https://github.com/yronglin created https://github.com/llvm/llvm-project/pull/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). >From 1e45decdaeb529904fd2076b9be42234dbd5a871 Mon Sep 17 00:00:00 2001 From: yronglin <yronglin...@gmail.com> Date: Tue, 30 Jan 2024 21:11:48 +0800 Subject: [PATCH] [Clang] Dump the rewritten sub-expressions in CXXDefaultArgExpr/CXXDefaultInitExpr Signed-off-by: yronglin <yronglin...@gmail.com> --- clang/include/clang/AST/TextNodeDumper.h | 2 + clang/lib/AST/TextNodeDumper.cpp | 20 +++++ .../test/AST/ast-dump-for-range-lifetime.cpp | 78 ++++++++++++++++++- .../Import/cxx-default-init-expr/test.cpp | 6 ++ 4 files changed, 105 insertions(+), 1 deletion(-) 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; _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits