Skip to content

Commit bd76284

Browse files
ccotterPiotrZSL
authored andcommitted
[clang-tidy] Ignore unevaluated exprs in rvalue-reference-param-not-moved
Ignore unevaluated expressions in rvalue-reference-param-not-moved check since they are not actual uses of a move(). Reviewed By: PiotrZSL Differential Revision: https://reviews.llvm.org/D146929
1 parent ae3c981 commit bd76284

File tree

4 files changed

+35
-21
lines changed

4 files changed

+35
-21
lines changed

clang-tools-extra/clang-tidy/bugprone/UseAfterMoveCheck.cpp

Lines changed: 3 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -10,38 +10,23 @@
1010

1111
#include "clang/AST/Expr.h"
1212
#include "clang/AST/ExprCXX.h"
13-
#include "clang/AST/ExprConcepts.h"
1413
#include "clang/ASTMatchers/ASTMatchers.h"
1514
#include "clang/Analysis/CFG.h"
1615
#include "clang/Lex/Lexer.h"
1716
#include "llvm/ADT/STLExtras.h"
1817

1918
#include "../utils/ExprSequence.h"
19+
#include "../utils/Matchers.h"
2020
#include <optional>
2121

2222
using namespace clang::ast_matchers;
2323
using namespace clang::tidy::utils;
2424

2525
namespace clang::tidy::bugprone {
2626

27-
namespace {
27+
using matchers::hasUnevaluatedContext;
2828

29-
AST_MATCHER(Expr, hasUnevaluatedContext) {
30-
if (isa<CXXNoexceptExpr>(Node) || isa<RequiresExpr>(Node))
31-
return true;
32-
if (const auto *UnaryExpr = dyn_cast<UnaryExprOrTypeTraitExpr>(&Node)) {
33-
switch (UnaryExpr->getKind()) {
34-
case UETT_SizeOf:
35-
case UETT_AlignOf:
36-
return true;
37-
default:
38-
return false;
39-
}
40-
}
41-
if (const auto *TypeIDExpr = dyn_cast<CXXTypeidExpr>(&Node))
42-
return !TypeIDExpr->isPotentiallyEvaluated();
43-
return false;
44-
}
29+
namespace {
4530

4631
/// Contains information about a use-after-move.
4732
struct UseAfterMove {
@@ -86,7 +71,6 @@ class UseAfterMoveFinder {
8671

8772
} // namespace
8873

89-
9074
// Matches nodes that are
9175
// - Part of a decltype argument or class template argument (we check this by
9276
// seeing if they are children of a TypeLoc), or

clang-tools-extra/clang-tidy/cppcoreguidelines/RvalueReferenceParamNotMovedCheck.cpp

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,13 +7,16 @@
77
//===----------------------------------------------------------------------===//
88

99
#include "RvalueReferenceParamNotMovedCheck.h"
10+
#include "../utils/Matchers.h"
1011
#include "clang/AST/ASTContext.h"
1112
#include "clang/ASTMatchers/ASTMatchFinder.h"
1213

1314
using namespace clang::ast_matchers;
1415

1516
namespace clang::tidy::cppcoreguidelines {
1617

18+
using matchers::hasUnevaluatedContext;
19+
1720
namespace {
1821
AST_MATCHER_P(LambdaExpr, valueCapturesVar, DeclarationMatcher, VarMatcher) {
1922
return std::find_if(Node.capture_begin(), Node.capture_end(),
@@ -39,16 +42,18 @@ void RvalueReferenceParamNotMovedCheck::registerMatchers(MatchFinder *Finder) {
3942

4043
StatementMatcher MoveCallMatcher =
4144
callExpr(
45+
argumentCountIs(1),
4246
anyOf(callee(functionDecl(hasName("::std::move"))),
4347
callee(unresolvedLookupExpr(hasAnyDeclaration(
4448
namedDecl(hasUnderlyingDecl(hasName("::std::move"))))))),
45-
argumentCountIs(1),
4649
hasArgument(
4750
0, argumentOf(
4851
AllowPartialMove,
4952
declRefExpr(to(equalsBoundNode("param"))).bind("ref"))),
5053
unless(hasAncestor(
51-
lambdaExpr(valueCapturesVar(equalsBoundNode("param"))))))
54+
lambdaExpr(valueCapturesVar(equalsBoundNode("param"))))),
55+
unless(anyOf(hasAncestor(typeLoc()),
56+
hasAncestor(expr(hasUnevaluatedContext())))))
5257
.bind("move-call");
5358

5459
Finder->addMatcher(

clang-tools-extra/clang-tidy/utils/Matchers.h

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010
#define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_UTILS_MATCHERS_H
1111

1212
#include "TypeTraits.h"
13+
#include "clang/AST/ExprConcepts.h"
1314
#include "clang/ASTMatchers/ASTMatchers.h"
1415
#include <optional>
1516

@@ -48,6 +49,23 @@ AST_MATCHER_FUNCTION(ast_matchers::TypeMatcher, isPointerToConst) {
4849
return pointerType(pointee(qualType(isConstQualified())));
4950
}
5051

52+
AST_MATCHER(Expr, hasUnevaluatedContext) {
53+
if (isa<CXXNoexceptExpr>(Node) || isa<RequiresExpr>(Node))
54+
return true;
55+
if (const auto *UnaryExpr = dyn_cast<UnaryExprOrTypeTraitExpr>(&Node)) {
56+
switch (UnaryExpr->getKind()) {
57+
case UETT_SizeOf:
58+
case UETT_AlignOf:
59+
return true;
60+
default:
61+
return false;
62+
}
63+
}
64+
if (const auto *TypeIDExpr = dyn_cast<CXXTypeidExpr>(&Node))
65+
return !TypeIDExpr->isPotentiallyEvaluated();
66+
return false;
67+
}
68+
5169
// A matcher implementation that matches a list of type name regular expressions
5270
// against a NamedDecl. If a regular expression contains the substring "::"
5371
// matching will occur against the qualified name, otherwise only the typename.

clang-tools-extra/test/clang-tidy/checkers/cppcoreguidelines/rvalue-reference-param-not-moved.cpp

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -156,6 +156,13 @@ void moves_parameter_extra_parens(Obj&& o) {
156156
Obj moved = std::move((o));
157157
}
158158

159+
void does_not_move_in_evaluated(Obj&& o) {
160+
// CHECK-MESSAGES: :[[@LINE-1]]:39: warning: rvalue reference parameter 'o' is never moved from inside the function body [cppcoreguidelines-rvalue-reference-param-not-moved]
161+
using result_t = decltype(std::move(o));
162+
unsigned size = sizeof(std::move(o));
163+
Obj moved = o;
164+
}
165+
159166
template <typename T1, typename T2>
160167
struct mypair {
161168
T1 first;

0 commit comments

Comments
 (0)