Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 10 additions & 4 deletions clang-tools-extra/clang-tidy/performance/MoveConstArgCheck.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,10 @@ void MoveConstArgCheck::registerMatchers(MatchFinder *Finder) {
unless(isInTemplateInstantiation()))
.bind("call-move");

// Match ternary expressions where either branch contains std::move
auto TernaryWithMoveMatcher =
conditionalOperator(hasDescendant(MoveCallMatcher));

Finder->addMatcher(
expr(anyOf(
castExpr(hasSourceExpression(MoveCallMatcher)),
Expand All @@ -58,13 +62,15 @@ void MoveConstArgCheck::registerMatchers(MatchFinder *Finder) {
qualType(rValueReferenceType()).bind("invocation-parm-type");
// Matches respective ParmVarDecl for a CallExpr or CXXConstructExpr.
auto ArgumentWithParamMatcher = forEachArgumentWithParam(
MoveCallMatcher, parmVarDecl(anyOf(hasType(ConstTypeParmMatcher),
hasType(RValueTypeParmMatcher)))
.bind("invocation-parm"));
anyOf(MoveCallMatcher, TernaryWithMoveMatcher),
parmVarDecl(
anyOf(hasType(ConstTypeParmMatcher), hasType(RValueTypeParmMatcher)))
.bind("invocation-parm"));
// Matches respective types of arguments for a CallExpr or CXXConstructExpr
// and it works on calls through function pointers as well.
auto ArgumentWithParamTypeMatcher = forEachArgumentWithParamType(
MoveCallMatcher, anyOf(ConstTypeParmMatcher, RValueTypeParmMatcher));
anyOf(MoveCallMatcher, TernaryWithMoveMatcher),
anyOf(ConstTypeParmMatcher, RValueTypeParmMatcher));

Finder->addMatcher(
invocation(anyOf(ArgumentWithParamMatcher, ArgumentWithParamTypeMatcher))
Expand Down
4 changes: 4 additions & 0 deletions clang-tools-extra/docs/ReleaseNotes.rst
Original file line number Diff line number Diff line change
Expand Up @@ -120,6 +120,10 @@ Changes in existing checks
tolerating fix-it breaking compilation when functions is used as pointers
to avoid matching usage of functions within the current compilation unit.

- Improved :doc:`performance-move-const-arg
<clang-tidy/checks/performance/move-const-arg>` check by fixing false negatives
on ternary operators calling ``std::move``.

Removed checks
^^^^^^^^^^^^^^

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -560,3 +560,26 @@ struct Result {
// CHECK-MESSAGES: :[[@LINE-1]]:{{[0-9]+}}: warning: passing result of std::move() as a const reference argument; no move will actually happen [performance-move-const-arg]
};
} // namespace GH111450

namespace GH126515 {

struct TernaryMoveCall {
TernaryMoveCall();
TernaryMoveCall(const TernaryMoveCall&);
TernaryMoveCall operator=(const TernaryMoveCall&);

void TernaryCheckTriviallyCopyable(const char * c) {}

void testTernaryMove() {
TernaryMoveCall t1;
TernaryMoveCall other(false ? TernaryMoveCall() : TernaryMoveCall(std::move(t1)) );
// CHECK-MESSAGES: :[[@LINE-1]]:69: warning: passing result of std::move() as a const reference argument; no move will actually happen [performance-move-const-arg]
// CHECK-MESSAGES: :[[@LINE-11]]:8: note: 'TernaryMoveCall' is not move assignable/constructible

const char* a = "a";
TernaryCheckTriviallyCopyable(true ? std::move(a) : "" );
// CHECK-MESSAGES: :[[@LINE-1]]:40: warning: std::move of the variable 'a' of the trivially-copyable type 'const char *' has no effect; remove std::move() [performance-move-const-arg]
}

};
} // namespace GH126515
Loading