-
Notifications
You must be signed in to change notification settings - Fork 10.8k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[Clang] Dump the rewritten sub-expressions in CXXDefaultArgExpr/CXXDefaultInitExpr #80001
Conversation
…faultInitExpr Signed-off-by: yronglin <yronglin777@gmail.com>
@llvm/pr-subscribers-clang Author: None (yronglin) ChangesThis patch dump the rewritten sub-expressions in Full diff: https://github.com/llvm/llvm-project/pull/80001.diff 4 Files Affected:
diff --git a/clang/include/clang/AST/TextNodeDumper.h b/clang/include/clang/AST/TextNodeDumper.h
index 732749ad305e..99183918dfde 100644
--- a/clang/include/clang/AST/TextNodeDumper.h
+++ b/clang/include/clang/AST/TextNodeDumper.h
@@ -291,6 +291,8 @@ class TextNodeDumper
void VisitTypeTraitExpr(const TypeTraitExpr *Node);
void VisitArrayTypeTraitExpr(const ArrayTypeTraitExpr *Node);
void VisitExpressionTraitExpr(const ExpressionTraitExpr *Node);
+ void VisitCXXDefaultArgExpr(const CXXDefaultArgExpr *Node);
+ void VisitCXXDefaultInitExpr(const CXXDefaultInitExpr *Node);
void VisitMaterializeTemporaryExpr(const MaterializeTemporaryExpr *Node);
void VisitExprWithCleanups(const ExprWithCleanups *Node);
void VisitUnresolvedLookupExpr(const UnresolvedLookupExpr *Node);
diff --git a/clang/lib/AST/TextNodeDumper.cpp b/clang/lib/AST/TextNodeDumper.cpp
index ecf5de0be543..748bfb0127a2 100644
--- a/clang/lib/AST/TextNodeDumper.cpp
+++ b/clang/lib/AST/TextNodeDumper.cpp
@@ -1397,6 +1397,26 @@ void TextNodeDumper::VisitExpressionTraitExpr(const ExpressionTraitExpr *Node) {
OS << " " << getTraitSpelling(Node->getTrait());
}
+void TextNodeDumper::VisitCXXDefaultArgExpr(const CXXDefaultArgExpr *Node) {
+ if (Node->hasRewrittenInit()) {
+ OS << " has rewritten init";
+ AddChild([=] {
+ ColorScope Color(OS, ShowColors, StmtColor);
+ Visit(Node->getExpr());
+ });
+ }
+}
+
+void TextNodeDumper::VisitCXXDefaultInitExpr(const CXXDefaultInitExpr *Node) {
+ if (Node->hasRewrittenInit()) {
+ OS << " has rewritten init";
+ AddChild([=] {
+ ColorScope Color(OS, ShowColors, StmtColor);
+ Visit(Node->getExpr());
+ });
+ }
+}
+
void TextNodeDumper::VisitMaterializeTemporaryExpr(
const MaterializeTemporaryExpr *Node) {
if (const ValueDecl *VD = Node->getExtendingDecl()) {
diff --git a/clang/test/AST/ast-dump-for-range-lifetime.cpp b/clang/test/AST/ast-dump-for-range-lifetime.cpp
index dec2e2918452..88b838268be2 100644
--- a/clang/test/AST/ast-dump-for-range-lifetime.cpp
+++ b/clang/test/AST/ast-dump-for-range-lifetime.cpp
@@ -122,7 +122,16 @@ int (&default_arg_fn(const A & = A()))[3];
void test4() {
// CHECK: FunctionDecl {{.*}} test4 'void ()'
- // FIXME: Should dump CXXDefaultArgExpr->getExpr() if CXXDefaultArgExpr has been rewrited?
+ // CHECK: -CXXForRangeStmt {{.*}}
+ // CHECK-NEXT: |-<<<NULL>>>
+ // CHECK-NEXT: |-DeclStmt {{.*}}
+ // CHECK-NEXT: | `-VarDecl{{.*}} implicit used __range1 'int (&)[3]' cinit
+ // CHECK-NEXT: | `-ExprWithCleanups {{.*}} 'int[3]' lvalue
+ // CHECK-NEXT: | `-CallExpr {{.*}} 'int[3]' lvalue
+ // CHECK-NEXT: | |-ImplicitCastExpr {{.*}} 'int (&(*)(const A &))[3]' <FunctionToPointerDecay>
+ // CHECK-NEXT: | | `-DeclRefExpr {{.*}} 'int (&(const A &))[3]' lvalue Function {{.*}} 'default_arg_fn' 'int (&(const A &))[3]'
+ // CHECK-NEXT: | `-CXXDefaultArgExpr {{.*}} <<invalid sloc>> 'const A':'const P2718R0::A' lvalue has rewritten init
+ // CHECK-NEXT: | `-MaterializeTemporaryExpr {{.*}} 'const A':'const P2718R0::A' lvalue extended by Var {{.*}} '__range1' 'int (&)[3]'
for (auto e : default_arg_fn())
bar(e);
}
@@ -137,6 +146,43 @@ A foo(const A&, const DefaultA &Default = DefaultA()) {
}
void test5() {
+ // CHECK: FunctionDecl {{.*}} test5 'void ()'
+ // CHECK: -CXXForRangeStmt {{.*}}
+ // CHECK-NEXT: |-<<<NULL>>>
+ // CHECK-NEXT: |-DeclStmt {{.*}}
+ // CHECK-NEXT: | `-VarDecl {{.*}} implicit used __range1 'int (&)[3]' cinit
+ // CHECK-NEXT: | `-ExprWithCleanups {{.*}} 'int[3]' lvalue
+ // CHECK-NEXT: | `-CallExpr {{.*}} 'int[3]' lvalue
+ // CHECK-NEXT: | |-ImplicitCastExpr {{.*}} 'int (&(*)(const A &))[3]' <FunctionToPointerDecay>
+ // CHECK-NEXT: | | `-DeclRefExpr {{.*}} 'int (&(const A &))[3]' lvalue Function {{.*}} 'default_arg_fn' 'int (&(const A &))[3]'
+ // CHECK-NEXT: | `-MaterializeTemporaryExpr {{.*}} 'const A':'const P2718R0::A' lvalue extended by Var {{.*}} '__range1' 'int (&)[3]'
+ // CHECK-NEXT: | `-ImplicitCastExpr {{.*}} 'const A':'const P2718R0::A' <NoOp>
+ // CHECK-NEXT: | `-CXXBindTemporaryExpr {{.*}} 'A':'P2718R0::A'
+ // CHECK-NEXT: | `-CallExpr {{.*}} 'A':'P2718R0::A'
+ // CHECK-NEXT: | |-ImplicitCastExpr {{.*}} 'A (*)(const A &, const DefaultA &)' <FunctionToPointerDecay>
+ // CHECK-NEXT: | | `-DeclRefExpr {{.*}} 'A (const A &, const DefaultA &)' lvalue Function {{.*}} 'foo' 'A (const A &, const DefaultA &)'
+ // CHECK-NEXT: | |-MaterializeTemporaryExpr {{.*}} 'const A':'const P2718R0::A' lvalue extended by Var {{.*}} '__range1' 'int (&)[3]'
+ // CHECK-NEXT: | | `-ImplicitCastExpr {{.*}} 'const A':'const P2718R0::A' <NoOp>
+ // CHECK-NEXT: | | `-CXXBindTemporaryExpr {{.*}} 'A':'P2718R0::A'
+ // CHECK-NEXT: | | `-CallExpr {{.*}} 'A':'P2718R0::A'
+ // CHECK-NEXT: | | |-ImplicitCastExpr {{.*}} 'A (*)(const A &, const DefaultA &)' <FunctionToPointerDecay>
+ // CHECK-NEXT: | | | `-DeclRefExpr {{.*}} 'A (const A &, const DefaultA &)' lvalue Function {{.*}} 'foo' 'A (const A &, const DefaultA &)'
+ // CHECK-NEXT: | | |-MaterializeTemporaryExpr {{.*}} 'const A':'const P2718R0::A' lvalue extended by Var {{.*}} '__range1' 'int (&)[3]'
+ // CHECK-NEXT: | | | `-ImplicitCastExpr {{.*}} 'const A':'const P2718R0::A' <NoOp>
+ // CHECK-NEXT: | | | `-CXXBindTemporaryExpr {{.*}} 'A':'P2718R0::A'
+ // CHECK-NEXT: | | | `-CallExpr {{.*}} 'A':'P2718R0::A'
+ // CHECK-NEXT: | | | |-ImplicitCastExpr {{.*}} 'A (*)(const A &, const DefaultA &)' <FunctionToPointerDecay>
+ // CHECK-NEXT: | | | | `-DeclRefExpr {{.*}} 'A (const A &, const DefaultA &)' lvalue Function {{.*}} 'foo' 'A (const A &, const DefaultA &)'
+ // CHECK-NEXT: | | | |-MaterializeTemporaryExpr {{.*}} 'const A':'const P2718R0::A' lvalue extended by Var {{.*}} '__range1' 'int (&)[3]'
+ // CHECK-NEXT: | | | | `-ImplicitCastExpr {{.*}} 'const A':'const P2718R0::A' <NoOp>
+ // CHECK-NEXT: | | | | `-CXXBindTemporaryExpr {{.*}} 'A':'P2718R0::A'
+ // CHECK-NEXT: | | | | `-CXXTemporaryObjectExpr {{.*}} 'A':'P2718R0::A' 'void ()'
+ // CHECK-NEXT: | | | `-CXXDefaultArgExpr {{.*}} <<invalid sloc>> 'const DefaultA':'const P2718R0::DefaultA' lvalue has rewritten init
+ // CHECK-NEXT: | | | `-MaterializeTemporaryExpr {{.*}} 'const DefaultA':'const P2718R0::DefaultA' lvalue extended by Var {{.*}} '__range1' 'int (&)[3]'
+ // CHECK-NEXT: | | `-CXXDefaultArgExpr {{.*}} <<invalid sloc>> 'const DefaultA':'const P2718R0::DefaultA' lvalue has rewritten init
+ // CHECK-NEXT: | | `-MaterializeTemporaryExpr {{.*}} 'const DefaultA':'const P2718R0::DefaultA' lvalue extended by Var {{.*}} '__range1' 'int (&)[3]'
+ // CHECK-NEXT: | `-CXXDefaultArgExpr {{.*}} <<invalid sloc>> 'const DefaultA':'const P2718R0::DefaultA' lvalue has rewritten init
+ // CHECK-NEXT: | `-MaterializeTemporaryExpr {{.*}} 'const DefaultA':'const P2718R0::DefaultA' lvalue extended by Var {{.*}} '__range1' 'int (&)[3]'
for (auto e : default_arg_fn(foo(foo(foo(A())))))
bar(e);
}
@@ -147,6 +193,36 @@ struct C : public A {
};
void test6() {
+ // CHECK: FunctionDecl {{.*}} test6 'void ()'
+ // CHECK: -CXXForRangeStmt {{.*}}
+ // CHECK-NEXT: |-<<<NULL>>>
+ // CHECK-NEXT: |-DeclStmt {{.*}}
+ // CHECK-NEXT: | `-VarDecl {{.*}} col:17 implicit used __range1 'C &&' cinit
+ // CHECK-NEXT: | `-ExprWithCleanups {{.*}} 'C':'P2718R0::C' xvalue
+ // CHECK-NEXT: | `-MaterializeTemporaryExpr {{.*}} 'C':'P2718R0::C' xvalue extended by Var {{.*}} '__range1' 'C &&'
+ // CHECK-NEXT: | `-CXXBindTemporaryExpr {{.*}} 'C':'P2718R0::C'
+ // CHECK-NEXT: | `-CXXTemporaryObjectExpr {{.*}} 'C':'P2718R0::C' 'void (int, const C &, const DefaultA &)'
+ // CHECK-NEXT: | |-IntegerLiteral {{.*}}'int' 0
+ // CHECK-NEXT: | |-MaterializeTemporaryExpr {{.*}} 'const C':'const P2718R0::C' lvalue extended by Var {{.*}} '__range1' 'C &&'
+ // CHECK-NEXT: | | `-ImplicitCastExpr {{.*}} 'const C':'const P2718R0::C' <NoOp>
+ // CHECK-NEXT: | | `-CXXBindTemporaryExpr {{.*}} 'C':'P2718R0::C'
+ // CHECK-NEXT: | | `-CXXTemporaryObjectExpr {{.*}} 'C':'P2718R0::C' 'void (int, const C &, const DefaultA &)'
+ // CHECK-NEXT: | | |-IntegerLiteral {{.*}} 'int' 0
+ // CHECK-NEXT: | | |-MaterializeTemporaryExpr {{.*}} 'const C':'const P2718R0::C' lvalue extended by Var {{.*}} '__range1' 'C &&'
+ // CHECK-NEXT: | | | `-ImplicitCastExpr {{.*}} 'const C':'const P2718R0::C' <NoOp>
+ // CHECK-NEXT: | | | `-CXXBindTemporaryExpr {{.*}} 'C':'P2718R0::C'
+ // CHECK-NEXT: | | | `-CXXTemporaryObjectExpr {{.*}} 'C':'P2718R0::C' 'void (int, const C &, const DefaultA &)'
+ // CHECK-NEXT: | | | |-IntegerLiteral {{.*}} 'int' 0
+ // CHECK-NEXT: | | | |-MaterializeTemporaryExpr {{.*}} 'const C':'const P2718R0::C' lvalue extended by Var {{.*}} '__range1' 'C &&'
+ // CHECK-NEXT: | | | | `-ImplicitCastExpr {{.*}} 'const C':'const P2718R0::C' <NoOp>
+ // CHECK-NEXT: | | | | `-CXXBindTemporaryExpr {{.*}} 'C':'P2718R0::C'
+ // CHECK-NEXT: | | | | `-CXXTemporaryObjectExpr {{.*}} 'C':'P2718R0::C' 'void ()'
+ // CHECK-NEXT: | | | `-CXXDefaultArgExpr {{.*}} <<invalid sloc>> 'const DefaultA':'const P2718R0::DefaultA' lvalue has rewritten init
+ // CHECK-NEXT: | | | `-MaterializeTemporaryExpr {{.*}} 'const DefaultA':'const P2718R0::DefaultA' lvalue extended by Var {{.*}} '__range1' 'C &&'
+ // CHECK-NEXT: | | `-CXXDefaultArgExpr {{.*}} <<invalid sloc>> 'const DefaultA':'const P2718R0::DefaultA' lvalue has rewritten init
+ // CHECK-NEXT: | | `-MaterializeTemporaryExpr {{.*}} 'const DefaultA':'const P2718R0::DefaultA' lvalue extended by Var {{.*}} '__range1' 'C &&'
+ // CHECK-NEXT: | `-CXXDefaultArgExpr {{.*}} <<invalid sloc>> 'const DefaultA':'const P2718R0::DefaultA' lvalue has rewritten init
+ // CHECK-NEXT: | `-MaterializeTemporaryExpr {{.*}} 'const DefaultA':'const P2718R0::DefaultA' lvalue extended by Var {{.*}} '__range1' 'C &&'
for (auto e : C(0, C(0, C(0, C()))))
bar(e);
}
diff --git a/clang/test/Import/cxx-default-init-expr/test.cpp b/clang/test/Import/cxx-default-init-expr/test.cpp
index a50b12b83e0d..0380097b26f9 100644
--- a/clang/test/Import/cxx-default-init-expr/test.cpp
+++ b/clang/test/Import/cxx-default-init-expr/test.cpp
@@ -4,18 +4,24 @@
// CHECK-SAME: 'int'
// CHECK-NEXT: CXXDefaultInitExpr
// CHECK-SAME: 'int'
+// CHECK-NEXT: IntegerLiteral
+// CHECK-SAME: 'int'
// CHECK-NEXT: CXXCtorInitializer
// CHECK-SAME: 'float_member'
// CHECK-SAME: 'float'
// CHECK-NEXT: CXXDefaultInitExpr
// CHECK-SAME: 'float'
+// CHECK-NEXT: FloatingLiteral
+// CHECK-SAME: 'float'
// CHECK-NEXT: CXXCtorInitializer
// CHECK-SAME: 'class_member'
// CHECK-SAME: 'Foo'
// CHECK-NEXT: CXXDefaultInitExpr
// CHECK-SAME: 'Foo'
+// CHECK-NEXT: ExprWithCleanups
+// CHECK-SAME: 'Foo'
void expr() {
struct S s;
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM
Thanks for your review! |
) This PR fix a AST dump issue since #80001 When Clang dumps `CXXDefaultArgExpr`/`CXXDefaultInitExpr`, there has no recursively dump the complete `CXXDefaultArgExpr`/`CXXDefaultInitExpr`. Since this PR, Clang will recursively dump a `CXXDefaultArgExpr`/`CXXDefaultInitExpr` node, even if the node has no rewritten init. *Consider*: ``` struct A { int arr[1]; }; struct B { const A &a = A{{0}}; }; void test() { B b{}; } ``` *Before*: ``` `-FunctionDecl <line:9:1, line:11:1> line:9:6 test 'void ()' `-CompoundStmt <col:13, line:11:1> `-DeclStmt <line:10:3, col:8> `-VarDecl <col:3, col:7> col:5 b 'B' listinit `-InitListExpr <col:6, col:7> 'B' `-CXXDefaultInitExpr <col:7> 'const A' lvalue has rewritten init `-ExprWithCleanups <line:6:16, col:21> 'const A' lvalue ``` *After*: ``` `-FunctionDecl 0x15a9455a8 <line:9:1, line:11:1> line:9:6 test 'void ()' `-CompoundStmt 0x15a945850 <col:13, line:11:1> `-DeclStmt 0x15a945838 <line:10:3, col:8> `-VarDecl 0x15a945708 <col:3, col:7> col:5 b 'B' listinit `-InitListExpr 0x15a9457b0 <col:6, col:7> 'B' `-CXXDefaultInitExpr 0x15a9457f8 <col:7> 'const A' lvalue has rewritten init `-ExprWithCleanups 0x15a945568 <line:6:16, col:21> 'const A' lvalue `-MaterializeTemporaryExpr 0x15a945500 <col:16, col:21> 'const A' lvalue extended by Field 0x15a945160 'a' 'const A &' `-ImplicitCastExpr 0x15a9454e8 <col:16, col:21> 'const A' <NoOp> `-CXXFunctionalCastExpr 0x15a9454c0 <col:16, col:21> 'A' functional cast to A <NoOp> `-InitListExpr 0x15a9452c0 <col:17, col:21> 'A' `-InitListExpr 0x15a945308 <col:18, col:20> 'int[1]' `-IntegerLiteral 0x15a945210 <col:19> 'int' 0 ``` --------- Signed-off-by: yronglin <yronglin777@gmail.com>
This patch dump the rewritten sub-expressions in
CXXDefaultArgExpr
andCXXDefaultInitExpr
.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).