Skip to content

Commit bb770f0

Browse files
authored
[Clang] Dump the rewritten sub-expressions in CXXDefaultArgExpr/CXXDefaultInitExpr (#80001)
This patch dump the rewritten sub-expressions in `CXXDefaultArgExpr` and `CXXDefaultInitExpr`. This machinery is useful for checking whether the materialized temporaries is lifetime-extended in the sub-AST of `CXXDefaultArgExpr` (`CXXDefaultInitExpr` has not been lifetime extendend now). Signed-off-by: yronglin <[email protected]>
1 parent e5cebec commit bb770f0

File tree

4 files changed

+105
-1
lines changed

4 files changed

+105
-1
lines changed

clang/include/clang/AST/TextNodeDumper.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -291,6 +291,8 @@ class TextNodeDumper
291291
void VisitTypeTraitExpr(const TypeTraitExpr *Node);
292292
void VisitArrayTypeTraitExpr(const ArrayTypeTraitExpr *Node);
293293
void VisitExpressionTraitExpr(const ExpressionTraitExpr *Node);
294+
void VisitCXXDefaultArgExpr(const CXXDefaultArgExpr *Node);
295+
void VisitCXXDefaultInitExpr(const CXXDefaultInitExpr *Node);
294296
void VisitMaterializeTemporaryExpr(const MaterializeTemporaryExpr *Node);
295297
void VisitExprWithCleanups(const ExprWithCleanups *Node);
296298
void VisitUnresolvedLookupExpr(const UnresolvedLookupExpr *Node);

clang/lib/AST/TextNodeDumper.cpp

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1397,6 +1397,26 @@ void TextNodeDumper::VisitExpressionTraitExpr(const ExpressionTraitExpr *Node) {
13971397
OS << " " << getTraitSpelling(Node->getTrait());
13981398
}
13991399

1400+
void TextNodeDumper::VisitCXXDefaultArgExpr(const CXXDefaultArgExpr *Node) {
1401+
if (Node->hasRewrittenInit()) {
1402+
OS << " has rewritten init";
1403+
AddChild([=] {
1404+
ColorScope Color(OS, ShowColors, StmtColor);
1405+
Visit(Node->getExpr());
1406+
});
1407+
}
1408+
}
1409+
1410+
void TextNodeDumper::VisitCXXDefaultInitExpr(const CXXDefaultInitExpr *Node) {
1411+
if (Node->hasRewrittenInit()) {
1412+
OS << " has rewritten init";
1413+
AddChild([=] {
1414+
ColorScope Color(OS, ShowColors, StmtColor);
1415+
Visit(Node->getExpr());
1416+
});
1417+
}
1418+
}
1419+
14001420
void TextNodeDumper::VisitMaterializeTemporaryExpr(
14011421
const MaterializeTemporaryExpr *Node) {
14021422
if (const ValueDecl *VD = Node->getExtendingDecl()) {

clang/test/AST/ast-dump-for-range-lifetime.cpp

Lines changed: 77 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -122,7 +122,16 @@ int (&default_arg_fn(const A & = A()))[3];
122122
void test4() {
123123

124124
// CHECK: FunctionDecl {{.*}} test4 'void ()'
125-
// FIXME: Should dump CXXDefaultArgExpr->getExpr() if CXXDefaultArgExpr has been rewrited?
125+
// CHECK: -CXXForRangeStmt {{.*}}
126+
// CHECK-NEXT: |-<<<NULL>>>
127+
// CHECK-NEXT: |-DeclStmt {{.*}}
128+
// CHECK-NEXT: | `-VarDecl{{.*}} implicit used __range1 'int (&)[3]' cinit
129+
// CHECK-NEXT: | `-ExprWithCleanups {{.*}} 'int[3]' lvalue
130+
// CHECK-NEXT: | `-CallExpr {{.*}} 'int[3]' lvalue
131+
// CHECK-NEXT: | |-ImplicitCastExpr {{.*}} 'int (&(*)(const A &))[3]' <FunctionToPointerDecay>
132+
// CHECK-NEXT: | | `-DeclRefExpr {{.*}} 'int (&(const A &))[3]' lvalue Function {{.*}} 'default_arg_fn' 'int (&(const A &))[3]'
133+
// CHECK-NEXT: | `-CXXDefaultArgExpr {{.*}} <<invalid sloc>> 'const A':'const P2718R0::A' lvalue has rewritten init
134+
// CHECK-NEXT: | `-MaterializeTemporaryExpr {{.*}} 'const A':'const P2718R0::A' lvalue extended by Var {{.*}} '__range1' 'int (&)[3]'
126135
for (auto e : default_arg_fn())
127136
bar(e);
128137
}
@@ -137,6 +146,43 @@ A foo(const A&, const DefaultA &Default = DefaultA()) {
137146
}
138147

139148
void test5() {
149+
// CHECK: FunctionDecl {{.*}} test5 'void ()'
150+
// CHECK: -CXXForRangeStmt {{.*}}
151+
// CHECK-NEXT: |-<<<NULL>>>
152+
// CHECK-NEXT: |-DeclStmt {{.*}}
153+
// CHECK-NEXT: | `-VarDecl {{.*}} implicit used __range1 'int (&)[3]' cinit
154+
// CHECK-NEXT: | `-ExprWithCleanups {{.*}} 'int[3]' lvalue
155+
// CHECK-NEXT: | `-CallExpr {{.*}} 'int[3]' lvalue
156+
// CHECK-NEXT: | |-ImplicitCastExpr {{.*}} 'int (&(*)(const A &))[3]' <FunctionToPointerDecay>
157+
// CHECK-NEXT: | | `-DeclRefExpr {{.*}} 'int (&(const A &))[3]' lvalue Function {{.*}} 'default_arg_fn' 'int (&(const A &))[3]'
158+
// CHECK-NEXT: | `-MaterializeTemporaryExpr {{.*}} 'const A':'const P2718R0::A' lvalue extended by Var {{.*}} '__range1' 'int (&)[3]'
159+
// CHECK-NEXT: | `-ImplicitCastExpr {{.*}} 'const A':'const P2718R0::A' <NoOp>
160+
// CHECK-NEXT: | `-CXXBindTemporaryExpr {{.*}} 'A':'P2718R0::A'
161+
// CHECK-NEXT: | `-CallExpr {{.*}} 'A':'P2718R0::A'
162+
// CHECK-NEXT: | |-ImplicitCastExpr {{.*}} 'A (*)(const A &, const DefaultA &)' <FunctionToPointerDecay>
163+
// CHECK-NEXT: | | `-DeclRefExpr {{.*}} 'A (const A &, const DefaultA &)' lvalue Function {{.*}} 'foo' 'A (const A &, const DefaultA &)'
164+
// CHECK-NEXT: | |-MaterializeTemporaryExpr {{.*}} 'const A':'const P2718R0::A' lvalue extended by Var {{.*}} '__range1' 'int (&)[3]'
165+
// CHECK-NEXT: | | `-ImplicitCastExpr {{.*}} 'const A':'const P2718R0::A' <NoOp>
166+
// CHECK-NEXT: | | `-CXXBindTemporaryExpr {{.*}} 'A':'P2718R0::A'
167+
// CHECK-NEXT: | | `-CallExpr {{.*}} 'A':'P2718R0::A'
168+
// CHECK-NEXT: | | |-ImplicitCastExpr {{.*}} 'A (*)(const A &, const DefaultA &)' <FunctionToPointerDecay>
169+
// CHECK-NEXT: | | | `-DeclRefExpr {{.*}} 'A (const A &, const DefaultA &)' lvalue Function {{.*}} 'foo' 'A (const A &, const DefaultA &)'
170+
// CHECK-NEXT: | | |-MaterializeTemporaryExpr {{.*}} 'const A':'const P2718R0::A' lvalue extended by Var {{.*}} '__range1' 'int (&)[3]'
171+
// CHECK-NEXT: | | | `-ImplicitCastExpr {{.*}} 'const A':'const P2718R0::A' <NoOp>
172+
// CHECK-NEXT: | | | `-CXXBindTemporaryExpr {{.*}} 'A':'P2718R0::A'
173+
// CHECK-NEXT: | | | `-CallExpr {{.*}} 'A':'P2718R0::A'
174+
// CHECK-NEXT: | | | |-ImplicitCastExpr {{.*}} 'A (*)(const A &, const DefaultA &)' <FunctionToPointerDecay>
175+
// CHECK-NEXT: | | | | `-DeclRefExpr {{.*}} 'A (const A &, const DefaultA &)' lvalue Function {{.*}} 'foo' 'A (const A &, const DefaultA &)'
176+
// CHECK-NEXT: | | | |-MaterializeTemporaryExpr {{.*}} 'const A':'const P2718R0::A' lvalue extended by Var {{.*}} '__range1' 'int (&)[3]'
177+
// CHECK-NEXT: | | | | `-ImplicitCastExpr {{.*}} 'const A':'const P2718R0::A' <NoOp>
178+
// CHECK-NEXT: | | | | `-CXXBindTemporaryExpr {{.*}} 'A':'P2718R0::A'
179+
// CHECK-NEXT: | | | | `-CXXTemporaryObjectExpr {{.*}} 'A':'P2718R0::A' 'void ()'
180+
// CHECK-NEXT: | | | `-CXXDefaultArgExpr {{.*}} <<invalid sloc>> 'const DefaultA':'const P2718R0::DefaultA' lvalue has rewritten init
181+
// CHECK-NEXT: | | | `-MaterializeTemporaryExpr {{.*}} 'const DefaultA':'const P2718R0::DefaultA' lvalue extended by Var {{.*}} '__range1' 'int (&)[3]'
182+
// CHECK-NEXT: | | `-CXXDefaultArgExpr {{.*}} <<invalid sloc>> 'const DefaultA':'const P2718R0::DefaultA' lvalue has rewritten init
183+
// CHECK-NEXT: | | `-MaterializeTemporaryExpr {{.*}} 'const DefaultA':'const P2718R0::DefaultA' lvalue extended by Var {{.*}} '__range1' 'int (&)[3]'
184+
// CHECK-NEXT: | `-CXXDefaultArgExpr {{.*}} <<invalid sloc>> 'const DefaultA':'const P2718R0::DefaultA' lvalue has rewritten init
185+
// CHECK-NEXT: | `-MaterializeTemporaryExpr {{.*}} 'const DefaultA':'const P2718R0::DefaultA' lvalue extended by Var {{.*}} '__range1' 'int (&)[3]'
140186
for (auto e : default_arg_fn(foo(foo(foo(A())))))
141187
bar(e);
142188
}
@@ -147,6 +193,36 @@ struct C : public A {
147193
};
148194

149195
void test6() {
196+
// CHECK: FunctionDecl {{.*}} test6 'void ()'
197+
// CHECK: -CXXForRangeStmt {{.*}}
198+
// CHECK-NEXT: |-<<<NULL>>>
199+
// CHECK-NEXT: |-DeclStmt {{.*}}
200+
// CHECK-NEXT: | `-VarDecl {{.*}} col:17 implicit used __range1 'C &&' cinit
201+
// CHECK-NEXT: | `-ExprWithCleanups {{.*}} 'C':'P2718R0::C' xvalue
202+
// CHECK-NEXT: | `-MaterializeTemporaryExpr {{.*}} 'C':'P2718R0::C' xvalue extended by Var {{.*}} '__range1' 'C &&'
203+
// CHECK-NEXT: | `-CXXBindTemporaryExpr {{.*}} 'C':'P2718R0::C'
204+
// CHECK-NEXT: | `-CXXTemporaryObjectExpr {{.*}} 'C':'P2718R0::C' 'void (int, const C &, const DefaultA &)'
205+
// CHECK-NEXT: | |-IntegerLiteral {{.*}}'int' 0
206+
// CHECK-NEXT: | |-MaterializeTemporaryExpr {{.*}} 'const C':'const P2718R0::C' lvalue extended by Var {{.*}} '__range1' 'C &&'
207+
// CHECK-NEXT: | | `-ImplicitCastExpr {{.*}} 'const C':'const P2718R0::C' <NoOp>
208+
// CHECK-NEXT: | | `-CXXBindTemporaryExpr {{.*}} 'C':'P2718R0::C'
209+
// CHECK-NEXT: | | `-CXXTemporaryObjectExpr {{.*}} 'C':'P2718R0::C' 'void (int, const C &, const DefaultA &)'
210+
// CHECK-NEXT: | | |-IntegerLiteral {{.*}} 'int' 0
211+
// CHECK-NEXT: | | |-MaterializeTemporaryExpr {{.*}} 'const C':'const P2718R0::C' lvalue extended by Var {{.*}} '__range1' 'C &&'
212+
// CHECK-NEXT: | | | `-ImplicitCastExpr {{.*}} 'const C':'const P2718R0::C' <NoOp>
213+
// CHECK-NEXT: | | | `-CXXBindTemporaryExpr {{.*}} 'C':'P2718R0::C'
214+
// CHECK-NEXT: | | | `-CXXTemporaryObjectExpr {{.*}} 'C':'P2718R0::C' 'void (int, const C &, const DefaultA &)'
215+
// CHECK-NEXT: | | | |-IntegerLiteral {{.*}} 'int' 0
216+
// CHECK-NEXT: | | | |-MaterializeTemporaryExpr {{.*}} 'const C':'const P2718R0::C' lvalue extended by Var {{.*}} '__range1' 'C &&'
217+
// CHECK-NEXT: | | | | `-ImplicitCastExpr {{.*}} 'const C':'const P2718R0::C' <NoOp>
218+
// CHECK-NEXT: | | | | `-CXXBindTemporaryExpr {{.*}} 'C':'P2718R0::C'
219+
// CHECK-NEXT: | | | | `-CXXTemporaryObjectExpr {{.*}} 'C':'P2718R0::C' 'void ()'
220+
// CHECK-NEXT: | | | `-CXXDefaultArgExpr {{.*}} <<invalid sloc>> 'const DefaultA':'const P2718R0::DefaultA' lvalue has rewritten init
221+
// CHECK-NEXT: | | | `-MaterializeTemporaryExpr {{.*}} 'const DefaultA':'const P2718R0::DefaultA' lvalue extended by Var {{.*}} '__range1' 'C &&'
222+
// CHECK-NEXT: | | `-CXXDefaultArgExpr {{.*}} <<invalid sloc>> 'const DefaultA':'const P2718R0::DefaultA' lvalue has rewritten init
223+
// CHECK-NEXT: | | `-MaterializeTemporaryExpr {{.*}} 'const DefaultA':'const P2718R0::DefaultA' lvalue extended by Var {{.*}} '__range1' 'C &&'
224+
// CHECK-NEXT: | `-CXXDefaultArgExpr {{.*}} <<invalid sloc>> 'const DefaultA':'const P2718R0::DefaultA' lvalue has rewritten init
225+
// CHECK-NEXT: | `-MaterializeTemporaryExpr {{.*}} 'const DefaultA':'const P2718R0::DefaultA' lvalue extended by Var {{.*}} '__range1' 'C &&'
150226
for (auto e : C(0, C(0, C(0, C()))))
151227
bar(e);
152228
}

clang/test/Import/cxx-default-init-expr/test.cpp

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,18 +4,24 @@
44
// CHECK-SAME: 'int'
55
// CHECK-NEXT: CXXDefaultInitExpr
66
// CHECK-SAME: 'int'
7+
// CHECK-NEXT: IntegerLiteral
8+
// CHECK-SAME: 'int'
79

810
// CHECK-NEXT: CXXCtorInitializer
911
// CHECK-SAME: 'float_member'
1012
// CHECK-SAME: 'float'
1113
// CHECK-NEXT: CXXDefaultInitExpr
1214
// CHECK-SAME: 'float'
15+
// CHECK-NEXT: FloatingLiteral
16+
// CHECK-SAME: 'float'
1317

1418
// CHECK-NEXT: CXXCtorInitializer
1519
// CHECK-SAME: 'class_member'
1620
// CHECK-SAME: 'Foo'
1721
// CHECK-NEXT: CXXDefaultInitExpr
1822
// CHECK-SAME: 'Foo'
23+
// CHECK-NEXT: ExprWithCleanups
24+
// CHECK-SAME: 'Foo'
1925

2026
void expr() {
2127
struct S s;

0 commit comments

Comments
 (0)