aboutsummaryrefslogtreecommitdiff
path: root/contrib/llvm-project/clang/lib/Sema/SemaStmt.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'contrib/llvm-project/clang/lib/Sema/SemaStmt.cpp')
-rw-r--r--contrib/llvm-project/clang/lib/Sema/SemaStmt.cpp509
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(),