diff options
Diffstat (limited to 'gnu/llvm/tools/clang/lib/ASTMatchers/ASTMatchFinder.cpp')
| -rw-r--r-- | gnu/llvm/tools/clang/lib/ASTMatchers/ASTMatchFinder.cpp | 115 |
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) { |
