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
