Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add Interval Set domain for Interval Set analysis #966

Closed
wants to merge 104 commits into from
Closed
Show file tree
Hide file tree
Changes from 99 commits
Commits
Show all changes
104 commits
Select commit Hold shift + click to select a range
0e916c8
Implement skeleton of IntervalSet
BilelGho Nov 17, 2022
bf4f2ea
add helper functions
mfarider Nov 17, 2022
b9b018d
add leq
mfarider Nov 17, 2022
943e7dd
Implementing meet and join using sweeping line algorithm
BilelGho Nov 24, 2022
c60c215
add add
mfarider Nov 17, 2022
2641114
add mul
mfarider Nov 17, 2022
44d9c18
add sub
mfarider Nov 17, 2022
b528e06
implement `show` function for `IntervalSetFunctor`
gabryon99 Nov 24, 2022
7af0cc9
implement bottom
BilelGho Nov 24, 2022
94449e9
fix type error for IntervalSetFunctor.mul function
gabryon99 Nov 24, 2022
4118f12
re-implementing arithmetic operations based on IntervalSet ones
gabryon99 Nov 24, 2022
73671a4
implements remaining binary and unary operators for IntervalSetFunctor
gabryon99 Dec 8, 2022
f228575
add analysis support for interval_set
gabryon99 Dec 8, 2022
63acd73
fix description
gabryon99 Dec 22, 2022
57b333b
fixup! Implement skeleton of IntervalSet
BilelGho Nov 24, 2022
78ced0f
implement canonize
BilelGho Nov 24, 2022
a51db3c
implement cast_to
BilelGho Nov 24, 2022
9b102c3
implement refine_with_interval
BilelGho Nov 30, 2022
6a49d68
implement refine_with_incl_list
BilelGho Nov 30, 2022
9e9091a
implement refine_with_excl_list
BilelGho Nov 30, 2022
2b65e9c
implement invariant_ikind
BilelGho Dec 1, 2022
1b549cd
implement refine with congruence
BilelGho Dec 7, 2022
48f4be5
implement widen
BilelGho Dec 7, 2022
f9aec6f
implement project
BilelGho Dec 7, 2022
de2c921
implement arbitrary
BilelGho Dec 7, 2022
2280b42
implement narrow
BilelGho Dec 23, 2022
307e8a8
add TODO
BilelGho Dec 23, 2022
b8e0312
Running Interval Set Analysis and fixing bugs
gabryon99 Dec 23, 2022
4bcb0de
Fix and fix
gabryon99 Dec 23, 2022
96efa73
remove duplicates
BilelGho Dec 24, 2022
8ae5c91
consider the possibility of an op returning None
BilelGho Dec 24, 2022
05031db
fixup! gt
BilelGho Dec 24, 2022
14338ce
implement minimal
BilelGho Jan 6, 2023
cd47a76
implement narrow
BilelGho Jan 6, 2023
8410e44
fix refine_with_congruence
BilelGho Jan 6, 2023
b48045a
fix refine_with_incl_list
BilelGho Jan 6, 2023
25c188e
fix refine_with_excl_range+implement of_excl_list
BilelGho Jan 6, 2023
fdd71dd
Copied interval tests as new tests for Interval Sets
gabryon99 Jan 6, 2023
cfbf731
support wrap around
BilelGho Jan 6, 2023
526b1fd
test support for wrap around
BilelGho Jan 6, 2023
05582ed
Fixing overflow checks for IntDomTuple
gabryon99 Jan 5, 2023
075bc9f
remove extra maximal and minimal
gabryon99 Jan 6, 2023
0812401
Cleaning code
gabryon99 Jan 12, 2023
243967e
fixup! Cleanup code
BilelGho Jan 26, 2023
80eb43b
Add IntervalSetFunctor to intDomain.mli interface
gabryon99 Jan 12, 2023
38f9e5d
fix removeAttr name in int_precision_from_fundec
gabryon99 Jan 21, 2023
109df62
Update interval_set and interval descriptions inside schema
gabryon99 Jan 21, 2023
7681047
fix comment typo in precisionUtil.ml
gabryon99 Jan 21, 2023
32d2148
Re-use of Interval.leq and Interval.join
gabryon99 Jan 21, 2023
4d0e05c
Re-use of Interval.invariant_ikind
gabryon99 Jan 21, 2023
8defb6a
Remove _functor suffix from Interval_functor
gabryon99 Jan 21, 2023
831ddb4
Optimize getting last list element
gabryon99 Jan 21, 2023
6d96c31
run ocp-indent of intDomain.ml
gabryon99 Jan 21, 2023
11e332a
Replace physical inequality with structural one
gabryon99 Jan 21, 2023
cf5d31f
Remove extra `of_bool` function and rename unused parameter
gabryon99 Jan 21, 2023
a628462
remove useless comment
gabryon99 Jan 21, 2023
345e9e8
Replace custom `cartesian_product` with `BatList.cartesian_product`
gabryon99 Jan 21, 2023
acaa510
optimize getting last element list
gabryon99 Jan 21, 2023
0d8aa78
Use of List.concat_map
gabryon99 Jan 21, 2023
72e342b
Move `set_overflow_flag` at the top of `intdDomain.ml`
gabryon99 Jan 23, 2023
e60dab2
Improving running time complexity for `two_interval_sets_to_events`
gabryon99 Jan 23, 2023
dabad42
Define `refine_with_congruence_interval` within `refine_with_congruence`
gabryon99 Jan 23, 2023
899ceb2
Move `excl_to_intervalset` within `refine_with_excli_list`
gabryon99 Jan 23, 2023
7b79fa4
Add comment on IntervalSets elements
gabryon99 Jan 23, 2023
2332c93
implement threshold widening
BilelGho Jan 23, 2023
02a2d1f
undo skip test
BilelGho Jan 23, 2023
4a85e35
include new domain for unit tests
BilelGho Jan 23, 2023
22fdebc
update leq to be linear in time complexity.
BilelGho Jan 24, 2023
ba83ff4
Implementing arithmetic functions from IntervalFunctor
gabryon99 Jan 24, 2023
0fbfd1f
Formatting code
gabryon99 Jan 24, 2023
d32dbe5
Rename `norm` function into `norm_interval`
gabryon99 Jan 24, 2023
cad5f7b
Rename `remove_gaps` into `remove_empty_gaps`
gabryon99 Jan 24, 2023
32859cd
use minimal/maximal instead of lhs_rhs_boundaries
BilelGho Jan 24, 2023
b8873fc
create a not_bool function to eliminate boilerplate
BilelGho Jan 26, 2023
9eed3e5
enable suppress overflow warning
BilelGho Jan 26, 2023
01d9554
refactor widen and add comments
BilelGho Jan 26, 2023
6991f58
0-pad test filenames
BilelGho Jan 26, 2023
eb56b02
test: dead code with fun call
mfarider Feb 2, 2023
a23145f
Fix sum function signature in 65/58
gabryon99 Feb 3, 2023
33e5031
pass down the suppress_ovflow argument
BilelGho Feb 1, 2023
8414268
disable intervalSet in recursive calls
BilelGho Feb 1, 2023
f52c817
Remove inner function in IntervalFunctor
gabryon99 Feb 2, 2023
c31c854
centralize overflow calls
BilelGho Feb 3, 2023
6e604f7
make the use of should_ignore_overflow consistent
BilelGho Feb 7, 2023
6c2eced
rename regression test folders
BilelGho Feb 16, 2023
fbebec6
delete script file for renaming test files
BilelGho Feb 16, 2023
6e4ab8e
simplify defintions of helper functions
BilelGho Feb 16, 2023
c271642
get rid of unnecessary ik parameter passing
BilelGho Feb 16, 2023
cbb67f7
inline functions that are used only once
BilelGho Feb 16, 2023
5fe688b
add comment for narrow
BilelGho Feb 16, 2023
249adbf
move misplaced comment
BilelGho Feb 16, 2023
ab0348b
use better wording in comment
BilelGho Feb 16, 2023
9bc0976
refactor var name
BilelGho Feb 16, 2023
de255b5
reuse maximal and minimal
BilelGho Feb 16, 2023
bfd6995
refactor rename var names
BilelGho Feb 16, 2023
39ee471
refactor: add line seperators
BilelGho Feb 16, 2023
1aa9c3e
refactor: reword comment
BilelGho Feb 16, 2023
df511e2
remove unused function
BilelGho Feb 16, 2023
79f7215
run ocp-indent
BilelGho Feb 16, 2023
e56213c
add more line sperators for readability
BilelGho Feb 16, 2023
15edd12
refactor code style/ identation
BilelGho Feb 16, 2023
d188f79
add line sperators
BilelGho Feb 16, 2023
3c37e6f
remove redundant space
BilelGho Feb 16, 2023
7f9b684
fix unit tests
BilelGho Feb 16, 2023
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 7 additions & 4 deletions docs/user-guide/annotating.md
Original file line number Diff line number Diff line change
Expand Up @@ -21,10 +21,13 @@ The attribute `goblint_context` can be used to fine-tune function contexts.
The following string arguments are supported:

