Skip to content

Commit 087cb2e

Browse files
snarang181tru
authored andcommitted
[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 #145166 (cherry picked from commit 22fef00)
1 parent 8d38ccb commit 087cb2e

File tree

3 files changed

+35
-1
lines changed

3 files changed

+35
-1
lines changed

clang/lib/Sema/SemaDecl.cpp

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3267,6 +3267,14 @@ void Sema::mergeDeclAttributes(NamedDecl *New, Decl *Old,
32673267
if (isa<UsedAttr>(I) || isa<RetainAttr>(I))
32683268
continue;
32693269

3270+
if (isa<InferredNoReturnAttr>(I)) {
3271+
if (auto *FD = dyn_cast<FunctionDecl>(New)) {
3272+
if (FD->getTemplateSpecializationKind() == TSK_ExplicitSpecialization)
3273+
continue; // Don't propagate inferred noreturn attributes to explicit
3274+
// specializations.
3275+
}
3276+
}
3277+
32703278
if (mergeDeclAttribute(*this, New, I, LocalAMK))
32713279
foundAny = true;
32723280
}

clang/lib/Sema/SemaDeclAttr.cpp

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1970,6 +1970,13 @@ void clang::inferNoReturnAttr(Sema &S, const Decl *D) {
19701970
if (!FD)
19711971
return;
19721972

1973+
// Skip explicit specializations here as they may have
1974+
// a user-provided definition that may deliberately differ from the primary
1975+
// template. If an explicit specialization truly never returns, the user
1976+
// should explicitly mark it with [[noreturn]].
1977+
if (FD->getTemplateSpecializationKind() == TSK_ExplicitSpecialization)
1978+
return;
1979+
19731980
auto *NonConstFD = const_cast<FunctionDecl *>(FD);
19741981
DiagnosticsEngine &Diags = S.getDiagnostics();
19751982
if (Diags.isIgnored(diag::warn_falloff_nonvoid, FD->getLocation()) &&

clang/test/SemaCXX/wreturn-always-throws.cpp

Lines changed: 20 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
// RUN: %clang_cc1 -fsyntax-only -fcxx-exceptions -fexceptions -Wreturn-type -verify %s
1+
// RUN: %clang_cc1 -fsyntax-only -fcxx-exceptions -fexceptions -Wreturn-type -Winvalid-noreturn -verify %s
22
// expected-no-diagnostics
33

44
namespace std {
@@ -44,3 +44,22 @@ void testTemplates() {
4444
throwErrorTemplate("ERROR");
4545
(void)ensureZeroTemplate(42);
4646
}
47+
48+
// Ensure that explicit specialization of a member function does not inherit
49+
// the warning from the primary template.
50+
51+
template<typename T>
52+
struct S {
53+
void f();
54+
void g();
55+
};
56+
57+
template<typename T>
58+
void S<T>::f() { throw 0; }
59+
template<>
60+
void S<int>::f() {}
61+
62+
template<typename T>
63+
void S<T>::g() {}
64+
template<>
65+
void S<int>::g() { throw 0; }

0 commit comments

Comments
 (0)