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 05:24:09 PST 2016
On Wed, Feb 10, 2016 at 10:04 AM Manuel Klimek <klimek at google.com> wrote:
> 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.
>
Read up on the other thread, and understand your concern now.
The problem in matchers is:
a) we want to be able to match primary templates, even if they're not
instantiated
b) the most common pattern to match on is names
In
template<typename T> class X : public Y<T> {}
I think it would be very surprising if we didn't match that X is derived
from a class called Y.
>
>
>> 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/ae7057d2/attachment-0001.html>
More information about the cfe-commits
mailing list