Skip to content

Commit 5d7d6ad

Browse files
committed
[clang][Interp] Add toAPValue unittests
1 parent 321f831 commit 5d7d6ad

File tree

2 files changed

+91
-0
lines changed

2 files changed

+91
-0
lines changed

clang/unittests/AST/Interp/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
add_clang_unittest(InterpTests
22
Descriptor.cpp
3+
toAPValue.cpp
34
)
45

56
clang_target_link_libraries(InterpTests
Lines changed: 90 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,90 @@
1+
#include "../../../lib/AST/Interp/Context.h"
2+
#include "../../../lib/AST/Interp/Descriptor.h"
3+
#include "../../../lib/AST/Interp/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"
10+
11+
using namespace clang;
12+
using namespace clang::interp;
13+
using namespace clang::ast_matchers;
14+
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+
25+
auto AST = tooling::buildASTFromCodeWithArgs(
26+
Code, {"-fexperimental-new-constant-interpreter"});
27+
28+
auto &Ctx = AST->getASTContext().getInterpContext();
29+
Program &Prog = Ctx.getProgram();
30+
31+
auto getDecl = [&](const char *Name) -> const ValueDecl * {
32+
auto Nodes =
33+
match(valueDecl(hasName(Name)).bind("var"), AST->getASTContext());
34+
assert(Nodes.size() == 1);
35+
const auto *D = Nodes[0].getNodeAs<ValueDecl>("var");
36+
assert(D);
37+
return D;
38+
};
39+
auto getGlobalPtr = [&](const char *Name) -> Pointer {
40+
const VarDecl *D = cast<VarDecl>(getDecl(Name));
41+
return Prog.getPtrGlobal(*Prog.getGlobal(D));
42+
};
43+
44+
const Pointer &GP = getGlobalPtr("b");
45+
const Pointer &P = GP.deref<Pointer>();
46+
ASSERT_TRUE(P.isLive());
47+
APValue A = P.toAPValue();
48+
ASSERT_TRUE(A.isLValue());
49+
ASSERT_TRUE(A.hasLValuePath());
50+
const auto &Path = A.getLValuePath();
51+
ASSERT_EQ(Path.size(), 3u);
52+
ASSERT_EQ(A.getLValueBase(), getDecl("d"));
53+
}
54+
55+
TEST(ToAPValue, FunctionPointers) {
56+
constexpr char Code[] = " constexpr bool foo() { return true; }\n"
57+
" constexpr bool (*func)() = foo;\n";
58+
59+
auto AST = tooling::buildASTFromCodeWithArgs(
60+
Code, {"-fexperimental-new-constant-interpreter"});
61+
62+
auto &Ctx = AST->getASTContext().getInterpContext();
63+
Program &Prog = Ctx.getProgram();
64+
65+
auto getDecl = [&](const char *Name) -> const ValueDecl * {
66+
auto Nodes =
67+
match(valueDecl(hasName(Name)).bind("var"), AST->getASTContext());
68+
assert(Nodes.size() == 1);
69+
const auto *D = Nodes[0].getNodeAs<ValueDecl>("var");
70+
assert(D);
71+
return D;
72+
};
73+
74+
auto getGlobalPtr = [&](const char *Name) -> Pointer {
75+
const VarDecl *D = cast<VarDecl>(getDecl(Name));
76+
return Prog.getPtrGlobal(*Prog.getGlobal(D));
77+
};
78+
79+
const Pointer &GP = getGlobalPtr("func");
80+
const FunctionPointer &FP = GP.deref<FunctionPointer>();
81+
ASSERT_FALSE(FP.isZero());
82+
APValue A = FP.toAPValue();
83+
ASSERT_TRUE(A.hasValue());
84+
ASSERT_TRUE(A.isLValue());
85+
ASSERT_TRUE(A.hasLValuePath());
86+
const auto &Path = A.getLValuePath();
87+
ASSERT_EQ(Path.size(), 0u);
88+
ASSERT_FALSE(A.getLValueBase().isNull());
89+
ASSERT_EQ(A.getLValueBase().dyn_cast<const ValueDecl *>(), getDecl("foo"));
90+
}

0 commit comments

Comments
 (0)