Skip to content

Commit b2753fc

Browse files
giovannism20kidq330
authored andcommitted
replace memcpy with std::copy on clang-tidy
removed typo on files sort imports removed some typo solve linter reports update modernize-replace-memcpy-with-stdcopy.rst
1 parent 0f0a96b commit b2753fc

File tree

7 files changed

+225
-0
lines changed

7 files changed

+225
-0
lines changed

clang-tools-extra/clang-tidy/modernize/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ add_clang_library(clangTidyModernizeModule STATIC
2323
RedundantVoidArgCheck.cpp
2424
ReplaceAutoPtrCheck.cpp
2525
ReplaceDisallowCopyAndAssignMacroCheck.cpp
26+
ReplaceMemcpyWithStdCopy.cpp
2627
ReplaceRandomShuffleCheck.cpp
2728
ReturnBracedInitListCheck.cpp
2829
ShrinkToFitCheck.cpp

clang-tools-extra/clang-tidy/modernize/ModernizeTidyModule.cpp

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@
2424
#include "RedundantVoidArgCheck.h"
2525
#include "ReplaceAutoPtrCheck.h"
2626
#include "ReplaceDisallowCopyAndAssignMacroCheck.h"
27+
#include "ReplaceMemcpyWithStdCopy.h"
2728
#include "ReplaceRandomShuffleCheck.h"
2829
#include "ReturnBracedInitListCheck.h"
2930
#include "ShrinkToFitCheck.h"
@@ -91,6 +92,8 @@ class ModernizeModule : public ClangTidyModule {
9192
"modernize-replace-auto-ptr");
9293
CheckFactories.registerCheck<ReplaceDisallowCopyAndAssignMacroCheck>(
9394
"modernize-replace-disallow-copy-and-assign-macro");
95+
CheckFactories.registerCheck<ReplaceMemcpyWithStdCopy>(
96+
"modernize-replace-memcpy-by-stdcopy");
9497
CheckFactories.registerCheck<ReplaceRandomShuffleCheck>(
9598
"modernize-replace-random-shuffle");
9699
CheckFactories.registerCheck<ReturnBracedInitListCheck>(
Lines changed: 119 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,119 @@
1+
//===--- ReplaceMemcpyWithStdCopy.cpp - clang-tidy----------------*- C++-*-===//
2+
//
3+
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4+
// See https://llvm.org/LICENSE.txt for license information.
5+
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6+
//
7+
//===----------------------------------------------------------------------===//
8+
9+
#include "ReplaceMemcpyWithStdCopy.h"
10+
#include "../utils/OptionsUtils.h"
11+
#include <array>
12+
13+
using namespace clang;
14+
using namespace clang::ast_matchers;
15+
16+
namespace clang {
17+
namespace tidy {
18+
namespace modernize {
19+
20+
ReplaceMemcpyWithStdCopy::ReplaceMemcpyWithStdCopy(StringRef Name,
21+
ClangTidyContext *Context)
22+
: ClangTidyCheck(Name, Context),
23+
IncludeInserter(Options.getLocalOrGlobal("IncludeStyle",
24+
utils::IncludeSorter::IS_LLVM)) {
25+
}
26+
27+
void ReplaceMemcpyWithStdCopy::registerMatchers(MatchFinder *Finder) {
28+
assert(Finder != nullptr);
29+
30+
if (!getLangOpts().CPlusPlus)
31+
return;
32+
33+
auto MemcpyMatcher =
34+
callExpr(hasDeclaration(functionDecl(hasName("memcpy"),
35+
isExpansionInSystemHeader())),
36+
isExpansionInMainFile())
37+
.bind("memcpy_function");
38+
39+
Finder->addMatcher(MemcpyMatcher, this);
40+
}
41+
42+
void ReplaceMemcpyWithStdCopy::registerPPCallbacks(
43+
const SourceManager &SM, Preprocessor *PP, Preprocessor *ModuleExpanderPP) {
44+
if (!getLangOpts().CPlusPlus)
45+
return;
46+
47+
Inserter =
48+
std::make_unique<utils::IncludeInserter>(SM, getLangOpts(),
49+
IncludeStyle);
50+
PP->addPPCallbacks(Inserter->CreatePPCallbacks());
51+
}
52+
53+
void ReplaceMemcpyWithStdCopy::check(const MatchFinder::MatchResult &Result) {
54+
const auto *MemcpyNode = Result.Nodes.getNodeAs<CallExpr>("memcpy_function");
55+
assert(MemcpyNode != nullptr);
56+
57+
DiagnosticBuilder Diag =
58+
diag(MemcpyNode->getExprLoc(), "use std::copy instead of memcpy");
59+
60+
renameFunction(Diag, MemcpyNode);
61+
reorderArgs(Diag, MemcpyNode);
62+
insertHeader(Diag, MemcpyNode, Result.SourceManager);
63+
}
64+
65+
void ReplaceMemcpyWithStdCopy::storeOptions(ClangTidyOptions::OptionMap &Opts) {
66+
Options.store(Opts, "IncludeStyle",
67+
utils::IncludeSorter::toString(IncludeStyle));
68+
}
69+
70+
void ReplaceMemcpyWithStdCopy::renameFunction(DiagnosticBuilder &Diag,
71+
const CallExpr *MemcpyNode) {
72+
const CharSourceRange FunctionNameSourceRange = CharSourceRange::getCharRange(
73+
MemcpyNode->getBeginLoc(), MemcpyNode->getArg(0)->getBeginLoc());
74+
75+
Diag << FixItHint::CreateReplacement(FunctionNameSourceRange, "std::copy(");
76+
}
77+
78+
void ReplaceMemcpyWithStdCopy::reorderArgs(DiagnosticBuilder &Diag,
79+
const CallExpr *MemcpyNode) {
80+
std::array<std::string, 3> arg;
81+
82+
LangOptions LangOpts;
83+
LangOpts.CPlusPlus = true;
84+
PrintingPolicy Policy(LangOpts);
85+
86+
// Retrieve all the arguments
87+
for (uint8_t i = 0; i < arg.size(); i++) {
88+
llvm::raw_string_ostream s(arg[i]);
89+
MemcpyNode->getArg(i)->printPretty(s, nullptr, Policy);
90+
}
91+
92+
// Create lambda that return SourceRange of an argument
93+
auto getSourceRange = [MemcpyNode](uint8_t ArgCount) -> SourceRange {
94+
return SourceRange(MemcpyNode->getArg(ArgCount)->getBeginLoc(),
95+
MemcpyNode->getArg(ArgCount)->getEndLoc());
96+
};
97+
98+
// Reorder the arguments
99+
Diag << FixItHint::CreateReplacement(getSourceRange(0), arg[1]);
100+
101+
arg[2] = arg[1] + " + ((" + arg[2] + ") / sizeof(*(" + arg[1] + ")))";
102+
Diag << FixItHint::CreateReplacement(getSourceRange(1), arg[2]);
103+
104+
Diag << FixItHint::CreateReplacement(getSourceRange(2), arg[0]);
105+
}
106+
107+
void ReplaceMemcpyWithStdCopy::insertHeader(DiagnosticBuilder &Diag,
108+
const CallExpr *MemcpyNode,
109+
SourceManager *const SM) {
110+
Optional<FixItHint> FixInclude = Inserter->CreateIncludeInsertion(
111+
/*FileID=*/SM->getMainFileID(), /*Header=*/"algorithm",
112+
/*IsAngled=*/true);
113+
if (FixInclude)
114+
Diag << *FixInclude;
115+
}
116+
117+
} // namespace modernize
118+
} // namespace tidy
119+
} // namespace clang
Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
//===--- ReplaceMemcpyWithStdCopy.h - clang-tidy------------------*- C++-*-===//
2+
//
3+
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4+
// See https://llvm.org/LICENSE.txt for license information.
5+
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6+
//
7+
//===----------------------------------------------------------------------===//
8+
9+
#ifndef LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_MODERNIZE_REPLACE_MEMCPY_WITH_STDCOPY_H
10+
#define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_MODERNIZE_REPLACE_MEMCPY_WITH_STDCOPY_H
11+
12+
#include "../ClangTidyCheck.h"
13+
#include "../utils/IncludeInserter.h"
14+
#include <memory>
15+
#include <string>
16+
#include <vector>
17+
18+
namespace clang {
19+
namespace tidy {
20+
namespace modernize {
21+
22+
// Replace the C memcpy function with std::copy
23+
class ReplaceMemcpyWithStdCopy : public ClangTidyCheck {
24+
public:
25+
ReplaceMemcpyWithStdCopy(StringRef Name, ClangTidyContext *Context);
26+
~ReplaceMemcpyWithStdCopy() override = default;
27+
void registerMatchers(ast_matchers::MatchFinder *Finder) override;
28+
void registerPPCallbacks(const SourceManager &SM, Preprocessor *PP,
29+
Preprocessor *ModuleExpanderPP) override;
30+
void check(const ast_matchers::MatchFinder::MatchResult &Result) override;
31+
void storeOptions(ClangTidyOptions::OptionMap &Options) override;
32+
33+
private:
34+
void renameFunction(DiagnosticBuilder &Diag, const CallExpr *MemcpyNode);
35+
void reorderArgs(DiagnosticBuilder &Diag, const CallExpr *MemcpyNode);
36+
void insertHeader(DiagnosticBuilder &Diag, const CallExpr *MemcpyNode,
37+
SourceManager *const SM);
38+
39+
private:
40+
std::unique_ptr<utils::IncludeInserter> Inserter;
41+
utils::IncludeInserter IncludeInserter;
42+
const utils::IncludeSorter::IncludeStyle IncludeStyle;
43+
};
44+
45+
} // namespace modernize
46+
} // namespace tidy
47+
} // namespace clang
48+
49+
#endif // LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_MODERNIZE_REPLACE_MEMCPY_WITH_STDCOPY_H

clang-tools-extra/docs/ReleaseNotes.rst

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -217,6 +217,11 @@ Changes in existing checks
217217
member function calls too and to only expand macros starting with ``PRI``
218218
and ``__PRI`` from ``<inttypes.h>`` in the format string.
219219

220+
- New :doc:`modernize-replace-memcpy-with-stdcopy
221+
<clang-tidy/checks/modernize-replace-memcpy-by-stdcopy>` check.
222+
223+
Replaces all occurrences of the C ``memcpy`` function by ``std::copy``.
224+
220225
- Improved :doc:`modernize-use-std-print
221226
<clang-tidy/checks/modernize/use-std-print>` check to support replacing
222227
member function calls too and to only expand macros starting with ``PRI``

clang-tools-extra/docs/clang-tidy/checks/list.rst

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -286,6 +286,7 @@ Clang-Tidy Checks
286286
:doc:`modernize-raw-string-literal <modernize/raw-string-literal>`, "Yes"
287287
:doc:`modernize-redundant-void-arg <modernize/redundant-void-arg>`, "Yes"
288288
:doc:`modernize-replace-auto-ptr <modernize/replace-auto-ptr>`, "Yes"
289+
:doc:`modernize-replace-memcpy-with-std-copy <modernize/replace-auto-ptr>`, "Yes"
289290
:doc:`modernize-replace-disallow-copy-and-assign-macro <modernize/replace-disallow-copy-and-assign-macro>`, "Yes"
290291
:doc:`modernize-replace-random-shuffle <modernize/replace-random-shuffle>`, "Yes"
291292
:doc:`modernize-return-braced-init-list <modernize/return-braced-init-list>`, "Yes"
Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
.. title:: clang-tidy - modernize-replace-memcpy-with-stdcopy
2+
3+
modernize-replace-memcpy-with-stdcopy
4+
===================================
5+
6+
Replaces all occurrences of the C ``memcpy`` function with ``std::copy``
7+
8+
Example:
9+
10+
.. code-block:: c++
11+
12+
/*!
13+
* \param destination Pointer to the destination array where the content is to be copied
14+
* \param source Pointer to the source of data to be copied
15+
* \param num Number of bytes to copy
16+
*/
17+
memcpy(destination, source, num);
18+
19+
becomes
20+
21+
.. code-block:: c++
22+
23+
/*!
24+
* \param destination Pointer to the destination array where the content is to be copied
25+
* \param source Pointer to the source of data to be copied
26+
* \param num Number of bytes to copy
27+
*/
28+
std::copy(source, source + (num / sizeof *source), destination);
29+
30+
Bytes to iterator conversion
31+
----------------------------
32+
33+
Unlike ``std::copy`` that take an iterator on the last element of the source array, ``memcpy`` request the number of bytes to copy.
34+
In order to make the check working, it will convert the size parameter to an iterator by replacing it by ``source + (num / sizeof *source)``
35+
36+
Header inclusion
37+
----------------
38+
39+
``std::copy`` being provided by the ``algorithm`` header file, this check will include it if needed.
40+
41+
Options
42+
-------
43+
44+
.. option:: IncludeStyle
45+
46+
A string specifying which include-style is used, `llvm` or `google`. Default
47+
is `llvm`.

0 commit comments

Comments
 (0)