aboutsummaryrefslogtreecommitdiff
path: root/lib/Sema/SemaStmt.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'lib/Sema/SemaStmt.cpp')
-rw-r--r--lib/Sema/SemaStmt.cpp151
1 files changed, 101 insertions, 50 deletions
diff --git a/lib/Sema/SemaStmt.cpp b/lib/Sema/SemaStmt.cpp
index 480155df8990..6c680f29da4f 100644
--- a/lib/Sema/SemaStmt.cpp
+++ b/lib/Sema/SemaStmt.cpp
@@ -196,6 +196,25 @@ static bool DiagnoseUnusedComparison(Sema &S, const Expr *E) {
return true;
}
+static bool DiagnoseNoDiscard(Sema &S, const WarnUnusedResultAttr *A,
+ SourceLocation Loc, SourceRange R1,
+ SourceRange R2, bool IsCtor) {
+ if (!A)
+ return false;
+ StringRef Msg = A->getMessage();
+
+ if (Msg.empty()) {
+ if (IsCtor)
+ return S.Diag(Loc, diag::warn_unused_constructor) << A << R1 << R2;
+ return S.Diag(Loc, diag::warn_unused_result) << A << R1 << R2;
+ }
+
+ if (IsCtor)
+ return S.Diag(Loc, diag::warn_unused_constructor_msg) << A << Msg << R1
+ << R2;
+ return S.Diag(Loc, diag::warn_unused_result_msg) << A << Msg << R1 << R2;
+}
+
void Sema::DiagnoseUnusedExprResult(const Stmt *S) {
if (const LabelStmt *Label = dyn_cast_or_null<LabelStmt>(S))
return DiagnoseUnusedExprResult(Label->getSubStmt());
@@ -254,14 +273,19 @@ void Sema::DiagnoseUnusedExprResult(const Stmt *S) {
return;
E = WarnExpr;
+ if (const auto *Cast = dyn_cast<CastExpr>(E))
+ if (Cast->getCastKind() == CK_NoOp ||
+ Cast->getCastKind() == CK_ConstructorConversion)
+ E = Cast->getSubExpr()->IgnoreImpCasts();
+
if (const CallExpr *CE = dyn_cast<CallExpr>(E)) {
if (E->getType()->isVoidType())
return;
- if (const Attr *A = CE->getUnusedResultAttr(Context)) {
- Diag(Loc, diag::warn_unused_result) << A << R1 << R2;
+ if (DiagnoseNoDiscard(*this, cast_or_null<WarnUnusedResultAttr>(
+ CE->getUnusedResultAttr(Context)),
+ Loc, R1, R2, /*isCtor=*/false))
return;
- }
// If the callee has attribute pure, const, or warn_unused_result, warn with
// a more specific message to make it clear what is happening. If the call
@@ -279,9 +303,24 @@ void Sema::DiagnoseUnusedExprResult(const Stmt *S) {
return;
}
}
+ } else if (const auto *CE = dyn_cast<CXXConstructExpr>(E)) {
+ if (const CXXConstructorDecl *Ctor = CE->getConstructor()) {
+ const auto *A = Ctor->getAttr<WarnUnusedResultAttr>();
+ A = A ? A : Ctor->getParent()->getAttr<WarnUnusedResultAttr>();
+ if (DiagnoseNoDiscard(*this, A, Loc, R1, R2, /*isCtor=*/true))
+ return;
+ }
+ } else if (const auto *ILE = dyn_cast<InitListExpr>(E)) {
+ if (const TagDecl *TD = ILE->getType()->getAsTagDecl()) {
+
+ if (DiagnoseNoDiscard(*this, TD->getAttr<WarnUnusedResultAttr>(), Loc, R1,
+ R2, /*isCtor=*/false))
+ return;
+ }
} else if (ShouldSuppress)
return;
+ E = WarnExpr;
if (const ObjCMessageExpr *ME = dyn_cast<ObjCMessageExpr>(E)) {
if (getLangOpts().ObjCAutoRefCount && ME->isDelegateInitCall()) {
Diag(Loc, diag::err_arc_unused_init_message) << R1;
@@ -289,10 +328,9 @@ void Sema::DiagnoseUnusedExprResult(const Stmt *S) {
}
const ObjCMethodDecl *MD = ME->getMethodDecl();
if (MD) {
- if (const auto *A = MD->getAttr<WarnUnusedResultAttr>()) {
- Diag(Loc, diag::warn_unused_result) << A << R1 << R2;
+ if (DiagnoseNoDiscard(*this, MD->getAttr<WarnUnusedResultAttr>(), Loc, R1,
+ R2, /*isCtor=*/false))
return;
- }
}
} else if (const PseudoObjectExpr *POE = dyn_cast<PseudoObjectExpr>(E)) {
const Expr *Source = POE->getSyntacticForm();
@@ -392,45 +430,44 @@ Sema::ActOnCaseExpr(SourceLocation CaseLoc, ExprResult Val) {
// If we're not inside a switch, let the 'case' statement handling diagnose
// this. Just clean up after the expression as best we can.
- if (!getCurFunction()->SwitchStack.empty()) {
- Expr *CondExpr =
- getCurFunction()->SwitchStack.back().getPointer()->getCond();
- if (!CondExpr)
- return ExprError();
- QualType CondType = CondExpr->getType();
-
- auto CheckAndFinish = [&](Expr *E) {
- if (CondType->isDependentType() || E->isTypeDependent())
- return ExprResult(E);
-
- if (getLangOpts().CPlusPlus11) {
- // C++11 [stmt.switch]p2: the constant-expression shall be a converted
- // constant expression of the promoted type of the switch condition.
- llvm::APSInt TempVal;
- return CheckConvertedConstantExpression(E, CondType, TempVal,
- CCEK_CaseValue);
- }
+ if (getCurFunction()->SwitchStack.empty())
+ return ActOnFinishFullExpr(Val.get(), Val.get()->getExprLoc(), false,
+ getLangOpts().CPlusPlus11);
- ExprResult ER = E;
- if (!E->isValueDependent())
- ER = VerifyIntegerConstantExpression(E);
- if (!ER.isInvalid())
- ER = DefaultLvalueConversion(ER.get());
- if (!ER.isInvalid())
- ER = ImpCastExprToType(ER.get(), CondType, CK_IntegralCast);
- return ER;
- };
+ Expr *CondExpr =
+ getCurFunction()->SwitchStack.back().getPointer()->getCond();
+ if (!CondExpr)
+ return ExprError();
+ QualType CondType = CondExpr->getType();
- ExprResult Converted = CorrectDelayedTyposInExpr(Val, CheckAndFinish);
- if (Converted.get() == Val.get())
- Converted = CheckAndFinish(Val.get());
- if (Converted.isInvalid())
- return ExprError();
- Val = Converted;
- }
+ auto CheckAndFinish = [&](Expr *E) {
+ if (CondType->isDependentType() || E->isTypeDependent())
+ return ExprResult(E);
+
+ if (getLangOpts().CPlusPlus11) {
+ // C++11 [stmt.switch]p2: the constant-expression shall be a converted
+ // constant expression of the promoted type of the switch condition.
+ llvm::APSInt TempVal;
+ return CheckConvertedConstantExpression(E, CondType, TempVal,
+ CCEK_CaseValue);
+ }
- return ActOnFinishFullExpr(Val.get(), Val.get()->getExprLoc(), false,
- getLangOpts().CPlusPlus11);
+ ExprResult ER = E;
+ if (!E->isValueDependent())
+ ER = VerifyIntegerConstantExpression(E);
+ if (!ER.isInvalid())
+ ER = DefaultLvalueConversion(ER.get());
+ if (!ER.isInvalid())
+ ER = ImpCastExprToType(ER.get(), CondType, CK_IntegralCast);
+ if (!ER.isInvalid())
+ ER = ActOnFinishFullExpr(ER.get(), ER.get()->getExprLoc(), false);
+ return ER;
+ };
+
+ ExprResult Converted = CorrectDelayedTyposInExpr(Val, CheckAndFinish);
+ if (Converted.get() == Val.get())
+ Converted = CheckAndFinish(Val.get());
+ return Converted;
}
StmtResult
@@ -926,7 +963,7 @@ Sema::ActOnFinishSwitchStmt(SourceLocation SwitchLoc, Stmt *Switch,
// condition is constant.
llvm::APSInt ConstantCondValue;
bool HasConstantCond = false;
- if (!HasDependentValue && !TheDefaultStmt) {
+ if (!TheDefaultStmt) {
Expr::EvalResult Result;
HasConstantCond = CondExpr->EvaluateAsInt(Result, Context,
Expr::SE_AllowSideEffects);
@@ -2637,6 +2674,11 @@ StmtResult Sema::BuildCXXForRangeStmt(SourceLocation ForLoc,
if (Kind == BFRK_Check)
return StmtResult();
+ // 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());
+
return new (Context) CXXForRangeStmt(
InitStmt, RangeDS, cast_or_null<DeclStmt>(BeginDeclStmt.get()),
cast_or_null<DeclStmt>(EndDeclStmt.get()), NotEqExpr.get(),
@@ -3268,18 +3310,18 @@ Sema::ActOnCapScopeReturnStmt(SourceLocation ReturnLoc, Expr *RetValExp) {
}
assert(!FnRetType.isNull());
- if (BlockScopeInfo *CurBlock = dyn_cast<BlockScopeInfo>(CurCap)) {
- if (CurBlock->FunctionType->getAs<FunctionType>()->getNoReturnAttr()) {
+ if (auto *CurBlock = dyn_cast<BlockScopeInfo>(CurCap)) {
+ if (CurBlock->FunctionType->castAs<FunctionType>()->getNoReturnAttr()) {
Diag(ReturnLoc, diag::err_noreturn_block_has_return_expr);
return StmtError();
}
- } else if (CapturedRegionScopeInfo *CurRegion =
- dyn_cast<CapturedRegionScopeInfo>(CurCap)) {
+ } else if (auto *CurRegion = dyn_cast<CapturedRegionScopeInfo>(CurCap)) {
Diag(ReturnLoc, diag::err_return_in_captured_stmt) << CurRegion->getRegionName();
return StmtError();
} else {
assert(CurLambda && "unknown kind of captured scope");
- if (CurLambda->CallOperator->getType()->getAs<FunctionType>()
+ if (CurLambda->CallOperator->getType()
+ ->castAs<FunctionType>()
->getNoReturnAttr()) {
Diag(ReturnLoc, diag::err_noreturn_lambda_has_return_expr);
return StmtError();
@@ -3463,6 +3505,14 @@ bool Sema::DeduceFunctionTypeFromReturnExpr(FunctionDecl *FD,
return true;
}
+ // CUDA: Kernel function must have 'void' return type.
+ if (getLangOpts().CUDA)
+ if (FD->hasAttr<CUDAGlobalAttr>() && !Deduced->isVoidType()) {
+ Diag(FD->getLocation(), diag::err_kern_type_not_void_return)
+ << FD->getType() << FD->getSourceRange();
+ return true;
+ }
+
// 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 each deduction,
@@ -4296,7 +4346,8 @@ void Sema::ActOnCapturedRegionStart(SourceLocation Loc, Scope *CurScope,
void Sema::ActOnCapturedRegionStart(SourceLocation Loc, Scope *CurScope,
CapturedRegionKind Kind,
- ArrayRef<CapturedParamNameType> Params) {
+ ArrayRef<CapturedParamNameType> Params,
+ unsigned OpenMPCaptureLevel) {
CapturedDecl *CD = nullptr;
RecordDecl *RD = CreateCapturedStmtRecordDecl(CD, Loc, Params.size());
@@ -4341,7 +4392,7 @@ void Sema::ActOnCapturedRegionStart(SourceLocation Loc, Scope *CurScope,
CD->setContextParam(ParamNum, Param);
}
// Enter the capturing scope for this captured region.
- PushCapturedRegionScope(CurScope, CD, RD, Kind);
+ PushCapturedRegionScope(CurScope, CD, RD, Kind, OpenMPCaptureLevel);
if (CurScope)
PushDeclContext(CurScope, CD);