@@ -19,75 +19,87 @@ AST_MATCHER(FieldDecl, isMemberOfLambda) {
1919 return Node.getParent ()->isLambda ();
2020}
2121
22- struct MemberFunctionInfo {
23- bool Declared{};
24- bool Deleted{};
25- };
26-
27- struct MemberFunctionPairInfo {
28- MemberFunctionInfo Copy{};
29- MemberFunctionInfo Move{};
30- };
31-
32- MemberFunctionPairInfo getConstructorsInfo (CXXRecordDecl const &Node) {
33- MemberFunctionPairInfo Constructors{};
34-
35- for (CXXConstructorDecl const *Ctor : Node.ctors ()) {
36- if (Ctor->isCopyConstructor ()) {
37- Constructors.Copy .Declared = true ;
38- if (Ctor->isDeleted ())
39- Constructors.Copy .Deleted = true ;
40- }
41- if (Ctor->isMoveConstructor ()) {
42- Constructors.Move .Declared = true ;
43- if (Ctor->isDeleted ())
44- Constructors.Move .Deleted = true ;
22+ bool hasCopyConstructor (CXXRecordDecl const &Node) {
23+ if (Node.needsOverloadResolutionForCopyConstructor () &&
24+ Node.needsImplicitCopyConstructor ()) {
25+ // unresolved
26+ for (CXXBaseSpecifier const &BS : Node.bases ()) {
27+ CXXRecordDecl const *BRD = BS.getType ()->getAsCXXRecordDecl ();
28+ if (BRD != nullptr )
29+ if (!hasCopyConstructor (*BRD))
30+ return false ;
4531 }
4632 }
47-
48- return Constructors;
33+ if (Node.hasSimpleCopyConstructor ())
34+ return true ;
35+ for (CXXConstructorDecl const *Ctor : Node.ctors ())
36+ if (Ctor->isCopyConstructor ())
37+ return !Ctor->isDeleted ();
38+ return false ;
4939}
5040
51- MemberFunctionPairInfo getAssignmentsInfo (CXXRecordDecl const &Node) {
52- MemberFunctionPairInfo Assignments{};
53-
54- for (CXXMethodDecl const *Method : Node.methods ()) {
55- if (Method->isCopyAssignmentOperator ()) {
56- Assignments.Copy .Declared = true ;
57- if (Method->isDeleted ())
58- Assignments.Copy .Deleted = true ;
41+ bool hasMoveConstructor (CXXRecordDecl const &Node) {
42+ if (Node.needsOverloadResolutionForMoveConstructor () &&
43+ Node.needsImplicitMoveConstructor ()) {
44+ // unresolved
45+ for (CXXBaseSpecifier const &BS : Node.bases ()) {
46+ CXXRecordDecl const *BRD = BS.getType ()->getAsCXXRecordDecl ();
47+ if (BRD != nullptr )
48+ if (!hasMoveConstructor (*BRD))
49+ return false ;
5950 }
51+ }
52+ if (Node.hasSimpleMoveConstructor ())
53+ return true ;
54+ for (CXXConstructorDecl const *Ctor : Node.ctors ())
55+ if (Ctor->isMoveConstructor ())
56+ return !Ctor->isDeleted ();
57+ return false ;
58+ }
6059
61- if (Method->isMoveAssignmentOperator ()) {
62- Assignments.Move .Declared = true ;
63- if (Method->isDeleted ())
64- Assignments.Move .Deleted = true ;
60+ bool hasCopyAssignment (CXXRecordDecl const &Node) {
61+ if (Node.needsOverloadResolutionForCopyAssignment () &&
62+ Node.needsImplicitCopyAssignment ()) {
63+ // unresolved
64+ for (CXXBaseSpecifier const &BS : Node.bases ()) {
65+ CXXRecordDecl const *BRD = BS.getType ()->getAsCXXRecordDecl ();
66+ if (BRD != nullptr )
67+ if (!hasCopyAssignment (*BRD))
68+ return false ;
6569 }
6670 }
67-
68- return Assignments;
71+ if (Node.hasSimpleCopyAssignment ())
72+ return true ;
73+ for (CXXMethodDecl const *Method : Node.methods ())
74+ if (Method->isCopyAssignmentOperator ())
75+ return !Method->isDeleted ();
76+ return false ;
6977}
7078
71- AST_MATCHER (CXXRecordDecl, isCopyableOrMovable) {
72- MemberFunctionPairInfo Constructors = getConstructorsInfo (Node);
73- MemberFunctionPairInfo Assignments = getAssignmentsInfo (Node);
74-
75- if (Node.hasSimpleCopyConstructor () ||
76- (Constructors.Copy .Declared && !Constructors.Copy .Deleted ))
77- return true ;
78- if (Node.hasSimpleMoveConstructor () ||
79- (Constructors.Move .Declared && !Constructors.Move .Deleted ))
80- return true ;
81- if (Node.hasSimpleCopyAssignment () ||
82- (Assignments.Copy .Declared && !Assignments.Copy .Deleted ))
83- return true ;
84- if (Node.hasSimpleMoveAssignment () ||
85- (Assignments.Move .Declared && !Assignments.Move .Deleted ))
79+ bool hasMoveAssignment (CXXRecordDecl const &Node) {
80+ if (Node.needsOverloadResolutionForMoveAssignment () &&
81+ Node.needsImplicitMoveAssignment ()) {
82+ // unresolved
83+ for (CXXBaseSpecifier const &BS : Node.bases ()) {
84+ CXXRecordDecl const *BRD = BS.getType ()->getAsCXXRecordDecl ();
85+ if (BRD != nullptr )
86+ if (!hasMoveAssignment (*BRD))
87+ return false ;
88+ }
89+ }
90+ if (Node.hasSimpleMoveAssignment ())
8691 return true ;
87-
92+ for (CXXMethodDecl const *Method : Node.methods ())
93+ if (Method->isMoveAssignmentOperator ())
94+ return !Method->isDeleted ();
8895 return false ;
8996}
9097
98+ AST_MATCHER (CXXRecordDecl, isCopyableOrMovable) {
99+ return hasCopyConstructor (Node) || hasMoveConstructor (Node) ||
100+ hasCopyAssignment (Node) || hasMoveAssignment (Node);
101+ }
102+
91103} // namespace
92104
93105void AvoidConstOrRefDataMembersCheck::registerMatchers (MatchFinder *Finder) {
0 commit comments