[libcxx-commits] [clang] [libcxx] [Clang] emit -Wignored-qualifiers diagnostic for cv-qualified base classes (PR #121419)
Oleksandr T. via libcxx-commits
libcxx-commits at lists.llvm.org
Mon Jan 20 14:51:26 PST 2025
https://github.com/a-tarasyuk updated https://github.com/llvm/llvm-project/pull/121419
>From 3f6b1d68978857035a972f49b1cfd9d9d0151be9 Mon Sep 17 00:00:00 2001
From: Oleksandr T <oleksandr.tarasiuk at outlook.com>
Date: Wed, 1 Jan 2025 01:47:17 +0200
Subject: [PATCH 1/6] [Clang] emit -Wignored-qualifiers diagnostic for
cv-qualified base classes
---
clang/docs/ReleaseNotes.rst | 1 +
.../clang/Basic/DiagnosticSemaKinds.td | 4 ++++
clang/lib/Sema/SemaDeclCXX.cpp | 9 +++++++++
.../SemaCXX/warn-base-type-qualifiers.cpp | 20 +++++++++++++++++++
4 files changed, 34 insertions(+)
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..294cfa24975a73 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>, DefaultIgnore;
+
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..b82ca1541ba249 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() && !isa<SubstTemplateTypeParmType>(BaseType)) {
+ 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/SemaCXX/warn-base-type-qualifiers.cpp b/clang/test/SemaCXX/warn-base-type-qualifiers.cpp
new file mode 100644
index 00000000000000..a5af7ec7415bf5
--- /dev/null
+++ b/clang/test/SemaCXX/warn-base-type-qualifiers.cpp
@@ -0,0 +1,20 @@
+// 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}}
+
+struct D {
+ D(int);
+};
+template <typename T> struct E : T {
+ using T::T;
+ E(int &) : E(0) {}
+};
+E<const D> e(1);
>From 397097340707dbefe5f4b07357523ff7ad515304 Mon Sep 17 00:00:00 2001
From: Oleksandr T <oleksandr.tarasiuk at outlook.com>
Date: Thu, 2 Jan 2025 17:06:05 +0200
Subject: [PATCH 2/6] use explicit variable type
---
clang/lib/Sema/SemaDeclCXX.cpp | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/clang/lib/Sema/SemaDeclCXX.cpp b/clang/lib/Sema/SemaDeclCXX.cpp
index b82ca1541ba249..c4ec7fa4742bdf 100644
--- a/clang/lib/Sema/SemaDeclCXX.cpp
+++ b/clang/lib/Sema/SemaDeclCXX.cpp
@@ -2656,7 +2656,7 @@ CXXBaseSpecifier *Sema::CheckBaseSpecifier(CXXRecordDecl *Class,
}
if (BaseType.hasQualifiers() && !isa<SubstTemplateTypeParmType>(BaseType)) {
- auto Quals =
+ std::string Quals =
BaseType.getQualifiers().getAsString(Context.getPrintingPolicy());
Diag(BaseLoc, diag::warn_qual_base_type)
<< Quals << std::count(Quals.begin(), Quals.end(), ' ') + 1
>From 3129f7521984c68969f3dd0140d6001b25ab1a28 Mon Sep 17 00:00:00 2001
From: Oleksandr T <oleksandr.tarasiuk at outlook.com>
Date: Fri, 3 Jan 2025 00:47:47 +0200
Subject: [PATCH 3/6] eliminate template type constraint and add additional
tests
---
clang/lib/Sema/SemaDeclCXX.cpp | 2 +-
.../SemaCXX/warn-base-type-qualifiers.cpp | 19 +++++++++++++++++--
2 files changed, 18 insertions(+), 3 deletions(-)
diff --git a/clang/lib/Sema/SemaDeclCXX.cpp b/clang/lib/Sema/SemaDeclCXX.cpp
index c4ec7fa4742bdf..9a471f8d4c9678 100644
--- a/clang/lib/Sema/SemaDeclCXX.cpp
+++ b/clang/lib/Sema/SemaDeclCXX.cpp
@@ -2655,7 +2655,7 @@ CXXBaseSpecifier *Sema::CheckBaseSpecifier(CXXRecordDecl *Class,
return nullptr;
}
- if (BaseType.hasQualifiers() && !isa<SubstTemplateTypeParmType>(BaseType)) {
+ if (BaseType.hasQualifiers()) {
std::string Quals =
BaseType.getQualifiers().getAsString(Context.getPrintingPolicy());
Diag(BaseLoc, diag::warn_qual_base_type)
diff --git a/clang/test/SemaCXX/warn-base-type-qualifiers.cpp b/clang/test/SemaCXX/warn-base-type-qualifiers.cpp
index a5af7ec7415bf5..b9fd577c574b99 100644
--- a/clang/test/SemaCXX/warn-base-type-qualifiers.cpp
+++ b/clang/test/SemaCXX/warn-base-type-qualifiers.cpp
@@ -1,5 +1,10 @@
// RUN: %clang_cc1 %s -std=c++11 -Wignored-qualifiers -verify
+template <typename T> struct add_const {
+ using type = const T;
+};
+template <typename T> using add_const_t = typename add_const<T>::type;
+
class A { };
typedef const A A_Const;
@@ -13,8 +18,18 @@ class C : public A_Const_Volatile { }; // expected-warning {{'const volatile' qu
struct D {
D(int);
};
-template <typename T> struct E : T {
+
+template <typename T> struct E : T { // expected-warning {{'const' qualifier on base class type 'const D' have no effect}} \
+ // expected-note {{base class 'const D' specified here}}
using T::T;
E(int &) : E(0) {}
};
-E<const D> e(1);
+E<const D> e(1); // expected-note {{in instantiation of template class 'E<const D>' requested here}}
+
+template <typename T>
+struct G : add_const<T>::type { // expected-warning {{'const' qualifier on base class type 'add_const<D>::type' (aka 'const D') have no effect}} \
+ // expected-note {{base class 'add_const<D>::type' (aka 'const D') specified here}}
+ using T::T;
+ G(int &) : G(0) {}
+};
+G<D> g(1); // expected-note {{in instantiation of template class 'G<D>' requested here}}
>From 4da4f21c679ddd2daebff4d86d47e235a79d9876 Mon Sep 17 00:00:00 2001
From: Oleksandr T <oleksandr.tarasiuk at outlook.com>
Date: Tue, 14 Jan 2025 00:07:27 +0200
Subject: [PATCH 4/6] remove cv-qualifiers from inherited classes in tuple
declaration
---
libcxx/include/tuple | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/libcxx/include/tuple b/libcxx/include/tuple
index b2478746f5e26a..955583e7dc57e7 100644
--- a/libcxx/include/tuple
+++ b/libcxx/include/tuple
@@ -257,6 +257,7 @@ template <class... Types>
# include <__type_traits/maybe_const.h>
# include <__type_traits/nat.h>
# include <__type_traits/negation.h>
+# include <__type_traits/remove_cv.h>
# include <__type_traits/remove_cvref.h>
# include <__type_traits/remove_reference.h>
# include <__type_traits/unwrap_ref.h>
@@ -535,7 +536,7 @@ __memberwise_forward_assign(_Dest& __dest, _Source&& __source, __tuple_types<_Up
template <class... _Tp>
class _LIBCPP_TEMPLATE_VIS tuple {
- typedef __tuple_impl<typename __make_tuple_indices<sizeof...(_Tp)>::type, _Tp...> _BaseT;
+ typedef __tuple_impl<typename __make_tuple_indices<sizeof...(_Tp)>::type, __remove_cv_t<_Tp>...> _BaseT;
_BaseT __base_;
>From 0c90ff82622cb9c3ceacd5183567a850c3eb813b Mon Sep 17 00:00:00 2001
From: Oleksandr T <oleksandr.tarasiuk at outlook.com>
Date: Tue, 14 Jan 2025 14:41:52 +0200
Subject: [PATCH 5/6] update tuple declaration
---
libcxx/include/tuple | 16 +++++++++-------
1 file changed, 9 insertions(+), 7 deletions(-)
diff --git a/libcxx/include/tuple b/libcxx/include/tuple
index 90257e9bae0acf..1c575cb4a6f5d5 100644
--- a/libcxx/include/tuple
+++ b/libcxx/include/tuple
@@ -391,7 +391,9 @@ public:
};
template <size_t _Ip, class _Hp>
-class __tuple_leaf<_Ip, _Hp, true> : private _Hp {
+class __tuple_leaf<_Ip, _Hp, true> : private __remove_cv_t<_Hp> {
+ typedef __remove_cv_t<_Hp> _BaseT;
+
public:
_LIBCPP_CONSTEXPR_SINCE_CXX14 __tuple_leaf& operator=(const __tuple_leaf&) = delete;
@@ -402,29 +404,29 @@ public:
template <class _Alloc>
_LIBCPP_HIDE_FROM_ABI constexpr __tuple_leaf(integral_constant<int, 1>, const _Alloc& __a)
- : _Hp(allocator_arg_t(), __a) {}
+ : _BaseT(allocator_arg_t(), __a) {}
template <class _Alloc>
- _LIBCPP_HIDE_FROM_ABI constexpr __tuple_leaf(integral_constant<int, 2>, const _Alloc& __a) : _Hp(__a) {}
+ _LIBCPP_HIDE_FROM_ABI constexpr __tuple_leaf(integral_constant<int, 2>, const _Alloc& __a) : _BaseT(__a) {}
template <class _Tp,
__enable_if_t< _And< _IsNotSame<__remove_cvref_t<_Tp>, __tuple_leaf>, is_constructible<_Hp, _Tp> >::value,
int> = 0>
_LIBCPP_HIDE_FROM_ABI
_LIBCPP_CONSTEXPR_SINCE_CXX14 explicit __tuple_leaf(_Tp&& __t) noexcept(is_nothrow_constructible<_Hp, _Tp>::value)
- : _Hp(std::forward<_Tp>(__t)) {}
+ : _BaseT(std::forward<_Tp>(__t)) {}
template <class _Tp, class _Alloc>
_LIBCPP_HIDE_FROM_ABI constexpr explicit __tuple_leaf(integral_constant<int, 0>, const _Alloc&, _Tp&& __t)
- : _Hp(std::forward<_Tp>(__t)) {}
+ : _BaseT(std::forward<_Tp>(__t)) {}
template <class _Tp, class _Alloc>
_LIBCPP_HIDE_FROM_ABI constexpr explicit __tuple_leaf(integral_constant<int, 1>, const _Alloc& __a, _Tp&& __t)
- : _Hp(allocator_arg_t(), __a, std::forward<_Tp>(__t)) {}
+ : _BaseT(allocator_arg_t(), __a, std::forward<_Tp>(__t)) {}
template <class _Tp, class _Alloc>
_LIBCPP_HIDE_FROM_ABI constexpr explicit __tuple_leaf(integral_constant<int, 2>, const _Alloc& __a, _Tp&& __t)
- : _Hp(std::forward<_Tp>(__t), __a) {}
+ : _BaseT(std::forward<_Tp>(__t), __a) {}
__tuple_leaf(__tuple_leaf const&) = default;
__tuple_leaf(__tuple_leaf&&) = default;
>From 3aa2e5f13d144384120dd6d22e23d4c3a62a8774 Mon Sep 17 00:00:00 2001
From: Oleksandr T <oleksandr.tarasiuk at outlook.com>
Date: Tue, 14 Jan 2025 15:17:59 +0200
Subject: [PATCH 6/6] update tuple declaration
---
libcxx/include/tuple | 16 +++++++---------
1 file changed, 7 insertions(+), 9 deletions(-)
diff --git a/libcxx/include/tuple b/libcxx/include/tuple
index 1c575cb4a6f5d5..cda72a2fbb041c 100644
--- a/libcxx/include/tuple
+++ b/libcxx/include/tuple
@@ -392,8 +392,6 @@ public:
template <size_t _Ip, class _Hp>
class __tuple_leaf<_Ip, _Hp, true> : private __remove_cv_t<_Hp> {
- typedef __remove_cv_t<_Hp> _BaseT;
-
public:
_LIBCPP_CONSTEXPR_SINCE_CXX14 __tuple_leaf& operator=(const __tuple_leaf&) = delete;
@@ -404,29 +402,29 @@ public:
template <class _Alloc>
_LIBCPP_HIDE_FROM_ABI constexpr __tuple_leaf(integral_constant<int, 1>, const _Alloc& __a)
- : _BaseT(allocator_arg_t(), __a) {}
+ : _Hp(allocator_arg_t(), __a) {}
template <class _Alloc>
- _LIBCPP_HIDE_FROM_ABI constexpr __tuple_leaf(integral_constant<int, 2>, const _Alloc& __a) : _BaseT(__a) {}
+ _LIBCPP_HIDE_FROM_ABI constexpr __tuple_leaf(integral_constant<int, 2>, const _Alloc& __a) : _Hp(__a) {}
template <class _Tp,
__enable_if_t< _And< _IsNotSame<__remove_cvref_t<_Tp>, __tuple_leaf>, is_constructible<_Hp, _Tp> >::value,
int> = 0>
_LIBCPP_HIDE_FROM_ABI
_LIBCPP_CONSTEXPR_SINCE_CXX14 explicit __tuple_leaf(_Tp&& __t) noexcept(is_nothrow_constructible<_Hp, _Tp>::value)
- : _BaseT(std::forward<_Tp>(__t)) {}
+ : _Hp(std::forward<_Tp>(__t)) {}
template <class _Tp, class _Alloc>
_LIBCPP_HIDE_FROM_ABI constexpr explicit __tuple_leaf(integral_constant<int, 0>, const _Alloc&, _Tp&& __t)
- : _BaseT(std::forward<_Tp>(__t)) {}
+ : _Hp(std::forward<_Tp>(__t)) {}
template <class _Tp, class _Alloc>
_LIBCPP_HIDE_FROM_ABI constexpr explicit __tuple_leaf(integral_constant<int, 1>, const _Alloc& __a, _Tp&& __t)
- : _BaseT(allocator_arg_t(), __a, std::forward<_Tp>(__t)) {}
+ : _Hp(allocator_arg_t(), __a, std::forward<_Tp>(__t)) {}
template <class _Tp, class _Alloc>
_LIBCPP_HIDE_FROM_ABI constexpr explicit __tuple_leaf(integral_constant<int, 2>, const _Alloc& __a, _Tp&& __t)
- : _BaseT(std::forward<_Tp>(__t), __a) {}
+ : _Hp(std::forward<_Tp>(__t), __a) {}
__tuple_leaf(__tuple_leaf const&) = default;
__tuple_leaf(__tuple_leaf&&) = default;
@@ -538,7 +536,7 @@ __memberwise_forward_assign(_Dest& __dest, _Source&& __source, __tuple_types<_Up
template <class... _Tp>
class _LIBCPP_TEMPLATE_VIS tuple {
- typedef __tuple_impl<typename __make_tuple_indices<sizeof...(_Tp)>::type, __remove_cv_t<_Tp>...> _BaseT;
+ typedef __tuple_impl<typename __make_tuple_indices<sizeof...(_Tp)>::type, _Tp...> _BaseT;
_BaseT __base_;
More information about the libcxx-commits
mailing list