AMS21 created this revision. AMS21 added a reviewer: njames93. Herald added subscribers: PiotrZSL, carlosgalvezp, xazax.hun. Herald added a project: All. AMS21 requested review of this revision. Herald added a project: clang-tools-extra. Herald added a subscriber: cfe-commits.
Previously a struct like this: template <typename> struct A { A(A&&) = default; }; Would trigger a false positive, since it didn't realize that a defaulted move constructor is automatically considered being noexcept. Now we only give a warning if the defaulted move constrcutor has a noexcept expression which evaluated to false but is not simply `noexcept(false)`. This fixes llvm#56026 Repository: rG LLVM Github Monorepo https://reviews.llvm.org/D146922 Files: clang-tools-extra/clang-tidy/performance/NoexceptMoveConstructorCheck.cpp clang-tools-extra/test/clang-tidy/checkers/performance/noexcept-move-constructor-fix.cpp clang-tools-extra/test/clang-tidy/checkers/performance/noexcept-move-constructor.cpp
Index: clang-tools-extra/test/clang-tidy/checkers/performance/noexcept-move-constructor.cpp =================================================================== --- clang-tools-extra/test/clang-tidy/checkers/performance/noexcept-move-constructor.cpp +++ clang-tools-extra/test/clang-tidy/checkers/performance/noexcept-move-constructor.cpp @@ -13,6 +13,44 @@ // CHECK-MESSAGES: :[[@LINE-1]]:20: warning: noexcept specifier on the move constructor evaluates to 'false' [performance-noexcept-move-constructor] }; +template <typename> +struct C +{ + C(C &&); + // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: move constructors should be marked noexcept [performance-noexcept-move-constructor] + C& operator=(C &&); + // CHECK-MESSAGES: :[[@LINE-1]]:6: warning: move assignment operators should be marked noexcept [performance-noexcept-move-constructor] +}; + +struct D +{ + static constexpr bool kFalse = false; + D(D &&) noexcept(kFalse) = default; + // CHECK-MESSAGES: :[[@LINE-1]]:20: warning: noexcept specifier on the move constructor evaluates to 'false' [performance-noexcept-move-constructor] + D& operator=(D &&) noexcept(kFalse) = default; + // CHECK-MESSAGES: :[[@LINE-1]]:31: warning: noexcept specifier on the move assignment operator evaluates to 'false' +}; + +template <typename> +struct E +{ + static constexpr bool kFalse = false; + E(E &&) noexcept(kFalse); + // CHECK-MESSAGES: :[[@LINE-1]]:20: warning: noexcept specifier on the move constructor evaluates to 'false' [performance-noexcept-move-constructor] + E& operator=(E &&) noexcept(kFalse); + // CHECK-MESSAGES: :[[@LINE-1]]:31: warning: noexcept specifier on the move assignment operator evaluates to 'false' +}; + +template <typename> +struct F +{ + static constexpr bool kFalse = false; + F(F &&) noexcept(kFalse) = default; + // CHECK-MESSAGES: :[[@LINE-1]]:20: warning: noexcept specifier on the move constructor evaluates to 'false' [performance-noexcept-move-constructor] + F& operator=(F &&) noexcept(kFalse) = default; + // CHECK-MESSAGES: :[[@LINE-1]]:31: warning: noexcept specifier on the move assignment operator evaluates to 'false' +}; + class OK {}; void f() { @@ -52,3 +90,38 @@ OK5(OK5 &&) noexcept(true) = default; OK5 &operator=(OK5 &&) noexcept(true) = default; }; + +struct OK6 { + OK6(OK6 &&) = default; + OK6& operator=(OK6 &&) = default; +}; + +template <typename> +struct OK7 { + OK7(OK7 &&) = default; + OK7& operator=(OK7 &&) = default; +}; + +template <typename> +struct OK8 { + OK8(OK8 &&) noexcept = default; + OK8& operator=(OK8 &&) noexcept = default; +}; + +template <typename> +struct OK9 { + OK9(OK9 &&) noexcept(true) = default; + OK9& operator=(OK9 &&) noexcept(true) = default; +}; + +template <typename> +struct OK10 { + OK10(OK10 &&) noexcept(false) = default; + OK10& operator=(OK10 &&) noexcept(false) = default; +}; + +template <typename> +struct OK11 { + OK11(OK11 &&) = delete; + OK11& operator=(OK11 &&) = delete; +}; Index: clang-tools-extra/test/clang-tidy/checkers/performance/noexcept-move-constructor-fix.cpp =================================================================== --- clang-tools-extra/test/clang-tidy/checkers/performance/noexcept-move-constructor-fix.cpp +++ clang-tools-extra/test/clang-tidy/checkers/performance/noexcept-move-constructor-fix.cpp @@ -31,9 +31,7 @@ }; C_3::C_3(C_3&& a) = default; -// CHECK-FIXES: ){{.*}}noexcept{{.*}} = default; C_3& C_3::operator=(C_3&& a) = default; -// CHECK-FIXES: ){{.*}}noexcept{{.*}} = default; template <class T> struct C_4 { @@ -41,7 +39,6 @@ // CHECK-FIXES: ){{.*}}noexcept{{.*}} {} ~C_4() {} C_4& operator=(C_4&& a) = default; -// CHECK-FIXES: ){{.*}}noexcept{{.*}} = default; }; template <class T> @@ -50,7 +47,6 @@ // CHECK-FIXES:){{.*}}noexcept{{.*}} {} ~C_5() {} auto operator=(C_5&& a)->C_5<T> = default; -// CHECK-FIXES:){{.*}}noexcept{{.*}} = default; }; template <class T> Index: clang-tools-extra/clang-tidy/performance/NoexceptMoveConstructorCheck.cpp =================================================================== --- clang-tools-extra/clang-tidy/performance/NoexceptMoveConstructorCheck.cpp +++ clang-tools-extra/clang-tidy/performance/NoexceptMoveConstructorCheck.cpp @@ -41,6 +41,11 @@ if (isUnresolvedExceptionSpec(ProtoType->getExceptionSpecType())) return; + // Defaulted move constructors are noexcept even without a noexcept + // specifier + if (Decl->isDefaulted() && ProtoType->getExceptionSpecType() == EST_None) + return; + if (!isNoexceptExceptionSpec(ProtoType->getExceptionSpecType())) { auto Diag = diag(Decl->getLocation(), "move %select{assignment operator|constructor}0s should "
_______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits