[clang] [Clang][Sema] Fix crash in CheckUsingDeclQualifier due to diagnostic missing an argument (PR #161277)

Shafik Yaghmour via cfe-commits cfe-commits at lists.llvm.org
Tue Sep 30 13:38:07 PDT 2025


https://github.com/shafik updated https://github.com/llvm/llvm-project/pull/161277

>From 227d45e09c1fa20f35ca0142ba93276fe37e6ab0 Mon Sep 17 00:00:00 2001
From: Shafik Yaghmour <shafik.yaghmour at intel.com>
Date: Mon, 29 Sep 2025 13:54:54 -0700
Subject: [PATCH 1/3] [Clang][Sema] Fix crash in CheckUsingDeclQualifier due to
 diagnostic missing an argument

Crash report came in and it was pretty obvious the diagnostic line was just
missing an argument. I supplied the argument and added a test.

Fixes: https://github.com/llvm/llvm-project/issues/161072
---
 clang/lib/Sema/SemaDeclCXX.cpp      | 2 +-
 clang/test/SemaCXX/cxx98-compat.cpp | 4 ++++
 2 files changed, 5 insertions(+), 1 deletion(-)

diff --git a/clang/lib/Sema/SemaDeclCXX.cpp b/clang/lib/Sema/SemaDeclCXX.cpp
index 63ce87b9b0607..7fa411fd817ae 100644
--- a/clang/lib/Sema/SemaDeclCXX.cpp
+++ b/clang/lib/Sema/SemaDeclCXX.cpp
@@ -13643,7 +13643,7 @@ bool Sema::CheckUsingDeclQualifier(SourceLocation UsingLoc, bool HasTypename,
 
     if (Cxx20Enumerator) {
       Diag(NameLoc, diag::warn_cxx17_compat_using_decl_non_member_enumerator)
-          << SS.getRange();
+          << SS.getScopeRep() << SS.getRange();
       return false;
     }
 
diff --git a/clang/test/SemaCXX/cxx98-compat.cpp b/clang/test/SemaCXX/cxx98-compat.cpp
index 8e7acf73923e5..5651eee5a5c41 100644
--- a/clang/test/SemaCXX/cxx98-compat.cpp
+++ b/clang/test/SemaCXX/cxx98-compat.cpp
@@ -1,6 +1,7 @@
 // RUN: %clang_cc1 -fsyntax-only -std=c++11 -Wc++98-compat -verify %s
 // RUN: %clang_cc1 -fsyntax-only -std=c++14 -Wc++98-compat -verify %s -DCXX14COMPAT
 // RUN: %clang_cc1 -fsyntax-only -std=c++17 -Wc++98-compat -verify %s -DCXX14COMPAT -DCXX17COMPAT
+// RUN: %clang_cc1 -fsyntax-only -std=c++20 -Wc++98-compat -verify %s -DCXX14COMPAT -DCXX17COMPAT -DCXX20COMPAT
 
 namespace std {
   struct type_info;
@@ -225,9 +226,12 @@ void TrivialButNonPODThroughEllipsis() {
   Ellipsis(1, TrivialButNonPOD()); // expected-warning {{passing object of trivial but non-POD type 'TrivialButNonPOD' through variadic function is incompatible with C++98}}
 }
 
+// FIXME I think we generate this diagnostic in C++20
+#ifndef CXX20COMPAT
 struct HasExplicitConversion {
   explicit operator bool(); // expected-warning {{explicit conversion functions are incompatible with C++98}}
 };
+#endif
 
 struct Struct {};
 enum Enum { enum_val = 0 };

>From dece2b9c85709aa5733aeb30f16234ef474a05a7 Mon Sep 17 00:00:00 2001
From: Shafik Yaghmour <shafik.yaghmour at intel.com>
Date: Mon, 29 Sep 2025 16:25:01 -0700
Subject: [PATCH 2/3] Adding tests.

---
 clang/test/SemaCXX/cxx98-compat.cpp | 12 ++++++++++++
 1 file changed, 12 insertions(+)

diff --git a/clang/test/SemaCXX/cxx98-compat.cpp b/clang/test/SemaCXX/cxx98-compat.cpp
index 5651eee5a5c41..104ccb4640c11 100644
--- a/clang/test/SemaCXX/cxx98-compat.cpp
+++ b/clang/test/SemaCXX/cxx98-compat.cpp
@@ -434,3 +434,15 @@ void ctad_test() {
   CTAD t = s; // expected-warning {{class template argument deduction is incompatible with C++ standards before C++17}}
 }
 #endif
+
+namespace GH161702 {
+struct S {
+  enum E { A };
+  using E::A; // expected-warning {{enumeration type in nested name specifier is incompatible with C++98}}
+#ifndef CXX20COMPAT 
+	      // expected-error at -2 {{using declaration refers to its own class}}
+#else
+              // expected-warning at -4 {{member using declaration naming non-class ''E'' enumerator is incompatible with C++ standards before C++20}}
+#endif
+};
+}

>From 096c6e4dd039947366051d6c41320ffab56974fb Mon Sep 17 00:00:00 2001
From: Shafik Yaghmour <shafik.yaghmour at intel.com>
Date: Tue, 30 Sep 2025 13:37:40 -0700
Subject: [PATCH 3/3] Update test based on feedback.

---
 clang/test/SemaCXX/cxx98-compat.cpp | 7 +++----
 1 file changed, 3 insertions(+), 4 deletions(-)

diff --git a/clang/test/SemaCXX/cxx98-compat.cpp b/clang/test/SemaCXX/cxx98-compat.cpp
index 104ccb4640c11..692289cfa609e 100644
--- a/clang/test/SemaCXX/cxx98-compat.cpp
+++ b/clang/test/SemaCXX/cxx98-compat.cpp
@@ -1,7 +1,7 @@
 // RUN: %clang_cc1 -fsyntax-only -std=c++11 -Wc++98-compat -verify %s
 // RUN: %clang_cc1 -fsyntax-only -std=c++14 -Wc++98-compat -verify %s -DCXX14COMPAT
 // RUN: %clang_cc1 -fsyntax-only -std=c++17 -Wc++98-compat -verify %s -DCXX14COMPAT -DCXX17COMPAT
-// RUN: %clang_cc1 -fsyntax-only -std=c++20 -Wc++98-compat -verify %s -DCXX14COMPAT -DCXX17COMPAT -DCXX20COMPAT
+// RUN: %clang_cc1 -fsyntax-only -std=c++20 -Wc++98-compat -verify=expected,cpp20 %s -DCXX14COMPAT -DCXX17COMPAT -DCXX20COMPAT
 
 namespace std {
   struct type_info;
@@ -226,7 +226,7 @@ void TrivialButNonPODThroughEllipsis() {
   Ellipsis(1, TrivialButNonPOD()); // expected-warning {{passing object of trivial but non-POD type 'TrivialButNonPOD' through variadic function is incompatible with C++98}}
 }
 
-// FIXME I think we generate this diagnostic in C++20
+// FIXME I think we should generate this diagnostic in C++20
 #ifndef CXX20COMPAT
 struct HasExplicitConversion {
   explicit operator bool(); // expected-warning {{explicit conversion functions are incompatible with C++98}}
@@ -441,8 +441,7 @@ struct S {
   using E::A; // expected-warning {{enumeration type in nested name specifier is incompatible with C++98}}
 #ifndef CXX20COMPAT 
 	      // expected-error at -2 {{using declaration refers to its own class}}
-#else
-              // expected-warning at -4 {{member using declaration naming non-class ''E'' enumerator is incompatible with C++ standards before C++20}}
 #endif
+              // cpp20-warning at -4 {{member using declaration naming non-class ''E'' enumerator is incompatible with C++ standards before C++20}}
 };
 }



More information about the cfe-commits mailing list