1. `base.interval`/`base.no-interval` to override the `ana.base.context.interval` option.
2. `base.int`/`base.no-int` to override the `ana.base.context.interval` option.
3. `base.non-ptr`/`base.no-non-ptr` to override the `ana.base.context.non-ptr` option.
4. `relation.context`/`relation.no-context` to override the `ana.relation.context` option.
5. `widen`/`no-widen` to override the `ana.context.widen` option.
2. `base.interval_set`/`base.no-interval_set` to override the `ana.base.context.interval_set` option.
3. `base.int`/`base.no-int` to override the `ana.base.context.interval` option.
4. `base.non-ptr`/`base.no-non-ptr` to override the `ana.base.context.non-ptr` option.
5. `relation.context`/`relation.no-context` to override the `ana.relation.context` option.
6. `widen`/`no-widen` to override the `ana.context.widen` option.



### Apron attributes
The Apron library can be set to only track variables with the attribute `goblint_apron_track`
Expand Down
3 changes: 3 additions & 0 deletions src/analyses/base.ml
Original file line number Diff line number Diff line change
Expand Up @@ -595,6 +595,8 @@ struct

let drop_interval = CPA.map (function `Int x -> `Int (ID.no_interval x) | x -> x)

let drop_intervalSet = CPA.map (function `Int x -> `Int (ID.no_intervalSet x) | x -> x )

