[clang] [clang-repl] Suppress [[nodiscard]] warnings for REPL printed express (PR #178661)
via cfe-commits
cfe-commits at lists.llvm.org
Thu Jan 29 20:53:50 PST 2026
https://github.com/bala-bhargav updated https://github.com/llvm/llvm-project/pull/178661
>From 1d714597e5ddf4323e10fa7a2a7d832139518bab Mon Sep 17 00:00:00 2001
From: bhargav <penugondabalabharghav at gmail.com>
Date: Thu, 29 Jan 2026 22:20:31 +0530
Subject: [PATCH 1/2] [clang-repl] Suppress [[nodiscard]] warnings for REPL
printed expressions In clang-repl, expressions without semicolons have their
values printed by the value printing mechanism. Since the result is used (for
printing), we should not emit [[nodiscard]] warnings for these expressions.
This fixes the false positive warning when evaluating expressions like
v.size() in the REPL.
[clang-repl] Suppress [[nodiscard]] warnings for printed expressions
Fixes #178595
In clang-repl, expressions typed without a semicolon have their values
printed. This means the return value is actually being used, not discarded.
This fix suppresses [[nodiscard]] warnings for expressions that will be
printed, while still emitting warnings for expressions with semicolons
where the value is truly discarded#
---
clang/lib/Parse/ParseDecl.cpp | 4 ++++
clang/lib/Sema/SemaStmt.cpp | 9 +++++++++
clang/test/Interpreter/nodiscard.cpp | 25 +++++++++++++++++++++++++
3 files changed, 38 insertions(+)
create mode 100644 clang/test/Interpreter/nodiscard.cpp
diff --git a/clang/lib/Parse/ParseDecl.cpp b/clang/lib/Parse/ParseDecl.cpp
index df9e3878bffc0..59280f5ad8d29 100644
--- a/clang/lib/Parse/ParseDecl.cpp
+++ b/clang/lib/Parse/ParseDecl.cpp
@@ -5721,6 +5721,10 @@ Parser::DeclGroupPtrTy Parser::ParseTopLevelStmtDecl() {
Tok.getAnnotationValue() != nullptr) {
ConsumeAnnotationToken();
TLSD->setSemiMissing();
+ } else if (R.isUsable()) {
+ // Semicolon is present, so the value is being discarded.
+ // Re-diagnose [[nodiscard]] warnings that were suppressed during parsing.
+ Actions.DiagnoseUnusedExprResult(R.get(), diag::warn_unused_expr);
}
SmallVector<Decl *, 2> DeclsInGroup;
diff --git a/clang/lib/Sema/SemaStmt.cpp b/clang/lib/Sema/SemaStmt.cpp
index 5ab10fdfc7b74..4267f1a360d4a 100644
--- a/clang/lib/Sema/SemaStmt.cpp
+++ b/clang/lib/Sema/SemaStmt.cpp
@@ -239,6 +239,15 @@ void DiagnoseUnused(Sema &S, const Expr *E, std::optional<unsigned> DiagID) {
if (S.isUnevaluatedContext())
return;
+ // In incremental processing mode (REPL), expressions inside TopLevelStmtDecl
+ // without a semicolon will have their values printed by the value printing
+ // mechanism. The result is therefore "used" and we should not warn about
+ // [[nodiscard]] attributes.
+ if (S.PP.isIncrementalProcessingEnabled()) {
+ if (isa<TopLevelStmtDecl>(S.CurContext))
+ return;
+ }
+
SourceLocation ExprLoc = E->IgnoreParenImpCasts()->getExprLoc();
// In most cases, we don't want to warn if the expression is written in a
// macro body, or if the macro comes from a system header. If the offending
diff --git a/clang/test/Interpreter/nodiscard.cpp b/clang/test/Interpreter/nodiscard.cpp
new file mode 100644
index 0000000000000..154e8ae39f618
--- /dev/null
+++ b/clang/test/Interpreter/nodiscard.cpp
@@ -0,0 +1,25 @@
+// REQUIRES: host-supports-jit
+// RUN: cat %s | clang-repl 2>&1 | FileCheck %s
+
+// Test that [[nodiscard]] warnings are suppressed for REPL top-level
+// expressions that will have their values printed (no semicolon),
+// but are still emitted when the value is actually discarded (with semicolon).
+
+extern "C" int printf(const char*,...);
+
+[[nodiscard]] int getValue() { return 42; }
+
+// Negative test: Warning when value is discarded (with semicolon)
+getValue();
+// CHECK: warning: ignoring return value of function declared with 'nodiscard' attribute
+
+// Positive test: No warning when expression value is printed (no semicolon)
+getValue()
+// CHECK: (int) 42
+
+// Verify assignment doesn't warn
+int x = getValue();
+printf("x = %d\n", x);
+// CHECK: x = 42
+
+%quit
>From e022d15f052e29f0029e97708acf056d7e21dcd5 Mon Sep 17 00:00:00 2001
From: bhargav <penugondabalabharghav at gmail.com>
Date: Fri, 30 Jan 2026 10:09:09 +0530
Subject: [PATCH 2/2] [clang-repl] Fix [[nodiscard]] warning handling based on
reviewer feedback - Remove special case from SemaStmt.cpp as suggested by
reviewer - Suppress warn_unused_result in Interpreter.cpp during parsing -
Re-enable and diagnose [[nodiscard]] warnings in ParseDecl.cpp when semicolon
is present Fixes #178595
---
clang/lib/Interpreter/Interpreter.cpp | 6 ++++++
clang/lib/Parse/ParseDecl.cpp | 5 ++++-
clang/lib/Sema/SemaStmt.cpp | 9 ---------
3 files changed, 10 insertions(+), 10 deletions(-)
diff --git a/clang/lib/Interpreter/Interpreter.cpp b/clang/lib/Interpreter/Interpreter.cpp
index 9c94cfa5ee381..3eef722541eb8 100644
--- a/clang/lib/Interpreter/Interpreter.cpp
+++ b/clang/lib/Interpreter/Interpreter.cpp
@@ -469,6 +469,12 @@ Interpreter::Parse(llvm::StringRef Code) {
// printing could cause it.
getCompilerInstance()->getDiagnostics().setSeverity(
clang::diag::warn_unused_expr, diag::Severity::Ignored, SourceLocation());
+ // Suppress [[nodiscard]] warnings during parsing since we don't know yet
+ // if the expression has a missing semicolon (value printed) or not.
+ // If the value is printed, it's considered "used" so no warning is needed.
+ getCompilerInstance()->getDiagnostics().setSeverity(
+ clang::diag::warn_unused_result, diag::Severity::Ignored,
+ SourceLocation());
llvm::Expected<TranslationUnitDecl *> TuOrErr = IncrParser->Parse(Code);
if (!TuOrErr)
diff --git a/clang/lib/Parse/ParseDecl.cpp b/clang/lib/Parse/ParseDecl.cpp
index 59280f5ad8d29..70381195e33a3 100644
--- a/clang/lib/Parse/ParseDecl.cpp
+++ b/clang/lib/Parse/ParseDecl.cpp
@@ -5721,9 +5721,12 @@ Parser::DeclGroupPtrTy Parser::ParseTopLevelStmtDecl() {
Tok.getAnnotationValue() != nullptr) {
ConsumeAnnotationToken();
TLSD->setSemiMissing();
+ // Expression result will be printed, so it's "used" - no warning needed.
} else if (R.isUsable()) {
// Semicolon is present, so the value is being discarded.
- // Re-diagnose [[nodiscard]] warnings that were suppressed during parsing.
+ // Re-enable [[nodiscard]] warning and diagnose.
+ PP.getDiagnostics().setSeverity(diag::warn_unused_result,
+ diag::Severity::Warning, SourceLocation());
Actions.DiagnoseUnusedExprResult(R.get(), diag::warn_unused_expr);
}
diff --git a/clang/lib/Sema/SemaStmt.cpp b/clang/lib/Sema/SemaStmt.cpp
index 4267f1a360d4a..5ab10fdfc7b74 100644
--- a/clang/lib/Sema/SemaStmt.cpp
+++ b/clang/lib/Sema/SemaStmt.cpp
@@ -239,15 +239,6 @@ void DiagnoseUnused(Sema &S, const Expr *E, std::optional<unsigned> DiagID) {
if (S.isUnevaluatedContext())
return;
- // In incremental processing mode (REPL), expressions inside TopLevelStmtDecl
- // without a semicolon will have their values printed by the value printing
- // mechanism. The result is therefore "used" and we should not warn about
- // [[nodiscard]] attributes.
- if (S.PP.isIncrementalProcessingEnabled()) {
- if (isa<TopLevelStmtDecl>(S.CurContext))
- return;
- }
-
SourceLocation ExprLoc = E->IgnoreParenImpCasts()->getExprLoc();
// In most cases, we don't want to warn if the expression is written in a
// macro body, or if the macro comes from a system header. If the offending
More information about the cfe-commits
mailing list