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