diff options
Diffstat (limited to 'clang/lib/Sema/SemaStmt.cpp')
-rw-r--r-- | clang/lib/Sema/SemaStmt.cpp | 53 |
1 files changed, 38 insertions, 15 deletions
diff --git a/clang/lib/Sema/SemaStmt.cpp b/clang/lib/Sema/SemaStmt.cpp index 0adfb948009..b47e3d29d17 100644 --- a/clang/lib/Sema/SemaStmt.cpp +++ b/clang/lib/Sema/SemaStmt.cpp @@ -225,6 +225,18 @@ void Sema::DiagnoseUnusedExprResult(const Stmt *S) { DiagRuntimeBehavior(Loc, 0, PDiag(DiagID) << R1 << R2); } +void Sema::ActOnStartOfCompoundStmt() { + PushCompoundScope(); +} + +void Sema::ActOnFinishOfCompoundStmt() { + PopCompoundScope(); +} + +sema::CompoundScopeInfo &Sema::getCurCompoundScope() const { + return getCurFunction()->CompoundScopes.back(); +} + StmtResult Sema::ActOnCompoundStmt(SourceLocation L, SourceLocation R, MultiStmtArg elts, bool isStmtExpr) { @@ -257,6 +269,15 @@ Sema::ActOnCompoundStmt(SourceLocation L, SourceLocation R, DiagnoseUnusedExprResult(Elts[i]); } + // Check for suspicious empty body (null statement) in `for' and `while' + // statements. Don't do anything for template instantiations, this just adds + // noise. + if (NumElts != 0 && !CurrentInstantiationScope && + getCurCompoundScope().HasEmptyLoopBodies) { + for (unsigned i = 0; i != NumElts - 1; ++i) + DiagnoseEmptyLoopBody(Elts[i], Elts[i + 1]); + } + return Owned(new (Context) CompoundStmt(Context, Elts, NumElts, L, R)); } @@ -355,21 +376,9 @@ Sema::ActOnIfStmt(SourceLocation IfLoc, FullExprArg CondVal, Decl *CondVar, DiagnoseUnusedExprResult(thenStmt); - // Warn if the if block has a null body without an else value. - // this helps prevent bugs due to typos, such as - // if (condition); - // do_stuff(); - // if (!elseStmt) { - if (NullStmt* stmt = dyn_cast<NullStmt>(thenStmt)) - // But do not warn if the body is a macro that expands to nothing, e.g: - // - // #define CALL(x) - // if (condition) - // CALL(0); - // - if (!stmt->hasLeadingEmptyMacro()) - Diag(stmt->getSemiLoc(), diag::warn_empty_if_body); + DiagnoseEmptyStmtBody(ConditionExpr->getLocEnd(), thenStmt, + diag::warn_empty_if_body); } DiagnoseUnusedExprResult(elseStmt); @@ -957,6 +966,9 @@ Sema::ActOnFinishSwitchStmt(SourceLocation SwitchLoc, Stmt *Switch, } } + DiagnoseEmptyStmtBody(CondExpr->getLocEnd(), BodyStmt, + diag::warn_empty_switch_body); + // FIXME: If the case list was broken is some way, we don't have a good system // to patch it up. Instead, just return the whole substmt as broken. if (CaseListIsErroneous) @@ -983,6 +995,9 @@ Sema::ActOnWhileStmt(SourceLocation WhileLoc, FullExprArg Cond, DiagnoseUnusedExprResult(Body); + if (isa<NullStmt>(Body)) + getCurCompoundScope().setHasEmptyLoopBodies(); + return Owned(new (Context) WhileStmt(Context, ConditionVar, ConditionExpr, Body, WhileLoc)); } @@ -1046,6 +1061,9 @@ Sema::ActOnForStmt(SourceLocation ForLoc, SourceLocation LParenLoc, DiagnoseUnusedExprResult(Third); DiagnoseUnusedExprResult(Body); + if (isa<NullStmt>(Body)) + getCurCompoundScope().setHasEmptyLoopBodies(); + return Owned(new (Context) ForStmt(Context, First, SecondResult.take(), ConditionVar, Third, Body, ForLoc, LParenLoc, @@ -1587,7 +1605,12 @@ StmtResult Sema::FinishCXXForRangeStmt(Stmt *S, Stmt *B) { if (!S || !B) return StmtError(); - cast<CXXForRangeStmt>(S)->setBody(B); + CXXForRangeStmt *ForStmt = cast<CXXForRangeStmt>(S); + ForStmt->setBody(B); + + DiagnoseEmptyStmtBody(ForStmt->getRParenLoc(), B, + diag::warn_empty_range_based_for_body); + return S; } |