Revert "Implement a rudimentary form of generic lambdas."
This reverts commit 606f5d7a99b11957e057e4cd1f55f931f66a42c7.
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@189004 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/lib/Sema/SemaLambda.cpp b/lib/Sema/SemaLambda.cpp
index bed71a6..ae3a938 100644
--- a/lib/Sema/SemaLambda.cpp
+++ b/lib/Sema/SemaLambda.cpp
@@ -14,7 +14,6 @@
#include "clang/AST/ExprCXX.h"
#include "clang/Lex/Preprocessor.h"
#include "clang/Sema/Initialization.h"
-#include "clang/Sema/SemaLambda.h"
#include "clang/Sema/Lookup.h"
#include "clang/Sema/Scope.h"
#include "clang/Sema/ScopeInfo.h"
@@ -121,69 +120,11 @@
llvm_unreachable("unexpected context");
}
-
-ParmVarDecl *Sema::ActOnLambdaAutoParameter(ParmVarDecl *PVD) {
- LambdaScopeInfo *LSI = getCurLambda();
- assert(LSI && "No LambdaScopeInfo on the stack!");
- const unsigned TemplateParameterDepth = LSI->AutoTemplateParameterDepth;
- const unsigned AutoParameterPosition = LSI->AutoTemplateParams.size();
- // Invent a template type parameter corresponding to the auto
- // containing parameter.
- TemplateTypeParmDecl *TemplateParam =
- TemplateTypeParmDecl::Create(Context,
- // Temporarily add to the TranslationUnit DeclContext. When the
- // associated TemplateParameterList is attached to a template
- // declaration (such as FunctionTemplateDecl), the DeclContext
- // for each template parameter gets updated appropriately via
- // a call to AdoptTemplateParameterList.
- Context.getTranslationUnitDecl(),
- SourceLocation(),
- PVD->getLocation(),
- TemplateParameterDepth,
- AutoParameterPosition, // our template param index
- /* Identifier*/ 0, false, PVD->isParameterPack());
- LSI->AutoTemplateParams.push_back(TemplateParam);
- QualType AutoTy = PVD->getType();
- // Now replace the 'auto' in the function parameter with this invented
- // template type parameter.
- QualType TemplParamType = QualType(TemplateParam->getTypeForDecl(), 0);
-
- TypeSourceInfo *AutoTSI = PVD->getTypeSourceInfo();
- TypeSourceInfo *NewTSI = SubstAutoTypeSourceInfo(AutoTSI, TemplParamType);
- PVD->setType(NewTSI->getType());
- PVD->setTypeSourceInfo(NewTSI);
- return PVD;
-}
-
-
-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 *MethodType,
SourceLocation EndLoc,
ArrayRef<ParmVarDecl *> Params) {
- TemplateParameterList *TemplateParams =
- getGenericLambdaTemplateParameterList(getCurLambda(), *this);
// C++11 [expr.prim.lambda]p5:
// The closure type for a lambda-expression has a public inline function
// call operator (13.5.4) whose parameters and return type are described by
@@ -211,17 +152,6 @@
// Temporarily set the lexical declaration context to the current
// context, so that the Scope stack matches the lexical nesting.
Method->setLexicalDeclContext(CurContext);
- // Create a function template if we have a template parameter list
- FunctionTemplateDecl *const TemplateMethod = TemplateParams ?
- FunctionTemplateDecl::Create(Context, Class,
- Method->getLocation(), MethodName,
- TemplateParams,
- Method) : 0;
- if (TemplateMethod) {
- TemplateMethod->setLexicalDeclContext(CurContext);
- TemplateMethod->setAccess(AS_public);
- Method->setDescribedFunctionTemplate(TemplateMethod);
- }
// Add parameters.
if (!Params.empty()) {
@@ -247,16 +177,15 @@
return Method;
}
-void Sema::buildLambdaScope(LambdaScopeInfo *LSI,
- CXXMethodDecl *CallOperator,
+LambdaScopeInfo *Sema::enterLambdaScope(CXXMethodDecl *CallOperator,
SourceRange IntroducerRange,
LambdaCaptureDefault CaptureDefault,
SourceLocation CaptureDefaultLoc,
bool ExplicitParams,
bool ExplicitResultType,
bool Mutable) {
- LSI->CallOperator = CallOperator;
- LSI->Lambda = CallOperator->getParent();
+ PushLambdaScope(CallOperator->getParent(), CallOperator);
+ LambdaScopeInfo *LSI = getCurLambda();
if (CaptureDefault == LCD_ByCopy)
LSI->ImpCaptureStyle = LambdaScopeInfo::ImpCap_LambdaByval;
else if (CaptureDefault == LCD_ByRef)
@@ -279,6 +208,8 @@
} else {
LSI->HasImplicitReturnType = true;
}
+
+ return LSI;
}
void Sema::finishLambdaExplicitCaptures(LambdaScopeInfo *LSI) {
@@ -427,7 +358,7 @@
}
void Sema::deduceClosureReturnType(CapturingScopeInfo &CSI) {
- assert(CSI.HasImplicitReturnType || CSI.ReturnType->isUndeducedType());
+ assert(CSI.HasImplicitReturnType);
// C++ Core Issue #975, proposed resolution:
// If a lambda-expression does not include a trailing-return-type,
@@ -461,7 +392,7 @@
// Second case: at least one return statement has dependent type.
// Delay type checking until instantiation.
assert(!CSI.ReturnType.isNull() && "We should have a tentative return type.");
- if (CSI.ReturnType->isDependentType() || CSI.ReturnType->isUndeducedType())
+ if (CSI.ReturnType->isDependentType())
return;
// Try to apply the enum-fuzz rule.
@@ -588,25 +519,15 @@
}
void Sema::ActOnStartOfLambdaDefinition(LambdaIntroducer &Intro,
- Declarator &ParamInfo, Scope *CurScope) {
+ Declarator &ParamInfo,
+ Scope *CurScope) {
// Determine if we're within a context where we know that the lambda will
// be dependent, because there are template parameters in scope.
bool KnownDependent = false;
- LambdaScopeInfo *const LSI = getCurLambda();
- assert(LSI && "LambdaScopeInfo should be on stack!");
- TemplateParameterList *TemplateParams =
- getGenericLambdaTemplateParameterList(LSI, *this);
-
- if (Scope *TmplScope = CurScope->getTemplateParamParent()) {
- // Since we have our own TemplateParams, so check if an outer scope
- // has template params, only then are we in a dependent scope.
- if (TemplateParams) {
- TmplScope = TmplScope->getParent();
- TmplScope = TmplScope ? TmplScope->getTemplateParamParent() : 0;
- }
- if (TmplScope && !TmplScope->decl_empty())
+ if (Scope *TmplScope = CurScope->getTemplateParamParent())
+ if (!TmplScope->decl_empty())
KnownDependent = true;
- }
+
// Determine the signature of the call operator.
TypeSourceInfo *MethodTyInfo;
bool ExplicitParams = true;
@@ -621,11 +542,7 @@
FunctionProtoType::ExtProtoInfo EPI;
EPI.HasTrailingReturn = true;
EPI.TypeQuals |= DeclSpec::TQ_const;
- // For C++1y, use the new return type deduction machinery, by imaginging
- // 'auto' if no trailing return type.
- QualType DefaultTypeForNoTrailingReturn = getLangOpts().CPlusPlus1y ?
- Context.getAutoDeductType() : Context.DependentTy;
- QualType MethodTy = Context.getFunctionType(DefaultTypeForNoTrailingReturn, None,
+ QualType MethodTy = Context.getFunctionType(Context.DependentTy, None,
EPI);
MethodTyInfo = Context.getTrivialTypeSourceInfo(MethodTy);
ExplicitParams = false;
@@ -643,15 +560,14 @@
if (!FTI.hasMutableQualifier())
FTI.TypeQuals |= DeclSpec::TQ_const;
- ExplicitResultType = FTI.hasTrailingReturnType();
- // In C++11 if there is no explicit return type, the return type is
- // artificially set to DependentTy, whereas in C++1y it is set to AutoTy
- // (through ConvertDeclSpecToType) which allows us to support both
- // C++11 and C++1y return type deduction semantics.
MethodTyInfo = GetTypeForDeclarator(ParamInfo, CurScope);
assert(MethodTyInfo && "no type from lambda-declarator");
EndLoc = ParamInfo.getSourceRange().getEnd();
+ ExplicitResultType
+ = MethodTyInfo->getType()->getAs<FunctionType>()->getResultType()
+ != Context.DependentTy;
+
if (FTI.NumArgs == 1 && !FTI.isVariadic && FTI.ArgInfo[0].Ident == 0 &&
cast<ParmVarDecl>(FTI.ArgInfo[0].Param)->getType()->isVoidType()) {
// Empty arg list, don't push any params.
@@ -672,6 +588,7 @@
CXXMethodDecl *Method = startLambdaDefinition(Class, Intro.Range,
MethodTyInfo, EndLoc, Params);
+
if (ExplicitParams)
CheckCXXDefaultArguments(Method);
@@ -681,8 +598,9 @@
// Introduce the function call operator as the current declaration context.
PushDeclContext(CurScope, Method);
- // Build the lambda scope.
- buildLambdaScope(LSI, Method,
+ // Introduce the lambda scope.
+ LambdaScopeInfo *LSI
+ = enterLambdaScope(Method,
Intro.Range,
Intro.Default, Intro.DefaultLoc,
ExplicitParams,
@@ -894,8 +812,6 @@
SourceRange IntroducerRange,
CXXRecordDecl *Class,
CXXMethodDecl *CallOperator) {
- // FIXME: The conversion operator needs to be fixed for generic lambdas.
- if (Class->isGenericLambda()) return;
// Add the conversion to function pointer.
const FunctionProtoType *Proto
= CallOperator->getType()->getAs<FunctionProtoType>();
@@ -933,9 +849,10 @@
Conversion->setAccess(AS_public);
Conversion->setImplicit(true);
Class->addDecl(Conversion);
- // Add a non-static member function that will be the result of
- // the conversion with a certain unique ID.
- Name = &S.Context.Idents.get(getLambdaStaticInvokerName());
+
+ // Add a non-static member function "__invoke" that will be the result of
+ // the conversion.
+ Name = &S.Context.Idents.get("__invoke");
CXXMethodDecl *Invoke
= CXXMethodDecl::Create(S.Context, Class, Loc,
DeclarationNameInfo(Name, Loc), FunctionTy,
@@ -1083,11 +1000,8 @@
// If a lambda-expression does not include a
// trailing-return-type, it is as if the trailing-return-type
// denotes the following type:
- // Skip for C++1y return type deduction semantics which uses
- // different machinery currently.
- // FIXME: Refactor and Merge the return type deduction machinery.
// FIXME: Assumes current resolution to core issue 975.
- if (LSI->HasImplicitReturnType && !getLangOpts().CPlusPlus1y) {
+ if (LSI->HasImplicitReturnType) {
deduceClosureReturnType(*LSI);
// - if there are no return statements in the
@@ -1105,18 +1019,13 @@
LSI->ReturnType, Proto->getArgTypes(), Proto->getExtProtoInfo());
CallOperator->setType(FunctionTy);
}
+
// C++ [expr.prim.lambda]p7:
// The lambda-expression's compound-statement yields the
// function-body (8.4) of the function call operator [...].
ActOnFinishFunctionBody(CallOperator, Body, IsInstantiation);
CallOperator->setLexicalDeclContext(Class);
- Decl *TemplateOrNonTemplateCallOperatorDecl =
- !CallOperator->getDescribedFunctionTemplate() ? cast<Decl>(CallOperator)
- : CallOperator->getDescribedFunctionTemplate();
-
- TemplateOrNonTemplateCallOperatorDecl->setLexicalDeclContext(Class);
- Class->addDecl(TemplateOrNonTemplateCallOperatorDecl);
-
+ Class->addDecl(CallOperator);
PopExpressionEvaluationContext();
// C++11 [expr.prim.lambda]p6:
@@ -1156,7 +1065,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).
@@ -1176,15 +1085,7 @@
break;
}
}
- // TODO: Implement capturing.
- if (Lambda->isGenericLambda()) {
- if (Lambda->getCaptureDefault() != LCD_None) {
- Diag(Lambda->getIntroducerRange().getBegin(),
- diag::err_glambda_not_fully_implemented)
- << " capturing not implemented yet";
- return ExprError();
- }
- }
+
return MaybeBindToTemporary(Lambda);
}