summaryrefslogtreecommitdiffstats
path: root/gnu/llvm/tools/clang/lib/ASTMatchers/ASTMatchFinder.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'gnu/llvm/tools/clang/lib/ASTMatchers/ASTMatchFinder.cpp')
-rw-r--r--gnu/llvm/tools/clang/lib/ASTMatchers/ASTMatchFinder.cpp115
1 files changed, 54 insertions, 61 deletions
diff --git a/gnu/llvm/tools/clang/lib/ASTMatchers/ASTMatchFinder.cpp b/gnu/llvm/tools/clang/lib/ASTMatchers/ASTMatchFinder.cpp
index 847398c0861..19e5743ea1c 100644
--- a/gnu/llvm/tools/clang/lib/ASTMatchers/ASTMatchFinder.cpp
+++ b/gnu/llvm/tools/clang/lib/ASTMatchers/ASTMatchFinder.cpp
@@ -616,6 +616,10 @@ private:
ActiveASTContext->getTranslationUnitDecl())
return false;
+ // For AST-nodes that don't have an identity, we can't memoize.
+ if (!Builder->isComparable())
+ return matchesAncestorOfRecursively(Node, Matcher, Builder, MatchMode);
+
MatchKey Key;
Key.MatcherID = Matcher.getID();
Key.Node = Node;
@@ -630,22 +634,34 @@ private:
}
MemoizedMatchResult Result;
- Result.ResultOfMatch = false;
Result.Nodes = *Builder;
+ Result.ResultOfMatch =
+ matchesAncestorOfRecursively(Node, Matcher, &Result.Nodes, MatchMode);
+
+ MemoizedMatchResult &CachedResult = ResultCache[Key];
+ CachedResult = std::move(Result);
+ *Builder = CachedResult.Nodes;
+ return CachedResult.ResultOfMatch;
+ }
+
+ bool matchesAncestorOfRecursively(const ast_type_traits::DynTypedNode &Node,
+ const DynTypedMatcher &Matcher,
+ BoundNodesTreeBuilder *Builder,
+ AncestorMatchMode MatchMode) {
const auto &Parents = ActiveASTContext->getParents(Node);
assert(!Parents.empty() && "Found node that is not in the parent map.");
if (Parents.size() == 1) {
// Only one parent - do recursive memoization.
const ast_type_traits::DynTypedNode Parent = Parents[0];
- if (Matcher.matches(Parent, this, &Result.Nodes)) {
- Result.ResultOfMatch = true;
- } else if (MatchMode != ASTMatchFinder::AMM_ParentOnly) {
- // Reset the results to not include the bound nodes from the failed
- // match above.
- Result.Nodes = *Builder;
- Result.ResultOfMatch = memoizedMatchesAncestorOfRecursively(
- Parent, Matcher, &Result.Nodes, MatchMode);
+ BoundNodesTreeBuilder BuilderCopy = *Builder;
+ if (Matcher.matches(Parent, this, &BuilderCopy)) {
+ *Builder = std::move(BuilderCopy);
+ return true;
+ }
+ if (MatchMode != ASTMatchFinder::AMM_ParentOnly) {
+ return memoizedMatchesAncestorOfRecursively(Parent, Matcher, Builder,
+ MatchMode);
// Once we get back from the recursive call, the result will be the
// same as the parent's result.
}
@@ -655,10 +671,10 @@ private:
std::deque<ast_type_traits::DynTypedNode> Queue(Parents.begin(),
Parents.end());
while (!Queue.empty()) {
- Result.Nodes = *Builder;
- if (Matcher.matches(Queue.front(), this, &Result.Nodes)) {
- Result.ResultOfMatch = true;
- break;
+ BoundNodesTreeBuilder BuilderCopy = *Builder;
+ if (Matcher.matches(Queue.front(), this, &BuilderCopy)) {
+ *Builder = std::move(BuilderCopy);
+ return true;
}
if (MatchMode != ASTMatchFinder::AMM_ParentOnly) {
for (const auto &Parent :
@@ -673,12 +689,7 @@ private:
Queue.pop_front();
}
}
-
- MemoizedMatchResult &CachedResult = ResultCache[Key];
- CachedResult = std::move(Result);
-
- *Builder = CachedResult.Nodes;
- return CachedResult.ResultOfMatch;
+ return false;
}
// Implements a BoundNodesTree::Visitor that calls a MatchCallback with
@@ -701,7 +712,7 @@ private:
// Returns true if 'TypeNode' has an alias that matches the given matcher.
bool typeHasMatchingAlias(const Type *TypeNode,
- const Matcher<NamedDecl> Matcher,
+ const Matcher<NamedDecl> &Matcher,
BoundNodesTreeBuilder *Builder) {
const Type *const CanonicalType =
ActiveASTContext->getCanonicalType(TypeNode);
@@ -744,46 +755,25 @@ private:
MemoizationMap ResultCache;
};
-static CXXRecordDecl *getAsCXXRecordDecl(const Type *TypeNode) {
- // Type::getAs<...>() drills through typedefs.
- if (TypeNode->getAs<DependentNameType>() != nullptr ||
- TypeNode->getAs<DependentTemplateSpecializationType>() != nullptr ||
- TypeNode->getAs<TemplateTypeParmType>() != nullptr)
- // Dependent names and template TypeNode parameters will be matched when
- // the template is instantiated.
- return nullptr;
- TemplateSpecializationType const *TemplateType =
- TypeNode->getAs<TemplateSpecializationType>();
- if (!TemplateType) {
- return TypeNode->getAsCXXRecordDecl();
- }
- if (TemplateType->getTemplateName().isDependent())
- // Dependent template specializations will be matched when the
- // template is instantiated.
- return nullptr;
-
- // For template specialization types which are specializing a template
- // declaration which is an explicit or partial specialization of another
- // template declaration, getAsCXXRecordDecl() returns the corresponding
- // ClassTemplateSpecializationDecl.
- //
- // For template specialization types which are specializing a template
- // declaration which is neither an explicit nor partial specialization of
- // another template declaration, getAsCXXRecordDecl() returns NULL and
- // we get the CXXRecordDecl of the templated declaration.
- CXXRecordDecl *SpecializationDecl = TemplateType->getAsCXXRecordDecl();
- if (SpecializationDecl) {
- return SpecializationDecl;
- }
- NamedDecl *Templated =
- TemplateType->getTemplateName().getAsTemplateDecl()->getTemplatedDecl();
- if (CXXRecordDecl *TemplatedRecord = dyn_cast<CXXRecordDecl>(Templated)) {
- return TemplatedRecord;
- }
- // Now it can still be that we have an alias template.
- TypeAliasDecl *AliasDecl = dyn_cast<TypeAliasDecl>(Templated);
- assert(AliasDecl);
- return getAsCXXRecordDecl(AliasDecl->getUnderlyingType().getTypePtr());
+static CXXRecordDecl *
+getAsCXXRecordDeclOrPrimaryTemplate(const Type *TypeNode) {
+ if (auto *RD = TypeNode->getAsCXXRecordDecl())
+ return RD;
+
+ // Find the innermost TemplateSpecializationType that isn't an alias template.
+ auto *TemplateType = TypeNode->getAs<TemplateSpecializationType>();
+ while (TemplateType && TemplateType->isTypeAlias())
+ TemplateType =
+ TemplateType->getAliasedType()->getAs<TemplateSpecializationType>();
+
+ // If this is the name of a (dependent) template specialization, use the
+ // definition of the template, even though it might be specialized later.
+ if (TemplateType)
+ if (auto *ClassTemplate = dyn_cast_or_null<ClassTemplateDecl>(
+ TemplateType->getTemplateName().getAsTemplateDecl()))
+ return ClassTemplate->getTemplatedDecl();
+
+ return nullptr;
}
// Returns true if the given class is directly or indirectly derived
@@ -800,7 +790,10 @@ bool MatchASTVisitor::classIsDerivedFrom(const CXXRecordDecl *Declaration,
if (typeHasMatchingAlias(TypeNode, Base, Builder))
return true;
- CXXRecordDecl *ClassDecl = getAsCXXRecordDecl(TypeNode);
+ // FIXME: Going to the primary template here isn't really correct, but
+ // unfortunately we accept a Decl matcher for the base class not a Type
+ // matcher, so it's the best thing we can do with our current interface.
+ CXXRecordDecl *ClassDecl = getAsCXXRecordDeclOrPrimaryTemplate(TypeNode);
if (!ClassDecl)
continue;
if (ClassDecl == Declaration) {