xref: /llvm-project/clang-tools-extra/test/clang-tidy/checkers/abseil/cleanup-ctad.cpp (revision 89a1d03e2b379e325daa5249411e414bbd995b5e)
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)73 absl::Cleanup<cleanup_internal::Tag, Callback> MakeCleanup(Callback callback) {
74   return {static_cast<Callback &&>(callback)};
75 }
76 
77 } // namespace absl
78 
test()79 void 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