https://github.com/flash1729 created 
https://github.com/llvm/llvm-project/pull/207942

None

>From ba7b242aeb71a7c1ae0361b48046f023e4711e05 Mon Sep 17 00:00:00 2001
From: flash1729 <[email protected]>
Date: Tue, 7 Jul 2026 14:40:57 +0530
Subject: [PATCH 1/2] [flang-rt] Fix -Wunused-template in time intrinsics and
 test helpers (NFC)

time-intrinsic.cpp implements the timing intrinsics as SFINAE overload sets
(preferred/fallback per platform), so on any given platform some overloads
are intentionally never instantiated and trip -Wunused-template. Mark all
variants [[maybe_unused]].

StoreElement and MakeArray in unittests/Runtime/tools.h are static function
templates in a header, so any test TU that includes it without using all of
them trips the warning. Drop static.

Part of #202945.
---
 flang-rt/lib/runtime/time-intrinsic.cpp | 32 ++++++++++++++++---------
 flang-rt/unittests/Runtime/tools.h      |  6 ++---
 2 files changed, 24 insertions(+), 14 deletions(-)

diff --git a/flang-rt/lib/runtime/time-intrinsic.cpp 
b/flang-rt/lib/runtime/time-intrinsic.cpp
index e72b12663ec4c..89e199a1bc79d 100644
--- a/flang-rt/lib/runtime/time-intrinsic.cpp
+++ b/flang-rt/lib/runtime/time-intrinsic.cpp
@@ -54,7 +54,8 @@ using fallback_implementation = double;
 using preferred_implementation = int;
 
 // This is the fallback implementation, which should work everywhere.
