diff --git a/clang/lib/AST/Expr.cpp b/clang/lib/AST/Expr.cpp --- a/clang/lib/AST/Expr.cpp +++ b/clang/lib/AST/Expr.cpp @@ -2816,13 +2816,18 @@ Expr *Expr::IgnoreUnlessSpelledInSource() { auto IgnoreImplicitConstructorSingleStep = [](Expr *E) { + if (auto *Cast = dyn_cast(E)) { + auto *SE = Cast->getSubExpr(); + if (SE->getSourceRange() == E->getSourceRange()) + return SE; + } + if (auto *C = dyn_cast(E)) { auto NumArgs = C->getNumArgs(); if (NumArgs == 1 || (NumArgs > 1 && isa(C->getArg(1)))) { Expr *A = C->getArg(0); - if (A->getSourceRange() == E->getSourceRange() || - !isa(C)) + if (A->getSourceRange() == E->getSourceRange() || C->isElidable()) return A; } } diff --git a/clang/lib/AST/ParentMapContext.cpp b/clang/lib/AST/ParentMapContext.cpp --- a/clang/lib/AST/ParentMapContext.cpp +++ b/clang/lib/AST/ParentMapContext.cpp @@ -154,8 +154,13 @@ auto SR = Child->getSourceRange(); + if (const auto *C = dyn_cast(E)) { + if (C->getSourceRange() == SR) + return true; + } + if (const auto *C = dyn_cast(E)) { - if (C->getSourceRange() == SR || !isa(C)) + if (C->getSourceRange() == SR || C->isElidable()) return true; } diff --git a/clang/unittests/AST/ASTTraverserTest.cpp b/clang/unittests/AST/ASTTraverserTest.cpp --- a/clang/unittests/AST/ASTTraverserTest.cpp +++ b/clang/unittests/AST/ASTTraverserTest.cpp @@ -299,6 +299,34 @@ void actual_template_test() { template_test<4>(); } + +struct OneParamCtor { + explicit OneParamCtor(int); +}; +struct TwoParamCtor { + explicit TwoParamCtor(int, int); +}; + +void varDeclCtors() { + { + auto var1 = OneParamCtor(5); + auto var2 = TwoParamCtor(6, 7); + } + { + OneParamCtor var3(5); + TwoParamCtor var4(6, 7); + } + int i = 0; + { + auto var5 = OneParamCtor(i); + auto var6 = TwoParamCtor(i, 7); + } + { + OneParamCtor var7(i); + TwoParamCtor var8(i, 7); + } +} + )cpp"); { @@ -444,6 +472,145 @@ `-StringLiteral )cpp"); } + + auto varChecker = [&AST](StringRef varName, StringRef SemanticDump, + StringRef SyntacticDump) { + auto FN = ast_matchers::match( + functionDecl( + hasName("varDeclCtors"), + forEachDescendant(varDecl(hasName(varName)).bind("varDeclCtor"))), + AST->getASTContext()); + EXPECT_EQ(FN.size(), 1u); + + EXPECT_EQ(dumpASTString(TK_AsIs, FN[0].getNodeAs("varDeclCtor")), + SemanticDump); + + EXPECT_EQ(dumpASTString(TK_IgnoreUnlessSpelledInSource, + FN[0].getNodeAs("varDeclCtor")), + SyntacticDump); + }; + + varChecker("var1", + R"cpp( +VarDecl 'var1' +`-ExprWithCleanups + `-CXXConstructExpr + `-MaterializeTemporaryExpr + `-CXXFunctionalCastExpr + `-CXXConstructExpr + `-IntegerLiteral +)cpp", + R"cpp( +VarDecl 'var1' +`-CXXConstructExpr + `-IntegerLiteral +)cpp"); + + varChecker("var2", + R"cpp( +VarDecl 'var2' +`-ExprWithCleanups + `-CXXConstructExpr + `-MaterializeTemporaryExpr + `-CXXTemporaryObjectExpr + |-IntegerLiteral + `-IntegerLiteral +)cpp", + R"cpp( +VarDecl 'var2' +`-CXXTemporaryObjectExpr + |-IntegerLiteral + `-IntegerLiteral +)cpp"); + + varChecker("var3", + R"cpp( +VarDecl 'var3' +`-CXXConstructExpr + `-IntegerLiteral +)cpp", + R"cpp( +VarDecl 'var3' +`-CXXConstructExpr + `-IntegerLiteral +)cpp"); + + varChecker("var4", + R"cpp( +VarDecl 'var4' +`-CXXConstructExpr + |-IntegerLiteral + `-IntegerLiteral +)cpp", + R"cpp( +VarDecl 'var4' +`-CXXConstructExpr + |-IntegerLiteral + `-IntegerLiteral +)cpp"); + + varChecker("var5", + R"cpp( +VarDecl 'var5' +`-ExprWithCleanups + `-CXXConstructExpr + `-MaterializeTemporaryExpr + `-CXXFunctionalCastExpr + `-CXXConstructExpr + `-ImplicitCastExpr + `-DeclRefExpr 'i' +)cpp", + R"cpp( +VarDecl 'var5' +`-CXXConstructExpr + `-DeclRefExpr 'i' +)cpp"); + + varChecker("var6", + R"cpp( +VarDecl 'var6' +`-ExprWithCleanups + `-CXXConstructExpr + `-MaterializeTemporaryExpr + `-CXXTemporaryObjectExpr + |-ImplicitCastExpr + | `-DeclRefExpr 'i' + `-IntegerLiteral +)cpp", + R"cpp( +VarDecl 'var6' +`-CXXTemporaryObjectExpr + |-DeclRefExpr 'i' + `-IntegerLiteral +)cpp"); + + varChecker("var7", + R"cpp( +VarDecl 'var7' +`-CXXConstructExpr + `-ImplicitCastExpr + `-DeclRefExpr 'i' +)cpp", + R"cpp( +VarDecl 'var7' +`-CXXConstructExpr + `-DeclRefExpr 'i' +)cpp"); + + varChecker("var8", + R"cpp( +VarDecl 'var8' +`-CXXConstructExpr + |-ImplicitCastExpr + | `-DeclRefExpr 'i' + `-IntegerLiteral +)cpp", + R"cpp( +VarDecl 'var8' +`-CXXConstructExpr + |-DeclRefExpr 'i' + `-IntegerLiteral +)cpp"); } TEST(Traverse, IgnoreUnlessSpelledInSourceStructs) { @@ -647,7 +814,7 @@ FunctionDecl 'func3' `-CompoundStmt `-ReturnStmt - `-CXXFunctionalCastExpr + `-CXXConstructExpr `-IntegerLiteral )cpp"; EXPECT_EQ( diff --git a/clang/unittests/ASTMatchers/ASTMatchersTraversalTest.cpp b/clang/unittests/ASTMatchers/ASTMatchersTraversalTest.cpp --- a/clang/unittests/ASTMatchers/ASTMatchersTraversalTest.cpp +++ b/clang/unittests/ASTMatchers/ASTMatchersTraversalTest.cpp @@ -2088,6 +2088,98 @@ EXPECT_TRUE(matches(Code, traverse(TK_IgnoreUnlessSpelledInSource, staticAssertDecl(has(integerLiteral()))))); + + Code = R"cpp( + +struct OneParamCtor { + explicit OneParamCtor(int); +}; +struct TwoParamCtor { + explicit TwoParamCtor(int, int); +}; + +void varDeclCtors() { + { + auto var1 = OneParamCtor(5); + auto var2 = TwoParamCtor(6, 7); + } + { + OneParamCtor var3(5); + TwoParamCtor var4(6, 7); + } + int i = 0; + { + auto var5 = OneParamCtor(i); + auto var6 = TwoParamCtor(i, 7); + } + { + OneParamCtor var7(i); + TwoParamCtor var8(i, 7); + } +} + +)cpp"; + EXPECT_TRUE(matches( + Code, + traverse(TK_AsIs, varDecl(hasName("var1"), hasInitializer(hasDescendant( + cxxConstructExpr())))))); + EXPECT_TRUE(matches( + Code, + traverse(TK_AsIs, varDecl(hasName("var2"), hasInitializer(hasDescendant( + cxxConstructExpr())))))); + EXPECT_TRUE(matches( + Code, traverse(TK_AsIs, varDecl(hasName("var3"), + hasInitializer(cxxConstructExpr()))))); + EXPECT_TRUE(matches( + Code, traverse(TK_AsIs, varDecl(hasName("var4"), + hasInitializer(cxxConstructExpr()))))); + EXPECT_TRUE(matches( + Code, + traverse(TK_AsIs, varDecl(hasName("var5"), hasInitializer(hasDescendant( + cxxConstructExpr())))))); + EXPECT_TRUE(matches( + Code, + traverse(TK_AsIs, varDecl(hasName("var6"), hasInitializer(hasDescendant( + cxxConstructExpr())))))); + EXPECT_TRUE(matches( + Code, traverse(TK_AsIs, varDecl(hasName("var7"), + hasInitializer(cxxConstructExpr()))))); + EXPECT_TRUE(matches( + Code, traverse(TK_AsIs, varDecl(hasName("var8"), + hasInitializer(cxxConstructExpr()))))); + + EXPECT_TRUE(matches( + Code, + traverse(TK_IgnoreUnlessSpelledInSource, + varDecl(hasName("var1"), hasInitializer(cxxConstructExpr()))))); + EXPECT_TRUE(matches( + Code, + traverse(TK_IgnoreUnlessSpelledInSource, + varDecl(hasName("var2"), hasInitializer(cxxConstructExpr()))))); + EXPECT_TRUE(matches( + Code, + traverse(TK_IgnoreUnlessSpelledInSource, + varDecl(hasName("var3"), hasInitializer(cxxConstructExpr()))))); + EXPECT_TRUE(matches( + Code, + traverse(TK_IgnoreUnlessSpelledInSource, + varDecl(hasName("var4"), hasInitializer(cxxConstructExpr()))))); + EXPECT_TRUE(matches( + Code, + traverse(TK_IgnoreUnlessSpelledInSource, + varDecl(hasName("var5"), hasInitializer(cxxConstructExpr()))))); + EXPECT_TRUE(matches( + Code, + traverse(TK_IgnoreUnlessSpelledInSource, + varDecl(hasName("var6"), hasInitializer(cxxConstructExpr()))))); + EXPECT_TRUE(matches( + Code, + traverse(TK_IgnoreUnlessSpelledInSource, + varDecl(hasName("var7"), hasInitializer(cxxConstructExpr()))))); + EXPECT_TRUE(matches( + Code, + traverse(TK_IgnoreUnlessSpelledInSource, + varDecl(hasName("var8"), hasInitializer(cxxConstructExpr()))))); } template @@ -2293,21 +2385,20 @@ forFunction(functionDecl(hasName("func2"))))))))), langCxx20OrLater())); - EXPECT_TRUE(matches( - Code, - traverse( - TK_IgnoreUnlessSpelledInSource, - returnStmt(forFunction(functionDecl(hasName("func3"))), - hasReturnValue(cxxFunctionalCastExpr( - hasSourceExpression(integerLiteral(equals(42))))))), - langCxx20OrLater())); + EXPECT_TRUE( + matches(Code, + traverse(TK_IgnoreUnlessSpelledInSource, + returnStmt(forFunction(functionDecl(hasName("func3"))), + hasReturnValue(cxxConstructExpr(hasArgument( + 0, integerLiteral(equals(42))))))), + langCxx20OrLater())); EXPECT_TRUE(matches( Code, traverse( TK_IgnoreUnlessSpelledInSource, integerLiteral(equals(42), - hasParent(cxxFunctionalCastExpr(hasParent(returnStmt( + hasParent(cxxConstructExpr(hasParent(returnStmt( forFunction(functionDecl(hasName("func3"))))))))), langCxx20OrLater()));