[clang] [clang] Suppress -Wunneeded-internal-declaration for referenced constexpr functions (PR #196593)
via cfe-commits
cfe-commits at lists.llvm.org
Fri May 8 10:43:20 PDT 2026
llvmorg-github-actions[bot] wrote:
<!--LLVM PR SUMMARY COMMENT-->
@llvm/pr-subscribers-clang-static-analyzer-1
Author: Vineet Agarwal (PlutoDog95)
<details>
<summary>Changes</summary>
This patch suppresses `-Wunneeded-internal-declaration` for referenced `constexpr` functions used during constant evaluation.
`constexpr` variables already receive similar handling in `ShouldRemoveFromUnused()` because they may participate in constant expression evaluation without being odr-used. Referenced `constexpr` functions currently lack equivalent handling, which can produce false positives in cases such as dependent return type evaluation.
Add analogous handling for referenced `constexpr` functions and include a regression test.
Fixes #<!-- -->196564
---
Full diff: https://github.com/llvm/llvm-project/pull/196593.diff
5 Files Affected:
- (modified) clang/lib/Sema/Sema.cpp (+5)
- (modified) clang/lib/StaticAnalyzer/Checkers/EnumCastOutOfRangeChecker.cpp (+7-3)
- (added) clang/test/Analysis/Inputs/enum-system-header.h (+8)
- (added) clang/test/Analysis/enum-cast-out-of-range-system-header.cpp (+12)
- (added) clang/test/SemaCXX/warn-unused-constexpr-function.cpp (+24)
``````````diff
diff --git a/clang/lib/Sema/Sema.cpp b/clang/lib/Sema/Sema.cpp
index 8a68f2f19bf3d..9c8a84668454a 100644
--- a/clang/lib/Sema/Sema.cpp
+++ b/clang/lib/Sema/Sema.cpp
@@ -891,6 +891,11 @@ static bool ShouldRemoveFromUnused(Sema *SemaRef, const DeclaratorDecl *D) {
return true;
if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(D)) {
+ // If a constexpr function is referenced for constant evaluation,
+ // don't warn even if it is not odr-used.
+ if (FD->isReferenced() && FD->isConstexpr())
+ return true;
+
// If this is a function template and none of its specializations is used,
// we should warn.
if (FunctionTemplateDecl *Template = FD->getDescribedFunctionTemplate())
diff --git a/clang/lib/StaticAnalyzer/Checkers/EnumCastOutOfRangeChecker.cpp b/clang/lib/StaticAnalyzer/Checkers/EnumCastOutOfRangeChecker.cpp
index 76a1470aaac44..32a73a1d5c44f 100644
--- a/clang/lib/StaticAnalyzer/Checkers/EnumCastOutOfRangeChecker.cpp
+++ b/clang/lib/StaticAnalyzer/Checkers/EnumCastOutOfRangeChecker.cpp
@@ -85,8 +85,13 @@ void EnumCastOutOfRangeChecker::reportWarning(CheckerContext &C,
const CastExpr *CE,
const EnumDecl *E) const {
assert(E && "valid EnumDecl* is expected");
- if (const ExplodedNode *N = C.generateNonFatalErrorNode()) {
- std::string ValueStr = "", NameStr = "the enum";
+ auto &SM = C.getSourceManager();
+
+ if (SM.isInSystemHeader(CE->getExprLoc()))
+ return;
+
+ if (const ExplodedNode *N = C.generateNonFatalErrorNode()) {
+ std::string ValueStr = "", NameStr = "the enum";
// Try to add details to the message:
const auto ConcreteValue =
@@ -101,7 +106,6 @@ void EnumCastOutOfRangeChecker::reportWarning(CheckerContext &C,
std::string Msg = formatv("The value{0} provided to the cast expression is "
"not in the valid range of values for {1}",
ValueStr, NameStr);
-
auto BR = std::make_unique<PathSensitiveBugReport>(EnumValueCastOutOfRange,
Msg, N);
bugreporter::trackExpressionValue(N, CE->getSubExpr(), *BR);
diff --git a/clang/test/Analysis/Inputs/enum-system-header.h b/clang/test/Analysis/Inputs/enum-system-header.h
new file mode 100644
index 0000000000000..53c6bdac24093
--- /dev/null
+++ b/clang/test/Analysis/Inputs/enum-system-header.h
@@ -0,0 +1,8 @@
+enum MyEnum {
+ A = 1,
+ B = 2
+};
+
+static inline MyEnum bad_cast(int x) {
+ return (MyEnum)x;
+}
diff --git a/clang/test/Analysis/enum-cast-out-of-range-system-header.cpp b/clang/test/Analysis/enum-cast-out-of-range-system-header.cpp
new file mode 100644
index 0000000000000..073cde677bcd1
--- /dev/null
+++ b/clang/test/Analysis/enum-cast-out-of-range-system-header.cpp
@@ -0,0 +1,12 @@
+// RUN: %clang_analyze_cc1 \
+// RUN: -analyzer-checker=core,optin.core.EnumCastOutOfRange \
+// RUN: -isystem %S/Inputs \
+// RUN: -verify %s
+
+#include "enum-system-header.h"
+
+void test() {
+ bad_cast(100);
+}
+
+// expected-no-diagnostics
diff --git a/clang/test/SemaCXX/warn-unused-constexpr-function.cpp b/clang/test/SemaCXX/warn-unused-constexpr-function.cpp
new file mode 100644
index 0000000000000..329cfe954c1a6
--- /dev/null
+++ b/clang/test/SemaCXX/warn-unused-constexpr-function.cpp
@@ -0,0 +1,24 @@
+// RUN: %clang_cc1 -std=c++14 -Wunused-function -fsyntax-only %s
+
+static constexpr bool returnInt(int) { return true; }
+
+template <bool B>
+struct select;
+
+template <>
+struct select<true> {
+ using type = int;
+};
+
+template <>
+struct select<false> {
+ using type = float;
+};
+
+template <typename T>
+typename select<returnInt(T{})>::type make() {
+ return T{};
+}
+
+int makeInt() { return make<int>(); }
+float makeFloat() { return make<float>(); }
``````````
</details>
https://github.com/llvm/llvm-project/pull/196593
More information about the cfe-commits
mailing list