From dccc9091c8f8f0911c79f7f6662c70c627249997 Mon Sep 17 00:00:00 2001 From: Yong He Date: Thu, 29 Jun 2023 13:11:49 -0700 Subject: Warn on semicolon after `if`. (#2948) * Warn on semicolon after `if`. * add test result --------- Co-authored-by: Yong He --- source/slang/slang-diagnostic-defs.h | 2 ++ source/slang/slang-parser.cpp | 15 +++++++++++---- tests/diagnostics/if-empty-body.slang | 11 +++++++++++ tests/diagnostics/if-empty-body.slang.expected | 8 ++++++++ 4 files changed, 32 insertions(+), 4 deletions(-) create mode 100644 tests/diagnostics/if-empty-body.slang create mode 100644 tests/diagnostics/if-empty-body.slang.expected diff --git a/source/slang/slang-diagnostic-defs.h b/source/slang/slang-diagnostic-defs.h index 29ce30323..c01a6ddf1 100644 --- a/source/slang/slang-diagnostic-defs.h +++ b/source/slang/slang-diagnostic-defs.h @@ -234,6 +234,8 @@ DIAGNOSTIC(20013, Error, invalidCUDASMVersion, "Expecting CUDA SM version as eit DIAGNOSTIC(20014, Error, classIsReservedKeyword, "'class' is a reserved keyword in this context; use 'struct' instead.") +DIAGNOSTIC(20101, Warning, unintendedEmptyStatement, "potentially unintended empty statement at this location; use {} instead.") + // // 3xxxx - Semantic analysis // diff --git a/source/slang/slang-parser.cpp b/source/slang/slang-parser.cpp index d606698a1..dcf835234 100644 --- a/source/slang/slang-parser.cpp +++ b/source/slang/slang-parser.cpp @@ -184,7 +184,7 @@ namespace Slang void parseSourceFile(ModuleDecl* program); Decl* ParseStruct(); ClassDecl* ParseClass(); - Stmt* ParseStatement(); + Stmt* ParseStatement(Stmt* parentStmt = nullptr); Stmt* parseBlockStatement(); Stmt* parseLabelStatement(); DeclStmt* parseVarDeclrStatement(Modifiers modifiers); @@ -4438,7 +4438,7 @@ namespace Slang } } - Stmt* Parser::ParseStatement() + Stmt* Parser::ParseStatement(Stmt* parentStmt) { auto modifiers = ParseModifiers(this); @@ -4575,6 +4575,13 @@ namespace Slang } else if (LookAheadToken(TokenType::Semicolon)) { + if (as(parentStmt)) + { + // An empty statement after an `if` is probably a mistake, + // so we will diagnose it as such. + // + sink->diagnose(tokenReader.peekLoc(), Diagnostics::unintendedEmptyStatement); + } statement = astBuilder->create(); FillPosition(statement); ReadToken(TokenType::Semicolon); @@ -4690,11 +4697,11 @@ namespace Slang ReadToken(TokenType::LParent); ifStatement->predicate = ParseExpression(); ReadToken(TokenType::RParent); - ifStatement->positiveStatement = ParseStatement(); + ifStatement->positiveStatement = ParseStatement(ifStatement); if (LookAheadToken("else")) { ReadToken("else"); - ifStatement->negativeStatement = ParseStatement(); + ifStatement->negativeStatement = ParseStatement(ifStatement); } return ifStatement; } diff --git a/tests/diagnostics/if-empty-body.slang b/tests/diagnostics/if-empty-body.slang new file mode 100644 index 000000000..de8983352 --- /dev/null +++ b/tests/diagnostics/if-empty-body.slang @@ -0,0 +1,11 @@ +//DIAGNOSTIC_TEST(windows):SIMPLE: + +// Test that use of empty statement after an `if` leads to an warning. + +struct S {} + +void test() +{ + if (1+1==2); + return; +} \ No newline at end of file diff --git a/tests/diagnostics/if-empty-body.slang.expected b/tests/diagnostics/if-empty-body.slang.expected new file mode 100644 index 000000000..30915e39d --- /dev/null +++ b/tests/diagnostics/if-empty-body.slang.expected @@ -0,0 +1,8 @@ +result code = 0 +standard error = { +tests/diagnostics/if-empty-body.slang(9): warning 20101: potentially unintended empty statement at this location; use {} instead. + if (1+1==2); + ^ +} +standard output = { +} -- cgit v1.2.3