diff options
Diffstat (limited to 'contrib/llvm-project/clang/lib/Sema/SemaStmt.cpp')
-rw-r--r-- | contrib/llvm-project/clang/lib/Sema/SemaStmt.cpp | 509 |
1 files changed, 106 insertions, 403 deletions
diff --git a/contrib/llvm-project/clang/lib/Sema/SemaStmt.cpp b/contrib/llvm-project/clang/lib/Sema/SemaStmt.cpp index 9e7c8c7e4e8c..34d2d398f244 100644 --- a/contrib/llvm-project/clang/lib/Sema/SemaStmt.cpp +++ b/contrib/llvm-project/clang/lib/Sema/SemaStmt.cpp @@ -27,15 +27,20 @@ #include "clang/AST/TypeOrdering.h" #include "clang/Basic/TargetInfo.h" #include "clang/Lex/Preprocessor.h" +#include "clang/Sema/EnterExpressionEvaluationContext.h" #include "clang/Sema/Initialization.h" #include "clang/Sema/Lookup.h" #include "clang/Sema/Ownership.h" #include "clang/Sema/Scope.h" #include "clang/Sema/ScopeInfo.h" +#include "clang/Sema/SemaCUDA.h" #include "clang/Sema/SemaInternal.h" +#include "clang/Sema/SemaObjC.h" +#include "clang/Sema/SemaOpenMP.h" #include "llvm/ADT/ArrayRef.h" #include "llvm/ADT/DenseMap.h" #include "llvm/ADT/STLExtras.h" +#include "llvm/ADT/STLForwardCompat.h" #include "llvm/ADT/SmallPtrSet.h" #include "llvm/ADT/SmallString.h" #include "llvm/ADT/SmallVector.h" @@ -526,13 +531,19 @@ Sema::ActOnCaseStmt(SourceLocation CaseLoc, ExprResult LHSVal, return StmtError(); } + if (LangOpts.OpenACC && + getCurScope()->isInOpenACCComputeConstructScope(Scope::SwitchScope)) { + Diag(CaseLoc, diag::err_acc_branch_in_out_compute_construct) + << /*branch*/ 0 << /*into*/ 1; + return StmtError(); + } + auto *CS = CaseStmt::Create(Context, LHSVal.get(), RHSVal.get(), CaseLoc, DotDotDotLoc, ColonLoc); getCurFunction()->SwitchStack.back().getPointer()->addSwitchCase(CS); return CS; } -/// ActOnCaseStmtBody - This installs a statement as the body of a case. void Sema::ActOnCaseStmtBody(Stmt *S, Stmt *SubStmt) { cast<CaseStmt>(S)->setSubStmt(SubStmt); } @@ -545,6 +556,13 @@ Sema::ActOnDefaultStmt(SourceLocation DefaultLoc, SourceLocation ColonLoc, return SubStmt; } + if (LangOpts.OpenACC && + getCurScope()->isInOpenACCComputeConstructScope(Scope::SwitchScope)) { + Diag(DefaultLoc, diag::err_acc_branch_in_out_compute_construct) + << /*branch*/ 0 << /*into*/ 1; + return StmtError(); + } + DefaultStmt *DS = new (Context) DefaultStmt(DefaultLoc, ColonLoc, SubStmt); getCurFunction()->SwitchStack.back().getPointer()->addSwitchCase(DS); return DS; @@ -566,6 +584,11 @@ Sema::ActOnLabelStmt(SourceLocation IdentLoc, LabelDecl *TheDecl, Diag(IdentLoc, diag::warn_reserved_extern_symbol) << TheDecl << static_cast<int>(Status); + // If this label is in a compute construct scope, we need to make sure we + // check gotos in/out. + if (getCurScope()->isInOpenACCComputeConstructScope()) + setFunctionHasBranchProtectedScope(); + // Otherwise, things are good. Fill in the declaration and return it. LabelStmt *LS = new (Context) LabelStmt(IdentLoc, TheDecl, SubStmt); TheDecl->setStmt(LS); @@ -2196,10 +2219,6 @@ StmtResult Sema::ActOnForStmt(SourceLocation ForLoc, SourceLocation LParenLoc, Body, ForLoc, LParenLoc, RParenLoc); } -/// In an Objective C collection iteration statement: -/// for (x in y) -/// x can be an arbitrary l-value expression. Bind it up as a -/// full-expression. StmtResult Sema::ActOnForEachLValueExpr(Expr *E) { // Reduce placeholder expressions here. Note that this rejects the // use of pseudo-object l-values in this position. @@ -2213,166 +2232,6 @@ StmtResult Sema::ActOnForEachLValueExpr(Expr *E) { return StmtResult(static_cast<Stmt*>(FullExpr.get())); } -ExprResult -Sema::CheckObjCForCollectionOperand(SourceLocation forLoc, Expr *collection) { - if (!collection) - return ExprError(); - - ExprResult result = CorrectDelayedTyposInExpr(collection); - if (!result.isUsable()) - return ExprError(); - collection = result.get(); - - // Bail out early if we've got a type-dependent expression. - if (collection->isTypeDependent()) return collection; - - // Perform normal l-value conversion. - result = DefaultFunctionArrayLvalueConversion(collection); - if (result.isInvalid()) - return ExprError(); - collection = result.get(); - - // The operand needs to have object-pointer type. - // TODO: should we do a contextual conversion? - const ObjCObjectPointerType *pointerType = - collection->getType()->getAs<ObjCObjectPointerType>(); - if (!pointerType) - return Diag(forLoc, diag::err_collection_expr_type) - << collection->getType() << collection->getSourceRange(); - - // Check that the operand provides - // - countByEnumeratingWithState:objects:count: - const ObjCObjectType *objectType = pointerType->getObjectType(); - ObjCInterfaceDecl *iface = objectType->getInterface(); - - // If we have a forward-declared type, we can't do this check. - // Under ARC, it is an error not to have a forward-declared class. - if (iface && - (getLangOpts().ObjCAutoRefCount - ? RequireCompleteType(forLoc, QualType(objectType, 0), - diag::err_arc_collection_forward, collection) - : !isCompleteType(forLoc, QualType(objectType, 0)))) { - // Otherwise, if we have any useful type information, check that - // the type declares the appropriate method. - } else if (iface || !objectType->qual_empty()) { - IdentifierInfo *selectorIdents[] = { - &Context.Idents.get("countByEnumeratingWithState"), - &Context.Idents.get("objects"), - &Context.Idents.get("count") - }; - Selector selector = Context.Selectors.getSelector(3, &selectorIdents[0]); - - ObjCMethodDecl *method = nullptr; - - // If there's an interface, look in both the public and private APIs. - if (iface) { - method = iface->lookupInstanceMethod(selector); - if (!method) method = iface->lookupPrivateMethod(selector); - } - - // Also check protocol qualifiers. - if (!method) - method = LookupMethodInQualifiedType(selector, pointerType, - /*instance*/ true); - - // If we didn't find it anywhere, give up. - if (!method) { - Diag(forLoc, diag::warn_collection_expr_type) - << collection->getType() << selector << collection->getSourceRange(); - } - - // TODO: check for an incompatible signature? - } - - // Wrap up any cleanups in the expression. - return collection; -} - -StmtResult -Sema::ActOnObjCForCollectionStmt(SourceLocation ForLoc, - Stmt *First, Expr *collection, - SourceLocation RParenLoc) { - setFunctionHasBranchProtectedScope(); - - ExprResult CollectionExprResult = - CheckObjCForCollectionOperand(ForLoc, collection); - - if (First) { - QualType FirstType; - if (DeclStmt *DS = dyn_cast<DeclStmt>(First)) { - if (!DS->isSingleDecl()) - return StmtError(Diag((*DS->decl_begin())->getLocation(), - diag::err_toomany_element_decls)); - - VarDecl *D = dyn_cast<VarDecl>(DS->getSingleDecl()); - if (!D || D->isInvalidDecl()) - return StmtError(); - - FirstType = D->getType(); - // C99 6.8.5p3: The declaration part of a 'for' statement shall only - // declare identifiers for objects having storage class 'auto' or - // 'register'. - if (!D->hasLocalStorage()) - return StmtError(Diag(D->getLocation(), - diag::err_non_local_variable_decl_in_for)); - - // If the type contained 'auto', deduce the 'auto' to 'id'. - if (FirstType->getContainedAutoType()) { - SourceLocation Loc = D->getLocation(); - OpaqueValueExpr OpaqueId(Loc, Context.getObjCIdType(), VK_PRValue); - Expr *DeducedInit = &OpaqueId; - TemplateDeductionInfo Info(Loc); - FirstType = QualType(); - TemplateDeductionResult Result = DeduceAutoType( - D->getTypeSourceInfo()->getTypeLoc(), DeducedInit, FirstType, Info); - if (Result != TDK_Success && Result != TDK_AlreadyDiagnosed) - DiagnoseAutoDeductionFailure(D, DeducedInit); - if (FirstType.isNull()) { - D->setInvalidDecl(); - return StmtError(); - } - - D->setType(FirstType); - - if (!inTemplateInstantiation()) { - SourceLocation Loc = - D->getTypeSourceInfo()->getTypeLoc().getBeginLoc(); - Diag(Loc, diag::warn_auto_var_is_id) - << D->getDeclName(); - } - } - - } else { - Expr *FirstE = cast<Expr>(First); - if (!FirstE->isTypeDependent() && !FirstE->isLValue()) - return StmtError( - Diag(First->getBeginLoc(), diag::err_selector_element_not_lvalue) - << First->getSourceRange()); - - FirstType = static_cast<Expr*>(First)->getType(); - if (FirstType.isConstQualified()) - Diag(ForLoc, diag::err_selector_element_const_type) - << FirstType << First->getSourceRange(); - } - if (!FirstType->isDependentType() && - !FirstType->isObjCObjectPointerType() && - !FirstType->isBlockPointerType()) - return StmtError(Diag(ForLoc, diag::err_selector_element_type) - << FirstType << First->getSourceRange()); - } - - if (CollectionExprResult.isInvalid()) - return StmtError(); - - CollectionExprResult = - ActOnFinishFullExpr(CollectionExprResult.get(), /*DiscardedValue*/ false); - if (CollectionExprResult.isInvalid()) - return StmtError(); - - return new (Context) ObjCForCollectionStmt(First, CollectionExprResult.get(), - nullptr, ForLoc, RParenLoc); -} - /// Finish building a variable declaration for a for-range statement. /// \return true if an error occurs. static bool FinishForRangeVarDecl(Sema &SemaRef, VarDecl *Decl, Expr *Init, @@ -2393,9 +2252,10 @@ static bool FinishForRangeVarDecl(Sema &SemaRef, VarDecl *Decl, Expr *Init, SemaRef.Diag(Loc, DiagID) << Init->getType(); } else { TemplateDeductionInfo Info(Init->getExprLoc()); - Sema::TemplateDeductionResult Result = SemaRef.DeduceAutoType( + TemplateDeductionResult Result = SemaRef.DeduceAutoType( Decl->getTypeSourceInfo()->getTypeLoc(), Init, InitType, Info); - if (Result != Sema::TDK_Success && Result != Sema::TDK_AlreadyDiagnosed) + if (Result != TemplateDeductionResult::Success && + Result != TemplateDeductionResult::AlreadyDiagnosed) SemaRef.Diag(Loc, DiagID) << Init->getType(); } @@ -2409,7 +2269,7 @@ static bool FinishForRangeVarDecl(Sema &SemaRef, VarDecl *Decl, Expr *Init, // FIXME: ARC may want to turn this into 'const __unsafe_unretained' if // we're doing the equivalent of fast iteration. if (SemaRef.getLangOpts().ObjCAutoRefCount && - SemaRef.inferObjCARCLifetime(Decl)) + SemaRef.ObjC().inferObjCARCLifetime(Decl)) Decl->setInvalidDecl(); SemaRef.AddInitializerToDecl(Decl, Init, /*DirectInit=*/false); @@ -2471,29 +2331,11 @@ static bool ObjCEnumerationCollection(Expr *Collection) { && Collection->getType()->getAs<ObjCObjectPointerType>() != nullptr; } -/// ActOnCXXForRangeStmt - Check and build a C++11 for-range statement. -/// -/// C++11 [stmt.ranged]: -/// A range-based for statement is equivalent to -/// -/// { -/// auto && __range = range-init; -/// for ( auto __begin = begin-expr, -/// __end = end-expr; -/// __begin != __end; -/// ++__begin ) { -/// for-range-declaration = *__begin; -/// statement -/// } -/// } -/// -/// The body of the loop is not available yet, since it cannot be analysed until -/// we have determined the type of the for-range-declaration. -StmtResult Sema::ActOnCXXForRangeStmt(Scope *S, SourceLocation ForLoc, - SourceLocation CoawaitLoc, Stmt *InitStmt, - Stmt *First, SourceLocation ColonLoc, - Expr *Range, SourceLocation RParenLoc, - BuildForRangeKind Kind) { +StmtResult Sema::ActOnCXXForRangeStmt( + Scope *S, SourceLocation ForLoc, SourceLocation CoawaitLoc, Stmt *InitStmt, + Stmt *First, SourceLocation ColonLoc, Expr *Range, SourceLocation RParenLoc, + BuildForRangeKind Kind, + ArrayRef<MaterializeTemporaryExpr *> LifetimeExtendTemps) { // FIXME: recover in order to allow the body to be parsed. if (!First) return StmtError(); @@ -2503,7 +2345,7 @@ StmtResult Sema::ActOnCXXForRangeStmt(Scope *S, SourceLocation ForLoc, if (InitStmt) return Diag(InitStmt->getBeginLoc(), diag::err_objc_for_range_init_stmt) << InitStmt->getSourceRange(); - return ActOnObjCForCollectionStmt(ForLoc, First, Range, RParenLoc); + return ObjC().ActOnObjCForCollectionStmt(ForLoc, First, Range, RParenLoc); } DeclStmt *DS = dyn_cast<DeclStmt>(First); @@ -2557,7 +2399,8 @@ StmtResult Sema::ActOnCXXForRangeStmt(Scope *S, SourceLocation ForLoc, StmtResult R = BuildCXXForRangeStmt( ForLoc, CoawaitLoc, InitStmt, ColonLoc, RangeDecl.get(), /*BeginStmt=*/nullptr, /*EndStmt=*/nullptr, - /*Cond=*/nullptr, /*Inc=*/nullptr, DS, RParenLoc, Kind); + /*Cond=*/nullptr, /*Inc=*/nullptr, DS, RParenLoc, Kind, + LifetimeExtendTemps); if (R.isInvalid()) { ActOnInitializerError(LoopVar); return StmtError(); @@ -2746,14 +2589,12 @@ static StmtResult RebuildForRangeWithDereference(Sema &SemaRef, Scope *S, AdjustedRange.get(), RParenLoc, Sema::BFRK_Rebuild); } -/// BuildCXXForRangeStmt - Build or instantiate a C++11 for-range statement. -StmtResult Sema::BuildCXXForRangeStmt(SourceLocation ForLoc, - SourceLocation CoawaitLoc, Stmt *InitStmt, - SourceLocation ColonLoc, Stmt *RangeDecl, - Stmt *Begin, Stmt *End, Expr *Cond, - Expr *Inc, Stmt *LoopVarDecl, - SourceLocation RParenLoc, - BuildForRangeKind Kind) { +StmtResult Sema::BuildCXXForRangeStmt( + SourceLocation ForLoc, SourceLocation CoawaitLoc, Stmt *InitStmt, + SourceLocation ColonLoc, Stmt *RangeDecl, Stmt *Begin, Stmt *End, + Expr *Cond, Expr *Inc, Stmt *LoopVarDecl, SourceLocation RParenLoc, + BuildForRangeKind Kind, + ArrayRef<MaterializeTemporaryExpr *> LifetimeExtendTemps) { // FIXME: This should not be used during template instantiation. We should // pick up the set of unqualified lookup results for the != and + operators // in the initial parse. @@ -2813,6 +2654,14 @@ StmtResult Sema::BuildCXXForRangeStmt(SourceLocation ForLoc, diag::err_for_range_incomplete_type)) return StmtError(); + // P2718R0 - Lifetime extension in range-based for loops. + if (getLangOpts().CPlusPlus23 && !LifetimeExtendTemps.empty()) { + InitializedEntity Entity = + InitializedEntity::InitializeVariable(RangeVar); + for (auto *MTE : LifetimeExtendTemps) + MTE->setExtendingDecl(RangeVar, Entity.allocateManglingNumber()); + } + // Build auto __begin = begin-expr, __end = end-expr. // Divide by 2, since the variables are in the inner scope (loop body). const auto DepthStr = std::to_string(S->getDepth() / 2); @@ -3067,7 +2916,7 @@ StmtResult Sema::BuildCXXForRangeStmt(SourceLocation ForLoc, // In OpenMP loop region loop control variable must be private. Perform // analysis of first part (if any). if (getLangOpts().OpenMP >= 50 && BeginDeclStmt.isUsable()) - ActOnOpenMPLoopInitialization(ForLoc, BeginDeclStmt.get()); + OpenMP().ActOnOpenMPLoopInitialization(ForLoc, BeginDeclStmt.get()); return new (Context) CXXForRangeStmt( InitStmt, RangeDS, cast_or_null<DeclStmt>(BeginDeclStmt.get()), @@ -3076,17 +2925,6 @@ StmtResult Sema::BuildCXXForRangeStmt(SourceLocation ForLoc, ColonLoc, RParenLoc); } -/// FinishObjCForCollectionStmt - Attach the body to a objective-C foreach -/// statement. -StmtResult Sema::FinishObjCForCollectionStmt(Stmt *S, Stmt *B) { - if (!S || !B) - return StmtError(); - ObjCForCollectionStmt * ForStmt = cast<ObjCForCollectionStmt>(S); - - ForStmt->setBody(B); - return S; -} - // Warn when the loop variable is a const reference that creates a copy. // Suggest using the non-reference type for copies. If a copy can be prevented // suggest the const reference type that would do so. @@ -3267,16 +3105,12 @@ static void DiagnoseForRangeVariableCopies(Sema &SemaRef, } } -/// FinishCXXForRangeStmt - Attach the body to a C++0x for-range statement. -/// This is a separate step from ActOnCXXForRangeStmt because analysis of the -/// body cannot be performed until after the type of the range variable is -/// determined. StmtResult Sema::FinishCXXForRangeStmt(Stmt *S, Stmt *B) { if (!S || !B) return StmtError(); if (isa<ObjCForCollectionStmt>(S)) - return FinishObjCForCollectionStmt(S, B); + return ObjC().FinishObjCForCollectionStmt(S, B); CXXForRangeStmt *ForStmt = cast<CXXForRangeStmt>(S); ForStmt->setBody(B); @@ -3293,6 +3127,12 @@ StmtResult Sema::ActOnGotoStmt(SourceLocation GotoLoc, SourceLocation LabelLoc, LabelDecl *TheDecl) { setFunctionHasBranchIntoScope(); + + // If this goto is in a compute construct scope, we need to make sure we check + // gotos in/out. + if (getCurScope()->isInOpenACCComputeConstructScope()) + setFunctionHasBranchProtectedScope(); + TheDecl->markUsed(Context); return new (Context) GotoStmt(TheDecl, GotoLoc, LabelLoc); } @@ -3321,6 +3161,11 @@ Sema::ActOnIndirectGotoStmt(SourceLocation GotoLoc, SourceLocation StarLoc, setFunctionHasIndirectGoto(); + // If this goto is in a compute construct scope, we need to make sure we + // check gotos in/out. + if (getCurScope()->isInOpenACCComputeConstructScope()) + setFunctionHasBranchProtectedScope(); + return new (Context) IndirectGotoStmt(GotoLoc, StarLoc, E); } @@ -3345,6 +3190,15 @@ Sema::ActOnContinueStmt(SourceLocation ContinueLoc, Scope *CurScope) { // initialization of that variable. return StmtError(Diag(ContinueLoc, diag::err_continue_from_cond_var_init)); } + + // A 'continue' that would normally have execution continue on a block outside + // of a compute construct counts as 'branching out of' the compute construct, + // so diagnose here. + if (S->isOpenACCComputeConstructScope()) + return StmtError( + Diag(ContinueLoc, diag::err_acc_branch_in_out_compute_construct) + << /*branch*/ 0 << /*out of */ 0); + CheckJumpOutOfSEHFinally(*this, ContinueLoc, *S); return new (Context) ContinueStmt(ContinueLoc); @@ -3360,25 +3214,26 @@ Sema::ActOnBreakStmt(SourceLocation BreakLoc, Scope *CurScope) { if (S->isOpenMPLoopScope()) return StmtError(Diag(BreakLoc, diag::err_omp_loop_cannot_use_stmt) << "break"); + + // OpenACC doesn't allow 'break'ing from a compute construct, so diagnose if + // we are trying to do so. This can come in 2 flavors: 1-the break'able thing + // (besides the compute construct) 'contains' the compute construct, at which + // point the 'break' scope will be the compute construct. Else it could be a + // loop of some sort that has a direct parent of the compute construct. + // However, a 'break' in a 'switch' marked as a compute construct doesn't + // count as 'branch out of' the compute construct. + if (S->isOpenACCComputeConstructScope() || + (S->isLoopScope() && S->getParent() && + S->getParent()->isOpenACCComputeConstructScope())) + return StmtError( + Diag(BreakLoc, diag::err_acc_branch_in_out_compute_construct) + << /*branch*/ 0 << /*out of */ 0); + CheckJumpOutOfSEHFinally(*this, BreakLoc, *S); return new (Context) BreakStmt(BreakLoc); } -/// Determine whether the given expression might be move-eligible or -/// copy-elidable in either a (co_)return statement or throw expression, -/// without considering function return type, if applicable. -/// -/// \param E The expression being returned from the function or block, -/// being thrown, or being co_returned from a coroutine. This expression -/// might be modified by the implementation. -/// -/// \param Mode Overrides detection of current language mode -/// and uses the rules for C++23. -/// -/// \returns An aggregate which contains the Candidate and isMoveEligible -/// and isCopyElidable methods. If Candidate is non-null, it means -/// isMoveEligible() would be true under the most permissive language standard. Sema::NamedReturnInfo Sema::getNamedReturnInfo(Expr *&E, SimplerImplicitMoveMode Mode) { if (!E) @@ -3391,6 +3246,8 @@ Sema::NamedReturnInfo Sema::getNamedReturnInfo(Expr *&E, const auto *VD = dyn_cast<VarDecl>(DR->getDecl()); if (!VD) return NamedReturnInfo(); + if (VD->getInit() && VD->getInit()->containsErrors()) + return NamedReturnInfo(); NamedReturnInfo Res = getNamedReturnInfo(VD); if (Res.Candidate && !E->isXValue() && (Mode == SimplerImplicitMoveMode::ForceOn || @@ -3403,14 +3260,6 @@ Sema::NamedReturnInfo Sema::getNamedReturnInfo(Expr *&E, return Res; } -/// Determine whether the given NRVO candidate variable is move-eligible or -/// copy-elidable, without considering function return type. -/// -/// \param VD The NRVO candidate variable. -/// -/// \returns An aggregate which contains the Candidate and isMoveEligible -/// and isCopyElidable methods. If Candidate is non-null, it means -/// isMoveEligible() would be true under the most permissive language standard. Sema::NamedReturnInfo Sema::getNamedReturnInfo(const VarDecl *VD) { NamedReturnInfo Info{VD, NamedReturnInfo::MoveEligibleAndCopyElidable}; @@ -3456,22 +3305,13 @@ Sema::NamedReturnInfo Sema::getNamedReturnInfo(const VarDecl *VD) { // Variables with higher required alignment than their type's ABI // alignment cannot use NRVO. - if (!VD->hasDependentAlignment() && + if (!VD->hasDependentAlignment() && !VDType->isIncompleteType() && Context.getDeclAlign(VD) > Context.getTypeAlignInChars(VDType)) Info.S = NamedReturnInfo::MoveEligible; return Info; } -/// Updates given NamedReturnInfo's move-eligible and -/// copy-elidable statuses, considering the function -/// return type criteria as applicable to return statements. -/// -/// \param Info The NamedReturnInfo object to update. -/// -/// \param ReturnType This is the return type of the function. -/// \returns The copy elision candidate, in case the initial return expression -/// was copy elidable, or nullptr otherwise. const VarDecl *Sema::getCopyElisionCandidate(NamedReturnInfo &Info, QualType ReturnType) { if (!Info.Candidate) @@ -3529,12 +3369,6 @@ VerifyInitializationSequenceCXX98(const Sema &S, return true; } -/// Perform the initialization of a potentially-movable value, which -/// is the result of return value. -/// -/// This routine implements C++20 [class.copy.elision]p3, which attempts to -/// treat returned lvalues as rvalues in certain cases (to prefer move -/// construction), then falls back to treating them as lvalues if that failed. ExprResult Sema::PerformMoveOrCopyInitialization( const InitializedEntity &Entity, const NamedReturnInfo &NRInfo, Expr *Value, bool SupressSimplerImplicitMoves) { @@ -3575,9 +3409,6 @@ static bool hasDeducedReturnType(FunctionDecl *FD) { return FPT->getReturnType()->isUndeducedType(); } -/// ActOnCapScopeReturnStmt - Utility routine to type-check return statements -/// for capturing scopes. -/// StmtResult Sema::ActOnCapScopeReturnStmt(SourceLocation ReturnLoc, Expr *RetValExp, NamedReturnInfo &NRInfo, @@ -3791,8 +3622,6 @@ TypeLoc Sema::getReturnTypeLoc(FunctionDecl *FD) const { .getReturnLoc(); } -/// Deduce the return type for a function from a returned expression, per -/// C++1y [dcl.spec.auto]p6. bool Sema::DeduceFunctionTypeFromReturnExpr(FunctionDecl *FD, SourceLocation ReturnLoc, Expr *RetExpr, const AutoType *AT) { @@ -3802,7 +3631,7 @@ bool Sema::DeduceFunctionTypeFromReturnExpr(FunctionDecl *FD, if (isLambdaConversionOperator(FD)) return false; - if (RetExpr && isa<InitListExpr>(RetExpr)) { + if (isa_and_nonnull<InitListExpr>(RetExpr)) { // If the deduction is for a return statement and the initializer is // a braced-init-list, the program is ill-formed. Diag(RetExpr->getExprLoc(), @@ -3854,14 +3683,14 @@ bool Sema::DeduceFunctionTypeFromReturnExpr(FunctionDecl *FD, TemplateDeductionResult Res = DeduceAutoType( OrigResultType, RetExpr, Deduced, Info, /*DependentDeduction=*/false, /*IgnoreConstraints=*/false, &FailedTSC); - if (Res != TDK_Success && FD->isInvalidDecl()) + if (Res != TemplateDeductionResult::Success && FD->isInvalidDecl()) return true; switch (Res) { - case TDK_Success: + case TemplateDeductionResult::Success: break; - case TDK_AlreadyDiagnosed: + case TemplateDeductionResult::AlreadyDiagnosed: return true; - case TDK_Inconsistent: { + case TemplateDeductionResult::Inconsistent: { // If a function with a declared return type that contains a placeholder // type has multiple return statements, the return type is deduced for // each return statement. [...] if the type deduced is not the same in @@ -3912,6 +3741,12 @@ Sema::ActOnReturnStmt(SourceLocation ReturnLoc, Expr *RetValExp, RetValExp, nullptr, /*RecoverUncorrectedTypos=*/true); if (RetVal.isInvalid()) return StmtError(); + + if (getCurScope()->isInOpenACCComputeConstructScope()) + return StmtError( + Diag(ReturnLoc, diag::err_acc_branch_in_out_compute_construct) + << /*return*/ 1 << /*out of */ 0); + StmtResult R = BuildReturnStmt(ReturnLoc, RetVal.get(), /*AllowRecovery=*/true); if (R.isInvalid() || ExprEvalContexts.back().isDiscardedStatementContext()) @@ -4228,132 +4063,6 @@ StmtResult Sema::BuildReturnStmt(SourceLocation ReturnLoc, Expr *RetValExp, } StmtResult -Sema::ActOnObjCAtCatchStmt(SourceLocation AtLoc, - SourceLocation RParen, Decl *Parm, - Stmt *Body) { - VarDecl *Var = cast_or_null<VarDecl>(Parm); - if (Var && Var->isInvalidDecl()) - return StmtError(); - - return new (Context) ObjCAtCatchStmt(AtLoc, RParen, Var, Body); -} - -StmtResult -Sema::ActOnObjCAtFinallyStmt(SourceLocation AtLoc, Stmt *Body) { - return new (Context) ObjCAtFinallyStmt(AtLoc, Body); -} - -StmtResult -Sema::ActOnObjCAtTryStmt(SourceLocation AtLoc, Stmt *Try, - MultiStmtArg CatchStmts, Stmt *Finally) { - if (!getLangOpts().ObjCExceptions) - Diag(AtLoc, diag::err_objc_exceptions_disabled) << "@try"; - - // Objective-C try is incompatible with SEH __try. - sema::FunctionScopeInfo *FSI = getCurFunction(); - if (FSI->FirstSEHTryLoc.isValid()) { - Diag(AtLoc, diag::err_mixing_cxx_try_seh_try) << 1; - Diag(FSI->FirstSEHTryLoc, diag::note_conflicting_try_here) << "'__try'"; - } - - FSI->setHasObjCTry(AtLoc); - unsigned NumCatchStmts = CatchStmts.size(); - return ObjCAtTryStmt::Create(Context, AtLoc, Try, CatchStmts.data(), - NumCatchStmts, Finally); -} - -StmtResult Sema::BuildObjCAtThrowStmt(SourceLocation AtLoc, Expr *Throw) { - if (Throw) { - ExprResult Result = DefaultLvalueConversion(Throw); - if (Result.isInvalid()) - return StmtError(); - - Result = ActOnFinishFullExpr(Result.get(), /*DiscardedValue*/ false); - if (Result.isInvalid()) - return StmtError(); - Throw = Result.get(); - - QualType ThrowType = Throw->getType(); - // Make sure the expression type is an ObjC pointer or "void *". - if (!ThrowType->isDependentType() && - !ThrowType->isObjCObjectPointerType()) { - const PointerType *PT = ThrowType->getAs<PointerType>(); - if (!PT || !PT->getPointeeType()->isVoidType()) - return StmtError(Diag(AtLoc, diag::err_objc_throw_expects_object) - << Throw->getType() << Throw->getSourceRange()); - } - } - - return new (Context) ObjCAtThrowStmt(AtLoc, Throw); -} - -StmtResult -Sema::ActOnObjCAtThrowStmt(SourceLocation AtLoc, Expr *Throw, - Scope *CurScope) { - if (!getLangOpts().ObjCExceptions) - Diag(AtLoc, diag::err_objc_exceptions_disabled) << "@throw"; - - if (!Throw) { - // @throw without an expression designates a rethrow (which must occur - // in the context of an @catch clause). - Scope *AtCatchParent = CurScope; - while (AtCatchParent && !AtCatchParent->isAtCatchScope()) - AtCatchParent = AtCatchParent->getParent(); - if (!AtCatchParent) - return StmtError(Diag(AtLoc, diag::err_rethrow_used_outside_catch)); - } - return BuildObjCAtThrowStmt(AtLoc, Throw); -} - -ExprResult -Sema::ActOnObjCAtSynchronizedOperand(SourceLocation atLoc, Expr *operand) { - ExprResult result = DefaultLvalueConversion(operand); - if (result.isInvalid()) - return ExprError(); - operand = result.get(); - - // Make sure the expression type is an ObjC pointer or "void *". - QualType type = operand->getType(); - if (!type->isDependentType() && - !type->isObjCObjectPointerType()) { - const PointerType *pointerType = type->getAs<PointerType>(); - if (!pointerType || !pointerType->getPointeeType()->isVoidType()) { - if (getLangOpts().CPlusPlus) { - if (RequireCompleteType(atLoc, type, - diag::err_incomplete_receiver_type)) - return Diag(atLoc, diag::err_objc_synchronized_expects_object) - << type << operand->getSourceRange(); - - ExprResult result = PerformContextuallyConvertToObjCPointer(operand); - if (result.isInvalid()) - return ExprError(); - if (!result.isUsable()) - return Diag(atLoc, diag::err_objc_synchronized_expects_object) - << type << operand->getSourceRange(); - - operand = result.get(); - } else { - return Diag(atLoc, diag::err_objc_synchronized_expects_object) - << type << operand->getSourceRange(); - } - } - } - - // The operand to @synchronized is a full-expression. - return ActOnFinishFullExpr(operand, /*DiscardedValue*/ false); -} - -StmtResult -Sema::ActOnObjCAtSynchronizedStmt(SourceLocation AtLoc, Expr *SyncExpr, - Stmt *SyncBody) { - // We can't jump into or indirect-jump out of a @synchronized block. - setFunctionHasBranchProtectedScope(); - return new (Context) ObjCAtSynchronizedStmt(AtLoc, SyncExpr, SyncBody); -} - -/// ActOnCXXCatchBlock - Takes an exception declaration and a handler block -/// and creates a proper catch handler from them. -StmtResult Sema::ActOnCXXCatchBlock(SourceLocation CatchLoc, Decl *ExDecl, Stmt *HandlerBlock) { // There's nothing to test that ActOnExceptionDecl didn't already test. @@ -4361,15 +4070,10 @@ Sema::ActOnCXXCatchBlock(SourceLocation CatchLoc, Decl *ExDecl, CXXCatchStmt(CatchLoc, cast_or_null<VarDecl>(ExDecl), HandlerBlock); } -StmtResult -Sema::ActOnObjCAutoreleasePoolStmt(SourceLocation AtLoc, Stmt *Body) { - setFunctionHasBranchProtectedScope(); - return new (Context) ObjCAutoreleasePoolStmt(AtLoc, Body); -} - namespace { class CatchHandlerType { QualType QT; + LLVM_PREFERRED_TYPE(bool) unsigned IsPointer : 1; // This is a special constructor to be used only with DenseMapInfo's @@ -4479,8 +4183,6 @@ public: }; } -/// ActOnCXXTryBlock - Takes a try compound-statement and a number of -/// handlers and creates a try statement from them. StmtResult Sema::ActOnCXXTryBlock(SourceLocation TryLoc, Stmt *TryBlock, ArrayRef<Stmt *> Handlers) { const llvm::Triple &T = Context.getTargetInfo().getTriple(); @@ -4501,8 +4203,8 @@ StmtResult Sema::ActOnCXXTryBlock(SourceLocation TryLoc, Stmt *TryBlock, // Exceptions aren't allowed in CUDA device code. if (getLangOpts().CUDA) - CUDADiagIfDeviceCode(TryLoc, diag::err_cuda_device_exceptions) - << "try" << CurrentCUDATarget(); + CUDA().DiagIfDeviceCode(TryLoc, diag::err_cuda_device_exceptions) + << "try" << llvm::to_underlying(CUDA().CurrentTarget()); if (getCurScope() && getCurScope()->isOpenMPSimdDirectiveScope()) Diag(TryLoc, diag::err_omp_simd_region_cannot_use_stmt) << "try"; @@ -4748,7 +4450,8 @@ buildCapturedStmtCaptureList(Sema &S, CapturedRegionScopeInfo *RSI, assert(Cap.isVariableCapture() && "unknown kind of capture"); if (S.getLangOpts().OpenMP && RSI->CapRegionKind == CR_OpenMP) - S.setOpenMPCaptureKind(Field, Cap.getVariable(), RSI->OpenMPLevel); + S.OpenMP().setOpenMPCaptureKind(Field, Cap.getVariable(), + RSI->OpenMPLevel); Captures.push_back(CapturedStmt::Capture( Cap.getLocation(), |