1 //===--- UndefinedMemoryManipulationCheck.cpp - clang-tidy-----------------===//
2 //
3 //                     The LLVM Compiler Infrastructure
4 //
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
7 //
8 //===----------------------------------------------------------------------===//
9 
10 #include "UndefinedMemoryManipulationCheck.h"
11 #include "clang/AST/ASTContext.h"
12 #include "clang/ASTMatchers/ASTMatchFinder.h"
13 
14 using namespace clang::ast_matchers;
15 
16 namespace clang {
17 namespace tidy {
18 namespace bugprone {
19 
20 namespace {
21 AST_MATCHER(CXXRecordDecl, isNotTriviallyCopyable) {
22   // For incomplete types, assume they are TriviallyCopyable.
23   return Node.hasDefinition() ? !Node.isTriviallyCopyable() : false;
24 }
25 } // namespace
26 
27 void UndefinedMemoryManipulationCheck::registerMatchers(MatchFinder *Finder) {
28   const auto NotTriviallyCopyableObject =
29       hasType(pointsTo(cxxRecordDecl(isNotTriviallyCopyable())));
30 
31   // Check whether destination object is not TriviallyCopyable.
32   // Applicable to all three memory manipulation functions.
33   Finder->addMatcher(callExpr(callee(functionDecl(hasAnyName(
34                                   "::memset", "::memcpy", "::memmove"))),
35                               hasArgument(0, NotTriviallyCopyableObject))
36                          .bind("dest"),
37                      this);
38 
39   // Check whether source object is not TriviallyCopyable.
40   // Only applicable to memcpy() and memmove().
41   Finder->addMatcher(
42       callExpr(callee(functionDecl(hasAnyName("::memcpy", "::memmove"))),
43                hasArgument(1, NotTriviallyCopyableObject))
44           .bind("src"),
45       this);
46 }
47 
48 void UndefinedMemoryManipulationCheck::check(
49     const MatchFinder::MatchResult &Result) {
50   if (const auto *Destination = Result.Nodes.getNodeAs<CallExpr>("dest")) {
51     diag(Destination->getLocStart(), "undefined behavior, destination "
52                                      "object is not TriviallyCopyable");
53   }
54   if (const auto *Source = Result.Nodes.getNodeAs<CallExpr>("src")) {
55     diag(Source->getLocStart(), "undefined behavior, source object is not "
56                                 "TriviallyCopyable");
57   }
58 }
59 
60 } // namespace bugprone
61 } // namespace tidy
62 } // namespace clang
63