[clang] [clang] Validate ABI tag attributes (PR #84272)
LocalSpook wrote: @erichkeane @AaronBallman https://github.com/llvm/llvm-project/pull/84272 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [clang] Validate ABI tag attributes (PR #84272)
LocalSpook wrote: > I kind of think "no enforcement for invalid input" is reasonable here. That > would be consistent with things like the alias attribute where we accept a > string that has to conform to ABI mangling rules (which could be a matter of > poor QoI rather than precedent). If I'm not mistaken, `alias` does *not* accept invalid input, because the compiler ensures the given string matches the mangled name of another entity in the program (whose name was checked and mangled by Clang and is therefore correct). https://github.com/llvm/llvm-project/pull/84272 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang-tools-extra] [clang-tidy] Add new check: `modernize-use-concise-preprocessor-directives` (PR #146830)
https://github.com/localspook created https://github.com/llvm/llvm-project/pull/146830 Closes #132561. This is a check that rewrites `#if`s and `#elif`s like so: ```cpp #if defined(MEOW) // -> #ifdef MEOW #if !defined(MEOW) // -> #ifndef MEOW ``` And, since C23 and C++23: ```cpp #elif defined(MEOW) // -> #elifdef MEOW #elif !defined(MEOW) // -> #elifndef MEOW ``` We can bikeshed the name and category. For example, `modernize` isn't *ideal*; rewriting `#if defined(A)` as `#ifdef A` isn't really "modernizing", because `#ifdef` has always existed, but rewriting `#elif defined(A)` as `#elifdef A` certainly is. >From 9eb58438d2b4061ad7a6bdbd1db82a5fd4043948 Mon Sep 17 00:00:00 2001 From: Victor Chernyakin Date: Thu, 3 Jul 2025 00:19:52 -0700 Subject: [PATCH] [clang-tidy] Add new check: `modernize-use-concise-preprocessor-directives` Rewrites preprocessor conditions like `#if defined(MEOW)` as `#ifdef MEOW` and `#elif !defined(MEOW)` as `#elifndef MEOW`. Closes #132561. --- .../clang-tidy/modernize/CMakeLists.txt | 1 + .../modernize/ModernizeTidyModule.cpp | 3 + .../UseConcisePreprocessorDirectivesCheck.cpp | 105 ++ .../UseConcisePreprocessorDirectivesCheck.h | 37 + clang-tools-extra/docs/ReleaseNotes.rst | 6 + .../docs/clang-tidy/checks/list.rst | 1 + .../use-concise-preprocessor-directives.rst | 28 .../use-concise-preprocessor-directives.cpp | 134 ++ 8 files changed, 315 insertions(+) create mode 100644 clang-tools-extra/clang-tidy/modernize/UseConcisePreprocessorDirectivesCheck.cpp create mode 100644 clang-tools-extra/clang-tidy/modernize/UseConcisePreprocessorDirectivesCheck.h create mode 100644 clang-tools-extra/docs/clang-tidy/checks/modernize/use-concise-preprocessor-directives.rst create mode 100644 clang-tools-extra/test/clang-tidy/checkers/modernize/use-concise-preprocessor-directives.cpp diff --git a/clang-tools-extra/clang-tidy/modernize/CMakeLists.txt b/clang-tools-extra/clang-tidy/modernize/CMakeLists.txt index 619a27b2f9bb6..22d5214b61441 100644 --- a/clang-tools-extra/clang-tidy/modernize/CMakeLists.txt +++ b/clang-tools-extra/clang-tidy/modernize/CMakeLists.txt @@ -30,6 +30,7 @@ add_clang_library(clangTidyModernizeModule STATIC UnaryStaticAssertCheck.cpp UseAutoCheck.cpp UseBoolLiteralsCheck.cpp + UseConcisePreprocessorDirectivesCheck.cpp UseConstraintsCheck.cpp UseDefaultMemberInitCheck.cpp UseDesignatedInitializersCheck.cpp diff --git a/clang-tools-extra/clang-tidy/modernize/ModernizeTidyModule.cpp b/clang-tools-extra/clang-tidy/modernize/ModernizeTidyModule.cpp index fdf38bc4b6308..28c5467f7b3e0 100644 --- a/clang-tools-extra/clang-tidy/modernize/ModernizeTidyModule.cpp +++ b/clang-tools-extra/clang-tidy/modernize/ModernizeTidyModule.cpp @@ -31,6 +31,7 @@ #include "UnaryStaticAssertCheck.h" #include "UseAutoCheck.h" #include "UseBoolLiteralsCheck.h" +#include "UseConcisePreprocessorDirectivesCheck.h" #include "UseConstraintsCheck.h" #include "UseDefaultMemberInitCheck.h" #include "UseDesignatedInitializersCheck.h" @@ -76,6 +77,8 @@ class ModernizeModule : public ClangTidyModule { CheckFactories.registerCheck( "modernize-min-max-use-initializer-list"); CheckFactories.registerCheck("modernize-pass-by-value"); +CheckFactories.registerCheck( +"modernize-use-concise-preprocessor-directives"); CheckFactories.registerCheck( "modernize-use-designated-initializers"); CheckFactories.registerCheck( diff --git a/clang-tools-extra/clang-tidy/modernize/UseConcisePreprocessorDirectivesCheck.cpp b/clang-tools-extra/clang-tidy/modernize/UseConcisePreprocessorDirectivesCheck.cpp new file mode 100644 index 0..56ed1b3cc879d --- /dev/null +++ b/clang-tools-extra/clang-tidy/modernize/UseConcisePreprocessorDirectivesCheck.cpp @@ -0,0 +1,105 @@ +//===--- UseConcisePreprocessorDirectivesCheck.cpp - clang-tidy ---===// +// +// 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 "UseConcisePreprocessorDirectivesCheck.h" +#include "clang/Basic/TokenKinds.h" +#include "clang/Lex/Lexer.h" +#include "clang/Lex/PPCallbacks.h" +#include "clang/Lex/Preprocessor.h" + +namespace clang::tidy::modernize { + +namespace { + +class IfPreprocessorCallbacks final : public PPCallbacks { +public: + IfPreprocessorCallbacks(ClangTidyCheck &Check, Preprocessor &PP) + : Check(Check), PP(PP) {} + + void If(SourceLocation Loc, SourceRange ConditionRange, + ConditionValueKind) override { +impl(Loc, ConditionRange, {"ifdef", "ifndef"}); + } + + void Elif(SourceLocation Loc, SourceRange ConditionRange, ConditionValueKind, +SourceLocation) override { +
[clang-tools-extra] [clang-tidy] Add new check: `modernize-use-concise-preprocessor-directives` (PR #146830)
https://github.com/localspook converted_to_draft https://github.com/llvm/llvm-project/pull/146830 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang-tools-extra] [clang-tidy] Add new check: `modernize-use-concise-preprocessor-directives` (PR #146830)
https://github.com/localspook updated https://github.com/llvm/llvm-project/pull/146830 >From 9eb58438d2b4061ad7a6bdbd1db82a5fd4043948 Mon Sep 17 00:00:00 2001 From: Victor Chernyakin Date: Thu, 3 Jul 2025 00:19:52 -0700 Subject: [PATCH 1/4] [clang-tidy] Add new check: `modernize-use-concise-preprocessor-directives` Rewrites preprocessor conditions like `#if defined(MEOW)` as `#ifdef MEOW` and `#elif !defined(MEOW)` as `#elifndef MEOW`. Closes #132561. --- .../clang-tidy/modernize/CMakeLists.txt | 1 + .../modernize/ModernizeTidyModule.cpp | 3 + .../UseConcisePreprocessorDirectivesCheck.cpp | 105 ++ .../UseConcisePreprocessorDirectivesCheck.h | 37 + clang-tools-extra/docs/ReleaseNotes.rst | 6 + .../docs/clang-tidy/checks/list.rst | 1 + .../use-concise-preprocessor-directives.rst | 28 .../use-concise-preprocessor-directives.cpp | 134 ++ 8 files changed, 315 insertions(+) create mode 100644 clang-tools-extra/clang-tidy/modernize/UseConcisePreprocessorDirectivesCheck.cpp create mode 100644 clang-tools-extra/clang-tidy/modernize/UseConcisePreprocessorDirectivesCheck.h create mode 100644 clang-tools-extra/docs/clang-tidy/checks/modernize/use-concise-preprocessor-directives.rst create mode 100644 clang-tools-extra/test/clang-tidy/checkers/modernize/use-concise-preprocessor-directives.cpp diff --git a/clang-tools-extra/clang-tidy/modernize/CMakeLists.txt b/clang-tools-extra/clang-tidy/modernize/CMakeLists.txt index 619a27b2f9bb6..22d5214b61441 100644 --- a/clang-tools-extra/clang-tidy/modernize/CMakeLists.txt +++ b/clang-tools-extra/clang-tidy/modernize/CMakeLists.txt @@ -30,6 +30,7 @@ add_clang_library(clangTidyModernizeModule STATIC UnaryStaticAssertCheck.cpp UseAutoCheck.cpp UseBoolLiteralsCheck.cpp + UseConcisePreprocessorDirectivesCheck.cpp UseConstraintsCheck.cpp UseDefaultMemberInitCheck.cpp UseDesignatedInitializersCheck.cpp diff --git a/clang-tools-extra/clang-tidy/modernize/ModernizeTidyModule.cpp b/clang-tools-extra/clang-tidy/modernize/ModernizeTidyModule.cpp index fdf38bc4b6308..28c5467f7b3e0 100644 --- a/clang-tools-extra/clang-tidy/modernize/ModernizeTidyModule.cpp +++ b/clang-tools-extra/clang-tidy/modernize/ModernizeTidyModule.cpp @@ -31,6 +31,7 @@ #include "UnaryStaticAssertCheck.h" #include "UseAutoCheck.h" #include "UseBoolLiteralsCheck.h" +#include "UseConcisePreprocessorDirectivesCheck.h" #include "UseConstraintsCheck.h" #include "UseDefaultMemberInitCheck.h" #include "UseDesignatedInitializersCheck.h" @@ -76,6 +77,8 @@ class ModernizeModule : public ClangTidyModule { CheckFactories.registerCheck( "modernize-min-max-use-initializer-list"); CheckFactories.registerCheck("modernize-pass-by-value"); +CheckFactories.registerCheck( +"modernize-use-concise-preprocessor-directives"); CheckFactories.registerCheck( "modernize-use-designated-initializers"); CheckFactories.registerCheck( diff --git a/clang-tools-extra/clang-tidy/modernize/UseConcisePreprocessorDirectivesCheck.cpp b/clang-tools-extra/clang-tidy/modernize/UseConcisePreprocessorDirectivesCheck.cpp new file mode 100644 index 0..56ed1b3cc879d --- /dev/null +++ b/clang-tools-extra/clang-tidy/modernize/UseConcisePreprocessorDirectivesCheck.cpp @@ -0,0 +1,105 @@ +//===--- UseConcisePreprocessorDirectivesCheck.cpp - clang-tidy ---===// +// +// 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 "UseConcisePreprocessorDirectivesCheck.h" +#include "clang/Basic/TokenKinds.h" +#include "clang/Lex/Lexer.h" +#include "clang/Lex/PPCallbacks.h" +#include "clang/Lex/Preprocessor.h" + +namespace clang::tidy::modernize { + +namespace { + +class IfPreprocessorCallbacks final : public PPCallbacks { +public: + IfPreprocessorCallbacks(ClangTidyCheck &Check, Preprocessor &PP) + : Check(Check), PP(PP) {} + + void If(SourceLocation Loc, SourceRange ConditionRange, + ConditionValueKind) override { +impl(Loc, ConditionRange, {"ifdef", "ifndef"}); + } + + void Elif(SourceLocation Loc, SourceRange ConditionRange, ConditionValueKind, +SourceLocation) override { +if (PP.getLangOpts().C23 || PP.getLangOpts().CPlusPlus23) { + impl(Loc, ConditionRange, {"elifdef", "elifndef"}); +} + } + +private: + void impl(SourceLocation DirectiveLoc, SourceRange ConditionRange, +const llvm::StringLiteral (&Replacements)[2]) { +StringRef Condition = +Lexer::getSourceText(CharSourceRange::getTokenRange(ConditionRange), + PP.getSourceManager(), PP.getLangOpts()); +Lexer Lex(DirectiveLoc, PP.getLangOpts(), Condition.data(), + C
[clang-tools-extra] [clang-tidy] Add new check: `modernize-use-concise-preprocessor-directives` (PR #146830)
@@ -0,0 +1,105 @@ +//===--- UseConcisePreprocessorDirectivesCheck.cpp - clang-tidy ---===// +// +// 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 "UseConcisePreprocessorDirectivesCheck.h" +#include "clang/Basic/TokenKinds.h" +#include "clang/Lex/Lexer.h" +#include "clang/Lex/PPCallbacks.h" +#include "clang/Lex/Preprocessor.h" + +namespace clang::tidy::modernize { + +namespace { + +class IfPreprocessorCallbacks final : public PPCallbacks { +public: + IfPreprocessorCallbacks(ClangTidyCheck &Check, Preprocessor &PP) + : Check(Check), PP(PP) {} + + void If(SourceLocation Loc, SourceRange ConditionRange, + ConditionValueKind) override { +impl(Loc, ConditionRange, {"ifdef", "ifndef"}); + } + + void Elif(SourceLocation Loc, SourceRange ConditionRange, ConditionValueKind, +SourceLocation) override { +if (PP.getLangOpts().C23 || PP.getLangOpts().CPlusPlus23) { + impl(Loc, ConditionRange, {"elifdef", "elifndef"}); +} + } + +private: + void impl(SourceLocation DirectiveLoc, SourceRange ConditionRange, +const llvm::StringLiteral (&Replacements)[2]) { +StringRef Condition = localspook wrote: Are we more strict about const correctness in new code? (I'm a fan, it's just that from skimming some files, it seems like most LLVM code doesn't care about const correctness much). https://github.com/llvm/llvm-project/pull/146830 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang-tools-extra] [clang-tidy] Add new check: `modernize-use-concise-preprocessor-directives` (PR #146830)
https://github.com/localspook ready_for_review https://github.com/llvm/llvm-project/pull/146830 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang-tools-extra] [clang-tidy] Add new check: `modernize-use-concise-preprocessor-directives` (PR #146830)
https://github.com/localspook updated https://github.com/llvm/llvm-project/pull/146830 >From 9eb58438d2b4061ad7a6bdbd1db82a5fd4043948 Mon Sep 17 00:00:00 2001 From: Victor Chernyakin Date: Thu, 3 Jul 2025 00:19:52 -0700 Subject: [PATCH 1/5] [clang-tidy] Add new check: `modernize-use-concise-preprocessor-directives` Rewrites preprocessor conditions like `#if defined(MEOW)` as `#ifdef MEOW` and `#elif !defined(MEOW)` as `#elifndef MEOW`. Closes #132561. --- .../clang-tidy/modernize/CMakeLists.txt | 1 + .../modernize/ModernizeTidyModule.cpp | 3 + .../UseConcisePreprocessorDirectivesCheck.cpp | 105 ++ .../UseConcisePreprocessorDirectivesCheck.h | 37 + clang-tools-extra/docs/ReleaseNotes.rst | 6 + .../docs/clang-tidy/checks/list.rst | 1 + .../use-concise-preprocessor-directives.rst | 28 .../use-concise-preprocessor-directives.cpp | 134 ++ 8 files changed, 315 insertions(+) create mode 100644 clang-tools-extra/clang-tidy/modernize/UseConcisePreprocessorDirectivesCheck.cpp create mode 100644 clang-tools-extra/clang-tidy/modernize/UseConcisePreprocessorDirectivesCheck.h create mode 100644 clang-tools-extra/docs/clang-tidy/checks/modernize/use-concise-preprocessor-directives.rst create mode 100644 clang-tools-extra/test/clang-tidy/checkers/modernize/use-concise-preprocessor-directives.cpp diff --git a/clang-tools-extra/clang-tidy/modernize/CMakeLists.txt b/clang-tools-extra/clang-tidy/modernize/CMakeLists.txt index 619a27b2f9bb6..22d5214b61441 100644 --- a/clang-tools-extra/clang-tidy/modernize/CMakeLists.txt +++ b/clang-tools-extra/clang-tidy/modernize/CMakeLists.txt @@ -30,6 +30,7 @@ add_clang_library(clangTidyModernizeModule STATIC UnaryStaticAssertCheck.cpp UseAutoCheck.cpp UseBoolLiteralsCheck.cpp + UseConcisePreprocessorDirectivesCheck.cpp UseConstraintsCheck.cpp UseDefaultMemberInitCheck.cpp UseDesignatedInitializersCheck.cpp diff --git a/clang-tools-extra/clang-tidy/modernize/ModernizeTidyModule.cpp b/clang-tools-extra/clang-tidy/modernize/ModernizeTidyModule.cpp index fdf38bc4b6308..28c5467f7b3e0 100644 --- a/clang-tools-extra/clang-tidy/modernize/ModernizeTidyModule.cpp +++ b/clang-tools-extra/clang-tidy/modernize/ModernizeTidyModule.cpp @@ -31,6 +31,7 @@ #include "UnaryStaticAssertCheck.h" #include "UseAutoCheck.h" #include "UseBoolLiteralsCheck.h" +#include "UseConcisePreprocessorDirectivesCheck.h" #include "UseConstraintsCheck.h" #include "UseDefaultMemberInitCheck.h" #include "UseDesignatedInitializersCheck.h" @@ -76,6 +77,8 @@ class ModernizeModule : public ClangTidyModule { CheckFactories.registerCheck( "modernize-min-max-use-initializer-list"); CheckFactories.registerCheck("modernize-pass-by-value"); +CheckFactories.registerCheck( +"modernize-use-concise-preprocessor-directives"); CheckFactories.registerCheck( "modernize-use-designated-initializers"); CheckFactories.registerCheck( diff --git a/clang-tools-extra/clang-tidy/modernize/UseConcisePreprocessorDirectivesCheck.cpp b/clang-tools-extra/clang-tidy/modernize/UseConcisePreprocessorDirectivesCheck.cpp new file mode 100644 index 0..56ed1b3cc879d --- /dev/null +++ b/clang-tools-extra/clang-tidy/modernize/UseConcisePreprocessorDirectivesCheck.cpp @@ -0,0 +1,105 @@ +//===--- UseConcisePreprocessorDirectivesCheck.cpp - clang-tidy ---===// +// +// 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 "UseConcisePreprocessorDirectivesCheck.h" +#include "clang/Basic/TokenKinds.h" +#include "clang/Lex/Lexer.h" +#include "clang/Lex/PPCallbacks.h" +#include "clang/Lex/Preprocessor.h" + +namespace clang::tidy::modernize { + +namespace { + +class IfPreprocessorCallbacks final : public PPCallbacks { +public: + IfPreprocessorCallbacks(ClangTidyCheck &Check, Preprocessor &PP) + : Check(Check), PP(PP) {} + + void If(SourceLocation Loc, SourceRange ConditionRange, + ConditionValueKind) override { +impl(Loc, ConditionRange, {"ifdef", "ifndef"}); + } + + void Elif(SourceLocation Loc, SourceRange ConditionRange, ConditionValueKind, +SourceLocation) override { +if (PP.getLangOpts().C23 || PP.getLangOpts().CPlusPlus23) { + impl(Loc, ConditionRange, {"elifdef", "elifndef"}); +} + } + +private: + void impl(SourceLocation DirectiveLoc, SourceRange ConditionRange, +const llvm::StringLiteral (&Replacements)[2]) { +StringRef Condition = +Lexer::getSourceText(CharSourceRange::getTokenRange(ConditionRange), + PP.getSourceManager(), PP.getLangOpts()); +Lexer Lex(DirectiveLoc, PP.getLangOpts(), Condition.data(), + C
[clang-tools-extra] [clang-tidy] Add new check: `readability-use-concise-preprocessor-directives` (PR #146830)
@@ -0,0 +1,40 @@ +//===--- UseConcisePreprocessorDirectivesCheck.h - clang-tidy ---*- C++ -*-===// +// +// 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_USECONCISEPREPROCESSORDIRECTIVESCHECK_H +#define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_READABILITY_USECONCISEPREPROCESSORDIRECTIVESCHECK_H + +#include "../ClangTidyCheck.h" + +namespace clang::tidy::readability { + +/// Shortens `#if` preprocessor conditions: +/// +/// #if defined(MEOW) -> #ifdef MEOW +/// #if !defined(MEOW) -> #ifndef MEOW +/// +/// And, since C23 and C++23, shortens `#elif` conditions too: +/// +/// #elif defined(MEOW) -> #elifdef MEOW +/// #elif !defined(MEOW) -> #elifndef MEOW +/// +/// User-facing documentation: +/// https://clang.llvm.org/extra/clang-tidy/checks/readability/use-concise-preprocessor-directives.html +class UseConcisePreprocessorDirectivesCheck : public ClangTidyCheck { +public: + using ClangTidyCheck::ClangTidyCheck; + void registerPPCallbacks(const SourceManager &SM, Preprocessor *PP, + Preprocessor *ModuleExpanderPP) override; + bool isLanguageVersionSupported(const LangOptions &LangOpts) const override { +return LangOpts.CPlusPlus || LangOpts.C99; localspook wrote: Since this is a preprocessor-level check, it works in all C and C++ language versions. I don't see how to express "works in any C mode" though, `LangOptions` doesn't have a `C` member variable, analogous to `CPlusPlus`. https://github.com/llvm/llvm-project/pull/146830 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang-tools-extra] [clang-tidy] Teach `modernize-type-traits` about more type traits (PR #147074)
@@ -130,6 +155,10 @@ static const llvm::StringSet<> TypeTraits = { "result_of", "invoke_result", "type_identity", +"compare_three_way_result", +"common_comparison_category", localspook wrote: > We usually don't care if there would be a warning inside system headers, we > only check user-code. It's okay if internal implementation would give a > warning - it is usually filtered out. Ah, that's what I was missing! https://github.com/llvm/llvm-project/pull/147074 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang-tools-extra] [clang-tidy] Teach `modernize-type-traits` about more type traits (PR #147074)
https://github.com/localspook updated https://github.com/llvm/llvm-project/pull/147074 >From 7ad6f7b8663980183e8bb8e79843942870e36267 Mon Sep 17 00:00:00 2001 From: Victor Chernyakin Date: Fri, 4 Jul 2025 07:42:54 -0700 Subject: [PATCH 1/6] [clang-tidy] Teach `modernize-type-traits` about more type traits --- .../clang-tidy/modernize/TypeTraitsCheck.cpp | 27 +++ clang-tools-extra/docs/ReleaseNotes.rst | 3 +++ 2 files changed, 30 insertions(+) diff --git a/clang-tools-extra/clang-tidy/modernize/TypeTraitsCheck.cpp b/clang-tools-extra/clang-tidy/modernize/TypeTraitsCheck.cpp index c0766395ec5cc..92e6f61a6d9d4 100644 --- a/clang-tools-extra/clang-tidy/modernize/TypeTraitsCheck.cpp +++ b/clang-tools-extra/clang-tidy/modernize/TypeTraitsCheck.cpp @@ -28,8 +28,10 @@ static const llvm::StringSet<> ValueTraits = { "is_array", "is_assignable", "is_base_of", +"is_bind_expression", "is_bounded_array", "is_class", +"is_clock", "is_compound", "is_const", "is_constructible", @@ -40,10 +42,14 @@ static const llvm::StringSet<> ValueTraits = { "is_destructible", "is_empty", "is_enum", +"is_error_code_enum", +"is_error_condition_enum", +"is_execution_policy", "is_final", "is_floating_point", "is_function", "is_fundamental", +"is_implicit_lifetime", "is_integral", "is_invocable", "is_invocable_r", @@ -65,14 +71,17 @@ static const llvm::StringSet<> ValueTraits = { "is_nothrow_invocable_r", "is_nothrow_move_assignable", "is_nothrow_move_constructible", +"is_nothrow_relocatable", "is_nothrow_swappable", "is_nothrow_swappable_with", "is_null_pointer", "is_object", +"is_placeholder", "is_pointer", "is_pointer_interconvertible_base_of", "is_polymorphic", "is_reference", +"is_replaceable", "is_rvalue_reference", "is_same", "is_scalar", @@ -91,15 +100,27 @@ static const llvm::StringSet<> ValueTraits = { "is_trivially_destructible", "is_trivially_move_assignable", "is_trivially_move_constructible", +"is_trivially_relocatable", "is_unbounded_array", "is_union", "is_unsigned", +"is_virtual_base_of", "is_void", "is_volatile", "negation", "rank", +"ratio_equal", +"ratio_greater_equal", +"ratio_greater", +"ratio_less_equal", +"ratio_less", +"ratio_not_equal", "reference_constructs_from_temporary", "reference_converts_from_temporary", +"treat_as_floating_point", +"tuple_size", +"uses_allocator", +"variant_size", }; static const llvm::StringSet<> TypeTraits = { @@ -130,6 +151,12 @@ static const llvm::StringSet<> TypeTraits = { "result_of", "invoke_result", "type_identity", + "tuple_element", + "variant_alternative", + "compare_three_way_result", + "common_comparison_category", + "unwrap_ref_decay", + "unwrap_reference", }; static DeclarationName getName(const DependentScopeDeclRefExpr &D) { diff --git a/clang-tools-extra/docs/ReleaseNotes.rst b/clang-tools-extra/docs/ReleaseNotes.rst index f8f183e9de1cc..3d554733ad3fd 100644 --- a/clang-tools-extra/docs/ReleaseNotes.rst +++ b/clang-tools-extra/docs/ReleaseNotes.rst @@ -276,6 +276,9 @@ Changes in existing checks excluding variables with ``thread_local`` storage class specifier from being matched. +- Improved :doc:`modernize-type-traits + ` check by detecting more type traits. + - Improved :doc:`modernize-use-default-member-init ` check by matching arithmetic operations, ``constexpr`` and ``static`` values, and detecting >From 930db523cdbe6bf44b334a17667229e3586981aa Mon Sep 17 00:00:00 2001 From: Victor Chernyakin Date: Fri, 4 Jul 2025 07:59:02 -0700 Subject: [PATCH 2/6] Whoops, didn't exclude `treat_as_floating_point_v` or `is_clock_v` --- clang-tools-extra/clang-tidy/modernize/TypeTraitsCheck.cpp | 2 -- 1 file changed, 2 deletions(-) diff --git a/clang-tools-extra/clang-tidy/modernize/TypeTraitsCheck.cpp b/clang-tools-extra/clang-tidy/modernize/TypeTraitsCheck.cpp index 92e6f61a6d9d4..aaf9d08c63b2e 100644 --- a/clang-tools-extra/clang-tidy/modernize/TypeTraitsCheck.cpp +++ b/clang-tools-extra/clang-tidy/modernize/TypeTraitsCheck.cpp @@ -31,7 +31,6 @@ static const llvm::StringSet<> ValueTraits = { "is_bind_expression", "is_bounded_array", "is_class", -"is_clock", "is_compound", "is_const", "is_constructible", @@ -117,7 +116,6 @@ static const llvm::StringSet<> ValueTraits = { "ratio_not_equal", "reference_constructs_from_temporary", "reference_converts_from_temporary", -"treat_as_floating_point", "tuple_size", "uses_allocator", "variant_size", >From 13dcaabd66610972db0e6e52e49bb63878e248a6 Mon Sep 17 00:00:00 2001 From: Victor Chernyakin Date: Fri, 4 Jul 2025 08:15:53 -0700 Subject: [PATCH 3/6] clang-format
[clang-tools-extra] [clang-tidy] Add new check: `readability-use-concise-preprocessor-directives` (PR #146830)
@@ -0,0 +1,40 @@ +//===--- UseConcisePreprocessorDirectivesCheck.h - clang-tidy ---*- C++ -*-===// +// +// 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_USECONCISEPREPROCESSORDIRECTIVESCHECK_H +#define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_READABILITY_USECONCISEPREPROCESSORDIRECTIVESCHECK_H + +#include "../ClangTidyCheck.h" + +namespace clang::tidy::readability { + +/// Shortens `#if` preprocessor conditions: +/// +/// #if defined(MEOW) -> #ifdef MEOW +/// #if !defined(MEOW) -> #ifndef MEOW +/// +/// And, since C23 and C++23, shortens `#elif` conditions too: +/// +/// #elif defined(MEOW) -> #elifdef MEOW +/// #elif !defined(MEOW) -> #elifndef MEOW +/// +/// User-facing documentation: +/// https://clang.llvm.org/extra/clang-tidy/checks/readability/use-concise-preprocessor-directives.html +class UseConcisePreprocessorDirectivesCheck : public ClangTidyCheck { +public: + using ClangTidyCheck::ClangTidyCheck; + void registerPPCallbacks(const SourceManager &SM, Preprocessor *PP, + Preprocessor *ModuleExpanderPP) override; + bool isLanguageVersionSupported(const LangOptions &LangOpts) const override { +return LangOpts.CPlusPlus || LangOpts.C99; localspook wrote: Should it just be `return true;`? https://github.com/llvm/llvm-project/pull/146830 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang-tools-extra] [clang-tidy] Teach `modernize-type-traits` about more type traits (PR #147074)
@@ -130,6 +155,10 @@ static const llvm::StringSet<> TypeTraits = { "result_of", "invoke_result", "type_identity", +"compare_three_way_result", +"common_comparison_category", localspook wrote: Hm, I've looked into it some more, and it turns out we do already have recursive traits: `common_type` and `common_reference` (also `conjunction` and `disjunction`, but those are "metatraits", they're somewhat different). So maybe recursive traits are alright? I've looked at some implementations, and I thought they were written like this: ```cpp template <...> struct trait { using type = trait<...>::type; // Triggers the check. }; ``` but actually they seem to be written like this: ```cpp template <...> struct trait : trait<...> {}; // No warning. ``` https://github.com/llvm/llvm-project/pull/147074 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang-tools-extra] [clang-tidy] Teach `modernize-type-traits` about more type traits (PR #147074)
https://github.com/localspook edited https://github.com/llvm/llvm-project/pull/147074 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang-tools-extra] [clang-tidy] Add new check: `readability-use-concise-preprocessor-directives` (PR #146830)
https://github.com/localspook edited https://github.com/llvm/llvm-project/pull/146830 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang-tools-extra] [clang-tidy] Add new check: `readability-use-concise-preprocessor-directives` (PR #146830)
https://github.com/localspook updated https://github.com/llvm/llvm-project/pull/146830 >From 9eb58438d2b4061ad7a6bdbd1db82a5fd4043948 Mon Sep 17 00:00:00 2001 From: Victor Chernyakin Date: Thu, 3 Jul 2025 00:19:52 -0700 Subject: [PATCH 1/9] [clang-tidy] Add new check: `modernize-use-concise-preprocessor-directives` Rewrites preprocessor conditions like `#if defined(MEOW)` as `#ifdef MEOW` and `#elif !defined(MEOW)` as `#elifndef MEOW`. Closes #132561. --- .../clang-tidy/modernize/CMakeLists.txt | 1 + .../modernize/ModernizeTidyModule.cpp | 3 + .../UseConcisePreprocessorDirectivesCheck.cpp | 105 ++ .../UseConcisePreprocessorDirectivesCheck.h | 37 + clang-tools-extra/docs/ReleaseNotes.rst | 6 + .../docs/clang-tidy/checks/list.rst | 1 + .../use-concise-preprocessor-directives.rst | 28 .../use-concise-preprocessor-directives.cpp | 134 ++ 8 files changed, 315 insertions(+) create mode 100644 clang-tools-extra/clang-tidy/modernize/UseConcisePreprocessorDirectivesCheck.cpp create mode 100644 clang-tools-extra/clang-tidy/modernize/UseConcisePreprocessorDirectivesCheck.h create mode 100644 clang-tools-extra/docs/clang-tidy/checks/modernize/use-concise-preprocessor-directives.rst create mode 100644 clang-tools-extra/test/clang-tidy/checkers/modernize/use-concise-preprocessor-directives.cpp diff --git a/clang-tools-extra/clang-tidy/modernize/CMakeLists.txt b/clang-tools-extra/clang-tidy/modernize/CMakeLists.txt index 619a27b2f9bb6..22d5214b61441 100644 --- a/clang-tools-extra/clang-tidy/modernize/CMakeLists.txt +++ b/clang-tools-extra/clang-tidy/modernize/CMakeLists.txt @@ -30,6 +30,7 @@ add_clang_library(clangTidyModernizeModule STATIC UnaryStaticAssertCheck.cpp UseAutoCheck.cpp UseBoolLiteralsCheck.cpp + UseConcisePreprocessorDirectivesCheck.cpp UseConstraintsCheck.cpp UseDefaultMemberInitCheck.cpp UseDesignatedInitializersCheck.cpp diff --git a/clang-tools-extra/clang-tidy/modernize/ModernizeTidyModule.cpp b/clang-tools-extra/clang-tidy/modernize/ModernizeTidyModule.cpp index fdf38bc4b6308..28c5467f7b3e0 100644 --- a/clang-tools-extra/clang-tidy/modernize/ModernizeTidyModule.cpp +++ b/clang-tools-extra/clang-tidy/modernize/ModernizeTidyModule.cpp @@ -31,6 +31,7 @@ #include "UnaryStaticAssertCheck.h" #include "UseAutoCheck.h" #include "UseBoolLiteralsCheck.h" +#include "UseConcisePreprocessorDirectivesCheck.h" #include "UseConstraintsCheck.h" #include "UseDefaultMemberInitCheck.h" #include "UseDesignatedInitializersCheck.h" @@ -76,6 +77,8 @@ class ModernizeModule : public ClangTidyModule { CheckFactories.registerCheck( "modernize-min-max-use-initializer-list"); CheckFactories.registerCheck("modernize-pass-by-value"); +CheckFactories.registerCheck( +"modernize-use-concise-preprocessor-directives"); CheckFactories.registerCheck( "modernize-use-designated-initializers"); CheckFactories.registerCheck( diff --git a/clang-tools-extra/clang-tidy/modernize/UseConcisePreprocessorDirectivesCheck.cpp b/clang-tools-extra/clang-tidy/modernize/UseConcisePreprocessorDirectivesCheck.cpp new file mode 100644 index 0..56ed1b3cc879d --- /dev/null +++ b/clang-tools-extra/clang-tidy/modernize/UseConcisePreprocessorDirectivesCheck.cpp @@ -0,0 +1,105 @@ +//===--- UseConcisePreprocessorDirectivesCheck.cpp - clang-tidy ---===// +// +// 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 "UseConcisePreprocessorDirectivesCheck.h" +#include "clang/Basic/TokenKinds.h" +#include "clang/Lex/Lexer.h" +#include "clang/Lex/PPCallbacks.h" +#include "clang/Lex/Preprocessor.h" + +namespace clang::tidy::modernize { + +namespace { + +class IfPreprocessorCallbacks final : public PPCallbacks { +public: + IfPreprocessorCallbacks(ClangTidyCheck &Check, Preprocessor &PP) + : Check(Check), PP(PP) {} + + void If(SourceLocation Loc, SourceRange ConditionRange, + ConditionValueKind) override { +impl(Loc, ConditionRange, {"ifdef", "ifndef"}); + } + + void Elif(SourceLocation Loc, SourceRange ConditionRange, ConditionValueKind, +SourceLocation) override { +if (PP.getLangOpts().C23 || PP.getLangOpts().CPlusPlus23) { + impl(Loc, ConditionRange, {"elifdef", "elifndef"}); +} + } + +private: + void impl(SourceLocation DirectiveLoc, SourceRange ConditionRange, +const llvm::StringLiteral (&Replacements)[2]) { +StringRef Condition = +Lexer::getSourceText(CharSourceRange::getTokenRange(ConditionRange), + PP.getSourceManager(), PP.getLangOpts()); +Lexer Lex(DirectiveLoc, PP.getLangOpts(), Condition.data(), + C
[clang-tools-extra] [clang-tidy] Add new check: `readability-use-concise-preprocessor-directives` (PR #146830)
https://github.com/localspook edited https://github.com/llvm/llvm-project/pull/146830 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang-tools-extra] [clang-tidy] Teach `modernize-type-traits` about more type traits (PR #147074)
@@ -130,6 +149,12 @@ static const llvm::StringSet<> TypeTraits = { "result_of", "invoke_result", "type_identity", +"tuple_element", localspook wrote: Good catch -- recursive traits are indeed problematic, the check fires on the recursive use in the definition. Unfortunately I'm not confident fixing it (that's kinda why I'm not addressing `treat_as_floating_point_v` or `is_clock_v` either...), so I've just removed `tuple_element` and added a `FIXME`. https://github.com/llvm/llvm-project/pull/147074 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang-tools-extra] [clang-tidy] Teach `modernize-type-traits` about more type traits (PR #147074)
https://github.com/localspook updated https://github.com/llvm/llvm-project/pull/147074 >From 7ad6f7b8663980183e8bb8e79843942870e36267 Mon Sep 17 00:00:00 2001 From: Victor Chernyakin Date: Fri, 4 Jul 2025 07:42:54 -0700 Subject: [PATCH 1/4] [clang-tidy] Teach `modernize-type-traits` about more type traits --- .../clang-tidy/modernize/TypeTraitsCheck.cpp | 27 +++ clang-tools-extra/docs/ReleaseNotes.rst | 3 +++ 2 files changed, 30 insertions(+) diff --git a/clang-tools-extra/clang-tidy/modernize/TypeTraitsCheck.cpp b/clang-tools-extra/clang-tidy/modernize/TypeTraitsCheck.cpp index c0766395ec5cc..92e6f61a6d9d4 100644 --- a/clang-tools-extra/clang-tidy/modernize/TypeTraitsCheck.cpp +++ b/clang-tools-extra/clang-tidy/modernize/TypeTraitsCheck.cpp @@ -28,8 +28,10 @@ static const llvm::StringSet<> ValueTraits = { "is_array", "is_assignable", "is_base_of", +"is_bind_expression", "is_bounded_array", "is_class", +"is_clock", "is_compound", "is_const", "is_constructible", @@ -40,10 +42,14 @@ static const llvm::StringSet<> ValueTraits = { "is_destructible", "is_empty", "is_enum", +"is_error_code_enum", +"is_error_condition_enum", +"is_execution_policy", "is_final", "is_floating_point", "is_function", "is_fundamental", +"is_implicit_lifetime", "is_integral", "is_invocable", "is_invocable_r", @@ -65,14 +71,17 @@ static const llvm::StringSet<> ValueTraits = { "is_nothrow_invocable_r", "is_nothrow_move_assignable", "is_nothrow_move_constructible", +"is_nothrow_relocatable", "is_nothrow_swappable", "is_nothrow_swappable_with", "is_null_pointer", "is_object", +"is_placeholder", "is_pointer", "is_pointer_interconvertible_base_of", "is_polymorphic", "is_reference", +"is_replaceable", "is_rvalue_reference", "is_same", "is_scalar", @@ -91,15 +100,27 @@ static const llvm::StringSet<> ValueTraits = { "is_trivially_destructible", "is_trivially_move_assignable", "is_trivially_move_constructible", +"is_trivially_relocatable", "is_unbounded_array", "is_union", "is_unsigned", +"is_virtual_base_of", "is_void", "is_volatile", "negation", "rank", +"ratio_equal", +"ratio_greater_equal", +"ratio_greater", +"ratio_less_equal", +"ratio_less", +"ratio_not_equal", "reference_constructs_from_temporary", "reference_converts_from_temporary", +"treat_as_floating_point", +"tuple_size", +"uses_allocator", +"variant_size", }; static const llvm::StringSet<> TypeTraits = { @@ -130,6 +151,12 @@ static const llvm::StringSet<> TypeTraits = { "result_of", "invoke_result", "type_identity", + "tuple_element", + "variant_alternative", + "compare_three_way_result", + "common_comparison_category", + "unwrap_ref_decay", + "unwrap_reference", }; static DeclarationName getName(const DependentScopeDeclRefExpr &D) { diff --git a/clang-tools-extra/docs/ReleaseNotes.rst b/clang-tools-extra/docs/ReleaseNotes.rst index f8f183e9de1cc..3d554733ad3fd 100644 --- a/clang-tools-extra/docs/ReleaseNotes.rst +++ b/clang-tools-extra/docs/ReleaseNotes.rst @@ -276,6 +276,9 @@ Changes in existing checks excluding variables with ``thread_local`` storage class specifier from being matched. +- Improved :doc:`modernize-type-traits + ` check by detecting more type traits. + - Improved :doc:`modernize-use-default-member-init ` check by matching arithmetic operations, ``constexpr`` and ``static`` values, and detecting >From 930db523cdbe6bf44b334a17667229e3586981aa Mon Sep 17 00:00:00 2001 From: Victor Chernyakin Date: Fri, 4 Jul 2025 07:59:02 -0700 Subject: [PATCH 2/4] Whoops, didn't exclude `treat_as_floating_point_v` or `is_clock_v` --- clang-tools-extra/clang-tidy/modernize/TypeTraitsCheck.cpp | 2 -- 1 file changed, 2 deletions(-) diff --git a/clang-tools-extra/clang-tidy/modernize/TypeTraitsCheck.cpp b/clang-tools-extra/clang-tidy/modernize/TypeTraitsCheck.cpp index 92e6f61a6d9d4..aaf9d08c63b2e 100644 --- a/clang-tools-extra/clang-tidy/modernize/TypeTraitsCheck.cpp +++ b/clang-tools-extra/clang-tidy/modernize/TypeTraitsCheck.cpp @@ -31,7 +31,6 @@ static const llvm::StringSet<> ValueTraits = { "is_bind_expression", "is_bounded_array", "is_class", -"is_clock", "is_compound", "is_const", "is_constructible", @@ -117,7 +116,6 @@ static const llvm::StringSet<> ValueTraits = { "ratio_not_equal", "reference_constructs_from_temporary", "reference_converts_from_temporary", -"treat_as_floating_point", "tuple_size", "uses_allocator", "variant_size", >From 13dcaabd66610972db0e6e52e49bb63878e248a6 Mon Sep 17 00:00:00 2001 From: Victor Chernyakin Date: Fri, 4 Jul 2025 08:15:53 -0700 Subject: [PATCH 3/4] clang-format
[clang-tools-extra] [clang-tidy] Teach `modernize-type-traits` about more type traits (PR #147074)
localspook wrote: I've changed the tests to use `-std=c++17-or-later`, but I don't think we need to add tests for the new traits because they wouldn't exercise any new codepaths. It's not like we only match on `compare_three_way_result_t` if compiling in C++20, no, we match on all traits in all modes. https://github.com/llvm/llvm-project/pull/147074 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang-tools-extra] [clang-tidy] Teach `modernize-type-traits` about more type traits (PR #147074)
https://github.com/localspook edited https://github.com/llvm/llvm-project/pull/147074 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang-tools-extra] [clang-tidy] Teach `modernize-type-traits` about more type traits (PR #147074)
https://github.com/localspook updated https://github.com/llvm/llvm-project/pull/147074 >From 7ad6f7b8663980183e8bb8e79843942870e36267 Mon Sep 17 00:00:00 2001 From: Victor Chernyakin Date: Fri, 4 Jul 2025 07:42:54 -0700 Subject: [PATCH 1/2] [clang-tidy] Teach `modernize-type-traits` about more type traits --- .../clang-tidy/modernize/TypeTraitsCheck.cpp | 27 +++ clang-tools-extra/docs/ReleaseNotes.rst | 3 +++ 2 files changed, 30 insertions(+) diff --git a/clang-tools-extra/clang-tidy/modernize/TypeTraitsCheck.cpp b/clang-tools-extra/clang-tidy/modernize/TypeTraitsCheck.cpp index c0766395ec5cc..92e6f61a6d9d4 100644 --- a/clang-tools-extra/clang-tidy/modernize/TypeTraitsCheck.cpp +++ b/clang-tools-extra/clang-tidy/modernize/TypeTraitsCheck.cpp @@ -28,8 +28,10 @@ static const llvm::StringSet<> ValueTraits = { "is_array", "is_assignable", "is_base_of", +"is_bind_expression", "is_bounded_array", "is_class", +"is_clock", "is_compound", "is_const", "is_constructible", @@ -40,10 +42,14 @@ static const llvm::StringSet<> ValueTraits = { "is_destructible", "is_empty", "is_enum", +"is_error_code_enum", +"is_error_condition_enum", +"is_execution_policy", "is_final", "is_floating_point", "is_function", "is_fundamental", +"is_implicit_lifetime", "is_integral", "is_invocable", "is_invocable_r", @@ -65,14 +71,17 @@ static const llvm::StringSet<> ValueTraits = { "is_nothrow_invocable_r", "is_nothrow_move_assignable", "is_nothrow_move_constructible", +"is_nothrow_relocatable", "is_nothrow_swappable", "is_nothrow_swappable_with", "is_null_pointer", "is_object", +"is_placeholder", "is_pointer", "is_pointer_interconvertible_base_of", "is_polymorphic", "is_reference", +"is_replaceable", "is_rvalue_reference", "is_same", "is_scalar", @@ -91,15 +100,27 @@ static const llvm::StringSet<> ValueTraits = { "is_trivially_destructible", "is_trivially_move_assignable", "is_trivially_move_constructible", +"is_trivially_relocatable", "is_unbounded_array", "is_union", "is_unsigned", +"is_virtual_base_of", "is_void", "is_volatile", "negation", "rank", +"ratio_equal", +"ratio_greater_equal", +"ratio_greater", +"ratio_less_equal", +"ratio_less", +"ratio_not_equal", "reference_constructs_from_temporary", "reference_converts_from_temporary", +"treat_as_floating_point", +"tuple_size", +"uses_allocator", +"variant_size", }; static const llvm::StringSet<> TypeTraits = { @@ -130,6 +151,12 @@ static const llvm::StringSet<> TypeTraits = { "result_of", "invoke_result", "type_identity", + "tuple_element", + "variant_alternative", + "compare_three_way_result", + "common_comparison_category", + "unwrap_ref_decay", + "unwrap_reference", }; static DeclarationName getName(const DependentScopeDeclRefExpr &D) { diff --git a/clang-tools-extra/docs/ReleaseNotes.rst b/clang-tools-extra/docs/ReleaseNotes.rst index f8f183e9de1cc..3d554733ad3fd 100644 --- a/clang-tools-extra/docs/ReleaseNotes.rst +++ b/clang-tools-extra/docs/ReleaseNotes.rst @@ -276,6 +276,9 @@ Changes in existing checks excluding variables with ``thread_local`` storage class specifier from being matched. +- Improved :doc:`modernize-type-traits + ` check by detecting more type traits. + - Improved :doc:`modernize-use-default-member-init ` check by matching arithmetic operations, ``constexpr`` and ``static`` values, and detecting >From 930db523cdbe6bf44b334a17667229e3586981aa Mon Sep 17 00:00:00 2001 From: Victor Chernyakin Date: Fri, 4 Jul 2025 07:59:02 -0700 Subject: [PATCH 2/2] Whoops, didn't exclude `treat_as_floating_point_v` or `is_clock_v` --- clang-tools-extra/clang-tidy/modernize/TypeTraitsCheck.cpp | 2 -- 1 file changed, 2 deletions(-) diff --git a/clang-tools-extra/clang-tidy/modernize/TypeTraitsCheck.cpp b/clang-tools-extra/clang-tidy/modernize/TypeTraitsCheck.cpp index 92e6f61a6d9d4..aaf9d08c63b2e 100644 --- a/clang-tools-extra/clang-tidy/modernize/TypeTraitsCheck.cpp +++ b/clang-tools-extra/clang-tidy/modernize/TypeTraitsCheck.cpp @@ -31,7 +31,6 @@ static const llvm::StringSet<> ValueTraits = { "is_bind_expression", "is_bounded_array", "is_class", -"is_clock", "is_compound", "is_const", "is_constructible", @@ -117,7 +116,6 @@ static const llvm::StringSet<> ValueTraits = { "ratio_not_equal", "reference_constructs_from_temporary", "reference_converts_from_temporary", -"treat_as_floating_point", "tuple_size", "uses_allocator", "variant_size", ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang-tools-extra] [clang-tidy] Teach `modernize-type-traits` about more type traits (PR #147074)
@@ -130,6 +149,12 @@ static const llvm::StringSet<> TypeTraits = { "result_of", "invoke_result", "type_identity", +"tuple_element", localspook wrote: Done https://github.com/llvm/llvm-project/pull/147074 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang-tools-extra] [clang-tidy] Teach `modernize-type-traits` about more type traits (PR #147074)
https://github.com/localspook updated https://github.com/llvm/llvm-project/pull/147074 >From 7ad6f7b8663980183e8bb8e79843942870e36267 Mon Sep 17 00:00:00 2001 From: Victor Chernyakin Date: Fri, 4 Jul 2025 07:42:54 -0700 Subject: [PATCH 1/5] [clang-tidy] Teach `modernize-type-traits` about more type traits --- .../clang-tidy/modernize/TypeTraitsCheck.cpp | 27 +++ clang-tools-extra/docs/ReleaseNotes.rst | 3 +++ 2 files changed, 30 insertions(+) diff --git a/clang-tools-extra/clang-tidy/modernize/TypeTraitsCheck.cpp b/clang-tools-extra/clang-tidy/modernize/TypeTraitsCheck.cpp index c0766395ec5cc..92e6f61a6d9d4 100644 --- a/clang-tools-extra/clang-tidy/modernize/TypeTraitsCheck.cpp +++ b/clang-tools-extra/clang-tidy/modernize/TypeTraitsCheck.cpp @@ -28,8 +28,10 @@ static const llvm::StringSet<> ValueTraits = { "is_array", "is_assignable", "is_base_of", +"is_bind_expression", "is_bounded_array", "is_class", +"is_clock", "is_compound", "is_const", "is_constructible", @@ -40,10 +42,14 @@ static const llvm::StringSet<> ValueTraits = { "is_destructible", "is_empty", "is_enum", +"is_error_code_enum", +"is_error_condition_enum", +"is_execution_policy", "is_final", "is_floating_point", "is_function", "is_fundamental", +"is_implicit_lifetime", "is_integral", "is_invocable", "is_invocable_r", @@ -65,14 +71,17 @@ static const llvm::StringSet<> ValueTraits = { "is_nothrow_invocable_r", "is_nothrow_move_assignable", "is_nothrow_move_constructible", +"is_nothrow_relocatable", "is_nothrow_swappable", "is_nothrow_swappable_with", "is_null_pointer", "is_object", +"is_placeholder", "is_pointer", "is_pointer_interconvertible_base_of", "is_polymorphic", "is_reference", +"is_replaceable", "is_rvalue_reference", "is_same", "is_scalar", @@ -91,15 +100,27 @@ static const llvm::StringSet<> ValueTraits = { "is_trivially_destructible", "is_trivially_move_assignable", "is_trivially_move_constructible", +"is_trivially_relocatable", "is_unbounded_array", "is_union", "is_unsigned", +"is_virtual_base_of", "is_void", "is_volatile", "negation", "rank", +"ratio_equal", +"ratio_greater_equal", +"ratio_greater", +"ratio_less_equal", +"ratio_less", +"ratio_not_equal", "reference_constructs_from_temporary", "reference_converts_from_temporary", +"treat_as_floating_point", +"tuple_size", +"uses_allocator", +"variant_size", }; static const llvm::StringSet<> TypeTraits = { @@ -130,6 +151,12 @@ static const llvm::StringSet<> TypeTraits = { "result_of", "invoke_result", "type_identity", + "tuple_element", + "variant_alternative", + "compare_three_way_result", + "common_comparison_category", + "unwrap_ref_decay", + "unwrap_reference", }; static DeclarationName getName(const DependentScopeDeclRefExpr &D) { diff --git a/clang-tools-extra/docs/ReleaseNotes.rst b/clang-tools-extra/docs/ReleaseNotes.rst index f8f183e9de1cc..3d554733ad3fd 100644 --- a/clang-tools-extra/docs/ReleaseNotes.rst +++ b/clang-tools-extra/docs/ReleaseNotes.rst @@ -276,6 +276,9 @@ Changes in existing checks excluding variables with ``thread_local`` storage class specifier from being matched. +- Improved :doc:`modernize-type-traits + ` check by detecting more type traits. + - Improved :doc:`modernize-use-default-member-init ` check by matching arithmetic operations, ``constexpr`` and ``static`` values, and detecting >From 930db523cdbe6bf44b334a17667229e3586981aa Mon Sep 17 00:00:00 2001 From: Victor Chernyakin Date: Fri, 4 Jul 2025 07:59:02 -0700 Subject: [PATCH 2/5] Whoops, didn't exclude `treat_as_floating_point_v` or `is_clock_v` --- clang-tools-extra/clang-tidy/modernize/TypeTraitsCheck.cpp | 2 -- 1 file changed, 2 deletions(-) diff --git a/clang-tools-extra/clang-tidy/modernize/TypeTraitsCheck.cpp b/clang-tools-extra/clang-tidy/modernize/TypeTraitsCheck.cpp index 92e6f61a6d9d4..aaf9d08c63b2e 100644 --- a/clang-tools-extra/clang-tidy/modernize/TypeTraitsCheck.cpp +++ b/clang-tools-extra/clang-tidy/modernize/TypeTraitsCheck.cpp @@ -31,7 +31,6 @@ static const llvm::StringSet<> ValueTraits = { "is_bind_expression", "is_bounded_array", "is_class", -"is_clock", "is_compound", "is_const", "is_constructible", @@ -117,7 +116,6 @@ static const llvm::StringSet<> ValueTraits = { "ratio_not_equal", "reference_constructs_from_temporary", "reference_converts_from_temporary", -"treat_as_floating_point", "tuple_size", "uses_allocator", "variant_size", >From 13dcaabd66610972db0e6e52e49bb63878e248a6 Mon Sep 17 00:00:00 2001 From: Victor Chernyakin Date: Fri, 4 Jul 2025 08:15:53 -0700 Subject: [PATCH 3/5] clang-format
[clang-tools-extra] [clang-tidy] Teach `modernize-type-traits` about more type traits (PR #147074)
localspook wrote: Mostly manually: I took a list of [all standard library symbols](https://timsong-cpp.github.io/cppwp/libraryindex), used a hacky regex to find `foo`/`foo_[tv]` pairs, filtered out the false positives, diffed against the check's current list, and added what was missing. https://github.com/llvm/llvm-project/pull/147074 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang-tools-extra] [clang-tidy] Add new check: `modernize-use-concise-preprocessor-directives` (PR #146830)
https://github.com/localspook updated https://github.com/llvm/llvm-project/pull/146830 >From 9eb58438d2b4061ad7a6bdbd1db82a5fd4043948 Mon Sep 17 00:00:00 2001 From: Victor Chernyakin Date: Thu, 3 Jul 2025 00:19:52 -0700 Subject: [PATCH 1/8] [clang-tidy] Add new check: `modernize-use-concise-preprocessor-directives` Rewrites preprocessor conditions like `#if defined(MEOW)` as `#ifdef MEOW` and `#elif !defined(MEOW)` as `#elifndef MEOW`. Closes #132561. --- .../clang-tidy/modernize/CMakeLists.txt | 1 + .../modernize/ModernizeTidyModule.cpp | 3 + .../UseConcisePreprocessorDirectivesCheck.cpp | 105 ++ .../UseConcisePreprocessorDirectivesCheck.h | 37 + clang-tools-extra/docs/ReleaseNotes.rst | 6 + .../docs/clang-tidy/checks/list.rst | 1 + .../use-concise-preprocessor-directives.rst | 28 .../use-concise-preprocessor-directives.cpp | 134 ++ 8 files changed, 315 insertions(+) create mode 100644 clang-tools-extra/clang-tidy/modernize/UseConcisePreprocessorDirectivesCheck.cpp create mode 100644 clang-tools-extra/clang-tidy/modernize/UseConcisePreprocessorDirectivesCheck.h create mode 100644 clang-tools-extra/docs/clang-tidy/checks/modernize/use-concise-preprocessor-directives.rst create mode 100644 clang-tools-extra/test/clang-tidy/checkers/modernize/use-concise-preprocessor-directives.cpp diff --git a/clang-tools-extra/clang-tidy/modernize/CMakeLists.txt b/clang-tools-extra/clang-tidy/modernize/CMakeLists.txt index 619a27b2f9bb6..22d5214b61441 100644 --- a/clang-tools-extra/clang-tidy/modernize/CMakeLists.txt +++ b/clang-tools-extra/clang-tidy/modernize/CMakeLists.txt @@ -30,6 +30,7 @@ add_clang_library(clangTidyModernizeModule STATIC UnaryStaticAssertCheck.cpp UseAutoCheck.cpp UseBoolLiteralsCheck.cpp + UseConcisePreprocessorDirectivesCheck.cpp UseConstraintsCheck.cpp UseDefaultMemberInitCheck.cpp UseDesignatedInitializersCheck.cpp diff --git a/clang-tools-extra/clang-tidy/modernize/ModernizeTidyModule.cpp b/clang-tools-extra/clang-tidy/modernize/ModernizeTidyModule.cpp index fdf38bc4b6308..28c5467f7b3e0 100644 --- a/clang-tools-extra/clang-tidy/modernize/ModernizeTidyModule.cpp +++ b/clang-tools-extra/clang-tidy/modernize/ModernizeTidyModule.cpp @@ -31,6 +31,7 @@ #include "UnaryStaticAssertCheck.h" #include "UseAutoCheck.h" #include "UseBoolLiteralsCheck.h" +#include "UseConcisePreprocessorDirectivesCheck.h" #include "UseConstraintsCheck.h" #include "UseDefaultMemberInitCheck.h" #include "UseDesignatedInitializersCheck.h" @@ -76,6 +77,8 @@ class ModernizeModule : public ClangTidyModule { CheckFactories.registerCheck( "modernize-min-max-use-initializer-list"); CheckFactories.registerCheck("modernize-pass-by-value"); +CheckFactories.registerCheck( +"modernize-use-concise-preprocessor-directives"); CheckFactories.registerCheck( "modernize-use-designated-initializers"); CheckFactories.registerCheck( diff --git a/clang-tools-extra/clang-tidy/modernize/UseConcisePreprocessorDirectivesCheck.cpp b/clang-tools-extra/clang-tidy/modernize/UseConcisePreprocessorDirectivesCheck.cpp new file mode 100644 index 0..56ed1b3cc879d --- /dev/null +++ b/clang-tools-extra/clang-tidy/modernize/UseConcisePreprocessorDirectivesCheck.cpp @@ -0,0 +1,105 @@ +//===--- UseConcisePreprocessorDirectivesCheck.cpp - clang-tidy ---===// +// +// 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 "UseConcisePreprocessorDirectivesCheck.h" +#include "clang/Basic/TokenKinds.h" +#include "clang/Lex/Lexer.h" +#include "clang/Lex/PPCallbacks.h" +#include "clang/Lex/Preprocessor.h" + +namespace clang::tidy::modernize { + +namespace { + +class IfPreprocessorCallbacks final : public PPCallbacks { +public: + IfPreprocessorCallbacks(ClangTidyCheck &Check, Preprocessor &PP) + : Check(Check), PP(PP) {} + + void If(SourceLocation Loc, SourceRange ConditionRange, + ConditionValueKind) override { +impl(Loc, ConditionRange, {"ifdef", "ifndef"}); + } + + void Elif(SourceLocation Loc, SourceRange ConditionRange, ConditionValueKind, +SourceLocation) override { +if (PP.getLangOpts().C23 || PP.getLangOpts().CPlusPlus23) { + impl(Loc, ConditionRange, {"elifdef", "elifndef"}); +} + } + +private: + void impl(SourceLocation DirectiveLoc, SourceRange ConditionRange, +const llvm::StringLiteral (&Replacements)[2]) { +StringRef Condition = +Lexer::getSourceText(CharSourceRange::getTokenRange(ConditionRange), + PP.getSourceManager(), PP.getLangOpts()); +Lexer Lex(DirectiveLoc, PP.getLangOpts(), Condition.data(), + C
[clang-tools-extra] [clang-tidy] Add new check: `modernize-use-concise-preprocessor-directives` (PR #146830)
localspook wrote: Maybe I'm misunderstanding, but are you concerned about ```cpp #if defined(foo) && defined(bar) ``` being rewritten to this? ```cpp #ifdef foo && if defined(bar) ``` It won't do that, that's not valid syntax (there's not really any way to rewrite it). I've added a test to ensure the check doesn't touch it. https://github.com/llvm/llvm-project/pull/146830 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang-tools-extra] [clang-tidy] Add new check: `readability-use-concise-preprocessor-directives` (PR #146830)
https://github.com/localspook edited https://github.com/llvm/llvm-project/pull/146830 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang-tools-extra] [clang-tidy] Add new check: `readability-use-concise-preprocessor-directives` (PR #146830)
https://github.com/localspook edited https://github.com/llvm/llvm-project/pull/146830 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang-tools-extra] [clang-tidy] Add new check: `readability-use-concise-preprocessor-directives` (PR #146830)
https://github.com/localspook updated https://github.com/llvm/llvm-project/pull/146830 >From 9eb58438d2b4061ad7a6bdbd1db82a5fd4043948 Mon Sep 17 00:00:00 2001 From: Victor Chernyakin Date: Thu, 3 Jul 2025 00:19:52 -0700 Subject: [PATCH 01/10] [clang-tidy] Add new check: `modernize-use-concise-preprocessor-directives` Rewrites preprocessor conditions like `#if defined(MEOW)` as `#ifdef MEOW` and `#elif !defined(MEOW)` as `#elifndef MEOW`. Closes #132561. --- .../clang-tidy/modernize/CMakeLists.txt | 1 + .../modernize/ModernizeTidyModule.cpp | 3 + .../UseConcisePreprocessorDirectivesCheck.cpp | 105 ++ .../UseConcisePreprocessorDirectivesCheck.h | 37 + clang-tools-extra/docs/ReleaseNotes.rst | 6 + .../docs/clang-tidy/checks/list.rst | 1 + .../use-concise-preprocessor-directives.rst | 28 .../use-concise-preprocessor-directives.cpp | 134 ++ 8 files changed, 315 insertions(+) create mode 100644 clang-tools-extra/clang-tidy/modernize/UseConcisePreprocessorDirectivesCheck.cpp create mode 100644 clang-tools-extra/clang-tidy/modernize/UseConcisePreprocessorDirectivesCheck.h create mode 100644 clang-tools-extra/docs/clang-tidy/checks/modernize/use-concise-preprocessor-directives.rst create mode 100644 clang-tools-extra/test/clang-tidy/checkers/modernize/use-concise-preprocessor-directives.cpp diff --git a/clang-tools-extra/clang-tidy/modernize/CMakeLists.txt b/clang-tools-extra/clang-tidy/modernize/CMakeLists.txt index 619a27b2f9bb6..22d5214b61441 100644 --- a/clang-tools-extra/clang-tidy/modernize/CMakeLists.txt +++ b/clang-tools-extra/clang-tidy/modernize/CMakeLists.txt @@ -30,6 +30,7 @@ add_clang_library(clangTidyModernizeModule STATIC UnaryStaticAssertCheck.cpp UseAutoCheck.cpp UseBoolLiteralsCheck.cpp + UseConcisePreprocessorDirectivesCheck.cpp UseConstraintsCheck.cpp UseDefaultMemberInitCheck.cpp UseDesignatedInitializersCheck.cpp diff --git a/clang-tools-extra/clang-tidy/modernize/ModernizeTidyModule.cpp b/clang-tools-extra/clang-tidy/modernize/ModernizeTidyModule.cpp index fdf38bc4b6308..28c5467f7b3e0 100644 --- a/clang-tools-extra/clang-tidy/modernize/ModernizeTidyModule.cpp +++ b/clang-tools-extra/clang-tidy/modernize/ModernizeTidyModule.cpp @@ -31,6 +31,7 @@ #include "UnaryStaticAssertCheck.h" #include "UseAutoCheck.h" #include "UseBoolLiteralsCheck.h" +#include "UseConcisePreprocessorDirectivesCheck.h" #include "UseConstraintsCheck.h" #include "UseDefaultMemberInitCheck.h" #include "UseDesignatedInitializersCheck.h" @@ -76,6 +77,8 @@ class ModernizeModule : public ClangTidyModule { CheckFactories.registerCheck( "modernize-min-max-use-initializer-list"); CheckFactories.registerCheck("modernize-pass-by-value"); +CheckFactories.registerCheck( +"modernize-use-concise-preprocessor-directives"); CheckFactories.registerCheck( "modernize-use-designated-initializers"); CheckFactories.registerCheck( diff --git a/clang-tools-extra/clang-tidy/modernize/UseConcisePreprocessorDirectivesCheck.cpp b/clang-tools-extra/clang-tidy/modernize/UseConcisePreprocessorDirectivesCheck.cpp new file mode 100644 index 0..56ed1b3cc879d --- /dev/null +++ b/clang-tools-extra/clang-tidy/modernize/UseConcisePreprocessorDirectivesCheck.cpp @@ -0,0 +1,105 @@ +//===--- UseConcisePreprocessorDirectivesCheck.cpp - clang-tidy ---===// +// +// 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 "UseConcisePreprocessorDirectivesCheck.h" +#include "clang/Basic/TokenKinds.h" +#include "clang/Lex/Lexer.h" +#include "clang/Lex/PPCallbacks.h" +#include "clang/Lex/Preprocessor.h" + +namespace clang::tidy::modernize { + +namespace { + +class IfPreprocessorCallbacks final : public PPCallbacks { +public: + IfPreprocessorCallbacks(ClangTidyCheck &Check, Preprocessor &PP) + : Check(Check), PP(PP) {} + + void If(SourceLocation Loc, SourceRange ConditionRange, + ConditionValueKind) override { +impl(Loc, ConditionRange, {"ifdef", "ifndef"}); + } + + void Elif(SourceLocation Loc, SourceRange ConditionRange, ConditionValueKind, +SourceLocation) override { +if (PP.getLangOpts().C23 || PP.getLangOpts().CPlusPlus23) { + impl(Loc, ConditionRange, {"elifdef", "elifndef"}); +} + } + +private: + void impl(SourceLocation DirectiveLoc, SourceRange ConditionRange, +const llvm::StringLiteral (&Replacements)[2]) { +StringRef Condition = +Lexer::getSourceText(CharSourceRange::getTokenRange(ConditionRange), + PP.getSourceManager(), PP.getLangOpts()); +Lexer Lex(DirectiveLoc, PP.getLangOpts(), Condition.data(), +
[clang-tools-extra] [clang-tidy] Add new check: `readability-use-concise-preprocessor-directives` (PR #146830)
@@ -0,0 +1,138 @@ +// RUN: %check_clang_tidy -std=c++98 -check-suffixes=,CXX %s readability-use-concise-preprocessor-directives %t +// RUN: %check_clang_tidy -std=c++11 -check-suffixes=,CXX %s readability-use-concise-preprocessor-directives %t +// RUN: %check_clang_tidy -std=c++14 -check-suffixes=,CXX %s readability-use-concise-preprocessor-directives %t +// RUN: %check_clang_tidy -std=c++17 -check-suffixes=,CXX %s readability-use-concise-preprocessor-directives %t +// RUN: %check_clang_tidy -std=c++20 -check-suffixes=,CXX %s readability-use-concise-preprocessor-directives %t +// RUN: %check_clang_tidy -std=c++23-or-later -check-suffixes=,23,CXX,CXX23 %s readability-use-concise-preprocessor-directives %t + +// RUN: %check_clang_tidy -std=c99 %s readability-use-concise-preprocessor-directives %t -- -- -x c +// RUN: %check_clang_tidy -std=c11 %s readability-use-concise-preprocessor-directives %t -- -- -x c +// RUN: %check_clang_tidy -std=c23-or-later -check-suffixes=,23 %s readability-use-concise-preprocessor-directives %t -- -- -x c + +// CHECK-MESSAGES: :[[@LINE+2]]:2: warning: preprocessor condition can be written more concisely using #ifdef [readability-use-concise-preprocessor-directives] +// CHECK-FIXES: #ifdef FOO +#if defined(FOO) +// CHECK-MESSAGES-23: :[[@LINE+2]]:2: warning: preprocessor condition can be written more concisely using #elifdef [readability-use-concise-preprocessor-directives] +// CHECK-FIXES-23: #elifdef BAR +#elif defined(BAR) +#endif + +// CHECK-MESSAGES: :[[@LINE+2]]:2: warning: preprocessor condition can be written more concisely using #ifdef [readability-use-concise-preprocessor-directives] +// CHECK-FIXES: #ifdef FOO +#if defined FOO +// CHECK-MESSAGES-23: :[[@LINE+2]]:2: warning: preprocessor condition can be written more concisely using #elifdef [readability-use-concise-preprocessor-directives] +// CHECK-FIXES-23: #elifdef BAR +#elif defined BAR +#endif + +// CHECK-MESSAGES: :[[@LINE+2]]:2: warning: preprocessor condition can be written more concisely using #ifdef [readability-use-concise-preprocessor-directives] +// CHECK-FIXES: #ifdef FOO +#if (defined(FOO)) +// CHECK-MESSAGES-23: :[[@LINE+2]]:4: warning: preprocessor condition can be written more concisely using #elifdef [readability-use-concise-preprocessor-directives] +// CHECK-FIXES-23: # elifdef BAR +# elif (defined(BAR)) +#endif + +// CHECK-MESSAGES: :[[@LINE+2]]:2: warning: preprocessor condition can be written more concisely using #ifdef [readability-use-concise-preprocessor-directives] +// CHECK-FIXES: #ifdef FOO +#if (defined FOO) +// CHECK-MESSAGES-23: :[[@LINE+2]]:4: warning: preprocessor condition can be written more concisely using #elifdef [readability-use-concise-preprocessor-directives] +// CHECK-FIXES-23: # elifdef BAR +# elif (defined BAR) +#endif + +// CHECK-MESSAGES: :[[@LINE+2]]:2: warning: preprocessor condition can be written more concisely using #ifndef [readability-use-concise-preprocessor-directives] +// CHECK-FIXES: #ifndef FOO +#if !defined(FOO) +// CHECK-MESSAGES-23: :[[@LINE+2]]:2: warning: preprocessor condition can be written more concisely using #elifndef [readability-use-concise-preprocessor-directives] +// CHECK-FIXES-23: #elifndef BAR +#elif !defined(BAR) +#endif + +#ifdef __cplusplus +// CHECK-MESSAGES-CXX: :[[@LINE+2]]:2: warning: preprocessor condition can be written more concisely using #ifndef [readability-use-concise-preprocessor-directives] +// CHECK-FIXES-CXX: #ifndef FOO +#if not defined(FOO) +// CHECK-MESSAGES-CXX23: :[[@LINE+2]]:2: warning: preprocessor condition can be written more concisely using #elifndef [readability-use-concise-preprocessor-directives] +// CHECK-FIXES-CXX23: #elifndef BAR +#elif not defined(BAR) +#endif +#endif // __cplusplus + +// CHECK-MESSAGES: :[[@LINE+2]]:2: warning: preprocessor condition can be written more concisely using #ifndef [readability-use-concise-preprocessor-directives] +// CHECK-FIXES: #ifndef FOO +#if !defined FOO +// CHECK-MESSAGES-23: :[[@LINE+2]]:2: warning: preprocessor condition can be written more concisely using #elifndef [readability-use-concise-preprocessor-directives] +// CHECK-FIXES-23: #elifndef BAR +#elif !defined BAR +#endif + +#ifdef __cplusplus +// CHECK-MESSAGES-CXX: :[[@LINE+2]]:2: warning: preprocessor condition can be written more concisely using #ifndef [readability-use-concise-preprocessor-directives] +// CHECK-FIXES-CXX: #ifndef FOO +#if not defined FOO +// CHECK-MESSAGES-CXX23: :[[@LINE+2]]:2: warning: preprocessor condition can be written more concisely using #elifndef [readability-use-concise-preprocessor-directives] +// CHECK-FIXES-CXX23: #elifndef BAR +#elif not defined BAR +#endif +#endif // __cplusplus + +// CHECK-MESSAGES: :[[@LINE+2]]:2: warning: preprocessor condition can be written more concisely using #ifndef [readability-use-concise-preprocessor-directives] +// CHECK-FIXES: #ifndef FOO +#if (!defined(FOO)) +// CHECK-MESSAGES-23: :[[@LIN
[clang-tools-extra] [clang-tidy] Add new check: `readability-use-concise-preprocessor-directives` (PR #146830)
https://github.com/localspook updated https://github.com/llvm/llvm-project/pull/146830 >From 9eb58438d2b4061ad7a6bdbd1db82a5fd4043948 Mon Sep 17 00:00:00 2001 From: Victor Chernyakin Date: Thu, 3 Jul 2025 00:19:52 -0700 Subject: [PATCH 01/11] [clang-tidy] Add new check: `modernize-use-concise-preprocessor-directives` Rewrites preprocessor conditions like `#if defined(MEOW)` as `#ifdef MEOW` and `#elif !defined(MEOW)` as `#elifndef MEOW`. Closes #132561. --- .../clang-tidy/modernize/CMakeLists.txt | 1 + .../modernize/ModernizeTidyModule.cpp | 3 + .../UseConcisePreprocessorDirectivesCheck.cpp | 105 ++ .../UseConcisePreprocessorDirectivesCheck.h | 37 + clang-tools-extra/docs/ReleaseNotes.rst | 6 + .../docs/clang-tidy/checks/list.rst | 1 + .../use-concise-preprocessor-directives.rst | 28 .../use-concise-preprocessor-directives.cpp | 134 ++ 8 files changed, 315 insertions(+) create mode 100644 clang-tools-extra/clang-tidy/modernize/UseConcisePreprocessorDirectivesCheck.cpp create mode 100644 clang-tools-extra/clang-tidy/modernize/UseConcisePreprocessorDirectivesCheck.h create mode 100644 clang-tools-extra/docs/clang-tidy/checks/modernize/use-concise-preprocessor-directives.rst create mode 100644 clang-tools-extra/test/clang-tidy/checkers/modernize/use-concise-preprocessor-directives.cpp diff --git a/clang-tools-extra/clang-tidy/modernize/CMakeLists.txt b/clang-tools-extra/clang-tidy/modernize/CMakeLists.txt index 619a27b2f9bb6..22d5214b61441 100644 --- a/clang-tools-extra/clang-tidy/modernize/CMakeLists.txt +++ b/clang-tools-extra/clang-tidy/modernize/CMakeLists.txt @@ -30,6 +30,7 @@ add_clang_library(clangTidyModernizeModule STATIC UnaryStaticAssertCheck.cpp UseAutoCheck.cpp UseBoolLiteralsCheck.cpp + UseConcisePreprocessorDirectivesCheck.cpp UseConstraintsCheck.cpp UseDefaultMemberInitCheck.cpp UseDesignatedInitializersCheck.cpp diff --git a/clang-tools-extra/clang-tidy/modernize/ModernizeTidyModule.cpp b/clang-tools-extra/clang-tidy/modernize/ModernizeTidyModule.cpp index fdf38bc4b6308..28c5467f7b3e0 100644 --- a/clang-tools-extra/clang-tidy/modernize/ModernizeTidyModule.cpp +++ b/clang-tools-extra/clang-tidy/modernize/ModernizeTidyModule.cpp @@ -31,6 +31,7 @@ #include "UnaryStaticAssertCheck.h" #include "UseAutoCheck.h" #include "UseBoolLiteralsCheck.h" +#include "UseConcisePreprocessorDirectivesCheck.h" #include "UseConstraintsCheck.h" #include "UseDefaultMemberInitCheck.h" #include "UseDesignatedInitializersCheck.h" @@ -76,6 +77,8 @@ class ModernizeModule : public ClangTidyModule { CheckFactories.registerCheck( "modernize-min-max-use-initializer-list"); CheckFactories.registerCheck("modernize-pass-by-value"); +CheckFactories.registerCheck( +"modernize-use-concise-preprocessor-directives"); CheckFactories.registerCheck( "modernize-use-designated-initializers"); CheckFactories.registerCheck( diff --git a/clang-tools-extra/clang-tidy/modernize/UseConcisePreprocessorDirectivesCheck.cpp b/clang-tools-extra/clang-tidy/modernize/UseConcisePreprocessorDirectivesCheck.cpp new file mode 100644 index 0..56ed1b3cc879d --- /dev/null +++ b/clang-tools-extra/clang-tidy/modernize/UseConcisePreprocessorDirectivesCheck.cpp @@ -0,0 +1,105 @@ +//===--- UseConcisePreprocessorDirectivesCheck.cpp - clang-tidy ---===// +// +// 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 "UseConcisePreprocessorDirectivesCheck.h" +#include "clang/Basic/TokenKinds.h" +#include "clang/Lex/Lexer.h" +#include "clang/Lex/PPCallbacks.h" +#include "clang/Lex/Preprocessor.h" + +namespace clang::tidy::modernize { + +namespace { + +class IfPreprocessorCallbacks final : public PPCallbacks { +public: + IfPreprocessorCallbacks(ClangTidyCheck &Check, Preprocessor &PP) + : Check(Check), PP(PP) {} + + void If(SourceLocation Loc, SourceRange ConditionRange, + ConditionValueKind) override { +impl(Loc, ConditionRange, {"ifdef", "ifndef"}); + } + + void Elif(SourceLocation Loc, SourceRange ConditionRange, ConditionValueKind, +SourceLocation) override { +if (PP.getLangOpts().C23 || PP.getLangOpts().CPlusPlus23) { + impl(Loc, ConditionRange, {"elifdef", "elifndef"}); +} + } + +private: + void impl(SourceLocation DirectiveLoc, SourceRange ConditionRange, +const llvm::StringLiteral (&Replacements)[2]) { +StringRef Condition = +Lexer::getSourceText(CharSourceRange::getTokenRange(ConditionRange), + PP.getSourceManager(), PP.getLangOpts()); +Lexer Lex(DirectiveLoc, PP.getLangOpts(), Condition.data(), +
[clang-tools-extra] [clang-tidy] Add new check: `readability-use-concise-preprocessor-directives` (PR #146830)
https://github.com/localspook edited https://github.com/llvm/llvm-project/pull/146830 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang-tools-extra] [clang-tidy] Add new check: `readability-use-concise-preprocessor-directives` (PR #146830)
@@ -0,0 +1,40 @@ +//===--- UseConcisePreprocessorDirectivesCheck.h - clang-tidy ---*- C++ -*-===// +// +// 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_USECONCISEPREPROCESSORDIRECTIVESCHECK_H +#define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_READABILITY_USECONCISEPREPROCESSORDIRECTIVESCHECK_H + +#include "../ClangTidyCheck.h" + +namespace clang::tidy::readability { + +/// Shortens `#if` preprocessor conditions: +/// +/// #if defined(MEOW) -> #ifdef MEOW +/// #if !defined(MEOW) -> #ifndef MEOW +/// +/// And, since C23 and C++23, shortens `#elif` conditions too: +/// +/// #elif defined(MEOW) -> #elifdef MEOW +/// #elif !defined(MEOW) -> #elifndef MEOW +/// +/// User-facing documentation: +/// https://clang.llvm.org/extra/clang-tidy/checks/readability/use-concise-preprocessor-directives.html +class UseConcisePreprocessorDirectivesCheck : public ClangTidyCheck { +public: + using ClangTidyCheck::ClangTidyCheck; + void registerPPCallbacks(const SourceManager &SM, Preprocessor *PP, + Preprocessor *ModuleExpanderPP) override; + bool isLanguageVersionSupported(const LangOptions &LangOpts) const override { +return LangOpts.CPlusPlus || LangOpts.C99; localspook wrote: I know basically nothing about Objective-C/C++, but from some research it seems like a superset of C/C++, and the preprocessor also seems to be a superset, so should we extend support to Objective-C/C++ and `return true`? https://github.com/llvm/llvm-project/pull/146830 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang-tools-extra] [clang-tidy] Teach `modernize-type-traits` about more type traits (PR #147074)
localspook wrote: When we're ready to merge, someone please do it for me, I don't have write permissions. https://github.com/llvm/llvm-project/pull/147074 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang-tools-extra] [clang-tidy] Add new check: `readability-use-concise-preprocessor-directives` (PR #146830)
@@ -0,0 +1,108 @@ +//===--- UseConcisePreprocessorDirectivesCheck.cpp - clang-tidy ---===// +// +// 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 "UseConcisePreprocessorDirectivesCheck.h" +#include "clang/Basic/TokenKinds.h" +#include "clang/Lex/Lexer.h" +#include "clang/Lex/PPCallbacks.h" +#include "clang/Lex/Preprocessor.h" + +namespace clang::tidy::readability { + +namespace { + +class IfPreprocessorCallbacks final : public PPCallbacks { +public: + IfPreprocessorCallbacks(ClangTidyCheck &Check, const Preprocessor &PP) + : Check(Check), PP(PP) {} + + void If(SourceLocation Loc, SourceRange ConditionRange, + ConditionValueKind) override { +impl(Loc, ConditionRange, {"ifdef", "ifndef"}); + } + + void Elif(SourceLocation Loc, SourceRange ConditionRange, ConditionValueKind, +SourceLocation) override { +if (PP.getLangOpts().C23 || PP.getLangOpts().CPlusPlus23) { + impl(Loc, ConditionRange, {"elifdef", "elifndef"}); +} + } + +private: + void impl(SourceLocation DirectiveLoc, SourceRange ConditionRange, +const llvm::StringLiteral (&Replacements)[2]) { localspook wrote: Neither of those allow me to encode "I want exactly 2" into the type (`std::span` would, but that's C++20). I suppose I could use `const std::array&`; would you prefer that? https://github.com/llvm/llvm-project/pull/146830 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang-tools-extra] [clang-tidy] Add new check: `readability-use-concise-preprocessor-directives` (PR #146830)
https://github.com/localspook edited https://github.com/llvm/llvm-project/pull/146830 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [clang-tools-extra] [ASTMatchers][NFC] Replace `makeMatcher` function with CTAD (PR #147197)
https://github.com/localspook created https://github.com/llvm/llvm-project/pull/147197 C++17's CTAD obsoletes `makeMatcher` (and many `make*` functions like it). The deduction guide is written out explicitly to avoid `-Wctad-maybe-unsupported` warnings. >From c9da8d946b867fb6e095cefee44388f240c28c28 Mon Sep 17 00:00:00 2001 From: Victor Chernyakin Date: Sun, 6 Jul 2025 08:32:49 -0700 Subject: [PATCH] [ASTMatchers][NFC] Replace `makeMatcher` function with CTAD --- clang-tools-extra/clang-tidy/utils/Matchers.h | 4 ++-- clang/include/clang/ASTMatchers/ASTMatchersInternal.h | 7 +-- clang/include/clang/ASTMatchers/ASTMatchersMacros.h | 8 clang/lib/Tooling/Transformer/RewriteRule.cpp | 4 ++-- 4 files changed, 9 insertions(+), 14 deletions(-) diff --git a/clang-tools-extra/clang-tidy/utils/Matchers.h b/clang-tools-extra/clang-tidy/utils/Matchers.h index 2b6d377b8fd10..a7683024d69c4 100644 --- a/clang-tools-extra/clang-tidy/utils/Matchers.h +++ b/clang-tools-extra/clang-tidy/utils/Matchers.h @@ -145,7 +145,7 @@ class MatchesAnyListedNameMatcher // qualified name will be used for matching, otherwise its name will be used. inline ::clang::ast_matchers::internal::Matcher matchesAnyListedName(llvm::ArrayRef NameList) { - return ::clang::ast_matchers::internal::makeMatcher( + return ::clang::ast_matchers::internal::Matcher( new MatchesAnyListedNameMatcher(NameList)); } @@ -188,7 +188,7 @@ class MatchesAnyListedTypeNameMatcher inline ::clang::ast_matchers::internal::Matcher matchesAnyListedTypeName(llvm::ArrayRef NameList, bool CanonicalTypes) { - return ::clang::ast_matchers::internal::makeMatcher( + return ::clang::ast_matchers::internal::Matcher( new MatchesAnyListedTypeNameMatcher(NameList, CanonicalTypes)); } inline ::clang::ast_matchers::internal::Matcher diff --git a/clang/include/clang/ASTMatchers/ASTMatchersInternal.h b/clang/include/clang/ASTMatchers/ASTMatchersInternal.h index 667a044abcef1..5b092537e5e7c 100644 --- a/clang/include/clang/ASTMatchers/ASTMatchersInternal.h +++ b/clang/include/clang/ASTMatchers/ASTMatchersInternal.h @@ -672,12 +672,7 @@ class Matcher { DynTypedMatcher Implementation; }; // class Matcher -/// A convenient helper for creating a Matcher without specifying -/// the template type argument. -template -inline Matcher makeMatcher(MatcherInterface *Implementation) { - return Matcher(Implementation); -} +template Matcher(MatcherInterface *) -> Matcher; /// Interface that allows matchers to traverse the AST. /// FIXME: Find a better name. diff --git a/clang/include/clang/ASTMatchers/ASTMatchersMacros.h b/clang/include/clang/ASTMatchers/ASTMatchersMacros.h index f781e0a565eb3..8ac55e5bb1fc0 100644 --- a/clang/include/clang/ASTMatchers/ASTMatchersMacros.h +++ b/clang/include/clang/ASTMatchers/ASTMatchersMacros.h @@ -106,7 +106,7 @@ }; \ } \ inline ::clang::ast_matchers::internal::Matcher DefineMatcher() { \ -return ::clang::ast_matchers::internal::makeMatcher( \ +return ::clang::ast_matchers::internal::Matcher( \ new internal::matcher_##DefineMatcher##Matcher()); \ } \ inline bool internal::matcher_##DefineMatcher##Matcher::matches( \ @@ -150,7 +150,7 @@ } \ inline ::clang::ast_matchers::internal::Matcher DefineMatcher( \ ParamType const &Param) { \ -return ::clang::ast_matchers::internal::makeMatcher( \ +return ::clang::ast_matchers::internal::Matcher( \ new internal::matcher_##DefineMatcher##OverloadId##Matcher(Param)); \ } \ typedef ::clang::ast_matchers::internal::Matcher ( \ @@ -200,7 +200,7 @@ } \ inline ::clang::ast_matchers::internal::Matcher DefineMatcher( \ ParamType1 const &Param1, ParamType2 const &Param2) { \ -return ::clang::ast_matchers::internal::makeMatcher( \ +return ::clang::ast_matchers::internal::Matcher( \ new internal::matcher_##DefineMatcher##OverloadId##Matcher(Param1, \ Param2)); \ } \ @@ -476,7 +476,7 @@ }
[clang-tools-extra] [clang-tidy] filter check options by enabled checks in '--dump-config' (PR #147142)
@@ -503,6 +503,21 @@ getCheckNames(const ClangTidyOptions &Options, return Factory.getCheckNames(); } +void filterCheckOptions(ClangTidyOptions &Options, +const std::vector &EnabledChecks) { + StringSet<> EnabledChecksSet(llvm::from_range, EnabledChecks); + ClangTidyOptions::OptionMap FilteredOptions; + for (const auto &[OptionName, Value] : Options.CheckOptions) { +const size_t CheckNameEndPos = OptionName.find('.'); +if (CheckNameEndPos == StringRef::npos) + continue; +const StringRef CheckName = OptionName.substr(0, CheckNameEndPos); +if (EnabledChecksSet.contains(CheckName)) + FilteredOptions[OptionName] = Value; + } + Options.CheckOptions = std::move(FilteredOptions); +} localspook wrote: Instead of building up a new `OptionMap` and then overwriting `Options.CheckOptions`, could we avoid allocations by directly erasing the elements we don't want to keep from `Options.CheckOptions`? Something like this (not tested): ```diff void filterCheckOptions(ClangTidyOptions &Options, const std::vector &EnabledChecks) { StringSet<> EnabledChecksSet(llvm::from_range, EnabledChecks); - ClangTidyOptions::OptionMap FilteredOptions; - for (const auto &[OptionName, Value] : Options.CheckOptions) { + for (auto I = Options.CheckOptions.begin(), E = Options.CheckOptions.end(); I != E; ++I) { + const auto &[OptionName, Value] = *I; const size_t CheckNameEndPos = OptionName.find('.'); if (CheckNameEndPos == StringRef::npos) continue; const StringRef CheckName = OptionName.substr(0, CheckNameEndPos); -if (EnabledChecksSet.contains(CheckName)) - FilteredOptions[OptionName] = Value; +if (!EnabledChecksSet.contains(CheckName)) + Options.CheckOptions.erase(I); } - Options.CheckOptions = std::move(FilteredOptions); } ``` https://github.com/llvm/llvm-project/pull/147142 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang-tools-extra] [clang-tidy] Teach `modernize-type-traits` about more type traits (PR #147074)
https://github.com/localspook created https://github.com/llvm/llvm-project/pull/147074 These new traits come from various standard versions: C++14: - `tuple_element_t` C++17: - `is_placeholder_v` - `is_bind_expression_v` - `ratio_equal_v` - `ratio_not_equal_v` - `ratio_less_v` - `ratio_less_equal_v` - `ratio_greater_v` - `ratio_greater_equal_v` - `is_error_code_enum_v` - `is_error_condition_enum_v` - `is_execution_policy_v` - `tuple_size_v` - `variant_size_v` - `uses_allocator_v` - `variant_alternative_t` C++20: - `compare_three_way_result_t` - `common_comparison_category_t` - `unwrap_ref_decay_t` - `unwrap_reference_t` C++23: - `is_implicit_lifetime_v` C++26: - `is_nothrow_relocatable_v` - `is_replaceable_v` - `is_trivially_relocatable_v` - `is_virtual_base_of_v` This doesn't add `treat_as_floating_point_v` or `is_clock_v` because they require more invasive changes; instead I've opened #147072 to track them. >From 7ad6f7b8663980183e8bb8e79843942870e36267 Mon Sep 17 00:00:00 2001 From: Victor Chernyakin Date: Fri, 4 Jul 2025 07:42:54 -0700 Subject: [PATCH] [clang-tidy] Teach `modernize-type-traits` about more type traits --- .../clang-tidy/modernize/TypeTraitsCheck.cpp | 27 +++ clang-tools-extra/docs/ReleaseNotes.rst | 3 +++ 2 files changed, 30 insertions(+) diff --git a/clang-tools-extra/clang-tidy/modernize/TypeTraitsCheck.cpp b/clang-tools-extra/clang-tidy/modernize/TypeTraitsCheck.cpp index c0766395ec5cc..92e6f61a6d9d4 100644 --- a/clang-tools-extra/clang-tidy/modernize/TypeTraitsCheck.cpp +++ b/clang-tools-extra/clang-tidy/modernize/TypeTraitsCheck.cpp @@ -28,8 +28,10 @@ static const llvm::StringSet<> ValueTraits = { "is_array", "is_assignable", "is_base_of", +"is_bind_expression", "is_bounded_array", "is_class", +"is_clock", "is_compound", "is_const", "is_constructible", @@ -40,10 +42,14 @@ static const llvm::StringSet<> ValueTraits = { "is_destructible", "is_empty", "is_enum", +"is_error_code_enum", +"is_error_condition_enum", +"is_execution_policy", "is_final", "is_floating_point", "is_function", "is_fundamental", +"is_implicit_lifetime", "is_integral", "is_invocable", "is_invocable_r", @@ -65,14 +71,17 @@ static const llvm::StringSet<> ValueTraits = { "is_nothrow_invocable_r", "is_nothrow_move_assignable", "is_nothrow_move_constructible", +"is_nothrow_relocatable", "is_nothrow_swappable", "is_nothrow_swappable_with", "is_null_pointer", "is_object", +"is_placeholder", "is_pointer", "is_pointer_interconvertible_base_of", "is_polymorphic", "is_reference", +"is_replaceable", "is_rvalue_reference", "is_same", "is_scalar", @@ -91,15 +100,27 @@ static const llvm::StringSet<> ValueTraits = { "is_trivially_destructible", "is_trivially_move_assignable", "is_trivially_move_constructible", +"is_trivially_relocatable", "is_unbounded_array", "is_union", "is_unsigned", +"is_virtual_base_of", "is_void", "is_volatile", "negation", "rank", +"ratio_equal", +"ratio_greater_equal", +"ratio_greater", +"ratio_less_equal", +"ratio_less", +"ratio_not_equal", "reference_constructs_from_temporary", "reference_converts_from_temporary", +"treat_as_floating_point", +"tuple_size", +"uses_allocator", +"variant_size", }; static const llvm::StringSet<> TypeTraits = { @@ -130,6 +151,12 @@ static const llvm::StringSet<> TypeTraits = { "result_of", "invoke_result", "type_identity", + "tuple_element", + "variant_alternative", + "compare_three_way_result", + "common_comparison_category", + "unwrap_ref_decay", + "unwrap_reference", }; static DeclarationName getName(const DependentScopeDeclRefExpr &D) { diff --git a/clang-tools-extra/docs/ReleaseNotes.rst b/clang-tools-extra/docs/ReleaseNotes.rst index f8f183e9de1cc..3d554733ad3fd 100644 --- a/clang-tools-extra/docs/ReleaseNotes.rst +++ b/clang-tools-extra/docs/ReleaseNotes.rst @@ -276,6 +276,9 @@ Changes in existing checks excluding variables with ``thread_local`` storage class specifier from being matched. +- Improved :doc:`modernize-type-traits + ` check by detecting more type traits. + - Improved :doc:`modernize-use-default-member-init ` check by matching arithmetic operations, ``constexpr`` and ``static`` values, and detecting ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang-tools-extra] [clang-tidy] Teach `modernize-type-traits` about more type traits (PR #147074)
@@ -130,6 +149,12 @@ static const llvm::StringSet<> TypeTraits = { "result_of", "invoke_result", "type_identity", + "tuple_element", localspook wrote: The `TypeTraits` are already not in alphabetical order (`ValueTraits` are though), and I didn't want to reorder them in this PR because it would make it harder to see which traits were being added. https://github.com/llvm/llvm-project/pull/147074 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang-tools-extra] [clang-tidy] Teach `modernize-type-traits` about more type traits (PR #147074)
https://github.com/localspook updated https://github.com/llvm/llvm-project/pull/147074 >From 7ad6f7b8663980183e8bb8e79843942870e36267 Mon Sep 17 00:00:00 2001 From: Victor Chernyakin Date: Fri, 4 Jul 2025 07:42:54 -0700 Subject: [PATCH 1/3] [clang-tidy] Teach `modernize-type-traits` about more type traits --- .../clang-tidy/modernize/TypeTraitsCheck.cpp | 27 +++ clang-tools-extra/docs/ReleaseNotes.rst | 3 +++ 2 files changed, 30 insertions(+) diff --git a/clang-tools-extra/clang-tidy/modernize/TypeTraitsCheck.cpp b/clang-tools-extra/clang-tidy/modernize/TypeTraitsCheck.cpp index c0766395ec5cc..92e6f61a6d9d4 100644 --- a/clang-tools-extra/clang-tidy/modernize/TypeTraitsCheck.cpp +++ b/clang-tools-extra/clang-tidy/modernize/TypeTraitsCheck.cpp @@ -28,8 +28,10 @@ static const llvm::StringSet<> ValueTraits = { "is_array", "is_assignable", "is_base_of", +"is_bind_expression", "is_bounded_array", "is_class", +"is_clock", "is_compound", "is_const", "is_constructible", @@ -40,10 +42,14 @@ static const llvm::StringSet<> ValueTraits = { "is_destructible", "is_empty", "is_enum", +"is_error_code_enum", +"is_error_condition_enum", +"is_execution_policy", "is_final", "is_floating_point", "is_function", "is_fundamental", +"is_implicit_lifetime", "is_integral", "is_invocable", "is_invocable_r", @@ -65,14 +71,17 @@ static const llvm::StringSet<> ValueTraits = { "is_nothrow_invocable_r", "is_nothrow_move_assignable", "is_nothrow_move_constructible", +"is_nothrow_relocatable", "is_nothrow_swappable", "is_nothrow_swappable_with", "is_null_pointer", "is_object", +"is_placeholder", "is_pointer", "is_pointer_interconvertible_base_of", "is_polymorphic", "is_reference", +"is_replaceable", "is_rvalue_reference", "is_same", "is_scalar", @@ -91,15 +100,27 @@ static const llvm::StringSet<> ValueTraits = { "is_trivially_destructible", "is_trivially_move_assignable", "is_trivially_move_constructible", +"is_trivially_relocatable", "is_unbounded_array", "is_union", "is_unsigned", +"is_virtual_base_of", "is_void", "is_volatile", "negation", "rank", +"ratio_equal", +"ratio_greater_equal", +"ratio_greater", +"ratio_less_equal", +"ratio_less", +"ratio_not_equal", "reference_constructs_from_temporary", "reference_converts_from_temporary", +"treat_as_floating_point", +"tuple_size", +"uses_allocator", +"variant_size", }; static const llvm::StringSet<> TypeTraits = { @@ -130,6 +151,12 @@ static const llvm::StringSet<> TypeTraits = { "result_of", "invoke_result", "type_identity", + "tuple_element", + "variant_alternative", + "compare_three_way_result", + "common_comparison_category", + "unwrap_ref_decay", + "unwrap_reference", }; static DeclarationName getName(const DependentScopeDeclRefExpr &D) { diff --git a/clang-tools-extra/docs/ReleaseNotes.rst b/clang-tools-extra/docs/ReleaseNotes.rst index f8f183e9de1cc..3d554733ad3fd 100644 --- a/clang-tools-extra/docs/ReleaseNotes.rst +++ b/clang-tools-extra/docs/ReleaseNotes.rst @@ -276,6 +276,9 @@ Changes in existing checks excluding variables with ``thread_local`` storage class specifier from being matched. +- Improved :doc:`modernize-type-traits + ` check by detecting more type traits. + - Improved :doc:`modernize-use-default-member-init ` check by matching arithmetic operations, ``constexpr`` and ``static`` values, and detecting >From 930db523cdbe6bf44b334a17667229e3586981aa Mon Sep 17 00:00:00 2001 From: Victor Chernyakin Date: Fri, 4 Jul 2025 07:59:02 -0700 Subject: [PATCH 2/3] Whoops, didn't exclude `treat_as_floating_point_v` or `is_clock_v` --- clang-tools-extra/clang-tidy/modernize/TypeTraitsCheck.cpp | 2 -- 1 file changed, 2 deletions(-) diff --git a/clang-tools-extra/clang-tidy/modernize/TypeTraitsCheck.cpp b/clang-tools-extra/clang-tidy/modernize/TypeTraitsCheck.cpp index 92e6f61a6d9d4..aaf9d08c63b2e 100644 --- a/clang-tools-extra/clang-tidy/modernize/TypeTraitsCheck.cpp +++ b/clang-tools-extra/clang-tidy/modernize/TypeTraitsCheck.cpp @@ -31,7 +31,6 @@ static const llvm::StringSet<> ValueTraits = { "is_bind_expression", "is_bounded_array", "is_class", -"is_clock", "is_compound", "is_const", "is_constructible", @@ -117,7 +116,6 @@ static const llvm::StringSet<> ValueTraits = { "ratio_not_equal", "reference_constructs_from_temporary", "reference_converts_from_temporary", -"treat_as_floating_point", "tuple_size", "uses_allocator", "variant_size", >From 13dcaabd66610972db0e6e52e49bb63878e248a6 Mon Sep 17 00:00:00 2001 From: Victor Chernyakin Date: Fri, 4 Jul 2025 08:15:53 -0700 Subject: [PATCH 3/3] clang-format
[clang-tools-extra] [clang-tidy] Add new check: `readability-use-concise-preprocessor-directives` (PR #146830)
localspook wrote: When we're ready to merge, someone please do it for me, I don't have write permissions. https://github.com/llvm/llvm-project/pull/146830 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang-tools-extra] [clang-tidy][NFC] Make global variable constexpr (PR #147301)
https://github.com/localspook created https://github.com/llvm/llvm-project/pull/147301 ```cpp static const char *AnalyzerCheckNamePrefix = "clang-analyzer-"; ``` Right now, `AnalyzerCheckNamePrefix` is global mutable state. Probably not what was intended! >From e7b9da97611b272aae38ab3e4c7ed4113fec1728 Mon Sep 17 00:00:00 2001 From: Victor Chernyakin Date: Mon, 7 Jul 2025 06:34:02 -0700 Subject: [PATCH] [clang-tidy][NFC] Make global variable constexpr --- clang-tools-extra/clang-tidy/ClangTidy.cpp | 8 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/clang-tools-extra/clang-tidy/ClangTidy.cpp b/clang-tools-extra/clang-tidy/ClangTidy.cpp index f4ab93b51f4a7..c24e339d3628d 100644 --- a/clang-tools-extra/clang-tidy/ClangTidy.cpp +++ b/clang-tools-extra/clang-tidy/ClangTidy.cpp @@ -55,7 +55,8 @@ namespace clang::tidy { namespace { #if CLANG_TIDY_ENABLE_STATIC_ANALYZER -static const char *AnalyzerCheckNamePrefix = "clang-analyzer-"; +static constexpr llvm::StringLiteral AnalyzerCheckNamePrefix = +"clang-analyzer-"; class AnalyzerDiagnosticConsumer : public ento::PathDiagnosticConsumer { public: @@ -351,10 +352,9 @@ ClangTidyASTConsumerFactory::ClangTidyASTConsumerFactory( static void setStaticAnalyzerCheckerOpts(const ClangTidyOptions &Opts, clang::AnalyzerOptions &AnalyzerOptions) { - StringRef AnalyzerPrefix(AnalyzerCheckNamePrefix); for (const auto &Opt : Opts.CheckOptions) { StringRef OptName(Opt.getKey()); -if (!OptName.consume_front(AnalyzerPrefix)) +if (!OptName.consume_front(AnalyzerCheckNamePrefix)) continue; // Analyzer options are always local options so we can ignore priority. AnalyzerOptions.Config[OptName] = Opt.getValue().Value; @@ -476,7 +476,7 @@ std::vector ClangTidyASTConsumerFactory::getCheckNames() { #if CLANG_TIDY_ENABLE_STATIC_ANALYZER for (const auto &AnalyzerCheck : getAnalyzerCheckersAndPackages( Context, Context.canEnableAnalyzerAlphaCheckers())) -CheckNames.push_back(AnalyzerCheckNamePrefix + AnalyzerCheck.first); +CheckNames.emplace_back(AnalyzerCheckNamePrefix + AnalyzerCheck.first); #endif // CLANG_TIDY_ENABLE_STATIC_ANALYZER llvm::sort(CheckNames); ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang-tools-extra] [clang-tidy][NFC] Prefer `constexpr llvm::StringLiteral` over `const char *` (PR #147301)
https://github.com/localspook edited https://github.com/llvm/llvm-project/pull/147301 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang-tools-extra] [clang-tidy][NFC] Prefer `constexpr llvm::StringLiteral` over `const char *` (PR #147301)
@@ -55,7 +55,8 @@ namespace clang::tidy { namespace { #if CLANG_TIDY_ENABLE_STATIC_ANALYZER -static const char *AnalyzerCheckNamePrefix = "clang-analyzer-"; +static constexpr llvm::StringLiteral AnalyzerCheckNamePrefix = localspook wrote: I can't do that, it conflicts with: https://github.com/llvm/llvm-project/blob/45d679218aebdac5c9818be211d8e3a517c944c3/clang/include/clang/AST/Expr.h#L1794-L1796 That's why I'm qualifying with the namespace everywhere. https://github.com/llvm/llvm-project/pull/147301 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang-tools-extra] [clang-tidy][NFC] Make global variable constexpr (PR #147301)
https://github.com/localspook updated https://github.com/llvm/llvm-project/pull/147301 >From bad855d41d4350f51af955a33c079f3f1cf605f3 Mon Sep 17 00:00:00 2001 From: Victor Chernyakin Date: Mon, 7 Jul 2025 06:34:02 -0700 Subject: [PATCH] [clang-tidy][NFC] Prefer `constexpr llvm::StringLiteral` over `const char *` --- clang-tools-extra/clang-tidy/ClangTidy.cpp| 8 clang-tools-extra/clang-tidy/abseil/AbseilMatcher.h | 4 ++-- .../ComparePointerToMemberVirtualFunctionCheck.cpp| 2 +- .../cppcoreguidelines/ProTypeMemberInitCheck.cpp | 4 ++-- clang-tools-extra/clang-tidy/modernize/UseUsingCheck.cpp | 3 ++- 5 files changed, 11 insertions(+), 10 deletions(-) diff --git a/clang-tools-extra/clang-tidy/ClangTidy.cpp b/clang-tools-extra/clang-tidy/ClangTidy.cpp index f4ab93b51f4a7..c24e339d3628d 100644 --- a/clang-tools-extra/clang-tidy/ClangTidy.cpp +++ b/clang-tools-extra/clang-tidy/ClangTidy.cpp @@ -55,7 +55,8 @@ namespace clang::tidy { namespace { #if CLANG_TIDY_ENABLE_STATIC_ANALYZER -static const char *AnalyzerCheckNamePrefix = "clang-analyzer-"; +static constexpr llvm::StringLiteral AnalyzerCheckNamePrefix = +"clang-analyzer-"; class AnalyzerDiagnosticConsumer : public ento::PathDiagnosticConsumer { public: @@ -351,10 +352,9 @@ ClangTidyASTConsumerFactory::ClangTidyASTConsumerFactory( static void setStaticAnalyzerCheckerOpts(const ClangTidyOptions &Opts, clang::AnalyzerOptions &AnalyzerOptions) { - StringRef AnalyzerPrefix(AnalyzerCheckNamePrefix); for (const auto &Opt : Opts.CheckOptions) { StringRef OptName(Opt.getKey()); -if (!OptName.consume_front(AnalyzerPrefix)) +if (!OptName.consume_front(AnalyzerCheckNamePrefix)) continue; // Analyzer options are always local options so we can ignore priority. AnalyzerOptions.Config[OptName] = Opt.getValue().Value; @@ -476,7 +476,7 @@ std::vector ClangTidyASTConsumerFactory::getCheckNames() { #if CLANG_TIDY_ENABLE_STATIC_ANALYZER for (const auto &AnalyzerCheck : getAnalyzerCheckersAndPackages( Context, Context.canEnableAnalyzerAlphaCheckers())) -CheckNames.push_back(AnalyzerCheckNamePrefix + AnalyzerCheck.first); +CheckNames.emplace_back(AnalyzerCheckNamePrefix + AnalyzerCheck.first); #endif // CLANG_TIDY_ENABLE_STATIC_ANALYZER llvm::sort(CheckNames); diff --git a/clang-tools-extra/clang-tidy/abseil/AbseilMatcher.h b/clang-tools-extra/clang-tidy/abseil/AbseilMatcher.h index 1eef86ddc00b9..2ae3c00f7ee3e 100644 --- a/clang-tools-extra/clang-tidy/abseil/AbseilMatcher.h +++ b/clang-tools-extra/clang-tidy/abseil/AbseilMatcher.h @@ -46,12 +46,12 @@ AST_POLYMORPHIC_MATCHER( if (PrefixPosition == StringRef::npos) return false; Path = Path.drop_front(PrefixPosition + AbslPrefix.size()); - static const char *AbseilLibraries[] = { + static constexpr llvm::StringLiteral AbseilLibraries[] = { "algorithm", "base", "container", "debugging", "flags", "hash", "iterator", "memory","meta", "numeric", "profiling", "random", "status","strings", "synchronization", "time", "types","utility"}; - return llvm::any_of(AbseilLibraries, [&](const char *Library) { + return llvm::any_of(AbseilLibraries, [&](llvm::StringLiteral Library) { return Path.starts_with(Library); }); } diff --git a/clang-tools-extra/clang-tidy/bugprone/ComparePointerToMemberVirtualFunctionCheck.cpp b/clang-tools-extra/clang-tidy/bugprone/ComparePointerToMemberVirtualFunctionCheck.cpp index f2746ba159d04..1cbf1e22a33a7 100644 --- a/clang-tools-extra/clang-tidy/bugprone/ComparePointerToMemberVirtualFunctionCheck.cpp +++ b/clang-tools-extra/clang-tidy/bugprone/ComparePointerToMemberVirtualFunctionCheck.cpp @@ -25,7 +25,7 @@ namespace { AST_MATCHER(CXXMethodDecl, isVirtual) { return Node.isVirtual(); } -static const char *const ErrorMsg = +static constexpr llvm::StringLiteral ErrorMsg = "comparing a pointer to member virtual function with other pointer is " "unspecified behavior, only compare it with a null-pointer constant for " "equality."; diff --git a/clang-tools-extra/clang-tidy/cppcoreguidelines/ProTypeMemberInitCheck.cpp b/clang-tools-extra/clang-tidy/cppcoreguidelines/ProTypeMemberInitCheck.cpp index f6b66b51a..b413b12cd37ab 100644 --- a/clang-tools-extra/clang-tidy/cppcoreguidelines/ProTypeMemberInitCheck.cpp +++ b/clang-tools-extra/clang-tidy/cppcoreguidelines/ProTypeMemberInitCheck.cpp @@ -373,8 +373,8 @@ static bool isEmpty(ASTContext &Context, const QualType &Type) { return isIncompleteOrZeroLengthArrayType(Context, Type); } -static const char *getInitializer(QualType QT, bool UseAssignment) { - const char *DefaultInitializer = "{}"; +static llvm::StringLiteral getInitializer(QualType QT, bool UseAssignment) { + static constexpr llvm::StringLiteral DefaultInitializer = "{}"; if (!UseAssignment) return DefaultInitializ
[clang-tools-extra] [clang-tidy][NFC] Prefer `constexpr llvm::StringLiteral` over `const char *` (PR #147301)
https://github.com/localspook edited https://github.com/llvm/llvm-project/pull/147301 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang-tools-extra] [clang-tidy][NFC] Prefer `constexpr llvm::StringLiteral` over `const char *` (PR #147301)
https://github.com/localspook edited https://github.com/llvm/llvm-project/pull/147301 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang-tools-extra] [clang-tidy][NFC] Prefer `constexpr llvm::StringLiteral` over `const char *` (PR #147301)
https://github.com/localspook edited https://github.com/llvm/llvm-project/pull/147301 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang-tools-extra] [clang-tidy][NFC] Prefer `constexpr llvm::StringLiteral` over `const char *` (PR #147301)
https://github.com/localspook updated https://github.com/llvm/llvm-project/pull/147301 >From bad855d41d4350f51af955a33c079f3f1cf605f3 Mon Sep 17 00:00:00 2001 From: Victor Chernyakin Date: Mon, 7 Jul 2025 06:34:02 -0700 Subject: [PATCH 1/2] [clang-tidy][NFC] Prefer `constexpr llvm::StringLiteral` over `const char *` --- clang-tools-extra/clang-tidy/ClangTidy.cpp| 8 clang-tools-extra/clang-tidy/abseil/AbseilMatcher.h | 4 ++-- .../ComparePointerToMemberVirtualFunctionCheck.cpp| 2 +- .../cppcoreguidelines/ProTypeMemberInitCheck.cpp | 4 ++-- clang-tools-extra/clang-tidy/modernize/UseUsingCheck.cpp | 3 ++- 5 files changed, 11 insertions(+), 10 deletions(-) diff --git a/clang-tools-extra/clang-tidy/ClangTidy.cpp b/clang-tools-extra/clang-tidy/ClangTidy.cpp index f4ab93b51f4a7..c24e339d3628d 100644 --- a/clang-tools-extra/clang-tidy/ClangTidy.cpp +++ b/clang-tools-extra/clang-tidy/ClangTidy.cpp @@ -55,7 +55,8 @@ namespace clang::tidy { namespace { #if CLANG_TIDY_ENABLE_STATIC_ANALYZER -static const char *AnalyzerCheckNamePrefix = "clang-analyzer-"; +static constexpr llvm::StringLiteral AnalyzerCheckNamePrefix = +"clang-analyzer-"; class AnalyzerDiagnosticConsumer : public ento::PathDiagnosticConsumer { public: @@ -351,10 +352,9 @@ ClangTidyASTConsumerFactory::ClangTidyASTConsumerFactory( static void setStaticAnalyzerCheckerOpts(const ClangTidyOptions &Opts, clang::AnalyzerOptions &AnalyzerOptions) { - StringRef AnalyzerPrefix(AnalyzerCheckNamePrefix); for (const auto &Opt : Opts.CheckOptions) { StringRef OptName(Opt.getKey()); -if (!OptName.consume_front(AnalyzerPrefix)) +if (!OptName.consume_front(AnalyzerCheckNamePrefix)) continue; // Analyzer options are always local options so we can ignore priority. AnalyzerOptions.Config[OptName] = Opt.getValue().Value; @@ -476,7 +476,7 @@ std::vector ClangTidyASTConsumerFactory::getCheckNames() { #if CLANG_TIDY_ENABLE_STATIC_ANALYZER for (const auto &AnalyzerCheck : getAnalyzerCheckersAndPackages( Context, Context.canEnableAnalyzerAlphaCheckers())) -CheckNames.push_back(AnalyzerCheckNamePrefix + AnalyzerCheck.first); +CheckNames.emplace_back(AnalyzerCheckNamePrefix + AnalyzerCheck.first); #endif // CLANG_TIDY_ENABLE_STATIC_ANALYZER llvm::sort(CheckNames); diff --git a/clang-tools-extra/clang-tidy/abseil/AbseilMatcher.h b/clang-tools-extra/clang-tidy/abseil/AbseilMatcher.h index 1eef86ddc00b9..2ae3c00f7ee3e 100644 --- a/clang-tools-extra/clang-tidy/abseil/AbseilMatcher.h +++ b/clang-tools-extra/clang-tidy/abseil/AbseilMatcher.h @@ -46,12 +46,12 @@ AST_POLYMORPHIC_MATCHER( if (PrefixPosition == StringRef::npos) return false; Path = Path.drop_front(PrefixPosition + AbslPrefix.size()); - static const char *AbseilLibraries[] = { + static constexpr llvm::StringLiteral AbseilLibraries[] = { "algorithm", "base", "container", "debugging", "flags", "hash", "iterator", "memory","meta", "numeric", "profiling", "random", "status","strings", "synchronization", "time", "types","utility"}; - return llvm::any_of(AbseilLibraries, [&](const char *Library) { + return llvm::any_of(AbseilLibraries, [&](llvm::StringLiteral Library) { return Path.starts_with(Library); }); } diff --git a/clang-tools-extra/clang-tidy/bugprone/ComparePointerToMemberVirtualFunctionCheck.cpp b/clang-tools-extra/clang-tidy/bugprone/ComparePointerToMemberVirtualFunctionCheck.cpp index f2746ba159d04..1cbf1e22a33a7 100644 --- a/clang-tools-extra/clang-tidy/bugprone/ComparePointerToMemberVirtualFunctionCheck.cpp +++ b/clang-tools-extra/clang-tidy/bugprone/ComparePointerToMemberVirtualFunctionCheck.cpp @@ -25,7 +25,7 @@ namespace { AST_MATCHER(CXXMethodDecl, isVirtual) { return Node.isVirtual(); } -static const char *const ErrorMsg = +static constexpr llvm::StringLiteral ErrorMsg = "comparing a pointer to member virtual function with other pointer is " "unspecified behavior, only compare it with a null-pointer constant for " "equality."; diff --git a/clang-tools-extra/clang-tidy/cppcoreguidelines/ProTypeMemberInitCheck.cpp b/clang-tools-extra/clang-tidy/cppcoreguidelines/ProTypeMemberInitCheck.cpp index f6b66b51a..b413b12cd37ab 100644 --- a/clang-tools-extra/clang-tidy/cppcoreguidelines/ProTypeMemberInitCheck.cpp +++ b/clang-tools-extra/clang-tidy/cppcoreguidelines/ProTypeMemberInitCheck.cpp @@ -373,8 +373,8 @@ static bool isEmpty(ASTContext &Context, const QualType &Type) { return isIncompleteOrZeroLengthArrayType(Context, Type); } -static const char *getInitializer(QualType QT, bool UseAssignment) { - const char *DefaultInitializer = "{}"; +static llvm::StringLiteral getInitializer(QualType QT, bool UseAssignment) { + static constexpr llvm::StringLiteral DefaultInitializer = "{}"; if (!UseAssignment) return DefaultIniti
[clang-tools-extra] [clang-tidy] Add new check: `readability-use-concise-preprocessor-directives` (PR #146830)
https://github.com/localspook updated https://github.com/llvm/llvm-project/pull/146830 >From 9eb58438d2b4061ad7a6bdbd1db82a5fd4043948 Mon Sep 17 00:00:00 2001 From: Victor Chernyakin Date: Thu, 3 Jul 2025 00:19:52 -0700 Subject: [PATCH 01/12] [clang-tidy] Add new check: `modernize-use-concise-preprocessor-directives` Rewrites preprocessor conditions like `#if defined(MEOW)` as `#ifdef MEOW` and `#elif !defined(MEOW)` as `#elifndef MEOW`. Closes #132561. --- .../clang-tidy/modernize/CMakeLists.txt | 1 + .../modernize/ModernizeTidyModule.cpp | 3 + .../UseConcisePreprocessorDirectivesCheck.cpp | 105 ++ .../UseConcisePreprocessorDirectivesCheck.h | 37 + clang-tools-extra/docs/ReleaseNotes.rst | 6 + .../docs/clang-tidy/checks/list.rst | 1 + .../use-concise-preprocessor-directives.rst | 28 .../use-concise-preprocessor-directives.cpp | 134 ++ 8 files changed, 315 insertions(+) create mode 100644 clang-tools-extra/clang-tidy/modernize/UseConcisePreprocessorDirectivesCheck.cpp create mode 100644 clang-tools-extra/clang-tidy/modernize/UseConcisePreprocessorDirectivesCheck.h create mode 100644 clang-tools-extra/docs/clang-tidy/checks/modernize/use-concise-preprocessor-directives.rst create mode 100644 clang-tools-extra/test/clang-tidy/checkers/modernize/use-concise-preprocessor-directives.cpp diff --git a/clang-tools-extra/clang-tidy/modernize/CMakeLists.txt b/clang-tools-extra/clang-tidy/modernize/CMakeLists.txt index 619a27b2f9bb6..22d5214b61441 100644 --- a/clang-tools-extra/clang-tidy/modernize/CMakeLists.txt +++ b/clang-tools-extra/clang-tidy/modernize/CMakeLists.txt @@ -30,6 +30,7 @@ add_clang_library(clangTidyModernizeModule STATIC UnaryStaticAssertCheck.cpp UseAutoCheck.cpp UseBoolLiteralsCheck.cpp + UseConcisePreprocessorDirectivesCheck.cpp UseConstraintsCheck.cpp UseDefaultMemberInitCheck.cpp UseDesignatedInitializersCheck.cpp diff --git a/clang-tools-extra/clang-tidy/modernize/ModernizeTidyModule.cpp b/clang-tools-extra/clang-tidy/modernize/ModernizeTidyModule.cpp index fdf38bc4b6308..28c5467f7b3e0 100644 --- a/clang-tools-extra/clang-tidy/modernize/ModernizeTidyModule.cpp +++ b/clang-tools-extra/clang-tidy/modernize/ModernizeTidyModule.cpp @@ -31,6 +31,7 @@ #include "UnaryStaticAssertCheck.h" #include "UseAutoCheck.h" #include "UseBoolLiteralsCheck.h" +#include "UseConcisePreprocessorDirectivesCheck.h" #include "UseConstraintsCheck.h" #include "UseDefaultMemberInitCheck.h" #include "UseDesignatedInitializersCheck.h" @@ -76,6 +77,8 @@ class ModernizeModule : public ClangTidyModule { CheckFactories.registerCheck( "modernize-min-max-use-initializer-list"); CheckFactories.registerCheck("modernize-pass-by-value"); +CheckFactories.registerCheck( +"modernize-use-concise-preprocessor-directives"); CheckFactories.registerCheck( "modernize-use-designated-initializers"); CheckFactories.registerCheck( diff --git a/clang-tools-extra/clang-tidy/modernize/UseConcisePreprocessorDirectivesCheck.cpp b/clang-tools-extra/clang-tidy/modernize/UseConcisePreprocessorDirectivesCheck.cpp new file mode 100644 index 0..56ed1b3cc879d --- /dev/null +++ b/clang-tools-extra/clang-tidy/modernize/UseConcisePreprocessorDirectivesCheck.cpp @@ -0,0 +1,105 @@ +//===--- UseConcisePreprocessorDirectivesCheck.cpp - clang-tidy ---===// +// +// 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 "UseConcisePreprocessorDirectivesCheck.h" +#include "clang/Basic/TokenKinds.h" +#include "clang/Lex/Lexer.h" +#include "clang/Lex/PPCallbacks.h" +#include "clang/Lex/Preprocessor.h" + +namespace clang::tidy::modernize { + +namespace { + +class IfPreprocessorCallbacks final : public PPCallbacks { +public: + IfPreprocessorCallbacks(ClangTidyCheck &Check, Preprocessor &PP) + : Check(Check), PP(PP) {} + + void If(SourceLocation Loc, SourceRange ConditionRange, + ConditionValueKind) override { +impl(Loc, ConditionRange, {"ifdef", "ifndef"}); + } + + void Elif(SourceLocation Loc, SourceRange ConditionRange, ConditionValueKind, +SourceLocation) override { +if (PP.getLangOpts().C23 || PP.getLangOpts().CPlusPlus23) { + impl(Loc, ConditionRange, {"elifdef", "elifndef"}); +} + } + +private: + void impl(SourceLocation DirectiveLoc, SourceRange ConditionRange, +const llvm::StringLiteral (&Replacements)[2]) { +StringRef Condition = +Lexer::getSourceText(CharSourceRange::getTokenRange(ConditionRange), + PP.getSourceManager(), PP.getLangOpts()); +Lexer Lex(DirectiveLoc, PP.getLangOpts(), Condition.data(), +
[clang-tools-extra] [clang-tidy] Add new check: `readability-use-concise-preprocessor-directives` (PR #146830)
@@ -0,0 +1,40 @@ +//===--- UseConcisePreprocessorDirectivesCheck.h - clang-tidy ---*- C++ -*-===// +// +// 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_USECONCISEPREPROCESSORDIRECTIVESCHECK_H +#define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_READABILITY_USECONCISEPREPROCESSORDIRECTIVESCHECK_H + +#include "../ClangTidyCheck.h" + +namespace clang::tidy::readability { + +/// Shortens `#if` preprocessor conditions: +/// +/// #if defined(MEOW) -> #ifdef MEOW +/// #if !defined(MEOW) -> #ifndef MEOW +/// +/// And, since C23 and C++23, shortens `#elif` conditions too: +/// +/// #elif defined(MEOW) -> #elifdef MEOW +/// #elif !defined(MEOW) -> #elifndef MEOW +/// +/// User-facing documentation: +/// https://clang.llvm.org/extra/clang-tidy/checks/readability/use-concise-preprocessor-directives.html +class UseConcisePreprocessorDirectivesCheck : public ClangTidyCheck { +public: + using ClangTidyCheck::ClangTidyCheck; + void registerPPCallbacks(const SourceManager &SM, Preprocessor *PP, + Preprocessor *ModuleExpanderPP) override; + bool isLanguageVersionSupported(const LangOptions &LangOpts) const override { +return LangOpts.CPlusPlus || LangOpts.C99; localspook wrote: Changed to `return true` https://github.com/llvm/llvm-project/pull/146830 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang-tools-extra] [clang-tidy] filter check options by enabled checks in '--dump-config' (PR #147142)
@@ -503,6 +503,21 @@ getCheckNames(const ClangTidyOptions &Options, return Factory.getCheckNames(); } +void filterCheckOptions(ClangTidyOptions &Options, +const std::vector &EnabledChecks) { + StringSet<> EnabledChecksSet(llvm::from_range, EnabledChecks); + ClangTidyOptions::OptionMap FilteredOptions; + for (const auto &[OptionName, Value] : Options.CheckOptions) { +const size_t CheckNameEndPos = OptionName.find('.'); +if (CheckNameEndPos == StringRef::npos) + continue; +const StringRef CheckName = OptionName.substr(0, CheckNameEndPos); +if (EnabledChecksSet.contains(CheckName)) + FilteredOptions[OptionName] = Value; + } + Options.CheckOptions = std::move(FilteredOptions); +} localspook wrote: `StringMap::erase` returns `void`, which I *think* means it doesn't invalidate iterators, but I agree, involving iterators at all makes it less readable. If `StringMap` was compatible with `llvm::erase_if`, we could get the best of both worlds, but it doesn't seem to be right now... https://github.com/llvm/llvm-project/pull/147142 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [clang-tools-extra] [ASTMatchers][NFC] Replace `makeMatcher` function with CTAD (PR #147197)
https://github.com/localspook updated https://github.com/llvm/llvm-project/pull/147197 >From c9da8d946b867fb6e095cefee44388f240c28c28 Mon Sep 17 00:00:00 2001 From: Victor Chernyakin Date: Sun, 6 Jul 2025 08:32:49 -0700 Subject: [PATCH 1/2] [ASTMatchers][NFC] Replace `makeMatcher` function with CTAD --- clang-tools-extra/clang-tidy/utils/Matchers.h | 4 ++-- clang/include/clang/ASTMatchers/ASTMatchersInternal.h | 7 +-- clang/include/clang/ASTMatchers/ASTMatchersMacros.h | 8 clang/lib/Tooling/Transformer/RewriteRule.cpp | 4 ++-- 4 files changed, 9 insertions(+), 14 deletions(-) diff --git a/clang-tools-extra/clang-tidy/utils/Matchers.h b/clang-tools-extra/clang-tidy/utils/Matchers.h index 2b6d377b8fd10..a7683024d69c4 100644 --- a/clang-tools-extra/clang-tidy/utils/Matchers.h +++ b/clang-tools-extra/clang-tidy/utils/Matchers.h @@ -145,7 +145,7 @@ class MatchesAnyListedNameMatcher // qualified name will be used for matching, otherwise its name will be used. inline ::clang::ast_matchers::internal::Matcher matchesAnyListedName(llvm::ArrayRef NameList) { - return ::clang::ast_matchers::internal::makeMatcher( + return ::clang::ast_matchers::internal::Matcher( new MatchesAnyListedNameMatcher(NameList)); } @@ -188,7 +188,7 @@ class MatchesAnyListedTypeNameMatcher inline ::clang::ast_matchers::internal::Matcher matchesAnyListedTypeName(llvm::ArrayRef NameList, bool CanonicalTypes) { - return ::clang::ast_matchers::internal::makeMatcher( + return ::clang::ast_matchers::internal::Matcher( new MatchesAnyListedTypeNameMatcher(NameList, CanonicalTypes)); } inline ::clang::ast_matchers::internal::Matcher diff --git a/clang/include/clang/ASTMatchers/ASTMatchersInternal.h b/clang/include/clang/ASTMatchers/ASTMatchersInternal.h index 667a044abcef1..5b092537e5e7c 100644 --- a/clang/include/clang/ASTMatchers/ASTMatchersInternal.h +++ b/clang/include/clang/ASTMatchers/ASTMatchersInternal.h @@ -672,12 +672,7 @@ class Matcher { DynTypedMatcher Implementation; }; // class Matcher -/// A convenient helper for creating a Matcher without specifying -/// the template type argument. -template -inline Matcher makeMatcher(MatcherInterface *Implementation) { - return Matcher(Implementation); -} +template Matcher(MatcherInterface *) -> Matcher; /// Interface that allows matchers to traverse the AST. /// FIXME: Find a better name. diff --git a/clang/include/clang/ASTMatchers/ASTMatchersMacros.h b/clang/include/clang/ASTMatchers/ASTMatchersMacros.h index f781e0a565eb3..8ac55e5bb1fc0 100644 --- a/clang/include/clang/ASTMatchers/ASTMatchersMacros.h +++ b/clang/include/clang/ASTMatchers/ASTMatchersMacros.h @@ -106,7 +106,7 @@ }; \ } \ inline ::clang::ast_matchers::internal::Matcher DefineMatcher() { \ -return ::clang::ast_matchers::internal::makeMatcher( \ +return ::clang::ast_matchers::internal::Matcher( \ new internal::matcher_##DefineMatcher##Matcher()); \ } \ inline bool internal::matcher_##DefineMatcher##Matcher::matches( \ @@ -150,7 +150,7 @@ } \ inline ::clang::ast_matchers::internal::Matcher DefineMatcher( \ ParamType const &Param) { \ -return ::clang::ast_matchers::internal::makeMatcher( \ +return ::clang::ast_matchers::internal::Matcher( \ new internal::matcher_##DefineMatcher##OverloadId##Matcher(Param)); \ } \ typedef ::clang::ast_matchers::internal::Matcher ( \ @@ -200,7 +200,7 @@ } \ inline ::clang::ast_matchers::internal::Matcher DefineMatcher( \ ParamType1 const &Param1, ParamType2 const &Param2) { \ -return ::clang::ast_matchers::internal::makeMatcher( \ +return ::clang::ast_matchers::internal::Matcher( \ new internal::matcher_##DefineMatcher##OverloadId##Matcher(Param1, \ Param2)); \ } \ @@ -476,7 +476,7 @@ } \ inline ::clang::ast_matchers::internal::Matcher DefineMatcher( \ llvm::StringRef Param, llvm::Regex::RegexFlags RegexFlag
[clang-tools-extra] [clang-tidy][NFC] concat static-analyzer name at compilation time (PR #147406)
https://github.com/localspook updated https://github.com/llvm/llvm-project/pull/147406 >From 779dd600a1190b36c1343343e139f6579fa5190b Mon Sep 17 00:00:00 2001 From: Victor Chernyakin Date: Mon, 7 Jul 2025 14:14:44 -0700 Subject: [PATCH 1/3] [clang-tidy][NFC] Do more work at compile time --- clang-tools-extra/clang-tidy/ClangTidy.cpp | 11 ++- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/clang-tools-extra/clang-tidy/ClangTidy.cpp b/clang-tools-extra/clang-tidy/ClangTidy.cpp index f4ab93b51f4a7..815033c2e5175 100644 --- a/clang-tools-extra/clang-tidy/ClangTidy.cpp +++ b/clang-tools-extra/clang-tidy/ClangTidy.cpp @@ -668,18 +668,19 @@ getAllChecksAndOptions(bool AllowEnablingAnalyzerAlphaCheckers) { Buffer.append(AnalyzerCheck); Result.Checks.insert(Buffer); } - for (std::string OptionName : { + + static constexpr llvm::StringLiteral OptionNames[] = { #define GET_CHECKER_OPTIONS #define CHECKER_OPTION(TYPE, CHECKER, OPTION_NAME, DESCRIPTION, DEFAULT, \ RELEASE, HIDDEN) \ - Twine(AnalyzerCheckNamePrefix).concat(CHECKER ":" OPTION_NAME).str(), + "clang-analyzer-" CHECKER ":" OPTION_NAME, #include "clang/StaticAnalyzer/Checkers/Checkers.inc" #undef CHECKER_OPTION #undef GET_CHECKER_OPTIONS - }) { -Result.Options.insert(OptionName); - } + }; + + Result.Options.insert_range(OptionNames); #endif // CLANG_TIDY_ENABLE_STATIC_ANALYZER Context.setOptionsCollector(&Result.Options); >From 19492a294f364dae68ba8432a8d2a17597dda82d Mon Sep 17 00:00:00 2001 From: Victor Chernyakin Date: Wed, 9 Jul 2025 02:31:29 -0700 Subject: [PATCH 2/3] Macroize --- clang-tools-extra/clang-tidy/ClangTidy.cpp | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/clang-tools-extra/clang-tidy/ClangTidy.cpp b/clang-tools-extra/clang-tidy/ClangTidy.cpp index 815033c2e5175..93f798643a5ca 100644 --- a/clang-tools-extra/clang-tidy/ClangTidy.cpp +++ b/clang-tools-extra/clang-tidy/ClangTidy.cpp @@ -55,7 +55,8 @@ namespace clang::tidy { namespace { #if CLANG_TIDY_ENABLE_STATIC_ANALYZER -static const char *AnalyzerCheckNamePrefix = "clang-analyzer-"; +#define ANALYZER_CHECK_NAME_PREFIX "clang-analyzer-" +static const char *AnalyzerCheckNamePrefix = ANALYZER_CHECK_NAME_PREFIX; class AnalyzerDiagnosticConsumer : public ento::PathDiagnosticConsumer { public: @@ -673,7 +674,7 @@ getAllChecksAndOptions(bool AllowEnablingAnalyzerAlphaCheckers) { #define GET_CHECKER_OPTIONS #define CHECKER_OPTION(TYPE, CHECKER, OPTION_NAME, DESCRIPTION, DEFAULT, \ RELEASE, HIDDEN) \ - "clang-analyzer-" CHECKER ":" OPTION_NAME, + ANALYZER_CHECK_NAME_PREFIX CHECKER ":" OPTION_NAME, #include "clang/StaticAnalyzer/Checkers/Checkers.inc" #undef CHECKER_OPTION >From d4c06bf30763341fbc3969c97531f680b4304e63 Mon Sep 17 00:00:00 2001 From: Victor Chernyakin Date: Wed, 9 Jul 2025 02:35:49 -0700 Subject: [PATCH 3/3] Fix merge conflict --- clang-tools-extra/clang-tidy/ClangTidy.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/clang-tools-extra/clang-tidy/ClangTidy.cpp b/clang-tools-extra/clang-tidy/ClangTidy.cpp index 93f798643a5ca..dc46841f1c266 100644 --- a/clang-tools-extra/clang-tidy/ClangTidy.cpp +++ b/clang-tools-extra/clang-tidy/ClangTidy.cpp @@ -56,7 +56,8 @@ namespace clang::tidy { namespace { #if CLANG_TIDY_ENABLE_STATIC_ANALYZER #define ANALYZER_CHECK_NAME_PREFIX "clang-analyzer-" -static const char *AnalyzerCheckNamePrefix = ANALYZER_CHECK_NAME_PREFIX; +static constexpr llvm::StringLiteral AnalyzerCheckNamePrefix = +ANALYZER_CHECK_NAME_PREFIX; class AnalyzerDiagnosticConsumer : public ento::PathDiagnosticConsumer { public: ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang-tools-extra] [clang-tidy][NFC] concat static-analyzer name at compilation time (PR #147406)
https://github.com/localspook updated https://github.com/llvm/llvm-project/pull/147406 >From 6f1c9ae3079e4958f29c71a9e09b74b33758effe Mon Sep 17 00:00:00 2001 From: Victor Chernyakin Date: Mon, 7 Jul 2025 14:14:44 -0700 Subject: [PATCH 1/2] [clang-tidy][NFC] Do more work at compile time --- clang-tools-extra/clang-tidy/ClangTidy.cpp | 11 ++- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/clang-tools-extra/clang-tidy/ClangTidy.cpp b/clang-tools-extra/clang-tidy/ClangTidy.cpp index 808515c463b91..1c07c3ad549c5 100644 --- a/clang-tools-extra/clang-tidy/ClangTidy.cpp +++ b/clang-tools-extra/clang-tidy/ClangTidy.cpp @@ -669,18 +669,19 @@ getAllChecksAndOptions(bool AllowEnablingAnalyzerAlphaCheckers) { Buffer.append(AnalyzerCheck); Result.Checks.insert(Buffer); } - for (std::string OptionName : { + + static constexpr llvm::StringLiteral OptionNames[] = { #define GET_CHECKER_OPTIONS #define CHECKER_OPTION(TYPE, CHECKER, OPTION_NAME, DESCRIPTION, DEFAULT, \ RELEASE, HIDDEN) \ - Twine(AnalyzerCheckNamePrefix).concat(CHECKER ":" OPTION_NAME).str(), + "clang-analyzer-" CHECKER ":" OPTION_NAME, #include "clang/StaticAnalyzer/Checkers/Checkers.inc" #undef CHECKER_OPTION #undef GET_CHECKER_OPTIONS - }) { -Result.Options.insert(OptionName); - } + }; + + Result.Options.insert_range(OptionNames); #endif // CLANG_TIDY_ENABLE_STATIC_ANALYZER Context.setOptionsCollector(&Result.Options); >From cfa47b311ad71799aeecd20c94e3c3ef02aa9aab Mon Sep 17 00:00:00 2001 From: Victor Chernyakin Date: Wed, 9 Jul 2025 02:39:12 -0700 Subject: [PATCH 2/2] Macroize and rebase to resolve merge conflict --- clang-tools-extra/clang-tidy/ClangTidy.cpp | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/clang-tools-extra/clang-tidy/ClangTidy.cpp b/clang-tools-extra/clang-tidy/ClangTidy.cpp index 1c07c3ad549c5..ad59b90cebb95 100644 --- a/clang-tools-extra/clang-tidy/ClangTidy.cpp +++ b/clang-tools-extra/clang-tidy/ClangTidy.cpp @@ -55,8 +55,9 @@ namespace clang::tidy { namespace { #if CLANG_TIDY_ENABLE_STATIC_ANALYZER +#define ANALYZER_CHECK_NAME_PREFIX "clang-analyzer-" static constexpr llvm::StringLiteral AnalyzerCheckNamePrefix = -"clang-analyzer-"; +ANALYZER_CHECK_NAME_PREFIX; class AnalyzerDiagnosticConsumer : public ento::PathDiagnosticConsumer { public: @@ -674,7 +675,7 @@ getAllChecksAndOptions(bool AllowEnablingAnalyzerAlphaCheckers) { #define GET_CHECKER_OPTIONS #define CHECKER_OPTION(TYPE, CHECKER, OPTION_NAME, DESCRIPTION, DEFAULT, \ RELEASE, HIDDEN) \ - "clang-analyzer-" CHECKER ":" OPTION_NAME, + ANALYZER_CHECK_NAME_PREFIX CHECKER ":" OPTION_NAME, #include "clang/StaticAnalyzer/Checkers/Checkers.inc" #undef CHECKER_OPTION ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang-tools-extra] [clang-tidy][NFC] concat static-analyzer name at compilation time (PR #147406)
https://github.com/localspook updated https://github.com/llvm/llvm-project/pull/147406 >From 779dd600a1190b36c1343343e139f6579fa5190b Mon Sep 17 00:00:00 2001 From: Victor Chernyakin Date: Mon, 7 Jul 2025 14:14:44 -0700 Subject: [PATCH 1/2] [clang-tidy][NFC] Do more work at compile time --- clang-tools-extra/clang-tidy/ClangTidy.cpp | 11 ++- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/clang-tools-extra/clang-tidy/ClangTidy.cpp b/clang-tools-extra/clang-tidy/ClangTidy.cpp index f4ab93b51f4a7..815033c2e5175 100644 --- a/clang-tools-extra/clang-tidy/ClangTidy.cpp +++ b/clang-tools-extra/clang-tidy/ClangTidy.cpp @@ -668,18 +668,19 @@ getAllChecksAndOptions(bool AllowEnablingAnalyzerAlphaCheckers) { Buffer.append(AnalyzerCheck); Result.Checks.insert(Buffer); } - for (std::string OptionName : { + + static constexpr llvm::StringLiteral OptionNames[] = { #define GET_CHECKER_OPTIONS #define CHECKER_OPTION(TYPE, CHECKER, OPTION_NAME, DESCRIPTION, DEFAULT, \ RELEASE, HIDDEN) \ - Twine(AnalyzerCheckNamePrefix).concat(CHECKER ":" OPTION_NAME).str(), + "clang-analyzer-" CHECKER ":" OPTION_NAME, #include "clang/StaticAnalyzer/Checkers/Checkers.inc" #undef CHECKER_OPTION #undef GET_CHECKER_OPTIONS - }) { -Result.Options.insert(OptionName); - } + }; + + Result.Options.insert_range(OptionNames); #endif // CLANG_TIDY_ENABLE_STATIC_ANALYZER Context.setOptionsCollector(&Result.Options); >From 19492a294f364dae68ba8432a8d2a17597dda82d Mon Sep 17 00:00:00 2001 From: Victor Chernyakin Date: Wed, 9 Jul 2025 02:31:29 -0700 Subject: [PATCH 2/2] Macroize --- clang-tools-extra/clang-tidy/ClangTidy.cpp | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/clang-tools-extra/clang-tidy/ClangTidy.cpp b/clang-tools-extra/clang-tidy/ClangTidy.cpp index 815033c2e5175..93f798643a5ca 100644 --- a/clang-tools-extra/clang-tidy/ClangTidy.cpp +++ b/clang-tools-extra/clang-tidy/ClangTidy.cpp @@ -55,7 +55,8 @@ namespace clang::tidy { namespace { #if CLANG_TIDY_ENABLE_STATIC_ANALYZER -static const char *AnalyzerCheckNamePrefix = "clang-analyzer-"; +#define ANALYZER_CHECK_NAME_PREFIX "clang-analyzer-" +static const char *AnalyzerCheckNamePrefix = ANALYZER_CHECK_NAME_PREFIX; class AnalyzerDiagnosticConsumer : public ento::PathDiagnosticConsumer { public: @@ -673,7 +674,7 @@ getAllChecksAndOptions(bool AllowEnablingAnalyzerAlphaCheckers) { #define GET_CHECKER_OPTIONS #define CHECKER_OPTION(TYPE, CHECKER, OPTION_NAME, DESCRIPTION, DEFAULT, \ RELEASE, HIDDEN) \ - "clang-analyzer-" CHECKER ":" OPTION_NAME, + ANALYZER_CHECK_NAME_PREFIX CHECKER ":" OPTION_NAME, #include "clang/StaticAnalyzer/Checkers/Checkers.inc" #undef CHECKER_OPTION ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang-tools-extra] [clang-tidy][NFC] Do less unnecessary work in `NoLintDirectiveHandler` (PR #147553)
https://github.com/localspook created https://github.com/llvm/llvm-project/pull/147553 I plan to do more work in this area, but I feel this is a good first set of changes. Summary: - `NoLintBlockToken` is too big: it stores a whole `NoLintToken` inside itself, when all it needs from that `NoLintToken` is its `Pos` and `ChecksGlob`. - `formNoLintBlocks` builds up a vector of unmatched tokens, which are later transformed into errors. We can skip the middle step and make `formNoLintBlocks` create errors directly. - In `generateCache`, the line `Cache[FileName] = ...;` default-constructs a cache entry only to immediately overwrite it. We can avoid that by using `Cache.try_emplace(FileName, ...);` instead. - `NoLintToken`'s constructor takes `const std::optional&` when all it needs is `const std::optional&`. This forces its caller, `getNoLints`, to create temporary strings. - `NoLintToken::checks` returns `std::optional` by value, creating unnecessary copies in `formNoLintBlocks`. >From 9b772adf9cf32f0ae47011e41c16d1dc180887cd Mon Sep 17 00:00:00 2001 From: Victor Chernyakin Date: Mon, 7 Jul 2025 18:00:28 -0700 Subject: [PATCH] [clang-tidy][NFC] Do less unnecessary work in `NoLintDirectiveHandler` --- .../clang-tidy/NoLintDirectiveHandler.cpp | 115 +- .../clang-tidy/NoLintDirectiveHandler.h | 2 - 2 files changed, 55 insertions(+), 62 deletions(-) diff --git a/clang-tools-extra/clang-tidy/NoLintDirectiveHandler.cpp b/clang-tools-extra/clang-tidy/NoLintDirectiveHandler.cpp index ed03b456f4954..bbae2c171f790 100644 --- a/clang-tools-extra/clang-tidy/NoLintDirectiveHandler.cpp +++ b/clang-tools-extra/clang-tidy/NoLintDirectiveHandler.cpp @@ -25,10 +25,9 @@ #include "llvm/ADT/StringSwitch.h" #include #include -#include +#include #include #include -#include #include namespace clang::tidy { @@ -79,7 +78,7 @@ class NoLintToken { // - An empty string means nothing is suppressed - equivalent to NOLINT(). // - Negative globs ignored (which would effectively disable the suppression). NoLintToken(NoLintType Type, size_t Pos, - const std::optional &Checks) + const std::optional &Checks) : Type(Type), Pos(Pos), ChecksGlob(std::make_unique( Checks.value_or("*"), /*KeepNegativeGlobs=*/false)) { @@ -93,15 +92,17 @@ class NoLintToken { // The location of the first character, "N", in "NOLINT". size_t Pos; + // A glob of the checks this NOLINT token disables. + std::unique_ptr ChecksGlob; + // If this NOLINT specifies checks, return the checks. - std::optional checks() const { return Checks; } + const std::optional &checks() const { return Checks; } // Whether this NOLINT applies to the provided check. bool suppresses(StringRef Check) const { return ChecksGlob->contains(Check); } private: std::optional Checks; - std::unique_ptr ChecksGlob; }; } // namespace @@ -131,11 +132,11 @@ static SmallVector getNoLints(StringRef Buffer) { continue; // Get checks, if specified. -std::optional Checks; +std::optional Checks; if (Pos < Buffer.size() && Buffer[Pos] == '(') { size_t ClosingBracket = Buffer.find_first_of("\n)", ++Pos); if (ClosingBracket != StringRef::npos && Buffer[ClosingBracket] == ')') { -Checks = Buffer.slice(Pos, ClosingBracket).str(); +Checks = Buffer.slice(Pos, ClosingBracket); Pos = ClosingBracket + 1; } } @@ -155,34 +156,51 @@ namespace { // Represents a source range within a pair of NOLINT(BEGIN/END) comments. class NoLintBlockToken { public: - NoLintBlockToken(NoLintToken Begin, const NoLintToken &End) - : Begin(std::move(Begin)), EndPos(End.Pos) { -assert(this->Begin.Type == NoLintType::NoLintBegin); -assert(End.Type == NoLintType::NoLintEnd); -assert(this->Begin.Pos < End.Pos); -assert(this->Begin.checks() == End.checks()); - } + NoLintBlockToken(size_t BeginPos, size_t EndPos, + std::unique_ptr ChecksGlob) + : BeginPos(BeginPos), EndPos(EndPos), ChecksGlob(std::move(ChecksGlob)) {} // Whether the provided diagnostic is within and is suppressible by this block // of NOLINT(BEGIN/END) comments. bool suppresses(size_t DiagPos, StringRef DiagName) const { -return (Begin.Pos < DiagPos) && (DiagPos < EndPos) && - Begin.suppresses(DiagName); +return (BeginPos < DiagPos) && (DiagPos < EndPos) && + ChecksGlob->contains(DiagName); } private: - NoLintToken Begin; + size_t BeginPos; size_t EndPos; + std::unique_ptr ChecksGlob; }; } // namespace +// Construct a [clang-tidy-nolint] diagnostic to do with the unmatched +// NOLINT(BEGIN/END) pair. +static tooling::Diagnostic makeNoLintError(const SourceManager &SrcMgr, + FileID File, + const NoLintToken &No
[clang-tools-extra] [clang-tidy][NFC] Do less unnecessary work in `NoLintDirectiveHandler` (PR #147553)
@@ -31,8 +31,6 @@ class NoLintDirectiveHandler { public: NoLintDirectiveHandler(); ~NoLintDirectiveHandler(); - NoLintDirectiveHandler(const NoLintDirectiveHandler &) = delete; - NoLintDirectiveHandler &operator=(const NoLintDirectiveHandler &) = delete; localspook wrote: This class holds a `std::unique_ptr`, so it's already noncopyable. https://github.com/llvm/llvm-project/pull/147553 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang-tools-extra] [clang-tidy] Teach `readability-uppercase-literal-suffix` about C++23 and C23 suffixes (PR #148275)
https://github.com/localspook created https://github.com/llvm/llvm-project/pull/148275 C++23 integer literal suffixes: | Suffix | Type | |-|-| |`z` | `std::make_signed_t`| |`uz` | `std::size_t`| C++23 floating-point literal suffixes: | Suffix | Type | |-|-| |`bf16` | `std::bfloat16_t`| |`f16` | `std::float16_t`| |`f32` | `std::float32_t`| |`f64` | `std::float64_t`| |`f128` | `std::float128_t`| C23 integer literal suffixes: | Suffix | Type | |-|-| |`wb ` | `_BitInt(N)`| |`uwb ` | `unsigned _BitInt(N)`| C23 floating-point literal suffixes: | Suffix | Type | |-|-| |`df` | `_Decimal32`| |`dd` | `_Decimal64`| |`dl` | `_Decimal128`| Clang doesn't actually support any of the new floating point types yet (except for `f16`). I've decided to add disabled tests for them, so that when the support comes, we can flip the switch and support them with no delay. >From b19ad9cda58288d727861bdd0a9d2a7cedc7c1a6 Mon Sep 17 00:00:00 2001 From: Victor Chernyakin Date: Fri, 11 Jul 2025 11:35:50 -0700 Subject: [PATCH] [clang-tidy] Teach `readability-uppercase-literal-suffix` about C++23 and C23 suffixes --- .../UppercaseLiteralSuffixCheck.cpp | 13 +- clang-tools-extra/docs/ReleaseNotes.rst | 4 + .../uppercase-literal-suffix-c23.c| 162 ...literal-suffix-extended-floating-point.cpp | 248 ++ .../uppercase-literal-suffix-float16.cpp | 51 .../uppercase-literal-suffix-integer.cpp | 86 +- 6 files changed, 506 insertions(+), 58 deletions(-) create mode 100644 clang-tools-extra/test/clang-tidy/checkers/readability/uppercase-literal-suffix-c23.c create mode 100644 clang-tools-extra/test/clang-tidy/checkers/readability/uppercase-literal-suffix-extended-floating-point.cpp delete mode 100644 clang-tools-extra/test/clang-tidy/checkers/readability/uppercase-literal-suffix-float16.cpp diff --git a/clang-tools-extra/clang-tidy/readability/UppercaseLiteralSuffixCheck.cpp b/clang-tools-extra/clang-tidy/readability/UppercaseLiteralSuffixCheck.cpp index 678aa8dad48a7..dd43ee200f4c0 100644 --- a/clang-tools-extra/clang-tidy/readability/UppercaseLiteralSuffixCheck.cpp +++ b/clang-tools-extra/clang-tidy/readability/UppercaseLiteralSuffixCheck.cpp @@ -25,10 +25,11 @@ struct IntegerLiteralCheck { static constexpr llvm::StringLiteral Name = llvm::StringLiteral("integer"); // What should be skipped before looking for the Suffixes? (Nothing here.) static constexpr llvm::StringLiteral SkipFirst = llvm::StringLiteral(""); - // Suffix can only consist of 'u' and 'l' chars, and can be a complex number - // ('i', 'j'). In MS compatibility mode, suffixes like i32 are supported. + // Suffix can only consist of 'u', 'l', and 'z' chars, can be a bit-precise + // integer (wb), and can be a complex number ('i', 'j'). In MS compatibility + // mode, suffixes like i32 are supported. static constexpr llvm::StringLiteral Suffixes = - llvm::StringLiteral("uUlLiIjJ"); + llvm::StringLiteral("uUlLzZwWbBiIjJ"); }; constexpr llvm::StringLiteral IntegerLiteralCheck::Name; constexpr llvm::StringLiteral IntegerLiteralCheck::SkipFirst; @@ -45,10 +46,10 @@ struct FloatingLiteralCheck { // Since the exponent ('p'/'P') is mandatory for hexadecimal floating-point // literals, we first skip everything before the exponent. static constexpr llvm::StringLiteral SkipFirst = llvm::StringLiteral("pP"); - // Suffix can only consist of 'f', 'l', "f16", 'h', 'q' chars, - // and can be a complex number ('i', 'j'). + // Suffix can only consist of 'f', 'l', "f16", "bf16", "df", "dd", "dl", + // 'h', 'q' chars, and can be a complex number ('i', 'j'). static constexpr llvm::StringLiteral Suffixes = - llvm::StringLiteral("fFlLhHqQiIjJ"); + llvm::StringLiteral("fFlLbBdDhHqQiIjJ"); }; constexpr llvm::StringLiteral FloatingLiteralCheck::Name; constexpr llvm::StringLiteral FloatingLiteralCheck::SkipFirst; diff --git a/clang-tools-extra/docs/ReleaseNotes.rst b/clang-tools-extra/docs/ReleaseNotes.rst index ad869265a2db5..119c030b43852 100644 --- a/clang-tools-extra/docs/ReleaseNotes.rst +++ b/clang-tools-extra/docs/ReleaseNotes.rst @@ -354,6 +354,10 @@ Changes in existing checks ` check by fixing some false positives involving smart pointers to arrays. +- Improved :doc:`readability-uppercase-literal-suffix + ` check to recognize + literal suffixes added in C++23 and C23. + Removed checks ^^ diff --git a/clang-tools-extra/test/clang-tidy/checkers/readability/uppercase-literal-suffix-c23.c b/clang-tools-extra/test/clang-tidy/checkers/readability/uppercase-literal-suffix-c23.c new file mode 100644 index 0..75727fc69e68c --- /dev/null +++ b/clang-tools-extra/test/clang-tidy/checkers/readability/uppercase-literal-suffix-c23.c @@ -0,0 +1,162 @@ +// TODO: When Clang adds supp
[clang-tools-extra] [clang-tidy] Teach `readability-uppercase-literal-suffix` about C++23 and C23 suffixes (PR #148275)
https://github.com/localspook edited https://github.com/llvm/llvm-project/pull/148275 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang-tools-extra] [clang-tidy] `misc-confusable-identifiers`: Update `confusables.txt` (PR #148399)
https://github.com/localspook created https://github.com/llvm/llvm-project/pull/148399 We're currently on Unicode 14.0.0. This PR updates it to Unicode 16.0.0. >From e252ea0a1ac94e8324bb332037508fd3f9b61317 Mon Sep 17 00:00:00 2001 From: Victor Chernyakin Date: Sat, 12 Jul 2025 12:46:01 -0700 Subject: [PATCH] [clang-tidy] `misc-confusable-identifiers`: Update `confusables.txt` --- .../misc/ConfusableTable/confusables.txt | 95 ++- 1 file changed, 71 insertions(+), 24 deletions(-) diff --git a/clang-tools-extra/clang-tidy/misc/ConfusableTable/confusables.txt b/clang-tools-extra/clang-tidy/misc/ConfusableTable/confusables.txt index 706177e3cf0bf..f88841b7ff0f5 100644 --- a/clang-tools-extra/clang-tidy/misc/ConfusableTable/confusables.txt +++ b/clang-tools-extra/clang-tidy/misc/ConfusableTable/confusables.txt @@ -1,13 +1,13 @@ - confusables.txt -# Date: 2021-05-29, 22:09:29 GMT -# © 2021 Unicode®, Inc. +# confusables.txt +# Date: 2024-08-14, 23:39:57 GMT +# © 2024 Unicode®, Inc. # Unicode and the Unicode Logo are registered trademarks of Unicode, Inc. in the U.S. and other countries. -# For terms of use, see http://www.unicode.org/terms_of_use.html +# For terms of use and license, see https://www.unicode.org/terms_of_use.html # # Unicode Security Mechanisms for UTS #39 -# Version: 14.0.0 +# Version: 16.0.0 # -# For documentation and usage, see http://www.unicode.org/reports/tr39 +# For documentation and usage, see https://www.unicode.org/reports/tr39 # 05AD ; 0596 ; MA # ( ֭ → ֖ ) HEBREW ACCENT DEHI → HEBREW ACCENT TIPEHA # @@ -349,8 +349,8 @@ A4FA ; 002E 002E ; MA # ( ꓺ → .. ) LISU LETTER TONE MYA CYA → FULL STOP, F A6F4 ; A6F3 A6F3 ; MA #* ( ꛴ → ꛳꛳ ) BAMUM COLON → BAMUM FULL STOP, BAMUM FULL STOP# -30FB ; 00B7 ; MA #* ( ・ → · ) KATAKANA MIDDLE DOT → MIDDLE DOT # →•→ -FF65 ; 00B7 ; MA #* ( ・ → · ) HALFWIDTH KATAKANA MIDDLE DOT → MIDDLE DOT # →•→ +30FB ; 00B7 ; MA # ( ・ → · ) KATAKANA MIDDLE DOT → MIDDLE DOT# →•→ +FF65 ; 00B7 ; MA # ( ・ → · ) HALFWIDTH KATAKANA MIDDLE DOT → MIDDLE DOT # →•→ 16EB ; 00B7 ; MA #* ( ᛫ → · ) RUNIC SINGLE PUNCTUATION → MIDDLE DOT # 0387 ; 00B7 ; MA # ( · → · ) GREEK ANO TELEIA → MIDDLE DOT # 2E31 ; 00B7 ; MA #* ( ⸱ → · ) WORD SEPARATOR MIDDLE DOT → MIDDLE DOT # @@ -577,10 +577,10 @@ FF07 ;0027 ; MA #* ( ' → ' ) FULLWIDTH APOSTROPHE → APOSTROPHE # →’ 2018 ; 0027 ; MA #* ( ‘ → ' ) LEFT SINGLE QUOTATION MARK → APOSTROPHE # 2019 ; 0027 ; MA #* ( ’ → ' ) RIGHT SINGLE QUOTATION MARK → APOSTROPHE # 201B ; 0027 ; MA #* ( ‛ → ' ) SINGLE HIGH-REVERSED-9 QUOTATION MARK → APOSTROPHE # →′→ +05F3 ; 0027 ; MA #* ( ׳ → ' ) HEBREW PUNCTUATION GERESH → APOSTROPHE # 2032 ; 0027 ; MA #* ( ′ → ' ) PRIME → APOSTROPHE # 2035 ; 0027 ; MA #* ( ‵ → ' ) REVERSED PRIME → APOSTROPHE# →ʽ→→‘→ 055A ; 0027 ; MA #* ( ՚ → ' ) ARMENIAN APOSTROPHE → APOSTROPHE # →’→ -05F3 ; 0027 ; MA #* ( ׳ → ' ) HEBREW PUNCTUATION GERESH → APOSTROPHE # 0060 ; 0027 ; MA #* ( ` → ' ) GRAVE ACCENT → APOSTROPHE # →ˋ→→`→→‘→ 1FEF ; 0027 ; MA #* ( ` → ' ) GREEK VARIA → APOSTROPHE # →ˋ→→`→→‘→ FF40 ; 0027 ; MA #* ( ` → ' ) FULLWIDTH GRAVE ACCENT → APOSTROPHE # →‘→ @@ -615,10 +615,10 @@ FF02 ;0027 0027 ; MA #* ( " → '' ) FULLWIDTH QUOTATION MARK → APOSTROPHE, 201C ; 0027 0027 ; MA #* ( “ → '' ) LEFT DOUBLE QUOTATION MARK → APOSTROPHE, APOSTROPHE # →"→ 201D ; 0027 0027 ; MA #* ( ” → '' ) RIGHT DOUBLE QUOTATION MARK → APOSTROPHE, APOSTROPHE # →"→ 201F ; 0027 0027 ; MA #* ( ‟ → '' ) DOUBLE HIGH-REVERSED-9 QUOTATION MARK → APOSTROPHE, APOSTROPHE# →“→→"→ +05F4 ; 0027 0027 ; MA #* ( ״ → '' ) HEBREW PUNCTUATION GERSHAYIM → APOSTROPHE, APOSTROPHE # →"→ 2033 ; 0027 0027 ; MA #* ( ″ → '' ) DOUBLE PRIME → APOSTROPHE, APOSTROPHE # →"→ 2036 ; 0027 0027 ; MA #* ( ‶ → '' ) REVERSED DOUBLE PRIME → APOSTROPHE, APOSTROPHE# →‵‵→ 3003 ; 0027 0027 ; MA #* ( 〃 → '' ) DITTO MARK → APOSTROPHE, APOSTROPHE # →″→→"→ -05F4 ; 0027 0027 ; MA #* ( ״ → '' ) HEBREW PUNCTUATION GERSHAYIM → APOSTROPHE, APOSTROPHE # →"→ 02DD ; 0027 0027 ; MA #* ( ˝ → '' ) DOUBLE ACUTE ACCENT → APOSTROPHE, APOSTROPHE # →"→ 02BA ; 0027 0027 ; MA # ( ʺ → '' ) MODIFIER LETTER DOUBLE PRIME → APOSTROPHE, APOSTROPHE # →"→ 02F6 ; 0027 0027 ; MA #* ( ˶ → '' ) MODIFIER LETTER MIDDLE DOUBLE ACUTE ACCENT → APOSTROPHE, APOSTROPHE # →˝→→"→ @@ -1071,7 +1071,7 @@ A714 ;02EB ; MA #* ( ꜔ → ˫ ) MODIFIER LETTER MID LEFT-STEM TONE BAR → MO 25CB ; 00B0 ; MA #* ( ○ → ° ) WHITE CIRCLE → DEGREE SIGN # →◦→→∘→ 25E6 ; 00B0 ; MA #* ( ◦ → ° ) WHITE BULLET → DEGREE SIGN # →∘→ -235C ; 00B0 0332 ; MA #* ( ⍜ → °̲ ) APL F
[clang-tools-extra] Add clang tidy check performance constexpr non static in scope (PR #147809)
@@ -0,0 +1,37 @@ +//===--- ConstexprNonStaticInScopeCheck.h - clang-tidy --*- C++ -*-===// +// +// 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_PERFORMANCE_CONSTEXPRNONSTATICINSCOPECHECK_H +#define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_PERFORMANCE_CONSTEXPRNONSTATICINSCOPECHECK_H + +#include "../ClangTidyCheck.h" + +namespace clang::tidy::performance { + +/// FIXME: Write a short description. +/// +/// For the user-facing documentation see: +/// http://clang.llvm.org/extra/clang-tidy/checks/performance/constexpr-non-static-in-scope.html +class ConstexprNonStaticInScopeCheck : public ClangTidyCheck { +public: + ConstexprNonStaticInScopeCheck(StringRef Name, ClangTidyContext *Context) + : ClangTidyCheck(Name, Context), +WarnInConstexprFuncCpp23(Options.get("WarnInConstexprFuncCpp23", /*Default=*/true)) {} + void registerMatchers(ast_matchers::MatchFinder *Finder) override; + void check(const ast_matchers::MatchFinder::MatchResult &Result) override; + bool isLanguageVersionSupported(const LangOptions &LangOpts) const override { +return LangOpts.CPlusPlus; localspook wrote: ```suggestion return LangOpts.CPlusPlus11; ``` `constexpr` is only since C++11 https://github.com/llvm/llvm-project/pull/147809 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang-tools-extra] Add clang tidy check performance constexpr non static in scope (PR #147809)
https://github.com/localspook edited https://github.com/llvm/llvm-project/pull/147809 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang-tools-extra] [clang-tidy] Teach `cppcoreguidelines-interfaces-global-init` about `constinit` (PR #148334)
@@ -1,4 +1,4 @@ -// RUN: %check_clang_tidy %s cppcoreguidelines-interfaces-global-init %t +// RUN: %check_clang_tidy -std=c++20 %s cppcoreguidelines-interfaces-global-init %t localspook wrote: Would you be fine with some `#if __cplusplus >= 202002L` guards instead? The code blocks with `constinit` mirror code blocks without it, so I feel the test reads better when they stay together. https://github.com/llvm/llvm-project/pull/148334 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang-tools-extra] [clang-tidy] Teach `cppcoreguidelines-interfaces-global-init` about `constinit` (PR #148334)
https://github.com/localspook created https://github.com/llvm/llvm-project/pull/148334 This check already understands how `constexpr` makes initialization order problems impossible, and C++20's `constinit` provides the exact same guarantees while placing fewer restrictions on the user. >From e6b9c9ab548986d26fe24a91ab360e7c0363817d Mon Sep 17 00:00:00 2001 From: Victor Chernyakin Date: Fri, 11 Jul 2025 21:09:22 -0700 Subject: [PATCH] [clang-tidy] Teach `cppcoreguidelines-interfaces-global-init` about `constinit` --- .../InterfacesGlobalInitCheck.cpp | 2 +- clang-tools-extra/docs/ReleaseNotes.rst | 4 +++ .../interfaces-global-init.cpp| 28 +-- 3 files changed, 31 insertions(+), 3 deletions(-) diff --git a/clang-tools-extra/clang-tidy/cppcoreguidelines/InterfacesGlobalInitCheck.cpp b/clang-tools-extra/clang-tidy/cppcoreguidelines/InterfacesGlobalInitCheck.cpp index e8a2e7b8ef86d..e9f0bd98cad16 100644 --- a/clang-tools-extra/clang-tidy/cppcoreguidelines/InterfacesGlobalInitCheck.cpp +++ b/clang-tools-extra/clang-tidy/cppcoreguidelines/InterfacesGlobalInitCheck.cpp @@ -19,7 +19,7 @@ void InterfacesGlobalInitCheck::registerMatchers(MatchFinder *Finder) { hasDeclContext(anyOf(translationUnitDecl(), // Global scope. namespaceDecl(), // Namespace scope. recordDecl())),// Class scope. - unless(isConstexpr())); + unless(isConstexpr()), unless(isConstinit())); const auto ReferencesUndefinedGlobalVar = declRefExpr(hasDeclaration( varDecl(GlobalVarDecl, unless(isDefinition())).bind("referencee"))); diff --git a/clang-tools-extra/docs/ReleaseNotes.rst b/clang-tools-extra/docs/ReleaseNotes.rst index ad869265a2db5..bff7cfa4fe525 100644 --- a/clang-tools-extra/docs/ReleaseNotes.rst +++ b/clang-tools-extra/docs/ReleaseNotes.rst @@ -212,6 +212,10 @@ Changes in existing checks ` check by adding the option `IgnoreMacros` to ignore ``goto`` labels defined in macros. +- Improved :doc:`cppcoreguidelines-interfaces-global-init + ` check by + fixing false positives on uses of ``constinit`` variables. + - Improved :doc:`cppcoreguidelines-missing-std-forward ` check by adding a flag to specify the function used for forwarding instead of ``std::forward``. diff --git a/clang-tools-extra/test/clang-tidy/checkers/cppcoreguidelines/interfaces-global-init.cpp b/clang-tools-extra/test/clang-tidy/checkers/cppcoreguidelines/interfaces-global-init.cpp index 51f79e522c0ca..38d02c6a7f186 100644 --- a/clang-tools-extra/test/clang-tidy/checkers/cppcoreguidelines/interfaces-global-init.cpp +++ b/clang-tools-extra/test/clang-tidy/checkers/cppcoreguidelines/interfaces-global-init.cpp @@ -1,4 +1,4 @@ -// RUN: %check_clang_tidy %s cppcoreguidelines-interfaces-global-init %t +// RUN: %check_clang_tidy -std=c++20 %s cppcoreguidelines-interfaces-global-init %t constexpr int makesInt() { return 3; } constexpr int takesInt(int i) { return i + 1; } @@ -14,11 +14,19 @@ static int GlobalScopeBadInit3 = takesIntPtr(&ExternGlobal); static int GlobalScopeBadInit4 = 3 * (ExternGlobal + 2); // CHECK-MESSAGES: [[@LINE-1]]:12: warning: initializing non-local variable with non-const expression depending on uninitialized non-local variable 'ExternGlobal' +extern constinit int ExternConstinitGlobal; +static int GlobalScopeConstinit1 = ExternConstinitGlobal; +static int GlobalScopeConstinit2 = takesInt(ExternConstinitGlobal); +static int GlobalScopeConstinit3 = takesIntPtr(&ExternConstinitGlobal); +static int GlobalScopeConstinit4 = 3 * (ExternConstinitGlobal + 2); + namespace ns { static int NamespaceScope = makesInt(); static int NamespaceScopeBadInit = takesInt(ExternGlobal); // CHECK-MESSAGES: [[@LINE-1]]:12: warning: initializing non-local variable with non-const expression depending on uninitialized non-local variable 'ExternGlobal' +static int NamespaceScopeConstinit = takesInt(ExternConstinitGlobal); + struct A { static int ClassScope; static int ClassScopeBadInit; @@ -29,6 +37,15 @@ int A::ClassScopeBadInit = takesInt(ExternGlobal); static int FromClassBadInit = takesInt(A::ClassScope); // CHECK-MESSAGES: [[@LINE-1]]:12: warning: initializing non-local variable with non-const expression depending on uninitialized non-local variable 'ClassScope' + +struct B { + static constinit int ClassScopeConstinit; + static int ClassScopeFromConstinit; +}; + +int B::ClassScopeFromConstinit = takesInt(ExternConstinitGlobal); +static int FromClassScopeConstinit = takesInt(B::ClassScopeConstinit); + } // namespace ns // "const int B::I;" is fine, it just ODR-defines B::I. See [9.4.3] Static @@ -42,6 +59,14 @@ const int B1::J; // CHECK-MESSAGES: [[@LINE-1]]:15: warning: initializing non-local variable with non-const expression depending on uninitialized non-local variable 'I' const int B1::I; +class D { + st
[clang-tools-extra] [clang-tidy] Teach `cppcoreguidelines-interfaces-global-init` about `constinit` (PR #148334)
https://github.com/localspook updated https://github.com/llvm/llvm-project/pull/148334 >From e6b9c9ab548986d26fe24a91ab360e7c0363817d Mon Sep 17 00:00:00 2001 From: Victor Chernyakin Date: Fri, 11 Jul 2025 21:09:22 -0700 Subject: [PATCH 1/2] [clang-tidy] Teach `cppcoreguidelines-interfaces-global-init` about `constinit` --- .../InterfacesGlobalInitCheck.cpp | 2 +- clang-tools-extra/docs/ReleaseNotes.rst | 4 +++ .../interfaces-global-init.cpp| 28 +-- 3 files changed, 31 insertions(+), 3 deletions(-) diff --git a/clang-tools-extra/clang-tidy/cppcoreguidelines/InterfacesGlobalInitCheck.cpp b/clang-tools-extra/clang-tidy/cppcoreguidelines/InterfacesGlobalInitCheck.cpp index e8a2e7b8ef86d..e9f0bd98cad16 100644 --- a/clang-tools-extra/clang-tidy/cppcoreguidelines/InterfacesGlobalInitCheck.cpp +++ b/clang-tools-extra/clang-tidy/cppcoreguidelines/InterfacesGlobalInitCheck.cpp @@ -19,7 +19,7 @@ void InterfacesGlobalInitCheck::registerMatchers(MatchFinder *Finder) { hasDeclContext(anyOf(translationUnitDecl(), // Global scope. namespaceDecl(), // Namespace scope. recordDecl())),// Class scope. - unless(isConstexpr())); + unless(isConstexpr()), unless(isConstinit())); const auto ReferencesUndefinedGlobalVar = declRefExpr(hasDeclaration( varDecl(GlobalVarDecl, unless(isDefinition())).bind("referencee"))); diff --git a/clang-tools-extra/docs/ReleaseNotes.rst b/clang-tools-extra/docs/ReleaseNotes.rst index ad869265a2db5..bff7cfa4fe525 100644 --- a/clang-tools-extra/docs/ReleaseNotes.rst +++ b/clang-tools-extra/docs/ReleaseNotes.rst @@ -212,6 +212,10 @@ Changes in existing checks ` check by adding the option `IgnoreMacros` to ignore ``goto`` labels defined in macros. +- Improved :doc:`cppcoreguidelines-interfaces-global-init + ` check by + fixing false positives on uses of ``constinit`` variables. + - Improved :doc:`cppcoreguidelines-missing-std-forward ` check by adding a flag to specify the function used for forwarding instead of ``std::forward``. diff --git a/clang-tools-extra/test/clang-tidy/checkers/cppcoreguidelines/interfaces-global-init.cpp b/clang-tools-extra/test/clang-tidy/checkers/cppcoreguidelines/interfaces-global-init.cpp index 51f79e522c0ca..38d02c6a7f186 100644 --- a/clang-tools-extra/test/clang-tidy/checkers/cppcoreguidelines/interfaces-global-init.cpp +++ b/clang-tools-extra/test/clang-tidy/checkers/cppcoreguidelines/interfaces-global-init.cpp @@ -1,4 +1,4 @@ -// RUN: %check_clang_tidy %s cppcoreguidelines-interfaces-global-init %t +// RUN: %check_clang_tidy -std=c++20 %s cppcoreguidelines-interfaces-global-init %t constexpr int makesInt() { return 3; } constexpr int takesInt(int i) { return i + 1; } @@ -14,11 +14,19 @@ static int GlobalScopeBadInit3 = takesIntPtr(&ExternGlobal); static int GlobalScopeBadInit4 = 3 * (ExternGlobal + 2); // CHECK-MESSAGES: [[@LINE-1]]:12: warning: initializing non-local variable with non-const expression depending on uninitialized non-local variable 'ExternGlobal' +extern constinit int ExternConstinitGlobal; +static int GlobalScopeConstinit1 = ExternConstinitGlobal; +static int GlobalScopeConstinit2 = takesInt(ExternConstinitGlobal); +static int GlobalScopeConstinit3 = takesIntPtr(&ExternConstinitGlobal); +static int GlobalScopeConstinit4 = 3 * (ExternConstinitGlobal + 2); + namespace ns { static int NamespaceScope = makesInt(); static int NamespaceScopeBadInit = takesInt(ExternGlobal); // CHECK-MESSAGES: [[@LINE-1]]:12: warning: initializing non-local variable with non-const expression depending on uninitialized non-local variable 'ExternGlobal' +static int NamespaceScopeConstinit = takesInt(ExternConstinitGlobal); + struct A { static int ClassScope; static int ClassScopeBadInit; @@ -29,6 +37,15 @@ int A::ClassScopeBadInit = takesInt(ExternGlobal); static int FromClassBadInit = takesInt(A::ClassScope); // CHECK-MESSAGES: [[@LINE-1]]:12: warning: initializing non-local variable with non-const expression depending on uninitialized non-local variable 'ClassScope' + +struct B { + static constinit int ClassScopeConstinit; + static int ClassScopeFromConstinit; +}; + +int B::ClassScopeFromConstinit = takesInt(ExternConstinitGlobal); +static int FromClassScopeConstinit = takesInt(B::ClassScopeConstinit); + } // namespace ns // "const int B::I;" is fine, it just ODR-defines B::I. See [9.4.3] Static @@ -42,6 +59,14 @@ const int B1::J; // CHECK-MESSAGES: [[@LINE-1]]:15: warning: initializing non-local variable with non-const expression depending on uninitialized non-local variable 'I' const int B1::I; +class D { + static const constinit int I = 0; + static const int J = I; +}; + +const int D::J; +const int D::I; + void f() { // This is fine, it's executed after dynamic initialization occurs. static int G
[clang-tools-extra] [clang-tidy] Teach `cppcoreguidelines-interfaces-global-init` about `constinit` (PR #148334)
https://github.com/localspook edited https://github.com/llvm/llvm-project/pull/148334 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang-tools-extra] [clang-tidy] `misc-confusable-identifiers`: Update `confusables.txt` (PR #148399)
localspook wrote: Taken from: https://www.unicode.org/Public/security/16.0.0/confusables.txt https://github.com/llvm/llvm-project/pull/148399 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang-tools-extra] [clang-tidy] Update `confusables.txt` in `misc-confusable-identifiers` (PR #148399)
https://github.com/localspook edited https://github.com/llvm/llvm-project/pull/148399 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang-tools-extra] [clang-tidy] Speed up `misc-header-include-cycle` (PR #148757)
https://github.com/localspook updated https://github.com/llvm/llvm-project/pull/148757 >From 7cab196f263cc4d1787fe74ae49d4340fcb88624 Mon Sep 17 00:00:00 2001 From: Victor Chernyakin Date: Sun, 13 Jul 2025 11:30:49 -0700 Subject: [PATCH 1/2] [clang-tidy] Speed up `misc-header-include-cycle` --- .../misc/HeaderIncludeCycleCheck.cpp | 66 --- 1 file changed, 26 insertions(+), 40 deletions(-) diff --git a/clang-tools-extra/clang-tidy/misc/HeaderIncludeCycleCheck.cpp b/clang-tools-extra/clang-tidy/misc/HeaderIncludeCycleCheck.cpp index 21d443a1f34ff..1bd51c5902cde 100644 --- a/clang-tools-extra/clang-tidy/misc/HeaderIncludeCycleCheck.cpp +++ b/clang-tools-extra/clang-tidy/misc/HeaderIncludeCycleCheck.cpp @@ -13,8 +13,8 @@ #include "clang/Lex/Preprocessor.h" #include "llvm/Support/Regex.h" #include -#include #include +#include using namespace clang::ast_matchers; @@ -23,8 +23,8 @@ namespace clang::tidy::misc { namespace { struct Include { - FileID Id; - llvm::StringRef Name; + const FileEntry *File; + StringRef Name; SourceLocation Loc; }; @@ -50,31 +50,27 @@ class CyclicDependencyCallbacks : public PPCallbacks { if (Reason != EnterFile && Reason != ExitFile) return; -FileID Id = SM.getFileID(Loc); +const FileID Id = SM.getFileID(Loc); if (Id.isInvalid()) return; +const FileEntry *NewFile = SM.getFileEntryForID(Id); +const FileEntry *PrevFile = SM.getFileEntryForID(PrevFID); + if (Reason == ExitFile) { - if ((Files.size() > 1U) && (Files.back().Id == PrevFID) && - (Files[Files.size() - 2U].Id == Id)) + if ((Files.size() > 1U) && (Files.back().File == PrevFile) && + (Files[Files.size() - 2U].File == NewFile)) Files.pop_back(); return; } -if (!Files.empty() && Files.back().Id == Id) +if (!Files.empty() && Files.back().File == NewFile) return; -std::optional FilePath = SM.getNonBuiltinFilenameForID(Id); -llvm::StringRef FileName = -FilePath ? llvm::sys::path::filename(*FilePath) : llvm::StringRef(); - -if (!NextToEnter) - NextToEnter = Include{Id, FileName, SourceLocation()}; - -assert(NextToEnter->Name == FileName); -NextToEnter->Id = Id; -Files.emplace_back(*NextToEnter); -NextToEnter.reset(); +const std::optional FilePath = SM.getNonBuiltinFilenameForID(Id); +const StringRef FileName = +FilePath ? llvm::sys::path::filename(*FilePath) : StringRef(); +Files.push_back({NewFile, FileName, std::exchange(NextToEnter, {})}); } void InclusionDirective(SourceLocation, const Token &, StringRef FilePath, @@ -85,36 +81,26 @@ class CyclicDependencyCallbacks : public PPCallbacks { if (FileType != clang::SrcMgr::C_User) return; -llvm::StringRef FileName = llvm::sys::path::filename(FilePath); -NextToEnter = {FileID(), FileName, Range.getBegin()}; +NextToEnter = Range.getBegin(); if (!File) return; -FileID Id = SM.translateFile(*File); -if (Id.isInvalid()) - return; - -checkForDoubleInclude(Id, FileName, Range.getBegin()); +checkForDoubleInclude(&File->getFileEntry(), + llvm::sys::path::filename(FilePath), + Range.getBegin()); } - void EndOfMainFile() override { -if (!Files.empty() && Files.back().Id == SM.getMainFileID()) - Files.pop_back(); - -assert(Files.empty()); - } - - void checkForDoubleInclude(FileID Id, llvm::StringRef FileName, + void checkForDoubleInclude(const FileEntry *File, StringRef FileName, SourceLocation Loc) { -auto It = -std::find_if(Files.rbegin(), Files.rend(), - [&](const Include &Entry) { return Entry.Id == Id; }); +const auto It = +llvm::find_if(llvm::reverse(Files), + [&](const Include &Entry) { return Entry.File == File; }); if (It == Files.rend()) return; -const std::optional FilePath = SM.getNonBuiltinFilenameForID(Id); -if (!FilePath || isFileIgnored(*FilePath)) +const StringRef FilePath = File->tryGetRealPathName(); +if (FilePath.empty() || isFileIgnored(FilePath)) return; if (It == Files.rbegin()) { @@ -145,8 +131,8 @@ class CyclicDependencyCallbacks : public PPCallbacks { } private: - std::deque Files; - std::optional NextToEnter; + std::vector Files; + SourceLocation NextToEnter; HeaderIncludeCycleCheck &Check; const SourceManager &SM; std::vector IgnoredFilesRegexes; >From 477eef1d60387b66eb477822827238e537178ea1 Mon Sep 17 00:00:00 2001 From: Victor Chernyakin Date: Tue, 15 Jul 2025 11:23:13 -0700 Subject: [PATCH 2/2] Add release notes, restore `EndOfMainFile` override --- .../clang-tidy/misc/HeaderIncludeCycleCheck.cpp| 10 ++ clang-tools-extra/docs/ReleaseNotes.rst| 3 +++ 2 files changed, 13 insertions(+) diff --git a
[clang-tools-extra] [clang-tidy] Speed up `misc-header-include-cycle` (PR #148757)
@@ -85,36 +81,26 @@ class CyclicDependencyCallbacks : public PPCallbacks { if (FileType != clang::SrcMgr::C_User) return; -llvm::StringRef FileName = llvm::sys::path::filename(FilePath); -NextToEnter = {FileID(), FileName, Range.getBegin()}; +NextToEnter = Range.getBegin(); if (!File) return; -FileID Id = SM.translateFile(*File); -if (Id.isInvalid()) - return; - -checkForDoubleInclude(Id, FileName, Range.getBegin()); +checkForDoubleInclude(&File->getFileEntry(), + llvm::sys::path::filename(FilePath), + Range.getBegin()); } - void EndOfMainFile() override { -if (!Files.empty() && Files.back().Id == SM.getMainFileID()) - Files.pop_back(); - -assert(Files.empty()); - } localspook wrote: Restored the override. I've put it behind an `#ifndef NDEBUG`, I think that signals better that the whole override is a debug check. https://github.com/llvm/llvm-project/pull/148757 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang-tools-extra] [clang-tidy] Speed up `misc-header-include-cycle` (PR #148757)
localspook wrote: It doesn't seem like preprocessor-based checks appear in the profile. You can see this with an existing preprocessor check; running `clang-tidy --checks=-*,readability-redundant-preprocessor -enable-check-profile` produces no output. https://github.com/llvm/llvm-project/pull/148757 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang-tools-extra] [clang-tidy] Speed up `misc-header-include-cycle` (PR #148757)
https://github.com/localspook edited https://github.com/llvm/llvm-project/pull/148757 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang-tools-extra] [clang-tidy] Speed up `misc-header-include-cycle` (PR #148757)
@@ -85,36 +81,26 @@ class CyclicDependencyCallbacks : public PPCallbacks { if (FileType != clang::SrcMgr::C_User) return; -llvm::StringRef FileName = llvm::sys::path::filename(FilePath); -NextToEnter = {FileID(), FileName, Range.getBegin()}; +NextToEnter = Range.getBegin(); if (!File) return; -FileID Id = SM.translateFile(*File); -if (Id.isInvalid()) - return; - -checkForDoubleInclude(Id, FileName, Range.getBegin()); +checkForDoubleInclude(&File->getFileEntry(), + llvm::sys::path::filename(FilePath), + Range.getBegin()); } - void EndOfMainFile() override { -if (!Files.empty() && Files.back().Id == SM.getMainFileID()) - Files.pop_back(); - -assert(Files.empty()); - } localspook wrote: Confirmed that the assert doesn't fire when running over `llvm`. https://github.com/llvm/llvm-project/pull/148757 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits