Skip to content

Commit a79754b

Browse files
committed
C++: Resolve functions using complete mangled names
1 parent 972d86c commit a79754b

File tree

3 files changed

+64
-0
lines changed

3 files changed

+64
-0
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
/**
Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
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, true)) = 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, true) 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, true)
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+
not function_instantiation(incomplete, complete) and
28+
(
29+
not compgenerated(incomplete) or
30+
not compgenerated(complete)
31+
) and
32+
exists(@mangledname name |
33+
isFunctionWithMangledNameAndWithoutDefinition(name, incomplete) and
34+
isFunctionWithMangledNameAndWithDefinition(name, complete)
35+
)
36+
}
37+
38+
import Cached
39+
40+
cached
41+
private module Cached {
42+
/**
43+
* If `f` is a function without a definition, and there exists a unique
44+
* function with the same name that does have a definition, then the
45+
* result is that unique function. Otherwise, the result is `f`.
46+
*/
47+
cached
48+
@function resolveFunction(@function f) {
49+
hasTwinWithDefinition(f, result)
50+
or
51+
not hasTwinWithDefinition(f, _) and
52+
result = f
53+
}
54+
55+
cached
56+
predicate isFunction(@function f) { f = resolveFunction(_) }
57+
}

0 commit comments

Comments
 (0)