r260277 - Simplify and rename ASTMatchFinder's getCXXRecordDecl to make it more obvious

Manuel Klimek via cfe-commits cfe-commits at lists.llvm.org
Wed Feb 10 01:04:42 PST 2016


On Tue, Feb 9, 2016 at 10:03 PM Richard Smith via cfe-commits <
cfe-commits at lists.llvm.org> wrote:

> Author: rsmith
> Date: Tue Feb  9 14:59:05 2016
> New Revision: 260277
>
> URL: http://llvm.org/viewvc/llvm-project?rev=260277&view=rev
> Log:
> Simplify and rename ASTMatchFinder's getCXXRecordDecl to make it more
> obvious
> what it's actually trying to do.
>
> Modified:
>     cfe/trunk/lib/ASTMatchers/ASTMatchFinder.cpp
>
> Modified: cfe/trunk/lib/ASTMatchers/ASTMatchFinder.cpp
> URL:
> http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/ASTMatchers/ASTMatchFinder.cpp?rev=260277&r1=260276&r2=260277&view=diff
>
> ==============================================================================
> --- cfe/trunk/lib/ASTMatchers/ASTMatchFinder.cpp (original)
> +++ cfe/trunk/lib/ASTMatchers/ASTMatchFinder.cpp Tue Feb  9 14:59:05 2016
> @@ -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
>      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


Why not? Specifically, it seems to match what the user wants in most cases.
Now, I'm all for also exposing a more complex interface to the user, where
they can / have to control exactly where to dive into the primary
templates, but experience shows that this is really hard for anybody who's
not a C++ expert to understand, and the current behavior here matches what
people expect when they want to match classes in the inheritance hierarchy.


> interface.
> +    CXXRecordDecl *ClassDecl =
> getAsCXXRecordDeclOrPrimaryTemplate(TypeNode);
>      if (!ClassDecl)
>        continue;
>      if (ClassDecl == Declaration) {
>
>
> _______________________________________________
> cfe-commits mailing list
> cfe-commits at lists.llvm.org
> http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.llvm.org/pipermail/cfe-commits/attachments/20160210/2823be0e/attachment-0001.html>


More information about the cfe-commits mailing list