Thanks!
On Thu, Apr 3, 2014 at 9:32 AM, Faisal Vali <[email protected]> wrote: > Author: faisalv > Date: Thu Apr 3 11:32:21 2014 > New Revision: 205543 > > URL: http://llvm.org/viewvc/llvm-project?rev=205543&view=rev > Log: > Teach getTemplateInstantiationPattern to deal with generic lambdas. > > No functionality change. > > When determining the pattern for instantiating a generic lambda call > operator specialization - we must not go drilling down for the 'prototype' > (i.e. as written) pattern - rather we must use our partially transformed > pattern (whose DeclRefExprs are wired correctly to any enclosing lambda's > decls that should be mapped correctly in a local instantiation scope) that > is the templated pattern of the specialization's primary template (even > though the primary template might be instantiated from a 'prototype' > member-template). Previously, the drilling down was haltted by marking the > instantiated-from primary template as a member-specialization (incorrectly). > > This prompted Richard to remark ( > http://llvm-reviews.chandlerc.com/D1784?id=4687#inline-10272) > "It's a bit nasty to (essentially) set this bit incorrectly. Can you put > the check into getTemplateInstantiationPattern instead?" > > In my reckless youth, I chose to ignore that comment. With the passage of > time, I have come to learn the value of bowing to the will of the angry > Gods ;) > > > > Modified: > cfe/trunk/include/clang/AST/ASTLambda.h > cfe/trunk/lib/AST/Decl.cpp > cfe/trunk/lib/Sema/SemaTemplateInstantiate.cpp > > Modified: cfe/trunk/include/clang/AST/ASTLambda.h > URL: > http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/ASTLambda.h?rev=205543&r1=205542&r2=205543&view=diff > > ============================================================================== > --- cfe/trunk/include/clang/AST/ASTLambda.h (original) > +++ cfe/trunk/include/clang/AST/ASTLambda.h Thu Apr 3 11:32:21 2014 > @@ -36,9 +36,9 @@ inline bool isLambdaCallOperator(const D > return isLambdaCallOperator(cast<CXXMethodDecl>(DC)); > } > > -inline bool isGenericLambdaCallOperatorSpecialization(CXXMethodDecl *MD) { > +inline bool isGenericLambdaCallOperatorSpecialization(const CXXMethodDecl > *MD) { > if (!MD) return false; > - CXXRecordDecl *LambdaClass = MD->getParent(); > + const CXXRecordDecl *LambdaClass = MD->getParent(); > if (LambdaClass && LambdaClass->isGenericLambda()) > return isLambdaCallOperator(MD) && > MD->isFunctionTemplateSpecialization(); > > Modified: cfe/trunk/lib/AST/Decl.cpp > URL: > http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/Decl.cpp?rev=205543&r1=205542&r2=205543&view=diff > > ============================================================================== > --- cfe/trunk/lib/AST/Decl.cpp (original) > +++ cfe/trunk/lib/AST/Decl.cpp Thu Apr 3 11:32:21 2014 > @@ -13,6 +13,7 @@ > > #include "clang/AST/Decl.h" > #include "clang/AST/ASTContext.h" > +#include "clang/AST/ASTLambda.h" > #include "clang/AST/ASTMutationListener.h" > #include "clang/AST/Attr.h" > #include "clang/AST/DeclCXX.h" > @@ -2830,14 +2831,34 @@ FunctionDecl *FunctionDecl::getTemplateI > // Handle class scope explicit specialization special case. > if (getTemplateSpecializationKind() == TSK_ExplicitSpecialization) > return getClassScopeSpecializationPattern(); > - > + > + // If this is a generic lambda call operator specialization, its > + // instantiation pattern is always its primary template's pattern > + // even if its primary template was instantiated from another > + // member template (which happens with nested generic lambdas). > + // Since a lambda's call operator's body is transformed eagerly, > + // we don't have to go hunting for a prototype definition template > + // (i.e. instantiated-from-member-template) to use as an instantiation > + // pattern. > + > + if (isGenericLambdaCallOperatorSpecialization( > + dyn_cast<CXXMethodDecl>(this))) { > + assert(getPrimaryTemplate() && "A generic lambda specialization must > be " > + "generated from a primary call > operator " > + "template"); > + assert(getPrimaryTemplate()->getTemplatedDecl()->getBody() && > + "A generic lambda call operator template must always have a > body - " > + "even if instantiated from a prototype (i.e. as written) > member " > + "template"); > + return getPrimaryTemplate()->getTemplatedDecl(); > + } > + > if (FunctionTemplateDecl *Primary = getPrimaryTemplate()) { > while (Primary->getInstantiatedFromMemberTemplate()) { > // If we have hit a point where the user provided a specialization > of > // this template, we're done looking. > if (Primary->isMemberSpecialization()) > break; > - > Primary = Primary->getInstantiatedFromMemberTemplate(); > } > > > Modified: cfe/trunk/lib/Sema/SemaTemplateInstantiate.cpp > URL: > http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaTemplateInstantiate.cpp?rev=205543&r1=205542&r2=205543&view=diff > > ============================================================================== > --- cfe/trunk/lib/Sema/SemaTemplateInstantiate.cpp (original) > +++ cfe/trunk/lib/Sema/SemaTemplateInstantiate.cpp Thu Apr 3 11:32:21 2014 > @@ -837,8 +837,6 @@ namespace { > > OldCallOperator->getDescribedFunctionTemplate(); > NewCallOperatorTemplate->setInstantiatedFromMemberTemplate( > > OldCallOperatorTemplate); > - // Mark the NewCallOperatorTemplate a specialization. > - NewCallOperatorTemplate->setMemberSpecialization(); > } else > // For a non-generic lambda we set the NewCallOperator to > // be an instantiation of the OldCallOperator. > > > _______________________________________________ > cfe-commits mailing list > [email protected] > http://lists.cs.uiuc.edu/mailman/listinfo/cfe-commits >
_______________________________________________ cfe-commits mailing list [email protected] http://lists.cs.uiuc.edu/mailman/listinfo/cfe-commits
