Skip to content

Commit 6c91ee6

Browse files
committed
[FOLD] only enable cwg1835 behavior in c++23 and up
1 parent 9674d15 commit 6c91ee6

File tree

5 files changed

+63
-48
lines changed

5 files changed

+63
-48
lines changed

clang/lib/Sema/SemaTemplate.cpp

Lines changed: 33 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -410,6 +410,35 @@ bool Sema::LookupTemplateName(LookupResult &Found, Scope *S, CXXScopeSpec &SS,
410410
LookupParsedName(Found, S, &SS, ObjectType,
411411
/*AllowBuiltinCreation=*/false, EnteringContext);
412412

413+
bool ObjectTypeSearchedInScope = false;
414+
415+
// C++ [basic.lookup.qual.general]p2:
416+
// A member-qualified name is the (unique) component name, if any, of
417+
// - an unqualified-id or
418+
// - a nested-name-specifier of the form type-name :: or namespace-name ::
419+
// in the id-expression of a class member access expression.
420+
//
421+
// C++ [basic.lookup.qual.general]p3:
422+
// [...] If nothing is found by qualified lookup for a member-qualified
423+
// name that is the terminal name of a nested-name-specifier and is not
424+
// dependent, it undergoes unqualified lookup.
425+
//
426+
// In 'x.A::B::y', 'A' will undergo unqualified lookup if qualified lookup
427+
// in the type of 'x' finds nothing. If the lookup context is dependent,
428+
// we perform the unqualified lookup in the template definition context
429+
// and store the results so we can replicate the lookup during instantiation.
430+
if (MayBeNNS && Found.empty() && !ObjectType.isNull() &&
431+
(!getLangOpts().CPlusPlus23 ||
432+
!Found.wasNotFoundInCurrentInstantiation())) {
433+
if (S) {
434+
LookupName(Found, S);
435+
} else if (!SS.getUnqualifiedLookups().empty()) {
436+
Found.addAllDecls(SS.getUnqualifiedLookups());
437+
Found.resolveKind();
438+
}
439+
ObjectTypeSearchedInScope = true;
440+
}
441+
413442
// C++ [basic.lookup.qual.general]p3:
414443
// [...] Unless otherwise specified, a qualified name undergoes qualified
415444
// name lookup in its lookup context from the point where it appears unless
@@ -445,33 +474,6 @@ bool Sema::LookupTemplateName(LookupResult &Found, Scope *S, CXXScopeSpec &SS,
445474
if (Found.wasNotFoundInCurrentInstantiation())
446475
return false;
447476

448-
bool ObjectTypeSearchedInScope = false;
449-
450-
// C++ [basic.lookup.qual.general]p2:
451-
// A member-qualified name is the (unique) component name, if any, of
452-
// - an unqualified-id or
453-
// - a nested-name-specifier of the form type-name :: or namespace-name ::
454-
// in the id-expression of a class member access expression.
455-
//
456-
// C++ [basic.lookup.qual.general]p3:
457-
// [...] If nothing is found by qualified lookup for a member-qualified
458-
// name that is the terminal name of a nested-name-specifier and is not
459-
// dependent, it undergoes unqualified lookup.
460-
//
461-
// In 'x.A::B::y', 'A' will undergo unqualified lookup if qualified lookup
462-
// in the type of 'x' finds nothing. If the lookup context is dependent,
463-
// we perform the unqualified lookup in the template definition context
464-
// and store the results so we can replicate the lookup during instantiation.
465-
if (MayBeNNS && Found.empty() && !ObjectType.isNull()) {
466-
if (S) {
467-
LookupName(Found, S);
468-
} else if (!SS.getUnqualifiedLookups().empty()) {
469-
Found.addAllDecls(SS.getUnqualifiedLookups());
470-
Found.resolveKind();
471-
}
472-
ObjectTypeSearchedInScope = true;
473-
}
474-
475477
if (Found.isAmbiguous())
476478
return false;
477479

@@ -542,7 +544,10 @@ bool Sema::LookupTemplateName(LookupResult &Found, Scope *S, CXXScopeSpec &SS,
542544

543545
NamedDecl *ExampleLookupResult =
544546
Found.empty() ? nullptr : Found.getRepresentativeDecl();
545-
FilterAcceptableTemplateNames(Found);
547+
FilterAcceptableTemplateNames(
548+
Found,
549+
/*AllowFunctionTemplates=*/getLangOpts().CPlusPlus23 ||
550+
!ObjectTypeSearchedInScope);
546551
if (Found.empty()) {
547552
// If a 'template' keyword was used, a lookup that finds only non-template
548553
// names is an error.

clang/test/CXX/class.derived/class.member.lookup/p8.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -47,8 +47,8 @@ template<typename T>
4747
void DerivedT<T>::Inner() {
4848
Derived1T<T>::Foo();
4949
Derived2T<T>::Member = 42;
50-
this->Derived1T<T>::Foo(); // expected-warning{{use 'template' keyword to treat 'Derived1T' as a dependent template name}}
51-
this->Derived2T<T>::Member = 42; // expected-warning{{use 'template' keyword to treat 'Derived2T' as a dependent template name}}
50+
this->Derived1T<T>::Foo();
51+
this->Derived2T<T>::Member = 42;
5252
this->Foo(); // expected-error{{non-static member 'Foo' found in multiple base-class subobjects of type 'BaseT<int>'}}
5353
}
5454

clang/test/CXX/drs/cwg13xx.cpp

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
1-
// RUN: %clang_cc1 -std=c++98 %s -verify=expected,cxx98-14,cxx98 -fexceptions -fcxx-exceptions -pedantic-errors
2-
// RUN: %clang_cc1 -std=c++11 %s -verify=expected,cxx11-20,cxx11-17,cxx11-14,cxx98-14,since-cxx11,cxx11 -fexceptions -fcxx-exceptions -pedantic-errors
3-
// RUN: %clang_cc1 -std=c++14 %s -verify=expected,cxx11-20,cxx11-17,cxx11-14,since-cxx14,cxx98-14,since-cxx11 -fexceptions -fcxx-exceptions -pedantic-errors
4-
// RUN: %clang_cc1 -std=c++17 %s -verify=expected,cxx11-20,cxx11-17,since-cxx14,since-cxx17,since-cxx11 -fexceptions -fcxx-exceptions -pedantic-errors
5-
// RUN: %clang_cc1 -std=c++20 %s -verify=expected,cxx11-20,since-cxx14,since-cxx20,since-cxx17,since-cxx11 -fexceptions -fcxx-exceptions -pedantic-errors
1+
// RUN: %clang_cc1 -std=c++98 %s -verify=expected,cxx98-14,cxx98-20,cxx98 -fexceptions -fcxx-exceptions -pedantic-errors
2+
// RUN: %clang_cc1 -std=c++11 %s -verify=expected,cxx11-20,cxx11-17,cxx11-14,cxx98-14,cxx98-20,since-cxx11,cxx11 -fexceptions -fcxx-exceptions -pedantic-errors
3+
// RUN: %clang_cc1 -std=c++14 %s -verify=expected,cxx11-20,cxx11-17,cxx11-14,since-cxx14,cxx98-14,cxx98-20,since-cxx11 -fexceptions -fcxx-exceptions -pedantic-errors
4+
// RUN: %clang_cc1 -std=c++17 %s -verify=expected,cxx11-20,cxx11-17,cxx98-20,since-cxx14,since-cxx17,since-cxx11 -fexceptions -fcxx-exceptions -pedantic-errors
5+
// RUN: %clang_cc1 -std=c++20 %s -verify=expected,cxx11-20,cxx98-20,since-cxx14,since-cxx20,since-cxx17,since-cxx11 -fexceptions -fcxx-exceptions -pedantic-errors
66
// RUN: %clang_cc1 -std=c++23 %s -verify=expected,since-cxx14,since-cxx20,since-cxx17,since-cxx11 -fexceptions -fcxx-exceptions -pedantic-errors
77
// RUN: %clang_cc1 -std=c++2c %s -verify=expected,since-cxx14,since-cxx20,since-cxx17,since-cxx11 -fexceptions -fcxx-exceptions -pedantic-errors
88

@@ -136,6 +136,7 @@ namespace cwg1310 { // cwg1310: 5
136136
// expected-error@-1 {{ISO C++ specifies that qualified reference to 'W' is a constructor name rather than a template name in this context, despite preceding 'template' keyword}}
137137
}
138138
template<typename W>
139+
// cxx98-20-note@-1 2{{declared as a non-template here}}
139140
void wt_test_good() {
140141
typename W::W::X w2ax;
141142
typename W::template W<int>::X w4x;
@@ -146,7 +147,9 @@ namespace cwg1310 { // cwg1310: 5
146147
(void)w.W::W::n;
147148
(void)w.W::template W<int>::n;
148149
(void)w.template W<int>::W::n;
150+
// cxx98-20-error@-1 {{'W' following the 'template' keyword does not refer to a template}}
149151
(void)w.template W<int>::template W<int>::n;
152+
// cxx98-20-error@-1 {{'W' following the 'template' keyword does not refer to a template}}
150153
}
151154
template void wt_test<W<int> >(); // #cwg1310-W-int
152155
template void wt_test_good<W<int> >();

clang/test/CXX/drs/cwg1xx.cpp

Lines changed: 10 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,9 @@
1-
// RUN: %clang_cc1 -std=c++98 -triple x86_64-unknown-unknown %s -verify=expected,cxx98,cxx98-11,cxx98-14,cxx98-17 -fexceptions -fcxx-exceptions -pedantic-errors
2-
// RUN: %clang_cc1 -std=c++11 -triple x86_64-unknown-unknown %s -verify=expected,since-cxx11,cxx98-11,cxx98-14,cxx98-17,cxx11-14 -fexceptions -fcxx-exceptions -pedantic-errors
3-
// RUN: %clang_cc1 -std=c++14 -triple x86_64-unknown-unknown %s -verify=expected,since-cxx11,cxx98-14,cxx98-17,cxx11-14 -fexceptions -fcxx-exceptions -pedantic-errors
4-
// RUN: %clang_cc1 -std=c++17 -triple x86_64-unknown-unknown %s -verify=expected,since-cxx11,since-cxx17,cxx98-17 -fexceptions -fcxx-exceptions -pedantic-errors
5-
// RUN: %clang_cc1 -std=c++20 -triple x86_64-unknown-unknown %s -verify=expected,since-cxx11,since-cxx17 -fexceptions -fcxx-exceptions -pedantic-errors
6-
// RUN: %clang_cc1 -std=c++23 -triple x86_64-unknown-unknown %s -verify=expected,since-cxx11,since-cxx17 -fexceptions -fcxx-exceptions -pedantic-errors
1+
// RUN: %clang_cc1 -std=c++98 -triple x86_64-unknown-unknown %s -verify=expected,cxx98,cxx98-11,cxx98-14,cxx98-17,cxx98-20 -fexceptions -fcxx-exceptions -pedantic-errors
2+
// RUN: %clang_cc1 -std=c++11 -triple x86_64-unknown-unknown %s -verify=expected,since-cxx11,cxx98-11,cxx98-14,cxx98-17,cxx98-20,cxx11-14 -fexceptions -fcxx-exceptions -pedantic-errors
3+
// RUN: %clang_cc1 -std=c++14 -triple x86_64-unknown-unknown %s -verify=expected,since-cxx11,cxx98-14,cxx98-17,cxx98-20,cxx11-14 -fexceptions -fcxx-exceptions -pedantic-errors
4+
// RUN: %clang_cc1 -std=c++17 -triple x86_64-unknown-unknown %s -verify=expected,since-cxx11,since-cxx17,cxx98-17,cxx98-20 -fexceptions -fcxx-exceptions -pedantic-errors
5+
// RUN: %clang_cc1 -std=c++20 -triple x86_64-unknown-unknown %s -verify=expected,since-cxx11,since-cxx17,cxx98-20 -fexceptions -fcxx-exceptions -pedantic-errors
6+
// RUN: %clang_cc1 -std=c++23 -triple x86_64-unknown-unknown %s -verify=expected,since-cxx11,since-cxx17,since-cxx23 -fexceptions -fcxx-exceptions -pedantic-errors
77

88
#if __cplusplus == 199711L
99
#define static_assert(...) __extension__ _Static_assert(__VA_ARGS__)
@@ -617,6 +617,8 @@ namespace cwg141 { // cwg141: 3.1
617617
// expected-note@#cwg141-S {{'::cwg141::S<int>::n' declared here}}
618618
b.f<int>();
619619
// expected-error@-1 {{no member named 'f' in 'cwg141::B'}}
620+
// cxx98-20-error@-2 {{expected '(' for function-style cast or type construction}}
621+
// cxx98-20-error@-3 {{expected expression}}
620622
(void)b.S<int>::n;
621623
}
622624
template<typename T> struct C {
@@ -627,11 +629,11 @@ namespace cwg141 { // cwg141: 3.1
627629
}
628630
void h() {
629631
(void)t.S<int>::n;
630-
// expected-error@-1 {{use 'template' keyword to treat 'S' as a dependent template name}}
632+
// since-cxx23-error@-1 {{use 'template' keyword to treat 'S' as a dependent template name}}
631633
}
632634
void i() {
633635
(void)t.S<int>();
634-
// expected-error@-1 {{use 'template' keyword to treat 'S' as a dependent template name}}
636+
// since-cxx23-error@-1 {{use 'template' keyword to treat 'S' as a dependent template name}}
635637
}
636638
};
637639
void h() { C<B>().h(); } // ok

clang/test/SemaCXX/pseudo-destructors.cpp

Lines changed: 10 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
1-
// RUN: %clang_cc1 -emit-llvm-only -verify -std=c++11 %s
1+
// RUN: %clang_cc1 -emit-llvm-only -std=c++11 -verify=expected,cxx98-20 %s
2+
// RUN: %clang_cc1 -emit-llvm-only -std=c++23 -verify=expected,since-cxx23 %s
23
struct A {};
34

45
enum Foo { F };
@@ -148,12 +149,13 @@ namespace TwoPhaseLookup {
148149
namespace Template {
149150
template<typename T> struct Y {};
150151
template<class U> using G = Y<U>;
151-
template<typename T> void f(T *p) { p->~G<int>(); } // expected-error {{no member named 'G'}}
152+
template<typename T> void f(T *p) { p->~G<int>(); } // since-cxx23-error {{no member named 'G'}}
153+
// cxx98-20-error@-1 {{no member named '~Y' in 'TwoPhaseLookup::Template::N::G<int>'}}
152154
void h1(Y<int> *p) { p->~G<int>(); }
153-
void h2(Y<int> *p) { f(p); } // expected-note {{instantiation of}}
155+
void h2(Y<int> *p) { f(p); } // since-cxx23-note {{in instantiation of}}
154156
namespace N { template<typename T> struct G {}; }
155157
void h3(N::G<int> *p) { p->~G<int>(); }
156-
void h4(N::G<int> *p) { f(p); }
158+
void h4(N::G<int> *p) { f(p); } // cxx98-20-note {{in instantiation of}}
157159
}
158160

159161
namespace TemplateUndeclared {
@@ -172,7 +174,10 @@ namespace TwoPhaseLookup {
172174

173175
namespace TemplateNamesNonTemplate {
174176
int A; // expected-note 2{{non-template here}}
175-
template<typename> int B; // expected-note 2{{variable template 'B' declared here}} expected-warning {{extension}}
177+
template<typename> int B; // expected-note 2{{variable template 'B' declared here}}
178+
#if __cplusplus < 201402L
179+
// expected-warning@-2 {{extension}}
180+
#endif
176181
using C = int; // expected-note 2{{non-template here}}
177182

178183
template<typename T> void f1(int *p) { p->~A<int>(); } // expected-error {{'A' does not refer to a template}}

0 commit comments

Comments
 (0)