1 // RUN: %check_clang_tidy %s performance-trivially-destructible %t
2 // RUN: grep -Ev "// *[A-Z-]+:" %s > %t.cpp
3 // RUN: clang-tidy %t.cpp -checks='-*,performance-trivially-destructible' -fix
4 // RUN: clang-tidy %t.cpp -checks='-*,performance-trivially-destructible' -warnings-as-errors='-*,performance-trivially-destructible'
5 
6 struct TriviallyDestructible1 {
7   int a;
8 };
9 
10 struct TriviallyDestructible2 : TriviallyDestructible1 {
11   ~TriviallyDestructible2() = default;
12   TriviallyDestructible1 b;
13 };
14 
15 struct NotTriviallyDestructible1 : TriviallyDestructible2 {
16   ~NotTriviallyDestructible1();
17   // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: class 'NotTriviallyDestructible1' can be made trivially destructible by defaulting the destructor on its first declaration [performance-trivially-destructible]
18   // CHECK-FIXES: ~NotTriviallyDestructible1() = default;
19   TriviallyDestructible2 b;
20 };
21 
22 NotTriviallyDestructible1::~NotTriviallyDestructible1() = default; // to-be-removed
23 // CHECK-MESSAGES: :[[@LINE-1]]:28: note: destructor definition is here
24 // CHECK-FIXES: {{^}}// to-be-removed
25 
26 // Don't emit for class template with type-dependent fields.
27 template <class T>
28 struct MaybeTriviallyDestructible1 {
29   ~MaybeTriviallyDestructible1() noexcept;
30   T t;
31 };
32 
33 template <class T>
34 MaybeTriviallyDestructible1<T>::~MaybeTriviallyDestructible1() noexcept = default;
35 
36 // Don't emit for specializations.
37 template struct MaybeTriviallyDestructible1<int>;
38 
39 // Don't emit for class template with type-dependent bases.
40 template <class T>
41 struct MaybeTriviallyDestructible2 : T {
42   ~MaybeTriviallyDestructible2() noexcept;
43 };
44 
45 template <class T>
46 MaybeTriviallyDestructible2<T>::~MaybeTriviallyDestructible2() noexcept = default;
47 
48 // Emit for templates without dependent bases and fields.
49 template <class T>
50 struct MaybeTriviallyDestructible1<T *> {
51   ~MaybeTriviallyDestructible1() noexcept;
52   // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: class 'MaybeTriviallyDestructible1<T *>' can be made trivially destructible by defaulting the destructor on its first declaration [performance-trivially-destructible]
53   // CHECK-FIXES: ~MaybeTriviallyDestructible1() noexcept = default;
54   TriviallyDestructible1 t;
55 };
56 
57 template <class T>
58 MaybeTriviallyDestructible1<T *>::~MaybeTriviallyDestructible1() noexcept = default; // to-be-removed
59 // CHECK-MESSAGES: :[[@LINE-1]]:35: note: destructor definition is here
60 // CHECK-FIXES: {{^}}// to-be-removed
61 
62 // Emit for explicit specializations.
63 template <>
64 struct MaybeTriviallyDestructible1<double>: TriviallyDestructible1 {
65   ~MaybeTriviallyDestructible1() noexcept;
66   // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: class 'MaybeTriviallyDestructible1<double>' can be made trivially destructible by defaulting the destructor on its first declaration [performance-trivially-destructible]
67   // CHECK-FIXES: ~MaybeTriviallyDestructible1() noexcept = default;
68 };
69 
70 MaybeTriviallyDestructible1<double>::~MaybeTriviallyDestructible1() noexcept = default; // to-be-removed
71 // CHECK-MESSAGES: :[[@LINE-1]]:38: note: destructor definition is here
72 // CHECK-FIXES: {{^}}// to-be-removed
73 
74 struct NotTriviallyDestructible2 {
75   virtual ~NotTriviallyDestructible2();
76 };
77 
78 NotTriviallyDestructible2::~NotTriviallyDestructible2() = default;
79 
80 struct NotTriviallyDestructible3: NotTriviallyDestructible2 {
81   ~NotTriviallyDestructible3();
82 };
83 
84 NotTriviallyDestructible3::~NotTriviallyDestructible3() = default;
85