Skip to content

[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

Merged
merged 2 commits into from
Jul 5, 2025

Conversation

zwuis
Copy link
Contributor

@zwuis zwuis commented Jul 4, 2025

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.

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

@llvmbot llvmbot added clang Clang issues not falling into any other category clang:frontend Language frontend issues, e.g. anything involving "Sema" labels Jul 4, 2025
@llvmbot
Copy link
Member

llvmbot commented Jul 4, 2025

@llvm/pr-subscribers-clang

Author: Yanzuo Liu (zwuis)

Changes

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.

template &lt;typename...&gt; struct V {};
struct S : V&lt;&gt; {
  using S::V; // error recovery here
  V&lt;&gt; 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:

  • (modified) clang/docs/ReleaseNotes.rst (+1)
  • (modified) clang/lib/Sema/SemaDeclCXX.cpp (+1-1)
  • (modified) clang/test/SemaCXX/nested-name-spec.cpp (+29-11)
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
+};
+}

Copy link
Contributor

@cor3ntin cor3ntin left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks!

@zwuis zwuis merged commit 3d6f4fb into llvm:main Jul 5, 2025
10 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
clang:frontend Language frontend issues, e.g. anything involving "Sema" clang Clang issues not falling into any other category
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Clang frontend C++ crash when using declaration refers to its own class c++20 and above
3 participants