[SYCL] AST support for SYCL kernel entry point functions. (#122379)
[llvm-project.git] / clang / unittests / AST / ByteCode / toAPValue.cpp
blobcd62338ee23c14dad864b530b7e2d65ec0a16ba9
1 #include "../../../lib/AST/ByteCode/Context.h"
2 #include "../../../lib/AST/ByteCode/Descriptor.h"
3 #include "../../../lib/AST/ByteCode/Program.h"
4 #include "clang/AST/ASTContext.h"
5 #include "clang/AST/Decl.h"
6 #include "clang/ASTMatchers/ASTMatchFinder.h"
7 #include "clang/ASTMatchers/ASTMatchers.h"
8 #include "clang/Tooling/Tooling.h"
9 #include "gtest/gtest.h"
11 using namespace clang;
12 using namespace clang::interp;
13 using namespace clang::ast_matchers;
15 /// Test the various toAPValue implementations.
16 TEST(ToAPValue, Pointers) {
17 constexpr char Code[] =
18 "struct A { bool a; bool z; };\n"
19 "struct S {\n"
20 " A a[3];\n"
21 "};\n"
22 "constexpr S d = {{{true, false}, {false, true}, {false, false}}};\n"
23 "constexpr const bool *b = &d.a[1].z;\n"
24 "const void *p = (void*)12;\n"
25 "const void *nullp = (void*)0;\n"
26 "extern int earr[5][5];\n"
27 "constexpr const int *arrp = &earr[2][4];\n";
29 auto AST = tooling::buildASTFromCodeWithArgs(
30 Code, {"-fexperimental-new-constant-interpreter"});
32 auto &ASTCtx = AST->getASTContext();
33 auto &Ctx = AST->getASTContext().getInterpContext();
34 Program &Prog = Ctx.getProgram();
36 auto getDecl = [&](const char *Name) -> const ValueDecl * {
37 auto Nodes =
38 match(valueDecl(hasName(Name)).bind("var"), AST->getASTContext());
39 assert(Nodes.size() == 1);
40 const auto *D = Nodes[0].getNodeAs<ValueDecl>("var");
41 assert(D);
42 return D;
44 auto getGlobalPtr = [&](const char *Name) -> Pointer {
45 const VarDecl *D = cast<VarDecl>(getDecl(Name));
46 return Prog.getPtrGlobal(*Prog.getGlobal(D));
50 const Pointer &GP = getGlobalPtr("b");
51 const Pointer &P = GP.deref<Pointer>();
52 ASSERT_TRUE(P.isLive());
53 APValue A = P.toAPValue(ASTCtx);
54 ASSERT_TRUE(A.isLValue());
55 ASSERT_TRUE(A.hasLValuePath());
56 const auto &Path = A.getLValuePath();
57 ASSERT_EQ(Path.size(), 3u);
58 ASSERT_EQ(A.getLValueBase(), getDecl("d"));
59 // FIXME: Also test all path elements.
63 const ValueDecl *D = getDecl("p");
64 ASSERT_NE(D, nullptr);
65 const Pointer &GP = getGlobalPtr("p");
66 const Pointer &P = GP.deref<Pointer>();
67 ASSERT_TRUE(P.isIntegralPointer());
68 APValue A = P.toAPValue(ASTCtx);
69 ASSERT_TRUE(A.isLValue());
70 ASSERT_TRUE(A.getLValueBase().isNull());
71 APSInt I;
72 bool Success = A.toIntegralConstant(I, D->getType(), AST->getASTContext());
73 ASSERT_TRUE(Success);
74 ASSERT_EQ(I, 12);
78 const ValueDecl *D = getDecl("nullp");
79 ASSERT_NE(D, nullptr);
80 const Pointer &GP = getGlobalPtr("nullp");
81 const Pointer &P = GP.deref<Pointer>();
82 ASSERT_TRUE(P.isIntegralPointer());
83 APValue A = P.toAPValue(ASTCtx);
84 ASSERT_TRUE(A.isLValue());
85 ASSERT_TRUE(A.getLValueBase().isNull());
86 ASSERT_TRUE(A.isNullPointer());
87 APSInt I;
88 bool Success = A.toIntegralConstant(I, D->getType(), AST->getASTContext());
89 ASSERT_TRUE(Success);
90 ASSERT_EQ(I, 0);
93 // A multidimensional array.
95 const ValueDecl *D = getDecl("arrp");
96 ASSERT_NE(D, nullptr);
97 const Pointer &GP = getGlobalPtr("arrp").deref<Pointer>();
98 APValue A = GP.toAPValue(ASTCtx);
99 ASSERT_TRUE(A.isLValue());
100 ASSERT_TRUE(A.hasLValuePath());
101 ASSERT_EQ(A.getLValuePath().size(), 2u);
102 ASSERT_EQ(A.getLValuePath()[0].getAsArrayIndex(), 2u);
103 ASSERT_EQ(A.getLValuePath()[1].getAsArrayIndex(), 4u);
104 ASSERT_EQ(A.getLValueOffset().getQuantity(), 56u);
105 ASSERT_TRUE(
106 GP.atIndex(0).getFieldDesc()->getElemQualType()->isIntegerType());
110 TEST(ToAPValue, FunctionPointers) {
111 constexpr char Code[] = " constexpr bool foo() { return true; }\n"
112 " constexpr bool (*func)() = foo;\n"
113 " constexpr bool (*nullp)() = nullptr;\n";
115 auto AST = tooling::buildASTFromCodeWithArgs(
116 Code, {"-fexperimental-new-constant-interpreter"});
118 auto &ASTCtx = AST->getASTContext();
119 auto &Ctx = AST->getASTContext().getInterpContext();
120 Program &Prog = Ctx.getProgram();
122 auto getDecl = [&](const char *Name) -> const ValueDecl * {
123 auto Nodes =
124 match(valueDecl(hasName(Name)).bind("var"), AST->getASTContext());
125 assert(Nodes.size() == 1);
126 const auto *D = Nodes[0].getNodeAs<ValueDecl>("var");
127 assert(D);
128 return D;
131 auto getGlobalPtr = [&](const char *Name) -> Pointer {
132 const VarDecl *D = cast<VarDecl>(getDecl(Name));
133 return Prog.getPtrGlobal(*Prog.getGlobal(D));
137 const Pointer &GP = getGlobalPtr("func");
138 const FunctionPointer &FP = GP.deref<FunctionPointer>();
139 ASSERT_FALSE(FP.isZero());
140 APValue A = FP.toAPValue(ASTCtx);
141 ASSERT_TRUE(A.hasValue());
142 ASSERT_TRUE(A.isLValue());
143 ASSERT_TRUE(A.hasLValuePath());
144 const auto &Path = A.getLValuePath();
145 ASSERT_EQ(Path.size(), 0u);
146 ASSERT_FALSE(A.getLValueBase().isNull());
147 ASSERT_EQ(A.getLValueBase().dyn_cast<const ValueDecl *>(), getDecl("foo"));
151 const ValueDecl *D = getDecl("nullp");
152 ASSERT_NE(D, nullptr);
153 const Pointer &GP = getGlobalPtr("nullp");
154 const auto &P = GP.deref<FunctionPointer>();
155 APValue A = P.toAPValue(ASTCtx);
156 ASSERT_TRUE(A.isLValue());
157 ASSERT_TRUE(A.getLValueBase().isNull());
158 ASSERT_TRUE(A.isNullPointer());
159 APSInt I;
160 bool Success = A.toIntegralConstant(I, D->getType(), AST->getASTContext());
161 ASSERT_TRUE(Success);
162 ASSERT_EQ(I, 0);
166 TEST(ToAPValue, FunctionPointersC) {
167 // NB: The declaration of func2 is useless, but it makes us register a global
168 // variable for func.
169 constexpr char Code[] = "const int (* const func)(int *) = (void*)17;\n"
170 "const int (*func2)(int *) = func;\n";
171 auto AST = tooling::buildASTFromCodeWithArgs(
172 Code, {"-x", "c", "-fexperimental-new-constant-interpreter"});
174 auto &ASTCtx = AST->getASTContext();
175 auto &Ctx = AST->getASTContext().getInterpContext();
176 Program &Prog = Ctx.getProgram();
178 auto getDecl = [&](const char *Name) -> const ValueDecl * {
179 auto Nodes =
180 match(valueDecl(hasName(Name)).bind("var"), AST->getASTContext());
181 assert(Nodes.size() == 1);
182 const auto *D = Nodes[0].getNodeAs<ValueDecl>("var");
183 assert(D);
184 return D;
187 auto getGlobalPtr = [&](const char *Name) -> Pointer {
188 const VarDecl *D = cast<VarDecl>(getDecl(Name));
189 return Prog.getPtrGlobal(*Prog.getGlobal(D));
193 const ValueDecl *D = getDecl("func");
194 const Pointer &GP = getGlobalPtr("func");
195 ASSERT_TRUE(GP.isLive());
196 const FunctionPointer &FP = GP.deref<FunctionPointer>();
197 ASSERT_FALSE(FP.isZero());
198 APValue A = FP.toAPValue(ASTCtx);
199 ASSERT_TRUE(A.hasValue());
200 ASSERT_TRUE(A.isLValue());
201 const auto &Path = A.getLValuePath();
202 ASSERT_EQ(Path.size(), 0u);
203 ASSERT_TRUE(A.getLValueBase().isNull());
204 APSInt I;
205 bool Success = A.toIntegralConstant(I, D->getType(), AST->getASTContext());
206 ASSERT_TRUE(Success);
207 ASSERT_EQ(I, 17);
211 TEST(ToAPValue, MemberPointers) {
212 constexpr char Code[] = "struct S {\n"
213 " int m, n;\n"
214 "};\n"
215 "constexpr int S::*pm = &S::m;\n"
216 "constexpr int S::*nn = nullptr;\n";
218 auto AST = tooling::buildASTFromCodeWithArgs(
219 Code, {"-fexperimental-new-constant-interpreter"});
221 auto &ASTCtx = AST->getASTContext();
222 auto &Ctx = AST->getASTContext().getInterpContext();
223 Program &Prog = Ctx.getProgram();
225 auto getDecl = [&](const char *Name) -> const ValueDecl * {
226 auto Nodes =
227 match(valueDecl(hasName(Name)).bind("var"), AST->getASTContext());
228 assert(Nodes.size() == 1);
229 const auto *D = Nodes[0].getNodeAs<ValueDecl>("var");
230 assert(D);
231 return D;
234 auto getGlobalPtr = [&](const char *Name) -> Pointer {
235 const VarDecl *D = cast<VarDecl>(getDecl(Name));
236 return Prog.getPtrGlobal(*Prog.getGlobal(D));
240 const Pointer &GP = getGlobalPtr("pm");
241 ASSERT_TRUE(GP.isLive());
242 const MemberPointer &FP = GP.deref<MemberPointer>();
243 APValue A = FP.toAPValue(ASTCtx);
244 ASSERT_EQ(A.getMemberPointerDecl(), getDecl("m"));
245 ASSERT_EQ(A.getKind(), APValue::MemberPointer);
249 const Pointer &GP = getGlobalPtr("nn");
250 ASSERT_TRUE(GP.isLive());
251 const MemberPointer &NP = GP.deref<MemberPointer>();
252 ASSERT_TRUE(NP.isZero());
253 APValue A = NP.toAPValue(ASTCtx);
254 ASSERT_EQ(A.getKind(), APValue::MemberPointer);