let context (fd: fundec) (st: store): store =
let f keep drop_fn (st: store) = if keep then st else { st with cpa = drop_fn st.cpa} in
st |>
Expand All @@ -604,6 +606,7 @@ struct
%> f (ContextUtil.should_keep ~isAttr:GobContext ~keepOption:"ana.base.context.non-ptr" ~removeAttr:"base.no-non-ptr" ~keepAttr:"base.non-ptr" fd) drop_non_ptrs
%> f (ContextUtil.should_keep ~isAttr:GobContext ~keepOption:"ana.base.context.int" ~removeAttr:"base.no-int" ~keepAttr:"base.int" fd) drop_ints
%> f (ContextUtil.should_keep ~isAttr:GobContext ~keepOption:"ana.base.context.interval" ~removeAttr:"base.no-interval" ~keepAttr:"base.interval" fd) drop_interval
%> f (ContextUtil.should_keep ~isAttr:GobContext ~keepOption:"ana.base.context.interval_set" ~removeAttr:"base.no-interval_set" ~keepAttr:"base.interval_set" fd) drop_intervalSet

let context_cpa fd (st: store) = (context fd st).cpa

Expand Down
4 changes: 2 additions & 2 deletions src/autoTune.ml
Original file line number Diff line number Diff line change
Expand Up @@ -129,8 +129,8 @@ let disableIntervalContextsInRecursiveFunctions () =
ResettableLazy.force functionCallMaps |> fun (x,_,_) -> x |> FunctionCallMap.iter (fun f set ->
(*detect direct recursion and recursion with one indirection*)
if FunctionSet.mem f set || (not @@ FunctionSet.disjoint (calledFunctions f) (callingFunctions f)) then (
print_endline ("function " ^ (f.vname) ^" is recursive, disable interval context");
f.vattr <- addAttributes (f.vattr) [Attr ("goblint_context",[AStr "base.no-interval"; AStr "relation.no-context"])];
print_endline ("function " ^ (f.vname) ^" is recursive, disable interval and intervalSet contexts");
f.vattr <- addAttributes (f.vattr) [Attr ("goblint_context",[AStr "base.no-interval"; AStr "base.no-interval_set"; AStr "relation.no-context"])];
)
)

