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 <congcongcai0...@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 <congcongcai0...@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)); _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits