Skip to content

Commit 4f9d734

Browse files
committed
[FOLD] apply cwg1835 in all c++ language modes
1 parent 922780b commit 4f9d734

File tree

6 files changed

+51
-58
lines changed

6 files changed

+51
-58
lines changed

clang/lib/Sema/SemaTemplate.cpp

Lines changed: 30 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -405,36 +405,6 @@ bool Sema::LookupTemplateName(LookupResult &Found, Scope *S, CXXScopeSpec &SS,
405405
LookupParsedName(Found, S, &SS, ObjectType,
406406
/*AllowBuiltinCreation=*/false, EnteringContext);
407407

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

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

@@ -499,7 +496,7 @@ bool Sema::LookupTemplateName(LookupResult &Found, Scope *S, CXXScopeSpec &SS,
499496
}
500497
}
501498

502-
if (Found.empty() && AllowTypoCorrection && !IsDependent) {
499+
if (Found.empty() && AllowTypoCorrection) {
503500
// If we did not find any names, and this is not a disambiguation, attempt
504501
// to correct any typos.
505502
DeclarationName Name = Found.getLookupName();
@@ -540,12 +537,9 @@ bool Sema::LookupTemplateName(LookupResult &Found, Scope *S, CXXScopeSpec &SS,
540537

541538
NamedDecl *ExampleLookupResult =
542539
Found.empty() ? nullptr : Found.getRepresentativeDecl();
543-
FilterAcceptableTemplateNames(Found, getLangOpts().CPlusPlus23 ||
544-
!ObjectTypeSearchedInScope);
540+
FilterAcceptableTemplateNames(Found);
545541
if (Found.empty()) {
546-
if (IsDependent) {
547-
Found.setNotFoundInCurrentInstantiation();
548-
} else if (ExampleLookupResult && RequiredTemplate) {
542+
if (ExampleLookupResult && RequiredTemplate) {
549543
// If a 'template' keyword was used, a lookup that finds only non-template
550544
// names is an error.
551545
Diag(Found.getNameLoc(), diag::err_template_kw_refers_to_non_template)

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();
51-
this->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}}
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/cwg1xx.cpp

Lines changed: 8 additions & 10 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,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
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
77

88
#if __cplusplus == 199711L
99
#define static_assert(...) __extension__ _Static_assert(__VA_ARGS__)
@@ -705,8 +705,6 @@ namespace cwg141 { // cwg141: 3.1
705705
// expected-note@#cwg141-S {{'::cwg141::S<int>::n' declared here}}
706706
b.f<int>();
707707
// expected-error@-1 {{no member named 'f' in 'cwg141::B'}}
708-
// cxx98-20-error@-2 {{expected '(' for function-style cast or type construction}}
709-
// cxx98-20-error@-3 {{expected expression}}
710708
(void)b.S<int>::n;
711709
}
712710
template<typename T> struct C {
@@ -717,11 +715,11 @@ namespace cwg141 { // cwg141: 3.1
717715
}
718716
void h() {
719717
(void)t.S<int>::n;
720-
// since-cxx23-error@-1 {{use 'template' keyword to treat 'S' as a dependent template name}}
718+
// expected-error@-1 {{use 'template' keyword to treat 'S' as a dependent template name}}
721719
}
722720
void i() {
723721
(void)t.S<int>();
724-
// since-cxx23-error@-1 {{use 'template' keyword to treat 'S' as a dependent template name}}
722+
// expected-error@-1 {{use 'template' keyword to treat 'S' as a dependent template name}}
725723
}
726724
};
727725
void h() { C<B>().h(); } // ok

clang/test/SemaCXX/pseudo-destructors.cpp

Lines changed: 4 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,4 @@
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
1+
// RUN: %clang_cc1 -emit-llvm-only -verify -std=c++11 %s
32
struct A {};
43

54
enum Foo { F };
@@ -149,13 +148,12 @@ namespace TwoPhaseLookup {
149148
namespace Template {
150149
template<typename T> struct Y {};
151150
template<class U> using G = Y<U>;
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>'}}
151+
template<typename T> void f(T *p) { p->~G<int>(); } // expected-error {{no member named 'G'}}
154152
void h1(Y<int> *p) { p->~G<int>(); }
155-
void h2(Y<int> *p) { f(p); } // since-cxx23-note {{in instantiation of}}
153+
void h2(Y<int> *p) { f(p); } // expected-note {{in instantiation of}}
156154
namespace N { template<typename T> struct G {}; }
157155
void h3(N::G<int> *p) { p->~G<int>(); }
158-
void h4(N::G<int> *p) { f(p); } // cxx98-20-note {{in instantiation of}}
156+
void h4(N::G<int> *p) { f(p); }
159157
}
160158

161159
namespace TemplateUndeclared {

clang/test/SemaCXX/static-assert-cxx17.cpp

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -98,7 +98,8 @@ void foo6() {
9898
// expected-error@-1{{static assertion failed due to requirement '(const X<int>[0]){} == nullptr'}}
9999
static_assert(sizeof(X<decltype(X<typename T::T>().X<typename T::T>::~X())>) == 0);
100100
// expected-error@-1{{static assertion failed due to requirement 'sizeof(X<void>) == 0'}} \
101-
// expected-note@-1 {{evaluates to '8 == 0'}}
101+
// expected-note@-1 {{evaluates to '8 == 0'}} \
102+
// expected-warning@-1 {{use 'template' keyword to treat 'X' as a dependent template name}}
102103
static_assert(constexpr_return_false<typename T::T, typename T::U>());
103104
// expected-error@-1{{static assertion failed due to requirement 'constexpr_return_false<int, float>()'}}
104105
}

clang/test/SemaTemplate/dependent-template-recover.cpp

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -7,15 +7,15 @@ struct X {
77

88
t->operator+<U const, 1>(1); // expected-warning{{use 'template' keyword to treat 'operator +' as a dependent template name}}
99
t->f1<int const, 2>(1); // expected-warning{{use 'template' keyword to treat 'f1' as a dependent template name}}
10-
t->f1<3, int const>(1); // expected-error{{missing 'template' keyword prior to dependent template name 'f1'}}
10+
t->f1<3, int const>(1); // expected-warning{{use 'template' keyword to treat 'f1' as a dependent template name}}
1111

1212
T::getAs<U>(); // expected-warning{{use 'template' keyword to treat 'getAs' as a dependent template name}}
1313
t->T::getAs<U>(); // expected-warning{{use 'template' keyword to treat 'getAs' as a dependent template name}}
1414

1515
(*t).f2<N>(); // expected-error{{missing 'template' keyword prior to dependent template name 'f2'}}
1616
(*t).f2<0>(); // expected-error{{missing 'template' keyword prior to dependent template name 'f2'}}
1717
T::f2<0>(); // expected-error{{missing 'template' keyword prior to dependent template name 'f2'}}
18-
T::f2<0, int>(0); // expected-error{{missing 'template' keyword prior to dependent template name 'f2'}}
18+
T::f2<0, int>(0); // expected-warning{{use 'template' keyword to treat 'f2' as a dependent template name}}
1919

2020
T::foo<N < 2 || N >= 4>(); // expected-error{{missing 'template' keyword prior to dependent template name 'foo'}}
2121

@@ -83,12 +83,14 @@ template<int N, typename T> void f(T t) {
8383
T::g<mb>(0);
8484

8585
// ... but this one must be a template-id.
86-
T::g<mb, int>(0); // expected-error {{missing 'template' keyword prior to dependent template name 'g'}}
86+
T::g<mb, int>(0); // expected-warning {{use 'template' keyword to treat 'g' as a dependent template name}}
87+
// expected-error@-1 {{no matching function for call to 'g'}}
8788
}
8889

8990
struct Y {
9091
template <int> void f(int);
9192
template <int = 0> static void g(int); // expected-warning 0-1{{extension}}
93+
// expected-note@-1 {{candidate template ignored: invalid explicitly-specified argument for 1st template parameter}}
9294
};
9395
void q() { void (*p)(int) = Y::g; }
9496
template void f<0>(Y); // expected-note {{in instantiation of}}

0 commit comments

Comments
 (0)