[clang] aa5d2d2 - Traverse-ignore invisible CXXConstructExprs with default args

Stephen Kelly via cfe-commits cfe-commits at lists.llvm.org
Fri May 22 17:06:07 PDT 2020


Author: Stephen Kelly
Date: 2020-05-23T01:04:44+01:00
New Revision: aa5d2d22485470365cc8f7016c1be672a273c2fe

URL: https://github.com/llvm/llvm-project/commit/aa5d2d22485470365cc8f7016c1be672a273c2fe
DIFF: https://github.com/llvm/llvm-project/commit/aa5d2d22485470365cc8f7016c1be672a273c2fe.diff

LOG: Traverse-ignore invisible CXXConstructExprs with default args

Added: 
    

Modified: 
    clang/lib/AST/Expr.cpp
    clang/unittests/AST/ASTTraverserTest.cpp
    clang/unittests/ASTMatchers/ASTMatchersTraversalTest.cpp

Removed: 
    


################################################################################
diff  --git a/clang/lib/AST/Expr.cpp b/clang/lib/AST/Expr.cpp
index 468540ddf06f..7b1badf133f9 100644
--- a/clang/lib/AST/Expr.cpp
+++ b/clang/lib/AST/Expr.cpp
@@ -2915,7 +2915,9 @@ Expr *Expr::IgnoreUnlessSpelledInSource() {
     auto SR = E->getSourceRange();
 
     if (auto *C = dyn_cast<CXXConstructExpr>(E)) {
-      if (C->getNumArgs() == 1) {
+      auto NumArgs = C->getNumArgs();
+      if (NumArgs == 1 ||
+          (NumArgs > 1 && isa<CXXDefaultArgExpr>(C->getArg(1)))) {
         Expr *A = C->getArg(0);
         if (A->getSourceRange() == SR || !isa<CXXTemporaryObjectExpr>(C))
           E = A;

diff  --git a/clang/unittests/AST/ASTTraverserTest.cpp b/clang/unittests/AST/ASTTraverserTest.cpp
index 4ecb02325d6a..9a951c7bec5e 100644
--- a/clang/unittests/AST/ASTTraverserTest.cpp
+++ b/clang/unittests/AST/ASTTraverserTest.cpp
@@ -258,6 +258,71 @@ TemplateArgument
             19u);
 }
 
+TEST(Traverse, IgnoreUnlessSpelledInSourceVars) {
+
+  auto AST = buildASTFromCode(R"cpp(
+
+struct String
+{
+    String(const char*, int = -1) {}
+};
+
+void stringConstruct()
+{
+    String s = "foo";
+    s = "bar";
+}
+
+)cpp");
+
+  {
+    auto FN =
+        ast_matchers::match(functionDecl(hasName("stringConstruct")).bind("fn"),
+                            AST->getASTContext());
+    EXPECT_EQ(FN.size(), 1u);
+
+    EXPECT_EQ(dumpASTString(TK_AsIs, FN[0].getNodeAs<Decl>("fn")),
+              R"cpp(
+FunctionDecl 'stringConstruct'
+`-CompoundStmt
+  |-DeclStmt
+  | `-VarDecl 's'
+  |   `-ExprWithCleanups
+  |     `-CXXConstructExpr
+  |       `-MaterializeTemporaryExpr
+  |         `-ImplicitCastExpr
+  |           `-CXXConstructExpr
+  |             |-ImplicitCastExpr
+  |             | `-StringLiteral
+  |             `-CXXDefaultArgExpr
+  `-ExprWithCleanups
+    `-CXXOperatorCallExpr
+      |-ImplicitCastExpr
+      | `-DeclRefExpr 'operator='
+      |-DeclRefExpr 's'
+      `-MaterializeTemporaryExpr
+        `-CXXConstructExpr
+          |-ImplicitCastExpr
+          | `-StringLiteral
+          `-CXXDefaultArgExpr
+)cpp");
+
+    EXPECT_EQ(dumpASTString(TK_IgnoreUnlessSpelledInSource,
+                            FN[0].getNodeAs<Decl>("fn")),
+              R"cpp(
+FunctionDecl 'stringConstruct'
+`-CompoundStmt
+  |-DeclStmt
+  | `-VarDecl 's'
+  |   `-StringLiteral
+  `-CXXOperatorCallExpr
+    |-DeclRefExpr 'operator='
+    |-DeclRefExpr 's'
+    `-StringLiteral
+)cpp");
+  }
+}
+
 TEST(Traverse, IgnoreUnlessSpelledInSourceStructs) {
   auto AST = buildASTFromCode(R"cpp(
 

diff  --git a/clang/unittests/ASTMatchers/ASTMatchersTraversalTest.cpp b/clang/unittests/ASTMatchers/ASTMatchersTraversalTest.cpp
index 2a36d7a64efd..b4b7e2b43cf7 100644
--- a/clang/unittests/ASTMatchers/ASTMatchersTraversalTest.cpp
+++ b/clang/unittests/ASTMatchers/ASTMatchersTraversalTest.cpp
@@ -1780,6 +1780,55 @@ const char *SomeString{"str"};
   EXPECT_TRUE(
       matches(Code, traverse(TK_IgnoreUnlessSpelledInSource,
                              stringLiteral(hasParent(initListExpr())))));
+
+  Code = R"cpp(
+struct String
+{
+    String(const char*, int = -1) {}
+};
+
+void stringConstruct()
+{
+    String s = "foo";
+    s = "bar";
+}
+)cpp";
+  EXPECT_TRUE(matches(
+      Code,
+      traverse(
+          TK_AsIs,
+          functionDecl(
+              hasName("stringConstruct"),
+              hasDescendant(varDecl(
+                  hasName("s"),
+                  hasInitializer(ignoringImplicit(cxxConstructExpr(hasArgument(
+                      0, ignoringImplicit(cxxConstructExpr(hasArgument(
+                             0, ignoringImplicit(stringLiteral()))))))))))))));
+
+  EXPECT_TRUE(matches(
+      Code,
+      traverse(
+          TK_AsIs,
+          functionDecl(hasName("stringConstruct"),
+                       hasDescendant(cxxOperatorCallExpr(
+                           isAssignmentOperator(),
+                           hasArgument(1, ignoringImplicit(
+                            cxxConstructExpr(hasArgument(
+                               0, ignoringImplicit(stringLiteral())))))
+                           ))))));
+
+  EXPECT_TRUE(matches(
+      Code, traverse(TK_IgnoreUnlessSpelledInSource,
+                     functionDecl(hasName("stringConstruct"),
+                                  hasDescendant(varDecl(
+                                      hasName("s"),
+                                      hasInitializer(stringLiteral())))))));
+  EXPECT_TRUE(
+      matches(Code, traverse(TK_IgnoreUnlessSpelledInSource,
+                             functionDecl(hasName("stringConstruct"),
+                                          hasDescendant(cxxOperatorCallExpr(
+                                              isAssignmentOperator(),
+                                              hasArgument(1, stringLiteral())))))));
 }
 
 template <typename MatcherT>


        


More information about the cfe-commits mailing list