Expand Down
1,376 changes: 1,033 additions & 343 deletions src/cdomains/intDomain.ml

Large diffs are not rendered by default.

40 changes: 38 additions & 2 deletions src/cdomains/intDomain.mli
Original file line number Diff line number Diff line change
Expand Up @@ -273,6 +273,37 @@ sig
end
(** Interface of IntDomain implementations taking an ikind for arithmetic operations *)

module type SOverFlow =
sig

include S

val add : ?no_ov:bool -> Cil.ikind -> t -> t -> t * bool * bool * bool

val sub : ?no_ov:bool -> Cil.ikind -> t -> t -> t * bool * bool * bool

val mul : ?no_ov:bool -> Cil.ikind -> t -> t -> t * bool * bool * bool

val div : ?no_ov:bool -> Cil.ikind -> t -> t -> t * bool * bool * bool

val neg : ?no_ov:bool -> Cil.ikind -> t -> t * bool * bool * bool

val cast_to : ?torg:Cil.typ -> ?no_ov:bool -> Cil.ikind -> t -> t * bool * bool * bool

val of_int : Cil.ikind -> int_t -> t * bool * bool * bool

val of_interval: ?suppress_ovwarn:bool -> Cil.ikind -> int_t * int_t -> t * bool * bool * bool

val starting : ?suppress_ovwarn:bool -> Cil.ikind -> int_t -> t * bool * bool * bool
val ending : ?suppress_ovwarn:bool -> Cil.ikind -> int_t -> t * bool * bool * bool

val shift_left : Cil.ikind -> t -> t -> t * bool * bool * bool

val shift_right: Cil.ikind -> t -> t -> t * bool * bool * bool


end

module OldDomainFacade (Old : IkindUnawareS with type int_t = int64) : S with type int_t = IntOps.BigIntOps.t and type t = Old.t
(** Facade for IntDomain implementations that do not implement the interface where arithmetic functions take an ikind parameter. *)

Expand Down Expand Up @@ -320,6 +351,7 @@ module IntDomWithDefaultIkind (I: Y) (Ik: Ikind) : Y with type t = I.t and type
module IntDomTuple : sig
include Z
val no_interval: t -> t
val no_intervalSet: t -> t
val ikind: t -> ikind
end

