-
Notifications
You must be signed in to change notification settings - Fork 76
Expand file tree
/
Copy pathAnalyzableClass.qll
More file actions
112 lines (94 loc) · 3.29 KB
/
AnalyzableClass.qll
File metadata and controls
112 lines (94 loc) · 3.29 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
import cpp
private predicate isUsable(MemberFunction f) {
not f.isDeleted() and
f.isPublic()
}
private predicate isMemberCustomized(MemberFunction f) {
exists(f.getDefinition()) and
not f.isDefaulted() and
not f.isDeleted() and
not f.isCompilerGenerated()
}
private predicate isUserDeclared(MemberFunction f) { not f.isCompilerGenerated() }
/**
* Holds if the implicit move constructor or move assignment operator of the class `c` will not be
* declared.
*
* See [class.copy]/8 and [class.copy]
*/
private predicate implicitMoveIsSuppressed(Class c) {
isUserDeclared(c.getAConstructor().(CopyConstructor))
or
isUserDeclared(c.getAConstructor().(CopyAssignmentOperator))
or
isUserDeclared(c.getDestructor())
}
Constructor getMoveConstructor(Class c) {
if
not exists(MoveConstructor mc | mc = c.getAConstructor() and isUserDeclared(mc)) and
implicitMoveIsSuppressed(c)
then result = c.getAConstructor().(CopyConstructor)
else result = c.getAConstructor().(MoveConstructor)
}
Operator getMoveAssign(Class c) {
if
not exists(MoveAssignmentOperator mc | mc = c.getAMemberFunction() and isUserDeclared(mc)) and
implicitMoveIsSuppressed(c)
then result = c.getAMemberFunction().(CopyAssignmentOperator)
else result = c.getAMemberFunction().(MoveAssignmentOperator)
}
newtype TSpecialMember =
TMoveConstructor() or
TMoveAssignmentOperator() or
TCopyConstructor() or
TCopyAssignmentOperator() or
TDestructor()
class AnalyzableClass extends Class {
CopyConstructor copyCtor;
// The move constructor may be suppressed, and the copy constructor may be used during moves.
Constructor moveCtor;
CopyAssignmentOperator copyAssign;
// The move assignment operator may be suppressed, and the copy assignment operator may be used during moves.
Operator moveAssign;
Destructor dtor;
AnalyzableClass() {
copyCtor = this.getAConstructor() and
moveCtor = getMoveConstructor(this) and
copyAssign = this.getAMemberFunction() and
moveAssign = getMoveAssign(this) and
dtor = this.getDestructor()
}
predicate exposes(TSpecialMember m) {
m instanceof TMoveConstructor and moveConstructible()
or
m instanceof TMoveAssignmentOperator and moveAssignable()
or
m instanceof TCopyConstructor and copyConstructible()
or
m instanceof TCopyAssignmentOperator and copyAssignable()
or
m instanceof TDestructor and destructible()
}
predicate moveConstructible() { isUsable(moveCtor) }
predicate copyConstructible() { isUsable(copyCtor) }
predicate moveAssignable() { isUsable(moveAssign) }
predicate copyAssignable() { isUsable(copyAssign) }
predicate destructible() { isUsable(dtor) }
predicate isCustomized(TSpecialMember s) {
s instanceof TMoveConstructor and
isMemberCustomized(moveCtor) and
declaresMoveConstructor()
or
s instanceof TMoveAssignmentOperator and
isMemberCustomized(moveAssign) and
declaresMoveAssignmentOperator()
or
s instanceof TCopyConstructor and isMemberCustomized(copyCtor)
or
s instanceof TCopyAssignmentOperator and isMemberCustomized(copyAssign)
or
s instanceof TDestructor and isMemberCustomized(dtor)
}
predicate declaresMoveConstructor() { not moveCtor = copyCtor }
predicate declaresMoveAssignmentOperator() { not moveAssign = copyAssign }
}