diff options
Diffstat (limited to 'clang/lib/Sema/SemaStmt.cpp')
-rw-r--r-- | clang/lib/Sema/SemaStmt.cpp | 127 |
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; |