Skip to content

Commit d7f442b

Browse files
committed
C++: Force unique resolveClass results
1 parent b633ee1 commit d7f442b

File tree

3 files changed

+18
-21
lines changed

3 files changed

+18
-21
lines changed

cpp/ql/src/semmle/code/cpp/internal/ResolveClass.qll

Lines changed: 13 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,23 +1,28 @@
11
import semmle.code.cpp.Type
22

3-
/** Holds if `d` is a complete class named `name`. */
3+
pragma[noinline]
4+
private string getTopLevelClassName(@usertype c) {
5+
isClass(c) and
6+
usertypes(c, result, _)
7+
}
8+
9+
/** Holds if `d` is a unique complete class named `name`. */
410
pragma[noinline]
511
private predicate existsCompleteWithName(string name, @usertype d) {
6-
isClass(d) and
712
is_complete(d) and
8-
usertypes(d, name, _)
13+
name = getTopLevelClassName(d) and
14+
strictcount(@usertype other | is_complete(other) and getTopLevelClassName(other) = name) = 1
915
}
1016

1117
/** Holds if `c` is an incomplete class named `name`. */
1218
pragma[noinline]
1319
private predicate existsIncompleteWithName(string name, @usertype c) {
14-
isClass(c) and
1520
not is_complete(c) and
16-
usertypes(c, name, _)
21+
name = getTopLevelClassName(c)
1722
}
1823

1924
/**
20-
* Holds if `c` is an imcomplete class, and there exists a complete class `d`
25+
* Holds if `c` is an imcomplete class, and there exists a unique complete class `d`
2126
* with the same name.
2227
*/
2328
private predicate hasCompleteTwin(@usertype c, @usertype d) {
@@ -30,10 +35,8 @@ private predicate hasCompleteTwin(@usertype c, @usertype d) {
3035
import Cached
3136
cached private module Cached {
3237
/**
33-
* If `c` is incomplete, and there exists a complete class with the same name,
34-
* then the result is that complete class. Otherwise, the result is `c`. If
35-
* multiple complete classes have the same name, this predicate may have
36-
* multiple results.
38+
* If `c` is incomplete, and there exists a unique complete class with the same name,
39+
* then the result is that complete class. Otherwise, the result is `c`.
3740
*/
3841
cached @usertype resolveClass(@usertype c) {
3942
hasCompleteTwin(c, result)
Lines changed: 3 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,7 @@
1-
| a.h:5:8:5:13 | cheese | x.cpp:6:10:6:12 | Foo | 3 |
2-
| a.h:5:8:5:13 | cheese | x.cpp:12:9:12:11 | Foo | 3 |
1+
| a.h:5:8:5:13 | cheese | a.h:2:8:2:10 | Foo | 0 |
32
| a.h:5:8:5:13 | cheese | y.cpp:4:8:4:10 | Foo | 3 |
43
| x.cpp:3:6:3:10 | bar_x | a.h:4:8:4:10 | Bar | 3 |
5-
| x.cpp:19:6:19:10 | foo_x | x.cpp:6:10:6:12 | Foo | 3 |
6-
| x.cpp:19:6:19:10 | foo_x | x.cpp:12:9:12:11 | Foo | 3 |
7-
| x.cpp:19:6:19:10 | foo_x | y.cpp:4:8:4:10 | Foo | 3 |
4+
| x.cpp:19:6:19:10 | foo_x | a.h:2:8:2:10 | Foo | 0 |
85
| x.cpp:23:5:23:17 | templateField | x.cpp:6:10:6:12 | Foo | 3 |
96
| x.cpp:23:5:23:17 | templateField | x.cpp:12:9:12:11 | Foo | 3 |
10-
| x.cpp:26:18:26:29 | template_foo | x.cpp:22:7:22:14 | Template<Foo *> | 3 |
11-
| x.cpp:26:18:26:29 | template_foo | x.cpp:22:7:22:14 | Template<Foo *> | 3 |
7+
| x.cpp:26:18:26:29 | template_foo | x.cpp:22:7:22:14 | Template<Foo *> | 0 |
Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,4 @@
1-
| decls.cpp:4:6:4:6 | x | defs.cpp:2:9:2:9 | C |
2-
| decls.cpp:4:6:4:6 | x | defs.cpp:7:9:7:9 | C |
1+
| decls.cpp:4:6:4:6 | x | decls.cpp:2:9:2:9 | C |
32
| defs.cpp:18:21:18:38 | definedAndDeclared | defs.cpp:11:7:11:24 | DefinedAndDeclared |
4-
| defs.cpp:25:28:25:32 | mdbsh | c1.cpp:3:8:3:32 | MultipleDefsButSameHeader |
5-
| defs.cpp:25:28:25:32 | mdbsh | c2.cpp:3:8:3:32 | MultipleDefsButSameHeader |
3+
| defs.cpp:25:28:25:32 | mdbsh | header.h:1:8:1:32 | MultipleDefsButSameHeader |
64
| defs.cpp:29:24:29:28 | odidf | c1.cpp:7:8:7:28 | OneDefInDifferentFile |

0 commit comments

Comments
 (0)