Skip to content

[Clang][Sema] Reject declaring an alias template with the same name as its template parameter. #123533

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 9 commits into from
Jan 25, 2025
1 change: 1 addition & 0 deletions clang/docs/ReleaseNotes.rst
Original file line number Diff line number Diff line change
Expand Up @@ -990,6 +990,7 @@ Bug Fixes to C++ Support
- Fix immediate escalation not propagating through inherited constructors. (#GH112677)
- Fixed assertions or false compiler diagnostics in the case of C++ modules for
lambda functions or inline friend functions defined inside templates (#GH122493).
- Clang now rejects declaring an alias template with the same name as its template parameter. (#GH123423)

Bug Fixes to AST Handling
^^^^^^^^^^^^^^^^^^^^^^^^^
Expand Down
5 changes: 3 additions & 2 deletions clang/lib/Sema/SemaDeclCXX.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -13406,8 +13406,6 @@ Decl *Sema::ActOnAliasDeclaration(Scope *S, AccessSpecifier AS,
SourceLocation UsingLoc, UnqualifiedId &Name,
const ParsedAttributesView &AttrList,
TypeResult Type, Decl *DeclFromDeclSpec) {
// Get the innermost enclosing declaration scope.
S = S->getDeclParent();

if (Type.isInvalid())
return nullptr;
Expand Down Expand Up @@ -13458,6 +13456,9 @@ Decl *Sema::ActOnAliasDeclaration(Scope *S, AccessSpecifier AS,
CheckTypedefForVariablyModifiedType(S, NewTD);
Invalid |= NewTD->isInvalidDecl();

// Get the innermost enclosing declaration scope.
S = S->getDeclParent();

bool Redeclaration = false;

NamedDecl *NewND;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -121,8 +121,8 @@ namespace PartialSpecialization {

namespace FixedAliasTemplate {
template<typename,typename,typename> struct S {};
template<typename T, typename U> using U = S<T, int, U>; // expected-note 2{{template parameter is declared here}}
template<typename...Ts> U<Ts...> &f(U<Ts...>, Ts...); // expected-error 2{{pack expansion used as argument for non-pack parameter of alias template}}
template<typename T, typename U> using Z = S<T, int, U>; // expected-note 2{{template parameter is declared here}}
template<typename...Ts> Z<Ts...> &f(Z<Ts...>, Ts...); // expected-error 2{{pack expansion used as argument for non-pack parameter of alias template}}
S<int, int, double> &s1 = f({}, 0, 0.0); // expected-error {{no matching function}}
}

Expand Down
10 changes: 8 additions & 2 deletions clang/test/SemaCXX/alias-template.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -54,18 +54,24 @@ namespace LookupFilter {
template<typename U> using S = S<U>*; // ok
}

namespace InFunctions {
namespace UnexpandedPack {
template<typename...T> struct S0 {
template<typename Z> using U = T*; // expected-error {{declaration type contains unexpanded parameter pack 'T'}}
U<char> u;
};
}

namespace InvalidType {
template<typename Z> using T1 = int;
template<typename Z> using T2 = int[-1]; // expected-error {{array size is negative}}
}

namespace ShadowTemplateParam {
template<typename...T> struct S3 { // expected-note {{template parameter is declared here}}
template<typename Z> using T = int; // expected-error {{declaration of 'T' shadows template parameter}}
};
template<typename Z> using Z = Z;
template<typename Z> // expected-note {{template parameter is declared here}}
using Z = Z; // expected-error {{declaration of 'Z' shadows template parameter}}
}

namespace ClassNameRedecl {
Expand Down
Loading