8000 C++: Ensure that only one `Function` exists for every function · github/codeql@bdb4d3c · GitHub
[go: up one dir, main page]

Skip to content

Commit bdb4d3c

Browse files
committed
C++: Ensure that only one Function exists for every function
1 parent 6831775 commit bdb4d3c

File tree

4 files changed

+61
-1
lines changed

4 files changed

+61
-1
lines changed

cpp/ql/lib/semmle/code/cpp/Element.qll

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ import semmle.code.cpp.Location
77
private import semmle.code.cpp.Enclosing
88
private import semmle.code.cpp.internal.ResolveClass
99
private import semmle.code.cpp.internal.ResolveGlobalVariable
10+
private import semmle.code.cpp.internal.ResolveFunction
1011

1112
/**
1213
* Get the `Element` that represents this `@element`.
@@ -30,11 +31,14 @@ pragma[inline]
3031
@element unresolveElement(Element e) {
3132
not result instanceof @usertype and
3233
not result instanceof @variable and
34+
not result instanceof @function and
3335
result = e
3436
or
3537
e = resolveClass(result)
3638
or
3739
e = resolveGlobalVariable(result)
40+
or
41+
e = resolveFunction(result)
3842
}
3943

4044
/**

cpp/ql/lib/semmle/code/cpp/Function.qll

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ import semmle.code.cpp.exprs.Call
99
import semmle.code.cpp.metrics.MetricFunction
1010
import semmle.code.cpp.Linkage
1111
private import semmle.code.cpp.internal.ResolveClass
12+
private import semmle.code.cpp.internal.ResolveFunction
1213

1314
/**
1415
* A C/C++ function [N4140 8.3.5]. Both member functions and non-member
@@ -25,6 +26,8 @@ private import semmle.code.cpp.internal.ResolveClass
2526
* in more detail in `Declaration.qll`.
2627
*/
2728
class Function extends Declaration, ControlFlowNode, AccessHolder, @function {
29+
Function() { isFunction(underlyingElement(this)) }
30+
2831
override string getName() { functions(underlyingElement(this), result, _) }
2932

3033
/**

cpp/ql/lib/semmle/code/cpp/controlflow/internal/ConstantExprs.qll

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -122,7 +122,7 @@ private predicate isFunction(Element el) {
122122
*/
123123
pragma[noopt]
124124
private predicate callHasNoTarget(@funbindexpr fc) {
125-
exists(Function f |
125+
exists(@function f |
126126
funbind(fc, f) and
127127
not isFunction(f)
128128
)
Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
private predicate hasDefinition(@function f) {
2+
exists(@fun_decl fd | fun_decls(fd, f, _, _, _) | fun_def(fd))
3+
}
4+
5+
private predicate onlyOneCompleteFunctionExistsWithMangledName(@mangledname name) {
6+
strictcount(@function f | hasDefinition(f) and mangled_name(f, name)) = 1
7+
}
8+
9+
/** Holds if `f` is a unique function with a definition named `name`. */
10+
private predicate isFunctionWithMangledNameAndWithDefinition(@mangledname name, @function f) {
11+
hasDefinition(f) and
12+
mangled_name(f, name) and
13+
onlyOneCompleteFunctionExistsWithMangledName(name)
14+
}
15+
16+
/** Holds if `f` is a function without a definition named `name`. */
17+
private predicate isFunctionWithMangledNameAndWithoutDefinition(@mangledname name, @function f) {
18+
not hasDefinition(f) and
19+
mangled_name(f, name)
20+
}
21+
22+
/**
23+
* Holds if `incomplete` is a function without a definition, and there exists
24+
* a unique function `complete` with the same name that does have a definition.
25+
*/
26+
private predicate hasTwinWithDefinition(@function incomplete, @function complete) {
27+
exists(@mangledname name |
28+
not function_instantiation(incomplete, complete) and
29+
isFunctionWithMangledNameAndWithoutDefinition(name, incomplete) and
30+
isFunctionWithMangledNameAndWithDefinition(name, complete)
31+
)
32+
}
33+
34+
import Cached
35+
36+
cached
37+
private module Cached {
38+
/**
39+
* If `f` is a function without a definition, and there exists a unique
40+
* function with the same name that does have a definition, then the
41+
* result is that unique function. Otherwise, the result is `f`.
42+
*/
43+
cached
44+
@function resolveFunction(@function f) {
45+
hasTwinWithDefinition(f, result)
46+
or
47+
not hasTwinWithDefinition(f, _) and
48+
result = f
49+
}
50+
51+
cached
52+
predicate isFunction(@function f) { f = resolveFunction(_) }
53+
}

0 commit comments

Comments
 (0)
0