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
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits