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/CharPtrCast.cc | |
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/CharPtrCast.cc')
-rw-r--r-- | subprojects/lix-clang-tidy/CharPtrCast.cc | 45 |
1 files changed, 45 insertions, 0 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 |