Revert r193223 and r193216.
They were causing CodeGenCXX/mangle-exprs.cpp to fail.
Revert "Remove the circular reference to LambdaExpr in CXXRecordDecl."
Revert "Again: Teach TreeTransform and family how to transform generic lambdas nested within templates and themselves."
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@193226 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/lib/Sema/SemaDecl.cpp b/lib/Sema/SemaDecl.cpp
index bc7be6d..80f95e6 100644
--- a/lib/Sema/SemaDecl.cpp
+++ b/lib/Sema/SemaDecl.cpp
@@ -9401,29 +9401,6 @@
Diag(Definition->getLocation(), diag::note_previous_definition);
FD->setInvalidDecl();
}
-static void RebuildLambdaScopeInfo(CXXMethodDecl *CallOperator,
- Sema &S) {
- CXXRecordDecl *const LambdaClass = CallOperator->getParent();
- S.PushLambdaScope();
- LambdaScopeInfo *LSI = S.getCurLambda();
- LSI->CallOperator = CallOperator;
- LSI->Lambda = LambdaClass;
- LSI->ReturnType = CallOperator->getResultType();
- const LambdaCaptureDefault LCD = LambdaClass->getLambdaCaptureDefault();
-
- if (LCD == LCD_None)
- LSI->ImpCaptureStyle = CapturingScopeInfo::ImpCap_None;
- else if (LCD == LCD_ByCopy)
- LSI->ImpCaptureStyle = CapturingScopeInfo::ImpCap_LambdaByval;
- else if (LCD == LCD_ByRef)
- LSI->ImpCaptureStyle = CapturingScopeInfo::ImpCap_LambdaByref;
- DeclarationNameInfo DNI = CallOperator->getNameInfo();
-
- LSI->IntroducerRange = DNI.getCXXOperatorNameRange();
- LSI->Mutable = !CallOperator->isConst();
-
- // FIXME: Add the captures to the LSI.
-}
Decl *Sema::ActOnStartOfFunctionDef(Scope *FnBodyScope, Decl *D) {
// Clear the last template instantiation error context.
@@ -9439,18 +9416,31 @@
FD = cast<FunctionDecl>(D);
// If we are instantiating a generic lambda call operator, push
// a LambdaScopeInfo onto the function stack. But use the information
- // that's already been calculated (ActOnLambdaExpr) to prime the current
- // LambdaScopeInfo.
- // When the template operator is being specialized, the LambdaScopeInfo,
- // has to be properly restored so that tryCaptureVariable doesn't try
- // and capture any new variables. In addition when calculating potential
- // captures during transformation of nested lambdas, it is necessary to
- // have the LSI properly restored.
+ // that's already been calculated (ActOnLambdaExpr) when analyzing the
+ // template version, to prime the current LambdaScopeInfo.
if (isGenericLambdaCallOperatorSpecialization(FD)) {
+ CXXMethodDecl *CallOperator = cast<CXXMethodDecl>(D);
+ CXXRecordDecl *LambdaClass = CallOperator->getParent();
+ LambdaExpr *LE = LambdaClass->getLambdaExpr();
+ assert(LE &&
+ "No LambdaExpr of closure class when instantiating a generic lambda!");
assert(ActiveTemplateInstantiations.size() &&
"There should be an active template instantiation on the stack "
"when instantiating a generic lambda!");
- RebuildLambdaScopeInfo(cast<CXXMethodDecl>(D), *this);
+ PushLambdaScope();
+ LambdaScopeInfo *LSI = getCurLambda();
+ LSI->CallOperator = CallOperator;
+ LSI->Lambda = LambdaClass;
+ LSI->ReturnType = CallOperator->getResultType();
+
+ if (LE->getCaptureDefault() == LCD_None)
+ LSI->ImpCaptureStyle = CapturingScopeInfo::ImpCap_None;
+ else if (LE->getCaptureDefault() == LCD_ByCopy)
+ LSI->ImpCaptureStyle = CapturingScopeInfo::ImpCap_LambdaByval;
+ else if (LE->getCaptureDefault() == LCD_ByRef)
+ LSI->ImpCaptureStyle = CapturingScopeInfo::ImpCap_LambdaByref;
+
+ LSI->IntroducerRange = LE->getIntroducerRange();
}
else
// Enter a new function scope
@@ -9814,6 +9804,7 @@
PopDeclContext();
PopFunctionScopeInfo(ActivePolicy, dcl);
+
// If any errors have occurred, clear out any temporaries that may have
// been leftover. This ensures that these temporaries won't be picked up for
// deletion in some later function.
diff --git a/lib/Sema/SemaLambda.cpp b/lib/Sema/SemaLambda.cpp
index 9b3afc9..32a385c 100644
--- a/lib/Sema/SemaLambda.cpp
+++ b/lib/Sema/SemaLambda.cpp
@@ -24,43 +24,17 @@
using namespace clang;
using namespace sema;
-
-static inline TemplateParameterList *
-getGenericLambdaTemplateParameterList(LambdaScopeInfo *LSI, Sema &SemaRef) {
- if (LSI->GLTemplateParameterList)
- return LSI->GLTemplateParameterList;
-
- if (LSI->AutoTemplateParams.size()) {
- SourceRange IntroRange = LSI->IntroducerRange;
- SourceLocation LAngleLoc = IntroRange.getBegin();
- SourceLocation RAngleLoc = IntroRange.getEnd();
- LSI->GLTemplateParameterList = TemplateParameterList::Create(
- SemaRef.Context,
- /*Template kw loc*/SourceLocation(),
- LAngleLoc,
- (NamedDecl**)LSI->AutoTemplateParams.data(),
- LSI->AutoTemplateParams.size(), RAngleLoc);
- }
- return LSI->GLTemplateParameterList;
-}
-
-
-
CXXRecordDecl *Sema::createLambdaClosureType(SourceRange IntroducerRange,
TypeSourceInfo *Info,
- bool KnownDependent,
- LambdaCaptureDefault CaptureDefault) {
+ bool KnownDependent) {
DeclContext *DC = CurContext;
while (!(DC->isFunctionOrMethod() || DC->isRecord() || DC->isFileContext()))
DC = DC->getParent();
- bool IsGenericLambda = getGenericLambdaTemplateParameterList(getCurLambda(),
- *this);
+
// Start constructing the lambda class.
CXXRecordDecl *Class = CXXRecordDecl::CreateLambda(Context, DC, Info,
IntroducerRange.getBegin(),
- KnownDependent,
- IsGenericLambda,
- CaptureDefault);
+ KnownDependent);
DC->addDecl(Class);
return Class;
@@ -157,6 +131,25 @@
return *MangleNumbering;
}
+static inline TemplateParameterList *
+getGenericLambdaTemplateParameterList(LambdaScopeInfo *LSI, Sema &SemaRef) {
+ if (LSI->GLTemplateParameterList)
+ return LSI->GLTemplateParameterList;
+ else if (LSI->AutoTemplateParams.size()) {
+ SourceRange IntroRange = LSI->IntroducerRange;
+ SourceLocation LAngleLoc = IntroRange.getBegin();
+ SourceLocation RAngleLoc = IntroRange.getEnd();
+ LSI->GLTemplateParameterList =
+ TemplateParameterList::Create(SemaRef.Context,
+ /* Template kw loc */ SourceLocation(),
+ LAngleLoc,
+ (NamedDecl**)LSI->AutoTemplateParams.data(),
+ LSI->AutoTemplateParams.size(), RAngleLoc);
+ }
+ return LSI->GLTemplateParameterList;
+}
+
+
CXXMethodDecl *Sema::startLambdaDefinition(CXXRecordDecl *Class,
SourceRange IntroducerRange,
TypeSourceInfo *MethodTypeInfo,
@@ -250,8 +243,7 @@
bool ExplicitResultType,
bool Mutable) {
LSI->CallOperator = CallOperator;
- CXXRecordDecl *LambdaClass = CallOperator->getParent();
- LSI->Lambda = LambdaClass;
+ LSI->Lambda = CallOperator->getParent();
if (CaptureDefault == LCD_ByCopy)
LSI->ImpCaptureStyle = LambdaScopeInfo::ImpCap_LambdaByval;
else if (CaptureDefault == LCD_ByRef)
@@ -636,7 +628,7 @@
}
CXXRecordDecl *Class = createLambdaClosureType(Intro.Range, MethodTyInfo,
- KnownDependent, Intro.Default);
+ KnownDependent);
CXXMethodDecl *Method = startLambdaDefinition(Class, Intro.Range,
MethodTyInfo, EndLoc, Params);
@@ -1163,6 +1155,7 @@
CaptureInits, ArrayIndexVars,
ArrayIndexStarts, Body->getLocEnd(),
ContainsUnexpandedParameterPack);
+ Class->setLambdaExpr(Lambda);
// C++11 [expr.prim.lambda]p2:
// A lambda-expression shall not appear in an unevaluated operand
// (Clause 5).
diff --git a/lib/Sema/SemaTemplateInstantiate.cpp b/lib/Sema/SemaTemplateInstantiate.cpp
index 3c621da..f13b14b 100644
--- a/lib/Sema/SemaTemplateInstantiate.cpp
+++ b/lib/Sema/SemaTemplateInstantiate.cpp
@@ -14,7 +14,6 @@
#include "TreeTransform.h"
#include "clang/AST/ASTConsumer.h"
#include "clang/AST/ASTContext.h"
-#include "clang/AST/ASTLambda.h"
#include "clang/AST/DeclTemplate.h"
#include "clang/AST/Expr.h"
#include "clang/Basic/LangOptions.h"
@@ -131,11 +130,6 @@
assert(Function->getPrimaryTemplate() && "No function template?");
if (Function->getPrimaryTemplate()->isMemberSpecialization())
break;
-
- // If this function is a generic lambda specialization, we are done.
- if (isGenericLambdaCallOperatorSpecialization(Function))
- break;
-
} else if (FunctionTemplateDecl *FunTmpl
= Function->getDescribedFunctionTemplate()) {
// Add the "injected" template arguments.
@@ -917,36 +911,13 @@
}
ExprResult TransformLambdaScope(LambdaExpr *E,
- CXXMethodDecl *NewCallOperator) {
- CXXMethodDecl *const OldCallOperator = E->getCallOperator();
- // In the generic lambda case, we set the NewTemplate to be considered
- // an "instantiation" of the OldTemplate.
- if (FunctionTemplateDecl *const NewCallOperatorTemplate =
- NewCallOperator->getDescribedFunctionTemplate()) {
-
- FunctionTemplateDecl *const OldCallOperatorTemplate =
- 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.
- NewCallOperator->setInstantiationOfMemberFunction(OldCallOperator,
- TSK_ImplicitInstantiation);
-
- return inherited::TransformLambdaScope(E, NewCallOperator);
+ CXXMethodDecl *CallOperator) {
+ CallOperator->setInstantiationOfMemberFunction(E->getCallOperator(),
+ TSK_ImplicitInstantiation);
+ return TreeTransform<TemplateInstantiator>::
+ TransformLambdaScope(E, CallOperator);
}
- TemplateParameterList *TransformTemplateParameterList(
- TemplateParameterList *OrigTPL) {
- if (!OrigTPL || !OrigTPL->size()) return OrigTPL;
-
- DeclContext *Owner = OrigTPL->getParam(0)->getDeclContext();
- TemplateDeclInstantiator DeclInstantiator(getSema(),
- /* DeclContext *Owner */ Owner, TemplateArgs);
- return DeclInstantiator.SubstTemplateParams(OrigTPL);
- }
+
private:
ExprResult transformNonTypeTemplateParmRef(NonTypeTemplateParmDecl *parm,
SourceLocation loc,
diff --git a/lib/Sema/SemaTemplateInstantiateDecl.cpp b/lib/Sema/SemaTemplateInstantiateDecl.cpp
index d0c3ac6..d1512c2 100644
--- a/lib/Sema/SemaTemplateInstantiateDecl.cpp
+++ b/lib/Sema/SemaTemplateInstantiateDecl.cpp
@@ -4174,8 +4174,7 @@
NamedDecl *Sema::FindInstantiatedDecl(SourceLocation Loc, NamedDecl *D,
const MultiLevelTemplateArgumentList &TemplateArgs) {
DeclContext *ParentDC = D->getDeclContext();
-
- if (isa<NonTypeTemplateParmDecl>(D) ||
+ if (isa<ParmVarDecl>(D) || isa<NonTypeTemplateParmDecl>(D) ||
isa<TemplateTypeParmDecl>(D) || isa<TemplateTemplateParmDecl>(D) ||
(ParentDC->isFunctionOrMethod() && ParentDC->isDependentContext()) ||
(isa<CXXRecordDecl>(D) && cast<CXXRecordDecl>(D)->isLambda())) {
diff --git a/lib/Sema/TreeTransform.h b/lib/Sema/TreeTransform.h
index 2d22e4c..97e12d7 100644
--- a/lib/Sema/TreeTransform.h
+++ b/lib/Sema/TreeTransform.h
@@ -593,11 +593,6 @@
/// \brief Transform the captures and body of a lambda expression.
ExprResult TransformLambdaScope(LambdaExpr *E, CXXMethodDecl *CallOperator);
- TemplateParameterList *TransformTemplateParameterList(
- TemplateParameterList *TPL) {
- return TPL;
- }
-
ExprResult TransformAddressOfOperand(Expr *E);
ExprResult TransformDependentScopeDeclRefExpr(DependentScopeDeclRefExpr *E,
bool IsAddressOfOperand);
@@ -8272,102 +8267,48 @@
ExprResult
TreeTransform<Derived>::TransformLambdaExpr(LambdaExpr *E) {
- getSema().PushLambdaScope();
- LambdaScopeInfo *LSI = getSema().getCurLambda();
- // Transform the template parameters, and add them to the current
- // instantiation scope. The null case is handled correctly.
- 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>();
- TypeSourceInfo *NewCallOpTSI = 0;
-
- 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.
-
- TypeLocBuilder NewCallOpTLBuilder;
- QualType NewCallOpType = TransformFunctionProtoType(NewCallOpTLBuilder,
- OldCallOpFPTL,
- 0, 0);
- NewCallOpTSI = NewCallOpTLBuilder.getTypeSourceInfo(getSema().Context,
- NewCallOpType);
+ // FIXME: Implement nested generic lambda transformations.
+ if (E->isGenericLambda()) {
+ getSema().Diag(E->getIntroducerRange().getBegin(),
+ diag::err_glambda_not_fully_implemented)
+ << " template transformation of generic lambdas not implemented yet";
+ 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<ParmVarDecl *, 4> Params;
- {
- FunctionProtoTypeLoc NewCallOpFPTL =
- NewCallOpTSI->getTypeLoc().castAs<FunctionProtoTypeLoc>();
- ParmVarDecl **NewParamDeclArray = NewCallOpFPTL.getParmArray();
- const unsigned NewNumArgs = NewCallOpFPTL.getNumArgs();
-
- 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)
+ // Transform the type of the lambda parameters and start the definition of
+ // the lambda itself.
+ TypeSourceInfo *MethodTy
+ = TransformType(E->getCallOperator()->getTypeSourceInfo());
+ if (!MethodTy)
return ExprError();
// Create the local class that will describe the lambda.
CXXRecordDecl *Class
= getSema().createLambdaClosureType(E->getIntroducerRange(),
- NewCallOpTSI,
- /*KnownDependent=*/false,
- E->getCaptureDefault());
-
+ MethodTy,
+ /*KnownDependent=*/false);
getDerived().transformedLocalDecl(E->getLambdaClass(), Class);
+ // Transform lambda parameters.
+ SmallVector<QualType, 4> ParamTypes;
+ SmallVector<ParmVarDecl *, 4> Params;
+ if (getDerived().TransformFunctionTypeParams(E->getLocStart(),
+ E->getCallOperator()->param_begin(),
+ E->getCallOperator()->param_size(),
+ 0, ParamTypes, &Params))
+ return ExprError();
+ getSema().PushLambdaScope();
+ LambdaScopeInfo *LSI = getSema().getCurLambda();
+ // TODO: Fix for nested lambdas
+ LSI->GLTemplateParameterList = 0;
// Build the call operator.
- CXXMethodDecl *NewCallOperator
+ CXXMethodDecl *CallOperator
= getSema().startLambdaDefinition(Class, E->getIntroducerRange(),
- NewCallOpTSI,
+ MethodTy,
E->getCallOperator()->getLocEnd(),
Params);
- LSI->CallOperator = NewCallOperator;
+ getDerived().transformAttrs(E->getCallOperator(), CallOperator);
- getDerived().transformAttrs(E->getCallOperator(), NewCallOperator);
-
- return getDerived().TransformLambdaScope(E, NewCallOperator);
+ return getDerived().TransformLambdaScope(E, CallOperator);
}
template<typename Derived>