diff --git a/clang/lib/AST/Expr.cpp b/clang/lib/AST/Expr.cpp index 8351989587662c..20505b21b15c1a 100644 --- a/clang/lib/AST/Expr.cpp +++ b/clang/lib/AST/Expr.cpp @@ -2900,6 +2900,12 @@ static Expr *IgnoreImplicitAsWrittenSingleStep(Expr *E) { return IgnoreImplicitSingleStep(E); } +static Expr *IgnoreParensOnlySingleStep(Expr *E) { + if (auto *PE = dyn_cast(E)) + return PE->getSubExpr(); + return E; +} + static Expr *IgnoreParensSingleStep(Expr *E) { if (auto *PE = dyn_cast(E)) return PE->getSubExpr(); @@ -3026,7 +3032,8 @@ Expr *Expr::IgnoreUnlessSpelledInSource() { Expr *LastE = nullptr; while (E != LastE) { LastE = E; - E = E->IgnoreParenImpCasts(); + E = IgnoreExprNodes(E, IgnoreImplicitSingleStep, IgnoreImpCastsSingleStep, + IgnoreParensOnlySingleStep); auto SR = E->getSourceRange(); diff --git a/clang/unittests/AST/ASTTraverserTest.cpp b/clang/unittests/AST/ASTTraverserTest.cpp index 88921a0020538a..a8f254fb70cdde 100644 --- a/clang/unittests/AST/ASTTraverserTest.cpp +++ b/clang/unittests/AST/ASTTraverserTest.cpp @@ -260,7 +260,90 @@ TemplateArgument 19u); } -TEST(Traverse, IgnoreUnlessSpelledInSource) { +TEST(Traverse, IgnoreUnlessSpelledInSourceStructs) { + auto AST = buildASTFromCode(R"cpp( + +struct MyStruct { + MyStruct(); + MyStruct(int i) { + MyStruct(); + } + ~MyStruct(); +}; + +)cpp"); + + auto BN = ast_matchers::match( + cxxConstructorDecl(hasName("MyStruct"), + hasParameter(0, parmVarDecl(hasType(isInteger())))) + .bind("ctor"), + AST->getASTContext()); + EXPECT_EQ(BN.size(), 1u); + + EXPECT_EQ(dumpASTString(ast_type_traits::TK_IgnoreUnlessSpelledInSource, + BN[0].getNodeAs("ctor")), + R"cpp( +CXXConstructorDecl 'MyStruct' +|-ParmVarDecl 'i' +`-CompoundStmt + `-CXXTemporaryObjectExpr +)cpp"); + + EXPECT_EQ( + dumpASTString(ast_type_traits::TK_AsIs, BN[0].getNodeAs("ctor")), + R"cpp( +CXXConstructorDecl 'MyStruct' +|-ParmVarDecl 'i' +`-CompoundStmt + `-ExprWithCleanups + `-CXXBindTemporaryExpr + `-CXXTemporaryObjectExpr +)cpp"); +} + +TEST(Traverse, IgnoreUnlessSpelledInSourceReturnStruct) { + + auto AST = buildASTFromCode(R"cpp( +struct Retval { + Retval() {} + ~Retval() {} +}; + +Retval someFun(); + +void foo() +{ + someFun(); +} +)cpp"); + + auto BN = ast_matchers::match(functionDecl(hasName("foo")).bind("fn"), + AST->getASTContext()); + EXPECT_EQ(BN.size(), 1u); + + EXPECT_EQ(dumpASTString(ast_type_traits::TK_IgnoreUnlessSpelledInSource, + BN[0].getNodeAs("fn")), + R"cpp( +FunctionDecl 'foo' +`-CompoundStmt + `-CallExpr + `-DeclRefExpr 'someFun' +)cpp"); + + EXPECT_EQ( + dumpASTString(ast_type_traits::TK_AsIs, BN[0].getNodeAs("fn")), + R"cpp( +FunctionDecl 'foo' +`-CompoundStmt + `-ExprWithCleanups + `-CXXBindTemporaryExpr + `-CallExpr + `-ImplicitCastExpr + `-DeclRefExpr 'someFun' +)cpp"); +} + +TEST(Traverse, IgnoreUnlessSpelledInSourceReturns) { auto AST = buildASTFromCode(R"cpp(