JDevlieghere updated this revision to Diff 65246.
JDevlieghere added a comment.

- Added new check to release notes
- Renamed to modernize-use-copy
- Addressed comments from Prazek


Repository:
  rL LLVM

https://reviews.llvm.org/D22725

Files:
  clang-tidy/modernize/CMakeLists.txt
  clang-tidy/modernize/ModernizeTidyModule.cpp
  clang-tidy/modernize/UseCopyCheck.cpp
  clang-tidy/modernize/UseCopyCheck.h
  docs/ReleaseNotes.rst
  docs/clang-tidy/checks/list.rst
  docs/clang-tidy/checks/modernize-use-copy.rst
  test/clang-tidy/modernize-use-copy.cpp

Index: test/clang-tidy/modernize-use-copy.cpp
===================================================================
--- /dev/null
+++ test/clang-tidy/modernize-use-copy.cpp
@@ -0,0 +1,38 @@
+// RUN: %check_clang_tidy %s modernize-use-copy %t
+
+// CHECK-FIXES: #include <algorithm>
+
+namespace std {
+typedef unsigned int size_t;
+void *memcpy(void *dest, const void *src, std::size_t count);
+
+template <class InputIt, class OutputIt>
+OutputIt copy(InputIt first, InputIt last, OutputIt d_first);
+}
+
+void f() {
+  char foo[] = "foo", bar[3], baz[3];
+  std::memcpy(bar, foo, sizeof bar);
+  // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: Use std::copy instead of memcpy
+  // [modernize-use-copy]
+  // CHECK-FIXES: std::copy(foo, (foo) + (sizeof bar), bar);
+
+  bool b = false;
+  std::memcpy(baz, b ? foo : bar, 3);
+  // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: Use std::copy instead of memcpy
+  // [modernize-use-copy]
+  // CHECK-FIXES: std::copy(b ? foo : bar, (b ? foo : bar) + (3), baz);
+
+  std::memcpy(bar, foo, sizeof bar);
+  // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: Use std::copy instead of memcpy
+  // [modernize-use-copy]
+  // CHECK-FIXES: std::copy(foo, (foo) + (sizeof bar), bar);
+
+  std::copy(foo, foo + sizeof bar, bar);
+}
+
+#define memcpy(dest, src, len) std::memcpy((dest), (src), (len))
+void g() {
+  char foo[] = "foo", bar[3];
+  memcpy(bar, foo, sizeof bar);
+}
Index: docs/clang-tidy/checks/modernize-use-copy.rst
===================================================================
--- /dev/null
+++ docs/clang-tidy/checks/modernize-use-copy.rst
@@ -0,0 +1,32 @@
+.. title:: clang-tidy - modernize-use-copy
+
+modernize-use-copy
+==================
+
+Replaces ``memcpy`` with ``std::copy``. This makes the code cleaner and allows
+the compiler to decide on the preferred implementation.
+
+Example:
+
+.. code:: c++
+
+    std::memcpy(dest, source, sizeof dest);
+
+    // transforms to:
+
+    std::copy(source, (source) + (sizeof dest), dest);
+
+Parenthesis are added devensively to preclude the summation from taking
+precedence over operators used in the arguments of ``memcpy``.
+
+.. code:: c++
+
+    std::memcpy(baz, b ? foo : bar, 3);
+
+    // transforms to:
+
+    std::copy(b ? foo : bar, (b ? foo : bar) + (3), baz);
+
+    // but without the parenthesis it would have become the equivalent of:
+
+    std::copy(b ? foo : bar, b ? foo : (bar + 3), baz);
Index: docs/clang-tidy/checks/list.rst
===================================================================
--- docs/clang-tidy/checks/list.rst
+++ docs/clang-tidy/checks/list.rst
@@ -29,6 +29,7 @@
    cppcoreguidelines-pro-type-static-cast-downcast
    cppcoreguidelines-pro-type-union-access
    cppcoreguidelines-pro-type-vararg
+   cppcoreguidelines-slicing
    google-build-explicit-make-pair
    google-build-namespaces
    google-build-using-namespace
@@ -103,6 +104,7 @@
    modernize-shrink-to-fit
    modernize-use-auto
    modernize-use-bool-literals
+   modernize-use-copy
    modernize-use-default
    modernize-use-emplace
    modernize-use-nullptr
Index: docs/ReleaseNotes.rst
===================================================================
--- docs/ReleaseNotes.rst
+++ docs/ReleaseNotes.rst
@@ -64,6 +64,11 @@
 
   Flags slicing of member variables or vtable.
 
+- New `modernize-replace-memcpy
+  <http://clang.llvm.org/extra/clang-tidy/checks/modernize-replace-memcpy.html>`_ check
+
+  Replaces calls to memcpy with std::copy.
+
 Improvements to include-fixer
 -----------------------------
 
