-
Notifications
You must be signed in to change notification settings - Fork 11k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[clang-tidy] Replace memcpy with std::copy #74663
base: main
Are you sure you want to change the base?
Conversation
You can test this locally with the following command:git-clang-format --diff 64454daab0c34d9f3a488979b6b7dfbe315fa9f8 bd8e10820557a538ec1cd93f3f020d286132c688 -- clang-tools-extra/clang-tidy/modernize/ReplaceMemcpyWithStdCopy.cpp clang-tools-extra/clang-tidy/modernize/ReplaceMemcpyWithStdCopy.h clang-tools-extra/clang-tidy/modernize/ModernizeTidyModule.cpp View the diff from clang-format here.diff --git a/clang-tools-extra/clang-tidy/modernize/ReplaceMemcpyWithStdCopy.cpp b/clang-tools-extra/clang-tidy/modernize/ReplaceMemcpyWithStdCopy.cpp
index af6b365c16..fd728e2995 100644
--- a/clang-tools-extra/clang-tidy/modernize/ReplaceMemcpyWithStdCopy.cpp
+++ b/clang-tools-extra/clang-tidy/modernize/ReplaceMemcpyWithStdCopy.cpp
@@ -45,8 +45,7 @@ void ReplaceMemcpyWithStdCopy::registerPPCallbacks(
return;
Inserter =
- std::make_unique<utils::IncludeInserter>(SM, getLangOpts(),
- IncludeStyle);
+ std::make_unique<utils::IncludeInserter>(SM, getLangOpts(), IncludeStyle);
PP->addPPCallbacks(Inserter->CreatePPCallbacks());
}
|
@llvm/pr-subscribers-clang-tidy Author: Giovanni Martins (giovannism20) Changes#22583 Full diff: https://github.com/llvm/llvm-project/pull/74663.diff 7 Files Affected:
diff --git a/clang-tools-extra/clang-tidy/modernize/CMakeLists.txt b/clang-tools-extra/clang-tidy/modernize/CMakeLists.txt
index c40065358d2dc3..d0a996d3be7292 100644
--- a/clang-tools-extra/clang-tidy/modernize/CMakeLists.txt
+++ b/clang-tools-extra/clang-tidy/modernize/CMakeLists.txt
@@ -22,6 +22,7 @@ add_clang_library(clangTidyModernizeModule
RedundantVoidArgCheck.cpp
ReplaceAutoPtrCheck.cpp
ReplaceDisallowCopyAndAssignMacroCheck.cpp
+ ReplaceMemcpyWithStdCopy.cpp
ReplaceRandomShuffleCheck.cpp
ReturnBracedInitListCheck.cpp
ShrinkToFitCheck.cpp
diff --git a/clang-tools-extra/clang-tidy/modernize/ModernizeTidyModule.cpp b/clang-tools-extra/clang-tidy/modernize/ModernizeTidyModule.cpp
index e994ffd2a75c85..6bb9efa694eb2f 100644
--- a/clang-tools-extra/clang-tidy/modernize/ModernizeTidyModule.cpp
+++ b/clang-tools-extra/clang-tidy/modernize/ModernizeTidyModule.cpp
@@ -23,6 +23,7 @@
#include "RedundantVoidArgCheck.h"
#include "ReplaceAutoPtrCheck.h"
#include "ReplaceDisallowCopyAndAssignMacroCheck.h"
+#include "ReplaceMemcpyWithStdCopy.h"
#include "ReplaceRandomShuffleCheck.h"
#include "ReturnBracedInitListCheck.h"
#include "ShrinkToFitCheck.h"
@@ -78,6 +79,8 @@ class ModernizeModule : public ClangTidyModule {
"modernize-replace-auto-ptr");
CheckFactories.registerCheck<ReplaceDisallowCopyAndAssignMacroCheck>(
"modernize-replace-disallow-copy-and-assign-macro");
+ CheckFactories.registerCheck<ReplaceMemcpyWithStdCopy>(
+ "modernize-replace-memcpy-by-stdcopy");
CheckFactories.registerCheck<ReplaceRandomShuffleCheck>(
"modernize-replace-random-shuffle");
CheckFactories.registerCheck<ReturnBracedInitListCheck>(
diff --git a/clang-tools-extra/clang-tidy/modernize/ReplaceMemcpyWithStdCopy.cpp b/clang-tools-extra/clang-tidy/modernize/ReplaceMemcpyWithStdCopy.cpp
new file mode 100644
index 00000000000000..af6b365c162517
--- /dev/null
+++ b/clang-tools-extra/clang-tidy/modernize/ReplaceMemcpyWithStdCopy.cpp
@@ -0,0 +1,119 @@
+//===--- ReplaceMemcpyWithStdCopy.cpp - 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
+//
+//===----------------------------------------------------------------------===//
+
+#include "ReplaceMemcpyWithStdCopy.h"
+#include "../utils/OptionsUtils.h"
+#include <array>
+
+using namespace clang;
+using namespace clang::ast_matchers;
+
+namespace clang {
+namespace tidy {
+namespace modernize {
+
+ReplaceMemcpyWithStdCopy::ReplaceMemcpyWithStdCopy(StringRef Name,
+ ClangTidyContext *Context)
+ : ClangTidyCheck(Name, Context),
+ IncludeInserter(Options.getLocalOrGlobal("IncludeStyle",
+ utils::IncludeSorter::IS_LLVM)) {
+}
+
+void ReplaceMemcpyWithStdCopy::registerMatchers(MatchFinder *Finder) {
+ assert(Finder != nullptr);
+
+ if (!getLangOpts().CPlusPlus)
+ return;
+
+ auto MemcpyMatcher =
+ callExpr(hasDeclaration(functionDecl(hasName("memcpy"),
+ isExpansionInSystemHeader())),
+ isExpansionInMainFile())
+ .bind("memcpy_function");
+
+ Finder->addMatcher(MemcpyMatcher, this);
+}
+
+void ReplaceMemcpyWithStdCopy::registerPPCallbacks(
+ const SourceManager &SM, Preprocessor *PP, Preprocessor *ModuleExpanderPP) {
+ if (!getLangOpts().CPlusPlus)
+ return;
+
+ Inserter =
+ std::make_unique<utils::IncludeInserter>(SM, getLangOpts(),
+ IncludeStyle);
+ PP->addPPCallbacks(Inserter->CreatePPCallbacks());
+}
+
+void ReplaceMemcpyWithStdCopy::check(const MatchFinder::MatchResult &Result) {
+ const auto *MemcpyNode = Result.Nodes.getNodeAs<CallExpr>("memcpy_function");
+ assert(MemcpyNode != nullptr);
+
+ DiagnosticBuilder Diag =
+ diag(MemcpyNode->getExprLoc(), "use std::copy instead of memcpy");
+
+ renameFunction(Diag, MemcpyNode);
+ reorderArgs(Diag, MemcpyNode);
+ insertHeader(Diag, MemcpyNode, Result.SourceManager);
+}
+
+void ReplaceMemcpyWithStdCopy::storeOptions(ClangTidyOptions::OptionMap &Opts) {
+ Options.store(Opts, "IncludeStyle",
+ utils::IncludeSorter::toString(IncludeStyle));
+}
+
+void ReplaceMemcpyWithStdCopy::renameFunction(DiagnosticBuilder &Diag,
+ const CallExpr *MemcpyNode) {
+ const CharSourceRange FunctionNameSourceRange = CharSourceRange::getCharRange(
+ MemcpyNode->getBeginLoc(), MemcpyNode->getArg(0)->getBeginLoc());
+
+ Diag << FixItHint::CreateReplacement(FunctionNameSourceRange, "std::copy(");
+}
+
+void ReplaceMemcpyWithStdCopy::reorderArgs(DiagnosticBuilder &Diag,
+ const CallExpr *MemcpyNode) {
+ std::array<std::string, 3> arg;
+
+ LangOptions LangOpts;
+ LangOpts.CPlusPlus = true;
+ PrintingPolicy Policy(LangOpts);
+
+ // Retrieve all the arguments
+ for (uint8_t i = 0; i < arg.size(); i++) {
+ llvm::raw_string_ostream s(arg[i]);
+ MemcpyNode->getArg(i)->printPretty(s, nullptr, Policy);
+ }
+
+ // Create lambda that return SourceRange of an argument
+ auto getSourceRange = [MemcpyNode](uint8_t ArgCount) -> SourceRange {
+ return SourceRange(MemcpyNode->getArg(ArgCount)->getBeginLoc(),
+ MemcpyNode->getArg(ArgCount)->getEndLoc());
+ };
+
+ // Reorder the arguments
+ Diag << FixItHint::CreateReplacement(getSourceRange(0), arg[1]);
+
+ arg[2] = arg[1] + " + ((" + arg[2] + ") / sizeof(*(" + arg[1] + ")))";
+ Diag << FixItHint::CreateReplacement(getSourceRange(1), arg[2]);
+
+ Diag << FixItHint::CreateReplacement(getSourceRange(2), arg[0]);
+}
+
+void ReplaceMemcpyWithStdCopy::insertHeader(DiagnosticBuilder &Diag,
+ const CallExpr *MemcpyNode,
+ SourceManager *const SM) {
+ Optional<FixItHint> FixInclude = Inserter->CreateIncludeInsertion(
+ /*FileID=*/SM->getMainFileID(), /*Header=*/"algorithm",
+ /*IsAngled=*/true);
+ if (FixInclude)
+ Diag << *FixInclude;
+}
+
+} // namespace modernize
+} // namespace tidy
+} // namespace clang
diff --git a/clang-tools-extra/clang-tidy/modernize/ReplaceMemcpyWithStdCopy.h b/clang-tools-extra/clang-tidy/modernize/ReplaceMemcpyWithStdCopy.h
new file mode 100644
index 00000000000000..0f262bf839af24
--- /dev/null
+++ b/clang-tools-extra/clang-tidy/modernize/ReplaceMemcpyWithStdCopy.h
@@ -0,0 +1,49 @@
+//===--- ReplaceMemcpyWithStdCopy.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_MODERNIZE_REPLACE_MEMCPY_WITH_STDCOPY_H
+#define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_MODERNIZE_REPLACE_MEMCPY_WITH_STDCOPY_H
+
+#include "../ClangTidyCheck.h"
+#include "../utils/IncludeInserter.h"
+#include <memory>
+#include <string>
+#include <vector>
+
+namespace clang {
+namespace tidy {
+namespace modernize {
+
+// Replace the C memcpy function with std::copy
+class ReplaceMemcpyWithStdCopy : public ClangTidyCheck {
+public:
+ ReplaceMemcpyWithStdCopy(StringRef Name, ClangTidyContext *Context);
+ ~ReplaceMemcpyWithStdCopy() override = default;
+ void registerMatchers(ast_matchers::MatchFinder *Finder) override;
+ void registerPPCallbacks(const SourceManager &SM, Preprocessor *PP,
+ Preprocessor *ModuleExpanderPP) override;
+ void check(const ast_matchers::MatchFinder::MatchResult &Result) override;
+ void storeOptions(ClangTidyOptions::OptionMap &Options) override;
+
+private:
+ void renameFunction(DiagnosticBuilder &Diag, const CallExpr *MemcpyNode);
+ void reorderArgs(DiagnosticBuilder &Diag, const CallExpr *MemcpyNode);
+ void insertHeader(DiagnosticBuilder &Diag, const CallExpr *MemcpyNode,
+ SourceManager *const SM);
+
+private:
+ std::unique_ptr<utils::IncludeInserter> Inserter;
+ utils::IncludeInserter IncludeInserter;
+ const utils::IncludeSorter::IncludeStyle IncludeStyle;
+};
+
+} // namespace modernize
+} // namespace tidy
+} // namespace clang
+
+#endif // LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_MODERNIZE_REPLACE_MEMCPY_WITH_STDCOPY_H
diff --git a/clang-tools-extra/docs/ReleaseNotes.rst b/clang-tools-extra/docs/ReleaseNotes.rst
index 4ff4494cef5624..2191e418cead24 100644
--- a/clang-tools-extra/docs/ReleaseNotes.rst
+++ b/clang-tools-extra/docs/ReleaseNotes.rst
@@ -377,6 +377,11 @@ Changes in existing checks
<clang-tidy/checks/modernize/use-nullptr>` check by adding option
`IgnoredTypes` that can be used to exclude some pointer types.
+- New :doc:`modernize-replace-memcpy-with-stdcopy
+ <clang-tidy/checks/modernize-replace-memcpy-by-stdcopy>` check.
+
+ Replaces all occurrences of the C ``memcpy`` function by ``std::copy``.
+
- Improved :doc:`modernize-use-std-print
<clang-tidy/checks/modernize/use-std-print>` check to accurately generate
fixes for reordering arguments.
diff --git a/clang-tools-extra/docs/clang-tidy/checks/list.rst b/clang-tools-extra/docs/clang-tidy/checks/list.rst
index df2d5d15238d63..57d13aacb81890 100644
--- a/clang-tools-extra/docs/clang-tidy/checks/list.rst
+++ b/clang-tools-extra/docs/clang-tidy/checks/list.rst
@@ -275,6 +275,7 @@ Clang-Tidy Checks
:doc:`modernize-raw-string-literal <modernize/raw-string-literal>`, "Yes"
:doc:`modernize-redundant-void-arg <modernize/redundant-void-arg>`, "Yes"
:doc:`modernize-replace-auto-ptr <modernize/replace-auto-ptr>`, "Yes"
+ :doc:`modernize-replace-memcpy-with-std-copy <modernize/replace-auto-ptr>`, "Yes"
:doc:`modernize-replace-disallow-copy-and-assign-macro <modernize/replace-disallow-copy-and-assign-macro>`, "Yes"
:doc:`modernize-replace-random-shuffle <modernize/replace-random-shuffle>`, "Yes"
:doc:`modernize-return-braced-init-list <modernize/return-braced-init-list>`, "Yes"
diff --git a/clang-tools-extra/docs/clang-tidy/checks/modernize/modernize-replace-memcpy-with-stdcopy.rst b/clang-tools-extra/docs/clang-tidy/checks/modernize/modernize-replace-memcpy-with-stdcopy.rst
new file mode 100644
index 00000000000000..922a7f36e7e078
--- /dev/null
+++ b/clang-tools-extra/docs/clang-tidy/checks/modernize/modernize-replace-memcpy-with-stdcopy.rst
@@ -0,0 +1,47 @@
+.. title:: clang-tidy - modernize-replace-memcpy-with-stdcopy
+
+modernize-replace-memcpy-with-stdcopy
+===================================
+
+Replaces all occurrences of the C ``memcpy`` function with ``std::copy``
+
+Example:
+
+.. code-block:: c++
+
+ /*!
+ * \param destination Pointer to the destination array where the content is to be copied
+ * \param source Pointer to the source of data to be copied
+ * \param num Number of bytes to copy
+ */
+ memcpy(destination, source, num);
+
+becomes
+
+.. code-block:: c++
+
+ /*!
+ * \param destination Pointer to the destination array where the content is to be copied
+ * \param source Pointer to the source of data to be copied
+ * \param num Number of bytes to copy
+ */
+ std::copy(source, source + (num / sizeof *source), destination);
+
+Bytes to iterator conversion
+----------------------------
+
+Unlike ``std::copy`` that take an iterator on the last element of the source array, ``memcpy`` request the number of bytes to copy.
+In order to make the check working, it will convert the size parameter to an iterator by replacing it by ``source + (num / sizeof *source)``
+
+Header inclusion
+----------------
+
+``std::copy`` being provided by the ``algorithm`` header file, this check will include it if needed.
+
+Options
+-------
+
+.. option:: IncludeStyle
+
+ A string specifying which include-style is used, `llvm` or `google`. Default
+ is `llvm`.
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Missing tests.
Lot of issues.
Personally i would consider modernize-use-std-copy-fill as an name, and cover also memset, as this would be the same code. And I would convert this into std::copy_n or std::full_n.
The only thing when std::copy should eb used would be if call to memset would be:
memset(other_begin, begin, end-begin);
void ReplaceMemcpyWithStdCopy::registerMatchers(MatchFinder *Finder) { | ||
assert(Finder != nullptr); | ||
|
||
if (!getLangOpts().CPlusPlus) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
use
bool
isLanguageVersionSupported(const LangOptions &LangOptions) const override {
return LangOptions.CPlusPlus;
}
instead
} | ||
|
||
void ReplaceMemcpyWithStdCopy::registerMatchers(MatchFinder *Finder) { | ||
assert(Finder != nullptr); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
not needed
SourceManager *const SM); | ||
|
||
private: | ||
std::unique_ptr<utils::IncludeInserter> Inserter; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why you create 2 Include inserters ? create only one.
private: | ||
std::unique_ptr<utils::IncludeInserter> Inserter; | ||
utils::IncludeInserter IncludeInserter; | ||
const utils::IncludeSorter::IncludeStyle IncludeStyle; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
IncludeStyle is uninitialized.
return; | ||
|
||
auto MemcpyMatcher = | ||
callExpr(hasDeclaration(functionDecl(hasName("memcpy"), |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
use callee instead of hasDeclaration
.. title:: clang-tidy - modernize-replace-memcpy-with-stdcopy | ||
|
||
modernize-replace-memcpy-with-stdcopy | ||
=================================== |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
should cover check name
|
||
.. code-block:: c++ | ||
|
||
/*! |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
those doxygen comments arent needed
* \param source Pointer to the source of data to be copied | ||
* \param num Number of bytes to copy | ||
*/ | ||
std::copy(source, source + (num / sizeof *source), destination); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
again, use std::copy_n
Bytes to iterator conversion | ||
---------------------------- | ||
|
||
Unlike ``std::copy`` that take an iterator on the last element of the source array, ``memcpy`` request the number of bytes to copy. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
looks like workaround
Header inclusion | ||
---------------- | ||
|
||
``std::copy`` being provided by the ``algorithm`` header file, this check will include it if needed. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Not needed info
Closes #22583