aboutsummaryrefslogtreecommitdiff
path: root/subprojects/lix-clang-tidy/CharPtrCast.cc
diff options
context:
space:
mode:
authorJade Lovelace <lix@jade.fyi>2024-08-04 22:02:53 -0700
committerJade Lovelace <lix@jade.fyi>2024-08-08 14:53:17 -0700
commita5f0954c290157875b4dfb79edcf651f55742dc2 (patch)
tree16efd430c4c0828ee236eda636015e79e15bb965 /subprojects/lix-clang-tidy/CharPtrCast.cc
parenta85c4ce535c940bd2f48c34ab823fb3a8f5be0cc (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.cc45
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