https://github.com/a-tarasyuk created 
https://github.com/llvm/llvm-project/pull/121419

Fixes #55474 

>From a9fdfac9f8655b8def5f99adde75bb5f2176057a Mon Sep 17 00:00:00 2001
From: Oleksandr T <oleksandr.taras...@outlook.com>
Date: Wed, 1 Jan 2025 01:47:17 +0200
Subject: [PATCH] [Clang] emit -Wignored-qualifiers diagnostic for cv-qualified
 base classes

---
 clang/docs/ReleaseNotes.rst                        |  1 +
 clang/include/clang/Basic/DiagnosticSemaKinds.td   |  4 ++++
 clang/lib/Sema/SemaDeclCXX.cpp                     |  9 +++++++++
 clang/test/CXX/drs/cwg4xx.cpp                      |  3 ++-
 clang/test/CXX/special/class.inhctor/elsewhere.cpp |  5 +++--
 clang/test/Sema/GH70594.cpp                        | 13 +++++++------
 clang/test/SemaCXX/class-base-member-init.cpp      |  3 ++-
 clang/test/SemaCXX/warn-base-type-qualifiers.cpp   | 11 +++++++++++
 8 files changed, 39 insertions(+), 10 deletions(-)
 create mode 100644 clang/test/SemaCXX/warn-base-type-qualifiers.cpp

diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst
index b7da12bcf65818..659f0ebd97fc46 100644
--- a/clang/docs/ReleaseNotes.rst
+++ b/clang/docs/ReleaseNotes.rst
@@ -733,6 +733,7 @@ Improvements to Clang's diagnostics
       scope.Unlock();
       require(scope); // Warning!  Requires mu1.
     }
+- Clang now emits a ``-Wignored-qualifiers`` diagnostic when a base class 
includes cv-qualifiers (#GH55474).
 
 Improvements to Clang's time-trace
 ----------------------------------
diff --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td 
b/clang/include/clang/Basic/DiagnosticSemaKinds.td
index 330ae045616aba..ce8e9fc99dcbff 100644
--- a/clang/include/clang/Basic/DiagnosticSemaKinds.td
+++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td
@@ -487,6 +487,10 @@ def err_noreturn_non_function : Error<
 def warn_qual_return_type : Warning<
   "'%0' type qualifier%s1 on return type %plural{1:has|:have}1 no effect">,
   InGroup<IgnoredQualifiers>, DefaultIgnore;
+def warn_qual_base_type : Warning<
+  "'%0' qualifier%s1 on base class type %2 have no effect">,
+  InGroup<IgnoredQualifiers>;
+
 def warn_deprecated_redundant_constexpr_static_def : Warning<
   "out-of-line definition of constexpr static data member is redundant "
   "in C++17 and is deprecated">,
diff --git a/clang/lib/Sema/SemaDeclCXX.cpp b/clang/lib/Sema/SemaDeclCXX.cpp
index c5a72cf812ebc9..df0a15fc44e3e3 100644
--- a/clang/lib/Sema/SemaDeclCXX.cpp
+++ b/clang/lib/Sema/SemaDeclCXX.cpp
@@ -2655,6 +2655,15 @@ CXXBaseSpecifier *Sema::CheckBaseSpecifier(CXXRecordDecl 
*Class,
       return nullptr;
     }
 
+    if (BaseType.hasQualifiers()) {
+      auto Quals =
+          BaseType.getQualifiers().getAsString(Context.getPrintingPolicy());
+      Diag(BaseLoc, diag::warn_qual_base_type)
+          << Quals << std::count(Quals.begin(), Quals.end(), ' ') + 1
+          << BaseType;
+      Diag(BaseLoc, diag::note_base_class_specified_here) << BaseType;
+    }
+
     // For the MS ABI, propagate DLL attributes to base class templates.
     if (Context.getTargetInfo().getCXXABI().isMicrosoft() ||
         Context.getTargetInfo().getTriple().isPS()) {
diff --git a/clang/test/CXX/drs/cwg4xx.cpp b/clang/test/CXX/drs/cwg4xx.cpp
index 825065840f1181..0c3ed2f4ebf534 100644
--- a/clang/test/CXX/drs/cwg4xx.cpp
+++ b/clang/test/CXX/drs/cwg4xx.cpp
@@ -1309,7 +1309,8 @@ namespace cwg484 { // cwg484: yes
   }
   CA::A() {}
 
-  struct B : CA {
+  struct B : CA { // expected-warning {{'const' qualifier on base class type 
'CA' (aka 'const cwg484::A') have no effect}} \
+                  // expected-note {{base class 'CA' (aka 'const cwg484::A') 
specified here}}
     B() : CA() {}
     void f() { return CA::f(); }
   };
