diff options
Diffstat (limited to 'contrib/llvm-project/clang/lib/Sema/SemaLambda.cpp')
-rw-r--r-- | contrib/llvm-project/clang/lib/Sema/SemaLambda.cpp | 2031 |
1 files changed, 2031 insertions, 0 deletions
diff --git a/contrib/llvm-project/clang/lib/Sema/SemaLambda.cpp b/contrib/llvm-project/clang/lib/Sema/SemaLambda.cpp new file mode 100644 index 000000000000..c1c6a4bf5c68 --- /dev/null +++ b/contrib/llvm-project/clang/lib/Sema/SemaLambda.cpp @@ -0,0 +1,2031 @@ +//===--- SemaLambda.cpp - Semantic Analysis for C++11 Lambdas -------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// +// +// This file implements semantic analysis for C++ lambda expressions. +// +//===----------------------------------------------------------------------===// +#include "clang/Sema/DeclSpec.h" +#include "TypeLocBuilder.h" +#include "clang/AST/ASTLambda.h" +#include "clang/AST/ExprCXX.h" +#include "clang/Basic/TargetInfo.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 "llvm/ADT/STLExtras.h" +using namespace clang; +using namespace sema; + +/// Examines the FunctionScopeInfo stack to determine the nearest +/// enclosing lambda (to the current lambda) that is 'capture-ready' for +/// the variable referenced in the current lambda (i.e. \p VarToCapture). +/// If successful, returns the index into Sema's FunctionScopeInfo stack +/// of the capture-ready lambda's LambdaScopeInfo. +/// +/// Climbs down the stack of lambdas (deepest nested lambda - i.e. current +/// lambda - is on top) to determine the index of the nearest enclosing/outer +/// lambda that is ready to capture the \p VarToCapture being referenced in +/// the current lambda. +/// As we climb down the stack, we want the index of the first such lambda - +/// that is the lambda with the highest index that is 'capture-ready'. +/// +/// A lambda 'L' is capture-ready for 'V' (var or this) if: +/// - its enclosing context is non-dependent +/// - and if the chain of lambdas between L and the lambda in which +/// V is potentially used (i.e. the lambda at the top of the scope info +/// stack), can all capture or have already captured V. +/// If \p VarToCapture is 'null' then we are trying to capture 'this'. +/// +/// Note that a lambda that is deemed 'capture-ready' still needs to be checked +/// for whether it is 'capture-capable' (see +/// getStackIndexOfNearestEnclosingCaptureCapableLambda), before it can truly +/// capture. +/// +/// \param FunctionScopes - Sema's stack of nested FunctionScopeInfo's (which a +/// LambdaScopeInfo inherits from). The current/deepest/innermost lambda +/// is at the top of the stack and has the highest index. +/// \param VarToCapture - the variable to capture. If NULL, capture 'this'. +/// +/// \returns An Optional<unsigned> Index that if evaluates to 'true' contains +/// the index (into Sema's FunctionScopeInfo stack) of the innermost lambda +/// which is capture-ready. If the return value evaluates to 'false' then +/// no lambda is capture-ready for \p VarToCapture. + +static inline Optional<unsigned> +getStackIndexOfNearestEnclosingCaptureReadyLambda( + ArrayRef<const clang::sema::FunctionScopeInfo *> FunctionScopes, + VarDecl *VarToCapture) { + // Label failure to capture. + const Optional<unsigned> NoLambdaIsCaptureReady; + + // Ignore all inner captured regions. + unsigned CurScopeIndex = FunctionScopes.size() - 1; + while (CurScopeIndex > 0 && isa<clang::sema::CapturedRegionScopeInfo>( + FunctionScopes[CurScopeIndex])) + --CurScopeIndex; + assert( + isa<clang::sema::LambdaScopeInfo>(FunctionScopes[CurScopeIndex]) && + "The function on the top of sema's function-info stack must be a lambda"); + + // If VarToCapture is null, we are attempting to capture 'this'. + const bool IsCapturingThis = !VarToCapture; + const bool IsCapturingVariable = !IsCapturingThis; + + // Start with the current lambda at the top of the stack (highest index). + DeclContext *EnclosingDC = + cast<sema::LambdaScopeInfo>(FunctionScopes[CurScopeIndex])->CallOperator; + + do { + const clang::sema::LambdaScopeInfo *LSI = + cast<sema::LambdaScopeInfo>(FunctionScopes[CurScopeIndex]); + // IF we have climbed down to an intervening enclosing lambda that contains + // the variable declaration - it obviously can/must not capture the + // variable. + // Since its enclosing DC is dependent, all the lambdas between it and the + // innermost nested lambda are dependent (otherwise we wouldn't have + // arrived here) - so we don't yet have a lambda that can capture the + // variable. + if (IsCapturingVariable && + VarToCapture->getDeclContext()->Equals(EnclosingDC)) + return NoLambdaIsCaptureReady; + + // For an enclosing lambda to be capture ready for an entity, all + // intervening lambda's have to be able to capture that entity. If even + // one of the intervening lambda's is not capable of capturing the entity + // then no enclosing lambda can ever capture that entity. + // For e.g. + // const int x = 10; + // [=](auto a) { #1 + // [](auto b) { #2 <-- an intervening lambda that can never capture 'x' + // [=](auto c) { #3 + // f(x, c); <-- can not lead to x's speculative capture by #1 or #2 + // }; }; }; + // 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(VarToCapture)) + return NoLambdaIsCaptureReady; + if (IsCapturingThis && !LSI->isCXXThisCaptured()) + return NoLambdaIsCaptureReady; + } + EnclosingDC = getLambdaAwareParentOfDeclContext(EnclosingDC); + + assert(CurScopeIndex); + --CurScopeIndex; + } while (!EnclosingDC->isTranslationUnit() && + EnclosingDC->isDependentContext() && + isLambdaCallOperator(EnclosingDC)); + + assert(CurScopeIndex < (FunctionScopes.size() - 1)); + // If the enclosingDC is not dependent, then the immediately nested lambda + // (one index above) is capture-ready. + if (!EnclosingDC->isDependentContext()) + return CurScopeIndex + 1; + return NoLambdaIsCaptureReady; +} + +/// Examines the FunctionScopeInfo stack to determine the nearest +/// enclosing lambda (to the current lambda) that is 'capture-capable' for +/// the variable referenced in the current lambda (i.e. \p VarToCapture). +/// If successful, returns the index into Sema's FunctionScopeInfo stack +/// of the capture-capable lambda's LambdaScopeInfo. +/// +/// Given the current stack of lambdas being processed by Sema and +/// the variable of interest, to identify the nearest enclosing lambda (to the +/// current lambda at the top of the stack) that can truly capture +/// a variable, it has to have the following two properties: +/// a) 'capture-ready' - be the innermost lambda that is 'capture-ready': +/// - climb down the stack (i.e. starting from the innermost and examining +/// each outer lambda step by step) checking if each enclosing +/// lambda can either implicitly or explicitly capture the variable. +/// Record the first such lambda that is enclosed in a non-dependent +/// context. If no such lambda currently exists return failure. +/// b) 'capture-capable' - make sure the 'capture-ready' lambda can truly +/// capture the variable by checking all its enclosing lambdas: +/// - check if all outer lambdas enclosing the 'capture-ready' lambda +/// identified above in 'a' can also capture the variable (this is done +/// via tryCaptureVariable for variables and CheckCXXThisCapture for +/// 'this' by passing in the index of the Lambda identified in step 'a') +/// +/// \param FunctionScopes - Sema's stack of nested FunctionScopeInfo's (which a +/// LambdaScopeInfo inherits from). The current/deepest/innermost lambda +/// is at the top of the stack. +/// +/// \param VarToCapture - the variable to capture. If NULL, capture 'this'. +/// +/// +/// \returns An Optional<unsigned> Index that if evaluates to 'true' contains +/// the index (into Sema's FunctionScopeInfo stack) of the innermost lambda +/// which is capture-capable. If the return value evaluates to 'false' then +/// no lambda is capture-capable for \p VarToCapture. + +Optional<unsigned> clang::getStackIndexOfNearestEnclosingCaptureCapableLambda( + ArrayRef<const sema::FunctionScopeInfo *> FunctionScopes, + VarDecl *VarToCapture, Sema &S) { + + const Optional<unsigned> NoLambdaIsCaptureCapable; + + const Optional<unsigned> OptionalStackIndex = + getStackIndexOfNearestEnclosingCaptureReadyLambda(FunctionScopes, + VarToCapture); + if (!OptionalStackIndex) + return NoLambdaIsCaptureCapable; + + const unsigned IndexOfCaptureReadyLambda = OptionalStackIndex.getValue(); + assert(((IndexOfCaptureReadyLambda != (FunctionScopes.size() - 1)) || + S.getCurGenericLambda()) && + "The capture ready lambda for a potential capture can only be the " + "current lambda if it is a generic lambda"); + + const sema::LambdaScopeInfo *const CaptureReadyLambdaLSI = + cast<sema::LambdaScopeInfo>(FunctionScopes[IndexOfCaptureReadyLambda]); + + // If VarToCapture is null, we are attempting to capture 'this' + const bool IsCapturingThis = !VarToCapture; + const bool IsCapturingVariable = !IsCapturingThis; + + if (IsCapturingVariable) { + // Check if the capture-ready lambda can truly capture the variable, by + // checking whether all enclosing lambdas of the capture-ready lambda allow + // the capture - i.e. make sure it is capture-capable. + QualType CaptureType, DeclRefType; + const bool CanCaptureVariable = + !S.tryCaptureVariable(VarToCapture, + /*ExprVarIsUsedInLoc*/ SourceLocation(), + clang::Sema::TryCapture_Implicit, + /*EllipsisLoc*/ SourceLocation(), + /*BuildAndDiagnose*/ false, CaptureType, + DeclRefType, &IndexOfCaptureReadyLambda); + if (!CanCaptureVariable) + return NoLambdaIsCaptureCapable; + } else { + // Check if the capture-ready lambda can truly capture 'this' by checking + // whether all enclosing lambdas of the capture-ready lambda can capture + // 'this'. + const bool CanCaptureThis = + !S.CheckCXXThisCapture( + CaptureReadyLambdaLSI->PotentialThisCaptureLocation, + /*Explicit*/ false, /*BuildAndDiagnose*/ false, + &IndexOfCaptureReadyLambda); + if (!CanCaptureThis) + return NoLambdaIsCaptureCapable; + } + return IndexOfCaptureReadyLambda; +} + +static inline TemplateParameterList * +getGenericLambdaTemplateParameterList(LambdaScopeInfo *LSI, Sema &SemaRef) { + if (!LSI->GLTemplateParameterList && !LSI->TemplateParams.empty()) { + LSI->GLTemplateParameterList = TemplateParameterList::Create( + SemaRef.Context, + /*Template kw loc*/ SourceLocation(), + /*L angle loc*/ LSI->ExplicitTemplateParamsRange.getBegin(), + LSI->TemplateParams, + /*R angle loc*/LSI->ExplicitTemplateParamsRange.getEnd(), + LSI->RequiresClause.get()); + } + return LSI->GLTemplateParameterList; +} + +CXXRecordDecl *Sema::createLambdaClosureType(SourceRange IntroducerRange, + TypeSourceInfo *Info, + 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, + IsGenericLambda, + CaptureDefault); + DC->addDecl(Class); + + return Class; +} + +/// Determine whether the given context is or is enclosed in an inline +/// function. +static bool isInInlineFunction(const DeclContext *DC) { + while (!DC->isFileContext()) { + if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(DC)) + if (FD->isInlined()) + return true; + + DC = DC->getLexicalParent(); + } + + return false; +} + +std::tuple<MangleNumberingContext *, Decl *> +Sema::getCurrentMangleNumberContext(const DeclContext *DC) { + // Compute the context for allocating mangling numbers in the current + // expression, if the ABI requires them. + Decl *ManglingContextDecl = ExprEvalContexts.back().ManglingContextDecl; + + enum ContextKind { + Normal, + DefaultArgument, + DataMember, + StaticDataMember, + InlineVariable, + VariableTemplate + } Kind = Normal; + + // 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 (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>(ManglingContextDecl)) { + if (Var->getDeclContext()->isRecord()) + Kind = StaticDataMember; + else if (Var->getMostRecentDecl()->isInline()) + Kind = InlineVariable; + else if (Var->getDescribedVarTemplate()) + Kind = VariableTemplate; + else if (auto *VTS = dyn_cast<VarTemplateSpecializationDecl>(Var)) { + if (!VTS->isExplicitSpecialization()) + Kind = VariableTemplate; + } + } else if (isa<FieldDecl>(ManglingContextDecl)) { + Kind = DataMember; + } + } + + // Itanium ABI [5.1.7]: + // In the following contexts [...] the one-definition rule requires closure + // types in different translation units to "correspond": + bool IsInNonspecializedTemplate = + inTemplateInstantiation() || CurContext->isDependentContext(); + switch (Kind) { + case Normal: { + // -- the bodies of non-exported nonspecialized template functions + // -- the bodies of inline functions + if ((IsInNonspecializedTemplate && + !(ManglingContextDecl && isa<ParmVarDecl>(ManglingContextDecl))) || + isInInlineFunction(CurContext)) { + while (auto *CD = dyn_cast<CapturedDecl>(DC)) + DC = CD->getParent(); + return std::make_tuple(&Context.getManglingNumberContext(DC), nullptr); + } + + return std::make_tuple(nullptr, nullptr); + } + + case StaticDataMember: + // -- the initializers of nonspecialized static members of template classes + if (!IsInNonspecializedTemplate) + return std::make_tuple(nullptr, ManglingContextDecl); + // Fall through to get the current context. + LLVM_FALLTHROUGH; + + case DataMember: + // -- the in-class initializers of class members + case DefaultArgument: + // -- default arguments appearing in class definitions + case InlineVariable: + // -- the initializers of inline variables + case VariableTemplate: + // -- the initializers of templated variables + return std::make_tuple( + &Context.getManglingNumberContext(ASTContext::NeedExtraManglingDecl, + ManglingContextDecl), + ManglingContextDecl); + } + + llvm_unreachable("unexpected context"); +} + +CXXMethodDecl *Sema::startLambdaDefinition(CXXRecordDecl *Class, + SourceRange IntroducerRange, + TypeSourceInfo *MethodTypeInfo, + SourceLocation EndLoc, + ArrayRef<ParmVarDecl *> Params, + ConstexprSpecKind ConstexprKind, + Expr *TrailingRequiresClause) { + 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->getReturnType(); + if (Result->isUndeducedType()) { + Result = SubstAutoType(Result, Context.DependentTy); + MethodType = Context.getFunctionType(Result, FPT->getParamTypes(), + 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, ConstexprKind, EndLoc, TrailingRequiresClause); + Method->setAccess(AS_public); + if (!TemplateParams) + Class->addDecl(Method); + + // 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) : nullptr; + if (TemplateMethod) { + TemplateMethod->setAccess(AS_public); + Method->setDescribedFunctionTemplate(TemplateMethod); + Class->addDecl(TemplateMethod); + TemplateMethod->setLexicalDeclContext(CurContext); + } + + // Add parameters. + if (!Params.empty()) { + Method->setParams(Params); + CheckParmsForFunctionDef(Params, + /*CheckParameterNames=*/false); + + for (auto P : Method->parameters()) + P->setOwningFunction(Method); + } + + return Method; +} + +void Sema::handleLambdaNumbering( + CXXRecordDecl *Class, CXXMethodDecl *Method, + Optional<std::tuple<bool, unsigned, unsigned, Decl *>> Mangling) { + if (Mangling) { + bool HasKnownInternalLinkage; + unsigned ManglingNumber, DeviceManglingNumber; + Decl *ManglingContextDecl; + std::tie(HasKnownInternalLinkage, ManglingNumber, DeviceManglingNumber, + ManglingContextDecl) = Mangling.getValue(); + Class->setLambdaMangling(ManglingNumber, ManglingContextDecl, + HasKnownInternalLinkage); + Class->setDeviceLambdaManglingNumber(DeviceManglingNumber); + return; + } + + auto getMangleNumberingContext = + [this](CXXRecordDecl *Class, + Decl *ManglingContextDecl) -> MangleNumberingContext * { + // Get mangle numbering context if there's any extra decl context. + if (ManglingContextDecl) + return &Context.getManglingNumberContext( + ASTContext::NeedExtraManglingDecl, ManglingContextDecl); + // Otherwise, from that lambda's decl context. + auto DC = Class->getDeclContext(); + while (auto *CD = dyn_cast<CapturedDecl>(DC)) + DC = CD->getParent(); + return &Context.getManglingNumberContext(DC); + }; + + MangleNumberingContext *MCtx; + Decl *ManglingContextDecl; + std::tie(MCtx, ManglingContextDecl) = + getCurrentMangleNumberContext(Class->getDeclContext()); + bool HasKnownInternalLinkage = false; + if (!MCtx && getLangOpts().CUDA) { + // Force lambda numbering in CUDA/HIP as we need to name lambdas following + // ODR. Both device- and host-compilation need to have a consistent naming + // on kernel functions. As lambdas are potential part of these `__global__` + // function names, they needs numbering following ODR. + MCtx = getMangleNumberingContext(Class, ManglingContextDecl); + assert(MCtx && "Retrieving mangle numbering context failed!"); + HasKnownInternalLinkage = true; + } + if (MCtx) { + unsigned ManglingNumber = MCtx->getManglingNumber(Method); + Class->setLambdaMangling(ManglingNumber, ManglingContextDecl, + HasKnownInternalLinkage); + Class->setDeviceLambdaManglingNumber(MCtx->getDeviceManglingNumber(Method)); + } +} + +void Sema::buildLambdaScope(LambdaScopeInfo *LSI, + CXXMethodDecl *CallOperator, + SourceRange IntroducerRange, + LambdaCaptureDefault CaptureDefault, + SourceLocation CaptureDefaultLoc, + bool ExplicitParams, + bool ExplicitResultType, + bool Mutable) { + 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; + + if (ExplicitResultType) { + LSI->ReturnType = CallOperator->getReturnType(); + + if (!LSI->ReturnType->isDependentType() && + !LSI->ReturnType->isVoidType()) { + if (RequireCompleteType(CallOperator->getBeginLoc(), LSI->ReturnType, + diag::err_lambda_incomplete_result)) { + // Do nothing. + } + } + } else { + LSI->HasImplicitReturnType = true; + } +} + +void Sema::finishLambdaExplicitCaptures(LambdaScopeInfo *LSI) { + LSI->finishedExplicitCaptures(); +} + +void Sema::ActOnLambdaExplicitTemplateParameterList(SourceLocation LAngleLoc, + ArrayRef<NamedDecl *> TParams, + SourceLocation RAngleLoc, + ExprResult RequiresClause) { + LambdaScopeInfo *LSI = getCurLambda(); + assert(LSI && "Expected a lambda scope"); + assert(LSI->NumExplicitTemplateParams == 0 && + "Already acted on explicit template parameters"); + assert(LSI->TemplateParams.empty() && + "Explicit template parameters should come " + "before invented (auto) ones"); + assert(!TParams.empty() && + "No template parameters to act on"); + LSI->TemplateParams.append(TParams.begin(), TParams.end()); + LSI->NumExplicitTemplateParams = TParams.size(); + LSI->ExplicitTemplateParamsRange = {LAngleLoc, RAngleLoc}; + LSI->RequiresClause = RequiresClause; +} + +void Sema::addLambdaParameters( + ArrayRef<LambdaIntroducer::LambdaCapture> Captures, + CXXMethodDecl *CallOperator, Scope *CurScope) { + // Introduce our parameters into the function scope + for (unsigned p = 0, NumParams = CallOperator->getNumParams(); + p < NumParams; ++p) { + ParmVarDecl *Param = CallOperator->getParamDecl(p); + + // If this has an identifier, add it to the scope stack. + if (CurScope && Param->getIdentifier()) { + bool Error = false; + // Resolution of CWG 2211 in C++17 renders shadowing ill-formed, but we + // retroactively apply it. + for (const auto &Capture : Captures) { + if (Capture.Id == Param->getIdentifier()) { + Error = true; + Diag(Param->getLocation(), diag::err_parameter_shadow_capture); + Diag(Capture.Loc, diag::note_var_explicitly_captured_here) + << Capture.Id << true; + } + } + if (!Error) + CheckShadow(CurScope, Param); + + PushOnScopeChains(Param, CurScope); + } + } +} + +/// If this expression is an enumerator-like expression of some type +/// T, return the type T; otherwise, return null. +/// +/// Pointer comparisons on the result here should always work because +/// it's derived from either the parent of an EnumConstantDecl +/// (i.e. the definition) or the declaration returned by +/// EnumType::getDecl() (i.e. the definition). +static EnumDecl *findEnumForBlockReturn(Expr *E) { + // An expression is an enumerator-like expression of type T if, + // ignoring parens and parens-like expressions: + E = E->IgnoreParens(); + + // - it is an enumerator whose enum type is T or + if (DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(E)) { + if (EnumConstantDecl *D + = dyn_cast<EnumConstantDecl>(DRE->getDecl())) { + return cast<EnumDecl>(D->getDeclContext()); + } + return nullptr; + } + + // - it is a comma expression whose RHS is an enumerator-like + // expression of type T or + if (BinaryOperator *BO = dyn_cast<BinaryOperator>(E)) { + if (BO->getOpcode() == BO_Comma) + return findEnumForBlockReturn(BO->getRHS()); + return nullptr; + } + + // - it is a statement-expression whose value expression is an + // enumerator-like expression of type T or + if (StmtExpr *SE = dyn_cast<StmtExpr>(E)) { + if (Expr *last = dyn_cast_or_null<Expr>(SE->getSubStmt()->body_back())) + return findEnumForBlockReturn(last); + return nullptr; + } + + // - it is a ternary conditional operator (not the GNU ?: + // extension) whose second and third operands are + // enumerator-like expressions of type T or + if (ConditionalOperator *CO = dyn_cast<ConditionalOperator>(E)) { + if (EnumDecl *ED = findEnumForBlockReturn(CO->getTrueExpr())) + if (ED == findEnumForBlockReturn(CO->getFalseExpr())) + return ED; + return nullptr; + } + + // (implicitly:) + // - 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 sometimes see integral conversions in valid + // enumerator-like expressions. + if (ICE->getCastKind() == CK_IntegralCast) + return findEnumForBlockReturn(ICE->getSubExpr()); + + // Otherwise, just rely on the type. + } + + // - it is an expression of that formal enum type. + if (const EnumType *ET = E->getType()->getAs<EnumType>()) { + return ET->getDecl(); + } + + // Otherwise, nope. + return nullptr; +} + +/// Attempt to find a type T for which the returned expression of the +/// given statement is an enumerator-like expression of that type. +static EnumDecl *findEnumForBlockReturn(ReturnStmt *ret) { + if (Expr *retValue = ret->getRetValue()) + return findEnumForBlockReturn(retValue); + return nullptr; +} + +/// Attempt to find a common type T for which all of the returned +/// expressions in a block are enumerator-like expressions of that +/// type. +static EnumDecl *findCommonEnumForBlockReturns(ArrayRef<ReturnStmt*> returns) { + ArrayRef<ReturnStmt*>::iterator i = returns.begin(), e = returns.end(); + + // Try to find one for the first return. + EnumDecl *ED = findEnumForBlockReturn(*i); + if (!ED) return nullptr; + + // Check that the rest of the returns have the same enum. + for (++i; i != e; ++i) { + if (findEnumForBlockReturn(*i) != ED) + return nullptr; + } + + // Never infer an anonymous enum type. + if (!ED->hasNameForLinkage()) return nullptr; + + return ED; +} + +/// Adjust the given return statements so that they formally return +/// the given type. It should require, at most, an IntegralCast. +static void adjustBlockReturnsToEnum(Sema &S, ArrayRef<ReturnStmt*> returns, + QualType returnType) { + for (ArrayRef<ReturnStmt*>::iterator + i = returns.begin(), e = returns.end(); i != e; ++i) { + ReturnStmt *ret = *i; + Expr *retValue = ret->getRetValue(); + if (S.Context.hasSameType(retValue->getType(), returnType)) + continue; + + // Right now we only support integral fixup casts. + assert(returnType->isIntegralOrUnscopedEnumerationType()); + assert(retValue->getType()->isIntegralOrUnscopedEnumerationType()); + + ExprWithCleanups *cleanups = dyn_cast<ExprWithCleanups>(retValue); + + Expr *E = (cleanups ? cleanups->getSubExpr() : retValue); + E = ImplicitCastExpr::Create(S.Context, returnType, CK_IntegralCast, E, + /*base path*/ nullptr, VK_RValue, + FPOptionsOverride()); + if (cleanups) { + cleanups->setSubExpr(E); + } else { + ret->setRetValue(E); + } + } +} + +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()); + assert((!isa<LambdaScopeInfo>(CSI) || !getLangOpts().CPlusPlus14) && + "lambda expressions use auto deduction in C++14 onwards"); + + // C++ core issue 975: + // If a lambda-expression does not include a trailing-return-type, + // it is as if the trailing-return-type denotes the following type: + // - if there are no return statements in the compound-statement, + // or all return statements return either an expression of type + // void or no expression or braced-init-list, the type void; + // - otherwise, if all return statements return an expression + // and the types of the returned expressions after + // lvalue-to-rvalue conversion (4.1 [conv.lval]), + // array-to-pointer conversion (4.2 [conv.array]), and + // function-to-pointer conversion (4.3 [conv.func]) are the + // same, that common type; + // - otherwise, the program is ill-formed. + // + // C++ core issue 1048 additionally removes top-level cv-qualifiers + // from the types of returned expressions to match the C++14 auto + // deduction rules. + // + // In addition, in blocks in non-C++ modes, if all of the return + // statements are enumerator-like expressions of some type T, where + // T has a name for linkage, then we infer the return type of the + // block to be that type. + + // First case: no return statements, implicit void return type. + ASTContext &Ctx = getASTContext(); + if (CSI.Returns.empty()) { + // It's possible there were simply no /valid/ return statements. + // In this case, the first one we found may have at least given us a type. + if (CSI.ReturnType.isNull()) + CSI.ReturnType = Ctx.VoidTy; + return; + } + + // 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()) + return; + + // Try to apply the enum-fuzz rule. + if (!getLangOpts().CPlusPlus) { + assert(isa<BlockScopeInfo>(CSI)); + const EnumDecl *ED = findCommonEnumForBlockReturns(CSI.Returns); + if (ED) { + CSI.ReturnType = Context.getTypeDeclType(ED); + adjustBlockReturnsToEnum(*this, CSI.Returns, CSI.ReturnType); + return; + } + } + + // Third case: only one return statement. Don't bother doing extra work! + if (CSI.Returns.size() == 1) + return; + + // General case: many return statements. + // Check that they all have compatible return types. + + // We require the return types to strictly match here. + // Note that we've already done the required promotions as part of + // processing the return statement. + for (const ReturnStmt *RS : CSI.Returns) { + const Expr *RetE = RS->getRetValue(); + + QualType ReturnType = + (RetE ? RetE->getType() : Context.VoidTy).getUnqualifiedType(); + if (Context.getCanonicalFunctionResultType(ReturnType) == + Context.getCanonicalFunctionResultType(CSI.ReturnType)) { + // Use the return type with the strictest possible nullability annotation. + auto RetTyNullability = ReturnType->getNullability(Ctx); + auto BlockNullability = CSI.ReturnType->getNullability(Ctx); + if (BlockNullability && + (!RetTyNullability || + hasWeakerNullability(*RetTyNullability, *BlockNullability))) + CSI.ReturnType = ReturnType; + continue; + } + + // FIXME: This is a poor diagnostic for ReturnStmts without expressions. + // TODO: It's possible that the *first* return is the divergent one. + Diag(RS->getBeginLoc(), + diag::err_typecheck_missing_return_type_incompatible) + << ReturnType << CSI.ReturnType << isa<LambdaScopeInfo>(CSI); + // Continue iterating so that we keep emitting diagnostics. + } +} + +QualType Sema::buildLambdaInitCaptureInitialization( + SourceLocation Loc, bool ByRef, SourceLocation EllipsisLoc, + Optional<unsigned> NumExpansions, IdentifierInfo *Id, bool IsDirectInit, + Expr *&Init) { + // Create an 'auto' or 'auto&' TypeSourceInfo that we can use to + // deduce against. + QualType DeductType = Context.getAutoDeductType(); + TypeLocBuilder TLB; + AutoTypeLoc TL = TLB.push<AutoTypeLoc>(DeductType); + TL.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); + } + if (EllipsisLoc.isValid()) { + if (Init->containsUnexpandedParameterPack()) { + Diag(EllipsisLoc, getLangOpts().CPlusPlus20 + ? diag::warn_cxx17_compat_init_capture_pack + : diag::ext_init_capture_pack); + DeductType = Context.getPackExpansionType(DeductType, NumExpansions, + /*ExpectPackInType=*/false); + TLB.push<PackExpansionTypeLoc>(DeductType).setEllipsisLoc(EllipsisLoc); + } else { + // Just ignore the ellipsis for now and form a non-pack variable. We'll + // diagnose this later when we try to capture it. + } + } + TypeSourceInfo *TSI = TLB.getTypeSourceInfo(Context, DeductType); + + // Deduce the type of the init capture. + QualType DeducedType = deduceVarTypeFromInitializer( + /*VarDecl*/nullptr, DeclarationName(Id), DeductType, TSI, + SourceRange(Loc, Loc), IsDirectInit, Init); + if (DeducedType.isNull()) + return QualType(); + + // Are we a non-list direct initialization? + ParenListExpr *CXXDirectInit = dyn_cast<ParenListExpr>(Init); + + // 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->getBeginLoc(), Init->getEndLoc()) + : InitializationKind::CreateDirectList(Loc)) + : InitializationKind::CreateCopy(Loc, Init->getBeginLoc()); + + 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.getAs<Expr>(); + return DeducedType; +} + +VarDecl *Sema::createLambdaInitCaptureVarDecl(SourceLocation Loc, + QualType InitCaptureType, + SourceLocation EllipsisLoc, + IdentifierInfo *Id, + unsigned InitStyle, Expr *Init) { + // FIXME: Retain the TypeSourceInfo from buildLambdaInitCaptureInitialization + // rather than reconstructing it here. + TypeSourceInfo *TSI = Context.getTrivialTypeSourceInfo(InitCaptureType, Loc); + if (auto PETL = TSI->getTypeLoc().getAs<PackExpansionTypeLoc>()) + PETL.setEllipsisLoc(EllipsisLoc); + + // 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); + // FIXME: Pass in a VarDecl::InitializationStyle. + NewVD->setInitStyle(static_cast<VarDecl::InitializationStyle>(InitStyle)); + NewVD->markUsed(Context); + NewVD->setInit(Init); + if (NewVD->isParameterPack()) + getCurLambda()->LocalPacks.push_back(NewVD); + return NewVD; +} + +void Sema::addInitCapture(LambdaScopeInfo *LSI, VarDecl *Var) { + assert(Var->isInitCapture() && "init capture flag should be set"); + LSI->addCapture(Var, /*isBlock*/false, Var->getType()->isReferenceType(), + /*isNested*/false, Var->getLocation(), SourceLocation(), + Var->getType(), /*Invalid*/false); +} + +void Sema::ActOnStartOfLambdaDefinition(LambdaIntroducer &Intro, + Declarator &ParamInfo, + Scope *CurScope) { + LambdaScopeInfo *const LSI = getCurLambda(); + assert(LSI && "LambdaScopeInfo should be on stack!"); + + // 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; + if (LSI->NumExplicitTemplateParams > 0) { + auto *TemplateParamScope = CurScope->getTemplateParamParent(); + assert(TemplateParamScope && + "Lambda with explicit template param list should establish a " + "template param scope"); + assert(TemplateParamScope->getParent()); + KnownDependent = TemplateParamScope->getParent() + ->getTemplateParamParent() != nullptr; + } else { + KnownDependent = CurScope->getTemplateParamParent() != nullptr; + } + + // Determine the signature of the call operator. + TypeSourceInfo *MethodTyInfo; + bool ExplicitParams = true; + bool ExplicitResultType = true; + bool ContainsUnexpandedParameterPack = false; + SourceLocation EndLoc; + SmallVector<ParmVarDecl *, 8> Params; + if (ParamInfo.getNumTypeObjects() == 0) { + // 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(Context.getDefaultCallingConvention( + /*IsVariadic=*/false, /*IsCXXMethod=*/true)); + EPI.HasTrailingReturn = true; + EPI.TypeQuals.addConst(); + LangAS AS = getDefaultCXXMethodAddrSpace(); + if (AS != LangAS::Default) + EPI.TypeQuals.addAddressSpace(AS); + + // 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().CPlusPlus14 ? Context.getAutoDeductType() + : Context.DependentTy; + QualType MethodTy = + Context.getFunctionType(DefaultTypeForNoTrailingReturn, None, EPI); + MethodTyInfo = Context.getTrivialTypeSourceInfo(MethodTy); + ExplicitParams = false; + ExplicitResultType = false; + EndLoc = Intro.Range.getEnd(); + } else { + 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.getOrCreateMethodQualifiers().SetTypeQual(DeclSpec::TQ_const, + SourceLocation()); + } + + MethodTyInfo = GetTypeForDeclarator(ParamInfo, CurScope); + assert(MethodTyInfo && "no type from lambda-declarator"); + EndLoc = ParamInfo.getSourceRange().getEnd(); + + ExplicitResultType = FTI.hasTrailingReturnType(); + + if (FTIHasNonVoidParameters(FTI)) { + Params.reserve(FTI.NumParams); + for (unsigned i = 0, e = FTI.NumParams; i != e; ++i) + Params.push_back(cast<ParmVarDecl>(FTI.Params[i].Param)); + } + + // Check for unexpanded parameter packs in the method type. + if (MethodTyInfo->getType()->containsUnexpandedParameterPack()) + DiagnoseUnexpandedParameterPack(Intro.Range.getBegin(), MethodTyInfo, + UPPC_DeclarationType); + } + + CXXRecordDecl *Class = createLambdaClosureType(Intro.Range, MethodTyInfo, + KnownDependent, Intro.Default); + CXXMethodDecl *Method = + startLambdaDefinition(Class, Intro.Range, MethodTyInfo, EndLoc, Params, + ParamInfo.getDeclSpec().getConstexprSpecifier(), + ParamInfo.getTrailingRequiresClause()); + if (ExplicitParams) + CheckCXXDefaultArguments(Method); + + // This represents the function body for the lambda function, check if we + // have to apply optnone due to a pragma. + AddRangeBasedOptnone(Method); + + // code_seg attribute on lambda apply to the method. + if (Attr *A = getImplicitCodeSegOrSectionAttrForFunction(Method, /*IsDefinition=*/true)) + Method->addAttr(A); + + // Attributes on the lambda apply to the method. + ProcessDeclAttributes(CurScope, Method, ParamInfo); + + // CUDA lambdas get implicit host and device attributes. + if (getLangOpts().CUDA) + CUDASetLambdaAttrs(Method); + + // OpenMP lambdas might get assumumption attributes. + if (LangOpts.OpenMP) + ActOnFinishedFunctionDefinitionInOpenMPAssumeScope(Method); + + // Number the lambda for linkage purposes if necessary. + handleLambdaNumbering(Class, Method); + + // Introduce the function call operator as the current declaration context. + PushDeclContext(CurScope, Method); + + // Build the lambda scope. + buildLambdaScope(LSI, Method, Intro.Range, Intro.Default, Intro.DefaultLoc, + ExplicitParams, ExplicitResultType, !Method->isConst()); + + // C++11 [expr.prim.lambda]p9: + // A lambda-expression whose smallest enclosing scope is a block scope is a + // local lambda expression; any other lambda expression shall not have a + // capture-default or simple-capture in its lambda-introducer. + // + // For simple-captures, this is covered by the check below that any named + // entity is a variable that can be captured. + // + // For DR1632, we also allow a capture-default in any context where we can + // odr-use 'this' (in particular, in a default initializer for a non-static + // data member). + if (Intro.Default != LCD_None && !Class->getParent()->isFunctionOrMethod() && + (getCurrentThisType().isNull() || + CheckCXXThisCapture(SourceLocation(), /*Explicit*/true, + /*BuildAndDiagnose*/false))) + Diag(Intro.DefaultLoc, diag::err_capture_default_non_local); + + // 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 (auto C = Intro.Captures.begin(), E = Intro.Captures.end(); C != E; + PrevCaptureLoc = C->Loc, ++C) { + if (C->Kind == LCK_This || C->Kind == LCK_StarThis) { + if (C->Kind == LCK_StarThis) + Diag(C->Loc, !getLangOpts().CPlusPlus17 + ? diag::ext_star_this_lambda_capture_cxx17 + : diag::warn_cxx14_compat_star_this_lambda_capture); + + // C++11 [expr.prim.lambda]p8: + // An identifier or this shall not appear more than once in a + // lambda-capture. + if (LSI->isCXXThisCaptured()) { + Diag(C->Loc, diag::err_capture_more_than_once) + << "'this'" << SourceRange(LSI->getCXXThisCapture().getLocation()) + << FixItHint::CreateRemoval( + SourceRange(getLocForEndOfToken(PrevCaptureLoc), C->Loc)); + continue; + } + + // C++2a [expr.prim.lambda]p8: + // If a lambda-capture includes a capture-default that is =, + // each simple-capture of that lambda-capture shall be of the form + // "&identifier", "this", or "* this". [ Note: The form [&,this] is + // redundant but accepted for compatibility with ISO C++14. --end note ] + if (Intro.Default == LCD_ByCopy && C->Kind != LCK_StarThis) + Diag(C->Loc, !getLangOpts().CPlusPlus20 + ? diag::ext_equals_this_lambda_capture_cxx20 + : diag::warn_cxx17_compat_equals_this_lambda_capture); + + // C++11 [expr.prim.lambda]p12: + // If this is captured by a local lambda expression, its nearest + // enclosing function shall be a non-static member function. + QualType ThisCaptureType = getCurrentThisType(); + if (ThisCaptureType.isNull()) { + Diag(C->Loc, diag::err_this_capture) << true; + continue; + } + + CheckCXXThisCapture(C->Loc, /*Explicit=*/true, /*BuildAndDiagnose*/ true, + /*FunctionScopeIndexToStopAtPtr*/ nullptr, + C->Kind == LCK_StarThis); + if (!LSI->Captures.empty()) + LSI->ExplicitCaptureRanges[LSI->Captures.size() - 1] = C->ExplicitRange; + continue; + } + + assert(C->Id && "missing identifier for capture"); + + if (C->Init.isInvalid()) + continue; + + VarDecl *Var = nullptr; + if (C->Init.isUsable()) { + Diag(C->Loc, getLangOpts().CPlusPlus14 + ? diag::warn_cxx11_compat_init_capture + : diag::ext_init_capture); + + // 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; + + if (C->Init.get()->containsUnexpandedParameterPack() && + !C->InitCaptureType.get()->getAs<PackExpansionType>()) + DiagnoseUnexpandedParameterPack(C->Init.get(), UPPC_Initializer); + + unsigned InitStyle; + switch (C->InitKind) { + case LambdaCaptureInitKind::NoInit: + llvm_unreachable("not an init-capture?"); + case LambdaCaptureInitKind::CopyInit: + InitStyle = VarDecl::CInit; + break; + case LambdaCaptureInitKind::DirectInit: + InitStyle = VarDecl::CallInit; + break; + case LambdaCaptureInitKind::ListInit: + InitStyle = VarDecl::ListInit; + break; + } + Var = createLambdaInitCaptureVarDecl(C->Loc, C->InitCaptureType.get(), + C->EllipsisLoc, C->Id, InitStyle, + C->Init.get()); + // 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 { + assert(C->InitKind == LambdaCaptureInitKind::NoInit && + "init capture has valid but null init?"); + + // 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(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(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>(); + if (Var && DiagnoseUseOfDecl(Var, C->Loc)) + continue; + } + + // 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).second) { + if (Var && LSI->isCaptured(Var)) { + Diag(C->Loc, diag::err_capture_more_than_once) + << C->Id << SourceRange(LSI->getCapture(Var).getLocation()) + << FixItHint::CreateRemoval( + SourceRange(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; + } + + // C++11 [expr.prim.lambda]p10: + // [...] 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(). + if (!Var) { + Diag(C->Loc, diag::err_capture_does_not_name_variable) << C->Id; + continue; + } + + // Ignore invalid decls; they'll just confuse the code later. + if (Var->isInvalidDecl()) + continue; + + if (!Var->hasLocalStorage()) { + Diag(C->Loc, diag::err_capture_non_automatic_variable) << C->Id; + Diag(Var->getLocation(), diag::note_previous_decl) << C->Id; + continue; + } + + // C++11 [expr.prim.lambda]p23: + // A capture followed by an ellipsis is a pack expansion (14.5.3). + SourceLocation EllipsisLoc; + if (C->EllipsisLoc.isValid()) { + if (Var->isParameterPack()) { + EllipsisLoc = C->EllipsisLoc; + } else { + Diag(C->EllipsisLoc, diag::err_pack_expansion_without_parameter_packs) + << (C->Init.isUsable() ? C->Init.get()->getSourceRange() + : SourceRange(C->Loc)); + + // Just ignore the ellipsis. + } + } else if (Var->isParameterPack()) { + ContainsUnexpandedParameterPack = true; + } + + if (C->Init.isUsable()) { + addInitCapture(LSI, Var); + } else { + TryCaptureKind Kind = C->Kind == LCK_ByRef ? TryCapture_ExplicitByRef : + TryCapture_ExplicitByVal; + tryCaptureVariable(Var, C->Loc, Kind, EllipsisLoc); + } + if (!LSI->Captures.empty()) + LSI->ExplicitCaptureRanges[LSI->Captures.size() - 1] = C->ExplicitRange; + } + finishLambdaExplicitCaptures(LSI); + + LSI->ContainsUnexpandedParameterPack |= ContainsUnexpandedParameterPack; + + // Add lambda parameters into scope. + addLambdaParameters(Intro.Captures, Method, CurScope); + + // Enter a new evaluation context to insulate the lambda from any + // cleanups from the enclosing full-expression. + PushExpressionEvaluationContext( + LSI->CallOperator->isConsteval() + ? ExpressionEvaluationContext::ConstantEvaluated + : ExpressionEvaluationContext::PotentiallyEvaluated); +} + +void Sema::ActOnLambdaError(SourceLocation StartLoc, Scope *CurScope, + bool IsInstantiation) { + LambdaScopeInfo *LSI = cast<LambdaScopeInfo>(FunctionScopes.back()); + + // Leave the expression-evaluation context. + DiscardCleanupsInEvaluationContext(); + PopExpressionEvaluationContext(); + + // Leave the context of the lambda. + if (!IsInstantiation) + PopDeclContext(); + + // Finalize the lambda. + CXXRecordDecl *Class = LSI->Lambda; + Class->setInvalidDecl(); + SmallVector<Decl*, 4> Fields(Class->fields()); + ActOnFields(nullptr, Class->getLocation(), Class, Fields, SourceLocation(), + SourceLocation(), ParsedAttributesView()); + CheckCompletedCXXClass(nullptr, Class); + + PopFunctionScopeInfo(); +} + +template <typename Func> +static void repeatForLambdaConversionFunctionCallingConvs( + Sema &S, const FunctionProtoType &CallOpProto, Func F) { + CallingConv DefaultFree = S.Context.getDefaultCallingConvention( + CallOpProto.isVariadic(), /*IsCXXMethod=*/false); + CallingConv DefaultMember = S.Context.getDefaultCallingConvention( + CallOpProto.isVariadic(), /*IsCXXMethod=*/true); + CallingConv CallOpCC = CallOpProto.getCallConv(); + + /// Implement emitting a version of the operator for many of the calling + /// conventions for MSVC, as described here: + /// https://devblogs.microsoft.com/oldnewthing/20150220-00/?p=44623. + /// Experimentally, we determined that cdecl, stdcall, fastcall, and + /// vectorcall are generated by MSVC when it is supported by the target. + /// Additionally, we are ensuring that the default-free/default-member and + /// call-operator calling convention are generated as well. + /// NOTE: We intentionally generate a 'thiscall' on Win32 implicitly from the + /// 'member default', despite MSVC not doing so. We do this in order to ensure + /// that someone who intentionally places 'thiscall' on the lambda call + /// operator will still get that overload, since we don't have the a way of + /// detecting the attribute by the time we get here. + if (S.getLangOpts().MSVCCompat) { + CallingConv Convs[] = { + CC_C, CC_X86StdCall, CC_X86FastCall, CC_X86VectorCall, + DefaultFree, DefaultMember, CallOpCC}; + llvm::sort(Convs); + llvm::iterator_range<CallingConv *> Range( + std::begin(Convs), std::unique(std::begin(Convs), std::end(Convs))); + const TargetInfo &TI = S.getASTContext().getTargetInfo(); + + for (CallingConv C : Range) { + if (TI.checkCallingConvention(C) == TargetInfo::CCCR_OK) + F(C); + } + return; + } + + if (CallOpCC == DefaultMember && DefaultMember != DefaultFree) { + F(DefaultFree); + F(DefaultMember); + } else { + F(CallOpCC); + } +} + +// Returns the 'standard' calling convention to be used for the lambda +// conversion function, that is, the 'free' function calling convention unless +// it is overridden by a non-default calling convention attribute. +static CallingConv +getLambdaConversionFunctionCallConv(Sema &S, + const FunctionProtoType *CallOpProto) { + CallingConv DefaultFree = S.Context.getDefaultCallingConvention( + CallOpProto->isVariadic(), /*IsCXXMethod=*/false); + CallingConv DefaultMember = S.Context.getDefaultCallingConvention( + CallOpProto->isVariadic(), /*IsCXXMethod=*/true); + CallingConv CallOpCC = CallOpProto->getCallConv(); + + // If the call-operator hasn't been changed, return both the 'free' and + // 'member' function calling convention. + if (CallOpCC == DefaultMember && DefaultMember != DefaultFree) + return DefaultFree; + return CallOpCC; +} + +QualType Sema::getLambdaConversionFunctionResultType( + const FunctionProtoType *CallOpProto, CallingConv CC) { + const FunctionProtoType::ExtProtoInfo CallOpExtInfo = + CallOpProto->getExtProtoInfo(); + FunctionProtoType::ExtProtoInfo InvokerExtInfo = CallOpExtInfo; + InvokerExtInfo.ExtInfo = InvokerExtInfo.ExtInfo.withCallingConv(CC); + InvokerExtInfo.TypeQuals = Qualifiers(); + assert(InvokerExtInfo.RefQualifier == RQ_None && + "Lambda's call operator should not have a reference qualifier"); + return Context.getFunctionType(CallOpProto->getReturnType(), + CallOpProto->getParamTypes(), InvokerExtInfo); +} + +/// Add a lambda's conversion to function pointer, as described in +/// C++11 [expr.prim.lambda]p6. +static void addFunctionPointerConversion(Sema &S, SourceRange IntroducerRange, + CXXRecordDecl *Class, + CXXMethodDecl *CallOperator, + QualType InvokerFunctionTy) { + // This conversion is explicitly disabled if the lambda's function has + // pass_object_size attributes on any of its parameters. + auto HasPassObjectSizeAttr = [](const ParmVarDecl *P) { + return P->hasAttr<PassObjectSizeAttr>(); + }; + if (llvm::any_of(CallOperator->parameters(), HasPassObjectSizeAttr)) + return; + + // Add the conversion to function pointer. + QualType PtrToFunctionTy = S.Context.getPointerType(InvokerFunctionTy); + + // Create the type of the conversion function. + FunctionProtoType::ExtProtoInfo ConvExtInfo( + S.Context.getDefaultCallingConvention( + /*IsVariadic=*/false, /*IsCXXMethod=*/true)); + // The conversion function is always const and noexcept. + ConvExtInfo.TypeQuals = Qualifiers(); + ConvExtInfo.TypeQuals.addConst(); + ConvExtInfo.ExceptionSpec.Type = EST_BasicNoexcept; + QualType ConvTy = + S.Context.getFunctionType(PtrToFunctionTy, None, ConvExtInfo); + + SourceLocation Loc = IntroducerRange.getBegin(); + DeclarationName ConversionName + = S.Context.DeclarationNames.getCXXConversionFunctionName( + 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.getReturnLoc().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->getBeginLoc(), + From->getLocation(), From->getIdentifier(), From->getType(), + From->getTypeSourceInfo(), From->getStorageClass(), + /*DefArg=*/nullptr)); + CallOpConvTL.setParam(I, From); + CallOpConvNameTL.setParam(I, From); + } + + CXXConversionDecl *Conversion = CXXConversionDecl::Create( + S.Context, Class, Loc, + DeclarationNameInfo(ConversionName, Loc, ConvNameLoc), ConvTy, ConvTSI, + /*isInline=*/true, ExplicitSpecifier(), + S.getLangOpts().CPlusPlus17 ? ConstexprSpecKind::Constexpr + : ConstexprSpecKind::Unspecified, + CallOperator->getBody()->getEndLoc()); + Conversion->setAccess(AS_public); + Conversion->setImplicit(true); + + 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(InvokerName, Loc), + InvokerFunctionTy, CallOperator->getTypeSourceInfo(), SC_Static, + /*isInline=*/true, ConstexprSpecKind::Unspecified, + CallOperator->getBody()->getEndLoc()); + for (unsigned I = 0, N = CallOperator->getNumParams(); I != N; ++I) + InvokerParams[I]->setOwningFunction(Invoke); + Invoke->setParams(InvokerParams); + Invoke->setAccess(AS_private); + Invoke->setImplicit(true); + 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); +} + +/// Add a lambda's conversion to function pointers, as described in +/// C++11 [expr.prim.lambda]p6. Note that in most cases, this should emit only a +/// single pointer conversion. In the event that the default calling convention +/// for free and member functions is different, it will emit both conventions. +static void addFunctionPointerConversions(Sema &S, SourceRange IntroducerRange, + CXXRecordDecl *Class, + CXXMethodDecl *CallOperator) { + const FunctionProtoType *CallOpProto = + CallOperator->getType()->castAs<FunctionProtoType>(); + + repeatForLambdaConversionFunctionCallingConvs( + S, *CallOpProto, [&](CallingConv CC) { + QualType InvokerFunctionTy = + S.getLambdaConversionFunctionResultType(CallOpProto, CC); + addFunctionPointerConversion(S, IntroducerRange, Class, CallOperator, + InvokerFunctionTy); + }); +} + +/// Add a lambda's conversion to block pointer. +static void addBlockPointerConversion(Sema &S, + SourceRange IntroducerRange, + CXXRecordDecl *Class, + CXXMethodDecl *CallOperator) { + const FunctionProtoType *CallOpProto = + CallOperator->getType()->castAs<FunctionProtoType>(); + QualType FunctionTy = S.getLambdaConversionFunctionResultType( + CallOpProto, getLambdaConversionFunctionCallConv(S, CallOpProto)); + QualType BlockPtrTy = S.Context.getBlockPointerType(FunctionTy); + + FunctionProtoType::ExtProtoInfo ConversionEPI( + S.Context.getDefaultCallingConvention( + /*IsVariadic=*/false, /*IsCXXMethod=*/true)); + ConversionEPI.TypeQuals = Qualifiers(); + ConversionEPI.TypeQuals.addConst(); + QualType ConvTy = S.Context.getFunctionType(BlockPtrTy, None, ConversionEPI); + + SourceLocation Loc = IntroducerRange.getBegin(); + DeclarationName Name + = S.Context.DeclarationNames.getCXXConversionFunctionName( + S.Context.getCanonicalType(BlockPtrTy)); + DeclarationNameLoc NameLoc; + NameLoc.NamedType.TInfo = S.Context.getTrivialTypeSourceInfo(BlockPtrTy, Loc); + CXXConversionDecl *Conversion = CXXConversionDecl::Create( + S.Context, Class, Loc, DeclarationNameInfo(Name, Loc, NameLoc), ConvTy, + S.Context.getTrivialTypeSourceInfo(ConvTy, Loc), + /*isInline=*/true, ExplicitSpecifier(), ConstexprSpecKind::Unspecified, + CallOperator->getBody()->getEndLoc()); + Conversion->setAccess(AS_public); + Conversion->setImplicit(true); + Class->addDecl(Conversion); +} + +ExprResult Sema::BuildCaptureInit(const Capture &Cap, + SourceLocation ImplicitCaptureLoc, + bool IsOpenMPMapping) { + // VLA captures don't have a stored initialization expression. + if (Cap.isVLATypeCapture()) + return ExprResult(); + + // An init-capture is initialized directly from its stored initializer. + if (Cap.isInitCapture()) + return Cap.getVariable()->getInit(); + + // For anything else, build an initialization expression. For an implicit + // capture, the capture notionally happens at the capture-default, so use + // that location here. + SourceLocation Loc = + ImplicitCaptureLoc.isValid() ? ImplicitCaptureLoc : Cap.getLocation(); + + // C++11 [expr.prim.lambda]p21: + // When the lambda-expression is evaluated, the entities that + // are captured by copy are used to direct-initialize each + // corresponding non-static data member of the resulting closure + // object. (For array members, the array elements are + // direct-initialized in increasing subscript order.) These + // initializations are performed in the (unspecified) order in + // which the non-static data members are declared. + + // C++ [expr.prim.lambda]p12: + // An entity captured by a lambda-expression is odr-used (3.2) in + // the scope containing the lambda-expression. + ExprResult Init; + IdentifierInfo *Name = nullptr; + if (Cap.isThisCapture()) { + QualType ThisTy = getCurrentThisType(); + Expr *This = BuildCXXThisExpr(Loc, ThisTy, ImplicitCaptureLoc.isValid()); + if (Cap.isCopyCapture()) + Init = CreateBuiltinUnaryOp(Loc, UO_Deref, This); + else + Init = This; + } else { + assert(Cap.isVariableCapture() && "unknown kind of capture"); + VarDecl *Var = Cap.getVariable(); + Name = Var->getIdentifier(); + Init = BuildDeclarationNameExpr( + CXXScopeSpec(), DeclarationNameInfo(Var->getDeclName(), Loc), Var); + } + + // In OpenMP, the capture kind doesn't actually describe how to capture: + // variables are "mapped" onto the device in a process that does not formally + // make a copy, even for a "copy capture". + if (IsOpenMPMapping) + return Init; + + if (Init.isInvalid()) + return ExprError(); + + Expr *InitExpr = Init.get(); + InitializedEntity Entity = InitializedEntity::InitializeLambdaCapture( + Name, Cap.getCaptureType(), Loc); + InitializationKind InitKind = + InitializationKind::CreateDirect(Loc, Loc, Loc); + InitializationSequence InitSeq(*this, Entity, InitKind, InitExpr); + return InitSeq.Perform(*this, Entity, InitKind, InitExpr); +} + +ExprResult Sema::ActOnLambdaExpr(SourceLocation StartLoc, Stmt *Body, + Scope *CurScope) { + LambdaScopeInfo LSI = *cast<LambdaScopeInfo>(FunctionScopes.back()); + ActOnFinishFunctionBody(LSI.CallOperator, Body); + return BuildLambdaExpr(StartLoc, Body->getEndLoc(), &LSI); +} + +static LambdaCaptureDefault +mapImplicitCaptureStyle(CapturingScopeInfo::ImplicitCaptureStyle ICS) { + switch (ICS) { + case CapturingScopeInfo::ImpCap_None: + return LCD_None; + case CapturingScopeInfo::ImpCap_LambdaByval: + return LCD_ByCopy; + case CapturingScopeInfo::ImpCap_CapturedRegion: + case CapturingScopeInfo::ImpCap_LambdaByref: + return LCD_ByRef; + case CapturingScopeInfo::ImpCap_Block: + llvm_unreachable("block capture in lambda"); + } + llvm_unreachable("Unknown implicit capture style"); +} + +bool Sema::CaptureHasSideEffects(const Capture &From) { + if (From.isInitCapture()) { + Expr *Init = From.getVariable()->getInit(); + if (Init && Init->HasSideEffects(Context)) + return true; + } + + if (!From.isCopyCapture()) + return false; + + const QualType T = From.isThisCapture() + ? getCurrentThisType()->getPointeeType() + : From.getCaptureType(); + + if (T.isVolatileQualified()) + return true; + + const Type *BaseT = T->getBaseElementTypeUnsafe(); + if (const CXXRecordDecl *RD = BaseT->getAsCXXRecordDecl()) + return !RD->isCompleteDefinition() || !RD->hasTrivialCopyConstructor() || + !RD->hasTrivialDestructor(); + + return false; +} + +bool Sema::DiagnoseUnusedLambdaCapture(SourceRange CaptureRange, + const Capture &From) { + if (CaptureHasSideEffects(From)) + return false; + + if (From.isVLATypeCapture()) + return false; + + auto diag = Diag(From.getLocation(), diag::warn_unused_lambda_capture); + if (From.isThisCapture()) + diag << "'this'"; + else + diag << From.getVariable(); + diag << From.isNonODRUsed(); + diag << FixItHint::CreateRemoval(CaptureRange); + return true; +} + +/// Create a field within the lambda class or captured statement record for the +/// given capture. +FieldDecl *Sema::BuildCaptureField(RecordDecl *RD, + const sema::Capture &Capture) { + SourceLocation Loc = Capture.getLocation(); + QualType FieldType = Capture.getCaptureType(); + + TypeSourceInfo *TSI = nullptr; + if (Capture.isVariableCapture()) { + auto *Var = Capture.getVariable(); + if (Var->isInitCapture()) + TSI = Capture.getVariable()->getTypeSourceInfo(); + } + + // FIXME: Should we really be doing this? A null TypeSourceInfo seems more + // appropriate, at least for an implicit capture. + if (!TSI) + TSI = Context.getTrivialTypeSourceInfo(FieldType, Loc); + + // Build the non-static data member. + FieldDecl *Field = + FieldDecl::Create(Context, RD, /*StartLoc=*/Loc, /*IdLoc=*/Loc, + /*Id=*/nullptr, FieldType, TSI, /*BW=*/nullptr, + /*Mutable=*/false, ICIS_NoInit); + // If the variable being captured has an invalid type, mark the class as + // invalid as well. + if (!FieldType->isDependentType()) { + if (RequireCompleteSizedType(Loc, FieldType, + diag::err_field_incomplete_or_sizeless)) { + RD->setInvalidDecl(); + Field->setInvalidDecl(); + } else { + NamedDecl *Def; + FieldType->isIncompleteType(&Def); + if (Def && Def->isInvalidDecl()) { + RD->setInvalidDecl(); + Field->setInvalidDecl(); + } + } + } + Field->setImplicit(true); + Field->setAccess(AS_private); + RD->addDecl(Field); + + if (Capture.isVLATypeCapture()) + Field->setCapturedVLAType(Capture.getCapturedVLAType()); + + return Field; +} + +ExprResult Sema::BuildLambdaExpr(SourceLocation StartLoc, SourceLocation EndLoc, + LambdaScopeInfo *LSI) { + // Collect information from the lambda scope. + SmallVector<LambdaCapture, 4> Captures; + SmallVector<Expr *, 4> CaptureInits; + SourceLocation CaptureDefaultLoc = LSI->CaptureDefaultLoc; + LambdaCaptureDefault CaptureDefault = + mapImplicitCaptureStyle(LSI->ImpCaptureStyle); + CXXRecordDecl *Class; + CXXMethodDecl *CallOperator; + SourceRange IntroducerRange; + bool ExplicitParams; + bool ExplicitResultType; + CleanupInfo LambdaCleanup; + bool ContainsUnexpandedParameterPack; + bool IsGenericLambda; + { + CallOperator = LSI->CallOperator; + Class = LSI->Lambda; + IntroducerRange = LSI->IntroducerRange; + ExplicitParams = LSI->ExplicitParams; + ExplicitResultType = !LSI->HasImplicitReturnType; + LambdaCleanup = LSI->Cleanup; + ContainsUnexpandedParameterPack = LSI->ContainsUnexpandedParameterPack; + IsGenericLambda = Class->isGenericLambda(); + + CallOperator->setLexicalDeclContext(Class); + Decl *TemplateOrNonTemplateCallOperatorDecl = + CallOperator->getDescribedFunctionTemplate() + ? CallOperator->getDescribedFunctionTemplate() + : cast<Decl>(CallOperator); + + // FIXME: Is this really the best choice? Keeping the lexical decl context + // set as CurContext seems more faithful to the source. + TemplateOrNonTemplateCallOperatorDecl->setLexicalDeclContext(Class); + + PopExpressionEvaluationContext(); + + // True if the current capture has a used capture or default before it. + bool CurHasPreviousCapture = CaptureDefault != LCD_None; + SourceLocation PrevCaptureLoc = CurHasPreviousCapture ? + CaptureDefaultLoc : IntroducerRange.getBegin(); + + for (unsigned I = 0, N = LSI->Captures.size(); I != N; ++I) { + const Capture &From = LSI->Captures[I]; + + if (From.isInvalid()) + return ExprError(); + + assert(!From.isBlockCapture() && "Cannot capture __block variables"); + bool IsImplicit = I >= LSI->NumExplicitCaptures; + SourceLocation ImplicitCaptureLoc = + IsImplicit ? CaptureDefaultLoc : SourceLocation(); + + // Use source ranges of explicit captures for fixits where available. + SourceRange CaptureRange = LSI->ExplicitCaptureRanges[I]; + + // Warn about unused explicit captures. + bool IsCaptureUsed = true; + if (!CurContext->isDependentContext() && !IsImplicit && + !From.isODRUsed()) { + // Initialized captures that are non-ODR used may not be eliminated. + // FIXME: Where did the IsGenericLambda here come from? + bool NonODRUsedInitCapture = + IsGenericLambda && From.isNonODRUsed() && From.isInitCapture(); + if (!NonODRUsedInitCapture) { + bool IsLast = (I + 1) == LSI->NumExplicitCaptures; + SourceRange FixItRange; + if (CaptureRange.isValid()) { + if (!CurHasPreviousCapture && !IsLast) { + // If there are no captures preceding this capture, remove the + // following comma. + FixItRange = SourceRange(CaptureRange.getBegin(), + getLocForEndOfToken(CaptureRange.getEnd())); + } else { + // Otherwise, remove the comma since the last used capture. + FixItRange = SourceRange(getLocForEndOfToken(PrevCaptureLoc), + CaptureRange.getEnd()); + } + } + + IsCaptureUsed = !DiagnoseUnusedLambdaCapture(FixItRange, From); + } + } + + if (CaptureRange.isValid()) { + CurHasPreviousCapture |= IsCaptureUsed; + PrevCaptureLoc = CaptureRange.getEnd(); + } + + // Map the capture to our AST representation. + LambdaCapture Capture = [&] { + if (From.isThisCapture()) { + // Capturing 'this' implicitly with a default of '[=]' is deprecated, + // because it results in a reference capture. Don't warn prior to + // C++2a; there's nothing that can be done about it before then. + if (getLangOpts().CPlusPlus20 && IsImplicit && + CaptureDefault == LCD_ByCopy) { + Diag(From.getLocation(), diag::warn_deprecated_this_capture); + Diag(CaptureDefaultLoc, diag::note_deprecated_this_capture) + << FixItHint::CreateInsertion( + getLocForEndOfToken(CaptureDefaultLoc), ", this"); + } + return LambdaCapture(From.getLocation(), IsImplicit, + From.isCopyCapture() ? LCK_StarThis : LCK_This); + } else if (From.isVLATypeCapture()) { + return LambdaCapture(From.getLocation(), IsImplicit, LCK_VLAType); + } else { + assert(From.isVariableCapture() && "unknown kind of capture"); + VarDecl *Var = From.getVariable(); + LambdaCaptureKind Kind = + From.isCopyCapture() ? LCK_ByCopy : LCK_ByRef; + return LambdaCapture(From.getLocation(), IsImplicit, Kind, Var, + From.getEllipsisLoc()); + } + }(); + + // Form the initializer for the capture field. + ExprResult Init = BuildCaptureInit(From, ImplicitCaptureLoc); + + // FIXME: Skip this capture if the capture is not used, the initializer + // has no side-effects, the type of the capture is trivial, and the + // lambda is not externally visible. + + // Add a FieldDecl for the capture and form its initializer. + BuildCaptureField(Class, From); + Captures.push_back(Capture); + CaptureInits.push_back(Init.get()); + + if (LangOpts.CUDA) + CUDACheckLambdaCapture(CallOperator, From); + } + + Class->setCaptures(Context, Captures); + + // C++11 [expr.prim.lambda]p6: + // The closure type for a lambda-expression with no lambda-capture + // has a public non-virtual non-explicit const conversion function + // to pointer to function having the same parameter and return + // types as the closure type's function call operator. + if (Captures.empty() && CaptureDefault == LCD_None) + addFunctionPointerConversions(*this, IntroducerRange, Class, + CallOperator); + + // Objective-C++: + // The closure type for a lambda-expression has a public non-virtual + // non-explicit const conversion function to a block pointer having the + // same parameter and return types as the closure type's function call + // operator. + // FIXME: Fix generic lambda to block conversions. + if (getLangOpts().Blocks && getLangOpts().ObjC && !IsGenericLambda) + addBlockPointerConversion(*this, IntroducerRange, Class, CallOperator); + + // Finalize the lambda class. + SmallVector<Decl*, 4> Fields(Class->fields()); + ActOnFields(nullptr, Class->getLocation(), Class, Fields, SourceLocation(), + SourceLocation(), ParsedAttributesView()); + CheckCompletedCXXClass(nullptr, Class); + } + + Cleanup.mergeFrom(LambdaCleanup); + + LambdaExpr *Lambda = LambdaExpr::Create(Context, Class, IntroducerRange, + CaptureDefault, CaptureDefaultLoc, + ExplicitParams, ExplicitResultType, + CaptureInits, EndLoc, + ContainsUnexpandedParameterPack); + // If the lambda expression's call operator is not explicitly marked constexpr + // and we are not in a dependent context, analyze the call operator to infer + // its constexpr-ness, suppressing diagnostics while doing so. + if (getLangOpts().CPlusPlus17 && !CallOperator->isInvalidDecl() && + !CallOperator->isConstexpr() && + !isa<CoroutineBodyStmt>(CallOperator->getBody()) && + !Class->getDeclContext()->isDependentContext()) { + CallOperator->setConstexprKind( + CheckConstexprFunctionDefinition(CallOperator, + CheckConstexprKind::CheckValid) + ? ConstexprSpecKind::Constexpr + : ConstexprSpecKind::Unspecified); + } + + // Emit delayed shadowing warnings now that the full capture list is known. + DiagnoseShadowingLambdaDecls(LSI); + + 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 ExpressionEvaluationContext::Unevaluated: + case ExpressionEvaluationContext::UnevaluatedList: + case ExpressionEvaluationContext::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 ExpressionEvaluationContext::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 ExpressionEvaluationContext::DiscardedStatement: + case ExpressionEvaluationContext::PotentiallyEvaluated: + case ExpressionEvaluationContext::PotentiallyEvaluatedIfUsed: + break; + } + } + + return MaybeBindToTemporary(Lambda); +} + +ExprResult Sema::BuildBlockForLambdaConversion(SourceLocation CurrentLocation, + SourceLocation ConvLocation, + CXXConversionDecl *Conv, + Expr *Src) { + // Make sure that the lambda call operator is marked used. + CXXRecordDecl *Lambda = Conv->getParent(); + CXXMethodDecl *CallOperator + = cast<CXXMethodDecl>( + Lambda->lookup( + Context.DeclarationNames.getCXXOperatorName(OO_Call)).front()); + CallOperator->setReferenced(); + CallOperator->markUsed(Context); + + ExprResult Init = PerformCopyInitialization( + InitializedEntity::InitializeLambdaToBlock(ConvLocation, Src->getType(), + /*NRVO=*/false), + CurrentLocation, Src); + if (!Init.isInvalid()) + Init = ActOnFinishFullExpr(Init.get(), /*DiscardedValue*/ false); + + if (Init.isInvalid()) + return ExprError(); + + // Create the new block to be returned. + BlockDecl *Block = BlockDecl::Create(Context, CurContext, ConvLocation); + + // Set the type information. + Block->setSignatureAsWritten(CallOperator->getTypeSourceInfo()); + Block->setIsVariadic(CallOperator->isVariadic()); + Block->setBlockMissingReturnType(false); + + // Add parameters. + SmallVector<ParmVarDecl *, 4> BlockParams; + for (unsigned I = 0, N = CallOperator->getNumParams(); I != N; ++I) { + ParmVarDecl *From = CallOperator->getParamDecl(I); + BlockParams.push_back(ParmVarDecl::Create( + Context, Block, From->getBeginLoc(), From->getLocation(), + From->getIdentifier(), From->getType(), From->getTypeSourceInfo(), + From->getStorageClass(), + /*DefArg=*/nullptr)); + } + Block->setParams(BlockParams); + + Block->setIsConversionFromLambda(true); + + // Add capture. The capture uses a fake variable, which doesn't correspond + // to any actual memory location. However, the initializer copy-initializes + // the lambda object. + TypeSourceInfo *CapVarTSI = + Context.getTrivialTypeSourceInfo(Src->getType()); + VarDecl *CapVar = VarDecl::Create(Context, Block, ConvLocation, + ConvLocation, nullptr, + Src->getType(), CapVarTSI, + SC_None); + BlockDecl::Capture Capture(/*variable=*/CapVar, /*byRef=*/false, + /*nested=*/false, /*copy=*/Init.get()); + Block->setCaptures(Context, Capture, /*CapturesCXXThis=*/false); + + // Add a fake function body to the block. IR generation is responsible + // for filling in the actual body, which cannot be expressed as an AST. + Block->setBody(new (Context) CompoundStmt(ConvLocation)); + + // Create the block literal expression. + Expr *BuildBlock = new (Context) BlockExpr(Block, Conv->getConversionType()); + ExprCleanupObjects.push_back(Block); + Cleanup.setExprNeedsCleanups(true); + + return BuildBlock; +} |