From: Richard Smith Date: Thu, 20 Nov 2014 23:53:14 +0000 (+0000) Subject: Remove code that tries to avoid transforming non-dependent call operator types X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=01014cee76f2da9df70c9e17bebaebf7f0a52c6d;p=platform%2Fupstream%2Fllvm.git 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. llvm-svn: 222482 --- diff --git a/clang/lib/Sema/TreeTransform.h b/clang/lib/Sema/TreeTransform.h index 62475bc..295d208 100644 --- a/clang/lib/Sema/TreeTransform.h +++ b/clang/lib/Sema/TreeTransform.h @@ -9090,37 +9090,34 @@ TreeTransform::TransformCXXTemporaryObjectExpr( template ExprResult TreeTransform::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 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::TransformLambdaExpr(LambdaExpr *E) { 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(); + // 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(); TypeLocBuilder NewCallOpTLBuilder; SmallVector ExceptionStorage; @@ -9161,47 +9147,9 @@ TreeTransform::TransformLambdaExpr(LambdaExpr *E) { }); NewCallOpTSI = NewCallOpTLBuilder.getTypeSourceInfo(getSema().Context, NewCallOpType); + if (!NewCallOpTSI) + return ExprError(); } - // 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 Params; - { - FunctionProtoTypeLoc NewCallOpFPTL = - NewCallOpTSI->getTypeLoc().castAs(); - 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 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(); // Create the local class that will describe the lambda. CXXRecordDecl *Class @@ -9209,15 +9157,13 @@ TreeTransform::TransformLambdaExpr(LambdaExpr *E) { 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().getParams()); LSI->CallOperator = NewCallOperator; getDerived().transformAttrs(E->getCallOperator(), NewCallOperator); diff --git a/clang/test/SemaCXX/lambda-expressions.cpp b/clang/test/SemaCXX/lambda-expressions.cpp index 29dffc4..1346c3d 100644 --- a/clang/test/SemaCXX/lambda-expressions.cpp +++ b/clang/test/SemaCXX/lambda-expressions.cpp @@ -419,4 +419,9 @@ namespace lambda_in_default_mem_init { struct S { int n = []{ return 0; }(); }; } template void f(); + + template void g() { + struct S { int n = [](int n){ return n; }(0); }; + } + template void g(); }