1 // RUN: %check_clang_tidy %s abseil-cleanup-ctad -std=c++17 %t 2 3 namespace std { 4 5 template <typename, typename> 6 struct is_same { 7 static const bool value = false; 8 }; 9 10 template <typename T> 11 struct is_same<T, T> { static const bool value = true; }; 12 13 template <typename> 14 class function { 15 public: 16 template <typename T> function(T)17 function(T) {} function(const function &)18 function(const function &) {} 19 }; 20 21 } // namespace std 22 23 namespace absl { 24 25 namespace cleanup_internal { 26 27 struct Tag {}; 28 29 template <typename Callback> 30 class Storage { 31 public: 32 Storage() = delete; 33 Storage(Callback callback)34 explicit Storage(Callback callback) {} 35 Storage(Storage && other)36 Storage(Storage &&other) {} 37 38 Storage(const Storage &other) = delete; 39 40 Storage &operator=(Storage &&other) = delete; 41 42 Storage &operator=(const Storage &other) = delete; 43 44 private: 45 bool is_callback_engaged_; 46 alignas(Callback) char callback_buffer_[sizeof(Callback)]; 47 }; 48 49 } // namespace cleanup_internal 50 51 template <typename Arg, typename Callback = void()> 52 class Cleanup final { 53 public: Cleanup(Callback callback)54 Cleanup(Callback callback) // NOLINT 55 : storage_(static_cast<Callback &&>(callback)) {} 56 57 Cleanup(Cleanup &&other) = default; 58 59 void Cancel() &&; 60 61 void Invoke() &&; 62 63 ~Cleanup(); 64 65 private: 66 cleanup_internal::Storage<Callback> storage_; 67 }; 68 69 template <typename Callback> 70 Cleanup(Callback callback) -> Cleanup<cleanup_internal::Tag, Callback>; 71 72 template <typename... Args, typename Callback> MakeCleanup(Callback callback)73absl::Cleanup<cleanup_internal::Tag, Callback> MakeCleanup(Callback callback) { 74 return {static_cast<Callback &&>(callback)}; 75 } 76 77 } // namespace absl 78 test()79void test() { 80 auto a = absl::MakeCleanup([] {}); 81 // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: prefer absl::Cleanup's class template argument deduction pattern in C++17 and higher 82 // CHECK-FIXES: {{^}} absl::Cleanup a = [] {};{{$}} 83 84 auto b = absl::MakeCleanup(std::function<void()>([] {})); 85 // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: prefer absl::Cleanup{{.*}}C++17 and higher 86 // CHECK-FIXES: {{^}} absl::Cleanup b = std::function<void()>([] {});{{$}} 87 88 const auto c = absl::MakeCleanup([] {}); 89 // CHECK-MESSAGES: :[[@LINE-1]]:9: warning: prefer absl::Cleanup{{.*}}C++17 and higher 90 // CHECK-FIXES: {{^}} const absl::Cleanup c = [] {};{{$}} 91 92 const auto d = absl::MakeCleanup(std::function<void()>([] {})); 93 // CHECK-MESSAGES: :[[@LINE-1]]:9: warning: prefer absl::Cleanup{{.*}}C++17 and higher 94 // CHECK-FIXES: {{^}} const absl::Cleanup d = std::function<void()>([] {});{{$}} 95 96 // Preserves extra parens 97 auto e = absl::MakeCleanup(([] {})); 98 // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: prefer absl::Cleanup{{.*}}C++17 and higher 99 // CHECK-FIXES: {{^}} absl::Cleanup e = ([] {});{{$}} 100 101 // Preserves comments 102 auto f = /* a */ absl::MakeCleanup(/* b */ [] { /* c */ } /* d */) /* e */; 103 // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: prefer absl::Cleanup{{.*}}C++17 and higher 104 // CHECK-FIXES: {{^}} absl::Cleanup f = /* a */ /* b */ [] { /* c */ } /* d */ /* e */;{{$}} 105 } 106