diff options
Diffstat (limited to 'contrib/llvm/tools/clang/lib/Sema/SemaLambda.cpp')
-rw-r--r-- | contrib/llvm/tools/clang/lib/Sema/SemaLambda.cpp | 115 |
1 files changed, 51 insertions, 64 deletions
diff --git a/contrib/llvm/tools/clang/lib/Sema/SemaLambda.cpp b/contrib/llvm/tools/clang/lib/Sema/SemaLambda.cpp index 8220641..884add2 100644 --- a/contrib/llvm/tools/clang/lib/Sema/SemaLambda.cpp +++ b/contrib/llvm/tools/clang/lib/Sema/SemaLambda.cpp @@ -226,15 +226,16 @@ getGenericLambdaTemplateParameterList(LambdaScopeInfo *LSI, Sema &SemaRef) { if (LSI->GLTemplateParameterList) return LSI->GLTemplateParameterList; - if (LSI->AutoTemplateParams.size()) { + if (!LSI->AutoTemplateParams.empty()) { SourceRange IntroRange = LSI->IntroducerRange; SourceLocation LAngleLoc = IntroRange.getBegin(); SourceLocation RAngleLoc = IntroRange.getEnd(); LSI->GLTemplateParameterList = TemplateParameterList::Create( SemaRef.Context, /*Template kw loc*/ SourceLocation(), LAngleLoc, - (NamedDecl **)LSI->AutoTemplateParams.data(), - LSI->AutoTemplateParams.size(), RAngleLoc); + llvm::makeArrayRef((NamedDecl *const *)LSI->AutoTemplateParams.data(), + LSI->AutoTemplateParams.size()), + RAngleLoc); } return LSI->GLTemplateParameterList; } @@ -685,7 +686,8 @@ void Sema::deduceClosureReturnType(CapturingScopeInfo &CSI) { QualType ReturnType = (RetE ? RetE->getType() : Context.VoidTy).getUnqualifiedType(); - if (Context.hasSameType(ReturnType, CSI.ReturnType)) + if (Context.getCanonicalFunctionResultType(ReturnType) == + Context.getCanonicalFunctionResultType(CSI.ReturnType)) continue; // FIXME: This is a poor diagnostic for ReturnStmts without expressions. @@ -698,18 +700,11 @@ void Sema::deduceClosureReturnType(CapturingScopeInfo &CSI) { } } -QualType Sema::performLambdaInitCaptureInitialization(SourceLocation Loc, - bool ByRef, - IdentifierInfo *Id, - Expr *&Init) { - - // We do not need to distinguish between direct-list-initialization - // and copy-list-initialization here, because we will always deduce - // std::initializer_list<T>, and direct- and copy-list-initialization - // always behave the same for such a type. - // FIXME: We should model whether an '=' was present. - const bool IsDirectInit = isa<ParenListExpr>(Init) || isa<InitListExpr>(Init); - +QualType Sema::buildLambdaInitCaptureInitialization(SourceLocation Loc, + bool ByRef, + IdentifierInfo *Id, + bool IsDirectInit, + Expr *&Init) { // Create an 'auto' or 'auto&' TypeSourceInfo that we can use to // deduce against. QualType DeductType = Context.getAutoDeductType(); @@ -722,50 +717,16 @@ QualType Sema::performLambdaInitCaptureInitialization(SourceLocation Loc, } TypeSourceInfo *TSI = TLB.getTypeSourceInfo(Context, DeductType); - // Are we a non-list direct initialization? - ParenListExpr *CXXDirectInit = dyn_cast<ParenListExpr>(Init); - - Expr *DeduceInit = Init; - // Initializer could be a C++ direct-initializer. Deduction only works if it - // contains exactly one expression. - if (CXXDirectInit) { - if (CXXDirectInit->getNumExprs() == 0) { - Diag(CXXDirectInit->getLocStart(), diag::err_init_capture_no_expression) - << DeclarationName(Id) << TSI->getType() << Loc; - return QualType(); - } else if (CXXDirectInit->getNumExprs() > 1) { - Diag(CXXDirectInit->getExpr(1)->getLocStart(), - diag::err_init_capture_multiple_expressions) - << DeclarationName(Id) << TSI->getType() << Loc; - return QualType(); - } else { - DeduceInit = CXXDirectInit->getExpr(0); - if (isa<InitListExpr>(DeduceInit)) - Diag(CXXDirectInit->getLocStart(), diag::err_init_capture_paren_braces) - << DeclarationName(Id) << Loc; - } - } - - // Now deduce against the initialization expression and store the deduced - // type below. - QualType DeducedType; - if (DeduceAutoType(TSI, DeduceInit, DeducedType) == DAR_Failed) { - if (isa<InitListExpr>(Init)) - Diag(Loc, diag::err_init_capture_deduction_failure_from_init_list) - << DeclarationName(Id) - << (DeduceInit->getType().isNull() ? TSI->getType() - : DeduceInit->getType()) - << DeduceInit->getSourceRange(); - else - Diag(Loc, diag::err_init_capture_deduction_failure) - << DeclarationName(Id) << TSI->getType() - << (DeduceInit->getType().isNull() ? TSI->getType() - : DeduceInit->getType()) - << DeduceInit->getSourceRange(); - } + // 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 = @@ -802,9 +763,10 @@ QualType Sema::performLambdaInitCaptureInitialization(SourceLocation Loc, return DeducedType; } -VarDecl *Sema::createLambdaInitCaptureVarDecl(SourceLocation Loc, - QualType InitCaptureType, IdentifierInfo *Id, Expr *Init) { - +VarDecl *Sema::createLambdaInitCaptureVarDecl(SourceLocation Loc, + QualType InitCaptureType, + IdentifierInfo *Id, + unsigned InitStyle, Expr *Init) { TypeSourceInfo *TSI = Context.getTrivialTypeSourceInfo(InitCaptureType, Loc); // Create a dummy variable representing the init-capture. This is not actually @@ -815,6 +777,8 @@ VarDecl *Sema::createLambdaInitCaptureVarDecl(SourceLocation 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); return NewVD; @@ -1013,8 +977,23 @@ void Sema::ActOnStartOfLambdaDefinition(LambdaIntroducer &Intro, // in this case. if (C->InitCaptureType.get().isNull()) continue; - Var = createLambdaInitCaptureVarDecl(C->Loc, C->InitCaptureType.get(), - C->Id, C->Init.get()); + + 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->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 @@ -1022,6 +1001,9 @@ void Sema::ActOnStartOfLambdaDefinition(LambdaIntroducer &Intro, 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 &. @@ -1160,6 +1142,12 @@ static void addFunctionPointerConversion(Sema &S, SourceRange IntroducerRange, CXXRecordDecl *Class, CXXMethodDecl *CallOperator) { + // This conversion is explicitly disabled if the lambda's function has + // pass_object_size attributes on any of its parameters. + if (std::any_of(CallOperator->param_begin(), CallOperator->param_end(), + std::mem_fn(&ParmVarDecl::hasAttr<PassObjectSizeAttr>))) + return; + // Add the conversion to function pointer. const FunctionProtoType *CallOpProto = CallOperator->getType()->getAs<FunctionProtoType>(); @@ -1700,8 +1688,7 @@ ExprResult Sema::BuildBlockForLambdaConversion(SourceLocation CurrentLocation, SC_None); BlockDecl::Capture Capture(/*Variable=*/CapVar, /*ByRef=*/false, /*Nested=*/false, /*Copy=*/Init.get()); - Block->setCaptures(Context, &Capture, &Capture + 1, - /*CapturesCXXThis=*/false); + 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. |