Skip to content

Commit e569adf

Browse files
steveirememfrob
authored andcommitted
[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
1 parent 6cb85e9 commit e569adf

File tree

4 files changed

+281
-13
lines changed

4 files changed

+281
-13
lines changed

clang/lib/AST/Expr.cpp

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2816,13 +2816,18 @@ Expr *Expr::IgnoreParenNoopCasts(const ASTContext &Ctx) {
28162816

28172817
Expr *Expr::IgnoreUnlessSpelledInSource() {
28182818
auto IgnoreImplicitConstructorSingleStep = [](Expr *E) {
2819+
if (auto *Cast = dyn_cast<CXXFunctionalCastExpr>(E)) {
2820+
auto *SE = Cast->getSubExpr();
2821+
if (SE->getSourceRange() == E->getSourceRange())
2822+
return SE;
2823+
}
2824+
28192825
if (auto *C = dyn_cast<CXXConstructExpr>(E)) {
28202826
auto NumArgs = C->getNumArgs();
28212827
if (NumArgs == 1 ||
28222828
(NumArgs > 1 && isa<CXXDefaultArgExpr>(C->getArg(1)))) {
28232829
Expr *A = C->getArg(0);
2824-
if (A->getSourceRange() == E->getSourceRange() ||
2825-
!isa<CXXTemporaryObjectExpr>(C))
2830+
if (A->getSourceRange() == E->getSourceRange() || C->isElidable())
28262831
return A;
28272832
}
28282833
}

clang/lib/AST/ParentMapContext.cpp

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -154,8 +154,13 @@ class ParentMapContext::ParentMap {
154154

155155
auto SR = Child->getSourceRange();
156156

157+
if (const auto *C = dyn_cast<CXXFunctionalCastExpr>(E)) {
158+
if (C->getSourceRange() == SR)
159+
return true;
160+
}
161+
157162
if (const auto *C = dyn_cast<CXXConstructExpr>(E)) {
158-
if (C->getSourceRange() == SR || !isa<CXXTemporaryObjectExpr>(C))
163+
if (C->getSourceRange() == SR || C->isElidable())
159164
return true;
160165
}
161166

clang/unittests/AST/ASTTraverserTest.cpp

Lines changed: 168 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -299,6 +299,34 @@ void template_test() {
299299
void actual_template_test() {
300300
template_test<4>();
301301
}
302+
303+
struct OneParamCtor {
304+
explicit OneParamCtor(int);
305+
};
306+
struct TwoParamCtor {
307+
explicit TwoParamCtor(int, int);
308+
};
309+
310+
void varDeclCtors() {
311+
{
312+
auto var1 = OneParamCtor(5);
313+
auto var2 = TwoParamCtor(6, 7);
314+
}
315+
{
316+
OneParamCtor var3(5);
317+
TwoParamCtor var4(6, 7);
318+
}
319+
int i = 0;
320+
{
321+
auto var5 = OneParamCtor(i);
322+
auto var6 = TwoParamCtor(i, 7);
323+
}
324+
{
325+
OneParamCtor var7(i);
326+
TwoParamCtor var8(i, 7);
327+
}
328+
}
329+
302330
)cpp");
303331

304332
{
@@ -444,6 +472,145 @@ StaticAssertDecl
444472
`-StringLiteral
445473
)cpp");
446474
}
475+
476+
auto varChecker = [&AST](StringRef varName, StringRef SemanticDump,
477+
StringRef SyntacticDump) {
478+
auto FN = ast_matchers::match(
479+
functionDecl(
480+
hasName("varDeclCtors"),
481+
forEachDescendant(varDecl(hasName(varName)).bind("varDeclCtor"))),
482+
AST->getASTContext());
483+
EXPECT_EQ(FN.size(), 1u);
484+
485+
EXPECT_EQ(dumpASTString(TK_AsIs, FN[0].getNodeAs<Decl>("varDeclCtor")),
486+
SemanticDump);
487+
488+
EXPECT_EQ(dumpASTString(TK_IgnoreUnlessSpelledInSource,
489+
FN[0].getNodeAs<Decl>("varDeclCtor")),
490+
SyntacticDump);
491+
};
492+
493+
varChecker("var1",
494+
R"cpp(
495+
VarDecl 'var1'
496+
`-ExprWithCleanups
497+
`-CXXConstructExpr
498+
`-MaterializeTemporaryExpr
499+
`-CXXFunctionalCastExpr
500+
`-CXXConstructExpr
501+
`-IntegerLiteral
502+
)cpp",
503+
R"cpp(
504+
VarDecl 'var1'
505+
`-CXXConstructExpr
506+
`-IntegerLiteral
507+
)cpp");
508+
509+
varChecker("var2",
510+
R"cpp(
511+
VarDecl 'var2'
512+
`-ExprWithCleanups
513+
`-CXXConstructExpr
514+
`-MaterializeTemporaryExpr
515+
`-CXXTemporaryObjectExpr
516+
|-IntegerLiteral
517+
`-IntegerLiteral
518+
)cpp",
519+
R"cpp(
520+
VarDecl 'var2'
521+
`-CXXTemporaryObjectExpr
522+
|-IntegerLiteral
523+
`-IntegerLiteral
524+
)cpp");
525+
526+
varChecker("var3",
527+
R"cpp(
528+
VarDecl 'var3'
529+
`-CXXConstructExpr
530+
`-IntegerLiteral
531+
)cpp",
532+
R"cpp(
533+
VarDecl 'var3'
534+
`-CXXConstructExpr
535+
`-IntegerLiteral
536+
)cpp");
537+
538+
varChecker("var4",
539+
R"cpp(
540+
VarDecl 'var4'
541+
`-CXXConstructExpr
542+
|-IntegerLiteral
543+
`-IntegerLiteral
544+
)cpp",
545+
R"cpp(
546+
VarDecl 'var4'
547+
`-CXXConstructExpr
548+
|-IntegerLiteral
549+
`-IntegerLiteral
550+
)cpp");
551+
552+
varChecker("var5",
553+
R"cpp(
554+
VarDecl 'var5'
555+
`-ExprWithCleanups
556+
`-CXXConstructExpr
557+
`-MaterializeTemporaryExpr
558+
`-CXXFunctionalCastExpr
559+
`-CXXConstructExpr
560+
`-ImplicitCastExpr
561+
`-DeclRefExpr 'i'
562+
)cpp",
563+
R"cpp(
564+
VarDecl 'var5'
565+
`-CXXConstructExpr
566+
`-DeclRefExpr 'i'
567+
)cpp");
568+
569+
varChecker("var6",
570+
R"cpp(
571+
VarDecl 'var6'
572+
`-ExprWithCleanups
573+
`-CXXConstructExpr
574+
`-MaterializeTemporaryExpr
575+
`-CXXTemporaryObjectExpr
576+
|-ImplicitCastExpr
577+
| `-DeclRefExpr 'i'
578+
`-IntegerLiteral
579+
)cpp",
580+
R"cpp(
581+
VarDecl 'var6'
582+
`-CXXTemporaryObjectExpr
583+
|-DeclRefExpr 'i'
584+
`-IntegerLiteral
585+
)cpp");
586+
587+
varChecker("var7",
588+
R"cpp(
589+
VarDecl 'var7'
590+
`-CXXConstructExpr
591+
`-ImplicitCastExpr
592+
`-DeclRefExpr 'i'
593+
)cpp",
594+
R"cpp(
595+
VarDecl 'var7'
596+
`-CXXConstructExpr
597+
`-DeclRefExpr 'i'
598+
)cpp");
599+
600+
varChecker("var8",
601+
R"cpp(
602+
VarDecl 'var8'
603+
`-CXXConstructExpr
604+
|-ImplicitCastExpr
605+
| `-DeclRefExpr 'i'
606+
`-IntegerLiteral
607+
)cpp",
608+
R"cpp(
609+
VarDecl 'var8'
610+
`-CXXConstructExpr
611+
|-DeclRefExpr 'i'
612+
`-IntegerLiteral
613+
)cpp");
447614
}
448615

449616
TEST(Traverse, IgnoreUnlessSpelledInSourceStructs) {
@@ -647,7 +814,7 @@ FunctionDecl 'func2'
647814
FunctionDecl 'func3'
648815
`-CompoundStmt
649816
`-ReturnStmt
650-
`-CXXFunctionalCastExpr
817+
`-CXXConstructExpr
651818
`-IntegerLiteral
652819
)cpp";
653820
EXPECT_EQ(

clang/unittests/ASTMatchers/ASTMatchersTraversalTest.cpp

Lines changed: 100 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -2088,6 +2088,98 @@ void actual_template_test() {
20882088

20892089
EXPECT_TRUE(matches(Code, traverse(TK_IgnoreUnlessSpelledInSource,
20902090
staticAssertDecl(has(integerLiteral())))));
2091+
2092+
Code = R"cpp(
2093+
2094+
struct OneParamCtor {
2095+
explicit OneParamCtor(int);
2096+
};
2097+
struct TwoParamCtor {
2098+
explicit TwoParamCtor(int, int);
2099+
};
2100+
2101+
void varDeclCtors() {
2102+
{
2103+
auto var1 = OneParamCtor(5);
2104+
auto var2 = TwoParamCtor(6, 7);
2105+
}
2106+
{
2107+
OneParamCtor var3(5);
2108+
TwoParamCtor var4(6, 7);
2109+
}
2110+
int i = 0;
2111+
{
2112+
auto var5 = OneParamCtor(i);
2113+
auto var6 = TwoParamCtor(i, 7);
2114+
}
2115+
{
2116+
OneParamCtor var7(i);
2117+
TwoParamCtor var8(i, 7);
2118+
}
2119+
}
2120+
2121+
)cpp";
2122+
EXPECT_TRUE(matches(
2123+
Code,
2124+
traverse(TK_AsIs, varDecl(hasName("var1"), hasInitializer(hasDescendant(
2125+
cxxConstructExpr()))))));
2126+
EXPECT_TRUE(matches(
2127+
Code,
2128+
traverse(TK_AsIs, varDecl(hasName("var2"), hasInitializer(hasDescendant(
2129+
cxxConstructExpr()))))));
2130+
EXPECT_TRUE(matches(
2131+
Code, traverse(TK_AsIs, varDecl(hasName("var3"),
2132+
hasInitializer(cxxConstructExpr())))));
2133+
EXPECT_TRUE(matches(
2134+
Code, traverse(TK_AsIs, varDecl(hasName("var4"),
2135+
hasInitializer(cxxConstructExpr())))));
2136+
EXPECT_TRUE(matches(
2137+
Code,
2138+
traverse(TK_AsIs, varDecl(hasName("var5"), hasInitializer(hasDescendant(
2139+
cxxConstructExpr()))))));
2140+
EXPECT_TRUE(matches(
2141+
Code,
2142+
traverse(TK_AsIs, varDecl(hasName("var6"), hasInitializer(hasDescendant(
2143+
cxxConstructExpr()))))));
2144+
EXPECT_TRUE(matches(
2145+
Code, traverse(TK_AsIs, varDecl(hasName("var7"),
2146+
hasInitializer(cxxConstructExpr())))));
2147+
EXPECT_TRUE(matches(
2148+
Code, traverse(TK_AsIs, varDecl(hasName("var8"),
2149+
hasInitializer(cxxConstructExpr())))));
2150+
2151+
EXPECT_TRUE(matches(
2152+
Code,
2153+
traverse(TK_IgnoreUnlessSpelledInSource,
2154+
varDecl(hasName("var1"), hasInitializer(cxxConstructExpr())))));
2155+
EXPECT_TRUE(matches(
2156+
Code,
2157+
traverse(TK_IgnoreUnlessSpelledInSource,
2158+
varDecl(hasName("var2"), hasInitializer(cxxConstructExpr())))));
2159+
EXPECT_TRUE(matches(
2160+
Code,
2161+
traverse(TK_IgnoreUnlessSpelledInSource,
2162+
varDecl(hasName("var3"), hasInitializer(cxxConstructExpr())))));
2163+
EXPECT_TRUE(matches(
2164+
Code,
2165+
traverse(TK_IgnoreUnlessSpelledInSource,
2166+
varDecl(hasName("var4"), hasInitializer(cxxConstructExpr())))));
2167+
EXPECT_TRUE(matches(
2168+
Code,
2169+
traverse(TK_IgnoreUnlessSpelledInSource,
2170+
varDecl(hasName("var5"), hasInitializer(cxxConstructExpr())))));
2171+
EXPECT_TRUE(matches(
2172+
Code,
2173+
traverse(TK_IgnoreUnlessSpelledInSource,
2174+
varDecl(hasName("var6"), hasInitializer(cxxConstructExpr())))));
2175+
EXPECT_TRUE(matches(
2176+
Code,
2177+
traverse(TK_IgnoreUnlessSpelledInSource,
2178+
varDecl(hasName("var7"), hasInitializer(cxxConstructExpr())))));
2179+
EXPECT_TRUE(matches(
2180+
Code,
2181+
traverse(TK_IgnoreUnlessSpelledInSource,
2182+
varDecl(hasName("var8"), hasInitializer(cxxConstructExpr())))));
20912183
}
20922184

20932185
template <typename MatcherT>
@@ -2293,21 +2385,20 @@ void func14() {
22932385
forFunction(functionDecl(hasName("func2"))))))))),
22942386
langCxx20OrLater()));
22952387

