mirror of
https://github.com/github/codeql.git
synced 2026-04-30 19:26:02 +02:00
Merge branch 'master' into rdmarsh/cpp/ir-flow-through-outparams
This commit is contained in:
@@ -8349,3 +8349,184 @@ perf-regression.cpp:
|
||||
# 12| Type = [IntType] int
|
||||
# 12| Value = [Literal] 0
|
||||
# 12| ValueCategory = prvalue
|
||||
struct_init.cpp:
|
||||
# 1| [TopLevelFunction] int handler1(void*)
|
||||
# 1| params:
|
||||
# 1| 0: [Parameter] p
|
||||
# 1| Type = [VoidPointerType] void *
|
||||
# 2| [TopLevelFunction] int handler2(void*)
|
||||
# 2| params:
|
||||
# 2| 0: [Parameter] p
|
||||
# 2| Type = [VoidPointerType] void *
|
||||
# 4| [CopyAssignmentOperator] Info& Info::operator=(Info const&)
|
||||
# 4| params:
|
||||
#-----| 0: [Parameter] p#0
|
||||
#-----| Type = [LValueReferenceType] const Info &
|
||||
# 4| [MoveAssignmentOperator] Info& Info::operator=(Info&&)
|
||||
# 4| params:
|
||||
#-----| 0: [Parameter] p#0
|
||||
#-----| Type = [RValueReferenceType] Info &&
|
||||
# 16| [TopLevelFunction] void let_info_escape(Info*)
|
||||
# 16| params:
|
||||
# 16| 0: [Parameter] info
|
||||
# 16| Type = [PointerType] Info *
|
||||
# 16| body: [Block] { ... }
|
||||
# 17| 0: [ExprStmt] ExprStmt
|
||||
# 17| 0: [AssignExpr] ... = ...
|
||||
# 17| Type = [PointerType] Info *
|
||||
# 17| ValueCategory = lvalue
|
||||
# 17| 0: [VariableAccess] global_pointer
|
||||
# 17| Type = [PointerType] Info *
|
||||
# 17| ValueCategory = lvalue
|
||||
# 17| 1: [VariableAccess] info
|
||||
# 17| Type = [PointerType] Info *
|
||||
# 17| ValueCategory = prvalue(load)
|
||||
# 18| 1: [ReturnStmt] return ...
|
||||
# 20| [TopLevelFunction] void declare_static_infos()
|
||||
# 20| params:
|
||||
# 20| body: [Block] { ... }
|
||||
# 21| 0: [DeclStmt] declaration
|
||||
# 21| 0: [VariableDeclarationEntry] definition of static_infos
|
||||
# 21| Type = [ArrayType] Info[]
|
||||
# 21| init: [Initializer] initializer for static_infos
|
||||
# 21| expr: [ArrayAggregateLiteral] {...}
|
||||
# 21| Type = [ArrayType] Info[2]
|
||||
# 21| ValueCategory = prvalue
|
||||
# 22| [0]: [ClassAggregateLiteral] {...}
|
||||
# 22| Type = [Struct] Info
|
||||
# 22| ValueCategory = prvalue
|
||||
# 22| .name: [ArrayToPointerConversion] array to pointer conversion
|
||||
# 22| Type = [PointerType] const char *
|
||||
# 22| ValueCategory = prvalue
|
||||
# 22| expr: 1
|
||||
# 22| Type = [ArrayType] const char[2]
|
||||
# 22| Value = [StringLiteral] "1"
|
||||
# 22| ValueCategory = lvalue
|
||||
# 22| .handler: [FunctionAccess] handler1
|
||||
# 22| Type = [FunctionPointerType] ..(*)(..)
|
||||
# 22| ValueCategory = prvalue(load)
|
||||
# 23| [1]: [ClassAggregateLiteral] {...}
|
||||
# 23| Type = [Struct] Info
|
||||
# 23| ValueCategory = prvalue
|
||||
# 23| .name: [ArrayToPointerConversion] array to pointer conversion
|
||||
# 23| Type = [PointerType] const char *
|
||||
# 23| ValueCategory = prvalue
|
||||
# 23| expr: 2
|
||||
# 23| Type = [ArrayType] const char[2]
|
||||
# 23| Value = [StringLiteral] "2"
|
||||
# 23| ValueCategory = lvalue
|
||||
# 23| .handler: [AddressOfExpr] & ...
|
||||
# 23| Type = [FunctionPointerType] ..(*)(..)
|
||||
# 23| ValueCategory = prvalue
|
||||
# 23| 0: [FunctionAccess] handler2
|
||||
# 23| Type = [RoutineType] ..()(..)
|
||||
# 23| ValueCategory = lvalue
|
||||
# 25| 1: [ExprStmt] ExprStmt
|
||||
# 25| 0: [FunctionCall] call to let_info_escape
|
||||
# 25| Type = [VoidType] void
|
||||
# 25| ValueCategory = prvalue
|
||||
# 25| 0: [ArrayToPointerConversion] array to pointer conversion
|
||||
# 25| Type = [PointerType] Info *
|
||||
# 25| ValueCategory = prvalue
|
||||
# 25| expr: [VariableAccess] static_infos
|
||||
# 25| Type = [ArrayType] Info[2]
|
||||
# 25| ValueCategory = lvalue
|
||||
# 26| 2: [ReturnStmt] return ...
|
||||
# 28| [TopLevelFunction] void declare_local_infos()
|
||||
# 28| params:
|
||||
# 28| body: [Block] { ... }
|
||||
# 29| 0: [DeclStmt] declaration
|
||||
# 29| 0: [VariableDeclarationEntry] definition of local_infos
|
||||
# 29| Type = [ArrayType] Info[]
|
||||
# 29| init: [Initializer] initializer for local_infos
|
||||
# 29| expr: [ArrayAggregateLiteral] {...}
|
||||
# 29| Type = [ArrayType] Info[2]
|
||||
# 29| ValueCategory = prvalue
|
||||
# 30| [0]: [ClassAggregateLiteral] {...}
|
||||
# 30| Type = [Struct] Info
|
||||
# 30| ValueCategory = prvalue
|
||||
# 30| .name: [ArrayToPointerConversion] array to pointer conversion
|
||||
# 30| Type = [PointerType] const char *
|
||||
# 30| ValueCategory = prvalue
|
||||
# 30| expr: 1
|
||||
# 30| Type = [ArrayType] const char[2]
|
||||
# 30| Value = [StringLiteral] "1"
|
||||
# 30| ValueCategory = lvalue
|
||||
# 30| .handler: [FunctionAccess] handler1
|
||||
# 30| Type = [FunctionPointerType] ..(*)(..)
|
||||
# 30| ValueCategory = prvalue(load)
|
||||
# 31| [1]: [ClassAggregateLiteral] {...}
|
||||
# 31| Type = [Struct] Info
|
||||
# 31| ValueCategory = prvalue
|
||||
# 31| .name: [ArrayToPointerConversion] array to pointer conversion
|
||||
# 31| Type = [PointerType] const char *
|
||||
# 31| ValueCategory = prvalue
|
||||
# 31| expr: 2
|
||||
# 31| Type = [ArrayType] const char[2]
|
||||
# 31| Value = [StringLiteral] "2"
|
||||
# 31| ValueCategory = lvalue
|
||||
# 31| .handler: [AddressOfExpr] & ...
|
||||
# 31| Type = [FunctionPointerType] ..(*)(..)
|
||||
# 31| ValueCategory = prvalue
|
||||
# 31| 0: [FunctionAccess] handler2
|
||||
# 31| Type = [RoutineType] ..()(..)
|
||||
# 31| ValueCategory = lvalue
|
||||
# 33| 1: [ExprStmt] ExprStmt
|
||||
# 33| 0: [FunctionCall] call to let_info_escape
|
||||
# 33| Type = [VoidType] void
|
||||
# 33| ValueCategory = prvalue
|
||||
# 33| 0: [ArrayToPointerConversion] array to pointer conversion
|
||||
# 33| Type = [PointerType] Info *
|
||||
# 33| ValueCategory = prvalue
|
||||
# 33| expr: [VariableAccess] local_infos
|
||||
# 33| Type = [ArrayType] Info[2]
|
||||
# 33| ValueCategory = lvalue
|
||||
# 34| 2: [ReturnStmt] return ...
|
||||
# 36| [TopLevelFunction] void declare_static_runtime_infos(char const*)
|
||||
# 36| params:
|
||||
# 36| 0: [Parameter] name1
|
||||
# 36| Type = [PointerType] const char *
|
||||
# 36| body: [Block] { ... }
|
||||
# 37| 0: [DeclStmt] declaration
|
||||
# 37| 0: [VariableDeclarationEntry] definition of static_infos
|
||||
# 37| Type = [ArrayType] Info[]
|
||||
# 37| init: [Initializer] initializer for static_infos
|
||||
# 37| expr: [ArrayAggregateLiteral] {...}
|
||||
# 37| Type = [ArrayType] Info[2]
|
||||
# 37| ValueCategory = prvalue
|
||||
# 38| [0]: [ClassAggregateLiteral] {...}
|
||||
# 38| Type = [Struct] Info
|
||||
# 38| ValueCategory = prvalue
|
||||
# 38| .name: [VariableAccess] name1
|
||||
# 38| Type = [PointerType] const char *
|
||||
# 38| ValueCategory = prvalue(load)
|
||||
# 38| .handler: [FunctionAccess] handler1
|
||||
# 38| Type = [FunctionPointerType] ..(*)(..)
|
||||
# 38| ValueCategory = prvalue(load)
|
||||
# 39| [1]: [ClassAggregateLiteral] {...}
|
||||
# 39| Type = [Struct] Info
|
||||
# 39| ValueCategory = prvalue
|
||||
# 39| .name: [ArrayToPointerConversion] array to pointer conversion
|
||||
# 39| Type = [PointerType] const char *
|
||||
# 39| ValueCategory = prvalue
|
||||
# 39| expr: 2
|
||||
# 39| Type = [ArrayType] const char[2]
|
||||
# 39| Value = [StringLiteral] "2"
|
||||
# 39| ValueCategory = lvalue
|
||||
# 39| .handler: [AddressOfExpr] & ...
|
||||
# 39| Type = [FunctionPointerType] ..(*)(..)
|
||||
# 39| ValueCategory = prvalue
|
||||
# 39| 0: [FunctionAccess] handler2
|
||||
# 39| Type = [RoutineType] ..()(..)
|
||||
# 39| ValueCategory = lvalue
|
||||
# 41| 1: [ExprStmt] ExprStmt
|
||||
# 41| 0: [FunctionCall] call to let_info_escape
|
||||
# 41| Type = [VoidType] void
|
||||
# 41| ValueCategory = prvalue
|
||||
# 41| 0: [ArrayToPointerConversion] array to pointer conversion
|
||||
# 41| Type = [PointerType] Info *
|
||||
# 41| ValueCategory = prvalue
|
||||
# 41| expr: [VariableAccess] static_infos
|
||||
# 41| Type = [ArrayType] Info[2]
|
||||
# 41| ValueCategory = lvalue
|
||||
# 42| 2: [ReturnStmt] return ...
|
||||
|
||||
@@ -6272,3 +6272,131 @@ perf-regression.cpp:
|
||||
# 9| v9_7(void) = UnmodeledUse : mu*
|
||||
# 9| v9_8(void) = AliasedUse : ~mu9_4
|
||||
# 9| v9_9(void) = ExitFunction :
|
||||
|
||||
struct_init.cpp:
|
||||
# 16| void let_info_escape(Info*)
|
||||
# 16| Block 0
|
||||
# 16| v16_1(void) = EnterFunction :
|
||||
# 16| mu16_2(unknown) = AliasedDefinition :
|
||||
# 16| mu16_3(unknown) = InitializeNonLocal :
|
||||
# 16| mu16_4(unknown) = UnmodeledDefinition :
|
||||
# 16| r16_5(glval<Info *>) = VariableAddress[info] :
|
||||
# 16| mu16_6(Info *) = InitializeParameter[info] : &:r16_5
|
||||
# 16| r16_7(Info *) = Load : &:r16_5, ~mu16_6
|
||||
# 16| mu16_8(unknown) = InitializeIndirection[info] : &:r16_7
|
||||
# 17| r17_1(glval<Info *>) = VariableAddress[info] :
|
||||
# 17| r17_2(Info *) = Load : &:r17_1, ~mu16_4
|
||||
# 17| r17_3(glval<Info *>) = VariableAddress[global_pointer] :
|
||||
# 17| mu17_4(Info *) = Store : &:r17_3, r17_2
|
||||
# 18| v18_1(void) = NoOp :
|
||||
# 16| v16_9(void) = ReturnIndirection : &:r16_7, ~mu16_4
|
||||
# 16| v16_10(void) = ReturnVoid :
|
||||
# 16| v16_11(void) = UnmodeledUse : mu*
|
||||
# 16| v16_12(void) = AliasedUse : ~mu16_4
|
||||
# 16| v16_13(void) = ExitFunction :
|
||||
|
||||
# 20| void declare_static_infos()
|
||||
# 20| Block 0
|
||||
# 20| v20_1(void) = EnterFunction :
|
||||
# 20| mu20_2(unknown) = AliasedDefinition :
|
||||
# 20| mu20_3(unknown) = InitializeNonLocal :
|
||||
# 20| mu20_4(unknown) = UnmodeledDefinition :
|
||||
# 21| r21_1(glval<Info[2]>) = VariableAddress[static_infos] :
|
||||
# 21| mu21_2(Info[2]) = Uninitialized[static_infos] : &:r21_1
|
||||
# 25| r25_1(glval<unknown>) = FunctionAddress[let_info_escape] :
|
||||
# 25| r25_2(glval<Info[2]>) = VariableAddress[static_infos] :
|
||||
# 25| r25_3(Info *) = Convert : r25_2
|
||||
# 25| v25_4(void) = Call : func:r25_1, 0:r25_3
|
||||
# 25| mu25_5(unknown) = ^CallSideEffect : ~mu20_4
|
||||
# 25| v25_6(void) = ^BufferReadSideEffect[0] : &:r25_3, ~mu20_4
|
||||
# 25| mu25_7(unknown) = ^BufferMayWriteSideEffect[0] : &:r25_3
|
||||
# 26| v26_1(void) = NoOp :
|
||||
# 20| v20_5(void) = ReturnVoid :
|
||||
# 20| v20_6(void) = UnmodeledUse : mu*
|
||||
# 20| v20_7(void) = AliasedUse : ~mu20_4
|
||||
# 20| v20_8(void) = ExitFunction :
|
||||
|
||||
# 28| void declare_local_infos()
|
||||
# 28| Block 0
|
||||
# 28| v28_1(void) = EnterFunction :
|
||||
# 28| mu28_2(unknown) = AliasedDefinition :
|
||||
# 28| mu28_3(unknown) = InitializeNonLocal :
|
||||
# 28| mu28_4(unknown) = UnmodeledDefinition :
|
||||
# 29| r29_1(glval<Info[2]>) = VariableAddress[local_infos] :
|
||||
# 29| mu29_2(Info[2]) = Uninitialized[local_infos] : &:r29_1
|
||||
# 29| r29_3(int) = Constant[0] :
|
||||
# 29| r29_4(glval<Info>) = PointerAdd[16] : r29_1, r29_3
|
||||
# 30| r30_1(glval<char *>) = FieldAddress[name] : r29_4
|
||||
# 30| r30_2(glval<char[2]>) = StringConstant["1"] :
|
||||
# 30| r30_3(char *) = Convert : r30_2
|
||||
# 30| mu30_4(char *) = Store : &:r30_1, r30_3
|
||||
# 30| r30_5(glval<..(*)(..)>) = FieldAddress[handler] : r29_4
|
||||
# 30| r30_6(..(*)(..)) = FunctionAddress[handler1] :
|
||||
# 30| mu30_7(..(*)(..)) = Store : &:r30_5, r30_6
|
||||
# 29| r29_5(int) = Constant[1] :
|
||||
# 29| r29_6(glval<Info>) = PointerAdd[16] : r29_1, r29_5
|
||||
# 31| r31_1(glval<char *>) = FieldAddress[name] : r29_6
|
||||
# 31| r31_2(glval<char[2]>) = StringConstant["2"] :
|
||||
# 31| r31_3(char *) = Convert : r31_2
|
||||
# 31| mu31_4(char *) = Store : &:r31_1, r31_3
|
||||
# 31| r31_5(glval<..(*)(..)>) = FieldAddress[handler] : r29_6
|
||||
# 31| r31_6(glval<..()(..)>) = FunctionAddress[handler2] :
|
||||
# 31| r31_7(..(*)(..)) = CopyValue : r31_6
|
||||
# 31| mu31_8(..(*)(..)) = Store : &:r31_5, r31_7
|
||||
# 33| r33_1(glval<unknown>) = FunctionAddress[let_info_escape] :
|
||||
# 33| r33_2(glval<Info[2]>) = VariableAddress[local_infos] :
|
||||
# 33| r33_3(Info *) = Convert : r33_2
|
||||
# 33| v33_4(void) = Call : func:r33_1, 0:r33_3
|
||||
# 33| mu33_5(unknown) = ^CallSideEffect : ~mu28_4
|
||||
# 33| v33_6(void) = ^BufferReadSideEffect[0] : &:r33_3, ~mu28_4
|
||||
# 33| mu33_7(unknown) = ^BufferMayWriteSideEffect[0] : &:r33_3
|
||||
# 34| v34_1(void) = NoOp :
|
||||
# 28| v28_5(void) = ReturnVoid :
|
||||
# 28| v28_6(void) = UnmodeledUse : mu*
|
||||
# 28| v28_7(void) = AliasedUse : ~mu28_4
|
||||
# 28| v28_8(void) = ExitFunction :
|
||||
|
||||
# 36| void declare_static_runtime_infos(char const*)
|
||||
# 36| Block 0
|
||||
# 36| v36_1(void) = EnterFunction :
|
||||
# 36| mu36_2(unknown) = AliasedDefinition :
|
||||
# 36| mu36_3(unknown) = InitializeNonLocal :
|
||||
# 36| mu36_4(unknown) = UnmodeledDefinition :
|
||||
# 36| r36_5(glval<char *>) = VariableAddress[name1] :
|
||||
# 36| mu36_6(char *) = InitializeParameter[name1] : &:r36_5
|
||||
# 36| r36_7(char *) = Load : &:r36_5, ~mu36_6
|
||||
# 36| mu36_8(unknown) = InitializeIndirection[name1] : &:r36_7
|
||||
# 37| r37_1(glval<Info[2]>) = VariableAddress[static_infos] :
|
||||
# 37| mu37_2(Info[2]) = Uninitialized[static_infos] : &:r37_1
|
||||
# 37| r37_3(int) = Constant[0] :
|
||||
# 37| r37_4(glval<Info>) = PointerAdd[16] : r37_1, r37_3
|
||||
# 38| r38_1(glval<char *>) = FieldAddress[name] : r37_4
|
||||
# 38| r38_2(glval<char *>) = VariableAddress[name1] :
|
||||
# 38| r38_3(char *) = Load : &:r38_2, ~mu36_4
|
||||
# 38| mu38_4(char *) = Store : &:r38_1, r38_3
|
||||
# 38| r38_5(glval<..(*)(..)>) = FieldAddress[handler] : r37_4
|
||||
# 38| r38_6(..(*)(..)) = FunctionAddress[handler1] :
|
||||
# 38| mu38_7(..(*)(..)) = Store : &:r38_5, r38_6
|
||||
# 37| r37_5(int) = Constant[1] :
|
||||
# 37| r37_6(glval<Info>) = PointerAdd[16] : r37_1, r37_5
|
||||
# 39| r39_1(glval<char *>) = FieldAddress[name] : r37_6
|
||||
# 39| r39_2(glval<char[2]>) = StringConstant["2"] :
|
||||
# 39| r39_3(char *) = Convert : r39_2
|
||||
# 39| mu39_4(char *) = Store : &:r39_1, r39_3
|
||||
# 39| r39_5(glval<..(*)(..)>) = FieldAddress[handler] : r37_6
|
||||
# 39| r39_6(glval<..()(..)>) = FunctionAddress[handler2] :
|
||||
# 39| r39_7(..(*)(..)) = CopyValue : r39_6
|
||||
# 39| mu39_8(..(*)(..)) = Store : &:r39_5, r39_7
|
||||
# 41| r41_1(glval<unknown>) = FunctionAddress[let_info_escape] :
|
||||
# 41| r41_2(glval<Info[2]>) = VariableAddress[static_infos] :
|
||||
# 41| r41_3(Info *) = Convert : r41_2
|
||||
# 41| v41_4(void) = Call : func:r41_1, 0:r41_3
|
||||
# 41| mu41_5(unknown) = ^CallSideEffect : ~mu36_4
|
||||
# 41| v41_6(void) = ^BufferReadSideEffect[0] : &:r41_3, ~mu36_4
|
||||
# 41| mu41_7(unknown) = ^BufferMayWriteSideEffect[0] : &:r41_3
|
||||
# 42| v42_1(void) = NoOp :
|
||||
# 36| v36_9(void) = ReturnIndirection : &:r36_7, ~mu36_4
|
||||
# 36| v36_10(void) = ReturnVoid :
|
||||
# 36| v36_11(void) = UnmodeledUse : mu*
|
||||
# 36| v36_12(void) = AliasedUse : ~mu36_4
|
||||
# 36| v36_13(void) = ExitFunction :
|
||||
|
||||
42
cpp/ql/test/library-tests/ir/ir/struct_init.cpp
Normal file
42
cpp/ql/test/library-tests/ir/ir/struct_init.cpp
Normal file
@@ -0,0 +1,42 @@
|
||||
int handler1(void *p);
|
||||
int handler2(void *p);
|
||||
|
||||
struct Info {
|
||||
const char *name;
|
||||
int (*handler)(void *);
|
||||
};
|
||||
|
||||
static Info infos_in_file[] = {
|
||||
{ "1", handler1 },
|
||||
{ "3", &handler2 },
|
||||
};
|
||||
|
||||
Info *global_pointer;
|
||||
|
||||
void let_info_escape(Info *info) {
|
||||
global_pointer = info;
|
||||
}
|
||||
|
||||
void declare_static_infos() {
|
||||
static Info static_infos[] = {
|
||||
{ "1", handler1 },
|
||||
{ "2", &handler2 },
|
||||
};
|
||||
let_info_escape(static_infos);
|
||||
}
|
||||
|
||||
void declare_local_infos() {
|
||||
Info local_infos[] = {
|
||||
{ "1", handler1 },
|
||||
{ "2", &handler2 },
|
||||
};
|
||||
let_info_escape(local_infos);
|
||||
}
|
||||
|
||||
void declare_static_runtime_infos(const char *name1) {
|
||||
static Info static_infos[] = {
|
||||
{ name1, handler1 },
|
||||
{ "2", &handler2 },
|
||||
};
|
||||
let_info_escape(static_infos);
|
||||
}
|
||||
@@ -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())
|
||||
@@ -137,8 +137,12 @@
|
||||
| test.c:109:14:109:16 | Constant: 44 | positive strictlyPositive |
|
||||
| test.c:110:14:110:14 | Constant: 1 | positive strictlyPositive |
|
||||
| test.c:110:14:110:14 | Store: 1 | positive strictlyPositive |
|
||||
| test.c:118:20:118:20 | Uninitialized: definition of n | positive |
|
||||
| test.c:119:10:119:10 | Load: n | positive |
|
||||
| test.c:119:10:119:12 | Add: ... ++ | positive strictlyPositive |
|
||||
| test.c:119:10:119:12 | Constant: ... ++ | positive strictlyPositive |
|
||||
| test.c:119:10:119:12 | CopyValue: ... ++ | positive |
|
||||
| test.c:119:10:119:12 | Store: ... ++ | positive |
|
||||
| test.c:119:10:119:12 | Store: ... ++ | positive strictlyPositive |
|
||||
| test.c:124:11:124:15 | Load: Start | positive |
|
||||
| test.c:124:11:124:15 | Phi: Start | positive |
|
||||
|
||||
@@ -47,7 +47,6 @@ instructionWithoutSuccessor
|
||||
| ms_try_mix.cpp:11:12:11:15 | Chi: call to C |
|
||||
| ms_try_mix.cpp:28:12:28:15 | Chi: call to C |
|
||||
| ms_try_mix.cpp:48:10:48:13 | Chi: call to C |
|
||||
| pointer_to_member.cpp:36:11:36:30 | FieldAddress: {...} |
|
||||
| stmt_expr.cpp:27:5:27:15 | Store: ... = ... |
|
||||
| vla.c:5:9:5:14 | Uninitialized: definition of matrix |
|
||||
| vla.c:11:6:11:16 | UnmodeledDefinition: vla_typedef |
|
||||
|
||||
@@ -34,8 +34,6 @@ missingOperand
|
||||
| misc.c:220:3:223:3 | Store: ... = ... | Instruction 'Store' is missing an expected operand with tag 'StoreValue' in function '$@'. | misc.c:219:5:219:26 | IR: assign_designated_init | int assign_designated_init(someStruct*) |
|
||||
| misc.c:220:9:223:3 | FieldAddress: {...} | Instruction 'FieldAddress' is missing an expected operand with tag 'Unary' in function '$@'. | misc.c:219:5:219:26 | IR: assign_designated_init | int assign_designated_init(someStruct*) |
|
||||
| misc.c:220:9:223:3 | FieldAddress: {...} | Instruction 'FieldAddress' is missing an expected operand with tag 'Unary' in function '$@'. | misc.c:219:5:219:26 | IR: assign_designated_init | int assign_designated_init(someStruct*) |
|
||||
| pointer_to_member.cpp:36:13:36:19 | FieldAddress: x1 | Instruction 'FieldAddress' is missing an expected operand with tag 'Unary' in function '$@'. | pointer_to_member.cpp:32:6:32:14 | IR: pmIsConst | void pmIsConst() |
|
||||
| pointer_to_member.cpp:36:22:36:28 | Store: f1 | Instruction 'Store' is missing an expected operand with tag 'StoreValue' in function '$@'. | pointer_to_member.cpp:32:6:32:14 | IR: pmIsConst | void pmIsConst() |
|
||||
| range_analysis.c:368:10:368:21 | Store: ... ? ... : ... | Instruction 'Store' is missing an expected operand with tag 'StoreValue' in function '$@'. | range_analysis.c:355:14:355:27 | IR: test_ternary01 | unsigned int test_ternary01(unsigned int) |
|
||||
| range_analysis.c:369:10:369:36 | Store: ... ? ... : ... | Instruction 'Store' is missing an expected operand with tag 'StoreValue' in function '$@'. | range_analysis.c:355:14:355:27 | IR: test_ternary01 | unsigned int test_ternary01(unsigned int) |
|
||||
| range_analysis.c:370:10:370:38 | Store: ... ? ... : ... | Instruction 'Store' is missing an expected operand with tag 'StoreValue' in function '$@'. | range_analysis.c:355:14:355:27 | IR: test_ternary01 | unsigned int test_ternary01(unsigned int) |
|
||||
@@ -93,16 +91,6 @@ instructionWithoutSuccessor
|
||||
| ms_try_mix.cpp:48:10:48:13 | IndirectMayWriteSideEffect: call to C |
|
||||
| ms_try_mix.cpp:51:5:51:11 | ThrowValue: throw ... |
|
||||
| ms_try_mix.cpp:53:13:54:3 | NoOp: { ... } |
|
||||
| pointer_to_member.cpp:36:11:36:30 | FieldAddress: {...} |
|
||||
| pointer_to_member.cpp:36:11:36:30 | FieldAddress: {...} |
|
||||
| static_init_templates.cpp:80:27:80:36 | Convert: (void *)... |
|
||||
| static_init_templates.cpp:80:27:80:36 | Convert: (void *)... |
|
||||
| static_init_templates.cpp:89:27:89:36 | Convert: (void *)... |
|
||||
| static_init_templates.cpp:89:27:89:36 | Convert: (void *)... |
|
||||
| static_init_templates.cpp:97:27:97:36 | Convert: (void *)... |
|
||||
| static_init_templates.cpp:97:27:97:36 | Convert: (void *)... |
|
||||
| static_init_templates.cpp:105:27:105:27 | Constant: (void *)... |
|
||||
| static_init_templates.cpp:105:27:105:27 | Constant: (void *)... |
|
||||
| stmt_expr.cpp:27:5:27:15 | Store: ... = ... |
|
||||
| stmt_expr.cpp:29:11:32:11 | CopyValue: (statement expression) |
|
||||
| stmt_in_type.cpp:5:53:5:53 | Constant: 1 |
|
||||
@@ -640,9 +628,6 @@ backEdgeCountMismatch
|
||||
useNotDominatedByDefinition
|
||||
| VacuousDestructorCall.cpp:2:29:2:29 | Address | Operand 'Address' is not dominated by its definition in function '$@'. | VacuousDestructorCall.cpp:2:6:2:6 | IR: CallDestructor | void CallDestructor<int>(int, int*) |
|
||||
| misc.c:219:47:219:48 | Address | Operand 'Address' is not dominated by its definition in function '$@'. | misc.c:219:5:219:26 | IR: assign_designated_init | int assign_designated_init(someStruct*) |
|
||||
| pointer_to_member.cpp:36:11:36:30 | Unary | Operand 'Unary' is not dominated by its definition in function '$@'. | pointer_to_member.cpp:32:6:32:14 | IR: pmIsConst | void pmIsConst() |
|
||||
| pointer_to_member.cpp:36:13:36:19 | Address | Operand 'Address' is not dominated by its definition in function '$@'. | pointer_to_member.cpp:32:6:32:14 | IR: pmIsConst | void pmIsConst() |
|
||||
| pointer_to_member.cpp:36:22:36:28 | Address | Operand 'Address' is not dominated by its definition in function '$@'. | pointer_to_member.cpp:32:6:32:14 | IR: pmIsConst | void pmIsConst() |
|
||||
| try_catch.cpp:21:13:21:24 | Address | Operand 'Address' is not dominated by its definition in function '$@'. | try_catch.cpp:19:6:19:23 | IR: throw_from_nonstmt | void throw_from_nonstmt(int) |
|
||||
| vla.c:3:27:3:30 | Address | Operand 'Address' is not dominated by its definition in function '$@'. | vla.c:3:5:3:8 | IR: main | int main(int, char**) |
|
||||
switchInstructionWithoutDefaultEdge
|
||||
|
||||
@@ -56,7 +56,6 @@ instructionWithoutSuccessor
|
||||
| ms_try_mix.cpp:11:12:11:15 | IndirectMayWriteSideEffect: call to C |
|
||||
| ms_try_mix.cpp:28:12:28:15 | IndirectMayWriteSideEffect: call to C |
|
||||
| ms_try_mix.cpp:48:10:48:13 | IndirectMayWriteSideEffect: call to C |
|
||||
| pointer_to_member.cpp:36:11:36:30 | FieldAddress: {...} |
|
||||
| stmt_expr.cpp:27:5:27:15 | Store: ... = ... |
|
||||
| vla.c:5:9:5:14 | Uninitialized: definition of matrix |
|
||||
| vla.c:11:6:11:16 | UnmodeledDefinition: vla_typedef |
|
||||
|
||||
@@ -7,37 +7,65 @@
|
||||
| file://:0:0:0:0 | p#0 | file://:0:0:0:0 | const address & | SemanticStackVariable | | |
|
||||
| file://:0:0:0:0 | reg_save_area | file://:0:0:0:0 | void * | Field | | |
|
||||
| variables.cpp:1:12:1:12 | i | file://:0:0:0:0 | int | GlobalVariable | | |
|
||||
| variables.cpp:1:12:1:12 | i | file://:0:0:0:0 | int | StaticStorageDurationVariable | | |
|
||||
| variables.cpp:2:12:2:12 | i | file://:0:0:0:0 | int | GlobalVariable | | |
|
||||
| variables.cpp:2:12:2:12 | i | file://:0:0:0:0 | int | StaticStorageDurationVariable | | |
|
||||
| variables.cpp:3:12:3:12 | i | file://:0:0:0:0 | int | GlobalVariable | | |
|
||||
| variables.cpp:3:12:3:12 | i | file://:0:0:0:0 | int | StaticStorageDurationVariable | | |
|
||||
| variables.cpp:5:11:5:11 | c | file://:0:0:0:0 | const int | GlobalVariable | const | static |
|
||||
| variables.cpp:5:11:5:11 | c | file://:0:0:0:0 | const int | StaticStorageDurationVariable | const | static |
|
||||
| variables.cpp:6:14:6:15 | pi | file://:0:0:0:0 | const double | GlobalVariable | const | static |
|
||||
| variables.cpp:6:14:6:15 | pi | file://:0:0:0:0 | const double | StaticStorageDurationVariable | const | static |
|
||||
| variables.cpp:8:10:8:10 | a | file://:0:0:0:0 | unsigned int | GlobalVariable | | |
|
||||
| variables.cpp:8:10:8:10 | a | file://:0:0:0:0 | unsigned int | StaticStorageDurationVariable | | |
|
||||
| variables.cpp:10:14:10:14 | b | file://:0:0:0:0 | unsigned int | GlobalVariable | | |
|
||||
| variables.cpp:10:14:10:14 | b | file://:0:0:0:0 | unsigned int | StaticStorageDurationVariable | | |
|
||||
| variables.cpp:12:13:12:17 | kings | file://:0:0:0:0 | const char *[] | GlobalVariable | | |
|
||||
| variables.cpp:12:13:12:17 | kings | file://:0:0:0:0 | const char *[] | StaticStorageDurationVariable | | |
|
||||
| variables.cpp:14:6:14:6 | p | file://:0:0:0:0 | int * | GlobalVariable | | |
|
||||
| variables.cpp:14:6:14:6 | p | file://:0:0:0:0 | int * | StaticStorageDurationVariable | | |
|
||||
| variables.cpp:14:9:14:9 | q | file://:0:0:0:0 | int | GlobalVariable | | |
|
||||
| variables.cpp:14:9:14:9 | q | file://:0:0:0:0 | int | StaticStorageDurationVariable | | |
|
||||
| variables.cpp:15:12:15:13 | v1 | file://:0:0:0:0 | int[10] | GlobalVariable | | static |
|
||||
| variables.cpp:15:12:15:13 | v1 | file://:0:0:0:0 | int[10] | StaticStorageDurationVariable | | static |
|
||||
| variables.cpp:15:21:15:22 | pv | file://:0:0:0:0 | int * | GlobalVariable | | static |
|
||||
| variables.cpp:15:21:15:22 | pv | file://:0:0:0:0 | int * | StaticStorageDurationVariable | | static |
|
||||
| variables.cpp:17:7:17:8 | fp | file://:0:0:0:0 | ..(*)(..) | FunctionPointerVariable | | |
|
||||
| variables.cpp:17:7:17:8 | fp | file://:0:0:0:0 | ..(*)(..) | GlobalVariable | | |
|
||||
| variables.cpp:17:7:17:8 | fp | file://:0:0:0:0 | ..(*)(..) | StaticStorageDurationVariable | | |
|
||||
| variables.cpp:19:7:19:8 | v2 | file://:0:0:0:0 | float[3] | GlobalVariable | | |
|
||||
| variables.cpp:19:7:19:8 | v2 | file://:0:0:0:0 | float[3] | StaticStorageDurationVariable | | |
|
||||
| variables.cpp:20:7:20:8 | v3 | file://:0:0:0:0 | char *[32] | GlobalVariable | | |
|
||||
| variables.cpp:20:7:20:8 | v3 | file://:0:0:0:0 | char *[32] | StaticStorageDurationVariable | | |
|
||||
| variables.cpp:22:5:22:6 | d2 | file://:0:0:0:0 | int[10][20] | GlobalVariable | | |
|
||||
| variables.cpp:22:5:22:6 | d2 | file://:0:0:0:0 | int[10][20] | StaticStorageDurationVariable | | |
|
||||
| variables.cpp:24:6:24:7 | v4 | file://:0:0:0:0 | char[3] | GlobalVariable | | |
|
||||
| variables.cpp:24:6:24:7 | v4 | file://:0:0:0:0 | char[3] | StaticStorageDurationVariable | | |
|
||||
| variables.cpp:26:5:26:6 | v5 | file://:0:0:0:0 | int[8] | GlobalVariable | | |
|
||||
| variables.cpp:26:5:26:6 | v5 | file://:0:0:0:0 | int[8] | StaticStorageDurationVariable | | |
|
||||
| variables.cpp:28:7:28:8 | p2 | file://:0:0:0:0 | char * | GlobalVariable | | |
|
||||
| variables.cpp:28:7:28:8 | p2 | file://:0:0:0:0 | char * | StaticStorageDurationVariable | | |
|
||||
| variables.cpp:29:6:29:7 | p3 | file://:0:0:0:0 | char[] | GlobalVariable | | |
|
||||
| variables.cpp:29:6:29:7 | p3 | file://:0:0:0:0 | char[] | StaticStorageDurationVariable | | |
|
||||
| variables.cpp:31:6:31:10 | alpha | file://:0:0:0:0 | char[] | GlobalVariable | | |
|
||||
| variables.cpp:31:6:31:10 | alpha | file://:0:0:0:0 | char[] | StaticStorageDurationVariable | | |
|
||||
| variables.cpp:34:5:34:6 | av | file://:0:0:0:0 | int[] | GlobalVariable | | |
|
||||
| variables.cpp:34:5:34:6 | av | file://:0:0:0:0 | int[] | StaticStorageDurationVariable | | |
|
||||
| variables.cpp:35:6:35:8 | ap1 | file://:0:0:0:0 | int * | GlobalVariable | | |
|
||||
| variables.cpp:35:6:35:8 | ap1 | file://:0:0:0:0 | int * | StaticStorageDurationVariable | | |
|
||||
| variables.cpp:36:6:36:8 | ap2 | file://:0:0:0:0 | int * | GlobalVariable | | |
|
||||
| variables.cpp:36:6:36:8 | ap2 | file://:0:0:0:0 | int * | StaticStorageDurationVariable | | |
|
||||
| variables.cpp:37:6:37:8 | ap3 | file://:0:0:0:0 | int * | GlobalVariable | | |
|
||||
| variables.cpp:37:6:37:8 | ap3 | file://:0:0:0:0 | int * | StaticStorageDurationVariable | | |
|
||||
| variables.cpp:41:7:41:11 | local | file://:0:0:0:0 | char[] | LocalVariable | | |
|
||||
| variables.cpp:41:7:41:11 | local | file://:0:0:0:0 | char[] | SemanticStackVariable | | |
|
||||
| variables.cpp:43:14:43:18 | local | file://:0:0:0:0 | int | LocalVariable | | static |
|
||||
| variables.cpp:43:14:43:18 | local | file://:0:0:0:0 | int | StaticStorageDurationVariable | | static |
|
||||
| variables.cpp:48:9:48:12 | name | file://:0:0:0:0 | char * | Field | | |
|
||||
| variables.cpp:49:12:49:17 | number | file://:0:0:0:0 | long | Field | | |
|
||||
| variables.cpp:50:9:50:14 | street | file://:0:0:0:0 | char * | Field | | |
|
||||
| variables.cpp:51:9:51:12 | town | file://:0:0:0:0 | char * | Field | | |
|
||||
| variables.cpp:52:16:52:22 | country | file://:0:0:0:0 | char * | MemberVariable | | static |
|
||||
| variables.cpp:52:16:52:22 | country | file://:0:0:0:0 | char * | StaticStorageDurationVariable | | static |
|
||||
| variables.cpp:56:14:56:29 | externInFunction | file://:0:0:0:0 | int | GlobalVariable | | |
|
||||
| variables.cpp:56:14:56:29 | externInFunction | file://:0:0:0:0 | int | StaticStorageDurationVariable | | |
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
| test2.cpp:19:3:19:6 | call to free | There is a new/free mismatch between this free and the corresponding $@. | test2.cpp:18:12:18:18 | new | new |
|
||||
| test2.cpp:26:3:26:6 | call to free | There is a new/free mismatch between this free and the corresponding $@. | test2.cpp:25:7:25:13 | new | new |
|
||||
| test.cpp:36:2:36:17 | delete | There is a malloc/delete mismatch between this delete and the corresponding $@. | test.cpp:27:18:27:23 | call to malloc | malloc |
|
||||
| test.cpp:41:2:41:5 | call to free | There is a new/free mismatch between this free and the corresponding $@. | test.cpp:26:7:26:17 | new | new |
|
||||
| test.cpp:68:3:68:11 | delete | There is a malloc/delete mismatch between this delete and the corresponding $@. | test.cpp:64:28:64:33 | call to malloc | malloc |
|
||||
|
||||
36
cpp/ql/test/query-tests/Critical/NewFree/test2.cpp
Normal file
36
cpp/ql/test/query-tests/Critical/NewFree/test2.cpp
Normal file
@@ -0,0 +1,36 @@
|
||||
// semmle-extractor-options: -std=gnu++14
|
||||
|
||||
typedef unsigned long size_t;
|
||||
|
||||
void *malloc(size_t size);
|
||||
void free(void *ptr);
|
||||
|
||||
void* operator new(size_t _Size, void *_Where);
|
||||
|
||||
// ---
|
||||
|
||||
template<typename T>
|
||||
class MyTest2Class
|
||||
{
|
||||
public:
|
||||
MyTest2Class()
|
||||
{
|
||||
int *a = new int;
|
||||
free(a); // BAD
|
||||
|
||||
int *ptr_b = (int *)malloc(sizeof(int));
|
||||
int *b = new(ptr_b) int;
|
||||
free(b); // GOOD
|
||||
|
||||
c = new int;
|
||||
free(c); // BAD
|
||||
|
||||
int *ptr_d = (int *)malloc(sizeof(int));
|
||||
d = new(ptr_d) int;
|
||||
free(d); // GOOD
|
||||
}
|
||||
|
||||
int *c, *d;
|
||||
};
|
||||
|
||||
MyTest2Class<int> mt2c_i;
|
||||
Reference in New Issue
Block a user