forked from OSchip/llvm-project
Make sure TraverseInitListExpr visits InitListExpr exactly twice
... once each for the syntactic and semantic form. Without this fix, behavior of the newly added tests would have been InitListExprIsPreOrderVisitedTwice: syntactic: 1 semantic: 2 InitListExprIsPostOrderVisitedTwice: syntactic: 0 semantic: 1 InitListExprIsPreOrderNoQueueVisitedTwice: syntactic: 1 semantic: 2 InitListExprIsPostOrderNoQueueVisitedTwice: syntactic: 0 semantic: 2 llvm-svn: 306374
This commit is contained in:
parent
83e6a82636
commit
a504c433f1
|
@ -593,6 +593,16 @@ bool RecursiveASTVisitor<Derived>::PostVisitStmt(Stmt *S) {
|
|||
#define STMT(CLASS, PARENT) \
|
||||
case Stmt::CLASS##Class: \
|
||||
TRY_TO(WalkUpFrom##CLASS(static_cast<CLASS *>(S))); break;
|
||||
#define INITLISTEXPR(CLASS, PARENT) \
|
||||
case Stmt::CLASS##Class: \
|
||||
{ \
|
||||
auto ILE = static_cast<CLASS *>(S); \
|
||||
if (auto Syn = ILE->isSemanticForm() ? ILE->getSyntacticForm() : ILE) \
|
||||
TRY_TO(WalkUpFrom##CLASS(Syn)); \
|
||||
if (auto Sem = ILE->isSemanticForm() ? ILE : ILE->getSemanticForm()) \
|
||||
TRY_TO(WalkUpFrom##CLASS(Sem)); \
|
||||
break; \
|
||||
}
|
||||
#include "clang/AST/StmtNodes.inc"
|
||||
}
|
||||
|
||||
|
@ -2220,13 +2230,15 @@ bool RecursiveASTVisitor<Derived>::TraverseSynOrSemInitListExpr(
|
|||
// the syntactic and the semantic form.
|
||||
//
|
||||
// There is no guarantee about which form \p S takes when this method is called.
|
||||
DEF_TRAVERSE_STMT(InitListExpr, {
|
||||
template <typename Derived>
|
||||
bool RecursiveASTVisitor<Derived>::TraverseInitListExpr(
|
||||
InitListExpr *S, DataRecursionQueue *Queue) {
|
||||
TRY_TO(TraverseSynOrSemInitListExpr(
|
||||
S->isSemanticForm() ? S->getSyntacticForm() : S, Queue));
|
||||
TRY_TO(TraverseSynOrSemInitListExpr(
|
||||
S->isSemanticForm() ? S : S->getSemanticForm(), Queue));
|
||||
ShouldVisitChildren = false;
|
||||
})
|
||||
return true;
|
||||
}
|
||||
|
||||
// GenericSelectionExpr is a special case because the types and expressions
|
||||
// are interleaved. We also need to watch out for null types (default
|
||||
|
|
|
@ -158,4 +158,90 @@ TEST(RecursiveASTVisitor, DefaultArgumentsAreVisited) {
|
|||
"static int k = f();\n"));
|
||||
}
|
||||
|
||||
// Check to ensure that InitListExpr is visited twice, once each for the
|
||||
// syntactic and semantic form.
|
||||
class InitListExprPreOrderVisitor
|
||||
: public ExpectedLocationVisitor<InitListExprPreOrderVisitor> {
|
||||
public:
|
||||
bool VisitInitListExpr(InitListExpr *ILE) {
|
||||
Match(ILE->isSemanticForm() ? "semantic" : "syntactic", ILE->getLocStart());
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
class InitListExprPostOrderVisitor
|
||||
: public ExpectedLocationVisitor<InitListExprPostOrderVisitor> {
|
||||
public:
|
||||
bool shouldTraversePostOrder() const { return true; }
|
||||
|
||||
bool VisitInitListExpr(InitListExpr *ILE) {
|
||||
Match(ILE->isSemanticForm() ? "semantic" : "syntactic", ILE->getLocStart());
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
class InitListExprPreOrderNoQueueVisitor
|
||||
: public ExpectedLocationVisitor<InitListExprPreOrderNoQueueVisitor> {
|
||||
public:
|
||||
bool TraverseInitListExpr(InitListExpr *ILE) {
|
||||
return ExpectedLocationVisitor::TraverseInitListExpr(ILE);
|
||||
}
|
||||
|
||||
bool VisitInitListExpr(InitListExpr *ILE) {
|
||||
Match(ILE->isSemanticForm() ? "semantic" : "syntactic", ILE->getLocStart());
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
class InitListExprPostOrderNoQueueVisitor
|
||||
: public ExpectedLocationVisitor<InitListExprPostOrderNoQueueVisitor> {
|
||||
public:
|
||||
bool shouldTraversePostOrder() const { return true; }
|
||||
|
||||
bool TraverseInitListExpr(InitListExpr *ILE) {
|
||||
return ExpectedLocationVisitor::TraverseInitListExpr(ILE);
|
||||
}
|
||||
|
||||
bool VisitInitListExpr(InitListExpr *ILE) {
|
||||
Match(ILE->isSemanticForm() ? "semantic" : "syntactic", ILE->getLocStart());
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
TEST(RecursiveASTVisitor, InitListExprIsPreOrderVisitedTwice) {
|
||||
InitListExprPreOrderVisitor Visitor;
|
||||
Visitor.ExpectMatch("syntactic", 2, 21);
|
||||
Visitor.ExpectMatch("semantic", 2, 21);
|
||||
EXPECT_TRUE(Visitor.runOver("struct S { int x; };\n"
|
||||
"static struct S s = {.x = 0};\n",
|
||||
InitListExprPreOrderVisitor::Lang_C));
|
||||
}
|
||||
|
||||
TEST(RecursiveASTVisitor, InitListExprIsPostOrderVisitedTwice) {
|
||||
InitListExprPostOrderVisitor Visitor;
|
||||
Visitor.ExpectMatch("syntactic", 2, 21);
|
||||
Visitor.ExpectMatch("semantic", 2, 21);
|
||||
EXPECT_TRUE(Visitor.runOver("struct S { int x; };\n"
|
||||
"static struct S s = {.x = 0};\n",
|
||||
InitListExprPostOrderVisitor::Lang_C));
|
||||
}
|
||||
|
||||
TEST(RecursiveASTVisitor, InitListExprIsPreOrderNoQueueVisitedTwice) {
|
||||
InitListExprPreOrderNoQueueVisitor Visitor;
|
||||
Visitor.ExpectMatch("syntactic", 2, 21);
|
||||
Visitor.ExpectMatch("semantic", 2, 21);
|
||||
EXPECT_TRUE(Visitor.runOver("struct S { int x; };\n"
|
||||
"static struct S s = {.x = 0};\n",
|
||||
InitListExprPreOrderNoQueueVisitor::Lang_C));
|
||||
}
|
||||
|
||||
TEST(RecursiveASTVisitor, InitListExprIsPostOrderNoQueueVisitedTwice) {
|
||||
InitListExprPostOrderNoQueueVisitor Visitor;
|
||||
Visitor.ExpectMatch("syntactic", 2, 21);
|
||||
Visitor.ExpectMatch("semantic", 2, 21);
|
||||
EXPECT_TRUE(Visitor.runOver("struct S { int x; };\n"
|
||||
"static struct S s = {.x = 0};\n",
|
||||
InitListExprPostOrderNoQueueVisitor::Lang_C));
|
||||
}
|
||||
|
||||
} // end anonymous namespace
|
||||
|
|
Loading…
Reference in New Issue