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