diff options
author | Richard Smith <richard-llvm@metafoo.co.uk> | 2016-02-09 20:59:05 +0000 |
---|---|---|
committer | Richard Smith <richard-llvm@metafoo.co.uk> | 2016-02-09 20:59:05 +0000 |
commit | e33f5dfa8fb525cad72763e37a2d8654a1554005 (patch) | |
tree | e5f8412affec1321ae3eed791490f951a73657ed /lib/ASTMatchers | |
parent | 95b8564b85eb67cdf7cfafe1985e58894ab7134b (diff) |
Simplify and rename ASTMatchFinder's getCXXRecordDecl to make it more obvious
what it's actually trying to do.
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@260277 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/ASTMatchers')
-rw-r--r-- | lib/ASTMatchers/ASTMatchFinder.cpp | 64 |
1 files changed, 23 insertions, 41 deletions
diff --git a/lib/ASTMatchers/ASTMatchFinder.cpp b/lib/ASTMatchers/ASTMatchFinder.cpp index 847398c086..e13985bca8 100644 --- a/lib/ASTMatchers/ASTMatchFinder.cpp +++ b/lib/ASTMatchers/ASTMatchFinder.cpp @@ -744,46 +744,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 +779,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) { |