Skip to content

Commit 3912541

Browse files
committed
Reapply "[Clang][Sema] Diagnose function/variable templates that shadow their own template parameters (#78274)"
1 parent faef68b commit 3912541

File tree

6 files changed

+55
-18
lines changed

6 files changed

+55
-18
lines changed

clang/docs/ReleaseNotes.rst

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,8 @@ C/C++ Language Potentially Breaking Changes
4242

4343
C++ Specific Potentially Breaking Changes
4444
-----------------------------------------
45+
- Clang now diagnoses function/variable templates that shadow their own template parameters, e.g. ``template<class T> void T();``.
46+
This error can be disabled via `-Wno-strict-primary-template-shadow` for compatibility with previous versions of clang.
4547

4648
ABI Changes in This Version
4749
---------------------------

clang/include/clang/Basic/DiagnosticSemaKinds.td

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4966,6 +4966,9 @@ def err_template_param_shadow : Error<
49664966
"declaration of %0 shadows template parameter">;
49674967
def ext_template_param_shadow : ExtWarn<
49684968
err_template_param_shadow.Summary>, InGroup<MicrosoftTemplateShadow>;
4969+
def ext_compat_template_param_shadow : ExtWarn<
4970+
err_template_param_shadow.Summary>, InGroup<
4971+
DiagGroup<"strict-primary-template-shadow">>, DefaultError;
49694972
def note_template_param_here : Note<"template parameter is declared here">;
49704973
def note_template_param_external : Note<
49714974
"template parameter from hidden source: %0">;

clang/include/clang/Sema/Sema.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8256,7 +8256,8 @@ class Sema final {
82568256
TemplateSpecializationKind TSK,
82578257
bool Complain = true);
82588258

8259-
void DiagnoseTemplateParameterShadow(SourceLocation Loc, Decl *PrevDecl);
8259+
void DiagnoseTemplateParameterShadow(SourceLocation Loc, Decl *PrevDecl,
8260+
bool IssueWarning = false);
82608261
TemplateDecl *AdjustDeclIfTemplate(Decl *&Decl);
82618262

