[llvm-branch-commits] [clang] 087cb2e - [clang] Avoid inheriting [[noreturn]] in explicit function template specializations (#150003)
Tobias Hieta via llvm-branch-commits
llvm-branch-commits at lists.llvm.org
Tue Aug 5 01:55:22 PDT 2025
Author: Samarth Narang
Date: 2025-08-05T10:54:39+02:00
New Revision: 087cb2e91c5b276531b617781974e76145b7da0f
URL: https://github.com/llvm/llvm-project/commit/087cb2e91c5b276531b617781974e76145b7da0f
DIFF: https://github.com/llvm/llvm-project/commit/087cb2e91c5b276531b617781974e76145b7da0f.diff
LOG: [clang] Avoid inheriting [[noreturn]] in explicit function template specializations (#150003)
This patch fixes incorrect behavior in Clang where [[noreturn]] (either
spelled or inferred) was being inherited by explicit specializations of
function templates or member function templates, even when those
specializations returned normally.
Follow up on https://github.com/llvm/llvm-project/pull/145166
(cherry picked from commit 22fef005225b129d73ade4ed995fc0ec0c7be044)
Added:
Modified:
clang/lib/Sema/SemaDecl.cpp
clang/lib/Sema/SemaDeclAttr.cpp
clang/test/SemaCXX/wreturn-always-throws.cpp
Removed:
################################################################################
diff --git a/clang/lib/Sema/SemaDecl.cpp b/clang/lib/Sema/SemaDecl.cpp
index 14403e65e8f42..bb412ef6788e7 100644
--- a/clang/lib/Sema/SemaDecl.cpp
+++ b/clang/lib/Sema/SemaDecl.cpp
@@ -3267,6 +3267,14 @@ void Sema::mergeDeclAttributes(NamedDecl *New, Decl *Old,
if (isa<UsedAttr>(I) || isa<RetainAttr>(I))
continue;
+ if (isa<InferredNoReturnAttr>(I)) {
+ if (auto *FD = dyn_cast<FunctionDecl>(New)) {
+ if (FD->getTemplateSpecializationKind() == TSK_ExplicitSpecialization)
+ continue; // Don't propagate inferred noreturn attributes to explicit
+ // specializations.
+ }
+ }
+
if (mergeDeclAttribute(*this, New, I, LocalAMK))
foundAny = true;
}
diff --git a/clang/lib/Sema/SemaDeclAttr.cpp b/clang/lib/Sema/SemaDeclAttr.cpp
index eff5f9568236a..a7897bdfe6e0f 100644
--- a/clang/lib/Sema/SemaDeclAttr.cpp
+++ b/clang/lib/Sema/SemaDeclAttr.cpp
@@ -1970,6 +1970,13 @@ void clang::inferNoReturnAttr(Sema &S, const Decl *D) {
if (!FD)
return;
+ // Skip explicit specializations here as they may have
+ // a user-provided definition that may deliberately
diff er from the primary
+ // template. If an explicit specialization truly never returns, the user
+ // should explicitly mark it with [[noreturn]].
+ if (FD->getTemplateSpecializationKind() == TSK_ExplicitSpecialization)
+ return;
+
auto *NonConstFD = const_cast<FunctionDecl *>(FD);
DiagnosticsEngine &Diags = S.getDiagnostics();
if (Diags.isIgnored(diag::warn_falloff_nonvoid, FD->getLocation()) &&
diff --git a/clang/test/SemaCXX/wreturn-always-throws.cpp b/clang/test/SemaCXX/wreturn-always-throws.cpp
index addcadd1183dc..df7689f7063cc 100644
--- a/clang/test/SemaCXX/wreturn-always-throws.cpp
+++ b/clang/test/SemaCXX/wreturn-always-throws.cpp
@@ -1,4 +1,4 @@
-// RUN: %clang_cc1 -fsyntax-only -fcxx-exceptions -fexceptions -Wreturn-type -verify %s
+// RUN: %clang_cc1 -fsyntax-only -fcxx-exceptions -fexceptions -Wreturn-type -Winvalid-noreturn -verify %s
// expected-no-diagnostics
namespace std {
@@ -44,3 +44,22 @@ void testTemplates() {
throwErrorTemplate("ERROR");
(void)ensureZeroTemplate(42);
}
+
+// Ensure that explicit specialization of a member function does not inherit
+// the warning from the primary template.
+
+template<typename T>
+struct S {
+ void f();
+ void g();
+};
+
+template<typename T>
+void S<T>::f() { throw 0; }
+template<>
+void S<int>::f() {}
+
+template<typename T>
+void S<T>::g() {}
+template<>
+void S<int>::g() { throw 0; }
More information about the llvm-branch-commits
mailing list