https://github.com/berkaysahiin updated https://github.com/llvm/llvm-project/pull/189733
>From 8343df89f949fa30c75cbdd09130b08649577dee Mon Sep 17 00:00:00 2001 From: Berkay Sahin <[email protected]> Date: Tue, 31 Mar 2026 22:20:46 +0300 Subject: [PATCH 01/15] [clang-tidy] Adds readability-redundant-const check --- .../clang-tidy/readability/CMakeLists.txt | 1 + .../readability/ReadabilityTidyModule.cpp | 3 + .../readability/RedundantConstCheck.cpp | 106 ++++++++++++ .../readability/RedundantConstCheck.h | 31 ++++ clang-tools-extra/docs/ReleaseNotes.rst | 5 + .../docs/clang-tidy/checks/list.rst | 1 + .../checks/readability/redundant-const.rst | 49 ++++++ .../checkers/readability/redundant-const.cpp | 156 ++++++++++++++++++ 8 files changed, 352 insertions(+) create mode 100644 clang-tools-extra/clang-tidy/readability/RedundantConstCheck.cpp create mode 100644 clang-tools-extra/clang-tidy/readability/RedundantConstCheck.h create mode 100644 clang-tools-extra/docs/clang-tidy/checks/readability/redundant-const.rst create mode 100644 clang-tools-extra/test/clang-tidy/checkers/readability/redundant-const.cpp diff --git a/clang-tools-extra/clang-tidy/readability/CMakeLists.txt b/clang-tools-extra/clang-tidy/readability/CMakeLists.txt index 686e7c19d650b..95fb26b1fa7ac 100644 --- a/clang-tools-extra/clang-tidy/readability/CMakeLists.txt +++ b/clang-tools-extra/clang-tidy/readability/CMakeLists.txt @@ -41,6 +41,7 @@ add_clang_library(clangTidyReadabilityModule STATIC ReadabilityTidyModule.cpp RedundantAccessSpecifiersCheck.cpp RedundantCastingCheck.cpp + RedundantConstCheck.cpp RedundantControlFlowCheck.cpp RedundantDeclarationCheck.cpp RedundantFunctionPtrDereferenceCheck.cpp diff --git a/clang-tools-extra/clang-tidy/readability/ReadabilityTidyModule.cpp b/clang-tools-extra/clang-tidy/readability/ReadabilityTidyModule.cpp index 8e9e00b23c84a..090bc073cab93 100644 --- a/clang-tools-extra/clang-tidy/readability/ReadabilityTidyModule.cpp +++ b/clang-tools-extra/clang-tidy/readability/ReadabilityTidyModule.cpp @@ -42,6 +42,7 @@ #include "QualifiedAutoCheck.h" #include "RedundantAccessSpecifiersCheck.h" #include "RedundantCastingCheck.h" +#include "RedundantConstCheck.h" #include "RedundantControlFlowCheck.h" #include "RedundantDeclarationCheck.h" #include "RedundantFunctionPtrDereferenceCheck.h" @@ -141,6 +142,8 @@ class ReadabilityModule : public ClangTidyModule { "readability-redundant-access-specifiers"); CheckFactories.registerCheck<RedundantCastingCheck>( "readability-redundant-casting"); + CheckFactories.registerCheck<RedundantConstCheck>( + "readability-redundant-const"); CheckFactories.registerCheck<RedundantFunctionPtrDereferenceCheck>( "readability-redundant-function-ptr-dereference"); CheckFactories.registerCheck<RedundantMemberInitCheck>( diff --git a/clang-tools-extra/clang-tidy/readability/RedundantConstCheck.cpp b/clang-tools-extra/clang-tidy/readability/RedundantConstCheck.cpp new file mode 100644 index 0000000000000..1956f9a78e495 --- /dev/null +++ b/clang-tools-extra/clang-tidy/readability/RedundantConstCheck.cpp @@ -0,0 +1,106 @@ +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#include "RedundantConstCheck.h" +#include "../utils/LexerUtils.h" +#include "clang/ASTMatchers/ASTMatchFinder.h" +#include "clang/ASTMatchers/ASTMatchers.h" +#include <optional> + +using namespace clang::ast_matchers; + +namespace clang::tidy::readability { + +static const internal::VariadicDynCastAllOfMatcher<Decl, VarTemplateDecl> + varTemplateDecl; + +static std::optional<Token> +findConstToRemove(const VarDecl *VD, const MatchFinder::MatchResult &Result) { + const SourceManager &SM = *Result.SourceManager; + + const SourceLocation NameBeginLoc = VD->getQualifier() + ? VD->getQualifierLoc().getBeginLoc() + : VD->getLocation(); + + const bool IsPointer = VD->getType()->isPointerType() || + VD->getType()->isNullPtrType() || + VD->getType()->isMemberPointerType(); + + const auto ConstSearchStartLoc = [&]() -> std::optional<SourceLocation> { + if (!IsPointer) + return VD->getBeginLoc(); + + SourceLocation StarLoc = utils::lexer::findPreviousTokenKind( + NameBeginLoc, SM, Result.Context->getLangOpts(), tok::star); + + if (StarLoc.isValid()) + return StarLoc; + + // We know it is a pointer but cannot find the start token. + // This can happen when either type is aliased or `auto` was used. + // e.g: constexpr const auto const str = "hello"; + // In cases like this, clang analyzer already warns about the use of const + // as duplicate, so we can safely ignore these cases. + + return std::nullopt; + }(); + + if (!ConstSearchStartLoc || !ConstSearchStartLoc->isValid()) + return std::nullopt; + + const CharSourceRange FileRange = Lexer::makeFileCharRange( + CharSourceRange::getCharRange(*ConstSearchStartLoc, NameBeginLoc), SM, + Result.Context->getLangOpts()); + + if (!FileRange.isValid()) + return std::nullopt; + + return utils::lexer::getQualifyingToken(tok::kw_const, FileRange, + *Result.Context, SM); +} + +RedundantConstCheck::RedundantConstCheck(StringRef Name, + ClangTidyContext *Context) + : ClangTidyCheck(Name, Context) {} + +void RedundantConstCheck::registerMatchers(MatchFinder *Finder) { + Finder->addMatcher( + varDecl(isConstexpr(), unless(anyOf(hasAncestor(varTemplateDecl()), + hasType(referenceType())))) + .bind("var_decl"), + this); +} + +void RedundantConstCheck::check(const MatchFinder::MatchResult &Result) { + const auto *VD = Result.Nodes.getNodeAs<VarDecl>("var_decl"); + + // Since we cannot tell the difference between `constexpr const` and + // `constexpr` from the AST only, if we cannot find the actual `const` token, + // we cannot do anything + const std::optional<Token> Tok = findConstToRemove(VD, Result); + if (!Tok) + return; + + const auto ConstRange = + CharSourceRange::getCharRange(Tok->getLocation(), Tok->getEndLoc()); + diag(Tok->getLocation(), + "redundant 'const' in constexpr variable declaration") + << ConstRange << FixItHint::CreateRemoval(ConstRange); +} + +bool RedundantConstCheck::isLanguageVersionSupported( + const LangOptions &LangOpts) const { + return LangOpts.CPlusPlus11; +} + +std::optional<TraversalKind> +RedundantConstCheck::getCheckTraversalKind() const { + return TK_IgnoreUnlessSpelledInSource; +} + +} // namespace clang::tidy::readability diff --git a/clang-tools-extra/clang-tidy/readability/RedundantConstCheck.h b/clang-tools-extra/clang-tidy/readability/RedundantConstCheck.h new file mode 100644 index 0000000000000..882fe4f036f03 --- /dev/null +++ b/clang-tools-extra/clang-tidy/readability/RedundantConstCheck.h @@ -0,0 +1,31 @@ +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_READABILITY_REDUNDANTCONSTCHECK_H +#define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_READABILITY_REDUNDANTCONSTCHECK_H + +#include "../ClangTidyCheck.h" + +namespace clang::tidy::readability { + +/// Detects redundant `const` specifiers on variable declarations. +// +/// For the user-facing documentation see: +/// https://clang.llvm.org/extra/clang-tidy/checks/readability/redundant-const.html +class RedundantConstCheck : public ClangTidyCheck { +public: + RedundantConstCheck(StringRef Name, ClangTidyContext *Context); + void registerMatchers(ast_matchers::MatchFinder *Finder) override; + void check(const ast_matchers::MatchFinder::MatchResult &Result) override; + bool isLanguageVersionSupported(const LangOptions &LangOpts) const override; + std::optional<TraversalKind> getCheckTraversalKind() const override; +}; + +} // namespace clang::tidy::readability + +#endif // LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_READABILITY_REDUNDANTCONSTCHECK_H diff --git a/clang-tools-extra/docs/ReleaseNotes.rst b/clang-tools-extra/docs/ReleaseNotes.rst index 97b2ffdd9557b..3312beebcff55 100644 --- a/clang-tools-extra/docs/ReleaseNotes.rst +++ b/clang-tools-extra/docs/ReleaseNotes.rst @@ -163,6 +163,11 @@ New checks Finds redundant identity type aliases that re-expose a qualified name and can be replaced with a ``using`` declaration. +- New :doc:`readability-redundant-const + <clang-tidy/checks/readability/redundant-const>` check. + + Detects redundant ``const`` specifiers on variable declarations. + - New :doc:`readability-trailing-comma <clang-tidy/checks/readability/trailing-comma>` check. diff --git a/clang-tools-extra/docs/clang-tidy/checks/list.rst b/clang-tools-extra/docs/clang-tidy/checks/list.rst index ceab1e9414951..427babef23c9b 100644 --- a/clang-tools-extra/docs/clang-tidy/checks/list.rst +++ b/clang-tools-extra/docs/clang-tidy/checks/list.rst @@ -410,6 +410,7 @@ Clang-Tidy Checks :doc:`readability-qualified-auto <readability/qualified-auto>`, "Yes" :doc:`readability-redundant-access-specifiers <readability/redundant-access-specifiers>`, "Yes" :doc:`readability-redundant-casting <readability/redundant-casting>`, "Yes" + :doc:`readability-redundant-const <readability/redundant-const>`, "Yes" :doc:`readability-redundant-control-flow <readability/redundant-control-flow>`, "Yes" :doc:`readability-redundant-declaration <readability/redundant-declaration>`, "Yes" :doc:`readability-redundant-function-ptr-dereference <readability/redundant-function-ptr-dereference>`, "Yes" diff --git a/clang-tools-extra/docs/clang-tidy/checks/readability/redundant-const.rst b/clang-tools-extra/docs/clang-tidy/checks/readability/redundant-const.rst new file mode 100644 index 0000000000000..ed6957f21e312 --- /dev/null +++ b/clang-tools-extra/docs/clang-tidy/checks/readability/redundant-const.rst @@ -0,0 +1,49 @@ +.. title:: clang-tidy - readability-redundant-const + +readability-redundant-const +============================= + +Detects redundant ``const`` specifiers on variable declarations. + +Examples: + +.. code-block:: c++ + + // Finds: + constexpr const int var = {}; // redundant use of `const` + // replaced by: + constexpr int var = {}; + + // Finds: + constexpr const int arr[] = {}; // redundant use of `const` + // replaced by: + constexpr int arr[] = {}; + +In the examples above, use of ``const`` is redundant since ``constexpr`` +variables are implicitly ``const``. + +The check also analyzes pointers: + +.. code-block:: c++ + + // Finds: + constexpr int* const ptr = nullptr; // redundant use of `const` + // replaced by: + constexpr int* ptr = nullptr; + + // Finds: + constexpr int (*const func)(int) = nullptr; // redundant use of `const` + // replaced by: + constexpr int (*func)(int) = nullptr; + + // Finds: + constexpr const char* const greet = "hi"; // redundant use of `const` + // replaced by: + constexpr const char* greet = "hi"; + + // Note that `constexpr` only makes the pointer const but not the pointee. + // Thus, this usage is *not* redundant. + constexpr const char* ok = "ok"; // OK + + +Requires C++11 or above. diff --git a/clang-tools-extra/test/clang-tidy/checkers/readability/redundant-const.cpp b/clang-tools-extra/test/clang-tidy/checkers/readability/redundant-const.cpp new file mode 100644 index 0000000000000..6a49e9837b414 --- /dev/null +++ b/clang-tools-extra/test/clang-tidy/checkers/readability/redundant-const.cpp @@ -0,0 +1,156 @@ +// RUN: %check_clang_tidy -std=c++11-or-later %s readability-redundant-const %t -- + +struct Foo {}; + +// Simple allowed usages, nothing to warn +constexpr int n1 = 10; +const int n2 = 20; +constexpr Foo n3 = {}; + +constexpr const int p1 = 10; +// CHECK-MESSAGES: [[@LINE-1]]:11: warning: redundant 'const' in constexpr variable declaration +// CHECK-FIXES: constexpr int p1 = 10; + +const constexpr int p2 = 20; +// CHECK-MESSAGES: [[@LINE-1]]:1: warning: redundant 'const' in constexpr variable declaration +// CHECK-FIXES: constexpr int p2 = 20; + +static const constexpr int p3 = 20; +// CHECK-MESSAGES: [[@LINE-1]]:8: warning: redundant 'const' in constexpr variable declaration +// CHECK-FIXES: static constexpr int p3 = 20; + +constexpr const Foo p4 = {}; +// CHECK-MESSAGES: [[@LINE-1]]:11: warning: redundant 'const' in constexpr variable declaration +// CHECK-FIXES: constexpr Foo p4 = {}; + +// Since constexpr makes only the pointer const, this usage is not redundant. +constexpr const char* n4 = "hello"; + +constexpr const char* const n5 = "hello"; +// CHECK-MESSAGES: [[@LINE-1]]:23: warning: redundant 'const' in constexpr variable declaration +// CHECK-FIXES: constexpr const char* n5 = "hello"; + +// Since T might be a pointer type, we don't warn on this. +template<typename T> +const constexpr T n6 = {}; + +constexpr const int* n7 = n6<int*>; + +const constexpr double p5 = n6<double>; +// CHECK-MESSAGES: [[@LINE-1]]:1: warning: redundant 'const' in constexpr variable declaration +// CHECK-FIXES: constexpr double p5 = n6<double>; + +constexpr const int* const p6 = n6<int*>; +// CHECK-MESSAGES: [[@LINE-1]]:22: warning: redundant 'const' in constexpr variable declaration +// CHECK-FIXES: constexpr const int* p6 = n6<int*>; + +void f() { + constexpr Foo n1 = {}; + const Foo n2 = {}; + + const constexpr Foo p1 = {}; + // CHECK-MESSAGES: [[@LINE-1]]:3: warning: redundant 'const' in constexpr variable declaration + // CHECK-FIXES: constexpr Foo p1 = {}; + + static const constexpr Foo p2 = {}; + // CHECK-MESSAGES: [[@LINE-1]]:10: warning: redundant 'const' in constexpr variable declaration + // CHECK-FIXES: static constexpr Foo p2 = {}; +} + +struct Config { + static const constexpr bool p = false; + // CHECK-MESSAGES: [[@LINE-1]]:12: warning: redundant 'const' in constexpr variable declaration + // CHECK-FIXES: static constexpr bool p = false; +}; + +template <typename T> +class Templated { + static const constexpr int size = 10; + // CHECK-MESSAGES: [[@LINE-1]]:12: warning: redundant 'const' in constexpr variable declaration + // CHECK-FIXES: static constexpr int size = 10; + int data[size]; +}; + +constexpr Templated<int> b{}; + +template <int N> +struct Templated2 { + static const constexpr int size = N; + // CHECK-MESSAGES: [[@LINE-1]]:12: warning: redundant 'const' in constexpr variable declaration + // CHECK-FIXES: static constexpr int size = N; + int data[size]; +}; + +static constexpr int n8[] = {0, 1, 4, 9, 16}; + +constexpr const int p7[] = {0, 1, 4, 9, 16}; +// CHECK-MESSAGES: [[@LINE-1]]:11: warning: redundant 'const' in constexpr variable declaration +// CHECK-FIXES: constexpr int p7[] = {0, 1, 4, 9, 16}; + +constexpr int square(int n) { return n * n; } + +const constexpr int p8 = square(10); +// CHECK-MESSAGES: [[@LINE-1]]:1: warning: redundant 'const' in constexpr variable declaration +// CHECK-FIXES: constexpr int p8 = square(10); + +constexpr int n9 = square(5); + +constexpr Foo** n10 = nullptr; + +constexpr Foo* const* n11 = nullptr; + +constexpr Foo* const* const p9 = nullptr; +// CHECK-MESSAGES: [[@LINE-1]]:23: warning: redundant 'const' in constexpr variable declaration +// CHECK-FIXES: constexpr Foo* const* p9 = nullptr; + +constexpr const Foo* const* const p10 = nullptr; +// CHECK-MESSAGES: [[@LINE-1]]:29: warning: redundant 'const' in constexpr variable declaration +// CHECK-FIXES: constexpr const Foo* const* p10 = nullptr; + +constexpr const int (*n12)[10] = nullptr; + +constexpr const int (*const p11)[10] = nullptr; +// CHECK-MESSAGES: [[@LINE-1]]:23: warning: redundant 'const' in constexpr variable declaration +// CHECK-FIXES: constexpr const int (*p11)[10] = nullptr; + +constexpr int (*n13)(int) = nullptr; + +constexpr int (*const p12)(int) = nullptr; +// CHECK-MESSAGES: [[@LINE-1]]:17: warning: redundant 'const' in constexpr variable declaration +// CHECK-FIXES: constexpr int (*p12)(int) = nullptr; + +struct Bar { + int x, y; + int sum() { return x + y; } +}; + +// Pointer to data member +constexpr const int Bar::*n14 = &Bar::x; + +// Pointer to data member +constexpr const int Bar::* const p13 = &Bar::x; +// CHECK-MESSAGES: [[@LINE-1]]:28: warning: redundant 'const' in constexpr variable declaration +// CHECK-FIXES: constexpr const int Bar::* p13 = &Bar::x; + +// Pointer to member function +constexpr int (Bar::*n15)() = &Bar::sum; + +// Pointer to member function +constexpr int (Bar::* const p14)() = &Bar::sum; +// CHECK-MESSAGES: [[@LINE-1]]:23: warning: redundant 'const' in constexpr variable declaration +// CHECK-FIXES: constexpr int (Bar::* p14)() = &Bar::sum; + +#define CONSTEXPR constexpr + +CONSTEXPR Foo n16 = {}; + +CONSTEXPR const Foo p15 = {}; +// CHECK-MESSAGES: [[@LINE-1]]:11: warning: redundant 'const' in constexpr variable declaration +// CHECK-FIXES: CONSTEXPR Foo p15 = {}; + +const CONSTEXPR Foo p16 = {}; +// CHECK-MESSAGES: [[@LINE-1]]:1: warning: redundant 'const' in constexpr variable declaration +// CHECK-FIXES: CONSTEXPR Foo p16 = {}; + +// OK for references +constexpr const Foo& n17 = p15; >From 26d9a50843e015ec17b6d5aaadb62b18142d58b6 Mon Sep 17 00:00:00 2001 From: Berkay Sahin <[email protected]> Date: Tue, 31 Mar 2026 22:56:39 +0300 Subject: [PATCH 02/15] [clang-tidy] fix linter --- .../clang-tidy/readability/RedundantConstCheck.cpp | 4 ++-- clang-tools-extra/docs/ReleaseNotes.rst | 10 +++++----- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/clang-tools-extra/clang-tidy/readability/RedundantConstCheck.cpp b/clang-tools-extra/clang-tidy/readability/RedundantConstCheck.cpp index 1956f9a78e495..421143db7b2b7 100644 --- a/clang-tools-extra/clang-tidy/readability/RedundantConstCheck.cpp +++ b/clang-tools-extra/clang-tidy/readability/RedundantConstCheck.cpp @@ -17,7 +17,7 @@ using namespace clang::ast_matchers; namespace clang::tidy::readability { static const internal::VariadicDynCastAllOfMatcher<Decl, VarTemplateDecl> - varTemplateDecl; + VarTemplateDecl; static std::optional<Token> findConstToRemove(const VarDecl *VD, const MatchFinder::MatchResult &Result) { @@ -70,7 +70,7 @@ RedundantConstCheck::RedundantConstCheck(StringRef Name, void RedundantConstCheck::registerMatchers(MatchFinder *Finder) { Finder->addMatcher( - varDecl(isConstexpr(), unless(anyOf(hasAncestor(varTemplateDecl()), + varDecl(isConstexpr(), unless(anyOf(hasAncestor(VarTemplateDecl()), hasType(referenceType())))) .bind("var_decl"), this); diff --git a/clang-tools-extra/docs/ReleaseNotes.rst b/clang-tools-extra/docs/ReleaseNotes.rst index 3312beebcff55..96b962eec54c6 100644 --- a/clang-tools-extra/docs/ReleaseNotes.rst +++ b/clang-tools-extra/docs/ReleaseNotes.rst @@ -157,17 +157,17 @@ New checks Suggests insertion of ``std::move(...)`` to turn copy assignment operator calls into move assignment ones, when deemed valid and profitable. +- New :doc:`readability-redundant-const + <clang-tidy/checks/readability/redundant-const>` check. + + Detects redundant ``const`` specifiers on variable declarations. + - New :doc:`readability-redundant-qualified-alias <clang-tidy/checks/readability/redundant-qualified-alias>` check. Finds redundant identity type aliases that re-expose a qualified name and can be replaced with a ``using`` declaration. -- New :doc:`readability-redundant-const - <clang-tidy/checks/readability/redundant-const>` check. - - Detects redundant ``const`` specifiers on variable declarations. - - New :doc:`readability-trailing-comma <clang-tidy/checks/readability/trailing-comma>` check. >From 0f544a905ed0b861d9efb9d2f5a271ff1b5decef Mon Sep 17 00:00:00 2001 From: Berkay Sahin <[email protected]> Date: Wed, 1 Apr 2026 20:07:16 +0300 Subject: [PATCH 03/15] Update clang-tools-extra/docs/clang-tidy/checks/readability/redundant-const.rst Co-authored-by: EugeneZelenko <[email protected]> --- .../docs/clang-tidy/checks/readability/redundant-const.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/clang-tools-extra/docs/clang-tidy/checks/readability/redundant-const.rst b/clang-tools-extra/docs/clang-tidy/checks/readability/redundant-const.rst index ed6957f21e312..c33c0f5cd155b 100644 --- a/clang-tools-extra/docs/clang-tidy/checks/readability/redundant-const.rst +++ b/clang-tools-extra/docs/clang-tidy/checks/readability/redundant-const.rst @@ -1,7 +1,7 @@ .. title:: clang-tidy - readability-redundant-const readability-redundant-const -============================= +=========================== Detects redundant ``const`` specifiers on variable declarations. >From 5030149d16eac48351d41400d4a2cf863404a13e Mon Sep 17 00:00:00 2001 From: Berkay Sahin <[email protected]> Date: Fri, 3 Apr 2026 23:09:08 +0300 Subject: [PATCH 04/15] Update clang-tools-extra/test/clang-tidy/checkers/readability/redundant-const.cpp Co-authored-by: Victor Chernyakin <[email protected]> --- .../test/clang-tidy/checkers/readability/redundant-const.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/clang-tools-extra/test/clang-tidy/checkers/readability/redundant-const.cpp b/clang-tools-extra/test/clang-tidy/checkers/readability/redundant-const.cpp index 6a49e9837b414..6a749b8f02161 100644 --- a/clang-tools-extra/test/clang-tidy/checkers/readability/redundant-const.cpp +++ b/clang-tools-extra/test/clang-tidy/checkers/readability/redundant-const.cpp @@ -1,4 +1,4 @@ -// RUN: %check_clang_tidy -std=c++11-or-later %s readability-redundant-const %t -- +// RUN: %check_clang_tidy -std=c++11-or-later %s readability-redundant-const %t struct Foo {}; >From b69400b2d6e69c6f7e36b447f84bc950ab3f27e1 Mon Sep 17 00:00:00 2001 From: Berkay Sahin <[email protected]> Date: Fri, 3 Apr 2026 23:10:18 +0300 Subject: [PATCH 05/15] Update docs to avoid confusion Co-authored-by: Victor Chernyakin <[email protected]> --- .../docs/clang-tidy/checks/readability/redundant-const.rst | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/clang-tools-extra/docs/clang-tidy/checks/readability/redundant-const.rst b/clang-tools-extra/docs/clang-tidy/checks/readability/redundant-const.rst index c33c0f5cd155b..a8c265488d057 100644 --- a/clang-tools-extra/docs/clang-tidy/checks/readability/redundant-const.rst +++ b/clang-tools-extra/docs/clang-tidy/checks/readability/redundant-const.rst @@ -10,9 +10,9 @@ Examples: .. code-block:: c++ // Finds: - constexpr const int var = {}; // redundant use of `const` + constexpr const int var = 10; // redundant use of `const` // replaced by: - constexpr int var = {}; + constexpr int var = 10; // Finds: constexpr const int arr[] = {}; // redundant use of `const` >From 72c618b0868d34b96033296343568434ee0f2bf5 Mon Sep 17 00:00:00 2001 From: Berkay Sahin <[email protected]> Date: Fri, 3 Apr 2026 23:26:05 +0300 Subject: [PATCH 06/15] Simplifies const search logic Co-authored-by: Victor Chernyakin <[email protected]> --- .../readability/RedundantConstCheck.cpp | 28 +++++++------------ 1 file changed, 10 insertions(+), 18 deletions(-) diff --git a/clang-tools-extra/clang-tidy/readability/RedundantConstCheck.cpp b/clang-tools-extra/clang-tidy/readability/RedundantConstCheck.cpp index 421143db7b2b7..f7cc78cf7f19f 100644 --- a/clang-tools-extra/clang-tidy/readability/RedundantConstCheck.cpp +++ b/clang-tools-extra/clang-tidy/readability/RedundantConstCheck.cpp @@ -31,26 +31,18 @@ findConstToRemove(const VarDecl *VD, const MatchFinder::MatchResult &Result) { VD->getType()->isNullPtrType() || VD->getType()->isMemberPointerType(); - const auto ConstSearchStartLoc = [&]() -> std::optional<SourceLocation> { - if (!IsPointer) - return VD->getBeginLoc(); - - SourceLocation StarLoc = utils::lexer::findPreviousTokenKind( + // If the 'findPreviousTokenKind' below fails, + // we know it is a pointer but cannot find the start token. + // This can happen when either type is aliased or `auto` was used. + // e.g: constexpr const auto const str = "hello"; + // In cases like this, clang analyzer already warns about the use of const + // as duplicate, so we can safely ignore these cases. + const SourceLocation ConstSearchStartLoc = !IsPointer + ? VD->getBeginLoc() + : utils::lexer::findPreviousTokenKind( NameBeginLoc, SM, Result.Context->getLangOpts(), tok::star); - if (StarLoc.isValid()) - return StarLoc; - - // We know it is a pointer but cannot find the start token. - // This can happen when either type is aliased or `auto` was used. - // e.g: constexpr const auto const str = "hello"; - // In cases like this, clang analyzer already warns about the use of const - // as duplicate, so we can safely ignore these cases. - - return std::nullopt; - }(); - - if (!ConstSearchStartLoc || !ConstSearchStartLoc->isValid()) + if (ConstSearchStartLoc.isInvalid()) return std::nullopt; const CharSourceRange FileRange = Lexer::makeFileCharRange( >From 3da91747a6f59db5ae8c5d8f797320f185be3e85 Mon Sep 17 00:00:00 2001 From: Berkay Sahin <[email protected]> Date: Fri, 3 Apr 2026 23:45:08 +0300 Subject: [PATCH 07/15] Fix linter issues --- .../clang-tidy/readability/RedundantConstCheck.cpp | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/clang-tools-extra/clang-tidy/readability/RedundantConstCheck.cpp b/clang-tools-extra/clang-tidy/readability/RedundantConstCheck.cpp index f7cc78cf7f19f..b14f4a2f6e329 100644 --- a/clang-tools-extra/clang-tidy/readability/RedundantConstCheck.cpp +++ b/clang-tools-extra/clang-tidy/readability/RedundantConstCheck.cpp @@ -37,10 +37,11 @@ findConstToRemove(const VarDecl *VD, const MatchFinder::MatchResult &Result) { // e.g: constexpr const auto const str = "hello"; // In cases like this, clang analyzer already warns about the use of const // as duplicate, so we can safely ignore these cases. - const SourceLocation ConstSearchStartLoc = !IsPointer - ? VD->getBeginLoc() - : utils::lexer::findPreviousTokenKind( - NameBeginLoc, SM, Result.Context->getLangOpts(), tok::star); + const SourceLocation ConstSearchStartLoc = + !IsPointer + ? VD->getBeginLoc() + : utils::lexer::findPreviousTokenKind( + NameBeginLoc, SM, Result.Context->getLangOpts(), tok::star); if (ConstSearchStartLoc.isInvalid()) return std::nullopt; >From 9855bc6ba6dd3d1db15548f6f52feb591f67c178 Mon Sep 17 00:00:00 2001 From: Berkay Sahin <[email protected]> Date: Sat, 4 Apr 2026 00:17:41 +0300 Subject: [PATCH 08/15] Fix compile --- .../clang-tidy/readability/RedundantConstCheck.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/clang-tools-extra/clang-tidy/readability/RedundantConstCheck.cpp b/clang-tools-extra/clang-tidy/readability/RedundantConstCheck.cpp index b14f4a2f6e329..8449d32d191ca 100644 --- a/clang-tools-extra/clang-tidy/readability/RedundantConstCheck.cpp +++ b/clang-tools-extra/clang-tidy/readability/RedundantConstCheck.cpp @@ -47,7 +47,7 @@ findConstToRemove(const VarDecl *VD, const MatchFinder::MatchResult &Result) { return std::nullopt; const CharSourceRange FileRange = Lexer::makeFileCharRange( - CharSourceRange::getCharRange(*ConstSearchStartLoc, NameBeginLoc), SM, + CharSourceRange::getCharRange(ConstSearchStartLoc, NameBeginLoc), SM, Result.Context->getLangOpts()); if (!FileRange.isValid()) >From 2754e16f2ba35bd261e14e5b9384a06ad7dc2b09 Mon Sep 17 00:00:00 2001 From: Berkay Sahin <[email protected]> Date: Sat, 4 Apr 2026 19:21:35 +0300 Subject: [PATCH 09/15] Address PR comments - C23 support - Warn on template variable decls - Update warning message --- .../readability/RedundantConstCheck.cpp | 13 ++--- .../checks/readability/redundant-const.rst | 2 +- .../checkers/readability/redundant-const.c | 23 +++++++++ .../checkers/readability/redundant-const.cpp | 47 ++++++++++--------- 4 files changed, 52 insertions(+), 33 deletions(-) create mode 100644 clang-tools-extra/test/clang-tidy/checkers/readability/redundant-const.c diff --git a/clang-tools-extra/clang-tidy/readability/RedundantConstCheck.cpp b/clang-tools-extra/clang-tidy/readability/RedundantConstCheck.cpp index 8449d32d191ca..cd59accdab541 100644 --- a/clang-tools-extra/clang-tidy/readability/RedundantConstCheck.cpp +++ b/clang-tools-extra/clang-tidy/readability/RedundantConstCheck.cpp @@ -16,9 +16,6 @@ using namespace clang::ast_matchers; namespace clang::tidy::readability { -static const internal::VariadicDynCastAllOfMatcher<Decl, VarTemplateDecl> - VarTemplateDecl; - static std::optional<Token> findConstToRemove(const VarDecl *VD, const MatchFinder::MatchResult &Result) { const SourceManager &SM = *Result.SourceManager; @@ -35,7 +32,7 @@ findConstToRemove(const VarDecl *VD, const MatchFinder::MatchResult &Result) { // we know it is a pointer but cannot find the start token. // This can happen when either type is aliased or `auto` was used. // e.g: constexpr const auto const str = "hello"; - // In cases like this, clang analyzer already warns about the use of const + // In cases like this, Clang already warns about the use of const // as duplicate, so we can safely ignore these cases. const SourceLocation ConstSearchStartLoc = !IsPointer @@ -63,9 +60,7 @@ RedundantConstCheck::RedundantConstCheck(StringRef Name, void RedundantConstCheck::registerMatchers(MatchFinder *Finder) { Finder->addMatcher( - varDecl(isConstexpr(), unless(anyOf(hasAncestor(VarTemplateDecl()), - hasType(referenceType())))) - .bind("var_decl"), + varDecl(isConstexpr(), unless(hasType(referenceType()))).bind("var_decl"), this); } @@ -82,13 +77,13 @@ void RedundantConstCheck::check(const MatchFinder::MatchResult &Result) { const auto ConstRange = CharSourceRange::getCharRange(Tok->getLocation(), Tok->getEndLoc()); diag(Tok->getLocation(), - "redundant 'const' in constexpr variable declaration") + "redundant use of `const`; `constexpr` already implies `const`.") << ConstRange << FixItHint::CreateRemoval(ConstRange); } bool RedundantConstCheck::isLanguageVersionSupported( const LangOptions &LangOpts) const { - return LangOpts.CPlusPlus11; + return LangOpts.CPlusPlus11 || LangOpts.C23; } std::optional<TraversalKind> diff --git a/clang-tools-extra/docs/clang-tidy/checks/readability/redundant-const.rst b/clang-tools-extra/docs/clang-tidy/checks/readability/redundant-const.rst index a8c265488d057..c434ca28ffb07 100644 --- a/clang-tools-extra/docs/clang-tidy/checks/readability/redundant-const.rst +++ b/clang-tools-extra/docs/clang-tidy/checks/readability/redundant-const.rst @@ -46,4 +46,4 @@ The check also analyzes pointers: constexpr const char* ok = "ok"; // OK -Requires C++11 or above. +Requires C++11 or C23. diff --git a/clang-tools-extra/test/clang-tidy/checkers/readability/redundant-const.c b/clang-tools-extra/test/clang-tidy/checkers/readability/redundant-const.c new file mode 100644 index 0000000000000..1aa1835c8b55d --- /dev/null +++ b/clang-tools-extra/test/clang-tidy/checkers/readability/redundant-const.c @@ -0,0 +1,23 @@ +// RUN: %check_clang_tidy -std=c23-or-later %s readability-redundant-const %t + +const int n1 = 20; + +// C23 constexpr +constexpr const int p1 = 10; +// CHECK-MESSAGES: [[@LINE-1]]:11: warning: redundant use of `const`; `constexpr` already implies `const`. +// CHECK-FIXES: constexpr int p1 = 10; + +const constexpr int p2 = 20; +// CHECK-MESSAGES: [[@LINE-1]]:1: warning: redundant use of `const`; `constexpr` already implies `const`. +// CHECK-FIXES: constexpr int p2 = 20; + +static const constexpr int p3 = 20; +// CHECK-MESSAGES: [[@LINE-1]]:8: warning: redundant use of `const`; `constexpr` already implies `const`. +// CHECK-FIXES: static constexpr int p3 = 20; + +// Since constexpr makes only the pointer const, this usage is not redundant. +constexpr const char *n2 = 0; + +constexpr const char *const p4 = 0; +// CHECK-MESSAGES: [[@LINE-1]]:23: warning: redundant use of `const`; `constexpr` already implies `const`. +// CHECK-FIXES: constexpr const char *p4 = 0; diff --git a/clang-tools-extra/test/clang-tidy/checkers/readability/redundant-const.cpp b/clang-tools-extra/test/clang-tidy/checkers/readability/redundant-const.cpp index 6a749b8f02161..fcdee5b02f8a9 100644 --- a/clang-tools-extra/test/clang-tidy/checkers/readability/redundant-const.cpp +++ b/clang-tools-extra/test/clang-tidy/checkers/readability/redundant-const.cpp @@ -8,40 +8,41 @@ const int n2 = 20; constexpr Foo n3 = {}; constexpr const int p1 = 10; -// CHECK-MESSAGES: [[@LINE-1]]:11: warning: redundant 'const' in constexpr variable declaration +// CHECK-MESSAGES: [[@LINE-1]]:11: warning: redundant use of `const`; `constexpr` already implies `const`. // CHECK-FIXES: constexpr int p1 = 10; const constexpr int p2 = 20; -// CHECK-MESSAGES: [[@LINE-1]]:1: warning: redundant 'const' in constexpr variable declaration +// CHECK-MESSAGES: [[@LINE-1]]:1: warning: redundant use of `const`; `constexpr` already implies `const`. // CHECK-FIXES: constexpr int p2 = 20; static const constexpr int p3 = 20; -// CHECK-MESSAGES: [[@LINE-1]]:8: warning: redundant 'const' in constexpr variable declaration +// CHECK-MESSAGES: [[@LINE-1]]:8: warning: redundant use of `const`; `constexpr` already implies `const`. // CHECK-FIXES: static constexpr int p3 = 20; constexpr const Foo p4 = {}; -// CHECK-MESSAGES: [[@LINE-1]]:11: warning: redundant 'const' in constexpr variable declaration +// CHECK-MESSAGES: [[@LINE-1]]:11: warning: redundant use of `const`; `constexpr` already implies `const`. // CHECK-FIXES: constexpr Foo p4 = {}; // Since constexpr makes only the pointer const, this usage is not redundant. constexpr const char* n4 = "hello"; constexpr const char* const n5 = "hello"; -// CHECK-MESSAGES: [[@LINE-1]]:23: warning: redundant 'const' in constexpr variable declaration +// CHECK-MESSAGES: [[@LINE-1]]:23: warning: redundant use of `const`; `constexpr` already implies `const`. // CHECK-FIXES: constexpr const char* n5 = "hello"; -// Since T might be a pointer type, we don't warn on this. template<typename T> const constexpr T n6 = {}; +// CHECK-MESSAGES: [[@LINE-1]]:1: warning: redundant use of `const`; `constexpr` already implies `const`. +// CHECK-FIXES: constexpr T n6 = {}; constexpr const int* n7 = n6<int*>; const constexpr double p5 = n6<double>; -// CHECK-MESSAGES: [[@LINE-1]]:1: warning: redundant 'const' in constexpr variable declaration +// CHECK-MESSAGES: [[@LINE-1]]:1: warning: redundant use of `const`; `constexpr` already implies `const`. // CHECK-FIXES: constexpr double p5 = n6<double>; constexpr const int* const p6 = n6<int*>; -// CHECK-MESSAGES: [[@LINE-1]]:22: warning: redundant 'const' in constexpr variable declaration +// CHECK-MESSAGES: [[@LINE-1]]:22: warning: redundant use of `const`; `constexpr` already implies `const`. // CHECK-FIXES: constexpr const int* p6 = n6<int*>; void f() { @@ -49,24 +50,24 @@ void f() { const Foo n2 = {}; const constexpr Foo p1 = {}; - // CHECK-MESSAGES: [[@LINE-1]]:3: warning: redundant 'const' in constexpr variable declaration + // CHECK-MESSAGES: [[@LINE-1]]:3: warning: redundant use of `const`; `constexpr` already implies `const`. // CHECK-FIXES: constexpr Foo p1 = {}; static const constexpr Foo p2 = {}; - // CHECK-MESSAGES: [[@LINE-1]]:10: warning: redundant 'const' in constexpr variable declaration + // CHECK-MESSAGES: [[@LINE-1]]:10: warning: redundant use of `const`; `constexpr` already implies `const`. // CHECK-FIXES: static constexpr Foo p2 = {}; } struct Config { static const constexpr bool p = false; - // CHECK-MESSAGES: [[@LINE-1]]:12: warning: redundant 'const' in constexpr variable declaration + // CHECK-MESSAGES: [[@LINE-1]]:12: warning: redundant use of `const`; `constexpr` already implies `const`. // CHECK-FIXES: static constexpr bool p = false; }; template <typename T> class Templated { static const constexpr int size = 10; - // CHECK-MESSAGES: [[@LINE-1]]:12: warning: redundant 'const' in constexpr variable declaration + // CHECK-MESSAGES: [[@LINE-1]]:12: warning: redundant use of `const`; `constexpr` already implies `const`. // CHECK-FIXES: static constexpr int size = 10; int data[size]; }; @@ -76,7 +77,7 @@ constexpr Templated<int> b{}; template <int N> struct Templated2 { static const constexpr int size = N; - // CHECK-MESSAGES: [[@LINE-1]]:12: warning: redundant 'const' in constexpr variable declaration + // CHECK-MESSAGES: [[@LINE-1]]:12: warning: redundant use of `const`; `constexpr` already implies `const`. // CHECK-FIXES: static constexpr int size = N; int data[size]; }; @@ -84,13 +85,13 @@ struct Templated2 { static constexpr int n8[] = {0, 1, 4, 9, 16}; constexpr const int p7[] = {0, 1, 4, 9, 16}; -// CHECK-MESSAGES: [[@LINE-1]]:11: warning: redundant 'const' in constexpr variable declaration +// CHECK-MESSAGES: [[@LINE-1]]:11: warning: redundant use of `const`; `constexpr` already implies `const`. // CHECK-FIXES: constexpr int p7[] = {0, 1, 4, 9, 16}; constexpr int square(int n) { return n * n; } const constexpr int p8 = square(10); -// CHECK-MESSAGES: [[@LINE-1]]:1: warning: redundant 'const' in constexpr variable declaration +// CHECK-MESSAGES: [[@LINE-1]]:1: warning: redundant use of `const`; `constexpr` already implies `const`. // CHECK-FIXES: constexpr int p8 = square(10); constexpr int n9 = square(5); @@ -100,23 +101,23 @@ constexpr Foo** n10 = nullptr; constexpr Foo* const* n11 = nullptr; constexpr Foo* const* const p9 = nullptr; -// CHECK-MESSAGES: [[@LINE-1]]:23: warning: redundant 'const' in constexpr variable declaration +// CHECK-MESSAGES: [[@LINE-1]]:23: warning: redundant use of `const`; `constexpr` already implies `const`. // CHECK-FIXES: constexpr Foo* const* p9 = nullptr; constexpr const Foo* const* const p10 = nullptr; -// CHECK-MESSAGES: [[@LINE-1]]:29: warning: redundant 'const' in constexpr variable declaration +// CHECK-MESSAGES: [[@LINE-1]]:29: warning: redundant use of `const`; `constexpr` already implies `const`. // CHECK-FIXES: constexpr const Foo* const* p10 = nullptr; constexpr const int (*n12)[10] = nullptr; constexpr const int (*const p11)[10] = nullptr; -// CHECK-MESSAGES: [[@LINE-1]]:23: warning: redundant 'const' in constexpr variable declaration +// CHECK-MESSAGES: [[@LINE-1]]:23: warning: redundant use of `const`; `constexpr` already implies `const`. // CHECK-FIXES: constexpr const int (*p11)[10] = nullptr; constexpr int (*n13)(int) = nullptr; constexpr int (*const p12)(int) = nullptr; -// CHECK-MESSAGES: [[@LINE-1]]:17: warning: redundant 'const' in constexpr variable declaration +// CHECK-MESSAGES: [[@LINE-1]]:17: warning: redundant use of `const`; `constexpr` already implies `const`. // CHECK-FIXES: constexpr int (*p12)(int) = nullptr; struct Bar { @@ -129,7 +130,7 @@ constexpr const int Bar::*n14 = &Bar::x; // Pointer to data member constexpr const int Bar::* const p13 = &Bar::x; -// CHECK-MESSAGES: [[@LINE-1]]:28: warning: redundant 'const' in constexpr variable declaration +// CHECK-MESSAGES: [[@LINE-1]]:28: warning: redundant use of `const`; `constexpr` already implies `const`. // CHECK-FIXES: constexpr const int Bar::* p13 = &Bar::x; // Pointer to member function @@ -137,7 +138,7 @@ constexpr int (Bar::*n15)() = &Bar::sum; // Pointer to member function constexpr int (Bar::* const p14)() = &Bar::sum; -// CHECK-MESSAGES: [[@LINE-1]]:23: warning: redundant 'const' in constexpr variable declaration +// CHECK-MESSAGES: [[@LINE-1]]:23: warning: redundant use of `const`; `constexpr` already implies `const`. // CHECK-FIXES: constexpr int (Bar::* p14)() = &Bar::sum; #define CONSTEXPR constexpr @@ -145,11 +146,11 @@ constexpr int (Bar::* const p14)() = &Bar::sum; CONSTEXPR Foo n16 = {}; CONSTEXPR const Foo p15 = {}; -// CHECK-MESSAGES: [[@LINE-1]]:11: warning: redundant 'const' in constexpr variable declaration +// CHECK-MESSAGES: [[@LINE-1]]:11: warning: redundant use of `const`; `constexpr` already implies `const`. // CHECK-FIXES: CONSTEXPR Foo p15 = {}; const CONSTEXPR Foo p16 = {}; -// CHECK-MESSAGES: [[@LINE-1]]:1: warning: redundant 'const' in constexpr variable declaration +// CHECK-MESSAGES: [[@LINE-1]]:1: warning: redundant use of `const`; `constexpr` already implies `const`. // CHECK-FIXES: CONSTEXPR Foo p16 = {}; // OK for references >From e61d425fb247989c9e9e84086b3fe2642ea53cc8 Mon Sep 17 00:00:00 2001 From: Berkay Sahin <[email protected]> Date: Sat, 4 Apr 2026 22:44:16 +0300 Subject: [PATCH 10/15] Prefer IsInvalid over !IsValid Co-authored-by: Victor Chernyakin <[email protected]> --- .../clang-tidy/readability/RedundantConstCheck.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/clang-tools-extra/clang-tidy/readability/RedundantConstCheck.cpp b/clang-tools-extra/clang-tidy/readability/RedundantConstCheck.cpp index cd59accdab541..f6310caad8b71 100644 --- a/clang-tools-extra/clang-tidy/readability/RedundantConstCheck.cpp +++ b/clang-tools-extra/clang-tidy/readability/RedundantConstCheck.cpp @@ -47,7 +47,7 @@ findConstToRemove(const VarDecl *VD, const MatchFinder::MatchResult &Result) { CharSourceRange::getCharRange(ConstSearchStartLoc, NameBeginLoc), SM, Result.Context->getLangOpts()); - if (!FileRange.isValid()) + if (FileRange.isInvalid()) return std::nullopt; return utils::lexer::getQualifyingToken(tok::kw_const, FileRange, >From afc21ff8e249a067bd8e518862354caa3ff747b9 Mon Sep 17 00:00:00 2001 From: Berkay Sahin <[email protected]> Date: Sun, 5 Apr 2026 14:55:06 +0300 Subject: [PATCH 11/15] Update clang-tools-extra/test/clang-tidy/checkers/readability/redundant-const.c Co-authored-by: Baranov Victor <[email protected]> --- .../test/clang-tidy/checkers/readability/redundant-const.c | 1 - 1 file changed, 1 deletion(-) diff --git a/clang-tools-extra/test/clang-tidy/checkers/readability/redundant-const.c b/clang-tools-extra/test/clang-tidy/checkers/readability/redundant-const.c index 1aa1835c8b55d..fa47c44c11c7f 100644 --- a/clang-tools-extra/test/clang-tidy/checkers/readability/redundant-const.c +++ b/clang-tools-extra/test/clang-tidy/checkers/readability/redundant-const.c @@ -2,7 +2,6 @@ const int n1 = 20; -// C23 constexpr constexpr const int p1 = 10; // CHECK-MESSAGES: [[@LINE-1]]:11: warning: redundant use of `const`; `constexpr` already implies `const`. // CHECK-FIXES: constexpr int p1 = 10; >From 7d422aa27c88ac7f59570ba406a6aaf238384cb2 Mon Sep 17 00:00:00 2001 From: Berkay Sahin <[email protected]> Date: Sun, 5 Apr 2026 20:13:50 +0300 Subject: [PATCH 12/15] [clang-tidy] Address PR comments - No need to specially handle nullptr - Simplify diag - Format warning message properly - Add more tests --- .../readability/RedundantConstCheck.cpp | 20 ++- .../checkers/readability/redundant-const.c | 8 +- .../checkers/readability/redundant-const.cpp | 130 ++++++++++-------- 3 files changed, 88 insertions(+), 70 deletions(-) diff --git a/clang-tools-extra/clang-tidy/readability/RedundantConstCheck.cpp b/clang-tools-extra/clang-tidy/readability/RedundantConstCheck.cpp index f6310caad8b71..fba08286d354f 100644 --- a/clang-tools-extra/clang-tidy/readability/RedundantConstCheck.cpp +++ b/clang-tools-extra/clang-tidy/readability/RedundantConstCheck.cpp @@ -24,9 +24,8 @@ findConstToRemove(const VarDecl *VD, const MatchFinder::MatchResult &Result) { ? VD->getQualifierLoc().getBeginLoc() : VD->getLocation(); - const bool IsPointer = VD->getType()->isPointerType() || - VD->getType()->isNullPtrType() || - VD->getType()->isMemberPointerType(); + const bool IsPointer = + VD->getType()->isPointerType() || VD->getType()->isMemberPointerType(); // If the 'findPreviousTokenKind' below fails, // we know it is a pointer but cannot find the start token. @@ -43,6 +42,15 @@ findConstToRemove(const VarDecl *VD, const MatchFinder::MatchResult &Result) { if (ConstSearchStartLoc.isInvalid()) return std::nullopt; + const SourceLocation PrevSemi = utils::lexer::findPreviousAnyTokenKind( + NameBeginLoc, SM, Result.Context->getLangOpts(), tok::semi); + + // Verify that there is no semicolon between ConstSearchStartLoc and + // NameBeginLoc This is to limit search area for our variable decl only + if (!PrevSemi.isInvalid() && + SM.isBeforeInTranslationUnit(ConstSearchStartLoc, PrevSemi)) + return std::nullopt; + const CharSourceRange FileRange = Lexer::makeFileCharRange( CharSourceRange::getCharRange(ConstSearchStartLoc, NameBeginLoc), SM, Result.Context->getLangOpts()); @@ -74,11 +82,9 @@ void RedundantConstCheck::check(const MatchFinder::MatchResult &Result) { if (!Tok) return; - const auto ConstRange = - CharSourceRange::getCharRange(Tok->getLocation(), Tok->getEndLoc()); diag(Tok->getLocation(), - "redundant use of `const`; `constexpr` already implies `const`.") - << ConstRange << FixItHint::CreateRemoval(ConstRange); + "redundant use of 'const'; 'constexpr' already implies 'const'") + << FixItHint::CreateRemoval(Tok->getLocation()); } bool RedundantConstCheck::isLanguageVersionSupported( diff --git a/clang-tools-extra/test/clang-tidy/checkers/readability/redundant-const.c b/clang-tools-extra/test/clang-tidy/checkers/readability/redundant-const.c index 1aa1835c8b55d..f21ca9cdf2c51 100644 --- a/clang-tools-extra/test/clang-tidy/checkers/readability/redundant-const.c +++ b/clang-tools-extra/test/clang-tidy/checkers/readability/redundant-const.c @@ -4,20 +4,20 @@ const int n1 = 20; // C23 constexpr constexpr const int p1 = 10; -// CHECK-MESSAGES: [[@LINE-1]]:11: warning: redundant use of `const`; `constexpr` already implies `const`. +// CHECK-MESSAGES: [[@LINE-1]]:11: warning: redundant use of 'const'; 'constexpr' already implies 'const' // CHECK-FIXES: constexpr int p1 = 10; const constexpr int p2 = 20; -// CHECK-MESSAGES: [[@LINE-1]]:1: warning: redundant use of `const`; `constexpr` already implies `const`. +// CHECK-MESSAGES: [[@LINE-1]]:1: warning: redundant use of 'const'; 'constexpr' already implies 'const' // CHECK-FIXES: constexpr int p2 = 20; static const constexpr int p3 = 20; -// CHECK-MESSAGES: [[@LINE-1]]:8: warning: redundant use of `const`; `constexpr` already implies `const`. +// CHECK-MESSAGES: [[@LINE-1]]:8: warning: redundant use of 'const'; 'constexpr' already implies 'const' // CHECK-FIXES: static constexpr int p3 = 20; // Since constexpr makes only the pointer const, this usage is not redundant. constexpr const char *n2 = 0; constexpr const char *const p4 = 0; -// CHECK-MESSAGES: [[@LINE-1]]:23: warning: redundant use of `const`; `constexpr` already implies `const`. +// CHECK-MESSAGES: [[@LINE-1]]:23: warning: redundant use of 'const'; 'constexpr' already implies 'const' // CHECK-FIXES: constexpr const char *p4 = 0; diff --git a/clang-tools-extra/test/clang-tidy/checkers/readability/redundant-const.cpp b/clang-tools-extra/test/clang-tidy/checkers/readability/redundant-const.cpp index fcdee5b02f8a9..86f6a915fa8ee 100644 --- a/clang-tools-extra/test/clang-tidy/checkers/readability/redundant-const.cpp +++ b/clang-tools-extra/test/clang-tidy/checkers/readability/redundant-const.cpp @@ -2,97 +2,98 @@ struct Foo {}; -// Simple allowed usages, nothing to warn constexpr int n1 = 10; const int n2 = 20; constexpr Foo n3 = {}; constexpr const int p1 = 10; -// CHECK-MESSAGES: [[@LINE-1]]:11: warning: redundant use of `const`; `constexpr` already implies `const`. +// CHECK-MESSAGES: [[@LINE-1]]:11: warning: redundant use of 'const'; 'constexpr' already implies 'const' // CHECK-FIXES: constexpr int p1 = 10; const constexpr int p2 = 20; -// CHECK-MESSAGES: [[@LINE-1]]:1: warning: redundant use of `const`; `constexpr` already implies `const`. +// CHECK-MESSAGES: [[@LINE-1]]:1: warning: redundant use of 'const'; 'constexpr' already implies 'const' // CHECK-FIXES: constexpr int p2 = 20; static const constexpr int p3 = 20; -// CHECK-MESSAGES: [[@LINE-1]]:8: warning: redundant use of `const`; `constexpr` already implies `const`. +// CHECK-MESSAGES: [[@LINE-1]]:8: warning: redundant use of 'const'; 'constexpr' already implies 'const' // CHECK-FIXES: static constexpr int p3 = 20; constexpr const Foo p4 = {}; -// CHECK-MESSAGES: [[@LINE-1]]:11: warning: redundant use of `const`; `constexpr` already implies `const`. +// CHECK-MESSAGES: [[@LINE-1]]:11: warning: redundant use of 'const'; 'constexpr' already implies 'const' // CHECK-FIXES: constexpr Foo p4 = {}; // Since constexpr makes only the pointer const, this usage is not redundant. constexpr const char* n4 = "hello"; -constexpr const char* const n5 = "hello"; -// CHECK-MESSAGES: [[@LINE-1]]:23: warning: redundant use of `const`; `constexpr` already implies `const`. -// CHECK-FIXES: constexpr const char* n5 = "hello"; +constexpr const auto n5 = "hello"; + +constexpr const char* const p5 = "hello"; +// CHECK-MESSAGES: [[@LINE-1]]:23: warning: redundant use of 'const'; 'constexpr' already implies 'const' +// CHECK-FIXES: constexpr const char* p5 = "hello"; template<typename T> -const constexpr T n6 = {}; -// CHECK-MESSAGES: [[@LINE-1]]:1: warning: redundant use of `const`; `constexpr` already implies `const`. -// CHECK-FIXES: constexpr T n6 = {}; +const constexpr T p6 = {}; +// CHECK-MESSAGES: [[@LINE-1]]:1: warning: redundant use of 'const'; 'constexpr' already implies 'const' +// CHECK-FIXES: constexpr T p6 = {}; -constexpr const int* n7 = n6<int*>; +constexpr const int* n6 = p6<int*>; -const constexpr double p5 = n6<double>; -// CHECK-MESSAGES: [[@LINE-1]]:1: warning: redundant use of `const`; `constexpr` already implies `const`. -// CHECK-FIXES: constexpr double p5 = n6<double>; +const constexpr double p7 = p6<double>; +// CHECK-MESSAGES: [[@LINE-1]]:1: warning: redundant use of 'const'; 'constexpr' already implies 'const' +// CHECK-FIXES: constexpr double p7 = p6<double>; -constexpr const int* const p6 = n6<int*>; -// CHECK-MESSAGES: [[@LINE-1]]:22: warning: redundant use of `const`; `constexpr` already implies `const`. -// CHECK-FIXES: constexpr const int* p6 = n6<int*>; +constexpr const int* const p8 = p6<int*>; +// CHECK-MESSAGES: [[@LINE-1]]:22: warning: redundant use of 'const'; 'constexpr' already implies 'const' +// CHECK-FIXES: constexpr const int* p8 = p6<int*>; void f() { constexpr Foo n1 = {}; const Foo n2 = {}; const constexpr Foo p1 = {}; - // CHECK-MESSAGES: [[@LINE-1]]:3: warning: redundant use of `const`; `constexpr` already implies `const`. + // CHECK-MESSAGES: [[@LINE-1]]:3: warning: redundant use of 'const'; 'constexpr' already implies 'const' // CHECK-FIXES: constexpr Foo p1 = {}; static const constexpr Foo p2 = {}; - // CHECK-MESSAGES: [[@LINE-1]]:10: warning: redundant use of `const`; `constexpr` already implies `const`. + // CHECK-MESSAGES: [[@LINE-1]]:10: warning: redundant use of 'const'; 'constexpr' already implies 'const' // CHECK-FIXES: static constexpr Foo p2 = {}; } struct Config { static const constexpr bool p = false; - // CHECK-MESSAGES: [[@LINE-1]]:12: warning: redundant use of `const`; `constexpr` already implies `const`. + // CHECK-MESSAGES: [[@LINE-1]]:12: warning: redundant use of 'const'; 'constexpr' already implies 'const' // CHECK-FIXES: static constexpr bool p = false; }; template <typename T> class Templated { static const constexpr int size = 10; - // CHECK-MESSAGES: [[@LINE-1]]:12: warning: redundant use of `const`; `constexpr` already implies `const`. + // CHECK-MESSAGES: [[@LINE-1]]:12: warning: redundant use of 'const'; 'constexpr' already implies 'const' // CHECK-FIXES: static constexpr int size = 10; int data[size]; }; -constexpr Templated<int> b{}; +constexpr Templated<int> n7{}; template <int N> struct Templated2 { static const constexpr int size = N; - // CHECK-MESSAGES: [[@LINE-1]]:12: warning: redundant use of `const`; `constexpr` already implies `const`. + // CHECK-MESSAGES: [[@LINE-1]]:12: warning: redundant use of 'const'; 'constexpr' already implies 'const' // CHECK-FIXES: static constexpr int size = N; int data[size]; }; static constexpr int n8[] = {0, 1, 4, 9, 16}; -constexpr const int p7[] = {0, 1, 4, 9, 16}; -// CHECK-MESSAGES: [[@LINE-1]]:11: warning: redundant use of `const`; `constexpr` already implies `const`. -// CHECK-FIXES: constexpr int p7[] = {0, 1, 4, 9, 16}; +constexpr const int p9[] = {0, 1, 4, 9, 16}; +// CHECK-MESSAGES: [[@LINE-1]]:11: warning: redundant use of 'const'; 'constexpr' already implies 'const' +// CHECK-FIXES: constexpr int p9[] = {0, 1, 4, 9, 16}; constexpr int square(int n) { return n * n; } -const constexpr int p8 = square(10); -// CHECK-MESSAGES: [[@LINE-1]]:1: warning: redundant use of `const`; `constexpr` already implies `const`. -// CHECK-FIXES: constexpr int p8 = square(10); +const constexpr int p10 = square(10); +// CHECK-MESSAGES: [[@LINE-1]]:1: warning: redundant use of 'const'; 'constexpr' already implies 'const' +// CHECK-FIXES: constexpr int p10 = square(10); constexpr int n9 = square(5); @@ -100,58 +101,69 @@ constexpr Foo** n10 = nullptr; constexpr Foo* const* n11 = nullptr; -constexpr Foo* const* const p9 = nullptr; -// CHECK-MESSAGES: [[@LINE-1]]:23: warning: redundant use of `const`; `constexpr` already implies `const`. -// CHECK-FIXES: constexpr Foo* const* p9 = nullptr; +constexpr Foo* const* const p11 = nullptr; +// CHECK-MESSAGES: [[@LINE-1]]:23: warning: redundant use of 'const'; 'constexpr' already implies 'const' +// CHECK-FIXES: constexpr Foo* const* p11 = nullptr; -constexpr const Foo* const* const p10 = nullptr; -// CHECK-MESSAGES: [[@LINE-1]]:29: warning: redundant use of `const`; `constexpr` already implies `const`. -// CHECK-FIXES: constexpr const Foo* const* p10 = nullptr; +constexpr const Foo* const* const p12 = nullptr; +// CHECK-MESSAGES: [[@LINE-1]]:29: warning: redundant use of 'const'; 'constexpr' already implies 'const' +// CHECK-FIXES: constexpr const Foo* const* p12 = nullptr; constexpr const int (*n12)[10] = nullptr; -constexpr const int (*const p11)[10] = nullptr; -// CHECK-MESSAGES: [[@LINE-1]]:23: warning: redundant use of `const`; `constexpr` already implies `const`. -// CHECK-FIXES: constexpr const int (*p11)[10] = nullptr; +constexpr const int (*const p13)[10] = nullptr; +// CHECK-MESSAGES: [[@LINE-1]]:23: warning: redundant use of 'const'; 'constexpr' already implies 'const' +// CHECK-FIXES: constexpr const int (*p13)[10] = nullptr; constexpr int (*n13)(int) = nullptr; -constexpr int (*const p12)(int) = nullptr; -// CHECK-MESSAGES: [[@LINE-1]]:17: warning: redundant use of `const`; `constexpr` already implies `const`. -// CHECK-FIXES: constexpr int (*p12)(int) = nullptr; +constexpr int (*const p14)(int) = nullptr; +// CHECK-MESSAGES: [[@LINE-1]]:17: warning: redundant use of 'const'; 'constexpr' already implies 'const' +// CHECK-FIXES: constexpr int (*p14)(int) = nullptr; struct Bar { int x, y; int sum() { return x + y; } }; -// Pointer to data member constexpr const int Bar::*n14 = &Bar::x; -// Pointer to data member -constexpr const int Bar::* const p13 = &Bar::x; -// CHECK-MESSAGES: [[@LINE-1]]:28: warning: redundant use of `const`; `constexpr` already implies `const`. -// CHECK-FIXES: constexpr const int Bar::* p13 = &Bar::x; +constexpr const int Bar::* const p15 = &Bar::x; +// CHECK-MESSAGES: [[@LINE-1]]:28: warning: redundant use of 'const'; 'constexpr' already implies 'const' +// CHECK-FIXES: constexpr const int Bar::* p15 = &Bar::x; -// Pointer to member function constexpr int (Bar::*n15)() = &Bar::sum; -// Pointer to member function -constexpr int (Bar::* const p14)() = &Bar::sum; -// CHECK-MESSAGES: [[@LINE-1]]:23: warning: redundant use of `const`; `constexpr` already implies `const`. -// CHECK-FIXES: constexpr int (Bar::* p14)() = &Bar::sum; +constexpr int (Bar::* const p16)() = &Bar::sum; +// CHECK-MESSAGES: [[@LINE-1]]:23: warning: redundant use of 'const'; 'constexpr' already implies 'const' +// CHECK-FIXES: constexpr int (Bar::* p16)() = &Bar::sum; #define CONSTEXPR constexpr +#define CONST const CONSTEXPR Foo n16 = {}; -CONSTEXPR const Foo p15 = {}; -// CHECK-MESSAGES: [[@LINE-1]]:11: warning: redundant use of `const`; `constexpr` already implies `const`. -// CHECK-FIXES: CONSTEXPR Foo p15 = {}; +CONSTEXPR const Foo p17 = {}; +// CHECK-MESSAGES: [[@LINE-1]]:11: warning: redundant use of 'const'; 'constexpr' already implies 'const' +// CHECK-FIXES: CONSTEXPR Foo p17 = {}; + +const CONSTEXPR Foo p18 = {}; +// CHECK-MESSAGES: [[@LINE-1]]:1: warning: redundant use of 'const'; 'constexpr' already implies 'const' +// CHECK-FIXES: CONSTEXPR Foo p18 = {}; + +CONST constexpr Foo n17 = {}; +constexpr CONST Foo n18 = {}; -const CONSTEXPR Foo p16 = {}; -// CHECK-MESSAGES: [[@LINE-1]]:1: warning: redundant use of `const`; `constexpr` already implies `const`. -// CHECK-FIXES: CONSTEXPR Foo p16 = {}; +const Foo* n20 = nullptr; // OK for references -constexpr const Foo& n17 = p15; +constexpr const Foo& n19 = p18; +constexpr const Foo*& n21 = n20; + +constexpr const decltype(nullptr) p19 = nullptr; +// CHECK-MESSAGES: [[@LINE-1]]:11: warning: redundant use of 'const'; 'constexpr' already implies 'const' +// CHECK-FIXES: constexpr decltype(nullptr) p19 = nullptr; + +constexpr const decltype(0) p20 = {}; +// CHECK-MESSAGES: [[@LINE-1]]:11: warning: redundant use of 'const'; 'constexpr' already implies 'const' +// CHECK-FIXES: constexpr decltype(0) p20 = {}; >From 4a547d86f0dc24cff454dcd4a72e9f39fecf82e1 Mon Sep 17 00:00:00 2001 From: Berkay Sahin <[email protected]> Date: Sun, 5 Apr 2026 20:25:30 +0300 Subject: [PATCH 13/15] [clang-tidy] Add missing period --- .../clang-tidy/readability/RedundantConstCheck.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/clang-tools-extra/clang-tidy/readability/RedundantConstCheck.cpp b/clang-tools-extra/clang-tidy/readability/RedundantConstCheck.cpp index fba08286d354f..4f3a16c98d1ff 100644 --- a/clang-tools-extra/clang-tidy/readability/RedundantConstCheck.cpp +++ b/clang-tools-extra/clang-tidy/readability/RedundantConstCheck.cpp @@ -46,7 +46,7 @@ findConstToRemove(const VarDecl *VD, const MatchFinder::MatchResult &Result) { NameBeginLoc, SM, Result.Context->getLangOpts(), tok::semi); // Verify that there is no semicolon between ConstSearchStartLoc and - // NameBeginLoc This is to limit search area for our variable decl only + // NameBeginLoc. This is to limit search area for our variable decl only if (!PrevSemi.isInvalid() && SM.isBeforeInTranslationUnit(ConstSearchStartLoc, PrevSemi)) return std::nullopt; >From 81dd7ee717fdf3b2ea5aa37330543e8993400d09 Mon Sep 17 00:00:00 2001 From: Berkay Sahin <[email protected]> Date: Sun, 5 Apr 2026 20:38:32 +0300 Subject: [PATCH 14/15] [clang-tidy] Add test --- .../checkers/readability/redundant-const.cpp | 32 ++++++++++--------- 1 file changed, 17 insertions(+), 15 deletions(-) diff --git a/clang-tools-extra/test/clang-tidy/checkers/readability/redundant-const.cpp b/clang-tools-extra/test/clang-tidy/checkers/readability/redundant-const.cpp index 86f6a915fa8ee..565899b90919a 100644 --- a/clang-tools-extra/test/clang-tidy/checkers/readability/redundant-const.cpp +++ b/clang-tools-extra/test/clang-tidy/checkers/readability/redundant-const.cpp @@ -27,6 +27,8 @@ constexpr const char* n4 = "hello"; constexpr const auto n5 = "hello"; +constexpr const auto const n6 = "hello"; + constexpr const char* const p5 = "hello"; // CHECK-MESSAGES: [[@LINE-1]]:23: warning: redundant use of 'const'; 'constexpr' already implies 'const' // CHECK-FIXES: constexpr const char* p5 = "hello"; @@ -36,7 +38,7 @@ const constexpr T p6 = {}; // CHECK-MESSAGES: [[@LINE-1]]:1: warning: redundant use of 'const'; 'constexpr' already implies 'const' // CHECK-FIXES: constexpr T p6 = {}; -constexpr const int* n6 = p6<int*>; +constexpr const int* n7 = p6<int*>; const constexpr double p7 = p6<double>; // CHECK-MESSAGES: [[@LINE-1]]:1: warning: redundant use of 'const'; 'constexpr' already implies 'const' @@ -73,7 +75,7 @@ class Templated { int data[size]; }; -constexpr Templated<int> n7{}; +constexpr Templated<int> n8{}; template <int N> struct Templated2 { @@ -83,7 +85,7 @@ struct Templated2 { int data[size]; }; -static constexpr int n8[] = {0, 1, 4, 9, 16}; +static constexpr int n9[] = {0, 1, 4, 9, 16}; constexpr const int p9[] = {0, 1, 4, 9, 16}; // CHECK-MESSAGES: [[@LINE-1]]:11: warning: redundant use of 'const'; 'constexpr' already implies 'const' @@ -95,11 +97,11 @@ const constexpr int p10 = square(10); // CHECK-MESSAGES: [[@LINE-1]]:1: warning: redundant use of 'const'; 'constexpr' already implies 'const' // CHECK-FIXES: constexpr int p10 = square(10); -constexpr int n9 = square(5); +constexpr int n10 = square(5); -constexpr Foo** n10 = nullptr; +constexpr Foo** n11 = nullptr; -constexpr Foo* const* n11 = nullptr; +constexpr Foo* const* n12 = nullptr; constexpr Foo* const* const p11 = nullptr; // CHECK-MESSAGES: [[@LINE-1]]:23: warning: redundant use of 'const'; 'constexpr' already implies 'const' @@ -109,13 +111,13 @@ constexpr const Foo* const* const p12 = nullptr; // CHECK-MESSAGES: [[@LINE-1]]:29: warning: redundant use of 'const'; 'constexpr' already implies 'const' // CHECK-FIXES: constexpr const Foo* const* p12 = nullptr; -constexpr const int (*n12)[10] = nullptr; +constexpr const int (*n13)[10] = nullptr; constexpr const int (*const p13)[10] = nullptr; // CHECK-MESSAGES: [[@LINE-1]]:23: warning: redundant use of 'const'; 'constexpr' already implies 'const' // CHECK-FIXES: constexpr const int (*p13)[10] = nullptr; -constexpr int (*n13)(int) = nullptr; +constexpr int (*n14)(int) = nullptr; constexpr int (*const p14)(int) = nullptr; // CHECK-MESSAGES: [[@LINE-1]]:17: warning: redundant use of 'const'; 'constexpr' already implies 'const' @@ -126,13 +128,13 @@ struct Bar { int sum() { return x + y; } }; -constexpr const int Bar::*n14 = &Bar::x; +constexpr const int Bar::*n15 = &Bar::x; constexpr const int Bar::* const p15 = &Bar::x; // CHECK-MESSAGES: [[@LINE-1]]:28: warning: redundant use of 'const'; 'constexpr' already implies 'const' // CHECK-FIXES: constexpr const int Bar::* p15 = &Bar::x; -constexpr int (Bar::*n15)() = &Bar::sum; +constexpr int (Bar::*n16)() = &Bar::sum; constexpr int (Bar::* const p16)() = &Bar::sum; // CHECK-MESSAGES: [[@LINE-1]]:23: warning: redundant use of 'const'; 'constexpr' already implies 'const' @@ -141,7 +143,7 @@ constexpr int (Bar::* const p16)() = &Bar::sum; #define CONSTEXPR constexpr #define CONST const -CONSTEXPR Foo n16 = {}; +CONSTEXPR Foo n17 = {}; CONSTEXPR const Foo p17 = {}; // CHECK-MESSAGES: [[@LINE-1]]:11: warning: redundant use of 'const'; 'constexpr' already implies 'const' @@ -151,14 +153,14 @@ const CONSTEXPR Foo p18 = {}; // CHECK-MESSAGES: [[@LINE-1]]:1: warning: redundant use of 'const'; 'constexpr' already implies 'const' // CHECK-FIXES: CONSTEXPR Foo p18 = {}; -CONST constexpr Foo n17 = {}; -constexpr CONST Foo n18 = {}; +CONST constexpr Foo n18 = {}; +constexpr CONST Foo n19 = {}; const Foo* n20 = nullptr; // OK for references -constexpr const Foo& n19 = p18; -constexpr const Foo*& n21 = n20; +constexpr const Foo& n21 = p18; +constexpr const Foo*& n22 = n20; constexpr const decltype(nullptr) p19 = nullptr; // CHECK-MESSAGES: [[@LINE-1]]:11: warning: redundant use of 'const'; 'constexpr' already implies 'const' >From 003c7926bdbf0e3367ff493c2a56ff4bdf39366b Mon Sep 17 00:00:00 2001 From: Berkay Sahin <[email protected]> Date: Sun, 5 Apr 2026 22:00:03 +0300 Subject: [PATCH 15/15] [clang-tidy] Update the doc --- .../docs/clang-tidy/checks/readability/redundant-const.rst | 3 --- 1 file changed, 3 deletions(-) diff --git a/clang-tools-extra/docs/clang-tidy/checks/readability/redundant-const.rst b/clang-tools-extra/docs/clang-tidy/checks/readability/redundant-const.rst index c434ca28ffb07..eceb22cf1c1df 100644 --- a/clang-tools-extra/docs/clang-tidy/checks/readability/redundant-const.rst +++ b/clang-tools-extra/docs/clang-tidy/checks/readability/redundant-const.rst @@ -44,6 +44,3 @@ The check also analyzes pointers: // Note that `constexpr` only makes the pointer const but not the pointee. // Thus, this usage is *not* redundant. constexpr const char* ok = "ok"; // OK - - -Requires C++11 or C23. _______________________________________________ cfe-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
