Skip to content

Commit 70928fc

Browse files
huqizhijcsxky
authored andcommitted
[Clang][Sema] qualifier should be transformed
1 parent 8742477 commit 70928fc

File tree

6 files changed

+60
-6
lines changed

6 files changed

+60
-6
lines changed

clang/docs/ReleaseNotes.rst

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -914,6 +914,7 @@ Bug Fixes to C++ Support
914914
- Clang now diagnoses explicit specializations with storage class specifiers in all contexts.
915915
- Fix an assertion failure caused by parsing a lambda used as a default argument for the value of a
916916
forward-declared class. (#GH93512).
917+
- Clang now transforms qualifier of template name. (#91677).
917918

918919
Bug Fixes to AST Handling
919920
^^^^^^^^^^^^^^^^^^^^^^^^^

clang/lib/Sema/TreeTransform.h

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4568,6 +4568,24 @@ TreeTransform<Derived>::TransformTemplateName(CXXScopeSpec &SS,
45684568
if (QualifiedTemplateName *QTN = Name.getAsQualifiedTemplateName()) {
45694569
TemplateDecl *Template = QTN->getUnderlyingTemplate().getAsTemplateDecl();
45704570
assert(Template && "qualified template name must refer to a template");
4571+
if (QTN->getQualifier()) {
4572+
CXXScopeSpec QualifierSS;
4573+
QualifierSS.MakeTrivial(getSema().getASTContext(), QTN->getQualifier(),
4574+
NameLoc);
4575+
NestedNameSpecifierLoc QualifierLoc =
4576+
QualifierSS.getWithLocInContext(getSema().getASTContext());
4577+
NestedNameSpecifierLoc TransformedQualifierLoc =
4578+
getDerived().TransformNestedNameSpecifierLoc(QualifierLoc);
4579+
if (!TransformedQualifierLoc)
4580+
return Name;
4581+
if (getDerived().AlwaysRebuild() ||
4582+
QualifierLoc != TransformedQualifierLoc) {
4583+
SS.Adopt(TransformedQualifierLoc);
4584+
return getDerived().RebuildTemplateName(
4585+
SS, SourceLocation(), *Template->getIdentifier(), NameLoc,
4586+
ObjectType, FirstQualifierInScope, /*AllowInjectedClassName=*/true);
4587+
}
4588+
}
45714589

45724590
TemplateDecl *TransTemplate
45734591
= cast_or_null<TemplateDecl>(getDerived().TransformDecl(NameLoc,

clang/test/SemaCXX/many-template-parameter-lists.cpp

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55
template <class T>
66
struct X {
77
template <class U>
8-
struct A { // expected-note {{not-yet-instantiated member is declared here}}
8+
struct A {
99
template <class V>
1010
struct B {
1111
template <class W>
@@ -28,9 +28,9 @@ struct X {
2828
template <class X>
2929
template <class Y>
3030
template <class Z>
31-
friend void A<U>::template B<V>::template C<W>::template D<X>::template E<Y>::operator+=(Z); // expected-warning {{not supported}} expected-error {{no member 'A' in 'X<int>'; it has not yet been instantiated}}
31+
friend void A<U>::template B<V>::template C<W>::template D<X>::template E<Y>::operator+=(Z); // expected-warning {{dependent nested name specifier 'A<U>::B<V>::C<W>::D<X>::template E<Y>::' for friend class declaration is not supported; turning off access control for 'X'}}
3232
};
3333

3434
void test() {
35-
X<int>::A<int>::B<int>::C<int>::D<int>::E<int>() += 1.0; // expected-note {{in instantiation of template class 'X<int>' requested here}}
35+
X<int>::A<int>::B<int>::C<int>::D<int>::E<int>() += 1.0;
3636
}
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
// RUN: %clang_cc1 -verify -std=c++20 -fsyntax-only %s
2+
3+
namespace PR12884_original {
4+
template <typename T> struct A {
5+
struct B {
6+
template <typename U> struct X {};
7+
typedef int arg;
8+
};
9+
struct C {
10+
typedef B::X<typename B::arg> x; // expected-error{{typename specifier refers to non-type member 'arg' in 'PR12884_original::A<int>::B'}}
11+
};
12+
};
13+
14+
template <> struct A<int>::B {
15+
template <int N> struct X {};
16+
static const int arg = 0; // expected-note{{referenced member 'arg' is declared here}}
17+
};
18+
19+
A<int>::C::x a; // expected-note{{in instantiation of member class 'PR12884_original::A<int>::C' requested here}}
20+
}

clang/test/SemaTemplate/PR91677.cpp

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
// RUN: %clang_cc1 -verify -std=c++20 -fsyntax-only %s
2+
// expected-no-diagnostics
3+
4+
template <typename> struct t1 {
5+
template <typename>
6+
struct t2 {};
7+
};
8+
9+
template <typename T>
10+
t1<T>::template t2<T> f1();
11+
12+
void f2() {
13+
f1<bool>();
14+
}

clang/test/SemaTemplate/typename-specifier-3.cpp

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -28,16 +28,17 @@ namespace PR12884_original {
2828
typedef int arg;
2929
};
3030
struct C {
31-
typedef B::X<typename B::arg> x; // precxx17-warning{{missing 'typename' prior to dependent type name B::X; implicit 'typename' is a C++20 extension}}
31+
typedef B::X<typename B::arg> x; // precxx17-warning{{missing 'typename' prior to dependent type name B::X; implicit 'typename' is a C++20 extension}} \
32+
expected-error{{typename specifier refers to non-type member 'arg' in 'PR12884_original::A<int>::B'}}
3233
};
3334
};
3435

3536
template <> struct A<int>::B {
3637
template <int N> struct X {};
37-
static const int arg = 0;
38+
static const int arg = 0; // expected-note{{referenced member 'arg' is declared here}}
3839
};
3940

40-
A<int>::C::x a;
41+
A<int>::C::x a; // expected-note{{in instantiation of member class 'PR12884_original::A<int>::C' requested here}}
4142
}
4243
namespace PR12884_half_fixed {
4344
template <typename T> struct A {

0 commit comments

Comments
 (0)