diff options
author | dim <dim@FreeBSD.org> | 2014-03-21 17:53:59 +0000 |
---|---|---|
committer | dim <dim@FreeBSD.org> | 2014-03-21 17:53:59 +0000 |
commit | 9cedb8bb69b89b0f0c529937247a6a80cabdbaec (patch) | |
tree | c978f0e9ec1ab92dc8123783f30b08a7fd1e2a39 /contrib/llvm/tools/clang/lib/Sema/SemaLambda.cpp | |
parent | 03fdc2934eb61c44c049a02b02aa974cfdd8a0eb (diff) | |
download | FreeBSD-src-9cedb8bb69b89b0f0c529937247a6a80cabdbaec.zip FreeBSD-src-9cedb8bb69b89b0f0c529937247a6a80cabdbaec.tar.gz |
MFC 261991:
Upgrade our copy of llvm/clang to 3.4 release. This version supports
all of the features in the current working draft of the upcoming C++
standard, provisionally named C++1y.
The code generator's performance is greatly increased, and the loop
auto-vectorizer is now enabled at -Os and -O2 in addition to -O3. The
PowerPC backend has made several major improvements to code generation
quality and compile time, and the X86, SPARC, ARM32, Aarch64 and SystemZ
backends have all seen major feature work.
Release notes for llvm and clang can be found here:
<http://llvm.org/releases/3.4/docs/ReleaseNotes.html>
<http://llvm.org/releases/3.4/tools/clang/docs/ReleaseNotes.html>
MFC 262121 (by emaste):
Update lldb for clang/llvm 3.4 import
This commit largely restores the lldb source to the upstream r196259
snapshot with the addition of threaded inferior support and a few bug
fixes.
Specific upstream lldb revisions restored include:
SVN git
181387 779e6ac
181703 7bef4e2
182099 b31044e
182650 f2dcf35
182683 0d91b80
183862 15c1774
183929 99447a6
184177 0b2934b
184948 4dc3761
184954 007e7bc
186990 eebd175
Sponsored by: DARPA, AFRL
MFC 262186 (by emaste):
Fix mismerge in r262121
A break statement was lost in the merge. The error had no functional
impact, but restore it to reduce the diff against upstream.
MFC 262303:
Pull in r197521 from upstream clang trunk (by rdivacky):
Use the integrated assembler by default on FreeBSD/ppc and ppc64.
Requested by: jhibbits
MFC 262611:
Pull in r196874 from upstream llvm trunk:
Fix a crash that occurs when PWD is invalid.
MCJIT needs to be able to run in hostile environments, even when PWD
is invalid. There's no need to crash MCJIT in this case.
The obvious fix is to simply leave MCContext's CompilationDir empty
when PWD can't be determined. This way, MCJIT clients,
and other clients that link with LLVM don't need a valid working directory.
If we do want to guarantee valid CompilationDir, that should be done
only for clients of getCompilationDir(). This is as simple as checking
for an empty string.
The only current use of getCompilationDir is EmitGenDwarfInfo, which
won't conceivably run with an invalid working dir. However, in the
purely hypothetically and untestable case that this happens, the
AT_comp_dir will be omitted from the compilation_unit DIE.
This should help fix assertions occurring with ports-mgmt/tinderbox,
when it is using jails, and sometimes invalidates clang's current
working directory.
Reported by: decke
MFC 262809:
Pull in r203007 from upstream clang trunk:
Don't produce an alias between destructors with different calling conventions.
Fixes pr19007.
(Please note that is an LLVM PR identifier, not a FreeBSD one.)
This should fix Firefox and/or libxul crashes (due to problems with
regparm/stdcall calling conventions) on i386.
Reported by: multiple users on freebsd-current
PR: bin/187103
MFC 263048:
Repair recognition of "CC" as an alias for the C++ compiler, since it
was silently broken by upstream for a Windows-specific use-case.
Apparently some versions of CMake still rely on this archaic feature...
Reported by: rakuco
MFC 263049:
Garbage collect the old way of adding the libstdc++ include directories
in clang's InitHeaderSearch.cpp. This has been superseded by David
Chisnall's commit in r255321.
Moreover, if libc++ is used, the libstdc++ include directories should
not be in the search path at all. These directories are now only used
if you pass -stdlib=libstdc++.
Diffstat (limited to 'contrib/llvm/tools/clang/lib/Sema/SemaLambda.cpp')
-rw-r--r-- | contrib/llvm/tools/clang/lib/Sema/SemaLambda.cpp | 948 |
1 files changed, 721 insertions, 227 deletions
diff --git a/contrib/llvm/tools/clang/lib/Sema/SemaLambda.cpp b/contrib/llvm/tools/clang/lib/Sema/SemaLambda.cpp index c7ba3cc..a7d5b65 100644 --- a/contrib/llvm/tools/clang/lib/Sema/SemaLambda.cpp +++ b/contrib/llvm/tools/clang/lib/Sema/SemaLambda.cpp @@ -11,27 +11,163 @@ // //===----------------------------------------------------------------------===// #include "clang/Sema/DeclSpec.h" +#include "clang/AST/ASTLambda.h" #include "clang/AST/ExprCXX.h" +#include "clang/Basic/TargetInfo.h" #include "clang/Lex/Preprocessor.h" #include "clang/Sema/Initialization.h" #include "clang/Sema/Lookup.h" #include "clang/Sema/Scope.h" #include "clang/Sema/ScopeInfo.h" #include "clang/Sema/SemaInternal.h" +#include "clang/Sema/SemaLambda.h" +#include "TypeLocBuilder.h" using namespace clang; using namespace sema; +// returns -1 if none of the lambdas on the scope stack can capture. +// A lambda 'L' is capture-ready for a certain variable 'V' if, +// - its enclosing context is non-dependent +// - and if the chain of lambdas between L and the lambda in which +// V is potentially used, call all capture or have captured V. +static inline int GetScopeIndexOfNearestCaptureReadyLambda( + ArrayRef<clang::sema::FunctionScopeInfo*> FunctionScopes, + DeclContext *const CurContext, VarDecl *VD) { + + DeclContext *EnclosingDC = CurContext; + // If VD is null, we are attempting to capture 'this' + const bool IsCapturingThis = !VD; + const bool IsCapturingVariable = !IsCapturingThis; + int RetIndex = -1; + unsigned CurScopeIndex = FunctionScopes.size() - 1; + while (!EnclosingDC->isTranslationUnit() && + EnclosingDC->isDependentContext() && isLambdaCallOperator(EnclosingDC)) { + RetIndex = CurScopeIndex; + clang::sema::LambdaScopeInfo *LSI = + cast<sema::LambdaScopeInfo>(FunctionScopes[CurScopeIndex]); + // We have crawled up to an intervening lambda that contains the + // variable declaration - so not only does it not need to capture; + // none of the enclosing lambdas need to capture it, and since all + // other nested lambdas are dependent (otherwise we wouldn't have + // arrived here) - we don't yet have a lambda that can capture the + // variable. + if (IsCapturingVariable && VD->getDeclContext()->Equals(EnclosingDC)) + return -1; + // All intervening lambda call operators have to be able to capture. + // If they do not have a default implicit capture, check to see + // if the entity has already been explicitly captured. + // If even a single dependent enclosing lambda lacks the capability + // to ever capture this variable, there is no further enclosing + // non-dependent lambda that can capture this variable. + if (LSI->ImpCaptureStyle == sema::LambdaScopeInfo::ImpCap_None) { + if (IsCapturingVariable && !LSI->isCaptured(VD)) + return -1; + if (IsCapturingThis && !LSI->isCXXThisCaptured()) + return -1; + } + EnclosingDC = getLambdaAwareParentOfDeclContext(EnclosingDC); + --CurScopeIndex; + } + // If the enclosingDC is not dependent, then the immediately nested lambda + // is capture-ready. + if (!EnclosingDC->isDependentContext()) + return RetIndex; + return -1; +} +// Given a lambda's call operator and a variable (or null for 'this'), +// compute the nearest enclosing lambda that is capture-ready (i.e +// the enclosing context is not dependent, and all intervening lambdas can +// either implicitly or explicitly capture Var) +// +// The approach is as follows, for the entity VD ('this' if null): +// - start with the current lambda +// - if it is non-dependent and can capture VD, return it. +// - if it is dependent and has an implicit or explicit capture, check its parent +// whether the parent is non-depdendent and all its intervening lambdas +// can capture, if so return the child. +// [Note: When we hit a generic lambda specialization, do not climb up +// the scope stack any further since not only do we not need to, +// the scope stack will often not be synchronized with any lambdas +// enclosing the specialized generic lambda] +// +// Return the CallOperator of the capturable lambda and set function scope +// index to the correct index within the function scope stack to correspond +// to the capturable lambda. +// If VarDecl *VD is null, we check for 'this' capture. +CXXMethodDecl* clang::GetInnermostEnclosingCapturableLambda( + ArrayRef<sema::FunctionScopeInfo*> FunctionScopes, + unsigned &FunctionScopeIndex, + DeclContext *const CurContext, VarDecl *VD, + Sema &S) { + + const int IndexOfCaptureReadyLambda = + GetScopeIndexOfNearestCaptureReadyLambda(FunctionScopes,CurContext, VD); + if (IndexOfCaptureReadyLambda == -1) return 0; + assert(IndexOfCaptureReadyLambda >= 0); + const unsigned IndexOfCaptureReadyLambdaU = + static_cast<unsigned>(IndexOfCaptureReadyLambda); + sema::LambdaScopeInfo *const CaptureReadyLambdaLSI = + cast<sema::LambdaScopeInfo>(FunctionScopes[IndexOfCaptureReadyLambdaU]); + // If VD is null, we are attempting to capture 'this' + const bool IsCapturingThis = !VD; + const bool IsCapturingVariable = !IsCapturingThis; + + if (IsCapturingVariable) { + // Now check to see if this lambda can truly capture, and also + // if all enclosing lambdas of this lambda allow this capture. + QualType CaptureType, DeclRefType; + const bool CanCaptureVariable = !S.tryCaptureVariable(VD, + /*ExprVarIsUsedInLoc*/SourceLocation(), clang::Sema::TryCapture_Implicit, + /*EllipsisLoc*/ SourceLocation(), + /*BuildAndDiagnose*/false, CaptureType, DeclRefType, + &IndexOfCaptureReadyLambdaU); + if (!CanCaptureVariable) return 0; + } else { + const bool CanCaptureThis = !S.CheckCXXThisCapture( + CaptureReadyLambdaLSI->PotentialThisCaptureLocation, false, false, + &IndexOfCaptureReadyLambdaU); + if (!CanCaptureThis) return 0; + } // end 'this' capture test + FunctionScopeIndex = IndexOfCaptureReadyLambdaU; + return CaptureReadyLambdaLSI->CallOperator; +} + +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) { + bool KnownDependent, + LambdaCaptureDefault CaptureDefault) { 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); + KnownDependent, + IsGenericLambda, + CaptureDefault); DC->addDecl(Class); return Class; @@ -51,55 +187,12 @@ static bool isInInlineFunction(const DeclContext *DC) { return false; } -CXXMethodDecl *Sema::startLambdaDefinition(CXXRecordDecl *Class, - SourceRange IntroducerRange, - TypeSourceInfo *MethodType, - SourceLocation EndLoc, - ArrayRef<ParmVarDecl *> Params) { - // 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 - // the lambda-expression's parameter-declaration-clause and - // trailing-return-type respectively. - DeclarationName MethodName - = Context.DeclarationNames.getCXXOperatorName(OO_Call); - DeclarationNameLoc MethodNameLoc; - MethodNameLoc.CXXOperatorName.BeginOpNameLoc - = IntroducerRange.getBegin().getRawEncoding(); - MethodNameLoc.CXXOperatorName.EndOpNameLoc - = IntroducerRange.getEnd().getRawEncoding(); - CXXMethodDecl *Method - = CXXMethodDecl::Create(Context, Class, EndLoc, - DeclarationNameInfo(MethodName, - IntroducerRange.getBegin(), - MethodNameLoc), - MethodType->getType(), MethodType, - SC_None, - /*isInline=*/true, - /*isConstExpr=*/false, - EndLoc); - Method->setAccess(AS_public); - - // Temporarily set the lexical declaration context to the current - // context, so that the Scope stack matches the lexical nesting. - Method->setLexicalDeclContext(CurContext); - - // Add parameters. - if (!Params.empty()) { - Method->setParams(Params); - CheckParmsForFunctionDef(const_cast<ParmVarDecl **>(Params.begin()), - const_cast<ParmVarDecl **>(Params.end()), - /*CheckParameterNames=*/false); - - for (CXXMethodDecl::param_iterator P = Method->param_begin(), - PEnd = Method->param_end(); - P != PEnd; ++P) - (*P)->setOwningFunction(Method); - } - - // Allocate a mangling number for this lambda expression, if the ABI - // requires one. - Decl *ContextDecl = ExprEvalContexts.back().LambdaContextDecl; +MangleNumberingContext * +Sema::getCurrentMangleNumberContext(const DeclContext *DC, + Decl *&ManglingContextDecl) { + // Compute the context for allocating mangling numbers in the current + // expression, if the ABI requires them. + ManglingContextDecl = ExprEvalContexts.back().ManglingContextDecl; enum ContextKind { Normal, @@ -111,16 +204,16 @@ CXXMethodDecl *Sema::startLambdaDefinition(CXXRecordDecl *Class, // Default arguments of member function parameters that appear in a class // definition, as well as the initializers of data members, receive special // treatment. Identify them. - if (ContextDecl) { - if (ParmVarDecl *Param = dyn_cast<ParmVarDecl>(ContextDecl)) { + if (ManglingContextDecl) { + if (ParmVarDecl *Param = dyn_cast<ParmVarDecl>(ManglingContextDecl)) { if (const DeclContext *LexicalDC = Param->getDeclContext()->getLexicalParent()) if (LexicalDC->isRecord()) Kind = DefaultArgument; - } else if (VarDecl *Var = dyn_cast<VarDecl>(ContextDecl)) { + } else if (VarDecl *Var = dyn_cast<VarDecl>(ManglingContextDecl)) { if (Var->getDeclContext()->isRecord()) Kind = StaticDataMember; - } else if (isa<FieldDecl>(ContextDecl)) { + } else if (isa<FieldDecl>(ManglingContextDecl)) { Kind = DataMember; } } @@ -130,57 +223,147 @@ CXXMethodDecl *Sema::startLambdaDefinition(CXXRecordDecl *Class, // types in different translation units to "correspond": bool IsInNonspecializedTemplate = !ActiveTemplateInstantiations.empty() || CurContext->isDependentContext(); - unsigned ManglingNumber; switch (Kind) { case Normal: // -- the bodies of non-exported nonspecialized template functions // -- the bodies of inline functions if ((IsInNonspecializedTemplate && - !(ContextDecl && isa<ParmVarDecl>(ContextDecl))) || - isInInlineFunction(CurContext)) - ManglingNumber = Context.getLambdaManglingNumber(Method); - else - ManglingNumber = 0; + !(ManglingContextDecl && isa<ParmVarDecl>(ManglingContextDecl))) || + isInInlineFunction(CurContext)) { + ManglingContextDecl = 0; + return &Context.getManglingNumberContext(DC); + } - // There is no special context for this lambda. - ContextDecl = 0; - break; + ManglingContextDecl = 0; + return 0; case StaticDataMember: // -- the initializers of nonspecialized static members of template classes if (!IsInNonspecializedTemplate) { - ManglingNumber = 0; - ContextDecl = 0; - break; + ManglingContextDecl = 0; + return 0; } - // Fall through to assign a mangling number. + // Fall through to get the current context. case DataMember: // -- the in-class initializers of class members case DefaultArgument: // -- default arguments appearing in class definitions - ManglingNumber = ExprEvalContexts.back().getLambdaMangleContext() - .getManglingNumber(Method); - break; + return &ExprEvalContexts.back().getMangleNumberingContext(Context); } - Class->setLambdaMangling(ManglingNumber, ContextDecl); + llvm_unreachable("unexpected context"); +} + +MangleNumberingContext & +Sema::ExpressionEvaluationContextRecord::getMangleNumberingContext( + ASTContext &Ctx) { + assert(ManglingContextDecl && "Need to have a context declaration"); + if (!MangleNumbering) + MangleNumbering = Ctx.createMangleNumberingContext(); + return *MangleNumbering; +} + +CXXMethodDecl *Sema::startLambdaDefinition(CXXRecordDecl *Class, + SourceRange IntroducerRange, + TypeSourceInfo *MethodTypeInfo, + SourceLocation EndLoc, + ArrayRef<ParmVarDecl *> Params) { + QualType MethodType = MethodTypeInfo->getType(); + TemplateParameterList *TemplateParams = + getGenericLambdaTemplateParameterList(getCurLambda(), *this); + // If a lambda appears in a dependent context or is a generic lambda (has + // template parameters) and has an 'auto' return type, deduce it to a + // dependent type. + if (Class->isDependentContext() || TemplateParams) { + const FunctionProtoType *FPT = MethodType->castAs<FunctionProtoType>(); + QualType Result = FPT->getResultType(); + if (Result->isUndeducedType()) { + Result = SubstAutoType(Result, Context.DependentTy); + MethodType = Context.getFunctionType(Result, FPT->getArgTypes(), + FPT->getExtProtoInfo()); + } + } + + // 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 + // the lambda-expression's parameter-declaration-clause and + // trailing-return-type respectively. + DeclarationName MethodName + = Context.DeclarationNames.getCXXOperatorName(OO_Call); + DeclarationNameLoc MethodNameLoc; + MethodNameLoc.CXXOperatorName.BeginOpNameLoc + = IntroducerRange.getBegin().getRawEncoding(); + MethodNameLoc.CXXOperatorName.EndOpNameLoc + = IntroducerRange.getEnd().getRawEncoding(); + CXXMethodDecl *Method + = CXXMethodDecl::Create(Context, Class, EndLoc, + DeclarationNameInfo(MethodName, + IntroducerRange.getBegin(), + MethodNameLoc), + MethodType, MethodTypeInfo, + SC_None, + /*isInline=*/true, + /*isConstExpr=*/false, + EndLoc); + Method->setAccess(AS_public); + + // 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()) { + Method->setParams(Params); + CheckParmsForFunctionDef(const_cast<ParmVarDecl **>(Params.begin()), + const_cast<ParmVarDecl **>(Params.end()), + /*CheckParameterNames=*/false); + + for (CXXMethodDecl::param_iterator P = Method->param_begin(), + PEnd = Method->param_end(); + P != PEnd; ++P) + (*P)->setOwningFunction(Method); + } + + Decl *ManglingContextDecl; + if (MangleNumberingContext *MCtx = + getCurrentMangleNumberContext(Class->getDeclContext(), + ManglingContextDecl)) { + unsigned ManglingNumber = MCtx->getManglingNumber(Method); + Class->setLambdaMangling(ManglingNumber, ManglingContextDecl); + } return Method; } -LambdaScopeInfo *Sema::enterLambdaScope(CXXMethodDecl *CallOperator, +void Sema::buildLambdaScope(LambdaScopeInfo *LSI, + CXXMethodDecl *CallOperator, SourceRange IntroducerRange, LambdaCaptureDefault CaptureDefault, + SourceLocation CaptureDefaultLoc, bool ExplicitParams, bool ExplicitResultType, bool Mutable) { - PushLambdaScope(CallOperator->getParent(), CallOperator); - LambdaScopeInfo *LSI = getCurLambda(); + LSI->CallOperator = CallOperator; + CXXRecordDecl *LambdaClass = CallOperator->getParent(); + LSI->Lambda = LambdaClass; if (CaptureDefault == LCD_ByCopy) LSI->ImpCaptureStyle = LambdaScopeInfo::ImpCap_LambdaByval; else if (CaptureDefault == LCD_ByRef) LSI->ImpCaptureStyle = LambdaScopeInfo::ImpCap_LambdaByref; + LSI->CaptureDefaultLoc = CaptureDefaultLoc; LSI->IntroducerRange = IntroducerRange; LSI->ExplicitParams = ExplicitParams; LSI->Mutable = Mutable; @@ -193,16 +376,11 @@ LambdaScopeInfo *Sema::enterLambdaScope(CXXMethodDecl *CallOperator, if (RequireCompleteType(CallOperator->getLocStart(), LSI->ReturnType, diag::err_lambda_incomplete_result)) { // Do nothing. - } else if (LSI->ReturnType->isObjCObjectOrInterfaceType()) { - Diag(CallOperator->getLocStart(), diag::err_lambda_objc_object_result) - << LSI->ReturnType; } } } else { LSI->HasImplicitReturnType = true; } - - return LSI; } void Sema::finishLambdaExplicitCaptures(LambdaScopeInfo *LSI) { @@ -275,11 +453,12 @@ static EnumDecl *findEnumForBlockReturn(Expr *E) { // - it is an implicit integral conversion applied to an // enumerator-like expression of type T or if (ImplicitCastExpr *ICE = dyn_cast<ImplicitCastExpr>(E)) { - // We can only see integral conversions in valid enumerator-like - // expressions. + // We can sometimes see integral conversions in valid + // enumerator-like expressions. if (ICE->getCastKind() == CK_IntegralCast) return findEnumForBlockReturn(ICE->getSubExpr()); - return 0; + + // Otherwise, just rely on the type. } // - it is an expression of that formal enum type. @@ -351,6 +530,8 @@ static void adjustBlockReturnsToEnum(Sema &S, ArrayRef<ReturnStmt*> returns, void Sema::deduceClosureReturnType(CapturingScopeInfo &CSI) { assert(CSI.HasImplicitReturnType); + // If it was ever a placeholder, it had to been deduced to DependentTy. + assert(CSI.ReturnType.isNull() || !CSI.ReturnType->isUndeducedType()); // C++ Core Issue #975, proposed resolution: // If a lambda-expression does not include a trailing-return-type, @@ -428,16 +609,160 @@ void Sema::deduceClosureReturnType(CapturingScopeInfo &CSI) { } } +QualType Sema::performLambdaInitCaptureInitialization(SourceLocation Loc, + bool ByRef, + IdentifierInfo *Id, + Expr *&Init) { + + // We do not need to distinguish between direct-list-initialization + // and copy-list-initialization here, because we will always deduce + // std::initializer_list<T>, and direct- and copy-list-initialization + // always behave the same for such a type. + // FIXME: We should model whether an '=' was present. + const bool IsDirectInit = isa<ParenListExpr>(Init) || isa<InitListExpr>(Init); + + // Create an 'auto' or 'auto&' TypeSourceInfo that we can use to + // deduce against. + QualType DeductType = Context.getAutoDeductType(); + TypeLocBuilder TLB; + TLB.pushTypeSpec(DeductType).setNameLoc(Loc); + if (ByRef) { + DeductType = BuildReferenceType(DeductType, true, Loc, Id); + assert(!DeductType.isNull() && "can't build reference to auto"); + TLB.push<ReferenceTypeLoc>(DeductType).setSigilLoc(Loc); + } + TypeSourceInfo *TSI = TLB.getTypeSourceInfo(Context, DeductType); + + // Are we a non-list direct initialization? + ParenListExpr *CXXDirectInit = dyn_cast<ParenListExpr>(Init); + + Expr *DeduceInit = Init; + // Initializer could be a C++ direct-initializer. Deduction only works if it + // contains exactly one expression. + if (CXXDirectInit) { + if (CXXDirectInit->getNumExprs() == 0) { + Diag(CXXDirectInit->getLocStart(), diag::err_init_capture_no_expression) + << DeclarationName(Id) << TSI->getType() << Loc; + return QualType(); + } else if (CXXDirectInit->getNumExprs() > 1) { + Diag(CXXDirectInit->getExpr(1)->getLocStart(), + diag::err_init_capture_multiple_expressions) + << DeclarationName(Id) << TSI->getType() << Loc; + return QualType(); + } else { + DeduceInit = CXXDirectInit->getExpr(0); + } + } + + // Now deduce against the initialization expression and store the deduced + // type below. + QualType DeducedType; + if (DeduceAutoType(TSI, DeduceInit, DeducedType) == DAR_Failed) { + if (isa<InitListExpr>(Init)) + Diag(Loc, diag::err_init_capture_deduction_failure_from_init_list) + << DeclarationName(Id) + << (DeduceInit->getType().isNull() ? TSI->getType() + : DeduceInit->getType()) + << DeduceInit->getSourceRange(); + else + Diag(Loc, diag::err_init_capture_deduction_failure) + << DeclarationName(Id) << TSI->getType() + << (DeduceInit->getType().isNull() ? TSI->getType() + : DeduceInit->getType()) + << DeduceInit->getSourceRange(); + } + if (DeducedType.isNull()) + return QualType(); + + // Perform initialization analysis and ensure any implicit conversions + // (such as lvalue-to-rvalue) are enforced. + InitializedEntity Entity = + InitializedEntity::InitializeLambdaCapture(Id, DeducedType, Loc); + InitializationKind Kind = + IsDirectInit + ? (CXXDirectInit ? InitializationKind::CreateDirect( + Loc, Init->getLocStart(), Init->getLocEnd()) + : InitializationKind::CreateDirectList(Loc)) + : InitializationKind::CreateCopy(Loc, Init->getLocStart()); + + MultiExprArg Args = Init; + if (CXXDirectInit) + Args = + MultiExprArg(CXXDirectInit->getExprs(), CXXDirectInit->getNumExprs()); + QualType DclT; + InitializationSequence InitSeq(*this, Entity, Kind, Args); + ExprResult Result = InitSeq.Perform(*this, Entity, Kind, Args, &DclT); + + if (Result.isInvalid()) + return QualType(); + Init = Result.takeAs<Expr>(); + + // The init-capture initialization is a full-expression that must be + // processed as one before we enter the declcontext of the lambda's + // call-operator. + Result = ActOnFinishFullExpr(Init, Loc, /*DiscardedValue*/ false, + /*IsConstexpr*/ false, + /*IsLambdaInitCaptureInitalizer*/ true); + if (Result.isInvalid()) + return QualType(); + + Init = Result.takeAs<Expr>(); + return DeducedType; +} + +VarDecl *Sema::createLambdaInitCaptureVarDecl(SourceLocation Loc, + QualType InitCaptureType, IdentifierInfo *Id, Expr *Init) { + + TypeSourceInfo *TSI = Context.getTrivialTypeSourceInfo(InitCaptureType, + Loc); + // Create a dummy variable representing the init-capture. This is not actually + // used as a variable, and only exists as a way to name and refer to the + // init-capture. + // FIXME: Pass in separate source locations for '&' and identifier. + VarDecl *NewVD = VarDecl::Create(Context, CurContext, Loc, + Loc, Id, InitCaptureType, TSI, SC_Auto); + NewVD->setInitCapture(true); + NewVD->setReferenced(true); + NewVD->markUsed(Context); + NewVD->setInit(Init); + return NewVD; + +} + +FieldDecl *Sema::buildInitCaptureField(LambdaScopeInfo *LSI, VarDecl *Var) { + FieldDecl *Field = FieldDecl::Create( + Context, LSI->Lambda, Var->getLocation(), Var->getLocation(), + 0, Var->getType(), Var->getTypeSourceInfo(), 0, false, ICIS_NoInit); + Field->setImplicit(true); + Field->setAccess(AS_private); + LSI->Lambda->addDecl(Field); + + LSI->addCapture(Var, /*isBlock*/false, Var->getType()->isReferenceType(), + /*isNested*/false, Var->getLocation(), SourceLocation(), + Var->getType(), Var->getInit()); + return Field; +} + 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; - if (Scope *TmplScope = CurScope->getTemplateParamParent()) - if (!TmplScope->decl_empty()) + 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()) KnownDependent = true; - + } // Determine the signature of the call operator. TypeSourceInfo *MethodTyInfo; bool ExplicitParams = true; @@ -449,11 +774,21 @@ void Sema::ActOnStartOfLambdaDefinition(LambdaIntroducer &Intro, // C++11 [expr.prim.lambda]p4: // If a lambda-expression does not include a lambda-declarator, it is as // if the lambda-declarator were (). - FunctionProtoType::ExtProtoInfo EPI; + FunctionProtoType::ExtProtoInfo EPI(Context.getDefaultCallingConvention( + /*IsVariadic=*/false, /*IsCXXMethod=*/true)); EPI.HasTrailingReturn = true; EPI.TypeQuals |= DeclSpec::TQ_const; - QualType MethodTy = Context.getFunctionType(Context.DependentTy, None, - EPI); + // C++1y [expr.prim.lambda]: + // The lambda return type is 'auto', which is replaced by the + // trailing-return type if provided and/or deduced from 'return' + // statements + // We don't do this before C++1y, because we don't support deduced return + // types there. + QualType DefaultTypeForNoTrailingReturn = + getLangOpts().CPlusPlus1y ? Context.getAutoDeductType() + : Context.DependentTy; + QualType MethodTy = + Context.getFunctionType(DefaultTypeForNoTrailingReturn, None, EPI); MethodTyInfo = Context.getTrivialTypeSourceInfo(MethodTy); ExplicitParams = false; ExplicitResultType = false; @@ -462,21 +797,19 @@ void Sema::ActOnStartOfLambdaDefinition(LambdaIntroducer &Intro, assert(ParamInfo.isFunctionDeclarator() && "lambda-declarator is a function"); DeclaratorChunk::FunctionTypeInfo &FTI = ParamInfo.getFunctionTypeInfo(); - + // C++11 [expr.prim.lambda]p5: // This function call operator is declared const (9.3.1) if and only if // the lambda-expression's parameter-declaration-clause is not followed // by mutable. It is neither virtual nor declared volatile. [...] if (!FTI.hasMutableQualifier()) FTI.TypeQuals |= DeclSpec::TQ_const; - + MethodTyInfo = GetTypeForDeclarator(ParamInfo, CurScope); assert(MethodTyInfo && "no type from lambda-declarator"); EndLoc = ParamInfo.getSourceRange().getEnd(); - - ExplicitResultType - = MethodTyInfo->getType()->getAs<FunctionType>()->getResultType() - != Context.DependentTy; + + ExplicitResultType = FTI.hasTrailingReturnType(); if (FTI.NumArgs == 1 && !FTI.isVariadic && FTI.ArgInfo[0].Ident == 0 && cast<ParmVarDecl>(FTI.ArgInfo[0].Param)->getType()->isVoidType()) { @@ -494,11 +827,10 @@ void Sema::ActOnStartOfLambdaDefinition(LambdaIntroducer &Intro, } CXXRecordDecl *Class = createLambdaClosureType(Intro.Range, MethodTyInfo, - KnownDependent); + KnownDependent, Intro.Default); CXXMethodDecl *Method = startLambdaDefinition(Class, Intro.Range, MethodTyInfo, EndLoc, Params); - if (ExplicitParams) CheckCXXDefaultArguments(Method); @@ -508,19 +840,24 @@ void Sema::ActOnStartOfLambdaDefinition(LambdaIntroducer &Intro, // Introduce the function call operator as the current declaration context. PushDeclContext(CurScope, Method); - // Introduce the lambda scope. - LambdaScopeInfo *LSI - = enterLambdaScope(Method, Intro.Range, Intro.Default, ExplicitParams, + // Build the lambda scope. + buildLambdaScope(LSI, Method, + Intro.Range, + Intro.Default, Intro.DefaultLoc, + ExplicitParams, ExplicitResultType, !Method->isConst()); - + + // Distinct capture names, for diagnostics. + llvm::SmallSet<IdentifierInfo*, 8> CaptureNames; + // Handle explicit captures. SourceLocation PrevCaptureLoc = Intro.Default == LCD_None? Intro.Range.getBegin() : Intro.DefaultLoc; - for (SmallVector<LambdaCapture, 4>::const_iterator - C = Intro.Captures.begin(), - E = Intro.Captures.end(); - C != E; + for (SmallVectorImpl<LambdaCapture>::const_iterator + C = Intro.Captures.begin(), + E = Intro.Captures.end(); + C != E; PrevCaptureLoc = C->Loc, ++C) { if (C->Kind == LCK_This) { // C++11 [expr.prim.lambda]p8: @@ -560,44 +897,89 @@ void Sema::ActOnStartOfLambdaDefinition(LambdaIntroducer &Intro, assert(C->Id && "missing identifier for capture"); - // C++11 [expr.prim.lambda]p8: - // If a lambda-capture includes a capture-default that is &, the - // identifiers in the lambda-capture shall not be preceded by &. - // If a lambda-capture includes a capture-default that is =, [...] - // each identifier it contains shall be preceded by &. - if (C->Kind == LCK_ByRef && Intro.Default == LCD_ByRef) { - Diag(C->Loc, diag::err_reference_capture_with_reference_default) - << FixItHint::CreateRemoval( - SourceRange(PP.getLocForEndOfToken(PrevCaptureLoc), C->Loc)); - continue; - } else if (C->Kind == LCK_ByCopy && Intro.Default == LCD_ByCopy) { - Diag(C->Loc, diag::err_copy_capture_with_copy_default) - << FixItHint::CreateRemoval( - SourceRange(PP.getLocForEndOfToken(PrevCaptureLoc), C->Loc)); + if (C->Init.isInvalid()) continue; + + VarDecl *Var = 0; + if (C->Init.isUsable()) { + Diag(C->Loc, getLangOpts().CPlusPlus1y + ? diag::warn_cxx11_compat_init_capture + : diag::ext_init_capture); + + if (C->Init.get()->containsUnexpandedParameterPack()) + ContainsUnexpandedParameterPack = true; + // If the initializer expression is usable, but the InitCaptureType + // is not, then an error has occurred - so ignore the capture for now. + // for e.g., [n{0}] { }; <-- if no <initializer_list> is included. + // FIXME: we should create the init capture variable and mark it invalid + // in this case. + if (C->InitCaptureType.get().isNull()) + continue; + Var = createLambdaInitCaptureVarDecl(C->Loc, C->InitCaptureType.get(), + C->Id, C->Init.take()); + // C++1y [expr.prim.lambda]p11: + // An init-capture behaves as if it declares and explicitly + // captures a variable [...] whose declarative region is the + // lambda-expression's compound-statement + if (Var) + PushOnScopeChains(Var, CurScope, false); + } else { + // C++11 [expr.prim.lambda]p8: + // If a lambda-capture includes a capture-default that is &, the + // identifiers in the lambda-capture shall not be preceded by &. + // If a lambda-capture includes a capture-default that is =, [...] + // each identifier it contains shall be preceded by &. + if (C->Kind == LCK_ByRef && Intro.Default == LCD_ByRef) { + Diag(C->Loc, diag::err_reference_capture_with_reference_default) + << FixItHint::CreateRemoval( + SourceRange(PP.getLocForEndOfToken(PrevCaptureLoc), C->Loc)); + continue; + } else if (C->Kind == LCK_ByCopy && Intro.Default == LCD_ByCopy) { + Diag(C->Loc, diag::err_copy_capture_with_copy_default) + << FixItHint::CreateRemoval( + SourceRange(PP.getLocForEndOfToken(PrevCaptureLoc), C->Loc)); + continue; + } + + // C++11 [expr.prim.lambda]p10: + // The identifiers in a capture-list are looked up using the usual + // rules for unqualified name lookup (3.4.1) + DeclarationNameInfo Name(C->Id, C->Loc); + LookupResult R(*this, Name, LookupOrdinaryName); + LookupName(R, CurScope); + if (R.isAmbiguous()) + continue; + if (R.empty()) { + // FIXME: Disable corrections that would add qualification? + CXXScopeSpec ScopeSpec; + DeclFilterCCC<VarDecl> Validator; + if (DiagnoseEmptyLookup(CurScope, ScopeSpec, R, Validator)) + continue; + } + + Var = R.getAsSingle<VarDecl>(); } - DeclarationNameInfo Name(C->Id, C->Loc); - LookupResult R(*this, Name, LookupOrdinaryName); - LookupName(R, CurScope); - if (R.isAmbiguous()) + // C++11 [expr.prim.lambda]p8: + // An identifier or this shall not appear more than once in a + // lambda-capture. + if (!CaptureNames.insert(C->Id)) { + if (Var && LSI->isCaptured(Var)) { + Diag(C->Loc, diag::err_capture_more_than_once) + << C->Id << SourceRange(LSI->getCapture(Var).getLocation()) + << FixItHint::CreateRemoval( + SourceRange(PP.getLocForEndOfToken(PrevCaptureLoc), C->Loc)); + } else + // Previous capture captured something different (one or both was + // an init-cpature): no fixit. + Diag(C->Loc, diag::err_capture_more_than_once) << C->Id; continue; - if (R.empty()) { - // FIXME: Disable corrections that would add qualification? - CXXScopeSpec ScopeSpec; - DeclFilterCCC<VarDecl> Validator; - if (DiagnoseEmptyLookup(CurScope, ScopeSpec, R, Validator)) - continue; } // C++11 [expr.prim.lambda]p10: - // The identifiers in a capture-list are looked up using the usual rules - // for unqualified name lookup (3.4.1); each such lookup shall find a - // variable with automatic storage duration declared in the reaching - // scope of the local lambda expression. - // + // [...] each such lookup shall find a variable with automatic storage + // duration declared in the reaching scope of the local lambda expression. // Note that the 'reaching scope' check happens in tryCaptureVariable(). - VarDecl *Var = R.getAsSingle<VarDecl>(); if (!Var) { Diag(C->Loc, diag::err_capture_does_not_name_variable) << C->Id; continue; @@ -613,18 +995,6 @@ void Sema::ActOnStartOfLambdaDefinition(LambdaIntroducer &Intro, continue; } - // C++11 [expr.prim.lambda]p8: - // An identifier or this shall not appear more than once in a - // lambda-capture. - if (LSI->isCaptured(Var)) { - Diag(C->Loc, diag::err_capture_more_than_once) - << C->Id - << SourceRange(LSI->getCapture(Var).getLocation()) - << FixItHint::CreateRemoval( - SourceRange(PP.getLocForEndOfToken(PrevCaptureLoc), C->Loc)); - continue; - } - // C++11 [expr.prim.lambda]p23: // A capture followed by an ellipsis is a pack expansion (14.5.3). SourceLocation EllipsisLoc; @@ -640,10 +1010,14 @@ void Sema::ActOnStartOfLambdaDefinition(LambdaIntroducer &Intro, } else if (Var->isParameterPack()) { ContainsUnexpandedParameterPack = true; } - - TryCaptureKind Kind = C->Kind == LCK_ByRef ? TryCapture_ExplicitByRef : - TryCapture_ExplicitByVal; - tryCaptureVariable(Var, C->Loc, Kind, EllipsisLoc); + + if (C->Init.isUsable()) { + buildInitCaptureField(LSI, Var); + } else { + TryCaptureKind Kind = C->Kind == LCK_ByRef ? TryCapture_ExplicitByRef : + TryCapture_ExplicitByVal; + tryCaptureVariable(Var, C->Loc, Kind, EllipsisLoc); + } } finishLambdaExplicitCaptures(LSI); @@ -689,72 +1063,173 @@ static void addFunctionPointerConversion(Sema &S, CXXRecordDecl *Class, CXXMethodDecl *CallOperator) { // Add the conversion to function pointer. - const FunctionProtoType *Proto - = CallOperator->getType()->getAs<FunctionProtoType>(); - QualType FunctionPtrTy; - QualType FunctionTy; + const FunctionProtoType *CallOpProto = + CallOperator->getType()->getAs<FunctionProtoType>(); + const FunctionProtoType::ExtProtoInfo CallOpExtInfo = + CallOpProto->getExtProtoInfo(); + QualType PtrToFunctionTy; + QualType InvokerFunctionTy; { - FunctionProtoType::ExtProtoInfo ExtInfo = Proto->getExtProtoInfo(); - ExtInfo.TypeQuals = 0; - FunctionTy = - S.Context.getFunctionType(Proto->getResultType(), - ArrayRef<QualType>(Proto->arg_type_begin(), - Proto->getNumArgs()), - ExtInfo); - FunctionPtrTy = S.Context.getPointerType(FunctionTy); + FunctionProtoType::ExtProtoInfo InvokerExtInfo = CallOpExtInfo; + CallingConv CC = S.Context.getDefaultCallingConvention( + CallOpProto->isVariadic(), /*IsCXXMethod=*/false); + InvokerExtInfo.ExtInfo = InvokerExtInfo.ExtInfo.withCallingConv(CC); + InvokerExtInfo.TypeQuals = 0; + assert(InvokerExtInfo.RefQualifier == RQ_None && + "Lambda's call operator should not have a reference qualifier"); + InvokerFunctionTy = S.Context.getFunctionType(CallOpProto->getResultType(), + CallOpProto->getArgTypes(), InvokerExtInfo); + PtrToFunctionTy = S.Context.getPointerType(InvokerFunctionTy); } - - FunctionProtoType::ExtProtoInfo ExtInfo; - ExtInfo.TypeQuals = Qualifiers::Const; - QualType ConvTy = - S.Context.getFunctionType(FunctionPtrTy, None, ExtInfo); - + + // Create the type of the conversion function. + FunctionProtoType::ExtProtoInfo ConvExtInfo( + S.Context.getDefaultCallingConvention( + /*IsVariadic=*/false, /*IsCXXMethod=*/true)); + // The conversion function is always const. + ConvExtInfo.TypeQuals = Qualifiers::Const; + QualType ConvTy = + S.Context.getFunctionType(PtrToFunctionTy, None, ConvExtInfo); + SourceLocation Loc = IntroducerRange.getBegin(); - DeclarationName Name + DeclarationName ConversionName = S.Context.DeclarationNames.getCXXConversionFunctionName( - S.Context.getCanonicalType(FunctionPtrTy)); - DeclarationNameLoc NameLoc; - NameLoc.NamedType.TInfo = S.Context.getTrivialTypeSourceInfo(FunctionPtrTy, - Loc); + S.Context.getCanonicalType(PtrToFunctionTy)); + DeclarationNameLoc ConvNameLoc; + // Construct a TypeSourceInfo for the conversion function, and wire + // all the parameters appropriately for the FunctionProtoTypeLoc + // so that everything works during transformation/instantiation of + // generic lambdas. + // The main reason for wiring up the parameters of the conversion + // function with that of the call operator is so that constructs + // like the following work: + // auto L = [](auto b) { <-- 1 + // return [](auto a) -> decltype(a) { <-- 2 + // return a; + // }; + // }; + // int (*fp)(int) = L(5); + // Because the trailing return type can contain DeclRefExprs that refer + // to the original call operator's variables, we hijack the call + // operators ParmVarDecls below. + TypeSourceInfo *ConvNamePtrToFunctionTSI = + S.Context.getTrivialTypeSourceInfo(PtrToFunctionTy, Loc); + ConvNameLoc.NamedType.TInfo = ConvNamePtrToFunctionTSI; + + // The conversion function is a conversion to a pointer-to-function. + TypeSourceInfo *ConvTSI = S.Context.getTrivialTypeSourceInfo(ConvTy, Loc); + FunctionProtoTypeLoc ConvTL = + ConvTSI->getTypeLoc().getAs<FunctionProtoTypeLoc>(); + // Get the result of the conversion function which is a pointer-to-function. + PointerTypeLoc PtrToFunctionTL = + ConvTL.getResultLoc().getAs<PointerTypeLoc>(); + // Do the same for the TypeSourceInfo that is used to name the conversion + // operator. + PointerTypeLoc ConvNamePtrToFunctionTL = + ConvNamePtrToFunctionTSI->getTypeLoc().getAs<PointerTypeLoc>(); + + // Get the underlying function types that the conversion function will + // be converting to (should match the type of the call operator). + FunctionProtoTypeLoc CallOpConvTL = + PtrToFunctionTL.getPointeeLoc().getAs<FunctionProtoTypeLoc>(); + FunctionProtoTypeLoc CallOpConvNameTL = + ConvNamePtrToFunctionTL.getPointeeLoc().getAs<FunctionProtoTypeLoc>(); + + // Wire up the FunctionProtoTypeLocs with the call operator's parameters. + // These parameter's are essentially used to transform the name and + // the type of the conversion operator. By using the same parameters + // as the call operator's we don't have to fix any back references that + // the trailing return type of the call operator's uses (such as + // decltype(some_type<decltype(a)>::type{} + decltype(a){}) etc.) + // - we can simply use the return type of the call operator, and + // everything should work. + SmallVector<ParmVarDecl *, 4> InvokerParams; + for (unsigned I = 0, N = CallOperator->getNumParams(); I != N; ++I) { + ParmVarDecl *From = CallOperator->getParamDecl(I); + + InvokerParams.push_back(ParmVarDecl::Create(S.Context, + // Temporarily add to the TU. This is set to the invoker below. + S.Context.getTranslationUnitDecl(), + From->getLocStart(), + From->getLocation(), + From->getIdentifier(), + From->getType(), + From->getTypeSourceInfo(), + From->getStorageClass(), + /*DefaultArg=*/0)); + CallOpConvTL.setArg(I, From); + CallOpConvNameTL.setArg(I, From); + } + CXXConversionDecl *Conversion = CXXConversionDecl::Create(S.Context, Class, Loc, - DeclarationNameInfo(Name, Loc, NameLoc), + DeclarationNameInfo(ConversionName, + Loc, ConvNameLoc), ConvTy, - S.Context.getTrivialTypeSourceInfo(ConvTy, - Loc), - /*isInline=*/false, /*isExplicit=*/false, + ConvTSI, + /*isInline=*/true, /*isExplicit=*/false, /*isConstexpr=*/false, CallOperator->getBody()->getLocEnd()); Conversion->setAccess(AS_public); Conversion->setImplicit(true); - Class->addDecl(Conversion); - - // Add a non-static member function "__invoke" that will be the result of - // the conversion. - Name = &S.Context.Idents.get("__invoke"); + + if (Class->isGenericLambda()) { + // Create a template version of the conversion operator, using the template + // parameter list of the function call operator. + FunctionTemplateDecl *TemplateCallOperator = + CallOperator->getDescribedFunctionTemplate(); + FunctionTemplateDecl *ConversionTemplate = + FunctionTemplateDecl::Create(S.Context, Class, + Loc, ConversionName, + TemplateCallOperator->getTemplateParameters(), + Conversion); + ConversionTemplate->setAccess(AS_public); + ConversionTemplate->setImplicit(true); + Conversion->setDescribedFunctionTemplate(ConversionTemplate); + Class->addDecl(ConversionTemplate); + } else + Class->addDecl(Conversion); + // Add a non-static member function that will be the result of + // the conversion with a certain unique ID. + DeclarationName InvokerName = &S.Context.Idents.get( + getLambdaStaticInvokerName()); + // FIXME: Instead of passing in the CallOperator->getTypeSourceInfo() + // we should get a prebuilt TrivialTypeSourceInfo from Context + // using FunctionTy & Loc and get its TypeLoc as a FunctionProtoTypeLoc + // then rewire the parameters accordingly, by hoisting up the InvokeParams + // loop below and then use its Params to set Invoke->setParams(...) below. + // This would avoid the 'const' qualifier of the calloperator from + // contaminating the type of the invoker, which is currently adjusted + // in SemaTemplateDeduction.cpp:DeduceTemplateArguments. Fixing the + // trailing return type of the invoker would require a visitor to rebuild + // the trailing return type and adjusting all back DeclRefExpr's to refer + // to the new static invoker parameters - not the call operator's. CXXMethodDecl *Invoke = CXXMethodDecl::Create(S.Context, Class, Loc, - DeclarationNameInfo(Name, Loc), FunctionTy, - CallOperator->getTypeSourceInfo(), + DeclarationNameInfo(InvokerName, Loc), + InvokerFunctionTy, + CallOperator->getTypeSourceInfo(), SC_Static, /*IsInline=*/true, /*IsConstexpr=*/false, CallOperator->getBody()->getLocEnd()); - SmallVector<ParmVarDecl *, 4> InvokeParams; - for (unsigned I = 0, N = CallOperator->getNumParams(); I != N; ++I) { - ParmVarDecl *From = CallOperator->getParamDecl(I); - InvokeParams.push_back(ParmVarDecl::Create(S.Context, Invoke, - From->getLocStart(), - From->getLocation(), - From->getIdentifier(), - From->getType(), - From->getTypeSourceInfo(), - From->getStorageClass(), - /*DefaultArg=*/0)); - } - Invoke->setParams(InvokeParams); + for (unsigned I = 0, N = CallOperator->getNumParams(); I != N; ++I) + InvokerParams[I]->setOwningFunction(Invoke); + Invoke->setParams(InvokerParams); Invoke->setAccess(AS_private); Invoke->setImplicit(true); - Class->addDecl(Invoke); + if (Class->isGenericLambda()) { + FunctionTemplateDecl *TemplateCallOperator = + CallOperator->getDescribedFunctionTemplate(); + FunctionTemplateDecl *StaticInvokerTemplate = FunctionTemplateDecl::Create( + S.Context, Class, Loc, InvokerName, + TemplateCallOperator->getTemplateParameters(), + Invoke); + StaticInvokerTemplate->setAccess(AS_private); + StaticInvokerTemplate->setImplicit(true); + Invoke->setDescribedFunctionTemplate(StaticInvokerTemplate); + Class->addDecl(StaticInvokerTemplate); + } else + Class->addDecl(Invoke); } /// \brief Add a lambda's conversion to block pointer. @@ -768,15 +1243,13 @@ static void addBlockPointerConversion(Sema &S, { FunctionProtoType::ExtProtoInfo ExtInfo = Proto->getExtProtoInfo(); ExtInfo.TypeQuals = 0; - QualType FunctionTy - = S.Context.getFunctionType(Proto->getResultType(), - ArrayRef<QualType>(Proto->arg_type_begin(), - Proto->getNumArgs()), - ExtInfo); + QualType FunctionTy = S.Context.getFunctionType( + Proto->getResultType(), Proto->getArgTypes(), ExtInfo); BlockPtrTy = S.Context.getBlockPointerType(FunctionTy); } - - FunctionProtoType::ExtProtoInfo ExtInfo; + + FunctionProtoType::ExtProtoInfo ExtInfo(S.Context.getDefaultCallingConvention( + /*IsVariadic=*/false, /*IsCXXMethod=*/true)); ExtInfo.TypeQuals = Qualifiers::Const; QualType ConvTy = S.Context.getFunctionType(BlockPtrTy, None, ExtInfo); @@ -791,7 +1264,7 @@ static void addBlockPointerConversion(Sema &S, DeclarationNameInfo(Name, Loc, NameLoc), ConvTy, S.Context.getTrivialTypeSourceInfo(ConvTy, Loc), - /*isInline=*/false, /*isExplicit=*/false, + /*isInline=*/true, /*isExplicit=*/false, /*isConstexpr=*/false, CallOperator->getBody()->getLocEnd()); Conversion->setAccess(AS_public); @@ -806,6 +1279,7 @@ ExprResult Sema::ActOnLambdaExpr(SourceLocation StartLoc, Stmt *Body, SmallVector<LambdaExpr::Capture, 4> Captures; SmallVector<Expr *, 4> CaptureInits; LambdaCaptureDefault CaptureDefault; + SourceLocation CaptureDefaultLoc; CXXRecordDecl *Class; CXXMethodDecl *CallOperator; SourceRange IntroducerRange; @@ -848,7 +1322,7 @@ ExprResult Sema::ActOnLambdaExpr(SourceLocation StartLoc, Stmt *Body, LambdaCaptureKind Kind = From.isCopyCapture()? LCK_ByCopy : LCK_ByRef; Captures.push_back(LambdaExpr::Capture(From.getLocation(), IsImplicit, Kind, Var, From.getEllipsisLoc())); - CaptureInits.push_back(From.getCopyExpr()); + CaptureInits.push_back(From.getInitExpr()); } switch (LSI->ImpCaptureStyle) { @@ -869,13 +1343,18 @@ ExprResult Sema::ActOnLambdaExpr(SourceLocation StartLoc, Stmt *Body, llvm_unreachable("block capture in lambda"); break; } + CaptureDefaultLoc = LSI->CaptureDefaultLoc; // C++11 [expr.prim.lambda]p4: // 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. + // FIXME: Refactor and Merge the return type deduction machinery. // FIXME: Assumes current resolution to core issue 975. - if (LSI->HasImplicitReturnType) { + if (LSI->HasImplicitReturnType && !getLangOpts().CPlusPlus1y) { deduceClosureReturnType(*LSI); // - if there are no return statements in the @@ -889,20 +1368,23 @@ ExprResult Sema::ActOnLambdaExpr(SourceLocation StartLoc, Stmt *Body, // Create a function type with the inferred return type. const FunctionProtoType *Proto = CallOperator->getType()->getAs<FunctionProtoType>(); - QualType FunctionTy - = Context.getFunctionType(LSI->ReturnType, - ArrayRef<QualType>(Proto->arg_type_begin(), - Proto->getNumArgs()), - Proto->getExtProtoInfo()); + QualType FunctionTy = Context.getFunctionType( + 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); - Class->addDecl(CallOperator); + Decl *TemplateOrNonTemplateCallOperatorDecl = + CallOperator->getDescribedFunctionTemplate() + ? CallOperator->getDescribedFunctionTemplate() + : cast<Decl>(CallOperator); + + TemplateOrNonTemplateCallOperatorDecl->setLexicalDeclContext(Class); + Class->addDecl(TemplateOrNonTemplateCallOperatorDecl); + PopExpressionEvaluationContext(); // C++11 [expr.prim.lambda]p6: @@ -919,7 +1401,9 @@ ExprResult Sema::ActOnLambdaExpr(SourceLocation StartLoc, Stmt *Body, // non-explicit const conversion function to a block pointer having the // same parameter and return types as the closure type's function call // operator. - if (getLangOpts().Blocks && getLangOpts().ObjC1) + // FIXME: Fix generic lambda to block conversions. + if (getLangOpts().Blocks && getLangOpts().ObjC1 && + !Class->isGenericLambda()) addBlockPointerConversion(*this, IntroducerRange, Class, CallOperator); // Finalize the lambda class. @@ -936,32 +1420,42 @@ ExprResult Sema::ActOnLambdaExpr(SourceLocation StartLoc, Stmt *Body, ExprNeedsCleanups = true; LambdaExpr *Lambda = LambdaExpr::Create(Context, Class, IntroducerRange, - CaptureDefault, Captures, + CaptureDefault, CaptureDefaultLoc, + Captures, ExplicitParams, ExplicitResultType, CaptureInits, ArrayIndexVars, ArrayIndexStarts, Body->getLocEnd(), ContainsUnexpandedParameterPack); - // C++11 [expr.prim.lambda]p2: - // A lambda-expression shall not appear in an unevaluated operand - // (Clause 5). if (!CurContext->isDependentContext()) { switch (ExprEvalContexts.back().Context) { + // C++11 [expr.prim.lambda]p2: + // A lambda-expression shall not appear in an unevaluated operand + // (Clause 5). case Unevaluated: case UnevaluatedAbstract: + // C++1y [expr.const]p2: + // A conditional-expression e is a core constant expression unless the + // evaluation of e, following the rules of the abstract machine, would + // evaluate [...] a lambda-expression. + // + // This is technically incorrect, there are some constant evaluated contexts + // where this should be allowed. We should probably fix this when DR1607 is + // ratified, it lays out the exact set of conditions where we shouldn't + // allow a lambda-expression. + case ConstantEvaluated: // We don't actually diagnose this case immediately, because we // could be within a context where we might find out later that // the expression is potentially evaluated (e.g., for typeid). ExprEvalContexts.back().Lambdas.push_back(Lambda); break; - case ConstantEvaluated: case PotentiallyEvaluated: case PotentiallyEvaluatedIfUsed: break; } } - + return MaybeBindToTemporary(Lambda); } @@ -976,7 +1470,7 @@ ExprResult Sema::BuildBlockForLambdaConversion(SourceLocation CurrentLocation, Lambda->lookup( Context.DeclarationNames.getCXXOperatorName(OO_Call)).front()); CallOperator->setReferenced(); - CallOperator->setUsed(); + CallOperator->markUsed(Context); ExprResult Init = PerformCopyInitialization( InitializedEntity::InitializeBlock(ConvLocation, |