189a1d03eSRichard // RUN: %check_clang_tidy %s cppcoreguidelines-special-member-functions %t
289a1d03eSRichard 
389a1d03eSRichard class DefinesDestructor {
489a1d03eSRichard   ~DefinesDestructor();
589a1d03eSRichard };
6*aa56e66bSRoy Jacobson // CHECK-MESSAGES: [[@LINE-3]]:7: warning: class 'DefinesDestructor' defines a destructor but does not define a copy constructor, a copy assignment operator, a move constructor or a move assignment operator [cppcoreguidelines-special-member-functions]
789a1d03eSRichard 
889a1d03eSRichard class DefinesDefaultedDestructor {
989a1d03eSRichard   ~DefinesDefaultedDestructor() = default;
1089a1d03eSRichard };
1189a1d03eSRichard // CHECK-MESSAGES: [[@LINE-3]]:7: warning: class 'DefinesDefaultedDestructor' defines a default destructor but does not define a copy constructor, a copy assignment operator, a move constructor or a move assignment operator [cppcoreguidelines-special-member-functions]
1289a1d03eSRichard 
1389a1d03eSRichard class DefinesCopyConstructor {
1489a1d03eSRichard   DefinesCopyConstructor(const DefinesCopyConstructor &);
1589a1d03eSRichard };
1689a1d03eSRichard // CHECK-MESSAGES: [[@LINE-3]]:7: warning: class 'DefinesCopyConstructor' defines a copy constructor but does not define a destructor, a copy assignment operator, a move constructor or a move assignment operator [cppcoreguidelines-special-member-functions]
1789a1d03eSRichard 
1889a1d03eSRichard class DefinesCopyAssignment {
1989a1d03eSRichard   DefinesCopyAssignment &operator=(const DefinesCopyAssignment &);
2089a1d03eSRichard };
2189a1d03eSRichard // CHECK-MESSAGES: [[@LINE-3]]:7: warning: class 'DefinesCopyAssignment' defines a copy assignment operator but does not define a destructor, a copy constructor, a move constructor or a move assignment operator [cppcoreguidelines-special-member-functions]
2289a1d03eSRichard 
2389a1d03eSRichard class DefinesMoveConstructor {
2489a1d03eSRichard   DefinesMoveConstructor(DefinesMoveConstructor &&);
2589a1d03eSRichard };
2689a1d03eSRichard // CHECK-MESSAGES: [[@LINE-3]]:7: warning: class 'DefinesMoveConstructor' defines a move constructor but does not define a destructor, a copy constructor, a copy assignment operator or a move assignment operator [cppcoreguidelines-special-member-functions]
2789a1d03eSRichard 
2889a1d03eSRichard class DefinesMoveAssignment {
2989a1d03eSRichard   DefinesMoveAssignment &operator=(DefinesMoveAssignment &&);
3089a1d03eSRichard };
3189a1d03eSRichard // CHECK-MESSAGES: [[@LINE-3]]:7: warning: class 'DefinesMoveAssignment' defines a move assignment operator but does not define a destructor, a copy constructor, a copy assignment operator or a move constructor [cppcoreguidelines-special-member-functions]
3289a1d03eSRichard class DefinesNothing {
3389a1d03eSRichard };
3489a1d03eSRichard 
3589a1d03eSRichard class DefinesEverything {
3689a1d03eSRichard   DefinesEverything(const DefinesEverything &);
3789a1d03eSRichard   DefinesEverything &operator=(const DefinesEverything &);
3889a1d03eSRichard   DefinesEverything(DefinesEverything &&);
3989a1d03eSRichard   DefinesEverything &operator=(DefinesEverything &&);
4089a1d03eSRichard   ~DefinesEverything();
4189a1d03eSRichard };
4289a1d03eSRichard 
4389a1d03eSRichard class DeletesEverything {
4489a1d03eSRichard   DeletesEverything(const DeletesEverything &) = delete;
4589a1d03eSRichard   DeletesEverything &operator=(const DeletesEverything &) = delete;
4689a1d03eSRichard   DeletesEverything(DeletesEverything &&) = delete;
4789a1d03eSRichard   DeletesEverything &operator=(DeletesEverything &&) = delete;
4889a1d03eSRichard   ~DeletesEverything() = delete;
4989a1d03eSRichard };
5089a1d03eSRichard 
5189a1d03eSRichard class DeletesCopyDefaultsMove {
5289a1d03eSRichard   DeletesCopyDefaultsMove(const DeletesCopyDefaultsMove &) = delete;
5389a1d03eSRichard   DeletesCopyDefaultsMove &operator=(const DeletesCopyDefaultsMove &) = delete;
5489a1d03eSRichard   DeletesCopyDefaultsMove(DeletesCopyDefaultsMove &&) = default;
5589a1d03eSRichard   DeletesCopyDefaultsMove &operator=(DeletesCopyDefaultsMove &&) = default;
5689a1d03eSRichard   ~DeletesCopyDefaultsMove() = default;
5789a1d03eSRichard };
5889a1d03eSRichard 
5989a1d03eSRichard template <typename T>
6089a1d03eSRichard struct TemplateClass {
6189a1d03eSRichard   TemplateClass() = default;
6289a1d03eSRichard   TemplateClass(const TemplateClass &);
6389a1d03eSRichard   TemplateClass &operator=(const TemplateClass &);
6489a1d03eSRichard   TemplateClass(TemplateClass &&);
6589a1d03eSRichard   TemplateClass &operator=(TemplateClass &&);
6689a1d03eSRichard   ~TemplateClass();
6789a1d03eSRichard };
6889a1d03eSRichard 
6989a1d03eSRichard // Multiple instantiations of a class template will trigger multiple matches for defined special members.
7089a1d03eSRichard // This should not cause problems.
7189a1d03eSRichard TemplateClass<int> InstantiationWithInt;
7289a1d03eSRichard TemplateClass<double> InstantiationWithDouble;
73