Skip to content

Commit

Permalink
[clang][Sema] Warn on self move for inlined static cast (#76646)
Browse files Browse the repository at this point in the history
There are code bases that inline `std::move` manually via `static_cast`.
Treat a static cast to an xvalue as an inlined `std::move` call and warn
on a self move.
  • Loading branch information
MaxEW707 committed Mar 6, 2024
1 parent 12fdabc commit d9d9301
Show file tree
Hide file tree
Showing 2 changed files with 24 additions and 10 deletions.
19 changes: 9 additions & 10 deletions clang/lib/Sema/SemaChecking.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -19093,18 +19093,17 @@ void Sema::DiagnoseSelfMove(const Expr *LHSExpr, const Expr *RHSExpr,
LHSExpr = LHSExpr->IgnoreParenImpCasts();
RHSExpr = RHSExpr->IgnoreParenImpCasts();

// Check for a call expression
const CallExpr *CE = dyn_cast<CallExpr>(RHSExpr);
if (!CE || CE->getNumArgs() != 1)
return;

// Check for a call to std::move
if (!CE->isCallToStdMove())
// Check for a call to std::move or for a static_cast<T&&>(..) to an xvalue
// which we can treat as an inlined std::move
if (const auto *CE = dyn_cast<CallExpr>(RHSExpr);
CE && CE->getNumArgs() == 1 && CE->isCallToStdMove())
RHSExpr = CE->getArg(0);
else if (const auto *CXXSCE = dyn_cast<CXXStaticCastExpr>(RHSExpr);
CXXSCE && CXXSCE->isXValue())
RHSExpr = CXXSCE->getSubExpr();
else
return;

// Get argument from std::move
RHSExpr = CE->getArg(0);

const DeclRefExpr *LHSDeclRef = dyn_cast<DeclRefExpr>(LHSExpr);
const DeclRefExpr *RHSDeclRef = dyn_cast<DeclRefExpr>(RHSExpr);

Expand Down
15 changes: 15 additions & 0 deletions clang/test/SemaCXX/warn-self-move.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,9 @@ void int_test() {
x = std::move(x); // expected-warning{{explicitly moving}}
(x) = std::move(x); // expected-warning{{explicitly moving}}

x = static_cast<int&&>(x); // expected-warning{{explicitly moving}}
(x) = static_cast<int&&>(x); // expected-warning{{explicitly moving}}

using std::move;
x = move(x); // expected-warning{{explicitly moving}} \
expected-warning {{unqualified call to 'std::move}}
Expand All @@ -26,6 +29,9 @@ void global_int_test() {
global = std::move(global); // expected-warning{{explicitly moving}}
(global) = std::move(global); // expected-warning{{explicitly moving}}

global = static_cast<int&&>(global); // expected-warning{{explicitly moving}}
(global) = static_cast<int&&>(global); // expected-warning{{explicitly moving}}

using std::move;
global = move(global); // expected-warning{{explicitly moving}} \
expected-warning {{unqualified call to 'std::move}}
Expand All @@ -35,11 +41,16 @@ class field_test {
int x;
field_test(field_test&& other) {
x = std::move(x); // expected-warning{{explicitly moving}}
x = static_cast<int&&>(x); // expected-warning{{explicitly moving}}
x = std::move(other.x);
x = static_cast<int&&>(other.x);
other.x = std::move(x);
other.x = static_cast<int&&>(x);
other.x = std::move(other.x); // expected-warning{{explicitly moving}}
other.x = static_cast<int&&>(other.x); // expected-warning{{explicitly moving}}
}
void withSuggest(int x) {
x = static_cast<int&&>(x); // expected-warning{{explicitly moving variable of type 'int' to itself; did you mean to move to member 'x'?}}
x = std::move(x); // expected-warning{{explicitly moving variable of type 'int' to itself; did you mean to move to member 'x'?}}
}
};
Expand All @@ -50,11 +61,15 @@ struct C { C() {}; ~C() {} };
void struct_test() {
A a;
a = std::move(a); // expected-warning{{explicitly moving}}
a = static_cast<A&&>(a); // expected-warning{{explicitly moving}}

B b;
b = std::move(b); // expected-warning{{explicitly moving}}
b = static_cast<B&&>(b); // expected-warning{{explicitly moving}}
b.a = std::move(b.a); // expected-warning{{explicitly moving}}
b.a = static_cast<A&&>(b.a); // expected-warning{{explicitly moving}}

C c;
c = std::move(c); // expected-warning{{explicitly moving}}
c = static_cast<C&&>(c); // expected-warning{{explicitly moving}}
}

0 comments on commit d9d9301

Please sign in to comment.