Index: clang-tidy/modernize/UseCopyCheck.h
===================================================================
--- /dev/null
+++ clang-tidy/modernize/UseCopyCheck.h
@@ -0,0 +1,44 @@
+//===--- UseCopyCheck.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_MODERNIZE_USE_COPY_H
+#define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_MODERNIZE_USE_COPY_H
+
+#include "../ClangTidy.h"
+#include "../utils/IncludeInserter.h"
+
+namespace clang {
+namespace tidy {
+namespace modernize {
+
+/// Replaces memcpy with std::copy
+///
+/// For the user-facing documentation see:
+/// http://clang.llvm.org/extra/clang-tidy/checks/modernize-use-copy.html
+class UseCopyCheck : public ClangTidyCheck {
+public:
+  UseCopyCheck(StringRef Name, ClangTidyContext *Context)
+      : ClangTidyCheck(Name, Context),
+        IncludeStyle(utils::IncludeSorter::parseIncludeStyle(
+            Options.get("IncludeStyle", "llvm"))) {}
+
+  void registerMatchers(ast_matchers::MatchFinder *Finder) override;
+  void registerPPCallbacks(CompilerInstance &Compiler) override;
+  void check(const ast_matchers::MatchFinder::MatchResult &Result) override;
+
+private:
+  std::unique_ptr<utils::IncludeInserter> Inserter;
+  const utils::IncludeSorter::IncludeStyle IncludeStyle;
+};
+
+} // namespace modernize
+} // namespace tidy
+} // namespace clang
+
+#endif // LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_MODERNIZE_USE_COPY_H
Index: clang-tidy/modernize/UseCopyCheck.cpp
===================================================================
--- /dev/null
+++ clang-tidy/modernize/UseCopyCheck.cpp
@@ -0,0 +1,87 @@
+//===--- UseCopyCheck.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 "UseCopyCheck.h"
+#include "clang/AST/ASTContext.h"
+#include "clang/ASTMatchers/ASTMatchFinder.h"
+#include "clang/Frontend/CompilerInstance.h"
+#include "clang/Lex/Lexer.h"
+#include "clang/Lex/Preprocessor.h"
+
+#include <string>
+
+using namespace clang::ast_matchers;
+
+namespace clang {
+namespace tidy {
+namespace modernize {
+
+static StringRef getText(const Expr *Expression, const SourceManager &SM,
+                         const LangOptions &LangOpts) {
+  return Lexer::getSourceText(
+      CharSourceRange::getTokenRange(Expression->getSourceRange()), SM,
+      LangOpts);
+}
+
+void UseCopyCheck::registerMatchers(MatchFinder *Finder) {
+  // Only register the matchers for C++
+  if (!getLangOpts().CPlusPlus)
+    return;
+
+  // Match calls to memcpy with 3 arguments
+  Finder->addMatcher(callExpr(allOf(callee(functionDecl(hasName("memcpy"))),
+                                    argumentCountIs(3)))
+                         .bind("expr"),
+                     this);
+}
+
+void UseCopyCheck::registerPPCallbacks(CompilerInstance &Compiler) {
+  // Only register the preprocessor callbacks for C++; the functionality
+  // currently does not provide any benefit to other languages, despite being
+  // benign.
+  if (getLangOpts().CPlusPlus) {
+    Inserter.reset(new utils::IncludeInserter(
+        Compiler.getSourceManager(), Compiler.getLangOpts(), IncludeStyle));
+    Compiler.getPreprocessor().addPPCallbacks(Inserter->CreatePPCallbacks());
+  }
+}
+
+void UseCopyCheck::check(const MatchFinder::MatchResult &Result) {
+  const auto *MatchedExpr = Result.Nodes.getNodeAs<CallExpr>("expr");
+  const auto Loc = MatchedExpr->getExprLoc();
+
+  // Don't make replacements in macro
+  if (Loc.isMacroID())
+    return;
+
+  const auto &SM = *Result.SourceManager;
+  const auto &LangOptions = Result.Context->getLangOpts();
+
+  StringRef Destination = getText(MatchedExpr->getArg(0), SM, LangOptions);
+  StringRef Source = getText(MatchedExpr->getArg(1), SM, LangOptions);
+  StringRef Count = getText(MatchedExpr->getArg(2), SM, LangOptions);
+
+  const std::string Insertion = "std::copy(" + Source.str() + ", (" +
+                                Source.str() + ") + (" + Count.str() + "), " +
+                                Destination.str() + ")";
+
+  auto Diag = diag(Loc, "Use std::copy instead of memcpy");
+  Diag << FixItHint::CreateReplacement(MatchedExpr->getSourceRange(),
+                                       Insertion);
+
+  if (auto IncludeFixit = Inserter->CreateIncludeInsertion(
+          Result.SourceManager->getFileID(Loc), "algorithm",
+          /*IsAngled=*/true)) {
+    Diag << *IncludeFixit;
+  }
+}
+
+} // namespace modernize
+} // namespace tidy
+} // namespace clang
Index: clang-tidy/modernize/ModernizeTidyModule.cpp
===================================================================
--- clang-tidy/modernize/ModernizeTidyModule.cpp
+++ clang-tidy/modernize/ModernizeTidyModule.cpp
@@ -22,6 +22,7 @@
 #include "ShrinkToFitCheck.h"
 #include "UseAutoCheck.h"
 #include "UseBoolLiteralsCheck.h"
+#include "UseCopyCheck.h"
 #include "UseDefaultCheck.h"
 #include "UseEmplaceCheck.h"
 #include "UseNullptrCheck.h"
@@ -55,6 +56,8 @@
     CheckFactories.registerCheck<UseAutoCheck>("modernize-use-auto");
     CheckFactories.registerCheck<UseBoolLiteralsCheck>(
         "modernize-use-bool-literals");
+    CheckFactories.registerCheck<UseCopyCheck>(
+        "modernize-use-copy");
     CheckFactories.registerCheck<UseDefaultCheck>("modernize-use-default");
     CheckFactories.registerCheck<UseEmplaceCheck>("modernize-use-emplace");
     CheckFactories.registerCheck<UseNullptrCheck>("modernize-use-nullptr");
Index: clang-tidy/modernize/CMakeLists.txt
===================================================================
--- clang-tidy/modernize/CMakeLists.txt
+++ clang-tidy/modernize/CMakeLists.txt
@@ -16,6 +16,7 @@
   ShrinkToFitCheck.cpp
   UseAutoCheck.cpp
   UseBoolLiteralsCheck.cpp
+  UseCopyCheck.cpp
   UseDefaultCheck.cpp
   UseEmplaceCheck.cpp
   UseNullptrCheck.cpp
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to