Traverse-ignore invisible CXXConstructExprs with default args

This commit is contained in:
Stephen Kelly 2020-05-22 00:23:59 +01:00
parent a8a048ac72
commit aa5d2d2248
3 changed files with 117 additions and 1 deletions

View File

@ -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;

View File

@ -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(

View File

@ -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>