// RUN: %check_clang_tidy %s performance-trivially-destructible %t // RUN: grep -Ev "// *[A-Z-]+:" %s > %t.cpp // RUN: clang-tidy %t.cpp -checks='-*,performance-trivially-destructible' -fix // RUN: clang-tidy %t.cpp -checks='-*,performance-trivially-destructible' -warnings-as-errors='-*,performance-trivially-destructible' struct TriviallyDestructible1 { int a; }; struct TriviallyDestructible2 : TriviallyDestructible1 { ~TriviallyDestructible2() = default; TriviallyDestructible1 b; }; struct NotTriviallyDestructible1 : TriviallyDestructible2 { ~NotTriviallyDestructible1(); // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: class 'NotTriviallyDestructible1' can be made trivially destructible by defaulting the destructor on its first declaration [performance-trivially-destructible] // CHECK-FIXES: ~NotTriviallyDestructible1() = default; TriviallyDestructible2 b; }; NotTriviallyDestructible1::~NotTriviallyDestructible1() = default; // to-be-removed // CHECK-MESSAGES: :[[@LINE-1]]:28: note: destructor definition is here // CHECK-FIXES: {{^}}// to-be-removed // Don't emit for class template with type-dependent fields. template <class T> struct MaybeTriviallyDestructible1 { ~MaybeTriviallyDestructible1() noexcept; T t; }; template <class T> MaybeTriviallyDestructible1<T>::~MaybeTriviallyDestructible1() noexcept = default; // Don't emit for specializations. template struct MaybeTriviallyDestructible1<int>; // Don't emit for class template with type-dependent bases. template <class T> struct MaybeTriviallyDestructible2 : T { ~MaybeTriviallyDestructible2() noexcept; }; template <class T> MaybeTriviallyDestructible2<T>::~MaybeTriviallyDestructible2() noexcept = default; // Emit for templates without dependent bases and fields. template <class T> struct MaybeTriviallyDestructible1<T *> { ~MaybeTriviallyDestructible1() noexcept; // 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] // CHECK-FIXES: ~MaybeTriviallyDestructible1() noexcept = default; TriviallyDestructible1 t; }; template <class T> MaybeTriviallyDestructible1<T *>::~MaybeTriviallyDestructible1() noexcept = default; // to-be-removed // CHECK-MESSAGES: :[[@LINE-1]]:35: note: destructor definition is here // CHECK-FIXES: {{^}}// to-be-removed // Emit for explicit specializations. template <> struct MaybeTriviallyDestructible1<double>: TriviallyDestructible1 { ~MaybeTriviallyDestructible1() noexcept; // 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] // CHECK-FIXES: ~MaybeTriviallyDestructible1() noexcept = default; }; MaybeTriviallyDestructible1<double>::~MaybeTriviallyDestructible1() noexcept = default; // to-be-removed // CHECK-MESSAGES: :[[@LINE-1]]:38: note: destructor definition is here // CHECK-FIXES: {{^}}// to-be-removed struct NotTriviallyDestructible2 { virtual ~NotTriviallyDestructible2(); }; NotTriviallyDestructible2::~NotTriviallyDestructible2() = default; struct NotTriviallyDestructible3: NotTriviallyDestructible2 { ~NotTriviallyDestructible3(); }; NotTriviallyDestructible3::~NotTriviallyDestructible3() = default;