summaryrefslogtreecommitdiff
path: root/clang/lib/Sema/SemaStmt.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'clang/lib/Sema/SemaStmt.cpp')
-rw-r--r--clang/lib/Sema/SemaStmt.cpp127
1 files changed, 74 insertions, 53 deletions
diff --git a/clang/lib/Sema/SemaStmt.cpp b/clang/lib/Sema/SemaStmt.cpp
index d6c3af9e84c80..73f3183c163f3 100644
--- a/clang/lib/Sema/SemaStmt.cpp
+++ b/clang/lib/Sema/SemaStmt.cpp
@@ -334,6 +334,11 @@ void Sema::DiagnoseUnusedExprResult(const Stmt *S) {
}
} else if (const PseudoObjectExpr *POE = dyn_cast<PseudoObjectExpr>(E)) {
const Expr *Source = POE->getSyntacticForm();
+ // Handle the actually selected call of an OpenMP specialized call.
+ if (LangOpts.OpenMP && isa<CallExpr>(Source) &&
+ POE->getNumSemanticExprs() == 1 &&
+ isa<CallExpr>(POE->getSemanticExpr(0)))
+ return DiagnoseUnusedExprResult(POE->getSemanticExpr(0));
if (isa<ObjCSubscriptRefExpr>(Source))
DiagID = diag::warn_unused_container_subscript_expr;
else
@@ -365,7 +370,10 @@ void Sema::DiagnoseUnusedExprResult(const Stmt *S) {
}
}
- if (E->isGLValue() && E->getType().isVolatileQualified()) {
+ // Tell the user to assign it into a variable to force a volatile load if this
+ // isn't an array.
+ if (E->isGLValue() && E->getType().isVolatileQualified() &&
+ !E->getType()->isArrayType()) {
Diag(Loc, diag::warn_unused_volatile) << R1 << R2;
return;
}
@@ -389,6 +397,11 @@ StmtResult Sema::ActOnCompoundStmt(SourceLocation L, SourceLocation R,
ArrayRef<Stmt *> Elts, bool isStmtExpr) {
const unsigned NumElts = Elts.size();
+ // Mark the current function as usng floating point constrained intrinsics
+ if (getCurFPFeatures().isFPConstrained())
+ if (FunctionDecl *F = dyn_cast<FunctionDecl>(CurContext))
+ F->setUsesFPIntrin(true);
+
// If we're in C89 mode, check that we don't have any decls after stmts. If
// so, emit an extension diagnostic.
if (!getLangOpts().C99 && !getLangOpts().CPlusPlus) {
@@ -464,7 +477,9 @@ Sema::ActOnCaseExpr(SourceLocation CaseLoc, ExprResult Val) {
return ER;
};
- ExprResult Converted = CorrectDelayedTyposInExpr(Val, CheckAndFinish);
+ ExprResult Converted = CorrectDelayedTyposInExpr(
+ Val, /*InitDecl=*/nullptr, /*RecoverUncorrectedTypos=*/false,
+ CheckAndFinish);
if (Converted.get() == Val.get())
Converted = CheckAndFinish(Val.get());
return Converted;
@@ -730,11 +745,11 @@ StmtResult Sema::ActOnStartOfSwitchStmt(SourceLocation SwitchLoc,
if (CondExpr && !CondExpr->isTypeDependent()) {
// We have already converted the expression to an integral or enumeration
- // type, when we parsed the switch condition. If we don't have an
- // appropriate type now, enter the switch scope but remember that it's
- // invalid.
- assert(CondExpr->getType()->isIntegralOrEnumerationType() &&
- "invalid condition type");
+ // type, when we parsed the switch condition. There are cases where we don't
+ // have an appropriate type, e.g. a typo-expr Cond was corrected to an
+ // inappropriate-type expr, we just return an error.
+ if (!CondExpr->getType()->isIntegralOrEnumerationType())
+ return StmtError();
if (CondExpr->isKnownToHaveBooleanValue()) {
// switch(bool_expr) {...} is often a programmer error, e.g.
// switch(n && mask) { ... } // Doh - should be "n & mask".
@@ -1313,8 +1328,9 @@ Sema::DiagnoseAssignmentEnum(QualType DstType, QualType SrcType,
}
}
-StmtResult Sema::ActOnWhileStmt(SourceLocation WhileLoc, ConditionResult Cond,
- Stmt *Body) {
+StmtResult Sema::ActOnWhileStmt(SourceLocation WhileLoc,
+ SourceLocation LParenLoc, ConditionResult Cond,
+ SourceLocation RParenLoc, Stmt *Body) {
if (Cond.isInvalid())
return StmtError();
@@ -1329,7 +1345,7 @@ StmtResult Sema::ActOnWhileStmt(SourceLocation WhileLoc, ConditionResult Cond,
getCurCompoundScope().setHasEmptyLoopBodies();
return WhileStmt::Create(Context, CondVal.first, CondVal.second, Body,
- WhileLoc);
+ WhileLoc, LParenLoc, RParenLoc);
}
StmtResult
@@ -1387,10 +1403,9 @@ namespace {
Simple = false;
}
- // Any Stmt not whitelisted will cause the condition to be marked complex.
- void VisitStmt(Stmt *S) {
- Simple = false;
- }
+ // Any Stmt not explicitly listed will cause the condition to be marked
+ // complex.
+ void VisitStmt(Stmt *S) { Simple = false; }
void VisitBinaryOperator(BinaryOperator *E) {
Visit(E->getLHS());
@@ -2114,18 +2129,22 @@ StmtResult Sema::ActOnCXXForRangeStmt(Scope *S, SourceLocation ForLoc,
return StmtError();
}
+ // This function is responsible for attaching an initializer to LoopVar. We
+ // must call ActOnInitializerError if we fail to do so.
Decl *LoopVar = DS->getSingleDecl();
if (LoopVar->isInvalidDecl() || !Range ||
DiagnoseUnexpandedParameterPack(Range, UPPC_Expression)) {
- LoopVar->setInvalidDecl();
+ ActOnInitializerError(LoopVar);
return StmtError();
}
// Build the coroutine state immediately and not later during template
// instantiation
if (!CoawaitLoc.isInvalid()) {
- if (!ActOnCoroutineBodyStart(S, CoawaitLoc, "co_await"))
+ if (!ActOnCoroutineBodyStart(S, CoawaitLoc, "co_await")) {
+ ActOnInitializerError(LoopVar);
return StmtError();
+ }
}
// Build auto && __range = range-init
@@ -2137,7 +2156,7 @@ StmtResult Sema::ActOnCXXForRangeStmt(Scope *S, SourceLocation ForLoc,
std::string("__range") + DepthStr);
if (FinishForRangeVarDecl(*this, RangeVar, Range, RangeLoc,
diag::err_for_range_deduction_failure)) {
- LoopVar->setInvalidDecl();
+ ActOnInitializerError(LoopVar);
return StmtError();
}
@@ -2146,14 +2165,20 @@ StmtResult Sema::ActOnCXXForRangeStmt(Scope *S, SourceLocation ForLoc,
BuildDeclaratorGroup(MutableArrayRef<Decl *>((Decl **)&RangeVar, 1));
StmtResult RangeDecl = ActOnDeclStmt(RangeGroup, RangeLoc, RangeLoc);
if (RangeDecl.isInvalid()) {
- LoopVar->setInvalidDecl();
+ ActOnInitializerError(LoopVar);
return StmtError();
}
- return BuildCXXForRangeStmt(
+ StmtResult R = BuildCXXForRangeStmt(
ForLoc, CoawaitLoc, InitStmt, ColonLoc, RangeDecl.get(),
/*BeginStmt=*/nullptr, /*EndStmt=*/nullptr,
/*Cond=*/nullptr, /*Inc=*/nullptr, DS, RParenLoc, Kind);
+ if (R.isInvalid()) {
+ ActOnInitializerError(LoopVar);
+ return StmtError();
+ }
+
+ return R;
}
/// Create the initialization, compare, and increment steps for
@@ -2336,22 +2361,6 @@ static StmtResult RebuildForRangeWithDereference(Sema &SemaRef, Scope *S,
AdjustedRange.get(), RParenLoc, Sema::BFRK_Rebuild);
}
-namespace {
-/// RAII object to automatically invalidate a declaration if an error occurs.
-struct InvalidateOnErrorScope {
- InvalidateOnErrorScope(Sema &SemaRef, Decl *D, bool Enabled)
- : Trap(SemaRef.Diags), D(D), Enabled(Enabled) {}
- ~InvalidateOnErrorScope() {
- if (Enabled && Trap.hasErrorOccurred())
- D->setInvalidDecl();
- }
-
- DiagnosticErrorTrap Trap;
- Decl *D;
- bool Enabled;
-};
-}
-
/// BuildCXXForRangeStmt - Build or instantiate a C++11 for-range statement.
StmtResult Sema::BuildCXXForRangeStmt(SourceLocation ForLoc,
SourceLocation CoawaitLoc, Stmt *InitStmt,
@@ -2378,11 +2387,6 @@ StmtResult Sema::BuildCXXForRangeStmt(SourceLocation ForLoc,
DeclStmt *LoopVarDS = cast<DeclStmt>(LoopVarDecl);
VarDecl *LoopVar = cast<VarDecl>(LoopVarDS->getSingleDecl());
- // If we hit any errors, mark the loop variable as invalid if its type
- // contains 'auto'.
- InvalidateOnErrorScope Invalidate(*this, LoopVar,
- LoopVar->getType()->isUndeducedType());
-
StmtResult BeginDeclStmt = Begin;
StmtResult EndDeclStmt = End;
ExprResult NotEqExpr = Cond, IncrExpr = Inc;
@@ -2664,7 +2668,8 @@ StmtResult Sema::BuildCXXForRangeStmt(SourceLocation ForLoc,
// trying to determine whether this would be a valid range.
if (!LoopVar->isInvalidDecl() && Kind != BFRK_Check) {
AddInitializerToDecl(LoopVar, DerefExpr.get(), /*DirectInit=*/false);
- if (LoopVar->isInvalidDecl())
+ if (LoopVar->isInvalidDecl() ||
+ (LoopVar->getInit() && LoopVar->getInit()->containsErrors()))
NoteForRangeBeginEndFunction(*this, BeginExpr.get(), BEF_begin);
}
}
@@ -2741,22 +2746,24 @@ static void DiagnoseForRangeReferenceVariableCopies(Sema &SemaRef,
E = E->IgnoreImpCasts();
}
- bool ReturnsReference = false;
+ QualType ReferenceReturnType;
if (isa<UnaryOperator>(E)) {
- ReturnsReference = true;
+ ReferenceReturnType = SemaRef.Context.getLValueReferenceType(E->getType());
} else {
const CXXOperatorCallExpr *Call = cast<CXXOperatorCallExpr>(E);
const FunctionDecl *FD = Call->getDirectCallee();
QualType ReturnType = FD->getReturnType();
- ReturnsReference = ReturnType->isReferenceType();
+ if (ReturnType->isReferenceType())
+ ReferenceReturnType = ReturnType;
}
- if (ReturnsReference) {
+ if (!ReferenceReturnType.isNull()) {
// Loop variable creates a temporary. Suggest either to go with
// non-reference loop variable to indicate a copy is made, or
- // the correct time to bind a const reference.
- SemaRef.Diag(VD->getLocation(), diag::warn_for_range_const_reference_copy)
- << VD << VariableType << E->getType();
+ // the correct type to bind a const reference.
+ SemaRef.Diag(VD->getLocation(),
+ diag::warn_for_range_const_ref_binds_temp_built_from_ref)
+ << VD << VariableType << ReferenceReturnType;
QualType NonReferenceType = VariableType.getNonReferenceType();
NonReferenceType.removeLocalConst();
QualType NewReferenceType =
@@ -2769,7 +2776,7 @@ static void DiagnoseForRangeReferenceVariableCopies(Sema &SemaRef,
// Suggest removing the reference from the loop variable.
// If the type is a rvalue reference do not warn since that changes the
// semantic of the code.
- SemaRef.Diag(VD->getLocation(), diag::warn_for_range_variable_always_copy)
+ SemaRef.Diag(VD->getLocation(), diag::warn_for_range_ref_binds_ret_temp)
<< VD << RangeInitType;
QualType NonReferenceType = VariableType.getNonReferenceType();
NonReferenceType.removeLocalConst();
@@ -2821,7 +2828,7 @@ static void DiagnoseForRangeConstVariableCopies(Sema &SemaRef,
// Suggest changing from a const variable to a const reference variable
// if doing so will prevent a copy.
SemaRef.Diag(VD->getLocation(), diag::warn_for_range_copy)
- << VD << VariableType << InitExpr->getType();
+ << VD << VariableType;
SemaRef.Diag(VD->getBeginLoc(), diag::note_use_reference_type)
<< SemaRef.Context.getLValueReferenceType(VariableType)
<< VD->getSourceRange()
@@ -2838,9 +2845,13 @@ static void DiagnoseForRangeConstVariableCopies(Sema &SemaRef,
/// Suggest "const foo &x" to prevent the copy.
static void DiagnoseForRangeVariableCopies(Sema &SemaRef,
const CXXForRangeStmt *ForStmt) {
- if (SemaRef.Diags.isIgnored(diag::warn_for_range_const_reference_copy,
- ForStmt->getBeginLoc()) &&
- SemaRef.Diags.isIgnored(diag::warn_for_range_variable_always_copy,
+ if (SemaRef.inTemplateInstantiation())
+ return;
+
+ if (SemaRef.Diags.isIgnored(
+ diag::warn_for_range_const_ref_binds_temp_built_from_ref,
+ ForStmt->getBeginLoc()) &&
+ SemaRef.Diags.isIgnored(diag::warn_for_range_ref_binds_ret_temp,
ForStmt->getBeginLoc()) &&
SemaRef.Diags.isIgnored(diag::warn_for_range_copy,
ForStmt->getBeginLoc())) {
@@ -2860,6 +2871,9 @@ static void DiagnoseForRangeVariableCopies(Sema &SemaRef,
if (!InitExpr)
return;
+ if (InitExpr->getExprLoc().isMacroID())
+ return;
+
if (VariableType->isReferenceType()) {
DiagnoseForRangeReferenceVariableCopies(SemaRef, VD,
ForStmt->getRangeInit()->getType());
@@ -3286,6 +3300,7 @@ Sema::ActOnCapScopeReturnStmt(SourceLocation ReturnLoc, Expr *RetValExp) {
assert(AT && "lost auto type from lambda return type");
if (DeduceFunctionTypeFromReturnExpr(FD, ReturnLoc, RetValExp, AT)) {
FD->setInvalidDecl();
+ // FIXME: preserve the ill-formed return expression.
return StmtError();
}
CurCap->ReturnType = FnRetType = FD->getReturnType();
@@ -3616,6 +3631,12 @@ StmtResult Sema::BuildReturnStmt(SourceLocation ReturnLoc, Expr *RetValExp) {
if (isa<CXXBoolLiteralExpr>(RetValExp))
Diag(ReturnLoc, diag::warn_main_returns_bool_literal)
<< RetValExp->getSourceRange();
+ if (FD->hasAttr<CmseNSEntryAttr>() && RetValExp) {
+ if (const auto *RT = dyn_cast<RecordType>(FnRetType.getCanonicalType())) {
+ if (RT->getDecl()->isOrContainsUnion())
+ Diag(RetValExp->getBeginLoc(), diag::warn_cmse_nonsecure_union) << 1;
+ }
+ }
} else if (ObjCMethodDecl *MD = getCurMethodDecl()) {
FnRetType = MD->getReturnType();
isObjCMethod = true;