diff options
Diffstat (limited to 'contrib/llvm-project/clang/lib/Sema/SemaStmt.cpp')
-rw-r--r-- | contrib/llvm-project/clang/lib/Sema/SemaStmt.cpp | 61 |
1 files changed, 42 insertions, 19 deletions
diff --git a/contrib/llvm-project/clang/lib/Sema/SemaStmt.cpp b/contrib/llvm-project/clang/lib/Sema/SemaStmt.cpp index 1d90759f2406..746eb82a5bdc 100644 --- a/contrib/llvm-project/clang/lib/Sema/SemaStmt.cpp +++ b/contrib/llvm-project/clang/lib/Sema/SemaStmt.cpp @@ -410,9 +410,13 @@ StmtResult Sema::ActOnCompoundStmt(SourceLocation L, SourceLocation R, ArrayRef<Stmt *> Elts, bool isStmtExpr) { const unsigned NumElts = Elts.size(); - // 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) { + // If we're in C mode, check that we don't have any decls after stmts. If + // so, emit an extension diagnostic in C89 and potentially a warning in later + // versions. + const unsigned MixedDeclsCodeID = getLangOpts().C99 + ? diag::warn_mixed_decls_code + : diag::ext_mixed_decls_code; + if (!getLangOpts().CPlusPlus && !Diags.isIgnored(MixedDeclsCodeID, L)) { // Note that __extension__ can be around a decl. unsigned i = 0; // Skip over all declarations. @@ -425,7 +429,7 @@ StmtResult Sema::ActOnCompoundStmt(SourceLocation L, SourceLocation R, if (i != NumElts) { Decl *D = *cast<DeclStmt>(Elts[i])->decl_begin(); - Diag(D->getLocation(), diag::ext_mixed_decls_code); + Diag(D->getLocation(), MixedDeclsCodeID); } } @@ -869,12 +873,7 @@ StmtResult Sema::ActOnIfStmt(SourceLocation IfLoc, Stmt *thenStmt, SourceLocation ElseLoc, Stmt *elseStmt) { if (Cond.isInvalid()) - Cond = ConditionResult( - *this, nullptr, - MakeFullExpr(new (Context) OpaqueValueExpr(SourceLocation(), - Context.BoolTy, VK_PRValue), - IfLoc), - false); + return StmtError(); bool ConstevalOrNegatedConsteval = StatementKind == IfStatementKind::ConstevalNonNegated || @@ -2468,6 +2467,7 @@ StmtResult Sema::ActOnCXXForRangeStmt(Scope *S, SourceLocation ForLoc, Stmt *First, SourceLocation ColonLoc, Expr *Range, SourceLocation RParenLoc, BuildForRangeKind Kind) { + // FIXME: recover in order to allow the body to be parsed. if (!First) return StmtError(); @@ -3878,7 +3878,8 @@ Sema::ActOnReturnStmt(SourceLocation ReturnLoc, Expr *RetValExp, RetValExp, nullptr, /*RecoverUncorrectedTypos=*/true); if (RetVal.isInvalid()) return StmtError(); - StmtResult R = BuildReturnStmt(ReturnLoc, RetVal.get()); + StmtResult R = + BuildReturnStmt(ReturnLoc, RetVal.get(), /*AllowRecovery=*/true); if (R.isInvalid() || ExprEvalContexts.back().isDiscardedStatementContext()) return R; @@ -3908,7 +3909,8 @@ static bool CheckSimplerImplicitMovesMSVCWorkaround(const Sema &S, return false; } -StmtResult Sema::BuildReturnStmt(SourceLocation ReturnLoc, Expr *RetValExp) { +StmtResult Sema::BuildReturnStmt(SourceLocation ReturnLoc, Expr *RetValExp, + bool AllowRecovery) { // Check for unexpanded parameter packs. if (RetValExp && DiagnoseUnexpandedParameterPack(RetValExp)) return StmtError(); @@ -3985,11 +3987,25 @@ StmtResult Sema::BuildReturnStmt(SourceLocation ReturnLoc, Expr *RetValExp) { // If we've already decided this function is invalid, e.g. because // we saw a `return` whose expression had an error, don't keep // trying to deduce its return type. - if (FD->isInvalidDecl()) - return StmtError(); - if (DeduceFunctionTypeFromReturnExpr(FD, ReturnLoc, RetValExp, AT)) { + // (Some return values may be needlessly wrapped in RecoveryExpr). + if (FD->isInvalidDecl() || + DeduceFunctionTypeFromReturnExpr(FD, ReturnLoc, RetValExp, AT)) { FD->setInvalidDecl(); - return StmtError(); + if (!AllowRecovery) + return StmtError(); + // The deduction failure is diagnosed and marked, try to recover. + if (RetValExp) { + // Wrap return value with a recovery expression of the previous type. + // If no deduction yet, use DependentTy. + auto Recovery = CreateRecoveryExpr( + RetValExp->getBeginLoc(), RetValExp->getEndLoc(), RetValExp, + AT->isDeduced() ? FnRetType : QualType()); + if (Recovery.isInvalid()) + return StmtError(); + RetValExp = Recovery.get(); + } else { + // Nothing to do: a ReturnStmt with no value is fine recovery. + } } else { FnRetType = FD->getReturnType(); } @@ -4002,7 +4018,7 @@ StmtResult Sema::BuildReturnStmt(SourceLocation ReturnLoc, Expr *RetValExp) { ReturnStmt *Result = nullptr; if (FnRetType->isVoidType()) { if (RetValExp) { - if (isa<InitListExpr>(RetValExp)) { + if (auto *ILE = dyn_cast<InitListExpr>(RetValExp)) { // We simply never allow init lists as the return value of void // functions. This is compatible because this was never allowed before, // so there's no legacy code to deal with. @@ -4018,8 +4034,12 @@ StmtResult Sema::BuildReturnStmt(SourceLocation ReturnLoc, Expr *RetValExp) { Diag(ReturnLoc, diag::err_return_init_list) << CurDecl << FunctionKind << RetValExp->getSourceRange(); - // Drop the expression. - RetValExp = nullptr; + // Preserve the initializers in the AST. + RetValExp = AllowRecovery + ? CreateRecoveryExpr(ILE->getLBraceLoc(), + ILE->getRBraceLoc(), ILE->inits()) + .get() + : nullptr; } else if (!RetValExp->isTypeDependent()) { // C99 6.8.6.4p1 (ext_ since GCC warns) unsigned D = diag::ext_return_has_expr; @@ -4116,6 +4136,9 @@ StmtResult Sema::BuildReturnStmt(SourceLocation ReturnLoc, Expr *RetValExp) { InitializedEntity::InitializeResult(ReturnLoc, RetType); ExprResult Res = PerformMoveOrCopyInitialization( Entity, NRInfo, RetValExp, SupressSimplerImplicitMoves); + if (Res.isInvalid() && AllowRecovery) + Res = CreateRecoveryExpr(RetValExp->getBeginLoc(), + RetValExp->getEndLoc(), RetValExp, RetType); if (Res.isInvalid()) { // FIXME: Clean up temporaries here anyway? return StmtError(); |