[clang-tidy] Add bugprone-undefined-memory-manipulation check

Patch by: Reka Nikolett Kovacs

Differential Revision: https://reviews.llvm.org/D35051

llvm-svn: 308021
diff --git a/clang-tools-extra/clang-tidy/bugprone/BugproneTidyModule.cpp b/clang-tools-extra/clang-tidy/bugprone/BugproneTidyModule.cpp
index 65353a2..aa5f629 100644
--- a/clang-tools-extra/clang-tidy/bugprone/BugproneTidyModule.cpp
+++ b/clang-tools-extra/clang-tidy/bugprone/BugproneTidyModule.cpp
@@ -11,6 +11,7 @@
 #include "../ClangTidyModule.h"
 #include "../ClangTidyModuleRegistry.h"
 #include "SuspiciousMemsetUsageCheck.h"
+#include "UndefinedMemoryManipulationCheck.h"
 
 namespace clang {
 namespace tidy {
@@ -21,6 +22,8 @@
   void addCheckFactories(ClangTidyCheckFactories &CheckFactories) override {
     CheckFactories.registerCheck<SuspiciousMemsetUsageCheck>(
         "bugprone-suspicious-memset-usage");
+    CheckFactories.registerCheck<UndefinedMemoryManipulationCheck>(
+        "bugprone-undefined-memory-manipulation");
   }
 };
 
diff --git a/clang-tools-extra/clang-tidy/bugprone/CMakeLists.txt b/clang-tools-extra/clang-tidy/bugprone/CMakeLists.txt
index 1f0ec6e..9ec45c5 100644
--- a/clang-tools-extra/clang-tidy/bugprone/CMakeLists.txt
+++ b/clang-tools-extra/clang-tidy/bugprone/CMakeLists.txt
@@ -3,6 +3,7 @@
 add_clang_library(clangTidyBugproneModule
   BugproneTidyModule.cpp
   SuspiciousMemsetUsageCheck.cpp
+  UndefinedMemoryManipulationCheck.cpp
 
   LINK_LIBS
   clangAnalysis
diff --git a/clang-tools-extra/clang-tidy/bugprone/UndefinedMemoryManipulationCheck.cpp b/clang-tools-extra/clang-tidy/bugprone/UndefinedMemoryManipulationCheck.cpp
new file mode 100644
index 0000000..cbc1f34
--- /dev/null
+++ b/clang-tools-extra/clang-tidy/bugprone/UndefinedMemoryManipulationCheck.cpp
@@ -0,0 +1,61 @@
+//===--- UndefinedMemoryManipulationCheck.cpp - clang-tidy-----------------===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "UndefinedMemoryManipulationCheck.h"
+#include "clang/AST/ASTContext.h"
+#include "clang/ASTMatchers/ASTMatchFinder.h"
+
+using namespace clang::ast_matchers;
+
+namespace clang {
+namespace tidy {
+namespace bugprone {
+
+namespace {
+AST_MATCHER(CXXRecordDecl, isNotTriviallyCopyable) {
+  return !Node.isTriviallyCopyable();
+}
+} // namespace
+
+void UndefinedMemoryManipulationCheck::registerMatchers(MatchFinder *Finder) {
+  const auto NotTriviallyCopyableObject =
+      hasType(pointsTo(cxxRecordDecl(isNotTriviallyCopyable())));
+
+  // Check whether destination object is not TriviallyCopyable.
+  // Applicable to all three memory manipulation functions.
+  Finder->addMatcher(callExpr(callee(functionDecl(hasAnyName(
+                                  "::memset", "::memcpy", "::memmove"))),
+                              hasArgument(0, NotTriviallyCopyableObject))
+                         .bind("dest"),
+                     this);
+
+  // Check whether source object is not TriviallyCopyable.
+  // Only applicable to memcpy() and memmove().
+  Finder->addMatcher(
+      callExpr(callee(functionDecl(hasAnyName("::memcpy", "::memmove"))),
+               hasArgument(1, NotTriviallyCopyableObject))
+          .bind("src"),
+      this);
+}
+
+void UndefinedMemoryManipulationCheck::check(
+    const MatchFinder::MatchResult &Result) {
+  if (const auto *Destination = Result.Nodes.getNodeAs<CallExpr>("dest")) {
+    diag(Destination->getLocStart(), "undefined behavior, destination "
+                                     "object is not TriviallyCopyable");
+  }
+  if (const auto *Source = Result.Nodes.getNodeAs<CallExpr>("src")) {
+    diag(Source->getLocStart(), "undefined behavior, source object is not "
+                                "TriviallyCopyable");
+  }
+}
+
+} // namespace bugprone
+} // namespace tidy
+} // namespace clang
diff --git a/clang-tools-extra/clang-tidy/bugprone/UndefinedMemoryManipulationCheck.h b/clang-tools-extra/clang-tidy/bugprone/UndefinedMemoryManipulationCheck.h
new file mode 100644
index 0000000..64d6c56
--- /dev/null
+++ b/clang-tools-extra/clang-tidy/bugprone/UndefinedMemoryManipulationCheck.h
@@ -0,0 +1,37 @@
+//===--- UndefinedMemoryManipulationCheck.h - clang-tidy---------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_BUGPRONE_UNDEFINED_MEMORY_MANIPULATION_H
+#define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_BUGPRONE_UNDEFINED_MEMORY_MANIPULATION_H
+
+#include "../ClangTidy.h"
+
+namespace clang {
+namespace tidy {
+namespace bugprone {
+
+/// Finds calls of memory manipulation functions ``memset()``, ``memcpy()`` and
+/// ``memmove()`` on not TriviallyCopyable objects resulting in undefined
+/// behavior.
+///
+/// For the user-facing documentation see:
+/// http://clang.llvm.org/extra/clang-tidy/checks/bugprone-undefined-memory-manipulation.html
+class UndefinedMemoryManipulationCheck : public ClangTidyCheck {
+public:
+  UndefinedMemoryManipulationCheck(StringRef Name, ClangTidyContext *Context)
+      : ClangTidyCheck(Name, Context) {}
+  void registerMatchers(ast_matchers::MatchFinder *Finder) override;
+  void check(const ast_matchers::MatchFinder::MatchResult &Result) override;
+};
+
+} // namespace bugprone
+} // namespace tidy
+} // namespace clang
+
+#endif // LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_BUGPRONE_UNDEFINED_MEMORY_MANIPULATION_H