[clang] 52ff86d - [AST] Fix traversal over CXXConstructExpr in Syntactic mode
Stephen Kelly via cfe-commits
cfe-commits at lists.llvm.org
Fri Oct 30 05:14:50 PDT 2020
Author: Stephen Kelly
Date: 2020-10-30T12:14:41Z
New Revision: 52ff86d25598175d3304498b14c0f6c780e46ae3
URL: https://github.com/llvm/llvm-project/commit/52ff86d25598175d3304498b14c0f6c780e46ae3
DIFF: https://github.com/llvm/llvm-project/commit/52ff86d25598175d3304498b14c0f6c780e46ae3.diff
LOG: [AST] Fix traversal over CXXConstructExpr in Syntactic mode
Summary:
Skip over elidable nodes, and ensure that intermediate
CXXFunctionalCastExpr nodes are also skipped if they are semantic.
Reviewers: klimek, ymandel
Subscribers: cfe-commits
Tags: #clang
Differential Revision: https://reviews.llvm.org/D82278
Added:
Modified:
clang/lib/AST/Expr.cpp
clang/lib/AST/ParentMapContext.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 c6b2c47a48fb..f55ee20f2476 100644
--- a/clang/lib/AST/Expr.cpp
+++ b/clang/lib/AST/Expr.cpp
@@ -2816,13 +2816,18 @@ Expr *Expr::IgnoreParenNoopCasts(const ASTContext &Ctx) {
Expr *Expr::IgnoreUnlessSpelledInSource() {
auto IgnoreImplicitConstructorSingleStep = [](Expr *E) {
+ if (auto *Cast = dyn_cast<CXXFunctionalCastExpr>(E)) {
+ auto *SE = Cast->getSubExpr();
+ if (SE->getSourceRange() == E->getSourceRange())
+ return SE;
+ }
+
if (auto *C = dyn_cast<CXXConstructExpr>(E)) {
auto NumArgs = C->getNumArgs();
if (NumArgs == 1 ||
(NumArgs > 1 && isa<CXXDefaultArgExpr>(C->getArg(1)))) {
Expr *A = C->getArg(0);
- if (A->getSourceRange() == E->getSourceRange() ||
- !isa<CXXTemporaryObjectExpr>(C))
+ if (A->getSourceRange() == E->getSourceRange() || C->isElidable())
return A;
}
}
diff --git a/clang/lib/AST/ParentMapContext.cpp b/clang/lib/AST/ParentMapContext.cpp
index bae4d016ff6b..c80c8bc23e00 100644
--- a/clang/lib/AST/ParentMapContext.cpp
+++ b/clang/lib/AST/ParentMapContext.cpp
@@ -154,8 +154,13 @@ class ParentMapContext::ParentMap {
auto SR = Child->getSourceRange();
+ if (const auto *C = dyn_cast<CXXFunctionalCastExpr>(E)) {
+ if (C->getSourceRange() == SR)
+ return true;
+ }
+
if (const auto *C = dyn_cast<CXXConstructExpr>(E)) {
- if (C->getSourceRange() == SR || !isa<CXXTemporaryObjectExpr>(C))
+ if (C->getSourceRange() == SR || C->isElidable())
return true;
}
diff --git a/clang/unittests/AST/ASTTraverserTest.cpp b/clang/unittests/AST/ASTTraverserTest.cpp
index 2f131c3fd04f..c24b43164cc8 100644
--- a/clang/unittests/AST/ASTTraverserTest.cpp
+++ b/clang/unittests/AST/ASTTraverserTest.cpp
@@ -299,6 +299,34 @@ void template_test() {
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 @@ StaticAssertDecl
`-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<Decl>("varDeclCtor")),
+ SemanticDump);
+
+ EXPECT_EQ(dumpASTString(TK_IgnoreUnlessSpelledInSource,
+ FN[0].getNodeAs<Decl>("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 'func2'
FunctionDecl 'func3'
`-CompoundStmt
`-ReturnStmt
- `-CXXFunctionalCastExpr
+ `-CXXConstructExpr
`-IntegerLiteral
)cpp";
EXPECT_EQ(
diff --git a/clang/unittests/ASTMatchers/ASTMatchersTraversalTest.cpp b/clang/unittests/ASTMatchers/ASTMatchersTraversalTest.cpp
index 39222fbe4249..ee4fb032dd51 100644
--- a/clang/unittests/ASTMatchers/ASTMatchersTraversalTest.cpp
+++ b/clang/unittests/ASTMatchers/ASTMatchersTraversalTest.cpp
@@ -2088,6 +2088,98 @@ void actual_template_test() {
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 <typename MatcherT>
@@ -2293,21 +2385,20 @@ void func14() {
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()));
More information about the cfe-commits
mailing list