aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--clang-tidy/cert/CERTTidyModule.cpp5
-rw-r--r--clang-tidy/misc/MoveConstructorInitCheck.cpp81
-rw-r--r--clang-tidy/misc/MoveConstructorInitCheck.h6
-rw-r--r--clang-tidy/modernize/PassByValueCheck.cpp11
-rw-r--r--clang-tidy/modernize/PassByValueCheck.h1
-rw-r--r--clang-tidy/performance/UnnecessaryValueParamCheck.cpp2
-rw-r--r--docs/ReleaseNotes.rst10
-rw-r--r--docs/clang-tidy/checks/misc-move-constructor-init.rst10
-rw-r--r--docs/clang-tidy/checks/modernize-pass-by-value.rst5
-rw-r--r--test/clang-tidy/misc-move-constructor-init.cpp12
10 files changed, 34 insertions, 109 deletions
diff --git a/clang-tidy/cert/CERTTidyModule.cpp b/clang-tidy/cert/CERTTidyModule.cpp
index d88825be..d28f013a 100644
--- a/clang-tidy/cert/CERTTidyModule.cpp
+++ b/clang-tidy/cert/CERTTidyModule.cpp
@@ -67,11 +67,6 @@ public:
// MSC
CheckFactories.registerCheck<LimitedRandomnessCheck>("cert-msc30-c");
}
- ClangTidyOptions getModuleOptions() override {
- ClangTidyOptions Options;
- Options.CheckOptions["cert-oop11-cpp.UseCERTSemantics"] = "1";
- return Options;
- }
};
} // namespace cert
diff --git a/clang-tidy/misc/MoveConstructorInitCheck.cpp b/clang-tidy/misc/MoveConstructorInitCheck.cpp
index b27918cd..5d098722 100644
--- a/clang-tidy/misc/MoveConstructorInitCheck.cpp
+++ b/clang-tidy/misc/MoveConstructorInitCheck.cpp
@@ -21,30 +21,11 @@ namespace clang {
namespace tidy {
namespace misc {
-namespace {
-
-unsigned int
-parmVarDeclRefExprOccurences(const ParmVarDecl &MovableParam,
- const CXXConstructorDecl &ConstructorDecl,
- ASTContext &Context) {
- unsigned int Occurrences = 0;
- auto AllDeclRefs =
- findAll(declRefExpr(to(parmVarDecl(equalsNode(&MovableParam)))));
- Occurrences += match(AllDeclRefs, *ConstructorDecl.getBody(), Context).size();
- for (const auto *Initializer : ConstructorDecl.inits()) {
- Occurrences += match(AllDeclRefs, *Initializer->getInit(), Context).size();
- }
- return Occurrences;
-}
-
-} // namespace
-
MoveConstructorInitCheck::MoveConstructorInitCheck(StringRef Name,
ClangTidyContext *Context)
: ClangTidyCheck(Name, Context),
IncludeStyle(utils::IncludeSorter::parseIncludeStyle(
- Options.get("IncludeStyle", "llvm"))),
- UseCERTSemantics(Options.get("UseCERTSemantics", 0) != 0) {}
+ Options.get("IncludeStyle", "llvm"))) {}
void MoveConstructorInitCheck::registerMatchers(MatchFinder *Finder) {
// Only register the matchers for C++11; the functionality currently does not
@@ -63,68 +44,9 @@ void MoveConstructorInitCheck::registerMatchers(MatchFinder *Finder) {
.bind("ctor")))))
.bind("move-init")))),
this);
-
- auto NonConstValueMovableAndExpensiveToCopy =
- qualType(allOf(unless(pointerType()), unless(isConstQualified()),
- hasDeclaration(cxxRecordDecl(hasMethod(cxxConstructorDecl(
- isMoveConstructor(), unless(isDeleted()))))),
- matchers::isExpensiveToCopy()));
-
- // This checker is also used to implement cert-oop11-cpp, but when using that
- // form of the checker, we do not want to diagnose movable parameters.
- if (!UseCERTSemantics) {
- Finder->addMatcher(
- cxxConstructorDecl(
- allOf(
- unless(isMoveConstructor()),
- hasAnyConstructorInitializer(withInitializer(cxxConstructExpr(
- hasDeclaration(cxxConstructorDecl(isCopyConstructor())),
- hasArgument(
- 0,
- declRefExpr(
- to(parmVarDecl(
- hasType(
- NonConstValueMovableAndExpensiveToCopy))
- .bind("movable-param")))
- .bind("init-arg")))))))
- .bind("ctor-decl"),
- this);
- }
}
void MoveConstructorInitCheck::check(const MatchFinder::MatchResult &Result) {
- if (Result.Nodes.getNodeAs<CXXCtorInitializer>("move-init") != nullptr)
- handleMoveConstructor(Result);
- if (Result.Nodes.getNodeAs<ParmVarDecl>("movable-param") != nullptr)
- handleParamNotMoved(Result);
-}
-
-void MoveConstructorInitCheck::handleParamNotMoved(
- const MatchFinder::MatchResult &Result) {
- const auto *MovableParam =
- Result.Nodes.getNodeAs<ParmVarDecl>("movable-param");
- const auto *ConstructorDecl =
- Result.Nodes.getNodeAs<CXXConstructorDecl>("ctor-decl");
- const auto *InitArg = Result.Nodes.getNodeAs<DeclRefExpr>("init-arg");
- // If the parameter is referenced more than once it is not safe to move it.
- if (parmVarDeclRefExprOccurences(*MovableParam, *ConstructorDecl,
- *Result.Context) > 1)
- return;
- auto DiagOut = diag(InitArg->getLocStart(),
- "value argument %0 can be moved to avoid copy")
- << MovableParam;
- DiagOut << FixItHint::CreateReplacement(
- InitArg->getSourceRange(),
- (Twine("std::move(") + MovableParam->getName() + ")").str());
- if (auto IncludeFixit = Inserter->CreateIncludeInsertion(
- Result.SourceManager->getFileID(InitArg->getLocStart()), "utility",
- /*IsAngled=*/true)) {
- DiagOut << *IncludeFixit;
- }
-}
-
-void MoveConstructorInitCheck::handleMoveConstructor(
- const MatchFinder::MatchResult &Result) {
const auto *CopyCtor = Result.Nodes.getNodeAs<CXXConstructorDecl>("ctor");
const auto *Initializer =
Result.Nodes.getNodeAs<CXXCtorInitializer>("move-init");
@@ -178,7 +100,6 @@ void MoveConstructorInitCheck::registerPPCallbacks(CompilerInstance &Compiler) {
void MoveConstructorInitCheck::storeOptions(ClangTidyOptions::OptionMap &Opts) {
Options.store(Opts, "IncludeStyle",
utils::IncludeSorter::toString(IncludeStyle));
- Options.store(Opts, "UseCERTSemantics", UseCERTSemantics ? 1 : 0);
}
} // namespace misc
diff --git a/clang-tidy/misc/MoveConstructorInitCheck.h b/clang-tidy/misc/MoveConstructorInitCheck.h
index 6f9dacb6..adfba029 100644
--- a/clang-tidy/misc/MoveConstructorInitCheck.h
+++ b/clang-tidy/misc/MoveConstructorInitCheck.h
@@ -33,14 +33,8 @@ public:
void storeOptions(ClangTidyOptions::OptionMap &Opts) override;
private:
- void
- handleMoveConstructor(const ast_matchers::MatchFinder::MatchResult &Result);
- void
- handleParamNotMoved(const ast_matchers::MatchFinder::MatchResult &Result);
-
std::unique_ptr<utils::IncludeInserter> Inserter;
const utils::IncludeSorter::IncludeStyle IncludeStyle;
- const bool UseCERTSemantics;
};
} // namespace misc
diff --git a/clang-tidy/modernize/PassByValueCheck.cpp b/clang-tidy/modernize/PassByValueCheck.cpp
index 41251610..7ad8c586 100644
--- a/clang-tidy/modernize/PassByValueCheck.cpp
+++ b/clang-tidy/modernize/PassByValueCheck.cpp
@@ -119,11 +119,13 @@ collectParamDecls(const CXXConstructorDecl *Ctor,
PassByValueCheck::PassByValueCheck(StringRef Name, ClangTidyContext *Context)
: ClangTidyCheck(Name, Context),
IncludeStyle(utils::IncludeSorter::parseIncludeStyle(
- Options.get("IncludeStyle", "llvm"))) {}
+ Options.get("IncludeStyle", "llvm"))),
+ ValuesOnly(Options.get("ValuesOnly", 0) != 0) {}
void PassByValueCheck::storeOptions(ClangTidyOptions::OptionMap &Opts) {
Options.store(Opts, "IncludeStyle",
utils::IncludeSorter::toString(IncludeStyle));
+ Options.store(Opts, "ValuesOnly", ValuesOnly);
}
void PassByValueCheck::registerMatchers(MatchFinder *Finder) {
@@ -136,7 +138,8 @@ void PassByValueCheck::registerMatchers(MatchFinder *Finder) {
cxxConstructorDecl(
forEachConstructorInitializer(
cxxCtorInitializer(
- // Clang builds a CXXConstructExpr only whin it knows which
+ unless(isBaseInitializer()),
+ // Clang builds a CXXConstructExpr only when it knows which
// constructor will be called. In dependent contexts a
// ParenListExpr is generated instead of a CXXConstructExpr,
// filtering out templates automatically for us.
@@ -147,7 +150,9 @@ void PassByValueCheck::registerMatchers(MatchFinder *Finder) {
// Match only const-ref or a non-const value
// parameters. Rvalues and const-values
// shouldn't be modified.
- anyOf(constRefType(), nonConstValueType()))))
+ ValuesOnly ? nonConstValueType()
+ : anyOf(constRefType(),
+ nonConstValueType()))))
.bind("Param"))))),
hasDeclaration(cxxConstructorDecl(
isCopyConstructor(), unless(isDeleted()),
diff --git a/clang-tidy/modernize/PassByValueCheck.h b/clang-tidy/modernize/PassByValueCheck.h
index 6443b447..37deb3f7 100644
--- a/clang-tidy/modernize/PassByValueCheck.h
+++ b/clang-tidy/modernize/PassByValueCheck.h
@@ -30,6 +30,7 @@ public:
private:
std::unique_ptr<utils::IncludeInserter> Inserter;
const utils::IncludeSorter::IncludeStyle IncludeStyle;
+ const bool ValuesOnly;
};
} // namespace modernize
diff --git a/clang-tidy/performance/UnnecessaryValueParamCheck.cpp b/clang-tidy/performance/UnnecessaryValueParamCheck.cpp
index 0b583843..edc3cf20 100644
--- a/clang-tidy/performance/UnnecessaryValueParamCheck.cpp
+++ b/clang-tidy/performance/UnnecessaryValueParamCheck.cpp
@@ -95,7 +95,7 @@ void UnnecessaryValueParamCheck::check(const MatchFinder::MatchResult &Result) {
// Do not trigger on non-const value parameters when:
// 1. they are in a constructor definition since they can likely trigger
- // misc-move-constructor-init which will suggest to move the argument.
+ // modernize-pass-by-value which will suggest to move the argument.
if (!IsConstQualified && (llvm::isa<CXXConstructorDecl>(Function) ||
!Function->doesThisDeclarationHaveABody()))
return;
diff --git a/docs/ReleaseNotes.rst b/docs/ReleaseNotes.rst
index 6679cbd0..3fbeffef 100644
--- a/docs/ReleaseNotes.rst
+++ b/docs/ReleaseNotes.rst
@@ -67,6 +67,11 @@ Improvements to clang-tidy
Flags classes where some, but not all, special member functions are user-defined.
+- The UseCERTSemantics option for the `misc-move-constructor-init
+ <http://clang.llvm.org/extra/clang-tidy/checks/misc-move-constructor-init.html>`_ check
+ has been removed as it duplicated the `modernize-pass-by-value
+ <http://clang.llvm.org/extra/clang-tidy/checks/modernize-pass-by-value.html>`_ check.
+
- New `misc-move-forwarding-reference
<http://clang.llvm.org/extra/clang-tidy/checks/misc-move-forwarding-reference.html>`_ check
@@ -91,6 +96,11 @@ Improvements to clang-tidy
<http://clang.llvm.org/extra/clang-tidy/checks/modernize-make-shared.html>`_
now handle calls to the smart pointer's ``reset()`` method.
+- The `modernize-pass-by-value
+ <http://clang.llvm.org/extra/clang-tidy/checks/modernize-pass-by-value.html>`_ check
+ now has a ValuesOnly option to only warn about parameters that are passed by
+ value but not moved.
+
- The `modernize-use-auto
<http://clang.llvm.org/extra/clang-tidy/checks/modernize-use-auto.html>`_ check
now warns about variable declarations that are initialized with a cast, or by
diff --git a/docs/clang-tidy/checks/misc-move-constructor-init.rst b/docs/clang-tidy/checks/misc-move-constructor-init.rst
index 06c339a9..f56c592b 100644
--- a/docs/clang-tidy/checks/misc-move-constructor-init.rst
+++ b/docs/clang-tidy/checks/misc-move-constructor-init.rst
@@ -9,9 +9,6 @@ The check flags user-defined move constructors that have a ctor-initializer
initializing a member or base class through a copy constructor instead of a
move constructor.
-It also flags constructor arguments that are passed by value, have a non-deleted
-move-constructor and are assigned to a class field by copy construction.
-
Options
-------
@@ -19,10 +16,3 @@ Options
A string specifying which include-style is used, `llvm` or `google`. Default
is `llvm`.
-
-.. option:: UseCERTSemantics
-
- When non-zero, the check conforms to the behavior expected by the CERT secure
- coding recommendation
- `OOP11-CPP <https://www.securecoding.cert.org/confluence/display/cplusplus/OOP11-CPP.+Do+not+copy-initialize+members+or+base+classes+from+a+move+constructor>`_.
- Default is `0` for misc-move-constructor-init and `1` for cert-oop11-cpp.
diff --git a/docs/clang-tidy/checks/modernize-pass-by-value.rst b/docs/clang-tidy/checks/modernize-pass-by-value.rst
index ff3583ab..c2da7227 100644
--- a/docs/clang-tidy/checks/modernize-pass-by-value.rst
+++ b/docs/clang-tidy/checks/modernize-pass-by-value.rst
@@ -159,3 +159,8 @@ Options
A string specifying which include-style is used, `llvm` or `google`. Default
is `llvm`.
+
+.. option:: ValuesOnly
+
+ When non-zero, the check only warns about copied parameters that are already
+ passed by value. Default is `0`.
diff --git a/test/clang-tidy/misc-move-constructor-init.cpp b/test/clang-tidy/misc-move-constructor-init.cpp
index 55d309e7..0ea7fb4b 100644
--- a/test/clang-tidy/misc-move-constructor-init.cpp
+++ b/test/clang-tidy/misc-move-constructor-init.cpp
@@ -1,4 +1,7 @@
-// RUN: %check_clang_tidy %s misc-move-constructor-init %t -- -- -std=c++11 -isystem %S/Inputs/Headers
+// RUN: %check_clang_tidy %s misc-move-constructor-init,modernize-pass-by-value %t -- \
+// RUN: -config='{CheckOptions: \
+// RUN: [{key: modernize-pass-by-value.ValuesOnly, value: 1}]}' \
+// RUN: -- -std=c++11 -isystem %S/Inputs/Headers
#include <s.h>
@@ -28,8 +31,8 @@ struct D : B {
D() : B() {}
D(const D &RHS) : B(RHS) {}
// CHECK-MESSAGES: :[[@LINE+3]]:16: warning: move constructor initializes base class by calling a copy constructor [misc-move-constructor-init]
- // CHECK-MESSAGES: 23:3: note: copy constructor being called
- // CHECK-MESSAGES: 24:3: note: candidate move constructor here
+ // CHECK-MESSAGES: 26:3: note: copy constructor being called
+ // CHECK-MESSAGES: 27:3: note: candidate move constructor here
D(D &&RHS) : B(RHS) {}
};
@@ -96,7 +99,7 @@ struct TriviallyCopyable {
struct Positive {
Positive(Movable M) : M_(M) {}
- // CHECK-MESSAGES: [[@LINE-1]]:28: warning: value argument 'M' can be moved to avoid copy [misc-move-constructor-init]
+ // CHECK-MESSAGES: [[@LINE-1]]:12: warning: pass by value and use std::move [modernize-pass-by-value]
// CHECK-FIXES: Positive(Movable M) : M_(std::move(M)) {}
Movable M_;
};
@@ -121,6 +124,7 @@ struct NegativeParamTriviallyCopyable {
};
struct NegativeNotPassedByValue {
+ // This const ref constructor isn't warned about because the ValuesOnly option is set.
NegativeNotPassedByValue(const Movable &M) : M_(M) {}
NegativeNotPassedByValue(const Movable M) : M_(M) {}
NegativeNotPassedByValue(Movable &M) : M_(M) {}