-
Notifications
You must be signed in to change notification settings - Fork 14.6k
[Clang][Sema] Do not perform error recovery for invalid member using-declaration in C++20+ mode #147003
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
Conversation
@llvm/pr-subscribers-clang Author: Yanzuo Liu (zwuis) ChangesPreviously, 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. 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 Full diff: https://github.com/llvm/llvm-project/pull/147003.diff 3 Files Affected:
diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst
index 73a80b6272d84..53fe56a270001 100644
--- a/clang/docs/ReleaseNotes.rst
+++ b/clang/docs/ReleaseNotes.rst
@@ -899,6 +899,7 @@ Bug Fixes to C++ Support
- Fixed a crash when constant evaluating some explicit object member assignment operators. (#GH142835)
- Fixed an access checking bug when substituting into concepts (#GH115838)
- Fix a bug where private access specifier of overloaded function not respected. (#GH107629)
+- Fixed a crash when handling invalid member using-declaration in C++20+ mode. (#GH63254)
Bug Fixes to AST Handling
^^^^^^^^^^^^^^^^^^^^^^^^^
diff --git a/clang/lib/Sema/SemaDeclCXX.cpp b/clang/lib/Sema/SemaDeclCXX.cpp
index 773148500f0af..f0247f865ba40 100644
--- a/clang/lib/Sema/SemaDeclCXX.cpp
+++ b/clang/lib/Sema/SemaDeclCXX.cpp
@@ -13638,7 +13638,7 @@ bool Sema::CheckUsingDeclQualifier(SourceLocation UsingLoc, bool HasTypename,
Diag(SS.getBeginLoc(),
diag::err_using_decl_nested_name_specifier_is_current_class)
<< SS.getRange();
- return !getLangOpts().CPlusPlus20;
+ return true;
}
if (!cast<CXXRecordDecl>(NamedContext)->isInvalidDecl()) {
diff --git a/clang/test/SemaCXX/nested-name-spec.cpp b/clang/test/SemaCXX/nested-name-spec.cpp
index abeaba9d8dde2..fedbb3070070b 100644
--- a/clang/test/SemaCXX/nested-name-spec.cpp
+++ b/clang/test/SemaCXX/nested-name-spec.cpp
@@ -1,4 +1,11 @@
-// RUN: %clang_cc1 -fsyntax-only -std=c++98 -verify -fblocks %s
+// RUN: %clang_cc1 -fsyntax-only -std=c++98 -verify=expected,cxx98,cxx98-11 -fblocks %s
+// RUN: %clang_cc1 -fsyntax-only -std=c++11 -verify=expected,since-cxx11,cxx98-11 -fblocks %s
+// RUN: %clang_cc1 -fsyntax-only -std=c++14 -verify=expected,since-cxx11 -fblocks %s
+// RUN: %clang_cc1 -fsyntax-only -std=c++17 -verify=expected,since-cxx11 -fblocks %s
+// RUN: %clang_cc1 -fsyntax-only -std=c++20 -verify=expected,since-cxx11,since-cxx20 -fblocks %s
+// RUN: %clang_cc1 -fsyntax-only -std=c++23 -verify=expected,since-cxx11,since-cxx20 -fblocks %s
+// RUN: %clang_cc1 -fsyntax-only -std=c++26 -verify=expected,since-cxx11,since-cxx20 -fblocks %s
+
namespace A {
struct C {
static int cx;
@@ -118,7 +125,7 @@ namespace E {
};
int f() {
- return E::X; // expected-warning{{use of enumeration in a nested name specifier is a C++11 extension}}
+ return E::X; // cxx98-warning{{use of enumeration in a nested name specifier is a C++11 extension}}
}
}
}
@@ -170,8 +177,9 @@ void ::global_func2(int) { } // expected-warning{{extra qualification on member
void N::f() { } // okay
-struct Y; // expected-note{{forward declaration of 'Y'}}
-Y::foo y; // expected-error{{incomplete type 'Y' named in nested name specifier}}
+// FIXME (GH147000): duplicate diagnostics
+struct Y; // expected-note{{forward declaration of 'Y'}} since-cxx20-note{{forward declaration of 'Y'}}
+Y::foo y; // expected-error{{incomplete type 'Y' named in nested name specifier}} since-cxx20-error{{incomplete type 'Y' named in nested name specifier}}
namespace PR25156 {
struct Y; // expected-note{{forward declaration of 'PR25156::Y'}}
@@ -189,7 +197,9 @@ bool (foo_S::value);
namespace somens {
- struct a { }; // expected-note{{candidate constructor (the implicit copy constructor)}}
+ struct a { };
+ // expected-note@-1 {{candidate constructor (the implicit copy constructor)}}
+ // since-cxx11-note@-2 {{candidate constructor (the implicit move constructor)}}
}
template <typename T>
@@ -432,20 +442,20 @@ namespace PR16951 {
};
}
- int x1 = ns::an_enumeration::ENUMERATOR; // expected-warning{{use of enumeration in a nested name specifier is a C++11 extension}}
+ int x1 = ns::an_enumeration::ENUMERATOR; // cxx98-warning{{use of enumeration in a nested name specifier is a C++11 extension}}
- int x2 = ns::an_enumeration::ENUMERATOR::vvv; // expected-warning{{use of enumeration in a nested name specifier is a C++11 extension}} \
+ int x2 = ns::an_enumeration::ENUMERATOR::vvv; // cxx98-warning{{use of enumeration in a nested name specifier is a C++11 extension}} \
// expected-error{{'ENUMERATOR' is not a class, namespace, or enumeration}} \
- int x3 = ns::an_enumeration::X; // expected-warning{{use of enumeration in a nested name specifier is a C++11 extension}} \
+ int x3 = ns::an_enumeration::X; // cxx98-warning {{use of enumeration in a nested name specifier is a C++11 extension}} \
// expected-error{{no member named 'X'}}
enum enumerator_2 {
ENUMERATOR_2
};
- int x4 = enumerator_2::ENUMERATOR_2; // expected-warning{{use of enumeration in a nested name specifier is a C++11 extension}}
- int x5 = enumerator_2::X2; // expected-warning{{use of enumeration in a nested name specifier is a C++11 extension}} \
+ int x4 = enumerator_2::ENUMERATOR_2; // cxx98-warning{{use of enumeration in a nested name specifier is a C++11 extension}}
+ int x5 = enumerator_2::X2; // cxx98-warning{{use of enumeration in a nested name specifier is a C++11 extension}} \
// expected-error{{no member named 'X2' in 'PR16951::enumerator_2'}} \
// expected-error{{cannot initialize a variable of type 'int' with an lvalue of type 'int (*)()'}}
@@ -487,7 +497,7 @@ struct x; // expected-note {{template is declared here}}
template <typename T>
int issue55962 = x::a; // expected-error {{use of class template 'x' requires template arguments}} \
- // expected-warning {{variable templates are a C++14 extension}}
+ // cxx98-11-warning {{variable templates are a C++14 extension}}
namespace ForwardDeclared {
typedef class A B;
@@ -496,3 +506,11 @@ namespace ForwardDeclared {
void F(B::C);
};
}
+
+namespace GH63254 {
+template <typename...> struct V {}; // cxx98-warning {{variadic templates are a C++11 extension}}
+struct S : V<> {
+ using S::V; // expected-error {{using declaration refers to its own class}}
+ V<> v; // no crash
+};
+}
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks!
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.
This PR disables the error recovery to fix the crash.
Fixes #63254