82628263
NamedDecl *ActOnTypeParameter(Scope *S, bool Typename,

clang/lib/Sema/SemaDecl.cpp

Lines changed: 24 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -6377,12 +6377,6 @@ NamedDecl *Sema::HandleDeclarator(Scope *S, Declarator &D,
63776377
} else if (DiagnoseUnexpandedParameterPack(NameInfo, UPPC_DeclarationType))
63786378
return nullptr;
63796379

6380-
// The scope passed in may not be a decl scope. Zip up the scope tree until
6381-
// we find one that is.
6382-
while ((S->getFlags() & Scope::DeclScope) == 0 ||
6383-
(S->getFlags() & Scope::TemplateParamScope) != 0)
6384-
S = S->getParent();
6385-
63866380
DeclContext *DC = CurContext;
63876381
if (D.getCXXScopeSpec().isInvalid())
63886382
D.setInvalidType();
@@ -6506,12 +6500,26 @@ NamedDecl *Sema::HandleDeclarator(Scope *S, Declarator &D,
65066500
RemoveUsingDecls(Previous);
65076501
}
65086502

6509-
if (Previous.isSingleResult() &&
6510-
Previous.getFoundDecl()->isTemplateParameter()) {
6503+
// if (Previous.isSingleResult() &&
6504+
// Previous.getFoundDecl()->isTemplateParameter()) {
6505+
if (auto *TPD = Previous.getAsSingle<NamedDecl>();
6506+
TPD && TPD->isTemplateParameter()) {
6507+
// Older versions of clang allowed the names of function/variable templates
6508+
// to shadow the names of their template parameters. For the compatibility
6509+
// purposes we detect such cases and issue a default-to-error warning that
6510+
// can be disabled with -Wno-strict-primary-template-shadow.
6511+
bool IssueShadowingWarning = false;
6512+
for (Scope *Inner = S; (Inner->getFlags() & Scope::DeclScope) == 0 ||
6513+
Inner->isTemplateParamScope();
6514+
Inner = Inner->getParent()) {
6515+
if (IssueShadowingWarning = Inner->isDeclScope(TPD))
6516+
break;
6517+
}
6518+
65116519
// Maybe we will complain about the shadowed template parameter.
65126520
if (!D.isInvalidType())
6513-
DiagnoseTemplateParameterShadow(D.getIdentifierLoc(),
6514-
Previous.getFoundDecl());
6521+
DiagnoseTemplateParameterShadow(D.getIdentifierLoc(), TPD,
6522+
IssueShadowingWarning);
65156523

65166524
// Just pretend that we didn't see the previous declaration.
65176525
Previous.clear();
@@ -6535,6 +6543,12 @@ NamedDecl *Sema::HandleDeclarator(Scope *S, Declarator &D,
65356543
if (getLangOpts().CPlusPlus)
65366544
CheckExtraCXXDefaultArguments(D);
65376545

6546+
// The scope passed in may not be a decl scope. Zip up the scope tree until
6547+
// we find one that is.
6548+
while ((S->getFlags() & Scope::DeclScope) == 0 ||
6549+
(S->getFlags() & Scope::TemplateParamScope) != 0)
6550+
S = S->getParent();
6551+
65386552
NamedDecl *New;
65396553

65406554
bool AddToScope = true;

clang/lib/Sema/SemaTemplate.cpp

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -885,16 +885,19 @@ bool Sema::DiagnoseUninstantiableTemplate(SourceLocation PointOfInstantiation,
885885
/// that the template parameter 'PrevDecl' is being shadowed by a new
886886
/// declaration at location Loc. Returns true to indicate that this is
887887
/// an error, and false otherwise.
888-
void Sema::DiagnoseTemplateParameterShadow(SourceLocation Loc, Decl *PrevDecl) {
888+
void Sema::DiagnoseTemplateParameterShadow(SourceLocation Loc, Decl *PrevDecl,
889+
bool IssueWarning) {
889890
assert(PrevDecl->isTemplateParameter() && "Not a template parameter");
890891

891892
// C++ [temp.local]p4:
892893
// A template-parameter shall not be redeclared within its
893894
// scope (including nested scopes).
894895
//
895896
// Make this a warning when MSVC compatibility is requested.
896-
unsigned DiagId = getLangOpts().MSVCCompat ? diag::ext_template_param_shadow
897-
: diag::err_template_param_shadow;
897+
unsigned DiagId = getLangOpts().MSVCCompat
898+
? diag::ext_template_param_shadow
899+
: (IssueWarning ? diag::ext_compat_template_param_shadow
900+
: diag::err_template_param_shadow);
898901
const auto *ND = cast<NamedDecl>(PrevDecl);
899902
Diag(Loc, DiagId) << ND->getDeclName();
900903
NoteTemplateParameterLocation(*ND);

clang/test/CXX/temp/temp.res/temp.local/p6.cpp

Lines changed: 18 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
// RUN: %clang_cc1 -verify %s -fcxx-exceptions -std=c++1y
1+
// RUN: %clang_cc1 -verify %s -fcxx-exceptions -std=c++1y -Wno-error=strict-primary-template-shadow
22

33
namespace N {}
44

@@ -127,16 +127,30 @@ template<int T> struct Z { // expected-note 16{{declared here}}
127127
template<typename T> // expected-note {{declared here}}
128128
void f(int T) {} // expected-error {{declaration of 'T' shadows template parameter}}
129129

130-
// FIXME: These are ill-formed: a template-parameter shall not have the same name as the template name.
131130
namespace A {
132131
template<typename T> struct T {}; // expected-error{{declaration of 'T' shadows template parameter}}
133132
// expected-note@-1{{template parameter is declared here}}
133+
template<typename T> struct U {
134+
template<typename V> struct V {}; // expected-error{{declaration of 'V' shadows template parameter}}
135+
// expected-note@-1{{template parameter is declared here}}
136+
};
134137
}
135138
namespace B {
136-
template<typename T> void T() {}
139+
template<typename T> void T() {} // expected-warning{{declaration of 'T' shadows template parameter}}
140+
// expected-note@-1{{template parameter is declared here}}
141+
142+
template<typename T> struct U {
143+
template<typename V> void V(); // expected-warning{{declaration of 'V' shadows template parameter}}
144+
// expected-note@-1{{template parameter is declared here}}
145+
};
137146
}
138147
namespace C {
139-
template<typename T> int T;
148+
template<typename T> int T; // expected-warning{{declaration of 'T' shadows template parameter}}
149+
// expected-note@-1{{template parameter is declared here}}
150+
template<typename T> struct U {
151+
template<typename V> static int V; // expected-warning{{declaration of 'V' shadows template parameter}}
152+
// expected-note@-1{{template parameter is declared here}}
153+
};
140154
}
141155

142156
namespace PR28023 {

0 commit comments

Comments
 (0)