Complete support for the cxxCtorInitializer() AST matcher so that it can be used as a top-level matcher.

llvm-svn: 282417
This commit is contained in:
Aaron Ballman 2016-09-26 17:04:27 +00:00
parent b3d2546c43
commit 5fa302cb65
4 changed files with 47 additions and 0 deletions

View File

@ -158,6 +158,8 @@ public:
MatchCallback *Action);
void addMatcher(const TypeLocMatcher &NodeMatch,
MatchCallback *Action);
void addMatcher(const CXXCtorInitializerMatcher &NodeMatch,
MatchCallback *Action);
/// @}
/// \brief Adds a matcher to execute when running over the AST.
@ -208,6 +210,7 @@ public:
std::vector<std::pair<NestedNameSpecifierLocMatcher, MatchCallback *>>
NestedNameSpecifierLoc;
std::vector<std::pair<TypeLocMatcher, MatchCallback *>> TypeLoc;
std::vector<std::pair<CXXCtorInitializerMatcher, MatchCallback *>> CtorInit;
/// \brief All the callbacks in one container to simplify iteration.
llvm::SmallPtrSet<MatchCallback *, 16> AllCallbacks;
};

View File

@ -125,6 +125,7 @@ typedef internal::Matcher<QualType> TypeMatcher;
typedef internal::Matcher<TypeLoc> TypeLocMatcher;
typedef internal::Matcher<NestedNameSpecifier> NestedNameSpecifierMatcher;
typedef internal::Matcher<NestedNameSpecifierLoc> NestedNameSpecifierLocMatcher;
typedef internal::Matcher<CXXCtorInitializer> CXXCtorInitializerMatcher;
/// @}
/// \brief Matches any node.

View File

@ -126,6 +126,8 @@ public:
traverse(*Q);
else if (const TypeLoc *T = DynNode.get<TypeLoc>())
traverse(*T);
else if (const auto *C = DynNode.get<CXXCtorInitializer>())
traverse(*C);
// FIXME: Add other base types after adding tests.
// It's OK to always overwrite the bound nodes, as if there was
@ -194,6 +196,12 @@ public:
return false;
return traverse(NNS);
}
bool TraverseConstructorInitializer(CXXCtorInitializer *CtorInit) {
if (!CtorInit)
return true;
ScopedIncrement ScopedDepth(&CurrentDepth);
return traverse(*CtorInit);
}
bool shouldVisitTemplateInstantiations() const { return true; }
bool shouldVisitImplicitCode() const { return true; }
@ -235,6 +243,10 @@ private:
bool baseTraverse(NestedNameSpecifierLoc NNS) {
return VisitorBase::TraverseNestedNameSpecifierLoc(NNS);
}
bool baseTraverse(const CXXCtorInitializer &CtorInit) {
return VisitorBase::TraverseConstructorInitializer(
const_cast<CXXCtorInitializer *>(&CtorInit));
}
// Sets 'Matched' to true if 'Matcher' matches 'Node' and:
// 0 < CurrentDepth <= MaxDepth.
@ -371,6 +383,7 @@ public:
bool TraverseTypeLoc(TypeLoc TypeNode);
bool TraverseNestedNameSpecifier(NestedNameSpecifier *NNS);
bool TraverseNestedNameSpecifierLoc(NestedNameSpecifierLoc NNS);
bool TraverseConstructorInitializer(CXXCtorInitializer *CtorInit);
// Matches children or descendants of 'Node' with 'BaseMatcher'.
bool memoizedMatchesRecursively(const ast_type_traits::DynTypedNode &Node,
@ -472,6 +485,8 @@ public:
match(*N);
} else if (auto *N = Node.get<TypeLoc>()) {
match(*N);
} else if (auto *N = Node.get<CXXCtorInitializer>()) {
match(*N);
}
}
@ -593,6 +608,9 @@ private:
void matchDispatch(const NestedNameSpecifierLoc *Node) {
matchWithoutFilter(*Node, Matchers->NestedNameSpecifierLoc);
}
void matchDispatch(const CXXCtorInitializer *Node) {
matchWithoutFilter(*Node, Matchers->CtorInit);
}
void matchDispatch(const void *) { /* Do nothing. */ }
/// @}
@ -864,6 +882,17 @@ bool MatchASTVisitor::TraverseNestedNameSpecifierLoc(
RecursiveASTVisitor<MatchASTVisitor>::TraverseNestedNameSpecifierLoc(NNS);
}
bool MatchASTVisitor::TraverseConstructorInitializer(
CXXCtorInitializer *CtorInit) {
if (!CtorInit)
return true;
match(*CtorInit);
return RecursiveASTVisitor<MatchASTVisitor>::TraverseConstructorInitializer(
CtorInit);
}
class MatchASTConsumer : public ASTConsumer {
public:
MatchASTConsumer(MatchFinder *Finder,
@ -934,6 +963,12 @@ void MatchFinder::addMatcher(const TypeLocMatcher &NodeMatch,
Matchers.AllCallbacks.insert(Action);
}
void MatchFinder::addMatcher(const CXXCtorInitializerMatcher &NodeMatch,
MatchCallback *Action) {
Matchers.CtorInit.emplace_back(NodeMatch, Action);
Matchers.AllCallbacks.insert(Action);
}
bool MatchFinder::addDynamicMatcher(const internal::DynTypedMatcher &NodeMatch,
MatchCallback *Action) {
if (NodeMatch.canConvertTo<Decl>()) {
@ -954,6 +989,9 @@ bool MatchFinder::addDynamicMatcher(const internal::DynTypedMatcher &NodeMatch,
} else if (NodeMatch.canConvertTo<TypeLoc>()) {
addMatcher(NodeMatch.convertTo<TypeLoc>(), Action);
return true;
} else if (NodeMatch.canConvertTo<CXXCtorInitializer>()) {
addMatcher(NodeMatch.convertTo<CXXCtorInitializer>(), Action);
return true;
}
return false;
}

View File

@ -528,6 +528,11 @@ TEST(Matcher, ConstructorCall) {
EXPECT_TRUE(matches("class X {}; void x(int) { X x; }", Constructor));
}
TEST(Match, ConstructorInitializers) {
EXPECT_TRUE(matches("class C { int i; public: C(int ii) : i(ii) {} };",
cxxCtorInitializer(forField(hasName("i")))));
}
TEST(Matcher, ThisExpr) {
EXPECT_TRUE(
matches("struct X { int a; int f () { return a; } };", cxxThisExpr()));