[clang-tools-extra] [clang-tidy]Add new check bugprone-casting-through-void (PR #69465)
Congcong Cai via cfe-commits
cfe-commits at lists.llvm.org
Wed Oct 18 07:44:22 PDT 2023
https://github.com/HerrCai0907 updated https://github.com/llvm/llvm-project/pull/69465
>From 627f68e57b2526fb72285ef4831fc3c02a6ee6d0 Mon Sep 17 00:00:00 2001
From: Congcong Cai <congcongcai0907 at 163.com>
Date: Wed, 18 Oct 2023 08:47:02 +0800
Subject: [PATCH 1/2] [clang-tidy]Add new check bugprone-casting-through-void
Fixes: #68532
---
.../bugprone/BugproneTidyModule.cpp | 3 ++
.../clang-tidy/bugprone/CMakeLists.txt | 1 +
.../bugprone/CastingThroughVoidCheck.cpp | 46 +++++++++++++++++++
.../bugprone/CastingThroughVoidCheck.h | 37 +++++++++++++++
clang-tools-extra/docs/ReleaseNotes.rst | 6 +++
.../checks/bugprone/casting-through-void.rst | 11 +++++
.../docs/clang-tidy/checks/list.rst | 1 +
.../bugprone/casting-through-void.cpp | 18 ++++++++
8 files changed, 123 insertions(+)
create mode 100644 clang-tools-extra/clang-tidy/bugprone/CastingThroughVoidCheck.cpp
create mode 100644 clang-tools-extra/clang-tidy/bugprone/CastingThroughVoidCheck.h
create mode 100644 clang-tools-extra/docs/clang-tidy/checks/bugprone/casting-through-void.rst
create mode 100644 clang-tools-extra/test/clang-tidy/checkers/bugprone/casting-through-void.cpp
diff --git a/clang-tools-extra/clang-tidy/bugprone/BugproneTidyModule.cpp b/clang-tools-extra/clang-tidy/bugprone/BugproneTidyModule.cpp
index 543c522899d7a52..7a910037368c832 100644
--- a/clang-tools-extra/clang-tidy/bugprone/BugproneTidyModule.cpp
+++ b/clang-tools-extra/clang-tidy/bugprone/BugproneTidyModule.cpp
@@ -16,6 +16,7 @@
#include "BadSignalToKillThreadCheck.h"
#include "BoolPointerImplicitConversionCheck.h"
#include "BranchCloneCheck.h"
+#include "CastingThroughVoidCheck.h"
#include "ComparePointerToMemberVirtualFunctionCheck.h"
#include "CopyConstructorInitCheck.h"
#include "DanglingHandleCheck.h"
@@ -104,6 +105,8 @@ class BugproneModule : public ClangTidyModule {
CheckFactories.registerCheck<BoolPointerImplicitConversionCheck>(
"bugprone-bool-pointer-implicit-conversion");
CheckFactories.registerCheck<BranchCloneCheck>("bugprone-branch-clone");
+ CheckFactories.registerCheck<CastingThroughVoidCheck>(
+ "bugprone-casting-through-void");
CheckFactories.registerCheck<ComparePointerToMemberVirtualFunctionCheck>(
"bugprone-compare-pointer-to-member-virtual-function");
CheckFactories.registerCheck<CopyConstructorInitCheck>(
diff --git a/clang-tools-extra/clang-tidy/bugprone/CMakeLists.txt b/clang-tools-extra/clang-tidy/bugprone/CMakeLists.txt
index 0df9e439b715e5a..d443fd8d1452f16 100644
--- a/clang-tools-extra/clang-tidy/bugprone/CMakeLists.txt
+++ b/clang-tools-extra/clang-tidy/bugprone/CMakeLists.txt
@@ -11,6 +11,7 @@ add_clang_library(clangTidyBugproneModule
BoolPointerImplicitConversionCheck.cpp
BranchCloneCheck.cpp
BugproneTidyModule.cpp
+ CastingThroughVoidCheck.cpp
ComparePointerToMemberVirtualFunctionCheck.cpp
CopyConstructorInitCheck.cpp
DanglingHandleCheck.cpp
diff --git a/clang-tools-extra/clang-tidy/bugprone/CastingThroughVoidCheck.cpp b/clang-tools-extra/clang-tidy/bugprone/CastingThroughVoidCheck.cpp
new file mode 100644
index 000000000000000..7b9cd7dd51fc47f
--- /dev/null
+++ b/clang-tools-extra/clang-tidy/bugprone/CastingThroughVoidCheck.cpp
@@ -0,0 +1,46 @@
+//===--- CastingThroughVoidCheck.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 "CastingThroughVoidCheck.h"
+#include "clang/AST/ASTContext.h"
+#include "clang/AST/Expr.h"
+#include "clang/AST/Type.h"
+#include "clang/ASTMatchers/ASTMatchFinder.h"
+#include "clang/ASTMatchers/ASTMatchers.h"
+#include "llvm/ADT/StringSet.h"
+
+using namespace clang::ast_matchers;
+
+namespace clang::tidy::bugprone {
+
+void CastingThroughVoidCheck::registerMatchers(MatchFinder *Finder) {
+ Finder->addMatcher(
+ explicitCastExpr(
+ hasDestinationType(qualType(pointsTo(qualType(unless(voidType()))))
+ .bind("target_type")),
+ hasSourceExpression(
+ explicitCastExpr(hasSourceExpression(expr(
+ hasType(qualType().bind("source_type")))),
+ hasDestinationType(pointsTo(voidType())))))
+ .bind("cast"),
+ this);
+}
+
+void CastingThroughVoidCheck::check(const MatchFinder::MatchResult &Result) {
+ ASTContext *Context = Result.Context;
+ const auto *CE = Result.Nodes.getNodeAs<ExplicitCastExpr>("cast");
+ const auto *TT = Result.Nodes.getNodeAs<QualType>("target_type");
+ const auto *ST = Result.Nodes.getNodeAs<QualType>("source_type");
+ if (Context->hasSameType(*TT, *ST))
+ return;
+ diag(CE->getSourceRange().getBegin(), "do not cast %0 to %1 through void *",
+ DiagnosticIDs::Level::Warning)
+ << ST->getAsString() << TT->getAsString();
+}
+
+} // namespace clang::tidy::bugprone
diff --git a/clang-tools-extra/clang-tidy/bugprone/CastingThroughVoidCheck.h b/clang-tools-extra/clang-tidy/bugprone/CastingThroughVoidCheck.h
new file mode 100644
index 000000000000000..542b1c50dc782e7
--- /dev/null
+++ b/clang-tools-extra/clang-tidy/bugprone/CastingThroughVoidCheck.h
@@ -0,0 +1,37 @@
+//===--- CastingThroughVoidCheck.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_BUGPRONE_CASTINGTHROUGHVOIDCHECK_H
+#define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_BUGPRONE_CASTINGTHROUGHVOIDCHECK_H
+
+#include "../ClangTidyCheck.h"
+
+namespace clang::tidy::bugprone {
+
+/// A check detects usage of ``static_cast`` pointer to the other pointer
+/// throght
+/// ``static_cast`` to ``void *`` in C++ code.
+/// For the user-facing documentation see:
+/// http://clang.llvm.org/extra/clang-tidy/checks/bugprone/casting-through-void.html
+class CastingThroughVoidCheck : public ClangTidyCheck {
+public:
+ CastingThroughVoidCheck(StringRef Name, ClangTidyContext *Context)
+ : ClangTidyCheck(Name, Context) {}
+ 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;
+ }
+ std::optional<TraversalKind> getCheckTraversalKind() const override {
+ return TK_IgnoreUnlessSpelledInSource;
+ }
+};
+
+} // namespace clang::tidy::bugprone
+
+#endif // LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_BUGPRONE_CASTINGTHROUGHVOIDCHECK_H
diff --git a/clang-tools-extra/docs/ReleaseNotes.rst b/clang-tools-extra/docs/ReleaseNotes.rst
index af164d0462d52c1..3ceb844a036240c 100644
--- a/clang-tools-extra/docs/ReleaseNotes.rst
+++ b/clang-tools-extra/docs/ReleaseNotes.rst
@@ -125,6 +125,12 @@ Improvements to clang-tidy
New checks
^^^^^^^^^^
+- New :doc:`bugprone-casting-through-void
+ <clang-tidy/checks/bugprone/casting-through-void>` check.
+
+ Detects usage of ``static_cast`` pointer to the other pointer throght
+ ``static_cast`` to ``void *`` in C++ code.
+
- New :doc:`bugprone-compare-pointer-to-member-virtual-function
<clang-tidy/checks/bugprone/compare-pointer-to-member-virtual-function>` check.
diff --git a/clang-tools-extra/docs/clang-tidy/checks/bugprone/casting-through-void.rst b/clang-tools-extra/docs/clang-tidy/checks/bugprone/casting-through-void.rst
new file mode 100644
index 000000000000000..4a20d8eb9b41c8b
--- /dev/null
+++ b/clang-tools-extra/docs/clang-tidy/checks/bugprone/casting-through-void.rst
@@ -0,0 +1,11 @@
+.. title:: clang-tidy - bugprone-casting-through-void
+
+bugprone-casting-through-void
+=============================
+
+A check detects usage of ``static_cast`` pointer to the other pointer throght
+``static_cast`` to ``void *`` in C++ code.
+
+Use of these casts can violate type safety and cause the program to access a
+variable that is actually of type ``X`` to be accessed as if it were of an
+unrelated type ``Z``.
diff --git a/clang-tools-extra/docs/clang-tidy/checks/list.rst b/clang-tools-extra/docs/clang-tidy/checks/list.rst
index 2125ebd7a213c15..fa95bffdc45f9cb 100644
--- a/clang-tools-extra/docs/clang-tidy/checks/list.rst
+++ b/clang-tools-extra/docs/clang-tidy/checks/list.rst
@@ -82,6 +82,7 @@ Clang-Tidy Checks
:doc:`bugprone-bad-signal-to-kill-thread <bugprone/bad-signal-to-kill-thread>`,
:doc:`bugprone-bool-pointer-implicit-conversion <bugprone/bool-pointer-implicit-conversion>`, "Yes"
:doc:`bugprone-branch-clone <bugprone/branch-clone>`,
+ :doc:`bugprone-casting-through-void <bugprone/casting-through-void>`, "Yes"
:doc:`bugprone-compare-pointer-to-member-virtual-function <bugprone/compare-pointer-to-member-virtual-function>`,
:doc:`bugprone-copy-constructor-init <bugprone/copy-constructor-init>`, "Yes"
:doc:`bugprone-dangling-handle <bugprone/dangling-handle>`,
diff --git a/clang-tools-extra/test/clang-tidy/checkers/bugprone/casting-through-void.cpp b/clang-tools-extra/test/clang-tidy/checkers/bugprone/casting-through-void.cpp
new file mode 100644
index 000000000000000..f9e8c57201ee802
--- /dev/null
+++ b/clang-tools-extra/test/clang-tidy/checkers/bugprone/casting-through-void.cpp
@@ -0,0 +1,18 @@
+// RUN: %check_clang_tidy %s bugprone-casting-through-void %t
+
+using T = void*;
+
+void test() {
+ int i = 100;
+ double d = 100;
+
+ static_cast<int *>(static_cast<void *>(&d));
+ // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: do not cast double * to int * through void * [bugprone-casting-through-void]
+
+ static_cast<int *>(static_cast<T>(&d));
+ // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: do not cast double * to int * through void * [bugprone-casting-through-void]
+
+ static_cast<int *>(static_cast<void *>(&i));
+
+ static_cast<void *>(static_cast<void *>(&i));
+}
>From 0dc68b2bd3dd8f790ad36288f8a70a3423f01bd7 Mon Sep 17 00:00:00 2001
From: Congcong Cai <congcongcai0907 at 163.com>
Date: Wed, 18 Oct 2023 22:43:03 +0800
Subject: [PATCH 2/2] fix
---
.../bugprone/CastingThroughVoidCheck.cpp | 18 ++++++++----------
.../checkers/bugprone/casting-through-void.cpp | 4 ++--
2 files changed, 10 insertions(+), 12 deletions(-)
diff --git a/clang-tools-extra/clang-tidy/bugprone/CastingThroughVoidCheck.cpp b/clang-tools-extra/clang-tidy/bugprone/CastingThroughVoidCheck.cpp
index 7b9cd7dd51fc47f..0bd400bd5257c86 100644
--- a/clang-tools-extra/clang-tidy/bugprone/CastingThroughVoidCheck.cpp
+++ b/clang-tools-extra/clang-tidy/bugprone/CastingThroughVoidCheck.cpp
@@ -26,21 +26,19 @@ void CastingThroughVoidCheck::registerMatchers(MatchFinder *Finder) {
hasSourceExpression(
explicitCastExpr(hasSourceExpression(expr(
hasType(qualType().bind("source_type")))),
- hasDestinationType(pointsTo(voidType())))))
- .bind("cast"),
+ hasDestinationType(pointsTo(voidType())))
+ .bind("cast"))),
this);
}
void CastingThroughVoidCheck::check(const MatchFinder::MatchResult &Result) {
- ASTContext *Context = Result.Context;
- const auto *CE = Result.Nodes.getNodeAs<ExplicitCastExpr>("cast");
- const auto *TT = Result.Nodes.getNodeAs<QualType>("target_type");
- const auto *ST = Result.Nodes.getNodeAs<QualType>("source_type");
- if (Context->hasSameType(*TT, *ST))
+ const auto TT = *Result.Nodes.getNodeAs<QualType>("target_type");
+ const auto ST = *Result.Nodes.getNodeAs<QualType>("source_type");
+ if (Result.Context->hasSameType(TT, ST))
return;
- diag(CE->getSourceRange().getBegin(), "do not cast %0 to %1 through void *",
- DiagnosticIDs::Level::Warning)
- << ST->getAsString() << TT->getAsString();
+ const auto *CE = Result.Nodes.getNodeAs<ExplicitCastExpr>("cast");
+ diag(CE->getSourceRange().getBegin(), "do not cast %0 to %1 through void*")
+ << ST << TT;
}
} // namespace clang::tidy::bugprone
diff --git a/clang-tools-extra/test/clang-tidy/checkers/bugprone/casting-through-void.cpp b/clang-tools-extra/test/clang-tidy/checkers/bugprone/casting-through-void.cpp
index f9e8c57201ee802..ee553e0a74246a0 100644
--- a/clang-tools-extra/test/clang-tidy/checkers/bugprone/casting-through-void.cpp
+++ b/clang-tools-extra/test/clang-tidy/checkers/bugprone/casting-through-void.cpp
@@ -7,10 +7,10 @@ void test() {
double d = 100;
static_cast<int *>(static_cast<void *>(&d));
- // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: do not cast double * to int * through void * [bugprone-casting-through-void]
+ // CHECK-MESSAGES: :[[@LINE-1]]:22: warning: do not cast 'double *' to 'int *' through void* [bugprone-casting-through-void]
static_cast<int *>(static_cast<T>(&d));
- // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: do not cast double * to int * through void * [bugprone-casting-through-void]
+ // CHECK-MESSAGES: :[[@LINE-1]]:22: warning: do not cast 'double *' to 'int *' through void* [bugprone-casting-through-void]
static_cast<int *>(static_cast<void *>(&i));
More information about the cfe-commits
mailing list