summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorYong He <yonghe@outlook.com>2023-06-29 13:11:49 -0700
committerGitHub <noreply@github.com>2023-06-29 13:11:49 -0700
commitdccc9091c8f8f0911c79f7f6662c70c627249997 (patch)
treea043e9143c947b3ef36a19a84af3ea5497e118ca
parentb45e5aa07cf5e2e0bd23cf4c14bb40104b0b641c (diff)
Warn on semicolon after `if`. (#2948)
* Warn on semicolon after `if`. * add test result --------- Co-authored-by: Yong He <yhe@nvidia.com>
-rw-r--r--source/slang/slang-diagnostic-defs.h2
-rw-r--r--source/slang/slang-parser.cpp15
-rw-r--r--tests/diagnostics/if-empty-body.slang11
-rw-r--r--tests/diagnostics/if-empty-body.slang.expected8
4 files changed, 32 insertions, 4 deletions
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<IfStmt>(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<EmptyStmt>();
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 = {
+}