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