[clang] [Clang][Sema] Do not perform error recovery for invalid member using-declaration in C++20+ mode (PR #147003)
Yanzuo Liu via cfe-commits
cfe-commits at lists.llvm.org
Fri Jul 4 22:40:31 PDT 2025
https://github.com/zwuis updated https://github.com/llvm/llvm-project/pull/147003
>From 32e2c12d44da29e20212bdeed3628d4c736191ad Mon Sep 17 00:00:00 2001
From: Yanzuo Liu <zwuis at outlook.com>
Date: Fri, 4 Jul 2025 13:58:17 +0800
Subject: [PATCH] Do not perform error recovery for invalid member
using-declaration in C++20+ mode
---
clang/docs/ReleaseNotes.rst | 1 +
clang/lib/Sema/SemaDeclCXX.cpp | 2 +-
clang/test/SemaCXX/nested-name-spec.cpp | 40 ++++++++++++++++++-------
3 files changed, 31 insertions(+), 12 deletions(-)
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 at -1 {{candidate constructor (the implicit copy constructor)}}
+ // since-cxx11-note at -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
+};
+}
More information about the cfe-commits
mailing list