Merge pull request #2970 from jbj/multiple-types-test

C++: Tests for variables with ambiguous types
This commit is contained in:
Mathias Vorreiter Pedersen
2020-03-11 09:53:59 +01:00
committed by GitHub
6 changed files with 93 additions and 0 deletions

View File

@@ -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);

View File

@@ -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);

View File

@@ -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

View File

@@ -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

View File

@@ -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 |

View File

@@ -0,0 +1,5 @@
import cpp
from Variable var
where exists(var.getFile().getRelativePath())
select var, var.getType(), strictcount(var.getType())