Expand Down Expand Up @@ -369,7 +401,9 @@ module FlattenedBI : IkindUnawareS with type t = [`Top | `Lifted of IntOps.BigIn
module Lifted : IkindUnawareS with type t = [`Top | `Lifted of int64 | `Bot] and type int_t = int64
(** Artificially bounded integers in their natural ordering. *)

module IntervalFunctor(Ints_t : IntOps.IntOps): S with type int_t = Ints_t.t and type t = (Ints_t.t * Ints_t.t) option
module IntervalFunctor(Ints_t : IntOps.IntOps): SOverFlow with type int_t = Ints_t.t and type t = (Ints_t.t * Ints_t.t) option

module IntervalSetFunctor(Ints_t : IntOps.IntOps): SOverFlow with type int_t = Ints_t.t and type t = (Ints_t.t * Ints_t.t) list

module Interval32 :Y with (* type t = (IntOps.Int64Ops.t * IntOps.Int64Ops.t) option and *) type int_t = IntOps.Int64Ops.t

Expand All @@ -379,7 +413,9 @@ module BigInt:
val cast_to: Cil.ikind -> Z.t -> Z.t
end

module Interval : S with type int_t = IntOps.BigIntOps.t
module Interval : SOverFlow with type int_t = IntOps.BigIntOps.t

module IntervalSet : SOverFlow with type int_t = IntOps.BigIntOps.t

module Congruence : S with type int_t = IntOps.BigIntOps.t

Expand Down
17 changes: 15 additions & 2 deletions src/util/options.schema.json
Original file line number Diff line number Diff line change
Expand Up @@ -357,7 +357,13 @@
"interval": {
"title": "ana.int.interval",
"description":
"Use IntDomain.Interval32: (int64 * int64) option.",
"Use IntDomain.Interval32: (Z.t * Z.t) option.",
"type": "boolean",
"default": false
},
"interval_set": {
"title": "ana.int.interval_set",
"description": "Use IntDomain.IntervalSet: (Z.t * Z.t) list.",
"type": "boolean",
"default": false
},
Expand Down Expand Up @@ -589,6 +595,13 @@
"Integer values of the Interval domain in function contexts.",
"type": "boolean",
"default": true
},
"interval_set": {
"title": "ana.base.context.interval_set",
"description":
"Integer values of the IntervalSet domain in function contexts.",
"type": "boolean",
"default": true
}
},
"additionalProperties": false
Expand Down Expand Up @@ -1430,7 +1443,7 @@
"type": "array",
"items": {
"type": "string",
"enum": ["base.no-non-ptr", "base.non-ptr", "base.no-int", "base.int", "base.no-interval", "base.interval", "relation.no-context", "relation.context", "no-widen", "widen"]
"enum": ["base.no-non-ptr", "base.non-ptr", "base.no-int", "base.int", "base.no-interval", "base.no-interval_set","base.interval", "base.interval_set","relation.no-context", "relation.context", "no-widen", "widen"]
},
"default": []
}
Expand Down
13 changes: 7 additions & 6 deletions src/util/precisionUtil.ml
Original file line number Diff line number Diff line change
@@ -1,19 +1,20 @@
(* We define precision by the number of IntDomains activated.
* We currently have 4 types: DefExc, Interval, Enums, Congruence *)
type int_precision = (bool * bool * bool * bool)
* We currently have 5 types: DefExc, Interval, Enums, Congruence, IntervalSet *)
type int_precision = (bool * bool * bool * bool * bool)
(* Same applies for FloatDomain
* We currently have only an interval type analysis *)
type float_precision = (bool)


(* Thus for maximum precision we activate all Domains *)
let max_int_precision : int_precision = (true, true, true, true)
let max_int_precision : int_precision = (true, true, true, true, true)
let max_float_precision : float_precision = (true)
let int_precision_from_fundec (fd: GoblintCil.fundec): int_precision =
((ContextUtil.should_keep ~isAttr:GobPrecision ~keepOption:"ana.int.def_exc" ~removeAttr:"no-def_exc" ~keepAttr:"def_exc" fd),
(ContextUtil.should_keep ~isAttr:GobPrecision ~keepOption:"ana.int.interval" ~removeAttr:"no-interval" ~keepAttr:"interval" fd),
(ContextUtil.should_keep ~isAttr:GobPrecision ~keepOption:"ana.int.enums" ~removeAttr:"no-enums" ~keepAttr:"enums" fd),
(ContextUtil.should_keep ~isAttr:GobPrecision ~keepOption:"ana.int.congruence" ~removeAttr:"no-congruence" ~keepAttr:"congruence" fd))
(ContextUtil.should_keep ~isAttr:GobPrecision ~keepOption:"ana.int.congruence" ~removeAttr:"no-congruence" ~keepAttr:"congruence" fd),
(ContextUtil.should_keep ~isAttr:GobPrecision ~keepOption:"ana.int.interval_set" ~removeAttr:"no-interval_set" ~keepAttr:"interval_set" fd))

let float_precision_from_fundec (fd: GoblintCil.fundec): float_precision =
((ContextUtil.should_keep ~isAttr:GobPrecision ~keepOption:"ana.float.interval" ~removeAttr:"no-float-interval" ~keepAttr:"float-interval" fd))
Expand All @@ -22,7 +23,7 @@ let int_precision_from_node (): int_precision =
| Some n -> int_precision_from_fundec (Node.find_fundec n)
| _ -> max_int_precision (* In case a Node is None we have to handle Globals, i.e. we activate all IntDomains (TODO: verify this assumption) *)

let is_congruence_active (_, _, _, c: int_precision): bool = c
let is_congruence_active (_, _, _, c,_: int_precision): bool = c

let float_precision_from_node (): float_precision =
match !MyCFG.current_node with
Expand All @@ -34,7 +35,7 @@ let int_precision_from_node_or_config (): int_precision =
int_precision_from_node ()
else
let f n = GobConfig.get_bool ("ana.int."^n) in
(f "def_exc", f "interval", f "enums", f "congruence")
(f "def_exc", f "interval", f "enums", f "congruence", f "interval_set")

let float_precision_from_node_or_config (): float_precision =
if GobConfig.get_bool "annotation.float.enabled" then
Expand Down
24 changes: 24 additions & 0 deletions tests/regression/66-interval-set-one/00-was_problematic_2.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
// PARAM: --enable ana.int.interval_set --set ana.base.arrays.domain partitioned
int main(void)
{
int arr[260];
int n;

n = 5;
arr[0] = 0;

while (n > 1) { //here
arr[1] = 7;
n--;
}

int arr2[260];

n = 5;
arr2[259] = 0;

while (n > 1) {
arr2[258] = 7;
n--;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
// PARAM: --enable ana.arrayoob --enable ana.int.interval_set --enable ana.int.interval_set --enable ana.int.enums

// Variable sized array: oob access

#include <stdio.h>
#include <stdlib.h>
int main() {
int top;
int N;
// The if statement is needed, so the size is actually dynamic
if (top) {
N = 5;
} else {
N = 10;
}
int arr[N];
arr[0] = 1;
arr[1] = 2;
arr[2] = 3;
arr[3] = 4;
arr[4] = 5; // NOWARN
arr[-1] = 10; // WARN
for (int i = 0; i < 5; ++i) {
arr[i] = 5; // NOWARN
}
for (int i = 0; i <= 5; ++i) {
arr[i] = 5; // WARN
}
for (int i = -2; i < 5; ++i) {
arr[i] = 5; // WARN
}
return 0;
}
20 changes: 20 additions & 0 deletions tests/regression/66-interval-set-one/02-continue.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
// PARAM: --enable ana.int.interval_set --set exp.unrolling-factor 5 --set ana.base.arrays.domain unroll --set ana.base.arrays.unrolling-factor 5
// Simple example
#include <goblint.h>

void main(void)
{
int j = 0;

for(int i=0;i < 50;i++) {
if(i < 2) {
continue;
}
if(i>4) {
break;
}
j++;
}

__goblint_check(j==3);
}
52 changes: 52 additions & 0 deletions tests/regression/66-interval-set-one/03-was_problematic_3.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
// PARAM: --enable ana.int.interval_set --set ana.base.arrays.domain partitioned
struct some_struct
{
int dir[7];
int length;
double coeff;
double forwback;
};

struct some_struct q_paths[200];
int num_q_paths;

int add_basic_path(int length, double coeff)
{
int ir[4];
int j;
int flag;

ir[2] = 0;
while (ir[2] < 2)
{
ir[3] = 0;
while (ir[3] < 2)
{
j = 0;
while (j < num_q_paths)
{
if (flag == 1)
{
break;
}
j++;
}

q_paths[num_q_paths].length = length;

num_q_paths++;

(ir[3])++;
}
(ir[2])++;
}

return 42;
}

int main(int argc, char **argv)
{
double this_coeff;
int pl;
add_basic_path(pl, this_coeff);
}
44 changes: 44 additions & 0 deletions tests/regression/66-interval-set-one/04-interval-overflow.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
// PARAM: --enable ana.int.interval_set --enable ana.int.congruence --disable ana.int.def_exc
// Overflow information should be passed from the interval domain to congruences
#include <goblint.h>
#include <stdio.h>

int main(){
signed char r;

if (r) {
r = -68;
} else {
r = -63;
}

signed char k = r - 80;
__goblint_check(k == 0); //UNKNOWN!

signed char non_ov = r - 10;
__goblint_check(non_ov == -78); //UNKNOWN!

signed char m = r * 2;

__goblint_check(m == 0); //UNKNOWN!

signed char l = r + (-80);
__goblint_check(l == 0); //UNKNOWN!

int g;

if (g) {
g = -126;
} else {
g = -128;
}

signed char f = g / (-1);
__goblint_check(f == 1); //UNKNOWN!

signed char d = -g;
__goblint_check(d == 1); //UNKNOWN!

return 0;

}
Loading