20
20
21
21
using namespace clang ;
22
22
23
+ using clang::ast_matchers::cxxRecordDecl;
24
+ using clang::ast_matchers::hasName;
25
+ using clang::ast_matchers::match;
26
+ using clang::ast_matchers::varDecl;
27
+ using clang::tooling::buildASTFromCode;
28
+
29
+ static IntegerLiteral *createIntLiteral (ASTContext &Ctx, uint32_t Value) {
30
+ const int numBits = 32 ;
31
+ return IntegerLiteral::Create (Ctx, llvm::APInt (numBits, Value), Ctx.IntTy ,
32
+ {});
33
+ }
34
+
35
+ const CXXRecordDecl *getCXXRecordDeclNode (ASTUnit *AST,
36
+ const std::string &Name) {
37
+ auto Result =
38
+ match (cxxRecordDecl (hasName (Name)).bind (" record" ), AST->getASTContext ());
39
+ EXPECT_FALSE (Result.empty ());
40
+ return Result[0 ].getNodeAs <CXXRecordDecl>(" record" );
41
+ }
42
+
43
+ const VarDecl *getVariableNode (ASTUnit *AST, const std::string &Name) {
44
+ auto Result = match (varDecl (hasName (Name)).bind (" var" ), AST->getASTContext ());
45
+ EXPECT_EQ (Result.size (), 1u );
46
+ return Result[0 ].getNodeAs <VarDecl>(" var" );
47
+ }
48
+
23
49
TEST (ASTExpr, IgnoreExprCallbackForwarded) {
24
50
constexpr char Code[] = " " ;
25
51
auto AST = tooling::buildASTFromCodeWithArgs (Code, /* Args=*/ {" -std=c++20" });
26
52
ASTContext &Ctx = AST->getASTContext ();
27
53
28
- auto createIntLiteral = [&](uint32_t Value) -> IntegerLiteral * {
29
- const int numBits = 32 ;
30
- return IntegerLiteral::Create (Ctx, llvm::APInt (numBits, Value),
31
- Ctx.UnsignedIntTy , {});
32
- };
33
-
34
54
struct IgnoreParens {
35
55
Expr *operator ()(Expr *E) & { return nullptr ; }
36
56
Expr *operator ()(Expr *E) && {
@@ -42,17 +62,49 @@ TEST(ASTExpr, IgnoreExprCallbackForwarded) {
42
62
};
43
63
44
64
{
45
- auto *IntExpr = createIntLiteral (10 );
65
+ auto *IntExpr = createIntLiteral (Ctx, 10 );
46
66
ParenExpr *PE =
47
67
new (Ctx) ParenExpr (SourceLocation{}, SourceLocation{}, IntExpr);
48
68
EXPECT_EQ (IntExpr, IgnoreExprNodes (PE, IgnoreParens{}));
49
69
}
50
70
51
71
{
52
72
IgnoreParens CB{};
53
- auto *IntExpr = createIntLiteral (10 );
73
+ auto *IntExpr = createIntLiteral (Ctx, 10 );
54
74
ParenExpr *PE =
55
75
new (Ctx) ParenExpr (SourceLocation{}, SourceLocation{}, IntExpr);
56
76
EXPECT_EQ (nullptr , IgnoreExprNodes (PE, CB));
57
77
}
58
78
}
79
+
80
+ TEST (ASTExpr, InitListIsConstantInitialized) {
81
+ auto AST = buildASTFromCode (R"cpp(
82
+ struct Empty {};
83
+ struct Foo : Empty { int x, y; };
84
+ int gv;
85
+ )cpp" );
86
+ ASTContext &Ctx = AST->getASTContext ();
87
+ const CXXRecordDecl *Empty = getCXXRecordDeclNode (AST.get (), " Empty" );
88
+ const CXXRecordDecl *Foo = getCXXRecordDeclNode (AST.get (), " Foo" );
89
+
90
+ SourceLocation Loc{};
91
+ InitListExpr *BaseInit = new (Ctx) InitListExpr (Ctx, Loc, {}, Loc);
92
+ BaseInit->setType (Ctx.getRecordType (Empty));
93
+ Expr *Exprs[3 ] = {
94
+ BaseInit,
95
+ createIntLiteral (Ctx, 13 ),
96
+ createIntLiteral (Ctx, 42 ),
97
+ };
98
+ InitListExpr *FooInit = new (Ctx) InitListExpr (Ctx, Loc, Exprs, Loc);
99
+ FooInit->setType (Ctx.getRecordType (Foo));
100
+ EXPECT_TRUE (FooInit->isConstantInitializer (Ctx, false ));
101
+
102
+ // Replace the last initializer with something non-constant and make sure
103
+ // this returns false. Previously we had a bug where we didn't count base
104
+ // initializers, and only iterated over fields.
105
+ const VarDecl *GV = getVariableNode (AST.get (), " gv" );
106
+ auto *Ref = new (Ctx) DeclRefExpr (Ctx, const_cast <VarDecl *>(GV), false ,
107
+ Ctx.IntTy , VK_LValue, Loc);
108
+ (void )FooInit->updateInit (Ctx, 2 , Ref);
109
+ EXPECT_FALSE (FooInit->isConstantInitializer (Ctx, false ));
110
+ }
0 commit comments