diff options
author | Jade Lovelace <lix@jade.fyi> | 2024-08-04 22:02:53 -0700 |
---|---|---|
committer | Jade Lovelace <lix@jade.fyi> | 2024-08-08 14:53:17 -0700 |
commit | a5f0954c290157875b4dfb79edcf651f55742dc2 (patch) | |
tree | 16efd430c4c0828ee236eda636015e79e15bb965 /subprojects/lix-clang-tidy | |
parent | a85c4ce535c940bd2f48c34ab823fb3a8f5be0cc (diff) |
clang-tidy: write a lint for charptr_cast
This lets us ensure that nobody is putting in new reinterpret_cast
instances where they could safely use charptr_cast instead.
Change-Id: I6358a3934c8133c7150042635843bdbb6b9218d4
Diffstat (limited to 'subprojects/lix-clang-tidy')
-rw-r--r-- | subprojects/lix-clang-tidy/CharPtrCast.cc | 45 | ||||
-rw-r--r-- | subprojects/lix-clang-tidy/CharPtrCast.hh | 32 | ||||
-rw-r--r-- | subprojects/lix-clang-tidy/LixClangTidyChecks.cc | 2 | ||||
-rw-r--r-- | subprojects/lix-clang-tidy/meson.build | 3 |
4 files changed, 81 insertions, 1 deletions
diff --git a/subprojects/lix-clang-tidy/CharPtrCast.cc b/subprojects/lix-clang-tidy/CharPtrCast.cc new file mode 100644 index 000000000..e76797f5d --- /dev/null +++ b/subprojects/lix-clang-tidy/CharPtrCast.cc @@ -0,0 +1,45 @@ +#include "CharPtrCast.hh" +#include <clang/AST/ExprCXX.h> +#include <clang/Basic/Diagnostic.h> +#include <clang/Tooling/Transformer/SourceCode.h> + +namespace nix::clang_tidy { +using namespace clang::ast_matchers; +using namespace clang; + +void CharPtrCastCheck::registerMatchers(ast_matchers::MatchFinder *Finder) { + Finder->addMatcher( + traverse(clang::TK_IgnoreUnlessSpelledInSource, + cxxReinterpretCastExpr(allOf( + hasDestinationType(qualType(pointsTo(isAnyCharacter()))), + has(expr(hasType(qualType(pointsTo(isAnyCharacter())))))))) + .bind("reinterpret-cast-expr"), + this); +} + +void CharPtrCastCheck::check( + const ast_matchers::MatchFinder::MatchResult &Result) { + const auto ReinterpretCastExpr = + Result.Nodes.getNodeAs<CXXReinterpretCastExpr>("reinterpret-cast-expr"); + const auto ToTypeSpan = ReinterpretCastExpr->getAngleBrackets(); + const auto & SM = Result.Context->getSourceManager(); + + auto Diag = + diag(ReinterpretCastExpr->getExprLoc(), + "reinterpret_cast used for trivially safe character pointer cast"); + Diag << ReinterpretCastExpr->getSourceRange(); + + auto Inside = tooling::getText(*ReinterpretCastExpr->getSubExprAsWritten(), + *Result.Context); + + Diag << Inserter.createIncludeInsertion(SM.getFileID(ReinterpretCastExpr->getExprLoc()), "charptr-cast.hh"); + + llvm::Twine Replacement = + "charptr_cast" + + tooling::getText(CharSourceRange(ToTypeSpan, true), *Result.Context) + + "(" + Inside + ")"; + Diag << FixItHint::CreateReplacement(ReinterpretCastExpr->getSourceRange(), + Replacement.str()); +} + +} // namespace nix::clang_tidy diff --git a/subprojects/lix-clang-tidy/CharPtrCast.hh b/subprojects/lix-clang-tidy/CharPtrCast.hh new file mode 100644 index 000000000..66883d055 --- /dev/null +++ b/subprojects/lix-clang-tidy/CharPtrCast.hh @@ -0,0 +1,32 @@ +#pragma once +///@file + +#include <clang-tidy/ClangTidyCheck.h> +#include <clang-tidy/utils/IncludeInserter.h> +#include <clang/ASTMatchers/ASTMatchFinder.h> +#include <llvm/ADT/StringRef.h> + +namespace nix::clang_tidy { + +using namespace clang; +using namespace clang::tidy; + +class CharPtrCastCheck : public ClangTidyCheck { + tidy::utils::IncludeInserter Inserter{ + Options.getLocalOrGlobal("IncludeStyle", + tidy::utils::IncludeSorter::IS_Google), + false}; + +public: + CharPtrCastCheck(StringRef Name, ClangTidyContext *Context) + : ClangTidyCheck(Name, Context) {} + + void registerPPCallbacks(const SourceManager &, Preprocessor *PP, + Preprocessor *) override { + Inserter.registerPreprocessor(PP); + } + + void registerMatchers(ast_matchers::MatchFinder *Finder) override; + void check(const ast_matchers::MatchFinder::MatchResult &Result) override; +}; +} // namespace nix::clang_tidy diff --git a/subprojects/lix-clang-tidy/LixClangTidyChecks.cc b/subprojects/lix-clang-tidy/LixClangTidyChecks.cc index b3503dd3a..283e0e7c8 100644 --- a/subprojects/lix-clang-tidy/LixClangTidyChecks.cc +++ b/subprojects/lix-clang-tidy/LixClangTidyChecks.cc @@ -2,6 +2,7 @@ #include <clang-tidy/ClangTidyModuleRegistry.h> #include "FixIncludes.hh" #include "HasPrefixSuffix.hh" +#include "CharPtrCast.hh" namespace nix::clang_tidy { using namespace clang; @@ -12,6 +13,7 @@ class NixClangTidyChecks : public ClangTidyModule { void addCheckFactories(ClangTidyCheckFactories &CheckFactories) override { CheckFactories.registerCheck<HasPrefixSuffixCheck>("lix-hasprefixsuffix"); CheckFactories.registerCheck<FixIncludesCheck>("lix-fixincludes"); + CheckFactories.registerCheck<CharPtrCastCheck>("lix-charptrcast"); } }; diff --git a/subprojects/lix-clang-tidy/meson.build b/subprojects/lix-clang-tidy/meson.build index ef0226420..43648a1c8 100644 --- a/subprojects/lix-clang-tidy/meson.build +++ b/subprojects/lix-clang-tidy/meson.build @@ -5,9 +5,10 @@ project('lix-clang-tidy', ['cpp', 'c'], llvm = dependency('Clang', version: '>= 17', modules: ['libclang']) sources = files( + 'CharPtrCast.cc', + 'FixIncludes.cc', 'HasPrefixSuffix.cc', 'LixClangTidyChecks.cc', - 'FixIncludes.cc', ) lix_clang_tidy = shared_module('lix-clang-tidy', sources, |