r222482 - Remove code that tries to avoid transforming non-dependent call operator types

Richard Smith richard-llvm at metafoo.co.uk
Thu Nov 20 15:53:15 PST 2014


Author: rsmith
Date: Thu Nov 20 17:53:14 2014
New Revision: 222482

URL: http://llvm.org/viewvc/llvm-project?rev=222482&view=rev
Log:
Remove code that tries to avoid transforming non-dependent call operator types
for lambda expressions. That can't ever work; we need to transform the
parameters in order to create new ones in the new call operator context.

Fixes a rejects-valid when transforming a context containing a
lambda-expression that uses its function parameters in C++14 mode.

Modified:
    cfe/trunk/lib/Sema/TreeTransform.h
    cfe/trunk/test/SemaCXX/lambda-expressions.cpp

Modified: cfe/trunk/lib/Sema/TreeTransform.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/TreeTransform.h?rev=222482&r1=222481&r2=222482&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/TreeTransform.h (original)
+++ cfe/trunk/lib/Sema/TreeTransform.h Thu Nov 20 17:53:14 2014
@@ -9090,37 +9090,34 @@ TreeTransform<Derived>::TransformCXXTemp
 template<typename Derived>
 ExprResult
 TreeTransform<Derived>::TransformLambdaExpr(LambdaExpr *E) {
-   
-  // Transform any init-capture expressions before entering the scope of the 
+  // Transform any init-capture expressions before entering the scope of the
   // lambda body, because they are not semantically within that scope.
   SmallVector<InitCaptureInfoTy, 8> InitCaptureExprsAndTypes;
   InitCaptureExprsAndTypes.resize(E->explicit_capture_end() -
       E->explicit_capture_begin());
-  
   for (LambdaExpr::capture_iterator C = E->capture_begin(),
-      CEnd = E->capture_end();
-      C != CEnd; ++C) {
+                                    CEnd = E->capture_end();
+       C != CEnd; ++C) {
     if (!C->isInitCapture())
       continue;
-    EnterExpressionEvaluationContext  EEEC(getSema(), 
-        Sema::PotentiallyEvaluated);    
+    EnterExpressionEvaluationContext EEEC(getSema(),
+                                          Sema::PotentiallyEvaluated);
     ExprResult NewExprInitResult = getDerived().TransformInitializer(
         C->getCapturedVar()->getInit(),
         C->getCapturedVar()->getInitStyle() == VarDecl::CallInit);
-    
+
     if (NewExprInitResult.isInvalid())
       return ExprError();
     Expr *NewExprInit = NewExprInitResult.get();
-      
+
     VarDecl *OldVD = C->getCapturedVar();
-    QualType NewInitCaptureType = 
-        getSema().performLambdaInitCaptureInitialization(C->getLocation(), 
-            OldVD->getType()->isReferenceType(), OldVD->getIdentifier(), 
+    QualType NewInitCaptureType =
+        getSema().performLambdaInitCaptureInitialization(C->getLocation(),
+            OldVD->getType()->isReferenceType(), OldVD->getIdentifier(),
             NewExprInit);
     NewExprInitResult = NewExprInit;
     InitCaptureExprsAndTypes[C - E->capture_begin()] =
         std::make_pair(NewExprInitResult, NewInitCaptureType);
-
   }
 
   LambdaScopeInfo *LSI = getSema().PushLambdaScope();
@@ -9129,26 +9126,15 @@ TreeTransform<Derived>::TransformLambdaE
   LSI->GLTemplateParameterList = getDerived().TransformTemplateParameterList(
       E->getTemplateParameterList());
 
-  // Check to see if the TypeSourceInfo of the call operator needs to
-  // be transformed, and if so do the transformation in the 
-  // CurrentInstantiationScope.
-
-  TypeSourceInfo *OldCallOpTSI = E->getCallOperator()->getTypeSourceInfo();
-  FunctionProtoTypeLoc OldCallOpFPTL = 
-      OldCallOpTSI->getTypeLoc().getAs<FunctionProtoTypeLoc>();
+  // Transform the type of the original lambda's call operator.
+  // The transformation MUST be done in the CurrentInstantiationScope since
+  // it introduces a mapping of the original to the newly created
+  // transformed parameters.
   TypeSourceInfo *NewCallOpTSI = nullptr;
-
-  const bool CallOpWasAlreadyTransformed = 
-      getDerived().AlreadyTransformed(OldCallOpTSI->getType()); 
-  
-  // Use the Old Call Operator's TypeSourceInfo if it is already transformed.
-  if (CallOpWasAlreadyTransformed)  
-    NewCallOpTSI = OldCallOpTSI;  
-  else {
-    // Transform the TypeSourceInfo of the Original Lambda's Call Operator.
-    // The transformation MUST be done in the CurrentInstantiationScope since
-    // it introduces a mapping of the original to the newly created 
-    // transformed parameters.
+  {
+    TypeSourceInfo *OldCallOpTSI = E->getCallOperator()->getTypeSourceInfo();
+    FunctionProtoTypeLoc OldCallOpFPTL = 
+        OldCallOpTSI->getTypeLoc().getAs<FunctionProtoTypeLoc>();
 
     TypeLocBuilder NewCallOpTLBuilder;
     SmallVector<QualType, 4> ExceptionStorage;
@@ -9161,63 +9147,23 @@ TreeTransform<Derived>::TransformLambdaE
         });
     NewCallOpTSI = NewCallOpTLBuilder.getTypeSourceInfo(getSema().Context,
                                                         NewCallOpType);
-  }
-  // Extract the ParmVarDecls from the NewCallOpTSI and add them to
-  // the vector below - this will be used to synthesize the 
-  // NewCallOperator.  Additionally, add the parameters of the untransformed 
-  // lambda call operator to the CurrentInstantiationScope.
-  SmallVector<ParmVarDecl *, 4> Params;  
-  {
-    FunctionProtoTypeLoc NewCallOpFPTL = 
-        NewCallOpTSI->getTypeLoc().castAs<FunctionProtoTypeLoc>();
-    ParmVarDecl **NewParamDeclArray = NewCallOpFPTL.getParmArray();
-    const unsigned NewNumArgs = NewCallOpFPTL.getNumParams();
-
-    for (unsigned I = 0; I < NewNumArgs; ++I) {
-      // If this call operator's type does not require transformation, 
-      // the parameters do not get added to the current instantiation scope, 
-      // - so ADD them! This allows the following to compile when the enclosing
-      // template is specialized and the entire lambda expression has to be
-      // transformed. 
-      // template<class T> void foo(T t) {
-      //   auto L = [](auto a) {
-      //       auto M = [](char b) { <-- note: non-generic lambda
-      //         auto N = [](auto c) {
-      //            int x = sizeof(a);
-      //            x = sizeof(b); <-- specifically this line
-      //            x = sizeof(c);
-      //          };
-      //        };
-      //      };
-      //    }
-      // foo('a')
-      if (CallOpWasAlreadyTransformed)
-        getDerived().transformedLocalDecl(NewParamDeclArray[I],
-                                          NewParamDeclArray[I]);
-      // Add to Params array, so these parameters can be used to create
-      // the newly transformed call operator.
-      Params.push_back(NewParamDeclArray[I]);
-    }
+    if (!NewCallOpTSI)
+      return ExprError();
   }
 
-  if (!NewCallOpTSI)
-    return ExprError();
-
   // Create the local class that will describe the lambda.
   CXXRecordDecl *Class
     = getSema().createLambdaClosureType(E->getIntroducerRange(),
                                         NewCallOpTSI,
                                         /*KnownDependent=*/false,
                                         E->getCaptureDefault());
-
   getDerived().transformedLocalDecl(E->getLambdaClass(), Class);
 
   // Build the call operator.
-  CXXMethodDecl *NewCallOperator
-    = getSema().startLambdaDefinition(Class, E->getIntroducerRange(),
-                                      NewCallOpTSI,
-                                      E->getCallOperator()->getLocEnd(),
-                                      Params);
+  CXXMethodDecl *NewCallOperator = getSema().startLambdaDefinition(
+      Class, E->getIntroducerRange(), NewCallOpTSI,
+      E->getCallOperator()->getLocEnd(),
+      NewCallOpTSI->getTypeLoc().castAs<FunctionProtoTypeLoc>().getParams());
   LSI->CallOperator = NewCallOperator;
 
   getDerived().transformAttrs(E->getCallOperator(), NewCallOperator);

Modified: cfe/trunk/test/SemaCXX/lambda-expressions.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaCXX/lambda-expressions.cpp?rev=222482&r1=222481&r2=222482&view=diff
==============================================================================
--- cfe/trunk/test/SemaCXX/lambda-expressions.cpp (original)
+++ cfe/trunk/test/SemaCXX/lambda-expressions.cpp Thu Nov 20 17:53:14 2014
@@ -419,4 +419,9 @@ namespace lambda_in_default_mem_init {
     struct S { int n = []{ return 0; }(); };
   }
   template void f<int>();
+
+  template<typename T> void g() {
+    struct S { int n = [](int n){ return n; }(0); };
+  }
+  template void g<int>();
 }





More information about the cfe-commits mailing list