@@ -90,7 +90,8 @@ TEST(ToAPValue, Pointers) {
90
90
91
91
TEST (ToAPValue, FunctionPointers) {
92
92
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 " ;
94
95
95
96
auto AST = tooling::buildASTFromCodeWithArgs (
96
97
Code, {" -fexperimental-new-constant-interpreter" });
@@ -112,15 +113,76 @@ TEST(ToAPValue, FunctionPointers) {
112
113
return Prog.getPtrGlobal (*Prog.getGlobal (D));
113
114
};
114
115
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
+ }
126
188
}
0 commit comments