diff --git a/clang/test/CXX/special/class.inhctor/elsewhere.cpp 
b/clang/test/CXX/special/class.inhctor/elsewhere.cpp
index f86f4b86faa7d7..079422fd99d98a 100644
--- a/clang/test/CXX/special/class.inhctor/elsewhere.cpp
+++ b/clang/test/CXX/special/class.inhctor/elsewhere.cpp
@@ -57,9 +57,10 @@ template<typename T> struct F : D<bool> {
 F<bool> fb; // expected-note {{here}}
 
 template<typename T>
-struct G : T {
+struct G : T {        // expected-warning {{'const' qualifier on base class 
type 'const B1' have no effect}} \
+                      // expected-note {{base class 'const B1' specified here}}
   using T::T;
   G(int &) : G(0) {}
 };
 G<B1> g(123);
-G<const B1> g2(123);
+G<const B1> g2(123); // expected-note {{in instantiation of template class 
'G<const B1>' requested here}}
diff --git a/clang/test/Sema/GH70594.cpp b/clang/test/Sema/GH70594.cpp
index ce98e9b12b5cba..91ec31f6b053cb 100644
--- a/clang/test/Sema/GH70594.cpp
+++ b/clang/test/Sema/GH70594.cpp
@@ -1,12 +1,11 @@
 // RUN: %clang_cc1 -fsyntax-only -std=c++11 %s -verify
 // RUN: %clang_cc1 -fsyntax-only -std=c++23 %s -verify
 
-// expected-no-diagnostics
-
 struct A {};
 using CA = const A;
 
-struct S1 : CA {
+struct S1 : CA {           // expected-warning {{'const' qualifier on base 
class type 'CA' (aka 'const A') have no effect}} \
+                           // expected-note {{base class 'CA' (aka 'const A') 
specified here}}
   constexpr S1() : CA() {}
 };
 
@@ -14,15 +13,17 @@ struct S2 : A {
   constexpr S2() : CA() {}
 };
 
-struct S3 : CA {
+struct S3 : CA {          // expected-warning {{'const' qualifier on base 
class type 'CA' (aka 'const A') have no effect}} \
+                          // expected-note {{base class 'CA' (aka 'const A') 
specified here}}
   constexpr S3() : A() {}
 };
 
 struct Int {};
 
 template <class _Hp>
-struct __tuple_leaf : _Hp {
+struct __tuple_leaf : _Hp {           // expected-warning {{'const' qualifier 
on base class type 'const Int' have no effect}} \
+                                      // expected-note {{base class 'const 
Int' specified here}}
   constexpr __tuple_leaf() : _Hp() {}
 };
 
-constexpr __tuple_leaf<const Int> t;
+constexpr __tuple_leaf<const Int> t;  // expected-note {{in instantiation of 
template class '__tuple_leaf<const Int>' requested here}}
diff --git a/clang/test/SemaCXX/class-base-member-init.cpp 
b/clang/test/SemaCXX/class-base-member-init.cpp
index a6bb4410a81c84..e46c79a2b68b9c 100644
--- a/clang/test/SemaCXX/class-base-member-init.cpp
+++ b/clang/test/SemaCXX/class-base-member-init.cpp
@@ -103,7 +103,8 @@ namespace PR16596 {
   class A { public: virtual ~A(); };
   typedef const A Foo;
   void Apply(Foo processor);
-  struct Bar : public Foo {};
+  struct Bar : public Foo {}; // expected-warning {{'const' qualifier on base 
class type 'Foo' (aka 'const PR16596::A') have no effect}}\
+                              // expected-note {{base class 'Foo' (aka 'const 
PR16596::A') specified here}}
   void Fetch() {
     Apply(Bar());
   }
diff --git a/clang/test/SemaCXX/warn-base-type-qualifiers.cpp 
b/clang/test/SemaCXX/warn-base-type-qualifiers.cpp
new file mode 100644
index 00000000000000..5074140700cc36
--- /dev/null
+++ b/clang/test/SemaCXX/warn-base-type-qualifiers.cpp
@@ -0,0 +1,11 @@
+// RUN: %clang_cc1 %s -std=c++11 -Wignored-qualifiers -verify
+
+class A { };
+
+typedef const A A_Const;
+class B : public A_Const { }; // expected-warning {{'const' qualifier on base 
class type 'A_Const' (aka 'const A') have no effect}} \
+                              // expected-note {{base class 'A_Const' (aka 
'const A') specified here}}
+
+typedef const volatile A A_Const_Volatile;
+class C : public A_Const_Volatile { }; // expected-warning {{'const volatile' 
qualifiers on base class type 'A_Const_Volatile' (aka 'const volatile A') have 
no effect}} \
+                                       // expected-note {{base class 
'A_Const_Volatile' (aka 'const volatile A') specified here}}

_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to