-
Notifications
You must be signed in to change notification settings - Fork 76
Expand file tree
/
Copy pathUnusedLocalFunctionOld.ql
More file actions
110 lines (102 loc) · 4.41 KB
/
UnusedLocalFunctionOld.ql
File metadata and controls
110 lines (102 loc) · 4.41 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
/**
* @id cpp/autosar/unused-local-function
* @name A0-1-3: Unused local function
* @description Every function defined in an anonymous namespace, or static function with internal
* linkage, or private member function shall be used.
* @kind problem
* @precision very-high
* @problem.severity warning
* @tags external/autosar/id/a0-1-3
* readability
* maintainability
* external/autosar/allocated-target/implementation
* external/autosar/enforcement/automated
* external/autosar/obligation/required
*/
import cpp
import codingstandards.cpp.autosar
import codingstandards.cpp.DynamicCallGraph
import codingstandards.cpp.deadcode.UnusedFunctions
/**
* Checks if an overloaded function of
* the function passed in the arguments, is called.
*/
predicate overloadedFunctionIsCalled(Function unusedFunction) {
exists(Function f | f = unusedFunction.getAnOverload() and f = getTarget(_))
}
/** Checks if a Function's address was taken. */
predicate addressBeenTaken(Function unusedFunction) {
exists(FunctionAccess fa | fa.getTarget() = unusedFunction)
}
/** A `Function` nested in an anonymous namespace. */
class AnonymousNamespaceFunction extends Function {
AnonymousNamespaceFunction() { getNamespace().getParentNamespace*().isAnonymous() }
}
/**
* A function which is "local" to a particular scope or translation unit.
*/
class LocalFunction extends UnusedFunctions::UsableFunction {
string localFunctionType;
LocalFunction() {
this.(MemberFunction).isPrivate() and
localFunctionType = "Private member"
or
// A function in an anonymous namespace (which is deduced to have internal linkage)
this instanceof AnonymousNamespaceFunction and
// Not member functions, which don't have internal linkage
not this instanceof MemberFunction and
localFunctionType = "Anonymous namespace"
or
// Static functions with internal linkage
this.isStatic() and
// Member functions never have internal linkage
not this instanceof MemberFunction and
// Functions in anonymous namespaces automatically have the "static" specifier added by the
// extractor. We therefore excluded them from this case, and instead report them in the
// anonymous namespace, as we don't know whether the "static" specifier was explicitly
// provided by the user.
not this instanceof AnonymousNamespaceFunction and
localFunctionType = "Static"
}
/** Gets the type of local function. */
string getLocalFunctionType() { result = localFunctionType }
}
from LocalFunction unusedLocalFunction, string name
where
not isExcluded(unusedLocalFunction, DeadCodePackage::unusedLocalFunctionQuery()) and
// No static or dynamic call target for this function
not unusedLocalFunction = getTarget(_) and
// If this is a TemplateFunction or an instantiation of a template, then only report it as unused
// if all other instantiations of the template are unused
not exists(
Function functionFromUninstantiatedTemplate, Function functionFromInstantiatedTemplate
|
// `unusedLocalFunction` is a template instantiation from `functionFromUninstantiatedTemplate`
unusedLocalFunction.isConstructedFrom(functionFromUninstantiatedTemplate)
or
// `unusedLocalFunction` is from an uninstantiated template
unusedLocalFunction = functionFromUninstantiatedTemplate
|
// There exists an instantiation which is called
functionFromInstantiatedTemplate.isConstructedFrom(functionFromUninstantiatedTemplate) and
functionFromInstantiatedTemplate = getTarget(_)
) and
// A function is defined as "used" if any one of the following holds true:
// - It's an explicitly deleted functions e.g. =delete
// - It's annotated as "[[maybe_unused]]"
// - It's part of an overloaded set and any one of the overloaded instance
// is called.
// - It's an operand of an expression in an unevaluated context.
not unusedLocalFunction.isDeleted() and
not unusedLocalFunction.getAnAttribute().getName() = "maybe_unused" and
not overloadedFunctionIsCalled(unusedLocalFunction) and
not addressBeenTaken(unusedLocalFunction) and
// Get a printable name
(
if exists(unusedLocalFunction.getQualifiedName())
then name = unusedLocalFunction.getQualifiedName()
else name = unusedLocalFunction.getName()
)
select unusedLocalFunction,
unusedLocalFunction.getLocalFunctionType() + " function " + name +
" is not statically called, or is in an unused template."