clang: Tweak behaviour of warn_empty_while_body and warn_empty_if_body

Use the if/while statement right paren location instead of the end of the
condition expression to determine if the semicolon is on its own line, for the
purpose of not warning about code like this:

    while (foo())
      ;

Using the condition location meant that we would also not report a warning on
code like this:

    while (MACRO(a,
                 b));
      body();

The right paren loc wasn't stored in the AST or passed into Sema::ActOnIfStmt
when this logic was first written.

Reviewed By: rnk, gribozavr2

Differential Revision: https://reviews.llvm.org/D128406
This commit is contained in:
Dmitri Gribenko 2022-06-24 02:26:07 +02:00
parent 8b987ca5e3
commit 37b881aa0b
4 changed files with 13 additions and 5 deletions
clang
lib/Sema
test
CXX/stmt.stmt/stmt.select
SemaCXX

View File

@ -16673,7 +16673,7 @@ void Sema::DiagnoseEmptyLoopBody(const Stmt *S,
Body = FS->getBody();
DiagID = diag::warn_empty_for_body;
} else if (const WhileStmt *WS = dyn_cast<WhileStmt>(S)) {
StmtLoc = WS->getCond()->getSourceRange().getEnd();
StmtLoc = WS->getRParenLoc();
Body = WS->getBody();
DiagID = diag::warn_empty_while_body;
} else

View File

@ -888,8 +888,7 @@ StmtResult Sema::ActOnIfStmt(SourceLocation IfLoc,
CommaVisitor(*this).Visit(CondExpr);
if (!ConstevalOrNegatedConsteval && !elseStmt)
DiagnoseEmptyStmtBody(CondExpr->getEndLoc(), thenStmt,
diag::warn_empty_if_body);
DiagnoseEmptyStmtBody(RParenLoc, thenStmt, diag::warn_empty_if_body);
if (ConstevalOrNegatedConsteval ||
StatementKind == IfStatementKind::Constexpr) {

View File

@ -63,8 +63,6 @@ void whileInitStatement() {
// expected-note@-1 {{to match this '('}}
// expected-error@-2 {{expected ';' after expression}}
// expected-error@-3 {{expected expression}}
// expected-warning@-4 {{while loop has empty body}}
// expected-note@-5 {{put the semicolon on a separate line to silence this warning}}
}
// TODO: This is needed because clang can't seem to diagnose invalid syntax after the

View File

@ -6,6 +6,8 @@ int c();
#define MACRO_A 0
#define AND(x, y) ((x) && (y))
void test1(int x, int y) {
while(true) {
if (x); // expected-warning {{if statement has empty body}} expected-note{{put the semicolon on a separate line to silence this warning}}
@ -15,6 +17,15 @@ void test1(int x, int y) {
if (x == MACRO_A); // expected-warning {{if statement has empty body}} expected-note{{put the semicolon on a separate line to silence this warning}}
if (MACRO_A == x); // expected-warning {{if statement has empty body}} expected-note{{put the semicolon on a separate line to silence this warning}}
// Check that we handle the case where the condition comes from a macro
// expansion over multiple lines.
if (AND(b(),
c())); // expected-warning {{if statement has empty body}} expected-note{{put the semicolon on a separate line to silence this warning}}
while (AND(b(),
c())); // expected-warning{{while loop has empty body}} expected-note{{put the semicolon on a separate line to silence this warning}}
a(0);
int i;
// PR11329
for (i = 0; i < x; i++); { // expected-warning{{for loop has empty body}} expected-note{{put the semicolon on a separate line to silence this warning}}