Author: Max Winkler Date: 2024-03-06T16:58:12+01:00 New Revision: d9d9301eec6dfefcf53fd04b61324f140f273033
URL: https://github.com/llvm/llvm-project/commit/d9d9301eec6dfefcf53fd04b61324f140f273033 DIFF: https://github.com/llvm/llvm-project/commit/d9d9301eec6dfefcf53fd04b61324f140f273033.diff LOG: [clang][Sema] Warn on self move for inlined static cast (#76646) 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. Added: Modified: clang/lib/Sema/SemaChecking.cpp clang/test/SemaCXX/warn-self-move.cpp Removed: ################################################################################ diff --git a/clang/lib/Sema/SemaChecking.cpp b/clang/lib/Sema/SemaChecking.cpp index 6ed61a19ff17dd..3597f93a017136 100644 --- a/clang/lib/Sema/SemaChecking.cpp +++ b/clang/lib/Sema/SemaChecking.cpp @@ -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); diff --git a/clang/test/SemaCXX/warn-self-move.cpp b/clang/test/SemaCXX/warn-self-move.cpp index 0987e9b6bf6017..5937bb705ed227 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,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'?}} } }; @@ -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}} } _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits