forked from github/codeql-coding-standards
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathMemberFunctionConstIfPossible.ql
More file actions
138 lines (126 loc) · 4.1 KB
/
MemberFunctionConstIfPossible.ql
File metadata and controls
138 lines (126 loc) · 4.1 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
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
/**
* @id cpp/autosar/member-function-const-if-possible
* @name M9-3-3: A member function shall be made const where possible
* @description Using `const` specifiers for member functions where possible prevents unintentional
* data modification (and therefore unintentional program behaviour).
* @kind problem
* @precision high
* @problem.severity warning
* @tags external/autosar/id/m9-3-3
* correctness
* external/autosar/allocated-target/implementation
* external/autosar/enforcement/automated
* external/autosar/obligation/required
*/
import cpp
import codingstandards.cpp.autosar
import codingstandards.cpp.SideEffect
/**
* `Declaration` is declared in `Class` c
* or any of c's parents
*/
predicate belongsToClass(Declaration m, Class c) {
m.getDeclaringType() = c
or
exists(Class anyParent |
m.getDeclaringType() = anyParent and
anyParent.getADerivedClass+() = c
)
}
/**
* `MemberFunction`s that are not const
*/
class NonConstMemberFunction extends MemberFunction {
NonConstMemberFunction() { not this.hasSpecifier("const") }
}
/**
* References that are not const
*/
class NonConstReferenceType extends ReferenceType {
NonConstReferenceType() { not this.isConst() }
}
/**
* `MemberFunction`s that are not const
* and not `Constructor`s ect as const constructors are
* not a thing in cpp
* also not static because there is no `this` in
* static `MemberFunction`
*/
class ConstMemberFunctionCandidate extends NonConstMemberFunction {
ConstMemberFunctionCandidate() {
//can't be const if already static
not this.isStatic() and
//leave compiler generateds and operators and constructors alone
not this.isCompilerGenerated() and
not this instanceof Constructor and
not this instanceof Destructor and
not this instanceof Operator and
//less interested in MemberFunctions with no definition
this.hasDefinition() and
// For uninstantiated templates we have only partial information that prevents us from determining
// if the candidate calls non-const functions. Therefore we exclude these.
not this.isFromUninstantiatedTemplate(_) and
// Cannot recommend const if it returns a non-const reference.
not this.getType() instanceof NonConstReferenceType
}
/**
* A `MemberVariable` is modified in this `MemberFunction`
* directly
*/
predicate modifiesMemberData() {
exists(VariableEffect e, NonStaticMemberVariable v |
e.getTarget() = v and
this = e.getEnclosingFunction() and
belongsToClass(v, this.getDeclaringType())
)
}
/**
* Calls a `MemberFunction` that it owns that is nonconst
*/
predicate callsNonConstOwnMember() {
exists(NonConstMemberFunction f |
//omit recursive functions
not f = this and
belongsToClass(f, this.getDeclaringType()) and
f.getACallToThisFunction().getEnclosingFunction() = this
)
}
/**
* Calls any nonconst `MemberFunction` that its `MemberVariable`s own
*/
predicate callsNonConstFromMemberVariable() {
exists(NonConstMemberFunction f, MemberVariable m |
belongsToClass(m, f.getDeclaringType()) and
belongsToClass(f, m.getDeclaringType()) and
f.getACallToThisFunction().getEnclosingFunction() = this
)
}
/**
* `ThisExpr`s that are on left hand side
* of `AssignExpr`s
* example: `*this = *i;`
*/
predicate modifiesThis() { exists(AssignExprToThis e | e.getEnclosingFunction() = this) }
}
class AssignExprToThis extends AssignExpr {
AssignExprToThis() {
exists(ThisExpr t | this.getLValue().(PointerDereferenceExpr).getOperand() = t)
}
}
/**
* A nonstatic `MemberVariable`
*/
class NonStaticMemberVariable extends MemberVariable {
NonStaticMemberVariable() { not this.isStatic() }
}
from ConstMemberFunctionCandidate f
where
not isExcluded(f, ConstPackage::memberFunctionConstIfPossibleQuery()) and
not f.modifiesMemberData() and
not f.modifiesThis() and
not f.callsNonConstOwnMember() and
not f.callsNonConstFromMemberVariable() and
not f.isOverride() and
not f.isFinal() and
not f.isDeleted()
select f, "Member function can be declared as const."