@@ -90,7 +90,8 @@ TEST(ToAPValue, Pointers) {
9090
9191TEST (ToAPValue, FunctionPointers) {
9292 constexpr char Code[] = " constexpr bool foo() { return true; }\n "
93- " constexpr bool (*func)() = foo;\n " ;
93+ " constexpr bool (*func)() = foo;\n "
94+ " constexpr bool (*nullp)() = nullptr;\n " ;
9495
9596 auto AST = tooling::buildASTFromCodeWithArgs (
9697 Code, {" -fexperimental-new-constant-interpreter" });
@@ -112,15 +113,76 @@ TEST(ToAPValue, FunctionPointers) {
112113 return Prog.getPtrGlobal (*Prog.getGlobal (D));
113114 };
114115
115- const Pointer &GP = getGlobalPtr (" func" );
116- const FunctionPointer &FP = GP.deref <FunctionPointer>();
117- ASSERT_FALSE (FP.isZero ());
118- APValue A = FP.toAPValue ();
119- ASSERT_TRUE (A.hasValue ());
120- ASSERT_TRUE (A.isLValue ());
121- ASSERT_TRUE (A.hasLValuePath ());
122- const auto &Path = A.getLValuePath ();
123- ASSERT_EQ (Path.size (), 0u );
124- ASSERT_FALSE (A.getLValueBase ().isNull ());
125- ASSERT_EQ (A.getLValueBase ().dyn_cast <const ValueDecl *>(), getDecl (" foo" ));
116+ {
117+ const Pointer &GP = getGlobalPtr (" func" );
118+ const FunctionPointer &FP = GP.deref <FunctionPointer>();
119+ ASSERT_FALSE (FP.isZero ());
120+ APValue A = FP.toAPValue ();
121+ ASSERT_TRUE (A.hasValue ());
122+ ASSERT_TRUE (A.isLValue ());
123+ ASSERT_TRUE (A.hasLValuePath ());
124+ const auto &Path = A.getLValuePath ();
125+ ASSERT_EQ (Path.size (), 0u );
126+ ASSERT_FALSE (A.getLValueBase ().isNull ());
127+ ASSERT_EQ (A.getLValueBase ().dyn_cast <const ValueDecl *>(), getDecl (" foo" ));
128+ }
129+
130+ {
131+ const ValueDecl *D = getDecl (" nullp" );
132+ ASSERT_NE (D, nullptr );
133+ const Pointer &GP = getGlobalPtr (" nullp" );
134+ const auto &P = GP.deref <FunctionPointer>();
135+ APValue A = P.toAPValue ();
136+ ASSERT_TRUE (A.isLValue ());
137+ ASSERT_TRUE (A.getLValueBase ().isNull ());
138+ ASSERT_TRUE (A.isNullPointer ());
139+ APSInt I;
140+ bool Success = A.toIntegralConstant (I, D->getType (), AST->getASTContext ());
141+ ASSERT_TRUE (Success);
142+ ASSERT_EQ (I, 0 );
143+ }
144+ }
145+
146+ TEST (ToAPValue, FunctionPointersC) {
147+ // NB: The declaration of func2 is useless, but it makes us register a global
148+ // variable for func.
149+ constexpr char Code[] = " const int (* const func)(int *) = (void*)17;\n "
150+ " const int (*func2)(int *) = func;\n " ;
151+ auto AST = tooling::buildASTFromCodeWithArgs (
152+ Code, {" -x" , " c" , " -fexperimental-new-constant-interpreter" });
153+
154+ auto &Ctx = AST->getASTContext ().getInterpContext ();
155+ Program &Prog = Ctx.getProgram ();
156+
157+ auto getDecl = [&](const char *Name) -> const ValueDecl * {
158+ auto Nodes =
159+ match (valueDecl (hasName (Name)).bind (" var" ), AST->getASTContext ());
160+ assert (Nodes.size () == 1 );
161+ const auto *D = Nodes[0 ].getNodeAs <ValueDecl>(" var" );
162+ assert (D);
163+ return D;
164+ };
165+
166+ auto getGlobalPtr = [&](const char *Name) -> Pointer {
167+ const VarDecl *D = cast<VarDecl>(getDecl (Name));
168+ return Prog.getPtrGlobal (*Prog.getGlobal (D));
169+ };
170+
171+ {
172+ const ValueDecl *D = getDecl (" func" );
173+ const Pointer &GP = getGlobalPtr (" func" );
174+ ASSERT_TRUE (GP.isLive ());
175+ const FunctionPointer &FP = GP.deref <FunctionPointer>();
176+ ASSERT_FALSE (FP.isZero ());
177+ APValue A = FP.toAPValue ();
178+ ASSERT_TRUE (A.hasValue ());
179+ ASSERT_TRUE (A.isLValue ());
180+ const auto &Path = A.getLValuePath ();
181+ ASSERT_EQ (Path.size (), 0u );
182+ ASSERT_TRUE (A.getLValueBase ().isNull ());
183+ APSInt I;
184+ bool Success = A.toIntegralConstant (I, D->getType (), AST->getASTContext ());
185+ ASSERT_TRUE (Success);
186+ ASSERT_EQ (I, 17 );
187+ }
126188}
0 commit comments