xref: /llvm-project/clang-tools-extra/clang-tidy/bugprone/BitwisePointerCastCheck.cpp (revision fb0ef6b66e3c7e91481568c15ed67c047dab84e1)
1*fb0ef6b6SCarlos Galvez //===--- BitwisePointerCastCheck.cpp - clang-tidy -------------------------===//
2*fb0ef6b6SCarlos Galvez //
3*fb0ef6b6SCarlos Galvez // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4*fb0ef6b6SCarlos Galvez // See https://llvm.org/LICENSE.txt for license information.
5*fb0ef6b6SCarlos Galvez // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6*fb0ef6b6SCarlos Galvez //
7*fb0ef6b6SCarlos Galvez //===----------------------------------------------------------------------===//
8*fb0ef6b6SCarlos Galvez 
9*fb0ef6b6SCarlos Galvez #include "BitwisePointerCastCheck.h"
10*fb0ef6b6SCarlos Galvez #include "clang/ASTMatchers/ASTMatchFinder.h"
11*fb0ef6b6SCarlos Galvez 
12*fb0ef6b6SCarlos Galvez using namespace clang::ast_matchers;
13*fb0ef6b6SCarlos Galvez 
14*fb0ef6b6SCarlos Galvez namespace clang::tidy::bugprone {
15*fb0ef6b6SCarlos Galvez 
16*fb0ef6b6SCarlos Galvez void BitwisePointerCastCheck::registerMatchers(MatchFinder *Finder) {
17*fb0ef6b6SCarlos Galvez   if (getLangOpts().CPlusPlus20) {
18*fb0ef6b6SCarlos Galvez     auto IsPointerType = refersToType(qualType(isAnyPointer()));
19*fb0ef6b6SCarlos Galvez     Finder->addMatcher(callExpr(hasDeclaration(functionDecl(allOf(
20*fb0ef6b6SCarlos Galvez                                     hasName("::std::bit_cast"),
21*fb0ef6b6SCarlos Galvez                                     hasTemplateArgument(0, IsPointerType),
22*fb0ef6b6SCarlos Galvez                                     hasTemplateArgument(1, IsPointerType)))))
23*fb0ef6b6SCarlos Galvez                            .bind("bit_cast"),
24*fb0ef6b6SCarlos Galvez                        this);
25*fb0ef6b6SCarlos Galvez   }
26*fb0ef6b6SCarlos Galvez 
27*fb0ef6b6SCarlos Galvez   auto IsDoublePointerType =
28*fb0ef6b6SCarlos Galvez       hasType(qualType(pointsTo(qualType(isAnyPointer()))));
29*fb0ef6b6SCarlos Galvez   Finder->addMatcher(callExpr(hasArgument(0, IsDoublePointerType),
30*fb0ef6b6SCarlos Galvez                               hasArgument(1, IsDoublePointerType),
31*fb0ef6b6SCarlos Galvez                               hasDeclaration(functionDecl(hasName("::memcpy"))))
32*fb0ef6b6SCarlos Galvez                          .bind("memcpy"),
33*fb0ef6b6SCarlos Galvez                      this);
34*fb0ef6b6SCarlos Galvez }
35*fb0ef6b6SCarlos Galvez 
36*fb0ef6b6SCarlos Galvez void BitwisePointerCastCheck::check(const MatchFinder::MatchResult &Result) {
37*fb0ef6b6SCarlos Galvez   if (const auto *Call = Result.Nodes.getNodeAs<CallExpr>("bit_cast"))
38*fb0ef6b6SCarlos Galvez     diag(Call->getBeginLoc(),
39*fb0ef6b6SCarlos Galvez          "do not use 'std::bit_cast' to cast between pointers")
40*fb0ef6b6SCarlos Galvez         << Call->getSourceRange();
41*fb0ef6b6SCarlos Galvez   else if (const auto *Call = Result.Nodes.getNodeAs<CallExpr>("memcpy"))
42*fb0ef6b6SCarlos Galvez     diag(Call->getBeginLoc(), "do not use 'memcpy' to cast between pointers")
43*fb0ef6b6SCarlos Galvez         << Call->getSourceRange();
44*fb0ef6b6SCarlos Galvez }
45*fb0ef6b6SCarlos Galvez 
46*fb0ef6b6SCarlos Galvez } // namespace clang::tidy::bugprone
47