Skip to content

Commit 30b43b9

Browse files
committed
C++: Tests for variables with ambiguous types
1 parent 228bd73 commit 30b43b9

File tree

6 files changed

+93
-0
lines changed

6 files changed

+93
-0
lines changed
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
// This header file is extracted only once even though it's included by both
2+
// file1.c and file2.c. That's presumably because it's wrongly considered to
3+
// expand to the same trap in both contexts. In practice, this header gets
4+
// extracted together with the extraction of file1.c.
5+
6+
// BUG: types of members depend on extraction order.
7+
// Only one copy of this struct is extracted, and the types of its members refer
8+
// to the typedefs in file1.c. Had file2.c been extracted first instead, the
9+
// types of its members would be different.
10+
struct UnifiableOnce {
11+
intAlias intMember;
12+
qualifiedIntAlias qualifiedIntMember;
13+
};
14+
15+
// BUG: types of parameters depend on extraction order.
16+
void functionOnce(intAlias param);
Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
// This header file is extracted twice because its inclusions in file1.c and
2+
// file2.c lead to different context hashes, seemingly because this file (unlike
3+
// extracted_once.h) refers to `structAlias`. That means the resulting trap has
4+
// two copies of all declarations in this file, and those copies have to be
5+
// unified in the trap import step or in QL.
6+
7+
// GOOD. The types of the members of this struct are unifiable, which in this
8+
// context means that they share the same unspecified types. This means that the
9+
// two extractions of the struct get the same content hash and therefore become
10+
// one entry in the database. Both struct members have multiple types in the
11+
// `membervariables` table, but those are unified in the
12+
// `MemberVariable.getType()` predicate.
13+
struct UnifiableTwice {
14+
intAlias intMember;
15+
qualifiedIntAlias qualifiedIntMember;
16+
};
17+
18+
// BUG: Non-member variables of this type have two types in the database.
19+
// The type of `structMember` is ambiguous, and the two possible types are not
20+
// unifiable, meaning in this context that they don't share an unspecified type.
21+
// The types are nevertheless _compatible_, so it's valid C (not C++) to use
22+
// these two definitions interchangably in the same program.
23+
struct NotUnifiableTwice {
24+
structAlias structMember;
25+
};
26+
27+
// BUG: The parameter of this function has two types.
28+
// Because the `MemberVariable.getType()` workaround does not apply to a
29+
// `Parameter`, this `Parameter` gets two types.
30+
void functionTwice(intAlias param);
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
// These typedefs are all _compatible_ (see
2+
// https://en.cppreference.com/w/c/language/type#Compatible_types) with their
3+
// siblings in file2.c. It varies whether they have a canonical form that's
4+
// common to them both.
5+
typedef int localInt;
6+
typedef localInt intAlias; // has common `getUnderlyingType()` and `getUnspecifiedType()`
7+
typedef int qualifiedIntAlias; // only has common `getUnspecifiedType()`
8+
typedef struct emptyStruct1 { } structAlias; // has no common type
9+
10+
#include "extracted_once.h"
11+
struct UnifiableOnce uOnce;
12+
13+
#include "extracted_twice.h"
14+
struct UnifiableTwice uTwice;
15+
struct NotUnifiableTwice nTwice; // BUG: this variable has two types
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
typedef int intAlias;
2+
typedef const int qualifiedIntAlias;
3+
typedef struct emptyStruct2 { } structAlias;
4+
5+
#include "extracted_once.h"
6+
struct UnifiableOnce uOnce;
7+
8+
#include "extracted_twice.h"
9+
struct UnifiableTwice uTwice;
10+
struct NotUnifiableTwice nTwice; // BUG: this variable has two types
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
| extracted_once.h:11:14:11:22 | intMember | file1.c:6:18:6:25 | intAlias | 1 |
2+
| extracted_once.h:12:23:12:40 | qualifiedIntMember | file1.c:7:13:7:29 | qualifiedIntAlias | 1 |
3+
| extracted_once.h:16:28:16:32 | param | file1.c:6:18:6:25 | intAlias | 1 |
4+
| extracted_twice.h:14:14:14:22 | intMember | file://:0:0:0:0 | int | 1 |
5+
| extracted_twice.h:15:23:15:40 | qualifiedIntMember | file://:0:0:0:0 | int | 1 |
6+
| extracted_twice.h:24:17:24:28 | structMember | file1.c:8:33:8:43 | structAlias | 1 |
7+
| extracted_twice.h:24:17:24:28 | structMember | file2.c:3:33:3:43 | structAlias | 1 |
8+
| extracted_twice.h:30:29:30:33 | param | file1.c:6:18:6:25 | intAlias | 2 |
9+
| extracted_twice.h:30:29:30:33 | param | file2.c:1:13:1:20 | intAlias | 2 |
10+
| file1.c:11:22:11:26 | uOnce | extracted_once.h:10:8:10:20 | UnifiableOnce | 1 |
11+
| file1.c:14:23:14:28 | uTwice | extracted_twice.h:13:8:13:21 | UnifiableTwice | 1 |
12+
| file1.c:15:26:15:31 | nTwice | extracted_twice.h:23:8:23:24 | NotUnifiableTwice | 2 |
13+
| file1.c:15:26:15:31 | nTwice | extracted_twice.h:23:8:23:24 | NotUnifiableTwice | 2 |
14+
| file2.c:6:22:6:26 | uOnce | extracted_once.h:10:8:10:20 | UnifiableOnce | 1 |
15+
| file2.c:9:23:9:28 | uTwice | extracted_twice.h:13:8:13:21 | UnifiableTwice | 1 |
16+
| file2.c:10:26:10:31 | nTwice | extracted_twice.h:23:8:23:24 | NotUnifiableTwice | 2 |
17+
| file2.c:10:26:10:31 | nTwice | extracted_twice.h:23:8:23:24 | NotUnifiableTwice | 2 |
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
import cpp
2+
3+
from Variable var
4+
where exists(var.getFile().getRelativePath())
5+
select var, var.getType(), strictcount(var.getType())

0 commit comments

Comments
 (0)