2296-
EXPECT_TRUE(matches(
2297-
Code,
2298-
traverse(
2299-
TK_IgnoreUnlessSpelledInSource,
2300-
returnStmt(forFunction(functionDecl(hasName("func3"))),
2301-
hasReturnValue(cxxFunctionalCastExpr(
2302-
hasSourceExpression(integerLiteral(equals(42))))))),
2303-
langCxx20OrLater()));
2388+
EXPECT_TRUE(
2389+
matches(Code,
2390+
traverse(TK_IgnoreUnlessSpelledInSource,
2391+
returnStmt(forFunction(functionDecl(hasName("func3"))),
2392+
hasReturnValue(cxxConstructExpr(hasArgument(
2393+
0, integerLiteral(equals(42))))))),
2394+
langCxx20OrLater()));
23042395

23052396
EXPECT_TRUE(matches(
23062397
Code,
23072398
traverse(
23082399
TK_IgnoreUnlessSpelledInSource,
23092400
integerLiteral(equals(42),
2310-
hasParent(cxxFunctionalCastExpr(hasParent(returnStmt(
2401+
hasParent(cxxConstructExpr(hasParent(returnStmt(
23112402
forFunction(functionDecl(hasName("func3"))))))))),
23122403
langCxx20OrLater()));
23132404

0 commit comments

Comments
 (0)