Loading clang/lib/AST/Expr.cpp +8 −1 Original line number Diff line number Diff line Loading @@ -2900,6 +2900,12 @@ static Expr *IgnoreImplicitAsWrittenSingleStep(Expr *E) { return IgnoreImplicitSingleStep(E); } static Expr *IgnoreParensOnlySingleStep(Expr *E) { if (auto *PE = dyn_cast<ParenExpr>(E)) return PE->getSubExpr(); return E; } static Expr *IgnoreParensSingleStep(Expr *E) { if (auto *PE = dyn_cast<ParenExpr>(E)) return PE->getSubExpr(); Loading Loading @@ -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(); Loading clang/unittests/AST/ASTTraverserTest.cpp +84 −1 Original line number Diff line number Diff line Loading @@ -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<Decl>("ctor")), R"cpp( CXXConstructorDecl 'MyStruct' |-ParmVarDecl 'i' `-CompoundStmt `-CXXTemporaryObjectExpr )cpp"); EXPECT_EQ( dumpASTString(ast_type_traits::TK_AsIs, BN[0].getNodeAs<Decl>("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<Decl>("fn")), R"cpp( FunctionDecl 'foo' `-CompoundStmt `-CallExpr `-DeclRefExpr 'someFun' )cpp"); EXPECT_EQ( dumpASTString(ast_type_traits::TK_AsIs, BN[0].getNodeAs<Decl>("fn")), R"cpp( FunctionDecl 'foo' `-CompoundStmt `-ExprWithCleanups `-CXXBindTemporaryExpr `-CallExpr `-ImplicitCastExpr `-DeclRefExpr 'someFun' )cpp"); } TEST(Traverse, IgnoreUnlessSpelledInSourceReturns) { auto AST = buildASTFromCode(R"cpp( Loading Loading
clang/lib/AST/Expr.cpp +8 −1 Original line number Diff line number Diff line Loading @@ -2900,6 +2900,12 @@ static Expr *IgnoreImplicitAsWrittenSingleStep(Expr *E) { return IgnoreImplicitSingleStep(E); } static Expr *IgnoreParensOnlySingleStep(Expr *E) { if (auto *PE = dyn_cast<ParenExpr>(E)) return PE->getSubExpr(); return E; } static Expr *IgnoreParensSingleStep(Expr *E) { if (auto *PE = dyn_cast<ParenExpr>(E)) return PE->getSubExpr(); Loading Loading @@ -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(); Loading
clang/unittests/AST/ASTTraverserTest.cpp +84 −1 Original line number Diff line number Diff line Loading @@ -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<Decl>("ctor")), R"cpp( CXXConstructorDecl 'MyStruct' |-ParmVarDecl 'i' `-CompoundStmt `-CXXTemporaryObjectExpr )cpp"); EXPECT_EQ( dumpASTString(ast_type_traits::TK_AsIs, BN[0].getNodeAs<Decl>("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<Decl>("fn")), R"cpp( FunctionDecl 'foo' `-CompoundStmt `-CallExpr `-DeclRefExpr 'someFun' )cpp"); EXPECT_EQ( dumpASTString(ast_type_traits::TK_AsIs, BN[0].getNodeAs<Decl>("fn")), R"cpp( FunctionDecl 'foo' `-CompoundStmt `-ExprWithCleanups `-CXXBindTemporaryExpr `-CallExpr `-ImplicitCastExpr `-DeclRefExpr 'someFun' )cpp"); } TEST(Traverse, IgnoreUnlessSpelledInSourceReturns) { auto AST = buildASTFromCode(R"cpp( Loading