diff options
author | Dimitry Andric <dim@FreeBSD.org> | 2019-08-20 20:50:49 +0000 |
---|---|---|
committer | Dimitry Andric <dim@FreeBSD.org> | 2019-08-20 20:50:49 +0000 |
commit | 2298981669bf3bd63335a4be179bc0f96823a8f4 (patch) | |
tree | 1cbe2eb27f030d2d70b80ee5ca3c86bee7326a9f /lib/Sema/SemaLambda.cpp | |
parent | 9a83721404652cea39e9f02ae3e3b5c964602a5c (diff) |
Diffstat (limited to 'lib/Sema/SemaLambda.cpp')
-rw-r--r-- | lib/Sema/SemaLambda.cpp | 407 |
1 files changed, 261 insertions, 146 deletions
diff --git a/lib/Sema/SemaLambda.cpp b/lib/Sema/SemaLambda.cpp index af233b96d69b..986524e6d56b 100644 --- a/lib/Sema/SemaLambda.cpp +++ b/lib/Sema/SemaLambda.cpp @@ -1,9 +1,8 @@ //===--- SemaLambda.cpp - Semantic Analysis for C++11 Lambdas -------------===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// // @@ -21,6 +20,7 @@ #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; @@ -226,19 +226,14 @@ Optional<unsigned> clang::getStackIndexOfNearestEnclosingCaptureCapableLambda( static inline TemplateParameterList * getGenericLambdaTemplateParameterList(LambdaScopeInfo *LSI, Sema &SemaRef) { - if (LSI->GLTemplateParameterList) - return LSI->GLTemplateParameterList; - - if (!LSI->AutoTemplateParams.empty()) { - SourceRange IntroRange = LSI->IntroducerRange; - SourceLocation LAngleLoc = IntroRange.getBegin(); - SourceLocation RAngleLoc = IntroRange.getEnd(); + if (!LSI->GLTemplateParameterList && !LSI->TemplateParams.empty()) { LSI->GLTemplateParameterList = TemplateParameterList::Create( SemaRef.Context, - /*Template kw loc*/ SourceLocation(), LAngleLoc, - llvm::makeArrayRef((NamedDecl *const *)LSI->AutoTemplateParams.data(), - LSI->AutoTemplateParams.size()), - RAngleLoc, nullptr); + /*Template kw loc*/ SourceLocation(), + /*L angle loc*/ LSI->ExplicitTemplateParamsRange.getBegin(), + LSI->TemplateParams, + /*R angle loc*/LSI->ExplicitTemplateParamsRange.getEnd(), + nullptr); } return LSI->GLTemplateParameterList; } @@ -372,12 +367,11 @@ Sema::ExpressionEvaluationContextRecord::getMangleNumberingContext( return *MangleNumbering; } -CXXMethodDecl *Sema::startLambdaDefinition(CXXRecordDecl *Class, - SourceRange IntroducerRange, - TypeSourceInfo *MethodTypeInfo, - SourceLocation EndLoc, - ArrayRef<ParmVarDecl *> Params, - const bool IsConstexprSpecified) { +CXXMethodDecl *Sema::startLambdaDefinition( + CXXRecordDecl *Class, SourceRange IntroducerRange, + TypeSourceInfo *MethodTypeInfo, SourceLocation EndLoc, + ArrayRef<ParmVarDecl *> Params, ConstexprSpecKind ConstexprKind, + Optional<std::pair<unsigned, Decl *>> Mangling) { QualType MethodType = MethodTypeInfo->getType(); TemplateParameterList *TemplateParams = getGenericLambdaTemplateParameterList(getCurLambda(), *this); @@ -406,16 +400,12 @@ CXXMethodDecl *Sema::startLambdaDefinition(CXXRecordDecl *Class, = 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, - IsConstexprSpecified, - EndLoc); + CXXMethodDecl *Method = CXXMethodDecl::Create( + Context, Class, EndLoc, + DeclarationNameInfo(MethodName, IntroducerRange.getBegin(), + MethodNameLoc), + MethodType, MethodTypeInfo, SC_None, + /*isInline=*/true, ConstexprKind, EndLoc); Method->setAccess(AS_public); // Temporarily set the lexical declaration context to the current @@ -443,12 +433,16 @@ CXXMethodDecl *Sema::startLambdaDefinition(CXXRecordDecl *Class, P->setOwningFunction(Method); } - Decl *ManglingContextDecl; - if (MangleNumberingContext *MCtx = - getCurrentMangleNumberContext(Class->getDeclContext(), - ManglingContextDecl)) { - unsigned ManglingNumber = MCtx->getManglingNumber(Method); - Class->setLambdaMangling(ManglingNumber, ManglingContextDecl); + if (Mangling) { + Class->setLambdaMangling(Mangling->first, Mangling->second); + } else { + Decl *ManglingContextDecl; + if (MangleNumberingContext *MCtx = + getCurrentMangleNumberContext(Class->getDeclContext(), + ManglingContextDecl)) { + unsigned ManglingNumber = MCtx->getManglingNumber(Method); + Class->setLambdaMangling(ManglingNumber, ManglingContextDecl); + } } return Method; @@ -493,6 +487,23 @@ void Sema::finishLambdaExplicitCaptures(LambdaScopeInfo *LSI) { LSI->finishedExplicitCaptures(); } +void Sema::ActOnLambdaExplicitTemplateParameterList(SourceLocation LAngleLoc, + ArrayRef<NamedDecl *> TParams, + SourceLocation RAngleLoc) { + 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}; +} + void Sema::addLambdaParameters( ArrayRef<LambdaIntroducer::LambdaCapture> Captures, CXXMethodDecl *CallOperator, Scope *CurScope) { @@ -741,11 +752,10 @@ void Sema::deduceClosureReturnType(CapturingScopeInfo &CSI) { } } -QualType Sema::buildLambdaInitCaptureInitialization(SourceLocation Loc, - bool ByRef, - IdentifierInfo *Id, - bool IsDirectInit, - Expr *&Init) { +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(); @@ -756,18 +766,29 @@ QualType Sema::buildLambdaInitCaptureInitialization(SourceLocation Loc, assert(!DeductType.isNull() && "can't build reference to auto"); TLB.push<ReferenceTypeLoc>(DeductType).setSigilLoc(Loc); } + if (EllipsisLoc.isValid()) { + if (Init->containsUnexpandedParameterPack()) { + Diag(EllipsisLoc, getLangOpts().CPlusPlus2a + ? diag::warn_cxx17_compat_init_capture_pack + : diag::ext_init_capture_pack); + DeductType = Context.getPackExpansionType(DeductType, NumExpansions); + 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. - Expr *DeduceInit = Init; QualType DeducedType = deduceVarTypeFromInitializer( /*VarDecl*/nullptr, DeclarationName(Id), DeductType, TSI, - SourceRange(Loc, Loc), IsDirectInit, DeduceInit); + SourceRange(Loc, Loc), IsDirectInit, Init); if (DeducedType.isNull()) return QualType(); // Are we a non-list direct initialization? - bool CXXDirectInit = isa<ParenListExpr>(Init); + ParenListExpr *CXXDirectInit = dyn_cast<ParenListExpr>(Init); // Perform initialization analysis and ensure any implicit conversions // (such as lvalue-to-rvalue) are enforced. @@ -780,7 +801,10 @@ QualType Sema::buildLambdaInitCaptureInitialization(SourceLocation Loc, : InitializationKind::CreateDirectList(Loc)) : InitializationKind::CreateCopy(Loc, Init->getBeginLoc()); - MultiExprArg Args = DeduceInit; + 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); @@ -794,10 +818,15 @@ QualType Sema::buildLambdaInitCaptureInitialization(SourceLocation Loc, VarDecl *Sema::createLambdaInitCaptureVarDecl(SourceLocation Loc, QualType InitCaptureType, + SourceLocation EllipsisLoc, IdentifierInfo *Id, unsigned InitStyle, Expr *Init) { - TypeSourceInfo *TSI = Context.getTrivialTypeSourceInfo(InitCaptureType, - Loc); + // 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. @@ -813,35 +842,33 @@ VarDecl *Sema::createLambdaInitCaptureVarDecl(SourceLocation Loc, return NewVD; } -FieldDecl *Sema::buildInitCaptureField(LambdaScopeInfo *LSI, VarDecl *Var) { - FieldDecl *Field = FieldDecl::Create( - Context, LSI->Lambda, Var->getLocation(), Var->getLocation(), - nullptr, Var->getType(), Var->getTypeSourceInfo(), nullptr, false, - ICIS_NoInit); - Field->setImplicit(true); - Field->setAccess(AS_private); - LSI->Lambda->addDecl(Field); - +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(), Var->getInit()); - return Field; + Var->getType(), /*Invalid*/false); } void Sema::ActOnStartOfLambdaDefinition(LambdaIntroducer &Intro, Declarator &ParamInfo, Scope *CurScope) { - // Determine if we're within a context where we know that the lambda will - // be dependent, because there are template parameters in scope. - bool KnownDependent = false; LambdaScopeInfo *const LSI = getCurLambda(); assert(LSI && "LambdaScopeInfo should be on stack!"); - // The lambda-expression's closure type might be dependent even if its - // semantic context isn't, if it appears within a default argument of a - // function template. - if (CurScope->getTemplateParamParent()) - KnownDependent = true; + // 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; @@ -909,7 +936,7 @@ void Sema::ActOnStartOfLambdaDefinition(LambdaIntroducer &Intro, CXXMethodDecl *Method = startLambdaDefinition(Class, Intro.Range, MethodTyInfo, EndLoc, Params, - ParamInfo.getDeclSpec().isConstexprSpecified()); + ParamInfo.getDeclSpec().getConstexprSpecifier()); if (ExplicitParams) CheckCXXDefaultArguments(Method); @@ -1016,8 +1043,6 @@ void Sema::ActOnStartOfLambdaDefinition(LambdaIntroducer &Intro, ? 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. @@ -1026,6 +1051,10 @@ void Sema::ActOnStartOfLambdaDefinition(LambdaIntroducer &Intro, if (C->InitCaptureType.get().isNull()) continue; + if (C->Init.get()->containsUnexpandedParameterPack() && + !C->InitCaptureType.get()->getAs<PackExpansionType>()) + ContainsUnexpandedParameterPack = true; + unsigned InitStyle; switch (C->InitKind) { case LambdaCaptureInitKind::NoInit: @@ -1041,7 +1070,8 @@ void Sema::ActOnStartOfLambdaDefinition(LambdaIntroducer &Intro, break; } Var = createLambdaInitCaptureVarDecl(C->Loc, C->InitCaptureType.get(), - C->Id, InitStyle, C->Init.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 @@ -1080,8 +1110,8 @@ void Sema::ActOnStartOfLambdaDefinition(LambdaIntroducer &Intro, if (R.empty()) { // FIXME: Disable corrections that would add qualification? CXXScopeSpec ScopeSpec; - if (DiagnoseEmptyLookup(CurScope, ScopeSpec, R, - llvm::make_unique<DeclFilterCCC<VarDecl>>())) + DeclFilterCCC<VarDecl> Validator{}; + if (DiagnoseEmptyLookup(CurScope, ScopeSpec, R, Validator)) continue; } @@ -1133,7 +1163,8 @@ void Sema::ActOnStartOfLambdaDefinition(LambdaIntroducer &Intro, EllipsisLoc = C->EllipsisLoc; } else { Diag(C->EllipsisLoc, diag::err_pack_expansion_without_parameter_packs) - << SourceRange(C->Loc); + << (C->Init.isUsable() ? C->Init.get()->getSourceRange() + : SourceRange(C->Loc)); // Just ignore the ellipsis. } @@ -1142,7 +1173,7 @@ void Sema::ActOnStartOfLambdaDefinition(LambdaIntroducer &Intro, } if (C->Init.isUsable()) { - buildInitCaptureField(LSI, Var); + addInitCapture(LSI, Var); } else { TryCaptureKind Kind = C->Kind == LCK_ByRef ? TryCapture_ExplicitByRef : TryCapture_ExplicitByVal; @@ -1228,9 +1259,10 @@ static void addFunctionPointerConversion(Sema &S, FunctionProtoType::ExtProtoInfo ConvExtInfo( S.Context.getDefaultCallingConvention( /*IsVariadic=*/false, /*IsCXXMethod=*/true)); - // The conversion function is always const. + // 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); @@ -1296,7 +1328,7 @@ static void addFunctionPointerConversion(Sema &S, S.Context.getTranslationUnitDecl(), From->getBeginLoc(), From->getLocation(), From->getIdentifier(), From->getType(), From->getTypeSourceInfo(), From->getStorageClass(), - /*DefaultArg=*/nullptr)); + /*DefArg=*/nullptr)); CallOpConvTL.setParam(I, From); CallOpConvNameTL.setParam(I, From); } @@ -1304,8 +1336,8 @@ static void addFunctionPointerConversion(Sema &S, CXXConversionDecl *Conversion = CXXConversionDecl::Create( S.Context, Class, Loc, DeclarationNameInfo(ConversionName, Loc, ConvNameLoc), ConvTy, ConvTSI, - /*isInline=*/true, /*isExplicit=*/false, - /*isConstexpr=*/S.getLangOpts().CPlusPlus17, + /*isInline=*/true, ExplicitSpecifier(), + S.getLangOpts().CPlusPlus17 ? CSK_constexpr : CSK_unspecified, CallOperator->getBody()->getEndLoc()); Conversion->setAccess(AS_public); Conversion->setImplicit(true); @@ -1344,8 +1376,7 @@ static void addFunctionPointerConversion(Sema &S, CXXMethodDecl *Invoke = CXXMethodDecl::Create( S.Context, Class, Loc, DeclarationNameInfo(InvokerName, Loc), InvokerFunctionTy, CallOperator->getTypeSourceInfo(), SC_Static, - /*IsInline=*/true, - /*IsConstexpr=*/false, CallOperator->getBody()->getEndLoc()); + /*isInline=*/true, CSK_unspecified, CallOperator->getBody()->getEndLoc()); for (unsigned I = 0, N = CallOperator->getNumParams(); I != N; ++I) InvokerParams[I]->setOwningFunction(Invoke); Invoke->setParams(InvokerParams); @@ -1391,21 +1422,29 @@ static void addBlockPointerConversion(Sema &S, CXXConversionDecl *Conversion = CXXConversionDecl::Create( S.Context, Class, Loc, DeclarationNameInfo(Name, Loc, NameLoc), ConvTy, S.Context.getTrivialTypeSourceInfo(ConvTy, Loc), - /*isInline=*/true, /*isExplicit=*/false, - /*isConstexpr=*/false, CallOperator->getBody()->getEndLoc()); + /*isInline=*/true, ExplicitSpecifier(), CSK_unspecified, + CallOperator->getBody()->getEndLoc()); Conversion->setAccess(AS_public); Conversion->setImplicit(true); Class->addDecl(Conversion); } -static ExprResult performLambdaVarCaptureInitialization( - Sema &S, const Capture &Capture, FieldDecl *Field, - SourceLocation ImplicitCaptureLoc, bool IsImplicitCapture) { - assert(Capture.isVariableCapture() && "not a variable capture"); +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(); - auto *Var = Capture.getVariable(); + // 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 = - IsImplicitCapture ? ImplicitCaptureLoc : Capture.getLocation(); + ImplicitCaptureLoc.isValid() ? ImplicitCaptureLoc : Cap.getLocation(); // C++11 [expr.prim.lambda]p21: // When the lambda-expression is evaluated, the entities that @@ -1419,17 +1458,39 @@ static ExprResult performLambdaVarCaptureInitialization( // 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 RefResult = S.BuildDeclarationNameExpr( + 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); - if (RefResult.isInvalid()) + } + + // 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 *Ref = RefResult.get(); - auto Entity = InitializedEntity::InitializeLambdaCapture( - Var->getIdentifier(), Field->getType(), Loc); - InitializationKind InitKind = InitializationKind::CreateDirect(Loc, Loc, Loc); - InitializationSequence Init(S, Entity, InitKind, Ref); - return Init.Perform(S, Entity, InitKind, Ref); + 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, @@ -1456,8 +1517,8 @@ mapImplicitCaptureStyle(CapturingScopeInfo::ImplicitCaptureStyle ICS) { } bool Sema::CaptureHasSideEffects(const Capture &From) { - if (!From.isVLATypeCapture()) { - Expr *Init = From.getInitExpr(); + if (From.isInitCapture()) { + Expr *Init = From.getVariable()->getInit(); if (Init && Init->HasSideEffects(Context)) return true; } @@ -1498,6 +1559,54 @@ bool Sema::DiagnoseUnusedLambdaCapture(SourceRange 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, Loc, Loc, nullptr, FieldType, TSI, nullptr, + false, ICIS_NoInit); + // If the variable being captured has an invalid type, mark the class as + // invalid as well. + if (!FieldType->isDependentType()) { + if (RequireCompleteType(Loc, FieldType, diag::err_field_incomplete)) { + 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. @@ -1535,28 +1644,33 @@ ExprResult Sema::BuildLambdaExpr(SourceLocation StartLoc, SourceLocation EndLoc, PopExpressionEvaluationContext(); - // Translate captures. - auto CurField = Class->field_begin(); // 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, ++CurField) { + 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()) { + 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.getInitExpr(); + IsGenericLambda && From.isNonODRUsed() && From.isInitCapture(); if (!NonODRUsedInitCapture) { bool IsLast = (I + 1) == LSI->NumExplicitCaptures; SourceRange FixItRange; @@ -1582,45 +1696,44 @@ ExprResult Sema::BuildLambdaExpr(SourceLocation StartLoc, SourceLocation EndLoc, PrevCaptureLoc = CaptureRange.getEnd(); } - // Handle 'this' 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().CPlusPlus2a && IsImplicit && - CaptureDefault == LCD_ByCopy) { - Diag(From.getLocation(), diag::warn_deprecated_this_capture); - Diag(CaptureDefaultLoc, diag::note_deprecated_this_capture) - << FixItHint::CreateInsertion( - getLocForEndOfToken(CaptureDefaultLoc), ", this"); + // 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().CPlusPlus2a && 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()); } + }(); - Captures.push_back( - LambdaCapture(From.getLocation(), IsImplicit, - From.isCopyCapture() ? LCK_StarThis : LCK_This)); - CaptureInits.push_back(From.getInitExpr()); - continue; - } - if (From.isVLATypeCapture()) { - Captures.push_back( - LambdaCapture(From.getLocation(), IsImplicit, LCK_VLAType)); - CaptureInits.push_back(nullptr); - continue; - } + // Form the initializer for the capture field. + ExprResult Init = BuildCaptureInit(From, ImplicitCaptureLoc); - VarDecl *Var = From.getVariable(); - LambdaCaptureKind Kind = From.isCopyCapture() ? LCK_ByCopy : LCK_ByRef; - Captures.push_back(LambdaCapture(From.getLocation(), IsImplicit, Kind, - Var, From.getEllipsisLoc())); - Expr *Init = From.getInitExpr(); - if (!Init) { - auto InitResult = performLambdaVarCaptureInitialization( - *this, From, *CurField, CaptureDefaultLoc, IsImplicit); - if (InitResult.isInvalid()) - return ExprError(); - Init = InitResult.get(); - } - CaptureInits.push_back(Init); + // 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()); } // C++11 [expr.prim.lambda]p6: @@ -1664,9 +1777,11 @@ ExprResult Sema::BuildLambdaExpr(SourceLocation StartLoc, SourceLocation EndLoc, !isa<CoroutineBodyStmt>(CallOperator->getBody()) && !Class->getDeclContext()->isDependentContext()) { TentativeAnalysisScope DiagnosticScopeGuard(*this); - CallOperator->setConstexpr( - CheckConstexprFunctionDecl(CallOperator) && - CheckConstexprFunctionBody(CallOperator, CallOperator->getBody())); + CallOperator->setConstexprKind( + (CheckConstexprFunctionDecl(CallOperator) && + CheckConstexprFunctionBody(CallOperator, CallOperator->getBody())) + ? CSK_constexpr + : CSK_unspecified); } // Emit delayed shadowing warnings now that the full capture list is known. @@ -1745,7 +1860,7 @@ ExprResult Sema::BuildBlockForLambdaConversion(SourceLocation CurrentLocation, Context, Block, From->getBeginLoc(), From->getLocation(), From->getIdentifier(), From->getType(), From->getTypeSourceInfo(), From->getStorageClass(), - /*DefaultArg=*/nullptr)); + /*DefArg=*/nullptr)); } Block->setParams(BlockParams); @@ -1760,8 +1875,8 @@ ExprResult Sema::BuildBlockForLambdaConversion(SourceLocation CurrentLocation, ConvLocation, nullptr, Src->getType(), CapVarTSI, SC_None); - BlockDecl::Capture Capture(/*Variable=*/CapVar, /*ByRef=*/false, - /*Nested=*/false, /*Copy=*/Init.get()); + 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 |