r205543 - Teach getTemplateInstantiationPattern to deal with generic lambdas.

Faisal Vali faisalv at yahoo.com
Thu Apr 3 09:32:22 PDT 2014


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.





More information about the cfe-commits mailing list