llvmbot wrote:
<!--LLVM PR SUMMARY COMMENT--> @llvm/pr-subscribers-clang Author: Max Winkler (MaxEW707) <details> <summary>Changes</summary> 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. --- Full diff: https://github.com/llvm/llvm-project/pull/76646.diff 2 Files Affected: - (modified) clang/lib/Sema/SemaChecking.cpp (+14-5) - (modified) clang/test/SemaCXX/warn-self-move.cpp (+13) ``````````diff diff --git a/clang/lib/Sema/SemaChecking.cpp b/clang/lib/Sema/SemaChecking.cpp index 2a69325f029514..a21410434d8099 100644 --- a/clang/lib/Sema/SemaChecking.cpp +++ b/clang/lib/Sema/SemaChecking.cpp @@ -18843,17 +18843,26 @@ void Sema::DiagnoseSelfMove(const Expr *LHSExpr, const Expr *RHSExpr, LHSExpr = LHSExpr->IgnoreParenImpCasts(); RHSExpr = RHSExpr->IgnoreParenImpCasts(); - // Check for a call expression + // Check for a call expression or static_cast expression const CallExpr *CE = dyn_cast<CallExpr>(RHSExpr); - if (!CE || CE->getNumArgs() != 1) + const CXXStaticCastExpr *CXXSCE = dyn_cast<CXXStaticCastExpr>(RHSExpr); + if (!CE && !CXXSCE) return; // Check for a call to std::move - if (!CE->isCallToStdMove()) + if (CE && (CE->getNumArgs() != 1 || !CE->isCallToStdMove())) return; - // Get argument from std::move - RHSExpr = CE->getArg(0); + // Check for a static_cast<T&&>(..) to an xvalue which we can treat as an + // inlined std::move + if (CXXSCE && !CXXSCE->isXValue()) + return; + + // Get argument from std::move or static_cast + if (CE) + RHSExpr = CE->getArg(0); + else + RHSExpr = CXXSCE->getSubExpr(); const DeclRefExpr *LHSDeclRef = dyn_cast<DeclRefExpr>(LHSExpr); const DeclRefExpr *RHSDeclRef = dyn_cast<DeclRefExpr>(RHSExpr); diff --git a/clang/test/SemaCXX/warn-self-move.cpp b/clang/test/SemaCXX/warn-self-move.cpp index 0987e9b6bf6017..d0158626424142 100644 --- a/clang/test/SemaCXX/warn-self-move.cpp +++ b/clang/test/SemaCXX/warn-self-move.cpp @@ -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}} @@ -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}} @@ -35,11 +41,14 @@ 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); other.x = std::move(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'?}} } }; @@ -50,11 +59,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}} } `````````` </details> https://github.com/llvm/llvm-project/pull/76646 _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits