Skip to content

Commit

Permalink
[Clang][Sema] Diagnose function/variable templates that shadow their …
Browse files Browse the repository at this point in the history
…own template parameters (#78274)

Previously, we skipped through template parameter scopes (until we hit a
declaration scope) prior to redeclaration lookup for declarators. For
template declarations, the meant that their template parameters would
not be found and shadowing would not be diagnosed. With these changes
applied, the following declarations are correctly diagnosed:
```cpp
template<typename T> void T(); // error: declaration of 'T' shadows template parameter
template<typename U> int U; // error: declaration of 'U' shadows template parameter
```

The reason for skipping past non-declaration & template parameter scopes
prior to lookup appears to have been because `GetTypeForDeclarator`
needed this adjusted scope... but it doesn't actually use this parameter
anymore. 

The scope adjustment now happens prior to calling
`ActOnFunctionDeclarator`/`ActOnVariableDeclarator`/`ActOnTypedefDeclarator`
(just in case they depend on this behavior... I didn't check in depth).
  • Loading branch information
sdkrystian committed Jan 17, 2024
1 parent 77d21e7 commit fc02532
Show file tree
Hide file tree
Showing 3 changed files with 24 additions and 9 deletions.
1 change: 1 addition & 0 deletions clang/docs/ReleaseNotes.rst
Original file line number Diff line number Diff line change
Expand Up @@ -568,6 +568,7 @@ Improvements to Clang's diagnostics
- Clang now diagnoses the requirement that non-template friend declarations with requires clauses
and template friend declarations with a constraint that depends on a template parameter from an
enclosing template must be a definition.
- Clang now diagnoses function/variable templates that shadow their own template parameters, e.g. ``template<class T> void T();``.


Improvements to Clang's time-trace
Expand Down
12 changes: 6 additions & 6 deletions clang/lib/Sema/SemaDecl.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -6377,12 +6377,6 @@ NamedDecl *Sema::HandleDeclarator(Scope *S, Declarator &D,
} else if (DiagnoseUnexpandedParameterPack(NameInfo, UPPC_DeclarationType))
return nullptr;

// The scope passed in may not be a decl scope. Zip up the scope tree until
// we find one that is.
while ((S->getFlags() & Scope::DeclScope) == 0 ||
(S->getFlags() & Scope::TemplateParamScope) != 0)
S = S->getParent();

DeclContext *DC = CurContext;
if (D.getCXXScopeSpec().isInvalid())
D.setInvalidType();
Expand Down Expand Up @@ -6535,6 +6529,12 @@ NamedDecl *Sema::HandleDeclarator(Scope *S, Declarator &D,
if (getLangOpts().CPlusPlus)
CheckExtraCXXDefaultArguments(D);

// The scope passed in may not be a decl scope. Zip up the scope tree until
// we find one that is.
while ((S->getFlags() & Scope::DeclScope) == 0 ||
(S->getFlags() & Scope::TemplateParamScope) != 0)
S = S->getParent();

NamedDecl *New;

bool AddToScope = true;
Expand Down
20 changes: 17 additions & 3 deletions clang/test/CXX/temp/temp.res/temp.local/p6.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -127,16 +127,30 @@ template<int T> struct Z { // expected-note 16{{declared here}}
template<typename T> // expected-note {{declared here}}
void f(int T) {} // expected-error {{declaration of 'T' shadows template parameter}}

// FIXME: These are ill-formed: a template-parameter shall not have the same name as the template name.
namespace A {
template<typename T> struct T {}; // expected-error{{declaration of 'T' shadows template parameter}}
// expected-note@-1{{template parameter is declared here}}
template<typename T> struct U {
template<typename V> struct V {}; // expected-error{{declaration of 'V' shadows template parameter}}
// expected-note@-1{{template parameter is declared here}}
};
}
namespace B {
template<typename T> void T() {}
template<typename T> void T() {} // expected-error{{declaration of 'T' shadows template parameter}}
// expected-note@-1{{template parameter is declared here}}

template<typename T> struct U {
template<typename V> void V(); // expected-error{{declaration of 'V' shadows template parameter}}
// expected-note@-1{{template parameter is declared here}}
};
}
namespace C {
template<typename T> int T;
template<typename T> int T; // expected-error{{declaration of 'T' shadows template parameter}}
// expected-note@-1{{template parameter is declared here}}
template<typename T> struct U {
template<typename V> static int V; // expected-error{{declaration of 'V' shadows template parameter}}
// expected-note@-1{{template parameter is declared here}}
};
}

namespace PR28023 {
Expand Down

0 comments on commit fc02532

Please sign in to comment.