ilya-biryukov created this revision. Do not show it when `if` or `else` come from macros. E.g.,
#define USED(A) if (A); else #define SOME_IF(A) if (A) void test() { // No warnings are shown in those cases now. USED(0); SOME_IF(0); } https://reviews.llvm.org/D40185 Files: include/clang/Sema/Sema.h lib/Parse/ParseStmt.cpp lib/Sema/SemaChecking.cpp lib/Sema/SemaStmt.cpp test/SemaCXX/warn-empty-body.cpp Index: test/SemaCXX/warn-empty-body.cpp =================================================================== --- test/SemaCXX/warn-empty-body.cpp +++ test/SemaCXX/warn-empty-body.cpp @@ -301,3 +301,14 @@ if (x) IDENTITY(); // no-warning } +#define SOME_IF(A) if (A) +#define IF_ELSE(A) if (A); else + + +void test_macros() { + SOME_IF(0); + IF_ELSE(0); + + IDENTITY(if (0);) // expected-warning{{if statement has empty body}} expected-note{{separate line}} + IDENTITY(if (0); else;) // expected-warning{{else clause has empty body}} expected-note{{separate line}}} +} Index: lib/Sema/SemaStmt.cpp =================================================================== --- lib/Sema/SemaStmt.cpp +++ lib/Sema/SemaStmt.cpp @@ -530,8 +530,7 @@ if (elseStmt) DiagnoseEmptyStmtBody(ElseLoc, elseStmt, diag::warn_empty_else_body); else - DiagnoseEmptyStmtBody(CondExpr->getLocEnd(), thenStmt, - diag::warn_empty_if_body); + DiagnoseEmptyStmtBody(Cond.RParenLoc, thenStmt, diag::warn_empty_if_body); return BuildIfStmt(IfLoc, IsConstexpr, InitStmt, Cond, thenStmt, ElseLoc, elseStmt); Index: lib/Sema/SemaChecking.cpp =================================================================== --- lib/Sema/SemaChecking.cpp +++ lib/Sema/SemaChecking.cpp @@ -11815,7 +11815,7 @@ // Get line numbers of statement and body. bool StmtLineInvalid; - unsigned StmtLine = SourceMgr.getPresumedLineNumber(StmtLoc, + unsigned StmtLine = SourceMgr.getSpellingLineNumber(StmtLoc, &StmtLineInvalid); if (StmtLineInvalid) return false; Index: lib/Parse/ParseStmt.cpp =================================================================== --- lib/Parse/ParseStmt.cpp +++ lib/Parse/ParseStmt.cpp @@ -1101,6 +1101,7 @@ // Otherwise the condition is valid or the rparen is present. T.consumeClose(); + Cond.setRParLoc(T.getCloseLocation()); // Check for extraneous ')'s to catch things like "if (foo())) {". We know // that all callers are looking for a statement after the condition, so ")" Index: include/clang/Sema/Sema.h =================================================================== --- include/clang/Sema/Sema.h +++ include/clang/Sema/Sema.h @@ -9690,6 +9690,7 @@ class ConditionResult { Decl *ConditionVar; FullExprArg Condition; + SourceLocation RParenLoc; bool Invalid; bool HasKnownValue; bool KnownValue; @@ -9713,6 +9714,11 @@ return std::make_pair(cast_or_null<VarDecl>(ConditionVar), Condition.get()); } + + void setRParLoc(SourceLocation Loc) { + RParenLoc = Loc; + } + llvm::Optional<bool> getKnownValue() const { if (!HasKnownValue) return None;
Index: test/SemaCXX/warn-empty-body.cpp =================================================================== --- test/SemaCXX/warn-empty-body.cpp +++ test/SemaCXX/warn-empty-body.cpp @@ -301,3 +301,14 @@ if (x) IDENTITY(); // no-warning } +#define SOME_IF(A) if (A) +#define IF_ELSE(A) if (A); else + + +void test_macros() { + SOME_IF(0); + IF_ELSE(0); + + IDENTITY(if (0);) // expected-warning{{if statement has empty body}} expected-note{{separate line}} + IDENTITY(if (0); else;) // expected-warning{{else clause has empty body}} expected-note{{separate line}}} +} Index: lib/Sema/SemaStmt.cpp =================================================================== --- lib/Sema/SemaStmt.cpp +++ lib/Sema/SemaStmt.cpp @@ -530,8 +530,7 @@ if (elseStmt) DiagnoseEmptyStmtBody(ElseLoc, elseStmt, diag::warn_empty_else_body); else - DiagnoseEmptyStmtBody(CondExpr->getLocEnd(), thenStmt, - diag::warn_empty_if_body); + DiagnoseEmptyStmtBody(Cond.RParenLoc, thenStmt, diag::warn_empty_if_body); return BuildIfStmt(IfLoc, IsConstexpr, InitStmt, Cond, thenStmt, ElseLoc, elseStmt); Index: lib/Sema/SemaChecking.cpp =================================================================== --- lib/Sema/SemaChecking.cpp +++ lib/Sema/SemaChecking.cpp @@ -11815,7 +11815,7 @@ // Get line numbers of statement and body. bool StmtLineInvalid; - unsigned StmtLine = SourceMgr.getPresumedLineNumber(StmtLoc, + unsigned StmtLine = SourceMgr.getSpellingLineNumber(StmtLoc, &StmtLineInvalid); if (StmtLineInvalid) return false; Index: lib/Parse/ParseStmt.cpp =================================================================== --- lib/Parse/ParseStmt.cpp +++ lib/Parse/ParseStmt.cpp @@ -1101,6 +1101,7 @@ // Otherwise the condition is valid or the rparen is present. T.consumeClose(); + Cond.setRParLoc(T.getCloseLocation()); // Check for extraneous ')'s to catch things like "if (foo())) {". We know // that all callers are looking for a statement after the condition, so ")" Index: include/clang/Sema/Sema.h =================================================================== --- include/clang/Sema/Sema.h +++ include/clang/Sema/Sema.h @@ -9690,6 +9690,7 @@ class ConditionResult { Decl *ConditionVar; FullExprArg Condition; + SourceLocation RParenLoc; bool Invalid; bool HasKnownValue; bool KnownValue; @@ -9713,6 +9714,11 @@ return std::make_pair(cast_or_null<VarDecl>(ConditionVar), Condition.get()); } + + void setRParLoc(SourceLocation Loc) { + RParenLoc = Loc; + } + llvm::Optional<bool> getKnownValue() const { if (!HasKnownValue) return None;
_______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits