Skip to content

Commit 3d6f4fb

Browse files
authored
[Clang][Sema] Do not perform error recovery for invalid member using-declaration in C++20+ mode (#147003)
Previously, Clang tried to perform error recovery for invalid member using-declaration whose nested-name-specifier refers to its own class in C++20+ mode, which causes crash. ```cpp template <typename...> struct V {}; struct S : V<> { using S::V; // error recovery here V<> v; // crash }; ``` This PR disables the error recovery to fix the crash. Fixes #63254
1 parent 9372f40 commit 3d6f4fb

File tree

3 files changed

+31
-12
lines changed

3 files changed

+31
-12
lines changed

clang/docs/ReleaseNotes.rst

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -900,6 +900,7 @@ Bug Fixes to C++ Support
900900
- Fixed an access checking bug when substituting into concepts (#GH115838)
901901
- Fix a bug where private access specifier of overloaded function not respected. (#GH107629)
902902
- Correctly handle allocations in the condition of a ``if constexpr``.(#GH120197) (#GH134820)
903+
- Fixed a crash when handling invalid member using-declaration in C++20+ mode. (#GH63254)
903904

904905
Bug Fixes to AST Handling
905906
^^^^^^^^^^^^^^^^^^^^^^^^^

clang/lib/Sema/SemaDeclCXX.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13638,7 +13638,7 @@ bool Sema::CheckUsingDeclQualifier(SourceLocation UsingLoc, bool HasTypename,
1363813638
Diag(SS.getBeginLoc(),
1363913639
diag::err_using_decl_nested_name_specifier_is_current_class)
1364013640
<< SS.getRange();
13641-
return !getLangOpts().CPlusPlus20;
13641+
return true;
1364213642
}
1364313643

1364413644
if (!cast<CXXRecordDecl>(NamedContext)->isInvalidDecl()) {

clang/test/SemaCXX/nested-name-spec.cpp

Lines changed: 29 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,11 @@
1-
// RUN: %clang_cc1 -fsyntax-only -std=c++98 -verify -fblocks %s
1+
// RUN: %clang_cc1 -fsyntax-only -std=c++98 -verify=expected,cxx98,cxx98-11 -fblocks %s
2+
// RUN: %clang_cc1 -fsyntax-only -std=c++11 -verify=expected,since-cxx11,cxx98-11 -fblocks %s
3+
// RUN: %clang_cc1 -fsyntax-only -std=c++14 -verify=expected,since-cxx11 -fblocks %s
4+
// RUN: %clang_cc1 -fsyntax-only -std=c++17 -verify=expected,since-cxx11 -fblocks %s
5+
// RUN: %clang_cc1 -fsyntax-only -std=c++20 -verify=expected,since-cxx11,since-cxx20 -fblocks %s
6+
// RUN: %clang_cc1 -fsyntax-only -std=c++23 -verify=expected,since-cxx11,since-cxx20 -fblocks %s
7+
// RUN: %clang_cc1 -fsyntax-only -std=c++26 -verify=expected,since-cxx11,since-cxx20 -fblocks %s
8+
29
namespace A {
310
struct C {
411
static int cx;
@@ -118,7 +125,7 @@ namespace E {
118125
};
119126

120127
int f() {
121-
return E::X; // expected-warning{{use of enumeration in a nested name specifier is a C++11 extension}}
128+
return E::X; // cxx98-warning{{use of enumeration in a nested name specifier is a C++11 extension}}
122129
}
123130
}
124131
}
@@ -170,8 +177,9 @@ void ::global_func2(int) { } // expected-warning{{extra qualification on member
170177

171178
void N::f() { } // okay
172179

173-
struct Y; // expected-note{{forward declaration of 'Y'}}
174-
Y::foo y; // expected-error{{incomplete type 'Y' named in nested name specifier}}
180+
// FIXME (GH147000): duplicate diagnostics
181+
struct Y; // expected-note{{forward declaration of 'Y'}} since-cxx20-note{{forward declaration of 'Y'}}
182+
Y::foo y; // expected-error{{incomplete type 'Y' named in nested name specifier}} since-cxx20-error{{incomplete type 'Y' named in nested name specifier}}
175183

176184
namespace PR25156 {
177185
struct Y; // expected-note{{forward declaration of 'PR25156::Y'}}
@@ -189,7 +197,9 @@ bool (foo_S::value);
189197

190198

191199
namespace somens {
192-
struct a { }; // expected-note{{candidate constructor (the implicit copy constructor)}}
200+
struct a { };
201+
// expected-note@-1 {{candidate constructor (the implicit copy constructor)}}
202+
// since-cxx11-note@-2 {{candidate constructor (the implicit move constructor)}}
193203
}
194204

195205
template <typename T>
@@ -432,20 +442,20 @@ namespace PR16951 {
432442
};
433443
}
434444

435-
int x1 = ns::an_enumeration::ENUMERATOR; // expected-warning{{use of enumeration in a nested name specifier is a C++11 extension}}
445+
int x1 = ns::an_enumeration::ENUMERATOR; // cxx98-warning{{use of enumeration in a nested name specifier is a C++11 extension}}
436446

437-
int x2 = ns::an_enumeration::ENUMERATOR::vvv; // expected-warning{{use of enumeration in a nested name specifier is a C++11 extension}} \
447+
int x2 = ns::an_enumeration::ENUMERATOR::vvv; // cxx98-warning{{use of enumeration in a nested name specifier is a C++11 extension}} \
438448
// expected-error{{'ENUMERATOR' is not a class, namespace, or enumeration}} \
439449
440-
int x3 = ns::an_enumeration::X; // expected-warning{{use of enumeration in a nested name specifier is a C++11 extension}} \
450+
int x3 = ns::an_enumeration::X; // cxx98-warning {{use of enumeration in a nested name specifier is a C++11 extension}} \
441451
// expected-error{{no member named 'X'}}
442452

443453
enum enumerator_2 {
444454
ENUMERATOR_2
445455
};
446456

447-
int x4 = enumerator_2::ENUMERATOR_2; // expected-warning{{use of enumeration in a nested name specifier is a C++11 extension}}
448-
int x5 = enumerator_2::X2; // expected-warning{{use of enumeration in a nested name specifier is a C++11 extension}} \
457+
int x4 = enumerator_2::ENUMERATOR_2; // cxx98-warning{{use of enumeration in a nested name specifier is a C++11 extension}}
458+
int x5 = enumerator_2::X2; // cxx98-warning{{use of enumeration in a nested name specifier is a C++11 extension}} \
449459
// expected-error{{no member named 'X2' in 'PR16951::enumerator_2'}} \
450460
// expected-error{{cannot initialize a variable of type 'int' with an lvalue of type 'int (*)()'}}
451461

@@ -487,7 +497,7 @@ struct x; // expected-note {{template is declared here}}
487497

488498
template <typename T>
489499
int issue55962 = x::a; // expected-error {{use of class template 'x' requires template arguments}} \
490-
// expected-warning {{variable templates are a C++14 extension}}
500+
// cxx98-11-warning {{variable templates are a C++14 extension}}
491501

492502
namespace ForwardDeclared {
493503
typedef class A B;
@@ -496,3 +506,11 @@ namespace ForwardDeclared {
496506
void F(B::C);
497507
};
498508
}
509+
510+
namespace GH63254 {
511+
template <typename...> struct V {}; // cxx98-warning {{variadic templates are a C++11 extension}}
512+
struct S : V<> {
513+
using S::V; // expected-error {{using declaration refers to its own class}}
514+
V<> v; // no crash
515+
};
516+
}

0 commit comments

Comments
 (0)