-template <typename Unused = void> double GetCpuTime(fallback_implementation) {
+template <typename Unused = void>
+[[maybe_unused]] double GetCpuTime(fallback_implementation) {
   std::clock_t timestamp{std::clock()};
   if (timestamp != static_cast<std::clock_t>(-1)) {
     return static_cast<double>(timestamp) / CLOCKS_PER_SEC;
@@ -106,7 +107,7 @@ template <typename Unused = void> double 
GetCpuTime(fallback_implementation) {
 // POSIX implementation using clock_gettime. This is only enabled where
 // clock_gettime is available.
 template <typename T = int, typename U = struct timespec>
-double GetCpuTime(preferred_implementation,
+[[maybe_unused]] double GetCpuTime(preferred_implementation,
     // We need some dummy parameters to pass to decltype(clock_gettime).
     T ClockId = 0, U *Timespec = nullptr,
     decltype(clock_gettime(ClockId, Timespec)) *Enabled = nullptr) {
@@ -165,7 +166,8 @@ static count_t ConvertTimevalToCount(int kind, const struct 
timeval &tval) {
 }
 
 template <typename Unused = void>
-static count_t GetSystemClockCount(int kind, fallback_implementation) {
+[[maybe_unused]] static count_t GetSystemClockCount(
+    int kind, fallback_implementation) {
   struct timeval tval;
 
   if (gettimeofday(&tval, /*timezone=*/nullptr) != 0) {
@@ -192,7 +194,8 @@ count_t ConvertTimeSpecToCount(int kind, const struct 
timespec &tspec) {
 #ifndef _AIX
 // More accurate version with nanosecond accuracy
 template <typename Unused = void>
-static count_t GetSystemClockCount(int kind, fallback_implementation) {
+[[maybe_unused]] static count_t GetSystemClockCount(
+    int kind, fallback_implementation) {
   struct timespec tspec;
 
   if (timespec_get(&tspec, TIME_UTC) < 0) {
@@ -208,12 +211,14 @@ static count_t GetSystemClockCount(int kind, 
fallback_implementation) {
 #endif // !NO_TIMESPEC
 
 template <typename Unused = void>
-static count_t GetSystemClockCountRate(int kind, fallback_implementation) {
+[[maybe_unused]] static count_t GetSystemClockCountRate(
+    int kind, fallback_implementation) {
   return kind >= 8 ? NS_PER_SEC : kind >= 2 ? MS_PER_SEC : DS_PER_SEC;
 }
 
 template <typename Unused = void>
-static count_t GetSystemClockCountMax(int kind, fallback_implementation) {
+[[maybe_unused]] static count_t GetSystemClockCountMax(
+    int kind, fallback_implementation) {
   unsigned_count_t maxCount{GetHUGE(kind)};
   return maxCount;
 }
@@ -221,7 +226,8 @@ static count_t GetSystemClockCountMax(int kind, 
fallback_implementation) {
 #ifndef NO_TIMESPEC
 #ifdef CLOCKID_ELAPSED_TIME
 template <typename T = int, typename U = struct timespec>
-static count_t GetSystemClockCount(int kind, preferred_implementation,
+[[maybe_unused]] static count_t GetSystemClockCount(int kind,
+    preferred_implementation,
     // We need some dummy parameters to pass to decltype(clock_gettime).
     T ClockId = 0, U *Timespec = nullptr,
     decltype(clock_gettime(ClockId, Timespec)) *Enabled = nullptr) {
@@ -238,7 +244,8 @@ static count_t GetSystemClockCount(int kind, 
preferred_implementation,
 #endif // CLOCKID_ELAPSED_TIME
 
 template <typename T = int, typename U = struct timespec>
-static count_t GetSystemClockCountRate(int kind, preferred_implementation,
+[[maybe_unused]] static count_t GetSystemClockCountRate(int kind,
+    preferred_implementation,
     // We need some dummy parameters to pass to decltype(clock_gettime).
     T ClockId = 0, U *Timespec = nullptr,
     decltype(clock_gettime(ClockId, Timespec)) *Enabled = nullptr) {
@@ -246,7 +253,8 @@ static count_t GetSystemClockCountRate(int kind, 
preferred_implementation,
 }
 
 template <typename T = int, typename U = struct timespec>
-static count_t GetSystemClockCountMax(int kind, preferred_implementation,
+[[maybe_unused]] static count_t GetSystemClockCountMax(int kind,
+    preferred_implementation,
     // We need some dummy parameters to pass to decltype(clock_gettime).
     T ClockId = 0, U *Timespec = nullptr,
     decltype(clock_gettime(ClockId, Timespec)) *Enabled = nullptr) {
@@ -361,14 +369,16 @@ static std::size_t getUTCOffsetToBuffer(
 // SFINAE helper to return the struct tm.tm_gmtoff which is not a POSIX 
standard
 // field.
 template <int KIND, typename TM = struct tm>
-Fortran::runtime::CppTypeFor<Fortran::common::TypeCategory::Integer, KIND>
+[[maybe_unused]] Fortran::runtime::CppTypeFor<
+    Fortran::common::TypeCategory::Integer, KIND>
 GetGmtOffset(const TM &tm, preferred_implementation,
     decltype(tm.tm_gmtoff) *Enabled = nullptr) {
   // Returns the GMT offset in minutes.
   return tm.tm_gmtoff / 60;
 }
 template <int KIND, typename TM = struct tm>
-Fortran::runtime::CppTypeFor<Fortran::common::TypeCategory::Integer, KIND>
+[[maybe_unused]] Fortran::runtime::CppTypeFor<
+    Fortran::common::TypeCategory::Integer, KIND>
 GetGmtOffset(const TM &tm, fallback_implementation) {
   // tm.tm_gmtoff is not available, there may be platform dependent 
alternatives
   // (such as using timezone from <time.h> when available), but so far just
diff --git a/flang-rt/unittests/Runtime/tools.h 
b/flang-rt/unittests/Runtime/tools.h
index 4ada862df110b..a20b21f4ea760 100644
--- a/flang-rt/unittests/Runtime/tools.h
+++ b/flang-rt/unittests/Runtime/tools.h
@@ -21,19 +21,19 @@
 namespace Fortran::runtime {
 
 template <typename A>
-static void StoreElement(void *p, const A &x, std::size_t bytes) {
+void StoreElement(void *p, const A &x, std::size_t bytes) {
   std::memcpy(p, &x, bytes);
 }
 
 template <typename CHAR>
-static void StoreElement(
+void StoreElement(
     void *p, const std::basic_string<CHAR> &str, std::size_t bytes) {
   ASSERT_LE(bytes, sizeof(CHAR) * str.size());
   std::memcpy(p, str.data(), bytes);
 }
 
 template <TypeCategory CAT, int KIND, typename A>
-static OwningPtr<Descriptor> MakeArray(const std::vector<int> &shape,
+OwningPtr<Descriptor> MakeArray(const std::vector<int> &shape,
     const std::vector<A> &data,
     std::size_t elemLen = CAT == TypeCategory::Complex ? 2 * KIND : KIND) {
   auto rank{static_cast<int>(shape.size())};

>From 6b33038502139b072c413b3ccbe678efbcba0686 Mon Sep 17 00:00:00 2001
From: flash1729 <[email protected]>
Date: Fri, 26 Jun 2026 21:40:49 +0530
Subject: [PATCH 2/2] [Clang] Enable -Wunused-template under -Wall

Uncomment UnusedTemplate in the Unused diagnostic group so -Wunused-template
is part of -Wall. It diagnoses unused function and variable templates with
internal linkage; in a header, such a template gives every translation unit
its own internal-linkage copy, which is a latent ODR violation.

Also update the affected tests (Misc/warning-wall.c and the
warn-func-not-needed.cpp / warn-variable-not-needed.cpp -verify tests) and add
a release note.

Closes #202945.
---
 clang/docs/ReleaseNotes.md                      | 5 +++++
 clang/include/clang/Basic/DiagnosticGroups.td   | 2 +-
 clang/test/Misc/warning-wall.c                  | 2 ++
 clang/test/SemaCXX/warn-func-not-needed.cpp     | 2 +-
 clang/test/SemaCXX/warn-variable-not-needed.cpp | 2 +-
 5 files changed, 10 insertions(+), 3 deletions(-)

diff --git a/clang/docs/ReleaseNotes.md b/clang/docs/ReleaseNotes.md
index cc85604343da9..e81670acb0452 100644
--- a/clang/docs/ReleaseNotes.md
+++ b/clang/docs/ReleaseNotes.md
@@ -563,6 +563,11 @@ latest release, please see the [Clang Web 
Site](https://clang.llvm.org) or the
   allowing it to be disabled independently with `-Wno-unused-but-set-global`.
   (#GH148361)
 
+- `-Wunused-template` is now part of `-Wunused` (which is enabled by `-Wall`).
+  It diagnoses unused function and variable templates with internal linkage,
+  which in a header is a latent ODR hazard. It can be disabled with
+  `-Wno-unused-template`. (#GH202945)
+
 - Added `-Wlifetime-safety` to enable lifetime safety analysis,
   a CFG-based intra-procedural analysis that detects use-after-free and related
   temporal safety bugs. See the
diff --git a/clang/include/clang/Basic/DiagnosticGroups.td 
b/clang/include/clang/Basic/DiagnosticGroups.td
index 73fb97aeeb302..79583534b9bbd 100644
--- a/clang/include/clang/Basic/DiagnosticGroups.td
+++ b/clang/include/clang/Basic/DiagnosticGroups.td
@@ -1369,7 +1369,7 @@ def Conversion
 def Unused : DiagGroup<"unused",
                        [UnusedArgument, UnusedFunction, UnusedLabel,
                         // UnusedParameter, (matches GCC's behavior)
-                        // UnusedTemplate, (clean-up libc++ before enabling)
+                        UnusedTemplate,
                         // UnusedMemberFunction, (clean-up llvm before 
enabling)
                         UnusedPrivateField, UnusedLambdaCapture,
                         UnusedLocalTypedef, UnusedValue, UnusedVariable,
diff --git a/clang/test/Misc/warning-wall.c b/clang/test/Misc/warning-wall.c
index 6d6c4e562400f..ade9cbaace77e 100644
--- a/clang/test/Misc/warning-wall.c
+++ b/clang/test/Misc/warning-wall.c
@@ -73,6 +73,8 @@ CHECK-NEXT:      -Wunused-argument
 CHECK-NEXT:      -Wunused-function
 CHECK-NEXT:        -Wunneeded-internal-declaration
 CHECK-NEXT:      -Wunused-label
+CHECK-NEXT:      -Wunused-template
+CHECK-NEXT:        -Wunneeded-internal-declaration
 CHECK-NEXT:      -Wunused-private-field
 CHECK-NEXT:      -Wunused-lambda-capture
 CHECK-NEXT:      -Wunused-local-typedef
diff --git a/clang/test/SemaCXX/warn-func-not-needed.cpp 
b/clang/test/SemaCXX/warn-func-not-needed.cpp
index cb3cae4cd6c76..74438543c43b7 100644
--- a/clang/test/SemaCXX/warn-func-not-needed.cpp
+++ b/clang/test/SemaCXX/warn-func-not-needed.cpp
@@ -10,7 +10,7 @@ void foo() {
 }
 
 namespace test1_template {
-template <typename T> static void f() {}
+template <typename T> static void f() {} // expected-warning {{unused function 
template}}
 template <> void f<int>() {} // expected-warning {{function 'f<int>' is not 
needed and will not be emitted}}
 template <typename T>
 void foo() {
diff --git a/clang/test/SemaCXX/warn-variable-not-needed.cpp 
b/clang/test/SemaCXX/warn-variable-not-needed.cpp
index 272c8998d15c0..d234e9140e3fd 100644
--- a/clang/test/SemaCXX/warn-variable-not-needed.cpp
+++ b/clang/test/SemaCXX/warn-variable-not-needed.cpp
@@ -4,7 +4,7 @@ namespace test1 {
   static int abc = 42; // expected-warning {{variable 'abc' is not needed and 
will not be emitted}}
 
   namespace {
-  template <typename T> int abc_template = 0;
+  template <typename T> int abc_template = 0; // expected-warning {{unused 
variable template}}
   template <> int abc_template<int> = 0; // expected-warning {{variable 
'abc_template<int>' is not needed and will not be emitted}}
   }                                      // namespace
   template <typename T>

_______________________________________________
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to