summaryrefslogtreecommitdiffstats
path: root/lib/ASTMatchers
diff options
context:
space:
mode:
authorRichard Smith <richard-llvm@metafoo.co.uk>2016-02-09 20:59:05 +0000
committerRichard Smith <richard-llvm@metafoo.co.uk>2016-02-09 20:59:05 +0000
commite33f5dfa8fb525cad72763e37a2d8654a1554005 (patch)
treee5f8412affec1321ae3eed791490f951a73657ed /lib/ASTMatchers
parent95b8564b85eb67cdf7cfafe1985e58894ab7134b (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.cpp64
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) {