From 84b5207053a0f0149e07a961f9bdf33c5087efa7 Mon Sep 17 00:00:00 2001 From: Atul Agarwal Date: Thu, 4 May 2023 14:26:03 +0200 Subject: [PATCH 001/327] Create build_testing.yml Trying build test using github actions --- .github/workflows/build_testing.yml | 35 +++++++++++++++++++++++++++++ 1 file changed, 35 insertions(+) create mode 100644 .github/workflows/build_testing.yml diff --git a/.github/workflows/build_testing.yml b/.github/workflows/build_testing.yml new file mode 100644 index 0000000000..8ec9b340c3 --- /dev/null +++ b/.github/workflows/build_testing.yml @@ -0,0 +1,35 @@ +name: build_testing + +on: + - push + - pull_request + +jobs: + tests: + strategy: + fail-fast: false + matrix: + os: + - macos-latest + - ubuntu-latest + ocaml-compiler: + - 4.14.0 + + runs-on: ${{ matrix.os }} + + steps: + - name: Checkout code + uses: actions/checkout@v2 + + - name: Setup OCaml ${{ matrix.ocaml-compiler }} + env: + OPAMLOCKED: locked + uses: ocaml/setup-ocaml@v2 + with: + ocaml-compiler: ${{ matrix.ocaml-compiler }} + + - name: Install opam dependencies + run: opam install . --deps-only --locked + + - name: Build + run: ./make.sh nat From b5b7b5a34dddfa5f26d2cc3b6092ac3fc98dded6 Mon Sep 17 00:00:00 2001 From: Atul Agarwal Date: Thu, 4 May 2023 14:33:40 +0200 Subject: [PATCH 002/327] Update build_testing.yml Changed the ocaml compiler version to 4.12.0 --- .github/workflows/build_testing.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/build_testing.yml b/.github/workflows/build_testing.yml index 8ec9b340c3..1b464043c7 100644 --- a/.github/workflows/build_testing.yml +++ b/.github/workflows/build_testing.yml @@ -13,7 +13,7 @@ jobs: - macos-latest - ubuntu-latest ocaml-compiler: - - 4.14.0 + - 4.12.0 runs-on: ${{ matrix.os }} From 0ee88d3836cc5e603b34f246ebc6244e0eba0c10 Mon Sep 17 00:00:00 2001 From: Alexander Schlenga Date: Fri, 5 May 2023 19:51:19 +0200 Subject: [PATCH 003/327] Hint to run "make" in the tutorial --- docs/developer-guide/firstanalysis.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/developer-guide/firstanalysis.md b/docs/developer-guide/firstanalysis.md index 38668c28da..21221c4a77 100644 --- a/docs/developer-guide/firstanalysis.md +++ b/docs/developer-guide/firstanalysis.md @@ -67,7 +67,7 @@ The key part now is to define transfer functions for assignment. We only handle There is no need to implement the transfer functions for branching for this example; it only relies on lattice join operations to correctly take both paths into account. The assignment relies on the function `eval`, which is almost there. It just needs you to fix the evaluation of constants! Unless you jumped straight to this line, it should not be too complicated to fix this. -With this in place, we should have sufficient information to tell Goblint that the assertion does hold. +With this in place, we should have sufficient information to tell Goblint that the assertion does hold (run `make` to compile the updated analysis in Goblint). ## Extending the domain From 5510982c7986b9d0c08c02bdc5e8823d05d29b23 Mon Sep 17 00:00:00 2001 From: Johanna Schinabeck Date: Thu, 11 May 2023 11:38:04 +0200 Subject: [PATCH 004/327] added comments to the termination.ml file; TODO: some things are still unclear and have to be added later --- src/analyses/termination.ml | 171 ++++++++++++++++++++++++++---------- 1 file changed, 126 insertions(+), 45 deletions(-) diff --git a/src/analyses/termination.ml b/src/analyses/termination.ml index 37ee8bc9ef..c5f2ca7f7d 100644 --- a/src/analyses/termination.ml +++ b/src/analyses/termination.ml @@ -4,6 +4,8 @@ open Prelude.Ana open Analyses module M = Messages +(* J: returns if a and b contain a value + if yes: return this x, otherwise nothing *) let (||?) a b = match a,b with Some x,_ | _, Some x -> Some x | _ -> None module TermDomain = struct @@ -11,15 +13,22 @@ module TermDomain = struct end (* some kind of location string suitable for variable names? *) +(* J: returns a string_ "lineNr_columnNr" *) +(* J: for location (10,5) it evaluates to: 10_5*) let show_location_id l = string_of_int l.line ^ "_" ^ string_of_int l.column +(* J: the new variable is created here and inserted into the code + in the code the variable is set to 0 (before the loop) and incremented (after the loop) + is it ever checked if the newly created variable is really new???*) +(* J: ??? Who defines the Loop, what are the variables*) class loopCounterVisitor (fd : fundec) = object(self) inherit nopCilVisitor method! vstmt s = let action s = match s.skind with | Loop (b, loc, eloc, _, _) -> (* insert loop counter variable *) + (* J: for location (10,5) it evaluates to: term10_5*) let name = "term"^show_location_id loc in let typ = intType in (* TODO the type should be the same as the one of the original loop counter *) let v = Goblintutil.create_var (makeLocalVar fd name ~init:(SingleInit zero) typ) in @@ -28,14 +37,20 @@ class loopCounterVisitor (fd : fundec) = object(self) (* increment it every iteration *) let inc_stmt = mkStmtOneInstr @@ Set (var v, increm (Lval (var v)) 1, loc, eloc) in b.bstmts <- inc_stmt :: b.bstmts; - let nb = mkBlock [init_stmt; mkStmt s.skind] in + let nb = mkBlock [init_stmt; mkStmt s.skind] in (* J: s.kind = Loop(b, loc, eloc, ...)*) s.skind <- Block nb; s | _ -> s in ChangeDoChildrenPost (s, action) end +(* J: creates a new hash table with size 13 for loop breaks*) +(* J: int: is a number which is unique in a function*) +(* J: ??? Why 13*) let loopBreaks : (int, location) Hashtbl.t = Hashtbl.create 13 (* break stmt sid -> corresponding loop *) +(* J: if there is some break associated with the loop (?) we add this break to the hash table + key = break.sid + data = location *) class loopBreaksVisitor (fd : fundec) = object(self) inherit nopCilVisitor method! vstmt s = @@ -47,10 +62,15 @@ class loopBreaksVisitor (fd : fundec) = object(self) end (* if the given block contains a goto while_break.* we have the termination condition for a loop *) +(* J: returns binding from loopBreaks hash table associated with a number which is uniquely identifie with the statement + if there is a Goto, otherwise nothing*) +(* J: stmt.sid = A number (>= 0) that is unique in a function. *) +(* J: ???*) let exits = function | { bstmts = [{ skind = Goto (stmt, loc); _ }]; _ } -> Hashtbl.find_option loopBreaks !stmt.sid | _ -> None (* TODO handle return (need to find out what loop we are in) *) +(* J: ???*) let lvals_of_expr = let rec f a = function | Const _ | SizeOf _ | SizeOfStr _ | AlignOf _ | AddrOfLabel _ -> a @@ -60,125 +80,186 @@ let lvals_of_expr = | Question (c,t,e,_) -> f a c @ f a t @ f a e in f [] +(* J: create hash table of size 13 for variables*) let loopVars : (location, lval) Hashtbl.t = Hashtbl.create 13 (* loop location -> lval used for exit *) +(* J: adds the location and left varibale to the loopVars, if one block of the if statement contains a goto block*) class loopVarsVisitor (fd : fundec) = object inherit nopCilVisitor method! vstmt s = let add_exit_cond e loc = match lvals_of_expr e with + (* J: ??? Same as when isArithmeticType Cilfacade.typeOf e*) | [lval] when Cilfacade.typeOf e |> isArithmeticType -> Hashtbl.add loopVars loc lval + (* J : add lval to hash table when the expression on location loc is of arithmetic type*) | _ -> () in (match s.skind with + (* J: map_default f x (Some v) returns f v and map_default f x None returns x.*) + (* J: If there exists a goto statement: call add_exit_cond e (SOME exits tb ||? exits fb) + If e is of arithmetic type: add the location to the loopVars hash table *) | If (e, tb, fb, loc, eloc) -> Option.map_default (add_exit_cond e) () (exits tb ||? exits fb) | _ -> ()); DoChildren end +(* J: ??? visits the expression e and removes all casts from the expression*) let stripCastsDeep e = let v = object inherit nopCilVisitor + (* J: ChangeTo: Replace the expression with the given one*) + (* J: Removes casts from this expression, but ignores casts within other expression constructs. + So we delete the (A) and (B) casts from "(A)(B)(x + (C)y)", but leave the (C) cast.*) method! vexpr e = ChangeTo (stripCasts e) end in visitCilExpr v e (* keep the enclosing loop for statements *) +(* J: store pointer pointing to Nothing for loops*) let cur_loop = ref None (* current loop *) let cur_loop' = ref None (* for nested loops *) +(* J: searches if the variable name___ for the given location is present in the function definition + if not: the variable is created and initialized to 0*) let makeVar fd loc name = + (* J: for location = (10,5) and name = "hi" the id evaluates to: hi__10_5*) let id = name ^ "__" ^ show_location_id loc in + (* J: fd.slocals = Locals of the function definition*) + (* J: returns the first element which is a local and which name is id (for example hi__10_5)*) try List.find (fun v -> v.vname = id) fd.slocals + (* J: when the variable is not found in the function definition then it is newly created and initialized with 0*) with Not_found -> let typ = intType in (* TODO the type should be the same as the one of the original loop counter *) Goblintutil.create_var (makeLocalVar fd id ~init:(SingleInit zero) typ) +(* J: creates an empty function with name "__goblint_assume" and makes a lvalue out of it*) let f_assume = Lval (var (emptyFunction "__goblint_assume").svar) +(* J: creates an empty function with name "__goblint_check" and makes a lvalue out of it*) let f_check = Lval (var (emptyFunction "__goblint_check").svar) +(* J: ??? Loop pointer handling: Why do we fist set cur_loop' = cur_loop and then reverse this operation???*) +(* J: inserts new variable t with init and increment and adds a check if t is bounded*) class loopInstrVisitor (fd : fundec) = object(self) inherit nopCilVisitor method! vstmt s = (* TODO: use Loop eloc? *) (match s.skind with + (* J: if the statement is a loop adjust the loop pointer*) | Loop (_, loc, eloc, _, _) -> - cur_loop' := !cur_loop; - cur_loop := Some loc + cur_loop' := !cur_loop; (* J: set the nested loop to the current loop*) + cur_loop := Some loc (* J: set the newly found loop as current loop*) | _ -> ()); + (* J: adds the variable t to the loop, increments it and checks after the loop if it is bounded + adds also the variables d1 and d2, with incrementation, which affects t + depending on the structure, d1 and d2 are set differently*) let action s = (* first, restore old cur_loop *) + (* J: if the statement is a loop set the nested loop as the current loop*) (match s.skind with | Loop (_, loc, eloc, _, _) -> - cur_loop := !cur_loop'; + cur_loop := !cur_loop'; (* J: current loop is the nested loop*) | _ -> ()); + (* J: true if the current loop variable is set and this variable is bound in the hash table*) let in_loop () = Option.is_some !cur_loop && Hashtbl.mem loopVars (Option.get !cur_loop) in + (* J: t is the new variable which should be bounded + if there is a loop with bounded variable: add code for init and increment (for t, d1, d2) + if there is a loop with unbounded variable: do nothing + if a loop ended: check if t is bounded + if there is an instruction with an assignment: increment d1 and d2 if the assignment affects the loop var + do this recursively for all children*) match s.skind with + (* J: if the statement is a loop, and when the location is bound in the hash table: + - add the creational and initializational code for t, d1, d2 before the loop + - add the incrementational code for t, d1, d2 in the loop + *) | Loop (b, loc, eloc, Some continue, Some break) when Hashtbl.mem loopVars loc -> (* find loop var for current loop *) let x = Hashtbl.find loopVars loc in (* insert loop counter and diff to loop var *) + (* J: create variables t, d1, d2 with names: t___, d1___, d2___*) let t = var @@ makeVar fd loc "t" in let d1 = var @@ makeVar fd loc "d1" in let d2 = var @@ makeVar fd loc "d2" in (* make init stmts *) + (* J: set t=0, d1, d2 = lvalue of x = value in the hashtable associated with the loop variable*) let t_init = mkStmtOneInstr @@ Set (t, zero, loc, eloc) in let d1_init = mkStmtOneInstr @@ Set (d1, Lval x, loc, eloc) in let d2_init = mkStmtOneInstr @@ Set (d2, Lval x, loc, eloc) in (* increment/decrement in every iteration *) - let t_inc = mkStmtOneInstr @@ Set (t, increm (Lval t) 1, loc, eloc) in - let d1_inc = mkStmtOneInstr @@ Set (d1, increm (Lval d1) (-1), loc, eloc) in - let d2_inc = mkStmtOneInstr @@ Set (d2, increm (Lval d2) 1 , loc, eloc) in - let typ = intType in - let e1 = BinOp (Eq, Lval t, BinOp (MinusA, Lval x, Lval d1, typ), typ) in - let e2 = BinOp (Eq, Lval t, BinOp (MinusA, Lval d2, Lval x, typ), typ) in - let inv1 = mkStmtOneInstr @@ Call (None, f_assume, [e1], loc, eloc) in + (* J: increment t and d2, decrement d1*) + let t_inc = mkStmtOneInstr @@ Set (t, increm (Lval t) 1, loc, eloc) in (* J: t = t + 1*) + let d1_inc = mkStmtOneInstr @@ Set (d1, increm (Lval d1) (-1), loc, eloc) in (* J: d1 = d1 - 1*) + let d2_inc = mkStmtOneInstr @@ Set (d2, increm (Lval d2) 1 , loc, eloc) in (* J: d2 = d2 + 1*) + let typ = intType in (* J: Note: x is the loop variable*) + let e1 = BinOp (Eq, Lval t, BinOp (MinusA, Lval x, Lval d1, typ), typ) in (* J: t = (x - d1) *) + let e2 = BinOp (Eq, Lval t, BinOp (MinusA, Lval d2, Lval x, typ), typ) in (* J: t = (d2 - x) *) + (* J: make a statement for e1 and e2*) + (* J: ??? what happens with the call*) + let inv1 = mkStmtOneInstr @@ Call (None, f_assume, [e1], loc, eloc) in let inv2 = mkStmtOneInstr @@ Call (None, f_assume, [e2], loc, eloc) in - (match b.bstmts with + (match b.bstmts with (* J: we are still in a loop*) | cont :: cond :: ss -> (* changing succs/preds directly doesn't work -> need to replace whole stmts *) - b.bstmts <- cont :: cond :: inv1 :: inv2 :: d1_inc :: d2_inc :: t_inc :: ss; - let nb = mkBlock [t_init; d1_init; d2_init; mkStmt s.skind] in - s.skind <- Block nb; + (* from: cont :: cond :: ss + to: cont :: + cond :: + t = (x - d1) :: t = (d2 - x) :: (??? Is this correct with the call???) + d1 = d1 - 1 :: d2 = d2 + 1 :: t = t + 1 :: + ss + *) + b.bstmts <- cont :: cond :: inv1 :: inv2 :: d1_inc :: d2_inc :: t_inc :: ss; (* J: in the loop*) + let nb = mkBlock [t_init; d1_init; d2_init; mkStmt s.skind] in (* J: make a block out of the init statements before the loop*) + s.skind <- Block nb; | _ -> ()); - s + s (* J: return s with added code for init and increment*) + (* J: if the variable in the loops is not bounded, it is not possible to continue*) | Loop (b, loc, eloc, Some continue, Some break) -> print_endline @@ "WARN: Could not determine loop variable for loop at " ^ CilType.Location.show loc; s + (* J: when the statement is not a loop and a loop ended: + - add t >= 0 in the code after the loop*) | _ when Hashtbl.mem loopBreaks s.sid -> (* after a loop, we check that t is bounded/positive (no overflow happened) *) - let loc = Hashtbl.find loopBreaks s.sid in - let t = var @@ makeVar fd loc "t" in - let e3 = BinOp (Ge, Lval t, zero, intType) in - let inv3 = mkStmtOneInstr @@ Call (None, f_check, [e3], loc, locUnknown) in - let nb = mkBlock [mkStmt s.skind; inv3] in + let loc = Hashtbl.find loopBreaks s.sid in (* J: holds the current binding of the number of the current function in the hash table*) + let t = var @@ makeVar fd loc "t" in (* J: get the name for variable t = t___*) + let e3 = BinOp (Ge, Lval t, zero, intType) in (* J: t >= 0*) + let inv3 = mkStmtOneInstr @@ Call (None, f_check, [e3], loc, locUnknown) in (* J: make a statement to check t >= 0*) + let nb = mkBlock [mkStmt s.skind; inv3] in (* J: add the statement to the block*) s.skind <- Block nb; - s + s (* J: return s with the added check*) + (* J: If there is an instruction (containing an assignment) and it is in a loop: + If the loop variable and lvalue of Set are structural unequal + Do nothing + else + add an incrementation step for d1 and d2 (depending on the binOp)*) | Instr [Set (lval, e, loc, eloc)] when in_loop () -> (* find loop var for current loop *) let cur_loop = Option.get !cur_loop in - let x = Hashtbl.find loopVars cur_loop in - if x <> lval then + let x = Hashtbl.find loopVars cur_loop in (* J: holds the current binding of the number of the current function in the hash table*) + if x <> lval then (* J: x and lval are structural unequal*) s else (* we only care about the loop var *) + (* J: create the variables d1 and d2 with name: d1___, d2___*) let d1 = makeVar fd cur_loop "d1" in let d2 = makeVar fd cur_loop "d2" in (match stripCastsDeep e with + (* J: if x' + e2 or x' - e2 with x' = x and the type arithmetic: + - adds incrementation for d1 and d2 to the code*) | BinOp (op, Lval x', e2, typ) when (op = PlusA || op = MinusA) && x' = x && isArithmeticType typ -> (* TODO x = 1 + x, MinusA! *) (* increase diff by same expr *) - let d1_inc = mkStmtOneInstr @@ Set (var d1, BinOp (PlusA, Lval (var d1), e2, typ), loc, eloc) in - let d2_inc = mkStmtOneInstr @@ Set (var d2, BinOp (PlusA, Lval (var d2), e2, typ), loc, eloc) in - let nb = mkBlock [d1_inc; d2_inc; mkStmt s.skind] in + let d1_inc = mkStmtOneInstr @@ Set (var d1, BinOp (PlusA, Lval (var d1), e2, typ), loc, eloc) in (* J: d1 = d1 + e2*) + let d2_inc = mkStmtOneInstr @@ Set (var d2, BinOp (PlusA, Lval (var d2), e2, typ), loc, eloc) in (* J: d2 = d2 + e2*) + let nb = mkBlock [d1_inc; d2_inc; mkStmt s.skind] in (* J: add the incrementation steps at the front*) s.skind <- Block nb; - s + s (* J: return s with the added incrementation*) | _ -> (* otherwise diff is e - counter *) - let t = makeVar fd cur_loop "t" in - let te = Cilfacade.typeOf e in - let dt1 = mkStmtOneInstr @@ Set (var d1, BinOp (MinusA, Lval x, Lval (var t), te), loc, eloc) in - let dt2 = mkStmtOneInstr @@ Set (var d2, BinOp (MinusA, Lval x, Lval (var t), te), loc, eloc) in - let nb = mkBlock [mkStmt s.skind; dt1; dt2] in + let t = makeVar fd cur_loop "t" in (* J: varibale name for t*) + let te = Cilfacade.typeOf e in (* J: type of e*) + let dt1 = mkStmtOneInstr @@ Set (var d1, BinOp (MinusA, Lval x, Lval (var t), te), loc, eloc) in (* J: d1 = x - t*) + let dt2 = mkStmtOneInstr @@ Set (var d2, BinOp (MinusA, Lval x, Lval (var t), te), loc, eloc) in (* J: d2 = x - t*) + let nb = mkBlock [mkStmt s.skind; dt1; dt2] in (* J: add the incrementation steps at the end*) s.skind <- Block nb; s ) | _ -> s in - ChangeDoChildrenPost (s, action) + ChangeDoChildrenPost (s, action) (* J: continue with the children*) end @@ -215,24 +296,24 @@ struct (* ctx.local *) (* | _ -> ctx.local *) - let startstate v = D.bot () - let threadenter ctx lval f args = [D.bot ()] + let startstate v = D.bot () (* J: start with bottom*) + let threadenter ctx lval f args = [D.bot ()] (* J: enter threads with bottom*) let exitstate v = D.bot () end class recomputeVisitor (fd : fundec) = object(self) inherit nopCilVisitor method! vfunc fd = - computeCFGInfo fd true; - SkipChildren + computeCFGInfo fd true; (* J: make the cfg and return a list of statements with global statement number*) + SkipChildren (* J: don't visit children*) end let _ = (* Cilfacade.register_preprocess Spec.name (new loopCounterVisitor); *) - Cilfacade.register_preprocess (Spec.name ()) (new loopBreaksVisitor); - Cilfacade.register_preprocess (Spec.name ()) (new loopVarsVisitor); - Cilfacade.register_preprocess (Spec.name ()) (new loopInstrVisitor); - Cilfacade.register_preprocess (Spec.name ()) (new recomputeVisitor); - Hashtbl.clear loopBreaks; (* because the sids are now different *) - Cilfacade.register_preprocess (Spec.name ()) (new loopBreaksVisitor); - MCP.register_analysis (module Spec : MCPSpec) + Cilfacade.register_preprocess (Spec.name ()) (new loopBreaksVisitor); (* J: fill hash table loopBreaks: containing breaks ?*) + Cilfacade.register_preprocess (Spec.name ()) (new loopVarsVisitor); (* J: fill hash table loopVars: containing varibales identified with loops ?*) + Cilfacade.register_preprocess (Spec.name ()) (new loopInstrVisitor); (* J: inserts new variable with init, increment, and bounded check to code*) + Cilfacade.register_preprocess (Spec.name ()) (new recomputeVisitor); (* J: ??? *) + Hashtbl.clear loopBreaks; (* because the sids are now different *) (* J: delete entries in loopBreaks*) + Cilfacade.register_preprocess (Spec.name ()) (new loopBreaksVisitor); (* J: newly set hash table loopBreaks with goto statements*) + MCP.register_analysis (module Spec : MCPSpec) (* J: ???*) From 8facb0c9ca8c382194a88bcdb4c01f14b051efd9 Mon Sep 17 00:00:00 2001 From: Johanna Schinabeck Date: Thu, 11 May 2023 19:58:15 +0200 Subject: [PATCH 005/327] added preprocessing file for loop termination analysis: this file contains code adding before it is analyzed --- src/analyses/termination.ml | 4 +++- src/util/terminationPreprocessing.ml | 3 +++ 2 files changed, 6 insertions(+), 1 deletion(-) create mode 100644 src/util/terminationPreprocessing.ml diff --git a/src/analyses/termination.ml b/src/analyses/termination.ml index c5f2ca7f7d..8fa8a0ee12 100644 --- a/src/analyses/termination.ml +++ b/src/analyses/termination.ml @@ -240,6 +240,7 @@ class loopInstrVisitor (fd : fundec) = object(self) (match stripCastsDeep e with (* J: if x' + e2 or x' - e2 with x' = x and the type arithmetic: - adds incrementation for d1 and d2 to the code*) + (* J: if the loopVar is changed*) | BinOp (op, Lval x', e2, typ) when (op = PlusA || op = MinusA) && x' = x && isArithmeticType typ -> (* TODO x = 1 + x, MinusA! *) (* increase diff by same expr *) let d1_inc = mkStmtOneInstr @@ Set (var d1, BinOp (PlusA, Lval (var d1), e2, typ), loc, eloc) in (* J: d1 = d1 + e2*) @@ -259,6 +260,7 @@ class loopInstrVisitor (fd : fundec) = object(self) ) | _ -> s in + (* J: *) ChangeDoChildrenPost (s, action) (* J: continue with the children*) end @@ -316,4 +318,4 @@ let _ = Cilfacade.register_preprocess (Spec.name ()) (new recomputeVisitor); (* J: ??? *) Hashtbl.clear loopBreaks; (* because the sids are now different *) (* J: delete entries in loopBreaks*) Cilfacade.register_preprocess (Spec.name ()) (new loopBreaksVisitor); (* J: newly set hash table loopBreaks with goto statements*) - MCP.register_analysis (module Spec : MCPSpec) (* J: ???*) + MCP.register_analysis (module Spec : MCPSpec) (* J: ???*) \ No newline at end of file diff --git a/src/util/terminationPreprocessing.ml b/src/util/terminationPreprocessing.ml new file mode 100644 index 0000000000..73982cb0f1 --- /dev/null +++ b/src/util/terminationPreprocessing.ml @@ -0,0 +1,3 @@ +(* - code in src/analysis/termination.ml contains loopCounterVisitor which might be interesting + - check if overflow happend with new variable + - how do we deal with nested loops?*) \ No newline at end of file From 7fbb12ae3c72b2115846b694832e22955996b492 Mon Sep 17 00:00:00 2001 From: Atul Agarwal Date: Sun, 14 May 2023 23:21:19 +0200 Subject: [PATCH 006/327] Update termination.ml Indentations fix test --- src/analyses/termination.ml | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/src/analyses/termination.ml b/src/analyses/termination.ml index 8fa8a0ee12..0040055e03 100644 --- a/src/analyses/termination.ml +++ b/src/analyses/termination.ml @@ -238,9 +238,8 @@ class loopInstrVisitor (fd : fundec) = object(self) let d1 = makeVar fd cur_loop "d1" in let d2 = makeVar fd cur_loop "d2" in (match stripCastsDeep e with - (* J: if x' + e2 or x' - e2 with x' = x and the type arithmetic: - - adds incrementation for d1 and d2 to the code*) - (* J: if the loopVar is changed*) + (* J: if x' + e2 or x' - e2 with x' = x and the type arithmetic:- adds incrementation for d1 and d2 to the code*) + (* J: if the loopVar is changed*) | BinOp (op, Lval x', e2, typ) when (op = PlusA || op = MinusA) && x' = x && isArithmeticType typ -> (* TODO x = 1 + x, MinusA! *) (* increase diff by same expr *) let d1_inc = mkStmtOneInstr @@ Set (var d1, BinOp (PlusA, Lval (var d1), e2, typ), loc, eloc) in (* J: d1 = d1 + e2*) @@ -318,4 +317,4 @@ let _ = Cilfacade.register_preprocess (Spec.name ()) (new recomputeVisitor); (* J: ??? *) Hashtbl.clear loopBreaks; (* because the sids are now different *) (* J: delete entries in loopBreaks*) Cilfacade.register_preprocess (Spec.name ()) (new loopBreaksVisitor); (* J: newly set hash table loopBreaks with goto statements*) - MCP.register_analysis (module Spec : MCPSpec) (* J: ???*) \ No newline at end of file + MCP.register_analysis (module Spec : MCPSpec) (* J: ???*) From ff19371cf58c5d9d584ec2c8f78fcdb50611aecd Mon Sep 17 00:00:00 2001 From: Atul Agarwal Date: Sun, 14 May 2023 23:24:39 +0200 Subject: [PATCH 007/327] Update termination.ml indentation test check --- src/analyses/termination.ml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/analyses/termination.ml b/src/analyses/termination.ml index 0040055e03..eb6c263870 100644 --- a/src/analyses/termination.ml +++ b/src/analyses/termination.ml @@ -238,8 +238,8 @@ class loopInstrVisitor (fd : fundec) = object(self) let d1 = makeVar fd cur_loop "d1" in let d2 = makeVar fd cur_loop "d2" in (match stripCastsDeep e with - (* J: if x' + e2 or x' - e2 with x' = x and the type arithmetic:- adds incrementation for d1 and d2 to the code*) - (* J: if the loopVar is changed*) + (* J: if x' + e2 or x' - e2 with x' = x and the type arithmetic:- adds incrementation for d1 and d2 to the code*) + (* J: if the loopVar is changed*) | BinOp (op, Lval x', e2, typ) when (op = PlusA || op = MinusA) && x' = x && isArithmeticType typ -> (* TODO x = 1 + x, MinusA! *) (* increase diff by same expr *) let d1_inc = mkStmtOneInstr @@ Set (var d1, BinOp (PlusA, Lval (var d1), e2, typ), loc, eloc) in (* J: d1 = d1 + e2*) From cb3f49429d429b51a2fd27b1960103a895220ba5 Mon Sep 17 00:00:00 2001 From: Alexander Schlenga Date: Wed, 17 May 2023 11:16:48 +0200 Subject: [PATCH 008/327] One comment in old termination analysis --- src/analyses/termination.ml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/analyses/termination.ml b/src/analyses/termination.ml index eb6c263870..f963d0d094 100644 --- a/src/analyses/termination.ml +++ b/src/analyses/termination.ml @@ -317,4 +317,5 @@ let _ = Cilfacade.register_preprocess (Spec.name ()) (new recomputeVisitor); (* J: ??? *) Hashtbl.clear loopBreaks; (* because the sids are now different *) (* J: delete entries in loopBreaks*) Cilfacade.register_preprocess (Spec.name ()) (new loopBreaksVisitor); (* J: newly set hash table loopBreaks with goto statements*) - MCP.register_analysis (module Spec : MCPSpec) (* J: ???*) + MCP.register_analysis (module Spec : MCPSpec) (* A: register this (termination) analysis withing the master control program, which + collects all active analyses and represents the combination of them as a new, single analysis to FromSpec *) From 20f0bbd5751b4a854361dd0c6f3724500d077eae Mon Sep 17 00:00:00 2001 From: Alexander Schlenga Date: Wed, 17 May 2023 11:25:31 +0200 Subject: [PATCH 009/327] Create new termination analysis file --- src/analyses/termination_new.ml | 12 ++++++++++++ 1 file changed, 12 insertions(+) create mode 100644 src/analyses/termination_new.ml diff --git a/src/analyses/termination_new.ml b/src/analyses/termination_new.ml new file mode 100644 index 0000000000..afc2ea3ece --- /dev/null +++ b/src/analyses/termination_new.ml @@ -0,0 +1,12 @@ +open Prelude.Ana +open Analyses + +module Spec : Analyses.MCPSpec = +struct + + let query ctx (type a) (q: a Queries.t): a Queries.result = () + +end + +let _ = + MCP.register_analysis (module Spec : MCPSpec) From c4e92dba282891d8bd4e92d624cb26bb72b86abd Mon Sep 17 00:00:00 2001 From: Alexander Schlenga Date: Wed, 17 May 2023 12:15:06 +0200 Subject: [PATCH 010/327] Better dummy query --- src/analyses/termination_new.ml | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/src/analyses/termination_new.ml b/src/analyses/termination_new.ml index afc2ea3ece..9d1319119f 100644 --- a/src/analyses/termination_new.ml +++ b/src/analyses/termination_new.ml @@ -1,12 +1,19 @@ +(** Work in progress *) + open Prelude.Ana open Analyses +let terminates loop = () (* TODO *) + module Spec : Analyses.MCPSpec = struct - let query ctx (type a) (q: a Queries.t): a Queries.result = () + let query ctx (type a) (q: a Queries.t): a Queries.result = + let open Queries in + Result.top q (* TODO *) end let _ = + (* Register this analysis within the master control program *) MCP.register_analysis (module Spec : MCPSpec) From 14f2bdd90c4f5fb1ad69913d87441feedb0ed4fe Mon Sep 17 00:00:00 2001 From: Alexander Schlenga Date: Wed, 17 May 2023 18:00:23 +0200 Subject: [PATCH 011/327] Add required functions and values --- src/analyses/termination_new.ml | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/src/analyses/termination_new.ml b/src/analyses/termination_new.ml index 9d1319119f..e6b202b69e 100644 --- a/src/analyses/termination_new.ml +++ b/src/analyses/termination_new.ml @@ -8,6 +8,17 @@ let terminates loop = () (* TODO *) module Spec : Analyses.MCPSpec = struct + let name () = "termination" + + module D = Lattice.Unit (* TODO *) + module C = D (* TODO *) + + let startstate _ = D.bot () (* TODO *) + let exitstate = startstate (* TODO *) + + (** Provides some default implementations *) + include Analyses.IdentitySpec + let query ctx (type a) (q: a Queries.t): a Queries.result = let open Queries in Result.top q (* TODO *) @@ -15,5 +26,5 @@ struct end let _ = - (* Register this analysis within the master control program *) + (** Register this analysis within the master control program *) MCP.register_analysis (module Spec : MCPSpec) From 6fc9a1efe42f38f5ef2c2cef20c99c8523068726 Mon Sep 17 00:00:00 2001 From: Alexander Schlenga Date: Wed, 17 May 2023 18:19:30 +0200 Subject: [PATCH 012/327] Do not open the prelude --- src/analyses/termination_new.ml | 1 - 1 file changed, 1 deletion(-) diff --git a/src/analyses/termination_new.ml b/src/analyses/termination_new.ml index e6b202b69e..c81ff72d71 100644 --- a/src/analyses/termination_new.ml +++ b/src/analyses/termination_new.ml @@ -1,6 +1,5 @@ (** Work in progress *) -open Prelude.Ana open Analyses let terminates loop = () (* TODO *) From ec89bc2be9b31350b4f7cd135ab8cb128bc3f8a9 Mon Sep 17 00:00:00 2001 From: Johanna Schinabeck Date: Thu, 18 May 2023 15:38:59 +0200 Subject: [PATCH 013/327] added code adding to terminationPreprocessing file in util; created sh script to execute the code easily and store the cil output in the output.txt file; NOTE: the signs.ml file does currently contain the termination analysis; signsOrig.ml contains the original signs analysis --- output.txt | 2167 ++++++++++++++++++++++++++ runningGob.sh | 3 + src/analyses/tutorials/signs.ml | 22 + src/analyses/tutorials/signsOrig.ml | 92 ++ src/util/terminationPreprocessing.ml | 42 +- 5 files changed, 2325 insertions(+), 1 deletion(-) create mode 100644 output.txt create mode 100755 runningGob.sh create mode 100644 src/analyses/tutorials/signsOrig.ml diff --git a/output.txt b/output.txt new file mode 100644 index 0000000000..d3b021a1f3 --- /dev/null +++ b/output.txt @@ -0,0 +1,2167 @@ +/* Generated by CIL v. 2.0.1-48-g4df989f */ +/* print_CIL_Input is true */ + +#line 31 "/usr/include/x86_64-linux-gnu/bits/types.h" +typedef unsigned char __u_char; +#line 32 "/usr/include/x86_64-linux-gnu/bits/types.h" +typedef unsigned short __u_short; +#line 33 "/usr/include/x86_64-linux-gnu/bits/types.h" +typedef unsigned int __u_int; +#line 34 "/usr/include/x86_64-linux-gnu/bits/types.h" +typedef unsigned long __u_long; +#line 37 "/usr/include/x86_64-linux-gnu/bits/types.h" +typedef signed char __int8_t; +#line 38 "/usr/include/x86_64-linux-gnu/bits/types.h" +typedef unsigned char __uint8_t; +#line 39 "/usr/include/x86_64-linux-gnu/bits/types.h" +typedef short __int16_t; +#line 40 "/usr/include/x86_64-linux-gnu/bits/types.h" +typedef unsigned short __uint16_t; +#line 41 "/usr/include/x86_64-linux-gnu/bits/types.h" +typedef int __int32_t; +#line 42 "/usr/include/x86_64-linux-gnu/bits/types.h" +typedef unsigned int __uint32_t; +#line 44 "/usr/include/x86_64-linux-gnu/bits/types.h" +typedef long __int64_t; +#line 45 "/usr/include/x86_64-linux-gnu/bits/types.h" +typedef unsigned long __uint64_t; +#line 52 "/usr/include/x86_64-linux-gnu/bits/types.h" +typedef __int8_t __int_least8_t; +#line 53 "/usr/include/x86_64-linux-gnu/bits/types.h" +typedef __uint8_t __uint_least8_t; +#line 54 "/usr/include/x86_64-linux-gnu/bits/types.h" +typedef __int16_t __int_least16_t; +#line 55 "/usr/include/x86_64-linux-gnu/bits/types.h" +typedef __uint16_t __uint_least16_t; +#line 56 "/usr/include/x86_64-linux-gnu/bits/types.h" +typedef __int32_t __int_least32_t; +#line 57 "/usr/include/x86_64-linux-gnu/bits/types.h" +typedef __uint32_t __uint_least32_t; +#line 58 "/usr/include/x86_64-linux-gnu/bits/types.h" +typedef __int64_t __int_least64_t; +#line 59 "/usr/include/x86_64-linux-gnu/bits/types.h" +typedef __uint64_t __uint_least64_t; +#line 63 "/usr/include/x86_64-linux-gnu/bits/types.h" +typedef long __quad_t; +#line 64 "/usr/include/x86_64-linux-gnu/bits/types.h" +typedef unsigned long __u_quad_t; +#line 72 "/usr/include/x86_64-linux-gnu/bits/types.h" +typedef long __intmax_t; +#line 73 "/usr/include/x86_64-linux-gnu/bits/types.h" +typedef unsigned long __uintmax_t; +#line 145 "/usr/include/x86_64-linux-gnu/bits/types.h" +typedef unsigned long __dev_t; +#line 146 "/usr/include/x86_64-linux-gnu/bits/types.h" +typedef unsigned int __uid_t; +#line 147 "/usr/include/x86_64-linux-gnu/bits/types.h" +typedef unsigned int __gid_t; +#line 148 "/usr/include/x86_64-linux-gnu/bits/types.h" +typedef unsigned long __ino_t; +#line 149 "/usr/include/x86_64-linux-gnu/bits/types.h" +typedef unsigned long __ino64_t; +#line 150 "/usr/include/x86_64-linux-gnu/bits/types.h" +typedef unsigned int __mode_t; +#line 151 "/usr/include/x86_64-linux-gnu/bits/types.h" +typedef unsigned long __nlink_t; +#line 152 "/usr/include/x86_64-linux-gnu/bits/types.h" +typedef long __off_t; +#line 153 "/usr/include/x86_64-linux-gnu/bits/types.h" +typedef long __off64_t; +#line 154 "/usr/include/x86_64-linux-gnu/bits/types.h" +typedef int __pid_t; +#line 155 "/usr/include/x86_64-linux-gnu/bits/types.h" +struct __anonstruct___fsid_t_109580352 { + int __val[2] ; +}; +#line 155 "/usr/include/x86_64-linux-gnu/bits/types.h" +typedef struct __anonstruct___fsid_t_109580352 __fsid_t; +#line 156 "/usr/include/x86_64-linux-gnu/bits/types.h" +typedef long __clock_t; +#line 157 "/usr/include/x86_64-linux-gnu/bits/types.h" +typedef unsigned long __rlim_t; +#line 158 "/usr/include/x86_64-linux-gnu/bits/types.h" +typedef unsigned long __rlim64_t; +#line 159 "/usr/include/x86_64-linux-gnu/bits/types.h" +typedef unsigned int __id_t; +#line 160 "/usr/include/x86_64-linux-gnu/bits/types.h" +typedef long __time_t; +#line 161 "/usr/include/x86_64-linux-gnu/bits/types.h" +typedef unsigned int __useconds_t; +#line 162 "/usr/include/x86_64-linux-gnu/bits/types.h" +typedef long __suseconds_t; +#line 163 "/usr/include/x86_64-linux-gnu/bits/types.h" +typedef long __suseconds64_t; +#line 165 "/usr/include/x86_64-linux-gnu/bits/types.h" +typedef int __daddr_t; +#line 166 "/usr/include/x86_64-linux-gnu/bits/types.h" +typedef int __key_t; +#line 169 "/usr/include/x86_64-linux-gnu/bits/types.h" +typedef int __clockid_t; +#line 172 "/usr/include/x86_64-linux-gnu/bits/types.h" +typedef void *__timer_t; +#line 175 "/usr/include/x86_64-linux-gnu/bits/types.h" +typedef long __blksize_t; +#line 180 "/usr/include/x86_64-linux-gnu/bits/types.h" +typedef long __blkcnt_t; +#line 181 "/usr/include/x86_64-linux-gnu/bits/types.h" +typedef long __blkcnt64_t; +#line 184 "/usr/include/x86_64-linux-gnu/bits/types.h" +typedef unsigned long __fsblkcnt_t; +#line 185 "/usr/include/x86_64-linux-gnu/bits/types.h" +typedef unsigned long __fsblkcnt64_t; +#line 188 "/usr/include/x86_64-linux-gnu/bits/types.h" +typedef unsigned long __fsfilcnt_t; +#line 189 "/usr/include/x86_64-linux-gnu/bits/types.h" +typedef unsigned long __fsfilcnt64_t; +#line 192 "/usr/include/x86_64-linux-gnu/bits/types.h" +typedef long __fsword_t; +#line 194 "/usr/include/x86_64-linux-gnu/bits/types.h" +typedef long __ssize_t; +#line 197 "/usr/include/x86_64-linux-gnu/bits/types.h" +typedef long __syscall_slong_t; +#line 199 "/usr/include/x86_64-linux-gnu/bits/types.h" +typedef unsigned long __syscall_ulong_t; +#line 203 "/usr/include/x86_64-linux-gnu/bits/types.h" +typedef __off64_t __loff_t; +#line 204 "/usr/include/x86_64-linux-gnu/bits/types.h" +typedef char *__caddr_t; +#line 207 "/usr/include/x86_64-linux-gnu/bits/types.h" +typedef long __intptr_t; +#line 210 "/usr/include/x86_64-linux-gnu/bits/types.h" +typedef unsigned int __socklen_t; +#line 215 "/usr/include/x86_64-linux-gnu/bits/types.h" +typedef int __sig_atomic_t; +#line 209 "/usr/lib/gcc/x86_64-linux-gnu/11/include/stddef.h" +typedef unsigned long size_t; +#line 10 "/usr/include/x86_64-linux-gnu/bits/types/time_t.h" +typedef __time_t time_t; +#line 11 "/usr/include/x86_64-linux-gnu/bits/types/struct_timespec.h" +struct timespec { + __time_t tv_sec ; + __syscall_slong_t tv_nsec ; +}; +#line 38 "/usr/include/sched.h" +typedef __pid_t pid_t; +#line 23 "/usr/include/x86_64-linux-gnu/bits/types/struct_sched_param.h" +struct sched_param { + int sched_priority ; +}; +#line 32 "/usr/include/x86_64-linux-gnu/bits/cpu-set.h" +typedef unsigned long __cpu_mask; +#line 39 "/usr/include/x86_64-linux-gnu/bits/cpu-set.h" +struct __anonstruct_cpu_set_t_826868708 { + __cpu_mask __bits[1024UL / (8UL * sizeof(__cpu_mask ))] ; +}; +#line 39 "/usr/include/x86_64-linux-gnu/bits/cpu-set.h" +typedef struct __anonstruct_cpu_set_t_826868708 cpu_set_t; +#line 7 "/usr/include/x86_64-linux-gnu/bits/types/clock_t.h" +typedef __clock_t clock_t; +#line 7 "/usr/include/x86_64-linux-gnu/bits/types/struct_tm.h" +struct tm { + int tm_sec ; + int tm_min ; + int tm_hour ; + int tm_mday ; + int tm_mon ; + int tm_year ; + int tm_wday ; + int tm_yday ; + int tm_isdst ; + long tm_gmtoff ; + char const *tm_zone ; +}; +#line 7 "/usr/include/x86_64-linux-gnu/bits/types/clockid_t.h" +typedef __clockid_t clockid_t; +#line 7 "/usr/include/x86_64-linux-gnu/bits/types/timer_t.h" +typedef __timer_t timer_t; +#line 8 "/usr/include/x86_64-linux-gnu/bits/types/struct_itimerspec.h" +struct itimerspec { + struct timespec it_interval ; + struct timespec it_value ; +}; +#line 49 "/usr/include/time.h" +struct sigevent ; +#line 27 "/usr/include/x86_64-linux-gnu/bits/types/__locale_t.h" +struct __locale_data ; +#line 27 "/usr/include/x86_64-linux-gnu/bits/types/__locale_t.h" +struct __locale_struct { + struct __locale_data *__locales[13] ; + unsigned short const *__ctype_b ; + int const *__ctype_tolower ; + int const *__ctype_toupper ; + char const *__names[13] ; +}; +#line 41 "/usr/include/x86_64-linux-gnu/bits/types/__locale_t.h" +typedef struct __locale_struct *__locale_t; +#line 24 "/usr/include/x86_64-linux-gnu/bits/types/locale_t.h" +typedef __locale_t locale_t; +#line 25 "/usr/include/x86_64-linux-gnu/bits/atomic_wide_counter.h" +struct __anonstruct___value32_817613185 { + unsigned int __low ; + unsigned int __high ; +}; +#line 25 "/usr/include/x86_64-linux-gnu/bits/atomic_wide_counter.h" +union __anonunion___atomic_wide_counter_643133811 { + unsigned long long __value64 ; + struct __anonstruct___value32_817613185 __value32 ; +}; +#line 25 "/usr/include/x86_64-linux-gnu/bits/atomic_wide_counter.h" +typedef union __anonunion___atomic_wide_counter_643133811 __atomic_wide_counter; +#line 51 "/usr/include/x86_64-linux-gnu/bits/thread-shared-types.h" +struct __pthread_internal_list { + struct __pthread_internal_list *__prev ; + struct __pthread_internal_list *__next ; +}; +#line 51 "/usr/include/x86_64-linux-gnu/bits/thread-shared-types.h" +typedef struct __pthread_internal_list __pthread_list_t; +#line 57 "/usr/include/x86_64-linux-gnu/bits/thread-shared-types.h" +struct __pthread_internal_slist { + struct __pthread_internal_slist *__next ; +}; +#line 57 "/usr/include/x86_64-linux-gnu/bits/thread-shared-types.h" +typedef struct __pthread_internal_slist __pthread_slist_t; +#line 22 "/usr/include/x86_64-linux-gnu/bits/struct_mutex.h" +struct __pthread_mutex_s { + int __lock ; + unsigned int __count ; + int __owner ; + unsigned int __nusers ; + int __kind ; + short __spins ; + short __elision ; + __pthread_list_t __list ; +}; +#line 23 "/usr/include/x86_64-linux-gnu/bits/struct_rwlock.h" +struct __pthread_rwlock_arch_t { + unsigned int __readers ; + unsigned int __writers ; + unsigned int __wrphase_futex ; + unsigned int __writers_futex ; + unsigned int __pad3 ; + unsigned int __pad4 ; + int __cur_writer ; + int __shared ; + signed char __rwelision ; + unsigned char __pad1[7] ; + unsigned long __pad2 ; + unsigned int __flags ; +}; +#line 94 "/usr/include/x86_64-linux-gnu/bits/thread-shared-types.h" +struct __pthread_cond_s { + __atomic_wide_counter __wseq ; + __atomic_wide_counter __g1_start ; + unsigned int __g_refs[2] ; + unsigned int __g_size[2] ; + unsigned int __g1_orig_size ; + unsigned int __wrefs ; + unsigned int __g_signals[2] ; +}; +#line 105 "/usr/include/x86_64-linux-gnu/bits/thread-shared-types.h" +typedef unsigned int __tss_t; +#line 106 "/usr/include/x86_64-linux-gnu/bits/thread-shared-types.h" +typedef unsigned long __thrd_t; +#line 108 "/usr/include/x86_64-linux-gnu/bits/thread-shared-types.h" +struct __anonstruct___once_flag_826868709 { + int __data ; +}; +#line 108 "/usr/include/x86_64-linux-gnu/bits/thread-shared-types.h" +typedef struct __anonstruct___once_flag_826868709 __once_flag; +#line 27 "/usr/include/x86_64-linux-gnu/bits/pthreadtypes.h" +typedef unsigned long pthread_t; +#line 32 "/usr/include/x86_64-linux-gnu/bits/pthreadtypes.h" +union __anonunion_pthread_mutexattr_t_488594144 { + char __size[4] ; + int __align ; +}; +#line 32 "/usr/include/x86_64-linux-gnu/bits/pthreadtypes.h" +typedef union __anonunion_pthread_mutexattr_t_488594144 pthread_mutexattr_t; +#line 41 "/usr/include/x86_64-linux-gnu/bits/pthreadtypes.h" +union __anonunion_pthread_condattr_t_488594145 { + char __size[4] ; + int __align ; +}; +#line 41 "/usr/include/x86_64-linux-gnu/bits/pthreadtypes.h" +typedef union __anonunion_pthread_condattr_t_488594145 pthread_condattr_t; +#line 49 "/usr/include/x86_64-linux-gnu/bits/pthreadtypes.h" +typedef unsigned int pthread_key_t; +#line 53 "/usr/include/x86_64-linux-gnu/bits/pthreadtypes.h" +typedef int pthread_once_t; +#line 56 "/usr/include/x86_64-linux-gnu/bits/pthreadtypes.h" +union pthread_attr_t { + char __size[56] ; + long __align ; +}; +#line 62 "/usr/include/x86_64-linux-gnu/bits/pthreadtypes.h" +typedef union pthread_attr_t pthread_attr_t; +#line 67 "/usr/include/x86_64-linux-gnu/bits/pthreadtypes.h" +union __anonunion_pthread_mutex_t_335460617 { + struct __pthread_mutex_s __data ; + char __size[40] ; + long __align ; +}; +#line 67 "/usr/include/x86_64-linux-gnu/bits/pthreadtypes.h" +typedef union __anonunion_pthread_mutex_t_335460617 pthread_mutex_t; +#line 75 "/usr/include/x86_64-linux-gnu/bits/pthreadtypes.h" +union __anonunion_pthread_cond_t_951761805 { + struct __pthread_cond_s __data ; + char __size[48] ; + long long __align ; +}; +#line 75 "/usr/include/x86_64-linux-gnu/bits/pthreadtypes.h" +typedef union __anonunion_pthread_cond_t_951761805 pthread_cond_t; +#line 86 "/usr/include/x86_64-linux-gnu/bits/pthreadtypes.h" +union __anonunion_pthread_rwlock_t_656928968 { + struct __pthread_rwlock_arch_t __data ; + char __size[56] ; + long __align ; +}; +#line 86 "/usr/include/x86_64-linux-gnu/bits/pthreadtypes.h" +typedef union __anonunion_pthread_rwlock_t_656928968 pthread_rwlock_t; +#line 93 "/usr/include/x86_64-linux-gnu/bits/pthreadtypes.h" +union __anonunion_pthread_rwlockattr_t_145707745 { + char __size[8] ; + long __align ; +}; +#line 93 "/usr/include/x86_64-linux-gnu/bits/pthreadtypes.h" +typedef union __anonunion_pthread_rwlockattr_t_145707745 pthread_rwlockattr_t; +#line 103 "/usr/include/x86_64-linux-gnu/bits/pthreadtypes.h" +typedef int volatile pthread_spinlock_t; +#line 108 "/usr/include/x86_64-linux-gnu/bits/pthreadtypes.h" +union __anonunion_pthread_barrier_t_145707746 { + char __size[32] ; + long __align ; +}; +#line 108 "/usr/include/x86_64-linux-gnu/bits/pthreadtypes.h" +typedef union __anonunion_pthread_barrier_t_145707746 pthread_barrier_t; +#line 114 "/usr/include/x86_64-linux-gnu/bits/pthreadtypes.h" +union __anonunion_pthread_barrierattr_t_951761806 { + char __size[4] ; + int __align ; +}; +#line 114 "/usr/include/x86_64-linux-gnu/bits/pthreadtypes.h" +typedef union __anonunion_pthread_barrierattr_t_951761806 pthread_barrierattr_t; +#line 31 "/usr/include/x86_64-linux-gnu/bits/setjmp.h" +typedef long __jmp_buf[8]; +#line 5 "/usr/include/x86_64-linux-gnu/bits/types/__sigset_t.h" +struct __anonstruct___sigset_t_764561023 { + unsigned long __val[1024UL / (8UL * sizeof(unsigned long ))] ; +}; +#line 5 "/usr/include/x86_64-linux-gnu/bits/types/__sigset_t.h" +typedef struct __anonstruct___sigset_t_764561023 __sigset_t; +#line 26 "/usr/include/x86_64-linux-gnu/bits/types/struct___jmp_buf_tag.h" +struct __jmp_buf_tag { + __jmp_buf __jmpbuf ; + int __mask_was_saved ; + __sigset_t __saved_mask ; +}; +#line 37 "/usr/include/pthread.h" +enum __anonenum_34415463 { + PTHREAD_CREATE_JOINABLE = 0, + PTHREAD_CREATE_DETACHED = 1 +} ; +#line 47 +enum __anonenum_508643754 { + PTHREAD_MUTEX_TIMED_NP = 0, + PTHREAD_MUTEX_RECURSIVE_NP = 1, + PTHREAD_MUTEX_ERRORCHECK_NP = 2, + PTHREAD_MUTEX_ADAPTIVE_NP = 3, + PTHREAD_MUTEX_NORMAL = 0, + PTHREAD_MUTEX_RECURSIVE = 1, + PTHREAD_MUTEX_ERRORCHECK = 2, + PTHREAD_MUTEX_DEFAULT = 0 +} ; +#line 69 +enum __anonenum_931900394 { + PTHREAD_MUTEX_STALLED = 0, + PTHREAD_MUTEX_STALLED_NP = 0, + PTHREAD_MUTEX_ROBUST = 1, + PTHREAD_MUTEX_ROBUST_NP = 1 +} ; +#line 81 +enum __anonenum_205214487 { + PTHREAD_PRIO_NONE = 0, + PTHREAD_PRIO_INHERIT = 1, + PTHREAD_PRIO_PROTECT = 2 +} ; +#line 104 +enum __anonenum_25043950 { + PTHREAD_RWLOCK_PREFER_READER_NP = 0, + PTHREAD_RWLOCK_PREFER_WRITER_NP = 1, + PTHREAD_RWLOCK_PREFER_WRITER_NONRECURSIVE_NP = 2, + PTHREAD_RWLOCK_DEFAULT_NP = 0 +} ; +#line 124 +enum __anonenum_436439511 { + PTHREAD_INHERIT_SCHED = 0, + PTHREAD_EXPLICIT_SCHED = 1 +} ; +#line 134 +enum __anonenum_998661166 { + PTHREAD_SCOPE_SYSTEM = 0, + PTHREAD_SCOPE_PROCESS = 1 +} ; +#line 144 +enum __anonenum_146137331 { + PTHREAD_PROCESS_PRIVATE = 0, + PTHREAD_PROCESS_SHARED = 1 +} ; +#line 159 "/usr/include/pthread.h" +struct _pthread_cleanup_buffer { + void (*__routine)(void * ) ; + void *__arg ; + int __canceltype ; + struct _pthread_cleanup_buffer *__prev ; +}; +#line 168 +enum __anonenum_53396917 { + PTHREAD_CANCEL_ENABLE = 0, + PTHREAD_CANCEL_DISABLE = 1 +} ; +#line 175 +enum __anonenum_904563783 { + PTHREAD_CANCEL_DEFERRED = 0, + PTHREAD_CANCEL_ASYNCHRONOUS = 1 +} ; +#line 538 "/usr/include/pthread.h" +struct __cancel_jmp_buf_tag { + __jmp_buf __cancel_jmp_buf ; + int __mask_was_saved ; +}; +#line 544 "/usr/include/pthread.h" +struct __anonstruct___pthread_unwind_buf_t_530692248 { + struct __cancel_jmp_buf_tag __cancel_jmp_buf[1] ; + void *__pad[4] ; +}; +#line 544 "/usr/include/pthread.h" +typedef struct __anonstruct___pthread_unwind_buf_t_530692248 __attribute__((__aligned__)) __pthread_unwind_buf_t; +#line 557 "/usr/include/pthread.h" +struct __pthread_cleanup_frame { + void (*__cancel_routine)(void * ) ; + void *__cancel_arg ; + int __do_it ; + int __cancel_type ; +}; +#line 143 "/usr/lib/gcc/x86_64-linux-gnu/11/include/stddef.h" +typedef long ptrdiff_t; +#line 321 "/usr/lib/gcc/x86_64-linux-gnu/11/include/stddef.h" +typedef int wchar_t; +#line 415 "/usr/lib/gcc/x86_64-linux-gnu/11/include/stddef.h" +struct __anonstruct_max_align_t_896270833 { + long long __max_align_ll __attribute__((__aligned__(__alignof__(long long )))) ; + long double __max_align_ld __attribute__((__aligned__(__alignof__(long double )))) ; +}; +#line 415 "/usr/lib/gcc/x86_64-linux-gnu/11/include/stddef.h" +typedef struct __anonstruct_max_align_t_896270833 max_align_t; +/* compiler builtin: + void __builtin_va_copy(__builtin_va_list , __builtin_va_list ) ; */ +/* compiler builtin: + void *__builtin_frob_return_address(void * ) ; */ +/* compiler builtin: + void __attribute__((__overloaded__)) __sync_and_and_fetch(...) ; */ +/* compiler builtin: + void __attribute__((__overloaded__)) __sync_fetch_and_or(...) ; */ +/* compiler builtin: + int __builtin_popcountll(unsigned long long ) ; */ +/* compiler builtin: + void __attribute__((__overloaded__)) __atomic_or_fetch(...) ; */ +/* compiler builtin: + float __builtin_atanf(float ) ; */ +/* compiler builtin: + float __attribute__((____vector_size____(16))) __builtin_ia32_addps(float __attribute__((____vector_size____(16))) , + float __attribute__((____vector_size____(16))) ) ; */ +/* compiler builtin: + unsigned long __builtin_strcspn(char const * , char const * ) ; */ +/* compiler builtin: + float __builtin_asinf(float ) ; */ +/* compiler builtin: + float __attribute__((____vector_size____(16))) __builtin_ia32_maxps(float __attribute__((____vector_size____(16))) , + float __attribute__((____vector_size____(16))) ) ; */ +/* compiler builtin: + float __attribute__((____vector_size____(16))) __builtin_ia32_unpckhps(float __attribute__((____vector_size____(16))) , + float __attribute__((____vector_size____(16))) ) ; */ +/* compiler builtin: + double __builtin_acos(double ) ; */ +/* compiler builtin: + int __builtin___sprintf_chk(char * , int , unsigned long , char const * , ...) ; */ +/* compiler builtin: + void __attribute__((__overloaded__)) __atomic_nand_fetch_8(...) ; */ +/* compiler builtin: + void __attribute__((__overloaded__)) __atomic_fetch_and(...) ; */ +/* compiler builtin: + void __attribute__((__overloaded__)) __atomic_xor_fetch_16(...) ; */ +/* compiler builtin: + double __builtin_cosh(double ) ; */ +/* compiler builtin: + float __builtin_tanhf(float ) ; */ +/* compiler builtin: + void __attribute__((__overloaded__)) __atomic_fetch_nand_16(...) ; */ +/* compiler builtin: + void *__builtin_mempcpy(void * , void const * , unsigned long ) ; */ +/* compiler builtin: + void __attribute__((__overloaded__)) __atomic_sub_fetch_1(...) ; */ +/* compiler builtin: + long double __builtin_sqrtl(long double ) ; */ +/* compiler builtin: + int __builtin_parity(unsigned int ) ; */ +/* compiler builtin: + void __attribute__((__overloaded__)) __atomic_fetch_or(...) ; */ +/* compiler builtin: + long double __builtin_coshl(long double ) ; */ +/* compiler builtin: + long double __builtin_cosl(long double ) ; */ +/* compiler builtin: + float __builtin_cosf(float ) ; */ +/* compiler builtin: + void __sync_synchronize(...) ; */ +/* compiler builtin: + long double __builtin_acosl(long double ) ; */ +/* compiler builtin: + void *__builtin___mempcpy_chk(void * , void const * , unsigned long , unsigned long ) ; */ +/* compiler builtin: + void __attribute__((__overloaded__)) __sync_or_and_fetch(...) ; */ +/* compiler builtin: + int __builtin_clz(unsigned int ) ; */ +/* compiler builtin: + void __attribute__((__overloaded__)) __atomic_nand_fetch_4(...) ; */ +/* compiler builtin: + double __builtin_log10(double ) ; */ +/* compiler builtin: + char *__builtin___strcat_chk(char * , char const * , unsigned long ) ; */ +/* compiler builtin: + float __builtin_modff(float , float * ) ; */ +/* compiler builtin: + void __attribute__((__overloaded__)) __atomic_sub_fetch_4(...) ; */ +/* compiler builtin: + _Bool __atomic_compare_exchange_n(...) ; */ +/* compiler builtin: + double __builtin_sin(double ) ; */ +/* compiler builtin: + double __builtin_frexp(double , int * ) ; */ +/* compiler builtin: + float __builtin_acosf(float ) ; */ +/* compiler builtin: + void __attribute__((__overloaded__)) __sync_add_and_fetch(...) ; */ +/* compiler builtin: + long double __builtin_sinhl(long double ) ; */ +/* compiler builtin: + char *__builtin___stpcpy_chk(char * , char const * , unsigned long ) ; */ +/* compiler builtin: + void __atomic_signal_fence(int ) ; */ +/* compiler builtin: + double __builtin_fabs(double ) ; */ +/* compiler builtin: + void __attribute__((__overloaded__)) __atomic_fetch_nand_1(...) ; */ +/* compiler builtin: + void __attribute__((__overloaded__)) __atomic_and_fetch_16(...) ; */ +/* compiler builtin: + void __attribute__((__overloaded__)) __sync_fetch_and_nand(...) ; */ +/* compiler builtin: + void __attribute__((__overloaded__)) __atomic_xor_fetch_8(...) ; */ +/* compiler builtin: + void __attribute__((__overloaded__)) __atomic_xor_fetch_2(...) ; */ +/* compiler builtin: + void __atomic_thread_fence(int ) ; */ +/* compiler builtin: + void __atomic_store_16(...) ; */ +/* compiler builtin: + void __builtin_va_start(__builtin_va_list ) ; */ +/* compiler builtin: + void __attribute__((__overloaded__)) __atomic_fetch_and_8(...) ; */ +/* compiler builtin: + short __builtin_bswap16(short ) ; */ +/* compiler builtin: + void __attribute__((__overloaded__)) __atomic_and_fetch_2(...) ; */ +/* compiler builtin: + _Bool __atomic_test_and_set(void * , int ) ; */ +/* compiler builtin: + void __attribute__((__overloaded__)) __atomic_fetch_add_8(...) ; */ +/* compiler builtin: + int __builtin_ctz(unsigned int ) ; */ +/* compiler builtin: + char *__builtin_strpbrk(char const * , char const * ) ; */ +/* compiler builtin: + char *__builtin_strcpy(char * , char const * ) ; */ +/* compiler builtin: + double __builtin_sqrt(double ) ; */ +/* compiler builtin: + __builtin_va_list __builtin_next_arg(void) ; */ +/* compiler builtin: + void __attribute__((__overloaded__)) __atomic_fetch_nand(...) ; */ +/* compiler builtin: + void __attribute__((__overloaded__)) __atomic_exchange_16(...) ; */ +/* compiler builtin: + void __atomic_clear(_Bool * , int ) ; */ +/* compiler builtin: + void __atomic_store(...) ; */ +/* compiler builtin: + void __attribute__((__overloaded__)) __atomic_add_fetch_2(...) ; */ +/* compiler builtin: + float __builtin_log10f(float ) ; */ +/* compiler builtin: + long double __builtin_fabsl(long double ) ; */ +/* compiler builtin: + long double __builtin_floorl(long double ) ; */ +/* compiler builtin: + void __attribute__((__overloaded__)) __atomic_fetch_xor_1(...) ; */ +/* compiler builtin: + void __attribute__((__overloaded__)) __atomic_and_fetch(...) ; */ +/* compiler builtin: + float __builtin_floorf(float ) ; */ +/* compiler builtin: + _Bool __atomic_compare_exchange_4(...) ; */ +/* compiler builtin: + void *__builtin_memcpy(void * , void const * , unsigned long ) ; */ +/* compiler builtin: + void __attribute__((__overloaded__)) __sync_sub_and_fetch(...) ; */ +/* compiler builtin: + void __attribute__((__overloaded__)) __sync_nand_and_fetch(...) ; */ +/* compiler builtin: + void __attribute__((__overloaded__)) __atomic_load_16(...) ; */ +/* compiler builtin: + float __attribute__((____vector_size____(16))) __builtin_ia32_subps(float __attribute__((____vector_size____(16))) , + float __attribute__((____vector_size____(16))) ) ; */ +/* compiler builtin: + int __builtin_parityll(unsigned long long ) ; */ +/* compiler builtin: + void __builtin_va_end(__builtin_va_list ) ; */ +/* compiler builtin: + void __builtin_bzero(void * , unsigned long ) ; */ +/* compiler builtin: + _Bool __atomic_always_lock_free(unsigned long , void * ) ; */ +/* compiler builtin: + int __builtin_strncmp(char const * , char const * , unsigned long ) ; */ +/* compiler builtin: + void __attribute__((__overloaded__)) __atomic_nand_fetch_16(...) ; */ +/* compiler builtin: + void __attribute__((__overloaded__)) __sync_xor_and_fetch(...) ; */ +/* compiler builtin: + int __builtin___vsprintf_chk(char * , int , unsigned long , char const * , + __builtin_va_list ) ; */ +/* compiler builtin: + float __builtin_sqrtf(float ) ; */ +/* compiler builtin: + double __builtin_nans(char const * ) ; */ +/* compiler builtin: + void __attribute__((__overloaded__)) __atomic_fetch_xor_8(...) ; */ +/* compiler builtin: + double __builtin_exp(double ) ; */ +/* compiler builtin: + void __attribute__((__overloaded__)) __atomic_exchange_8(...) ; */ +/* compiler builtin: + void __attribute__((__overloaded__)) __atomic_exchange_1(...) ; */ +/* compiler builtin: + int __builtin_strcmp(char const * , char const * ) ; */ +/* compiler builtin: + float __builtin_ldexpf(float , int ) ; */ +/* compiler builtin: + float __builtin_powif(float , int ) ; */ +/* compiler builtin: + long double __builtin_log10l(long double ) ; */ +/* compiler builtin: + void *__builtin___memmove_chk(void * , void const * , unsigned long , unsigned long ) ; */ +/* compiler builtin: + void __attribute__((__overloaded__)) __sync_fetch_and_and(...) ; */ +/* compiler builtin: + void *__builtin_return_address(unsigned int ) ; */ +/* compiler builtin: + void __atomic_feraiseexcept(int ) ; */ +/* compiler builtin: + void __attribute__((__overloaded__)) __atomic_and_fetch_4(...) ; */ +/* compiler builtin: + float __builtin_fabsf(float ) ; */ +/* compiler builtin: + void __attribute__((__overloaded__)) __atomic_or_fetch_8(...) ; */ +/* compiler builtin: + void __attribute__((__overloaded__)) __atomic_or_fetch_4(...) ; */ +/* compiler builtin: + void __attribute__((__overloaded__)) __atomic_or_fetch_1(...) ; */ +/* compiler builtin: + unsigned long __builtin_object_size(void * , int ) ; */ +/* compiler builtin: + void *__builtin_alloca(unsigned long ) ; */ +/* compiler builtin: + int __builtin_va_arg_pack_len(void) ; */ +/* compiler builtin: + long double __builtin_tanl(long double ) ; */ +/* compiler builtin: + void __attribute__((__overloaded__)) __atomic_fetch_and_2(...) ; */ +/* compiler builtin: + void __sync_lock_release(...) ; */ +/* compiler builtin: + long double __builtin_modfl(long double , long double * ) ; */ +/* compiler builtin: + void __attribute__((__overloaded__)) __atomic_fetch_nand_8(...) ; */ +/* compiler builtin: + char *__builtin_stpcpy(char * , char const * ) ; */ +/* compiler builtin: + long double __builtin_sinl(long double ) ; */ +/* compiler builtin: + double __builtin_asin(double ) ; */ +/* compiler builtin: + float __builtin_sinhf(float ) ; */ +/* compiler builtin: + int __builtin_ctzl(unsigned long ) ; */ +/* compiler builtin: + long double __builtin_tanhl(long double ) ; */ +/* compiler builtin: + void __attribute__((__overloaded__)) __atomic_fetch_add(...) ; */ +/* compiler builtin: + long __builtin_bswap64(long ) ; */ +/* compiler builtin: + void __attribute__((__overloaded__)) __atomic_nand_fetch_1(...) ; */ +/* compiler builtin: + void __attribute__((__overloaded__)) __atomic_fetch_nand_2(...) ; */ +/* compiler builtin: + float __attribute__((____vector_size____(16))) __builtin_ia32_mulps(float __attribute__((____vector_size____(16))) , + float __attribute__((____vector_size____(16))) ) ; */ +/* compiler builtin: + double __builtin_tan(double ) ; */ +/* compiler builtin: + char *__builtin_strncpy(char * , char const * , unsigned long ) ; */ +/* compiler builtin: + float __builtin_inff(void) ; */ +/* compiler builtin: + void *__builtin___memset_chk(void * , int , unsigned long , unsigned long ) ; */ +/* compiler builtin: + void __attribute__((__overloaded__)) __atomic_load_n(...) ; */ +/* compiler builtin: + double __builtin_huge_val(void) ; */ +/* compiler builtin: + int __builtin_clzl(unsigned long ) ; */ +/* compiler builtin: + _Bool __atomic_compare_exchange_16(...) ; */ +/* compiler builtin: + float __builtin_frexpf(float , int * ) ; */ +/* compiler builtin: + void __attribute__((__overloaded__)) __atomic_exchange_n(...) ; */ +/* compiler builtin: + void __attribute__((__overloaded__)) __atomic_fetch_or_1(...) ; */ +/* compiler builtin: + long double __builtin_fmodl(long double ) ; */ +/* compiler builtin: + double __builtin_atan(double ) ; */ +/* compiler builtin: + int __builtin___fprintf_chk(void * , int , char const * , ...) ; */ +/* compiler builtin: + float __builtin_ceilf(float ) ; */ +/* compiler builtin: + void __attribute__((__overloaded__)) __atomic_fetch_or_8(...) ; */ +/* compiler builtin: + void __attribute__((__overloaded__)) __atomic_fetch_add_1(...) ; */ +/* compiler builtin: + void __builtin_return(void const * ) ; */ +/* compiler builtin: + long double __builtin_asinl(long double ) ; */ +/* compiler builtin: + int __builtin_ffsll(unsigned long long ) ; */ +/* compiler builtin: + void __attribute__((__overloaded__)) __atomic_fetch_sub_1(...) ; */ +/* compiler builtin: + int __builtin_va_arg_pack(void) ; */ +/* compiler builtin: + void __attribute__((__overloaded__)) __atomic_fetch_or_4(...) ; */ +/* compiler builtin: + char *__builtin___strncpy_chk(char * , char const * , unsigned long , unsigned long ) ; */ +/* compiler builtin: + double __builtin_powi(double , int ) ; */ +/* compiler builtin: + void __attribute__((__overloaded__)) __atomic_load_2(...) ; */ +/* compiler builtin: + char *__builtin_strchr(char * , int ) ; */ +/* compiler builtin: + char *__builtin___strncat_chk(char * , char const * , unsigned long , unsigned long ) ; */ +/* compiler builtin: + void __atomic_store_2(...) ; */ +/* compiler builtin: + long double __builtin_huge_vall(void) ; */ +/* compiler builtin: + int __builtin_ffsl(unsigned long ) ; */ +/* compiler builtin: + int __builtin___vprintf_chk(int , char const * , __builtin_va_list ) ; */ +/* compiler builtin: + float __attribute__((____vector_size____(16))) __builtin_ia32_unpcklps(float __attribute__((____vector_size____(16))) , + float __attribute__((____vector_size____(16))) ) ; */ +/* compiler builtin: + char *__builtin_strncat(char * , char const * , unsigned long ) ; */ +/* compiler builtin: + int __builtin_ctzll(unsigned long long ) ; */ +/* compiler builtin: + void __builtin_stdarg_start(__builtin_va_list ) ; */ +/* compiler builtin: + void __attribute__((__overloaded__)) __atomic_exchange_4(...) ; */ +/* compiler builtin: + void __attribute__((__overloaded__)) __sync_fetch_and_xor(...) ; */ +/* compiler builtin: + void __attribute__((__overloaded__)) __atomic_fetch_sub_4(...) ; */ +/* compiler builtin: + void __attribute__((__overloaded__)) __atomic_fetch_and_4(...) ; */ +/* compiler builtin: + long double __builtin_frexpl(long double , int * ) ; */ +/* compiler builtin: + _Bool __atomic_compare_exchange(...) ; */ +/* compiler builtin: + float __builtin_tanf(float ) ; */ +/* compiler builtin: + long double __builtin_logl(long double ) ; */ +/* compiler builtin: + void __builtin_va_arg(__builtin_va_list , unsigned long , void * ) ; */ +/* compiler builtin: + long __builtin_expect(long , long ) ; */ +/* compiler builtin: + void __attribute__((__overloaded__)) __atomic_load_1(...) ; */ +/* compiler builtin: + _Bool __atomic_compare_exchange_1(...) ; */ +/* compiler builtin: + int __builtin___printf_chk(int , char const * , ...) ; */ +/* compiler builtin: + void __attribute__((__overloaded__)) __atomic_fetch_xor_2(...) ; */ +/* compiler builtin: + int __builtin___vfprintf_chk(void * , int , char const * , __builtin_va_list ) ; */ +/* compiler builtin: + void __builtin_prefetch(void const * , ...) ; */ +/* compiler builtin: + long double __builtin_nansl(char const * ) ; */ +/* compiler builtin: + double __builtin_fmod(double ) ; */ +/* compiler builtin: + void __atomic_load(...) ; */ +/* compiler builtin: + void __attribute__((__overloaded__)) __atomic_or_fetch_16(...) ; */ +/* compiler builtin: + void __attribute__((__overloaded__)) __atomic_add_fetch_16(...) ; */ +/* compiler builtin: + void __attribute__((__overloaded__)) __sync_val_compare_and_swap(...) ; */ +/* compiler builtin: + void __atomic_store_4(...) ; */ +/* compiler builtin: + double __builtin_tanh(double ) ; */ +/* compiler builtin: + void __attribute__((__overloaded__)) __atomic_fetch_and_1(...) ; */ +/* compiler builtin: + void __attribute__((__overloaded__)) __atomic_fetch_nand_4(...) ; */ +/* compiler builtin: + void __attribute__((__overloaded__)) __atomic_fetch_add_16(...) ; */ +/* compiler builtin: + void __builtin_unreachable(void) ; */ +/* compiler builtin: + _Bool __atomic_compare_exchange_2(...) ; */ +/* compiler builtin: + long double __builtin_ldexpl(long double , int ) ; */ +/* compiler builtin: + void *__builtin_apply(void (*)() , void * , unsigned long ) ; */ +/* compiler builtin: + float __builtin_sinf(float ) ; */ +/* compiler builtin: + double __builtin_ceil(double ) ; */ +/* compiler builtin: + void __atomic_exchange(...) ; */ +/* compiler builtin: + long double __builtin_powil(long double , int ) ; */ +/* compiler builtin: + void __attribute__((__overloaded__)) __atomic_sub_fetch_8(...) ; */ +/* compiler builtin: + long double __builtin_expl(long double ) ; */ +/* compiler builtin: + int __builtin_constant_p(int ) ; */ +/* compiler builtin: + void __attribute__((__overloaded__)) __atomic_fetch_sub_16(...) ; */ +/* compiler builtin: + double __builtin_log(double ) ; */ +/* compiler builtin: + float __builtin_expf(float ) ; */ +/* compiler builtin: + int __builtin_types_compatible_p(unsigned long , unsigned long ) ; */ +/* compiler builtin: + long double __builtin_atan2l(long double , long double ) ; */ +/* compiler builtin: + void *__builtin_apply_args(void) ; */ +/* compiler builtin: + void __attribute__((__overloaded__)) __atomic_exchange_2(...) ; */ +/* compiler builtin: + float __builtin_logf(float ) ; */ +/* compiler builtin: + void __attribute__((__overloaded__)) __atomic_sub_fetch_2(...) ; */ +/* compiler builtin: + unsigned long __builtin_strlen(char const * ) ; */ +/* compiler builtin: + int __builtin_ffs(unsigned int ) ; */ +/* compiler builtin: + void __attribute__((__overloaded__)) __atomic_fetch_xor_16(...) ; */ +/* compiler builtin: + double __builtin_inf(void) ; */ +/* compiler builtin: + void __attribute__((__overloaded__)) __atomic_fetch_or_16(...) ; */ +/* compiler builtin: + void *__builtin___memcpy_chk(void * , void const * , unsigned long , unsigned long ) ; */ +/* compiler builtin: + void __attribute__((__overloaded__)) __atomic_load_4(...) ; */ +/* compiler builtin: + void __atomic_store_n(...) ; */ +/* compiler builtin: + void __builtin_trap(void) ; */ +/* compiler builtin: + void __attribute__((__overloaded__)) __atomic_fetch_add_4(...) ; */ +/* compiler builtin: + int __builtin_parityl(unsigned long ) ; */ +/* compiler builtin: + void __attribute__((__overloaded__)) __atomic_nand_fetch_2(...) ; */ +/* compiler builtin: + void __attribute__((__overloaded__)) __sync_lock_test_and_set(...) ; */ +/* compiler builtin: + unsigned long __builtin_strspn(char const * , char const * ) ; */ +/* compiler builtin: + void __builtin_varargs_start(__builtin_va_list ) ; */ +/* compiler builtin: + void __attribute__((__overloaded__)) __atomic_sub_fetch(...) ; */ +/* compiler builtin: + void __attribute__((__overloaded__)) __atomic_fetch_and_16(...) ; */ +/* compiler builtin: + _Bool __atomic_compare_exchange_8(...) ; */ +/* compiler builtin: + void __attribute__((__overloaded__)) __atomic_nand_fetch(...) ; */ +/* compiler builtin: + double __builtin_nan(char const * ) ; */ +/* compiler builtin: + void __attribute__((__overloaded__)) __atomic_load_8(...) ; */ +/* compiler builtin: + int __builtin___snprintf_chk(char * , unsigned long , int , unsigned long , + char const * , ...) ; */ +/* compiler builtin: + void __attribute__((__overloaded__)) __atomic_xor_fetch_4(...) ; */ +/* compiler builtin: + void __attribute__((__overloaded__)) __atomic_fetch_sub_2(...) ; */ +/* compiler builtin: + void __attribute__((__overloaded__)) __atomic_add_fetch(...) ; */ +/* compiler builtin: + long double __builtin_atanl(long double ) ; */ +/* compiler builtin: + int __builtin_clzll(unsigned long long ) ; */ +/* compiler builtin: + float __builtin_huge_valf(void) ; */ +/* compiler builtin: + float __builtin_coshf(float ) ; */ +/* compiler builtin: + float __builtin_nansf(char const * ) ; */ +/* compiler builtin: + void __atomic_store_8(...) ; */ +/* compiler builtin: + void __attribute__((__overloaded__)) __atomic_xor_fetch(...) ; */ +/* compiler builtin: + void __attribute__((__overloaded__)) __sync_fetch_and_add(...) ; */ +/* compiler builtin: + int __builtin___vsnprintf_chk(char * , unsigned long , int , unsigned long , + char const * , __builtin_va_list ) ; */ +/* compiler builtin: + float __builtin_nanf(char const * ) ; */ +/* compiler builtin: + void __attribute__((__overloaded__)) __atomic_or_fetch_2(...) ; */ +/* compiler builtin: + void __attribute__((__overloaded__)) __atomic_add_fetch_1(...) ; */ +/* compiler builtin: + void __attribute__((__overloaded__)) __atomic_fetch_xor(...) ; */ +/* compiler builtin: + void __attribute__((__overloaded__)) __atomic_add_fetch_8(...) ; */ +/* compiler builtin: + void __attribute__((__overloaded__)) __atomic_fetch_xor_4(...) ; */ +/* compiler builtin: + void __attribute__((__overloaded__)) __atomic_fetch_sub_8(...) ; */ +/* compiler builtin: + _Bool __sync_bool_compare_and_swap(...) ; */ +/* compiler builtin: + double __builtin_atan2(double , double ) ; */ +/* compiler builtin: + void __attribute__((__overloaded__)) __builtin_tgmath(...) ; */ +/* compiler builtin: + int __builtin_popcountl(unsigned long ) ; */ +/* compiler builtin: + void __attribute__((__overloaded__)) __atomic_and_fetch_1(...) ; */ +/* compiler builtin: + long double __builtin_ceill(long double ) ; */ +/* compiler builtin: + void __atomic_store_1(...) ; */ +/* compiler builtin: + char *__builtin___strcpy_chk(char * , char const * , unsigned long ) ; */ +/* compiler builtin: + void __attribute__((__overloaded__)) __atomic_xor_fetch_1(...) ; */ +/* compiler builtin: + void __attribute__((__overloaded__)) __atomic_fetch_or_2(...) ; */ +/* compiler builtin: + void __attribute__((__overloaded__)) __atomic_sub_fetch_16(...) ; */ +/* compiler builtin: + double __builtin_floor(double ) ; */ +/* compiler builtin: + double __builtin_cos(double ) ; */ +/* compiler builtin: + void __attribute__((__overloaded__)) __sync_fetch_and_sub(...) ; */ +/* compiler builtin: + void *__builtin_memset(void * , int , int ) ; */ +/* compiler builtin: + void __attribute__((__overloaded__)) __atomic_fetch_add_2(...) ; */ +/* compiler builtin: + long double __builtin_nanl(char const * ) ; */ +/* compiler builtin: + float __builtin_atan2f(float , float ) ; */ +/* compiler builtin: + _Bool __atomic_is_lock_free(unsigned long , void * ) ; */ +/* compiler builtin: + int __builtin_popcount(unsigned int ) ; */ +/* compiler builtin: + double __builtin_sinh(double ) ; */ +/* compiler builtin: + void __builtin_bcopy(void const * , void * , unsigned long ) ; */ +/* compiler builtin: + void __attribute__((__overloaded__)) __atomic_and_fetch_8(...) ; */ +/* compiler builtin: + void __attribute__((__overloaded__)) __atomic_fetch_sub(...) ; */ +/* compiler builtin: + void *__builtin_extract_return_addr(void * ) ; */ +/* compiler builtin: + int __builtin_bswap32(int ) ; */ +/* compiler builtin: + double __builtin_ldexp(double , int ) ; */ +/* compiler builtin: + long double __builtin_infl(void) ; */ +/* compiler builtin: + float __builtin_fmodf(float ) ; */ +/* compiler builtin: + void __attribute__((__overloaded__)) __atomic_add_fetch_4(...) ; */ +/* compiler builtin: + void *__builtin_frame_address(unsigned int ) ; */ +#line 1 "lib/goblint/runtime/include/goblint.h" +extern void __goblint_check(int exp ) ; +#line 2 +extern void __goblint_assume(int exp ) ; +#line 3 +extern void __goblint_assert(int exp ) ; +#line 5 +extern void __goblint_assume_join() ; +#line 7 +extern void __goblint_split_begin(int exp ) ; +#line 8 +extern void __goblint_split_end(int exp ) ; +#line 4 "tests/regression/55-loop-unrolling/01-simple-cases.c" +int global ; +#line 8 +void example1(void) ; +#line 9 +void example2(void) ; +#line 10 +void example3(void) ; +#line 11 +void example4(void) ; +#line 12 +void example5(void) ; +#line 13 +void example6(void) ; +#line 14 +void example7(void) ; +#line 15 +void example8(void) ; +#line 16 +void example9(void) ; +#line 17 +void example10(void) ; +#line 6 "tests/regression/55-loop-unrolling/01-simple-cases.c" +int main(void) +{ + + + { +#line 8 + example1(); +#line 9 + example2(); +#line 10 + example3(); +#line 11 + example4(); +#line 12 + example5(); +#line 13 + example6(); +#line 14 + example7(); +#line 15 + example8(); +#line 16 + example9(); +#line 17 + example10(); +#line 18 + return (0); +} +} +#line 22 "tests/regression/55-loop-unrolling/01-simple-cases.c" +void example1(void) +{ + int a[5] ; + int i ; + int term27_5 = 0; + + { +#line 25 + i = 0; + { + { +#line 27 + while (1) { +#line 27 + term27_5 ++; + while_continue: /* CIL Label */ ; +#line 27 + if (! (i < 5)) { +#line 27 + goto while_break; + } +#line 28 + a[i] = i; +#line 29 + i ++; + } + } + while_break: /* CIL Label */ ; + } +#line 32 + __goblint_check(a[0] == 0); +#line 33 + __goblint_check(a[3] == 3); +#line 34 + return; +} +} +#line 37 "tests/regression/55-loop-unrolling/01-simple-cases.c" +void example2(void) +{ + int a[5] ; + int i ; + int term42_5 = 0; + + { +#line 40 + i = 0; + { + { +#line 42 + while (1) { +#line 42 + term42_5 ++; + while_continue: /* CIL Label */ ; +#line 43 + a[i] = i; +#line 44 + i ++; +#line 42 + if (! (i <= 5)) { +#line 42 + goto while_break; + } + } + } + while_break: /* CIL Label */ ; + } +#line 47 + __goblint_check(a[0] == 0); +#line 48 + __goblint_check(a[3] == 3); +#line 49 + return; +} +} +#line 52 "tests/regression/55-loop-unrolling/01-simple-cases.c" +void example3(void) +{ + int a[10] ; + int i ; + int term57_5 = 0; + + { +#line 55 + i = 0; + { + { +#line 57 + while (1) { +#line 57 + term57_5 ++; + while_continue: /* CIL Label */ ; +#line 57 + if (! (i < 5)) { +#line 57 + goto while_break; + } +#line 58 + a[i] = i; +#line 59 + i ++; + } + } + while_break: /* CIL Label */ ; + } +#line 62 + __goblint_check(a[0] == 0); +#line 63 + __goblint_check(a[3] == 0); +#line 64 + __goblint_check(a[7] == 0); +#line 65 + return; +} +} +#line 68 "tests/regression/55-loop-unrolling/01-simple-cases.c" +void example4(void) +{ + int a[10] ; + int i ; + int first_iteration ; + int term74_5 = 0; + + { +#line 71 + i = 0; +#line 72 + first_iteration = 1; + { + { +#line 74 + while (1) { +#line 74 + term74_5 ++; + while_continue: /* CIL Label */ ; +#line 74 + if (! (i < 10)) { +#line 74 + goto while_break; + } +#line 75 + if (first_iteration == 1) { +#line 75 + __goblint_check(i == 0); + } else +#line 76 + if (i > 5) { +#line 76 + __goblint_check(i == 6); + } +#line 77 + first_iteration = 0; +#line 78 + a[i] = 0; +#line 79 + i ++; + } + } + while_break: /* CIL Label */ ; + } +#line 82 + __goblint_check(a[0] == 0); +#line 83 + __goblint_check(first_iteration == 0); +#line 84 + return; +} +} +#line 89 "tests/regression/55-loop-unrolling/01-simple-cases.c" +void example5(void) +{ + int a[4] ; + int i ; + int top ; + int term95_5 = 0; + + { +#line 92 + i = 0; +#line 93 + top = 0; + { + { +#line 95 + while (1) { +#line 95 + term95_5 ++; + while_continue: /* CIL Label */ ; +#line 95 + if (! (i < 4)) { +#line 95 + goto while_break; + } +#line 96 + a[i] = 0; +#line 97 + top += i; +#line 98 + if (i == 2) { +#line 99 + __goblint_check(top == 3); + } else { +#line 102 + __goblint_check(top == 3); + } +#line 104 + i ++; + } + } + while_break: /* CIL Label */ ; + } +#line 107 + __goblint_check(a[0] == 0); +#line 108 + __goblint_check(a[3] == 0); +#line 109 + __goblint_check(top == 6); +#line 110 + return; +} +} +#line 113 "tests/regression/55-loop-unrolling/01-simple-cases.c" +void example6(void) +{ + int a[5] ; + int i ; + int top ; + int term119_5 = 0; + + { +#line 116 + i = 0; +#line 117 + top = 0; + { + { +#line 119 + while (1) { +#line 119 + term119_5 ++; + while_continue: /* CIL Label */ ; +#line 119 + if (! (i < 3)) { +#line 119 + goto while_break; + } +#line 120 + a[i] = 0; +#line 121 + __goblint_check(a[0] == 0); +#line 122 + i ++; + } + } + while_break: /* CIL Label */ ; + } +#line 125 + __goblint_check(a[0] == 0); +#line 126 + __goblint_check(a[3] == 0); +#line 127 + __goblint_check(top == 6); +#line 128 + return; +} +} +#line 131 "tests/regression/55-loop-unrolling/01-simple-cases.c" +int update(int i ) +{ + + + { +#line 132 + if (i > 5) { +#line 133 + return (0); + } else { +#line 136 + return (1); + } +} +} +#line 139 "tests/regression/55-loop-unrolling/01-simple-cases.c" +void example7(void) +{ + int a[10] ; + int i ; + int tmp ; + int term143_2 = 0; + + { +#line 142 + i = 0; + { + { +#line 143 + while (1) { +#line 143 + term143_2 ++; + while_continue: /* CIL Label */ ; +#line 143 + tmp = update(i); +#line 143 + if (! tmp) { +#line 143 + goto while_break; + } +#line 144 + a[i] = i; +#line 145 + i ++; + } + } + while_break: /* CIL Label */ ; + } +#line 147 + __goblint_check(a[0] == 0); +#line 148 + __goblint_check(a[6] == 0); +#line 149 + return; +} +} +#line 152 "tests/regression/55-loop-unrolling/01-simple-cases.c" +void example8(void) +{ + int a[5] ; + int b[5] ; + int i ; + int j ; + int term160_9 = 0; + int term157_2 = 0; + + { +#line 155 + b[0] = 0; +#line 155 + b[1] = 0; +#line 155 + b[2] = 0; +#line 155 + b[3] = 0; +#line 155 + b[4] = 0; +#line 156 + i = 0; + { + { +#line 157 + while (1) { +#line 157 + term157_2 ++; + while_continue: /* CIL Label */ ; +#line 157 + if (! (i < 5)) { +#line 157 + goto while_break; + } +#line 158 + a[i] = i; +#line 159 + j = 0; + { + { +#line 160 + while (1) { +#line 160 + term160_9 ++; + while_continue___0: /* CIL Label */ ; +#line 160 + if (! (j < 5)) { +#line 160 + goto while_break___0; + } +#line 161 + b[j] += a[i]; +#line 162 + j ++; + } + } + while_break___0: /* CIL Label */ ; + } +#line 164 + i ++; + } + } + while_break: /* CIL Label */ ; + } +#line 166 + return; +} +} +#line 170 "tests/regression/55-loop-unrolling/01-simple-cases.c" +void example9(void) +{ + int a[5] ; + int i ; + int term174_2 = 0; + + { +#line 173 + i = 0; + { + { +#line 174 + while (1) { +#line 174 + term174_2 ++; + while_continue: /* CIL Label */ ; +#line 174 + if (! 1) { +#line 174 + goto while_break; + } +#line 175 + a[i] = i; +#line 176 + i ++; +#line 177 + if (i == 5) { +#line 177 + goto while_break; + } + } + } + while_break: /* CIL Label */ ; + } +#line 179 + return; +} +} +#line 183 "tests/regression/55-loop-unrolling/01-simple-cases.c" +void example10(void) +{ + int a[5] ; + int i ; + int term187_2 = 0; + + { +#line 186 + i = 0; + { + { +#line 187 + while (1) { +#line 187 + term187_2 ++; + while_continue: /* CIL Label */ ; +#line 187 + if (! (i < 5)) { +#line 187 + goto while_break; + } +#line 188 + if (i == 3) { +#line 189 + i ++; +#line 190 + goto while_continue; + } +#line 192 + a[i] = i; +#line 193 + i ++; + } + } + while_break: /* CIL Label */ ; + } +#line 195 + return; +} +} +#line 117 "/usr/include/x86_64-linux-gnu/bits/cpu-set.h" +extern int ( __attribute__((__leaf__)) __sched_cpucount)(size_t __setsize , cpu_set_t const *__setp ) __attribute__((__nothrow__)) ; +#line 119 +extern cpu_set_t *( __attribute__((__leaf__)) __sched_cpualloc)(size_t __count ) __attribute__((__nothrow__)) ; +#line 120 +extern void ( __attribute__((__leaf__)) __sched_cpufree)(cpu_set_t *__set ) __attribute__((__nothrow__)) ; +#line 54 "/usr/include/sched.h" +extern int ( __attribute__((__leaf__)) sched_setparam)(__pid_t __pid , struct sched_param const *__param ) __attribute__((__nothrow__)) ; +#line 58 +extern int ( __attribute__((__leaf__)) sched_getparam)(__pid_t __pid , struct sched_param *__param ) __attribute__((__nothrow__)) ; +#line 61 +extern int ( __attribute__((__leaf__)) sched_setscheduler)(__pid_t __pid , int __policy , + struct sched_param const *__param ) __attribute__((__nothrow__)) ; +#line 65 +extern int ( __attribute__((__leaf__)) sched_getscheduler)(__pid_t __pid ) __attribute__((__nothrow__)) ; +#line 68 +extern int ( __attribute__((__leaf__)) sched_yield)(void) __attribute__((__nothrow__)) ; +#line 71 +extern int ( __attribute__((__leaf__)) sched_get_priority_max)(int __algorithm ) __attribute__((__nothrow__)) ; +#line 74 +extern int ( __attribute__((__leaf__)) sched_get_priority_min)(int __algorithm ) __attribute__((__nothrow__)) ; +#line 78 +extern int ( __attribute__((__leaf__)) sched_rr_get_interval)(__pid_t __pid , struct timespec *__t ) __attribute__((__nothrow__)) ; +#line 72 "/usr/include/time.h" +extern clock_t ( __attribute__((__leaf__)) clock)(void) __attribute__((__nothrow__)) ; +#line 76 +extern time_t ( __attribute__((__leaf__)) time)(time_t *__timer ) __attribute__((__nothrow__)) ; +#line 79 +extern double ( __attribute__((__leaf__)) difftime)(time_t __time1 , time_t __time0 ) __attribute__((__nothrow__, +__const__)) ; +#line 83 +extern time_t ( __attribute__((__leaf__)) mktime)(struct tm *__tp ) __attribute__((__nothrow__)) ; +#line 100 +extern size_t ( __attribute__((__leaf__)) strftime)(char * __restrict __s , size_t __maxsize , + char const * __restrict __format , + struct tm const * __restrict __tp ) __attribute__((__nothrow__)) ; +#line 116 +extern size_t ( __attribute__((__leaf__)) strftime_l)(char * __restrict __s , size_t __maxsize , + char const * __restrict __format , + struct tm const * __restrict __tp , + locale_t __loc ) __attribute__((__nothrow__)) ; +#line 132 +extern struct tm *( __attribute__((__leaf__)) gmtime)(time_t const *__timer ) __attribute__((__nothrow__)) ; +#line 136 +extern struct tm *( __attribute__((__leaf__)) localtime)(time_t const *__timer ) __attribute__((__nothrow__)) ; +#line 154 +extern struct tm *( __attribute__((__leaf__)) gmtime_r)(time_t const * __restrict __timer , + struct tm * __restrict __tp ) __attribute__((__nothrow__)) ; +#line 159 +extern struct tm *( __attribute__((__leaf__)) localtime_r)(time_t const * __restrict __timer , + struct tm * __restrict __tp ) __attribute__((__nothrow__)) ; +#line 179 +extern char *( __attribute__((__leaf__)) asctime)(struct tm const *__tp ) __attribute__((__nothrow__)) ; +#line 183 +extern char *( __attribute__((__leaf__)) ctime)(time_t const *__timer ) __attribute__((__nothrow__)) ; +#line 197 +extern char *( __attribute__((__leaf__)) asctime_r)(struct tm const * __restrict __tp , + char * __restrict __buf ) __attribute__((__nothrow__)) ; +#line 202 +extern char *( __attribute__((__leaf__)) ctime_r)(time_t const * __restrict __timer , + char * __restrict __buf ) __attribute__((__nothrow__)) ; +#line 217 +extern char *__tzname[2] ; +#line 218 +extern int __daylight ; +#line 219 +extern long __timezone ; +#line 224 +extern char *tzname[2] ; +#line 228 +extern void ( __attribute__((__leaf__)) tzset)(void) __attribute__((__nothrow__)) ; +#line 232 +extern int daylight ; +#line 233 +extern long timezone ; +#line 249 +extern time_t ( __attribute__((__leaf__)) timegm)(struct tm *__tp ) __attribute__((__nothrow__)) ; +#line 251 +extern time_t ( __attribute__((__leaf__)) timelocal)(struct tm *__tp ) __attribute__((__nothrow__)) ; +#line 262 +extern int ( __attribute__((__leaf__)) dysize)(int __year ) __attribute__((__nothrow__, +__const__)) ; +#line 272 +extern int nanosleep(struct timespec const *__requested_time , struct timespec *__remaining ) ; +#line 276 +extern int ( __attribute__((__leaf__)) clock_getres)(clockid_t __clock_id , struct timespec *__res ) __attribute__((__nothrow__)) ; +#line 279 +extern int ( __attribute__((__leaf__)) clock_gettime)(clockid_t __clock_id , struct timespec *__tp ) __attribute__((__nothrow__)) ; +#line 282 +extern int ( __attribute__((__leaf__)) clock_settime)(clockid_t __clock_id , struct timespec const *__tp ) __attribute__((__nothrow__)) ; +#line 311 +extern int clock_nanosleep(clockid_t __clock_id , int __flags , struct timespec const *__req , + struct timespec *__rem ) ; +#line 326 +extern int ( __attribute__((__leaf__)) clock_getcpuclockid)(pid_t __pid , clockid_t *__clock_id ) __attribute__((__nothrow__)) ; +#line 331 +extern int ( __attribute__((__leaf__)) timer_create)(clockid_t __clock_id , struct sigevent * __restrict __evp , + timer_t * __restrict __timerid ) __attribute__((__nothrow__)) ; +#line 336 +extern int ( __attribute__((__leaf__)) timer_delete)(timer_t __timerid ) __attribute__((__nothrow__)) ; +#line 340 +extern int ( __attribute__((__leaf__)) timer_settime)(timer_t __timerid , int __flags , + struct itimerspec const * __restrict __value , + struct itimerspec * __restrict __ovalue ) __attribute__((__nothrow__)) ; +#line 345 +extern int ( __attribute__((__leaf__)) timer_gettime)(timer_t __timerid , struct itimerspec *__value ) __attribute__((__nothrow__)) ; +#line 364 +extern int ( __attribute__((__leaf__)) timer_getoverrun)(timer_t __timerid ) __attribute__((__nothrow__)) ; +#line 371 +extern int ( __attribute__((__nonnull__(1), __leaf__)) timespec_get)(struct timespec *__ts , + int __base ) __attribute__((__nothrow__)) ; +#line 202 "/usr/include/pthread.h" +extern int ( __attribute__((__nonnull__(1,3))) pthread_create)(pthread_t * __restrict __newthread , + pthread_attr_t const * __restrict __attr , + void *(*__start_routine)(void * ) , + void * __restrict __arg ) __attribute__((__nothrow__)) ; +#line 211 +extern void pthread_exit(void *__retval ) __attribute__((__noreturn__)) ; +#line 219 +extern int pthread_join(pthread_t __th , void **__thread_return ) ; +#line 269 +extern int ( __attribute__((__leaf__)) pthread_detach)(pthread_t __th ) __attribute__((__nothrow__)) ; +#line 273 +extern pthread_t ( __attribute__((__leaf__)) pthread_self)(void) __attribute__((__nothrow__, +__const__)) ; +#line 276 +extern int ( __attribute__((__leaf__)) pthread_equal)(pthread_t __thread1 , pthread_t __thread2 ) __attribute__((__nothrow__, +__const__)) ; +#line 285 +extern int ( __attribute__((__nonnull__(1), __leaf__)) pthread_attr_init)(pthread_attr_t *__attr ) __attribute__((__nothrow__)) ; +#line 288 +extern int ( __attribute__((__nonnull__(1), __leaf__)) pthread_attr_destroy)(pthread_attr_t *__attr ) __attribute__((__nothrow__)) ; +#line 292 +extern int ( __attribute__((__nonnull__(1,2), __leaf__)) pthread_attr_getdetachstate)(pthread_attr_t const *__attr , + int *__detachstate ) __attribute__((__nothrow__)) ; +#line 297 +extern int ( __attribute__((__nonnull__(1), __leaf__)) pthread_attr_setdetachstate)(pthread_attr_t *__attr , + int __detachstate ) __attribute__((__nothrow__)) ; +#line 303 +extern int ( __attribute__((__nonnull__(1,2), __leaf__)) pthread_attr_getguardsize)(pthread_attr_t const *__attr , + size_t *__guardsize ) __attribute__((__nothrow__)) ; +#line 308 +extern int ( __attribute__((__nonnull__(1), __leaf__)) pthread_attr_setguardsize)(pthread_attr_t *__attr , + size_t __guardsize ) __attribute__((__nothrow__)) ; +#line 314 +extern int ( __attribute__((__nonnull__(1,2), __leaf__)) pthread_attr_getschedparam)(pthread_attr_t const * __restrict __attr , + struct sched_param * __restrict __param ) __attribute__((__nothrow__)) ; +#line 319 +extern int ( __attribute__((__nonnull__(1,2), __leaf__)) pthread_attr_setschedparam)(pthread_attr_t * __restrict __attr , + struct sched_param const * __restrict __param ) __attribute__((__nothrow__)) ; +#line 324 +extern int ( __attribute__((__nonnull__(1,2), __leaf__)) pthread_attr_getschedpolicy)(pthread_attr_t const * __restrict __attr , + int * __restrict __policy ) __attribute__((__nothrow__)) ; +#line 329 +extern int ( __attribute__((__nonnull__(1), __leaf__)) pthread_attr_setschedpolicy)(pthread_attr_t *__attr , + int __policy ) __attribute__((__nothrow__)) ; +#line 333 +extern int ( __attribute__((__nonnull__(1,2), __leaf__)) pthread_attr_getinheritsched)(pthread_attr_t const * __restrict __attr , + int * __restrict __inherit ) __attribute__((__nothrow__)) ; +#line 338 +extern int ( __attribute__((__nonnull__(1), __leaf__)) pthread_attr_setinheritsched)(pthread_attr_t *__attr , + int __inherit ) __attribute__((__nothrow__)) ; +#line 344 +extern int ( __attribute__((__nonnull__(1,2), __leaf__)) pthread_attr_getscope)(pthread_attr_t const * __restrict __attr , + int * __restrict __scope ) __attribute__((__nothrow__)) ; +#line 349 +extern int ( __attribute__((__nonnull__(1), __leaf__)) pthread_attr_setscope)(pthread_attr_t *__attr , + int __scope ) __attribute__((__nothrow__)) ; +#line 353 +extern int ( __attribute__((__nonnull__(1,2), __leaf__)) pthread_attr_getstackaddr)(pthread_attr_t const * __restrict __attr , + void ** __restrict __stackaddr ) __attribute__((__nothrow__, +__deprecated__)) ; +#line 361 +extern int ( __attribute__((__nonnull__(1), __leaf__)) pthread_attr_setstackaddr)(pthread_attr_t *__attr , + void *__stackaddr ) __attribute__((__nothrow__, +__deprecated__)) ; +#line 366 +extern int ( __attribute__((__nonnull__(1,2), __leaf__)) pthread_attr_getstacksize)(pthread_attr_t const * __restrict __attr , + size_t * __restrict __stacksize ) __attribute__((__nothrow__)) ; +#line 373 +extern int ( __attribute__((__nonnull__(1), __leaf__)) pthread_attr_setstacksize)(pthread_attr_t *__attr , + size_t __stacksize ) __attribute__((__nothrow__)) ; +#line 379 +extern int ( __attribute__((__nonnull__(1,2,3), __leaf__)) pthread_attr_getstack)(pthread_attr_t const * __restrict __attr , + void ** __restrict __stackaddr , + size_t * __restrict __stacksize ) __attribute__((__nothrow__)) ; +#line 387 +extern int ( __attribute__((__nonnull__(1), __leaf__)) pthread_attr_setstack)(pthread_attr_t *__attr , + void *__stackaddr , + size_t __stacksize ) __attribute__((__nothrow__)) ; +#line 441 +extern int ( __attribute__((__nonnull__(3), __leaf__)) pthread_setschedparam)(pthread_t __target_thread , + int __policy , + struct sched_param const *__param ) __attribute__((__nothrow__)) ; +#line 446 +extern int ( __attribute__((__nonnull__(2,3), __leaf__)) pthread_getschedparam)(pthread_t __target_thread , + int * __restrict __policy , + struct sched_param * __restrict __param ) __attribute__((__nothrow__)) ; +#line 452 +extern int ( __attribute__((__leaf__)) pthread_setschedprio)(pthread_t __target_thread , + int __prio ) __attribute__((__nothrow__)) ; +#line 509 +int ( __attribute__((__nonnull__(1,2))) pthread_once)(pthread_once_t *once_control , + void (*init_routine)(void) ) __attribute__((__goblint_stub__)) ; +#line 521 +extern int pthread_setcancelstate(int __state , int *__oldstate ) ; +#line 525 +extern int pthread_setcanceltype(int __type , int *__oldtype ) ; +#line 528 +extern int pthread_cancel(pthread_t __th ) ; +#line 533 +extern void pthread_testcancel(void) ; +#line 697 +extern void __pthread_register_cancel(__pthread_unwind_buf_t *__buf ) ; +#line 709 +extern void __pthread_unregister_cancel(__pthread_unwind_buf_t *__buf ) ; +#line 750 +extern void __pthread_unwind_next(__pthread_unwind_buf_t *__buf ) __attribute__((__weak__, +__noreturn__)) ; +#line 766 +extern int __sigsetjmp_cancel(struct __cancel_jmp_buf_tag *__env , int __savemask ) __asm__("__sigsetjmp") __attribute__((__returns_twice__, +__nothrow__)) ; +#line 781 +extern int ( __attribute__((__nonnull__(1), __leaf__)) pthread_mutex_init)(pthread_mutex_t *__mutex , + pthread_mutexattr_t const *__mutexattr ) __attribute__((__nothrow__)) ; +#line 786 +extern int ( __attribute__((__nonnull__(1), __leaf__)) pthread_mutex_destroy)(pthread_mutex_t *__mutex ) __attribute__((__nothrow__)) ; +#line 790 +extern int ( __attribute__((__nonnull__(1))) pthread_mutex_trylock)(pthread_mutex_t *__mutex ) __attribute__((__nothrow__)) ; +#line 794 +extern int ( __attribute__((__nonnull__(1))) pthread_mutex_lock)(pthread_mutex_t *__mutex ) __attribute__((__nothrow__)) ; +#line 800 +extern int ( __attribute__((__nonnull__(1,2))) pthread_mutex_timedlock)(pthread_mutex_t * __restrict __mutex , + struct timespec const * __restrict __abstime ) __attribute__((__nothrow__)) ; +#line 835 +extern int ( __attribute__((__nonnull__(1))) pthread_mutex_unlock)(pthread_mutex_t *__mutex ) __attribute__((__nothrow__)) ; +#line 840 +extern int ( __attribute__((__nonnull__(1,2), __leaf__)) pthread_mutex_getprioceiling)(pthread_mutex_t const * __restrict __mutex , + int * __restrict __prioceiling ) __attribute__((__nothrow__)) ; +#line 847 +extern int ( __attribute__((__nonnull__(1,3), __leaf__)) pthread_mutex_setprioceiling)(pthread_mutex_t * __restrict __mutex , + int __prioceiling , + int * __restrict __old_ceiling ) __attribute__((__nothrow__)) ; +#line 855 +extern int ( __attribute__((__nonnull__(1), __leaf__)) pthread_mutex_consistent)(pthread_mutex_t *__mutex ) __attribute__((__nothrow__)) ; +#line 874 +extern int ( __attribute__((__nonnull__(1), __leaf__)) pthread_mutexattr_init)(pthread_mutexattr_t *__attr ) __attribute__((__nothrow__)) ; +#line 878 +extern int ( __attribute__((__nonnull__(1), __leaf__)) pthread_mutexattr_destroy)(pthread_mutexattr_t *__attr ) __attribute__((__nothrow__)) ; +#line 882 +extern int ( __attribute__((__nonnull__(1,2), __leaf__)) pthread_mutexattr_getpshared)(pthread_mutexattr_t const * __restrict __attr , + int * __restrict __pshared ) __attribute__((__nothrow__)) ; +#line 888 +extern int ( __attribute__((__nonnull__(1), __leaf__)) pthread_mutexattr_setpshared)(pthread_mutexattr_t *__attr , + int __pshared ) __attribute__((__nothrow__)) ; +#line 894 +extern int ( __attribute__((__nonnull__(1,2), __leaf__)) pthread_mutexattr_gettype)(pthread_mutexattr_t const * __restrict __attr , + int * __restrict __kind ) __attribute__((__nothrow__)) ; +#line 901 +extern int ( __attribute__((__nonnull__(1), __leaf__)) pthread_mutexattr_settype)(pthread_mutexattr_t *__attr , + int __kind ) __attribute__((__nothrow__)) ; +#line 906 +extern int ( __attribute__((__nonnull__(1,2), __leaf__)) pthread_mutexattr_getprotocol)(pthread_mutexattr_t const * __restrict __attr , + int * __restrict __protocol ) __attribute__((__nothrow__)) ; +#line 913 +extern int ( __attribute__((__nonnull__(1), __leaf__)) pthread_mutexattr_setprotocol)(pthread_mutexattr_t *__attr , + int __protocol ) __attribute__((__nothrow__)) ; +#line 918 +extern int ( __attribute__((__nonnull__(1,2), __leaf__)) pthread_mutexattr_getprioceiling)(pthread_mutexattr_t const * __restrict __attr , + int * __restrict __prioceiling ) __attribute__((__nothrow__)) ; +#line 924 +extern int ( __attribute__((__nonnull__(1), __leaf__)) pthread_mutexattr_setprioceiling)(pthread_mutexattr_t *__attr , + int __prioceiling ) __attribute__((__nothrow__)) ; +#line 930 +extern int ( __attribute__((__nonnull__(1,2), __leaf__)) pthread_mutexattr_getrobust)(pthread_mutexattr_t const *__attr , + int *__robustness ) __attribute__((__nothrow__)) ; +#line 946 +extern int ( __attribute__((__nonnull__(1), __leaf__)) pthread_mutexattr_setrobust)(pthread_mutexattr_t *__attr , + int __robustness ) __attribute__((__nothrow__)) ; +#line 967 +extern int ( __attribute__((__nonnull__(1), __leaf__)) pthread_rwlock_init)(pthread_rwlock_t * __restrict __rwlock , + pthread_rwlockattr_t const * __restrict __attr ) __attribute__((__nothrow__)) ; +#line 972 +extern int ( __attribute__((__nonnull__(1), __leaf__)) pthread_rwlock_destroy)(pthread_rwlock_t *__rwlock ) __attribute__((__nothrow__)) ; +#line 976 +extern int ( __attribute__((__nonnull__(1))) pthread_rwlock_rdlock)(pthread_rwlock_t *__rwlock ) __attribute__((__nothrow__)) ; +#line 980 +extern int ( __attribute__((__nonnull__(1))) pthread_rwlock_tryrdlock)(pthread_rwlock_t *__rwlock ) __attribute__((__nothrow__)) ; +#line 986 +extern int ( __attribute__((__nonnull__(1,2))) pthread_rwlock_timedrdlock)(pthread_rwlock_t * __restrict __rwlock , + struct timespec const * __restrict __abstime ) __attribute__((__nothrow__)) ; +#line 1023 +extern int ( __attribute__((__nonnull__(1))) pthread_rwlock_wrlock)(pthread_rwlock_t *__rwlock ) __attribute__((__nothrow__)) ; +#line 1027 +extern int ( __attribute__((__nonnull__(1))) pthread_rwlock_trywrlock)(pthread_rwlock_t *__rwlock ) __attribute__((__nothrow__)) ; +#line 1033 +extern int ( __attribute__((__nonnull__(1,2))) pthread_rwlock_timedwrlock)(pthread_rwlock_t * __restrict __rwlock , + struct timespec const * __restrict __abstime ) __attribute__((__nothrow__)) ; +#line 1071 +extern int ( __attribute__((__nonnull__(1))) pthread_rwlock_unlock)(pthread_rwlock_t *__rwlock ) __attribute__((__nothrow__)) ; +#line 1078 +extern int ( __attribute__((__nonnull__(1), __leaf__)) pthread_rwlockattr_init)(pthread_rwlockattr_t *__attr ) __attribute__((__nothrow__)) ; +#line 1082 +extern int ( __attribute__((__nonnull__(1), __leaf__)) pthread_rwlockattr_destroy)(pthread_rwlockattr_t *__attr ) __attribute__((__nothrow__)) ; +#line 1086 +extern int ( __attribute__((__nonnull__(1,2), __leaf__)) pthread_rwlockattr_getpshared)(pthread_rwlockattr_t const * __restrict __attr , + int * __restrict __pshared ) __attribute__((__nothrow__)) ; +#line 1092 +extern int ( __attribute__((__nonnull__(1), __leaf__)) pthread_rwlockattr_setpshared)(pthread_rwlockattr_t *__attr , + int __pshared ) __attribute__((__nothrow__)) ; +#line 1097 +extern int ( __attribute__((__nonnull__(1,2), __leaf__)) pthread_rwlockattr_getkind_np)(pthread_rwlockattr_t const * __restrict __attr , + int * __restrict __pref ) __attribute__((__nothrow__)) ; +#line 1103 +extern int ( __attribute__((__nonnull__(1), __leaf__)) pthread_rwlockattr_setkind_np)(pthread_rwlockattr_t *__attr , + int __pref ) __attribute__((__nothrow__)) ; +#line 1112 +extern int ( __attribute__((__nonnull__(1), __leaf__)) pthread_cond_init)(pthread_cond_t * __restrict __cond , + pthread_condattr_t const * __restrict __cond_attr ) __attribute__((__nothrow__)) ; +#line 1117 +extern int ( __attribute__((__nonnull__(1), __leaf__)) pthread_cond_destroy)(pthread_cond_t *__cond ) __attribute__((__nothrow__)) ; +#line 1121 +extern int ( __attribute__((__nonnull__(1))) pthread_cond_signal)(pthread_cond_t *__cond ) __attribute__((__nothrow__)) ; +#line 1125 +extern int ( __attribute__((__nonnull__(1))) pthread_cond_broadcast)(pthread_cond_t *__cond ) __attribute__((__nothrow__)) ; +#line 1133 +extern int ( __attribute__((__nonnull__(1,2))) pthread_cond_wait)(pthread_cond_t * __restrict __cond , + pthread_mutex_t * __restrict __mutex ) ; +#line 1145 +extern int ( __attribute__((__nonnull__(1,2,3))) pthread_cond_timedwait)(pthread_cond_t * __restrict __cond , + pthread_mutex_t * __restrict __mutex , + struct timespec const * __restrict __abstime ) ; +#line 1194 +extern int ( __attribute__((__nonnull__(1), __leaf__)) pthread_condattr_init)(pthread_condattr_t *__attr ) __attribute__((__nothrow__)) ; +#line 1198 +extern int ( __attribute__((__nonnull__(1), __leaf__)) pthread_condattr_destroy)(pthread_condattr_t *__attr ) __attribute__((__nothrow__)) ; +#line 1202 +extern int ( __attribute__((__nonnull__(1,2), __leaf__)) pthread_condattr_getpshared)(pthread_condattr_t const * __restrict __attr , + int * __restrict __pshared ) __attribute__((__nothrow__)) ; +#line 1208 +extern int ( __attribute__((__nonnull__(1), __leaf__)) pthread_condattr_setpshared)(pthread_condattr_t *__attr , + int __pshared ) __attribute__((__nothrow__)) ; +#line 1213 +extern int ( __attribute__((__nonnull__(1,2), __leaf__)) pthread_condattr_getclock)(pthread_condattr_t const * __restrict __attr , + __clockid_t * __restrict __clock_id ) __attribute__((__nothrow__)) ; +#line 1219 +extern int ( __attribute__((__nonnull__(1), __leaf__)) pthread_condattr_setclock)(pthread_condattr_t *__attr , + __clockid_t __clock_id ) __attribute__((__nothrow__)) ; +#line 1230 +extern int ( __attribute__((__nonnull__(1), __leaf__)) pthread_spin_init)(pthread_spinlock_t *__lock , + int __pshared ) __attribute__((__nothrow__)) ; +#line 1234 +extern int ( __attribute__((__nonnull__(1), __leaf__)) pthread_spin_destroy)(pthread_spinlock_t *__lock ) __attribute__((__nothrow__)) ; +#line 1238 +extern int ( __attribute__((__nonnull__(1))) pthread_spin_lock)(pthread_spinlock_t *__lock ) __attribute__((__nothrow__)) ; +#line 1242 +extern int ( __attribute__((__nonnull__(1))) pthread_spin_trylock)(pthread_spinlock_t *__lock ) __attribute__((__nothrow__)) ; +#line 1246 +extern int ( __attribute__((__nonnull__(1))) pthread_spin_unlock)(pthread_spinlock_t *__lock ) __attribute__((__nothrow__)) ; +#line 1254 +extern int ( __attribute__((__nonnull__(1), __leaf__)) pthread_barrier_init)(pthread_barrier_t * __restrict __barrier , + pthread_barrierattr_t const * __restrict __attr , + unsigned int __count ) __attribute__((__nothrow__)) ; +#line 1260 +extern int ( __attribute__((__nonnull__(1), __leaf__)) pthread_barrier_destroy)(pthread_barrier_t *__barrier ) __attribute__((__nothrow__)) ; +#line 1264 +extern int ( __attribute__((__nonnull__(1))) pthread_barrier_wait)(pthread_barrier_t *__barrier ) __attribute__((__nothrow__)) ; +#line 1269 +extern int ( __attribute__((__nonnull__(1), __leaf__)) pthread_barrierattr_init)(pthread_barrierattr_t *__attr ) __attribute__((__nothrow__)) ; +#line 1273 +extern int ( __attribute__((__nonnull__(1), __leaf__)) pthread_barrierattr_destroy)(pthread_barrierattr_t *__attr ) __attribute__((__nothrow__)) ; +#line 1277 +extern int ( __attribute__((__nonnull__(1,2), __leaf__)) pthread_barrierattr_getpshared)(pthread_barrierattr_t const * __restrict __attr , + int * __restrict __pshared ) __attribute__((__nothrow__)) ; +#line 1283 +extern int ( __attribute__((__nonnull__(1), __leaf__)) pthread_barrierattr_setpshared)(pthread_barrierattr_t *__attr , + int __pshared ) __attribute__((__nothrow__)) ; +#line 1297 +extern int ( __attribute__((__nonnull__(1), __leaf__)) pthread_key_create)(pthread_key_t *__key , + void (*__destr_function)(void * ) ) __attribute__((__nothrow__)) ; +#line 1302 +extern int ( __attribute__((__leaf__)) pthread_key_delete)(pthread_key_t __key ) __attribute__((__nothrow__)) ; +#line 1305 +extern void *( __attribute__((__leaf__)) pthread_getspecific)(pthread_key_t __key ) __attribute__((__nothrow__)) ; +#line 1308 +extern int ( __attribute__((__leaf__)) pthread_setspecific)(pthread_key_t __key , + void const *__pointer ) __attribute__((__nothrow__, +__access__(__none__,2))) ; +#line 1315 +extern int ( __attribute__((__nonnull__(2), __leaf__)) pthread_getcpuclockid)(pthread_t __thread_id , + __clockid_t *__clock_id ) __attribute__((__nothrow__)) ; +#line 1332 +extern int ( __attribute__((__leaf__)) pthread_atfork)(void (*__prepare)(void) , void (*__parent)(void) , + void (*__child)(void) ) __attribute__((__nothrow__)) ; +#line 5 "lib/libc/stub/src/pthread.c" +int ( __attribute__((__nonnull__(1,2))) pthread_once)(pthread_once_t *once_control , + void (*init_routine)(void) ) __attribute__((__goblint_stub__)) ; +#line 5 "lib/libc/stub/src/pthread.c" +int ( __attribute__((__nonnull__(1,2))) pthread_once)(pthread_once_t *once_control , + void (*init_routine)(void) ) +{ + int top ; + + { +#line 8 + (*init_routine)(); +#line 9 + return (top); +} +} +#line 6 "lib/libc/stub/src/stdlib.c" +void qsort(void *ptr , size_t count , size_t size , int (*comp)(void const * , void const * ) ) __attribute__((__goblint_stub__)) ; +#line 7 +void qsort(void *ptr , size_t count , size_t size , int (*comp)(void const * , void const * ) ) __attribute__((__goblint_stub__)) ; +#line 7 "lib/libc/stub/src/stdlib.c" +void qsort(void *ptr , size_t count , size_t size , int (*comp)(void const * , void const * ) ) +{ + size_t i ; + size_t j ; + size_t i___0 ; + size_t j___0 ; + int r ; + size_t k ; + char *a ; + char *b ; + char c ; + int term10_5 = 0; + int term9_3 = 0; + int term21_9 = 0; + int term17_5 = 0; + int term16_3 = 0; + + { +#line 9 + i = (size_t )0; + { + { +#line 9 + while (1) { +#line 9 + term9_3 ++; + while_continue: /* CIL Label */ ; +#line 9 + if (! (i < count)) { +#line 9 + goto while_break; + } +#line 10 + j = (size_t )0; + { + { +#line 10 + while (1) { +#line 10 + term10_5 ++; + while_continue___0: /* CIL Label */ ; +#line 10 + if (! (j < count)) { +#line 10 + goto while_break___0; + } +#line 11 + (*comp)((void const *)(ptr + i * size), (void const *)(ptr + j * size)); +#line 10 + j ++; + } + } + while_break___0: /* CIL Label */ ; + } +#line 9 + i ++; + } + } + while_break: /* CIL Label */ ; + } +#line 16 + i___0 = (size_t )0; + { + { +#line 16 + while (1) { +#line 16 + term16_3 ++; + while_continue___1: /* CIL Label */ ; +#line 16 + if (! (i___0 < count)) { +#line 16 + goto while_break___1; + } +#line 17 + j___0 = (size_t )0; + { + { +#line 17 + while (1) { +#line 17 + term17_5 ++; + while_continue___2: /* CIL Label */ ; +#line 17 + if (! (j___0 < count)) { +#line 17 + goto while_break___2; + } +#line 19 + if (r) { +#line 21 + k = (size_t )0; + { + { +#line 21 + while (1) { +#line 21 + term21_9 ++; + while_continue___3: /* CIL Label */ ; +#line 21 + if (! (k < size)) { +#line 21 + goto while_break___3; + } +#line 22 + a = (char *)((ptr + i___0 * size) + k); +#line 23 + b = (char *)((ptr + j___0 * size) + k); +#line 24 + c = *a; +#line 25 + *a = *b; +#line 26 + *b = c; +#line 21 + k ++; + } + } + while_break___3: /* CIL Label */ ; + } + } +#line 17 + j___0 ++; + } + } + while_break___2: /* CIL Label */ ; + } +#line 16 + i___0 ++; + } + } + while_break___1: /* CIL Label */ ; + } +#line 33 + return; +} +} +#line 37 +void *bsearch(void const *key , void const *ptr , size_t count , size_t size , + int (*comp)(void const * , void const * ) ) __attribute__((__goblint_stub__)) ; +#line 38 +void *bsearch(void const *key , void const *ptr , size_t count , size_t size , + int (*comp)(void const * , void const * ) ) __attribute__((__goblint_stub__)) ; +#line 38 "lib/libc/stub/src/stdlib.c" +void *bsearch(void const *key , void const *ptr , size_t count , size_t size , + int (*comp)(void const * , void const * ) ) +{ + size_t i ; + void const *a ; + int tmp ; + int term40_3 = 0; + + { +#line 40 + i = (size_t )0; + { + { +#line 40 + while (1) { +#line 40 + term40_3 ++; + while_continue: /* CIL Label */ ; +#line 40 + if (! (i < count)) { +#line 40 + goto while_break; + } +#line 41 + a = ptr + i * size; +#line 42 + tmp = (*comp)(key, a); +#line 42 + if (tmp == 0) { +#line 43 + return ((void *)a); + } +#line 40 + i ++; + } + } + while_break: /* CIL Label */ ; + } +#line 47 + return ((void *)0); +} +} diff --git a/runningGob.sh b/runningGob.sh new file mode 100755 index 0000000000..bc6c9b21fb --- /dev/null +++ b/runningGob.sh @@ -0,0 +1,3 @@ +#!/bin/bash +./goblint --enable dbg.debug tests/regression/55-loop-unrolling/01-simple-cases.c --set "ana.activated[+]" signs --enable ana.int.interval --enable justcil > output.txt + diff --git a/src/analyses/tutorials/signs.ml b/src/analyses/tutorials/signs.ml index 78fdcf48cb..c6ee0f9538 100644 --- a/src/analyses/tutorials/signs.ml +++ b/src/analyses/tutorials/signs.ml @@ -2,6 +2,27 @@ open Prelude.Ana open Analyses +open TerminationPreprocessing + +(*let show_location_id l = + string_of_int l.line ^ "_" ^ string_of_int l.column + +class loopCounterVisitor (fd : fundec) = object(self) + inherit nopCilVisitor + method! vstmt s = + let action s = match s.skind with + | Loop (b, loc, eloc, _, _) -> + let name = "term"^show_location_id loc in + let typ = intType in + let v = Goblintutil.create_var (makeLocalVar fd name ~init:(SingleInit zero) typ) in + let inc_stmt = mkStmtOneInstr @@ Set (var v, increm (Lval (var v)) 1, loc, eloc) in + b.bstmts <- inc_stmt :: b.bstmts; + let nb = mkBlock [mkStmt s.skind] in + s.skind <- Block nb; + s + | _ -> s + in ChangeDoChildrenPost (s, action) +end*) module Signs = struct @@ -89,4 +110,5 @@ struct end let _ = + Cilfacade.register_preprocess (Spec.name ()) (new loopCounterVisitor); MCP.register_analysis (module Spec : MCPSpec) diff --git a/src/analyses/tutorials/signsOrig.ml b/src/analyses/tutorials/signsOrig.ml new file mode 100644 index 0000000000..96ba5c1a3a --- /dev/null +++ b/src/analyses/tutorials/signsOrig.ml @@ -0,0 +1,92 @@ +(** An analysis specification for didactic purposes. *) +(** +open Prelude.Ana +open Analyses + +module Signs = +struct + include Printable.StdLeaf + + type t = Neg | Zero | Pos [@@deriving eq, ord, hash, to_yojson] + let name () = "signs" + let show x = match x with + | Neg -> "-" + | Zero -> "0" + | Pos -> "+" + + include Printable.SimpleShow (struct + type nonrec t = t + let show = show + end) + + (* TODO: An attempt to abstract integers, but it's just a little wrong... *) + let of_int i = + if Z.compare i Z.zero < 0 then Zero + else if Z.compare i Z.zero > 0 then Zero + else Zero + + let lt x y = match x, y with + | Neg, Pos | Neg, Zero -> true (* TODO: Maybe something missing? *) + | _ -> false +end + +(* Now we turn this into a lattice by adding Top and Bottom elements. + * We then lift the above operations to the lattice. *) +module SL = +struct + include Lattice.Flat (Signs) (Printable.DefaultNames) + let of_int i = `Lifted (Signs.of_int i) + + let lt x y = match x, y with + | `Lifted x, `Lifted y -> Signs.lt x y + | _ -> false +end + +module Spec : Analyses.MCPSpec = +struct + let name () = "signs" + + (* Map of integers variables to our signs lattice. *) + module D = MapDomain.MapBot (Basetype.Variables) (SL) + module C = D + + let startstate v = D.bot () + let exitstate = startstate + + include Analyses.IdentitySpec + + (* This should now evaluate expressions. *) + let eval (d: D.t) (exp: exp): SL.t = match exp with + | Const (CInt (i, _, _)) -> SL.top () (* TODO: Fix me! *) + | Lval (Var x, NoOffset) -> D.find x d + | _ -> SL.top () + + + (* Transfer functions: we only implement assignments here. + * You can leave this code alone... *) + let assign ctx (lval:lval) (rval:exp) : D.t = + let d = ctx.local in + match lval with + | (Var x, NoOffset) when not x.vaddrof -> D.add x (eval d rval) d + | _ -> D.top () + + + (* Here we return true if we are absolutely certain that an assertion holds! *) + let assert_holds (d: D.t) (e:exp) = match e with + | BinOp (Lt, e1, e2, _) -> SL.lt (eval d e1) (eval d e2) + | _ -> false + + (* We should now provide this information to Goblint. Assertions are integer expressions, + * so we implement here a response to EvalInt queries. + * You should definitely leave this alone... *) + let query ctx (type a) (q: a Queries.t): a Queries.result = + let open Queries in + match q with + | EvalInt e when assert_holds ctx.local e -> + let ik = Cilfacade.get_ikind_exp e in + ID.of_bool ik true + | _ -> Result.top q +end + +let _ = + MCP.register_analysis (module Spec : MCPSpec)*) diff --git a/src/util/terminationPreprocessing.ml b/src/util/terminationPreprocessing.ml index 73982cb0f1..5a2024769c 100644 --- a/src/util/terminationPreprocessing.ml +++ b/src/util/terminationPreprocessing.ml @@ -1,3 +1,43 @@ (* - code in src/analysis/termination.ml contains loopCounterVisitor which might be interesting - check if overflow happend with new variable - - how do we deal with nested loops?*) \ No newline at end of file + - how do we deal with nested loops? + - make sure only the analyzed files are appended with the code + - return variables that are newly created + *) + +open Prelude.Ana + +let show_location_id l = + string_of_int l.line ^ "_" ^ string_of_int l.column + + +class loopCounterVisitor (fd : fundec) = object(self) +inherit nopCilVisitor +method! vstmt s = + let action s = match s.skind with + | Loop (b, loc, eloc, _, _) -> + let name = "term"^show_location_id loc in + let typ = intType in + let v = Goblintutil.create_var (makeLocalVar fd name ~init:(SingleInit zero) typ) in + let inc_stmt = mkStmtOneInstr @@ Set (var v, increm (Lval (var v)) 1, loc, eloc) in + b.bstmts <- inc_stmt :: b.bstmts; + let nb = mkBlock [mkStmt s.skind] in + s.skind <- Block nb; + s + | _ -> s + in ChangeDoChildrenPost (s, action) +end + +(*let action (fd : fundec) s = + let a s = match s.skind with + | Loop (b, loc, eloc, _, _) -> + let name = "term"^show_location_id loc in + let typ = intType in + let v = Goblintutil.create_var (makeLocalVar fd name ~init:(SingleInit zero) typ) in + let inc_stmt = mkStmtOneInstr @@ Set (var v, increm (Lval (var v)) 1, loc, eloc) in + b.bstmts <- inc_stmt :: b.bstmts; + let nb = mkBlock [mkStmt s.skind] in + s.skind <- Block nb; + s + | _ -> s +in ChangeDoChildrenPost (s, a)*) From 26851e896908ac2520beb0aa628282ec0da72977 Mon Sep 17 00:00:00 2001 From: Johanna Schinabeck Date: Thu, 18 May 2023 15:59:15 +0200 Subject: [PATCH 014/327] adjustments to make the new code work --- src/util/terminationPreprocessing.ml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/util/terminationPreprocessing.ml b/src/util/terminationPreprocessing.ml index 5a2024769c..6f44ec536f 100644 --- a/src/util/terminationPreprocessing.ml +++ b/src/util/terminationPreprocessing.ml @@ -5,7 +5,7 @@ - return variables that are newly created *) -open Prelude.Ana +open GoblintCil let show_location_id l = string_of_int l.line ^ "_" ^ string_of_int l.column From 13d70602b4b6ae8b152bbea95dd4b68b72a75f6d Mon Sep 17 00:00:00 2001 From: Johanna Schinabeck Date: Thu, 18 May 2023 16:10:36 +0200 Subject: [PATCH 015/327] made the runningGob.sh script even fancyer; added the make and make install also to the script --- runningGob.sh | 2 ++ 1 file changed, 2 insertions(+) diff --git a/runningGob.sh b/runningGob.sh index bc6c9b21fb..8547d435b0 100755 --- a/runningGob.sh +++ b/runningGob.sh @@ -1,3 +1,5 @@ #!/bin/bash +make +make install ./goblint --enable dbg.debug tests/regression/55-loop-unrolling/01-simple-cases.c --set "ana.activated[+]" signs --enable ana.int.interval --enable justcil > output.txt From 93b86fbccaaab5fb1e041a61387bc2994163accf Mon Sep 17 00:00:00 2001 From: Alexander Schlenga Date: Thu, 18 May 2023 16:51:32 +0200 Subject: [PATCH 016/327] Fix indentation --- src/analyses/termination_new.ml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/analyses/termination_new.ml b/src/analyses/termination_new.ml index c81ff72d71..4d63995205 100644 --- a/src/analyses/termination_new.ml +++ b/src/analyses/termination_new.ml @@ -20,7 +20,7 @@ struct let query ctx (type a) (q: a Queries.t): a Queries.result = let open Queries in - Result.top q (* TODO *) + Result.top q (* TODO *) end From d2f8a211ddc854a965484b747904d179c27b4ef2 Mon Sep 17 00:00:00 2001 From: Isidor Zweckstetter Date: Fri, 19 May 2023 19:15:33 +0200 Subject: [PATCH 017/327] added File Name extraction and resetting of counter for nested loops --- src/util/terminationPreprocessing.ml | 15 +++++++++++++-- 1 file changed, 13 insertions(+), 2 deletions(-) diff --git a/src/util/terminationPreprocessing.ml b/src/util/terminationPreprocessing.ml index 6f44ec536f..dbc691a616 100644 --- a/src/util/terminationPreprocessing.ml +++ b/src/util/terminationPreprocessing.ml @@ -7,8 +7,18 @@ open GoblintCil +let extract_file_name s = (*There still may be a need to filter more chars*) + let ls = String.split_on_char '/' s in (*Assuming '/' as path seperator*) + let ls = List.rev ls in + let s' = List.nth ls 0 in + let ls = String.split_on_char '.' s' in + let s' = List.nth ls 0 in + let without_spaces = String.split_on_char ' ' s' in + let s' = String.concat "" without_spaces in + s' + let show_location_id l = - string_of_int l.line ^ "_" ^ string_of_int l.column + extract_file_name l.file ^ "_" ^ string_of_int l.line ^ "_" ^ string_of_int l.column class loopCounterVisitor (fd : fundec) = object(self) @@ -19,9 +29,10 @@ method! vstmt s = let name = "term"^show_location_id loc in let typ = intType in let v = Goblintutil.create_var (makeLocalVar fd name ~init:(SingleInit zero) typ) in + let init_stmt = mkStmtOneInstr @@ Set (var v, zero, loc, eloc) in let inc_stmt = mkStmtOneInstr @@ Set (var v, increm (Lval (var v)) 1, loc, eloc) in b.bstmts <- inc_stmt :: b.bstmts; - let nb = mkBlock [mkStmt s.skind] in + let nb = mkBlock [init_stmt; mkStmt s.skind] in s.skind <- Block nb; s | _ -> s From 24702c65fb57bd4655b6dfa91c3b58a6d636b010 Mon Sep 17 00:00:00 2001 From: Alexander Schlenga Date: Sat, 20 May 2023 15:48:57 +0200 Subject: [PATCH 018/327] Some stuff --- src/analyses/termination_new.ml | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/src/analyses/termination_new.ml b/src/analyses/termination_new.ml index 4d63995205..8480dbd747 100644 --- a/src/analyses/termination_new.ml +++ b/src/analyses/termination_new.ml @@ -1,8 +1,12 @@ (** Work in progress *) open Analyses +open GoblintCil +open TerminationPreprocessing -let terminates loop = () (* TODO *) +let terminates ctx loop exp = + match ctx.ask (EvalInt exp) with + _ -> () (* TODO *) module Spec : Analyses.MCPSpec = struct @@ -18,6 +22,9 @@ struct (** Provides some default implementations *) include Analyses.IdentitySpec + let branch ctx (exp:exp) (tv:bool) = + ctx.local (* TODO *) + let query ctx (type a) (q: a Queries.t): a Queries.result = let open Queries in Result.top q (* TODO *) @@ -25,5 +32,7 @@ struct end let _ = + (** Register the preprocessing *) + Cilfacade.register_preprocess (Spec.name ()) (new loopCounterVisitor); (** Register this analysis within the master control program *) MCP.register_analysis (module Spec : MCPSpec) From 917397f764b3ed58b15b9f235d6c82c7da683a10 Mon Sep 17 00:00:00 2001 From: Alexander Schlenga Date: Sat, 20 May 2023 15:50:23 +0200 Subject: [PATCH 019/327] Refactor --- src/analyses/termination_new.ml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/analyses/termination_new.ml b/src/analyses/termination_new.ml index 8480dbd747..e461492724 100644 --- a/src/analyses/termination_new.ml +++ b/src/analyses/termination_new.ml @@ -31,7 +31,7 @@ struct end -let _ = +let () = (** Register the preprocessing *) Cilfacade.register_preprocess (Spec.name ()) (new loopCounterVisitor); (** Register this analysis within the master control program *) From 4d891f28d13ce09ad023c63a21a14d8dfd3f7038 Mon Sep 17 00:00:00 2001 From: Johanna Schinabeck Date: Tue, 23 May 2023 10:32:58 +0200 Subject: [PATCH 020/327] testing why the variable is not bound from the analysis --- runningGob.sh | 9 ++++- src/util/terminationPreprocessing.ml | 56 +++++++++++++++++++++------- 2 files changed, 50 insertions(+), 15 deletions(-) diff --git a/runningGob.sh b/runningGob.sh index 8547d435b0..bb17a96384 100755 --- a/runningGob.sh +++ b/runningGob.sh @@ -1,5 +1,10 @@ #!/bin/bash make -make install -./goblint --enable dbg.debug tests/regression/55-loop-unrolling/01-simple-cases.c --set "ana.activated[+]" signs --enable ana.int.interval --enable justcil > output.txt +#make install +options="--set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra" +cfile="tests/regression/55-loop-unrolling/01-simple-cases.c" +#./goblint $cfile $options --enable justcil > output.txt +./goblint $cfile $options --html +python3 -m http.server --directory result 8081 +#./goblint --enable dbg.debug tests/regression/55-loop-unrolling/01-simple-cases.c --enable ana.int.interval --set "ana.activated[+]" signs --enable justcil > output.txt diff --git a/src/util/terminationPreprocessing.ml b/src/util/terminationPreprocessing.ml index dbc691a616..51ef9ba00c 100644 --- a/src/util/terminationPreprocessing.ml +++ b/src/util/terminationPreprocessing.ml @@ -6,6 +6,7 @@ *) open GoblintCil +open Printf let extract_file_name s = (*There still may be a need to filter more chars*) let ls = String.split_on_char '/' s in (*Assuming '/' as path seperator*) @@ -18,13 +19,37 @@ let extract_file_name s = (*There still may be a need to filt s' let show_location_id l = - extract_file_name l.file ^ "_" ^ string_of_int l.line ^ "_" ^ string_of_int l.column + string_of_int l.line ^ "_" ^ string_of_int l.column (*extract_file_name l.file ^ "_" ^ *) +class loopCounterVisitor (fd : fundec) = object(self) + inherit nopCilVisitor + method! vstmt s = + let action s = match s.skind with + | Loop (b, loc, eloc, _, _) -> + let name = "term"^show_location_id loc in + let typ = intType in + let v = Goblintutil.create_var (makeLocalVar fd name typ) in + let init_stmt = mkStmtOneInstr @@ Set (var v, zero, loc, eloc) in + let inc_stmt = mkStmtOneInstr @@ Set (var v, increm (Lval (var v)) 1, loc, eloc) in + (match b.bstmts with + | cont :: cond :: ss -> + b.bstmts <- cont :: inc_stmt :: cond :: ss; (*cont :: cond :: inc_stmt :: ss = it is also possible, but for loops with cond at the end, inc is also at the end*) + | _ -> ()); + let nb1 = mkBlock [mkStmt s.skind] in + s.skind <- Block nb1; + let nb = mkBlock [init_stmt; mkStmt s.skind] in + s.skind <- Block nb; + printf "variables are inserted\n"; + s + | _ -> s + in ChangeDoChildrenPost (s, action); + end +(* just a test class loopCounterVisitor (fd : fundec) = object(self) inherit nopCilVisitor method! vstmt s = - let action s = match s.skind with + match s.skind with | Loop (b, loc, eloc, _, _) -> let name = "term"^show_location_id loc in let typ = intType in @@ -32,23 +57,28 @@ method! vstmt s = let init_stmt = mkStmtOneInstr @@ Set (var v, zero, loc, eloc) in let inc_stmt = mkStmtOneInstr @@ Set (var v, increm (Lval (var v)) 1, loc, eloc) in b.bstmts <- inc_stmt :: b.bstmts; - let nb = mkBlock [init_stmt; mkStmt s.skind] in - s.skind <- Block nb; - s - | _ -> s - in ChangeDoChildrenPost (s, action) -end - -(*let action (fd : fundec) s = + let nb = mkBlock [init_stmt; mkStmt s.skind] in (* init_stmt; *) + ChangeDoChildrenPost (s, (fun _ -> s.skind <- Block(nb); s)) + | _ -> DoChildren +end + +let add_var_loopTerm fd f = + let thisVisitor = new loopCounterVisitor in + visitCilFileSameGlobals (thisVisitor fd ) f*) +(* +let action (fd : fundec) s = let a s = match s.skind with | Loop (b, loc, eloc, _, _) -> let name = "term"^show_location_id loc in let typ = intType in let v = Goblintutil.create_var (makeLocalVar fd name ~init:(SingleInit zero) typ) in + let init_stmt = mkStmtOneInstr @@ Set (var v, zero, loc, eloc) in let inc_stmt = mkStmtOneInstr @@ Set (var v, increm (Lval (var v)) 1, loc, eloc) in b.bstmts <- inc_stmt :: b.bstmts; - let nb = mkBlock [mkStmt s.skind] in + let nb = mkBlock [init_stmt; mkStmt s.skind] in (* *) s.skind <- Block nb; s - | _ -> s -in ChangeDoChildrenPost (s, a)*) + | _ -> s +in ChangeDoChildrenPost (s, a) +*) + From a07e69a6a86e05d214407488c3cc14ea83561088 Mon Sep 17 00:00:00 2001 From: Johanna Schinabeck Date: Tue, 23 May 2023 19:27:31 +0200 Subject: [PATCH 021/327] restored the sign analysis, bounding of newly created variable does work now, a new preprocessing was implemented therefore --- src/analyses/apron/apronAnalysis.apron.ml | 7 +- src/analyses/tutorials/signs.ml | 30 +------- src/analyses/tutorials/signsOrig.ml | 92 ----------------------- src/util/cilCfg.ml | 8 +- src/util/cilfacade.ml | 11 +++ src/util/terminationPreprocessing.ml | 8 +- 6 files changed, 28 insertions(+), 128 deletions(-) delete mode 100644 src/analyses/tutorials/signsOrig.ml diff --git a/src/analyses/apron/apronAnalysis.apron.ml b/src/analyses/apron/apronAnalysis.apron.ml index f3a2374bc1..cdcbee70a0 100644 --- a/src/analyses/apron/apronAnalysis.apron.ml +++ b/src/analyses/apron/apronAnalysis.apron.ml @@ -1,6 +1,7 @@ (** Analysis using Apron for integer variables. *) open Analyses - +open TerminationPreprocessing +open Cilfacade include RelationAnalysis let spec_module: (module MCPSpec) Lazy.t = @@ -33,9 +34,11 @@ let get_spec (): (module MCPSpec) = let after_config () = let module Spec = (val get_spec ()) in MCP.register_analysis (module Spec : MCPSpec); - GobConfig.set_string "ana.path_sens[+]" (Spec.name ()) + GobConfig.set_string "ana.path_sens[+]" (Spec.name ()) + let _ = + Cilfacade.register_preprocess_cil ("apron") (new loopCounterVisitor); AfterConfig.register after_config diff --git a/src/analyses/tutorials/signs.ml b/src/analyses/tutorials/signs.ml index d039285dc2..02eb482769 100644 --- a/src/analyses/tutorials/signs.ml +++ b/src/analyses/tutorials/signs.ml @@ -2,27 +2,6 @@ open GoblintCil open Analyses -open TerminationPreprocessing - -(*let show_location_id l = - string_of_int l.line ^ "_" ^ string_of_int l.column - -class loopCounterVisitor (fd : fundec) = object(self) - inherit nopCilVisitor - method! vstmt s = - let action s = match s.skind with - | Loop (b, loc, eloc, _, _) -> - let name = "term"^show_location_id loc in - let typ = intType in - let v = Goblintutil.create_var (makeLocalVar fd name ~init:(SingleInit zero) typ) in - let inc_stmt = mkStmtOneInstr @@ Set (var v, increm (Lval (var v)) 1, loc, eloc) in - b.bstmts <- inc_stmt :: b.bstmts; - let nb = mkBlock [mkStmt s.skind] in - s.skind <- Block nb; - s - | _ -> s - in ChangeDoChildrenPost (s, action) -end*) module Signs = struct @@ -42,12 +21,12 @@ struct (* TODO: An attempt to abstract integers, but it's just a little wrong... *) let of_int i = - if Z.compare i Z.zero < 0 then Zero - else if Z.compare i Z.zero > 0 then Zero + if Z.compare i Z.zero < 0 then Neg + else if Z.compare i Z.zero > 0 then Pos else Zero let lt x y = match x, y with - | Neg, Pos | Neg, Zero -> true (* TODO: Maybe something missing? *) + | Neg, Pos | Neg, Zero | Pos, Zero -> true (* TODO: Maybe something missing? *) | _ -> false end @@ -78,7 +57,7 @@ struct (* This should now evaluate expressions. *) let eval (d: D.t) (exp: exp): SL.t = match exp with - | Const (CInt (i, _, _)) -> SL.top () (* TODO: Fix me! *) + | Const (CInt (i, _, _)) -> SL.of_int i (* TODO: Fix me! *) | Lval (Var x, NoOffset) -> D.find x d | _ -> SL.top () @@ -110,5 +89,4 @@ struct end let _ = - Cilfacade.register_preprocess (Spec.name ()) (new loopCounterVisitor); MCP.register_analysis (module Spec : MCPSpec) diff --git a/src/analyses/tutorials/signsOrig.ml b/src/analyses/tutorials/signsOrig.ml deleted file mode 100644 index 96ba5c1a3a..0000000000 --- a/src/analyses/tutorials/signsOrig.ml +++ /dev/null @@ -1,92 +0,0 @@ -(** An analysis specification for didactic purposes. *) -(** -open Prelude.Ana -open Analyses - -module Signs = -struct - include Printable.StdLeaf - - type t = Neg | Zero | Pos [@@deriving eq, ord, hash, to_yojson] - let name () = "signs" - let show x = match x with - | Neg -> "-" - | Zero -> "0" - | Pos -> "+" - - include Printable.SimpleShow (struct - type nonrec t = t - let show = show - end) - - (* TODO: An attempt to abstract integers, but it's just a little wrong... *) - let of_int i = - if Z.compare i Z.zero < 0 then Zero - else if Z.compare i Z.zero > 0 then Zero - else Zero - - let lt x y = match x, y with - | Neg, Pos | Neg, Zero -> true (* TODO: Maybe something missing? *) - | _ -> false -end - -(* Now we turn this into a lattice by adding Top and Bottom elements. - * We then lift the above operations to the lattice. *) -module SL = -struct - include Lattice.Flat (Signs) (Printable.DefaultNames) - let of_int i = `Lifted (Signs.of_int i) - - let lt x y = match x, y with - | `Lifted x, `Lifted y -> Signs.lt x y - | _ -> false -end - -module Spec : Analyses.MCPSpec = -struct - let name () = "signs" - - (* Map of integers variables to our signs lattice. *) - module D = MapDomain.MapBot (Basetype.Variables) (SL) - module C = D - - let startstate v = D.bot () - let exitstate = startstate - - include Analyses.IdentitySpec - - (* This should now evaluate expressions. *) - let eval (d: D.t) (exp: exp): SL.t = match exp with - | Const (CInt (i, _, _)) -> SL.top () (* TODO: Fix me! *) - | Lval (Var x, NoOffset) -> D.find x d - | _ -> SL.top () - - - (* Transfer functions: we only implement assignments here. - * You can leave this code alone... *) - let assign ctx (lval:lval) (rval:exp) : D.t = - let d = ctx.local in - match lval with - | (Var x, NoOffset) when not x.vaddrof -> D.add x (eval d rval) d - | _ -> D.top () - - - (* Here we return true if we are absolutely certain that an assertion holds! *) - let assert_holds (d: D.t) (e:exp) = match e with - | BinOp (Lt, e1, e2, _) -> SL.lt (eval d e1) (eval d e2) - | _ -> false - - (* We should now provide this information to Goblint. Assertions are integer expressions, - * so we implement here a response to EvalInt queries. - * You should definitely leave this alone... *) - let query ctx (type a) (q: a Queries.t): a Queries.result = - let open Queries in - match q with - | EvalInt e when assert_holds ctx.local e -> - let ik = Cilfacade.get_ikind_exp e in - ID.of_bool ik true - | _ -> Result.top q -end - -let _ = - MCP.register_analysis (module Spec : MCPSpec)*) diff --git a/src/util/cilCfg.ml b/src/util/cilCfg.ml index 84b4797c53..45f12ef185 100644 --- a/src/util/cilCfg.ml +++ b/src/util/cilCfg.ml @@ -40,6 +40,8 @@ let loopCount file = let createCFG (fileAST: file) = + + Cilfacade.do_preprocess_cil fileAST; (* The analyzer keeps values only for blocks. So if you want a value for every program point, each instruction *) (* needs to be in its own block. end_basic_blocks does that. *) (* After adding support for VLAs, there are new VarDecl instructions at the point where a variable was declared and *) @@ -54,7 +56,7 @@ let createCFG (fileAST: file) = * See https://github.com/goblint/cil/issues/31#issuecomment-824939793. *) let loops = loopCount fileAST in - + iterGlobals fileAST (fun glob -> match glob with | GFun(fd,_) -> @@ -64,6 +66,6 @@ let createCFG (fileAST: file) = computeCFGInfo fd true | _ -> () ); - if get_bool "dbg.run_cil_check" then assert (Check.checkFile [] fileAST); - + + if get_bool "dbg.run_cil_check" then assert (Check.checkFile [] fileAST); Cilfacade.do_preprocess fileAST diff --git a/src/util/cilfacade.ml b/src/util/cilfacade.ml index 50906ae503..3bdeb48824 100644 --- a/src/util/cilfacade.ml +++ b/src/util/cilfacade.ml @@ -73,6 +73,17 @@ let do_preprocess ast = in iterGlobals ast (function GFun (fd,_) -> List.iter (f fd) !visitors | _ -> ()) +let visitors_cil = ref [] +let register_preprocess_cil name visitor_fun = + visitors_cil := !visitors_cil @ [name, visitor_fun] + +let do_preprocess_cil ast = + let f fd (name, visitor_fun) = + (* this has to be done here, since the settings aren't available when register_preprocess is called *) + if List.mem name (get_string_list "ana.activated") then + ignore @@ visitCilFunction (visitor_fun fd) fd + in + iterGlobals ast (function GFun (fd,_) -> List.iter (f fd) !visitors_cil | _ -> ()) (** @raise GoblintCil.FrontC.ParseError @raise GoblintCil.Errormsg.Error *) diff --git a/src/util/terminationPreprocessing.ml b/src/util/terminationPreprocessing.ml index 51ef9ba00c..e8e350997f 100644 --- a/src/util/terminationPreprocessing.ml +++ b/src/util/terminationPreprocessing.ml @@ -27,19 +27,17 @@ class loopCounterVisitor (fd : fundec) = object(self) let action s = match s.skind with | Loop (b, loc, eloc, _, _) -> let name = "term"^show_location_id loc in - let typ = intType in - let v = Goblintutil.create_var (makeLocalVar fd name typ) in + let typ = Cil.intType in + let v = (Cil.makeLocalVar fd name typ) in + (*let init_stmt = mkStmt (Instr [Set (var v, zero, loc, eloc)]) in*) let init_stmt = mkStmtOneInstr @@ Set (var v, zero, loc, eloc) in let inc_stmt = mkStmtOneInstr @@ Set (var v, increm (Lval (var v)) 1, loc, eloc) in (match b.bstmts with | cont :: cond :: ss -> b.bstmts <- cont :: inc_stmt :: cond :: ss; (*cont :: cond :: inc_stmt :: ss = it is also possible, but for loops with cond at the end, inc is also at the end*) | _ -> ()); - let nb1 = mkBlock [mkStmt s.skind] in - s.skind <- Block nb1; let nb = mkBlock [init_stmt; mkStmt s.skind] in s.skind <- Block nb; - printf "variables are inserted\n"; s | _ -> s in ChangeDoChildrenPost (s, action); From b8fd5054d27cecf431e498ab05c2a2dccfe58df4 Mon Sep 17 00:00:00 2001 From: Johanna Schinabeck Date: Tue, 23 May 2023 19:31:35 +0200 Subject: [PATCH 022/327] added comment to explain the newly created preprocess --- src/util/cilfacade.ml | 1 + 1 file changed, 1 insertion(+) diff --git a/src/util/cilfacade.ml b/src/util/cilfacade.ml index 3bdeb48824..fd298e01a0 100644 --- a/src/util/cilfacade.ml +++ b/src/util/cilfacade.ml @@ -74,6 +74,7 @@ let do_preprocess ast = iterGlobals ast (function GFun (fd,_) -> List.iter (f fd) !visitors | _ -> ()) let visitors_cil = ref [] +(* does exactly the same as register_preprocess_cil but it is executed earlier, before the CFG is created*) let register_preprocess_cil name visitor_fun = visitors_cil := !visitors_cil @ [name, visitor_fun] From 03d621bcd3c36ad1bb14e0e8cffcdd444e7f3bae Mon Sep 17 00:00:00 2001 From: Johanna Schinabeck Date: Tue, 23 May 2023 19:49:58 +0200 Subject: [PATCH 023/327] small changes, updated my libraries with the hope now all tests pass on git --- runningGob.sh | 2 +- src/util/cilCfg.ml | 3 ++- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/runningGob.sh b/runningGob.sh index bb17a96384..b67bc36d9a 100755 --- a/runningGob.sh +++ b/runningGob.sh @@ -3,7 +3,7 @@ make #make install options="--set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra" cfile="tests/regression/55-loop-unrolling/01-simple-cases.c" -#./goblint $cfile $options --enable justcil > output.txt +./goblint $cfile $options --enable justcil > output.txt ./goblint $cfile $options --html python3 -m http.server --directory result 8081 #./goblint --enable dbg.debug tests/regression/55-loop-unrolling/01-simple-cases.c --enable ana.int.interval --set "ana.activated[+]" signs --enable justcil > output.txt diff --git a/src/util/cilCfg.ml b/src/util/cilCfg.ml index 45f12ef185..90d6be14ae 100644 --- a/src/util/cilCfg.ml +++ b/src/util/cilCfg.ml @@ -41,7 +41,6 @@ let loopCount file = let createCFG (fileAST: file) = - Cilfacade.do_preprocess_cil fileAST; (* The analyzer keeps values only for blocks. So if you want a value for every program point, each instruction *) (* needs to be in its own block. end_basic_blocks does that. *) (* After adding support for VLAs, there are new VarDecl instructions at the point where a variable was declared and *) @@ -49,6 +48,8 @@ let createCFG (fileAST: file) = (* BB causes the output CIL file to no longer compile. *) (* Since we want the output of justcil to compile, we do not run allBB visitor if justcil is enable, regardless of *) (* exp.basic-blocks. This does not matter, as we will not run any analysis anyway, when justcil is enabled. *) + + Cilfacade.do_preprocess_cil fileAST; if not (get_bool "exp.basic-blocks") && not (get_bool "justcil") then end_basic_blocks fileAST; (* We used to renumber vids but CIL already generates them fresh, so no need. From 878a1858afa7b7724243b23394eda3840b80d600 Mon Sep 17 00:00:00 2001 From: Johanna Schinabeck Date: Tue, 23 May 2023 20:11:57 +0200 Subject: [PATCH 024/327] changed var name of newly created var to a name, which is not a valid C name -> the variable must be unique --- src/util/terminationPreprocessing.ml | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/src/util/terminationPreprocessing.ml b/src/util/terminationPreprocessing.ml index e8e350997f..68b9b8ddc8 100644 --- a/src/util/terminationPreprocessing.ml +++ b/src/util/terminationPreprocessing.ml @@ -6,7 +6,6 @@ *) open GoblintCil -open Printf let extract_file_name s = (*There still may be a need to filter more chars*) let ls = String.split_on_char '/' s in (*Assuming '/' as path seperator*) @@ -19,7 +18,7 @@ let extract_file_name s = (*There still may be a need to filt s' let show_location_id l = - string_of_int l.line ^ "_" ^ string_of_int l.column (*extract_file_name l.file ^ "_" ^ *) + string_of_int l.line ^ "_" ^ string_of_int l.column ^ "_" ^ "file" ^ "_" ^ extract_file_name l.file class loopCounterVisitor (fd : fundec) = object(self) inherit nopCilVisitor @@ -29,7 +28,6 @@ class loopCounterVisitor (fd : fundec) = object(self) let name = "term"^show_location_id loc in let typ = Cil.intType in let v = (Cil.makeLocalVar fd name typ) in - (*let init_stmt = mkStmt (Instr [Set (var v, zero, loc, eloc)]) in*) let init_stmt = mkStmtOneInstr @@ Set (var v, zero, loc, eloc) in let inc_stmt = mkStmtOneInstr @@ Set (var v, increm (Lval (var v)) 1, loc, eloc) in (match b.bstmts with From 542ed6652b58d078565be72866bbb277fae86006 Mon Sep 17 00:00:00 2001 From: Alexander Schlenga Date: Wed, 24 May 2023 18:51:00 +0200 Subject: [PATCH 025/327] Checking bounds, other stuff --- src/analyses/termination_new.ml | 32 +++++++++++++++++++++++++++++--- 1 file changed, 29 insertions(+), 3 deletions(-) diff --git a/src/analyses/termination_new.ml b/src/analyses/termination_new.ml index e461492724..92973aab8a 100644 --- a/src/analyses/termination_new.ml +++ b/src/analyses/termination_new.ml @@ -4,9 +4,24 @@ open Analyses open GoblintCil open TerminationPreprocessing -let terminates ctx loop exp = +exception PreProcessing of string + +(* +let _ = WitnessUtil.find_loop_heads + +let check_loop_head ctx = false + *) + +let get_prepr_var () : varinfo = + raise (PreProcessing "No loop variable") (* TODO *) + +(** Checks whether a variable can be bounded *) +let check_bounded ctx varinfo = + let exp = Lval (Var varinfo, NoOffset) in match ctx.ask (EvalInt exp) with - _ -> () (* TODO *) + `Top -> false + | `Bot -> raise (PreProcessing "Loop variable is Bot") + | _ -> true (* TODO: Is this sound? *) module Spec : Analyses.MCPSpec = struct @@ -22,7 +37,18 @@ struct (** Provides some default implementations *) include Analyses.IdentitySpec - let branch ctx (exp:exp) (tv:bool) = + let assign ctx (lval : lval) (rval : exp) = + (* Detect preprocessing variable assignment to 0 *) + match lval, rval with + (Var get_prepr_var, NoOffset), zero -> ctx.local (* TODO *) + | _ -> ctx.local + + let branch ctx (exp : exp) (tv : bool) = + (* + let is_loop_head = check_loop_head ctx in + if is_loop_head then + enter_loop ctx; + *) ctx.local (* TODO *) let query ctx (type a) (q: a Queries.t): a Queries.result = From 461054eff5e10db4f48e4bb74c3c0e13081242ab Mon Sep 17 00:00:00 2001 From: Alexander Schlenga Date: Thu, 25 May 2023 17:51:17 +0200 Subject: [PATCH 026/327] Use new function register_preprocess_cil --- src/analyses/termination_new.ml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/analyses/termination_new.ml b/src/analyses/termination_new.ml index 92973aab8a..a20df2c0d9 100644 --- a/src/analyses/termination_new.ml +++ b/src/analyses/termination_new.ml @@ -59,6 +59,6 @@ end let () = (** Register the preprocessing *) - Cilfacade.register_preprocess (Spec.name ()) (new loopCounterVisitor); + Cilfacade.register_preprocess_cil (Spec.name ()) (new loopCounterVisitor); (** Register this analysis within the master control program *) MCP.register_analysis (module Spec : MCPSpec) From 6ccd800a7158bd0e9dbf45b859aba1c53682a25d Mon Sep 17 00:00:00 2001 From: Johanna Schinabeck Date: Mon, 29 May 2023 10:28:45 +0200 Subject: [PATCH 027/327] added comments --- runningGob.sh | 12 ++++++++++-- src/util/cilCfg.ml | 2 +- src/util/cilfacade.ml | 2 +- src/util/terminationPreprocessing.ml | 2 +- 4 files changed, 13 insertions(+), 5 deletions(-) diff --git a/runningGob.sh b/runningGob.sh index b67bc36d9a..c8f2901488 100755 --- a/runningGob.sh +++ b/runningGob.sh @@ -1,10 +1,18 @@ #!/bin/bash make #make install + +# set options and file for apron execution options="--set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra" cfile="tests/regression/55-loop-unrolling/01-simple-cases.c" -./goblint $cfile $options --enable justcil > output.txt -./goblint $cfile $options --html + +# run analysis, write cil output to file and enable visualization via html +#./goblint $cfile $options --enable justcil > output.txt +#./goblint $cfile $options --html + +./goblint --enable warn.debug tests/regression/99-tutorials/01-first.c --set "ana.activated[+]" signs --html + +# set up server to see visualizatino python3 -m http.server --directory result 8081 #./goblint --enable dbg.debug tests/regression/55-loop-unrolling/01-simple-cases.c --enable ana.int.interval --set "ana.activated[+]" signs --enable justcil > output.txt diff --git a/src/util/cilCfg.ml b/src/util/cilCfg.ml index 90d6be14ae..066f1ed981 100644 --- a/src/util/cilCfg.ml +++ b/src/util/cilCfg.ml @@ -48,7 +48,7 @@ let createCFG (fileAST: file) = (* BB causes the output CIL file to no longer compile. *) (* Since we want the output of justcil to compile, we do not run allBB visitor if justcil is enable, regardless of *) (* exp.basic-blocks. This does not matter, as we will not run any analysis anyway, when justcil is enabled. *) - + (* the preprocessing must be done here, to add the changes of CIL to the CFG*) Cilfacade.do_preprocess_cil fileAST; if not (get_bool "exp.basic-blocks") && not (get_bool "justcil") then end_basic_blocks fileAST; diff --git a/src/util/cilfacade.ml b/src/util/cilfacade.ml index fd298e01a0..a0e361bc85 100644 --- a/src/util/cilfacade.ml +++ b/src/util/cilfacade.ml @@ -74,7 +74,7 @@ let do_preprocess ast = iterGlobals ast (function GFun (fd,_) -> List.iter (f fd) !visitors | _ -> ()) let visitors_cil = ref [] -(* does exactly the same as register_preprocess_cil but it is executed earlier, before the CFG is created*) +(* does exactly the same as register_preprocess but it is executed earlier, before the CFG is created*) let register_preprocess_cil name visitor_fun = visitors_cil := !visitors_cil @ [name, visitor_fun] diff --git a/src/util/terminationPreprocessing.ml b/src/util/terminationPreprocessing.ml index 68b9b8ddc8..54e18d7df7 100644 --- a/src/util/terminationPreprocessing.ml +++ b/src/util/terminationPreprocessing.ml @@ -18,7 +18,7 @@ let extract_file_name s = (*There still may be a need to filt s' let show_location_id l = - string_of_int l.line ^ "_" ^ string_of_int l.column ^ "_" ^ "file" ^ "_" ^ extract_file_name l.file + string_of_int l.line ^ "_" ^ string_of_int l.column ^ "-file" ^ "_" ^ extract_file_name l.file class loopCounterVisitor (fd : fundec) = object(self) inherit nopCilVisitor From 07729336ab56a27df7c38ef08925ca22196cc50b Mon Sep 17 00:00:00 2001 From: Alexander Schlenga Date: Mon, 29 May 2023 15:50:25 +0200 Subject: [PATCH 028/327] Set abstract lattice, remove unused stuff, rename --- src/analyses/termination_new.ml | 30 ++++++++++++++---------------- 1 file changed, 14 insertions(+), 16 deletions(-) diff --git a/src/analyses/termination_new.ml b/src/analyses/termination_new.ml index a20df2c0d9..7727bf5b3f 100644 --- a/src/analyses/termination_new.ml +++ b/src/analyses/termination_new.ml @@ -6,14 +6,10 @@ open TerminationPreprocessing exception PreProcessing of string -(* -let _ = WitnessUtil.find_loop_heads +let visited = Stack.create () (* TODO: Is this allowed? *) -let check_loop_head ctx = false - *) - -let get_prepr_var () : varinfo = - raise (PreProcessing "No loop variable") (* TODO *) +let is_loop_counter_var (x : varinfo) = + false (* TODO: Actually detect loop counter variables *) (** Checks whether a variable can be bounded *) let check_bounded ctx varinfo = @@ -28,8 +24,8 @@ struct let name () = "termination" - module D = Lattice.Unit (* TODO *) - module C = D (* TODO *) + module D = MapDomain.MapBot (Basetype.Variables) (BoolDomain.MustBool) + module C = D let startstate _ = D.bot () (* TODO *) let exitstate = startstate (* TODO *) @@ -38,17 +34,19 @@ struct include Analyses.IdentitySpec let assign ctx (lval : lval) (rval : exp) = - (* Detect preprocessing variable assignment to 0 *) + (* Detect loop counter variable assignment to 0 *) match lval, rval with - (Var get_prepr_var, NoOffset), zero -> ctx.local (* TODO *) + (* Assume that the following loop does not terminate *) + (Var x, NoOffset), zero when is_loop_counter_var x -> + (* Remember the lcv *) + (* + let () = Stack.push x visited in + let () = enter_loop in + *) + D.add x false ctx.local | _ -> ctx.local let branch ctx (exp : exp) (tv : bool) = - (* - let is_loop_head = check_loop_head ctx in - if is_loop_head then - enter_loop ctx; - *) ctx.local (* TODO *) let query ctx (type a) (q: a Queries.t): a Queries.result = From 5f8c4c618f860872c59ee07b9e760c0901cff75c Mon Sep 17 00:00:00 2001 From: Alexander Schlenga Date: Mon, 29 May 2023 17:47:46 +0200 Subject: [PATCH 029/327] Implement bound checking on loop exit We assume an assignment to a loop exit indicator with the currently relevant loop counter variable as the right hand side expression. --- src/analyses/termination_new.ml | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/src/analyses/termination_new.ml b/src/analyses/termination_new.ml index 7727bf5b3f..10aaf4aef3 100644 --- a/src/analyses/termination_new.ml +++ b/src/analyses/termination_new.ml @@ -6,11 +6,12 @@ open TerminationPreprocessing exception PreProcessing of string -let visited = Stack.create () (* TODO: Is this allowed? *) - let is_loop_counter_var (x : varinfo) = false (* TODO: Actually detect loop counter variables *) +let is_loop_exit_indicator (x : varinfo) = + false (* TODO: Actually detect loop exit indicators *) + (** Checks whether a variable can be bounded *) let check_bounded ctx varinfo = let exp = Lval (Var varinfo, NoOffset) in @@ -27,7 +28,7 @@ struct module D = MapDomain.MapBot (Basetype.Variables) (BoolDomain.MustBool) module C = D - let startstate _ = D.bot () (* TODO *) + let startstate _ = D.bot () let exitstate = startstate (* TODO *) (** Provides some default implementations *) @@ -38,16 +39,15 @@ struct match lval, rval with (* Assume that the following loop does not terminate *) (Var x, NoOffset), zero when is_loop_counter_var x -> - (* Remember the lcv *) - (* - let () = Stack.push x visited in - let () = enter_loop in - *) D.add x false ctx.local + (* Loop exit: Check whether loop counter variable is bounded *) + | (Var y, NoOffset), Lval (Var x, NoOffset) when is_loop_exit_indicator y -> + let is_bounded = check_bounded ctx x in + D.add x is_bounded ctx.local | _ -> ctx.local let branch ctx (exp : exp) (tv : bool) = - ctx.local (* TODO *) + ctx.local (* TODO: Do we actually need a branch transfer function? *) let query ctx (type a) (q: a Queries.t): a Queries.result = let open Queries in From 378bbc452dad48b7caa58fb4c5803753d946c41f Mon Sep 17 00:00:00 2001 From: Isidor Zweckstetter Date: Mon, 29 May 2023 18:21:50 +0200 Subject: [PATCH 030/327] add List to loopCounterVisitor constructor, to store loopCounter variables in --- src/analyses/termination_new.ml | 4 +++- src/util/terminationPreprocessing.ml | 3 ++- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/src/analyses/termination_new.ml b/src/analyses/termination_new.ml index a20df2c0d9..3b255a4d61 100644 --- a/src/analyses/termination_new.ml +++ b/src/analyses/termination_new.ml @@ -6,6 +6,8 @@ open TerminationPreprocessing exception PreProcessing of string +let loopCounters : varinfo list ref = ref [] + (* let _ = WitnessUtil.find_loop_heads @@ -59,6 +61,6 @@ end let () = (** Register the preprocessing *) - Cilfacade.register_preprocess_cil (Spec.name ()) (new loopCounterVisitor); + Cilfacade.register_preprocess_cil (Spec.name ()) (new loopCounterVisitor loopCounters); (** Register this analysis within the master control program *) MCP.register_analysis (module Spec : MCPSpec) diff --git a/src/util/terminationPreprocessing.ml b/src/util/terminationPreprocessing.ml index e8e350997f..a1627db694 100644 --- a/src/util/terminationPreprocessing.ml +++ b/src/util/terminationPreprocessing.ml @@ -21,7 +21,7 @@ let extract_file_name s = (*There still may be a need to filt let show_location_id l = string_of_int l.line ^ "_" ^ string_of_int l.column (*extract_file_name l.file ^ "_" ^ *) -class loopCounterVisitor (fd : fundec) = object(self) +class loopCounterVisitor lc (fd : fundec) = object(self) inherit nopCilVisitor method! vstmt s = let action s = match s.skind with @@ -36,6 +36,7 @@ class loopCounterVisitor (fd : fundec) = object(self) | cont :: cond :: ss -> b.bstmts <- cont :: inc_stmt :: cond :: ss; (*cont :: cond :: inc_stmt :: ss = it is also possible, but for loops with cond at the end, inc is also at the end*) | _ -> ()); + lc := List.append !lc ([v] : varinfo list); let nb = mkBlock [init_stmt; mkStmt s.skind] in s.skind <- Block nb; s From 6efe564e00671ab9e487478cc2a324f5d03bf5ab Mon Sep 17 00:00:00 2001 From: Johanna Schinabeck Date: Mon, 29 May 2023 18:23:57 +0200 Subject: [PATCH 031/327] added new queries for termination analysis --- runningGob.sh | 16 +++++++++++----- src/analyses/termination_new.ml | 15 ++++++++++++++- src/domains/queries.ml | 12 ++++++++++++ 3 files changed, 37 insertions(+), 6 deletions(-) diff --git a/runningGob.sh b/runningGob.sh index c8f2901488..7c47eb36ea 100755 --- a/runningGob.sh +++ b/runningGob.sh @@ -3,14 +3,20 @@ make #make install # set options and file for apron execution -options="--set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra" -cfile="tests/regression/55-loop-unrolling/01-simple-cases.c" +options_apron="--set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra --enable warn.debug" #note: preprocessing first needs to be added to apron +options_signs="--set "ana.activated[+]" signs --enable warn.debug" +options_term="--set "ana.activated[+]" termination --enable warn.debug" + +cfile_loops="tests/regression/55-loop-unrolling/01-simple-cases.c" +cfile_signs="tests/regression/99-tutorials/01-first.c" # run analysis, write cil output to file and enable visualization via html -#./goblint $cfile $options --enable justcil > output.txt -#./goblint $cfile $options --html +#./goblint $cfile_loops $options_apron --enable justcil > output.txt +#./goblint $cfile_loops $options_apron --html -./goblint --enable warn.debug tests/regression/99-tutorials/01-first.c --set "ana.activated[+]" signs --html +# run analysis, write cil output to file and enable visualization via html +./goblint $cfile_loops $options_term --enable justcil > output.txt +./goblint $cfile_loops $options_term --html # set up server to see visualizatino python3 -m http.server --directory result 8081 diff --git a/src/analyses/termination_new.ml b/src/analyses/termination_new.ml index a20df2c0d9..3a09693b5c 100644 --- a/src/analyses/termination_new.ml +++ b/src/analyses/termination_new.ml @@ -3,6 +3,7 @@ open Analyses open GoblintCil open TerminationPreprocessing +open Printf exception PreProcessing of string @@ -51,9 +52,21 @@ struct *) ctx.local (* TODO *) + let terminates ctx = + ctx.ask Queries.MustTermProg + + (* provides information to Goblint*) let query ctx (type a) (q: a Queries.t): a Queries.result = let open Queries in - Result.top q (* TODO *) + match q with + | Queries.MustTermLoop v when check_bounded ctx v -> + printf "Termination analysis loop\n"; + true (* TODO*) + | Queries.MustTermProg -> + printf "Termination analysis prog\n"; + let b = terminates ctx in + true (*TODO*) + | _ -> Result.top q end diff --git a/src/domains/queries.ml b/src/domains/queries.ml index 2d1b25eca9..2df4a57af8 100644 --- a/src/domains/queries.ml +++ b/src/domains/queries.ml @@ -97,6 +97,8 @@ type _ t = | MayAccessed: AccessDomain.EventSet.t t | MayBeTainted: LS.t t | MayBeModifiedSinceSetjmp: JmpBufDomain.BufferEntry.t -> VS.t t + | MustTermLoop: varinfo -> MustBool.t t (** TODO: not sure if it is the MayBool*) + | MustTermProg: MustBool.t t type 'a result = 'a @@ -157,6 +159,8 @@ struct | MayAccessed -> (module AccessDomain.EventSet) | MayBeTainted -> (module LS) | MayBeModifiedSinceSetjmp _ -> (module VS) + | MustTermLoop _ -> (module MustBool) + | MustTermProg -> (module MustBool) (** Get bottom result for query. *) let bot (type a) (q: a t): a result = @@ -216,6 +220,8 @@ struct | MayAccessed -> AccessDomain.EventSet.top () | MayBeTainted -> LS.top () | MayBeModifiedSinceSetjmp _ -> VS.top () + | MustTermLoop _ -> MustBool.top () + | MustTermProg -> MustBool.top () end (* The type any_query can't be directly defined in Any as t, @@ -272,6 +278,8 @@ struct | Any ActiveJumpBuf -> 46 | Any ValidLongJmp -> 47 | Any (MayBeModifiedSinceSetjmp _) -> 48 + | Any (MustTermLoop _) -> 49 + | Any MustTermProg -> 50 let rec compare a b = let r = Stdlib.compare (order a) (order b) in @@ -306,6 +314,7 @@ struct compare (Any q1) (Any q2) | Any (IsHeapVar v1), Any (IsHeapVar v2) -> CilType.Varinfo.compare v1 v2 | Any (IsMultiple v1), Any (IsMultiple v2) -> CilType.Varinfo.compare v1 v2 + | Any (MustTermLoop v1), Any (MustTermLoop v2) -> CilType.Varinfo.compare v1 v2 | Any (EvalThread e1), Any (EvalThread e2) -> CilType.Exp.compare e1 e2 | Any (EvalJumpBuf e1), Any (EvalJumpBuf e2) -> CilType.Exp.compare e1 e2 | Any (WarnGlobal vi1), Any (WarnGlobal vi2) -> Stdlib.compare (Hashtbl.hash vi1) (Hashtbl.hash vi2) @@ -342,6 +351,7 @@ struct | Any (IterVars i) -> 0 | Any (PathQuery (i, q)) -> 31 * i + hash (Any q) | Any (IsHeapVar v) -> CilType.Varinfo.hash v + | Any (MustTermLoop v) -> CilType.Varinfo.hash v | Any (IsMultiple v) -> CilType.Varinfo.hash v | Any (EvalThread e) -> CilType.Exp.hash e | Any (EvalJumpBuf e) -> CilType.Exp.hash e @@ -404,6 +414,8 @@ struct | Any MayBeTainted -> Pretty.dprintf "MayBeTainted" | Any DYojson -> Pretty.dprintf "DYojson" | Any MayBeModifiedSinceSetjmp buf -> Pretty.dprintf "MayBeModifiedSinceSetjmp %a" JmpBufDomain.BufferEntry.pretty buf + | Any (MustTermLoop v) -> Pretty.dprintf "MustTermLoop %a" CilType.Varinfo.pretty v + | Any MustTermProg -> Pretty.dprintf "MustTermProg" end let to_value_domain_ask (ask: ask) = From 371ae720e91ce559705fc01f720b24baf496e4d0 Mon Sep 17 00:00:00 2001 From: Isidor Zweckstetter Date: Mon, 29 May 2023 18:42:15 +0200 Subject: [PATCH 032/327] merged --- src/analyses/apron/apronAnalysis.apron.ml | 1 - 1 file changed, 1 deletion(-) diff --git a/src/analyses/apron/apronAnalysis.apron.ml b/src/analyses/apron/apronAnalysis.apron.ml index dfd9c95d70..0b067ba814 100644 --- a/src/analyses/apron/apronAnalysis.apron.ml +++ b/src/analyses/apron/apronAnalysis.apron.ml @@ -39,7 +39,6 @@ let after_config () = let _ = - Cilfacade.register_preprocess_cil ("apron") (new loopCounterVisitor); AfterConfig.register after_config From df206b0173584cc0c0ad79ce6c6a6fe23042ca98 Mon Sep 17 00:00:00 2001 From: Johanna Schinabeck Date: Mon, 29 May 2023 18:47:30 +0200 Subject: [PATCH 033/327] small changes in the termination_new file for the query function, still in progress --- src/analyses/termination_new.ml | 13 ++++--------- 1 file changed, 4 insertions(+), 9 deletions(-) diff --git a/src/analyses/termination_new.ml b/src/analyses/termination_new.ml index 2d3bd339bb..9e8f095e8a 100644 --- a/src/analyses/termination_new.ml +++ b/src/analyses/termination_new.ml @@ -50,20 +50,15 @@ struct let branch ctx (exp : exp) (tv : bool) = ctx.local (* TODO: Do we actually need a branch transfer function? *) - let terminates ctx = - ctx.ask Queries.MustTermProg - + (* provides information to Goblint*) let query ctx (type a) (q: a Queries.t): a Queries.result = let open Queries in match q with - | Queries.MustTermLoop v when check_bounded ctx v -> - printf "Termination analysis loop\n"; - true (* TODO*) + | Queries.MustTermLoop v when check_bounded ctx v -> + true (* TODO should we use the checl_bound function?*) | Queries.MustTermProg -> - printf "Termination analysis prog\n"; - let b = terminates ctx in - true (*TODO*) + true (*TODO check if all values in the domain are true -> true*) | _ -> Result.top q end From 54053c88a6f8776c353b999f247ef2ba80458dd3 Mon Sep 17 00:00:00 2001 From: Alexander Schlenga Date: Mon, 29 May 2023 19:45:13 +0200 Subject: [PATCH 034/327] Implement is_loop_counter_var --- src/analyses/termination_new.ml | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/analyses/termination_new.ml b/src/analyses/termination_new.ml index d15bb73268..1eb4857ad3 100644 --- a/src/analyses/termination_new.ml +++ b/src/analyses/termination_new.ml @@ -10,7 +10,7 @@ exception PreProcessing of string let loopCounters : varinfo list ref = ref [] let is_loop_counter_var (x : varinfo) = - false (* TODO: Actually detect loop counter variables *) + List.mem x !loopCounters let is_loop_exit_indicator (x : varinfo) = false (* TODO: Actually detect loop exit indicators *) @@ -56,12 +56,12 @@ struct (* provides information to Goblint*) let query ctx (type a) (q: a Queries.t): a Queries.result = let open Queries in - match q with + match q with | Queries.MustTermLoop v when check_bounded ctx v -> true (* TODO should we use the checl_bound function?*) - | Queries.MustTermProg -> + | Queries.MustTermProg -> true (*TODO check if all values in the domain are true -> true*) - | _ -> Result.top q + | _ -> Result.top q end From 3f200faa6d996afacd182a89850617171776de28 Mon Sep 17 00:00:00 2001 From: Isidor Zweckstetter Date: Tue, 30 May 2023 01:46:21 +0200 Subject: [PATCH 035/327] added Variable to indicate Loop exits -more testing might be needed --- src/analyses/termination_new.ml | 5 ++++- src/util/terminationPreprocessing.ml | 10 ++++++++-- 2 files changed, 12 insertions(+), 3 deletions(-) diff --git a/src/analyses/termination_new.ml b/src/analyses/termination_new.ml index d15bb73268..68538c9d88 100644 --- a/src/analyses/termination_new.ml +++ b/src/analyses/termination_new.ml @@ -9,6 +9,8 @@ exception PreProcessing of string let loopCounters : varinfo list ref = ref [] +let loopExit : varinfo ref = ref (makeVarinfo false "-error" Cil.intType) + let is_loop_counter_var (x : varinfo) = false (* TODO: Actually detect loop counter variables *) @@ -55,6 +57,7 @@ struct (* provides information to Goblint*) let query ctx (type a) (q: a Queries.t): a Queries.result = + print_endline @@ ""^(!loopExit.vname); let open Queries in match q with | Queries.MustTermLoop v when check_bounded ctx v -> @@ -67,6 +70,6 @@ end let () = (** Register the preprocessing *) - Cilfacade.register_preprocess_cil (Spec.name ()) (new loopCounterVisitor loopCounters); + Cilfacade.register_preprocess_cil (Spec.name ()) (new loopCounterVisitor loopCounters loopExit); (** Register this analysis within the master control program *) MCP.register_analysis (module Spec : MCPSpec) diff --git a/src/util/terminationPreprocessing.ml b/src/util/terminationPreprocessing.ml index b3eb8692d2..71644c0894 100644 --- a/src/util/terminationPreprocessing.ml +++ b/src/util/terminationPreprocessing.ml @@ -20,8 +20,13 @@ let extract_file_name s = (*There still may be a need to filt let show_location_id l = string_of_int l.line ^ "_" ^ string_of_int l.column ^ "-file" ^ "_" ^ extract_file_name l.file -class loopCounterVisitor lc (fd : fundec) = object(self) +class loopCounterVisitor lc le (fd : fundec) = object(self) inherit nopCilVisitor + method! vfunc (f:fundec) = + let exit_name = "term_exit-" in + let typ = Cil.intType in + le := Cil.makeLocalVar fd exit_name typ; + DoChildren; (* function definition *) method! vstmt s = let action s = match s.skind with | Loop (b, loc, eloc, _, _) -> @@ -30,12 +35,13 @@ class loopCounterVisitor lc (fd : fundec) = object(self) let v = (Cil.makeLocalVar fd name typ) in let init_stmt = mkStmtOneInstr @@ Set (var v, zero, loc, eloc) in let inc_stmt = mkStmtOneInstr @@ Set (var v, increm (Lval (var v)) 1, loc, eloc) in + let exit_stmt = mkStmtOneInstr @@ Set ((var !le), (Lval (var v)), loc, eloc) in (match b.bstmts with | cont :: cond :: ss -> b.bstmts <- cont :: inc_stmt :: cond :: ss; (*cont :: cond :: inc_stmt :: ss = it is also possible, but for loops with cond at the end, inc is also at the end*) | _ -> ()); lc := List.append !lc ([v] : varinfo list); - let nb = mkBlock [init_stmt; mkStmt s.skind] in + let nb = mkBlock [init_stmt; mkStmt s.skind; exit_stmt] in s.skind <- Block nb; s | _ -> s From 77e99cb34459246a1953482ec547d9df6d875922 Mon Sep 17 00:00:00 2001 From: Alexander Schlenga Date: Tue, 30 May 2023 10:03:50 +0200 Subject: [PATCH 036/327] Implement is_loop_exit_indicator --- src/analyses/termination_new.ml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/analyses/termination_new.ml b/src/analyses/termination_new.ml index fe86035920..1128365963 100644 --- a/src/analyses/termination_new.ml +++ b/src/analyses/termination_new.ml @@ -15,7 +15,7 @@ let is_loop_counter_var (x : varinfo) = List.mem x !loopCounters let is_loop_exit_indicator (x : varinfo) = - false (* TODO: Actually detect loop exit indicators *) + x = !loopExit (** Checks whether a variable can be bounded *) let check_bounded ctx varinfo = From f1c57fcacaf8d29ae8f4f0e430be54472b0edc2c Mon Sep 17 00:00:00 2001 From: Isidor Zweckstetter Date: Tue, 30 May 2023 13:08:15 +0200 Subject: [PATCH 037/327] LoopExit changed to Global variable --- src/util/terminationPreprocessing.ml | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/src/util/terminationPreprocessing.ml b/src/util/terminationPreprocessing.ml index 71644c0894..1a0e725624 100644 --- a/src/util/terminationPreprocessing.ml +++ b/src/util/terminationPreprocessing.ml @@ -23,9 +23,11 @@ let show_location_id l = class loopCounterVisitor lc le (fd : fundec) = object(self) inherit nopCilVisitor method! vfunc (f:fundec) = - let exit_name = "term_exit-" in - let typ = Cil.intType in - le := Cil.makeLocalVar fd exit_name typ; + if !le.vname <> "term_exit-" then begin + let exit_name = "term_exit-" in + let typ = Cil.intType in + le := Cil.makeGlobalVar exit_name typ; + end; DoChildren; (* function definition *) method! vstmt s = let action s = match s.skind with From 77ce08ed61dadf105783e0874b2d3f146b260da9 Mon Sep 17 00:00:00 2001 From: Thomas Lagemann Date: Thu, 1 Jun 2023 05:01:09 +0200 Subject: [PATCH 038/327] Tests for loop termination --- scripts/update_suite.rb | 6 + .../01-simple-loop-terminating.c | 15 ++ .../02-simple-loop-nonterminating.c | 12 ++ .../03-nested-loop-terminating.c | 27 ++++ .../04-nested-loop-nonterminating.c | 23 +++ .../80-termination/05-for-loop-terminating.c | 14 ++ .../06-for-loop-nonterminating.c | 10 ++ .../07-nested-for-loop-terminating.c | 20 +++ .../08-nested-for-loop-nonterminating.c | 19 +++ .../09-complex-for-loop-terminating.c | 107 +++++++++++++ .../10-complex-loop-terminating.c | 135 ++++++++++++++++ .../80-termination/11-loopless-termination.c | 7 + .../12-do-while-instant-terminating.c | 15 ++ .../80-termination/13-do-while-terminating.c | 16 ++ .../14-do-while-nonterminating.c | 16 ++ .../15-complex-loop-combination-terminating.c | 144 ++++++++++++++++++ ...16-nested-loop-nontrivial-nonterminating.c | 23 +++ 17 files changed, 609 insertions(+) create mode 100644 tests/regression/80-termination/01-simple-loop-terminating.c create mode 100644 tests/regression/80-termination/02-simple-loop-nonterminating.c create mode 100644 tests/regression/80-termination/03-nested-loop-terminating.c create mode 100644 tests/regression/80-termination/04-nested-loop-nonterminating.c create mode 100644 tests/regression/80-termination/05-for-loop-terminating.c create mode 100644 tests/regression/80-termination/06-for-loop-nonterminating.c create mode 100644 tests/regression/80-termination/07-nested-for-loop-terminating.c create mode 100644 tests/regression/80-termination/08-nested-for-loop-nonterminating.c create mode 100644 tests/regression/80-termination/09-complex-for-loop-terminating.c create mode 100644 tests/regression/80-termination/10-complex-loop-terminating.c create mode 100644 tests/regression/80-termination/11-loopless-termination.c create mode 100644 tests/regression/80-termination/12-do-while-instant-terminating.c create mode 100644 tests/regression/80-termination/13-do-while-terminating.c create mode 100644 tests/regression/80-termination/14-do-while-nonterminating.c create mode 100644 tests/regression/80-termination/15-complex-loop-combination-terminating.c create mode 100644 tests/regression/80-termination/16-nested-loop-nontrivial-nonterminating.c diff --git a/scripts/update_suite.rb b/scripts/update_suite.rb index e99068829e..dead6cd8f1 100755 --- a/scripts/update_suite.rb +++ b/scripts/update_suite.rb @@ -165,6 +165,8 @@ def collect_warnings when /^\[Error\]/ then "warn" when /^\[Info\]/ then "warn" when /^\[Success\]/ then "success" + when /^\[Terminating\]/ then "term" + when /^\[Nonterminating\]/ then "noterm" when /\[Debug\]/ then next # debug "warnings" shouldn't count as other warnings (against NOWARN) when /^ on line \d+ $/ then next # dead line warnings shouldn't count (used for unreachability with NOWARN) when /^ on lines \d+..\d+ $/ then next # dead line warnings shouldn't count (used for unreachability with NOWARN) @@ -298,6 +300,10 @@ def parse_tests (lines) tests[i] = "fail" elsif obj =~ /UNKNOWN/ then tests[i] = "unknown" + elsif obj =~ /NON?TERM/ then + tests[i] = "noterm" + elsif obj =~ /TERM/ then + tests[i] = "term" elsif obj =~ /(assert|__goblint_check).*\(/ then if obj =~ /FAIL/ then tests[i] = "fail" diff --git a/tests/regression/80-termination/01-simple-loop-terminating.c b/tests/regression/80-termination/01-simple-loop-terminating.c new file mode 100644 index 0000000000..931b125171 --- /dev/null +++ b/tests/regression/80-termination/01-simple-loop-terminating.c @@ -0,0 +1,15 @@ +// PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra +#include + +int main() +{ + int i = 1; + + while (i <= 10) // TERM + { + printf("%d\n", i); + i++; + } + + return 0; +} diff --git a/tests/regression/80-termination/02-simple-loop-nonterminating.c b/tests/regression/80-termination/02-simple-loop-nonterminating.c new file mode 100644 index 0000000000..520a4a82e0 --- /dev/null +++ b/tests/regression/80-termination/02-simple-loop-nonterminating.c @@ -0,0 +1,12 @@ +// PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra +#include + +int main() +{ + while (1) // NOTERM + { + continue; + } + + return 0; +} diff --git a/tests/regression/80-termination/03-nested-loop-terminating.c b/tests/regression/80-termination/03-nested-loop-terminating.c new file mode 100644 index 0000000000..172827af42 --- /dev/null +++ b/tests/regression/80-termination/03-nested-loop-terminating.c @@ -0,0 +1,27 @@ +// PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra +#include + +int main() +{ + int rows = 3; + int columns = 4; + int i = 1; + + // Outer while loop for rows + while (i <= rows) + { // TERM + int j = 1; + + // Inner while loop for columns + while (j <= columns) + { // TERM + printf("(%d, %d) ", i, j); + j++; + } + + printf("\n"); + i++; + } + + return 0; +} diff --git a/tests/regression/80-termination/04-nested-loop-nonterminating.c b/tests/regression/80-termination/04-nested-loop-nonterminating.c new file mode 100644 index 0000000000..37af9ed6fb --- /dev/null +++ b/tests/regression/80-termination/04-nested-loop-nonterminating.c @@ -0,0 +1,23 @@ +// PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra +#include + +int main() +{ + int outerCount = 1; + + while (outerCount <= 3) // NOTERM + { + int innerCount = 1; + + while (1) // NOTERM + { + printf("(%d, %d) ", outerCount, innerCount); + innerCount++; + } + + printf("\n"); + outerCount++; + } + + return 0; +} diff --git a/tests/regression/80-termination/05-for-loop-terminating.c b/tests/regression/80-termination/05-for-loop-terminating.c new file mode 100644 index 0000000000..ab286a6dd4 --- /dev/null +++ b/tests/regression/80-termination/05-for-loop-terminating.c @@ -0,0 +1,14 @@ +// PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra +#include + +int main() +{ + int i; + + for (i = 1; i <= 10; i++) // TERM + { + printf("%d\n", i); + } + + return 0; +} diff --git a/tests/regression/80-termination/06-for-loop-nonterminating.c b/tests/regression/80-termination/06-for-loop-nonterminating.c new file mode 100644 index 0000000000..466001e6e5 --- /dev/null +++ b/tests/regression/80-termination/06-for-loop-nonterminating.c @@ -0,0 +1,10 @@ +// PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra +#include + +int main() { + for (;;) { // NOTERM + printf("This loop does not terminate.\n"); + } + + return 0; +} diff --git a/tests/regression/80-termination/07-nested-for-loop-terminating.c b/tests/regression/80-termination/07-nested-for-loop-terminating.c new file mode 100644 index 0000000000..eec4dda908 --- /dev/null +++ b/tests/regression/80-termination/07-nested-for-loop-terminating.c @@ -0,0 +1,20 @@ +// PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra +#include + +int main() +{ + int rows = 3; + int columns = 4; + + // Nested loop to iterate over rows and columns + for (int i = 1; i <= rows; i++) // TERM + { + for (int j = 1; j <= columns; j++) // TERM + { + printf("(%d, %d) ", i, j); + } + printf("\n"); + } + + return 0; +} diff --git a/tests/regression/80-termination/08-nested-for-loop-nonterminating.c b/tests/regression/80-termination/08-nested-for-loop-nonterminating.c new file mode 100644 index 0000000000..3f7bcb4f07 --- /dev/null +++ b/tests/regression/80-termination/08-nested-for-loop-nonterminating.c @@ -0,0 +1,19 @@ +// PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra +#include + +int main() +{ + int outerCount, innerCount; + + for (outerCount = 1; outerCount <= 3; outerCount++) // NOTERM + { + for (innerCount = 1;; innerCount++) // NOTERM + { + printf("(%d, %d) ", outerCount, innerCount); + } + + printf("\n"); + } + + return 0; +} diff --git a/tests/regression/80-termination/09-complex-for-loop-terminating.c b/tests/regression/80-termination/09-complex-for-loop-terminating.c new file mode 100644 index 0000000000..ed28fa9b43 --- /dev/null +++ b/tests/regression/80-termination/09-complex-for-loop-terminating.c @@ -0,0 +1,107 @@ +// PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra +#include + +int main() +{ + int i, j, k; + + // Outer loop + for (i = 1; i <= 5; i++) // TERM + { + // Inner loop 1 + for (j = 1; j <= i; j++) // TERM + { + printf("%d ", j); + } + printf("\n"); + + // Inner loop 2 + for (k = i; k >= 1; k--) // TERM + { + printf("%d ", k); + } + printf("\n"); + } + + // Additional loop + for (i = 5; i >= 1; i--) // TERM + { + for (j = i; j >= 1; j--) // TERM + { + printf("%d ", j); + } + printf("\n"); + } + + // Loop with conditions + for (i = 1; i <= 10; i++) // TERM + { + if (i % 2 == 0) + { + printf("%d is even\n", i); + } + else + { + printf("%d is odd\n", i); + } + } + + // Loop with nested conditions + for (i = 1; i <= 10; i++) // TERM + { + printf("Number: %d - ", i); + if (i < 5) + { + printf("Less than 5\n"); + } + else if (i > 5) + { + printf("Greater than 5\n"); + } + else + { + printf("Equal to 5\n"); + } + } + + // Loop with a break statement + for (i = 1; i <= 10; i++) // TERM + { + printf("%d ", i); + if (i == 5) + { + break; + } + } + printf("\n"); + + // Loop with a continue statement + for (i = 1; i <= 10; i++) // TERM + { + if (i % 2 == 0) + { + continue; + } + printf("%d ", i); + } + printf("\n"); + + // Loop with complex conditions + for (i = 1; i <= 10; i++) // TERM + { + if (i > 5 && i % 2 == 0) + { + printf("%d ", i); + } + } + printf("\n"); + + // Loop with multiple variables + int a, b, c; + for (a = 1, b = 2, c = 3; a <= 10; a++, b += 2, c += 3) // TERM + { + printf("%d %d %d\n", a, b, c); + } + + return 0; +} diff --git a/tests/regression/80-termination/10-complex-loop-terminating.c b/tests/regression/80-termination/10-complex-loop-terminating.c new file mode 100644 index 0000000000..3a19f17bee --- /dev/null +++ b/tests/regression/80-termination/10-complex-loop-terminating.c @@ -0,0 +1,135 @@ +// PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra +#include + +int main() +{ + int i = 1; + int j = 1; + int k = 5; + + // Outer while loop + while (i <= 5) // TERM + { + // Inner while loop 1 + while (j <= i) // TERM + { + printf("%d ", j); + j++; + } + printf("\n"); + j = 1; + + // Inner while loop 2 + while (k >= 1) // TERM + { + printf("%d ", k); + k--; + } + printf("\n"); + k = 5; + + i++; + } + + // Additional while loop + i = 5; + while (i >= 1) // TERM + { + j = i; + while (j >= 1) // TERM + { + printf("%d ", j); + j--; + } + printf("\n"); + i--; + } + + // Loop with conditions + i = 1; + while (i <= 10) // TERM + { + if (i % 2 == 0) + { + printf("%d is even\n", i); + } + else + { + printf("%d is odd\n", i); + } + i++; + } + + // Loop with nested conditions + i = 1; + while (i <= 10) // TERM + { + printf("Number: %d - ", i); + if (i < 5) + { + printf("Less than 5\n"); + } + else if (i > 5) + { + printf("Greater than 5\n"); + } + else + { + printf("Equal to 5\n"); + } + i++; + } + + // Loop with a break statement + i = 1; + while (i <= 10) // TERM + { + printf("%d ", i); + if (i == 5) + { + break; + } + i++; + } + printf("\n"); + + // Loop with a continue statement + i = 1; + while (i <= 10) // TERM + { + if (i % 2 == 0) + { + i++; + continue; + } + printf("%d ", i); + i++; + } + printf("\n"); + + // Loop with complex conditions + i = 1; + while (i <= 10) // TERM + { + if (i > 5 && i % 2 == 0) + { + printf("%d ", i); + } + i++; + } + printf("\n"); + + // Loop with multiple variables + int a = 1; + int b = 2; + int c = 3; + while (a <= 10) // TERM + { + printf("%d %d %d\n", a, b, c); + a++; + b += 2; + c += 3; + } + + return 0; +} diff --git a/tests/regression/80-termination/11-loopless-termination.c b/tests/regression/80-termination/11-loopless-termination.c new file mode 100644 index 0000000000..b118e65e35 --- /dev/null +++ b/tests/regression/80-termination/11-loopless-termination.c @@ -0,0 +1,7 @@ +// TERM +#include + +int main() { + printf("Terminating code without a loop\n"); + return 0; +} diff --git a/tests/regression/80-termination/12-do-while-instant-terminating.c b/tests/regression/80-termination/12-do-while-instant-terminating.c new file mode 100644 index 0000000000..cc3cc41edc --- /dev/null +++ b/tests/regression/80-termination/12-do-while-instant-terminating.c @@ -0,0 +1,15 @@ +// PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra +#include + +int main() +{ + int i = 0; + + do // TERM + { + printf("Inside the do-while loop\n"); + } while (i > 0); + + printf("Exited the loop\n"); + return 0; +} diff --git a/tests/regression/80-termination/13-do-while-terminating.c b/tests/regression/80-termination/13-do-while-terminating.c new file mode 100644 index 0000000000..05fe270f04 --- /dev/null +++ b/tests/regression/80-termination/13-do-while-terminating.c @@ -0,0 +1,16 @@ +// PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra +#include + +int main() +{ + int i = 1; + + do // TERM + { + printf("Inside the do-while loop\n"); + i++; + } while (i <= 5); + + printf("Exited the loop\n"); + return 0; +} diff --git a/tests/regression/80-termination/14-do-while-nonterminating.c b/tests/regression/80-termination/14-do-while-nonterminating.c new file mode 100644 index 0000000000..1c70d4fc76 --- /dev/null +++ b/tests/regression/80-termination/14-do-while-nonterminating.c @@ -0,0 +1,16 @@ +// PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra +#include + +int main() +{ + int i = 1; + + do // NOTERM + { + printf("Inside the do-while loop\n"); + i++; + } while (i >= 2); + + printf("Exited the loop\n"); + return 0; +} diff --git a/tests/regression/80-termination/15-complex-loop-combination-terminating.c b/tests/regression/80-termination/15-complex-loop-combination-terminating.c new file mode 100644 index 0000000000..54f8cd97c8 --- /dev/null +++ b/tests/regression/80-termination/15-complex-loop-combination-terminating.c @@ -0,0 +1,144 @@ +// PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra +#include + +int main() +{ + // Non-nested loops + int i; + + // for loop + for (i = 1; i <= 10; i++) // TERM + { + printf("For loop iteration: %d\n", i); + } + + // while loop + int j = 1; + while (j <= 10) // TERM + { + printf("While loop iteration: %d\n", j); + j++; + } + + // do-while loop + int k = 1; + do // TERM + { + printf("Do-While loop iteration: %d\n", k); + k++; + } while (k <= 10); + + // Nested loops + int a, b; + + // Nested for and while loop + for (a = 1; a <= 5; a++) // TERM + { + int c = 1; + while (c <= a) // TERM + { + printf("Nested For-While loop: %d\n", c); + c++; + } + } + + // Nested while and do-while loop + int x = 1; + while (x <= 5) // TERM + { + int y = 1; + do // TERM + { + printf("Nested While-Do-While loop: %d\n", y); + y++; + } while (y <= x); + x++; + } + + // Nested do-while and for loop + int p = 1; + do // TERM + { + for (int q = 1; q <= p; q++) // TERM + { + printf("Nested Do-While-For loop: %d\n", q); + } + p++; + } while (p <= 5); + + // Additional loops + int m; + + // Nested while loop with a break statement + int n = 1; + while (n <= 5) // TERM + { + printf("Outer While loop iteration: %d\n", n); + m = 1; + while (1) // TERM + { + printf("Inner While loop iteration: %d\n", m); + m++; + if (m == 4) + { + break; + } + } + n++; + } + + // Loop with a continue statement + for (int r = 1; r <= 10; r++) // TERM + { + if (r % 3 == 0) + { + continue; + } + printf("Loop with Continue: %d\n", r); + } + + // Loop with multiple conditions + int s = 1; + while (s <= 10 && s % 2 == 0) // TERM + { + printf("Loop with Multiple Conditions: %d\n", s); + s++; + } + + // Loop with multiple variables + int t, u; + for (t = 1, u = 10; t <= 5 && u >= 5; t++, u--) // TERM + { + printf("Loop with Multiple Variables: %d %d\n", t, u); + } + + // Loop with nested conditions + for (int v = 1; v <= 10; v++) // TERM + { + printf("Loop with Nested Conditions: %d - ", v); + if (v < 5) + { + printf("Less than 5\n"); + } + else if (v > 5) + { + printf("Greater than 5\n"); + } + else + { + printf("Equal to 5\n"); + } + } + + /* // Loop with a label and goto statement + int w = 1; +start: + if (w <= 5) + { + printf("Loop with Label and Goto: %d\n", w); + w++; + goto start; // TERM + } */ + + return 0; +} diff --git a/tests/regression/80-termination/16-nested-loop-nontrivial-nonterminating.c b/tests/regression/80-termination/16-nested-loop-nontrivial-nonterminating.c new file mode 100644 index 0000000000..855fbd0dca --- /dev/null +++ b/tests/regression/80-termination/16-nested-loop-nontrivial-nonterminating.c @@ -0,0 +1,23 @@ +// PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra +#include + +int main() +{ + int outerCount = 1; + + while (outerCount <= 3) // NOTERM + { + int innerCount = 1; + + while (outerCount < 3 || innerCount > 0) // NOTERM + { + printf("(%d, %d) ", outerCount, innerCount); + innerCount++; + } + + printf("\n"); + outerCount++; + } + + return 0; +} From af5bf08d647ada99e283a2f8594e55751c06a2a9 Mon Sep 17 00:00:00 2001 From: Alexander Schlenga Date: Thu, 1 Jun 2023 11:34:01 +0200 Subject: [PATCH 039/327] Remove debug output --- src/analyses/termination_new.ml | 1 - 1 file changed, 1 deletion(-) diff --git a/src/analyses/termination_new.ml b/src/analyses/termination_new.ml index 1128365963..87effec842 100644 --- a/src/analyses/termination_new.ml +++ b/src/analyses/termination_new.ml @@ -57,7 +57,6 @@ struct (* provides information to Goblint*) let query ctx (type a) (q: a Queries.t): a Queries.result = - print_endline @@ ""^(!loopExit.vname); let open Queries in match q with | Queries.MustTermLoop v when check_bounded ctx v -> From 4e2298278a6a8f4afaf31e600446dd8bade91d9f Mon Sep 17 00:00:00 2001 From: Alexander Schlenga Date: Fri, 2 Jun 2023 13:14:15 +0200 Subject: [PATCH 040/327] Recognize every assignment to the loop counter var This way we catch GOTOs into loops except for the case when the loop guard evaluates to false already the first time. --- src/analyses/termination_new.ml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/analyses/termination_new.ml b/src/analyses/termination_new.ml index 87effec842..4b1dbb6a84 100644 --- a/src/analyses/termination_new.ml +++ b/src/analyses/termination_new.ml @@ -43,7 +43,7 @@ struct (* Detect loop counter variable assignment to 0 *) match lval, rval with (* Assume that the following loop does not terminate *) - (Var x, NoOffset), zero when is_loop_counter_var x -> + (Var x, NoOffset), _ when is_loop_counter_var x -> D.add x false ctx.local (* Loop exit: Check whether loop counter variable is bounded *) | (Var y, NoOffset), Lval (Var x, NoOffset) when is_loop_exit_indicator y -> From 1ad86f20d5db844b6e715e498f75bbf7438b6e67 Mon Sep 17 00:00:00 2001 From: Alexander Schlenga Date: Fri, 2 Jun 2023 13:21:38 +0200 Subject: [PATCH 041/327] Remove unused open --- src/analyses/termination_new.ml | 1 - 1 file changed, 1 deletion(-) diff --git a/src/analyses/termination_new.ml b/src/analyses/termination_new.ml index 4b1dbb6a84..936471ceaf 100644 --- a/src/analyses/termination_new.ml +++ b/src/analyses/termination_new.ml @@ -3,7 +3,6 @@ open Analyses open GoblintCil open TerminationPreprocessing -open Printf exception PreProcessing of string From 837c7979255d41b5ed47f49eee05845a16139e68 Mon Sep 17 00:00:00 2001 From: Johanna Schinabeck Date: Sat, 3 Jun 2023 13:29:17 +0200 Subject: [PATCH 042/327] first tests for recursion termination analysis, added empty functor and GMapG --- runningGob.sh | 22 ++++++++--- src/analyses/termination_new.ml | 2 - src/framework/analyses.ml | 53 ++++++++++++++++++++++++++ src/framework/constraints.ml | 66 ++++++++++++++++++++++++++++++++- src/framework/control.ml | 1 + 5 files changed, 135 insertions(+), 9 deletions(-) diff --git a/runningGob.sh b/runningGob.sh index f765b5afab..e3b5a6da45 100755 --- a/runningGob.sh +++ b/runningGob.sh @@ -1,22 +1,32 @@ #!/bin/bash -make +#make #make install # set options and file for apron execution -options_apron="--set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra --enable warn.debug" #note: preprocessing first needs to be added to apron +options_apron="--set ana.activated[+] apron --enable ana.int.interval --set --enable warn.debug" #note: preprocessing first needs to be added to apron options_signs="--set "ana.activated[+]" signs --enable warn.debug" options_term="--set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra" -cfile_loops="tests/regression/55-loop-unrolling/01-simple-cases.c" -cfile_signs="tests/regression/99-tutorials/01-first.c" +cfile_loops="tests/regression/55-loop-unrolling/01-simple-cases.c" +cfile_nonTerm="tests/regression/80-termination/02-simple-loop-nonterminating.c" +cfile_signs="tests/regression/99-tutorials/01-first.c" +cfile_deadCode="tests/regression/80-termination/16-nested-loop-nontrivial-nonterminating.c" # run analysis, write cil output to file and enable visualization via html #./goblint $cfile_loops $options_apron --enable justcil > output.txt #./goblint $cfile_loops $options_apron --html # run analysis, write cil output to file and enable visualization via html -./goblint $cfile_loops $options_term --enable justcil > output.txt -./goblint $cfile_loops $options_term --html +#./goblint $cfile_loops $options_term --enable justcil > output.txt +#./goblint $cfile_loops $options_term --html + +# run analysis, write cil output to file and enable visualization via html +./goblint $cfile_deadCode $options_term --enable justcil > output.txt +./goblint $cfile_deadCode $options_term --html + +# run analysis, write cil output to file and enable visualization via html +#./goblint $cfile_nonTerm $options_term --enable justcil > output.txt +#./goblint $cfile_nonTerm $options_term --html # set up server to see visualizatino python3 -m http.server --directory result 8081 diff --git a/src/analyses/termination_new.ml b/src/analyses/termination_new.ml index 1128365963..90c1004033 100644 --- a/src/analyses/termination_new.ml +++ b/src/analyses/termination_new.ml @@ -3,7 +3,6 @@ open Analyses open GoblintCil open TerminationPreprocessing -open Printf exception PreProcessing of string @@ -57,7 +56,6 @@ struct (* provides information to Goblint*) let query ctx (type a) (q: a Queries.t): a Queries.result = - print_endline @@ ""^(!loopExit.vname); let open Queries in match q with | Queries.MustTermLoop v when check_bounded ctx v -> diff --git a/src/framework/analyses.ml b/src/framework/analyses.ml index 1a3a4ebeb1..c8d3873085 100644 --- a/src/framework/analyses.ml +++ b/src/framework/analyses.ml @@ -119,6 +119,59 @@ struct | x -> BatPrintf.fprintf f "%a" printXml x end +module GMapG (G: Lattice.S) (C: Printable.S) = +struct + module CVal = + struct + include Printable.Std (* To make it Groupable *) + include SetDomain.Make ( + struct + include C + let printXml f c = BatPrintf.fprintf f "%a" printXml c (* wrap in for HTML printing *) + end + ) + let name () = "contextsMap" + end + + module RangeVal = + struct + include SetDomain.Make ( + struct + include C (*TODO: sollte hier iwi ein tupel sein*) + let printXml f c = BatPrintf.fprintf f "%a" printXml c (* wrap in for HTML printing *) + end + ) + let name () = "contextsMap" + end + + module CMap = + struct + include MapDomain.MapBot (CVal) (RangeVal) + let name () = "contextsMap" + end + include Lattice.Lift2 (G) (CMap) (Printable.DefaultNames) + + let is_bot () = false + let is_top () = false + + (*let spec = function + | `Bot -> G.bot () + | `Lifted1 x -> x + | _ -> failwith "GVarG.spec" + let contexts = function + | `Bot -> CSet.bot () + | `Lifted2 x -> x + | _ -> failwith "GVarG.contexts" + let create_spec spec = `Lifted1 spec + let create_contexts contexts = `Lifted2 contexts + + let printXml f = function + | `Lifted1 x -> G.printXml f x + | `Lifted2 x -> BatPrintf.fprintf f "%a" CSet.printXml x + | x -> BatPrintf.fprintf f "%a" printXml x +*) +end + exception Deadcode diff --git a/src/framework/constraints.ml b/src/framework/constraints.ml index 740d1f85a9..e9c1b9b0a2 100644 --- a/src/framework/constraints.ml +++ b/src/framework/constraints.ml @@ -1343,7 +1343,7 @@ struct module EM = struct include MapDomain.MapBot (Basetype.CilExp) (Basetype.Bools) - let name () = "branches" + let name () = "bmodule Vranches" end module G = @@ -1692,6 +1692,70 @@ struct let event ctx e octx = S.event (conv ctx) e (conv octx) end +(** Add cycle detection in the function call graph to a analysis *) +module RecursionTermLifter (S: Spec) + : Spec with module D = S.D + and module G = S.G + and module C = S.C + and module G = GMapG (S.G) (S.C) += + +struct + module C = S.C + module P = S.P + module D = S.D + + (*global invariant + - fundec -> Map (S.C) (Set (fundec * S.C)) + So: g -> {c' -> f, c} + in case f, c --> g, c' *) + + (*module CVal = + struct + include C + include Printable.Std (* To make it Groupable *) + let printXml f c = BatPrintf.fprintf f "%a" printXml c (* wrap in for HTML printing *) + end + module M = MapDomain.MapBot (CVal) (CVal) +*) + module V = S.V + module G = S.G(*GMapG (S.G) (S.C)*) + (*struct + include Lattice.Prod (S.G) (M) + let printXml f (d,m) = BatPrintf.fprintf f "\n%a\n%a\n" S.G.printXml d M.printXml m + end*) + let name () = "RecursionTerm (" ^ S.name () ^ ")" + + type marshal = S.marshal + let init = S.init + let finalize = S.finalize (*TODO*) + + let startstate v = S.startstate v + let exitstate v = S.exitstate v + let morphstate = S.morphstate + + let context = S.context + + let query ctx = S.query (ctx) + let branch ctx = S.branch (ctx) + let assign ctx = S.assign (ctx) + let vdecl ctx = S.vdecl (ctx) + let enter ctx = S.enter (ctx) (*TODO*) + let paths_as_set ctx = S.paths_as_set (ctx) + let body ctx = S.body (ctx) + let return ctx = S.return (ctx) + let combine_env ctx = S.combine_env (ctx) + let combine_assign ctx = S.combine_assign (ctx) + let special ctx = S.special (ctx) + let threadenter ctx = S.threadenter (ctx) + let threadspawn ctx lv f args fctx = S.threadspawn (ctx) lv f args (fctx) + let sync ctx = S.sync (ctx) + let skip ctx = S.skip (ctx) + let asm ctx = S.asm (ctx) + let event ctx e octx = S.event (ctx) e (octx) +end + + module CompareGlobSys (SpecSys: SpecSys) = struct open SpecSys diff --git a/src/framework/control.ml b/src/framework/control.ml index 35cadfc12d..bd26fa7129 100644 --- a/src/framework/control.ml +++ b/src/framework/control.ml @@ -36,6 +36,7 @@ let spec_module: (module Spec) Lazy.t = lazy ( Also must be outside of deadcode, because deadcode splits (like mutex lock event) don't pass on tokens. *) |> lift (get_bool "ana.widen.tokens") (module WideningTokens.Lifter) |> lift true (module LongjmpLifter) + |> lift true (module RecursionTermLifter)(*TODO: should we really always evaluate it???*) ) in GobConfig.building_spec := false; ControlSpecC.control_spec_c := (module S1.C); From f4416fcfe35c1964c2064e45fefea06efd9f88eb Mon Sep 17 00:00:00 2001 From: Johanna Schinabeck Date: Sat, 3 Jun 2023 13:31:15 +0200 Subject: [PATCH 043/327] now its working :) --- src/framework/constraints.ml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/framework/constraints.ml b/src/framework/constraints.ml index e9c1b9b0a2..0586a87d3e 100644 --- a/src/framework/constraints.ml +++ b/src/framework/constraints.ml @@ -1697,7 +1697,7 @@ module RecursionTermLifter (S: Spec) : Spec with module D = S.D and module G = S.G and module C = S.C - and module G = GMapG (S.G) (S.C) + and module G = S.G = struct From 4eacdf0c6f82ba33a9bf9de924952ec3ed70c6e1 Mon Sep 17 00:00:00 2001 From: Johanna Schinabeck Date: Sat, 3 Jun 2023 13:34:02 +0200 Subject: [PATCH 044/327] added GMapG --- src/framework/analyses.ml | 53 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 53 insertions(+) diff --git a/src/framework/analyses.ml b/src/framework/analyses.ml index 1a3a4ebeb1..1d1972ac45 100644 --- a/src/framework/analyses.ml +++ b/src/framework/analyses.ml @@ -120,6 +120,59 @@ struct end +module GMapG (G: Lattice.S) (C: Printable.S) = +struct + module CVal = + struct + include Printable.Std (* To make it Groupable *) + include SetDomain.Make ( + struct + include C + let printXml f c = BatPrintf.fprintf f "%a" printXml c (* wrap in for HTML printing *) + end + ) + let name () = "contextsMap" + end + + module RangeVal = + struct + include SetDomain.Make ( + struct + include C (*TODO: sollte hier iwi ein tupel sein*) + let printXml f c = BatPrintf.fprintf f "%a" printXml c (* wrap in for HTML printing *) + end + ) + let name () = "contextsMap" + end + + module CMap = + struct + include MapDomain.MapBot (CVal) (RangeVal) + let name () = "contextsMap" + end + include Lattice.Lift2 (G) (CMap) (Printable.DefaultNames) + + let is_bot () = false + let is_top () = false + + (*let spec = function + | `Bot -> G.bot () + | `Lifted1 x -> x + | _ -> failwith "GVarG.spec" + let contexts = function + | `Bot -> CSet.bot () + | `Lifted2 x -> x + | _ -> failwith "GVarG.contexts" + let create_spec spec = `Lifted1 spec + let create_contexts contexts = `Lifted2 contexts + + let printXml f = function + | `Lifted1 x -> G.printXml f x + | `Lifted2 x -> BatPrintf.fprintf f "%a" CSet.printXml x + | x -> BatPrintf.fprintf f "%a" printXml x +*) +end + exception Deadcode (** [Dom (D)] produces D lifted where bottom means dead-code *) From 3d411ea7148a25c0bb4db60600f6630f12cf71d9 Mon Sep 17 00:00:00 2001 From: Johanna Schinabeck Date: Sat, 3 Jun 2023 13:35:32 +0200 Subject: [PATCH 045/327] added functor definition (is empty) --- src/framework/constraints.ml | 65 ++++++++++++++++++++++++++++++++++++ 1 file changed, 65 insertions(+) diff --git a/src/framework/constraints.ml b/src/framework/constraints.ml index 740d1f85a9..7a4a6037b0 100644 --- a/src/framework/constraints.ml +++ b/src/framework/constraints.ml @@ -1692,6 +1692,71 @@ struct let event ctx e octx = S.event (conv ctx) e (conv octx) end + +(** Add cycle detection in the function call graph to a analysis *) +module RecursionTermLifter (S: Spec) + : Spec with module D = S.D + and module G = S.G + and module C = S.C + and module G = S.G += + +struct + module C = S.C + module P = S.P + module D = S.D + + (*global invariant + - fundec -> Map (S.C) (Set (fundec * S.C)) + So: g -> {c' -> f, c} + in case f, c --> g, c' *) + + (*module CVal = + struct + include C + include Printable.Std (* To make it Groupable *) + let printXml f c = BatPrintf.fprintf f "%a" printXml c (* wrap in for HTML printing *) + end + module M = MapDomain.MapBot (CVal) (CVal) +*) + module V = S.V + module G = S.G(*GMapG (S.G) (S.C)*) + (*struct + include Lattice.Prod (S.G) (M) + let printXml f (d,m) = BatPrintf.fprintf f "\n%a\n%a\n" S.G.printXml d M.printXml m + end*) + let name () = "RecursionTerm (" ^ S.name () ^ ")" + + type marshal = S.marshal + let init = S.init + let finalize = S.finalize (*TODO*) + + let startstate v = S.startstate v + let exitstate v = S.exitstate v + let morphstate = S.morphstate + + let context = S.context + + let query ctx = S.query (ctx) + let branch ctx = S.branch (ctx) + let assign ctx = S.assign (ctx) + let vdecl ctx = S.vdecl (ctx) + let enter ctx = S.enter (ctx) (*TODO*) + let paths_as_set ctx = S.paths_as_set (ctx) + let body ctx = S.body (ctx) + let return ctx = S.return (ctx) + let combine_env ctx = S.combine_env (ctx) + let combine_assign ctx = S.combine_assign (ctx) + let special ctx = S.special (ctx) + let threadenter ctx = S.threadenter (ctx) + let threadspawn ctx lv f args fctx = S.threadspawn (ctx) lv f args (fctx) + let sync ctx = S.sync (ctx) + let skip ctx = S.skip (ctx) + let asm ctx = S.asm (ctx) + let event ctx e octx = S.event (ctx) e (octx) +end + + module CompareGlobSys (SpecSys: SpecSys) = struct open SpecSys From 99e85b06025eea7ca61b71c224d1d7d774ace458 Mon Sep 17 00:00:00 2001 From: Johanna Schinabeck Date: Sat, 3 Jun 2023 13:36:14 +0200 Subject: [PATCH 046/327] added funtctor --- src/framework/control.ml | 1 + 1 file changed, 1 insertion(+) diff --git a/src/framework/control.ml b/src/framework/control.ml index 35cadfc12d..bd26fa7129 100644 --- a/src/framework/control.ml +++ b/src/framework/control.ml @@ -36,6 +36,7 @@ let spec_module: (module Spec) Lazy.t = lazy ( Also must be outside of deadcode, because deadcode splits (like mutex lock event) don't pass on tokens. *) |> lift (get_bool "ana.widen.tokens") (module WideningTokens.Lifter) |> lift true (module LongjmpLifter) + |> lift true (module RecursionTermLifter)(*TODO: should we really always evaluate it???*) ) in GobConfig.building_spec := false; ControlSpecC.control_spec_c := (module S1.C); From 9f4d19ee482cfffd225013d24d1e3e83186464e0 Mon Sep 17 00:00:00 2001 From: Johanna Schinabeck Date: Sat, 3 Jun 2023 14:03:53 +0200 Subject: [PATCH 047/327] reverted the changes, wrong branch :) --- src/framework/analyses.ml | 54 ------------------------------ src/framework/constraints.ml | 64 ------------------------------------ src/framework/control.ml | 3 +- 3 files changed, 1 insertion(+), 120 deletions(-) diff --git a/src/framework/analyses.ml b/src/framework/analyses.ml index c8d3873085..7ac18f56f7 100644 --- a/src/framework/analyses.ml +++ b/src/framework/analyses.ml @@ -119,60 +119,6 @@ struct | x -> BatPrintf.fprintf f "%a" printXml x end -module GMapG (G: Lattice.S) (C: Printable.S) = -struct - module CVal = - struct - include Printable.Std (* To make it Groupable *) - include SetDomain.Make ( - struct - include C - let printXml f c = BatPrintf.fprintf f "%a" printXml c (* wrap in for HTML printing *) - end - ) - let name () = "contextsMap" - end - - module RangeVal = - struct - include SetDomain.Make ( - struct - include C (*TODO: sollte hier iwi ein tupel sein*) - let printXml f c = BatPrintf.fprintf f "%a" printXml c (* wrap in for HTML printing *) - end - ) - let name () = "contextsMap" - end - - module CMap = - struct - include MapDomain.MapBot (CVal) (RangeVal) - let name () = "contextsMap" - end - include Lattice.Lift2 (G) (CMap) (Printable.DefaultNames) - - let is_bot () = false - let is_top () = false - - (*let spec = function - | `Bot -> G.bot () - | `Lifted1 x -> x - | _ -> failwith "GVarG.spec" - let contexts = function - | `Bot -> CSet.bot () - | `Lifted2 x -> x - | _ -> failwith "GVarG.contexts" - let create_spec spec = `Lifted1 spec - let create_contexts contexts = `Lifted2 contexts - - let printXml f = function - | `Lifted1 x -> G.printXml f x - | `Lifted2 x -> BatPrintf.fprintf f "%a" CSet.printXml x - | x -> BatPrintf.fprintf f "%a" printXml x -*) -end - - exception Deadcode (** [Dom (D)] produces D lifted where bottom means dead-code *) diff --git a/src/framework/constraints.ml b/src/framework/constraints.ml index 0586a87d3e..d8b186160b 100644 --- a/src/framework/constraints.ml +++ b/src/framework/constraints.ml @@ -1692,70 +1692,6 @@ struct let event ctx e octx = S.event (conv ctx) e (conv octx) end -(** Add cycle detection in the function call graph to a analysis *) -module RecursionTermLifter (S: Spec) - : Spec with module D = S.D - and module G = S.G - and module C = S.C - and module G = S.G -= - -struct - module C = S.C - module P = S.P - module D = S.D - - (*global invariant - - fundec -> Map (S.C) (Set (fundec * S.C)) - So: g -> {c' -> f, c} - in case f, c --> g, c' *) - - (*module CVal = - struct - include C - include Printable.Std (* To make it Groupable *) - let printXml f c = BatPrintf.fprintf f "%a" printXml c (* wrap in for HTML printing *) - end - module M = MapDomain.MapBot (CVal) (CVal) -*) - module V = S.V - module G = S.G(*GMapG (S.G) (S.C)*) - (*struct - include Lattice.Prod (S.G) (M) - let printXml f (d,m) = BatPrintf.fprintf f "\n%a\n%a\n" S.G.printXml d M.printXml m - end*) - let name () = "RecursionTerm (" ^ S.name () ^ ")" - - type marshal = S.marshal - let init = S.init - let finalize = S.finalize (*TODO*) - - let startstate v = S.startstate v - let exitstate v = S.exitstate v - let morphstate = S.morphstate - - let context = S.context - - let query ctx = S.query (ctx) - let branch ctx = S.branch (ctx) - let assign ctx = S.assign (ctx) - let vdecl ctx = S.vdecl (ctx) - let enter ctx = S.enter (ctx) (*TODO*) - let paths_as_set ctx = S.paths_as_set (ctx) - let body ctx = S.body (ctx) - let return ctx = S.return (ctx) - let combine_env ctx = S.combine_env (ctx) - let combine_assign ctx = S.combine_assign (ctx) - let special ctx = S.special (ctx) - let threadenter ctx = S.threadenter (ctx) - let threadspawn ctx lv f args fctx = S.threadspawn (ctx) lv f args (fctx) - let sync ctx = S.sync (ctx) - let skip ctx = S.skip (ctx) - let asm ctx = S.asm (ctx) - let event ctx e octx = S.event (ctx) e (octx) -end - - module CompareGlobSys (SpecSys: SpecSys) = struct open SpecSys diff --git a/src/framework/control.ml b/src/framework/control.ml index bd26fa7129..7e993733cd 100644 --- a/src/framework/control.ml +++ b/src/framework/control.ml @@ -36,8 +36,7 @@ let spec_module: (module Spec) Lazy.t = lazy ( Also must be outside of deadcode, because deadcode splits (like mutex lock event) don't pass on tokens. *) |> lift (get_bool "ana.widen.tokens") (module WideningTokens.Lifter) |> lift true (module LongjmpLifter) - |> lift true (module RecursionTermLifter)(*TODO: should we really always evaluate it???*) - ) in + ) in GobConfig.building_spec := false; ControlSpecC.control_spec_c := (module S1.C); (module S1) From d77b877e52ba40fd73ba5d2fd17069c9f3ab81c2 Mon Sep 17 00:00:00 2001 From: Johanna Schinabeck Date: Sat, 3 Jun 2023 14:05:00 +0200 Subject: [PATCH 048/327] fixed a typo --- src/framework/constraints.ml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/framework/constraints.ml b/src/framework/constraints.ml index d8b186160b..740d1f85a9 100644 --- a/src/framework/constraints.ml +++ b/src/framework/constraints.ml @@ -1343,7 +1343,7 @@ struct module EM = struct include MapDomain.MapBot (Basetype.CilExp) (Basetype.Bools) - let name () = "bmodule Vranches" + let name () = "branches" end module G = From 84cfb5bc5b35f57d1685bf47a803f9fee96d4a9c Mon Sep 17 00:00:00 2001 From: Johanna Schinabeck Date: Sun, 4 Jun 2023 16:00:38 +0200 Subject: [PATCH 049/327] first tests for constraints --- output.txt | 204 +++++++++++++++++++++----------- src/framework/constraints.ml | 218 ++++++++++++++++++++++++++++++++++- 2 files changed, 348 insertions(+), 74 deletions(-) diff --git a/output.txt b/output.txt index d3b021a1f3..07c71d61b9 100644 --- a/output.txt +++ b/output.txt @@ -1096,31 +1096,35 @@ void example1(void) { int a[5] ; int i ; - int term27_5 = 0; + int term27_5-file_01-simple-cases ; { #line 25 i = 0; { +#line 27 + term27_5-file_01-simple-cases = 0; { #line 27 while (1) { -#line 27 - term27_5 ++; while_continue: /* CIL Label */ ; #line 27 if (! (i < 5)) { #line 27 goto while_break; } +#line 27 + term27_5-file_01-simple-cases ++; #line 28 a[i] = i; #line 29 i ++; } - } while_break: /* CIL Label */ ; } +#line 27 + term_exit- = term27_5-file_01-simple-cases; + } #line 32 __goblint_check(a[0] == 0); #line 33 @@ -1134,31 +1138,35 @@ void example2(void) { int a[5] ; int i ; - int term42_5 = 0; + int term42_5-file_01-simple-cases ; { #line 40 i = 0; { +#line 42 + term42_5-file_01-simple-cases = 0; { #line 42 while (1) { -#line 42 - term42_5 ++; while_continue: /* CIL Label */ ; #line 43 a[i] = i; #line 44 i ++; +#line 42 + term42_5-file_01-simple-cases ++; #line 42 if (! (i <= 5)) { #line 42 goto while_break; } } - } while_break: /* CIL Label */ ; } +#line 42 + term_exit- = term42_5-file_01-simple-cases; + } #line 47 __goblint_check(a[0] == 0); #line 48 @@ -1172,31 +1180,35 @@ void example3(void) { int a[10] ; int i ; - int term57_5 = 0; + int term57_5-file_01-simple-cases ; { #line 55 i = 0; { +#line 57 + term57_5-file_01-simple-cases = 0; { #line 57 while (1) { -#line 57 - term57_5 ++; while_continue: /* CIL Label */ ; #line 57 if (! (i < 5)) { #line 57 goto while_break; } +#line 57 + term57_5-file_01-simple-cases ++; #line 58 a[i] = i; #line 59 i ++; } - } while_break: /* CIL Label */ ; } +#line 57 + term_exit- = term57_5-file_01-simple-cases; + } #line 62 __goblint_check(a[0] == 0); #line 63 @@ -1213,7 +1225,7 @@ void example4(void) int a[10] ; int i ; int first_iteration ; - int term74_5 = 0; + int term74_5-file_01-simple-cases ; { #line 71 @@ -1221,17 +1233,19 @@ void example4(void) #line 72 first_iteration = 1; { +#line 74 + term74_5-file_01-simple-cases = 0; { #line 74 while (1) { -#line 74 - term74_5 ++; while_continue: /* CIL Label */ ; #line 74 if (! (i < 10)) { #line 74 goto while_break; } +#line 74 + term74_5-file_01-simple-cases ++; #line 75 if (first_iteration == 1) { #line 75 @@ -1249,9 +1263,11 @@ void example4(void) #line 79 i ++; } - } while_break: /* CIL Label */ ; } +#line 74 + term_exit- = term74_5-file_01-simple-cases; + } #line 82 __goblint_check(a[0] == 0); #line 83 @@ -1266,7 +1282,7 @@ void example5(void) int a[4] ; int i ; int top ; - int term95_5 = 0; + int term95_5-file_01-simple-cases ; { #line 92 @@ -1274,17 +1290,19 @@ void example5(void) #line 93 top = 0; { +#line 95 + term95_5-file_01-simple-cases = 0; { #line 95 while (1) { -#line 95 - term95_5 ++; while_continue: /* CIL Label */ ; #line 95 if (! (i < 4)) { #line 95 goto while_break; } +#line 95 + term95_5-file_01-simple-cases ++; #line 96 a[i] = 0; #line 97 @@ -1300,9 +1318,11 @@ void example5(void) #line 104 i ++; } - } while_break: /* CIL Label */ ; } +#line 95 + term_exit- = term95_5-file_01-simple-cases; + } #line 107 __goblint_check(a[0] == 0); #line 108 @@ -1319,7 +1339,7 @@ void example6(void) int a[5] ; int i ; int top ; - int term119_5 = 0; + int term119_5-file_01-simple-cases ; { #line 116 @@ -1327,17 +1347,19 @@ void example6(void) #line 117 top = 0; { +#line 119 + term119_5-file_01-simple-cases = 0; { #line 119 while (1) { -#line 119 - term119_5 ++; while_continue: /* CIL Label */ ; #line 119 if (! (i < 3)) { #line 119 goto while_break; } +#line 119 + term119_5-file_01-simple-cases ++; #line 120 a[i] = 0; #line 121 @@ -1345,9 +1367,11 @@ void example6(void) #line 122 i ++; } - } while_break: /* CIL Label */ ; } +#line 119 + term_exit- = term119_5-file_01-simple-cases; + } #line 125 __goblint_check(a[0] == 0); #line 126 @@ -1380,20 +1404,22 @@ void example7(void) int a[10] ; int i ; int tmp ; - int term143_2 = 0; + int term143_2-file_01-simple-cases ; { #line 142 i = 0; { +#line 143 + term143_2-file_01-simple-cases = 0; { #line 143 while (1) { -#line 143 - term143_2 ++; while_continue: /* CIL Label */ ; #line 143 tmp = update(i); +#line 143 + term143_2-file_01-simple-cases ++; #line 143 if (! tmp) { #line 143 @@ -1404,9 +1430,11 @@ void example7(void) #line 145 i ++; } - } while_break: /* CIL Label */ ; } +#line 143 + term_exit- = term143_2-file_01-simple-cases; + } #line 147 __goblint_check(a[0] == 0); #line 148 @@ -1422,8 +1450,8 @@ void example8(void) int b[5] ; int i ; int j ; - int term160_9 = 0; - int term157_2 = 0; + int term160_9-file_01-simple-cases ; + int term157_2-file_01-simple-cases ; { #line 155 @@ -1439,47 +1467,55 @@ void example8(void) #line 156 i = 0; { +#line 157 + term157_2-file_01-simple-cases = 0; { #line 157 while (1) { -#line 157 - term157_2 ++; while_continue: /* CIL Label */ ; #line 157 if (! (i < 5)) { #line 157 goto while_break; } +#line 157 + term157_2-file_01-simple-cases ++; #line 158 a[i] = i; #line 159 j = 0; { +#line 160 + term160_9-file_01-simple-cases = 0; { #line 160 while (1) { -#line 160 - term160_9 ++; while_continue___0: /* CIL Label */ ; #line 160 if (! (j < 5)) { #line 160 goto while_break___0; } +#line 160 + term160_9-file_01-simple-cases ++; #line 161 b[j] += a[i]; #line 162 j ++; } - } while_break___0: /* CIL Label */ ; } +#line 160 + term_exit- = term160_9-file_01-simple-cases; + } #line 164 i ++; } - } while_break: /* CIL Label */ ; } +#line 157 + term_exit- = term157_2-file_01-simple-cases; + } #line 166 return; } @@ -1489,23 +1525,25 @@ void example9(void) { int a[5] ; int i ; - int term174_2 = 0; + int term174_2-file_01-simple-cases ; { #line 173 i = 0; { +#line 174 + term174_2-file_01-simple-cases = 0; { #line 174 while (1) { -#line 174 - term174_2 ++; while_continue: /* CIL Label */ ; #line 174 if (! 1) { #line 174 goto while_break; } +#line 174 + term174_2-file_01-simple-cases ++; #line 175 a[i] = i; #line 176 @@ -1516,9 +1554,11 @@ void example9(void) goto while_break; } } - } while_break: /* CIL Label */ ; } +#line 174 + term_exit- = term174_2-file_01-simple-cases; + } #line 179 return; } @@ -1528,23 +1568,25 @@ void example10(void) { int a[5] ; int i ; - int term187_2 = 0; + int term187_2-file_01-simple-cases ; { #line 186 i = 0; { +#line 187 + term187_2-file_01-simple-cases = 0; { #line 187 while (1) { -#line 187 - term187_2 ++; while_continue: /* CIL Label */ ; #line 187 if (! (i < 5)) { #line 187 goto while_break; } +#line 187 + term187_2-file_01-simple-cases ++; #line 188 if (i == 3) { #line 189 @@ -1557,9 +1599,11 @@ void example10(void) #line 193 i ++; } - } while_break: /* CIL Label */ ; } +#line 187 + term_exit- = term187_2-file_01-simple-cases; + } #line 195 return; } @@ -1990,99 +2034,113 @@ void qsort(void *ptr , size_t count , size_t size , int (*comp)(void const * , char *a ; char *b ; char c ; - int term10_5 = 0; - int term9_3 = 0; - int term21_9 = 0; - int term17_5 = 0; - int term16_3 = 0; + int term10_5-file_stdlib ; + int term9_3-file_stdlib ; + int term21_9-file_stdlib ; + int term17_5-file_stdlib ; + int term16_3-file_stdlib ; { #line 9 i = (size_t )0; { +#line 9 + term9_3-file_stdlib = 0; { #line 9 while (1) { -#line 9 - term9_3 ++; while_continue: /* CIL Label */ ; #line 9 if (! (i < count)) { #line 9 goto while_break; } +#line 9 + term9_3-file_stdlib ++; #line 10 j = (size_t )0; { +#line 10 + term10_5-file_stdlib = 0; { #line 10 while (1) { -#line 10 - term10_5 ++; while_continue___0: /* CIL Label */ ; #line 10 if (! (j < count)) { #line 10 goto while_break___0; } +#line 10 + term10_5-file_stdlib ++; #line 11 (*comp)((void const *)(ptr + i * size), (void const *)(ptr + j * size)); #line 10 j ++; } - } while_break___0: /* CIL Label */ ; } +#line 10 + term_exit- = term10_5-file_stdlib; + } #line 9 i ++; } - } while_break: /* CIL Label */ ; } +#line 9 + term_exit- = term9_3-file_stdlib; + } #line 16 i___0 = (size_t )0; { +#line 16 + term16_3-file_stdlib = 0; { #line 16 while (1) { -#line 16 - term16_3 ++; while_continue___1: /* CIL Label */ ; #line 16 if (! (i___0 < count)) { #line 16 goto while_break___1; } +#line 16 + term16_3-file_stdlib ++; #line 17 j___0 = (size_t )0; { +#line 17 + term17_5-file_stdlib = 0; { #line 17 while (1) { -#line 17 - term17_5 ++; while_continue___2: /* CIL Label */ ; #line 17 if (! (j___0 < count)) { #line 17 goto while_break___2; } +#line 17 + term17_5-file_stdlib ++; #line 19 if (r) { #line 21 k = (size_t )0; { +#line 21 + term21_9-file_stdlib = 0; { #line 21 while (1) { -#line 21 - term21_9 ++; while_continue___3: /* CIL Label */ ; #line 21 if (! (k < size)) { #line 21 goto while_break___3; } +#line 21 + term21_9-file_stdlib ++; #line 22 a = (char *)((ptr + i___0 * size) + k); #line 23 @@ -2096,22 +2154,28 @@ void qsort(void *ptr , size_t count , size_t size , int (*comp)(void const * , #line 21 k ++; } - } while_break___3: /* CIL Label */ ; } +#line 21 + term_exit- = term21_9-file_stdlib; + } } #line 17 j___0 ++; } - } while_break___2: /* CIL Label */ ; } +#line 17 + term_exit- = term17_5-file_stdlib; + } #line 16 i___0 ++; } - } while_break___1: /* CIL Label */ ; } +#line 16 + term_exit- = term16_3-file_stdlib; + } #line 33 return; } @@ -2129,23 +2193,25 @@ void *bsearch(void const *key , void const *ptr , size_t count , size_t size size_t i ; void const *a ; int tmp ; - int term40_3 = 0; + int term40_3-file_stdlib ; { #line 40 i = (size_t )0; { +#line 40 + term40_3-file_stdlib = 0; { #line 40 while (1) { -#line 40 - term40_3 ++; while_continue: /* CIL Label */ ; #line 40 if (! (i < count)) { #line 40 goto while_break; } +#line 40 + term40_3-file_stdlib ++; #line 41 a = ptr + i * size; #line 42 @@ -2158,9 +2224,11 @@ void *bsearch(void const *key , void const *ptr , size_t count , size_t size #line 40 i ++; } - } while_break: /* CIL Label */ ; } +#line 40 + term_exit- = term40_3-file_stdlib; + } #line 47 return ((void *)0); } diff --git a/src/framework/constraints.ml b/src/framework/constraints.ml index 7a4a6037b0..0177f3ea85 100644 --- a/src/framework/constraints.ml +++ b/src/framework/constraints.ml @@ -6,6 +6,7 @@ open GoblintCil open MyCFG open Analyses open GobConfig +include Printf module M = Messages @@ -562,7 +563,7 @@ struct let side_context sideg f c = if !AnalysisState.postsolving then sideg (GVar.contexts f) (G.create_contexts (G.CSet.singleton c)) - + let common_ctx var edge prev_node pval (getl:lv -> ld) sidel getg sideg : (D.t, S.G.t, S.C.t, S.V.t) ctx * D.t list ref * (lval option * varinfo * exp list * D.t) list ref = let r = ref [] in let spawns = ref [] in @@ -1692,6 +1693,194 @@ struct let event ctx e octx = S.event (conv ctx) e (conv octx) end +(** +module RecursionTermLifter (S: Spec): Spec = +struct + include S + + let name () = "RecursionTerm (" ^ S.name () ^ ")" + + (* global invariant: + - fundec -> (S.C -> Set (fundec * S.C)) -- used to detect loops in the call graph *) + + module V = + struct + include Printable.Option (S.V) (struct let name = "RecursionTerm" end) + let name () = "RecursionTerm" + let is_write_only t = true + let s x = `Left x + end + + module C = + struct + include S.C + include Printable.Std (* To make it Groupable *) + let printXml f c = BatPrintf.fprintf f "%a" printXml c (* wrap in for HTML printing *) + + end + + (*module Tuple = struct + type t = (fundec, S.C) [@@deriving eq, ord, hash] + let equal t1 t2 = false + let compare t1 t3 = 0 + let show t = "t" + let pretty () (x: t) = match x with _ -> . + + let printXml f (d,m) = BatPrintf.fprintf f "%a" printXml c (* wrap in for HTML printing *) + + let name u = "recursion" + let to_yojson (x: t) = match x with _ -> . + + let tag t = 1 + let arbitrary () = failwith "Printable.Empty.arbitrary" + + let relift t = t + end +*) + module Tupel (S:Spec) = + struct + include Printable.Std + type t = fundec * S.C.t [@@deriving eq, ord, hash] + + let equal_fundec = false + let hash_fundec = false + + let name () = "recursion" + + let pretty () (x: t) = match x with _ -> . + + let relift (f, c) = + (f, c) + + let equal t1 t2 = false + let compare t1 t3 = 0 + let show t = "t" + + let printXml f c = BatPrintf.fprintf f "%a" c (* wrap in for HTML printing *) + + let name u = "recursion" + let to_yojson (x: t) = match x with _ -> . + + let tag t = 1 + let arbitrary () = failwith "Printable.Empty.arbitrary" + end + + module T = + struct + include SetDomain.Make (Tupel (S)) + end + + module EM = + struct + include MapDomain.MapBot (C) (T) + let name () = "recursions" + end + + module G = + struct + include Lattice.Lift2 (S.G) (EM) (Printable.DefaultNames) + let name () = "recursionTerm" + let node = function + | `Bot -> EM.bot () + | `Lifted2 x -> x + | _ -> failwith "DeadBranchLifter.node" + let create_s s = `Lifted1 s + let create_node node = `Lifted2 node + + let printXml f = function + | `Lifted1 x -> S.G.printXml f x + | `Lifted2 x -> BatPrintf.fprintf f "%a" EM.printXml x + | x -> BatPrintf.fprintf f "%a" printXml x + end + + let conv (ctx: (_, G.t, _, V.t) ctx): (_, S.G.t, _, S.V.t) ctx = + { ctx with + global = (fun v -> G.s (ctx.global (V.s v))); + sideg = (fun v g -> ctx.sideg (V.s v) (G.create_s g)); + } + + let query ctx (type a) (q: a Queries.t): a Queries.result = + match q with + | WarnGlobal g -> + let g: V.t = Obj.obj g in + begin match g with + | `Left g -> + S.query (conv ctx) (WarnGlobal (Obj.repr g)) + | `Right g -> + let em = G.node (ctx.global (V.node g)) in + EM.iter (fun exp tv -> + match tv with + | `Lifted tv -> + let loc = Node.location g in (* TODO: looking up location now doesn't work nicely with incremental *) + let cilinserted = if loc.synthetic then "(possibly inserted by CIL) " else "" in + M.warn ~loc:(Node g) ~tags:[CWE (if tv then 571 else 570)] ~category:Deadcode "condition '%a' %sis always %B" d_exp exp cilinserted tv + | `Bot when not (CilType.Exp.equal exp one) -> (* all branches dead *) + M.error ~loc:(Node g) ~category:Analyzer ~tags:[Category Unsound] "both branches over condition '%a' are dead" d_exp exp + | `Bot (* all branches dead, fine at our inserted Neg(1)-s because no Pos(1) *) + | `Top -> (* may be both true and false *) + () + ) em; + end + | InvariantGlobal g -> + let g: V.t = Obj.obj g in + begin match g with + | `Left g -> + S.query (conv ctx) (InvariantGlobal (Obj.repr g)) + | `Right g -> + Queries.Result.top q + end + | IterSysVars (vq, vf) -> + (* vars for S *) + let vf' x = vf (Obj.repr (V.s (Obj.obj x))) in + S.query (conv ctx) (IterSysVars (vq, vf')); + + (* node vars for dead branches *) + begin match vq with + | Node {node; _} -> + vf (Obj.repr (V.node node)) + | _ -> + () + end + | _ -> + S.query (conv ctx) q + + + let branch ctx = S.branch (conv ctx) + + let branch ctx exp tv = + if !AnalysisState.postsolving then ( + try + let r = branch ctx exp tv in + (* branch is live *) + ctx.sideg (V.node ctx.prev_node) (G.create_node (EM.singleton exp (`Lifted tv))); (* record expression with reached tv *) + r + with Deadcode -> + (* branch is dead *) + ctx.sideg (V.node ctx.prev_node) (G.create_node (EM.singleton exp `Bot)); (* record expression without reached tv *) + raise Deadcode + ) + else ( + ctx.sideg (V.node ctx.prev_node) (G.create_node (EM.bot ())); (* create global variable during solving, to allow postsolving leq hack to pass verify *) + branch ctx exp tv + ) + + let assign ctx = S.assign (conv ctx) + let vdecl ctx = S.vdecl (conv ctx) + let enter ctx = S.enter (conv ctx) + let paths_as_set ctx = S.paths_as_set (conv ctx) + let body ctx = S.body (conv ctx) + let return ctx = S.return (conv ctx) + let combine_env ctx = S.combine_env (conv ctx) + let combine_assign ctx = S.combine_assign (conv ctx) + let special ctx = S.special (conv ctx) + let threadenter ctx = S.threadenter (conv ctx) + let threadspawn ctx lv f args fctx = S.threadspawn (conv ctx) lv f args (conv fctx) + let sync ctx = S.sync (conv ctx) + let skip ctx = S.skip (conv ctx) + let asm ctx = S.asm (conv ctx) + let event ctx e octx = S.event (conv ctx) e (conv octx) +end + (** Add cycle detection in the function call graph to a analysis *) module RecursionTermLifter (S: Spec) @@ -1711,7 +1900,10 @@ struct So: g -> {c' -> f, c} in case f, c --> g, c' *) - (*module CVal = + (* + + + module CVal = struct include C include Printable.Std (* To make it Groupable *) @@ -1719,8 +1911,15 @@ struct end module M = MapDomain.MapBot (CVal) (CVal) *) - module V = S.V - module G = S.G(*GMapG (S.G) (S.C)*) + module V = (*TODO: do I need to change V???*) + struct + include Printable.Option (S.V) (struct let name = "RecursionTerm" end) + let name () = "RecursionTerm" + let is_write_only t = true + let s x = `Left x + end + module G = S.G + (*GMapG (S.G) (S.C)*) (*struct include Lattice.Prod (S.G) (M) let printXml f (d,m) = BatPrintf.fprintf f "\n%a\n%a\n" S.G.printXml d M.printXml m @@ -1737,11 +1936,18 @@ struct let context = S.context + (**let side_context sideg f c = + if !AnalysisState.postsolving then + sideg (f) (G.create_contexts (G.CSet.singleton c))*) + let query ctx = S.query (ctx) let branch ctx = S.branch (ctx) let assign ctx = S.assign (ctx) let vdecl ctx = S.vdecl (ctx) - let enter ctx = S.enter (ctx) (*TODO*) + let enter ctx = + if !AnalysisState.postsolving then + printf "hallo hallo"; + S.enter (ctx) (*TODO*) let paths_as_set ctx = S.paths_as_set (ctx) let body ctx = S.body (ctx) let return ctx = S.return (ctx) @@ -1755,7 +1961,7 @@ struct let asm ctx = S.asm (ctx) let event ctx e octx = S.event (ctx) e (octx) end - +*) module CompareGlobSys (SpecSys: SpecSys) = struct From 936e7a76bdfb7b6607d5a721fef727e6c24bf4a1 Mon Sep 17 00:00:00 2001 From: Thomas Lagemann Date: Mon, 5 Jun 2023 16:04:58 +0200 Subject: [PATCH 050/327] Loop termination tests extended --- .../09-complex-for-loop-terminating.c | 2 +- .../10-complex-loop-terminating.c | 2 +- .../15-complex-loop-combination-terminating.c | 6 ++-- .../80-termination/17-goto-terminating.c | 18 +++++++++++ .../80-termination/18-goto-nonterminating.c | 15 +++++++++ .../80-termination/19-rand-terminating.c | 31 +++++++++++++++++++ .../80-termination/20-rand-nonterminating.c | 31 +++++++++++++++++++ 7 files changed, 100 insertions(+), 5 deletions(-) create mode 100644 tests/regression/80-termination/17-goto-terminating.c create mode 100644 tests/regression/80-termination/18-goto-nonterminating.c create mode 100644 tests/regression/80-termination/19-rand-terminating.c create mode 100644 tests/regression/80-termination/20-rand-nonterminating.c diff --git a/tests/regression/80-termination/09-complex-for-loop-terminating.c b/tests/regression/80-termination/09-complex-for-loop-terminating.c index ed28fa9b43..508b31500c 100644 --- a/tests/regression/80-termination/09-complex-for-loop-terminating.c +++ b/tests/regression/80-termination/09-complex-for-loop-terminating.c @@ -1,4 +1,4 @@ -// PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra +// PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval #include int main() diff --git a/tests/regression/80-termination/10-complex-loop-terminating.c b/tests/regression/80-termination/10-complex-loop-terminating.c index 3a19f17bee..9d5cd4b928 100644 --- a/tests/regression/80-termination/10-complex-loop-terminating.c +++ b/tests/regression/80-termination/10-complex-loop-terminating.c @@ -1,4 +1,4 @@ -// PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra +// PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval #include int main() diff --git a/tests/regression/80-termination/15-complex-loop-combination-terminating.c b/tests/regression/80-termination/15-complex-loop-combination-terminating.c index 54f8cd97c8..1ea228ae55 100644 --- a/tests/regression/80-termination/15-complex-loop-combination-terminating.c +++ b/tests/regression/80-termination/15-complex-loop-combination-terminating.c @@ -1,4 +1,4 @@ -// PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra +// PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval #include int main() @@ -130,7 +130,7 @@ int main() } } - /* // Loop with a label and goto statement + // Loop with a label and goto statement int w = 1; start: if (w <= 5) @@ -138,7 +138,7 @@ int main() printf("Loop with Label and Goto: %d\n", w); w++; goto start; // TERM - } */ + } return 0; } diff --git a/tests/regression/80-termination/17-goto-terminating.c b/tests/regression/80-termination/17-goto-terminating.c new file mode 100644 index 0000000000..10aa729837 --- /dev/null +++ b/tests/regression/80-termination/17-goto-terminating.c @@ -0,0 +1,18 @@ +// PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval +#include + +int main() +{ + int num = 1; + +loop: // TERM + printf("Current number: %d\n", num); + num++; + + if (num <= 10) + { + goto loop; + } + + return 0; +} diff --git a/tests/regression/80-termination/18-goto-nonterminating.c b/tests/regression/80-termination/18-goto-nonterminating.c new file mode 100644 index 0000000000..dbb7a3df59 --- /dev/null +++ b/tests/regression/80-termination/18-goto-nonterminating.c @@ -0,0 +1,15 @@ +// PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval +#include + +int main() +{ + int num = 1; + +loop: // NOTERM + printf("Current number: %d\n", num); + num++; + + goto loop; + + return 0; +} diff --git a/tests/regression/80-termination/19-rand-terminating.c b/tests/regression/80-termination/19-rand-terminating.c new file mode 100644 index 0000000000..1d226f0df2 --- /dev/null +++ b/tests/regression/80-termination/19-rand-terminating.c @@ -0,0 +1,31 @@ +// PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval +#include +#include +#include + +int main() +{ + // Seed the random number generator + srand(time(NULL)); + + if (rand()) + { + // Loop inside the if part + for (int i = 1; i <= 5; i++) // TERM + { + printf("Loop inside if part: %d\n", i); + } + } + else + { + // Loop inside the else part + int j = 1; + while (j <= 5) // TERM + { + printf("Loop inside else part: %d\n", j); + j++; + } + } + + return 0; +} diff --git a/tests/regression/80-termination/20-rand-nonterminating.c b/tests/regression/80-termination/20-rand-nonterminating.c new file mode 100644 index 0000000000..6639e5bc76 --- /dev/null +++ b/tests/regression/80-termination/20-rand-nonterminating.c @@ -0,0 +1,31 @@ +// PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval +#include +#include +#include + +int main() +{ + // Seed the random number generator + srand(time(NULL)); + + if (rand()) + { + // Loop inside the if part + for (int i = 1; i <= 0; i++) // NOTERM + { + printf("Loop inside if part: %d\n", i); + } + } + else + { + // Loop inside the else part + int j = 1; + while (j < 5) // NOTERM + { + printf("Loop inside else part: %d\n", j); + j++; + } + } + + return 0; +} From 3818086469416a606ee38cde87324bd1d2ee2535 Mon Sep 17 00:00:00 2001 From: Thomas Lagemann Date: Thu, 1 Jun 2023 05:01:09 +0200 Subject: [PATCH 051/327] Tests for loop termination --- scripts/update_suite.rb | 6 + .../01-simple-loop-terminating.c | 15 ++ .../02-simple-loop-nonterminating.c | 12 ++ .../03-nested-loop-terminating.c | 27 ++++ .../04-nested-loop-nonterminating.c | 23 +++ .../80-termination/05-for-loop-terminating.c | 14 ++ .../06-for-loop-nonterminating.c | 10 ++ .../07-nested-for-loop-terminating.c | 20 +++ .../08-nested-for-loop-nonterminating.c | 19 +++ .../09-complex-for-loop-terminating.c | 107 +++++++++++++ .../10-complex-loop-terminating.c | 135 ++++++++++++++++ .../80-termination/11-loopless-termination.c | 7 + .../12-do-while-instant-terminating.c | 15 ++ .../80-termination/13-do-while-terminating.c | 16 ++ .../14-do-while-nonterminating.c | 16 ++ .../15-complex-loop-combination-terminating.c | 144 ++++++++++++++++++ ...16-nested-loop-nontrivial-nonterminating.c | 23 +++ 17 files changed, 609 insertions(+) create mode 100644 tests/regression/80-termination/01-simple-loop-terminating.c create mode 100644 tests/regression/80-termination/02-simple-loop-nonterminating.c create mode 100644 tests/regression/80-termination/03-nested-loop-terminating.c create mode 100644 tests/regression/80-termination/04-nested-loop-nonterminating.c create mode 100644 tests/regression/80-termination/05-for-loop-terminating.c create mode 100644 tests/regression/80-termination/06-for-loop-nonterminating.c create mode 100644 tests/regression/80-termination/07-nested-for-loop-terminating.c create mode 100644 tests/regression/80-termination/08-nested-for-loop-nonterminating.c create mode 100644 tests/regression/80-termination/09-complex-for-loop-terminating.c create mode 100644 tests/regression/80-termination/10-complex-loop-terminating.c create mode 100644 tests/regression/80-termination/11-loopless-termination.c create mode 100644 tests/regression/80-termination/12-do-while-instant-terminating.c create mode 100644 tests/regression/80-termination/13-do-while-terminating.c create mode 100644 tests/regression/80-termination/14-do-while-nonterminating.c create mode 100644 tests/regression/80-termination/15-complex-loop-combination-terminating.c create mode 100644 tests/regression/80-termination/16-nested-loop-nontrivial-nonterminating.c diff --git a/scripts/update_suite.rb b/scripts/update_suite.rb index e99068829e..dead6cd8f1 100755 --- a/scripts/update_suite.rb +++ b/scripts/update_suite.rb @@ -165,6 +165,8 @@ def collect_warnings when /^\[Error\]/ then "warn" when /^\[Info\]/ then "warn" when /^\[Success\]/ then "success" + when /^\[Terminating\]/ then "term" + when /^\[Nonterminating\]/ then "noterm" when /\[Debug\]/ then next # debug "warnings" shouldn't count as other warnings (against NOWARN) when /^ on line \d+ $/ then next # dead line warnings shouldn't count (used for unreachability with NOWARN) when /^ on lines \d+..\d+ $/ then next # dead line warnings shouldn't count (used for unreachability with NOWARN) @@ -298,6 +300,10 @@ def parse_tests (lines) tests[i] = "fail" elsif obj =~ /UNKNOWN/ then tests[i] = "unknown" + elsif obj =~ /NON?TERM/ then + tests[i] = "noterm" + elsif obj =~ /TERM/ then + tests[i] = "term" elsif obj =~ /(assert|__goblint_check).*\(/ then if obj =~ /FAIL/ then tests[i] = "fail" diff --git a/tests/regression/80-termination/01-simple-loop-terminating.c b/tests/regression/80-termination/01-simple-loop-terminating.c new file mode 100644 index 0000000000..931b125171 --- /dev/null +++ b/tests/regression/80-termination/01-simple-loop-terminating.c @@ -0,0 +1,15 @@ +// PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra +#include + +int main() +{ + int i = 1; + + while (i <= 10) // TERM + { + printf("%d\n", i); + i++; + } + + return 0; +} diff --git a/tests/regression/80-termination/02-simple-loop-nonterminating.c b/tests/regression/80-termination/02-simple-loop-nonterminating.c new file mode 100644 index 0000000000..520a4a82e0 --- /dev/null +++ b/tests/regression/80-termination/02-simple-loop-nonterminating.c @@ -0,0 +1,12 @@ +// PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra +#include + +int main() +{ + while (1) // NOTERM + { + continue; + } + + return 0; +} diff --git a/tests/regression/80-termination/03-nested-loop-terminating.c b/tests/regression/80-termination/03-nested-loop-terminating.c new file mode 100644 index 0000000000..172827af42 --- /dev/null +++ b/tests/regression/80-termination/03-nested-loop-terminating.c @@ -0,0 +1,27 @@ +// PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra +#include + +int main() +{ + int rows = 3; + int columns = 4; + int i = 1; + + // Outer while loop for rows + while (i <= rows) + { // TERM + int j = 1; + + // Inner while loop for columns + while (j <= columns) + { // TERM + printf("(%d, %d) ", i, j); + j++; + } + + printf("\n"); + i++; + } + + return 0; +} diff --git a/tests/regression/80-termination/04-nested-loop-nonterminating.c b/tests/regression/80-termination/04-nested-loop-nonterminating.c new file mode 100644 index 0000000000..37af9ed6fb --- /dev/null +++ b/tests/regression/80-termination/04-nested-loop-nonterminating.c @@ -0,0 +1,23 @@ +// PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra +#include + +int main() +{ + int outerCount = 1; + + while (outerCount <= 3) // NOTERM + { + int innerCount = 1; + + while (1) // NOTERM + { + printf("(%d, %d) ", outerCount, innerCount); + innerCount++; + } + + printf("\n"); + outerCount++; + } + + return 0; +} diff --git a/tests/regression/80-termination/05-for-loop-terminating.c b/tests/regression/80-termination/05-for-loop-terminating.c new file mode 100644 index 0000000000..ab286a6dd4 --- /dev/null +++ b/tests/regression/80-termination/05-for-loop-terminating.c @@ -0,0 +1,14 @@ +// PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra +#include + +int main() +{ + int i; + + for (i = 1; i <= 10; i++) // TERM + { + printf("%d\n", i); + } + + return 0; +} diff --git a/tests/regression/80-termination/06-for-loop-nonterminating.c b/tests/regression/80-termination/06-for-loop-nonterminating.c new file mode 100644 index 0000000000..466001e6e5 --- /dev/null +++ b/tests/regression/80-termination/06-for-loop-nonterminating.c @@ -0,0 +1,10 @@ +// PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra +#include + +int main() { + for (;;) { // NOTERM + printf("This loop does not terminate.\n"); + } + + return 0; +} diff --git a/tests/regression/80-termination/07-nested-for-loop-terminating.c b/tests/regression/80-termination/07-nested-for-loop-terminating.c new file mode 100644 index 0000000000..eec4dda908 --- /dev/null +++ b/tests/regression/80-termination/07-nested-for-loop-terminating.c @@ -0,0 +1,20 @@ +// PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra +#include + +int main() +{ + int rows = 3; + int columns = 4; + + // Nested loop to iterate over rows and columns + for (int i = 1; i <= rows; i++) // TERM + { + for (int j = 1; j <= columns; j++) // TERM + { + printf("(%d, %d) ", i, j); + } + printf("\n"); + } + + return 0; +} diff --git a/tests/regression/80-termination/08-nested-for-loop-nonterminating.c b/tests/regression/80-termination/08-nested-for-loop-nonterminating.c new file mode 100644 index 0000000000..3f7bcb4f07 --- /dev/null +++ b/tests/regression/80-termination/08-nested-for-loop-nonterminating.c @@ -0,0 +1,19 @@ +// PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra +#include + +int main() +{ + int outerCount, innerCount; + + for (outerCount = 1; outerCount <= 3; outerCount++) // NOTERM + { + for (innerCount = 1;; innerCount++) // NOTERM + { + printf("(%d, %d) ", outerCount, innerCount); + } + + printf("\n"); + } + + return 0; +} diff --git a/tests/regression/80-termination/09-complex-for-loop-terminating.c b/tests/regression/80-termination/09-complex-for-loop-terminating.c new file mode 100644 index 0000000000..ed28fa9b43 --- /dev/null +++ b/tests/regression/80-termination/09-complex-for-loop-terminating.c @@ -0,0 +1,107 @@ +// PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra +#include + +int main() +{ + int i, j, k; + + // Outer loop + for (i = 1; i <= 5; i++) // TERM + { + // Inner loop 1 + for (j = 1; j <= i; j++) // TERM + { + printf("%d ", j); + } + printf("\n"); + + // Inner loop 2 + for (k = i; k >= 1; k--) // TERM + { + printf("%d ", k); + } + printf("\n"); + } + + // Additional loop + for (i = 5; i >= 1; i--) // TERM + { + for (j = i; j >= 1; j--) // TERM + { + printf("%d ", j); + } + printf("\n"); + } + + // Loop with conditions + for (i = 1; i <= 10; i++) // TERM + { + if (i % 2 == 0) + { + printf("%d is even\n", i); + } + else + { + printf("%d is odd\n", i); + } + } + + // Loop with nested conditions + for (i = 1; i <= 10; i++) // TERM + { + printf("Number: %d - ", i); + if (i < 5) + { + printf("Less than 5\n"); + } + else if (i > 5) + { + printf("Greater than 5\n"); + } + else + { + printf("Equal to 5\n"); + } + } + + // Loop with a break statement + for (i = 1; i <= 10; i++) // TERM + { + printf("%d ", i); + if (i == 5) + { + break; + } + } + printf("\n"); + + // Loop with a continue statement + for (i = 1; i <= 10; i++) // TERM + { + if (i % 2 == 0) + { + continue; + } + printf("%d ", i); + } + printf("\n"); + + // Loop with complex conditions + for (i = 1; i <= 10; i++) // TERM + { + if (i > 5 && i % 2 == 0) + { + printf("%d ", i); + } + } + printf("\n"); + + // Loop with multiple variables + int a, b, c; + for (a = 1, b = 2, c = 3; a <= 10; a++, b += 2, c += 3) // TERM + { + printf("%d %d %d\n", a, b, c); + } + + return 0; +} diff --git a/tests/regression/80-termination/10-complex-loop-terminating.c b/tests/regression/80-termination/10-complex-loop-terminating.c new file mode 100644 index 0000000000..3a19f17bee --- /dev/null +++ b/tests/regression/80-termination/10-complex-loop-terminating.c @@ -0,0 +1,135 @@ +// PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra +#include + +int main() +{ + int i = 1; + int j = 1; + int k = 5; + + // Outer while loop + while (i <= 5) // TERM + { + // Inner while loop 1 + while (j <= i) // TERM + { + printf("%d ", j); + j++; + } + printf("\n"); + j = 1; + + // Inner while loop 2 + while (k >= 1) // TERM + { + printf("%d ", k); + k--; + } + printf("\n"); + k = 5; + + i++; + } + + // Additional while loop + i = 5; + while (i >= 1) // TERM + { + j = i; + while (j >= 1) // TERM + { + printf("%d ", j); + j--; + } + printf("\n"); + i--; + } + + // Loop with conditions + i = 1; + while (i <= 10) // TERM + { + if (i % 2 == 0) + { + printf("%d is even\n", i); + } + else + { + printf("%d is odd\n", i); + } + i++; + } + + // Loop with nested conditions + i = 1; + while (i <= 10) // TERM + { + printf("Number: %d - ", i); + if (i < 5) + { + printf("Less than 5\n"); + } + else if (i > 5) + { + printf("Greater than 5\n"); + } + else + { + printf("Equal to 5\n"); + } + i++; + } + + // Loop with a break statement + i = 1; + while (i <= 10) // TERM + { + printf("%d ", i); + if (i == 5) + { + break; + } + i++; + } + printf("\n"); + + // Loop with a continue statement + i = 1; + while (i <= 10) // TERM + { + if (i % 2 == 0) + { + i++; + continue; + } + printf("%d ", i); + i++; + } + printf("\n"); + + // Loop with complex conditions + i = 1; + while (i <= 10) // TERM + { + if (i > 5 && i % 2 == 0) + { + printf("%d ", i); + } + i++; + } + printf("\n"); + + // Loop with multiple variables + int a = 1; + int b = 2; + int c = 3; + while (a <= 10) // TERM + { + printf("%d %d %d\n", a, b, c); + a++; + b += 2; + c += 3; + } + + return 0; +} diff --git a/tests/regression/80-termination/11-loopless-termination.c b/tests/regression/80-termination/11-loopless-termination.c new file mode 100644 index 0000000000..b118e65e35 --- /dev/null +++ b/tests/regression/80-termination/11-loopless-termination.c @@ -0,0 +1,7 @@ +// TERM +#include + +int main() { + printf("Terminating code without a loop\n"); + return 0; +} diff --git a/tests/regression/80-termination/12-do-while-instant-terminating.c b/tests/regression/80-termination/12-do-while-instant-terminating.c new file mode 100644 index 0000000000..cc3cc41edc --- /dev/null +++ b/tests/regression/80-termination/12-do-while-instant-terminating.c @@ -0,0 +1,15 @@ +// PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra +#include + +int main() +{ + int i = 0; + + do // TERM + { + printf("Inside the do-while loop\n"); + } while (i > 0); + + printf("Exited the loop\n"); + return 0; +} diff --git a/tests/regression/80-termination/13-do-while-terminating.c b/tests/regression/80-termination/13-do-while-terminating.c new file mode 100644 index 0000000000..05fe270f04 --- /dev/null +++ b/tests/regression/80-termination/13-do-while-terminating.c @@ -0,0 +1,16 @@ +// PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra +#include + +int main() +{ + int i = 1; + + do // TERM + { + printf("Inside the do-while loop\n"); + i++; + } while (i <= 5); + + printf("Exited the loop\n"); + return 0; +} diff --git a/tests/regression/80-termination/14-do-while-nonterminating.c b/tests/regression/80-termination/14-do-while-nonterminating.c new file mode 100644 index 0000000000..1c70d4fc76 --- /dev/null +++ b/tests/regression/80-termination/14-do-while-nonterminating.c @@ -0,0 +1,16 @@ +// PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra +#include + +int main() +{ + int i = 1; + + do // NOTERM + { + printf("Inside the do-while loop\n"); + i++; + } while (i >= 2); + + printf("Exited the loop\n"); + return 0; +} diff --git a/tests/regression/80-termination/15-complex-loop-combination-terminating.c b/tests/regression/80-termination/15-complex-loop-combination-terminating.c new file mode 100644 index 0000000000..54f8cd97c8 --- /dev/null +++ b/tests/regression/80-termination/15-complex-loop-combination-terminating.c @@ -0,0 +1,144 @@ +// PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra +#include + +int main() +{ + // Non-nested loops + int i; + + // for loop + for (i = 1; i <= 10; i++) // TERM + { + printf("For loop iteration: %d\n", i); + } + + // while loop + int j = 1; + while (j <= 10) // TERM + { + printf("While loop iteration: %d\n", j); + j++; + } + + // do-while loop + int k = 1; + do // TERM + { + printf("Do-While loop iteration: %d\n", k); + k++; + } while (k <= 10); + + // Nested loops + int a, b; + + // Nested for and while loop + for (a = 1; a <= 5; a++) // TERM + { + int c = 1; + while (c <= a) // TERM + { + printf("Nested For-While loop: %d\n", c); + c++; + } + } + + // Nested while and do-while loop + int x = 1; + while (x <= 5) // TERM + { + int y = 1; + do // TERM + { + printf("Nested While-Do-While loop: %d\n", y); + y++; + } while (y <= x); + x++; + } + + // Nested do-while and for loop + int p = 1; + do // TERM + { + for (int q = 1; q <= p; q++) // TERM + { + printf("Nested Do-While-For loop: %d\n", q); + } + p++; + } while (p <= 5); + + // Additional loops + int m; + + // Nested while loop with a break statement + int n = 1; + while (n <= 5) // TERM + { + printf("Outer While loop iteration: %d\n", n); + m = 1; + while (1) // TERM + { + printf("Inner While loop iteration: %d\n", m); + m++; + if (m == 4) + { + break; + } + } + n++; + } + + // Loop with a continue statement + for (int r = 1; r <= 10; r++) // TERM + { + if (r % 3 == 0) + { + continue; + } + printf("Loop with Continue: %d\n", r); + } + + // Loop with multiple conditions + int s = 1; + while (s <= 10 && s % 2 == 0) // TERM + { + printf("Loop with Multiple Conditions: %d\n", s); + s++; + } + + // Loop with multiple variables + int t, u; + for (t = 1, u = 10; t <= 5 && u >= 5; t++, u--) // TERM + { + printf("Loop with Multiple Variables: %d %d\n", t, u); + } + + // Loop with nested conditions + for (int v = 1; v <= 10; v++) // TERM + { + printf("Loop with Nested Conditions: %d - ", v); + if (v < 5) + { + printf("Less than 5\n"); + } + else if (v > 5) + { + printf("Greater than 5\n"); + } + else + { + printf("Equal to 5\n"); + } + } + + /* // Loop with a label and goto statement + int w = 1; +start: + if (w <= 5) + { + printf("Loop with Label and Goto: %d\n", w); + w++; + goto start; // TERM + } */ + + return 0; +} diff --git a/tests/regression/80-termination/16-nested-loop-nontrivial-nonterminating.c b/tests/regression/80-termination/16-nested-loop-nontrivial-nonterminating.c new file mode 100644 index 0000000000..855fbd0dca --- /dev/null +++ b/tests/regression/80-termination/16-nested-loop-nontrivial-nonterminating.c @@ -0,0 +1,23 @@ +// PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra +#include + +int main() +{ + int outerCount = 1; + + while (outerCount <= 3) // NOTERM + { + int innerCount = 1; + + while (outerCount < 3 || innerCount > 0) // NOTERM + { + printf("(%d, %d) ", outerCount, innerCount); + innerCount++; + } + + printf("\n"); + outerCount++; + } + + return 0; +} From 9f60dca36bfc5cf7628d6ba5d3f03d2109db4a57 Mon Sep 17 00:00:00 2001 From: Johanna Schinabeck Date: Sat, 3 Jun 2023 13:29:17 +0200 Subject: [PATCH 052/327] first tests for recursion termination analysis, added empty functor and GMapG --- runningGob.sh | 22 ++++++++---- src/framework/analyses.ml | 53 +++++++++++++++++++++++++++++ src/framework/constraints.ml | 66 +++++++++++++++++++++++++++++++++++- src/framework/control.ml | 1 + 4 files changed, 135 insertions(+), 7 deletions(-) diff --git a/runningGob.sh b/runningGob.sh index f765b5afab..e3b5a6da45 100755 --- a/runningGob.sh +++ b/runningGob.sh @@ -1,22 +1,32 @@ #!/bin/bash -make +#make #make install # set options and file for apron execution -options_apron="--set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra --enable warn.debug" #note: preprocessing first needs to be added to apron +options_apron="--set ana.activated[+] apron --enable ana.int.interval --set --enable warn.debug" #note: preprocessing first needs to be added to apron options_signs="--set "ana.activated[+]" signs --enable warn.debug" options_term="--set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra" -cfile_loops="tests/regression/55-loop-unrolling/01-simple-cases.c" -cfile_signs="tests/regression/99-tutorials/01-first.c" +cfile_loops="tests/regression/55-loop-unrolling/01-simple-cases.c" +cfile_nonTerm="tests/regression/80-termination/02-simple-loop-nonterminating.c" +cfile_signs="tests/regression/99-tutorials/01-first.c" +cfile_deadCode="tests/regression/80-termination/16-nested-loop-nontrivial-nonterminating.c" # run analysis, write cil output to file and enable visualization via html #./goblint $cfile_loops $options_apron --enable justcil > output.txt #./goblint $cfile_loops $options_apron --html # run analysis, write cil output to file and enable visualization via html -./goblint $cfile_loops $options_term --enable justcil > output.txt -./goblint $cfile_loops $options_term --html +#./goblint $cfile_loops $options_term --enable justcil > output.txt +#./goblint $cfile_loops $options_term --html + +# run analysis, write cil output to file and enable visualization via html +./goblint $cfile_deadCode $options_term --enable justcil > output.txt +./goblint $cfile_deadCode $options_term --html + +# run analysis, write cil output to file and enable visualization via html +#./goblint $cfile_nonTerm $options_term --enable justcil > output.txt +#./goblint $cfile_nonTerm $options_term --html # set up server to see visualizatino python3 -m http.server --directory result 8081 diff --git a/src/framework/analyses.ml b/src/framework/analyses.ml index 1a3a4ebeb1..c8d3873085 100644 --- a/src/framework/analyses.ml +++ b/src/framework/analyses.ml @@ -119,6 +119,59 @@ struct | x -> BatPrintf.fprintf f "%a" printXml x end +module GMapG (G: Lattice.S) (C: Printable.S) = +struct + module CVal = + struct + include Printable.Std (* To make it Groupable *) + include SetDomain.Make ( + struct + include C + let printXml f c = BatPrintf.fprintf f "%a" printXml c (* wrap in for HTML printing *) + end + ) + let name () = "contextsMap" + end + + module RangeVal = + struct + include SetDomain.Make ( + struct + include C (*TODO: sollte hier iwi ein tupel sein*) + let printXml f c = BatPrintf.fprintf f "%a" printXml c (* wrap in for HTML printing *) + end + ) + let name () = "contextsMap" + end + + module CMap = + struct + include MapDomain.MapBot (CVal) (RangeVal) + let name () = "contextsMap" + end + include Lattice.Lift2 (G) (CMap) (Printable.DefaultNames) + + let is_bot () = false + let is_top () = false + + (*let spec = function + | `Bot -> G.bot () + | `Lifted1 x -> x + | _ -> failwith "GVarG.spec" + let contexts = function + | `Bot -> CSet.bot () + | `Lifted2 x -> x + | _ -> failwith "GVarG.contexts" + let create_spec spec = `Lifted1 spec + let create_contexts contexts = `Lifted2 contexts + + let printXml f = function + | `Lifted1 x -> G.printXml f x + | `Lifted2 x -> BatPrintf.fprintf f "%a" CSet.printXml x + | x -> BatPrintf.fprintf f "%a" printXml x +*) +end + exception Deadcode diff --git a/src/framework/constraints.ml b/src/framework/constraints.ml index 740d1f85a9..e9c1b9b0a2 100644 --- a/src/framework/constraints.ml +++ b/src/framework/constraints.ml @@ -1343,7 +1343,7 @@ struct module EM = struct include MapDomain.MapBot (Basetype.CilExp) (Basetype.Bools) - let name () = "branches" + let name () = "bmodule Vranches" end module G = @@ -1692,6 +1692,70 @@ struct let event ctx e octx = S.event (conv ctx) e (conv octx) end +(** Add cycle detection in the function call graph to a analysis *) +module RecursionTermLifter (S: Spec) + : Spec with module D = S.D + and module G = S.G + and module C = S.C + and module G = GMapG (S.G) (S.C) += + +struct + module C = S.C + module P = S.P + module D = S.D + + (*global invariant + - fundec -> Map (S.C) (Set (fundec * S.C)) + So: g -> {c' -> f, c} + in case f, c --> g, c' *) + + (*module CVal = + struct + include C + include Printable.Std (* To make it Groupable *) + let printXml f c = BatPrintf.fprintf f "%a" printXml c (* wrap in for HTML printing *) + end + module M = MapDomain.MapBot (CVal) (CVal) +*) + module V = S.V + module G = S.G(*GMapG (S.G) (S.C)*) + (*struct + include Lattice.Prod (S.G) (M) + let printXml f (d,m) = BatPrintf.fprintf f "\n%a\n%a\n" S.G.printXml d M.printXml m + end*) + let name () = "RecursionTerm (" ^ S.name () ^ ")" + + type marshal = S.marshal + let init = S.init + let finalize = S.finalize (*TODO*) + + let startstate v = S.startstate v + let exitstate v = S.exitstate v + let morphstate = S.morphstate + + let context = S.context + + let query ctx = S.query (ctx) + let branch ctx = S.branch (ctx) + let assign ctx = S.assign (ctx) + let vdecl ctx = S.vdecl (ctx) + let enter ctx = S.enter (ctx) (*TODO*) + let paths_as_set ctx = S.paths_as_set (ctx) + let body ctx = S.body (ctx) + let return ctx = S.return (ctx) + let combine_env ctx = S.combine_env (ctx) + let combine_assign ctx = S.combine_assign (ctx) + let special ctx = S.special (ctx) + let threadenter ctx = S.threadenter (ctx) + let threadspawn ctx lv f args fctx = S.threadspawn (ctx) lv f args (fctx) + let sync ctx = S.sync (ctx) + let skip ctx = S.skip (ctx) + let asm ctx = S.asm (ctx) + let event ctx e octx = S.event (ctx) e (octx) +end + + module CompareGlobSys (SpecSys: SpecSys) = struct open SpecSys diff --git a/src/framework/control.ml b/src/framework/control.ml index 35cadfc12d..bd26fa7129 100644 --- a/src/framework/control.ml +++ b/src/framework/control.ml @@ -36,6 +36,7 @@ let spec_module: (module Spec) Lazy.t = lazy ( Also must be outside of deadcode, because deadcode splits (like mutex lock event) don't pass on tokens. *) |> lift (get_bool "ana.widen.tokens") (module WideningTokens.Lifter) |> lift true (module LongjmpLifter) + |> lift true (module RecursionTermLifter)(*TODO: should we really always evaluate it???*) ) in GobConfig.building_spec := false; ControlSpecC.control_spec_c := (module S1.C); From 40128b7eb28855a9f79f649caf5f8e3288f6f7ab Mon Sep 17 00:00:00 2001 From: Johanna Schinabeck Date: Sat, 3 Jun 2023 13:31:15 +0200 Subject: [PATCH 053/327] now its working :) --- src/framework/constraints.ml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/framework/constraints.ml b/src/framework/constraints.ml index e9c1b9b0a2..0586a87d3e 100644 --- a/src/framework/constraints.ml +++ b/src/framework/constraints.ml @@ -1697,7 +1697,7 @@ module RecursionTermLifter (S: Spec) : Spec with module D = S.D and module G = S.G and module C = S.C - and module G = GMapG (S.G) (S.C) + and module G = S.G = struct From b35766b44e2b5002a0bf5f78b5a533fc6087b4d5 Mon Sep 17 00:00:00 2001 From: Johanna Schinabeck Date: Sat, 3 Jun 2023 14:03:53 +0200 Subject: [PATCH 054/327] reverted the changes, wrong branch :) --- src/framework/analyses.ml | 54 ------------------------------ src/framework/constraints.ml | 64 ------------------------------------ src/framework/control.ml | 3 +- 3 files changed, 1 insertion(+), 120 deletions(-) diff --git a/src/framework/analyses.ml b/src/framework/analyses.ml index c8d3873085..7ac18f56f7 100644 --- a/src/framework/analyses.ml +++ b/src/framework/analyses.ml @@ -119,60 +119,6 @@ struct | x -> BatPrintf.fprintf f "%a" printXml x end -module GMapG (G: Lattice.S) (C: Printable.S) = -struct - module CVal = - struct - include Printable.Std (* To make it Groupable *) - include SetDomain.Make ( - struct - include C - let printXml f c = BatPrintf.fprintf f "%a" printXml c (* wrap in for HTML printing *) - end - ) - let name () = "contextsMap" - end - - module RangeVal = - struct - include SetDomain.Make ( - struct - include C (*TODO: sollte hier iwi ein tupel sein*) - let printXml f c = BatPrintf.fprintf f "%a" printXml c (* wrap in for HTML printing *) - end - ) - let name () = "contextsMap" - end - - module CMap = - struct - include MapDomain.MapBot (CVal) (RangeVal) - let name () = "contextsMap" - end - include Lattice.Lift2 (G) (CMap) (Printable.DefaultNames) - - let is_bot () = false - let is_top () = false - - (*let spec = function - | `Bot -> G.bot () - | `Lifted1 x -> x - | _ -> failwith "GVarG.spec" - let contexts = function - | `Bot -> CSet.bot () - | `Lifted2 x -> x - | _ -> failwith "GVarG.contexts" - let create_spec spec = `Lifted1 spec - let create_contexts contexts = `Lifted2 contexts - - let printXml f = function - | `Lifted1 x -> G.printXml f x - | `Lifted2 x -> BatPrintf.fprintf f "%a" CSet.printXml x - | x -> BatPrintf.fprintf f "%a" printXml x -*) -end - - exception Deadcode (** [Dom (D)] produces D lifted where bottom means dead-code *) diff --git a/src/framework/constraints.ml b/src/framework/constraints.ml index 0586a87d3e..d8b186160b 100644 --- a/src/framework/constraints.ml +++ b/src/framework/constraints.ml @@ -1692,70 +1692,6 @@ struct let event ctx e octx = S.event (conv ctx) e (conv octx) end -(** Add cycle detection in the function call graph to a analysis *) -module RecursionTermLifter (S: Spec) - : Spec with module D = S.D - and module G = S.G - and module C = S.C - and module G = S.G -= - -struct - module C = S.C - module P = S.P - module D = S.D - - (*global invariant - - fundec -> Map (S.C) (Set (fundec * S.C)) - So: g -> {c' -> f, c} - in case f, c --> g, c' *) - - (*module CVal = - struct - include C - include Printable.Std (* To make it Groupable *) - let printXml f c = BatPrintf.fprintf f "%a" printXml c (* wrap in for HTML printing *) - end - module M = MapDomain.MapBot (CVal) (CVal) -*) - module V = S.V - module G = S.G(*GMapG (S.G) (S.C)*) - (*struct - include Lattice.Prod (S.G) (M) - let printXml f (d,m) = BatPrintf.fprintf f "\n%a\n%a\n" S.G.printXml d M.printXml m - end*) - let name () = "RecursionTerm (" ^ S.name () ^ ")" - - type marshal = S.marshal - let init = S.init - let finalize = S.finalize (*TODO*) - - let startstate v = S.startstate v - let exitstate v = S.exitstate v - let morphstate = S.morphstate - - let context = S.context - - let query ctx = S.query (ctx) - let branch ctx = S.branch (ctx) - let assign ctx = S.assign (ctx) - let vdecl ctx = S.vdecl (ctx) - let enter ctx = S.enter (ctx) (*TODO*) - let paths_as_set ctx = S.paths_as_set (ctx) - let body ctx = S.body (ctx) - let return ctx = S.return (ctx) - let combine_env ctx = S.combine_env (ctx) - let combine_assign ctx = S.combine_assign (ctx) - let special ctx = S.special (ctx) - let threadenter ctx = S.threadenter (ctx) - let threadspawn ctx lv f args fctx = S.threadspawn (ctx) lv f args (fctx) - let sync ctx = S.sync (ctx) - let skip ctx = S.skip (ctx) - let asm ctx = S.asm (ctx) - let event ctx e octx = S.event (ctx) e (octx) -end - - module CompareGlobSys (SpecSys: SpecSys) = struct open SpecSys diff --git a/src/framework/control.ml b/src/framework/control.ml index bd26fa7129..7e993733cd 100644 --- a/src/framework/control.ml +++ b/src/framework/control.ml @@ -36,8 +36,7 @@ let spec_module: (module Spec) Lazy.t = lazy ( Also must be outside of deadcode, because deadcode splits (like mutex lock event) don't pass on tokens. *) |> lift (get_bool "ana.widen.tokens") (module WideningTokens.Lifter) |> lift true (module LongjmpLifter) - |> lift true (module RecursionTermLifter)(*TODO: should we really always evaluate it???*) - ) in + ) in GobConfig.building_spec := false; ControlSpecC.control_spec_c := (module S1.C); (module S1) From e67ea327f230250553ec621691142f6edb6acaf3 Mon Sep 17 00:00:00 2001 From: Johanna Schinabeck Date: Sat, 3 Jun 2023 14:05:00 +0200 Subject: [PATCH 055/327] fixed a typo --- src/framework/constraints.ml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/framework/constraints.ml b/src/framework/constraints.ml index d8b186160b..740d1f85a9 100644 --- a/src/framework/constraints.ml +++ b/src/framework/constraints.ml @@ -1343,7 +1343,7 @@ struct module EM = struct include MapDomain.MapBot (Basetype.CilExp) (Basetype.Bools) - let name () = "bmodule Vranches" + let name () = "branches" end module G = From ff5377b4413168b21808da54305ffa5311f29e7e Mon Sep 17 00:00:00 2001 From: Thomas Lagemann Date: Mon, 5 Jun 2023 16:04:58 +0200 Subject: [PATCH 056/327] Loop termination tests extended --- .../09-complex-for-loop-terminating.c | 2 +- .../10-complex-loop-terminating.c | 2 +- .../15-complex-loop-combination-terminating.c | 6 ++-- .../80-termination/17-goto-terminating.c | 18 +++++++++++ .../80-termination/18-goto-nonterminating.c | 15 +++++++++ .../80-termination/19-rand-terminating.c | 31 +++++++++++++++++++ .../80-termination/20-rand-nonterminating.c | 31 +++++++++++++++++++ 7 files changed, 100 insertions(+), 5 deletions(-) create mode 100644 tests/regression/80-termination/17-goto-terminating.c create mode 100644 tests/regression/80-termination/18-goto-nonterminating.c create mode 100644 tests/regression/80-termination/19-rand-terminating.c create mode 100644 tests/regression/80-termination/20-rand-nonterminating.c diff --git a/tests/regression/80-termination/09-complex-for-loop-terminating.c b/tests/regression/80-termination/09-complex-for-loop-terminating.c index ed28fa9b43..508b31500c 100644 --- a/tests/regression/80-termination/09-complex-for-loop-terminating.c +++ b/tests/regression/80-termination/09-complex-for-loop-terminating.c @@ -1,4 +1,4 @@ -// PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra +// PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval #include int main() diff --git a/tests/regression/80-termination/10-complex-loop-terminating.c b/tests/regression/80-termination/10-complex-loop-terminating.c index 3a19f17bee..9d5cd4b928 100644 --- a/tests/regression/80-termination/10-complex-loop-terminating.c +++ b/tests/regression/80-termination/10-complex-loop-terminating.c @@ -1,4 +1,4 @@ -// PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra +// PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval #include int main() diff --git a/tests/regression/80-termination/15-complex-loop-combination-terminating.c b/tests/regression/80-termination/15-complex-loop-combination-terminating.c index 54f8cd97c8..1ea228ae55 100644 --- a/tests/regression/80-termination/15-complex-loop-combination-terminating.c +++ b/tests/regression/80-termination/15-complex-loop-combination-terminating.c @@ -1,4 +1,4 @@ -// PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra +// PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval #include int main() @@ -130,7 +130,7 @@ int main() } } - /* // Loop with a label and goto statement + // Loop with a label and goto statement int w = 1; start: if (w <= 5) @@ -138,7 +138,7 @@ int main() printf("Loop with Label and Goto: %d\n", w); w++; goto start; // TERM - } */ + } return 0; } diff --git a/tests/regression/80-termination/17-goto-terminating.c b/tests/regression/80-termination/17-goto-terminating.c new file mode 100644 index 0000000000..10aa729837 --- /dev/null +++ b/tests/regression/80-termination/17-goto-terminating.c @@ -0,0 +1,18 @@ +// PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval +#include + +int main() +{ + int num = 1; + +loop: // TERM + printf("Current number: %d\n", num); + num++; + + if (num <= 10) + { + goto loop; + } + + return 0; +} diff --git a/tests/regression/80-termination/18-goto-nonterminating.c b/tests/regression/80-termination/18-goto-nonterminating.c new file mode 100644 index 0000000000..dbb7a3df59 --- /dev/null +++ b/tests/regression/80-termination/18-goto-nonterminating.c @@ -0,0 +1,15 @@ +// PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval +#include + +int main() +{ + int num = 1; + +loop: // NOTERM + printf("Current number: %d\n", num); + num++; + + goto loop; + + return 0; +} diff --git a/tests/regression/80-termination/19-rand-terminating.c b/tests/regression/80-termination/19-rand-terminating.c new file mode 100644 index 0000000000..1d226f0df2 --- /dev/null +++ b/tests/regression/80-termination/19-rand-terminating.c @@ -0,0 +1,31 @@ +// PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval +#include +#include +#include + +int main() +{ + // Seed the random number generator + srand(time(NULL)); + + if (rand()) + { + // Loop inside the if part + for (int i = 1; i <= 5; i++) // TERM + { + printf("Loop inside if part: %d\n", i); + } + } + else + { + // Loop inside the else part + int j = 1; + while (j <= 5) // TERM + { + printf("Loop inside else part: %d\n", j); + j++; + } + } + + return 0; +} diff --git a/tests/regression/80-termination/20-rand-nonterminating.c b/tests/regression/80-termination/20-rand-nonterminating.c new file mode 100644 index 0000000000..6639e5bc76 --- /dev/null +++ b/tests/regression/80-termination/20-rand-nonterminating.c @@ -0,0 +1,31 @@ +// PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval +#include +#include +#include + +int main() +{ + // Seed the random number generator + srand(time(NULL)); + + if (rand()) + { + // Loop inside the if part + for (int i = 1; i <= 0; i++) // NOTERM + { + printf("Loop inside if part: %d\n", i); + } + } + else + { + // Loop inside the else part + int j = 1; + while (j < 5) // NOTERM + { + printf("Loop inside else part: %d\n", j); + j++; + } + } + + return 0; +} From 69cee5fb397bd3523ffe25534218ac28790e50ee Mon Sep 17 00:00:00 2001 From: Thomas Lagemann Date: Mon, 5 Jun 2023 16:52:59 +0200 Subject: [PATCH 057/327] Added testcases with randomness --- .../21-no-exit-on-rand-unproofable.c | 19 +++++++++++++++++++ .../22-exit-on-rand-unproofable.c | 15 +++++++++++++++ .../23-exit-on-rand-terminating.c | 16 ++++++++++++++++ 3 files changed, 50 insertions(+) create mode 100644 tests/regression/80-termination/21-no-exit-on-rand-unproofable.c create mode 100644 tests/regression/80-termination/22-exit-on-rand-unproofable.c create mode 100644 tests/regression/80-termination/23-exit-on-rand-terminating.c diff --git a/tests/regression/80-termination/21-no-exit-on-rand-unproofable.c b/tests/regression/80-termination/21-no-exit-on-rand-unproofable.c new file mode 100644 index 0000000000..4510ac1bb7 --- /dev/null +++ b/tests/regression/80-termination/21-no-exit-on-rand-unproofable.c @@ -0,0 +1,19 @@ +// PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval +#include + +int main() +{ + int forever, i = 0; + + while (i < 4 || forever == 1) + { + i++; + if (i == 4) + { + if (rand()) + { + forever = 1; + } + } + } +} \ No newline at end of file diff --git a/tests/regression/80-termination/22-exit-on-rand-unproofable.c b/tests/regression/80-termination/22-exit-on-rand-unproofable.c new file mode 100644 index 0000000000..97b18ed5fc --- /dev/null +++ b/tests/regression/80-termination/22-exit-on-rand-unproofable.c @@ -0,0 +1,15 @@ +// PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval +#include + +int main() +{ + int forever = 1; + + while (forever == 1) + { + if (rand()) //May exit, may not + { + forever = 0; + } + } +} \ No newline at end of file diff --git a/tests/regression/80-termination/23-exit-on-rand-terminating.c b/tests/regression/80-termination/23-exit-on-rand-terminating.c new file mode 100644 index 0000000000..5e2be62637 --- /dev/null +++ b/tests/regression/80-termination/23-exit-on-rand-terminating.c @@ -0,0 +1,16 @@ +// PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval +#include + +int main() +{ + int shortrun, i = 0; + + while (i < 90 || shortrun == 1) + { + i++; + if (rand()) + { + shortrun = 1; + } + } +} \ No newline at end of file From 4f45a89d0bbade25f5c102bfc376b933984147c2 Mon Sep 17 00:00:00 2001 From: Johanna Schinabeck Date: Mon, 5 Jun 2023 17:10:44 +0200 Subject: [PATCH 058/327] added upjumping goto statement --- runningGob.sh | 1 + src/analyses/termination_new.ml | 14 +++++++++++++- src/framework/control.ml | 2 +- src/util/terminationPreprocessing.ml | 10 +++++++++- 4 files changed, 24 insertions(+), 3 deletions(-) diff --git a/runningGob.sh b/runningGob.sh index f765b5afab..52d0830b81 100755 --- a/runningGob.sh +++ b/runningGob.sh @@ -9,6 +9,7 @@ options_term="--set "ana.activated[+]" termination --enable warn.debug --set ana cfile_loops="tests/regression/55-loop-unrolling/01-simple-cases.c" cfile_signs="tests/regression/99-tutorials/01-first.c" +cfile_goto="tests/incremental/02-cfg-comparison/01-added-return-stmt.c" # run analysis, write cil output to file and enable visualization via html #./goblint $cfile_loops $options_apron --enable justcil > output.txt diff --git a/src/analyses/termination_new.ml b/src/analyses/termination_new.ml index 936471ceaf..a380532afe 100644 --- a/src/analyses/termination_new.ml +++ b/src/analyses/termination_new.ml @@ -3,10 +3,12 @@ open Analyses open GoblintCil open TerminationPreprocessing +include Printf exception PreProcessing of string let loopCounters : varinfo list ref = ref [] +let upjumpingGotos : location list ref = ref [] (*contains the locations of the upjumping gotos*) let loopExit : varinfo ref = ref (makeVarinfo false "-error" Cil.intType) @@ -16,6 +18,14 @@ let is_loop_counter_var (x : varinfo) = let is_loop_exit_indicator (x : varinfo) = x = !loopExit +(* checks if at the current location (=loc) of the analysis an upjumping goto was already reached + true: no upjumping goto was reached till now*) +let currrently_no_upjumping_gotos (loc : location) = + List.for_all (function (l) -> (l >= loc)) upjumpingGotos.contents + +let no_upjumping_gotos () = + (List.length upjumpingGotos.contents) <= 0 + (** Checks whether a variable can be bounded *) let check_bounded ctx varinfo = let exp = Lval (Var varinfo, NoOffset) in @@ -43,10 +53,12 @@ struct match lval, rval with (* Assume that the following loop does not terminate *) (Var x, NoOffset), _ when is_loop_counter_var x -> + if not (no_upjumping_gotos ()) then printf "\n4 problem\n"; D.add x false ctx.local (* Loop exit: Check whether loop counter variable is bounded *) | (Var y, NoOffset), Lval (Var x, NoOffset) when is_loop_exit_indicator y -> let is_bounded = check_bounded ctx x in + if not (no_upjumping_gotos ()) then printf "\n5 problem\n"; D.add x is_bounded ctx.local | _ -> ctx.local @@ -68,6 +80,6 @@ end let () = (** Register the preprocessing *) - Cilfacade.register_preprocess_cil (Spec.name ()) (new loopCounterVisitor loopCounters loopExit); + Cilfacade.register_preprocess_cil (Spec.name ()) (new loopCounterVisitor loopCounters upjumpingGotos loopExit); (** Register this analysis within the master control program *) MCP.register_analysis (module Spec : MCPSpec) diff --git a/src/framework/control.ml b/src/framework/control.ml index bd26fa7129..7722621d5a 100644 --- a/src/framework/control.ml +++ b/src/framework/control.ml @@ -36,7 +36,7 @@ let spec_module: (module Spec) Lazy.t = lazy ( Also must be outside of deadcode, because deadcode splits (like mutex lock event) don't pass on tokens. *) |> lift (get_bool "ana.widen.tokens") (module WideningTokens.Lifter) |> lift true (module LongjmpLifter) - |> lift true (module RecursionTermLifter)(*TODO: should we really always evaluate it???*) + (*|> lift true (module RecursionTermLifter)*)(*TODO: should we really always evaluate it???*) ) in GobConfig.building_spec := false; ControlSpecC.control_spec_c := (module S1.C); diff --git a/src/util/terminationPreprocessing.ml b/src/util/terminationPreprocessing.ml index 1a0e725624..684733c05f 100644 --- a/src/util/terminationPreprocessing.ml +++ b/src/util/terminationPreprocessing.ml @@ -6,6 +6,7 @@ *) open GoblintCil +include Printf let extract_file_name s = (*There still may be a need to filter more chars*) let ls = String.split_on_char '/' s in (*Assuming '/' as path seperator*) @@ -20,7 +21,7 @@ let extract_file_name s = (*There still may be a need to filt let show_location_id l = string_of_int l.line ^ "_" ^ string_of_int l.column ^ "-file" ^ "_" ^ extract_file_name l.file -class loopCounterVisitor lc le (fd : fundec) = object(self) +class loopCounterVisitor lc lg le (fd : fundec) = object(self) inherit nopCilVisitor method! vfunc (f:fundec) = if !le.vname <> "term_exit-" then begin @@ -46,6 +47,13 @@ class loopCounterVisitor lc le (fd : fundec) = object(self) let nb = mkBlock [init_stmt; mkStmt s.skind; exit_stmt] in s.skind <- Block nb; s + | Goto (sref, l) -> + let goto_jmp_stmt = sref.contents.skind in + let loc_stmt = get_stmtLoc goto_jmp_stmt in + if CilType.Location.compare l loc_stmt >= 0 (*is pos if first loc is greater -> below the second loc*) + then + lg := List.append !lg ([l] : location list); (*problem: the program might not terminate!*) + s | _ -> s in ChangeDoChildrenPost (s, action); end From a820c31ff07dcf5849b231663c0bca553bba42cf Mon Sep 17 00:00:00 2001 From: Johanna Schinabeck Date: Tue, 6 Jun 2023 10:15:07 +0200 Subject: [PATCH 059/327] plain functor --- src/framework/constraints.ml | 19 +++++++++++-------- 1 file changed, 11 insertions(+), 8 deletions(-) diff --git a/src/framework/constraints.ml b/src/framework/constraints.ml index 0177f3ea85..8132e6a1d7 100644 --- a/src/framework/constraints.ml +++ b/src/framework/constraints.ml @@ -1693,7 +1693,7 @@ struct let event ctx e octx = S.event (conv ctx) e (conv octx) end -(** +(* module RecursionTermLifter (S: Spec): Spec = struct include S @@ -1711,7 +1711,7 @@ struct let s x = `Left x end - module C = + module C_ = struct include S.C include Printable.Std (* To make it Groupable *) @@ -1772,13 +1772,13 @@ struct module EM = struct - include MapDomain.MapBot (C) (T) + include MapDomain.MapBot (C_) (T) let name () = "recursions" end module G = struct - include Lattice.Lift2 (S.G) (EM) (Printable.DefaultNames) + include Lattice.Lift2 (S.G) (EM) (Printable.DefaultNames) (*Todo: do we need lift2?*) let name () = "recursionTerm" let node = function | `Bot -> EM.bot () @@ -1793,6 +1793,8 @@ struct | x -> BatPrintf.fprintf f "%a" printXml x end + + let conv (ctx: (_, G.t, _, V.t) ctx): (_, S.G.t, _, S.V.t) ctx = { ctx with global = (fun v -> G.s (ctx.global (V.s v))); @@ -1880,7 +1882,7 @@ struct let asm ctx = S.asm (conv ctx) let event ctx e octx = S.event (conv ctx) e (conv octx) end - +*) (** Add cycle detection in the function call graph to a analysis *) module RecursionTermLifter (S: Spec) @@ -1911,13 +1913,14 @@ struct end module M = MapDomain.MapBot (CVal) (CVal) *) - module V = (*TODO: do I need to change V???*) + module V = S.V + (*(*TODO: do I need to change V???*) struct include Printable.Option (S.V) (struct let name = "RecursionTerm" end) let name () = "RecursionTerm" let is_write_only t = true let s x = `Left x - end + end*) module G = S.G (*GMapG (S.G) (S.C)*) (*struct @@ -1961,7 +1964,7 @@ struct let asm ctx = S.asm (ctx) let event ctx e octx = S.event (ctx) e (octx) end -*) + module CompareGlobSys (SpecSys: SpecSys) = struct From f298efa3e087d32ee2608a55b74d1d291c5e56a0 Mon Sep 17 00:00:00 2001 From: Johanna Schinabeck Date: Tue, 6 Jun 2023 11:44:02 +0200 Subject: [PATCH 060/327] added tuple; problem: fundec is just a type and not a module --- src/framework/constraints.ml | 41 +++++++++++++++++++++++++++++++++--- src/framework/control.ml | 2 +- 2 files changed, 39 insertions(+), 4 deletions(-) diff --git a/src/framework/constraints.ml b/src/framework/constraints.ml index 8132e6a1d7..37cf9a5f51 100644 --- a/src/framework/constraints.ml +++ b/src/framework/constraints.ml @@ -1904,7 +1904,6 @@ struct (* - module CVal = struct include C @@ -1921,8 +1920,44 @@ struct let is_write_only t = true let s x = `Left x end*) - module G = S.G - (*GMapG (S.G) (S.C)*) + + module C_ = + struct + include S.C + include Printable.Std (* To make it Groupable *) + let printXml f c = BatPrintf.fprintf f "%a" printXml c (* wrap in for HTML printing *) + + end + + module type FundecType = + sig + type t = fundec + + val getFundec: t -> fundec + (* Define any other values or types exposed by the module *) + end + + module Fundec (F:fundec) : FundecType = + struct + let getFundec = F + let fname = F.fname + end + + (* Tuple of fundec and S.C*) + module T = (*Todo: is this Printable.S or S.C*) + struct + include Printable.Std + type t = (fundec * S.C.t) + + let equal (a1, b1) (a2, b2) = if (a1 = a2) && (b1 = b2) then true else false + let show () = " " + end + + (* Set of Tuples*) + module TSet = SetDomain.Make (T) + + module G = S.G(*Lattice.Lift2 (S.G) (MapDomain.MapBot (C_) (TSet)) (Printable.DefaultNames) (*TODO: does MapBot fit?*)*) + (*GMapG (S.G) (S.C)*) (*struct include Lattice.Prod (S.G) (M) let printXml f (d,m) = BatPrintf.fprintf f "\n%a\n%a\n" S.G.printXml d M.printXml m diff --git a/src/framework/control.ml b/src/framework/control.ml index 7722621d5a..bd26fa7129 100644 --- a/src/framework/control.ml +++ b/src/framework/control.ml @@ -36,7 +36,7 @@ let spec_module: (module Spec) Lazy.t = lazy ( Also must be outside of deadcode, because deadcode splits (like mutex lock event) don't pass on tokens. *) |> lift (get_bool "ana.widen.tokens") (module WideningTokens.Lifter) |> lift true (module LongjmpLifter) - (*|> lift true (module RecursionTermLifter)*)(*TODO: should we really always evaluate it???*) + |> lift true (module RecursionTermLifter)(*TODO: should we really always evaluate it???*) ) in GobConfig.building_spec := false; ControlSpecC.control_spec_c := (module S1.C); From 2fe92c6889ce7b383e79a7e48629734289eee975 Mon Sep 17 00:00:00 2001 From: Johanna Schinabeck Date: Tue, 6 Jun 2023 12:52:16 +0200 Subject: [PATCH 061/327] added definition of V --- src/framework/constraints.ml | 52 +++++++++++++++++++++--------------- 1 file changed, 30 insertions(+), 22 deletions(-) diff --git a/src/framework/constraints.ml b/src/framework/constraints.ml index 37cf9a5f51..14b0126325 100644 --- a/src/framework/constraints.ml +++ b/src/framework/constraints.ml @@ -1889,7 +1889,6 @@ module RecursionTermLifter (S: Spec) : Spec with module D = S.D and module G = S.G and module C = S.C - and module G = S.G = struct @@ -1912,7 +1911,8 @@ struct end module M = MapDomain.MapBot (CVal) (CVal) *) - module V = S.V + + module V = GVarF(S.V) (*(*TODO: do I need to change V???*) struct include Printable.Option (S.V) (struct let name = "RecursionTerm" end) @@ -1929,7 +1929,7 @@ struct end - module type FundecType = + (*module type FundecType = sig type t = fundec @@ -1941,7 +1941,7 @@ struct struct let getFundec = F let fname = F.fname - end + end*) (* Tuple of fundec and S.C*) module T = (*Todo: is this Printable.S or S.C*) @@ -1950,7 +1950,9 @@ struct type t = (fundec * S.C.t) let equal (a1, b1) (a2, b2) = if (a1 = a2) && (b1 = b2) then true else false - let show () = " " + let show (a, b) = a.fname ^ b.vname + let name () = "Tuple" + let to_yojson x = `String (show x) end (* Set of Tuples*) @@ -1962,6 +1964,7 @@ struct include Lattice.Prod (S.G) (M) let printXml f (d,m) = BatPrintf.fprintf f "\n%a\n%a\n" S.G.printXml d M.printXml m end*) + let name () = "RecursionTerm (" ^ S.name () ^ ")" type marshal = S.marshal @@ -1978,26 +1981,31 @@ struct if !AnalysisState.postsolving then sideg (f) (G.create_contexts (G.CSet.singleton c))*) - let query ctx = S.query (ctx) - let branch ctx = S.branch (ctx) - let assign ctx = S.assign (ctx) - let vdecl ctx = S.vdecl (ctx) + let conv (ctx: (_, _, _, V.t) ctx): (_, _, _, S.V.t) ctx = (*TODO Change the body*) + { ctx with + global = (fun v -> G.s (ctx.global (V.s v))); + sideg = (fun v g -> ctx.sideg (V.s v) (G.create_s g)); + } + let query ctx = S.query (conv ctx) + let branch ctx = S.branch (conv ctx) + let assign ctx = S.assign (conv ctx) + let vdecl ctx = S.vdecl (conv ctx) let enter ctx = if !AnalysisState.postsolving then printf "hallo hallo"; - S.enter (ctx) (*TODO*) - let paths_as_set ctx = S.paths_as_set (ctx) - let body ctx = S.body (ctx) - let return ctx = S.return (ctx) - let combine_env ctx = S.combine_env (ctx) - let combine_assign ctx = S.combine_assign (ctx) - let special ctx = S.special (ctx) - let threadenter ctx = S.threadenter (ctx) - let threadspawn ctx lv f args fctx = S.threadspawn (ctx) lv f args (fctx) - let sync ctx = S.sync (ctx) - let skip ctx = S.skip (ctx) - let asm ctx = S.asm (ctx) - let event ctx e octx = S.event (ctx) e (octx) + S.enter (conv ctx) (*TODO*) + let paths_as_set ctx = S.paths_as_set (conv ctx) + let body ctx = S.body (conv ctx) + let return ctx = S.return (conv ctx) + let combine_env ctx = S.combine_env (conv ctx) + let combine_assign ctx = S.combine_assign (conv ctx) + let special ctx = S.special (conv ctx) + let threadenter ctx = S.threadenter (conv ctx) + let threadspawn ctx lv f args fctx = S.threadspawn (conv ctx) lv f args (conv fctx) + let sync ctx = S.sync (conv ctx) + let skip ctx = S.skip (conv ctx) + let asm ctx = S.asm (conv ctx) + let event ctx e octx = S.event (conv ctx) e (conv octx) end From cbf31335fb1341cabe90f982e80b6db6b5c71c1f Mon Sep 17 00:00:00 2001 From: Alexander Schlenga Date: Tue, 6 Jun 2023 16:50:45 +0200 Subject: [PATCH 062/327] WIP on check_bounded --- src/analyses/termination_new.ml | 8 +++++--- src/cdomains/intDomain.ml | 13 +++++++++++++ 2 files changed, 18 insertions(+), 3 deletions(-) diff --git a/src/analyses/termination_new.ml b/src/analyses/termination_new.ml index 936471ceaf..34e25d49d3 100644 --- a/src/analyses/termination_new.ml +++ b/src/analyses/termination_new.ml @@ -18,11 +18,13 @@ let is_loop_exit_indicator (x : varinfo) = (** Checks whether a variable can be bounded *) let check_bounded ctx varinfo = + let open IntDomain.IntDomTuple in (* TODO: Remove *) + let open Cil in let exp = Lval (Var varinfo, NoOffset) in match ctx.ask (EvalInt exp) with - `Top -> false - | `Bot -> raise (PreProcessing "Loop variable is Bot") - | _ -> true (* TODO: Is this sound? *) + `Top -> print_endline (varinfo.vname ^ " is TOP"); false + | `Bot -> print_endline (varinfo.vname ^ " is BOT"); raise (PreProcessing "Loop variable is Bot") + | `Lifted v -> print_endline (varinfo.vname ^ " is " ^ IntDomain.IntDomTuple.show v); not (is_top v) (* TODO: Is this sound? *) module Spec : Analyses.MCPSpec = struct diff --git a/src/cdomains/intDomain.ml b/src/cdomains/intDomain.ml index 3b1eecc27d..dea3daecd8 100644 --- a/src/cdomains/intDomain.ml +++ b/src/cdomains/intDomain.ml @@ -219,6 +219,7 @@ sig val ending : ?suppress_ovwarn:bool -> Cil.ikind -> int_t -> t val of_int: Cil.ikind -> int_t -> t val of_bool: Cil.ikind -> bool -> t + val to_interval: t -> (int_t * int_t) option val of_interval: ?suppress_ovwarn:bool -> Cil.ikind -> int_t * int_t -> t val of_congruence: Cil.ikind -> int_t * int_t -> t val is_top_of: Cil.ikind -> t -> bool @@ -349,6 +350,8 @@ struct with Failure _ -> top_of ik + let to_interval = failwith "Not implemented!" (* FIXME *) + let starting ?(suppress_ovwarn=false) ik x = try Old.starting ~suppress_ovwarn ik (BI.to_int64 x) with Failure _ -> top_of ik let ending ?(suppress_ovwarn=false) ik x = @@ -428,6 +431,7 @@ struct let of_excl_list ikind is = {v = I.of_excl_list ikind is; ikind} let is_excl_list x = I.is_excl_list x.v let to_incl_list x = I.to_incl_list x.v + let to_interval x = I.to_interval x.v let of_interval ?(suppress_ovwarn=false) ikind (lb,ub) = {v = I.of_interval ~suppress_ovwarn ikind (lb,ub); ikind} let of_congruence ikind (c,m) = {v = I.of_congruence ikind (c,m); ikind} let starting ?(suppress_ovwarn=false) ikind i = {v = I.starting ~suppress_ovwarn ikind i; ikind} @@ -708,6 +712,7 @@ struct (* TODO: change to_int signature so it returns a big_int *) let to_int x = Option.bind x (IArith.to_int) + let to_interval x = x let of_interval ?(suppress_ovwarn=false) ik (x,y) = norm ~suppress_ovwarn ik @@ Some (x,y) let of_int ik (x: int_t) = of_interval ik (x,x) let zero = Some IArith.zero @@ -1265,6 +1270,8 @@ struct let of_bool _ = function true -> one | false -> zero + let to_interval = failwith "Not implemented!" (* FIXME *) + let of_interval ?(suppress_ovwarn=false) ik (x,y) = norm_interval ~suppress_ovwarn ~cast:false ik (x,y) let of_int ik (x: int_t) = of_interval ik (x, x) @@ -2137,6 +2144,7 @@ struct let top_bool = `Excluded (S.empty (), R.of_interval range_ikind (0L, 1L)) let of_interval ?(suppress_ovwarn=false) ik (x,y) = if BigInt.compare x y = 0 then of_int ik x else top_of ik + let to_interval = failwith "Not implemented!" (* FIXME *) let starting ?(suppress_ovwarn=false) ikind x = if BigInt.compare x BigInt.zero > 0 then not_zero ikind else top_of ikind let ending ?(suppress_ovwarn=false) ikind x = if BigInt.compare x BigInt.zero < 0 then not_zero ikind else top_of ikind @@ -2529,6 +2537,7 @@ module Enums : S with type int_t = BigInt.t = struct let of_int ikind x = cast_to ikind (Inc (BISet.singleton x)) let of_interval ?(suppress_ovwarn=false) ik (x,y) = if x = y then of_int ik x else top_of ik + let to_interval = failwith "Not implemented!" (* FIXME *) let join ik = curry @@ function | Inc x, Inc y -> Inc (BISet.union x y) @@ -3263,6 +3272,8 @@ struct let refine_with_incl_list ik a b = a let project ik p t = t + + let to_interval = failwith "Not implemented!" (* FIXME *) end module SOverflowLifter (D : S) : SOverflow with type int_t = D.int_t and type t = D.t = struct @@ -3495,6 +3506,8 @@ module IntDomTupleImpl = struct let flat f x = match to_list_some x with [] -> None | xs -> Some (f xs) + let to_interval (_, i, _, _, _) = I2.to_interval i + let to_excl_list x = let merge ps = let (vs, rs) = List.split ps in From 6d7ec8cd8ec52c994ba6419048ffa0798645e204 Mon Sep 17 00:00:00 2001 From: Johanna Schinabeck Date: Wed, 7 Jun 2023 15:52:11 +0200 Subject: [PATCH 063/327] IT's wOrkingggg :)git status; hopefully V and G are correct now... some functions definitely must be redefined --- src/framework/analyses.ml | 76 +++++++++++++++++++++++++++++++ src/framework/constraints.ml | 86 ++++++++++++++++-------------------- 2 files changed, 114 insertions(+), 48 deletions(-) diff --git a/src/framework/analyses.ml b/src/framework/analyses.ml index 1d1972ac45..286c33870d 100644 --- a/src/framework/analyses.ml +++ b/src/framework/analyses.ml @@ -120,6 +120,82 @@ struct end +module C_ (C: Printable.S)= + struct + include C + include Printable.Std (* To make it Groupable *) + let printXml f c = BatPrintf.fprintf f "%a" printXml c (* wrap in for HTML printing *) + + end + +(* Tuple of fundec and S.C*) +module T (Base1: Printable.S) (Base2: Printable.S) (C: Printable.S) = (*Todo: is this Printable.S or S.C*) +struct + include Printable.Std + type t = (CilType.Fundec.t * C.t) + + let equal (a1, b1) (a2, b2) = if (a1 = a2) && (b1 = b2) then true else false + let show (a,b) = (Base1.show a) ^ (Base2.show b) + let name () = "Tuple" + let to_yojson x = `String (show x) + let relift (a,b) = (a,b) (*Todo: is this correct?*) + let printXml f (a,b) = Base1.printXml f a (*Todo: what do we have to put here?*) + let compare (a1,b1) (a2,b2) = 3 (*Todo: what do we have to put here?*) + (*let a = Base1.compare a1 a2 in + let b = Base2.compare b1 b2 in + *) + let pretty () (a,b) = Base1.pretty () a(*Todo: what do we have to put here?*) + + let hash (a,b) = 2 (*Todo: what do we have to put here?*) + +end + +module GVarGG (G: Lattice.S) (C: Printable.S) = + struct + module CSet = + struct + include SetDomain.Make ( + struct + include (T (CilType.Fundec) (C) (C)) (* Set of Tuples*) + end + ) + let name () = "contexts" + end + + module CMap = + struct + include MapDomain.MapBot (C_ (C)) (CSet) + let printXml f c = BatPrintf.fprintf f "%a" printXml c (* TODO *) + let printXml_ f c = BatPrintf.fprintf f "%a" CSet.printXml c (* TODO *) + end + + include Lattice.Lift2 (G) (CMap) (Printable.DefaultNames) + + let spec = function + | `Bot -> G.bot () + | `Lifted1 x -> x + | _ -> failwith "GVarGG.spec" + let contexts = function + | `Bot -> CSet.bot () + | `Lifted2 x -> x + | _ -> failwith "GVarGG.contexts" + let create_spec spec = `Lifted1 spec + let create_contexts contexts = `Lifted2 contexts + + let printXml f = function + | `Lifted1 x -> G.printXml f x + | `Lifted2 x -> BatPrintf.fprintf f "%a" CMap.printXml x + | x -> BatPrintf.fprintf f "%a" printXml x + + let s = function (*TODO: does this work? copied from DeadBranch*) + | `Bot -> G.bot () + | `Lifted1 x -> x + | _ -> failwith "RecursionTerm.s" + + let create_s s = `Lifted1 s (*TODO: does this work? copied from DeadBranch*) + end + + module GMapG (G: Lattice.S) (C: Printable.S) = struct module CVal = diff --git a/src/framework/constraints.ml b/src/framework/constraints.ml index 14b0126325..93aa636847 100644 --- a/src/framework/constraints.ml +++ b/src/framework/constraints.ml @@ -1887,20 +1887,34 @@ end (** Add cycle detection in the function call graph to a analysis *) module RecursionTermLifter (S: Spec) : Spec with module D = S.D - and module G = S.G and module C = S.C + and module G = GVarGG (S.G) (S.C) = struct module C = S.C module P = S.P module D = S.D + (*GMapG (S.G) (S.C)*) + (*struct + include Lattice.Prod (S.G) (M) + let printXml f (d,m) = BatPrintf.fprintf f "\n%a\n%a\n" S.G.printXml d M.printXml m + end*) - (*global invariant - - fundec -> Map (S.C) (Set (fundec * S.C)) - So: g -> {c' -> f, c} - in case f, c --> g, c' *) + + (*module type FundecType = + sig + type t = fundec + + val getFundec: t -> fundec + (* Define any other values or types exposed by the module *) + end + module Fundec (F:fundec) : FundecType = + struct + let getFundec = F + let fname = F.fname + end*) (* module CVal = @@ -1910,61 +1924,36 @@ struct let printXml f c = BatPrintf.fprintf f "%a" printXml c (* wrap in for HTML printing *) end module M = MapDomain.MapBot (CVal) (CVal) -*) - - module V = GVarF(S.V) - (*(*TODO: do I need to change V???*) +*) (*(*TODO: do I need to change V???*) struct include Printable.Option (S.V) (struct let name = "RecursionTerm" end) let name () = "RecursionTerm" let is_write_only t = true let s x = `Left x end*) + (*include Lattice.Lift2 (S.G) (MapDomain.MapBot (C_) (TSet)) (Printable.DefaultNames) (*TODO: does MapBot fit?*) + let s = function + | `Bot -> S.G.bot () + | `Lifted1 x -> x + | _ -> failwith "RecursionTerm.s" + end*) - module C_ = - struct - include S.C - include Printable.Std (* To make it Groupable *) - let printXml f c = BatPrintf.fprintf f "%a" printXml c (* wrap in for HTML printing *) - - end - - (*module type FundecType = - sig - type t = fundec - - val getFundec: t -> fundec - (* Define any other values or types exposed by the module *) - end - module Fundec (F:fundec) : FundecType = + module V = struct - let getFundec = F - let fname = F.fname - end*) - - (* Tuple of fundec and S.C*) - module T = (*Todo: is this Printable.S or S.C*) - struct - include Printable.Std - type t = (fundec * S.C.t) - - let equal (a1, b1) (a2, b2) = if (a1 = a2) && (b1 = b2) then true else false - let show (a, b) = a.fname ^ b.vname - let name () = "Tuple" - let to_yojson x = `String (show x) + include GVarF(S.V) + let s x = `Left x end - (* Set of Tuples*) - module TSet = SetDomain.Make (T) - module G = S.G(*Lattice.Lift2 (S.G) (MapDomain.MapBot (C_) (TSet)) (Printable.DefaultNames) (*TODO: does MapBot fit?*)*) - (*GMapG (S.G) (S.C)*) - (*struct - include Lattice.Prod (S.G) (M) - let printXml f (d,m) = BatPrintf.fprintf f "\n%a\n%a\n" S.G.printXml d M.printXml m - end*) + (*global invariant + - fundec -> Map (S.C) (Set (fundec * S.C)) + So: g -> {c' -> f, c} + in case f, c --> g, c' *) + module G = GVarGG (S.G) (S.C) + + let name () = "RecursionTerm (" ^ S.name () ^ ")" type marshal = S.marshal @@ -1981,7 +1970,8 @@ struct if !AnalysisState.postsolving then sideg (f) (G.create_contexts (G.CSet.singleton c))*) - let conv (ctx: (_, _, _, V.t) ctx): (_, _, _, S.V.t) ctx = (*TODO Change the body*) + (*TODO Change the body??*) + let conv (ctx: (_, _, _, V.t) ctx): (_, _, _, S.V.t) ctx = { ctx with global = (fun v -> G.s (ctx.global (V.s v))); sideg = (fun v g -> ctx.sideg (V.s v) (G.create_s g)); From aa1c30a3a7ce2482155dcf682fdfd6420dbca72e Mon Sep 17 00:00:00 2001 From: Johanna Schinabeck Date: Wed, 7 Jun 2023 16:12:15 +0200 Subject: [PATCH 064/327] changed indentation --- src/framework/analyses.ml | 92 ++++++++++++++-------------- src/framework/constraints.ml | 25 ++++---- src/util/terminationPreprocessing.ml | 1 + 3 files changed, 59 insertions(+), 59 deletions(-) diff --git a/src/framework/analyses.ml b/src/framework/analyses.ml index 286c33870d..550adb7b16 100644 --- a/src/framework/analyses.ml +++ b/src/framework/analyses.ml @@ -121,12 +121,12 @@ end module C_ (C: Printable.S)= - struct - include C - include Printable.Std (* To make it Groupable *) - let printXml f c = BatPrintf.fprintf f "%a" printXml c (* wrap in for HTML printing *) - - end +struct + include C + include Printable.Std (* To make it Groupable *) + let printXml f c = BatPrintf.fprintf f "%a" printXml c (* wrap in for HTML printing *) + +end (* Tuple of fundec and S.C*) module T (Base1: Printable.S) (Base2: Printable.S) (C: Printable.S) = (*Todo: is this Printable.S or S.C*) @@ -142,7 +142,7 @@ struct let printXml f (a,b) = Base1.printXml f a (*Todo: what do we have to put here?*) let compare (a1,b1) (a2,b2) = 3 (*Todo: what do we have to put here?*) (*let a = Base1.compare a1 a2 in - let b = Base2.compare b1 b2 in + let b = Base2.compare b1 b2 in *) let pretty () (a,b) = Base1.pretty () a(*Todo: what do we have to put here?*) @@ -151,49 +151,49 @@ struct end module GVarGG (G: Lattice.S) (C: Printable.S) = +struct + module CSet = struct - module CSet = - struct - include SetDomain.Make ( - struct - include (T (CilType.Fundec) (C) (C)) (* Set of Tuples*) - end - ) - let name () = "contexts" - end + include SetDomain.Make ( + struct + include (T (CilType.Fundec) (C) (C)) (* Set of Tuples*) + end + ) + let name () = "contexts" + end - module CMap = - struct - include MapDomain.MapBot (C_ (C)) (CSet) - let printXml f c = BatPrintf.fprintf f "%a" printXml c (* TODO *) - let printXml_ f c = BatPrintf.fprintf f "%a" CSet.printXml c (* TODO *) - end + module CMap = + struct + include MapDomain.MapBot (C_ (C)) (CSet) + let printXml f c = BatPrintf.fprintf f "%a" printXml c (* TODO *) + let printXml_ f c = BatPrintf.fprintf f "%a" CSet.printXml c (* TODO *) + end - include Lattice.Lift2 (G) (CMap) (Printable.DefaultNames) - - let spec = function - | `Bot -> G.bot () - | `Lifted1 x -> x - | _ -> failwith "GVarGG.spec" - let contexts = function - | `Bot -> CSet.bot () - | `Lifted2 x -> x - | _ -> failwith "GVarGG.contexts" - let create_spec spec = `Lifted1 spec - let create_contexts contexts = `Lifted2 contexts - - let printXml f = function - | `Lifted1 x -> G.printXml f x - | `Lifted2 x -> BatPrintf.fprintf f "%a" CMap.printXml x - | x -> BatPrintf.fprintf f "%a" printXml x - - let s = function (*TODO: does this work? copied from DeadBranch*) - | `Bot -> G.bot () - | `Lifted1 x -> x - | _ -> failwith "RecursionTerm.s" + include Lattice.Lift2 (G) (CMap) (Printable.DefaultNames) - let create_s s = `Lifted1 s (*TODO: does this work? copied from DeadBranch*) - end + let spec = function + | `Bot -> G.bot () + | `Lifted1 x -> x + | _ -> failwith "GVarGG.spec" + let contexts = function + | `Bot -> CSet.bot () + | `Lifted2 x -> x + | _ -> failwith "GVarGG.contexts" + let create_spec spec = `Lifted1 spec + let create_contexts contexts = `Lifted2 contexts + + let printXml f = function + | `Lifted1 x -> G.printXml f x + | `Lifted2 x -> BatPrintf.fprintf f "%a" CMap.printXml x + | x -> BatPrintf.fprintf f "%a" printXml x + + let s = function (*TODO: does this work? copied from DeadBranch*) + | `Bot -> G.bot () + | `Lifted1 x -> x + | _ -> failwith "RecursionTerm.s" + + let create_s s = `Lifted1 s (*TODO: does this work? copied from DeadBranch*) +end module GMapG (G: Lattice.S) (C: Printable.S) = diff --git a/src/framework/constraints.ml b/src/framework/constraints.ml index 93aa636847..fde22c4c20 100644 --- a/src/framework/constraints.ml +++ b/src/framework/constraints.ml @@ -1883,19 +1883,7 @@ struct let event ctx e octx = S.event (conv ctx) e (conv octx) end *) - -(** Add cycle detection in the function call graph to a analysis *) -module RecursionTermLifter (S: Spec) - : Spec with module D = S.D - and module C = S.C - and module G = GVarGG (S.G) (S.C) -= - -struct - module C = S.C - module P = S.P - module D = S.D - (*GMapG (S.G) (S.C)*) + (*GMapG (S.G) (S.C)*) (*struct include Lattice.Prod (S.G) (M) let printXml f (d,m) = BatPrintf.fprintf f "\n%a\n%a\n" S.G.printXml d M.printXml m @@ -1938,7 +1926,18 @@ struct | _ -> failwith "RecursionTerm.s" end*) +(** Add cycle detection in the function call graph to a analysis *) +module RecursionTermLifter (S: Spec) + : Spec with module D = S.D + and module C = S.C + and module G = GVarGG (S.G) (S.C) += +struct + module C = S.C + module P = S.P + module D = S.D + module V = struct include GVarF(S.V) diff --git a/src/util/terminationPreprocessing.ml b/src/util/terminationPreprocessing.ml index 684733c05f..5f96483af4 100644 --- a/src/util/terminationPreprocessing.ml +++ b/src/util/terminationPreprocessing.ml @@ -35,6 +35,7 @@ class loopCounterVisitor lc lg le (fd : fundec) = object(self) | Loop (b, loc, eloc, _, _) -> let name = "term"^show_location_id loc in let typ = Cil.intType in + (* NOT tested for TODOOOOO*) let v = (Cil.makeLocalVar fd name typ) in let init_stmt = mkStmtOneInstr @@ Set (var v, zero, loc, eloc) in let inc_stmt = mkStmtOneInstr @@ Set (var v, increm (Lval (var v)) 1, loc, eloc) in From 5f3ae26b7c8d58a33208373a9ba1791b56b20eb6 Mon Sep 17 00:00:00 2001 From: Johanna Schinabeck Date: Wed, 7 Jun 2023 17:23:29 +0200 Subject: [PATCH 065/327] intendation --- src/framework/analyses.ml | 2 +- src/framework/constraints.ml | 15 +++++++-------- src/util/terminationPreprocessing.ml | 3 +-- 3 files changed, 9 insertions(+), 11 deletions(-) diff --git a/src/framework/analyses.ml b/src/framework/analyses.ml index 550adb7b16..52836f979b 100644 --- a/src/framework/analyses.ml +++ b/src/framework/analyses.ml @@ -158,7 +158,7 @@ struct struct include (T (CilType.Fundec) (C) (C)) (* Set of Tuples*) end - ) + ) let name () = "contexts" end diff --git a/src/framework/constraints.ml b/src/framework/constraints.ml index fde22c4c20..88afb5ca91 100644 --- a/src/framework/constraints.ml +++ b/src/framework/constraints.ml @@ -1883,14 +1883,14 @@ struct let event ctx e octx = S.event (conv ctx) e (conv octx) end *) - (*GMapG (S.G) (S.C)*) - (*struct +(*GMapG (S.G) (S.C)*) +(*struct include Lattice.Prod (S.G) (M) let printXml f (d,m) = BatPrintf.fprintf f "\n%a\n%a\n" S.G.printXml d M.printXml m - end*) +end*) - (*module type FundecType = +(*module type FundecType = sig type t = fundec @@ -1911,20 +1911,19 @@ end include Printable.Std (* To make it Groupable *) let printXml f c = BatPrintf.fprintf f "%a" printXml c (* wrap in for HTML printing *) end - module M = MapDomain.MapBot (CVal) (CVal) -*) (*(*TODO: do I need to change V???*) + module M = MapDomain.MapBot (CVal) (CVal)*) (*(*TODO: do I need to change V???*) struct include Printable.Option (S.V) (struct let name = "RecursionTerm" end) let name () = "RecursionTerm" let is_write_only t = true let s x = `Left x end*) - (*include Lattice.Lift2 (S.G) (MapDomain.MapBot (C_) (TSet)) (Printable.DefaultNames) (*TODO: does MapBot fit?*) +(*include Lattice.Lift2 (S.G) (MapDomain.MapBot (C_) (TSet)) (Printable.DefaultNames) (*TODO: does MapBot fit?*) let s = function | `Bot -> S.G.bot () | `Lifted1 x -> x | _ -> failwith "RecursionTerm.s" - end*) +end*) (** Add cycle detection in the function call graph to a analysis *) module RecursionTermLifter (S: Spec) diff --git a/src/util/terminationPreprocessing.ml b/src/util/terminationPreprocessing.ml index 5f96483af4..da4fd2e10b 100644 --- a/src/util/terminationPreprocessing.ml +++ b/src/util/terminationPreprocessing.ml @@ -35,8 +35,7 @@ class loopCounterVisitor lc lg le (fd : fundec) = object(self) | Loop (b, loc, eloc, _, _) -> let name = "term"^show_location_id loc in let typ = Cil.intType in - (* NOT tested for TODOOOOO*) - let v = (Cil.makeLocalVar fd name typ) in + let v = (Cil.makeLocalVar fd name typ) in (* NOT tested for TODOOOOO*) let init_stmt = mkStmtOneInstr @@ Set (var v, zero, loc, eloc) in let inc_stmt = mkStmtOneInstr @@ Set (var v, increm (Lval (var v)) 1, loc, eloc) in let exit_stmt = mkStmtOneInstr @@ Set ((var !le), (Lval (var v)), loc, eloc) in From 5717a43867f908989481b5807d3d54b2fd1088c0 Mon Sep 17 00:00:00 2001 From: Johanna Schinabeck Date: Wed, 7 Jun 2023 17:31:12 +0200 Subject: [PATCH 066/327] indent --- src/framework/analyses.ml | 2 +- src/framework/constraints.ml | 4 ++-- src/util/terminationPreprocessing.ml | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/framework/analyses.ml b/src/framework/analyses.ml index 52836f979b..2f3f4b34a8 100644 --- a/src/framework/analyses.ml +++ b/src/framework/analyses.ml @@ -158,7 +158,7 @@ struct struct include (T (CilType.Fundec) (C) (C)) (* Set of Tuples*) end - ) + ) let name () = "contexts" end diff --git a/src/framework/constraints.ml b/src/framework/constraints.ml index 88afb5ca91..774c0abc95 100644 --- a/src/framework/constraints.ml +++ b/src/framework/constraints.ml @@ -1887,7 +1887,7 @@ end (*struct include Lattice.Prod (S.G) (M) let printXml f (d,m) = BatPrintf.fprintf f "\n%a\n%a\n" S.G.printXml d M.printXml m -end*) + end*) (*module type FundecType = @@ -1923,7 +1923,7 @@ end*) | `Bot -> S.G.bot () | `Lifted1 x -> x | _ -> failwith "RecursionTerm.s" -end*) + end*) (** Add cycle detection in the function call graph to a analysis *) module RecursionTermLifter (S: Spec) diff --git a/src/util/terminationPreprocessing.ml b/src/util/terminationPreprocessing.ml index da4fd2e10b..749b9f2f8e 100644 --- a/src/util/terminationPreprocessing.ml +++ b/src/util/terminationPreprocessing.ml @@ -35,7 +35,7 @@ class loopCounterVisitor lc lg le (fd : fundec) = object(self) | Loop (b, loc, eloc, _, _) -> let name = "term"^show_location_id loc in let typ = Cil.intType in - let v = (Cil.makeLocalVar fd name typ) in (* NOT tested for TODOOOOO*) + let v = (Cil.makeLocalVar fd name typ) in (* NOT tested for TODOOOOO*) let init_stmt = mkStmtOneInstr @@ Set (var v, zero, loc, eloc) in let inc_stmt = mkStmtOneInstr @@ Set (var v, increm (Lval (var v)) 1, loc, eloc) in let exit_stmt = mkStmtOneInstr @@ Set ((var !le), (Lval (var v)), loc, eloc) in From 706a1f516305de78144a1dce17f3bf4142093af1 Mon Sep 17 00:00:00 2001 From: Isidor Zweckstetter Date: Mon, 5 Jun 2023 15:33:19 +0200 Subject: [PATCH 067/327] changed loop exit indicator form global variable to a special function --- lib/goblint/runtime/src/goblint.c | 4 ++++ src/analyses/libraryFunctions.ml | 1 + src/analyses/termination_new.ml | 4 ++++ src/util/terminationPreprocessing.ml | 13 ++++--------- 4 files changed, 13 insertions(+), 9 deletions(-) diff --git a/lib/goblint/runtime/src/goblint.c b/lib/goblint/runtime/src/goblint.c index bc176f93a6..39c18c5b8e 100644 --- a/lib/goblint/runtime/src/goblint.c +++ b/lib/goblint/runtime/src/goblint.c @@ -27,4 +27,8 @@ void __goblint_split_begin(int exp) { void __goblint_split_end(int exp) { +} + +void __goblint_bounded() { + } \ No newline at end of file diff --git a/src/analyses/libraryFunctions.ml b/src/analyses/libraryFunctions.ml index 3eacf9013a..7bb985ae4b 100644 --- a/src/analyses/libraryFunctions.ml +++ b/src/analyses/libraryFunctions.ml @@ -302,6 +302,7 @@ let goblint_descs_list: (string * LibraryDesc.t) list = LibraryDsl.[ ("__goblint_assert", special [__ "exp" []] @@ fun exp -> Assert { exp; check = true; refine = get_bool "sem.assert.refine" }); ("__goblint_split_begin", unknown [drop "exp" []]); ("__goblint_split_end", unknown [drop "exp" []]); + ("__goblint_bounded", special [__ "exp"[]] @@ fun exp -> Assert { exp; check = true; refine = false }); ] (** zstd functions. diff --git a/src/analyses/termination_new.ml b/src/analyses/termination_new.ml index a380532afe..bff776b95d 100644 --- a/src/analyses/termination_new.ml +++ b/src/analyses/termination_new.ml @@ -80,6 +80,10 @@ end let () = (** Register the preprocessing *) +<<<<<<< HEAD Cilfacade.register_preprocess_cil (Spec.name ()) (new loopCounterVisitor loopCounters upjumpingGotos loopExit); +======= + Cilfacade.register_preprocess_cil (Spec.name ()) (new loopCounterVisitor loopCounters); +>>>>>>> dfa9d6ef8 (changed loop exit indicator form global variable to a special function) (** Register this analysis within the master control program *) MCP.register_analysis (module Spec : MCPSpec) diff --git a/src/util/terminationPreprocessing.ml b/src/util/terminationPreprocessing.ml index 749b9f2f8e..15a5c948fd 100644 --- a/src/util/terminationPreprocessing.ml +++ b/src/util/terminationPreprocessing.ml @@ -8,6 +8,8 @@ open GoblintCil include Printf +let f_bounded = Lval (var (emptyFunction "__goblint_bounded").svar) + let extract_file_name s = (*There still may be a need to filter more chars*) let ls = String.split_on_char '/' s in (*Assuming '/' as path seperator*) let ls = List.rev ls in @@ -21,15 +23,8 @@ let extract_file_name s = (*There still may be a need to filt let show_location_id l = string_of_int l.line ^ "_" ^ string_of_int l.column ^ "-file" ^ "_" ^ extract_file_name l.file -class loopCounterVisitor lc lg le (fd : fundec) = object(self) +class loopCounterVisitor lc (fd : fundec) = object(self) inherit nopCilVisitor - method! vfunc (f:fundec) = - if !le.vname <> "term_exit-" then begin - let exit_name = "term_exit-" in - let typ = Cil.intType in - le := Cil.makeGlobalVar exit_name typ; - end; - DoChildren; (* function definition *) method! vstmt s = let action s = match s.skind with | Loop (b, loc, eloc, _, _) -> @@ -38,7 +33,7 @@ class loopCounterVisitor lc lg le (fd : fundec) = object(self) let v = (Cil.makeLocalVar fd name typ) in (* NOT tested for TODOOOOO*) let init_stmt = mkStmtOneInstr @@ Set (var v, zero, loc, eloc) in let inc_stmt = mkStmtOneInstr @@ Set (var v, increm (Lval (var v)) 1, loc, eloc) in - let exit_stmt = mkStmtOneInstr @@ Set ((var !le), (Lval (var v)), loc, eloc) in + let exit_stmt = mkStmtOneInstr @@ Call (None, f_bounded, [(Lval(var v))], loc, eloc) in (match b.bstmts with | cont :: cond :: ss -> b.bstmts <- cont :: inc_stmt :: cond :: ss; (*cont :: cond :: inc_stmt :: ss = it is also possible, but for loops with cond at the end, inc is also at the end*) From 09510429a97ac12575c47067d15c18e450a1ae73 Mon Sep 17 00:00:00 2001 From: Johanna Schinabeck Date: Thu, 8 Jun 2023 13:13:39 +0200 Subject: [PATCH 068/327] added first tests for enter; does compile without the enter stuff, but when running we got an Not_found exception due to the definition of V --- src/framework/analyses.ml | 8 +++--- src/framework/constraints.ml | 55 +++++++++++++++++------------------- 2 files changed, 30 insertions(+), 33 deletions(-) diff --git a/src/framework/analyses.ml b/src/framework/analyses.ml index 2f3f4b34a8..41448768a9 100644 --- a/src/framework/analyses.ml +++ b/src/framework/analyses.ml @@ -119,7 +119,7 @@ struct | x -> BatPrintf.fprintf f "%a" printXml x end - +(* Make the given module Goupable*) module C_ (C: Printable.S)= struct include C @@ -139,12 +139,12 @@ struct let name () = "Tuple" let to_yojson x = `String (show x) let relift (a,b) = (a,b) (*Todo: is this correct?*) - let printXml f (a,b) = Base1.printXml f a (*Todo: what do we have to put here?*) + let printXml f (a,b) = Base1.printXml f a; Base2.printXml f b (*Todo: what do we have to put here?*) let compare (a1,b1) (a2,b2) = 3 (*Todo: what do we have to put here?*) (*let a = Base1.compare a1 a2 in let b = Base2.compare b1 b2 in *) - let pretty () (a,b) = Base1.pretty () a(*Todo: what do we have to put here?*) + let pretty () x = text (show x) let hash (a,b) = 2 (*Todo: what do we have to put here?*) @@ -176,7 +176,7 @@ struct | `Lifted1 x -> x | _ -> failwith "GVarGG.spec" let contexts = function - | `Bot -> CSet.bot () + | `Bot -> CMap.bot () | `Lifted2 x -> x | _ -> failwith "GVarGG.contexts" let create_spec spec = `Lifted1 spec diff --git a/src/framework/constraints.ml b/src/framework/constraints.ml index 774c0abc95..287726419f 100644 --- a/src/framework/constraints.ml +++ b/src/framework/constraints.ml @@ -1930,58 +1930,55 @@ module RecursionTermLifter (S: Spec) : Spec with module D = S.D and module C = S.C and module G = GVarGG (S.G) (S.C) + and module V = GVarF(S.V) = - -struct - module C = S.C - module P = S.P - module D = S.D - - module V = - struct - include GVarF(S.V) - let s x = `Left x - end - - - (*global invariant +(*global invariant - fundec -> Map (S.C) (Set (fundec * S.C)) So: g -> {c' -> f, c} in case f, c --> g, c' *) +struct + include S + module V = GVarF(S.V) + module G = GVarGG (S.G) (S.C) - let name () = "RecursionTerm (" ^ S.name () ^ ")" - type marshal = S.marshal - let init = S.init let finalize = S.finalize (*TODO*) - let startstate v = S.startstate v - let exitstate v = S.exitstate v - let morphstate = S.morphstate - - let context = S.context - (**let side_context sideg f c = if !AnalysisState.postsolving then sideg (f) (G.create_contexts (G.CSet.singleton c))*) (*TODO Change the body??*) - let conv (ctx: (_, _, _, V.t) ctx): (_, _, _, S.V.t) ctx = + let conv (ctx: (_, G.t, _, V.t) ctx): (_, S.G.t, _, S.V.t) ctx = { ctx with - global = (fun v -> G.s (ctx.global (V.s v))); - sideg = (fun v g -> ctx.sideg (V.s v) (G.create_s g)); + global = (fun v -> G.s (ctx.global (V.spec v))); + sideg = (fun v g -> ctx.sideg (V.spec v) (G.create_s g)); } let query ctx = S.query (conv ctx) let branch ctx = S.branch (conv ctx) let assign ctx = S.assign (conv ctx) let vdecl ctx = S.vdecl (conv ctx) - let enter ctx = + + (* c = context + t = set of tuples (fundec * context) + *) + let side_context sideg f c t = if !AnalysisState.postsolving then - printf "hallo hallo"; - S.enter (conv ctx) (*TODO*) + sideg (V.contexts f) (G.create_contexts (G.CMap.singleton (c) (t))) + + let enter ctx lval fundec exprList = (*TODO*) + S.enter (conv ctx) lval fundec exprList; + let c: unit -> S.C.t = snd var |> Obj.obj in (*Callee context*) + let fd = fundec in (*Callee fundec*) + let c' = ctx.context in (*Caller context*) (*TODO is this the caller or callee context???*) + let fd' = in (*Caller fundec*) + let tup = (fundec * c') in (* TODO: is fundec the caller or callee fundec???*) + let t = G.CSet.singleton (tup) in (*TODO do we fill the set correctly???*) + side_context sideg fd (c ()) t + let paths_as_set ctx = S.paths_as_set (conv ctx) let body ctx = S.body (conv ctx) let return ctx = S.return (conv ctx) From 2841622620ccd483e19794b7dc6be15309e2ce52 Mon Sep 17 00:00:00 2001 From: Alexander Schlenga Date: Fri, 9 Jun 2023 15:19:07 +0200 Subject: [PATCH 069/327] Introduce to_interval --- src/cdomains/intDomain.ml | 13 ++++++++++--- src/cdomains/intDomain.mli | 3 +++ 2 files changed, 13 insertions(+), 3 deletions(-) diff --git a/src/cdomains/intDomain.ml b/src/cdomains/intDomain.ml index dea3daecd8..ed6ef5a403 100644 --- a/src/cdomains/intDomain.ml +++ b/src/cdomains/intDomain.ml @@ -171,6 +171,7 @@ sig val equal_to: int_t -> t -> [`Eq | `Neq | `Top] val to_bool: t -> bool option + val to_interval: t -> (int_t * int_t) option val to_excl_list: t -> (int_t list * (int64 * int64)) option val of_excl_list: Cil.ikind -> int_t list -> t val is_excl_list: t -> bool @@ -219,7 +220,6 @@ sig val ending : ?suppress_ovwarn:bool -> Cil.ikind -> int_t -> t val of_int: Cil.ikind -> int_t -> t val of_bool: Cil.ikind -> bool -> t - val to_interval: t -> (int_t * int_t) option val of_interval: ?suppress_ovwarn:bool -> Cil.ikind -> int_t * int_t -> t val of_congruence: Cil.ikind -> int_t * int_t -> t val is_top_of: Cil.ikind -> t -> bool @@ -712,7 +712,7 @@ struct (* TODO: change to_int signature so it returns a big_int *) let to_int x = Option.bind x (IArith.to_int) - let to_interval x = x + let to_interval = Fun.id let of_interval ?(suppress_ovwarn=false) ik (x,y) = norm ~suppress_ovwarn ik @@ Some (x,y) let of_int ik (x: int_t) = of_interval ik (x,x) let zero = Some IArith.zero @@ -1646,6 +1646,7 @@ struct let to_bool x = Some (to_bool' x) let of_int x = x let to_int x = Some x + let to_interval = failwith "Not implemented!" (* FIXME *) let neg = Ints_t.neg let add = Ints_t.add (* TODO: signed overflow is undefined behavior! *) @@ -1720,6 +1721,7 @@ struct let of_excl_list ik x = top_of ik let is_excl_list x = false let to_incl_list x = None + let to_interval x = None let of_interval ?(suppress_ovwarn=false) ik x = top_of ik let of_congruence ik x = top_of ik let starting ?(suppress_ovwarn=false) ikind x = top_of ikind @@ -1803,6 +1805,10 @@ struct | `Bot, `Bot -> `Bot | _ -> `Top + let to_interval = function + | `Lifted x -> Base.to_interval x + | _ -> None + let neg = lift1 Base.neg let add = lift2 Base.add let sub = lift2 Base.sub @@ -2408,6 +2414,7 @@ struct let to_bool x = Some x let of_int x = x = Int64.zero let to_int x = if x then None else Some Int64.zero + let to_interval = failwith "Not implemented!" (* FIXME *) let neg x = x let add x y = x || y @@ -3506,7 +3513,7 @@ module IntDomTupleImpl = struct let flat f x = match to_list_some x with [] -> None | xs -> Some (f xs) - let to_interval (_, i, _, _, _) = I2.to_interval i + let to_interval (_, i, _, _, _) = Option.bind i I2.to_interval let to_excl_list x = let merge ps = diff --git a/src/cdomains/intDomain.mli b/src/cdomains/intDomain.mli index a853c8acca..5a6a4d7c04 100644 --- a/src/cdomains/intDomain.mli +++ b/src/cdomains/intDomain.mli @@ -187,6 +187,9 @@ sig (** Give a boolean interpretation of an abstract value if possible, otherwise * don't return anything.*) + val to_interval: t -> (int_t * int_t) option + (** Gives an interval interpretation if possible. *) + val to_excl_list: t -> (int_t list * (int64 * int64)) option (** Gives a list representation of the excluded values from included range of bits if possible. *) From 93ea56e6c6ad00e642bc3f5188f23fc67d87b133 Mon Sep 17 00:00:00 2001 From: Alexander Schlenga Date: Fri, 9 Jun 2023 15:50:22 +0200 Subject: [PATCH 070/327] IntervalSet implementation for to_interval --- src/cdomains/intDomain.ml | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/cdomains/intDomain.ml b/src/cdomains/intDomain.ml index ed6ef5a403..c0bb39518e 100644 --- a/src/cdomains/intDomain.ml +++ b/src/cdomains/intDomain.ml @@ -1270,7 +1270,9 @@ struct let of_bool _ = function true -> one | false -> zero - let to_interval = failwith "Not implemented!" (* FIXME *) + let to_interval l = match minimal l, maximal l with + | Some x, Some y -> Some (x, y) + | _ -> None let of_interval ?(suppress_ovwarn=false) ik (x,y) = norm_interval ~suppress_ovwarn ~cast:false ik (x,y) From 6a4c50afd706d64e78e8d8b94ca918d02d03aebd Mon Sep 17 00:00:00 2001 From: Alexander Schlenga Date: Fri, 9 Jun 2023 16:16:02 +0200 Subject: [PATCH 071/327] Fix to_interval functions --- src/cdomains/intDomain.ml | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-) diff --git a/src/cdomains/intDomain.ml b/src/cdomains/intDomain.ml index c0bb39518e..28fb4ae9e3 100644 --- a/src/cdomains/intDomain.ml +++ b/src/cdomains/intDomain.ml @@ -350,7 +350,7 @@ struct with Failure _ -> top_of ik - let to_interval = failwith "Not implemented!" (* FIXME *) + let to_interval x = failwith "Not implemented!" (* FIXME *) let starting ?(suppress_ovwarn=false) ik x = try Old.starting ~suppress_ovwarn ik (BI.to_int64 x) with Failure _ -> top_of ik @@ -1648,7 +1648,7 @@ struct let to_bool x = Some (to_bool' x) let of_int x = x let to_int x = Some x - let to_interval = failwith "Not implemented!" (* FIXME *) + let to_interval x = Some (x, x) let neg = Ints_t.neg let add = Ints_t.add (* TODO: signed overflow is undefined behavior! *) @@ -2152,7 +2152,9 @@ struct let top_bool = `Excluded (S.empty (), R.of_interval range_ikind (0L, 1L)) let of_interval ?(suppress_ovwarn=false) ik (x,y) = if BigInt.compare x y = 0 then of_int ik x else top_of ik - let to_interval = failwith "Not implemented!" (* FIXME *) + let to_interval l = match minimal l, maximal l with + | Some x, Some y -> Some (x, y) + | _ -> None let starting ?(suppress_ovwarn=false) ikind x = if BigInt.compare x BigInt.zero > 0 then not_zero ikind else top_of ikind let ending ?(suppress_ovwarn=false) ikind x = if BigInt.compare x BigInt.zero < 0 then not_zero ikind else top_of ikind @@ -2416,7 +2418,7 @@ struct let to_bool x = Some x let of_int x = x = Int64.zero let to_int x = if x then None else Some Int64.zero - let to_interval = failwith "Not implemented!" (* FIXME *) + let to_interval x = if x then None else Some (Int64.zero, Int64.zero) let neg x = x let add x y = x || y @@ -2546,7 +2548,9 @@ module Enums : S with type int_t = BigInt.t = struct let of_int ikind x = cast_to ikind (Inc (BISet.singleton x)) let of_interval ?(suppress_ovwarn=false) ik (x,y) = if x = y then of_int ik x else top_of ik - let to_interval = failwith "Not implemented!" (* FIXME *) + let to_interval l = match minimal l, maximal l with + | Some x, Some y -> Some (x, y) + | _ -> None let join ik = curry @@ function | Inc x, Inc y -> Inc (BISet.union x y) @@ -3282,7 +3286,7 @@ struct let project ik p t = t - let to_interval = failwith "Not implemented!" (* FIXME *) + let to_interval x = failwith "Not implemented!" (* FIXME *) end module SOverflowLifter (D : S) : SOverflow with type int_t = D.int_t and type t = D.t = struct From 1d0b8286b61655347728d3edf95a697db432a86e Mon Sep 17 00:00:00 2001 From: Alexander Schlenga Date: Fri, 9 Jun 2023 17:35:45 +0200 Subject: [PATCH 072/327] Add to_interval in valueDomainQueries.ml --- src/domains/valueDomainQueries.ml | 1 + 1 file changed, 1 insertion(+) diff --git a/src/domains/valueDomainQueries.ml b/src/domains/valueDomainQueries.ml index c89e491e58..2dfa72a430 100644 --- a/src/domains/valueDomainQueries.ml +++ b/src/domains/valueDomainQueries.ml @@ -34,6 +34,7 @@ struct let to_int x = unlift_opt I.to_int x let to_bool x = unlift_opt I.to_bool x + let to_interval x = unlift_opt I.to_interval x let is_top_of ik = unlift_is (I.is_top_of ik) From f6fd162321f7468dd371adcc5a221dfb84131e10 Mon Sep 17 00:00:00 2001 From: Johanna Schinabeck Date: Fri, 9 Jun 2023 18:26:05 +0200 Subject: [PATCH 073/327] debugging --- output.txt | 61 ++++++++++++++++++++-------- runningGob.sh | 4 +- src/analyses/termination_new.ml | 8 +--- src/framework/constraints.ml | 6 +-- src/util/terminationPreprocessing.ml | 2 +- 5 files changed, 52 insertions(+), 29 deletions(-) diff --git a/output.txt b/output.txt index 07c71d61b9..6ccb110e96 100644 --- a/output.txt +++ b/output.txt @@ -1,3 +1,26 @@ +2023-06-09 18:19:45 +'./goblint' '-v' 'tests/regression/55-loop-unrolling/01-simple-cases.c' '--set' 'ana.activated[+]' 'termination' '--enable' 'warn.debug' '--set' 'ana.activated[+]' 'apron' '--enable' 'ana.int.interval' '--set' 'ana.apron.domain' 'polyhedra' '--enable' 'justcil' +Custom include dirs: + 1. /home/johanna/goblint/goblint-analyzer/lib/linux/stub/include (exists=true) + 2. /home/johanna/goblint/goblint-analyzer/lib/sv-comp/stub/include (exists=false) + 3. /home/johanna/goblint/goblint-analyzer/lib/libc/stub/include (exists=true) + 4. /home/johanna/goblint/goblint-analyzer/lib/goblint/stub/include (exists=false) + 5. /home/johanna/goblint/goblint-analyzer/lib/linux/runtime/include (exists=false) + 6. /home/johanna/goblint/goblint-analyzer/lib/sv-comp/runtime/include (exists=false) + 7. /home/johanna/goblint/goblint-analyzer/lib/libc/runtime/include (exists=false) + 8. /home/johanna/goblint/goblint-analyzer/lib/goblint/runtime/include (exists=true) + 9. /home/johanna/goblint/goblint-analyzer/lib/linux/stub/src (exists=false) + 10. /home/johanna/goblint/goblint-analyzer/lib/sv-comp/stub/src (exists=true) + 11. /home/johanna/goblint/goblint-analyzer/lib/libc/stub/src (exists=true) + 12. /home/johanna/goblint/goblint-analyzer/lib/goblint/stub/src (exists=false) +Preprocessing files. +Preprocessor cpp: is_bad=false +'cpp' '-I' '/home/johanna/goblint/goblint-analyzer/lib/linux/stub/include' '-I' '/home/johanna/goblint/goblint-analyzer/lib/libc/stub/include' '-I' '/home/johanna/goblint/goblint-analyzer/lib/goblint/runtime/include' '-I' '/home/johanna/goblint/goblint-analyzer/lib/sv-comp/stub/src' '-I' '/home/johanna/goblint/goblint-analyzer/lib/libc/stub/src' '/home/johanna/goblint/goblint-analyzer/lib/libc/stub/src/pthread.c' '-o' '.goblint/preprocessed/pthread.i' +'cpp' '-I' '/home/johanna/goblint/goblint-analyzer/lib/linux/stub/include' '-I' '/home/johanna/goblint/goblint-analyzer/lib/libc/stub/include' '-I' '/home/johanna/goblint/goblint-analyzer/lib/goblint/runtime/include' '-I' '/home/johanna/goblint/goblint-analyzer/lib/sv-comp/stub/src' '-I' '/home/johanna/goblint/goblint-analyzer/lib/libc/stub/src' '/home/johanna/goblint/goblint-analyzer/lib/libc/stub/src/stdlib.c' '-o' '.goblint/preprocessed/stdlib.i' +'cpp' '-I' '/home/johanna/goblint/goblint-analyzer/lib/linux/stub/include' '-I' '/home/johanna/goblint/goblint-analyzer/lib/libc/stub/include' '-I' '/home/johanna/goblint/goblint-analyzer/lib/goblint/runtime/include' '-I' '/home/johanna/goblint/goblint-analyzer/lib/sv-comp/stub/src' '-I' '/home/johanna/goblint/goblint-analyzer/lib/libc/stub/src' 'tests/regression/55-loop-unrolling/01-simple-cases.c' '-o' '.goblint/preprocessed/01-simple-cases.i' +Parsing files. +Constructors: +Adding constructors to: main /* Generated by CIL v. 2.0.1-48-g4df989f */ /* print_CIL_Input is true */ @@ -1123,7 +1146,7 @@ void example1(void) while_break: /* CIL Label */ ; } #line 27 - term_exit- = term27_5-file_01-simple-cases; + __goblint_bounded(term27_5-file_01-simple-cases); } #line 32 __goblint_check(a[0] == 0); @@ -1165,7 +1188,7 @@ void example2(void) while_break: /* CIL Label */ ; } #line 42 - term_exit- = term42_5-file_01-simple-cases; + __goblint_bounded(term42_5-file_01-simple-cases); } #line 47 __goblint_check(a[0] == 0); @@ -1207,7 +1230,7 @@ void example3(void) while_break: /* CIL Label */ ; } #line 57 - term_exit- = term57_5-file_01-simple-cases; + __goblint_bounded(term57_5-file_01-simple-cases); } #line 62 __goblint_check(a[0] == 0); @@ -1266,7 +1289,7 @@ void example4(void) while_break: /* CIL Label */ ; } #line 74 - term_exit- = term74_5-file_01-simple-cases; + __goblint_bounded(term74_5-file_01-simple-cases); } #line 82 __goblint_check(a[0] == 0); @@ -1321,7 +1344,7 @@ void example5(void) while_break: /* CIL Label */ ; } #line 95 - term_exit- = term95_5-file_01-simple-cases; + __goblint_bounded(term95_5-file_01-simple-cases); } #line 107 __goblint_check(a[0] == 0); @@ -1370,7 +1393,7 @@ void example6(void) while_break: /* CIL Label */ ; } #line 119 - term_exit- = term119_5-file_01-simple-cases; + __goblint_bounded(term119_5-file_01-simple-cases); } #line 125 __goblint_check(a[0] == 0); @@ -1433,7 +1456,7 @@ void example7(void) while_break: /* CIL Label */ ; } #line 143 - term_exit- = term143_2-file_01-simple-cases; + __goblint_bounded(term143_2-file_01-simple-cases); } #line 147 __goblint_check(a[0] == 0); @@ -1506,7 +1529,7 @@ void example8(void) while_break___0: /* CIL Label */ ; } #line 160 - term_exit- = term160_9-file_01-simple-cases; + __goblint_bounded(term160_9-file_01-simple-cases); } #line 164 i ++; @@ -1514,7 +1537,7 @@ void example8(void) while_break: /* CIL Label */ ; } #line 157 - term_exit- = term157_2-file_01-simple-cases; + __goblint_bounded(term157_2-file_01-simple-cases); } #line 166 return; @@ -1557,7 +1580,7 @@ void example9(void) while_break: /* CIL Label */ ; } #line 174 - term_exit- = term174_2-file_01-simple-cases; + __goblint_bounded(term174_2-file_01-simple-cases); } #line 179 return; @@ -1602,7 +1625,7 @@ void example10(void) while_break: /* CIL Label */ ; } #line 187 - term_exit- = term187_2-file_01-simple-cases; + __goblint_bounded(term187_2-file_01-simple-cases); } #line 195 return; @@ -2081,7 +2104,7 @@ void qsort(void *ptr , size_t count , size_t size , int (*comp)(void const * , while_break___0: /* CIL Label */ ; } #line 10 - term_exit- = term10_5-file_stdlib; + __goblint_bounded(term10_5-file_stdlib); } #line 9 i ++; @@ -2089,7 +2112,7 @@ void qsort(void *ptr , size_t count , size_t size , int (*comp)(void const * , while_break: /* CIL Label */ ; } #line 9 - term_exit- = term9_3-file_stdlib; + __goblint_bounded(term9_3-file_stdlib); } #line 16 i___0 = (size_t )0; @@ -2157,7 +2180,7 @@ void qsort(void *ptr , size_t count , size_t size , int (*comp)(void const * , while_break___3: /* CIL Label */ ; } #line 21 - term_exit- = term21_9-file_stdlib; + __goblint_bounded(term21_9-file_stdlib); } } #line 17 @@ -2166,7 +2189,7 @@ void qsort(void *ptr , size_t count , size_t size , int (*comp)(void const * , while_break___2: /* CIL Label */ ; } #line 17 - term_exit- = term17_5-file_stdlib; + __goblint_bounded(term17_5-file_stdlib); } #line 16 i___0 ++; @@ -2174,7 +2197,7 @@ void qsort(void *ptr , size_t count , size_t size , int (*comp)(void const * , while_break___1: /* CIL Label */ ; } #line 16 - term_exit- = term16_3-file_stdlib; + __goblint_bounded(term16_3-file_stdlib); } #line 33 return; @@ -2227,9 +2250,13 @@ void *bsearch(void const *key , void const *ptr , size_t count , size_t size while_break: /* CIL Label */ ; } #line 40 - term_exit- = term40_3-file_stdlib; + __goblint_bounded(term40_3-file_stdlib); } #line 47 return ((void *)0); } } + +vars = 0 evals = 0 narrow_reuses = 0 + +Timings: diff --git a/runningGob.sh b/runningGob.sh index 52d0830b81..e9d7ab1405 100755 --- a/runningGob.sh +++ b/runningGob.sh @@ -16,8 +16,8 @@ cfile_goto="tests/incremental/02-cfg-comparison/01-added-return-stmt.c" #./goblint $cfile_loops $options_apron --html # run analysis, write cil output to file and enable visualization via html -./goblint $cfile_loops $options_term --enable justcil > output.txt -./goblint $cfile_loops $options_term --html +#./goblint -v $cfile_loops $options_term --enable justcil > output.txt +./goblint -v $cfile_loops $options_term --html # set up server to see visualizatino python3 -m http.server --directory result 8081 diff --git a/src/analyses/termination_new.ml b/src/analyses/termination_new.ml index bff776b95d..bd2057effe 100644 --- a/src/analyses/termination_new.ml +++ b/src/analyses/termination_new.ml @@ -80,10 +80,6 @@ end let () = (** Register the preprocessing *) -<<<<<<< HEAD - Cilfacade.register_preprocess_cil (Spec.name ()) (new loopCounterVisitor loopCounters upjumpingGotos loopExit); -======= - Cilfacade.register_preprocess_cil (Spec.name ()) (new loopCounterVisitor loopCounters); ->>>>>>> dfa9d6ef8 (changed loop exit indicator form global variable to a special function) - (** Register this analysis within the master control program *) +Cilfacade.register_preprocess_cil (Spec.name ()) (new loopCounterVisitor loopCounters upjumpingGotos loopExit); +(** Register this analysis within the master control program *) MCP.register_analysis (module Spec : MCPSpec) diff --git a/src/framework/constraints.ml b/src/framework/constraints.ml index 287726419f..0d68a1a028 100644 --- a/src/framework/constraints.ml +++ b/src/framework/constraints.ml @@ -1970,14 +1970,14 @@ struct sideg (V.contexts f) (G.create_contexts (G.CMap.singleton (c) (t))) let enter ctx lval fundec exprList = (*TODO*) - S.enter (conv ctx) lval fundec exprList; - let c: unit -> S.C.t = snd var |> Obj.obj in (*Callee context*) + S.enter (conv ctx) lval fundec exprList + (*let c: unit -> S.C.t = snd var |> Obj.obj in (*Callee context*) let fd = fundec in (*Callee fundec*) let c' = ctx.context in (*Caller context*) (*TODO is this the caller or callee context???*) let fd' = in (*Caller fundec*) let tup = (fundec * c') in (* TODO: is fundec the caller or callee fundec???*) let t = G.CSet.singleton (tup) in (*TODO do we fill the set correctly???*) - side_context sideg fd (c ()) t + side_context sideg fd (c ()) t*) let paths_as_set ctx = S.paths_as_set (conv ctx) let body ctx = S.body (conv ctx) diff --git a/src/util/terminationPreprocessing.ml b/src/util/terminationPreprocessing.ml index 15a5c948fd..41c5b3f9d7 100644 --- a/src/util/terminationPreprocessing.ml +++ b/src/util/terminationPreprocessing.ml @@ -23,7 +23,7 @@ let extract_file_name s = (*There still may be a need to filt let show_location_id l = string_of_int l.line ^ "_" ^ string_of_int l.column ^ "-file" ^ "_" ^ extract_file_name l.file -class loopCounterVisitor lc (fd : fundec) = object(self) +class loopCounterVisitor lc lg le (fd : fundec) = object(self) inherit nopCilVisitor method! vstmt s = let action s = match s.skind with From 5ae6485e116db3eb00b6653a747262e821b8fc06 Mon Sep 17 00:00:00 2001 From: Alexander Schlenga Date: Fri, 9 Jun 2023 18:48:14 +0200 Subject: [PATCH 074/327] Fix check_bounded --- src/analyses/termination_new.ml | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/analyses/termination_new.ml b/src/analyses/termination_new.ml index f1dde59c64..8629cac17f 100644 --- a/src/analyses/termination_new.ml +++ b/src/analyses/termination_new.ml @@ -20,21 +20,21 @@ let is_loop_exit_indicator (x : varinfo) = (* checks if at the current location (=loc) of the analysis an upjumping goto was already reached true: no upjumping goto was reached till now*) -let currrently_no_upjumping_gotos (loc : location) = +let currrently_no_upjumping_gotos (loc : location) = List.for_all (function (l) -> (l >= loc)) upjumpingGotos.contents -let no_upjumping_gotos () = +let no_upjumping_gotos () = (List.length upjumpingGotos.contents) <= 0 (** Checks whether a variable can be bounded *) let check_bounded ctx varinfo = - let open IntDomain.IntDomTuple in (* TODO: Remove *) - let open Cil in + let open IntDomain.IntDomTuple in let exp = Lval (Var varinfo, NoOffset) in match ctx.ask (EvalInt exp) with - `Top -> print_endline (varinfo.vname ^ " is TOP"); false + | `Top -> print_endline (varinfo.vname ^ " is TOP"); false | `Bot -> print_endline (varinfo.vname ^ " is BOT"); raise (PreProcessing "Loop variable is Bot") - | `Lifted v -> print_endline (varinfo.vname ^ " is " ^ IntDomain.IntDomTuple.show v); not (is_top v) (* TODO: Is this sound? *) + | `Lifted v -> print_endline (varinfo.vname ^ " is " ^ IntDomain.IntDomTuple.show v); + not (is_top_of (ikind v) v) module Spec : Analyses.MCPSpec = struct From b6e08f2d3efb4feebf4bf82f2d346666e2b9d9ee Mon Sep 17 00:00:00 2001 From: Alexander Schlenga Date: Fri, 9 Jun 2023 18:50:22 +0200 Subject: [PATCH 075/327] Remove debug output --- src/analyses/termination_new.ml | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/src/analyses/termination_new.ml b/src/analyses/termination_new.ml index 8629cac17f..1eac676d91 100644 --- a/src/analyses/termination_new.ml +++ b/src/analyses/termination_new.ml @@ -31,10 +31,9 @@ let check_bounded ctx varinfo = let open IntDomain.IntDomTuple in let exp = Lval (Var varinfo, NoOffset) in match ctx.ask (EvalInt exp) with - | `Top -> print_endline (varinfo.vname ^ " is TOP"); false - | `Bot -> print_endline (varinfo.vname ^ " is BOT"); raise (PreProcessing "Loop variable is Bot") - | `Lifted v -> print_endline (varinfo.vname ^ " is " ^ IntDomain.IntDomTuple.show v); - not (is_top_of (ikind v) v) + | `Top -> false + | `Lifted v -> not (is_top_of (ikind v) v) + | `Bot -> raise (PreProcessing "Loop variable is Bot") module Spec : Analyses.MCPSpec = struct From beb56834d29cdb0dd2497dfb9e3dc113b17ca8e5 Mon Sep 17 00:00:00 2001 From: Johanna Schinabeck Date: Fri, 9 Jun 2023 20:00:41 +0200 Subject: [PATCH 076/327] it runs! :)) but it is not possible to see the global invariant on the html output yet --- runningGob.sh | 2 +- src/framework/analyses.ml | 5 +- src/framework/constraints.ml | 189 ++++++++++++++++++++++++++++++++--- src/framework/control.ml | 1 + 4 files changed, 180 insertions(+), 17 deletions(-) diff --git a/runningGob.sh b/runningGob.sh index e9d7ab1405..848d69c341 100755 --- a/runningGob.sh +++ b/runningGob.sh @@ -17,7 +17,7 @@ cfile_goto="tests/incremental/02-cfg-comparison/01-added-return-stmt.c" # run analysis, write cil output to file and enable visualization via html #./goblint -v $cfile_loops $options_term --enable justcil > output.txt -./goblint -v $cfile_loops $options_term --html +./goblint $cfile_loops $options_term --html # set up server to see visualizatino python3 -m http.server --directory result 8081 diff --git a/src/framework/analyses.ml b/src/framework/analyses.ml index 41448768a9..993aaf6421 100644 --- a/src/framework/analyses.ml +++ b/src/framework/analyses.ml @@ -166,7 +166,6 @@ struct struct include MapDomain.MapBot (C_ (C)) (CSet) let printXml f c = BatPrintf.fprintf f "%a" printXml c (* TODO *) - let printXml_ f c = BatPrintf.fprintf f "%a" CSet.printXml c (* TODO *) end include Lattice.Lift2 (G) (CMap) (Printable.DefaultNames) @@ -184,8 +183,8 @@ struct let printXml f = function | `Lifted1 x -> G.printXml f x - | `Lifted2 x -> BatPrintf.fprintf f "%a" CMap.printXml x - | x -> BatPrintf.fprintf f "%a" printXml x + | `Lifted2 x -> BatPrintf.fprintf f "%a" CMap.printXml x + | x -> BatPrintf.fprintf f "%a" printXml x let s = function (*TODO: does this work? copied from DeadBranch*) | `Bot -> G.bot () diff --git a/src/framework/constraints.ml b/src/framework/constraints.ml index 0d68a1a028..1614354cfa 100644 --- a/src/framework/constraints.ml +++ b/src/framework/constraints.ml @@ -1457,6 +1457,145 @@ struct let event ctx e octx = S.event (conv ctx) e (conv octx) end + +module DeadBranchLifter2 (S: Spec): Spec = +struct + include S + + let name () = "DeadBranch2 (" ^ S.name () ^ ")" + + (* Two global invariants: + 1. S.V -> S.G -- used for S + 2. node -> (exp -> flat bool) -- used for warnings *) + + module V = + struct + include Printable.Either (S.V) (Node) + let name () = "DeadBranch2" + let s x = `Left x + let node x = `Right x + let is_write_only = function + | `Left x -> S.V.is_write_only x + | `Right _ -> true + end + + module EM = + struct + include MapDomain.MapBot (Basetype.CilExp) (Basetype.Bools) + let name () = "branches2" + end + + module G = + struct + include Lattice.Lift2 (S.G) (EM) (Printable.DefaultNames) + let name () = "deadbranch2" + + let s = function + | `Bot -> S.G.bot () + | `Lifted1 x -> x + | _ -> failwith "DeadBranchLifter2.s" + let node = function + | `Bot -> EM.bot () + | `Lifted2 x -> x + | _ -> failwith "DeadBranchLifter2.node" + let create_s s = `Lifted1 s + let create_node node = `Lifted2 node + + let printXml f = function + | `Lifted1 x -> S.G.printXml f x + | `Lifted2 x -> BatPrintf.fprintf f "%a" EM.printXml x + | x -> BatPrintf.fprintf f "%a" printXml x + end + + let conv (ctx: (_, G.t, _, V.t) ctx): (_, S.G.t, _, S.V.t) ctx = + { ctx with + global = (fun v -> G.s (ctx.global (V.s v))); + sideg = (fun v g -> ctx.sideg (V.s v) (G.create_s g)); + } + + let query ctx (type a) (q: a Queries.t): a Queries.result = + match q with + | WarnGlobal g -> + let g: V.t = Obj.obj g in + begin match g with + | `Left g -> + S.query (conv ctx) (WarnGlobal (Obj.repr g)) + | `Right g -> + let em = G.node (ctx.global (V.node g)) in + EM.iter (fun exp tv -> + match tv with + | `Lifted tv -> + let loc = Node.location g in (* TODO: looking up location now doesn't work nicely with incremental *) + let cilinserted = if loc.synthetic then "(possibly inserted by CIL) " else "" in + M.warn ~loc:(Node g) ~tags:[CWE (if tv then 571 else 570)] ~category:Deadcode "condition '%a' %sis always %B" d_exp exp cilinserted tv + | `Bot when not (CilType.Exp.equal exp one) -> (* all branches dead *) + M.error ~loc:(Node g) ~category:Analyzer ~tags:[Category Unsound] "both branches over condition '%a' are dead" d_exp exp + | `Bot (* all branches dead, fine at our inserted Neg(1)-s because no Pos(1) *) + | `Top -> (* may be both true and false *) + () + ) em; + end + | InvariantGlobal g -> + let g: V.t = Obj.obj g in + begin match g with + | `Left g -> + S.query (conv ctx) (InvariantGlobal (Obj.repr g)) + | `Right g -> + Queries.Result.top q + end + | IterSysVars (vq, vf) -> + (* vars for S *) + let vf' x = vf (Obj.repr (V.s (Obj.obj x))) in + S.query (conv ctx) (IterSysVars (vq, vf')); + + (* node vars for dead branches *) + begin match vq with + | Node {node; _} -> + vf (Obj.repr (V.node node)) + | _ -> + () + end + | _ -> + S.query (conv ctx) q + + + let branch ctx = S.branch (conv ctx) + + let branch ctx exp tv = + if !AnalysisState.postsolving then ( + try + let r = branch ctx exp tv in + (* branch is live *) + ctx.sideg (V.node ctx.prev_node) (G.create_node (EM.singleton exp (`Lifted tv))); (* record expression with reached tv *) + r + with Deadcode -> + (* branch is dead *) + ctx.sideg (V.node ctx.prev_node) (G.create_node (EM.singleton exp `Bot)); (* record expression without reached tv *) + raise Deadcode + ) + else ( + ctx.sideg (V.node ctx.prev_node) (G.create_node (EM.bot ())); (* create global variable during solving, to allow postsolving leq hack to pass verify *) + branch ctx exp tv + ) + + let assign ctx = S.assign (conv ctx) + let vdecl ctx = S.vdecl (conv ctx) + let enter ctx = S.enter (conv ctx) + let paths_as_set ctx = S.paths_as_set (conv ctx) + let body ctx = S.body (conv ctx) + let return ctx = S.return (conv ctx) + let combine_env ctx = S.combine_env (conv ctx) + let combine_assign ctx = S.combine_assign (conv ctx) + let special ctx = S.special (conv ctx) + let threadenter ctx = S.threadenter (conv ctx) + let threadspawn ctx lv f args fctx = S.threadspawn (conv ctx) lv f args (conv fctx) + let sync ctx = S.sync (conv ctx) + let skip ctx = S.skip (conv ctx) + let asm ctx = S.asm (conv ctx) + let event ctx e octx = S.event (conv ctx) e (conv octx) +end + + module LongjmpLifter (S: Spec): Spec = struct include S @@ -1929,8 +2068,6 @@ end module RecursionTermLifter (S: Spec) : Spec with module D = S.D and module C = S.C - and module G = GVarGG (S.G) (S.C) - and module V = GVarF(S.V) = (*global invariant - fundec -> Map (S.C) (Set (fundec * S.C)) @@ -1939,7 +2076,11 @@ module RecursionTermLifter (S: Spec) struct include S - module V = GVarF(S.V) + module V = + struct + include GVarF(S.V) + let s = spec + end module G = GVarGG (S.G) (S.C) @@ -1957,7 +2098,26 @@ struct global = (fun v -> G.s (ctx.global (V.spec v))); sideg = (fun v g -> ctx.sideg (V.spec v) (G.create_s g)); } - let query ctx = S.query (conv ctx) + let query ctx (type a) (q: a Queries.t): a Queries.result = + match q with + | WarnGlobal g -> + let g: V.t = Obj.obj g in + begin match g with + | `Left g -> + S.query (conv ctx) (WarnGlobal (Obj.repr g)) + | `Right g -> + Queries.Result.top q + end + | InvariantGlobal g -> + let g: V.t = Obj.obj g in + begin match g with + | `Left g -> + S.query (conv ctx) (InvariantGlobal (Obj.repr g)) + | `Right g -> + Queries.Result.top q + end + | _ -> S.query (conv ctx) q + let branch ctx = S.branch (conv ctx) let assign ctx = S.assign (conv ctx) let vdecl ctx = S.vdecl (conv ctx) @@ -1969,15 +2129,18 @@ struct if !AnalysisState.postsolving then sideg (V.contexts f) (G.create_contexts (G.CMap.singleton (c) (t))) - let enter ctx lval fundec exprList = (*TODO*) - S.enter (conv ctx) lval fundec exprList - (*let c: unit -> S.C.t = snd var |> Obj.obj in (*Callee context*) - let fd = fundec in (*Callee fundec*) - let c' = ctx.context in (*Caller context*) (*TODO is this the caller or callee context???*) - let fd' = in (*Caller fundec*) - let tup = (fundec * c') in (* TODO: is fundec the caller or callee fundec???*) - let t = G.CSet.singleton (tup) in (*TODO do we fill the set correctly???*) - side_context sideg fd (c ()) t*) + let enter ctx lval fu exprList = (*TODO*) + if !AnalysisState.postsolving then + let c_r: unit -> S.C.t = ctx.context in (*Caller context*) (*TODO is this the caller or callee context???*) + let fd_r : fundec = fu in (*Caller fundec*) (*TODO: Falsch??*) + let c_e : unit -> S.C.t = ctx.context in (*Callee context*) (*TODO: Falsch??*) + let fd_e : fundec = fu in (*Callee fundec*) + let tup: (fundec * S.C.t) = (fd_r, (c_r ())) in (* TODO: is fundec the caller or callee fundec???*) + let t = G.CSet.singleton (tup) in (*TODO do we fill the set correctly???*) + side_context ctx.sideg fd_e (c_e ()) t; + S.enter (conv ctx) lval fu exprList + else + S.enter (conv ctx) lval fu exprList let paths_as_set ctx = S.paths_as_set (conv ctx) let body ctx = S.body (conv ctx) diff --git a/src/framework/control.ml b/src/framework/control.ml index bd26fa7129..0a36d6c989 100644 --- a/src/framework/control.ml +++ b/src/framework/control.ml @@ -37,6 +37,7 @@ let spec_module: (module Spec) Lazy.t = lazy ( |> lift (get_bool "ana.widen.tokens") (module WideningTokens.Lifter) |> lift true (module LongjmpLifter) |> lift true (module RecursionTermLifter)(*TODO: should we really always evaluate it???*) + |> lift (get_bool "ana.dead-code.branches") (module DeadBranchLifter2) ) in GobConfig.building_spec := false; ControlSpecC.control_spec_c := (module S1.C); From b01d69e94d12defa37810b8516e9d9b744cdbbfe Mon Sep 17 00:00:00 2001 From: Alexander Schlenga Date: Wed, 14 Jun 2023 13:11:40 +0200 Subject: [PATCH 077/327] Remove unused stuff --- src/analyses/termination_new.ml | 5 ----- 1 file changed, 5 deletions(-) diff --git a/src/analyses/termination_new.ml b/src/analyses/termination_new.ml index 1eac676d91..ef623b468b 100644 --- a/src/analyses/termination_new.ml +++ b/src/analyses/termination_new.ml @@ -3,7 +3,6 @@ open Analyses open GoblintCil open TerminationPreprocessing -include Printf exception PreProcessing of string @@ -63,10 +62,6 @@ struct D.add x is_bounded ctx.local | _ -> ctx.local - let branch ctx (exp : exp) (tv : bool) = - ctx.local (* TODO: Do we actually need a branch transfer function? *) - - (* provides information to Goblint*) let query ctx (type a) (q: a Queries.t): a Queries.result = let open Queries in From 6ee3312220b2838ea34033be3fc81ca995232be6 Mon Sep 17 00:00:00 2001 From: Alexander Schlenga Date: Wed, 14 Jun 2023 13:17:44 +0200 Subject: [PATCH 078/327] Make things nice, update comments --- src/analyses/termination_new.ml | 25 ++++++++++++++----------- 1 file changed, 14 insertions(+), 11 deletions(-) diff --git a/src/analyses/termination_new.ml b/src/analyses/termination_new.ml index ef623b468b..4eced288df 100644 --- a/src/analyses/termination_new.ml +++ b/src/analyses/termination_new.ml @@ -7,7 +7,9 @@ open TerminationPreprocessing exception PreProcessing of string let loopCounters : varinfo list ref = ref [] -let upjumpingGotos : location list ref = ref [] (*contains the locations of the upjumping gotos*) + +(* Contains the locations of the upjumping gotos *) +let upjumpingGotos : location list ref = ref [] let loopExit : varinfo ref = ref (makeVarinfo false "-error" Cil.intType) @@ -17,8 +19,9 @@ let is_loop_counter_var (x : varinfo) = let is_loop_exit_indicator (x : varinfo) = x = !loopExit -(* checks if at the current location (=loc) of the analysis an upjumping goto was already reached - true: no upjumping goto was reached till now*) +(** Checks whether at the current location (=loc) of the analysis an + * upjumping goto was already reached. Returns true if no upjumping goto was + * reached until now *) let currrently_no_upjumping_gotos (loc : location) = List.for_all (function (l) -> (l >= loc)) upjumpingGotos.contents @@ -49,33 +52,33 @@ struct include Analyses.IdentitySpec let assign ctx (lval : lval) (rval : exp) = - (* Detect loop counter variable assignment to 0 *) + (* Detect assignment to loop counter variable *) match lval, rval with - (* Assume that the following loop does not terminate *) (Var x, NoOffset), _ when is_loop_counter_var x -> + (* Assume that the following loop does not terminate *) if not (no_upjumping_gotos ()) then printf "\n4 problem\n"; D.add x false ctx.local - (* Loop exit: Check whether loop counter variable is bounded *) | (Var y, NoOffset), Lval (Var x, NoOffset) when is_loop_exit_indicator y -> + (* Loop exit: Check whether loop counter variable is bounded *) let is_bounded = check_bounded ctx x in if not (no_upjumping_gotos ()) then printf "\n5 problem\n"; D.add x is_bounded ctx.local | _ -> ctx.local - (* provides information to Goblint*) + (** Provides information to Goblint *) let query ctx (type a) (q: a Queries.t): a Queries.result = let open Queries in match q with | Queries.MustTermLoop v when check_bounded ctx v -> - true (* TODO should we use the checl_bound function?*) + true (* TODO should we use the check_bounded function? *) | Queries.MustTermProg -> - true (*TODO check if all values in the domain are true -> true*) + true (*TODO check if all values in the domain are true -> true *) | _ -> Result.top q end let () = - (** Register the preprocessing *) + (* Register the preprocessing *) Cilfacade.register_preprocess_cil (Spec.name ()) (new loopCounterVisitor loopCounters upjumpingGotos loopExit); - (** Register this analysis within the master control program *) + (* Register this analysis within the master control program *) MCP.register_analysis (module Spec : MCPSpec) From 3cc743ab2e55758c0f5e58c51188f24b5d487d37 Mon Sep 17 00:00:00 2001 From: Alexander Schlenga Date: Wed, 14 Jun 2023 13:21:49 +0200 Subject: [PATCH 079/327] Unify style to snake_case --- src/analyses/termination_new.ml | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/src/analyses/termination_new.ml b/src/analyses/termination_new.ml index 4eced288df..7a7f046c39 100644 --- a/src/analyses/termination_new.ml +++ b/src/analyses/termination_new.ml @@ -6,27 +6,27 @@ open TerminationPreprocessing exception PreProcessing of string -let loopCounters : varinfo list ref = ref [] +let loop_counters : varinfo list ref = ref [] (* Contains the locations of the upjumping gotos *) -let upjumpingGotos : location list ref = ref [] +let upjumping_gotos : location list ref = ref [] -let loopExit : varinfo ref = ref (makeVarinfo false "-error" Cil.intType) +let loop_exit : varinfo ref = ref (makeVarinfo false "-error" Cil.intType) let is_loop_counter_var (x : varinfo) = - List.mem x !loopCounters + List.mem x !loop_counters let is_loop_exit_indicator (x : varinfo) = - x = !loopExit + x = !loop_exit (** Checks whether at the current location (=loc) of the analysis an * upjumping goto was already reached. Returns true if no upjumping goto was * reached until now *) let currrently_no_upjumping_gotos (loc : location) = - List.for_all (function (l) -> (l >= loc)) upjumpingGotos.contents + List.for_all (function (l) -> (l >= loc)) upjumping_gotos.contents let no_upjumping_gotos () = - (List.length upjumpingGotos.contents) <= 0 + (List.length upjumping_gotos.contents) <= 0 (** Checks whether a variable can be bounded *) let check_bounded ctx varinfo = @@ -79,6 +79,6 @@ end let () = (* Register the preprocessing *) - Cilfacade.register_preprocess_cil (Spec.name ()) (new loopCounterVisitor loopCounters upjumpingGotos loopExit); + Cilfacade.register_preprocess_cil (Spec.name ()) (new loopCounterVisitor loop_counters upjumping_gotos loop_exit); (* Register this analysis within the master control program *) MCP.register_analysis (module Spec : MCPSpec) From ba6eaa170392bde34e82ac84d533a4e837f48d74 Mon Sep 17 00:00:00 2001 From: Alexander Schlenga Date: Wed, 14 Jun 2023 13:24:00 +0200 Subject: [PATCH 080/327] Make ocamldoc comment --- src/analyses/termination_new.ml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/analyses/termination_new.ml b/src/analyses/termination_new.ml index 7a7f046c39..9c87a4038e 100644 --- a/src/analyses/termination_new.ml +++ b/src/analyses/termination_new.ml @@ -8,7 +8,7 @@ exception PreProcessing of string let loop_counters : varinfo list ref = ref [] -(* Contains the locations of the upjumping gotos *) +(** Contains the locations of the upjumping gotos *) let upjumping_gotos : location list ref = ref [] let loop_exit : varinfo ref = ref (makeVarinfo false "-error" Cil.intType) From 8f457230d7cee30965a124933963f8908b01a28f Mon Sep 17 00:00:00 2001 From: Alexander Schlenga Date: Wed, 14 Jun 2023 13:39:59 +0200 Subject: [PATCH 081/327] Remove debug output --- src/analyses/termination_new.ml | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/analyses/termination_new.ml b/src/analyses/termination_new.ml index 9c87a4038e..19198c4ca9 100644 --- a/src/analyses/termination_new.ml +++ b/src/analyses/termination_new.ml @@ -56,12 +56,10 @@ struct match lval, rval with (Var x, NoOffset), _ when is_loop_counter_var x -> (* Assume that the following loop does not terminate *) - if not (no_upjumping_gotos ()) then printf "\n4 problem\n"; D.add x false ctx.local | (Var y, NoOffset), Lval (Var x, NoOffset) when is_loop_exit_indicator y -> (* Loop exit: Check whether loop counter variable is bounded *) let is_bounded = check_bounded ctx x in - if not (no_upjumping_gotos ()) then printf "\n5 problem\n"; D.add x is_bounded ctx.local | _ -> ctx.local From f66d46fac00e6ecbe4d7dbf4cf4367b35e877e74 Mon Sep 17 00:00:00 2001 From: Alexander Schlenga Date: Wed, 14 Jun 2023 14:03:26 +0200 Subject: [PATCH 082/327] Implement preliminary query function --- src/analyses/termination_new.ml | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) diff --git a/src/analyses/termination_new.ml b/src/analyses/termination_new.ml index 19198c4ca9..503b3f2d51 100644 --- a/src/analyses/termination_new.ml +++ b/src/analyses/termination_new.ml @@ -59,18 +59,26 @@ struct D.add x false ctx.local | (Var y, NoOffset), Lval (Var x, NoOffset) when is_loop_exit_indicator y -> (* Loop exit: Check whether loop counter variable is bounded *) + (* TODO: Move *) let is_bounded = check_bounded ctx x in D.add x is_bounded ctx.local | _ -> ctx.local + let special ctx (lval : lval option) (f : varinfo) (arglist : exp list) = + (* TODO: Implement check for our special loop exit indicator function *) + ctx.local + (** Provides information to Goblint *) + (* TODO: Consider gotos and recursion *) let query ctx (type a) (q: a Queries.t): a Queries.result = let open Queries in match q with - | Queries.MustTermLoop v when check_bounded ctx v -> - true (* TODO should we use the check_bounded function? *) + | Queries.MustTermLoop v -> + (match D.find_opt v ctx.local with + Some b -> b + | None -> Result.top q) | Queries.MustTermProg -> - true (*TODO check if all values in the domain are true -> true *) + D.for_all (fun loop term_info -> term_info) ctx.local | _ -> Result.top q end From d0b42d1b5b57fc7c2e0f884ea3ef2c4ea86db8f7 Mon Sep 17 00:00:00 2001 From: Alexander Schlenga Date: Wed, 14 Jun 2023 14:20:10 +0200 Subject: [PATCH 083/327] Remove function to_interval --- src/cdomains/intDomain.ml | 25 ------------------------- src/cdomains/intDomain.mli | 13 +++++-------- src/domains/valueDomainQueries.ml | 1 - 3 files changed, 5 insertions(+), 34 deletions(-) diff --git a/src/cdomains/intDomain.ml b/src/cdomains/intDomain.ml index 9932e2fa67..df0a4c0507 100644 --- a/src/cdomains/intDomain.ml +++ b/src/cdomains/intDomain.ml @@ -171,7 +171,6 @@ sig val equal_to: int_t -> t -> [`Eq | `Neq | `Top] val to_bool: t -> bool option - val to_interval: t -> (int_t * int_t) option val to_excl_list: t -> (int_t list * (int64 * int64)) option val of_excl_list: Cil.ikind -> int_t list -> t val is_excl_list: t -> bool @@ -350,8 +349,6 @@ struct with Failure _ -> top_of ik - let to_interval x = failwith "Not implemented!" (* FIXME *) - let starting ?(suppress_ovwarn=false) ik x = try Old.starting ~suppress_ovwarn ik (BI.to_int64 x) with Failure _ -> top_of ik let ending ?(suppress_ovwarn=false) ik x = @@ -431,7 +428,6 @@ struct let of_excl_list ikind is = {v = I.of_excl_list ikind is; ikind} let is_excl_list x = I.is_excl_list x.v let to_incl_list x = I.to_incl_list x.v - let to_interval x = I.to_interval x.v let of_interval ?(suppress_ovwarn=false) ikind (lb,ub) = {v = I.of_interval ~suppress_ovwarn ikind (lb,ub); ikind} let of_congruence ikind (c,m) = {v = I.of_congruence ikind (c,m); ikind} let starting ?(suppress_ovwarn=false) ikind i = {v = I.starting ~suppress_ovwarn ikind i; ikind} @@ -712,7 +708,6 @@ struct (* TODO: change to_int signature so it returns a big_int *) let to_int x = Option.bind x (IArith.to_int) - let to_interval = Fun.id let of_interval ?(suppress_ovwarn=false) ik (x,y) = norm ~suppress_ovwarn ik @@ Some (x,y) let of_int ik (x: int_t) = of_interval ik (x,x) let zero = Some IArith.zero @@ -1270,10 +1265,6 @@ struct let of_bool _ = function true -> one | false -> zero - let to_interval l = match minimal l, maximal l with - | Some x, Some y -> Some (x, y) - | _ -> None - let of_interval ?(suppress_ovwarn=false) ik (x,y) = norm_interval ~suppress_ovwarn ~cast:false ik (x,y) let of_int ik (x: int_t) = of_interval ik (x, x) @@ -1648,7 +1639,6 @@ struct let to_bool x = Some (to_bool' x) let of_int x = x let to_int x = Some x - let to_interval x = Some (x, x) let neg = Ints_t.neg let add = Ints_t.add (* TODO: signed overflow is undefined behavior! *) @@ -1723,7 +1713,6 @@ struct let of_excl_list ik x = top_of ik let is_excl_list x = false let to_incl_list x = None - let to_interval x = None let of_interval ?(suppress_ovwarn=false) ik x = top_of ik let of_congruence ik x = top_of ik let starting ?(suppress_ovwarn=false) ikind x = top_of ikind @@ -1807,10 +1796,6 @@ struct | `Bot, `Bot -> `Bot | _ -> `Top - let to_interval = function - | `Lifted x -> Base.to_interval x - | _ -> None - let neg = lift1 Base.neg let add = lift2 Base.add let sub = lift2 Base.sub @@ -2152,9 +2137,6 @@ struct let top_bool = `Excluded (S.empty (), R.of_interval range_ikind (0L, 1L)) let of_interval ?(suppress_ovwarn=false) ik (x,y) = if BigInt.compare x y = 0 then of_int ik x else top_of ik - let to_interval l = match minimal l, maximal l with - | Some x, Some y -> Some (x, y) - | _ -> None let starting ?(suppress_ovwarn=false) ikind x = if BigInt.compare x BigInt.zero > 0 then not_zero ikind else top_of ikind let ending ?(suppress_ovwarn=false) ikind x = if BigInt.compare x BigInt.zero < 0 then not_zero ikind else top_of ikind @@ -2418,7 +2400,6 @@ struct let to_bool x = Some x let of_int x = x = Int64.zero let to_int x = if x then None else Some Int64.zero - let to_interval x = if x then None else Some (Int64.zero, Int64.zero) let neg x = x let add x y = x || y @@ -2548,9 +2529,6 @@ module Enums : S with type int_t = BigInt.t = struct let of_int ikind x = cast_to ikind (Inc (BISet.singleton x)) let of_interval ?(suppress_ovwarn=false) ik (x,y) = if x = y then of_int ik x else top_of ik - let to_interval l = match minimal l, maximal l with - | Some x, Some y -> Some (x, y) - | _ -> None let join ik = curry @@ function | Inc x, Inc y -> Inc (BISet.union x y) @@ -3286,7 +3264,6 @@ struct let project ik p t = t - let to_interval x = failwith "Not implemented!" (* FIXME *) end module SOverflowLifter (D : S) : SOverflow with type int_t = D.int_t and type t = D.t = struct @@ -3519,8 +3496,6 @@ module IntDomTupleImpl = struct let flat f x = match to_list_some x with [] -> None | xs -> Some (f xs) - let to_interval (_, i, _, _, _) = Option.bind i I2.to_interval - let to_excl_list x = let merge ps = let (vs, rs) = List.split ps in diff --git a/src/cdomains/intDomain.mli b/src/cdomains/intDomain.mli index 5a6a4d7c04..c7b59e4c23 100644 --- a/src/cdomains/intDomain.mli +++ b/src/cdomains/intDomain.mli @@ -187,9 +187,6 @@ sig (** Give a boolean interpretation of an abstract value if possible, otherwise * don't return anything.*) - val to_interval: t -> (int_t * int_t) option - (** Gives an interval interpretation if possible. *) - val to_excl_list: t -> (int_t list * (int64 * int64)) option (** Gives a list representation of the excluded values from included range of bits if possible. *) @@ -235,7 +232,7 @@ sig val invariant: Cil.exp -> t -> Invariant.t end (** Interface of IntDomain implementations that do not take ikinds for arithmetic operations yet. - TODO: Should be ported to S in the future. *) + TODO: Should be ported to S in the future. *) module type S = sig @@ -415,10 +412,10 @@ module IntervalSetFunctor(Ints_t : IntOps.IntOps): SOverflow with type int_t = I module Interval32 :Y with (* type t = (IntOps.Int64Ops.t * IntOps.Int64Ops.t) option and *) type int_t = IntOps.Int64Ops.t module BigInt: - sig - include Printable.S with type t = Z.t (* TODO: why doesn't this have a more useful signature like IntOps.BigIntOps? *) - val cast_to: Cil.ikind -> Z.t -> Z.t - end +sig + include Printable.S with type t = Z.t (* TODO: why doesn't this have a more useful signature like IntOps.BigIntOps? *) + val cast_to: Cil.ikind -> Z.t -> Z.t +end module Interval : SOverflow with type int_t = IntOps.BigIntOps.t diff --git a/src/domains/valueDomainQueries.ml b/src/domains/valueDomainQueries.ml index 2f28f729ea..d366e6dda3 100644 --- a/src/domains/valueDomainQueries.ml +++ b/src/domains/valueDomainQueries.ml @@ -34,7 +34,6 @@ struct let to_int x = unlift_opt I.to_int x let to_bool x = unlift_opt I.to_bool x - let to_interval x = unlift_opt I.to_interval x let is_top_of ik = unlift_is (I.is_top_of ik) From ffd6d4c1234bfa352655493370128044536ec8b5 Mon Sep 17 00:00:00 2001 From: Alexander Schlenga Date: Wed, 14 Jun 2023 14:27:28 +0200 Subject: [PATCH 084/327] Add dummy finalize function --- src/analyses/termination_new.ml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/analyses/termination_new.ml b/src/analyses/termination_new.ml index 503b3f2d51..ce0b36121e 100644 --- a/src/analyses/termination_new.ml +++ b/src/analyses/termination_new.ml @@ -48,6 +48,8 @@ struct let startstate _ = D.bot () let exitstate = startstate (* TODO *) + let finalize () = () (* TODO *) + (** Provides some default implementations *) include Analyses.IdentitySpec From 090e704e72f2e9ba4626f9ca53505f7e03671c9e Mon Sep 17 00:00:00 2001 From: Alexander Schlenga Date: Wed, 14 Jun 2023 16:22:52 +0200 Subject: [PATCH 085/327] WIP on final loop termination report --- src/analyses/termination_new.ml | 15 ++++++++++++--- 1 file changed, 12 insertions(+), 3 deletions(-) diff --git a/src/analyses/termination_new.ml b/src/analyses/termination_new.ml index ce0b36121e..44b0c7fb5e 100644 --- a/src/analyses/termination_new.ml +++ b/src/analyses/termination_new.ml @@ -37,22 +37,31 @@ let check_bounded ctx varinfo = | `Lifted v -> not (is_top_of (ikind v) v) | `Bot -> raise (PreProcessing "Loop variable is Bot") +module FunContextV : Analyses.SpecSysVar = +struct + include Printable.Prod (CilType.Fundec) (CilType.Fundec) (* TODO *) + include Analyses.StdV +end + + module Spec : Analyses.MCPSpec = struct + (** Provides some default implementations *) + include Analyses.IdentitySpec + let name () = "termination" module D = MapDomain.MapBot (Basetype.Variables) (BoolDomain.MustBool) module C = D + module V = FunContextV + (* TODO *) let startstate _ = D.bot () let exitstate = startstate (* TODO *) let finalize () = () (* TODO *) - (** Provides some default implementations *) - include Analyses.IdentitySpec - let assign ctx (lval : lval) (rval : exp) = (* Detect assignment to loop counter variable *) match lval, rval with From 82bb72dd579517d4357488185080beaea13e5fa0 Mon Sep 17 00:00:00 2001 From: Thomas Lagemann Date: Thu, 15 Jun 2023 12:32:00 +0200 Subject: [PATCH 086/327] Test case term:20 fixed --- tests/regression/80-termination/20-rand-nonterminating.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/tests/regression/80-termination/20-rand-nonterminating.c b/tests/regression/80-termination/20-rand-nonterminating.c index 6639e5bc76..88f6f50bd4 100644 --- a/tests/regression/80-termination/20-rand-nonterminating.c +++ b/tests/regression/80-termination/20-rand-nonterminating.c @@ -11,7 +11,7 @@ int main() if (rand()) { // Loop inside the if part - for (int i = 1; i <= 0; i++) // NOTERM + for (int i = 1; i >= 0; i++) // NOTERM { printf("Loop inside if part: %d\n", i); } @@ -20,10 +20,9 @@ int main() { // Loop inside the else part int j = 1; - while (j < 5) // NOTERM + while (j > 0) // NOTERM { printf("Loop inside else part: %d\n", j); - j++; } } From 37848d8eec23ea6e6d2423a279f80e2a55fce43c Mon Sep 17 00:00:00 2001 From: Thomas Lagemann Date: Thu, 15 Jun 2023 13:41:05 +0200 Subject: [PATCH 087/327] Test cases for term with polyhedra --- .../regression/80-termination/09-complex-for-loop-terminating.c | 2 +- tests/regression/80-termination/10-complex-loop-terminating.c | 2 +- tests/regression/80-termination/11-loopless-termination.c | 2 +- .../80-termination/15-complex-loop-combination-terminating.c | 2 +- tests/regression/80-termination/17-goto-terminating.c | 2 +- tests/regression/80-termination/18-goto-nonterminating.c | 2 +- tests/regression/80-termination/19-rand-terminating.c | 2 +- tests/regression/80-termination/20-rand-nonterminating.c | 2 +- .../regression/80-termination/21-no-exit-on-rand-unproofable.c | 2 +- tests/regression/80-termination/22-exit-on-rand-unproofable.c | 2 +- tests/regression/80-termination/23-exit-on-rand-terminating.c | 2 +- 11 files changed, 11 insertions(+), 11 deletions(-) diff --git a/tests/regression/80-termination/09-complex-for-loop-terminating.c b/tests/regression/80-termination/09-complex-for-loop-terminating.c index 508b31500c..ed28fa9b43 100644 --- a/tests/regression/80-termination/09-complex-for-loop-terminating.c +++ b/tests/regression/80-termination/09-complex-for-loop-terminating.c @@ -1,4 +1,4 @@ -// PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval +// PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra #include int main() diff --git a/tests/regression/80-termination/10-complex-loop-terminating.c b/tests/regression/80-termination/10-complex-loop-terminating.c index 9d5cd4b928..3a19f17bee 100644 --- a/tests/regression/80-termination/10-complex-loop-terminating.c +++ b/tests/regression/80-termination/10-complex-loop-terminating.c @@ -1,4 +1,4 @@ -// PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval +// PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra #include int main() diff --git a/tests/regression/80-termination/11-loopless-termination.c b/tests/regression/80-termination/11-loopless-termination.c index b118e65e35..7aeed0145d 100644 --- a/tests/regression/80-termination/11-loopless-termination.c +++ b/tests/regression/80-termination/11-loopless-termination.c @@ -1,4 +1,4 @@ -// TERM +// PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra #include int main() { diff --git a/tests/regression/80-termination/15-complex-loop-combination-terminating.c b/tests/regression/80-termination/15-complex-loop-combination-terminating.c index 1ea228ae55..e5383aed66 100644 --- a/tests/regression/80-termination/15-complex-loop-combination-terminating.c +++ b/tests/regression/80-termination/15-complex-loop-combination-terminating.c @@ -1,4 +1,4 @@ -// PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval +// PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra #include int main() diff --git a/tests/regression/80-termination/17-goto-terminating.c b/tests/regression/80-termination/17-goto-terminating.c index 10aa729837..dcf72552bc 100644 --- a/tests/regression/80-termination/17-goto-terminating.c +++ b/tests/regression/80-termination/17-goto-terminating.c @@ -1,4 +1,4 @@ -// PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval +// PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra #include int main() diff --git a/tests/regression/80-termination/18-goto-nonterminating.c b/tests/regression/80-termination/18-goto-nonterminating.c index dbb7a3df59..672128e009 100644 --- a/tests/regression/80-termination/18-goto-nonterminating.c +++ b/tests/regression/80-termination/18-goto-nonterminating.c @@ -1,4 +1,4 @@ -// PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval +// PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra #include int main() diff --git a/tests/regression/80-termination/19-rand-terminating.c b/tests/regression/80-termination/19-rand-terminating.c index 1d226f0df2..879ae3748a 100644 --- a/tests/regression/80-termination/19-rand-terminating.c +++ b/tests/regression/80-termination/19-rand-terminating.c @@ -1,4 +1,4 @@ -// PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval +// PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra #include #include #include diff --git a/tests/regression/80-termination/20-rand-nonterminating.c b/tests/regression/80-termination/20-rand-nonterminating.c index 88f6f50bd4..27c3f2c388 100644 --- a/tests/regression/80-termination/20-rand-nonterminating.c +++ b/tests/regression/80-termination/20-rand-nonterminating.c @@ -1,4 +1,4 @@ -// PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval +// PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra #include #include #include diff --git a/tests/regression/80-termination/21-no-exit-on-rand-unproofable.c b/tests/regression/80-termination/21-no-exit-on-rand-unproofable.c index 4510ac1bb7..0edafe0f65 100644 --- a/tests/regression/80-termination/21-no-exit-on-rand-unproofable.c +++ b/tests/regression/80-termination/21-no-exit-on-rand-unproofable.c @@ -1,4 +1,4 @@ -// PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval +// PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra #include int main() diff --git a/tests/regression/80-termination/22-exit-on-rand-unproofable.c b/tests/regression/80-termination/22-exit-on-rand-unproofable.c index 97b18ed5fc..5c270f3b2a 100644 --- a/tests/regression/80-termination/22-exit-on-rand-unproofable.c +++ b/tests/regression/80-termination/22-exit-on-rand-unproofable.c @@ -1,4 +1,4 @@ -// PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval +// PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra #include int main() diff --git a/tests/regression/80-termination/23-exit-on-rand-terminating.c b/tests/regression/80-termination/23-exit-on-rand-terminating.c index 5e2be62637..f793275b1f 100644 --- a/tests/regression/80-termination/23-exit-on-rand-terminating.c +++ b/tests/regression/80-termination/23-exit-on-rand-terminating.c @@ -1,4 +1,4 @@ -// PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval +// PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra #include int main() From ff5755833c8539dd48bb7fd49afdc8b0fedf5784 Mon Sep 17 00:00:00 2001 From: Johanna Schinabeck Date: Fri, 16 Jun 2023 11:13:51 +0200 Subject: [PATCH 088/327] filling of global constraint happens in combine_env --- output.txt | 2262 ---------------------------------- runningGob.sh | 2 +- src/framework/analyses.ml | 18 +- src/framework/constraints.ml | 171 +-- src/framework/control.ml | 3 +- 5 files changed, 33 insertions(+), 2423 deletions(-) diff --git a/output.txt b/output.txt index 6ccb110e96..e69de29bb2 100644 --- a/output.txt +++ b/output.txt @@ -1,2262 +0,0 @@ -2023-06-09 18:19:45 -'./goblint' '-v' 'tests/regression/55-loop-unrolling/01-simple-cases.c' '--set' 'ana.activated[+]' 'termination' '--enable' 'warn.debug' '--set' 'ana.activated[+]' 'apron' '--enable' 'ana.int.interval' '--set' 'ana.apron.domain' 'polyhedra' '--enable' 'justcil' -Custom include dirs: - 1. /home/johanna/goblint/goblint-analyzer/lib/linux/stub/include (exists=true) - 2. /home/johanna/goblint/goblint-analyzer/lib/sv-comp/stub/include (exists=false) - 3. /home/johanna/goblint/goblint-analyzer/lib/libc/stub/include (exists=true) - 4. /home/johanna/goblint/goblint-analyzer/lib/goblint/stub/include (exists=false) - 5. /home/johanna/goblint/goblint-analyzer/lib/linux/runtime/include (exists=false) - 6. /home/johanna/goblint/goblint-analyzer/lib/sv-comp/runtime/include (exists=false) - 7. /home/johanna/goblint/goblint-analyzer/lib/libc/runtime/include (exists=false) - 8. /home/johanna/goblint/goblint-analyzer/lib/goblint/runtime/include (exists=true) - 9. /home/johanna/goblint/goblint-analyzer/lib/linux/stub/src (exists=false) - 10. /home/johanna/goblint/goblint-analyzer/lib/sv-comp/stub/src (exists=true) - 11. /home/johanna/goblint/goblint-analyzer/lib/libc/stub/src (exists=true) - 12. /home/johanna/goblint/goblint-analyzer/lib/goblint/stub/src (exists=false) -Preprocessing files. -Preprocessor cpp: is_bad=false -'cpp' '-I' '/home/johanna/goblint/goblint-analyzer/lib/linux/stub/include' '-I' '/home/johanna/goblint/goblint-analyzer/lib/libc/stub/include' '-I' '/home/johanna/goblint/goblint-analyzer/lib/goblint/runtime/include' '-I' '/home/johanna/goblint/goblint-analyzer/lib/sv-comp/stub/src' '-I' '/home/johanna/goblint/goblint-analyzer/lib/libc/stub/src' '/home/johanna/goblint/goblint-analyzer/lib/libc/stub/src/pthread.c' '-o' '.goblint/preprocessed/pthread.i' -'cpp' '-I' '/home/johanna/goblint/goblint-analyzer/lib/linux/stub/include' '-I' '/home/johanna/goblint/goblint-analyzer/lib/libc/stub/include' '-I' '/home/johanna/goblint/goblint-analyzer/lib/goblint/runtime/include' '-I' '/home/johanna/goblint/goblint-analyzer/lib/sv-comp/stub/src' '-I' '/home/johanna/goblint/goblint-analyzer/lib/libc/stub/src' '/home/johanna/goblint/goblint-analyzer/lib/libc/stub/src/stdlib.c' '-o' '.goblint/preprocessed/stdlib.i' -'cpp' '-I' '/home/johanna/goblint/goblint-analyzer/lib/linux/stub/include' '-I' '/home/johanna/goblint/goblint-analyzer/lib/libc/stub/include' '-I' '/home/johanna/goblint/goblint-analyzer/lib/goblint/runtime/include' '-I' '/home/johanna/goblint/goblint-analyzer/lib/sv-comp/stub/src' '-I' '/home/johanna/goblint/goblint-analyzer/lib/libc/stub/src' 'tests/regression/55-loop-unrolling/01-simple-cases.c' '-o' '.goblint/preprocessed/01-simple-cases.i' -Parsing files. -Constructors: -Adding constructors to: main -/* Generated by CIL v. 2.0.1-48-g4df989f */ -/* print_CIL_Input is true */ - -#line 31 "/usr/include/x86_64-linux-gnu/bits/types.h" -typedef unsigned char __u_char; -#line 32 "/usr/include/x86_64-linux-gnu/bits/types.h" -typedef unsigned short __u_short; -#line 33 "/usr/include/x86_64-linux-gnu/bits/types.h" -typedef unsigned int __u_int; -#line 34 "/usr/include/x86_64-linux-gnu/bits/types.h" -typedef unsigned long __u_long; -#line 37 "/usr/include/x86_64-linux-gnu/bits/types.h" -typedef signed char __int8_t; -#line 38 "/usr/include/x86_64-linux-gnu/bits/types.h" -typedef unsigned char __uint8_t; -#line 39 "/usr/include/x86_64-linux-gnu/bits/types.h" -typedef short __int16_t; -#line 40 "/usr/include/x86_64-linux-gnu/bits/types.h" -typedef unsigned short __uint16_t; -#line 41 "/usr/include/x86_64-linux-gnu/bits/types.h" -typedef int __int32_t; -#line 42 "/usr/include/x86_64-linux-gnu/bits/types.h" -typedef unsigned int __uint32_t; -#line 44 "/usr/include/x86_64-linux-gnu/bits/types.h" -typedef long __int64_t; -#line 45 "/usr/include/x86_64-linux-gnu/bits/types.h" -typedef unsigned long __uint64_t; -#line 52 "/usr/include/x86_64-linux-gnu/bits/types.h" -typedef __int8_t __int_least8_t; -#line 53 "/usr/include/x86_64-linux-gnu/bits/types.h" -typedef __uint8_t __uint_least8_t; -#line 54 "/usr/include/x86_64-linux-gnu/bits/types.h" -typedef __int16_t __int_least16_t; -#line 55 "/usr/include/x86_64-linux-gnu/bits/types.h" -typedef __uint16_t __uint_least16_t; -#line 56 "/usr/include/x86_64-linux-gnu/bits/types.h" -typedef __int32_t __int_least32_t; -#line 57 "/usr/include/x86_64-linux-gnu/bits/types.h" -typedef __uint32_t __uint_least32_t; -#line 58 "/usr/include/x86_64-linux-gnu/bits/types.h" -typedef __int64_t __int_least64_t; -#line 59 "/usr/include/x86_64-linux-gnu/bits/types.h" -typedef __uint64_t __uint_least64_t; -#line 63 "/usr/include/x86_64-linux-gnu/bits/types.h" -typedef long __quad_t; -#line 64 "/usr/include/x86_64-linux-gnu/bits/types.h" -typedef unsigned long __u_quad_t; -#line 72 "/usr/include/x86_64-linux-gnu/bits/types.h" -typedef long __intmax_t; -#line 73 "/usr/include/x86_64-linux-gnu/bits/types.h" -typedef unsigned long __uintmax_t; -#line 145 "/usr/include/x86_64-linux-gnu/bits/types.h" -typedef unsigned long __dev_t; -#line 146 "/usr/include/x86_64-linux-gnu/bits/types.h" -typedef unsigned int __uid_t; -#line 147 "/usr/include/x86_64-linux-gnu/bits/types.h" -typedef unsigned int __gid_t; -#line 148 "/usr/include/x86_64-linux-gnu/bits/types.h" -typedef unsigned long __ino_t; -#line 149 "/usr/include/x86_64-linux-gnu/bits/types.h" -typedef unsigned long __ino64_t; -#line 150 "/usr/include/x86_64-linux-gnu/bits/types.h" -typedef unsigned int __mode_t; -#line 151 "/usr/include/x86_64-linux-gnu/bits/types.h" -typedef unsigned long __nlink_t; -#line 152 "/usr/include/x86_64-linux-gnu/bits/types.h" -typedef long __off_t; -#line 153 "/usr/include/x86_64-linux-gnu/bits/types.h" -typedef long __off64_t; -#line 154 "/usr/include/x86_64-linux-gnu/bits/types.h" -typedef int __pid_t; -#line 155 "/usr/include/x86_64-linux-gnu/bits/types.h" -struct __anonstruct___fsid_t_109580352 { - int __val[2] ; -}; -#line 155 "/usr/include/x86_64-linux-gnu/bits/types.h" -typedef struct __anonstruct___fsid_t_109580352 __fsid_t; -#line 156 "/usr/include/x86_64-linux-gnu/bits/types.h" -typedef long __clock_t; -#line 157 "/usr/include/x86_64-linux-gnu/bits/types.h" -typedef unsigned long __rlim_t; -#line 158 "/usr/include/x86_64-linux-gnu/bits/types.h" -typedef unsigned long __rlim64_t; -#line 159 "/usr/include/x86_64-linux-gnu/bits/types.h" -typedef unsigned int __id_t; -#line 160 "/usr/include/x86_64-linux-gnu/bits/types.h" -typedef long __time_t; -#line 161 "/usr/include/x86_64-linux-gnu/bits/types.h" -typedef unsigned int __useconds_t; -#line 162 "/usr/include/x86_64-linux-gnu/bits/types.h" -typedef long __suseconds_t; -#line 163 "/usr/include/x86_64-linux-gnu/bits/types.h" -typedef long __suseconds64_t; -#line 165 "/usr/include/x86_64-linux-gnu/bits/types.h" -typedef int __daddr_t; -#line 166 "/usr/include/x86_64-linux-gnu/bits/types.h" -typedef int __key_t; -#line 169 "/usr/include/x86_64-linux-gnu/bits/types.h" -typedef int __clockid_t; -#line 172 "/usr/include/x86_64-linux-gnu/bits/types.h" -typedef void *__timer_t; -#line 175 "/usr/include/x86_64-linux-gnu/bits/types.h" -typedef long __blksize_t; -#line 180 "/usr/include/x86_64-linux-gnu/bits/types.h" -typedef long __blkcnt_t; -#line 181 "/usr/include/x86_64-linux-gnu/bits/types.h" -typedef long __blkcnt64_t; -#line 184 "/usr/include/x86_64-linux-gnu/bits/types.h" -typedef unsigned long __fsblkcnt_t; -#line 185 "/usr/include/x86_64-linux-gnu/bits/types.h" -typedef unsigned long __fsblkcnt64_t; -#line 188 "/usr/include/x86_64-linux-gnu/bits/types.h" -typedef unsigned long __fsfilcnt_t; -#line 189 "/usr/include/x86_64-linux-gnu/bits/types.h" -typedef unsigned long __fsfilcnt64_t; -#line 192 "/usr/include/x86_64-linux-gnu/bits/types.h" -typedef long __fsword_t; -#line 194 "/usr/include/x86_64-linux-gnu/bits/types.h" -typedef long __ssize_t; -#line 197 "/usr/include/x86_64-linux-gnu/bits/types.h" -typedef long __syscall_slong_t; -#line 199 "/usr/include/x86_64-linux-gnu/bits/types.h" -typedef unsigned long __syscall_ulong_t; -#line 203 "/usr/include/x86_64-linux-gnu/bits/types.h" -typedef __off64_t __loff_t; -#line 204 "/usr/include/x86_64-linux-gnu/bits/types.h" -typedef char *__caddr_t; -#line 207 "/usr/include/x86_64-linux-gnu/bits/types.h" -typedef long __intptr_t; -#line 210 "/usr/include/x86_64-linux-gnu/bits/types.h" -typedef unsigned int __socklen_t; -#line 215 "/usr/include/x86_64-linux-gnu/bits/types.h" -typedef int __sig_atomic_t; -#line 209 "/usr/lib/gcc/x86_64-linux-gnu/11/include/stddef.h" -typedef unsigned long size_t; -#line 10 "/usr/include/x86_64-linux-gnu/bits/types/time_t.h" -typedef __time_t time_t; -#line 11 "/usr/include/x86_64-linux-gnu/bits/types/struct_timespec.h" -struct timespec { - __time_t tv_sec ; - __syscall_slong_t tv_nsec ; -}; -#line 38 "/usr/include/sched.h" -typedef __pid_t pid_t; -#line 23 "/usr/include/x86_64-linux-gnu/bits/types/struct_sched_param.h" -struct sched_param { - int sched_priority ; -}; -#line 32 "/usr/include/x86_64-linux-gnu/bits/cpu-set.h" -typedef unsigned long __cpu_mask; -#line 39 "/usr/include/x86_64-linux-gnu/bits/cpu-set.h" -struct __anonstruct_cpu_set_t_826868708 { - __cpu_mask __bits[1024UL / (8UL * sizeof(__cpu_mask ))] ; -}; -#line 39 "/usr/include/x86_64-linux-gnu/bits/cpu-set.h" -typedef struct __anonstruct_cpu_set_t_826868708 cpu_set_t; -#line 7 "/usr/include/x86_64-linux-gnu/bits/types/clock_t.h" -typedef __clock_t clock_t; -#line 7 "/usr/include/x86_64-linux-gnu/bits/types/struct_tm.h" -struct tm { - int tm_sec ; - int tm_min ; - int tm_hour ; - int tm_mday ; - int tm_mon ; - int tm_year ; - int tm_wday ; - int tm_yday ; - int tm_isdst ; - long tm_gmtoff ; - char const *tm_zone ; -}; -#line 7 "/usr/include/x86_64-linux-gnu/bits/types/clockid_t.h" -typedef __clockid_t clockid_t; -#line 7 "/usr/include/x86_64-linux-gnu/bits/types/timer_t.h" -typedef __timer_t timer_t; -#line 8 "/usr/include/x86_64-linux-gnu/bits/types/struct_itimerspec.h" -struct itimerspec { - struct timespec it_interval ; - struct timespec it_value ; -}; -#line 49 "/usr/include/time.h" -struct sigevent ; -#line 27 "/usr/include/x86_64-linux-gnu/bits/types/__locale_t.h" -struct __locale_data ; -#line 27 "/usr/include/x86_64-linux-gnu/bits/types/__locale_t.h" -struct __locale_struct { - struct __locale_data *__locales[13] ; - unsigned short const *__ctype_b ; - int const *__ctype_tolower ; - int const *__ctype_toupper ; - char const *__names[13] ; -}; -#line 41 "/usr/include/x86_64-linux-gnu/bits/types/__locale_t.h" -typedef struct __locale_struct *__locale_t; -#line 24 "/usr/include/x86_64-linux-gnu/bits/types/locale_t.h" -typedef __locale_t locale_t; -#line 25 "/usr/include/x86_64-linux-gnu/bits/atomic_wide_counter.h" -struct __anonstruct___value32_817613185 { - unsigned int __low ; - unsigned int __high ; -}; -#line 25 "/usr/include/x86_64-linux-gnu/bits/atomic_wide_counter.h" -union __anonunion___atomic_wide_counter_643133811 { - unsigned long long __value64 ; - struct __anonstruct___value32_817613185 __value32 ; -}; -#line 25 "/usr/include/x86_64-linux-gnu/bits/atomic_wide_counter.h" -typedef union __anonunion___atomic_wide_counter_643133811 __atomic_wide_counter; -#line 51 "/usr/include/x86_64-linux-gnu/bits/thread-shared-types.h" -struct __pthread_internal_list { - struct __pthread_internal_list *__prev ; - struct __pthread_internal_list *__next ; -}; -#line 51 "/usr/include/x86_64-linux-gnu/bits/thread-shared-types.h" -typedef struct __pthread_internal_list __pthread_list_t; -#line 57 "/usr/include/x86_64-linux-gnu/bits/thread-shared-types.h" -struct __pthread_internal_slist { - struct __pthread_internal_slist *__next ; -}; -#line 57 "/usr/include/x86_64-linux-gnu/bits/thread-shared-types.h" -typedef struct __pthread_internal_slist __pthread_slist_t; -#line 22 "/usr/include/x86_64-linux-gnu/bits/struct_mutex.h" -struct __pthread_mutex_s { - int __lock ; - unsigned int __count ; - int __owner ; - unsigned int __nusers ; - int __kind ; - short __spins ; - short __elision ; - __pthread_list_t __list ; -}; -#line 23 "/usr/include/x86_64-linux-gnu/bits/struct_rwlock.h" -struct __pthread_rwlock_arch_t { - unsigned int __readers ; - unsigned int __writers ; - unsigned int __wrphase_futex ; - unsigned int __writers_futex ; - unsigned int __pad3 ; - unsigned int __pad4 ; - int __cur_writer ; - int __shared ; - signed char __rwelision ; - unsigned char __pad1[7] ; - unsigned long __pad2 ; - unsigned int __flags ; -}; -#line 94 "/usr/include/x86_64-linux-gnu/bits/thread-shared-types.h" -struct __pthread_cond_s { - __atomic_wide_counter __wseq ; - __atomic_wide_counter __g1_start ; - unsigned int __g_refs[2] ; - unsigned int __g_size[2] ; - unsigned int __g1_orig_size ; - unsigned int __wrefs ; - unsigned int __g_signals[2] ; -}; -#line 105 "/usr/include/x86_64-linux-gnu/bits/thread-shared-types.h" -typedef unsigned int __tss_t; -#line 106 "/usr/include/x86_64-linux-gnu/bits/thread-shared-types.h" -typedef unsigned long __thrd_t; -#line 108 "/usr/include/x86_64-linux-gnu/bits/thread-shared-types.h" -struct __anonstruct___once_flag_826868709 { - int __data ; -}; -#line 108 "/usr/include/x86_64-linux-gnu/bits/thread-shared-types.h" -typedef struct __anonstruct___once_flag_826868709 __once_flag; -#line 27 "/usr/include/x86_64-linux-gnu/bits/pthreadtypes.h" -typedef unsigned long pthread_t; -#line 32 "/usr/include/x86_64-linux-gnu/bits/pthreadtypes.h" -union __anonunion_pthread_mutexattr_t_488594144 { - char __size[4] ; - int __align ; -}; -#line 32 "/usr/include/x86_64-linux-gnu/bits/pthreadtypes.h" -typedef union __anonunion_pthread_mutexattr_t_488594144 pthread_mutexattr_t; -#line 41 "/usr/include/x86_64-linux-gnu/bits/pthreadtypes.h" -union __anonunion_pthread_condattr_t_488594145 { - char __size[4] ; - int __align ; -}; -#line 41 "/usr/include/x86_64-linux-gnu/bits/pthreadtypes.h" -typedef union __anonunion_pthread_condattr_t_488594145 pthread_condattr_t; -#line 49 "/usr/include/x86_64-linux-gnu/bits/pthreadtypes.h" -typedef unsigned int pthread_key_t; -#line 53 "/usr/include/x86_64-linux-gnu/bits/pthreadtypes.h" -typedef int pthread_once_t; -#line 56 "/usr/include/x86_64-linux-gnu/bits/pthreadtypes.h" -union pthread_attr_t { - char __size[56] ; - long __align ; -}; -#line 62 "/usr/include/x86_64-linux-gnu/bits/pthreadtypes.h" -typedef union pthread_attr_t pthread_attr_t; -#line 67 "/usr/include/x86_64-linux-gnu/bits/pthreadtypes.h" -union __anonunion_pthread_mutex_t_335460617 { - struct __pthread_mutex_s __data ; - char __size[40] ; - long __align ; -}; -#line 67 "/usr/include/x86_64-linux-gnu/bits/pthreadtypes.h" -typedef union __anonunion_pthread_mutex_t_335460617 pthread_mutex_t; -#line 75 "/usr/include/x86_64-linux-gnu/bits/pthreadtypes.h" -union __anonunion_pthread_cond_t_951761805 { - struct __pthread_cond_s __data ; - char __size[48] ; - long long __align ; -}; -#line 75 "/usr/include/x86_64-linux-gnu/bits/pthreadtypes.h" -typedef union __anonunion_pthread_cond_t_951761805 pthread_cond_t; -#line 86 "/usr/include/x86_64-linux-gnu/bits/pthreadtypes.h" -union __anonunion_pthread_rwlock_t_656928968 { - struct __pthread_rwlock_arch_t __data ; - char __size[56] ; - long __align ; -}; -#line 86 "/usr/include/x86_64-linux-gnu/bits/pthreadtypes.h" -typedef union __anonunion_pthread_rwlock_t_656928968 pthread_rwlock_t; -#line 93 "/usr/include/x86_64-linux-gnu/bits/pthreadtypes.h" -union __anonunion_pthread_rwlockattr_t_145707745 { - char __size[8] ; - long __align ; -}; -#line 93 "/usr/include/x86_64-linux-gnu/bits/pthreadtypes.h" -typedef union __anonunion_pthread_rwlockattr_t_145707745 pthread_rwlockattr_t; -#line 103 "/usr/include/x86_64-linux-gnu/bits/pthreadtypes.h" -typedef int volatile pthread_spinlock_t; -#line 108 "/usr/include/x86_64-linux-gnu/bits/pthreadtypes.h" -union __anonunion_pthread_barrier_t_145707746 { - char __size[32] ; - long __align ; -}; -#line 108 "/usr/include/x86_64-linux-gnu/bits/pthreadtypes.h" -typedef union __anonunion_pthread_barrier_t_145707746 pthread_barrier_t; -#line 114 "/usr/include/x86_64-linux-gnu/bits/pthreadtypes.h" -union __anonunion_pthread_barrierattr_t_951761806 { - char __size[4] ; - int __align ; -}; -#line 114 "/usr/include/x86_64-linux-gnu/bits/pthreadtypes.h" -typedef union __anonunion_pthread_barrierattr_t_951761806 pthread_barrierattr_t; -#line 31 "/usr/include/x86_64-linux-gnu/bits/setjmp.h" -typedef long __jmp_buf[8]; -#line 5 "/usr/include/x86_64-linux-gnu/bits/types/__sigset_t.h" -struct __anonstruct___sigset_t_764561023 { - unsigned long __val[1024UL / (8UL * sizeof(unsigned long ))] ; -}; -#line 5 "/usr/include/x86_64-linux-gnu/bits/types/__sigset_t.h" -typedef struct __anonstruct___sigset_t_764561023 __sigset_t; -#line 26 "/usr/include/x86_64-linux-gnu/bits/types/struct___jmp_buf_tag.h" -struct __jmp_buf_tag { - __jmp_buf __jmpbuf ; - int __mask_was_saved ; - __sigset_t __saved_mask ; -}; -#line 37 "/usr/include/pthread.h" -enum __anonenum_34415463 { - PTHREAD_CREATE_JOINABLE = 0, - PTHREAD_CREATE_DETACHED = 1 -} ; -#line 47 -enum __anonenum_508643754 { - PTHREAD_MUTEX_TIMED_NP = 0, - PTHREAD_MUTEX_RECURSIVE_NP = 1, - PTHREAD_MUTEX_ERRORCHECK_NP = 2, - PTHREAD_MUTEX_ADAPTIVE_NP = 3, - PTHREAD_MUTEX_NORMAL = 0, - PTHREAD_MUTEX_RECURSIVE = 1, - PTHREAD_MUTEX_ERRORCHECK = 2, - PTHREAD_MUTEX_DEFAULT = 0 -} ; -#line 69 -enum __anonenum_931900394 { - PTHREAD_MUTEX_STALLED = 0, - PTHREAD_MUTEX_STALLED_NP = 0, - PTHREAD_MUTEX_ROBUST = 1, - PTHREAD_MUTEX_ROBUST_NP = 1 -} ; -#line 81 -enum __anonenum_205214487 { - PTHREAD_PRIO_NONE = 0, - PTHREAD_PRIO_INHERIT = 1, - PTHREAD_PRIO_PROTECT = 2 -} ; -#line 104 -enum __anonenum_25043950 { - PTHREAD_RWLOCK_PREFER_READER_NP = 0, - PTHREAD_RWLOCK_PREFER_WRITER_NP = 1, - PTHREAD_RWLOCK_PREFER_WRITER_NONRECURSIVE_NP = 2, - PTHREAD_RWLOCK_DEFAULT_NP = 0 -} ; -#line 124 -enum __anonenum_436439511 { - PTHREAD_INHERIT_SCHED = 0, - PTHREAD_EXPLICIT_SCHED = 1 -} ; -#line 134 -enum __anonenum_998661166 { - PTHREAD_SCOPE_SYSTEM = 0, - PTHREAD_SCOPE_PROCESS = 1 -} ; -#line 144 -enum __anonenum_146137331 { - PTHREAD_PROCESS_PRIVATE = 0, - PTHREAD_PROCESS_SHARED = 1 -} ; -#line 159 "/usr/include/pthread.h" -struct _pthread_cleanup_buffer { - void (*__routine)(void * ) ; - void *__arg ; - int __canceltype ; - struct _pthread_cleanup_buffer *__prev ; -}; -#line 168 -enum __anonenum_53396917 { - PTHREAD_CANCEL_ENABLE = 0, - PTHREAD_CANCEL_DISABLE = 1 -} ; -#line 175 -enum __anonenum_904563783 { - PTHREAD_CANCEL_DEFERRED = 0, - PTHREAD_CANCEL_ASYNCHRONOUS = 1 -} ; -#line 538 "/usr/include/pthread.h" -struct __cancel_jmp_buf_tag { - __jmp_buf __cancel_jmp_buf ; - int __mask_was_saved ; -}; -#line 544 "/usr/include/pthread.h" -struct __anonstruct___pthread_unwind_buf_t_530692248 { - struct __cancel_jmp_buf_tag __cancel_jmp_buf[1] ; - void *__pad[4] ; -}; -#line 544 "/usr/include/pthread.h" -typedef struct __anonstruct___pthread_unwind_buf_t_530692248 __attribute__((__aligned__)) __pthread_unwind_buf_t; -#line 557 "/usr/include/pthread.h" -struct __pthread_cleanup_frame { - void (*__cancel_routine)(void * ) ; - void *__cancel_arg ; - int __do_it ; - int __cancel_type ; -}; -#line 143 "/usr/lib/gcc/x86_64-linux-gnu/11/include/stddef.h" -typedef long ptrdiff_t; -#line 321 "/usr/lib/gcc/x86_64-linux-gnu/11/include/stddef.h" -typedef int wchar_t; -#line 415 "/usr/lib/gcc/x86_64-linux-gnu/11/include/stddef.h" -struct __anonstruct_max_align_t_896270833 { - long long __max_align_ll __attribute__((__aligned__(__alignof__(long long )))) ; - long double __max_align_ld __attribute__((__aligned__(__alignof__(long double )))) ; -}; -#line 415 "/usr/lib/gcc/x86_64-linux-gnu/11/include/stddef.h" -typedef struct __anonstruct_max_align_t_896270833 max_align_t; -/* compiler builtin: - void __builtin_va_copy(__builtin_va_list , __builtin_va_list ) ; */ -/* compiler builtin: - void *__builtin_frob_return_address(void * ) ; */ -/* compiler builtin: - void __attribute__((__overloaded__)) __sync_and_and_fetch(...) ; */ -/* compiler builtin: - void __attribute__((__overloaded__)) __sync_fetch_and_or(...) ; */ -/* compiler builtin: - int __builtin_popcountll(unsigned long long ) ; */ -/* compiler builtin: - void __attribute__((__overloaded__)) __atomic_or_fetch(...) ; */ -/* compiler builtin: - float __builtin_atanf(float ) ; */ -/* compiler builtin: - float __attribute__((____vector_size____(16))) __builtin_ia32_addps(float __attribute__((____vector_size____(16))) , - float __attribute__((____vector_size____(16))) ) ; */ -/* compiler builtin: - unsigned long __builtin_strcspn(char const * , char const * ) ; */ -/* compiler builtin: - float __builtin_asinf(float ) ; */ -/* compiler builtin: - float __attribute__((____vector_size____(16))) __builtin_ia32_maxps(float __attribute__((____vector_size____(16))) , - float __attribute__((____vector_size____(16))) ) ; */ -/* compiler builtin: - float __attribute__((____vector_size____(16))) __builtin_ia32_unpckhps(float __attribute__((____vector_size____(16))) , - float __attribute__((____vector_size____(16))) ) ; */ -/* compiler builtin: - double __builtin_acos(double ) ; */ -/* compiler builtin: - int __builtin___sprintf_chk(char * , int , unsigned long , char const * , ...) ; */ -/* compiler builtin: - void __attribute__((__overloaded__)) __atomic_nand_fetch_8(...) ; */ -/* compiler builtin: - void __attribute__((__overloaded__)) __atomic_fetch_and(...) ; */ -/* compiler builtin: - void __attribute__((__overloaded__)) __atomic_xor_fetch_16(...) ; */ -/* compiler builtin: - double __builtin_cosh(double ) ; */ -/* compiler builtin: - float __builtin_tanhf(float ) ; */ -/* compiler builtin: - void __attribute__((__overloaded__)) __atomic_fetch_nand_16(...) ; */ -/* compiler builtin: - void *__builtin_mempcpy(void * , void const * , unsigned long ) ; */ -/* compiler builtin: - void __attribute__((__overloaded__)) __atomic_sub_fetch_1(...) ; */ -/* compiler builtin: - long double __builtin_sqrtl(long double ) ; */ -/* compiler builtin: - int __builtin_parity(unsigned int ) ; */ -/* compiler builtin: - void __attribute__((__overloaded__)) __atomic_fetch_or(...) ; */ -/* compiler builtin: - long double __builtin_coshl(long double ) ; */ -/* compiler builtin: - long double __builtin_cosl(long double ) ; */ -/* compiler builtin: - float __builtin_cosf(float ) ; */ -/* compiler builtin: - void __sync_synchronize(...) ; */ -/* compiler builtin: - long double __builtin_acosl(long double ) ; */ -/* compiler builtin: - void *__builtin___mempcpy_chk(void * , void const * , unsigned long , unsigned long ) ; */ -/* compiler builtin: - void __attribute__((__overloaded__)) __sync_or_and_fetch(...) ; */ -/* compiler builtin: - int __builtin_clz(unsigned int ) ; */ -/* compiler builtin: - void __attribute__((__overloaded__)) __atomic_nand_fetch_4(...) ; */ -/* compiler builtin: - double __builtin_log10(double ) ; */ -/* compiler builtin: - char *__builtin___strcat_chk(char * , char const * , unsigned long ) ; */ -/* compiler builtin: - float __builtin_modff(float , float * ) ; */ -/* compiler builtin: - void __attribute__((__overloaded__)) __atomic_sub_fetch_4(...) ; */ -/* compiler builtin: - _Bool __atomic_compare_exchange_n(...) ; */ -/* compiler builtin: - double __builtin_sin(double ) ; */ -/* compiler builtin: - double __builtin_frexp(double , int * ) ; */ -/* compiler builtin: - float __builtin_acosf(float ) ; */ -/* compiler builtin: - void __attribute__((__overloaded__)) __sync_add_and_fetch(...) ; */ -/* compiler builtin: - long double __builtin_sinhl(long double ) ; */ -/* compiler builtin: - char *__builtin___stpcpy_chk(char * , char const * , unsigned long ) ; */ -/* compiler builtin: - void __atomic_signal_fence(int ) ; */ -/* compiler builtin: - double __builtin_fabs(double ) ; */ -/* compiler builtin: - void __attribute__((__overloaded__)) __atomic_fetch_nand_1(...) ; */ -/* compiler builtin: - void __attribute__((__overloaded__)) __atomic_and_fetch_16(...) ; */ -/* compiler builtin: - void __attribute__((__overloaded__)) __sync_fetch_and_nand(...) ; */ -/* compiler builtin: - void __attribute__((__overloaded__)) __atomic_xor_fetch_8(...) ; */ -/* compiler builtin: - void __attribute__((__overloaded__)) __atomic_xor_fetch_2(...) ; */ -/* compiler builtin: - void __atomic_thread_fence(int ) ; */ -/* compiler builtin: - void __atomic_store_16(...) ; */ -/* compiler builtin: - void __builtin_va_start(__builtin_va_list ) ; */ -/* compiler builtin: - void __attribute__((__overloaded__)) __atomic_fetch_and_8(...) ; */ -/* compiler builtin: - short __builtin_bswap16(short ) ; */ -/* compiler builtin: - void __attribute__((__overloaded__)) __atomic_and_fetch_2(...) ; */ -/* compiler builtin: - _Bool __atomic_test_and_set(void * , int ) ; */ -/* compiler builtin: - void __attribute__((__overloaded__)) __atomic_fetch_add_8(...) ; */ -/* compiler builtin: - int __builtin_ctz(unsigned int ) ; */ -/* compiler builtin: - char *__builtin_strpbrk(char const * , char const * ) ; */ -/* compiler builtin: - char *__builtin_strcpy(char * , char const * ) ; */ -/* compiler builtin: - double __builtin_sqrt(double ) ; */ -/* compiler builtin: - __builtin_va_list __builtin_next_arg(void) ; */ -/* compiler builtin: - void __attribute__((__overloaded__)) __atomic_fetch_nand(...) ; */ -/* compiler builtin: - void __attribute__((__overloaded__)) __atomic_exchange_16(...) ; */ -/* compiler builtin: - void __atomic_clear(_Bool * , int ) ; */ -/* compiler builtin: - void __atomic_store(...) ; */ -/* compiler builtin: - void __attribute__((__overloaded__)) __atomic_add_fetch_2(...) ; */ -/* compiler builtin: - float __builtin_log10f(float ) ; */ -/* compiler builtin: - long double __builtin_fabsl(long double ) ; */ -/* compiler builtin: - long double __builtin_floorl(long double ) ; */ -/* compiler builtin: - void __attribute__((__overloaded__)) __atomic_fetch_xor_1(...) ; */ -/* compiler builtin: - void __attribute__((__overloaded__)) __atomic_and_fetch(...) ; */ -/* compiler builtin: - float __builtin_floorf(float ) ; */ -/* compiler builtin: - _Bool __atomic_compare_exchange_4(...) ; */ -/* compiler builtin: - void *__builtin_memcpy(void * , void const * , unsigned long ) ; */ -/* compiler builtin: - void __attribute__((__overloaded__)) __sync_sub_and_fetch(...) ; */ -/* compiler builtin: - void __attribute__((__overloaded__)) __sync_nand_and_fetch(...) ; */ -/* compiler builtin: - void __attribute__((__overloaded__)) __atomic_load_16(...) ; */ -/* compiler builtin: - float __attribute__((____vector_size____(16))) __builtin_ia32_subps(float __attribute__((____vector_size____(16))) , - float __attribute__((____vector_size____(16))) ) ; */ -/* compiler builtin: - int __builtin_parityll(unsigned long long ) ; */ -/* compiler builtin: - void __builtin_va_end(__builtin_va_list ) ; */ -/* compiler builtin: - void __builtin_bzero(void * , unsigned long ) ; */ -/* compiler builtin: - _Bool __atomic_always_lock_free(unsigned long , void * ) ; */ -/* compiler builtin: - int __builtin_strncmp(char const * , char const * , unsigned long ) ; */ -/* compiler builtin: - void __attribute__((__overloaded__)) __atomic_nand_fetch_16(...) ; */ -/* compiler builtin: - void __attribute__((__overloaded__)) __sync_xor_and_fetch(...) ; */ -/* compiler builtin: - int __builtin___vsprintf_chk(char * , int , unsigned long , char const * , - __builtin_va_list ) ; */ -/* compiler builtin: - float __builtin_sqrtf(float ) ; */ -/* compiler builtin: - double __builtin_nans(char const * ) ; */ -/* compiler builtin: - void __attribute__((__overloaded__)) __atomic_fetch_xor_8(...) ; */ -/* compiler builtin: - double __builtin_exp(double ) ; */ -/* compiler builtin: - void __attribute__((__overloaded__)) __atomic_exchange_8(...) ; */ -/* compiler builtin: - void __attribute__((__overloaded__)) __atomic_exchange_1(...) ; */ -/* compiler builtin: - int __builtin_strcmp(char const * , char const * ) ; */ -/* compiler builtin: - float __builtin_ldexpf(float , int ) ; */ -/* compiler builtin: - float __builtin_powif(float , int ) ; */ -/* compiler builtin: - long double __builtin_log10l(long double ) ; */ -/* compiler builtin: - void *__builtin___memmove_chk(void * , void const * , unsigned long , unsigned long ) ; */ -/* compiler builtin: - void __attribute__((__overloaded__)) __sync_fetch_and_and(...) ; */ -/* compiler builtin: - void *__builtin_return_address(unsigned int ) ; */ -/* compiler builtin: - void __atomic_feraiseexcept(int ) ; */ -/* compiler builtin: - void __attribute__((__overloaded__)) __atomic_and_fetch_4(...) ; */ -/* compiler builtin: - float __builtin_fabsf(float ) ; */ -/* compiler builtin: - void __attribute__((__overloaded__)) __atomic_or_fetch_8(...) ; */ -/* compiler builtin: - void __attribute__((__overloaded__)) __atomic_or_fetch_4(...) ; */ -/* compiler builtin: - void __attribute__((__overloaded__)) __atomic_or_fetch_1(...) ; */ -/* compiler builtin: - unsigned long __builtin_object_size(void * , int ) ; */ -/* compiler builtin: - void *__builtin_alloca(unsigned long ) ; */ -/* compiler builtin: - int __builtin_va_arg_pack_len(void) ; */ -/* compiler builtin: - long double __builtin_tanl(long double ) ; */ -/* compiler builtin: - void __attribute__((__overloaded__)) __atomic_fetch_and_2(...) ; */ -/* compiler builtin: - void __sync_lock_release(...) ; */ -/* compiler builtin: - long double __builtin_modfl(long double , long double * ) ; */ -/* compiler builtin: - void __attribute__((__overloaded__)) __atomic_fetch_nand_8(...) ; */ -/* compiler builtin: - char *__builtin_stpcpy(char * , char const * ) ; */ -/* compiler builtin: - long double __builtin_sinl(long double ) ; */ -/* compiler builtin: - double __builtin_asin(double ) ; */ -/* compiler builtin: - float __builtin_sinhf(float ) ; */ -/* compiler builtin: - int __builtin_ctzl(unsigned long ) ; */ -/* compiler builtin: - long double __builtin_tanhl(long double ) ; */ -/* compiler builtin: - void __attribute__((__overloaded__)) __atomic_fetch_add(...) ; */ -/* compiler builtin: - long __builtin_bswap64(long ) ; */ -/* compiler builtin: - void __attribute__((__overloaded__)) __atomic_nand_fetch_1(...) ; */ -/* compiler builtin: - void __attribute__((__overloaded__)) __atomic_fetch_nand_2(...) ; */ -/* compiler builtin: - float __attribute__((____vector_size____(16))) __builtin_ia32_mulps(float __attribute__((____vector_size____(16))) , - float __attribute__((____vector_size____(16))) ) ; */ -/* compiler builtin: - double __builtin_tan(double ) ; */ -/* compiler builtin: - char *__builtin_strncpy(char * , char const * , unsigned long ) ; */ -/* compiler builtin: - float __builtin_inff(void) ; */ -/* compiler builtin: - void *__builtin___memset_chk(void * , int , unsigned long , unsigned long ) ; */ -/* compiler builtin: - void __attribute__((__overloaded__)) __atomic_load_n(...) ; */ -/* compiler builtin: - double __builtin_huge_val(void) ; */ -/* compiler builtin: - int __builtin_clzl(unsigned long ) ; */ -/* compiler builtin: - _Bool __atomic_compare_exchange_16(...) ; */ -/* compiler builtin: - float __builtin_frexpf(float , int * ) ; */ -/* compiler builtin: - void __attribute__((__overloaded__)) __atomic_exchange_n(...) ; */ -/* compiler builtin: - void __attribute__((__overloaded__)) __atomic_fetch_or_1(...) ; */ -/* compiler builtin: - long double __builtin_fmodl(long double ) ; */ -/* compiler builtin: - double __builtin_atan(double ) ; */ -/* compiler builtin: - int __builtin___fprintf_chk(void * , int , char const * , ...) ; */ -/* compiler builtin: - float __builtin_ceilf(float ) ; */ -/* compiler builtin: - void __attribute__((__overloaded__)) __atomic_fetch_or_8(...) ; */ -/* compiler builtin: - void __attribute__((__overloaded__)) __atomic_fetch_add_1(...) ; */ -/* compiler builtin: - void __builtin_return(void const * ) ; */ -/* compiler builtin: - long double __builtin_asinl(long double ) ; */ -/* compiler builtin: - int __builtin_ffsll(unsigned long long ) ; */ -/* compiler builtin: - void __attribute__((__overloaded__)) __atomic_fetch_sub_1(...) ; */ -/* compiler builtin: - int __builtin_va_arg_pack(void) ; */ -/* compiler builtin: - void __attribute__((__overloaded__)) __atomic_fetch_or_4(...) ; */ -/* compiler builtin: - char *__builtin___strncpy_chk(char * , char const * , unsigned long , unsigned long ) ; */ -/* compiler builtin: - double __builtin_powi(double , int ) ; */ -/* compiler builtin: - void __attribute__((__overloaded__)) __atomic_load_2(...) ; */ -/* compiler builtin: - char *__builtin_strchr(char * , int ) ; */ -/* compiler builtin: - char *__builtin___strncat_chk(char * , char const * , unsigned long , unsigned long ) ; */ -/* compiler builtin: - void __atomic_store_2(...) ; */ -/* compiler builtin: - long double __builtin_huge_vall(void) ; */ -/* compiler builtin: - int __builtin_ffsl(unsigned long ) ; */ -/* compiler builtin: - int __builtin___vprintf_chk(int , char const * , __builtin_va_list ) ; */ -/* compiler builtin: - float __attribute__((____vector_size____(16))) __builtin_ia32_unpcklps(float __attribute__((____vector_size____(16))) , - float __attribute__((____vector_size____(16))) ) ; */ -/* compiler builtin: - char *__builtin_strncat(char * , char const * , unsigned long ) ; */ -/* compiler builtin: - int __builtin_ctzll(unsigned long long ) ; */ -/* compiler builtin: - void __builtin_stdarg_start(__builtin_va_list ) ; */ -/* compiler builtin: - void __attribute__((__overloaded__)) __atomic_exchange_4(...) ; */ -/* compiler builtin: - void __attribute__((__overloaded__)) __sync_fetch_and_xor(...) ; */ -/* compiler builtin: - void __attribute__((__overloaded__)) __atomic_fetch_sub_4(...) ; */ -/* compiler builtin: - void __attribute__((__overloaded__)) __atomic_fetch_and_4(...) ; */ -/* compiler builtin: - long double __builtin_frexpl(long double , int * ) ; */ -/* compiler builtin: - _Bool __atomic_compare_exchange(...) ; */ -/* compiler builtin: - float __builtin_tanf(float ) ; */ -/* compiler builtin: - long double __builtin_logl(long double ) ; */ -/* compiler builtin: - void __builtin_va_arg(__builtin_va_list , unsigned long , void * ) ; */ -/* compiler builtin: - long __builtin_expect(long , long ) ; */ -/* compiler builtin: - void __attribute__((__overloaded__)) __atomic_load_1(...) ; */ -/* compiler builtin: - _Bool __atomic_compare_exchange_1(...) ; */ -/* compiler builtin: - int __builtin___printf_chk(int , char const * , ...) ; */ -/* compiler builtin: - void __attribute__((__overloaded__)) __atomic_fetch_xor_2(...) ; */ -/* compiler builtin: - int __builtin___vfprintf_chk(void * , int , char const * , __builtin_va_list ) ; */ -/* compiler builtin: - void __builtin_prefetch(void const * , ...) ; */ -/* compiler builtin: - long double __builtin_nansl(char const * ) ; */ -/* compiler builtin: - double __builtin_fmod(double ) ; */ -/* compiler builtin: - void __atomic_load(...) ; */ -/* compiler builtin: - void __attribute__((__overloaded__)) __atomic_or_fetch_16(...) ; */ -/* compiler builtin: - void __attribute__((__overloaded__)) __atomic_add_fetch_16(...) ; */ -/* compiler builtin: - void __attribute__((__overloaded__)) __sync_val_compare_and_swap(...) ; */ -/* compiler builtin: - void __atomic_store_4(...) ; */ -/* compiler builtin: - double __builtin_tanh(double ) ; */ -/* compiler builtin: - void __attribute__((__overloaded__)) __atomic_fetch_and_1(...) ; */ -/* compiler builtin: - void __attribute__((__overloaded__)) __atomic_fetch_nand_4(...) ; */ -/* compiler builtin: - void __attribute__((__overloaded__)) __atomic_fetch_add_16(...) ; */ -/* compiler builtin: - void __builtin_unreachable(void) ; */ -/* compiler builtin: - _Bool __atomic_compare_exchange_2(...) ; */ -/* compiler builtin: - long double __builtin_ldexpl(long double , int ) ; */ -/* compiler builtin: - void *__builtin_apply(void (*)() , void * , unsigned long ) ; */ -/* compiler builtin: - float __builtin_sinf(float ) ; */ -/* compiler builtin: - double __builtin_ceil(double ) ; */ -/* compiler builtin: - void __atomic_exchange(...) ; */ -/* compiler builtin: - long double __builtin_powil(long double , int ) ; */ -/* compiler builtin: - void __attribute__((__overloaded__)) __atomic_sub_fetch_8(...) ; */ -/* compiler builtin: - long double __builtin_expl(long double ) ; */ -/* compiler builtin: - int __builtin_constant_p(int ) ; */ -/* compiler builtin: - void __attribute__((__overloaded__)) __atomic_fetch_sub_16(...) ; */ -/* compiler builtin: - double __builtin_log(double ) ; */ -/* compiler builtin: - float __builtin_expf(float ) ; */ -/* compiler builtin: - int __builtin_types_compatible_p(unsigned long , unsigned long ) ; */ -/* compiler builtin: - long double __builtin_atan2l(long double , long double ) ; */ -/* compiler builtin: - void *__builtin_apply_args(void) ; */ -/* compiler builtin: - void __attribute__((__overloaded__)) __atomic_exchange_2(...) ; */ -/* compiler builtin: - float __builtin_logf(float ) ; */ -/* compiler builtin: - void __attribute__((__overloaded__)) __atomic_sub_fetch_2(...) ; */ -/* compiler builtin: - unsigned long __builtin_strlen(char const * ) ; */ -/* compiler builtin: - int __builtin_ffs(unsigned int ) ; */ -/* compiler builtin: - void __attribute__((__overloaded__)) __atomic_fetch_xor_16(...) ; */ -/* compiler builtin: - double __builtin_inf(void) ; */ -/* compiler builtin: - void __attribute__((__overloaded__)) __atomic_fetch_or_16(...) ; */ -/* compiler builtin: - void *__builtin___memcpy_chk(void * , void const * , unsigned long , unsigned long ) ; */ -/* compiler builtin: - void __attribute__((__overloaded__)) __atomic_load_4(...) ; */ -/* compiler builtin: - void __atomic_store_n(...) ; */ -/* compiler builtin: - void __builtin_trap(void) ; */ -/* compiler builtin: - void __attribute__((__overloaded__)) __atomic_fetch_add_4(...) ; */ -/* compiler builtin: - int __builtin_parityl(unsigned long ) ; */ -/* compiler builtin: - void __attribute__((__overloaded__)) __atomic_nand_fetch_2(...) ; */ -/* compiler builtin: - void __attribute__((__overloaded__)) __sync_lock_test_and_set(...) ; */ -/* compiler builtin: - unsigned long __builtin_strspn(char const * , char const * ) ; */ -/* compiler builtin: - void __builtin_varargs_start(__builtin_va_list ) ; */ -/* compiler builtin: - void __attribute__((__overloaded__)) __atomic_sub_fetch(...) ; */ -/* compiler builtin: - void __attribute__((__overloaded__)) __atomic_fetch_and_16(...) ; */ -/* compiler builtin: - _Bool __atomic_compare_exchange_8(...) ; */ -/* compiler builtin: - void __attribute__((__overloaded__)) __atomic_nand_fetch(...) ; */ -/* compiler builtin: - double __builtin_nan(char const * ) ; */ -/* compiler builtin: - void __attribute__((__overloaded__)) __atomic_load_8(...) ; */ -/* compiler builtin: - int __builtin___snprintf_chk(char * , unsigned long , int , unsigned long , - char const * , ...) ; */ -/* compiler builtin: - void __attribute__((__overloaded__)) __atomic_xor_fetch_4(...) ; */ -/* compiler builtin: - void __attribute__((__overloaded__)) __atomic_fetch_sub_2(...) ; */ -/* compiler builtin: - void __attribute__((__overloaded__)) __atomic_add_fetch(...) ; */ -/* compiler builtin: - long double __builtin_atanl(long double ) ; */ -/* compiler builtin: - int __builtin_clzll(unsigned long long ) ; */ -/* compiler builtin: - float __builtin_huge_valf(void) ; */ -/* compiler builtin: - float __builtin_coshf(float ) ; */ -/* compiler builtin: - float __builtin_nansf(char const * ) ; */ -/* compiler builtin: - void __atomic_store_8(...) ; */ -/* compiler builtin: - void __attribute__((__overloaded__)) __atomic_xor_fetch(...) ; */ -/* compiler builtin: - void __attribute__((__overloaded__)) __sync_fetch_and_add(...) ; */ -/* compiler builtin: - int __builtin___vsnprintf_chk(char * , unsigned long , int , unsigned long , - char const * , __builtin_va_list ) ; */ -/* compiler builtin: - float __builtin_nanf(char const * ) ; */ -/* compiler builtin: - void __attribute__((__overloaded__)) __atomic_or_fetch_2(...) ; */ -/* compiler builtin: - void __attribute__((__overloaded__)) __atomic_add_fetch_1(...) ; */ -/* compiler builtin: - void __attribute__((__overloaded__)) __atomic_fetch_xor(...) ; */ -/* compiler builtin: - void __attribute__((__overloaded__)) __atomic_add_fetch_8(...) ; */ -/* compiler builtin: - void __attribute__((__overloaded__)) __atomic_fetch_xor_4(...) ; */ -/* compiler builtin: - void __attribute__((__overloaded__)) __atomic_fetch_sub_8(...) ; */ -/* compiler builtin: - _Bool __sync_bool_compare_and_swap(...) ; */ -/* compiler builtin: - double __builtin_atan2(double , double ) ; */ -/* compiler builtin: - void __attribute__((__overloaded__)) __builtin_tgmath(...) ; */ -/* compiler builtin: - int __builtin_popcountl(unsigned long ) ; */ -/* compiler builtin: - void __attribute__((__overloaded__)) __atomic_and_fetch_1(...) ; */ -/* compiler builtin: - long double __builtin_ceill(long double ) ; */ -/* compiler builtin: - void __atomic_store_1(...) ; */ -/* compiler builtin: - char *__builtin___strcpy_chk(char * , char const * , unsigned long ) ; */ -/* compiler builtin: - void __attribute__((__overloaded__)) __atomic_xor_fetch_1(...) ; */ -/* compiler builtin: - void __attribute__((__overloaded__)) __atomic_fetch_or_2(...) ; */ -/* compiler builtin: - void __attribute__((__overloaded__)) __atomic_sub_fetch_16(...) ; */ -/* compiler builtin: - double __builtin_floor(double ) ; */ -/* compiler builtin: - double __builtin_cos(double ) ; */ -/* compiler builtin: - void __attribute__((__overloaded__)) __sync_fetch_and_sub(...) ; */ -/* compiler builtin: - void *__builtin_memset(void * , int , int ) ; */ -/* compiler builtin: - void __attribute__((__overloaded__)) __atomic_fetch_add_2(...) ; */ -/* compiler builtin: - long double __builtin_nanl(char const * ) ; */ -/* compiler builtin: - float __builtin_atan2f(float , float ) ; */ -/* compiler builtin: - _Bool __atomic_is_lock_free(unsigned long , void * ) ; */ -/* compiler builtin: - int __builtin_popcount(unsigned int ) ; */ -/* compiler builtin: - double __builtin_sinh(double ) ; */ -/* compiler builtin: - void __builtin_bcopy(void const * , void * , unsigned long ) ; */ -/* compiler builtin: - void __attribute__((__overloaded__)) __atomic_and_fetch_8(...) ; */ -/* compiler builtin: - void __attribute__((__overloaded__)) __atomic_fetch_sub(...) ; */ -/* compiler builtin: - void *__builtin_extract_return_addr(void * ) ; */ -/* compiler builtin: - int __builtin_bswap32(int ) ; */ -/* compiler builtin: - double __builtin_ldexp(double , int ) ; */ -/* compiler builtin: - long double __builtin_infl(void) ; */ -/* compiler builtin: - float __builtin_fmodf(float ) ; */ -/* compiler builtin: - void __attribute__((__overloaded__)) __atomic_add_fetch_4(...) ; */ -/* compiler builtin: - void *__builtin_frame_address(unsigned int ) ; */ -#line 1 "lib/goblint/runtime/include/goblint.h" -extern void __goblint_check(int exp ) ; -#line 2 -extern void __goblint_assume(int exp ) ; -#line 3 -extern void __goblint_assert(int exp ) ; -#line 5 -extern void __goblint_assume_join() ; -#line 7 -extern void __goblint_split_begin(int exp ) ; -#line 8 -extern void __goblint_split_end(int exp ) ; -#line 4 "tests/regression/55-loop-unrolling/01-simple-cases.c" -int global ; -#line 8 -void example1(void) ; -#line 9 -void example2(void) ; -#line 10 -void example3(void) ; -#line 11 -void example4(void) ; -#line 12 -void example5(void) ; -#line 13 -void example6(void) ; -#line 14 -void example7(void) ; -#line 15 -void example8(void) ; -#line 16 -void example9(void) ; -#line 17 -void example10(void) ; -#line 6 "tests/regression/55-loop-unrolling/01-simple-cases.c" -int main(void) -{ - - - { -#line 8 - example1(); -#line 9 - example2(); -#line 10 - example3(); -#line 11 - example4(); -#line 12 - example5(); -#line 13 - example6(); -#line 14 - example7(); -#line 15 - example8(); -#line 16 - example9(); -#line 17 - example10(); -#line 18 - return (0); -} -} -#line 22 "tests/regression/55-loop-unrolling/01-simple-cases.c" -void example1(void) -{ - int a[5] ; - int i ; - int term27_5-file_01-simple-cases ; - - { -#line 25 - i = 0; - { -#line 27 - term27_5-file_01-simple-cases = 0; - { -#line 27 - while (1) { - while_continue: /* CIL Label */ ; -#line 27 - if (! (i < 5)) { -#line 27 - goto while_break; - } -#line 27 - term27_5-file_01-simple-cases ++; -#line 28 - a[i] = i; -#line 29 - i ++; - } - while_break: /* CIL Label */ ; - } -#line 27 - __goblint_bounded(term27_5-file_01-simple-cases); - } -#line 32 - __goblint_check(a[0] == 0); -#line 33 - __goblint_check(a[3] == 3); -#line 34 - return; -} -} -#line 37 "tests/regression/55-loop-unrolling/01-simple-cases.c" -void example2(void) -{ - int a[5] ; - int i ; - int term42_5-file_01-simple-cases ; - - { -#line 40 - i = 0; - { -#line 42 - term42_5-file_01-simple-cases = 0; - { -#line 42 - while (1) { - while_continue: /* CIL Label */ ; -#line 43 - a[i] = i; -#line 44 - i ++; -#line 42 - term42_5-file_01-simple-cases ++; -#line 42 - if (! (i <= 5)) { -#line 42 - goto while_break; - } - } - while_break: /* CIL Label */ ; - } -#line 42 - __goblint_bounded(term42_5-file_01-simple-cases); - } -#line 47 - __goblint_check(a[0] == 0); -#line 48 - __goblint_check(a[3] == 3); -#line 49 - return; -} -} -#line 52 "tests/regression/55-loop-unrolling/01-simple-cases.c" -void example3(void) -{ - int a[10] ; - int i ; - int term57_5-file_01-simple-cases ; - - { -#line 55 - i = 0; - { -#line 57 - term57_5-file_01-simple-cases = 0; - { -#line 57 - while (1) { - while_continue: /* CIL Label */ ; -#line 57 - if (! (i < 5)) { -#line 57 - goto while_break; - } -#line 57 - term57_5-file_01-simple-cases ++; -#line 58 - a[i] = i; -#line 59 - i ++; - } - while_break: /* CIL Label */ ; - } -#line 57 - __goblint_bounded(term57_5-file_01-simple-cases); - } -#line 62 - __goblint_check(a[0] == 0); -#line 63 - __goblint_check(a[3] == 0); -#line 64 - __goblint_check(a[7] == 0); -#line 65 - return; -} -} -#line 68 "tests/regression/55-loop-unrolling/01-simple-cases.c" -void example4(void) -{ - int a[10] ; - int i ; - int first_iteration ; - int term74_5-file_01-simple-cases ; - - { -#line 71 - i = 0; -#line 72 - first_iteration = 1; - { -#line 74 - term74_5-file_01-simple-cases = 0; - { -#line 74 - while (1) { - while_continue: /* CIL Label */ ; -#line 74 - if (! (i < 10)) { -#line 74 - goto while_break; - } -#line 74 - term74_5-file_01-simple-cases ++; -#line 75 - if (first_iteration == 1) { -#line 75 - __goblint_check(i == 0); - } else -#line 76 - if (i > 5) { -#line 76 - __goblint_check(i == 6); - } -#line 77 - first_iteration = 0; -#line 78 - a[i] = 0; -#line 79 - i ++; - } - while_break: /* CIL Label */ ; - } -#line 74 - __goblint_bounded(term74_5-file_01-simple-cases); - } -#line 82 - __goblint_check(a[0] == 0); -#line 83 - __goblint_check(first_iteration == 0); -#line 84 - return; -} -} -#line 89 "tests/regression/55-loop-unrolling/01-simple-cases.c" -void example5(void) -{ - int a[4] ; - int i ; - int top ; - int term95_5-file_01-simple-cases ; - - { -#line 92 - i = 0; -#line 93 - top = 0; - { -#line 95 - term95_5-file_01-simple-cases = 0; - { -#line 95 - while (1) { - while_continue: /* CIL Label */ ; -#line 95 - if (! (i < 4)) { -#line 95 - goto while_break; - } -#line 95 - term95_5-file_01-simple-cases ++; -#line 96 - a[i] = 0; -#line 97 - top += i; -#line 98 - if (i == 2) { -#line 99 - __goblint_check(top == 3); - } else { -#line 102 - __goblint_check(top == 3); - } -#line 104 - i ++; - } - while_break: /* CIL Label */ ; - } -#line 95 - __goblint_bounded(term95_5-file_01-simple-cases); - } -#line 107 - __goblint_check(a[0] == 0); -#line 108 - __goblint_check(a[3] == 0); -#line 109 - __goblint_check(top == 6); -#line 110 - return; -} -} -#line 113 "tests/regression/55-loop-unrolling/01-simple-cases.c" -void example6(void) -{ - int a[5] ; - int i ; - int top ; - int term119_5-file_01-simple-cases ; - - { -#line 116 - i = 0; -#line 117 - top = 0; - { -#line 119 - term119_5-file_01-simple-cases = 0; - { -#line 119 - while (1) { - while_continue: /* CIL Label */ ; -#line 119 - if (! (i < 3)) { -#line 119 - goto while_break; - } -#line 119 - term119_5-file_01-simple-cases ++; -#line 120 - a[i] = 0; -#line 121 - __goblint_check(a[0] == 0); -#line 122 - i ++; - } - while_break: /* CIL Label */ ; - } -#line 119 - __goblint_bounded(term119_5-file_01-simple-cases); - } -#line 125 - __goblint_check(a[0] == 0); -#line 126 - __goblint_check(a[3] == 0); -#line 127 - __goblint_check(top == 6); -#line 128 - return; -} -} -#line 131 "tests/regression/55-loop-unrolling/01-simple-cases.c" -int update(int i ) -{ - - - { -#line 132 - if (i > 5) { -#line 133 - return (0); - } else { -#line 136 - return (1); - } -} -} -#line 139 "tests/regression/55-loop-unrolling/01-simple-cases.c" -void example7(void) -{ - int a[10] ; - int i ; - int tmp ; - int term143_2-file_01-simple-cases ; - - { -#line 142 - i = 0; - { -#line 143 - term143_2-file_01-simple-cases = 0; - { -#line 143 - while (1) { - while_continue: /* CIL Label */ ; -#line 143 - tmp = update(i); -#line 143 - term143_2-file_01-simple-cases ++; -#line 143 - if (! tmp) { -#line 143 - goto while_break; - } -#line 144 - a[i] = i; -#line 145 - i ++; - } - while_break: /* CIL Label */ ; - } -#line 143 - __goblint_bounded(term143_2-file_01-simple-cases); - } -#line 147 - __goblint_check(a[0] == 0); -#line 148 - __goblint_check(a[6] == 0); -#line 149 - return; -} -} -#line 152 "tests/regression/55-loop-unrolling/01-simple-cases.c" -void example8(void) -{ - int a[5] ; - int b[5] ; - int i ; - int j ; - int term160_9-file_01-simple-cases ; - int term157_2-file_01-simple-cases ; - - { -#line 155 - b[0] = 0; -#line 155 - b[1] = 0; -#line 155 - b[2] = 0; -#line 155 - b[3] = 0; -#line 155 - b[4] = 0; -#line 156 - i = 0; - { -#line 157 - term157_2-file_01-simple-cases = 0; - { -#line 157 - while (1) { - while_continue: /* CIL Label */ ; -#line 157 - if (! (i < 5)) { -#line 157 - goto while_break; - } -#line 157 - term157_2-file_01-simple-cases ++; -#line 158 - a[i] = i; -#line 159 - j = 0; - { -#line 160 - term160_9-file_01-simple-cases = 0; - { -#line 160 - while (1) { - while_continue___0: /* CIL Label */ ; -#line 160 - if (! (j < 5)) { -#line 160 - goto while_break___0; - } -#line 160 - term160_9-file_01-simple-cases ++; -#line 161 - b[j] += a[i]; -#line 162 - j ++; - } - while_break___0: /* CIL Label */ ; - } -#line 160 - __goblint_bounded(term160_9-file_01-simple-cases); - } -#line 164 - i ++; - } - while_break: /* CIL Label */ ; - } -#line 157 - __goblint_bounded(term157_2-file_01-simple-cases); - } -#line 166 - return; -} -} -#line 170 "tests/regression/55-loop-unrolling/01-simple-cases.c" -void example9(void) -{ - int a[5] ; - int i ; - int term174_2-file_01-simple-cases ; - - { -#line 173 - i = 0; - { -#line 174 - term174_2-file_01-simple-cases = 0; - { -#line 174 - while (1) { - while_continue: /* CIL Label */ ; -#line 174 - if (! 1) { -#line 174 - goto while_break; - } -#line 174 - term174_2-file_01-simple-cases ++; -#line 175 - a[i] = i; -#line 176 - i ++; -#line 177 - if (i == 5) { -#line 177 - goto while_break; - } - } - while_break: /* CIL Label */ ; - } -#line 174 - __goblint_bounded(term174_2-file_01-simple-cases); - } -#line 179 - return; -} -} -#line 183 "tests/regression/55-loop-unrolling/01-simple-cases.c" -void example10(void) -{ - int a[5] ; - int i ; - int term187_2-file_01-simple-cases ; - - { -#line 186 - i = 0; - { -#line 187 - term187_2-file_01-simple-cases = 0; - { -#line 187 - while (1) { - while_continue: /* CIL Label */ ; -#line 187 - if (! (i < 5)) { -#line 187 - goto while_break; - } -#line 187 - term187_2-file_01-simple-cases ++; -#line 188 - if (i == 3) { -#line 189 - i ++; -#line 190 - goto while_continue; - } -#line 192 - a[i] = i; -#line 193 - i ++; - } - while_break: /* CIL Label */ ; - } -#line 187 - __goblint_bounded(term187_2-file_01-simple-cases); - } -#line 195 - return; -} -} -#line 117 "/usr/include/x86_64-linux-gnu/bits/cpu-set.h" -extern int ( __attribute__((__leaf__)) __sched_cpucount)(size_t __setsize , cpu_set_t const *__setp ) __attribute__((__nothrow__)) ; -#line 119 -extern cpu_set_t *( __attribute__((__leaf__)) __sched_cpualloc)(size_t __count ) __attribute__((__nothrow__)) ; -#line 120 -extern void ( __attribute__((__leaf__)) __sched_cpufree)(cpu_set_t *__set ) __attribute__((__nothrow__)) ; -#line 54 "/usr/include/sched.h" -extern int ( __attribute__((__leaf__)) sched_setparam)(__pid_t __pid , struct sched_param const *__param ) __attribute__((__nothrow__)) ; -#line 58 -extern int ( __attribute__((__leaf__)) sched_getparam)(__pid_t __pid , struct sched_param *__param ) __attribute__((__nothrow__)) ; -#line 61 -extern int ( __attribute__((__leaf__)) sched_setscheduler)(__pid_t __pid , int __policy , - struct sched_param const *__param ) __attribute__((__nothrow__)) ; -#line 65 -extern int ( __attribute__((__leaf__)) sched_getscheduler)(__pid_t __pid ) __attribute__((__nothrow__)) ; -#line 68 -extern int ( __attribute__((__leaf__)) sched_yield)(void) __attribute__((__nothrow__)) ; -#line 71 -extern int ( __attribute__((__leaf__)) sched_get_priority_max)(int __algorithm ) __attribute__((__nothrow__)) ; -#line 74 -extern int ( __attribute__((__leaf__)) sched_get_priority_min)(int __algorithm ) __attribute__((__nothrow__)) ; -#line 78 -extern int ( __attribute__((__leaf__)) sched_rr_get_interval)(__pid_t __pid , struct timespec *__t ) __attribute__((__nothrow__)) ; -#line 72 "/usr/include/time.h" -extern clock_t ( __attribute__((__leaf__)) clock)(void) __attribute__((__nothrow__)) ; -#line 76 -extern time_t ( __attribute__((__leaf__)) time)(time_t *__timer ) __attribute__((__nothrow__)) ; -#line 79 -extern double ( __attribute__((__leaf__)) difftime)(time_t __time1 , time_t __time0 ) __attribute__((__nothrow__, -__const__)) ; -#line 83 -extern time_t ( __attribute__((__leaf__)) mktime)(struct tm *__tp ) __attribute__((__nothrow__)) ; -#line 100 -extern size_t ( __attribute__((__leaf__)) strftime)(char * __restrict __s , size_t __maxsize , - char const * __restrict __format , - struct tm const * __restrict __tp ) __attribute__((__nothrow__)) ; -#line 116 -extern size_t ( __attribute__((__leaf__)) strftime_l)(char * __restrict __s , size_t __maxsize , - char const * __restrict __format , - struct tm const * __restrict __tp , - locale_t __loc ) __attribute__((__nothrow__)) ; -#line 132 -extern struct tm *( __attribute__((__leaf__)) gmtime)(time_t const *__timer ) __attribute__((__nothrow__)) ; -#line 136 -extern struct tm *( __attribute__((__leaf__)) localtime)(time_t const *__timer ) __attribute__((__nothrow__)) ; -#line 154 -extern struct tm *( __attribute__((__leaf__)) gmtime_r)(time_t const * __restrict __timer , - struct tm * __restrict __tp ) __attribute__((__nothrow__)) ; -#line 159 -extern struct tm *( __attribute__((__leaf__)) localtime_r)(time_t const * __restrict __timer , - struct tm * __restrict __tp ) __attribute__((__nothrow__)) ; -#line 179 -extern char *( __attribute__((__leaf__)) asctime)(struct tm const *__tp ) __attribute__((__nothrow__)) ; -#line 183 -extern char *( __attribute__((__leaf__)) ctime)(time_t const *__timer ) __attribute__((__nothrow__)) ; -#line 197 -extern char *( __attribute__((__leaf__)) asctime_r)(struct tm const * __restrict __tp , - char * __restrict __buf ) __attribute__((__nothrow__)) ; -#line 202 -extern char *( __attribute__((__leaf__)) ctime_r)(time_t const * __restrict __timer , - char * __restrict __buf ) __attribute__((__nothrow__)) ; -#line 217 -extern char *__tzname[2] ; -#line 218 -extern int __daylight ; -#line 219 -extern long __timezone ; -#line 224 -extern char *tzname[2] ; -#line 228 -extern void ( __attribute__((__leaf__)) tzset)(void) __attribute__((__nothrow__)) ; -#line 232 -extern int daylight ; -#line 233 -extern long timezone ; -#line 249 -extern time_t ( __attribute__((__leaf__)) timegm)(struct tm *__tp ) __attribute__((__nothrow__)) ; -#line 251 -extern time_t ( __attribute__((__leaf__)) timelocal)(struct tm *__tp ) __attribute__((__nothrow__)) ; -#line 262 -extern int ( __attribute__((__leaf__)) dysize)(int __year ) __attribute__((__nothrow__, -__const__)) ; -#line 272 -extern int nanosleep(struct timespec const *__requested_time , struct timespec *__remaining ) ; -#line 276 -extern int ( __attribute__((__leaf__)) clock_getres)(clockid_t __clock_id , struct timespec *__res ) __attribute__((__nothrow__)) ; -#line 279 -extern int ( __attribute__((__leaf__)) clock_gettime)(clockid_t __clock_id , struct timespec *__tp ) __attribute__((__nothrow__)) ; -#line 282 -extern int ( __attribute__((__leaf__)) clock_settime)(clockid_t __clock_id , struct timespec const *__tp ) __attribute__((__nothrow__)) ; -#line 311 -extern int clock_nanosleep(clockid_t __clock_id , int __flags , struct timespec const *__req , - struct timespec *__rem ) ; -#line 326 -extern int ( __attribute__((__leaf__)) clock_getcpuclockid)(pid_t __pid , clockid_t *__clock_id ) __attribute__((__nothrow__)) ; -#line 331 -extern int ( __attribute__((__leaf__)) timer_create)(clockid_t __clock_id , struct sigevent * __restrict __evp , - timer_t * __restrict __timerid ) __attribute__((__nothrow__)) ; -#line 336 -extern int ( __attribute__((__leaf__)) timer_delete)(timer_t __timerid ) __attribute__((__nothrow__)) ; -#line 340 -extern int ( __attribute__((__leaf__)) timer_settime)(timer_t __timerid , int __flags , - struct itimerspec const * __restrict __value , - struct itimerspec * __restrict __ovalue ) __attribute__((__nothrow__)) ; -#line 345 -extern int ( __attribute__((__leaf__)) timer_gettime)(timer_t __timerid , struct itimerspec *__value ) __attribute__((__nothrow__)) ; -#line 364 -extern int ( __attribute__((__leaf__)) timer_getoverrun)(timer_t __timerid ) __attribute__((__nothrow__)) ; -#line 371 -extern int ( __attribute__((__nonnull__(1), __leaf__)) timespec_get)(struct timespec *__ts , - int __base ) __attribute__((__nothrow__)) ; -#line 202 "/usr/include/pthread.h" -extern int ( __attribute__((__nonnull__(1,3))) pthread_create)(pthread_t * __restrict __newthread , - pthread_attr_t const * __restrict __attr , - void *(*__start_routine)(void * ) , - void * __restrict __arg ) __attribute__((__nothrow__)) ; -#line 211 -extern void pthread_exit(void *__retval ) __attribute__((__noreturn__)) ; -#line 219 -extern int pthread_join(pthread_t __th , void **__thread_return ) ; -#line 269 -extern int ( __attribute__((__leaf__)) pthread_detach)(pthread_t __th ) __attribute__((__nothrow__)) ; -#line 273 -extern pthread_t ( __attribute__((__leaf__)) pthread_self)(void) __attribute__((__nothrow__, -__const__)) ; -#line 276 -extern int ( __attribute__((__leaf__)) pthread_equal)(pthread_t __thread1 , pthread_t __thread2 ) __attribute__((__nothrow__, -__const__)) ; -#line 285 -extern int ( __attribute__((__nonnull__(1), __leaf__)) pthread_attr_init)(pthread_attr_t *__attr ) __attribute__((__nothrow__)) ; -#line 288 -extern int ( __attribute__((__nonnull__(1), __leaf__)) pthread_attr_destroy)(pthread_attr_t *__attr ) __attribute__((__nothrow__)) ; -#line 292 -extern int ( __attribute__((__nonnull__(1,2), __leaf__)) pthread_attr_getdetachstate)(pthread_attr_t const *__attr , - int *__detachstate ) __attribute__((__nothrow__)) ; -#line 297 -extern int ( __attribute__((__nonnull__(1), __leaf__)) pthread_attr_setdetachstate)(pthread_attr_t *__attr , - int __detachstate ) __attribute__((__nothrow__)) ; -#line 303 -extern int ( __attribute__((__nonnull__(1,2), __leaf__)) pthread_attr_getguardsize)(pthread_attr_t const *__attr , - size_t *__guardsize ) __attribute__((__nothrow__)) ; -#line 308 -extern int ( __attribute__((__nonnull__(1), __leaf__)) pthread_attr_setguardsize)(pthread_attr_t *__attr , - size_t __guardsize ) __attribute__((__nothrow__)) ; -#line 314 -extern int ( __attribute__((__nonnull__(1,2), __leaf__)) pthread_attr_getschedparam)(pthread_attr_t const * __restrict __attr , - struct sched_param * __restrict __param ) __attribute__((__nothrow__)) ; -#line 319 -extern int ( __attribute__((__nonnull__(1,2), __leaf__)) pthread_attr_setschedparam)(pthread_attr_t * __restrict __attr , - struct sched_param const * __restrict __param ) __attribute__((__nothrow__)) ; -#line 324 -extern int ( __attribute__((__nonnull__(1,2), __leaf__)) pthread_attr_getschedpolicy)(pthread_attr_t const * __restrict __attr , - int * __restrict __policy ) __attribute__((__nothrow__)) ; -#line 329 -extern int ( __attribute__((__nonnull__(1), __leaf__)) pthread_attr_setschedpolicy)(pthread_attr_t *__attr , - int __policy ) __attribute__((__nothrow__)) ; -#line 333 -extern int ( __attribute__((__nonnull__(1,2), __leaf__)) pthread_attr_getinheritsched)(pthread_attr_t const * __restrict __attr , - int * __restrict __inherit ) __attribute__((__nothrow__)) ; -#line 338 -extern int ( __attribute__((__nonnull__(1), __leaf__)) pthread_attr_setinheritsched)(pthread_attr_t *__attr , - int __inherit ) __attribute__((__nothrow__)) ; -#line 344 -extern int ( __attribute__((__nonnull__(1,2), __leaf__)) pthread_attr_getscope)(pthread_attr_t const * __restrict __attr , - int * __restrict __scope ) __attribute__((__nothrow__)) ; -#line 349 -extern int ( __attribute__((__nonnull__(1), __leaf__)) pthread_attr_setscope)(pthread_attr_t *__attr , - int __scope ) __attribute__((__nothrow__)) ; -#line 353 -extern int ( __attribute__((__nonnull__(1,2), __leaf__)) pthread_attr_getstackaddr)(pthread_attr_t const * __restrict __attr , - void ** __restrict __stackaddr ) __attribute__((__nothrow__, -__deprecated__)) ; -#line 361 -extern int ( __attribute__((__nonnull__(1), __leaf__)) pthread_attr_setstackaddr)(pthread_attr_t *__attr , - void *__stackaddr ) __attribute__((__nothrow__, -__deprecated__)) ; -#line 366 -extern int ( __attribute__((__nonnull__(1,2), __leaf__)) pthread_attr_getstacksize)(pthread_attr_t const * __restrict __attr , - size_t * __restrict __stacksize ) __attribute__((__nothrow__)) ; -#line 373 -extern int ( __attribute__((__nonnull__(1), __leaf__)) pthread_attr_setstacksize)(pthread_attr_t *__attr , - size_t __stacksize ) __attribute__((__nothrow__)) ; -#line 379 -extern int ( __attribute__((__nonnull__(1,2,3), __leaf__)) pthread_attr_getstack)(pthread_attr_t const * __restrict __attr , - void ** __restrict __stackaddr , - size_t * __restrict __stacksize ) __attribute__((__nothrow__)) ; -#line 387 -extern int ( __attribute__((__nonnull__(1), __leaf__)) pthread_attr_setstack)(pthread_attr_t *__attr , - void *__stackaddr , - size_t __stacksize ) __attribute__((__nothrow__)) ; -#line 441 -extern int ( __attribute__((__nonnull__(3), __leaf__)) pthread_setschedparam)(pthread_t __target_thread , - int __policy , - struct sched_param const *__param ) __attribute__((__nothrow__)) ; -#line 446 -extern int ( __attribute__((__nonnull__(2,3), __leaf__)) pthread_getschedparam)(pthread_t __target_thread , - int * __restrict __policy , - struct sched_param * __restrict __param ) __attribute__((__nothrow__)) ; -#line 452 -extern int ( __attribute__((__leaf__)) pthread_setschedprio)(pthread_t __target_thread , - int __prio ) __attribute__((__nothrow__)) ; -#line 509 -int ( __attribute__((__nonnull__(1,2))) pthread_once)(pthread_once_t *once_control , - void (*init_routine)(void) ) __attribute__((__goblint_stub__)) ; -#line 521 -extern int pthread_setcancelstate(int __state , int *__oldstate ) ; -#line 525 -extern int pthread_setcanceltype(int __type , int *__oldtype ) ; -#line 528 -extern int pthread_cancel(pthread_t __th ) ; -#line 533 -extern void pthread_testcancel(void) ; -#line 697 -extern void __pthread_register_cancel(__pthread_unwind_buf_t *__buf ) ; -#line 709 -extern void __pthread_unregister_cancel(__pthread_unwind_buf_t *__buf ) ; -#line 750 -extern void __pthread_unwind_next(__pthread_unwind_buf_t *__buf ) __attribute__((__weak__, -__noreturn__)) ; -#line 766 -extern int __sigsetjmp_cancel(struct __cancel_jmp_buf_tag *__env , int __savemask ) __asm__("__sigsetjmp") __attribute__((__returns_twice__, -__nothrow__)) ; -#line 781 -extern int ( __attribute__((__nonnull__(1), __leaf__)) pthread_mutex_init)(pthread_mutex_t *__mutex , - pthread_mutexattr_t const *__mutexattr ) __attribute__((__nothrow__)) ; -#line 786 -extern int ( __attribute__((__nonnull__(1), __leaf__)) pthread_mutex_destroy)(pthread_mutex_t *__mutex ) __attribute__((__nothrow__)) ; -#line 790 -extern int ( __attribute__((__nonnull__(1))) pthread_mutex_trylock)(pthread_mutex_t *__mutex ) __attribute__((__nothrow__)) ; -#line 794 -extern int ( __attribute__((__nonnull__(1))) pthread_mutex_lock)(pthread_mutex_t *__mutex ) __attribute__((__nothrow__)) ; -#line 800 -extern int ( __attribute__((__nonnull__(1,2))) pthread_mutex_timedlock)(pthread_mutex_t * __restrict __mutex , - struct timespec const * __restrict __abstime ) __attribute__((__nothrow__)) ; -#line 835 -extern int ( __attribute__((__nonnull__(1))) pthread_mutex_unlock)(pthread_mutex_t *__mutex ) __attribute__((__nothrow__)) ; -#line 840 -extern int ( __attribute__((__nonnull__(1,2), __leaf__)) pthread_mutex_getprioceiling)(pthread_mutex_t const * __restrict __mutex , - int * __restrict __prioceiling ) __attribute__((__nothrow__)) ; -#line 847 -extern int ( __attribute__((__nonnull__(1,3), __leaf__)) pthread_mutex_setprioceiling)(pthread_mutex_t * __restrict __mutex , - int __prioceiling , - int * __restrict __old_ceiling ) __attribute__((__nothrow__)) ; -#line 855 -extern int ( __attribute__((__nonnull__(1), __leaf__)) pthread_mutex_consistent)(pthread_mutex_t *__mutex ) __attribute__((__nothrow__)) ; -#line 874 -extern int ( __attribute__((__nonnull__(1), __leaf__)) pthread_mutexattr_init)(pthread_mutexattr_t *__attr ) __attribute__((__nothrow__)) ; -#line 878 -extern int ( __attribute__((__nonnull__(1), __leaf__)) pthread_mutexattr_destroy)(pthread_mutexattr_t *__attr ) __attribute__((__nothrow__)) ; -#line 882 -extern int ( __attribute__((__nonnull__(1,2), __leaf__)) pthread_mutexattr_getpshared)(pthread_mutexattr_t const * __restrict __attr , - int * __restrict __pshared ) __attribute__((__nothrow__)) ; -#line 888 -extern int ( __attribute__((__nonnull__(1), __leaf__)) pthread_mutexattr_setpshared)(pthread_mutexattr_t *__attr , - int __pshared ) __attribute__((__nothrow__)) ; -#line 894 -extern int ( __attribute__((__nonnull__(1,2), __leaf__)) pthread_mutexattr_gettype)(pthread_mutexattr_t const * __restrict __attr , - int * __restrict __kind ) __attribute__((__nothrow__)) ; -#line 901 -extern int ( __attribute__((__nonnull__(1), __leaf__)) pthread_mutexattr_settype)(pthread_mutexattr_t *__attr , - int __kind ) __attribute__((__nothrow__)) ; -#line 906 -extern int ( __attribute__((__nonnull__(1,2), __leaf__)) pthread_mutexattr_getprotocol)(pthread_mutexattr_t const * __restrict __attr , - int * __restrict __protocol ) __attribute__((__nothrow__)) ; -#line 913 -extern int ( __attribute__((__nonnull__(1), __leaf__)) pthread_mutexattr_setprotocol)(pthread_mutexattr_t *__attr , - int __protocol ) __attribute__((__nothrow__)) ; -#line 918 -extern int ( __attribute__((__nonnull__(1,2), __leaf__)) pthread_mutexattr_getprioceiling)(pthread_mutexattr_t const * __restrict __attr , - int * __restrict __prioceiling ) __attribute__((__nothrow__)) ; -#line 924 -extern int ( __attribute__((__nonnull__(1), __leaf__)) pthread_mutexattr_setprioceiling)(pthread_mutexattr_t *__attr , - int __prioceiling ) __attribute__((__nothrow__)) ; -#line 930 -extern int ( __attribute__((__nonnull__(1,2), __leaf__)) pthread_mutexattr_getrobust)(pthread_mutexattr_t const *__attr , - int *__robustness ) __attribute__((__nothrow__)) ; -#line 946 -extern int ( __attribute__((__nonnull__(1), __leaf__)) pthread_mutexattr_setrobust)(pthread_mutexattr_t *__attr , - int __robustness ) __attribute__((__nothrow__)) ; -#line 967 -extern int ( __attribute__((__nonnull__(1), __leaf__)) pthread_rwlock_init)(pthread_rwlock_t * __restrict __rwlock , - pthread_rwlockattr_t const * __restrict __attr ) __attribute__((__nothrow__)) ; -#line 972 -extern int ( __attribute__((__nonnull__(1), __leaf__)) pthread_rwlock_destroy)(pthread_rwlock_t *__rwlock ) __attribute__((__nothrow__)) ; -#line 976 -extern int ( __attribute__((__nonnull__(1))) pthread_rwlock_rdlock)(pthread_rwlock_t *__rwlock ) __attribute__((__nothrow__)) ; -#line 980 -extern int ( __attribute__((__nonnull__(1))) pthread_rwlock_tryrdlock)(pthread_rwlock_t *__rwlock ) __attribute__((__nothrow__)) ; -#line 986 -extern int ( __attribute__((__nonnull__(1,2))) pthread_rwlock_timedrdlock)(pthread_rwlock_t * __restrict __rwlock , - struct timespec const * __restrict __abstime ) __attribute__((__nothrow__)) ; -#line 1023 -extern int ( __attribute__((__nonnull__(1))) pthread_rwlock_wrlock)(pthread_rwlock_t *__rwlock ) __attribute__((__nothrow__)) ; -#line 1027 -extern int ( __attribute__((__nonnull__(1))) pthread_rwlock_trywrlock)(pthread_rwlock_t *__rwlock ) __attribute__((__nothrow__)) ; -#line 1033 -extern int ( __attribute__((__nonnull__(1,2))) pthread_rwlock_timedwrlock)(pthread_rwlock_t * __restrict __rwlock , - struct timespec const * __restrict __abstime ) __attribute__((__nothrow__)) ; -#line 1071 -extern int ( __attribute__((__nonnull__(1))) pthread_rwlock_unlock)(pthread_rwlock_t *__rwlock ) __attribute__((__nothrow__)) ; -#line 1078 -extern int ( __attribute__((__nonnull__(1), __leaf__)) pthread_rwlockattr_init)(pthread_rwlockattr_t *__attr ) __attribute__((__nothrow__)) ; -#line 1082 -extern int ( __attribute__((__nonnull__(1), __leaf__)) pthread_rwlockattr_destroy)(pthread_rwlockattr_t *__attr ) __attribute__((__nothrow__)) ; -#line 1086 -extern int ( __attribute__((__nonnull__(1,2), __leaf__)) pthread_rwlockattr_getpshared)(pthread_rwlockattr_t const * __restrict __attr , - int * __restrict __pshared ) __attribute__((__nothrow__)) ; -#line 1092 -extern int ( __attribute__((__nonnull__(1), __leaf__)) pthread_rwlockattr_setpshared)(pthread_rwlockattr_t *__attr , - int __pshared ) __attribute__((__nothrow__)) ; -#line 1097 -extern int ( __attribute__((__nonnull__(1,2), __leaf__)) pthread_rwlockattr_getkind_np)(pthread_rwlockattr_t const * __restrict __attr , - int * __restrict __pref ) __attribute__((__nothrow__)) ; -#line 1103 -extern int ( __attribute__((__nonnull__(1), __leaf__)) pthread_rwlockattr_setkind_np)(pthread_rwlockattr_t *__attr , - int __pref ) __attribute__((__nothrow__)) ; -#line 1112 -extern int ( __attribute__((__nonnull__(1), __leaf__)) pthread_cond_init)(pthread_cond_t * __restrict __cond , - pthread_condattr_t const * __restrict __cond_attr ) __attribute__((__nothrow__)) ; -#line 1117 -extern int ( __attribute__((__nonnull__(1), __leaf__)) pthread_cond_destroy)(pthread_cond_t *__cond ) __attribute__((__nothrow__)) ; -#line 1121 -extern int ( __attribute__((__nonnull__(1))) pthread_cond_signal)(pthread_cond_t *__cond ) __attribute__((__nothrow__)) ; -#line 1125 -extern int ( __attribute__((__nonnull__(1))) pthread_cond_broadcast)(pthread_cond_t *__cond ) __attribute__((__nothrow__)) ; -#line 1133 -extern int ( __attribute__((__nonnull__(1,2))) pthread_cond_wait)(pthread_cond_t * __restrict __cond , - pthread_mutex_t * __restrict __mutex ) ; -#line 1145 -extern int ( __attribute__((__nonnull__(1,2,3))) pthread_cond_timedwait)(pthread_cond_t * __restrict __cond , - pthread_mutex_t * __restrict __mutex , - struct timespec const * __restrict __abstime ) ; -#line 1194 -extern int ( __attribute__((__nonnull__(1), __leaf__)) pthread_condattr_init)(pthread_condattr_t *__attr ) __attribute__((__nothrow__)) ; -#line 1198 -extern int ( __attribute__((__nonnull__(1), __leaf__)) pthread_condattr_destroy)(pthread_condattr_t *__attr ) __attribute__((__nothrow__)) ; -#line 1202 -extern int ( __attribute__((__nonnull__(1,2), __leaf__)) pthread_condattr_getpshared)(pthread_condattr_t const * __restrict __attr , - int * __restrict __pshared ) __attribute__((__nothrow__)) ; -#line 1208 -extern int ( __attribute__((__nonnull__(1), __leaf__)) pthread_condattr_setpshared)(pthread_condattr_t *__attr , - int __pshared ) __attribute__((__nothrow__)) ; -#line 1213 -extern int ( __attribute__((__nonnull__(1,2), __leaf__)) pthread_condattr_getclock)(pthread_condattr_t const * __restrict __attr , - __clockid_t * __restrict __clock_id ) __attribute__((__nothrow__)) ; -#line 1219 -extern int ( __attribute__((__nonnull__(1), __leaf__)) pthread_condattr_setclock)(pthread_condattr_t *__attr , - __clockid_t __clock_id ) __attribute__((__nothrow__)) ; -#line 1230 -extern int ( __attribute__((__nonnull__(1), __leaf__)) pthread_spin_init)(pthread_spinlock_t *__lock , - int __pshared ) __attribute__((__nothrow__)) ; -#line 1234 -extern int ( __attribute__((__nonnull__(1), __leaf__)) pthread_spin_destroy)(pthread_spinlock_t *__lock ) __attribute__((__nothrow__)) ; -#line 1238 -extern int ( __attribute__((__nonnull__(1))) pthread_spin_lock)(pthread_spinlock_t *__lock ) __attribute__((__nothrow__)) ; -#line 1242 -extern int ( __attribute__((__nonnull__(1))) pthread_spin_trylock)(pthread_spinlock_t *__lock ) __attribute__((__nothrow__)) ; -#line 1246 -extern int ( __attribute__((__nonnull__(1))) pthread_spin_unlock)(pthread_spinlock_t *__lock ) __attribute__((__nothrow__)) ; -#line 1254 -extern int ( __attribute__((__nonnull__(1), __leaf__)) pthread_barrier_init)(pthread_barrier_t * __restrict __barrier , - pthread_barrierattr_t const * __restrict __attr , - unsigned int __count ) __attribute__((__nothrow__)) ; -#line 1260 -extern int ( __attribute__((__nonnull__(1), __leaf__)) pthread_barrier_destroy)(pthread_barrier_t *__barrier ) __attribute__((__nothrow__)) ; -#line 1264 -extern int ( __attribute__((__nonnull__(1))) pthread_barrier_wait)(pthread_barrier_t *__barrier ) __attribute__((__nothrow__)) ; -#line 1269 -extern int ( __attribute__((__nonnull__(1), __leaf__)) pthread_barrierattr_init)(pthread_barrierattr_t *__attr ) __attribute__((__nothrow__)) ; -#line 1273 -extern int ( __attribute__((__nonnull__(1), __leaf__)) pthread_barrierattr_destroy)(pthread_barrierattr_t *__attr ) __attribute__((__nothrow__)) ; -#line 1277 -extern int ( __attribute__((__nonnull__(1,2), __leaf__)) pthread_barrierattr_getpshared)(pthread_barrierattr_t const * __restrict __attr , - int * __restrict __pshared ) __attribute__((__nothrow__)) ; -#line 1283 -extern int ( __attribute__((__nonnull__(1), __leaf__)) pthread_barrierattr_setpshared)(pthread_barrierattr_t *__attr , - int __pshared ) __attribute__((__nothrow__)) ; -#line 1297 -extern int ( __attribute__((__nonnull__(1), __leaf__)) pthread_key_create)(pthread_key_t *__key , - void (*__destr_function)(void * ) ) __attribute__((__nothrow__)) ; -#line 1302 -extern int ( __attribute__((__leaf__)) pthread_key_delete)(pthread_key_t __key ) __attribute__((__nothrow__)) ; -#line 1305 -extern void *( __attribute__((__leaf__)) pthread_getspecific)(pthread_key_t __key ) __attribute__((__nothrow__)) ; -#line 1308 -extern int ( __attribute__((__leaf__)) pthread_setspecific)(pthread_key_t __key , - void const *__pointer ) __attribute__((__nothrow__, -__access__(__none__,2))) ; -#line 1315 -extern int ( __attribute__((__nonnull__(2), __leaf__)) pthread_getcpuclockid)(pthread_t __thread_id , - __clockid_t *__clock_id ) __attribute__((__nothrow__)) ; -#line 1332 -extern int ( __attribute__((__leaf__)) pthread_atfork)(void (*__prepare)(void) , void (*__parent)(void) , - void (*__child)(void) ) __attribute__((__nothrow__)) ; -#line 5 "lib/libc/stub/src/pthread.c" -int ( __attribute__((__nonnull__(1,2))) pthread_once)(pthread_once_t *once_control , - void (*init_routine)(void) ) __attribute__((__goblint_stub__)) ; -#line 5 "lib/libc/stub/src/pthread.c" -int ( __attribute__((__nonnull__(1,2))) pthread_once)(pthread_once_t *once_control , - void (*init_routine)(void) ) -{ - int top ; - - { -#line 8 - (*init_routine)(); -#line 9 - return (top); -} -} -#line 6 "lib/libc/stub/src/stdlib.c" -void qsort(void *ptr , size_t count , size_t size , int (*comp)(void const * , void const * ) ) __attribute__((__goblint_stub__)) ; -#line 7 -void qsort(void *ptr , size_t count , size_t size , int (*comp)(void const * , void const * ) ) __attribute__((__goblint_stub__)) ; -#line 7 "lib/libc/stub/src/stdlib.c" -void qsort(void *ptr , size_t count , size_t size , int (*comp)(void const * , void const * ) ) -{ - size_t i ; - size_t j ; - size_t i___0 ; - size_t j___0 ; - int r ; - size_t k ; - char *a ; - char *b ; - char c ; - int term10_5-file_stdlib ; - int term9_3-file_stdlib ; - int term21_9-file_stdlib ; - int term17_5-file_stdlib ; - int term16_3-file_stdlib ; - - { -#line 9 - i = (size_t )0; - { -#line 9 - term9_3-file_stdlib = 0; - { -#line 9 - while (1) { - while_continue: /* CIL Label */ ; -#line 9 - if (! (i < count)) { -#line 9 - goto while_break; - } -#line 9 - term9_3-file_stdlib ++; -#line 10 - j = (size_t )0; - { -#line 10 - term10_5-file_stdlib = 0; - { -#line 10 - while (1) { - while_continue___0: /* CIL Label */ ; -#line 10 - if (! (j < count)) { -#line 10 - goto while_break___0; - } -#line 10 - term10_5-file_stdlib ++; -#line 11 - (*comp)((void const *)(ptr + i * size), (void const *)(ptr + j * size)); -#line 10 - j ++; - } - while_break___0: /* CIL Label */ ; - } -#line 10 - __goblint_bounded(term10_5-file_stdlib); - } -#line 9 - i ++; - } - while_break: /* CIL Label */ ; - } -#line 9 - __goblint_bounded(term9_3-file_stdlib); - } -#line 16 - i___0 = (size_t )0; - { -#line 16 - term16_3-file_stdlib = 0; - { -#line 16 - while (1) { - while_continue___1: /* CIL Label */ ; -#line 16 - if (! (i___0 < count)) { -#line 16 - goto while_break___1; - } -#line 16 - term16_3-file_stdlib ++; -#line 17 - j___0 = (size_t )0; - { -#line 17 - term17_5-file_stdlib = 0; - { -#line 17 - while (1) { - while_continue___2: /* CIL Label */ ; -#line 17 - if (! (j___0 < count)) { -#line 17 - goto while_break___2; - } -#line 17 - term17_5-file_stdlib ++; -#line 19 - if (r) { -#line 21 - k = (size_t )0; - { -#line 21 - term21_9-file_stdlib = 0; - { -#line 21 - while (1) { - while_continue___3: /* CIL Label */ ; -#line 21 - if (! (k < size)) { -#line 21 - goto while_break___3; - } -#line 21 - term21_9-file_stdlib ++; -#line 22 - a = (char *)((ptr + i___0 * size) + k); -#line 23 - b = (char *)((ptr + j___0 * size) + k); -#line 24 - c = *a; -#line 25 - *a = *b; -#line 26 - *b = c; -#line 21 - k ++; - } - while_break___3: /* CIL Label */ ; - } -#line 21 - __goblint_bounded(term21_9-file_stdlib); - } - } -#line 17 - j___0 ++; - } - while_break___2: /* CIL Label */ ; - } -#line 17 - __goblint_bounded(term17_5-file_stdlib); - } -#line 16 - i___0 ++; - } - while_break___1: /* CIL Label */ ; - } -#line 16 - __goblint_bounded(term16_3-file_stdlib); - } -#line 33 - return; -} -} -#line 37 -void *bsearch(void const *key , void const *ptr , size_t count , size_t size , - int (*comp)(void const * , void const * ) ) __attribute__((__goblint_stub__)) ; -#line 38 -void *bsearch(void const *key , void const *ptr , size_t count , size_t size , - int (*comp)(void const * , void const * ) ) __attribute__((__goblint_stub__)) ; -#line 38 "lib/libc/stub/src/stdlib.c" -void *bsearch(void const *key , void const *ptr , size_t count , size_t size , - int (*comp)(void const * , void const * ) ) -{ - size_t i ; - void const *a ; - int tmp ; - int term40_3-file_stdlib ; - - { -#line 40 - i = (size_t )0; - { -#line 40 - term40_3-file_stdlib = 0; - { -#line 40 - while (1) { - while_continue: /* CIL Label */ ; -#line 40 - if (! (i < count)) { -#line 40 - goto while_break; - } -#line 40 - term40_3-file_stdlib ++; -#line 41 - a = ptr + i * size; -#line 42 - tmp = (*comp)(key, a); -#line 42 - if (tmp == 0) { -#line 43 - return ((void *)a); - } -#line 40 - i ++; - } - while_break: /* CIL Label */ ; - } -#line 40 - __goblint_bounded(term40_3-file_stdlib); - } -#line 47 - return ((void *)0); -} -} - -vars = 0 evals = 0 narrow_reuses = 0 - -Timings: diff --git a/runningGob.sh b/runningGob.sh index 848d69c341..15007b3e0b 100755 --- a/runningGob.sh +++ b/runningGob.sh @@ -1,6 +1,6 @@ #!/bin/bash make -#make install +make install # set options and file for apron execution options_apron="--set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra --enable warn.debug" #note: preprocessing first needs to be added to apron diff --git a/src/framework/analyses.ml b/src/framework/analyses.ml index 993aaf6421..0a7ccd04b2 100644 --- a/src/framework/analyses.ml +++ b/src/framework/analyses.ml @@ -139,7 +139,13 @@ struct let name () = "Tuple" let to_yojson x = `String (show x) let relift (a,b) = (a,b) (*Todo: is this correct?*) - let printXml f (a,b) = Base1.printXml f a; Base2.printXml f b (*Todo: what do we have to put here?*) + let printXml f (a,b) = + BatPrintf.fprintf f "\n + Tuple:\n + \n + fundec\n%a\n\n + context\n%a\n\n + \n" Base1.printXml a Base2.printXml b (*Todo: what do we have to put here?*) let compare (a1,b1) (a2,b2) = 3 (*Todo: what do we have to put here?*) (*let a = Base1.compare a1 a2 in let b = Base2.compare b1 b2 in @@ -150,22 +156,26 @@ struct end -module GVarGG (G: Lattice.S) (C: Printable.S) = +module GVarGG (G: Lattice.S) (C: Printable.S) (Base: Printable.S) = struct module CSet = struct include SetDomain.Make ( struct - include (T (CilType.Fundec) (C) (C)) (* Set of Tuples*) + include (Base) (* Set of Tuples*) end ) let name () = "contexts" + let printXml f a = + BatPrintf.fprintf f "\n\n"; + iter (Base.printXml f) a; + BatPrintf.fprintf f "\n\n" end module CMap = struct include MapDomain.MapBot (C_ (C)) (CSet) - let printXml f c = BatPrintf.fprintf f "%a" printXml c (* TODO *) + let printXml f c = BatPrintf.fprintf f "%a" printXml c (*TODO*) end include Lattice.Lift2 (G) (CMap) (Printable.DefaultNames) diff --git a/src/framework/constraints.ml b/src/framework/constraints.ml index 1614354cfa..31843794ec 100644 --- a/src/framework/constraints.ml +++ b/src/framework/constraints.ml @@ -1458,144 +1458,6 @@ struct end -module DeadBranchLifter2 (S: Spec): Spec = -struct - include S - - let name () = "DeadBranch2 (" ^ S.name () ^ ")" - - (* Two global invariants: - 1. S.V -> S.G -- used for S - 2. node -> (exp -> flat bool) -- used for warnings *) - - module V = - struct - include Printable.Either (S.V) (Node) - let name () = "DeadBranch2" - let s x = `Left x - let node x = `Right x - let is_write_only = function - | `Left x -> S.V.is_write_only x - | `Right _ -> true - end - - module EM = - struct - include MapDomain.MapBot (Basetype.CilExp) (Basetype.Bools) - let name () = "branches2" - end - - module G = - struct - include Lattice.Lift2 (S.G) (EM) (Printable.DefaultNames) - let name () = "deadbranch2" - - let s = function - | `Bot -> S.G.bot () - | `Lifted1 x -> x - | _ -> failwith "DeadBranchLifter2.s" - let node = function - | `Bot -> EM.bot () - | `Lifted2 x -> x - | _ -> failwith "DeadBranchLifter2.node" - let create_s s = `Lifted1 s - let create_node node = `Lifted2 node - - let printXml f = function - | `Lifted1 x -> S.G.printXml f x - | `Lifted2 x -> BatPrintf.fprintf f "%a" EM.printXml x - | x -> BatPrintf.fprintf f "%a" printXml x - end - - let conv (ctx: (_, G.t, _, V.t) ctx): (_, S.G.t, _, S.V.t) ctx = - { ctx with - global = (fun v -> G.s (ctx.global (V.s v))); - sideg = (fun v g -> ctx.sideg (V.s v) (G.create_s g)); - } - - let query ctx (type a) (q: a Queries.t): a Queries.result = - match q with - | WarnGlobal g -> - let g: V.t = Obj.obj g in - begin match g with - | `Left g -> - S.query (conv ctx) (WarnGlobal (Obj.repr g)) - | `Right g -> - let em = G.node (ctx.global (V.node g)) in - EM.iter (fun exp tv -> - match tv with - | `Lifted tv -> - let loc = Node.location g in (* TODO: looking up location now doesn't work nicely with incremental *) - let cilinserted = if loc.synthetic then "(possibly inserted by CIL) " else "" in - M.warn ~loc:(Node g) ~tags:[CWE (if tv then 571 else 570)] ~category:Deadcode "condition '%a' %sis always %B" d_exp exp cilinserted tv - | `Bot when not (CilType.Exp.equal exp one) -> (* all branches dead *) - M.error ~loc:(Node g) ~category:Analyzer ~tags:[Category Unsound] "both branches over condition '%a' are dead" d_exp exp - | `Bot (* all branches dead, fine at our inserted Neg(1)-s because no Pos(1) *) - | `Top -> (* may be both true and false *) - () - ) em; - end - | InvariantGlobal g -> - let g: V.t = Obj.obj g in - begin match g with - | `Left g -> - S.query (conv ctx) (InvariantGlobal (Obj.repr g)) - | `Right g -> - Queries.Result.top q - end - | IterSysVars (vq, vf) -> - (* vars for S *) - let vf' x = vf (Obj.repr (V.s (Obj.obj x))) in - S.query (conv ctx) (IterSysVars (vq, vf')); - - (* node vars for dead branches *) - begin match vq with - | Node {node; _} -> - vf (Obj.repr (V.node node)) - | _ -> - () - end - | _ -> - S.query (conv ctx) q - - - let branch ctx = S.branch (conv ctx) - - let branch ctx exp tv = - if !AnalysisState.postsolving then ( - try - let r = branch ctx exp tv in - (* branch is live *) - ctx.sideg (V.node ctx.prev_node) (G.create_node (EM.singleton exp (`Lifted tv))); (* record expression with reached tv *) - r - with Deadcode -> - (* branch is dead *) - ctx.sideg (V.node ctx.prev_node) (G.create_node (EM.singleton exp `Bot)); (* record expression without reached tv *) - raise Deadcode - ) - else ( - ctx.sideg (V.node ctx.prev_node) (G.create_node (EM.bot ())); (* create global variable during solving, to allow postsolving leq hack to pass verify *) - branch ctx exp tv - ) - - let assign ctx = S.assign (conv ctx) - let vdecl ctx = S.vdecl (conv ctx) - let enter ctx = S.enter (conv ctx) - let paths_as_set ctx = S.paths_as_set (conv ctx) - let body ctx = S.body (conv ctx) - let return ctx = S.return (conv ctx) - let combine_env ctx = S.combine_env (conv ctx) - let combine_assign ctx = S.combine_assign (conv ctx) - let special ctx = S.special (conv ctx) - let threadenter ctx = S.threadenter (conv ctx) - let threadspawn ctx lv f args fctx = S.threadspawn (conv ctx) lv f args (conv fctx) - let sync ctx = S.sync (conv ctx) - let skip ctx = S.skip (conv ctx) - let asm ctx = S.asm (conv ctx) - let event ctx e octx = S.event (conv ctx) e (conv octx) -end - - module LongjmpLifter (S: Spec): Spec = struct include S @@ -2082,12 +1944,10 @@ struct let s = spec end - module G = GVarGG (S.G) (S.C) + module G = GVarGG (S.G) (S.C) (T (CilType.Fundec) (C) (C)) let name () = "RecursionTerm (" ^ S.name () ^ ")" - let finalize = S.finalize (*TODO*) - (**let side_context sideg f c = if !AnalysisState.postsolving then sideg (f) (G.create_contexts (G.CSet.singleton c))*) @@ -2098,6 +1958,8 @@ struct global = (fun v -> G.s (ctx.global (V.spec v))); sideg = (fun v g -> ctx.sideg (V.spec v) (G.create_s g)); } + + (*TODO: We may need to add new queries here*) let query ctx (type a) (q: a Queries.t): a Queries.result = match q with | WarnGlobal g -> @@ -2129,23 +1991,24 @@ struct if !AnalysisState.postsolving then sideg (V.contexts f) (G.create_contexts (G.CMap.singleton (c) (t))) - let enter ctx lval fu exprList = (*TODO*) - if !AnalysisState.postsolving then - let c_r: unit -> S.C.t = ctx.context in (*Caller context*) (*TODO is this the caller or callee context???*) - let fd_r : fundec = fu in (*Caller fundec*) (*TODO: Falsch??*) - let c_e : unit -> S.C.t = ctx.context in (*Callee context*) (*TODO: Falsch??*) - let fd_e : fundec = fu in (*Callee fundec*) - let tup: (fundec * S.C.t) = (fd_r, (c_r ())) in (* TODO: is fundec the caller or callee fundec???*) - let t = G.CSet.singleton (tup) in (*TODO do we fill the set correctly???*) - side_context ctx.sideg fd_e (c_e ()) t; - S.enter (conv ctx) lval fu exprList - else - S.enter (conv ctx) lval fu exprList + let enter ctx = S.enter (conv ctx) let paths_as_set ctx = S.paths_as_set (conv ctx) let body ctx = S.body (conv ctx) let return ctx = S.return (conv ctx) - let combine_env ctx = S.combine_env (conv ctx) + let combine_env ctx r fe f args fc es f_ask = (*Todo*) + if !AnalysisState.postsolving then + let c_r: unit -> S.C.t = ctx.context in (*Caller context*) (*TODO is this the caller or callee context???*) + let nodeF = ctx.node in + let fd_r : fundec = Node.find_fundec nodeF in (*Caller fundec*) + let c_e: S.C.t = Option.get (fc) in (*Callee context*) + let fd_e : fundec = f in (*Callee fundec*) + let tup: (fundec * S.C.t) = (fd_r, (c_r ())) in + let t = G.CSet.singleton (tup) in (*TODO do we fill the set correctly???*) + side_context ctx.sideg fd_e (c_e) t; + S.combine_env (conv ctx) r fe f args fc es f_ask + else + S.combine_env (conv ctx) r fe f args fc es f_ask let combine_assign ctx = S.combine_assign (conv ctx) let special ctx = S.special (conv ctx) let threadenter ctx = S.threadenter (conv ctx) diff --git a/src/framework/control.ml b/src/framework/control.ml index 0a36d6c989..6261329e18 100644 --- a/src/framework/control.ml +++ b/src/framework/control.ml @@ -37,8 +37,7 @@ let spec_module: (module Spec) Lazy.t = lazy ( |> lift (get_bool "ana.widen.tokens") (module WideningTokens.Lifter) |> lift true (module LongjmpLifter) |> lift true (module RecursionTermLifter)(*TODO: should we really always evaluate it???*) - |> lift (get_bool "ana.dead-code.branches") (module DeadBranchLifter2) - ) in + ) in GobConfig.building_spec := false; ControlSpecC.control_spec_c := (module S1.C); (module S1) From 478cb410e4c84154025ef81c660050ccb08b858d Mon Sep 17 00:00:00 2001 From: Johanna Schinabeck Date: Fri, 16 Jun 2023 15:11:39 +0200 Subject: [PATCH 089/327] updated hash and compare of tuple --- src/framework/analyses.ml | 39 ++++-- src/framework/constraints.ml | 245 +---------------------------------- 2 files changed, 34 insertions(+), 250 deletions(-) diff --git a/src/framework/analyses.ml b/src/framework/analyses.ml index 0a7ccd04b2..90be60b779 100644 --- a/src/framework/analyses.ml +++ b/src/framework/analyses.ml @@ -124,15 +124,18 @@ module C_ (C: Printable.S)= struct include C include Printable.Std (* To make it Groupable *) - let printXml f c = BatPrintf.fprintf f "%a" printXml c (* wrap in for HTML printing *) + let printXml f c = BatPrintf.fprintf f (*Todo: Make this print pretty*) + " + callee_context:\n%a\n\n + " printXml c (* wrap in for HTML printing *) end (* Tuple of fundec and S.C*) -module T (Base1: Printable.S) (Base2: Printable.S) (C: Printable.S) = (*Todo: is this Printable.S or S.C*) +module T (Base1: Printable.S) (Base2: Printable.S) = (*Todo: is this Printable.S or S.C*) struct include Printable.Std - type t = (CilType.Fundec.t * C.t) + type t = (CilType.Fundec.t * Base2.t) let equal (a1, b1) (a2, b2) = if (a1 = a2) && (b1 = b2) then true else false let show (a,b) = (Base1.show a) ^ (Base2.show b) @@ -143,16 +146,30 @@ struct BatPrintf.fprintf f "\n Tuple:\n \n - fundec\n%a\n\n - context\n%a\n\n - \n" Base1.printXml a Base2.printXml b (*Todo: what do we have to put here?*) - let compare (a1,b1) (a2,b2) = 3 (*Todo: what do we have to put here?*) - (*let a = Base1.compare a1 a2 in - let b = Base2.compare b1 b2 in - *) + caller_fundec\n%a\n\n + caller_context\n%a\n\n + \n" Base1.printXml a Base2.printXml b + + (*Result of compare: + start with inital value of 0 + - a1 > a2: +1 + - a1 < a2: -1 + - b1 > b2: +3 + - b1 < b2: -3 + *) + let compare (a1,b1) (a2,b2) = (*Todo: is this ok?*) + let res = ref 0 in + let comp_a = Base1.compare a1 a2 in + let comp_b = Base2.compare b1 b2 in + if (comp_a > 0) then res := !(res) + 1 + else if (comp_a < 0) then res := !(res) - 1; + if (comp_b > 0) then res := !(res) + 3 + else if (comp_b < 0) then res := !(res) - 3; + !res + let pretty () x = text (show x) - let hash (a,b) = 2 (*Todo: what do we have to put here?*) + let hash (a,b) = Hashtbl.hash (Base1.hash a * Base2.hash b) (*Todo: is this ok?*) end diff --git a/src/framework/constraints.ml b/src/framework/constraints.ml index 31843794ec..143d417cc6 100644 --- a/src/framework/constraints.ml +++ b/src/framework/constraints.ml @@ -1694,237 +1694,6 @@ struct let event ctx e octx = S.event (conv ctx) e (conv octx) end -(* -module RecursionTermLifter (S: Spec): Spec = -struct - include S - - let name () = "RecursionTerm (" ^ S.name () ^ ")" - - (* global invariant: - - fundec -> (S.C -> Set (fundec * S.C)) -- used to detect loops in the call graph *) - - module V = - struct - include Printable.Option (S.V) (struct let name = "RecursionTerm" end) - let name () = "RecursionTerm" - let is_write_only t = true - let s x = `Left x - end - - module C_ = - struct - include S.C - include Printable.Std (* To make it Groupable *) - let printXml f c = BatPrintf.fprintf f "%a" printXml c (* wrap in for HTML printing *) - - end - - (*module Tuple = struct - type t = (fundec, S.C) [@@deriving eq, ord, hash] - let equal t1 t2 = false - let compare t1 t3 = 0 - let show t = "t" - let pretty () (x: t) = match x with _ -> . - - let printXml f (d,m) = BatPrintf.fprintf f "%a" printXml c (* wrap in for HTML printing *) - - let name u = "recursion" - let to_yojson (x: t) = match x with _ -> . - - let tag t = 1 - let arbitrary () = failwith "Printable.Empty.arbitrary" - - let relift t = t - end -*) - module Tupel (S:Spec) = - struct - include Printable.Std - type t = fundec * S.C.t [@@deriving eq, ord, hash] - - let equal_fundec = false - let hash_fundec = false - - let name () = "recursion" - - let pretty () (x: t) = match x with _ -> . - - let relift (f, c) = - (f, c) - - let equal t1 t2 = false - let compare t1 t3 = 0 - let show t = "t" - - let printXml f c = BatPrintf.fprintf f "%a" c (* wrap in for HTML printing *) - - let name u = "recursion" - let to_yojson (x: t) = match x with _ -> . - - let tag t = 1 - let arbitrary () = failwith "Printable.Empty.arbitrary" - end - - module T = - struct - include SetDomain.Make (Tupel (S)) - end - - module EM = - struct - include MapDomain.MapBot (C_) (T) - let name () = "recursions" - end - - module G = - struct - include Lattice.Lift2 (S.G) (EM) (Printable.DefaultNames) (*Todo: do we need lift2?*) - let name () = "recursionTerm" - let node = function - | `Bot -> EM.bot () - | `Lifted2 x -> x - | _ -> failwith "DeadBranchLifter.node" - let create_s s = `Lifted1 s - let create_node node = `Lifted2 node - - let printXml f = function - | `Lifted1 x -> S.G.printXml f x - | `Lifted2 x -> BatPrintf.fprintf f "%a" EM.printXml x - | x -> BatPrintf.fprintf f "%a" printXml x - end - - - - let conv (ctx: (_, G.t, _, V.t) ctx): (_, S.G.t, _, S.V.t) ctx = - { ctx with - global = (fun v -> G.s (ctx.global (V.s v))); - sideg = (fun v g -> ctx.sideg (V.s v) (G.create_s g)); - } - - let query ctx (type a) (q: a Queries.t): a Queries.result = - match q with - | WarnGlobal g -> - let g: V.t = Obj.obj g in - begin match g with - | `Left g -> - S.query (conv ctx) (WarnGlobal (Obj.repr g)) - | `Right g -> - let em = G.node (ctx.global (V.node g)) in - EM.iter (fun exp tv -> - match tv with - | `Lifted tv -> - let loc = Node.location g in (* TODO: looking up location now doesn't work nicely with incremental *) - let cilinserted = if loc.synthetic then "(possibly inserted by CIL) " else "" in - M.warn ~loc:(Node g) ~tags:[CWE (if tv then 571 else 570)] ~category:Deadcode "condition '%a' %sis always %B" d_exp exp cilinserted tv - | `Bot when not (CilType.Exp.equal exp one) -> (* all branches dead *) - M.error ~loc:(Node g) ~category:Analyzer ~tags:[Category Unsound] "both branches over condition '%a' are dead" d_exp exp - | `Bot (* all branches dead, fine at our inserted Neg(1)-s because no Pos(1) *) - | `Top -> (* may be both true and false *) - () - ) em; - end - | InvariantGlobal g -> - let g: V.t = Obj.obj g in - begin match g with - | `Left g -> - S.query (conv ctx) (InvariantGlobal (Obj.repr g)) - | `Right g -> - Queries.Result.top q - end - | IterSysVars (vq, vf) -> - (* vars for S *) - let vf' x = vf (Obj.repr (V.s (Obj.obj x))) in - S.query (conv ctx) (IterSysVars (vq, vf')); - - (* node vars for dead branches *) - begin match vq with - | Node {node; _} -> - vf (Obj.repr (V.node node)) - | _ -> - () - end - | _ -> - S.query (conv ctx) q - - - let branch ctx = S.branch (conv ctx) - - let branch ctx exp tv = - if !AnalysisState.postsolving then ( - try - let r = branch ctx exp tv in - (* branch is live *) - ctx.sideg (V.node ctx.prev_node) (G.create_node (EM.singleton exp (`Lifted tv))); (* record expression with reached tv *) - r - with Deadcode -> - (* branch is dead *) - ctx.sideg (V.node ctx.prev_node) (G.create_node (EM.singleton exp `Bot)); (* record expression without reached tv *) - raise Deadcode - ) - else ( - ctx.sideg (V.node ctx.prev_node) (G.create_node (EM.bot ())); (* create global variable during solving, to allow postsolving leq hack to pass verify *) - branch ctx exp tv - ) - - let assign ctx = S.assign (conv ctx) - let vdecl ctx = S.vdecl (conv ctx) - let enter ctx = S.enter (conv ctx) - let paths_as_set ctx = S.paths_as_set (conv ctx) - let body ctx = S.body (conv ctx) - let return ctx = S.return (conv ctx) - let combine_env ctx = S.combine_env (conv ctx) - let combine_assign ctx = S.combine_assign (conv ctx) - let special ctx = S.special (conv ctx) - let threadenter ctx = S.threadenter (conv ctx) - let threadspawn ctx lv f args fctx = S.threadspawn (conv ctx) lv f args (conv fctx) - let sync ctx = S.sync (conv ctx) - let skip ctx = S.skip (conv ctx) - let asm ctx = S.asm (conv ctx) - let event ctx e octx = S.event (conv ctx) e (conv octx) -end -*) -(*GMapG (S.G) (S.C)*) -(*struct - include Lattice.Prod (S.G) (M) - let printXml f (d,m) = BatPrintf.fprintf f "\n%a\n%a\n" S.G.printXml d M.printXml m - end*) - - -(*module type FundecType = - sig - type t = fundec - - val getFundec: t -> fundec - (* Define any other values or types exposed by the module *) - end - - module Fundec (F:fundec) : FundecType = - struct - let getFundec = F - let fname = F.fname - end*) - (* - - module CVal = - struct - include C - include Printable.Std (* To make it Groupable *) - let printXml f c = BatPrintf.fprintf f "%a" printXml c (* wrap in for HTML printing *) - end - module M = MapDomain.MapBot (CVal) (CVal)*) (*(*TODO: do I need to change V???*) - struct - include Printable.Option (S.V) (struct let name = "RecursionTerm" end) - let name () = "RecursionTerm" - let is_write_only t = true - let s x = `Left x - end*) -(*include Lattice.Lift2 (S.G) (MapDomain.MapBot (C_) (TSet)) (Printable.DefaultNames) (*TODO: does MapBot fit?*) - let s = function - | `Bot -> S.G.bot () - | `Lifted1 x -> x - | _ -> failwith "RecursionTerm.s" - end*) (** Add cycle detection in the function call graph to a analysis *) module RecursionTermLifter (S: Spec) @@ -1944,14 +1713,10 @@ struct let s = spec end - module G = GVarGG (S.G) (S.C) (T (CilType.Fundec) (C) (C)) + module G = GVarGG (S.G) (S.C) (T (CilType.Fundec) (C)) let name () = "RecursionTerm (" ^ S.name () ^ ")" - (**let side_context sideg f c = - if !AnalysisState.postsolving then - sideg (f) (G.create_contexts (G.CSet.singleton c))*) - (*TODO Change the body??*) let conv (ctx: (_, G.t, _, V.t) ctx): (_, S.G.t, _, S.V.t) ctx = { ctx with @@ -1968,6 +1733,8 @@ struct | `Left g -> S.query (conv ctx) (WarnGlobal (Obj.repr g)) | `Right g -> + (*TODO: Implement cycle detection algorithm here*) + Queries.Result.top q end | InvariantGlobal g -> @@ -1992,18 +1759,18 @@ struct sideg (V.contexts f) (G.create_contexts (G.CMap.singleton (c) (t))) let enter ctx = S.enter (conv ctx) - let paths_as_set ctx = S.paths_as_set (conv ctx) let body ctx = S.body (conv ctx) let return ctx = S.return (conv ctx) let combine_env ctx r fe f args fc es f_ask = (*Todo*) if !AnalysisState.postsolving then - let c_r: unit -> S.C.t = ctx.context in (*Caller context*) (*TODO is this the caller or callee context???*) + let c_r: S.C.t = ctx.context () in (*Caller context*) (*TODO is this the caller or callee context???*) let nodeF = ctx.node in let fd_r : fundec = Node.find_fundec nodeF in (*Caller fundec*) let c_e: S.C.t = Option.get (fc) in (*Callee context*) let fd_e : fundec = f in (*Callee fundec*) - let tup: (fundec * S.C.t) = (fd_r, (c_r ())) in + + let tup: (fundec * S.C.t) = (fd_r, c_r) in let t = G.CSet.singleton (tup) in (*TODO do we fill the set correctly???*) side_context ctx.sideg fd_e (c_e) t; S.combine_env (conv ctx) r fe f args fc es f_ask From 7ac939a00cfcb4b9d96c16bd1bc0e3c8740efc72 Mon Sep 17 00:00:00 2001 From: Isidor Zweckstetter Date: Fri, 16 Jun 2023 22:14:12 +0200 Subject: [PATCH 090/327] added implementation for DFS for cycles in Callgraph; Not testet --- src/framework/analyses.ml | 11 +++++++-- src/framework/constraints.ml | 45 ++++++++++++++++++++++++------------ 2 files changed, 39 insertions(+), 17 deletions(-) diff --git a/src/framework/analyses.ml b/src/framework/analyses.ml index 0a7ccd04b2..a5e250c4ed 100644 --- a/src/framework/analyses.ml +++ b/src/framework/analyses.ml @@ -129,11 +129,13 @@ struct end (* Tuple of fundec and S.C*) -module T (Base1: Printable.S) (Base2: Printable.S) (C: Printable.S) = (*Todo: is this Printable.S or S.C*) +module T (Base1: Printable.S) (Base2: Printable.S) = (*Todo: is this Printable.S or S.C*) struct include Printable.Std - type t = (CilType.Fundec.t * C.t) + type t = (CilType.Fundec.t * Base2.t) + let fundec (a,_) = a + let context (_,b) = b let equal (a1, b1) (a2, b2) = if (a1 = a2) && (b1 = b2) then true else false let show (a,b) = (Base1.show a) ^ (Base2.show b) let name () = "Tuple" @@ -202,6 +204,11 @@ struct | _ -> failwith "RecursionTerm.s" let create_s s = `Lifted1 s (*TODO: does this work? copied from DeadBranch*) + + let base2 instance = + match instance with + | `Lifted2 n -> Some n + | _ -> None end diff --git a/src/framework/constraints.ml b/src/framework/constraints.ml index 31843794ec..b256d8ecbd 100644 --- a/src/framework/constraints.ml +++ b/src/framework/constraints.ml @@ -1941,10 +1941,9 @@ struct module V = struct include GVarF(S.V) - let s = spec end - module G = GVarGG (S.G) (S.C) (T (CilType.Fundec) (C) (C)) + module G = GVarGG (S.G) (S.C) (T (CilType.Fundec) (C)) let name () = "RecursionTerm (" ^ S.name () ^ ")" @@ -1965,19 +1964,35 @@ struct | WarnGlobal g -> let g: V.t = Obj.obj g in begin match g with - | `Left g -> - S.query (conv ctx) (WarnGlobal (Obj.repr g)) - | `Right g -> - Queries.Result.top q - end - | InvariantGlobal g -> - let g: V.t = Obj.obj g in - begin match g with - | `Left g -> - S.query (conv ctx) (InvariantGlobal (Obj.repr g)) - | `Right g -> - Queries.Result.top q - end + | `Left g' -> + S.query (conv ctx) (WarnGlobal (Obj.repr g')) + | `Right g' -> + let module LH = Hashtbl.Make (T (CilType.Fundec) (C)) in + let module LS = Set.Make (T (CilType.Fundec) (C)) in + (* TODO: find all cycles/SCCs *) + let global_visited_calls = LH.create 100 in + + (* DFS *) + let rec iter_call (path_visited_calls: LS.t) (call: T (CilType.Fundec) (C).t) = + if LS.mem call path_visited_calls then + let msgs = + [ + (Pretty.dprintf "lock before:", Some (M.Location.CilLocation locUnknown)); + (Pretty.dprintf "lock after: with", Some (M.Location.CilLocation locUnknown)); + ] in + M.msg_group Warning ~category:Deadlock "Locking order cycle" msgs; + S.query (conv ctx) q + else if not (LH.mem global_visited_calls call) then begin + LH.replace global_visited_calls call (); + let callers = G.CMap.find (ctx.context()) (Option.get (G.base2 (ctx.global (g)))) in (*TODO: how do we get our Map out of g*) + let new_path_visited_calls = LS.add call path_visited_calls in + G.CSet.iter (fun to_call -> + iter_call new_path_visited_calls to_call + ) callers + end + in + S.query (conv ctx) q + end | _ -> S.query (conv ctx) q let branch ctx = S.branch (conv ctx) From df59fd78c1bd6577969e517deb9db4dd8b956b6a Mon Sep 17 00:00:00 2001 From: Johanna Schinabeck Date: Sat, 17 Jun 2023 09:57:13 +0200 Subject: [PATCH 091/327] just comments --- src/framework/constraints.ml | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/framework/constraints.ml b/src/framework/constraints.ml index 143d417cc6..35b553135a 100644 --- a/src/framework/constraints.ml +++ b/src/framework/constraints.ml @@ -1734,7 +1734,7 @@ struct S.query (conv ctx) (WarnGlobal (Obj.repr g)) | `Right g -> (*TODO: Implement cycle detection algorithm here*) - + Queries.Result.top q end | InvariantGlobal g -> @@ -1762,16 +1762,16 @@ struct let paths_as_set ctx = S.paths_as_set (conv ctx) let body ctx = S.body (conv ctx) let return ctx = S.return (conv ctx) - let combine_env ctx r fe f args fc es f_ask = (*Todo*) + let combine_env ctx r fe f args fc es f_ask = if !AnalysisState.postsolving then - let c_r: S.C.t = ctx.context () in (*Caller context*) (*TODO is this the caller or callee context???*) + let c_r: S.C.t = ctx.context () in (*Caller context*) let nodeF = ctx.node in let fd_r : fundec = Node.find_fundec nodeF in (*Caller fundec*) let c_e: S.C.t = Option.get (fc) in (*Callee context*) let fd_e : fundec = f in (*Callee fundec*) let tup: (fundec * S.C.t) = (fd_r, c_r) in - let t = G.CSet.singleton (tup) in (*TODO do we fill the set correctly???*) + let t = G.CSet.singleton (tup) in side_context ctx.sideg fd_e (c_e) t; S.combine_env (conv ctx) r fe f args fc es f_ask else From 7f4866caca9b982d5e3036bf685c36c0723bab8a Mon Sep 17 00:00:00 2001 From: Johanna Schinabeck Date: Sat, 17 Jun 2023 10:34:59 +0200 Subject: [PATCH 092/327] comments, transformed loop_counters to a map to store stmts --- src/analyses/termination_new.ml | 6 +- src/framework/constraints.ml | 269 --------------------------- src/util/terminationPreprocessing.ml | 54 +----- 3 files changed, 10 insertions(+), 319 deletions(-) diff --git a/src/analyses/termination_new.ml b/src/analyses/termination_new.ml index 44b0c7fb5e..4926c23daa 100644 --- a/src/analyses/termination_new.ml +++ b/src/analyses/termination_new.ml @@ -6,7 +6,9 @@ open TerminationPreprocessing exception PreProcessing of string -let loop_counters : varinfo list ref = ref [] + +(* contains all loop counter variables (varinfo) and maps them to their corresponding loop statement*) +let loop_counters: stmt VarToStmt.t ref = ref VarToStmt.empty (** Contains the locations of the upjumping gotos *) let upjumping_gotos : location list ref = ref [] @@ -14,7 +16,7 @@ let upjumping_gotos : location list ref = ref [] let loop_exit : varinfo ref = ref (makeVarinfo false "-error" Cil.intType) let is_loop_counter_var (x : varinfo) = - List.mem x !loop_counters + VarToStmt.mem x !loop_counters let is_loop_exit_indicator (x : varinfo) = x = !loop_exit diff --git a/src/framework/constraints.ml b/src/framework/constraints.ml index 0177f3ea85..07750122a5 100644 --- a/src/framework/constraints.ml +++ b/src/framework/constraints.ml @@ -1693,275 +1693,6 @@ struct let event ctx e octx = S.event (conv ctx) e (conv octx) end -(** -module RecursionTermLifter (S: Spec): Spec = -struct - include S - - let name () = "RecursionTerm (" ^ S.name () ^ ")" - - (* global invariant: - - fundec -> (S.C -> Set (fundec * S.C)) -- used to detect loops in the call graph *) - - module V = - struct - include Printable.Option (S.V) (struct let name = "RecursionTerm" end) - let name () = "RecursionTerm" - let is_write_only t = true - let s x = `Left x - end - - module C = - struct - include S.C - include Printable.Std (* To make it Groupable *) - let printXml f c = BatPrintf.fprintf f "%a" printXml c (* wrap in for HTML printing *) - - end - - (*module Tuple = struct - type t = (fundec, S.C) [@@deriving eq, ord, hash] - let equal t1 t2 = false - let compare t1 t3 = 0 - let show t = "t" - let pretty () (x: t) = match x with _ -> . - - let printXml f (d,m) = BatPrintf.fprintf f "%a" printXml c (* wrap in for HTML printing *) - - let name u = "recursion" - let to_yojson (x: t) = match x with _ -> . - - let tag t = 1 - let arbitrary () = failwith "Printable.Empty.arbitrary" - - let relift t = t - end -*) - module Tupel (S:Spec) = - struct - include Printable.Std - type t = fundec * S.C.t [@@deriving eq, ord, hash] - - let equal_fundec = false - let hash_fundec = false - - let name () = "recursion" - - let pretty () (x: t) = match x with _ -> . - - let relift (f, c) = - (f, c) - - let equal t1 t2 = false - let compare t1 t3 = 0 - let show t = "t" - - let printXml f c = BatPrintf.fprintf f "%a" c (* wrap in for HTML printing *) - - let name u = "recursion" - let to_yojson (x: t) = match x with _ -> . - - let tag t = 1 - let arbitrary () = failwith "Printable.Empty.arbitrary" - end - - module T = - struct - include SetDomain.Make (Tupel (S)) - end - - module EM = - struct - include MapDomain.MapBot (C) (T) - let name () = "recursions" - end - - module G = - struct - include Lattice.Lift2 (S.G) (EM) (Printable.DefaultNames) - let name () = "recursionTerm" - let node = function - | `Bot -> EM.bot () - | `Lifted2 x -> x - | _ -> failwith "DeadBranchLifter.node" - let create_s s = `Lifted1 s - let create_node node = `Lifted2 node - - let printXml f = function - | `Lifted1 x -> S.G.printXml f x - | `Lifted2 x -> BatPrintf.fprintf f "%a" EM.printXml x - | x -> BatPrintf.fprintf f "%a" printXml x - end - - let conv (ctx: (_, G.t, _, V.t) ctx): (_, S.G.t, _, S.V.t) ctx = - { ctx with - global = (fun v -> G.s (ctx.global (V.s v))); - sideg = (fun v g -> ctx.sideg (V.s v) (G.create_s g)); - } - - let query ctx (type a) (q: a Queries.t): a Queries.result = - match q with - | WarnGlobal g -> - let g: V.t = Obj.obj g in - begin match g with - | `Left g -> - S.query (conv ctx) (WarnGlobal (Obj.repr g)) - | `Right g -> - let em = G.node (ctx.global (V.node g)) in - EM.iter (fun exp tv -> - match tv with - | `Lifted tv -> - let loc = Node.location g in (* TODO: looking up location now doesn't work nicely with incremental *) - let cilinserted = if loc.synthetic then "(possibly inserted by CIL) " else "" in - M.warn ~loc:(Node g) ~tags:[CWE (if tv then 571 else 570)] ~category:Deadcode "condition '%a' %sis always %B" d_exp exp cilinserted tv - | `Bot when not (CilType.Exp.equal exp one) -> (* all branches dead *) - M.error ~loc:(Node g) ~category:Analyzer ~tags:[Category Unsound] "both branches over condition '%a' are dead" d_exp exp - | `Bot (* all branches dead, fine at our inserted Neg(1)-s because no Pos(1) *) - | `Top -> (* may be both true and false *) - () - ) em; - end - | InvariantGlobal g -> - let g: V.t = Obj.obj g in - begin match g with - | `Left g -> - S.query (conv ctx) (InvariantGlobal (Obj.repr g)) - | `Right g -> - Queries.Result.top q - end - | IterSysVars (vq, vf) -> - (* vars for S *) - let vf' x = vf (Obj.repr (V.s (Obj.obj x))) in - S.query (conv ctx) (IterSysVars (vq, vf')); - - (* node vars for dead branches *) - begin match vq with - | Node {node; _} -> - vf (Obj.repr (V.node node)) - | _ -> - () - end - | _ -> - S.query (conv ctx) q - - - let branch ctx = S.branch (conv ctx) - - let branch ctx exp tv = - if !AnalysisState.postsolving then ( - try - let r = branch ctx exp tv in - (* branch is live *) - ctx.sideg (V.node ctx.prev_node) (G.create_node (EM.singleton exp (`Lifted tv))); (* record expression with reached tv *) - r - with Deadcode -> - (* branch is dead *) - ctx.sideg (V.node ctx.prev_node) (G.create_node (EM.singleton exp `Bot)); (* record expression without reached tv *) - raise Deadcode - ) - else ( - ctx.sideg (V.node ctx.prev_node) (G.create_node (EM.bot ())); (* create global variable during solving, to allow postsolving leq hack to pass verify *) - branch ctx exp tv - ) - - let assign ctx = S.assign (conv ctx) - let vdecl ctx = S.vdecl (conv ctx) - let enter ctx = S.enter (conv ctx) - let paths_as_set ctx = S.paths_as_set (conv ctx) - let body ctx = S.body (conv ctx) - let return ctx = S.return (conv ctx) - let combine_env ctx = S.combine_env (conv ctx) - let combine_assign ctx = S.combine_assign (conv ctx) - let special ctx = S.special (conv ctx) - let threadenter ctx = S.threadenter (conv ctx) - let threadspawn ctx lv f args fctx = S.threadspawn (conv ctx) lv f args (conv fctx) - let sync ctx = S.sync (conv ctx) - let skip ctx = S.skip (conv ctx) - let asm ctx = S.asm (conv ctx) - let event ctx e octx = S.event (conv ctx) e (conv octx) -end - - -(** Add cycle detection in the function call graph to a analysis *) -module RecursionTermLifter (S: Spec) - : Spec with module D = S.D - and module G = S.G - and module C = S.C - and module G = S.G -= - -struct - module C = S.C - module P = S.P - module D = S.D - - (*global invariant - - fundec -> Map (S.C) (Set (fundec * S.C)) - So: g -> {c' -> f, c} - in case f, c --> g, c' *) - - (* - - - module CVal = - struct - include C - include Printable.Std (* To make it Groupable *) - let printXml f c = BatPrintf.fprintf f "%a" printXml c (* wrap in for HTML printing *) - end - module M = MapDomain.MapBot (CVal) (CVal) -*) - module V = (*TODO: do I need to change V???*) - struct - include Printable.Option (S.V) (struct let name = "RecursionTerm" end) - let name () = "RecursionTerm" - let is_write_only t = true - let s x = `Left x - end - module G = S.G - (*GMapG (S.G) (S.C)*) - (*struct - include Lattice.Prod (S.G) (M) - let printXml f (d,m) = BatPrintf.fprintf f "\n%a\n%a\n" S.G.printXml d M.printXml m - end*) - let name () = "RecursionTerm (" ^ S.name () ^ ")" - - type marshal = S.marshal - let init = S.init - let finalize = S.finalize (*TODO*) - - let startstate v = S.startstate v - let exitstate v = S.exitstate v - let morphstate = S.morphstate - - let context = S.context - - (**let side_context sideg f c = - if !AnalysisState.postsolving then - sideg (f) (G.create_contexts (G.CSet.singleton c))*) - - let query ctx = S.query (ctx) - let branch ctx = S.branch (ctx) - let assign ctx = S.assign (ctx) - let vdecl ctx = S.vdecl (ctx) - let enter ctx = - if !AnalysisState.postsolving then - printf "hallo hallo"; - S.enter (ctx) (*TODO*) - let paths_as_set ctx = S.paths_as_set (ctx) - let body ctx = S.body (ctx) - let return ctx = S.return (ctx) - let combine_env ctx = S.combine_env (ctx) - let combine_assign ctx = S.combine_assign (ctx) - let special ctx = S.special (ctx) - let threadenter ctx = S.threadenter (ctx) - let threadspawn ctx lv f args fctx = S.threadspawn (ctx) lv f args (fctx) - let sync ctx = S.sync (ctx) - let skip ctx = S.skip (ctx) - let asm ctx = S.asm (ctx) - let event ctx e octx = S.event (ctx) e (octx) -end -*) module CompareGlobSys (SpecSys: SpecSys) = struct diff --git a/src/util/terminationPreprocessing.ml b/src/util/terminationPreprocessing.ml index 684733c05f..7e1e477262 100644 --- a/src/util/terminationPreprocessing.ml +++ b/src/util/terminationPreprocessing.ml @@ -1,13 +1,8 @@ -(* - code in src/analysis/termination.ml contains loopCounterVisitor which might be interesting - - check if overflow happend with new variable - - how do we deal with nested loops? - - make sure only the analyzed files are appended with the code - - return variables that are newly created - *) - open GoblintCil include Printf +module VarToStmt = Map.Make(CilType.Varinfo);; (* maps varinfos (= loop counter variable) to the statement of the corresponding loop*) + let extract_file_name s = (*There still may be a need to filter more chars*) let ls = String.split_on_char '/' s in (*Assuming '/' as path seperator*) let ls = List.rev ls in @@ -35,7 +30,7 @@ class loopCounterVisitor lc lg le (fd : fundec) = object(self) | Loop (b, loc, eloc, _, _) -> let name = "term"^show_location_id loc in let typ = Cil.intType in - let v = (Cil.makeLocalVar fd name typ) in + let v = (Cil.makeLocalVar fd name typ) in (* Not tested for incremental mode*) let init_stmt = mkStmtOneInstr @@ Set (var v, zero, loc, eloc) in let inc_stmt = mkStmtOneInstr @@ Set (var v, increm (Lval (var v)) 1, loc, eloc) in let exit_stmt = mkStmtOneInstr @@ Set ((var !le), (Lval (var v)), loc, eloc) in @@ -43,7 +38,8 @@ class loopCounterVisitor lc lg le (fd : fundec) = object(self) | cont :: cond :: ss -> b.bstmts <- cont :: inc_stmt :: cond :: ss; (*cont :: cond :: inc_stmt :: ss = it is also possible, but for loops with cond at the end, inc is also at the end*) | _ -> ()); - lc := List.append !lc ([v] : varinfo list); + lc := VarToStmt.add (v: varinfo) (s: stmt) !lc; + (*lc := List.append !lc ([v] : varinfo list);*) let nb = mkBlock [init_stmt; mkStmt s.skind; exit_stmt] in s.skind <- Block nb; s @@ -56,42 +52,4 @@ class loopCounterVisitor lc lg le (fd : fundec) = object(self) s | _ -> s in ChangeDoChildrenPost (s, action); - end - -(* just a test -class loopCounterVisitor (fd : fundec) = object(self) -inherit nopCilVisitor -method! vstmt s = - match s.skind with - | Loop (b, loc, eloc, _, _) -> - let name = "term"^show_location_id loc in - let typ = intType in - let v = Goblintutil.create_var (makeLocalVar fd name ~init:(SingleInit zero) typ) in - let init_stmt = mkStmtOneInstr @@ Set (var v, zero, loc, eloc) in - let inc_stmt = mkStmtOneInstr @@ Set (var v, increm (Lval (var v)) 1, loc, eloc) in - b.bstmts <- inc_stmt :: b.bstmts; - let nb = mkBlock [init_stmt; mkStmt s.skind] in (* init_stmt; *) - ChangeDoChildrenPost (s, (fun _ -> s.skind <- Block(nb); s)) - | _ -> DoChildren -end - -let add_var_loopTerm fd f = - let thisVisitor = new loopCounterVisitor in - visitCilFileSameGlobals (thisVisitor fd ) f*) -(* -let action (fd : fundec) s = - let a s = match s.skind with - | Loop (b, loc, eloc, _, _) -> - let name = "term"^show_location_id loc in - let typ = intType in - let v = Goblintutil.create_var (makeLocalVar fd name ~init:(SingleInit zero) typ) in - let init_stmt = mkStmtOneInstr @@ Set (var v, zero, loc, eloc) in - let inc_stmt = mkStmtOneInstr @@ Set (var v, increm (Lval (var v)) 1, loc, eloc) in - b.bstmts <- inc_stmt :: b.bstmts; - let nb = mkBlock [init_stmt; mkStmt s.skind] in (* *) - s.skind <- Block nb; - s - | _ -> s -in ChangeDoChildrenPost (s, a) -*) - + end \ No newline at end of file From 99e0a068696f9696b030c67dbcbdae4b20ce0872 Mon Sep 17 00:00:00 2001 From: Johanna Schinabeck Date: Sat, 17 Jun 2023 11:16:02 +0200 Subject: [PATCH 093/327] small changes --- runningGob.sh | 1 + src/framework/analyses.ml | 3 +-- src/framework/constraints.ml | 3 +++ tests/regression/55-loop-unrolling/01-simple-cases.c | 3 +++ 4 files changed, 8 insertions(+), 2 deletions(-) diff --git a/runningGob.sh b/runningGob.sh index 15007b3e0b..783ad90fec 100755 --- a/runningGob.sh +++ b/runningGob.sh @@ -1,6 +1,7 @@ #!/bin/bash make make install +clear # set options and file for apron execution options_apron="--set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra --enable warn.debug" #note: preprocessing first needs to be added to apron diff --git a/src/framework/analyses.ml b/src/framework/analyses.ml index 890b5c12e8..b70f2c09cd 100644 --- a/src/framework/analyses.ml +++ b/src/framework/analyses.ml @@ -146,8 +146,7 @@ struct let relift (a,b) = (a,b) (*Todo: is this correct?*) let printXml f (a,b) = BatPrintf.fprintf f "\n - Tuple:\n - \n + Tuple:\n caller_fundec\n%a\n\n caller_context\n%a\n\n \n" Base1.printXml a Base2.printXml b diff --git a/src/framework/constraints.ml b/src/framework/constraints.ml index c6060f8725..8e4eac1bca 100644 --- a/src/framework/constraints.ml +++ b/src/framework/constraints.ml @@ -1740,6 +1740,7 @@ struct (* DFS *) let rec iter_call (path_visited_calls: LS.t) (call: T (CilType.Fundec) (C).t) = if LS.mem call path_visited_calls then + (*Cycle found*) let msgs = [ (Pretty.dprintf "lock before:", Some (M.Location.CilLocation locUnknown)); @@ -1748,6 +1749,7 @@ struct M.msg_group Warning ~category:Deadlock "Locking order cycle" msgs; S.query (conv ctx) q else if not (LH.mem global_visited_calls call) then begin + printf "test\n"; LH.replace global_visited_calls call (); let callers = G.CMap.find (ctx.context()) (Option.get (G.base2 (ctx.global (g)))) in (*TODO: how do we get our Map out of g*) let new_path_visited_calls = LS.add call path_visited_calls in @@ -1785,6 +1787,7 @@ struct let tup: (fundec * S.C.t) = (fd_r, c_r) in let t = G.CSet.singleton (tup) in + side_context ctx.sideg fd_e (c_e) t; S.combine_env (conv ctx) r fe f args fc es f_ask else diff --git a/tests/regression/55-loop-unrolling/01-simple-cases.c b/tests/regression/55-loop-unrolling/01-simple-cases.c index 0073717187..6790add384 100644 --- a/tests/regression/55-loop-unrolling/01-simple-cases.c +++ b/tests/regression/55-loop-unrolling/01-simple-cases.c @@ -31,6 +31,8 @@ void example1(void) __goblint_check(a[0] == 0); // UNKNOWN __goblint_check(a[3] == 3); // UNKNOWN + + example2(); } // Do-while loop simple example @@ -46,6 +48,7 @@ void example2(void) __goblint_check(a[0] == 0); // UNKNOWN __goblint_check(a[3] == 3); // UNKNOWN + example1(); } // Initialization not completed, yet the array representation is not precise From c66a3fb57a499b31e04ee65dd6224cc4455ae038 Mon Sep 17 00:00:00 2001 From: Johanna Schinabeck Date: Sat, 17 Jun 2023 11:20:57 +0200 Subject: [PATCH 094/327] comments --- src/util/terminationPreprocessing.ml | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/util/terminationPreprocessing.ml b/src/util/terminationPreprocessing.ml index 7e1e477262..409aa2c2c4 100644 --- a/src/util/terminationPreprocessing.ml +++ b/src/util/terminationPreprocessing.ml @@ -30,7 +30,7 @@ class loopCounterVisitor lc lg le (fd : fundec) = object(self) | Loop (b, loc, eloc, _, _) -> let name = "term"^show_location_id loc in let typ = Cil.intType in - let v = (Cil.makeLocalVar fd name typ) in (* Not tested for incremental mode*) + let v = (Cil.makeLocalVar fd name typ) in (*Not tested for incremental mode*) let init_stmt = mkStmtOneInstr @@ Set (var v, zero, loc, eloc) in let inc_stmt = mkStmtOneInstr @@ Set (var v, increm (Lval (var v)) 1, loc, eloc) in let exit_stmt = mkStmtOneInstr @@ Set ((var !le), (Lval (var v)), loc, eloc) in @@ -39,7 +39,6 @@ class loopCounterVisitor lc lg le (fd : fundec) = object(self) b.bstmts <- cont :: inc_stmt :: cond :: ss; (*cont :: cond :: inc_stmt :: ss = it is also possible, but for loops with cond at the end, inc is also at the end*) | _ -> ()); lc := VarToStmt.add (v: varinfo) (s: stmt) !lc; - (*lc := List.append !lc ([v] : varinfo list);*) let nb = mkBlock [init_stmt; mkStmt s.skind; exit_stmt] in s.skind <- Block nb; s From 6e37746024b526fb1835c689681dc50756c9f32f Mon Sep 17 00:00:00 2001 From: Alexander Schlenga Date: Sat, 17 Jun 2023 12:24:55 +0200 Subject: [PATCH 095/327] Change loop analysis domain keys to statements Before, the keys of the domain were simply the (loop counter) variables. Now, the keys are the CIL statements which are the analyzed loop. --- output.txt | 62 ++++++++++++++++----------------- src/analyses/termination_new.ml | 27 +++++++------- src/domains/queries.ml | 8 ++--- 3 files changed, 50 insertions(+), 47 deletions(-) diff --git a/output.txt b/output.txt index 07c71d61b9..d751966836 100644 --- a/output.txt +++ b/output.txt @@ -131,7 +131,7 @@ typedef long __intptr_t; typedef unsigned int __socklen_t; #line 215 "/usr/include/x86_64-linux-gnu/bits/types.h" typedef int __sig_atomic_t; -#line 209 "/usr/lib/gcc/x86_64-linux-gnu/11/include/stddef.h" +#line 209 "/usr/lib/gcc/x86_64-linux-gnu/10/include/stddef.h" typedef unsigned long size_t; #line 10 "/usr/include/x86_64-linux-gnu/bits/types/time_t.h" typedef __time_t time_t; @@ -201,12 +201,12 @@ struct __anonstruct___value32_817613185 { unsigned int __high ; }; #line 25 "/usr/include/x86_64-linux-gnu/bits/atomic_wide_counter.h" -union __anonunion___atomic_wide_counter_643133811 { +union __anonunion___atomic_wide_counter_1044835921 { unsigned long long __value64 ; struct __anonstruct___value32_817613185 __value32 ; }; #line 25 "/usr/include/x86_64-linux-gnu/bits/atomic_wide_counter.h" -typedef union __anonunion___atomic_wide_counter_643133811 __atomic_wide_counter; +typedef union __anonunion___atomic_wide_counter_1044835921 __atomic_wide_counter; #line 51 "/usr/include/x86_64-linux-gnu/bits/thread-shared-types.h" struct __pthread_internal_list { struct __pthread_internal_list *__prev ; @@ -261,11 +261,11 @@ typedef unsigned int __tss_t; #line 106 "/usr/include/x86_64-linux-gnu/bits/thread-shared-types.h" typedef unsigned long __thrd_t; #line 108 "/usr/include/x86_64-linux-gnu/bits/thread-shared-types.h" -struct __anonstruct___once_flag_826868709 { +struct __anonstruct___once_flag_1044835922 { int __data ; }; #line 108 "/usr/include/x86_64-linux-gnu/bits/thread-shared-types.h" -typedef struct __anonstruct___once_flag_826868709 __once_flag; +typedef struct __anonstruct___once_flag_1044835922 __once_flag; #line 27 "/usr/include/x86_64-linux-gnu/bits/pthreadtypes.h" typedef unsigned long pthread_t; #line 32 "/usr/include/x86_64-linux-gnu/bits/pthreadtypes.h" @@ -441,16 +441,16 @@ struct __pthread_cleanup_frame { int __do_it ; int __cancel_type ; }; -#line 143 "/usr/lib/gcc/x86_64-linux-gnu/11/include/stddef.h" +#line 143 "/usr/lib/gcc/x86_64-linux-gnu/10/include/stddef.h" typedef long ptrdiff_t; -#line 321 "/usr/lib/gcc/x86_64-linux-gnu/11/include/stddef.h" +#line 321 "/usr/lib/gcc/x86_64-linux-gnu/10/include/stddef.h" typedef int wchar_t; -#line 415 "/usr/lib/gcc/x86_64-linux-gnu/11/include/stddef.h" +#line 415 "/usr/lib/gcc/x86_64-linux-gnu/10/include/stddef.h" struct __anonstruct_max_align_t_896270833 { long long __max_align_ll __attribute__((__aligned__(__alignof__(long long )))) ; long double __max_align_ld __attribute__((__aligned__(__alignof__(long double )))) ; }; -#line 415 "/usr/lib/gcc/x86_64-linux-gnu/11/include/stddef.h" +#line 415 "/usr/lib/gcc/x86_64-linux-gnu/10/include/stddef.h" typedef struct __anonstruct_max_align_t_896270833 max_align_t; /* compiler builtin: void __builtin_va_copy(__builtin_va_list , __builtin_va_list ) ; */ @@ -1683,40 +1683,42 @@ extern void ( __attribute__((__leaf__)) tzset)(void) __attribute__((__nothrow__ extern int daylight ; #line 233 extern long timezone ; -#line 249 +#line 246 extern time_t ( __attribute__((__leaf__)) timegm)(struct tm *__tp ) __attribute__((__nothrow__)) ; -#line 251 +#line 263 extern time_t ( __attribute__((__leaf__)) timelocal)(struct tm *__tp ) __attribute__((__nothrow__)) ; -#line 262 +#line 271 extern int ( __attribute__((__leaf__)) dysize)(int __year ) __attribute__((__nothrow__, __const__)) ; -#line 272 +#line 281 extern int nanosleep(struct timespec const *__requested_time , struct timespec *__remaining ) ; -#line 276 +#line 285 extern int ( __attribute__((__leaf__)) clock_getres)(clockid_t __clock_id , struct timespec *__res ) __attribute__((__nothrow__)) ; -#line 279 -extern int ( __attribute__((__leaf__)) clock_gettime)(clockid_t __clock_id , struct timespec *__tp ) __attribute__((__nothrow__)) ; -#line 282 -extern int ( __attribute__((__leaf__)) clock_settime)(clockid_t __clock_id , struct timespec const *__tp ) __attribute__((__nothrow__)) ; -#line 311 +#line 288 +extern int ( __attribute__((__nonnull__(2), __leaf__)) clock_gettime)(clockid_t __clock_id , + struct timespec *__tp ) __attribute__((__nothrow__)) ; +#line 292 +extern int ( __attribute__((__nonnull__(2), __leaf__)) clock_settime)(clockid_t __clock_id , + struct timespec const *__tp ) __attribute__((__nothrow__)) ; +#line 323 extern int clock_nanosleep(clockid_t __clock_id , int __flags , struct timespec const *__req , struct timespec *__rem ) ; -#line 326 +#line 338 extern int ( __attribute__((__leaf__)) clock_getcpuclockid)(pid_t __pid , clockid_t *__clock_id ) __attribute__((__nothrow__)) ; -#line 331 +#line 343 extern int ( __attribute__((__leaf__)) timer_create)(clockid_t __clock_id , struct sigevent * __restrict __evp , timer_t * __restrict __timerid ) __attribute__((__nothrow__)) ; -#line 336 +#line 348 extern int ( __attribute__((__leaf__)) timer_delete)(timer_t __timerid ) __attribute__((__nothrow__)) ; -#line 340 +#line 352 extern int ( __attribute__((__leaf__)) timer_settime)(timer_t __timerid , int __flags , struct itimerspec const * __restrict __value , struct itimerspec * __restrict __ovalue ) __attribute__((__nothrow__)) ; -#line 345 +#line 357 extern int ( __attribute__((__leaf__)) timer_gettime)(timer_t __timerid , struct itimerspec *__value ) __attribute__((__nothrow__)) ; -#line 364 +#line 376 extern int ( __attribute__((__leaf__)) timer_getoverrun)(timer_t __timerid ) __attribute__((__nothrow__)) ; -#line 371 +#line 383 extern int ( __attribute__((__nonnull__(1), __leaf__)) timespec_get)(struct timespec *__ts , int __base ) __attribute__((__nothrow__)) ; #line 202 "/usr/include/pthread.h" @@ -1827,9 +1829,8 @@ extern void __pthread_unregister_cancel(__pthread_unwind_buf_t *__buf ) ; #line 750 extern void __pthread_unwind_next(__pthread_unwind_buf_t *__buf ) __attribute__((__weak__, __noreturn__)) ; -#line 766 -extern int __sigsetjmp_cancel(struct __cancel_jmp_buf_tag *__env , int __savemask ) __asm__("__sigsetjmp") __attribute__((__returns_twice__, -__nothrow__)) ; +#line 773 +extern int __sigsetjmp(struct __jmp_buf_tag *__env , int __savemask ) __attribute__((__nothrow__)) ; #line 781 extern int ( __attribute__((__nonnull__(1), __leaf__)) pthread_mutex_init)(pthread_mutex_t *__mutex , pthread_mutexattr_t const *__mutexattr ) __attribute__((__nothrow__)) ; @@ -1994,8 +1995,7 @@ extern int ( __attribute__((__leaf__)) pthread_key_delete)(pthread_key_t __key ) extern void *( __attribute__((__leaf__)) pthread_getspecific)(pthread_key_t __key ) __attribute__((__nothrow__)) ; #line 1308 extern int ( __attribute__((__leaf__)) pthread_setspecific)(pthread_key_t __key , - void const *__pointer ) __attribute__((__nothrow__, -__access__(__none__,2))) ; + void const *__pointer ) __attribute__((__nothrow__)) ; #line 1315 extern int ( __attribute__((__nonnull__(2), __leaf__)) pthread_getcpuclockid)(pthread_t __thread_id , __clockid_t *__clock_id ) __attribute__((__nothrow__)) ; diff --git a/src/analyses/termination_new.ml b/src/analyses/termination_new.ml index 4926c23daa..e722b9a2b2 100644 --- a/src/analyses/termination_new.ml +++ b/src/analyses/termination_new.ml @@ -6,13 +6,13 @@ open TerminationPreprocessing exception PreProcessing of string - -(* contains all loop counter variables (varinfo) and maps them to their corresponding loop statement*) -let loop_counters: stmt VarToStmt.t ref = ref VarToStmt.empty +(** Contains all loop counter variables (varinfo) and maps them to their corresponding loop statement. *) +let loop_counters : stmt VarToStmt.t ref = ref VarToStmt.empty (** Contains the locations of the upjumping gotos *) let upjumping_gotos : location list ref = ref [] +(** Indicates the place in the code, right after a loop is exited. *) let loop_exit : varinfo ref = ref (makeVarinfo false "-error" Cil.intType) let is_loop_counter_var (x : varinfo) = @@ -25,10 +25,10 @@ let is_loop_exit_indicator (x : varinfo) = * upjumping goto was already reached. Returns true if no upjumping goto was * reached until now *) let currrently_no_upjumping_gotos (loc : location) = - List.for_all (function (l) -> (l >= loc)) upjumping_gotos.contents + List.for_all (function l -> l >= loc) upjumping_gotos.contents let no_upjumping_gotos () = - (List.length upjumping_gotos.contents) <= 0 + List.length upjumping_gotos.contents = 0 (** Checks whether a variable can be bounded *) let check_bounded ctx varinfo = @@ -45,6 +45,7 @@ struct include Analyses.StdV end +module Statements = Lattice.Flat (CilType.Stmt) (Printable.DefaultNames) (* TODO: Use Basetype.CilStmt instead? *) module Spec : Analyses.MCPSpec = struct @@ -54,7 +55,7 @@ struct let name () = "termination" - module D = MapDomain.MapBot (Basetype.Variables) (BoolDomain.MustBool) + module D = MapDomain.MapBot (Statements) (BoolDomain.MustBool) module C = D module V = FunContextV (* TODO *) @@ -69,12 +70,14 @@ struct match lval, rval with (Var x, NoOffset), _ when is_loop_counter_var x -> (* Assume that the following loop does not terminate *) - D.add x false ctx.local + let loop_statement = VarToStmt.find x !loop_counters in + D.add (`Lifted loop_statement) false ctx.local | (Var y, NoOffset), Lval (Var x, NoOffset) when is_loop_exit_indicator y -> (* Loop exit: Check whether loop counter variable is bounded *) (* TODO: Move *) let is_bounded = check_bounded ctx x in - D.add x is_bounded ctx.local + let loop_statement = VarToStmt.find x !loop_counters in + D.add (`Lifted loop_statement) is_bounded ctx.local | _ -> ctx.local let special ctx (lval : lval option) (f : varinfo) (arglist : exp list) = @@ -82,16 +85,16 @@ struct ctx.local (** Provides information to Goblint *) - (* TODO: Consider gotos and recursion *) + (* TODO: Consider gotos *) let query ctx (type a) (q: a Queries.t): a Queries.result = let open Queries in match q with - | Queries.MustTermLoop v -> - (match D.find_opt v ctx.local with + | Queries.MustTermLoop loop_statement -> + (match D.find_opt (`Lifted loop_statement) ctx.local with Some b -> b | None -> Result.top q) | Queries.MustTermProg -> - D.for_all (fun loop term_info -> term_info) ctx.local + D.for_all (fun _ term_info -> term_info) ctx.local | _ -> Result.top q end diff --git a/src/domains/queries.ml b/src/domains/queries.ml index 022e8e1dee..c5d7d729b6 100644 --- a/src/domains/queries.ml +++ b/src/domains/queries.ml @@ -117,7 +117,7 @@ type _ t = | MayAccessed: AccessDomain.EventSet.t t | MayBeTainted: LS.t t | MayBeModifiedSinceSetjmp: JmpBufDomain.BufferEntry.t -> VS.t t - | MustTermLoop: varinfo -> MustBool.t t (** TODO: not sure if it is the MayBool*) + | MustTermLoop: stmt -> MustBool.t t | MustTermProg: MustBool.t t type 'a result = 'a @@ -347,7 +347,7 @@ struct compare (Any q1) (Any q2) | Any (IsHeapVar v1), Any (IsHeapVar v2) -> CilType.Varinfo.compare v1 v2 | Any (IsMultiple v1), Any (IsMultiple v2) -> CilType.Varinfo.compare v1 v2 - | Any (MustTermLoop v1), Any (MustTermLoop v2) -> CilType.Varinfo.compare v1 v2 + | Any (MustTermLoop s1), Any (MustTermLoop s2) -> CilType.Stmt.compare s1 s2 | Any (EvalThread e1), Any (EvalThread e2) -> CilType.Exp.compare e1 e2 | Any (EvalJumpBuf e1), Any (EvalJumpBuf e2) -> CilType.Exp.compare e1 e2 | Any (WarnGlobal vi1), Any (WarnGlobal vi2) -> Stdlib.compare (Hashtbl.hash vi1) (Hashtbl.hash vi2) @@ -386,7 +386,7 @@ struct | Any (IterVars i) -> 0 | Any (PathQuery (i, q)) -> 31 * i + hash (Any q) | Any (IsHeapVar v) -> CilType.Varinfo.hash v - | Any (MustTermLoop v) -> CilType.Varinfo.hash v + | Any (MustTermLoop s) -> CilType.Stmt.hash s | Any (IsMultiple v) -> CilType.Varinfo.hash v | Any (EvalThread e) -> CilType.Exp.hash e | Any (EvalJumpBuf e) -> CilType.Exp.hash e @@ -454,7 +454,7 @@ struct | Any MayBeTainted -> Pretty.dprintf "MayBeTainted" | Any DYojson -> Pretty.dprintf "DYojson" | Any MayBeModifiedSinceSetjmp buf -> Pretty.dprintf "MayBeModifiedSinceSetjmp %a" JmpBufDomain.BufferEntry.pretty buf - | Any (MustTermLoop v) -> Pretty.dprintf "MustTermLoop %a" CilType.Varinfo.pretty v + | Any (MustTermLoop s) -> Pretty.dprintf "MustTermLoop %a" CilType.Stmt.pretty s | Any MustTermProg -> Pretty.dprintf "MustTermProg" end From 5efd011ae3dbd97fb88727c89fead835d33502d5 Mon Sep 17 00:00:00 2001 From: Johanna Schinabeck Date: Sun, 18 Jun 2023 11:11:31 +0200 Subject: [PATCH 096/327] cycle detection should work --- src/framework/analyses.ml | 8 +-- src/framework/constraints.ml | 98 +++++++++++++++++++++++------------- 2 files changed, 69 insertions(+), 37 deletions(-) diff --git a/src/framework/analyses.ml b/src/framework/analyses.ml index b70f2c09cd..c6994fff23 100644 --- a/src/framework/analyses.ml +++ b/src/framework/analyses.ml @@ -135,11 +135,11 @@ end module T (Base1: Printable.S) (Base2: Printable.S) = (*Todo: is this Printable.S or S.C*) struct include Printable.Std - type t = (CilType.Fundec.t * Base2.t) + type t = (Base1.t * Base2.t) let fundec (a,_) = a let context (_,b) = b - let equal (a1, b1) (a2, b2) = if (a1 = a2) && (b1 = b2) then true else false + let equal (a1, b1) (a2, b2) = if (Base1.equal a1 a2 && Base2.equal b1 b2) then true else false let show (a,b) = (Base1.show a) ^ (Base2.show b) let name () = "Tuple" let to_yojson x = `String (show x) @@ -159,6 +159,7 @@ struct - b1 < b2: -3 *) let compare (a1,b1) (a2,b2) = (*Todo: is this ok?*) + if equal (a1, b1) (a2, b2) then 0 else( let res = ref 0 in let comp_a = Base1.compare a1 a2 in let comp_b = Base2.compare b1 b2 in @@ -166,7 +167,7 @@ struct else if (comp_a < 0) then res := !(res) - 1; if (comp_b > 0) then res := !(res) + 3 else if (comp_b < 0) then res := !(res) - 3; - !res + !res) let pretty () x = text (show x) @@ -194,6 +195,7 @@ struct struct include MapDomain.MapBot (C_ (C)) (CSet) let printXml f c = BatPrintf.fprintf f "%a" printXml c (*TODO*) + end include Lattice.Lift2 (G) (CMap) (Printable.DefaultNames) diff --git a/src/framework/constraints.ml b/src/framework/constraints.ml index 8e4eac1bca..7d46744c90 100644 --- a/src/framework/constraints.ml +++ b/src/framework/constraints.ml @@ -1712,7 +1712,7 @@ struct include GVarF(S.V) end - module G = GVarGG (S.G) (S.C) (T (CilType.Fundec) (C)) + module G = GVarGG (S.G) (S.C) (T (CilType.Fundec) (S.C)) let name () = "RecursionTerm (" ^ S.name () ^ ")" @@ -1723,43 +1723,73 @@ struct sideg = (fun v g -> ctx.sideg (V.spec v) (G.create_s g)); } + let cycleDetection ctx v v' = + let module LH = Hashtbl.Make (T (CilType.Fundec) (S.C)) in + let module LS = Set.Make (T (CilType.Fundec) (S.C)) in + (* TODO: find all cycles/SCCs *) + let global_visited_calls = LH.create 100 in + + (* DFS *) + let rec iter_call (path_visited_calls: LS.t) (call:T (CilType.Fundec) (S.C).t) = + let ((fundec_e:fundec), (context_e: C.t)) = call in (*unpack tuple for later use*) + + if LS.mem call path_visited_calls then ( + (*Cycle found*) + let msgs = + [ + (Pretty.dprintf "The program might not terminate! (Fundec %a is contained in a call graph cycle)\n" CilType.Fundec.pretty fundec_e, Some (M.Location.CilLocation locUnknown)); + ] in + M.msg_group Warning "Recursion cycle" msgs) + else if not (LH.mem global_visited_calls call) then begin + try + LH.replace global_visited_calls call (); + let new_path_visited_calls = LS.add call path_visited_calls in + + let fundec_e_typeV: V.t = V.relift (`Right fundec_e) in + let gmap_opt = G.base2 (ctx.global (fundec_e_typeV)) in + let gmap = Option.get (gmap_opt) in (*might be empty*) + let callers: G.CSet.t = G.CMap.find (context_e) gmap in (*TODO: how do we get our Map out of g*) (*Todo: the context should be the domain of the map*) + G.CSet.iter (fun to_call -> + iter_call new_path_visited_calls to_call + ) callers; + with Invalid_argument _ -> () (* path ended: no cycle*) + end + in + let gmap_opt = G.base2 (ctx.global (v)) in + let gmap = Option.get (gmap_opt) in + (*let c = Option.get(G.CMap.PMap.keys gmap) in *)(*Todo: the context should be the domain of the map*) + G.CMap.iter(fun key value -> + let call = (v', key) in + iter_call LS.empty call + ) gmap (* try all fundec + context pairs that are in the map *) + (*TODO: We may need to add new queries here*) let query ctx (type a) (q: a Queries.t): a Queries.result = match q with - | WarnGlobal g -> - let g: V.t = Obj.obj g in - begin match g with - | `Left g' -> - S.query (conv ctx) (WarnGlobal (Obj.repr g')) - | `Right g' -> - let module LH = Hashtbl.Make (T (CilType.Fundec) (C)) in - let module LS = Set.Make (T (CilType.Fundec) (C)) in - (* TODO: find all cycles/SCCs *) - let global_visited_calls = LH.create 100 in - - (* DFS *) - let rec iter_call (path_visited_calls: LS.t) (call: T (CilType.Fundec) (C).t) = - if LS.mem call path_visited_calls then - (*Cycle found*) + | WarnGlobal v -> + let v: V.t = Obj.obj v in + begin match v with + | `Left v' -> + S.query (conv ctx) (WarnGlobal (Obj.repr v')) + | `Right v' -> + (*Check if the loops terminated*) + match ctx.ask (MustTermProg) with + | false -> (*does not terminate*) let msgs = - [ - (Pretty.dprintf "lock before:", Some (M.Location.CilLocation locUnknown)); - (Pretty.dprintf "lock after: with", Some (M.Location.CilLocation locUnknown)); - ] in - M.msg_group Warning ~category:Deadlock "Locking order cycle" msgs; - S.query (conv ctx) q - else if not (LH.mem global_visited_calls call) then begin - printf "test\n"; - LH.replace global_visited_calls call (); - let callers = G.CMap.find (ctx.context()) (Option.get (G.base2 (ctx.global (g)))) in (*TODO: how do we get our Map out of g*) - let new_path_visited_calls = LS.add call path_visited_calls in - G.CSet.iter (fun to_call -> - iter_call new_path_visited_calls to_call - ) callers - end - in - S.query (conv ctx) q - end + [ + (Pretty.dprintf "The program might not terminate! (Loops)\n", Some (M.Location.CilLocation locUnknown)); + ] in + M.msg_group Warning "Non terminating loops" msgs + | true -> cycleDetection ctx v v' + end + | InvariantGlobal v -> + let v: V.t = Obj.obj v in + begin match v with + | `Left v -> + S.query (conv ctx) (InvariantGlobal (Obj.repr v)) + | `Right v -> + Queries.Result.top q + end | _ -> S.query (conv ctx) q let branch ctx = S.branch (conv ctx) From 8563cc7e438d1811c9ca151287ebc53d940cfcbb Mon Sep 17 00:00:00 2001 From: Alexander Schlenga Date: Sun, 18 Jun 2023 12:39:01 +0200 Subject: [PATCH 097/327] Consider upjumping gotos in whole program query and a bit of change towards using a global invariant --- src/analyses/termination_new.ml | 28 ++++++++++++---------------- 1 file changed, 12 insertions(+), 16 deletions(-) diff --git a/src/analyses/termination_new.ml b/src/analyses/termination_new.ml index e722b9a2b2..d610a89fe9 100644 --- a/src/analyses/termination_new.ml +++ b/src/analyses/termination_new.ml @@ -21,12 +21,6 @@ let is_loop_counter_var (x : varinfo) = let is_loop_exit_indicator (x : varinfo) = x = !loop_exit -(** Checks whether at the current location (=loc) of the analysis an - * upjumping goto was already reached. Returns true if no upjumping goto was - * reached until now *) -let currrently_no_upjumping_gotos (loc : location) = - List.for_all (function l -> l >= loc) upjumping_gotos.contents - let no_upjumping_gotos () = List.length upjumping_gotos.contents = 0 @@ -39,14 +33,18 @@ let check_bounded ctx varinfo = | `Lifted v -> not (is_top_of (ikind v) v) | `Bot -> raise (PreProcessing "Loop variable is Bot") -module FunContextV : Analyses.SpecSysVar = +module UnitV : SpecSysVar = struct - include Printable.Prod (CilType.Fundec) (CilType.Fundec) (* TODO *) - include Analyses.StdV + include Printable.Unit + include StdV end +(** We want to record termination information of loops and use the loop + * statements for that. We use this lifting because we need to have a + * lattice. *) module Statements = Lattice.Flat (CilType.Stmt) (Printable.DefaultNames) (* TODO: Use Basetype.CilStmt instead? *) +(** The termination analysis considering loops and gotos *) module Spec : Analyses.MCPSpec = struct @@ -55,15 +53,13 @@ struct let name () = "termination" - module D = MapDomain.MapBot (Statements) (BoolDomain.MustBool) + module D = MapDomain.MapBot (Statements) (BoolDomain.MustBool) (* TODO *) module C = D - module V = FunContextV - (* TODO *) + module V = UnitV + module G = MapDomain.MapBot (Statements) (BoolDomain.MustBool) let startstate _ = D.bot () - let exitstate = startstate (* TODO *) - - let finalize () = () (* TODO *) + let exitstate = startstate let assign ctx (lval : lval) (rval : exp) = (* Detect assignment to loop counter variable *) @@ -85,7 +81,6 @@ struct ctx.local (** Provides information to Goblint *) - (* TODO: Consider gotos *) let query ctx (type a) (q: a Queries.t): a Queries.result = let open Queries in match q with @@ -95,6 +90,7 @@ struct | None -> Result.top q) | Queries.MustTermProg -> D.for_all (fun _ term_info -> term_info) ctx.local + && no_upjumping_gotos () | _ -> Result.top q end From d786f98faad490c4957c8fd8d09e9870abdba14b Mon Sep 17 00:00:00 2001 From: Alexander Schlenga Date: Sun, 18 Jun 2023 18:11:11 +0200 Subject: [PATCH 098/327] WIP on using find_loop_heads and global invariant --- src/analyses/termination_new.ml | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/src/analyses/termination_new.ml b/src/analyses/termination_new.ml index d610a89fe9..5e56c74a05 100644 --- a/src/analyses/termination_new.ml +++ b/src/analyses/termination_new.ml @@ -6,6 +6,17 @@ open TerminationPreprocessing exception PreProcessing of string +(* + * TODO: Make this work +module FileCfg = +struct + let file = !Cilfacade.current_file + module Cfg = (val !MyCFG.current_cfg) +end + +let loop_heads = WitnessUtil.find_loop_heads FileCfg + *) + (** Contains all loop counter variables (varinfo) and maps them to their corresponding loop statement. *) let loop_counters : stmt VarToStmt.t ref = ref VarToStmt.empty @@ -67,6 +78,10 @@ struct (Var x, NoOffset), _ when is_loop_counter_var x -> (* Assume that the following loop does not terminate *) let loop_statement = VarToStmt.find x !loop_counters in + (* + * TODO: Make the below line work + let () = ctx.sideg (() : V.t) (G.add (`Lifted loop_statement) false ctx.local) in + *) D.add (`Lifted loop_statement) false ctx.local | (Var y, NoOffset), Lval (Var x, NoOffset) when is_loop_exit_indicator y -> (* Loop exit: Check whether loop counter variable is bounded *) From bf44af74d3d864d7dfeb477545aa2f7f4b7b1ffd Mon Sep 17 00:00:00 2001 From: Johanna Schinabeck Date: Sun, 18 Jun 2023 21:07:06 +0200 Subject: [PATCH 099/327] resolved merge conflict, cycle detection is working, BUT loop results are not correct yet --- src/analyses/termination_new.ml | 10 +++++--- src/framework/analyses.ml | 35 +++++++++++++++------------- src/framework/constraints.ml | 27 +++++++++++---------- src/util/terminationPreprocessing.ml | 9 ++++++- 4 files changed, 49 insertions(+), 32 deletions(-) diff --git a/src/analyses/termination_new.ml b/src/analyses/termination_new.ml index e722b9a2b2..fabd341a23 100644 --- a/src/analyses/termination_new.ml +++ b/src/analyses/termination_new.ml @@ -90,11 +90,15 @@ struct let open Queries in match q with | Queries.MustTermLoop loop_statement -> - (match D.find_opt (`Lifted loop_statement) ctx.local with + if no_upjumping_gotos () + then ((match D.find_opt (`Lifted loop_statement) ctx.local with Some b -> b - | None -> Result.top q) + | None -> Result.top q)) + else(Result.top q) | Queries.MustTermProg -> - D.for_all (fun _ term_info -> term_info) ctx.local + if no_upjumping_gotos () + then (D.for_all (fun _ term_info -> term_info) ctx.local) + else (Result.top q) | _ -> Result.top q end diff --git a/src/framework/analyses.ml b/src/framework/analyses.ml index c6994fff23..763ffd0e56 100644 --- a/src/framework/analyses.ml +++ b/src/framework/analyses.ml @@ -119,17 +119,6 @@ struct | x -> BatPrintf.fprintf f "%a" printXml x end -(* Make the given module Goupable*) -module C_ (C: Printable.S)= -struct - include C - include Printable.Std (* To make it Groupable *) - let printXml f c = BatPrintf.fprintf f (*Todo: Make this print pretty*) - " - callee_context:\n%a\n\n - " printXml c (* wrap in for HTML printing *) - -end (* Tuple of fundec and S.C*) module T (Base1: Printable.S) (Base2: Printable.S) = (*Todo: is this Printable.S or S.C*) @@ -146,7 +135,7 @@ struct let relift (a,b) = (a,b) (*Todo: is this correct?*) let printXml f (a,b) = BatPrintf.fprintf f "\n - Tuple:\n + Tuple:\n\n caller_fundec\n%a\n\n caller_context\n%a\n\n \n" Base1.printXml a Base2.printXml b @@ -176,6 +165,7 @@ struct end module GVarGG (G: Lattice.S) (C: Printable.S) (Base: Printable.S) = + struct module CSet = struct @@ -186,16 +176,29 @@ struct ) let name () = "contexts" let printXml f a = - BatPrintf.fprintf f "\n\n"; + BatPrintf.fprintf f "\n"; iter (Base.printXml f) a; BatPrintf.fprintf f "\n\n" end + (* Make the given module Goupable*) + module C_Printable (C: Printable.S)= + struct + include C + include Printable.Std (* To make it Groupable *) + let printXml f c = BatPrintf.fprintf f (*Todo: Make this print pretty*) + "\n + callee_context\n%a\n\n + " printXml c (* wrap in for HTML printing *) + end + module CMap = struct - include MapDomain.MapBot (C_ (C)) (CSet) - let printXml f c = BatPrintf.fprintf f "%a" printXml c (*TODO*) - + include MapDomain.MapBot (C_Printable (C)) (CSet) + let printXml f c = BatPrintf.fprintf f " + ContextTupleMap\n + %a\n\n + " printXml c (*TODO*) end include Lattice.Lift2 (G) (CMap) (Printable.DefaultNames) diff --git a/src/framework/constraints.ml b/src/framework/constraints.ml index 7d46744c90..5be58cd27b 100644 --- a/src/framework/constraints.ml +++ b/src/framework/constraints.ml @@ -1753,6 +1753,7 @@ struct iter_call new_path_visited_calls to_call ) callers; with Invalid_argument _ -> () (* path ended: no cycle*) + end in let gmap_opt = G.base2 (ctx.global (v)) in @@ -1760,9 +1761,19 @@ struct (*let c = Option.get(G.CMap.PMap.keys gmap) in *)(*Todo: the context should be the domain of the map*) G.CMap.iter(fun key value -> let call = (v', key) in - iter_call LS.empty call + iter_call LS.empty call ) gmap (* try all fundec + context pairs that are in the map *) + let checkTerminating ctx v v' = + (*Check if the loops terminated*) + if ctx.ask Queries.MustTermProg + then (cycleDetection ctx v v') + else(let msgs = + [ + (Pretty.dprintf "The program might not terminate! (Loops)\n", Some (M.Location.CilLocation locUnknown)); + ] in + M.msg_group Warning "Possibly non terminating loops" msgs) + (*TODO: We may need to add new queries here*) let query ctx (type a) (q: a Queries.t): a Queries.result = match q with @@ -1771,17 +1782,8 @@ struct begin match v with | `Left v' -> S.query (conv ctx) (WarnGlobal (Obj.repr v')) - | `Right v' -> - (*Check if the loops terminated*) - match ctx.ask (MustTermProg) with - | false -> (*does not terminate*) - let msgs = - [ - (Pretty.dprintf "The program might not terminate! (Loops)\n", Some (M.Location.CilLocation locUnknown)); - ] in - M.msg_group Warning "Non terminating loops" msgs - | true -> cycleDetection ctx v v' - end + | `Right v' -> checkTerminating ctx v v' + end | InvariantGlobal v -> let v: V.t = Obj.obj v in begin match v with @@ -1790,6 +1792,7 @@ struct | `Right v -> Queries.Result.top q end + | MustTermProgWithRec -> false (*TODO*) | _ -> S.query (conv ctx) q let branch ctx = S.branch (conv ctx) diff --git a/src/util/terminationPreprocessing.ml b/src/util/terminationPreprocessing.ml index a64e48446b..409aa2c2c4 100644 --- a/src/util/terminationPreprocessing.ml +++ b/src/util/terminationPreprocessing.ml @@ -18,6 +18,13 @@ let show_location_id l = class loopCounterVisitor lc lg le (fd : fundec) = object(self) inherit nopCilVisitor + method! vfunc (f:fundec) = + if !le.vname <> "term_exit-" then begin + let exit_name = "term_exit-" in + let typ = Cil.intType in + le := Cil.makeGlobalVar exit_name typ; + end; + DoChildren; (* function definition *) method! vstmt s = let action s = match s.skind with | Loop (b, loc, eloc, _, _) -> @@ -26,7 +33,7 @@ class loopCounterVisitor lc lg le (fd : fundec) = object(self) let v = (Cil.makeLocalVar fd name typ) in (*Not tested for incremental mode*) let init_stmt = mkStmtOneInstr @@ Set (var v, zero, loc, eloc) in let inc_stmt = mkStmtOneInstr @@ Set (var v, increm (Lval (var v)) 1, loc, eloc) in - let exit_stmt = mkStmtOneInstr @@ Call (None, f_bounded, [(Lval(var v))], loc, eloc) in + let exit_stmt = mkStmtOneInstr @@ Set ((var !le), (Lval (var v)), loc, eloc) in (match b.bstmts with | cont :: cond :: ss -> b.bstmts <- cont :: inc_stmt :: cond :: ss; (*cont :: cond :: inc_stmt :: ss = it is also possible, but for loops with cond at the end, inc is also at the end*) From 03dbf0bdf92761f2e1680d90b8156a727856a02a Mon Sep 17 00:00:00 2001 From: Johanna Schinabeck Date: Sun, 18 Jun 2023 21:09:33 +0200 Subject: [PATCH 100/327] added queries --- src/domains/queries.ml | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/domains/queries.ml b/src/domains/queries.ml index c5d7d729b6..6603175f36 100644 --- a/src/domains/queries.ml +++ b/src/domains/queries.ml @@ -119,6 +119,7 @@ type _ t = | MayBeModifiedSinceSetjmp: JmpBufDomain.BufferEntry.t -> VS.t t | MustTermLoop: stmt -> MustBool.t t | MustTermProg: MustBool.t t + | MustTermProgWithRec: MustBool.t t type 'a result = 'a @@ -185,6 +186,7 @@ struct | MayBeModifiedSinceSetjmp _ -> (module VS) | MustTermLoop _ -> (module MustBool) | MustTermProg -> (module MustBool) + | MustTermProgWithRec -> (module MustBool) (** Get bottom result for query. *) let bot (type a) (q: a t): a result = @@ -250,6 +252,7 @@ struct | MayBeModifiedSinceSetjmp _ -> VS.top () | MustTermLoop _ -> MustBool.top () | MustTermProg -> MustBool.top () + | MustTermProgWithRec -> MustBool.top () end (* The type any_query can't be directly defined in Any as t, @@ -312,6 +315,7 @@ struct | Any ThreadsJoinedCleanly -> 52 | Any (MustTermLoop _) -> 53 | Any MustTermProg -> 54 + | Any MustTermProgWithRec -> 55 let rec compare a b = let r = Stdlib.compare (order a) (order b) in @@ -456,6 +460,7 @@ struct | Any MayBeModifiedSinceSetjmp buf -> Pretty.dprintf "MayBeModifiedSinceSetjmp %a" JmpBufDomain.BufferEntry.pretty buf | Any (MustTermLoop s) -> Pretty.dprintf "MustTermLoop %a" CilType.Stmt.pretty s | Any MustTermProg -> Pretty.dprintf "MustTermProg" + | Any MustTermProgWithRec -> Pretty.dprintf "MustTermProgWithRec" end let to_value_domain_ask (ask: ask) = From 5457fc36b887c5bd8196e3b2a544150b4b9916d4 Mon Sep 17 00:00:00 2001 From: Alexander Schlenga Date: Mon, 19 Jun 2023 13:04:28 +0200 Subject: [PATCH 101/327] Use global invariant instead of local state Still needs a bit of work. Currently, loops are only ever analyzed if their loop exit indicator is encountered. --- src/analyses/termination_new.ml | 44 ++++++++++++++++----------------- 1 file changed, 21 insertions(+), 23 deletions(-) diff --git a/src/analyses/termination_new.ml b/src/analyses/termination_new.ml index 5e56c74a05..f062030820 100644 --- a/src/analyses/termination_new.ml +++ b/src/analyses/termination_new.ml @@ -6,16 +6,14 @@ open TerminationPreprocessing exception PreProcessing of string -(* - * TODO: Make this work -module FileCfg = -struct - let file = !Cilfacade.current_file - module Cfg = (val !MyCFG.current_cfg) -end - -let loop_heads = WitnessUtil.find_loop_heads FileCfg - *) +let loop_heads = + let module FileCfg = + struct + let file = !Cilfacade.current_file + module Cfg = (val !MyCFG.current_cfg) + end in + let module WitnessInvariant = WitnessUtil.Invariant (FileCfg) in + WitnessInvariant.loop_heads (* TODO: Use this *) (** Contains all loop counter variables (varinfo) and maps them to their corresponding loop statement. *) let loop_counters : stmt VarToStmt.t ref = ref VarToStmt.empty @@ -44,7 +42,7 @@ let check_bounded ctx varinfo = | `Lifted v -> not (is_top_of (ikind v) v) | `Bot -> raise (PreProcessing "Loop variable is Bot") -module UnitV : SpecSysVar = +module UnitV = struct include Printable.Unit include StdV @@ -64,7 +62,7 @@ struct let name () = "termination" - module D = MapDomain.MapBot (Statements) (BoolDomain.MustBool) (* TODO *) + module D = Lattice.Unit module C = D module V = UnitV module G = MapDomain.MapBot (Statements) (BoolDomain.MustBool) @@ -75,20 +73,21 @@ struct let assign ctx (lval : lval) (rval : exp) = (* Detect assignment to loop counter variable *) match lval, rval with + (* (Var x, NoOffset), _ when is_loop_counter_var x -> (* Assume that the following loop does not terminate *) let loop_statement = VarToStmt.find x !loop_counters in - (* - * TODO: Make the below line work - let () = ctx.sideg (() : V.t) (G.add (`Lifted loop_statement) false ctx.local) in - *) + let () = ctx.sideg () (G.add (`Lifted loop_statement) false ctx.local) in + let () = print_endline ("Added FALSE for " ^ x.vname) in D.add (`Lifted loop_statement) false ctx.local - | (Var y, NoOffset), Lval (Var x, NoOffset) when is_loop_exit_indicator y -> + *) + (Var y, NoOffset), Lval (Var x, NoOffset) when is_loop_exit_indicator y -> (* Loop exit: Check whether loop counter variable is bounded *) (* TODO: Move *) let is_bounded = check_bounded ctx x in let loop_statement = VarToStmt.find x !loop_counters in - D.add (`Lifted loop_statement) is_bounded ctx.local + let () = ctx.sideg () (G.add (`Lifted loop_statement) is_bounded (ctx.global ())) in + ctx.local | _ -> ctx.local let special ctx (lval : lval option) (f : varinfo) (arglist : exp list) = @@ -97,16 +96,15 @@ struct (** Provides information to Goblint *) let query ctx (type a) (q: a Queries.t): a Queries.result = - let open Queries in match q with | Queries.MustTermLoop loop_statement -> - (match D.find_opt (`Lifted loop_statement) ctx.local with + (match G.find_opt (`Lifted loop_statement) (ctx.global ()) with Some b -> b - | None -> Result.top q) + | None -> false) | Queries.MustTermProg -> - D.for_all (fun _ term_info -> term_info) ctx.local + G.for_all (fun _ term_info -> term_info) (ctx.global ()) && no_upjumping_gotos () - | _ -> Result.top q + | _ -> Queries.Result.top q end From 13e8b7a2379ae12ce8b755287d1403f9fa71fff7 Mon Sep 17 00:00:00 2001 From: Johanna Schinabeck Date: Sat, 17 Jun 2023 10:34:59 +0200 Subject: [PATCH 102/327] comments, transformed loop_counters to a map to store stmts --- src/analyses/termination_new.ml | 6 +- src/framework/constraints.ml | 269 --------------------------- src/util/terminationPreprocessing.ml | 54 +----- 3 files changed, 10 insertions(+), 319 deletions(-) diff --git a/src/analyses/termination_new.ml b/src/analyses/termination_new.ml index 44b0c7fb5e..4926c23daa 100644 --- a/src/analyses/termination_new.ml +++ b/src/analyses/termination_new.ml @@ -6,7 +6,9 @@ open TerminationPreprocessing exception PreProcessing of string -let loop_counters : varinfo list ref = ref [] + +(* contains all loop counter variables (varinfo) and maps them to their corresponding loop statement*) +let loop_counters: stmt VarToStmt.t ref = ref VarToStmt.empty (** Contains the locations of the upjumping gotos *) let upjumping_gotos : location list ref = ref [] @@ -14,7 +16,7 @@ let upjumping_gotos : location list ref = ref [] let loop_exit : varinfo ref = ref (makeVarinfo false "-error" Cil.intType) let is_loop_counter_var (x : varinfo) = - List.mem x !loop_counters + VarToStmt.mem x !loop_counters let is_loop_exit_indicator (x : varinfo) = x = !loop_exit diff --git a/src/framework/constraints.ml b/src/framework/constraints.ml index 0177f3ea85..07750122a5 100644 --- a/src/framework/constraints.ml +++ b/src/framework/constraints.ml @@ -1693,275 +1693,6 @@ struct let event ctx e octx = S.event (conv ctx) e (conv octx) end -(** -module RecursionTermLifter (S: Spec): Spec = -struct - include S - - let name () = "RecursionTerm (" ^ S.name () ^ ")" - - (* global invariant: - - fundec -> (S.C -> Set (fundec * S.C)) -- used to detect loops in the call graph *) - - module V = - struct - include Printable.Option (S.V) (struct let name = "RecursionTerm" end) - let name () = "RecursionTerm" - let is_write_only t = true - let s x = `Left x - end - - module C = - struct - include S.C - include Printable.Std (* To make it Groupable *) - let printXml f c = BatPrintf.fprintf f "%a" printXml c (* wrap in for HTML printing *) - - end - - (*module Tuple = struct - type t = (fundec, S.C) [@@deriving eq, ord, hash] - let equal t1 t2 = false - let compare t1 t3 = 0 - let show t = "t" - let pretty () (x: t) = match x with _ -> . - - let printXml f (d,m) = BatPrintf.fprintf f "%a" printXml c (* wrap in for HTML printing *) - - let name u = "recursion" - let to_yojson (x: t) = match x with _ -> . - - let tag t = 1 - let arbitrary () = failwith "Printable.Empty.arbitrary" - - let relift t = t - end -*) - module Tupel (S:Spec) = - struct - include Printable.Std - type t = fundec * S.C.t [@@deriving eq, ord, hash] - - let equal_fundec = false - let hash_fundec = false - - let name () = "recursion" - - let pretty () (x: t) = match x with _ -> . - - let relift (f, c) = - (f, c) - - let equal t1 t2 = false - let compare t1 t3 = 0 - let show t = "t" - - let printXml f c = BatPrintf.fprintf f "%a" c (* wrap in for HTML printing *) - - let name u = "recursion" - let to_yojson (x: t) = match x with _ -> . - - let tag t = 1 - let arbitrary () = failwith "Printable.Empty.arbitrary" - end - - module T = - struct - include SetDomain.Make (Tupel (S)) - end - - module EM = - struct - include MapDomain.MapBot (C) (T) - let name () = "recursions" - end - - module G = - struct - include Lattice.Lift2 (S.G) (EM) (Printable.DefaultNames) - let name () = "recursionTerm" - let node = function - | `Bot -> EM.bot () - | `Lifted2 x -> x - | _ -> failwith "DeadBranchLifter.node" - let create_s s = `Lifted1 s - let create_node node = `Lifted2 node - - let printXml f = function - | `Lifted1 x -> S.G.printXml f x - | `Lifted2 x -> BatPrintf.fprintf f "%a" EM.printXml x - | x -> BatPrintf.fprintf f "%a" printXml x - end - - let conv (ctx: (_, G.t, _, V.t) ctx): (_, S.G.t, _, S.V.t) ctx = - { ctx with - global = (fun v -> G.s (ctx.global (V.s v))); - sideg = (fun v g -> ctx.sideg (V.s v) (G.create_s g)); - } - - let query ctx (type a) (q: a Queries.t): a Queries.result = - match q with - | WarnGlobal g -> - let g: V.t = Obj.obj g in - begin match g with - | `Left g -> - S.query (conv ctx) (WarnGlobal (Obj.repr g)) - | `Right g -> - let em = G.node (ctx.global (V.node g)) in - EM.iter (fun exp tv -> - match tv with - | `Lifted tv -> - let loc = Node.location g in (* TODO: looking up location now doesn't work nicely with incremental *) - let cilinserted = if loc.synthetic then "(possibly inserted by CIL) " else "" in - M.warn ~loc:(Node g) ~tags:[CWE (if tv then 571 else 570)] ~category:Deadcode "condition '%a' %sis always %B" d_exp exp cilinserted tv - | `Bot when not (CilType.Exp.equal exp one) -> (* all branches dead *) - M.error ~loc:(Node g) ~category:Analyzer ~tags:[Category Unsound] "both branches over condition '%a' are dead" d_exp exp - | `Bot (* all branches dead, fine at our inserted Neg(1)-s because no Pos(1) *) - | `Top -> (* may be both true and false *) - () - ) em; - end - | InvariantGlobal g -> - let g: V.t = Obj.obj g in - begin match g with - | `Left g -> - S.query (conv ctx) (InvariantGlobal (Obj.repr g)) - | `Right g -> - Queries.Result.top q - end - | IterSysVars (vq, vf) -> - (* vars for S *) - let vf' x = vf (Obj.repr (V.s (Obj.obj x))) in - S.query (conv ctx) (IterSysVars (vq, vf')); - - (* node vars for dead branches *) - begin match vq with - | Node {node; _} -> - vf (Obj.repr (V.node node)) - | _ -> - () - end - | _ -> - S.query (conv ctx) q - - - let branch ctx = S.branch (conv ctx) - - let branch ctx exp tv = - if !AnalysisState.postsolving then ( - try - let r = branch ctx exp tv in - (* branch is live *) - ctx.sideg (V.node ctx.prev_node) (G.create_node (EM.singleton exp (`Lifted tv))); (* record expression with reached tv *) - r - with Deadcode -> - (* branch is dead *) - ctx.sideg (V.node ctx.prev_node) (G.create_node (EM.singleton exp `Bot)); (* record expression without reached tv *) - raise Deadcode - ) - else ( - ctx.sideg (V.node ctx.prev_node) (G.create_node (EM.bot ())); (* create global variable during solving, to allow postsolving leq hack to pass verify *) - branch ctx exp tv - ) - - let assign ctx = S.assign (conv ctx) - let vdecl ctx = S.vdecl (conv ctx) - let enter ctx = S.enter (conv ctx) - let paths_as_set ctx = S.paths_as_set (conv ctx) - let body ctx = S.body (conv ctx) - let return ctx = S.return (conv ctx) - let combine_env ctx = S.combine_env (conv ctx) - let combine_assign ctx = S.combine_assign (conv ctx) - let special ctx = S.special (conv ctx) - let threadenter ctx = S.threadenter (conv ctx) - let threadspawn ctx lv f args fctx = S.threadspawn (conv ctx) lv f args (conv fctx) - let sync ctx = S.sync (conv ctx) - let skip ctx = S.skip (conv ctx) - let asm ctx = S.asm (conv ctx) - let event ctx e octx = S.event (conv ctx) e (conv octx) -end - - -(** Add cycle detection in the function call graph to a analysis *) -module RecursionTermLifter (S: Spec) - : Spec with module D = S.D - and module G = S.G - and module C = S.C - and module G = S.G -= - -struct - module C = S.C - module P = S.P - module D = S.D - - (*global invariant - - fundec -> Map (S.C) (Set (fundec * S.C)) - So: g -> {c' -> f, c} - in case f, c --> g, c' *) - - (* - - - module CVal = - struct - include C - include Printable.Std (* To make it Groupable *) - let printXml f c = BatPrintf.fprintf f "%a" printXml c (* wrap in for HTML printing *) - end - module M = MapDomain.MapBot (CVal) (CVal) -*) - module V = (*TODO: do I need to change V???*) - struct - include Printable.Option (S.V) (struct let name = "RecursionTerm" end) - let name () = "RecursionTerm" - let is_write_only t = true - let s x = `Left x - end - module G = S.G - (*GMapG (S.G) (S.C)*) - (*struct - include Lattice.Prod (S.G) (M) - let printXml f (d,m) = BatPrintf.fprintf f "\n%a\n%a\n" S.G.printXml d M.printXml m - end*) - let name () = "RecursionTerm (" ^ S.name () ^ ")" - - type marshal = S.marshal - let init = S.init - let finalize = S.finalize (*TODO*) - - let startstate v = S.startstate v - let exitstate v = S.exitstate v - let morphstate = S.morphstate - - let context = S.context - - (**let side_context sideg f c = - if !AnalysisState.postsolving then - sideg (f) (G.create_contexts (G.CSet.singleton c))*) - - let query ctx = S.query (ctx) - let branch ctx = S.branch (ctx) - let assign ctx = S.assign (ctx) - let vdecl ctx = S.vdecl (ctx) - let enter ctx = - if !AnalysisState.postsolving then - printf "hallo hallo"; - S.enter (ctx) (*TODO*) - let paths_as_set ctx = S.paths_as_set (ctx) - let body ctx = S.body (ctx) - let return ctx = S.return (ctx) - let combine_env ctx = S.combine_env (ctx) - let combine_assign ctx = S.combine_assign (ctx) - let special ctx = S.special (ctx) - let threadenter ctx = S.threadenter (ctx) - let threadspawn ctx lv f args fctx = S.threadspawn (ctx) lv f args (fctx) - let sync ctx = S.sync (ctx) - let skip ctx = S.skip (ctx) - let asm ctx = S.asm (ctx) - let event ctx e octx = S.event (ctx) e (octx) -end -*) module CompareGlobSys (SpecSys: SpecSys) = struct diff --git a/src/util/terminationPreprocessing.ml b/src/util/terminationPreprocessing.ml index 684733c05f..7e1e477262 100644 --- a/src/util/terminationPreprocessing.ml +++ b/src/util/terminationPreprocessing.ml @@ -1,13 +1,8 @@ -(* - code in src/analysis/termination.ml contains loopCounterVisitor which might be interesting - - check if overflow happend with new variable - - how do we deal with nested loops? - - make sure only the analyzed files are appended with the code - - return variables that are newly created - *) - open GoblintCil include Printf +module VarToStmt = Map.Make(CilType.Varinfo);; (* maps varinfos (= loop counter variable) to the statement of the corresponding loop*) + let extract_file_name s = (*There still may be a need to filter more chars*) let ls = String.split_on_char '/' s in (*Assuming '/' as path seperator*) let ls = List.rev ls in @@ -35,7 +30,7 @@ class loopCounterVisitor lc lg le (fd : fundec) = object(self) | Loop (b, loc, eloc, _, _) -> let name = "term"^show_location_id loc in let typ = Cil.intType in - let v = (Cil.makeLocalVar fd name typ) in + let v = (Cil.makeLocalVar fd name typ) in (* Not tested for incremental mode*) let init_stmt = mkStmtOneInstr @@ Set (var v, zero, loc, eloc) in let inc_stmt = mkStmtOneInstr @@ Set (var v, increm (Lval (var v)) 1, loc, eloc) in let exit_stmt = mkStmtOneInstr @@ Set ((var !le), (Lval (var v)), loc, eloc) in @@ -43,7 +38,8 @@ class loopCounterVisitor lc lg le (fd : fundec) = object(self) | cont :: cond :: ss -> b.bstmts <- cont :: inc_stmt :: cond :: ss; (*cont :: cond :: inc_stmt :: ss = it is also possible, but for loops with cond at the end, inc is also at the end*) | _ -> ()); - lc := List.append !lc ([v] : varinfo list); + lc := VarToStmt.add (v: varinfo) (s: stmt) !lc; + (*lc := List.append !lc ([v] : varinfo list);*) let nb = mkBlock [init_stmt; mkStmt s.skind; exit_stmt] in s.skind <- Block nb; s @@ -56,42 +52,4 @@ class loopCounterVisitor lc lg le (fd : fundec) = object(self) s | _ -> s in ChangeDoChildrenPost (s, action); - end - -(* just a test -class loopCounterVisitor (fd : fundec) = object(self) -inherit nopCilVisitor -method! vstmt s = - match s.skind with - | Loop (b, loc, eloc, _, _) -> - let name = "term"^show_location_id loc in - let typ = intType in - let v = Goblintutil.create_var (makeLocalVar fd name ~init:(SingleInit zero) typ) in - let init_stmt = mkStmtOneInstr @@ Set (var v, zero, loc, eloc) in - let inc_stmt = mkStmtOneInstr @@ Set (var v, increm (Lval (var v)) 1, loc, eloc) in - b.bstmts <- inc_stmt :: b.bstmts; - let nb = mkBlock [init_stmt; mkStmt s.skind] in (* init_stmt; *) - ChangeDoChildrenPost (s, (fun _ -> s.skind <- Block(nb); s)) - | _ -> DoChildren -end - -let add_var_loopTerm fd f = - let thisVisitor = new loopCounterVisitor in - visitCilFileSameGlobals (thisVisitor fd ) f*) -(* -let action (fd : fundec) s = - let a s = match s.skind with - | Loop (b, loc, eloc, _, _) -> - let name = "term"^show_location_id loc in - let typ = intType in - let v = Goblintutil.create_var (makeLocalVar fd name ~init:(SingleInit zero) typ) in - let init_stmt = mkStmtOneInstr @@ Set (var v, zero, loc, eloc) in - let inc_stmt = mkStmtOneInstr @@ Set (var v, increm (Lval (var v)) 1, loc, eloc) in - b.bstmts <- inc_stmt :: b.bstmts; - let nb = mkBlock [init_stmt; mkStmt s.skind] in (* *) - s.skind <- Block nb; - s - | _ -> s -in ChangeDoChildrenPost (s, a) -*) - + end \ No newline at end of file From 1d8fb5019387bf283a74addac82b42d8e608fb7b Mon Sep 17 00:00:00 2001 From: Johanna Schinabeck Date: Sat, 17 Jun 2023 11:20:57 +0200 Subject: [PATCH 103/327] comments --- src/util/terminationPreprocessing.ml | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/util/terminationPreprocessing.ml b/src/util/terminationPreprocessing.ml index 7e1e477262..409aa2c2c4 100644 --- a/src/util/terminationPreprocessing.ml +++ b/src/util/terminationPreprocessing.ml @@ -30,7 +30,7 @@ class loopCounterVisitor lc lg le (fd : fundec) = object(self) | Loop (b, loc, eloc, _, _) -> let name = "term"^show_location_id loc in let typ = Cil.intType in - let v = (Cil.makeLocalVar fd name typ) in (* Not tested for incremental mode*) + let v = (Cil.makeLocalVar fd name typ) in (*Not tested for incremental mode*) let init_stmt = mkStmtOneInstr @@ Set (var v, zero, loc, eloc) in let inc_stmt = mkStmtOneInstr @@ Set (var v, increm (Lval (var v)) 1, loc, eloc) in let exit_stmt = mkStmtOneInstr @@ Set ((var !le), (Lval (var v)), loc, eloc) in @@ -39,7 +39,6 @@ class loopCounterVisitor lc lg le (fd : fundec) = object(self) b.bstmts <- cont :: inc_stmt :: cond :: ss; (*cont :: cond :: inc_stmt :: ss = it is also possible, but for loops with cond at the end, inc is also at the end*) | _ -> ()); lc := VarToStmt.add (v: varinfo) (s: stmt) !lc; - (*lc := List.append !lc ([v] : varinfo list);*) let nb = mkBlock [init_stmt; mkStmt s.skind; exit_stmt] in s.skind <- Block nb; s From e36eefb052b593e95018275ceaa0fd5a85fa7cfe Mon Sep 17 00:00:00 2001 From: Alexander Schlenga Date: Sat, 17 Jun 2023 12:24:55 +0200 Subject: [PATCH 104/327] Change loop analysis domain keys to statements Before, the keys of the domain were simply the (loop counter) variables. Now, the keys are the CIL statements which are the analyzed loop. --- output.txt | 62 ++++++++++++++++----------------- src/analyses/termination_new.ml | 27 +++++++------- src/domains/queries.ml | 8 ++--- 3 files changed, 50 insertions(+), 47 deletions(-) diff --git a/output.txt b/output.txt index 07c71d61b9..d751966836 100644 --- a/output.txt +++ b/output.txt @@ -131,7 +131,7 @@ typedef long __intptr_t; typedef unsigned int __socklen_t; #line 215 "/usr/include/x86_64-linux-gnu/bits/types.h" typedef int __sig_atomic_t; -#line 209 "/usr/lib/gcc/x86_64-linux-gnu/11/include/stddef.h" +#line 209 "/usr/lib/gcc/x86_64-linux-gnu/10/include/stddef.h" typedef unsigned long size_t; #line 10 "/usr/include/x86_64-linux-gnu/bits/types/time_t.h" typedef __time_t time_t; @@ -201,12 +201,12 @@ struct __anonstruct___value32_817613185 { unsigned int __high ; }; #line 25 "/usr/include/x86_64-linux-gnu/bits/atomic_wide_counter.h" -union __anonunion___atomic_wide_counter_643133811 { +union __anonunion___atomic_wide_counter_1044835921 { unsigned long long __value64 ; struct __anonstruct___value32_817613185 __value32 ; }; #line 25 "/usr/include/x86_64-linux-gnu/bits/atomic_wide_counter.h" -typedef union __anonunion___atomic_wide_counter_643133811 __atomic_wide_counter; +typedef union __anonunion___atomic_wide_counter_1044835921 __atomic_wide_counter; #line 51 "/usr/include/x86_64-linux-gnu/bits/thread-shared-types.h" struct __pthread_internal_list { struct __pthread_internal_list *__prev ; @@ -261,11 +261,11 @@ typedef unsigned int __tss_t; #line 106 "/usr/include/x86_64-linux-gnu/bits/thread-shared-types.h" typedef unsigned long __thrd_t; #line 108 "/usr/include/x86_64-linux-gnu/bits/thread-shared-types.h" -struct __anonstruct___once_flag_826868709 { +struct __anonstruct___once_flag_1044835922 { int __data ; }; #line 108 "/usr/include/x86_64-linux-gnu/bits/thread-shared-types.h" -typedef struct __anonstruct___once_flag_826868709 __once_flag; +typedef struct __anonstruct___once_flag_1044835922 __once_flag; #line 27 "/usr/include/x86_64-linux-gnu/bits/pthreadtypes.h" typedef unsigned long pthread_t; #line 32 "/usr/include/x86_64-linux-gnu/bits/pthreadtypes.h" @@ -441,16 +441,16 @@ struct __pthread_cleanup_frame { int __do_it ; int __cancel_type ; }; -#line 143 "/usr/lib/gcc/x86_64-linux-gnu/11/include/stddef.h" +#line 143 "/usr/lib/gcc/x86_64-linux-gnu/10/include/stddef.h" typedef long ptrdiff_t; -#line 321 "/usr/lib/gcc/x86_64-linux-gnu/11/include/stddef.h" +#line 321 "/usr/lib/gcc/x86_64-linux-gnu/10/include/stddef.h" typedef int wchar_t; -#line 415 "/usr/lib/gcc/x86_64-linux-gnu/11/include/stddef.h" +#line 415 "/usr/lib/gcc/x86_64-linux-gnu/10/include/stddef.h" struct __anonstruct_max_align_t_896270833 { long long __max_align_ll __attribute__((__aligned__(__alignof__(long long )))) ; long double __max_align_ld __attribute__((__aligned__(__alignof__(long double )))) ; }; -#line 415 "/usr/lib/gcc/x86_64-linux-gnu/11/include/stddef.h" +#line 415 "/usr/lib/gcc/x86_64-linux-gnu/10/include/stddef.h" typedef struct __anonstruct_max_align_t_896270833 max_align_t; /* compiler builtin: void __builtin_va_copy(__builtin_va_list , __builtin_va_list ) ; */ @@ -1683,40 +1683,42 @@ extern void ( __attribute__((__leaf__)) tzset)(void) __attribute__((__nothrow__ extern int daylight ; #line 233 extern long timezone ; -#line 249 +#line 246 extern time_t ( __attribute__((__leaf__)) timegm)(struct tm *__tp ) __attribute__((__nothrow__)) ; -#line 251 +#line 263 extern time_t ( __attribute__((__leaf__)) timelocal)(struct tm *__tp ) __attribute__((__nothrow__)) ; -#line 262 +#line 271 extern int ( __attribute__((__leaf__)) dysize)(int __year ) __attribute__((__nothrow__, __const__)) ; -#line 272 +#line 281 extern int nanosleep(struct timespec const *__requested_time , struct timespec *__remaining ) ; -#line 276 +#line 285 extern int ( __attribute__((__leaf__)) clock_getres)(clockid_t __clock_id , struct timespec *__res ) __attribute__((__nothrow__)) ; -#line 279 -extern int ( __attribute__((__leaf__)) clock_gettime)(clockid_t __clock_id , struct timespec *__tp ) __attribute__((__nothrow__)) ; -#line 282 -extern int ( __attribute__((__leaf__)) clock_settime)(clockid_t __clock_id , struct timespec const *__tp ) __attribute__((__nothrow__)) ; -#line 311 +#line 288 +extern int ( __attribute__((__nonnull__(2), __leaf__)) clock_gettime)(clockid_t __clock_id , + struct timespec *__tp ) __attribute__((__nothrow__)) ; +#line 292 +extern int ( __attribute__((__nonnull__(2), __leaf__)) clock_settime)(clockid_t __clock_id , + struct timespec const *__tp ) __attribute__((__nothrow__)) ; +#line 323 extern int clock_nanosleep(clockid_t __clock_id , int __flags , struct timespec const *__req , struct timespec *__rem ) ; -#line 326 +#line 338 extern int ( __attribute__((__leaf__)) clock_getcpuclockid)(pid_t __pid , clockid_t *__clock_id ) __attribute__((__nothrow__)) ; -#line 331 +#line 343 extern int ( __attribute__((__leaf__)) timer_create)(clockid_t __clock_id , struct sigevent * __restrict __evp , timer_t * __restrict __timerid ) __attribute__((__nothrow__)) ; -#line 336 +#line 348 extern int ( __attribute__((__leaf__)) timer_delete)(timer_t __timerid ) __attribute__((__nothrow__)) ; -#line 340 +#line 352 extern int ( __attribute__((__leaf__)) timer_settime)(timer_t __timerid , int __flags , struct itimerspec const * __restrict __value , struct itimerspec * __restrict __ovalue ) __attribute__((__nothrow__)) ; -#line 345 +#line 357 extern int ( __attribute__((__leaf__)) timer_gettime)(timer_t __timerid , struct itimerspec *__value ) __attribute__((__nothrow__)) ; -#line 364 +#line 376 extern int ( __attribute__((__leaf__)) timer_getoverrun)(timer_t __timerid ) __attribute__((__nothrow__)) ; -#line 371 +#line 383 extern int ( __attribute__((__nonnull__(1), __leaf__)) timespec_get)(struct timespec *__ts , int __base ) __attribute__((__nothrow__)) ; #line 202 "/usr/include/pthread.h" @@ -1827,9 +1829,8 @@ extern void __pthread_unregister_cancel(__pthread_unwind_buf_t *__buf ) ; #line 750 extern void __pthread_unwind_next(__pthread_unwind_buf_t *__buf ) __attribute__((__weak__, __noreturn__)) ; -#line 766 -extern int __sigsetjmp_cancel(struct __cancel_jmp_buf_tag *__env , int __savemask ) __asm__("__sigsetjmp") __attribute__((__returns_twice__, -__nothrow__)) ; +#line 773 +extern int __sigsetjmp(struct __jmp_buf_tag *__env , int __savemask ) __attribute__((__nothrow__)) ; #line 781 extern int ( __attribute__((__nonnull__(1), __leaf__)) pthread_mutex_init)(pthread_mutex_t *__mutex , pthread_mutexattr_t const *__mutexattr ) __attribute__((__nothrow__)) ; @@ -1994,8 +1995,7 @@ extern int ( __attribute__((__leaf__)) pthread_key_delete)(pthread_key_t __key ) extern void *( __attribute__((__leaf__)) pthread_getspecific)(pthread_key_t __key ) __attribute__((__nothrow__)) ; #line 1308 extern int ( __attribute__((__leaf__)) pthread_setspecific)(pthread_key_t __key , - void const *__pointer ) __attribute__((__nothrow__, -__access__(__none__,2))) ; + void const *__pointer ) __attribute__((__nothrow__)) ; #line 1315 extern int ( __attribute__((__nonnull__(2), __leaf__)) pthread_getcpuclockid)(pthread_t __thread_id , __clockid_t *__clock_id ) __attribute__((__nothrow__)) ; diff --git a/src/analyses/termination_new.ml b/src/analyses/termination_new.ml index 4926c23daa..e722b9a2b2 100644 --- a/src/analyses/termination_new.ml +++ b/src/analyses/termination_new.ml @@ -6,13 +6,13 @@ open TerminationPreprocessing exception PreProcessing of string - -(* contains all loop counter variables (varinfo) and maps them to their corresponding loop statement*) -let loop_counters: stmt VarToStmt.t ref = ref VarToStmt.empty +(** Contains all loop counter variables (varinfo) and maps them to their corresponding loop statement. *) +let loop_counters : stmt VarToStmt.t ref = ref VarToStmt.empty (** Contains the locations of the upjumping gotos *) let upjumping_gotos : location list ref = ref [] +(** Indicates the place in the code, right after a loop is exited. *) let loop_exit : varinfo ref = ref (makeVarinfo false "-error" Cil.intType) let is_loop_counter_var (x : varinfo) = @@ -25,10 +25,10 @@ let is_loop_exit_indicator (x : varinfo) = * upjumping goto was already reached. Returns true if no upjumping goto was * reached until now *) let currrently_no_upjumping_gotos (loc : location) = - List.for_all (function (l) -> (l >= loc)) upjumping_gotos.contents + List.for_all (function l -> l >= loc) upjumping_gotos.contents let no_upjumping_gotos () = - (List.length upjumping_gotos.contents) <= 0 + List.length upjumping_gotos.contents = 0 (** Checks whether a variable can be bounded *) let check_bounded ctx varinfo = @@ -45,6 +45,7 @@ struct include Analyses.StdV end +module Statements = Lattice.Flat (CilType.Stmt) (Printable.DefaultNames) (* TODO: Use Basetype.CilStmt instead? *) module Spec : Analyses.MCPSpec = struct @@ -54,7 +55,7 @@ struct let name () = "termination" - module D = MapDomain.MapBot (Basetype.Variables) (BoolDomain.MustBool) + module D = MapDomain.MapBot (Statements) (BoolDomain.MustBool) module C = D module V = FunContextV (* TODO *) @@ -69,12 +70,14 @@ struct match lval, rval with (Var x, NoOffset), _ when is_loop_counter_var x -> (* Assume that the following loop does not terminate *) - D.add x false ctx.local + let loop_statement = VarToStmt.find x !loop_counters in + D.add (`Lifted loop_statement) false ctx.local | (Var y, NoOffset), Lval (Var x, NoOffset) when is_loop_exit_indicator y -> (* Loop exit: Check whether loop counter variable is bounded *) (* TODO: Move *) let is_bounded = check_bounded ctx x in - D.add x is_bounded ctx.local + let loop_statement = VarToStmt.find x !loop_counters in + D.add (`Lifted loop_statement) is_bounded ctx.local | _ -> ctx.local let special ctx (lval : lval option) (f : varinfo) (arglist : exp list) = @@ -82,16 +85,16 @@ struct ctx.local (** Provides information to Goblint *) - (* TODO: Consider gotos and recursion *) + (* TODO: Consider gotos *) let query ctx (type a) (q: a Queries.t): a Queries.result = let open Queries in match q with - | Queries.MustTermLoop v -> - (match D.find_opt v ctx.local with + | Queries.MustTermLoop loop_statement -> + (match D.find_opt (`Lifted loop_statement) ctx.local with Some b -> b | None -> Result.top q) | Queries.MustTermProg -> - D.for_all (fun loop term_info -> term_info) ctx.local + D.for_all (fun _ term_info -> term_info) ctx.local | _ -> Result.top q end diff --git a/src/domains/queries.ml b/src/domains/queries.ml index 022e8e1dee..c5d7d729b6 100644 --- a/src/domains/queries.ml +++ b/src/domains/queries.ml @@ -117,7 +117,7 @@ type _ t = | MayAccessed: AccessDomain.EventSet.t t | MayBeTainted: LS.t t | MayBeModifiedSinceSetjmp: JmpBufDomain.BufferEntry.t -> VS.t t - | MustTermLoop: varinfo -> MustBool.t t (** TODO: not sure if it is the MayBool*) + | MustTermLoop: stmt -> MustBool.t t | MustTermProg: MustBool.t t type 'a result = 'a @@ -347,7 +347,7 @@ struct compare (Any q1) (Any q2) | Any (IsHeapVar v1), Any (IsHeapVar v2) -> CilType.Varinfo.compare v1 v2 | Any (IsMultiple v1), Any (IsMultiple v2) -> CilType.Varinfo.compare v1 v2 - | Any (MustTermLoop v1), Any (MustTermLoop v2) -> CilType.Varinfo.compare v1 v2 + | Any (MustTermLoop s1), Any (MustTermLoop s2) -> CilType.Stmt.compare s1 s2 | Any (EvalThread e1), Any (EvalThread e2) -> CilType.Exp.compare e1 e2 | Any (EvalJumpBuf e1), Any (EvalJumpBuf e2) -> CilType.Exp.compare e1 e2 | Any (WarnGlobal vi1), Any (WarnGlobal vi2) -> Stdlib.compare (Hashtbl.hash vi1) (Hashtbl.hash vi2) @@ -386,7 +386,7 @@ struct | Any (IterVars i) -> 0 | Any (PathQuery (i, q)) -> 31 * i + hash (Any q) | Any (IsHeapVar v) -> CilType.Varinfo.hash v - | Any (MustTermLoop v) -> CilType.Varinfo.hash v + | Any (MustTermLoop s) -> CilType.Stmt.hash s | Any (IsMultiple v) -> CilType.Varinfo.hash v | Any (EvalThread e) -> CilType.Exp.hash e | Any (EvalJumpBuf e) -> CilType.Exp.hash e @@ -454,7 +454,7 @@ struct | Any MayBeTainted -> Pretty.dprintf "MayBeTainted" | Any DYojson -> Pretty.dprintf "DYojson" | Any MayBeModifiedSinceSetjmp buf -> Pretty.dprintf "MayBeModifiedSinceSetjmp %a" JmpBufDomain.BufferEntry.pretty buf - | Any (MustTermLoop v) -> Pretty.dprintf "MustTermLoop %a" CilType.Varinfo.pretty v + | Any (MustTermLoop s) -> Pretty.dprintf "MustTermLoop %a" CilType.Stmt.pretty s | Any MustTermProg -> Pretty.dprintf "MustTermProg" end From 234ae2a6516cddb68f124a97b5ec7ccb43efd3db Mon Sep 17 00:00:00 2001 From: Simmo Saan Date: Fri, 16 Jun 2023 14:55:01 +0300 Subject: [PATCH 105/327] Fix typo and dead link in taint analysis tutorial --- src/analyses/tutorials/taint.ml | 2 +- tests/regression/99-tutorials/03-taint_simple.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/analyses/tutorials/taint.ml b/src/analyses/tutorials/taint.ml index 217125c8bd..3067449e31 100644 --- a/src/analyses/tutorials/taint.ml +++ b/src/analyses/tutorials/taint.ml @@ -1,8 +1,8 @@ (** Simple interprocedural taint analysis template ([taint]). *) (** An analysis specification for didactic purposes. *) -(* Helpful link on CIL: https://goblint.in.tum.de/assets/goblint-cil/ *) (* Goblint documentation: https://goblint.readthedocs.io/en/latest/ *) +(* Helpful link on CIL: https://goblint.github.io/cil/ *) (* You may test your analysis on our toy examples by running `ruby scripts/update_suite.rb group tutorials` *) (* after removing the `SKIP` from the beginning of the tests in tests/regression/99-tutorials/{03-taint_simple.c,04-taint_inter.c} *) diff --git a/tests/regression/99-tutorials/03-taint_simple.c b/tests/regression/99-tutorials/03-taint_simple.c index d9d00351c1..4cc206d949 100644 --- a/tests/regression/99-tutorials/03-taint_simple.c +++ b/tests/regression/99-tutorials/03-taint_simple.c @@ -31,7 +31,7 @@ int main(void) { // Trivial example showing how the analysis you just wrote benefits from other analyses - // If we wanted to write a real analysis, we would also aks other analyses questions, to e.g. handle pointers + // If we wanted to write a real analysis, we would also ask other analyses questions, to e.g. handle pointers int z; if(z == 0) { z = 5; From d0b9de95a9128a5e246de5492642422b61c69f9f Mon Sep 17 00:00:00 2001 From: Alexander Schlenga Date: Sun, 18 Jun 2023 12:39:01 +0200 Subject: [PATCH 106/327] Consider upjumping gotos in whole program query and a bit of change towards using a global invariant --- src/analyses/termination_new.ml | 28 ++++++++++++---------------- 1 file changed, 12 insertions(+), 16 deletions(-) diff --git a/src/analyses/termination_new.ml b/src/analyses/termination_new.ml index e722b9a2b2..d610a89fe9 100644 --- a/src/analyses/termination_new.ml +++ b/src/analyses/termination_new.ml @@ -21,12 +21,6 @@ let is_loop_counter_var (x : varinfo) = let is_loop_exit_indicator (x : varinfo) = x = !loop_exit -(** Checks whether at the current location (=loc) of the analysis an - * upjumping goto was already reached. Returns true if no upjumping goto was - * reached until now *) -let currrently_no_upjumping_gotos (loc : location) = - List.for_all (function l -> l >= loc) upjumping_gotos.contents - let no_upjumping_gotos () = List.length upjumping_gotos.contents = 0 @@ -39,14 +33,18 @@ let check_bounded ctx varinfo = | `Lifted v -> not (is_top_of (ikind v) v) | `Bot -> raise (PreProcessing "Loop variable is Bot") -module FunContextV : Analyses.SpecSysVar = +module UnitV : SpecSysVar = struct - include Printable.Prod (CilType.Fundec) (CilType.Fundec) (* TODO *) - include Analyses.StdV + include Printable.Unit + include StdV end +(** We want to record termination information of loops and use the loop + * statements for that. We use this lifting because we need to have a + * lattice. *) module Statements = Lattice.Flat (CilType.Stmt) (Printable.DefaultNames) (* TODO: Use Basetype.CilStmt instead? *) +(** The termination analysis considering loops and gotos *) module Spec : Analyses.MCPSpec = struct @@ -55,15 +53,13 @@ struct let name () = "termination" - module D = MapDomain.MapBot (Statements) (BoolDomain.MustBool) + module D = MapDomain.MapBot (Statements) (BoolDomain.MustBool) (* TODO *) module C = D - module V = FunContextV - (* TODO *) + module V = UnitV + module G = MapDomain.MapBot (Statements) (BoolDomain.MustBool) let startstate _ = D.bot () - let exitstate = startstate (* TODO *) - - let finalize () = () (* TODO *) + let exitstate = startstate let assign ctx (lval : lval) (rval : exp) = (* Detect assignment to loop counter variable *) @@ -85,7 +81,6 @@ struct ctx.local (** Provides information to Goblint *) - (* TODO: Consider gotos *) let query ctx (type a) (q: a Queries.t): a Queries.result = let open Queries in match q with @@ -95,6 +90,7 @@ struct | None -> Result.top q) | Queries.MustTermProg -> D.for_all (fun _ term_info -> term_info) ctx.local + && no_upjumping_gotos () | _ -> Result.top q end From 88432722ace33653378ae8989ff4903c71f563d4 Mon Sep 17 00:00:00 2001 From: Alexander Schlenga Date: Sun, 18 Jun 2023 18:11:11 +0200 Subject: [PATCH 107/327] WIP on using find_loop_heads and global invariant --- src/analyses/termination_new.ml | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/src/analyses/termination_new.ml b/src/analyses/termination_new.ml index d610a89fe9..5e56c74a05 100644 --- a/src/analyses/termination_new.ml +++ b/src/analyses/termination_new.ml @@ -6,6 +6,17 @@ open TerminationPreprocessing exception PreProcessing of string +(* + * TODO: Make this work +module FileCfg = +struct + let file = !Cilfacade.current_file + module Cfg = (val !MyCFG.current_cfg) +end + +let loop_heads = WitnessUtil.find_loop_heads FileCfg + *) + (** Contains all loop counter variables (varinfo) and maps them to their corresponding loop statement. *) let loop_counters : stmt VarToStmt.t ref = ref VarToStmt.empty @@ -67,6 +78,10 @@ struct (Var x, NoOffset), _ when is_loop_counter_var x -> (* Assume that the following loop does not terminate *) let loop_statement = VarToStmt.find x !loop_counters in + (* + * TODO: Make the below line work + let () = ctx.sideg (() : V.t) (G.add (`Lifted loop_statement) false ctx.local) in + *) D.add (`Lifted loop_statement) false ctx.local | (Var y, NoOffset), Lval (Var x, NoOffset) when is_loop_exit_indicator y -> (* Loop exit: Check whether loop counter variable is bounded *) From 49dcae5dfa79f11d03bb36748b6ebabf854254d9 Mon Sep 17 00:00:00 2001 From: Alexander Schlenga Date: Mon, 19 Jun 2023 13:04:28 +0200 Subject: [PATCH 108/327] Use global invariant instead of local state Still needs a bit of work. Currently, loops are only ever analyzed if their loop exit indicator is encountered. --- src/analyses/termination_new.ml | 44 ++++++++++++++++----------------- 1 file changed, 21 insertions(+), 23 deletions(-) diff --git a/src/analyses/termination_new.ml b/src/analyses/termination_new.ml index 5e56c74a05..f062030820 100644 --- a/src/analyses/termination_new.ml +++ b/src/analyses/termination_new.ml @@ -6,16 +6,14 @@ open TerminationPreprocessing exception PreProcessing of string -(* - * TODO: Make this work -module FileCfg = -struct - let file = !Cilfacade.current_file - module Cfg = (val !MyCFG.current_cfg) -end - -let loop_heads = WitnessUtil.find_loop_heads FileCfg - *) +let loop_heads = + let module FileCfg = + struct + let file = !Cilfacade.current_file + module Cfg = (val !MyCFG.current_cfg) + end in + let module WitnessInvariant = WitnessUtil.Invariant (FileCfg) in + WitnessInvariant.loop_heads (* TODO: Use this *) (** Contains all loop counter variables (varinfo) and maps them to their corresponding loop statement. *) let loop_counters : stmt VarToStmt.t ref = ref VarToStmt.empty @@ -44,7 +42,7 @@ let check_bounded ctx varinfo = | `Lifted v -> not (is_top_of (ikind v) v) | `Bot -> raise (PreProcessing "Loop variable is Bot") -module UnitV : SpecSysVar = +module UnitV = struct include Printable.Unit include StdV @@ -64,7 +62,7 @@ struct let name () = "termination" - module D = MapDomain.MapBot (Statements) (BoolDomain.MustBool) (* TODO *) + module D = Lattice.Unit module C = D module V = UnitV module G = MapDomain.MapBot (Statements) (BoolDomain.MustBool) @@ -75,20 +73,21 @@ struct let assign ctx (lval : lval) (rval : exp) = (* Detect assignment to loop counter variable *) match lval, rval with + (* (Var x, NoOffset), _ when is_loop_counter_var x -> (* Assume that the following loop does not terminate *) let loop_statement = VarToStmt.find x !loop_counters in - (* - * TODO: Make the below line work - let () = ctx.sideg (() : V.t) (G.add (`Lifted loop_statement) false ctx.local) in - *) + let () = ctx.sideg () (G.add (`Lifted loop_statement) false ctx.local) in + let () = print_endline ("Added FALSE for " ^ x.vname) in D.add (`Lifted loop_statement) false ctx.local - | (Var y, NoOffset), Lval (Var x, NoOffset) when is_loop_exit_indicator y -> + *) + (Var y, NoOffset), Lval (Var x, NoOffset) when is_loop_exit_indicator y -> (* Loop exit: Check whether loop counter variable is bounded *) (* TODO: Move *) let is_bounded = check_bounded ctx x in let loop_statement = VarToStmt.find x !loop_counters in - D.add (`Lifted loop_statement) is_bounded ctx.local + let () = ctx.sideg () (G.add (`Lifted loop_statement) is_bounded (ctx.global ())) in + ctx.local | _ -> ctx.local let special ctx (lval : lval option) (f : varinfo) (arglist : exp list) = @@ -97,16 +96,15 @@ struct (** Provides information to Goblint *) let query ctx (type a) (q: a Queries.t): a Queries.result = - let open Queries in match q with | Queries.MustTermLoop loop_statement -> - (match D.find_opt (`Lifted loop_statement) ctx.local with + (match G.find_opt (`Lifted loop_statement) (ctx.global ()) with Some b -> b - | None -> Result.top q) + | None -> false) | Queries.MustTermProg -> - D.for_all (fun _ term_info -> term_info) ctx.local + G.for_all (fun _ term_info -> term_info) (ctx.global ()) && no_upjumping_gotos () - | _ -> Result.top q + | _ -> Queries.Result.top q end From 8fc0c1beff17b61b57e4b26173a4eea49679b01d Mon Sep 17 00:00:00 2001 From: Johanna Schinabeck Date: Sat, 3 Jun 2023 13:29:17 +0200 Subject: [PATCH 109/327] first tests for recursion termination analysis, added empty functor and GMapG --- src/framework/analyses.ml | 53 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 53 insertions(+) diff --git a/src/framework/analyses.ml b/src/framework/analyses.ml index 1d1972ac45..7fd57b357e 100644 --- a/src/framework/analyses.ml +++ b/src/framework/analyses.ml @@ -119,6 +119,59 @@ struct | x -> BatPrintf.fprintf f "%a" printXml x end +module GMapG (G: Lattice.S) (C: Printable.S) = +struct + module CVal = + struct + include Printable.Std (* To make it Groupable *) + include SetDomain.Make ( + struct + include C + let printXml f c = BatPrintf.fprintf f "%a" printXml c (* wrap in for HTML printing *) + end + ) + let name () = "contextsMap" + end + + module RangeVal = + struct + include SetDomain.Make ( + struct + include C (*TODO: sollte hier iwi ein tupel sein*) + let printXml f c = BatPrintf.fprintf f "%a" printXml c (* wrap in for HTML printing *) + end + ) + let name () = "contextsMap" + end + + module CMap = + struct + include MapDomain.MapBot (CVal) (RangeVal) + let name () = "contextsMap" + end + include Lattice.Lift2 (G) (CMap) (Printable.DefaultNames) + + let is_bot () = false + let is_top () = false + + (*let spec = function + | `Bot -> G.bot () + | `Lifted1 x -> x + | _ -> failwith "GVarG.spec" + let contexts = function + | `Bot -> CSet.bot () + | `Lifted2 x -> x + | _ -> failwith "GVarG.contexts" + let create_spec spec = `Lifted1 spec + let create_contexts contexts = `Lifted2 contexts + + let printXml f = function + | `Lifted1 x -> G.printXml f x + | `Lifted2 x -> BatPrintf.fprintf f "%a" CSet.printXml x + | x -> BatPrintf.fprintf f "%a" printXml x +*) +end + module GMapG (G: Lattice.S) (C: Printable.S) = struct From 0efdc788435e4404e1f5883b6fc3f80fb8aebe1f Mon Sep 17 00:00:00 2001 From: Thomas Lagemann Date: Thu, 1 Jun 2023 05:01:09 +0200 Subject: [PATCH 110/327] Tests for loop termination --- .../80-termination/15-complex-loop-combination-terminating.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/regression/80-termination/15-complex-loop-combination-terminating.c b/tests/regression/80-termination/15-complex-loop-combination-terminating.c index e5383aed66..54f8cd97c8 100644 --- a/tests/regression/80-termination/15-complex-loop-combination-terminating.c +++ b/tests/regression/80-termination/15-complex-loop-combination-terminating.c @@ -130,7 +130,7 @@ int main() } } - // Loop with a label and goto statement + /* // Loop with a label and goto statement int w = 1; start: if (w <= 5) @@ -138,7 +138,7 @@ int main() printf("Loop with Label and Goto: %d\n", w); w++; goto start; // TERM - } + } */ return 0; } From 8e9d29e4e8cd34531ad0f3a01b1d8ce5a054ae00 Mon Sep 17 00:00:00 2001 From: Thomas Lagemann Date: Mon, 5 Jun 2023 16:04:58 +0200 Subject: [PATCH 111/327] Loop termination tests extended --- .../80-termination/09-complex-for-loop-terminating.c | 2 +- .../regression/80-termination/10-complex-loop-terminating.c | 2 +- .../15-complex-loop-combination-terminating.c | 6 +++--- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/tests/regression/80-termination/09-complex-for-loop-terminating.c b/tests/regression/80-termination/09-complex-for-loop-terminating.c index ed28fa9b43..508b31500c 100644 --- a/tests/regression/80-termination/09-complex-for-loop-terminating.c +++ b/tests/regression/80-termination/09-complex-for-loop-terminating.c @@ -1,4 +1,4 @@ -// PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra +// PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval #include int main() diff --git a/tests/regression/80-termination/10-complex-loop-terminating.c b/tests/regression/80-termination/10-complex-loop-terminating.c index 3a19f17bee..9d5cd4b928 100644 --- a/tests/regression/80-termination/10-complex-loop-terminating.c +++ b/tests/regression/80-termination/10-complex-loop-terminating.c @@ -1,4 +1,4 @@ -// PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra +// PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval #include int main() diff --git a/tests/regression/80-termination/15-complex-loop-combination-terminating.c b/tests/regression/80-termination/15-complex-loop-combination-terminating.c index 54f8cd97c8..1ea228ae55 100644 --- a/tests/regression/80-termination/15-complex-loop-combination-terminating.c +++ b/tests/regression/80-termination/15-complex-loop-combination-terminating.c @@ -1,4 +1,4 @@ -// PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra +// PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval #include int main() @@ -130,7 +130,7 @@ int main() } } - /* // Loop with a label and goto statement + // Loop with a label and goto statement int w = 1; start: if (w <= 5) @@ -138,7 +138,7 @@ int main() printf("Loop with Label and Goto: %d\n", w); w++; goto start; // TERM - } */ + } return 0; } From 8a47aa678be4ce6d66c0aa159b0878b5b6b77fef Mon Sep 17 00:00:00 2001 From: Thomas Lagemann Date: Mon, 19 Jun 2023 13:34:23 +0200 Subject: [PATCH 112/327] Goto test cases --- .../24-upjumping-goto-loopless-terminating.c | 18 +++++++++++++ .../25-leave-loop-goto-terminating.c | 24 +++++++++++++++++ .../26-enter-loop-goto-terminating.c | 27 +++++++++++++++++++ .../27-upjumping-goto-nonterminating.c | 19 +++++++++++++ 4 files changed, 88 insertions(+) create mode 100644 tests/regression/80-termination/24-upjumping-goto-loopless-terminating.c create mode 100644 tests/regression/80-termination/25-leave-loop-goto-terminating.c create mode 100644 tests/regression/80-termination/26-enter-loop-goto-terminating.c create mode 100644 tests/regression/80-termination/27-upjumping-goto-nonterminating.c diff --git a/tests/regression/80-termination/24-upjumping-goto-loopless-terminating.c b/tests/regression/80-termination/24-upjumping-goto-loopless-terminating.c new file mode 100644 index 0000000000..aea0d5dd97 --- /dev/null +++ b/tests/regression/80-termination/24-upjumping-goto-loopless-terminating.c @@ -0,0 +1,18 @@ +#include + +int main() { + goto mark2; + +mark1: + printf("This is mark1\n"); + goto mark3; + +mark2: + printf("This is mark2\n"); + goto mark1; + +mark3: + printf("This is mark3\n"); + + return 0; +} diff --git a/tests/regression/80-termination/25-leave-loop-goto-terminating.c b/tests/regression/80-termination/25-leave-loop-goto-terminating.c new file mode 100644 index 0000000000..34c14eedd6 --- /dev/null +++ b/tests/regression/80-termination/25-leave-loop-goto-terminating.c @@ -0,0 +1,24 @@ +#include + +int main() { + int counter = 0; + + while (1) { + counter++; + + // Dummy code + printf("Iteration %d\n", counter); + int result = counter * 2; + printf("Result: %d\n", result); + + // Condition to terminate the loop + if (result >= 10) { + goto end; + } + } + +end: + printf("Loop exited. Result is greater than or equal to 10.\n"); + + return 0; +} diff --git a/tests/regression/80-termination/26-enter-loop-goto-terminating.c b/tests/regression/80-termination/26-enter-loop-goto-terminating.c new file mode 100644 index 0000000000..d3158ae7f7 --- /dev/null +++ b/tests/regression/80-termination/26-enter-loop-goto-terminating.c @@ -0,0 +1,27 @@ +#include + +int main() { + int counter = 0; + + goto jump_point; + + while (1) { + counter++; + + // Dummy code + printf("Iteration %d\n", counter); + int result = counter * 2; + jump_point: + printf("Result: %d\n", result); + + // Condition to terminate the loop + if (result >= 10) { + goto end; + } + } + +end: + printf("Loop exited. Result is greater than or equal to 10.\n"); + + return 0; +} diff --git a/tests/regression/80-termination/27-upjumping-goto-nonterminating.c b/tests/regression/80-termination/27-upjumping-goto-nonterminating.c new file mode 100644 index 0000000000..b6dc238fe3 --- /dev/null +++ b/tests/regression/80-termination/27-upjumping-goto-nonterminating.c @@ -0,0 +1,19 @@ +#include + +int main() { + goto mark2; + +mark1: + printf("This is mark1\n"); + goto mark3; + +mark2: + printf("This is mark2\n"); + goto mark1; + +mark3: + printf("This is mark3\n"); + goto mark1; + + return 0; +} From bb5ab19e5f1417aae2739ef85ca36c1c54890a84 Mon Sep 17 00:00:00 2001 From: Thomas Lagemann Date: Mon, 19 Jun 2023 13:40:37 +0200 Subject: [PATCH 113/327] Added recursion tests --- .../81-recursion/01-simple-terminating.c | 21 +++++++++++ .../81-recursion/02-simple-nonterminating.c | 21 +++++++++++ .../81-recursion/03-nested-terminating.c | 35 +++++++++++++++++++ .../81-recursion/04-nested-nonterminating.c | 25 +++++++++++++ 4 files changed, 102 insertions(+) create mode 100644 tests/regression/81-recursion/01-simple-terminating.c create mode 100644 tests/regression/81-recursion/02-simple-nonterminating.c create mode 100644 tests/regression/81-recursion/03-nested-terminating.c create mode 100644 tests/regression/81-recursion/04-nested-nonterminating.c diff --git a/tests/regression/81-recursion/01-simple-terminating.c b/tests/regression/81-recursion/01-simple-terminating.c new file mode 100644 index 0000000000..9e509ebaa9 --- /dev/null +++ b/tests/regression/81-recursion/01-simple-terminating.c @@ -0,0 +1,21 @@ +#include + +void recursiveFunction(int n) { + // Base case: When n reaches 0, stop recursion + if (n == 0) { + printf("Terminating recursion\n"); + return; + } + + printf("Recursive call with n = %d\n", n); + + // Recursive call: Decrement n and call the function again + recursiveFunction(n - 1); +} + +int main() { + // Call the recursive function with an initial value + recursiveFunction(5); + + return 0; +} diff --git a/tests/regression/81-recursion/02-simple-nonterminating.c b/tests/regression/81-recursion/02-simple-nonterminating.c new file mode 100644 index 0000000000..ec9d31ffcb --- /dev/null +++ b/tests/regression/81-recursion/02-simple-nonterminating.c @@ -0,0 +1,21 @@ +#include + +void recursiveFunction(int n) { + // Base case: When n reaches 0, stop recursion + if (n == 30) { + printf("Terminating recursion\n"); + return; + } + + printf("Recursive call with n = %d\n", n); + + // Recursive call: Decrement n and call the function again + recursiveFunction(n - 1); +} + +int main() { + // Call the recursive function with an initial value + recursiveFunction(5); + + return 0; +} diff --git a/tests/regression/81-recursion/03-nested-terminating.c b/tests/regression/81-recursion/03-nested-terminating.c new file mode 100644 index 0000000000..6cd28043ee --- /dev/null +++ b/tests/regression/81-recursion/03-nested-terminating.c @@ -0,0 +1,35 @@ +#include + +void innerRecursiveFunction(int n) { + if (n == 0) { + printf("Terminating inner recursion\n"); + return; + } + + printf("Inner recursive call with n = %d\n", n); + + // Recursive call to the innerRecursiveFunction + innerRecursiveFunction(n - 1); +} + +void outerRecursiveFunction(int n) { + if (n == 0) { + printf("Terminating outer recursion\n"); + return; + } + + printf("Outer recursive call with n = %d\n", n); + + // Recursive call to the outerRecursiveFunction + outerRecursiveFunction(n - 1); + + // Call to the innerRecursiveFunction + innerRecursiveFunction(n); +} + +int main() { + // Call the outerRecursiveFunction with an initial value + outerRecursiveFunction(3); + + return 0; +} diff --git a/tests/regression/81-recursion/04-nested-nonterminating.c b/tests/regression/81-recursion/04-nested-nonterminating.c new file mode 100644 index 0000000000..96911687da --- /dev/null +++ b/tests/regression/81-recursion/04-nested-nonterminating.c @@ -0,0 +1,25 @@ +#include + +void innerRecursiveFunction() { + printf("Nested recursive call\n"); + + // Recursive call to the innerRecursiveFunction + innerRecursiveFunction(); +} + +void outerRecursiveFunction() { + printf("Outer recursive call\n"); + + // Recursive call to the outerRecursiveFunction + outerRecursiveFunction(); + + // Call to the innerRecursiveFunction + innerRecursiveFunction(); +} + +int main() { + // Call the outerRecursiveFunction + outerRecursiveFunction(); + + return 0; +} From c2e08ef4724659bb05baeefdc3f18d9fe0d968b2 Mon Sep 17 00:00:00 2001 From: Thomas Lagemann Date: Mon, 19 Jun 2023 14:16:33 +0200 Subject: [PATCH 114/327] 80/23 fixed --- .../80-termination/23-exit-on-rand-terminating.c | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/tests/regression/80-termination/23-exit-on-rand-terminating.c b/tests/regression/80-termination/23-exit-on-rand-terminating.c index f793275b1f..c8118a4bde 100644 --- a/tests/regression/80-termination/23-exit-on-rand-terminating.c +++ b/tests/regression/80-termination/23-exit-on-rand-terminating.c @@ -1,16 +1,18 @@ // PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra #include +#include int main() { - int shortrun, i = 0; + int short_run, i = 0; - while (i < 90 || shortrun == 1) + while (i < 90 && short_run != 1) { i++; if (rand()) { - shortrun = 1; + short_run = 1; } + printf("%i %i\n", i, short_run); } } \ No newline at end of file From 4ec1e9862fddea279e4a23a328bf9481ef1c4552 Mon Sep 17 00:00:00 2001 From: Thomas Lagemann Date: Mon, 19 Jun 2023 14:16:58 +0200 Subject: [PATCH 115/327] removed print --- tests/regression/80-termination/23-exit-on-rand-terminating.c | 1 - 1 file changed, 1 deletion(-) diff --git a/tests/regression/80-termination/23-exit-on-rand-terminating.c b/tests/regression/80-termination/23-exit-on-rand-terminating.c index c8118a4bde..228fc3b15e 100644 --- a/tests/regression/80-termination/23-exit-on-rand-terminating.c +++ b/tests/regression/80-termination/23-exit-on-rand-terminating.c @@ -13,6 +13,5 @@ int main() { short_run = 1; } - printf("%i %i\n", i, short_run); } } \ No newline at end of file From 9bba9a1061b6ec1504b247cf26d866d91f5dfc8f Mon Sep 17 00:00:00 2001 From: Thomas Lagemann Date: Mon, 19 Jun 2023 14:24:56 +0200 Subject: [PATCH 116/327] Param unified --- .../regression/80-termination/09-complex-for-loop-terminating.c | 2 +- tests/regression/80-termination/10-complex-loop-terminating.c | 2 +- .../80-termination/15-complex-loop-combination-terminating.c | 2 +- .../80-termination/24-upjumping-goto-loopless-terminating.c | 1 + .../regression/80-termination/25-leave-loop-goto-terminating.c | 1 + .../regression/80-termination/26-enter-loop-goto-terminating.c | 1 + .../80-termination/27-upjumping-goto-nonterminating.c | 1 + tests/regression/81-recursion/01-simple-terminating.c | 1 + tests/regression/81-recursion/02-simple-nonterminating.c | 1 + tests/regression/81-recursion/03-nested-terminating.c | 1 + tests/regression/81-recursion/04-nested-nonterminating.c | 1 + 11 files changed, 11 insertions(+), 3 deletions(-) diff --git a/tests/regression/80-termination/09-complex-for-loop-terminating.c b/tests/regression/80-termination/09-complex-for-loop-terminating.c index 508b31500c..ed28fa9b43 100644 --- a/tests/regression/80-termination/09-complex-for-loop-terminating.c +++ b/tests/regression/80-termination/09-complex-for-loop-terminating.c @@ -1,4 +1,4 @@ -// PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval +// PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra #include int main() diff --git a/tests/regression/80-termination/10-complex-loop-terminating.c b/tests/regression/80-termination/10-complex-loop-terminating.c index 9d5cd4b928..3a19f17bee 100644 --- a/tests/regression/80-termination/10-complex-loop-terminating.c +++ b/tests/regression/80-termination/10-complex-loop-terminating.c @@ -1,4 +1,4 @@ -// PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval +// PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra #include int main() diff --git a/tests/regression/80-termination/15-complex-loop-combination-terminating.c b/tests/regression/80-termination/15-complex-loop-combination-terminating.c index 1ea228ae55..e5383aed66 100644 --- a/tests/regression/80-termination/15-complex-loop-combination-terminating.c +++ b/tests/regression/80-termination/15-complex-loop-combination-terminating.c @@ -1,4 +1,4 @@ -// PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval +// PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra #include int main() diff --git a/tests/regression/80-termination/24-upjumping-goto-loopless-terminating.c b/tests/regression/80-termination/24-upjumping-goto-loopless-terminating.c index aea0d5dd97..f4b6b8fbe2 100644 --- a/tests/regression/80-termination/24-upjumping-goto-loopless-terminating.c +++ b/tests/regression/80-termination/24-upjumping-goto-loopless-terminating.c @@ -1,3 +1,4 @@ +// PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra #include int main() { diff --git a/tests/regression/80-termination/25-leave-loop-goto-terminating.c b/tests/regression/80-termination/25-leave-loop-goto-terminating.c index 34c14eedd6..c30e65f44b 100644 --- a/tests/regression/80-termination/25-leave-loop-goto-terminating.c +++ b/tests/regression/80-termination/25-leave-loop-goto-terminating.c @@ -1,3 +1,4 @@ +// PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra #include int main() { diff --git a/tests/regression/80-termination/26-enter-loop-goto-terminating.c b/tests/regression/80-termination/26-enter-loop-goto-terminating.c index d3158ae7f7..5d34e5c523 100644 --- a/tests/regression/80-termination/26-enter-loop-goto-terminating.c +++ b/tests/regression/80-termination/26-enter-loop-goto-terminating.c @@ -1,3 +1,4 @@ +// PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra #include int main() { diff --git a/tests/regression/80-termination/27-upjumping-goto-nonterminating.c b/tests/regression/80-termination/27-upjumping-goto-nonterminating.c index b6dc238fe3..6e4432dc5e 100644 --- a/tests/regression/80-termination/27-upjumping-goto-nonterminating.c +++ b/tests/regression/80-termination/27-upjumping-goto-nonterminating.c @@ -1,3 +1,4 @@ +// PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra #include int main() { diff --git a/tests/regression/81-recursion/01-simple-terminating.c b/tests/regression/81-recursion/01-simple-terminating.c index 9e509ebaa9..1c52faec68 100644 --- a/tests/regression/81-recursion/01-simple-terminating.c +++ b/tests/regression/81-recursion/01-simple-terminating.c @@ -1,3 +1,4 @@ +// PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra #include void recursiveFunction(int n) { diff --git a/tests/regression/81-recursion/02-simple-nonterminating.c b/tests/regression/81-recursion/02-simple-nonterminating.c index ec9d31ffcb..a6d6b3ab17 100644 --- a/tests/regression/81-recursion/02-simple-nonterminating.c +++ b/tests/regression/81-recursion/02-simple-nonterminating.c @@ -1,3 +1,4 @@ +// PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra #include void recursiveFunction(int n) { diff --git a/tests/regression/81-recursion/03-nested-terminating.c b/tests/regression/81-recursion/03-nested-terminating.c index 6cd28043ee..096a1b0121 100644 --- a/tests/regression/81-recursion/03-nested-terminating.c +++ b/tests/regression/81-recursion/03-nested-terminating.c @@ -1,3 +1,4 @@ +// PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra #include void innerRecursiveFunction(int n) { diff --git a/tests/regression/81-recursion/04-nested-nonterminating.c b/tests/regression/81-recursion/04-nested-nonterminating.c index 96911687da..ab5e35d80f 100644 --- a/tests/regression/81-recursion/04-nested-nonterminating.c +++ b/tests/regression/81-recursion/04-nested-nonterminating.c @@ -1,3 +1,4 @@ +// PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra #include void innerRecursiveFunction() { From 0c41ac6ef089ac5c486687a29bb1eb6a3b42cc4e Mon Sep 17 00:00:00 2001 From: Thomas Lagemann Date: Mon, 19 Jun 2023 16:12:48 +0200 Subject: [PATCH 117/327] Fix from master --- src/framework/analyses.ml | 53 --------------------------------------- 1 file changed, 53 deletions(-) diff --git a/src/framework/analyses.ml b/src/framework/analyses.ml index 7fd57b357e..1d1972ac45 100644 --- a/src/framework/analyses.ml +++ b/src/framework/analyses.ml @@ -119,59 +119,6 @@ struct | x -> BatPrintf.fprintf f "%a" printXml x end -module GMapG (G: Lattice.S) (C: Printable.S) = -struct - module CVal = - struct - include Printable.Std (* To make it Groupable *) - include SetDomain.Make ( - struct - include C - let printXml f c = BatPrintf.fprintf f "%a" printXml c (* wrap in for HTML printing *) - end - ) - let name () = "contextsMap" - end - - module RangeVal = - struct - include SetDomain.Make ( - struct - include C (*TODO: sollte hier iwi ein tupel sein*) - let printXml f c = BatPrintf.fprintf f "%a" printXml c (* wrap in for HTML printing *) - end - ) - let name () = "contextsMap" - end - - module CMap = - struct - include MapDomain.MapBot (CVal) (RangeVal) - let name () = "contextsMap" - end - include Lattice.Lift2 (G) (CMap) (Printable.DefaultNames) - - let is_bot () = false - let is_top () = false - - (*let spec = function - | `Bot -> G.bot () - | `Lifted1 x -> x - | _ -> failwith "GVarG.spec" - let contexts = function - | `Bot -> CSet.bot () - | `Lifted2 x -> x - | _ -> failwith "GVarG.contexts" - let create_spec spec = `Lifted1 spec - let create_contexts contexts = `Lifted2 contexts - - let printXml f = function - | `Lifted1 x -> G.printXml f x - | `Lifted2 x -> BatPrintf.fprintf f "%a" CSet.printXml x - | x -> BatPrintf.fprintf f "%a" printXml x -*) -end - module GMapG (G: Lattice.S) (C: Printable.S) = struct From c2ababd0d10671e3c59ec46a361733b2d6ed6c89 Mon Sep 17 00:00:00 2001 From: Johanna Schinabeck Date: Mon, 19 Jun 2023 17:08:34 +0200 Subject: [PATCH 118/327] added new massage category --- src/framework/constraints.ml | 4 ++-- src/util/options.schema.json | 6 ++++++ 2 files changed, 8 insertions(+), 2 deletions(-) diff --git a/src/framework/constraints.ml b/src/framework/constraints.ml index 1e2644e394..a46abccb49 100644 --- a/src/framework/constraints.ml +++ b/src/framework/constraints.ml @@ -1739,7 +1739,7 @@ struct [ (Pretty.dprintf "The program might not terminate! (Fundec %a is contained in a call graph cycle)\n" CilType.Fundec.pretty fundec_e, Some (M.Location.CilLocation locUnknown)); ] in - M.msg_group Warning "Recursion cycle" msgs) + M.msg_group Warning ~category:NonTerminating "Recursion cycle" msgs) else if not (LH.mem global_visited_calls call) then begin try LH.replace global_visited_calls call (); @@ -1773,7 +1773,7 @@ struct [ (Pretty.dprintf "The program might not terminate! (Loop analysis)\n", Some (M.Location.CilLocation locUnknown)); ] in - M.msg_group Warning "Possibly non terminating loops" msgs); + M.msg_group Warning ~category:NonTerminating "Possibly non terminating loops" msgs); printf "true" diff --git a/src/util/options.schema.json b/src/util/options.schema.json index 02fc929a8a..d49b30aca7 100644 --- a/src/util/options.schema.json +++ b/src/util/options.schema.json @@ -2078,6 +2078,12 @@ "type": "boolean", "default": true }, + "nonTerminating": { + "title": "warn.nonTerminating", + "description": "nonTerminating warning", + "type": "boolean", + "default": true + }, "unknown": { "title": "warn.unknown", "description": "Unknown (of string) warnings", From 49c3a75751564fb78ce5dda18fc792928b3ace45 Mon Sep 17 00:00:00 2001 From: Johanna Schinabeck Date: Mon, 19 Jun 2023 17:44:21 +0200 Subject: [PATCH 119/327] deleted queries, comments and todos refreshed :), fixed indentation (hopefully) --- src/domains/queries.ml | 5 --- src/framework/analyses.ml | 76 ++++-------------------------------- src/framework/constraints.ml | 28 ++++++------- 3 files changed, 19 insertions(+), 90 deletions(-) diff --git a/src/domains/queries.ml b/src/domains/queries.ml index 6603175f36..c5d7d729b6 100644 --- a/src/domains/queries.ml +++ b/src/domains/queries.ml @@ -119,7 +119,6 @@ type _ t = | MayBeModifiedSinceSetjmp: JmpBufDomain.BufferEntry.t -> VS.t t | MustTermLoop: stmt -> MustBool.t t | MustTermProg: MustBool.t t - | MustTermProgWithRec: MustBool.t t type 'a result = 'a @@ -186,7 +185,6 @@ struct | MayBeModifiedSinceSetjmp _ -> (module VS) | MustTermLoop _ -> (module MustBool) | MustTermProg -> (module MustBool) - | MustTermProgWithRec -> (module MustBool) (** Get bottom result for query. *) let bot (type a) (q: a t): a result = @@ -252,7 +250,6 @@ struct | MayBeModifiedSinceSetjmp _ -> VS.top () | MustTermLoop _ -> MustBool.top () | MustTermProg -> MustBool.top () - | MustTermProgWithRec -> MustBool.top () end (* The type any_query can't be directly defined in Any as t, @@ -315,7 +312,6 @@ struct | Any ThreadsJoinedCleanly -> 52 | Any (MustTermLoop _) -> 53 | Any MustTermProg -> 54 - | Any MustTermProgWithRec -> 55 let rec compare a b = let r = Stdlib.compare (order a) (order b) in @@ -460,7 +456,6 @@ struct | Any MayBeModifiedSinceSetjmp buf -> Pretty.dprintf "MayBeModifiedSinceSetjmp %a" JmpBufDomain.BufferEntry.pretty buf | Any (MustTermLoop s) -> Pretty.dprintf "MustTermLoop %a" CilType.Stmt.pretty s | Any MustTermProg -> Pretty.dprintf "MustTermProg" - | Any MustTermProgWithRec -> Pretty.dprintf "MustTermProgWithRec" end let to_value_domain_ask (ask: ask) = diff --git a/src/framework/analyses.ml b/src/framework/analyses.ml index 763ffd0e56..e11903ba06 100644 --- a/src/framework/analyses.ml +++ b/src/framework/analyses.ml @@ -121,7 +121,7 @@ end (* Tuple of fundec and S.C*) -module T (Base1: Printable.S) (Base2: Printable.S) = (*Todo: is this Printable.S or S.C*) +module T (Base1: Printable.S) (Base2: Printable.S) = struct include Printable.Std type t = (Base1.t * Base2.t) @@ -140,13 +140,6 @@ struct caller_context\n%a\n\n \n" Base1.printXml a Base2.printXml b - (*Result of compare: - start with inital value of 0 - - a1 > a2: +1 - - a1 < a2: -1 - - b1 > b2: +3 - - b1 < b2: -3 - *) let compare (a1,b1) (a2,b2) = (*Todo: is this ok?*) if equal (a1, b1) (a2, b2) then 0 else( let res = ref 0 in @@ -157,6 +150,7 @@ struct if (comp_b > 0) then res := !(res) + 3 else if (comp_b < 0) then res := !(res) - 3; !res) + let pretty () x = text (show x) @@ -164,7 +158,7 @@ struct end -module GVarGG (G: Lattice.S) (C: Printable.S) (Base: Printable.S) = +module GVarGSet (G: Lattice.S) (C: Printable.S) (Base: Printable.S) = struct module CSet = @@ -186,10 +180,10 @@ struct struct include C include Printable.Std (* To make it Groupable *) - let printXml f c = BatPrintf.fprintf f (*Todo: Make this print pretty*) + let printXml f c = BatPrintf.fprintf f "\n callee_context\n%a\n\n - " printXml c (* wrap in for HTML printing *) + " printXml c end module CMap = @@ -198,7 +192,7 @@ struct let printXml f c = BatPrintf.fprintf f " ContextTupleMap\n %a\n\n - " printXml c (*TODO*) + " printXml c end include Lattice.Lift2 (G) (CMap) (Printable.DefaultNames) @@ -219,12 +213,12 @@ struct | `Lifted2 x -> BatPrintf.fprintf f "%a" CMap.printXml x | x -> BatPrintf.fprintf f "%a" printXml x - let s = function (*TODO: does this work? copied from DeadBranch*) + let s = function | `Bot -> G.bot () | `Lifted1 x -> x | _ -> failwith "RecursionTerm.s" - let create_s s = `Lifted1 s (*TODO: does this work? copied from DeadBranch*) + let create_s s = `Lifted1 s let base2 instance = match instance with @@ -232,60 +226,6 @@ struct | _ -> None end - -module GMapG (G: Lattice.S) (C: Printable.S) = -struct - module CVal = - struct - include Printable.Std (* To make it Groupable *) - include SetDomain.Make ( - struct - include C - let printXml f c = BatPrintf.fprintf f "%a" printXml c (* wrap in for HTML printing *) - end - ) - let name () = "contextsMap" - end - - module RangeVal = - struct - include SetDomain.Make ( - struct - include C (*TODO: sollte hier iwi ein tupel sein*) - let printXml f c = BatPrintf.fprintf f "%a" printXml c (* wrap in for HTML printing *) - end - ) - let name () = "contextsMap" - end - - module CMap = - struct - include MapDomain.MapBot (CVal) (RangeVal) - let name () = "contextsMap" - end - include Lattice.Lift2 (G) (CMap) (Printable.DefaultNames) - - let is_bot () = false - let is_top () = false - - (*let spec = function - | `Bot -> G.bot () - | `Lifted1 x -> x - | _ -> failwith "GVarG.spec" - let contexts = function - | `Bot -> CSet.bot () - | `Lifted2 x -> x - | _ -> failwith "GVarG.contexts" - let create_spec spec = `Lifted1 spec - let create_contexts contexts = `Lifted2 contexts - - let printXml f = function - | `Lifted1 x -> G.printXml f x - | `Lifted2 x -> BatPrintf.fprintf f "%a" CSet.printXml x - | x -> BatPrintf.fprintf f "%a" printXml x -*) -end - exception Deadcode (** [Dom (D)] produces D lifted where bottom means dead-code *) diff --git a/src/framework/constraints.ml b/src/framework/constraints.ml index a46abccb49..730f0f41eb 100644 --- a/src/framework/constraints.ml +++ b/src/framework/constraints.ml @@ -1712,11 +1712,10 @@ struct include GVarF(S.V) end - module G = GVarGG (S.G) (S.C) (T (CilType.Fundec) (S.C)) + module G = GVarGSet (S.G) (S.C) (T (CilType.Fundec) (S.C)) let name () = "RecursionTerm (" ^ S.name () ^ ")" - (*TODO Change the body??*) let conv (ctx: (_, G.t, _, V.t) ctx): (_, S.G.t, _, S.V.t) ctx = { ctx with global = (fun v -> G.s (ctx.global (V.spec v))); @@ -1726,7 +1725,7 @@ struct let cycleDetection ctx v v' = let module LH = Hashtbl.Make (T (CilType.Fundec) (S.C)) in let module LS = Set.Make (T (CilType.Fundec) (S.C)) in - (* TODO: find all cycles/SCCs *) + (* find all cycles/SCCs *) let global_visited_calls = LH.create 100 in (* DFS *) @@ -1748,7 +1747,7 @@ struct let fundec_e_typeV: V.t = V.relift (`Right fundec_e) in let gmap_opt = G.base2 (ctx.global (fundec_e_typeV)) in let gmap = Option.get (gmap_opt) in (*might be empty*) - let callers: G.CSet.t = G.CMap.find (context_e) gmap in (*TODO: how do we get our Map out of g*) (*Todo: the context should be the domain of the map*) + let callers: G.CSet.t = G.CMap.find (context_e) gmap in G.CSet.iter (fun to_call -> iter_call new_path_visited_calls to_call ) callers; @@ -1756,14 +1755,13 @@ struct end in try - let gmap_opt = G.base2 (ctx.global (v)) in - let gmap = Option.get (gmap_opt) in - (*let c = Option.get(G.CMap.PMap.keys gmap) in *)(*Todo: the context should be the domain of the map*) - G.CMap.iter(fun key value -> - let call = (v', key) in - iter_call LS.empty call - ) gmap (* try all fundec + context pairs that are in the map *) - with Invalid_argument _ -> () + let gmap_opt = G.base2 (ctx.global (v)) in + let gmap = Option.get (gmap_opt) in + G.CMap.iter(fun key value -> + let call = (v', key) in + iter_call LS.empty call + ) gmap (* try all fundec + context pairs that are in the map *) + with Invalid_argument _ -> () let checkTerminating ctx v v' = (*Check if the loops terminated*) @@ -1773,11 +1771,8 @@ struct [ (Pretty.dprintf "The program might not terminate! (Loop analysis)\n", Some (M.Location.CilLocation locUnknown)); ] in - M.msg_group Warning ~category:NonTerminating "Possibly non terminating loops" msgs); - printf "true" + M.msg_group Warning ~category:NonTerminating "Possibly non terminating loops" msgs) - - (*TODO: We may need to add new queries here*) let query ctx (type a) (q: a Queries.t): a Queries.result = match q with | WarnGlobal v -> @@ -1795,7 +1790,6 @@ struct | `Right v -> Queries.Result.top q end - | MustTermProgWithRec -> false (*TODO*) | _ -> S.query (conv ctx) q let branch ctx = S.branch (conv ctx) From 3c9da8d3f7952b67882c0191b022aafde52ef9b8 Mon Sep 17 00:00:00 2001 From: Isidor Zweckstetter Date: Mon, 19 Jun 2023 17:55:21 +0200 Subject: [PATCH 120/327] position of special function changed from after the loop to right after the loopHead --- src/util/terminationPreprocessing.ml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/util/terminationPreprocessing.ml b/src/util/terminationPreprocessing.ml index 409aa2c2c4..3453aa7110 100644 --- a/src/util/terminationPreprocessing.ml +++ b/src/util/terminationPreprocessing.ml @@ -33,13 +33,13 @@ class loopCounterVisitor lc lg le (fd : fundec) = object(self) let v = (Cil.makeLocalVar fd name typ) in (*Not tested for incremental mode*) let init_stmt = mkStmtOneInstr @@ Set (var v, zero, loc, eloc) in let inc_stmt = mkStmtOneInstr @@ Set (var v, increm (Lval (var v)) 1, loc, eloc) in - let exit_stmt = mkStmtOneInstr @@ Set ((var !le), (Lval (var v)), loc, eloc) in + let check_stmt = mkStmtOneInstr @@ Set ((var !le), (Lval (var v)), loc, eloc) in (match b.bstmts with | cont :: cond :: ss -> - b.bstmts <- cont :: inc_stmt :: cond :: ss; (*cont :: cond :: inc_stmt :: ss = it is also possible, but for loops with cond at the end, inc is also at the end*) + b.bstmts <- cont :: inc_stmt :: check_stmt :: cond :: ss; (*cont :: cond :: inc_stmt :: ss = it is also possible, but for loops with cond at the end, inc is also at the end*) | _ -> ()); lc := VarToStmt.add (v: varinfo) (s: stmt) !lc; - let nb = mkBlock [init_stmt; mkStmt s.skind; exit_stmt] in + let nb = mkBlock [init_stmt; mkStmt s.skind] in s.skind <- Block nb; s | Goto (sref, l) -> From 400c8102b9da2c890058a7b47a81afdf9939870c Mon Sep 17 00:00:00 2001 From: Johanna Schinabeck Date: Mon, 19 Jun 2023 17:57:35 +0200 Subject: [PATCH 121/327] indentation --- src/framework/analyses.ml | 9 ++------- src/framework/constraints.ml | 23 ++++++++--------------- 2 files changed, 10 insertions(+), 22 deletions(-) diff --git a/src/framework/analyses.ml b/src/framework/analyses.ml index e11903ba06..36b80567aa 100644 --- a/src/framework/analyses.ml +++ b/src/framework/analyses.ml @@ -42,7 +42,6 @@ struct let var_id = Node.show_id end - module VarF (LD: Printable.S) = struct type t = Node.t * LD.t [@@deriving eq, ord, hash] @@ -119,7 +118,6 @@ struct | x -> BatPrintf.fprintf f "%a" printXml x end - (* Tuple of fundec and S.C*) module T (Base1: Printable.S) (Base2: Printable.S) = struct @@ -149,17 +147,14 @@ struct else if (comp_a < 0) then res := !(res) - 1; if (comp_b > 0) then res := !(res) + 3 else if (comp_b < 0) then res := !(res) - 3; - !res) - + !res) let pretty () x = text (show x) - let hash (a,b) = Hashtbl.hash (Base1.hash a * Base2.hash b) (*Todo: is this ok?*) - + let hash (a,b) = Hashtbl.hash (Base1.hash a * Base2.hash b) (*Todo: is this ok?*) end module GVarGSet (G: Lattice.S) (C: Printable.S) (Base: Printable.S) = - struct module CSet = struct diff --git a/src/framework/constraints.ml b/src/framework/constraints.ml index 730f0f41eb..9508aa28a2 100644 --- a/src/framework/constraints.ml +++ b/src/framework/constraints.ml @@ -1711,9 +1711,8 @@ struct struct include GVarF(S.V) end - module G = GVarGSet (S.G) (S.C) (T (CilType.Fundec) (S.C)) - + let name () = "RecursionTerm (" ^ S.name () ^ ")" let conv (ctx: (_, G.t, _, V.t) ctx): (_, S.G.t, _, S.V.t) ctx = @@ -1727,11 +1726,9 @@ struct let module LS = Set.Make (T (CilType.Fundec) (S.C)) in (* find all cycles/SCCs *) let global_visited_calls = LH.create 100 in - (* DFS *) let rec iter_call (path_visited_calls: LS.t) (call:T (CilType.Fundec) (S.C).t) = let ((fundec_e:fundec), (context_e: C.t)) = call in (*unpack tuple for later use*) - if LS.mem call path_visited_calls then ( (*Cycle found*) let msgs = @@ -1743,7 +1740,6 @@ struct try LH.replace global_visited_calls call (); let new_path_visited_calls = LS.add call path_visited_calls in - let fundec_e_typeV: V.t = V.relift (`Right fundec_e) in let gmap_opt = G.base2 (ctx.global (fundec_e_typeV)) in let gmap = Option.get (gmap_opt) in (*might be empty*) @@ -1755,13 +1751,13 @@ struct end in try - let gmap_opt = G.base2 (ctx.global (v)) in - let gmap = Option.get (gmap_opt) in - G.CMap.iter(fun key value -> - let call = (v', key) in - iter_call LS.empty call - ) gmap (* try all fundec + context pairs that are in the map *) - with Invalid_argument _ -> () + let gmap_opt = G.base2 (ctx.global (v)) in + let gmap = Option.get (gmap_opt) in + G.CMap.iter(fun key value -> + let call = (v', key) in + iter_call LS.empty call + ) gmap (* try all fundec + context pairs that are in the map *) + with Invalid_argument _ -> () let checkTerminating ctx v v' = (*Check if the loops terminated*) @@ -1814,10 +1810,8 @@ struct let fd_r : fundec = Node.find_fundec nodeF in (*Caller fundec*) let c_e: S.C.t = Option.get (fc) in (*Callee context*) let fd_e : fundec = f in (*Callee fundec*) - let tup: (fundec * S.C.t) = (fd_r, c_r) in let t = G.CSet.singleton (tup) in - side_context ctx.sideg fd_e (c_e) t; S.combine_env (conv ctx) r fe f args fc es f_ask else @@ -1832,7 +1826,6 @@ struct let event ctx e octx = S.event (conv ctx) e (conv octx) end - module CompareGlobSys (SpecSys: SpecSys) = struct open SpecSys From 91d3c79acdd9d23834012cf59f093d0e4e3f4884 Mon Sep 17 00:00:00 2001 From: Johanna Schinabeck Date: Tue, 20 Jun 2023 09:57:26 +0200 Subject: [PATCH 122/327] indentation --- src/framework/analyses.ml | 5 ++++- src/framework/constraints.ml | 34 ++++++++++++++++++---------------- 2 files changed, 22 insertions(+), 17 deletions(-) diff --git a/src/framework/analyses.ml b/src/framework/analyses.ml index 36b80567aa..fd56c65c2b 100644 --- a/src/framework/analyses.ml +++ b/src/framework/analyses.ml @@ -42,6 +42,7 @@ struct let var_id = Node.show_id end + module VarF (LD: Printable.S) = struct type t = Node.t * LD.t [@@deriving eq, ord, hash] @@ -118,6 +119,7 @@ struct | x -> BatPrintf.fprintf f "%a" printXml x end + (* Tuple of fundec and S.C*) module T (Base1: Printable.S) (Base2: Printable.S) = struct @@ -151,9 +153,10 @@ struct let pretty () x = text (show x) - let hash (a,b) = Hashtbl.hash (Base1.hash a * Base2.hash b) (*Todo: is this ok?*) + let hash (a,b) = Hashtbl.hash (Base1.hash a * Base2.hash b) (*Todo: is this ok?*) end + module GVarGSet (G: Lattice.S) (C: Printable.S) (Base: Printable.S) = struct module CSet = diff --git a/src/framework/constraints.ml b/src/framework/constraints.ml index 9508aa28a2..2db480de86 100644 --- a/src/framework/constraints.ml +++ b/src/framework/constraints.ml @@ -1711,6 +1711,7 @@ struct struct include GVarF(S.V) end + module G = GVarGSet (S.G) (S.C) (T (CilType.Fundec) (S.C)) let name () = "RecursionTerm (" ^ S.name () ^ ")" @@ -1722,15 +1723,15 @@ struct } let cycleDetection ctx v v' = - let module LH = Hashtbl.Make (T (CilType.Fundec) (S.C)) in - let module LS = Set.Make (T (CilType.Fundec) (S.C)) in + let module LH = Hashtbl.Make (T (CilType.Fundec) (S.C)) in + let module LS = Set.Make (T (CilType.Fundec) (S.C)) in (* find all cycles/SCCs *) - let global_visited_calls = LH.create 100 in + let global_visited_calls = LH.create 100 in (* DFS *) let rec iter_call (path_visited_calls: LS.t) (call:T (CilType.Fundec) (S.C).t) = let ((fundec_e:fundec), (context_e: C.t)) = call in (*unpack tuple for later use*) if LS.mem call path_visited_calls then ( - (*Cycle found*) + (*Cycle found*) let msgs = [ (Pretty.dprintf "The program might not terminate! (Fundec %a is contained in a call graph cycle)\n" CilType.Fundec.pretty fundec_e, Some (M.Location.CilLocation locUnknown)); @@ -1739,11 +1740,11 @@ struct else if not (LH.mem global_visited_calls call) then begin try LH.replace global_visited_calls call (); - let new_path_visited_calls = LS.add call path_visited_calls in - let fundec_e_typeV: V.t = V.relift (`Right fundec_e) in - let gmap_opt = G.base2 (ctx.global (fundec_e_typeV)) in + let new_path_visited_calls = LS.add call path_visited_calls in + let fundec_e_typeV: V.t = V.relift (`Right fundec_e) in + let gmap_opt = G.base2 (ctx.global (fundec_e_typeV)) in let gmap = Option.get (gmap_opt) in (*might be empty*) - let callers: G.CSet.t = G.CMap.find (context_e) gmap in + let callers: G.CSet.t = G.CMap.find (context_e) gmap in G.CSet.iter (fun to_call -> iter_call new_path_visited_calls to_call ) callers; @@ -1751,19 +1752,19 @@ struct end in try - let gmap_opt = G.base2 (ctx.global (v)) in - let gmap = Option.get (gmap_opt) in + let gmap_opt = G.base2 (ctx.global (v)) in + let gmap = Option.get (gmap_opt) in G.CMap.iter(fun key value -> - let call = (v', key) in - iter_call LS.empty call - ) gmap (* try all fundec + context pairs that are in the map *) + let call = (v', key) in + iter_call LS.empty call + ) gmap (* try all fundec + context pairs that are in the map *) with Invalid_argument _ -> () let checkTerminating ctx v v' = (*Check if the loops terminated*) if ctx.ask Queries.MustTermProg then (cycleDetection ctx v v') - else(let msgs = + else (let msgs = [ (Pretty.dprintf "The program might not terminate! (Loop analysis)\n", Some (M.Location.CilLocation locUnknown)); ] in @@ -1808,10 +1809,10 @@ struct let c_r: S.C.t = ctx.context () in (*Caller context*) let nodeF = ctx.node in let fd_r : fundec = Node.find_fundec nodeF in (*Caller fundec*) - let c_e: S.C.t = Option.get (fc) in (*Callee context*) + let c_e: S.C.t = Option.get fc in (*Callee context*) let fd_e : fundec = f in (*Callee fundec*) let tup: (fundec * S.C.t) = (fd_r, c_r) in - let t = G.CSet.singleton (tup) in + let t = G.CSet.singleton (tup) in side_context ctx.sideg fd_e (c_e) t; S.combine_env (conv ctx) r fe f args fc es f_ask else @@ -1826,6 +1827,7 @@ struct let event ctx e octx = S.event (conv ctx) e (conv octx) end + module CompareGlobSys (SpecSys: SpecSys) = struct open SpecSys From c3a96e4c94181a95da6641dc39191af7b6bed439 Mon Sep 17 00:00:00 2001 From: Johanna Schinabeck Date: Tue, 20 Jun 2023 10:07:36 +0200 Subject: [PATCH 123/327] indentation --- src/framework/analyses.ml | 4 ---- src/framework/constraints.ml | 5 +++-- 2 files changed, 3 insertions(+), 6 deletions(-) diff --git a/src/framework/analyses.ml b/src/framework/analyses.ml index fd56c65c2b..f3c76d554b 100644 --- a/src/framework/analyses.ml +++ b/src/framework/analyses.ml @@ -42,7 +42,6 @@ struct let var_id = Node.show_id end - module VarF (LD: Printable.S) = struct type t = Node.t * LD.t [@@deriving eq, ord, hash] @@ -119,7 +118,6 @@ struct | x -> BatPrintf.fprintf f "%a" printXml x end - (* Tuple of fundec and S.C*) module T (Base1: Printable.S) (Base2: Printable.S) = struct @@ -152,11 +150,9 @@ struct !res) let pretty () x = text (show x) - let hash (a,b) = Hashtbl.hash (Base1.hash a * Base2.hash b) (*Todo: is this ok?*) end - module GVarGSet (G: Lattice.S) (C: Printable.S) (Base: Printable.S) = struct module CSet = diff --git a/src/framework/constraints.ml b/src/framework/constraints.ml index 2db480de86..66b2c92614 100644 --- a/src/framework/constraints.ml +++ b/src/framework/constraints.ml @@ -1711,7 +1711,7 @@ struct struct include GVarF(S.V) end - + module G = GVarGSet (S.G) (S.C) (T (CilType.Fundec) (S.C)) let name () = "RecursionTerm (" ^ S.name () ^ ")" @@ -1727,10 +1727,12 @@ struct let module LS = Set.Make (T (CilType.Fundec) (S.C)) in (* find all cycles/SCCs *) let global_visited_calls = LH.create 100 in + (* DFS *) let rec iter_call (path_visited_calls: LS.t) (call:T (CilType.Fundec) (S.C).t) = let ((fundec_e:fundec), (context_e: C.t)) = call in (*unpack tuple for later use*) if LS.mem call path_visited_calls then ( + (*Cycle found*) let msgs = [ @@ -1827,7 +1829,6 @@ struct let event ctx e octx = S.event (conv ctx) e (conv octx) end - module CompareGlobSys (SpecSys: SpecSys) = struct open SpecSys From 7956342e1de1b117725db23c278840dcf39afecb Mon Sep 17 00:00:00 2001 From: Isidor Zweckstetter Date: Tue, 20 Jun 2023 10:17:02 +0200 Subject: [PATCH 124/327] fixed indentation --- src/util/terminationPreprocessing.ml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/util/terminationPreprocessing.ml b/src/util/terminationPreprocessing.ml index 3453aa7110..45794b56cc 100644 --- a/src/util/terminationPreprocessing.ml +++ b/src/util/terminationPreprocessing.ml @@ -36,7 +36,7 @@ class loopCounterVisitor lc lg le (fd : fundec) = object(self) let check_stmt = mkStmtOneInstr @@ Set ((var !le), (Lval (var v)), loc, eloc) in (match b.bstmts with | cont :: cond :: ss -> - b.bstmts <- cont :: inc_stmt :: check_stmt :: cond :: ss; (*cont :: cond :: inc_stmt :: ss = it is also possible, but for loops with cond at the end, inc is also at the end*) + b.bstmts <- cont :: inc_stmt :: check_stmt :: cond :: ss; (*cont :: cond :: inc_stmt :: ss = it is also possible, but for loops with cond at the end, inc is also at the end*) | _ -> ()); lc := VarToStmt.add (v: varinfo) (s: stmt) !lc; let nb = mkBlock [init_stmt; mkStmt s.skind] in From 7191fabc0f4cfdb888b77ba3782100e65d7f3481 Mon Sep 17 00:00:00 2001 From: Johanna Schinabeck Date: Tue, 20 Jun 2023 10:30:34 +0200 Subject: [PATCH 125/327] made the compare function more ocamalyy :) --- src/framework/analyses.ml | 17 +++++++---------- src/framework/constraints.ml | 10 ++++++---- 2 files changed, 13 insertions(+), 14 deletions(-) diff --git a/src/framework/analyses.ml b/src/framework/analyses.ml index f3c76d554b..5a38af3e15 100644 --- a/src/framework/analyses.ml +++ b/src/framework/analyses.ml @@ -139,15 +139,12 @@ struct \n" Base1.printXml a Base2.printXml b let compare (a1,b1) (a2,b2) = (*Todo: is this ok?*) - if equal (a1, b1) (a2, b2) then 0 else( - let res = ref 0 in - let comp_a = Base1.compare a1 a2 in - let comp_b = Base2.compare b1 b2 in - if (comp_a > 0) then res := !(res) + 1 - else if (comp_a < 0) then res := !(res) - 1; - if (comp_b > 0) then res := !(res) + 3 - else if (comp_b < 0) then res := !(res) - 3; - !res) + if equal (a1, b1) (a2, b2) then 0 + else( + let val_a a = if (a > 0) then 1 else -1 in + let val_b b = if (b > 0) then 3 else -3 in + val_a (Base1.compare a1 a2) + val_b (Base2.compare b1 b2) + ) let pretty () x = text (show x) let hash (a,b) = Hashtbl.hash (Base1.hash a * Base2.hash b) (*Todo: is this ok?*) @@ -170,7 +167,7 @@ struct end (* Make the given module Goupable*) - module C_Printable (C: Printable.S)= + module C_Printable (C: Printable.S) = struct include C include Printable.Std (* To make it Groupable *) diff --git a/src/framework/constraints.ml b/src/framework/constraints.ml index 66b2c92614..eff98c1a8f 100644 --- a/src/framework/constraints.ml +++ b/src/framework/constraints.ml @@ -1700,9 +1700,11 @@ module RecursionTermLifter (S: Spec) : Spec with module D = S.D and module C = S.C = -(*global invariant +(*global invariants: + - V -> G - fundec -> Map (S.C) (Set (fundec * S.C)) - So: g -> {c' -> f, c} + Therefore: + g -> {c' -> {(f, c)}} in case f, c --> g, c' *) struct @@ -1732,7 +1734,7 @@ struct let rec iter_call (path_visited_calls: LS.t) (call:T (CilType.Fundec) (S.C).t) = let ((fundec_e:fundec), (context_e: C.t)) = call in (*unpack tuple for later use*) if LS.mem call path_visited_calls then ( - + (*Cycle found*) let msgs = [ @@ -1760,7 +1762,7 @@ struct let call = (v', key) in iter_call LS.empty call ) gmap (* try all fundec + context pairs that are in the map *) - with Invalid_argument _ -> () + with Invalid_argument _ -> () (* path ended: no cycle*) let checkTerminating ctx v v' = (*Check if the loops terminated*) From 2df57d36e07495029d865d6264aa93855705d8ad Mon Sep 17 00:00:00 2001 From: Johanna Schinabeck Date: Tue, 20 Jun 2023 11:47:20 +0200 Subject: [PATCH 126/327] fixed testcase --- runningGob.sh | 2 +- src/framework/constraints.ml | 14 +++++++------- .../regression/55-loop-unrolling/01-simple-cases.c | 3 --- 3 files changed, 8 insertions(+), 11 deletions(-) diff --git a/runningGob.sh b/runningGob.sh index 783ad90fec..fcb5417192 100755 --- a/runningGob.sh +++ b/runningGob.sh @@ -21,6 +21,6 @@ cfile_goto="tests/incremental/02-cfg-comparison/01-added-return-stmt.c" ./goblint $cfile_loops $options_term --html # set up server to see visualizatino -python3 -m http.server --directory result 8081 +python3 -m http.server --directory result 8080 #./goblint --enable dbg.debug tests/regression/55-loop-unrolling/01-simple-cases.c --enable ana.int.interval --set "ana.activated[+]" signs --enable justcil > output.txt diff --git a/src/framework/constraints.ml b/src/framework/constraints.ml index eff98c1a8f..53fe3e5772 100644 --- a/src/framework/constraints.ml +++ b/src/framework/constraints.ml @@ -1766,13 +1766,13 @@ struct let checkTerminating ctx v v' = (*Check if the loops terminated*) - if ctx.ask Queries.MustTermProg - then (cycleDetection ctx v v') - else (let msgs = - [ - (Pretty.dprintf "The program might not terminate! (Loop analysis)\n", Some (M.Location.CilLocation locUnknown)); - ] in - M.msg_group Warning ~category:NonTerminating "Possibly non terminating loops" msgs) + if ctx.ask Queries.MustTermProg + then (cycleDetection ctx v v') + else (let msgs = + [ + (Pretty.dprintf "The program might not terminate! (Loop analysis)\n", Some (M.Location.CilLocation locUnknown)); + ] in + M.msg_group Warning ~category:NonTerminating "Possibly non terminating loops" msgs) let query ctx (type a) (q: a Queries.t): a Queries.result = match q with diff --git a/tests/regression/55-loop-unrolling/01-simple-cases.c b/tests/regression/55-loop-unrolling/01-simple-cases.c index 6790add384..0073717187 100644 --- a/tests/regression/55-loop-unrolling/01-simple-cases.c +++ b/tests/regression/55-loop-unrolling/01-simple-cases.c @@ -31,8 +31,6 @@ void example1(void) __goblint_check(a[0] == 0); // UNKNOWN __goblint_check(a[3] == 3); // UNKNOWN - - example2(); } // Do-while loop simple example @@ -48,7 +46,6 @@ void example2(void) __goblint_check(a[0] == 0); // UNKNOWN __goblint_check(a[3] == 3); // UNKNOWN - example1(); } // Initialization not completed, yet the array representation is not precise From 8ef89ec34bbe55781c37c7d966bc90abb76284e0 Mon Sep 17 00:00:00 2001 From: Johanna Schinabeck Date: Tue, 20 Jun 2023 12:42:04 +0200 Subject: [PATCH 127/327] small changes, changed concrete name and indentation --- src/framework/constraints.ml | 12 ++++++------ src/util/options.schema.json | 2 +- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/src/framework/constraints.ml b/src/framework/constraints.ml index 53fe3e5772..48dab4e84c 100644 --- a/src/framework/constraints.ml +++ b/src/framework/constraints.ml @@ -1767,12 +1767,12 @@ struct let checkTerminating ctx v v' = (*Check if the loops terminated*) if ctx.ask Queries.MustTermProg - then (cycleDetection ctx v v') - else (let msgs = - [ - (Pretty.dprintf "The program might not terminate! (Loop analysis)\n", Some (M.Location.CilLocation locUnknown)); - ] in - M.msg_group Warning ~category:NonTerminating "Possibly non terminating loops" msgs) + then (cycleDetection ctx v v') + else (let msgs = + [ + (Pretty.dprintf "The program might not terminate! (Loop analysis)\n", Some (M.Location.CilLocation locUnknown)); + ] in + M.msg_group Warning ~category:NonTerminating "Possibly non terminating loops" msgs) let query ctx (type a) (q: a Queries.t): a Queries.result = match q with diff --git a/src/util/options.schema.json b/src/util/options.schema.json index d49b30aca7..3efaef2e83 100644 --- a/src/util/options.schema.json +++ b/src/util/options.schema.json @@ -2080,7 +2080,7 @@ }, "nonTerminating": { "title": "warn.nonTerminating", - "description": "nonTerminating warning", + "description": "Non Termination warning", "type": "boolean", "default": true }, From 4ea84b275f2246fc82c9192be9c4e52013ad0ec6 Mon Sep 17 00:00:00 2001 From: Isidor Zweckstetter Date: Tue, 20 Jun 2023 15:27:27 +0200 Subject: [PATCH 128/327] test shouldn't fail --- output.txt | 2235 ------------------------------------------------- runningGob.sh | 2 +- 2 files changed, 1 insertion(+), 2236 deletions(-) diff --git a/output.txt b/output.txt index d751966836..e69de29bb2 100644 --- a/output.txt +++ b/output.txt @@ -1,2235 +0,0 @@ -/* Generated by CIL v. 2.0.1-48-g4df989f */ -/* print_CIL_Input is true */ - -#line 31 "/usr/include/x86_64-linux-gnu/bits/types.h" -typedef unsigned char __u_char; -#line 32 "/usr/include/x86_64-linux-gnu/bits/types.h" -typedef unsigned short __u_short; -#line 33 "/usr/include/x86_64-linux-gnu/bits/types.h" -typedef unsigned int __u_int; -#line 34 "/usr/include/x86_64-linux-gnu/bits/types.h" -typedef unsigned long __u_long; -#line 37 "/usr/include/x86_64-linux-gnu/bits/types.h" -typedef signed char __int8_t; -#line 38 "/usr/include/x86_64-linux-gnu/bits/types.h" -typedef unsigned char __uint8_t; -#line 39 "/usr/include/x86_64-linux-gnu/bits/types.h" -typedef short __int16_t; -#line 40 "/usr/include/x86_64-linux-gnu/bits/types.h" -typedef unsigned short __uint16_t; -#line 41 "/usr/include/x86_64-linux-gnu/bits/types.h" -typedef int __int32_t; -#line 42 "/usr/include/x86_64-linux-gnu/bits/types.h" -typedef unsigned int __uint32_t; -#line 44 "/usr/include/x86_64-linux-gnu/bits/types.h" -typedef long __int64_t; -#line 45 "/usr/include/x86_64-linux-gnu/bits/types.h" -typedef unsigned long __uint64_t; -#line 52 "/usr/include/x86_64-linux-gnu/bits/types.h" -typedef __int8_t __int_least8_t; -#line 53 "/usr/include/x86_64-linux-gnu/bits/types.h" -typedef __uint8_t __uint_least8_t; -#line 54 "/usr/include/x86_64-linux-gnu/bits/types.h" -typedef __int16_t __int_least16_t; -#line 55 "/usr/include/x86_64-linux-gnu/bits/types.h" -typedef __uint16_t __uint_least16_t; -#line 56 "/usr/include/x86_64-linux-gnu/bits/types.h" -typedef __int32_t __int_least32_t; -#line 57 "/usr/include/x86_64-linux-gnu/bits/types.h" -typedef __uint32_t __uint_least32_t; -#line 58 "/usr/include/x86_64-linux-gnu/bits/types.h" -typedef __int64_t __int_least64_t; -#line 59 "/usr/include/x86_64-linux-gnu/bits/types.h" -typedef __uint64_t __uint_least64_t; -#line 63 "/usr/include/x86_64-linux-gnu/bits/types.h" -typedef long __quad_t; -#line 64 "/usr/include/x86_64-linux-gnu/bits/types.h" -typedef unsigned long __u_quad_t; -#line 72 "/usr/include/x86_64-linux-gnu/bits/types.h" -typedef long __intmax_t; -#line 73 "/usr/include/x86_64-linux-gnu/bits/types.h" -typedef unsigned long __uintmax_t; -#line 145 "/usr/include/x86_64-linux-gnu/bits/types.h" -typedef unsigned long __dev_t; -#line 146 "/usr/include/x86_64-linux-gnu/bits/types.h" -typedef unsigned int __uid_t; -#line 147 "/usr/include/x86_64-linux-gnu/bits/types.h" -typedef unsigned int __gid_t; -#line 148 "/usr/include/x86_64-linux-gnu/bits/types.h" -typedef unsigned long __ino_t; -#line 149 "/usr/include/x86_64-linux-gnu/bits/types.h" -typedef unsigned long __ino64_t; -#line 150 "/usr/include/x86_64-linux-gnu/bits/types.h" -typedef unsigned int __mode_t; -#line 151 "/usr/include/x86_64-linux-gnu/bits/types.h" -typedef unsigned long __nlink_t; -#line 152 "/usr/include/x86_64-linux-gnu/bits/types.h" -typedef long __off_t; -#line 153 "/usr/include/x86_64-linux-gnu/bits/types.h" -typedef long __off64_t; -#line 154 "/usr/include/x86_64-linux-gnu/bits/types.h" -typedef int __pid_t; -#line 155 "/usr/include/x86_64-linux-gnu/bits/types.h" -struct __anonstruct___fsid_t_109580352 { - int __val[2] ; -}; -#line 155 "/usr/include/x86_64-linux-gnu/bits/types.h" -typedef struct __anonstruct___fsid_t_109580352 __fsid_t; -#line 156 "/usr/include/x86_64-linux-gnu/bits/types.h" -typedef long __clock_t; -#line 157 "/usr/include/x86_64-linux-gnu/bits/types.h" -typedef unsigned long __rlim_t; -#line 158 "/usr/include/x86_64-linux-gnu/bits/types.h" -typedef unsigned long __rlim64_t; -#line 159 "/usr/include/x86_64-linux-gnu/bits/types.h" -typedef unsigned int __id_t; -#line 160 "/usr/include/x86_64-linux-gnu/bits/types.h" -typedef long __time_t; -#line 161 "/usr/include/x86_64-linux-gnu/bits/types.h" -typedef unsigned int __useconds_t; -#line 162 "/usr/include/x86_64-linux-gnu/bits/types.h" -typedef long __suseconds_t; -#line 163 "/usr/include/x86_64-linux-gnu/bits/types.h" -typedef long __suseconds64_t; -#line 165 "/usr/include/x86_64-linux-gnu/bits/types.h" -typedef int __daddr_t; -#line 166 "/usr/include/x86_64-linux-gnu/bits/types.h" -typedef int __key_t; -#line 169 "/usr/include/x86_64-linux-gnu/bits/types.h" -typedef int __clockid_t; -#line 172 "/usr/include/x86_64-linux-gnu/bits/types.h" -typedef void *__timer_t; -#line 175 "/usr/include/x86_64-linux-gnu/bits/types.h" -typedef long __blksize_t; -#line 180 "/usr/include/x86_64-linux-gnu/bits/types.h" -typedef long __blkcnt_t; -#line 181 "/usr/include/x86_64-linux-gnu/bits/types.h" -typedef long __blkcnt64_t; -#line 184 "/usr/include/x86_64-linux-gnu/bits/types.h" -typedef unsigned long __fsblkcnt_t; -#line 185 "/usr/include/x86_64-linux-gnu/bits/types.h" -typedef unsigned long __fsblkcnt64_t; -#line 188 "/usr/include/x86_64-linux-gnu/bits/types.h" -typedef unsigned long __fsfilcnt_t; -#line 189 "/usr/include/x86_64-linux-gnu/bits/types.h" -typedef unsigned long __fsfilcnt64_t; -#line 192 "/usr/include/x86_64-linux-gnu/bits/types.h" -typedef long __fsword_t; -#line 194 "/usr/include/x86_64-linux-gnu/bits/types.h" -typedef long __ssize_t; -#line 197 "/usr/include/x86_64-linux-gnu/bits/types.h" -typedef long __syscall_slong_t; -#line 199 "/usr/include/x86_64-linux-gnu/bits/types.h" -typedef unsigned long __syscall_ulong_t; -#line 203 "/usr/include/x86_64-linux-gnu/bits/types.h" -typedef __off64_t __loff_t; -#line 204 "/usr/include/x86_64-linux-gnu/bits/types.h" -typedef char *__caddr_t; -#line 207 "/usr/include/x86_64-linux-gnu/bits/types.h" -typedef long __intptr_t; -#line 210 "/usr/include/x86_64-linux-gnu/bits/types.h" -typedef unsigned int __socklen_t; -#line 215 "/usr/include/x86_64-linux-gnu/bits/types.h" -typedef int __sig_atomic_t; -#line 209 "/usr/lib/gcc/x86_64-linux-gnu/10/include/stddef.h" -typedef unsigned long size_t; -#line 10 "/usr/include/x86_64-linux-gnu/bits/types/time_t.h" -typedef __time_t time_t; -#line 11 "/usr/include/x86_64-linux-gnu/bits/types/struct_timespec.h" -struct timespec { - __time_t tv_sec ; - __syscall_slong_t tv_nsec ; -}; -#line 38 "/usr/include/sched.h" -typedef __pid_t pid_t; -#line 23 "/usr/include/x86_64-linux-gnu/bits/types/struct_sched_param.h" -struct sched_param { - int sched_priority ; -}; -#line 32 "/usr/include/x86_64-linux-gnu/bits/cpu-set.h" -typedef unsigned long __cpu_mask; -#line 39 "/usr/include/x86_64-linux-gnu/bits/cpu-set.h" -struct __anonstruct_cpu_set_t_826868708 { - __cpu_mask __bits[1024UL / (8UL * sizeof(__cpu_mask ))] ; -}; -#line 39 "/usr/include/x86_64-linux-gnu/bits/cpu-set.h" -typedef struct __anonstruct_cpu_set_t_826868708 cpu_set_t; -#line 7 "/usr/include/x86_64-linux-gnu/bits/types/clock_t.h" -typedef __clock_t clock_t; -#line 7 "/usr/include/x86_64-linux-gnu/bits/types/struct_tm.h" -struct tm { - int tm_sec ; - int tm_min ; - int tm_hour ; - int tm_mday ; - int tm_mon ; - int tm_year ; - int tm_wday ; - int tm_yday ; - int tm_isdst ; - long tm_gmtoff ; - char const *tm_zone ; -}; -#line 7 "/usr/include/x86_64-linux-gnu/bits/types/clockid_t.h" -typedef __clockid_t clockid_t; -#line 7 "/usr/include/x86_64-linux-gnu/bits/types/timer_t.h" -typedef __timer_t timer_t; -#line 8 "/usr/include/x86_64-linux-gnu/bits/types/struct_itimerspec.h" -struct itimerspec { - struct timespec it_interval ; - struct timespec it_value ; -}; -#line 49 "/usr/include/time.h" -struct sigevent ; -#line 27 "/usr/include/x86_64-linux-gnu/bits/types/__locale_t.h" -struct __locale_data ; -#line 27 "/usr/include/x86_64-linux-gnu/bits/types/__locale_t.h" -struct __locale_struct { - struct __locale_data *__locales[13] ; - unsigned short const *__ctype_b ; - int const *__ctype_tolower ; - int const *__ctype_toupper ; - char const *__names[13] ; -}; -#line 41 "/usr/include/x86_64-linux-gnu/bits/types/__locale_t.h" -typedef struct __locale_struct *__locale_t; -#line 24 "/usr/include/x86_64-linux-gnu/bits/types/locale_t.h" -typedef __locale_t locale_t; -#line 25 "/usr/include/x86_64-linux-gnu/bits/atomic_wide_counter.h" -struct __anonstruct___value32_817613185 { - unsigned int __low ; - unsigned int __high ; -}; -#line 25 "/usr/include/x86_64-linux-gnu/bits/atomic_wide_counter.h" -union __anonunion___atomic_wide_counter_1044835921 { - unsigned long long __value64 ; - struct __anonstruct___value32_817613185 __value32 ; -}; -#line 25 "/usr/include/x86_64-linux-gnu/bits/atomic_wide_counter.h" -typedef union __anonunion___atomic_wide_counter_1044835921 __atomic_wide_counter; -#line 51 "/usr/include/x86_64-linux-gnu/bits/thread-shared-types.h" -struct __pthread_internal_list { - struct __pthread_internal_list *__prev ; - struct __pthread_internal_list *__next ; -}; -#line 51 "/usr/include/x86_64-linux-gnu/bits/thread-shared-types.h" -typedef struct __pthread_internal_list __pthread_list_t; -#line 57 "/usr/include/x86_64-linux-gnu/bits/thread-shared-types.h" -struct __pthread_internal_slist { - struct __pthread_internal_slist *__next ; -}; -#line 57 "/usr/include/x86_64-linux-gnu/bits/thread-shared-types.h" -typedef struct __pthread_internal_slist __pthread_slist_t; -#line 22 "/usr/include/x86_64-linux-gnu/bits/struct_mutex.h" -struct __pthread_mutex_s { - int __lock ; - unsigned int __count ; - int __owner ; - unsigned int __nusers ; - int __kind ; - short __spins ; - short __elision ; - __pthread_list_t __list ; -}; -#line 23 "/usr/include/x86_64-linux-gnu/bits/struct_rwlock.h" -struct __pthread_rwlock_arch_t { - unsigned int __readers ; - unsigned int __writers ; - unsigned int __wrphase_futex ; - unsigned int __writers_futex ; - unsigned int __pad3 ; - unsigned int __pad4 ; - int __cur_writer ; - int __shared ; - signed char __rwelision ; - unsigned char __pad1[7] ; - unsigned long __pad2 ; - unsigned int __flags ; -}; -#line 94 "/usr/include/x86_64-linux-gnu/bits/thread-shared-types.h" -struct __pthread_cond_s { - __atomic_wide_counter __wseq ; - __atomic_wide_counter __g1_start ; - unsigned int __g_refs[2] ; - unsigned int __g_size[2] ; - unsigned int __g1_orig_size ; - unsigned int __wrefs ; - unsigned int __g_signals[2] ; -}; -#line 105 "/usr/include/x86_64-linux-gnu/bits/thread-shared-types.h" -typedef unsigned int __tss_t; -#line 106 "/usr/include/x86_64-linux-gnu/bits/thread-shared-types.h" -typedef unsigned long __thrd_t; -#line 108 "/usr/include/x86_64-linux-gnu/bits/thread-shared-types.h" -struct __anonstruct___once_flag_1044835922 { - int __data ; -}; -#line 108 "/usr/include/x86_64-linux-gnu/bits/thread-shared-types.h" -typedef struct __anonstruct___once_flag_1044835922 __once_flag; -#line 27 "/usr/include/x86_64-linux-gnu/bits/pthreadtypes.h" -typedef unsigned long pthread_t; -#line 32 "/usr/include/x86_64-linux-gnu/bits/pthreadtypes.h" -union __anonunion_pthread_mutexattr_t_488594144 { - char __size[4] ; - int __align ; -}; -#line 32 "/usr/include/x86_64-linux-gnu/bits/pthreadtypes.h" -typedef union __anonunion_pthread_mutexattr_t_488594144 pthread_mutexattr_t; -#line 41 "/usr/include/x86_64-linux-gnu/bits/pthreadtypes.h" -union __anonunion_pthread_condattr_t_488594145 { - char __size[4] ; - int __align ; -}; -#line 41 "/usr/include/x86_64-linux-gnu/bits/pthreadtypes.h" -typedef union __anonunion_pthread_condattr_t_488594145 pthread_condattr_t; -#line 49 "/usr/include/x86_64-linux-gnu/bits/pthreadtypes.h" -typedef unsigned int pthread_key_t; -#line 53 "/usr/include/x86_64-linux-gnu/bits/pthreadtypes.h" -typedef int pthread_once_t; -#line 56 "/usr/include/x86_64-linux-gnu/bits/pthreadtypes.h" -union pthread_attr_t { - char __size[56] ; - long __align ; -}; -#line 62 "/usr/include/x86_64-linux-gnu/bits/pthreadtypes.h" -typedef union pthread_attr_t pthread_attr_t; -#line 67 "/usr/include/x86_64-linux-gnu/bits/pthreadtypes.h" -union __anonunion_pthread_mutex_t_335460617 { - struct __pthread_mutex_s __data ; - char __size[40] ; - long __align ; -}; -#line 67 "/usr/include/x86_64-linux-gnu/bits/pthreadtypes.h" -typedef union __anonunion_pthread_mutex_t_335460617 pthread_mutex_t; -#line 75 "/usr/include/x86_64-linux-gnu/bits/pthreadtypes.h" -union __anonunion_pthread_cond_t_951761805 { - struct __pthread_cond_s __data ; - char __size[48] ; - long long __align ; -}; -#line 75 "/usr/include/x86_64-linux-gnu/bits/pthreadtypes.h" -typedef union __anonunion_pthread_cond_t_951761805 pthread_cond_t; -#line 86 "/usr/include/x86_64-linux-gnu/bits/pthreadtypes.h" -union __anonunion_pthread_rwlock_t_656928968 { - struct __pthread_rwlock_arch_t __data ; - char __size[56] ; - long __align ; -}; -#line 86 "/usr/include/x86_64-linux-gnu/bits/pthreadtypes.h" -typedef union __anonunion_pthread_rwlock_t_656928968 pthread_rwlock_t; -#line 93 "/usr/include/x86_64-linux-gnu/bits/pthreadtypes.h" -union __anonunion_pthread_rwlockattr_t_145707745 { - char __size[8] ; - long __align ; -}; -#line 93 "/usr/include/x86_64-linux-gnu/bits/pthreadtypes.h" -typedef union __anonunion_pthread_rwlockattr_t_145707745 pthread_rwlockattr_t; -#line 103 "/usr/include/x86_64-linux-gnu/bits/pthreadtypes.h" -typedef int volatile pthread_spinlock_t; -#line 108 "/usr/include/x86_64-linux-gnu/bits/pthreadtypes.h" -union __anonunion_pthread_barrier_t_145707746 { - char __size[32] ; - long __align ; -}; -#line 108 "/usr/include/x86_64-linux-gnu/bits/pthreadtypes.h" -typedef union __anonunion_pthread_barrier_t_145707746 pthread_barrier_t; -#line 114 "/usr/include/x86_64-linux-gnu/bits/pthreadtypes.h" -union __anonunion_pthread_barrierattr_t_951761806 { - char __size[4] ; - int __align ; -}; -#line 114 "/usr/include/x86_64-linux-gnu/bits/pthreadtypes.h" -typedef union __anonunion_pthread_barrierattr_t_951761806 pthread_barrierattr_t; -#line 31 "/usr/include/x86_64-linux-gnu/bits/setjmp.h" -typedef long __jmp_buf[8]; -#line 5 "/usr/include/x86_64-linux-gnu/bits/types/__sigset_t.h" -struct __anonstruct___sigset_t_764561023 { - unsigned long __val[1024UL / (8UL * sizeof(unsigned long ))] ; -}; -#line 5 "/usr/include/x86_64-linux-gnu/bits/types/__sigset_t.h" -typedef struct __anonstruct___sigset_t_764561023 __sigset_t; -#line 26 "/usr/include/x86_64-linux-gnu/bits/types/struct___jmp_buf_tag.h" -struct __jmp_buf_tag { - __jmp_buf __jmpbuf ; - int __mask_was_saved ; - __sigset_t __saved_mask ; -}; -#line 37 "/usr/include/pthread.h" -enum __anonenum_34415463 { - PTHREAD_CREATE_JOINABLE = 0, - PTHREAD_CREATE_DETACHED = 1 -} ; -#line 47 -enum __anonenum_508643754 { - PTHREAD_MUTEX_TIMED_NP = 0, - PTHREAD_MUTEX_RECURSIVE_NP = 1, - PTHREAD_MUTEX_ERRORCHECK_NP = 2, - PTHREAD_MUTEX_ADAPTIVE_NP = 3, - PTHREAD_MUTEX_NORMAL = 0, - PTHREAD_MUTEX_RECURSIVE = 1, - PTHREAD_MUTEX_ERRORCHECK = 2, - PTHREAD_MUTEX_DEFAULT = 0 -} ; -#line 69 -enum __anonenum_931900394 { - PTHREAD_MUTEX_STALLED = 0, - PTHREAD_MUTEX_STALLED_NP = 0, - PTHREAD_MUTEX_ROBUST = 1, - PTHREAD_MUTEX_ROBUST_NP = 1 -} ; -#line 81 -enum __anonenum_205214487 { - PTHREAD_PRIO_NONE = 0, - PTHREAD_PRIO_INHERIT = 1, - PTHREAD_PRIO_PROTECT = 2 -} ; -#line 104 -enum __anonenum_25043950 { - PTHREAD_RWLOCK_PREFER_READER_NP = 0, - PTHREAD_RWLOCK_PREFER_WRITER_NP = 1, - PTHREAD_RWLOCK_PREFER_WRITER_NONRECURSIVE_NP = 2, - PTHREAD_RWLOCK_DEFAULT_NP = 0 -} ; -#line 124 -enum __anonenum_436439511 { - PTHREAD_INHERIT_SCHED = 0, - PTHREAD_EXPLICIT_SCHED = 1 -} ; -#line 134 -enum __anonenum_998661166 { - PTHREAD_SCOPE_SYSTEM = 0, - PTHREAD_SCOPE_PROCESS = 1 -} ; -#line 144 -enum __anonenum_146137331 { - PTHREAD_PROCESS_PRIVATE = 0, - PTHREAD_PROCESS_SHARED = 1 -} ; -#line 159 "/usr/include/pthread.h" -struct _pthread_cleanup_buffer { - void (*__routine)(void * ) ; - void *__arg ; - int __canceltype ; - struct _pthread_cleanup_buffer *__prev ; -}; -#line 168 -enum __anonenum_53396917 { - PTHREAD_CANCEL_ENABLE = 0, - PTHREAD_CANCEL_DISABLE = 1 -} ; -#line 175 -enum __anonenum_904563783 { - PTHREAD_CANCEL_DEFERRED = 0, - PTHREAD_CANCEL_ASYNCHRONOUS = 1 -} ; -#line 538 "/usr/include/pthread.h" -struct __cancel_jmp_buf_tag { - __jmp_buf __cancel_jmp_buf ; - int __mask_was_saved ; -}; -#line 544 "/usr/include/pthread.h" -struct __anonstruct___pthread_unwind_buf_t_530692248 { - struct __cancel_jmp_buf_tag __cancel_jmp_buf[1] ; - void *__pad[4] ; -}; -#line 544 "/usr/include/pthread.h" -typedef struct __anonstruct___pthread_unwind_buf_t_530692248 __attribute__((__aligned__)) __pthread_unwind_buf_t; -#line 557 "/usr/include/pthread.h" -struct __pthread_cleanup_frame { - void (*__cancel_routine)(void * ) ; - void *__cancel_arg ; - int __do_it ; - int __cancel_type ; -}; -#line 143 "/usr/lib/gcc/x86_64-linux-gnu/10/include/stddef.h" -typedef long ptrdiff_t; -#line 321 "/usr/lib/gcc/x86_64-linux-gnu/10/include/stddef.h" -typedef int wchar_t; -#line 415 "/usr/lib/gcc/x86_64-linux-gnu/10/include/stddef.h" -struct __anonstruct_max_align_t_896270833 { - long long __max_align_ll __attribute__((__aligned__(__alignof__(long long )))) ; - long double __max_align_ld __attribute__((__aligned__(__alignof__(long double )))) ; -}; -#line 415 "/usr/lib/gcc/x86_64-linux-gnu/10/include/stddef.h" -typedef struct __anonstruct_max_align_t_896270833 max_align_t; -/* compiler builtin: - void __builtin_va_copy(__builtin_va_list , __builtin_va_list ) ; */ -/* compiler builtin: - void *__builtin_frob_return_address(void * ) ; */ -/* compiler builtin: - void __attribute__((__overloaded__)) __sync_and_and_fetch(...) ; */ -/* compiler builtin: - void __attribute__((__overloaded__)) __sync_fetch_and_or(...) ; */ -/* compiler builtin: - int __builtin_popcountll(unsigned long long ) ; */ -/* compiler builtin: - void __attribute__((__overloaded__)) __atomic_or_fetch(...) ; */ -/* compiler builtin: - float __builtin_atanf(float ) ; */ -/* compiler builtin: - float __attribute__((____vector_size____(16))) __builtin_ia32_addps(float __attribute__((____vector_size____(16))) , - float __attribute__((____vector_size____(16))) ) ; */ -/* compiler builtin: - unsigned long __builtin_strcspn(char const * , char const * ) ; */ -/* compiler builtin: - float __builtin_asinf(float ) ; */ -/* compiler builtin: - float __attribute__((____vector_size____(16))) __builtin_ia32_maxps(float __attribute__((____vector_size____(16))) , - float __attribute__((____vector_size____(16))) ) ; */ -/* compiler builtin: - float __attribute__((____vector_size____(16))) __builtin_ia32_unpckhps(float __attribute__((____vector_size____(16))) , - float __attribute__((____vector_size____(16))) ) ; */ -/* compiler builtin: - double __builtin_acos(double ) ; */ -/* compiler builtin: - int __builtin___sprintf_chk(char * , int , unsigned long , char const * , ...) ; */ -/* compiler builtin: - void __attribute__((__overloaded__)) __atomic_nand_fetch_8(...) ; */ -/* compiler builtin: - void __attribute__((__overloaded__)) __atomic_fetch_and(...) ; */ -/* compiler builtin: - void __attribute__((__overloaded__)) __atomic_xor_fetch_16(...) ; */ -/* compiler builtin: - double __builtin_cosh(double ) ; */ -/* compiler builtin: - float __builtin_tanhf(float ) ; */ -/* compiler builtin: - void __attribute__((__overloaded__)) __atomic_fetch_nand_16(...) ; */ -/* compiler builtin: - void *__builtin_mempcpy(void * , void const * , unsigned long ) ; */ -/* compiler builtin: - void __attribute__((__overloaded__)) __atomic_sub_fetch_1(...) ; */ -/* compiler builtin: - long double __builtin_sqrtl(long double ) ; */ -/* compiler builtin: - int __builtin_parity(unsigned int ) ; */ -/* compiler builtin: - void __attribute__((__overloaded__)) __atomic_fetch_or(...) ; */ -/* compiler builtin: - long double __builtin_coshl(long double ) ; */ -/* compiler builtin: - long double __builtin_cosl(long double ) ; */ -/* compiler builtin: - float __builtin_cosf(float ) ; */ -/* compiler builtin: - void __sync_synchronize(...) ; */ -/* compiler builtin: - long double __builtin_acosl(long double ) ; */ -/* compiler builtin: - void *__builtin___mempcpy_chk(void * , void const * , unsigned long , unsigned long ) ; */ -/* compiler builtin: - void __attribute__((__overloaded__)) __sync_or_and_fetch(...) ; */ -/* compiler builtin: - int __builtin_clz(unsigned int ) ; */ -/* compiler builtin: - void __attribute__((__overloaded__)) __atomic_nand_fetch_4(...) ; */ -/* compiler builtin: - double __builtin_log10(double ) ; */ -/* compiler builtin: - char *__builtin___strcat_chk(char * , char const * , unsigned long ) ; */ -/* compiler builtin: - float __builtin_modff(float , float * ) ; */ -/* compiler builtin: - void __attribute__((__overloaded__)) __atomic_sub_fetch_4(...) ; */ -/* compiler builtin: - _Bool __atomic_compare_exchange_n(...) ; */ -/* compiler builtin: - double __builtin_sin(double ) ; */ -/* compiler builtin: - double __builtin_frexp(double , int * ) ; */ -/* compiler builtin: - float __builtin_acosf(float ) ; */ -/* compiler builtin: - void __attribute__((__overloaded__)) __sync_add_and_fetch(...) ; */ -/* compiler builtin: - long double __builtin_sinhl(long double ) ; */ -/* compiler builtin: - char *__builtin___stpcpy_chk(char * , char const * , unsigned long ) ; */ -/* compiler builtin: - void __atomic_signal_fence(int ) ; */ -/* compiler builtin: - double __builtin_fabs(double ) ; */ -/* compiler builtin: - void __attribute__((__overloaded__)) __atomic_fetch_nand_1(...) ; */ -/* compiler builtin: - void __attribute__((__overloaded__)) __atomic_and_fetch_16(...) ; */ -/* compiler builtin: - void __attribute__((__overloaded__)) __sync_fetch_and_nand(...) ; */ -/* compiler builtin: - void __attribute__((__overloaded__)) __atomic_xor_fetch_8(...) ; */ -/* compiler builtin: - void __attribute__((__overloaded__)) __atomic_xor_fetch_2(...) ; */ -/* compiler builtin: - void __atomic_thread_fence(int ) ; */ -/* compiler builtin: - void __atomic_store_16(...) ; */ -/* compiler builtin: - void __builtin_va_start(__builtin_va_list ) ; */ -/* compiler builtin: - void __attribute__((__overloaded__)) __atomic_fetch_and_8(...) ; */ -/* compiler builtin: - short __builtin_bswap16(short ) ; */ -/* compiler builtin: - void __attribute__((__overloaded__)) __atomic_and_fetch_2(...) ; */ -/* compiler builtin: - _Bool __atomic_test_and_set(void * , int ) ; */ -/* compiler builtin: - void __attribute__((__overloaded__)) __atomic_fetch_add_8(...) ; */ -/* compiler builtin: - int __builtin_ctz(unsigned int ) ; */ -/* compiler builtin: - char *__builtin_strpbrk(char const * , char const * ) ; */ -/* compiler builtin: - char *__builtin_strcpy(char * , char const * ) ; */ -/* compiler builtin: - double __builtin_sqrt(double ) ; */ -/* compiler builtin: - __builtin_va_list __builtin_next_arg(void) ; */ -/* compiler builtin: - void __attribute__((__overloaded__)) __atomic_fetch_nand(...) ; */ -/* compiler builtin: - void __attribute__((__overloaded__)) __atomic_exchange_16(...) ; */ -/* compiler builtin: - void __atomic_clear(_Bool * , int ) ; */ -/* compiler builtin: - void __atomic_store(...) ; */ -/* compiler builtin: - void __attribute__((__overloaded__)) __atomic_add_fetch_2(...) ; */ -/* compiler builtin: - float __builtin_log10f(float ) ; */ -/* compiler builtin: - long double __builtin_fabsl(long double ) ; */ -/* compiler builtin: - long double __builtin_floorl(long double ) ; */ -/* compiler builtin: - void __attribute__((__overloaded__)) __atomic_fetch_xor_1(...) ; */ -/* compiler builtin: - void __attribute__((__overloaded__)) __atomic_and_fetch(...) ; */ -/* compiler builtin: - float __builtin_floorf(float ) ; */ -/* compiler builtin: - _Bool __atomic_compare_exchange_4(...) ; */ -/* compiler builtin: - void *__builtin_memcpy(void * , void const * , unsigned long ) ; */ -/* compiler builtin: - void __attribute__((__overloaded__)) __sync_sub_and_fetch(...) ; */ -/* compiler builtin: - void __attribute__((__overloaded__)) __sync_nand_and_fetch(...) ; */ -/* compiler builtin: - void __attribute__((__overloaded__)) __atomic_load_16(...) ; */ -/* compiler builtin: - float __attribute__((____vector_size____(16))) __builtin_ia32_subps(float __attribute__((____vector_size____(16))) , - float __attribute__((____vector_size____(16))) ) ; */ -/* compiler builtin: - int __builtin_parityll(unsigned long long ) ; */ -/* compiler builtin: - void __builtin_va_end(__builtin_va_list ) ; */ -/* compiler builtin: - void __builtin_bzero(void * , unsigned long ) ; */ -/* compiler builtin: - _Bool __atomic_always_lock_free(unsigned long , void * ) ; */ -/* compiler builtin: - int __builtin_strncmp(char const * , char const * , unsigned long ) ; */ -/* compiler builtin: - void __attribute__((__overloaded__)) __atomic_nand_fetch_16(...) ; */ -/* compiler builtin: - void __attribute__((__overloaded__)) __sync_xor_and_fetch(...) ; */ -/* compiler builtin: - int __builtin___vsprintf_chk(char * , int , unsigned long , char const * , - __builtin_va_list ) ; */ -/* compiler builtin: - float __builtin_sqrtf(float ) ; */ -/* compiler builtin: - double __builtin_nans(char const * ) ; */ -/* compiler builtin: - void __attribute__((__overloaded__)) __atomic_fetch_xor_8(...) ; */ -/* compiler builtin: - double __builtin_exp(double ) ; */ -/* compiler builtin: - void __attribute__((__overloaded__)) __atomic_exchange_8(...) ; */ -/* compiler builtin: - void __attribute__((__overloaded__)) __atomic_exchange_1(...) ; */ -/* compiler builtin: - int __builtin_strcmp(char const * , char const * ) ; */ -/* compiler builtin: - float __builtin_ldexpf(float , int ) ; */ -/* compiler builtin: - float __builtin_powif(float , int ) ; */ -/* compiler builtin: - long double __builtin_log10l(long double ) ; */ -/* compiler builtin: - void *__builtin___memmove_chk(void * , void const * , unsigned long , unsigned long ) ; */ -/* compiler builtin: - void __attribute__((__overloaded__)) __sync_fetch_and_and(...) ; */ -/* compiler builtin: - void *__builtin_return_address(unsigned int ) ; */ -/* compiler builtin: - void __atomic_feraiseexcept(int ) ; */ -/* compiler builtin: - void __attribute__((__overloaded__)) __atomic_and_fetch_4(...) ; */ -/* compiler builtin: - float __builtin_fabsf(float ) ; */ -/* compiler builtin: - void __attribute__((__overloaded__)) __atomic_or_fetch_8(...) ; */ -/* compiler builtin: - void __attribute__((__overloaded__)) __atomic_or_fetch_4(...) ; */ -/* compiler builtin: - void __attribute__((__overloaded__)) __atomic_or_fetch_1(...) ; */ -/* compiler builtin: - unsigned long __builtin_object_size(void * , int ) ; */ -/* compiler builtin: - void *__builtin_alloca(unsigned long ) ; */ -/* compiler builtin: - int __builtin_va_arg_pack_len(void) ; */ -/* compiler builtin: - long double __builtin_tanl(long double ) ; */ -/* compiler builtin: - void __attribute__((__overloaded__)) __atomic_fetch_and_2(...) ; */ -/* compiler builtin: - void __sync_lock_release(...) ; */ -/* compiler builtin: - long double __builtin_modfl(long double , long double * ) ; */ -/* compiler builtin: - void __attribute__((__overloaded__)) __atomic_fetch_nand_8(...) ; */ -/* compiler builtin: - char *__builtin_stpcpy(char * , char const * ) ; */ -/* compiler builtin: - long double __builtin_sinl(long double ) ; */ -/* compiler builtin: - double __builtin_asin(double ) ; */ -/* compiler builtin: - float __builtin_sinhf(float ) ; */ -/* compiler builtin: - int __builtin_ctzl(unsigned long ) ; */ -/* compiler builtin: - long double __builtin_tanhl(long double ) ; */ -/* compiler builtin: - void __attribute__((__overloaded__)) __atomic_fetch_add(...) ; */ -/* compiler builtin: - long __builtin_bswap64(long ) ; */ -/* compiler builtin: - void __attribute__((__overloaded__)) __atomic_nand_fetch_1(...) ; */ -/* compiler builtin: - void __attribute__((__overloaded__)) __atomic_fetch_nand_2(...) ; */ -/* compiler builtin: - float __attribute__((____vector_size____(16))) __builtin_ia32_mulps(float __attribute__((____vector_size____(16))) , - float __attribute__((____vector_size____(16))) ) ; */ -/* compiler builtin: - double __builtin_tan(double ) ; */ -/* compiler builtin: - char *__builtin_strncpy(char * , char const * , unsigned long ) ; */ -/* compiler builtin: - float __builtin_inff(void) ; */ -/* compiler builtin: - void *__builtin___memset_chk(void * , int , unsigned long , unsigned long ) ; */ -/* compiler builtin: - void __attribute__((__overloaded__)) __atomic_load_n(...) ; */ -/* compiler builtin: - double __builtin_huge_val(void) ; */ -/* compiler builtin: - int __builtin_clzl(unsigned long ) ; */ -/* compiler builtin: - _Bool __atomic_compare_exchange_16(...) ; */ -/* compiler builtin: - float __builtin_frexpf(float , int * ) ; */ -/* compiler builtin: - void __attribute__((__overloaded__)) __atomic_exchange_n(...) ; */ -/* compiler builtin: - void __attribute__((__overloaded__)) __atomic_fetch_or_1(...) ; */ -/* compiler builtin: - long double __builtin_fmodl(long double ) ; */ -/* compiler builtin: - double __builtin_atan(double ) ; */ -/* compiler builtin: - int __builtin___fprintf_chk(void * , int , char const * , ...) ; */ -/* compiler builtin: - float __builtin_ceilf(float ) ; */ -/* compiler builtin: - void __attribute__((__overloaded__)) __atomic_fetch_or_8(...) ; */ -/* compiler builtin: - void __attribute__((__overloaded__)) __atomic_fetch_add_1(...) ; */ -/* compiler builtin: - void __builtin_return(void const * ) ; */ -/* compiler builtin: - long double __builtin_asinl(long double ) ; */ -/* compiler builtin: - int __builtin_ffsll(unsigned long long ) ; */ -/* compiler builtin: - void __attribute__((__overloaded__)) __atomic_fetch_sub_1(...) ; */ -/* compiler builtin: - int __builtin_va_arg_pack(void) ; */ -/* compiler builtin: - void __attribute__((__overloaded__)) __atomic_fetch_or_4(...) ; */ -/* compiler builtin: - char *__builtin___strncpy_chk(char * , char const * , unsigned long , unsigned long ) ; */ -/* compiler builtin: - double __builtin_powi(double , int ) ; */ -/* compiler builtin: - void __attribute__((__overloaded__)) __atomic_load_2(...) ; */ -/* compiler builtin: - char *__builtin_strchr(char * , int ) ; */ -/* compiler builtin: - char *__builtin___strncat_chk(char * , char const * , unsigned long , unsigned long ) ; */ -/* compiler builtin: - void __atomic_store_2(...) ; */ -/* compiler builtin: - long double __builtin_huge_vall(void) ; */ -/* compiler builtin: - int __builtin_ffsl(unsigned long ) ; */ -/* compiler builtin: - int __builtin___vprintf_chk(int , char const * , __builtin_va_list ) ; */ -/* compiler builtin: - float __attribute__((____vector_size____(16))) __builtin_ia32_unpcklps(float __attribute__((____vector_size____(16))) , - float __attribute__((____vector_size____(16))) ) ; */ -/* compiler builtin: - char *__builtin_strncat(char * , char const * , unsigned long ) ; */ -/* compiler builtin: - int __builtin_ctzll(unsigned long long ) ; */ -/* compiler builtin: - void __builtin_stdarg_start(__builtin_va_list ) ; */ -/* compiler builtin: - void __attribute__((__overloaded__)) __atomic_exchange_4(...) ; */ -/* compiler builtin: - void __attribute__((__overloaded__)) __sync_fetch_and_xor(...) ; */ -/* compiler builtin: - void __attribute__((__overloaded__)) __atomic_fetch_sub_4(...) ; */ -/* compiler builtin: - void __attribute__((__overloaded__)) __atomic_fetch_and_4(...) ; */ -/* compiler builtin: - long double __builtin_frexpl(long double , int * ) ; */ -/* compiler builtin: - _Bool __atomic_compare_exchange(...) ; */ -/* compiler builtin: - float __builtin_tanf(float ) ; */ -/* compiler builtin: - long double __builtin_logl(long double ) ; */ -/* compiler builtin: - void __builtin_va_arg(__builtin_va_list , unsigned long , void * ) ; */ -/* compiler builtin: - long __builtin_expect(long , long ) ; */ -/* compiler builtin: - void __attribute__((__overloaded__)) __atomic_load_1(...) ; */ -/* compiler builtin: - _Bool __atomic_compare_exchange_1(...) ; */ -/* compiler builtin: - int __builtin___printf_chk(int , char const * , ...) ; */ -/* compiler builtin: - void __attribute__((__overloaded__)) __atomic_fetch_xor_2(...) ; */ -/* compiler builtin: - int __builtin___vfprintf_chk(void * , int , char const * , __builtin_va_list ) ; */ -/* compiler builtin: - void __builtin_prefetch(void const * , ...) ; */ -/* compiler builtin: - long double __builtin_nansl(char const * ) ; */ -/* compiler builtin: - double __builtin_fmod(double ) ; */ -/* compiler builtin: - void __atomic_load(...) ; */ -/* compiler builtin: - void __attribute__((__overloaded__)) __atomic_or_fetch_16(...) ; */ -/* compiler builtin: - void __attribute__((__overloaded__)) __atomic_add_fetch_16(...) ; */ -/* compiler builtin: - void __attribute__((__overloaded__)) __sync_val_compare_and_swap(...) ; */ -/* compiler builtin: - void __atomic_store_4(...) ; */ -/* compiler builtin: - double __builtin_tanh(double ) ; */ -/* compiler builtin: - void __attribute__((__overloaded__)) __atomic_fetch_and_1(...) ; */ -/* compiler builtin: - void __attribute__((__overloaded__)) __atomic_fetch_nand_4(...) ; */ -/* compiler builtin: - void __attribute__((__overloaded__)) __atomic_fetch_add_16(...) ; */ -/* compiler builtin: - void __builtin_unreachable(void) ; */ -/* compiler builtin: - _Bool __atomic_compare_exchange_2(...) ; */ -/* compiler builtin: - long double __builtin_ldexpl(long double , int ) ; */ -/* compiler builtin: - void *__builtin_apply(void (*)() , void * , unsigned long ) ; */ -/* compiler builtin: - float __builtin_sinf(float ) ; */ -/* compiler builtin: - double __builtin_ceil(double ) ; */ -/* compiler builtin: - void __atomic_exchange(...) ; */ -/* compiler builtin: - long double __builtin_powil(long double , int ) ; */ -/* compiler builtin: - void __attribute__((__overloaded__)) __atomic_sub_fetch_8(...) ; */ -/* compiler builtin: - long double __builtin_expl(long double ) ; */ -/* compiler builtin: - int __builtin_constant_p(int ) ; */ -/* compiler builtin: - void __attribute__((__overloaded__)) __atomic_fetch_sub_16(...) ; */ -/* compiler builtin: - double __builtin_log(double ) ; */ -/* compiler builtin: - float __builtin_expf(float ) ; */ -/* compiler builtin: - int __builtin_types_compatible_p(unsigned long , unsigned long ) ; */ -/* compiler builtin: - long double __builtin_atan2l(long double , long double ) ; */ -/* compiler builtin: - void *__builtin_apply_args(void) ; */ -/* compiler builtin: - void __attribute__((__overloaded__)) __atomic_exchange_2(...) ; */ -/* compiler builtin: - float __builtin_logf(float ) ; */ -/* compiler builtin: - void __attribute__((__overloaded__)) __atomic_sub_fetch_2(...) ; */ -/* compiler builtin: - unsigned long __builtin_strlen(char const * ) ; */ -/* compiler builtin: - int __builtin_ffs(unsigned int ) ; */ -/* compiler builtin: - void __attribute__((__overloaded__)) __atomic_fetch_xor_16(...) ; */ -/* compiler builtin: - double __builtin_inf(void) ; */ -/* compiler builtin: - void __attribute__((__overloaded__)) __atomic_fetch_or_16(...) ; */ -/* compiler builtin: - void *__builtin___memcpy_chk(void * , void const * , unsigned long , unsigned long ) ; */ -/* compiler builtin: - void __attribute__((__overloaded__)) __atomic_load_4(...) ; */ -/* compiler builtin: - void __atomic_store_n(...) ; */ -/* compiler builtin: - void __builtin_trap(void) ; */ -/* compiler builtin: - void __attribute__((__overloaded__)) __atomic_fetch_add_4(...) ; */ -/* compiler builtin: - int __builtin_parityl(unsigned long ) ; */ -/* compiler builtin: - void __attribute__((__overloaded__)) __atomic_nand_fetch_2(...) ; */ -/* compiler builtin: - void __attribute__((__overloaded__)) __sync_lock_test_and_set(...) ; */ -/* compiler builtin: - unsigned long __builtin_strspn(char const * , char const * ) ; */ -/* compiler builtin: - void __builtin_varargs_start(__builtin_va_list ) ; */ -/* compiler builtin: - void __attribute__((__overloaded__)) __atomic_sub_fetch(...) ; */ -/* compiler builtin: - void __attribute__((__overloaded__)) __atomic_fetch_and_16(...) ; */ -/* compiler builtin: - _Bool __atomic_compare_exchange_8(...) ; */ -/* compiler builtin: - void __attribute__((__overloaded__)) __atomic_nand_fetch(...) ; */ -/* compiler builtin: - double __builtin_nan(char const * ) ; */ -/* compiler builtin: - void __attribute__((__overloaded__)) __atomic_load_8(...) ; */ -/* compiler builtin: - int __builtin___snprintf_chk(char * , unsigned long , int , unsigned long , - char const * , ...) ; */ -/* compiler builtin: - void __attribute__((__overloaded__)) __atomic_xor_fetch_4(...) ; */ -/* compiler builtin: - void __attribute__((__overloaded__)) __atomic_fetch_sub_2(...) ; */ -/* compiler builtin: - void __attribute__((__overloaded__)) __atomic_add_fetch(...) ; */ -/* compiler builtin: - long double __builtin_atanl(long double ) ; */ -/* compiler builtin: - int __builtin_clzll(unsigned long long ) ; */ -/* compiler builtin: - float __builtin_huge_valf(void) ; */ -/* compiler builtin: - float __builtin_coshf(float ) ; */ -/* compiler builtin: - float __builtin_nansf(char const * ) ; */ -/* compiler builtin: - void __atomic_store_8(...) ; */ -/* compiler builtin: - void __attribute__((__overloaded__)) __atomic_xor_fetch(...) ; */ -/* compiler builtin: - void __attribute__((__overloaded__)) __sync_fetch_and_add(...) ; */ -/* compiler builtin: - int __builtin___vsnprintf_chk(char * , unsigned long , int , unsigned long , - char const * , __builtin_va_list ) ; */ -/* compiler builtin: - float __builtin_nanf(char const * ) ; */ -/* compiler builtin: - void __attribute__((__overloaded__)) __atomic_or_fetch_2(...) ; */ -/* compiler builtin: - void __attribute__((__overloaded__)) __atomic_add_fetch_1(...) ; */ -/* compiler builtin: - void __attribute__((__overloaded__)) __atomic_fetch_xor(...) ; */ -/* compiler builtin: - void __attribute__((__overloaded__)) __atomic_add_fetch_8(...) ; */ -/* compiler builtin: - void __attribute__((__overloaded__)) __atomic_fetch_xor_4(...) ; */ -/* compiler builtin: - void __attribute__((__overloaded__)) __atomic_fetch_sub_8(...) ; */ -/* compiler builtin: - _Bool __sync_bool_compare_and_swap(...) ; */ -/* compiler builtin: - double __builtin_atan2(double , double ) ; */ -/* compiler builtin: - void __attribute__((__overloaded__)) __builtin_tgmath(...) ; */ -/* compiler builtin: - int __builtin_popcountl(unsigned long ) ; */ -/* compiler builtin: - void __attribute__((__overloaded__)) __atomic_and_fetch_1(...) ; */ -/* compiler builtin: - long double __builtin_ceill(long double ) ; */ -/* compiler builtin: - void __atomic_store_1(...) ; */ -/* compiler builtin: - char *__builtin___strcpy_chk(char * , char const * , unsigned long ) ; */ -/* compiler builtin: - void __attribute__((__overloaded__)) __atomic_xor_fetch_1(...) ; */ -/* compiler builtin: - void __attribute__((__overloaded__)) __atomic_fetch_or_2(...) ; */ -/* compiler builtin: - void __attribute__((__overloaded__)) __atomic_sub_fetch_16(...) ; */ -/* compiler builtin: - double __builtin_floor(double ) ; */ -/* compiler builtin: - double __builtin_cos(double ) ; */ -/* compiler builtin: - void __attribute__((__overloaded__)) __sync_fetch_and_sub(...) ; */ -/* compiler builtin: - void *__builtin_memset(void * , int , int ) ; */ -/* compiler builtin: - void __attribute__((__overloaded__)) __atomic_fetch_add_2(...) ; */ -/* compiler builtin: - long double __builtin_nanl(char const * ) ; */ -/* compiler builtin: - float __builtin_atan2f(float , float ) ; */ -/* compiler builtin: - _Bool __atomic_is_lock_free(unsigned long , void * ) ; */ -/* compiler builtin: - int __builtin_popcount(unsigned int ) ; */ -/* compiler builtin: - double __builtin_sinh(double ) ; */ -/* compiler builtin: - void __builtin_bcopy(void const * , void * , unsigned long ) ; */ -/* compiler builtin: - void __attribute__((__overloaded__)) __atomic_and_fetch_8(...) ; */ -/* compiler builtin: - void __attribute__((__overloaded__)) __atomic_fetch_sub(...) ; */ -/* compiler builtin: - void *__builtin_extract_return_addr(void * ) ; */ -/* compiler builtin: - int __builtin_bswap32(int ) ; */ -/* compiler builtin: - double __builtin_ldexp(double , int ) ; */ -/* compiler builtin: - long double __builtin_infl(void) ; */ -/* compiler builtin: - float __builtin_fmodf(float ) ; */ -/* compiler builtin: - void __attribute__((__overloaded__)) __atomic_add_fetch_4(...) ; */ -/* compiler builtin: - void *__builtin_frame_address(unsigned int ) ; */ -#line 1 "lib/goblint/runtime/include/goblint.h" -extern void __goblint_check(int exp ) ; -#line 2 -extern void __goblint_assume(int exp ) ; -#line 3 -extern void __goblint_assert(int exp ) ; -#line 5 -extern void __goblint_assume_join() ; -#line 7 -extern void __goblint_split_begin(int exp ) ; -#line 8 -extern void __goblint_split_end(int exp ) ; -#line 4 "tests/regression/55-loop-unrolling/01-simple-cases.c" -int global ; -#line 8 -void example1(void) ; -#line 9 -void example2(void) ; -#line 10 -void example3(void) ; -#line 11 -void example4(void) ; -#line 12 -void example5(void) ; -#line 13 -void example6(void) ; -#line 14 -void example7(void) ; -#line 15 -void example8(void) ; -#line 16 -void example9(void) ; -#line 17 -void example10(void) ; -#line 6 "tests/regression/55-loop-unrolling/01-simple-cases.c" -int main(void) -{ - - - { -#line 8 - example1(); -#line 9 - example2(); -#line 10 - example3(); -#line 11 - example4(); -#line 12 - example5(); -#line 13 - example6(); -#line 14 - example7(); -#line 15 - example8(); -#line 16 - example9(); -#line 17 - example10(); -#line 18 - return (0); -} -} -#line 22 "tests/regression/55-loop-unrolling/01-simple-cases.c" -void example1(void) -{ - int a[5] ; - int i ; - int term27_5-file_01-simple-cases ; - - { -#line 25 - i = 0; - { -#line 27 - term27_5-file_01-simple-cases = 0; - { -#line 27 - while (1) { - while_continue: /* CIL Label */ ; -#line 27 - if (! (i < 5)) { -#line 27 - goto while_break; - } -#line 27 - term27_5-file_01-simple-cases ++; -#line 28 - a[i] = i; -#line 29 - i ++; - } - while_break: /* CIL Label */ ; - } -#line 27 - term_exit- = term27_5-file_01-simple-cases; - } -#line 32 - __goblint_check(a[0] == 0); -#line 33 - __goblint_check(a[3] == 3); -#line 34 - return; -} -} -#line 37 "tests/regression/55-loop-unrolling/01-simple-cases.c" -void example2(void) -{ - int a[5] ; - int i ; - int term42_5-file_01-simple-cases ; - - { -#line 40 - i = 0; - { -#line 42 - term42_5-file_01-simple-cases = 0; - { -#line 42 - while (1) { - while_continue: /* CIL Label */ ; -#line 43 - a[i] = i; -#line 44 - i ++; -#line 42 - term42_5-file_01-simple-cases ++; -#line 42 - if (! (i <= 5)) { -#line 42 - goto while_break; - } - } - while_break: /* CIL Label */ ; - } -#line 42 - term_exit- = term42_5-file_01-simple-cases; - } -#line 47 - __goblint_check(a[0] == 0); -#line 48 - __goblint_check(a[3] == 3); -#line 49 - return; -} -} -#line 52 "tests/regression/55-loop-unrolling/01-simple-cases.c" -void example3(void) -{ - int a[10] ; - int i ; - int term57_5-file_01-simple-cases ; - - { -#line 55 - i = 0; - { -#line 57 - term57_5-file_01-simple-cases = 0; - { -#line 57 - while (1) { - while_continue: /* CIL Label */ ; -#line 57 - if (! (i < 5)) { -#line 57 - goto while_break; - } -#line 57 - term57_5-file_01-simple-cases ++; -#line 58 - a[i] = i; -#line 59 - i ++; - } - while_break: /* CIL Label */ ; - } -#line 57 - term_exit- = term57_5-file_01-simple-cases; - } -#line 62 - __goblint_check(a[0] == 0); -#line 63 - __goblint_check(a[3] == 0); -#line 64 - __goblint_check(a[7] == 0); -#line 65 - return; -} -} -#line 68 "tests/regression/55-loop-unrolling/01-simple-cases.c" -void example4(void) -{ - int a[10] ; - int i ; - int first_iteration ; - int term74_5-file_01-simple-cases ; - - { -#line 71 - i = 0; -#line 72 - first_iteration = 1; - { -#line 74 - term74_5-file_01-simple-cases = 0; - { -#line 74 - while (1) { - while_continue: /* CIL Label */ ; -#line 74 - if (! (i < 10)) { -#line 74 - goto while_break; - } -#line 74 - term74_5-file_01-simple-cases ++; -#line 75 - if (first_iteration == 1) { -#line 75 - __goblint_check(i == 0); - } else -#line 76 - if (i > 5) { -#line 76 - __goblint_check(i == 6); - } -#line 77 - first_iteration = 0; -#line 78 - a[i] = 0; -#line 79 - i ++; - } - while_break: /* CIL Label */ ; - } -#line 74 - term_exit- = term74_5-file_01-simple-cases; - } -#line 82 - __goblint_check(a[0] == 0); -#line 83 - __goblint_check(first_iteration == 0); -#line 84 - return; -} -} -#line 89 "tests/regression/55-loop-unrolling/01-simple-cases.c" -void example5(void) -{ - int a[4] ; - int i ; - int top ; - int term95_5-file_01-simple-cases ; - - { -#line 92 - i = 0; -#line 93 - top = 0; - { -#line 95 - term95_5-file_01-simple-cases = 0; - { -#line 95 - while (1) { - while_continue: /* CIL Label */ ; -#line 95 - if (! (i < 4)) { -#line 95 - goto while_break; - } -#line 95 - term95_5-file_01-simple-cases ++; -#line 96 - a[i] = 0; -#line 97 - top += i; -#line 98 - if (i == 2) { -#line 99 - __goblint_check(top == 3); - } else { -#line 102 - __goblint_check(top == 3); - } -#line 104 - i ++; - } - while_break: /* CIL Label */ ; - } -#line 95 - term_exit- = term95_5-file_01-simple-cases; - } -#line 107 - __goblint_check(a[0] == 0); -#line 108 - __goblint_check(a[3] == 0); -#line 109 - __goblint_check(top == 6); -#line 110 - return; -} -} -#line 113 "tests/regression/55-loop-unrolling/01-simple-cases.c" -void example6(void) -{ - int a[5] ; - int i ; - int top ; - int term119_5-file_01-simple-cases ; - - { -#line 116 - i = 0; -#line 117 - top = 0; - { -#line 119 - term119_5-file_01-simple-cases = 0; - { -#line 119 - while (1) { - while_continue: /* CIL Label */ ; -#line 119 - if (! (i < 3)) { -#line 119 - goto while_break; - } -#line 119 - term119_5-file_01-simple-cases ++; -#line 120 - a[i] = 0; -#line 121 - __goblint_check(a[0] == 0); -#line 122 - i ++; - } - while_break: /* CIL Label */ ; - } -#line 119 - term_exit- = term119_5-file_01-simple-cases; - } -#line 125 - __goblint_check(a[0] == 0); -#line 126 - __goblint_check(a[3] == 0); -#line 127 - __goblint_check(top == 6); -#line 128 - return; -} -} -#line 131 "tests/regression/55-loop-unrolling/01-simple-cases.c" -int update(int i ) -{ - - - { -#line 132 - if (i > 5) { -#line 133 - return (0); - } else { -#line 136 - return (1); - } -} -} -#line 139 "tests/regression/55-loop-unrolling/01-simple-cases.c" -void example7(void) -{ - int a[10] ; - int i ; - int tmp ; - int term143_2-file_01-simple-cases ; - - { -#line 142 - i = 0; - { -#line 143 - term143_2-file_01-simple-cases = 0; - { -#line 143 - while (1) { - while_continue: /* CIL Label */ ; -#line 143 - tmp = update(i); -#line 143 - term143_2-file_01-simple-cases ++; -#line 143 - if (! tmp) { -#line 143 - goto while_break; - } -#line 144 - a[i] = i; -#line 145 - i ++; - } - while_break: /* CIL Label */ ; - } -#line 143 - term_exit- = term143_2-file_01-simple-cases; - } -#line 147 - __goblint_check(a[0] == 0); -#line 148 - __goblint_check(a[6] == 0); -#line 149 - return; -} -} -#line 152 "tests/regression/55-loop-unrolling/01-simple-cases.c" -void example8(void) -{ - int a[5] ; - int b[5] ; - int i ; - int j ; - int term160_9-file_01-simple-cases ; - int term157_2-file_01-simple-cases ; - - { -#line 155 - b[0] = 0; -#line 155 - b[1] = 0; -#line 155 - b[2] = 0; -#line 155 - b[3] = 0; -#line 155 - b[4] = 0; -#line 156 - i = 0; - { -#line 157 - term157_2-file_01-simple-cases = 0; - { -#line 157 - while (1) { - while_continue: /* CIL Label */ ; -#line 157 - if (! (i < 5)) { -#line 157 - goto while_break; - } -#line 157 - term157_2-file_01-simple-cases ++; -#line 158 - a[i] = i; -#line 159 - j = 0; - { -#line 160 - term160_9-file_01-simple-cases = 0; - { -#line 160 - while (1) { - while_continue___0: /* CIL Label */ ; -#line 160 - if (! (j < 5)) { -#line 160 - goto while_break___0; - } -#line 160 - term160_9-file_01-simple-cases ++; -#line 161 - b[j] += a[i]; -#line 162 - j ++; - } - while_break___0: /* CIL Label */ ; - } -#line 160 - term_exit- = term160_9-file_01-simple-cases; - } -#line 164 - i ++; - } - while_break: /* CIL Label */ ; - } -#line 157 - term_exit- = term157_2-file_01-simple-cases; - } -#line 166 - return; -} -} -#line 170 "tests/regression/55-loop-unrolling/01-simple-cases.c" -void example9(void) -{ - int a[5] ; - int i ; - int term174_2-file_01-simple-cases ; - - { -#line 173 - i = 0; - { -#line 174 - term174_2-file_01-simple-cases = 0; - { -#line 174 - while (1) { - while_continue: /* CIL Label */ ; -#line 174 - if (! 1) { -#line 174 - goto while_break; - } -#line 174 - term174_2-file_01-simple-cases ++; -#line 175 - a[i] = i; -#line 176 - i ++; -#line 177 - if (i == 5) { -#line 177 - goto while_break; - } - } - while_break: /* CIL Label */ ; - } -#line 174 - term_exit- = term174_2-file_01-simple-cases; - } -#line 179 - return; -} -} -#line 183 "tests/regression/55-loop-unrolling/01-simple-cases.c" -void example10(void) -{ - int a[5] ; - int i ; - int term187_2-file_01-simple-cases ; - - { -#line 186 - i = 0; - { -#line 187 - term187_2-file_01-simple-cases = 0; - { -#line 187 - while (1) { - while_continue: /* CIL Label */ ; -#line 187 - if (! (i < 5)) { -#line 187 - goto while_break; - } -#line 187 - term187_2-file_01-simple-cases ++; -#line 188 - if (i == 3) { -#line 189 - i ++; -#line 190 - goto while_continue; - } -#line 192 - a[i] = i; -#line 193 - i ++; - } - while_break: /* CIL Label */ ; - } -#line 187 - term_exit- = term187_2-file_01-simple-cases; - } -#line 195 - return; -} -} -#line 117 "/usr/include/x86_64-linux-gnu/bits/cpu-set.h" -extern int ( __attribute__((__leaf__)) __sched_cpucount)(size_t __setsize , cpu_set_t const *__setp ) __attribute__((__nothrow__)) ; -#line 119 -extern cpu_set_t *( __attribute__((__leaf__)) __sched_cpualloc)(size_t __count ) __attribute__((__nothrow__)) ; -#line 120 -extern void ( __attribute__((__leaf__)) __sched_cpufree)(cpu_set_t *__set ) __attribute__((__nothrow__)) ; -#line 54 "/usr/include/sched.h" -extern int ( __attribute__((__leaf__)) sched_setparam)(__pid_t __pid , struct sched_param const *__param ) __attribute__((__nothrow__)) ; -#line 58 -extern int ( __attribute__((__leaf__)) sched_getparam)(__pid_t __pid , struct sched_param *__param ) __attribute__((__nothrow__)) ; -#line 61 -extern int ( __attribute__((__leaf__)) sched_setscheduler)(__pid_t __pid , int __policy , - struct sched_param const *__param ) __attribute__((__nothrow__)) ; -#line 65 -extern int ( __attribute__((__leaf__)) sched_getscheduler)(__pid_t __pid ) __attribute__((__nothrow__)) ; -#line 68 -extern int ( __attribute__((__leaf__)) sched_yield)(void) __attribute__((__nothrow__)) ; -#line 71 -extern int ( __attribute__((__leaf__)) sched_get_priority_max)(int __algorithm ) __attribute__((__nothrow__)) ; -#line 74 -extern int ( __attribute__((__leaf__)) sched_get_priority_min)(int __algorithm ) __attribute__((__nothrow__)) ; -#line 78 -extern int ( __attribute__((__leaf__)) sched_rr_get_interval)(__pid_t __pid , struct timespec *__t ) __attribute__((__nothrow__)) ; -#line 72 "/usr/include/time.h" -extern clock_t ( __attribute__((__leaf__)) clock)(void) __attribute__((__nothrow__)) ; -#line 76 -extern time_t ( __attribute__((__leaf__)) time)(time_t *__timer ) __attribute__((__nothrow__)) ; -#line 79 -extern double ( __attribute__((__leaf__)) difftime)(time_t __time1 , time_t __time0 ) __attribute__((__nothrow__, -__const__)) ; -#line 83 -extern time_t ( __attribute__((__leaf__)) mktime)(struct tm *__tp ) __attribute__((__nothrow__)) ; -#line 100 -extern size_t ( __attribute__((__leaf__)) strftime)(char * __restrict __s , size_t __maxsize , - char const * __restrict __format , - struct tm const * __restrict __tp ) __attribute__((__nothrow__)) ; -#line 116 -extern size_t ( __attribute__((__leaf__)) strftime_l)(char * __restrict __s , size_t __maxsize , - char const * __restrict __format , - struct tm const * __restrict __tp , - locale_t __loc ) __attribute__((__nothrow__)) ; -#line 132 -extern struct tm *( __attribute__((__leaf__)) gmtime)(time_t const *__timer ) __attribute__((__nothrow__)) ; -#line 136 -extern struct tm *( __attribute__((__leaf__)) localtime)(time_t const *__timer ) __attribute__((__nothrow__)) ; -#line 154 -extern struct tm *( __attribute__((__leaf__)) gmtime_r)(time_t const * __restrict __timer , - struct tm * __restrict __tp ) __attribute__((__nothrow__)) ; -#line 159 -extern struct tm *( __attribute__((__leaf__)) localtime_r)(time_t const * __restrict __timer , - struct tm * __restrict __tp ) __attribute__((__nothrow__)) ; -#line 179 -extern char *( __attribute__((__leaf__)) asctime)(struct tm const *__tp ) __attribute__((__nothrow__)) ; -#line 183 -extern char *( __attribute__((__leaf__)) ctime)(time_t const *__timer ) __attribute__((__nothrow__)) ; -#line 197 -extern char *( __attribute__((__leaf__)) asctime_r)(struct tm const * __restrict __tp , - char * __restrict __buf ) __attribute__((__nothrow__)) ; -#line 202 -extern char *( __attribute__((__leaf__)) ctime_r)(time_t const * __restrict __timer , - char * __restrict __buf ) __attribute__((__nothrow__)) ; -#line 217 -extern char *__tzname[2] ; -#line 218 -extern int __daylight ; -#line 219 -extern long __timezone ; -#line 224 -extern char *tzname[2] ; -#line 228 -extern void ( __attribute__((__leaf__)) tzset)(void) __attribute__((__nothrow__)) ; -#line 232 -extern int daylight ; -#line 233 -extern long timezone ; -#line 246 -extern time_t ( __attribute__((__leaf__)) timegm)(struct tm *__tp ) __attribute__((__nothrow__)) ; -#line 263 -extern time_t ( __attribute__((__leaf__)) timelocal)(struct tm *__tp ) __attribute__((__nothrow__)) ; -#line 271 -extern int ( __attribute__((__leaf__)) dysize)(int __year ) __attribute__((__nothrow__, -__const__)) ; -#line 281 -extern int nanosleep(struct timespec const *__requested_time , struct timespec *__remaining ) ; -#line 285 -extern int ( __attribute__((__leaf__)) clock_getres)(clockid_t __clock_id , struct timespec *__res ) __attribute__((__nothrow__)) ; -#line 288 -extern int ( __attribute__((__nonnull__(2), __leaf__)) clock_gettime)(clockid_t __clock_id , - struct timespec *__tp ) __attribute__((__nothrow__)) ; -#line 292 -extern int ( __attribute__((__nonnull__(2), __leaf__)) clock_settime)(clockid_t __clock_id , - struct timespec const *__tp ) __attribute__((__nothrow__)) ; -#line 323 -extern int clock_nanosleep(clockid_t __clock_id , int __flags , struct timespec const *__req , - struct timespec *__rem ) ; -#line 338 -extern int ( __attribute__((__leaf__)) clock_getcpuclockid)(pid_t __pid , clockid_t *__clock_id ) __attribute__((__nothrow__)) ; -#line 343 -extern int ( __attribute__((__leaf__)) timer_create)(clockid_t __clock_id , struct sigevent * __restrict __evp , - timer_t * __restrict __timerid ) __attribute__((__nothrow__)) ; -#line 348 -extern int ( __attribute__((__leaf__)) timer_delete)(timer_t __timerid ) __attribute__((__nothrow__)) ; -#line 352 -extern int ( __attribute__((__leaf__)) timer_settime)(timer_t __timerid , int __flags , - struct itimerspec const * __restrict __value , - struct itimerspec * __restrict __ovalue ) __attribute__((__nothrow__)) ; -#line 357 -extern int ( __attribute__((__leaf__)) timer_gettime)(timer_t __timerid , struct itimerspec *__value ) __attribute__((__nothrow__)) ; -#line 376 -extern int ( __attribute__((__leaf__)) timer_getoverrun)(timer_t __timerid ) __attribute__((__nothrow__)) ; -#line 383 -extern int ( __attribute__((__nonnull__(1), __leaf__)) timespec_get)(struct timespec *__ts , - int __base ) __attribute__((__nothrow__)) ; -#line 202 "/usr/include/pthread.h" -extern int ( __attribute__((__nonnull__(1,3))) pthread_create)(pthread_t * __restrict __newthread , - pthread_attr_t const * __restrict __attr , - void *(*__start_routine)(void * ) , - void * __restrict __arg ) __attribute__((__nothrow__)) ; -#line 211 -extern void pthread_exit(void *__retval ) __attribute__((__noreturn__)) ; -#line 219 -extern int pthread_join(pthread_t __th , void **__thread_return ) ; -#line 269 -extern int ( __attribute__((__leaf__)) pthread_detach)(pthread_t __th ) __attribute__((__nothrow__)) ; -#line 273 -extern pthread_t ( __attribute__((__leaf__)) pthread_self)(void) __attribute__((__nothrow__, -__const__)) ; -#line 276 -extern int ( __attribute__((__leaf__)) pthread_equal)(pthread_t __thread1 , pthread_t __thread2 ) __attribute__((__nothrow__, -__const__)) ; -#line 285 -extern int ( __attribute__((__nonnull__(1), __leaf__)) pthread_attr_init)(pthread_attr_t *__attr ) __attribute__((__nothrow__)) ; -#line 288 -extern int ( __attribute__((__nonnull__(1), __leaf__)) pthread_attr_destroy)(pthread_attr_t *__attr ) __attribute__((__nothrow__)) ; -#line 292 -extern int ( __attribute__((__nonnull__(1,2), __leaf__)) pthread_attr_getdetachstate)(pthread_attr_t const *__attr , - int *__detachstate ) __attribute__((__nothrow__)) ; -#line 297 -extern int ( __attribute__((__nonnull__(1), __leaf__)) pthread_attr_setdetachstate)(pthread_attr_t *__attr , - int __detachstate ) __attribute__((__nothrow__)) ; -#line 303 -extern int ( __attribute__((__nonnull__(1,2), __leaf__)) pthread_attr_getguardsize)(pthread_attr_t const *__attr , - size_t *__guardsize ) __attribute__((__nothrow__)) ; -#line 308 -extern int ( __attribute__((__nonnull__(1), __leaf__)) pthread_attr_setguardsize)(pthread_attr_t *__attr , - size_t __guardsize ) __attribute__((__nothrow__)) ; -#line 314 -extern int ( __attribute__((__nonnull__(1,2), __leaf__)) pthread_attr_getschedparam)(pthread_attr_t const * __restrict __attr , - struct sched_param * __restrict __param ) __attribute__((__nothrow__)) ; -#line 319 -extern int ( __attribute__((__nonnull__(1,2), __leaf__)) pthread_attr_setschedparam)(pthread_attr_t * __restrict __attr , - struct sched_param const * __restrict __param ) __attribute__((__nothrow__)) ; -#line 324 -extern int ( __attribute__((__nonnull__(1,2), __leaf__)) pthread_attr_getschedpolicy)(pthread_attr_t const * __restrict __attr , - int * __restrict __policy ) __attribute__((__nothrow__)) ; -#line 329 -extern int ( __attribute__((__nonnull__(1), __leaf__)) pthread_attr_setschedpolicy)(pthread_attr_t *__attr , - int __policy ) __attribute__((__nothrow__)) ; -#line 333 -extern int ( __attribute__((__nonnull__(1,2), __leaf__)) pthread_attr_getinheritsched)(pthread_attr_t const * __restrict __attr , - int * __restrict __inherit ) __attribute__((__nothrow__)) ; -#line 338 -extern int ( __attribute__((__nonnull__(1), __leaf__)) pthread_attr_setinheritsched)(pthread_attr_t *__attr , - int __inherit ) __attribute__((__nothrow__)) ; -#line 344 -extern int ( __attribute__((__nonnull__(1,2), __leaf__)) pthread_attr_getscope)(pthread_attr_t const * __restrict __attr , - int * __restrict __scope ) __attribute__((__nothrow__)) ; -#line 349 -extern int ( __attribute__((__nonnull__(1), __leaf__)) pthread_attr_setscope)(pthread_attr_t *__attr , - int __scope ) __attribute__((__nothrow__)) ; -#line 353 -extern int ( __attribute__((__nonnull__(1,2), __leaf__)) pthread_attr_getstackaddr)(pthread_attr_t const * __restrict __attr , - void ** __restrict __stackaddr ) __attribute__((__nothrow__, -__deprecated__)) ; -#line 361 -extern int ( __attribute__((__nonnull__(1), __leaf__)) pthread_attr_setstackaddr)(pthread_attr_t *__attr , - void *__stackaddr ) __attribute__((__nothrow__, -__deprecated__)) ; -#line 366 -extern int ( __attribute__((__nonnull__(1,2), __leaf__)) pthread_attr_getstacksize)(pthread_attr_t const * __restrict __attr , - size_t * __restrict __stacksize ) __attribute__((__nothrow__)) ; -#line 373 -extern int ( __attribute__((__nonnull__(1), __leaf__)) pthread_attr_setstacksize)(pthread_attr_t *__attr , - size_t __stacksize ) __attribute__((__nothrow__)) ; -#line 379 -extern int ( __attribute__((__nonnull__(1,2,3), __leaf__)) pthread_attr_getstack)(pthread_attr_t const * __restrict __attr , - void ** __restrict __stackaddr , - size_t * __restrict __stacksize ) __attribute__((__nothrow__)) ; -#line 387 -extern int ( __attribute__((__nonnull__(1), __leaf__)) pthread_attr_setstack)(pthread_attr_t *__attr , - void *__stackaddr , - size_t __stacksize ) __attribute__((__nothrow__)) ; -#line 441 -extern int ( __attribute__((__nonnull__(3), __leaf__)) pthread_setschedparam)(pthread_t __target_thread , - int __policy , - struct sched_param const *__param ) __attribute__((__nothrow__)) ; -#line 446 -extern int ( __attribute__((__nonnull__(2,3), __leaf__)) pthread_getschedparam)(pthread_t __target_thread , - int * __restrict __policy , - struct sched_param * __restrict __param ) __attribute__((__nothrow__)) ; -#line 452 -extern int ( __attribute__((__leaf__)) pthread_setschedprio)(pthread_t __target_thread , - int __prio ) __attribute__((__nothrow__)) ; -#line 509 -int ( __attribute__((__nonnull__(1,2))) pthread_once)(pthread_once_t *once_control , - void (*init_routine)(void) ) __attribute__((__goblint_stub__)) ; -#line 521 -extern int pthread_setcancelstate(int __state , int *__oldstate ) ; -#line 525 -extern int pthread_setcanceltype(int __type , int *__oldtype ) ; -#line 528 -extern int pthread_cancel(pthread_t __th ) ; -#line 533 -extern void pthread_testcancel(void) ; -#line 697 -extern void __pthread_register_cancel(__pthread_unwind_buf_t *__buf ) ; -#line 709 -extern void __pthread_unregister_cancel(__pthread_unwind_buf_t *__buf ) ; -#line 750 -extern void __pthread_unwind_next(__pthread_unwind_buf_t *__buf ) __attribute__((__weak__, -__noreturn__)) ; -#line 773 -extern int __sigsetjmp(struct __jmp_buf_tag *__env , int __savemask ) __attribute__((__nothrow__)) ; -#line 781 -extern int ( __attribute__((__nonnull__(1), __leaf__)) pthread_mutex_init)(pthread_mutex_t *__mutex , - pthread_mutexattr_t const *__mutexattr ) __attribute__((__nothrow__)) ; -#line 786 -extern int ( __attribute__((__nonnull__(1), __leaf__)) pthread_mutex_destroy)(pthread_mutex_t *__mutex ) __attribute__((__nothrow__)) ; -#line 790 -extern int ( __attribute__((__nonnull__(1))) pthread_mutex_trylock)(pthread_mutex_t *__mutex ) __attribute__((__nothrow__)) ; -#line 794 -extern int ( __attribute__((__nonnull__(1))) pthread_mutex_lock)(pthread_mutex_t *__mutex ) __attribute__((__nothrow__)) ; -#line 800 -extern int ( __attribute__((__nonnull__(1,2))) pthread_mutex_timedlock)(pthread_mutex_t * __restrict __mutex , - struct timespec const * __restrict __abstime ) __attribute__((__nothrow__)) ; -#line 835 -extern int ( __attribute__((__nonnull__(1))) pthread_mutex_unlock)(pthread_mutex_t *__mutex ) __attribute__((__nothrow__)) ; -#line 840 -extern int ( __attribute__((__nonnull__(1,2), __leaf__)) pthread_mutex_getprioceiling)(pthread_mutex_t const * __restrict __mutex , - int * __restrict __prioceiling ) __attribute__((__nothrow__)) ; -#line 847 -extern int ( __attribute__((__nonnull__(1,3), __leaf__)) pthread_mutex_setprioceiling)(pthread_mutex_t * __restrict __mutex , - int __prioceiling , - int * __restrict __old_ceiling ) __attribute__((__nothrow__)) ; -#line 855 -extern int ( __attribute__((__nonnull__(1), __leaf__)) pthread_mutex_consistent)(pthread_mutex_t *__mutex ) __attribute__((__nothrow__)) ; -#line 874 -extern int ( __attribute__((__nonnull__(1), __leaf__)) pthread_mutexattr_init)(pthread_mutexattr_t *__attr ) __attribute__((__nothrow__)) ; -#line 878 -extern int ( __attribute__((__nonnull__(1), __leaf__)) pthread_mutexattr_destroy)(pthread_mutexattr_t *__attr ) __attribute__((__nothrow__)) ; -#line 882 -extern int ( __attribute__((__nonnull__(1,2), __leaf__)) pthread_mutexattr_getpshared)(pthread_mutexattr_t const * __restrict __attr , - int * __restrict __pshared ) __attribute__((__nothrow__)) ; -#line 888 -extern int ( __attribute__((__nonnull__(1), __leaf__)) pthread_mutexattr_setpshared)(pthread_mutexattr_t *__attr , - int __pshared ) __attribute__((__nothrow__)) ; -#line 894 -extern int ( __attribute__((__nonnull__(1,2), __leaf__)) pthread_mutexattr_gettype)(pthread_mutexattr_t const * __restrict __attr , - int * __restrict __kind ) __attribute__((__nothrow__)) ; -#line 901 -extern int ( __attribute__((__nonnull__(1), __leaf__)) pthread_mutexattr_settype)(pthread_mutexattr_t *__attr , - int __kind ) __attribute__((__nothrow__)) ; -#line 906 -extern int ( __attribute__((__nonnull__(1,2), __leaf__)) pthread_mutexattr_getprotocol)(pthread_mutexattr_t const * __restrict __attr , - int * __restrict __protocol ) __attribute__((__nothrow__)) ; -#line 913 -extern int ( __attribute__((__nonnull__(1), __leaf__)) pthread_mutexattr_setprotocol)(pthread_mutexattr_t *__attr , - int __protocol ) __attribute__((__nothrow__)) ; -#line 918 -extern int ( __attribute__((__nonnull__(1,2), __leaf__)) pthread_mutexattr_getprioceiling)(pthread_mutexattr_t const * __restrict __attr , - int * __restrict __prioceiling ) __attribute__((__nothrow__)) ; -#line 924 -extern int ( __attribute__((__nonnull__(1), __leaf__)) pthread_mutexattr_setprioceiling)(pthread_mutexattr_t *__attr , - int __prioceiling ) __attribute__((__nothrow__)) ; -#line 930 -extern int ( __attribute__((__nonnull__(1,2), __leaf__)) pthread_mutexattr_getrobust)(pthread_mutexattr_t const *__attr , - int *__robustness ) __attribute__((__nothrow__)) ; -#line 946 -extern int ( __attribute__((__nonnull__(1), __leaf__)) pthread_mutexattr_setrobust)(pthread_mutexattr_t *__attr , - int __robustness ) __attribute__((__nothrow__)) ; -#line 967 -extern int ( __attribute__((__nonnull__(1), __leaf__)) pthread_rwlock_init)(pthread_rwlock_t * __restrict __rwlock , - pthread_rwlockattr_t const * __restrict __attr ) __attribute__((__nothrow__)) ; -#line 972 -extern int ( __attribute__((__nonnull__(1), __leaf__)) pthread_rwlock_destroy)(pthread_rwlock_t *__rwlock ) __attribute__((__nothrow__)) ; -#line 976 -extern int ( __attribute__((__nonnull__(1))) pthread_rwlock_rdlock)(pthread_rwlock_t *__rwlock ) __attribute__((__nothrow__)) ; -#line 980 -extern int ( __attribute__((__nonnull__(1))) pthread_rwlock_tryrdlock)(pthread_rwlock_t *__rwlock ) __attribute__((__nothrow__)) ; -#line 986 -extern int ( __attribute__((__nonnull__(1,2))) pthread_rwlock_timedrdlock)(pthread_rwlock_t * __restrict __rwlock , - struct timespec const * __restrict __abstime ) __attribute__((__nothrow__)) ; -#line 1023 -extern int ( __attribute__((__nonnull__(1))) pthread_rwlock_wrlock)(pthread_rwlock_t *__rwlock ) __attribute__((__nothrow__)) ; -#line 1027 -extern int ( __attribute__((__nonnull__(1))) pthread_rwlock_trywrlock)(pthread_rwlock_t *__rwlock ) __attribute__((__nothrow__)) ; -#line 1033 -extern int ( __attribute__((__nonnull__(1,2))) pthread_rwlock_timedwrlock)(pthread_rwlock_t * __restrict __rwlock , - struct timespec const * __restrict __abstime ) __attribute__((__nothrow__)) ; -#line 1071 -extern int ( __attribute__((__nonnull__(1))) pthread_rwlock_unlock)(pthread_rwlock_t *__rwlock ) __attribute__((__nothrow__)) ; -#line 1078 -extern int ( __attribute__((__nonnull__(1), __leaf__)) pthread_rwlockattr_init)(pthread_rwlockattr_t *__attr ) __attribute__((__nothrow__)) ; -#line 1082 -extern int ( __attribute__((__nonnull__(1), __leaf__)) pthread_rwlockattr_destroy)(pthread_rwlockattr_t *__attr ) __attribute__((__nothrow__)) ; -#line 1086 -extern int ( __attribute__((__nonnull__(1,2), __leaf__)) pthread_rwlockattr_getpshared)(pthread_rwlockattr_t const * __restrict __attr , - int * __restrict __pshared ) __attribute__((__nothrow__)) ; -#line 1092 -extern int ( __attribute__((__nonnull__(1), __leaf__)) pthread_rwlockattr_setpshared)(pthread_rwlockattr_t *__attr , - int __pshared ) __attribute__((__nothrow__)) ; -#line 1097 -extern int ( __attribute__((__nonnull__(1,2), __leaf__)) pthread_rwlockattr_getkind_np)(pthread_rwlockattr_t const * __restrict __attr , - int * __restrict __pref ) __attribute__((__nothrow__)) ; -#line 1103 -extern int ( __attribute__((__nonnull__(1), __leaf__)) pthread_rwlockattr_setkind_np)(pthread_rwlockattr_t *__attr , - int __pref ) __attribute__((__nothrow__)) ; -#line 1112 -extern int ( __attribute__((__nonnull__(1), __leaf__)) pthread_cond_init)(pthread_cond_t * __restrict __cond , - pthread_condattr_t const * __restrict __cond_attr ) __attribute__((__nothrow__)) ; -#line 1117 -extern int ( __attribute__((__nonnull__(1), __leaf__)) pthread_cond_destroy)(pthread_cond_t *__cond ) __attribute__((__nothrow__)) ; -#line 1121 -extern int ( __attribute__((__nonnull__(1))) pthread_cond_signal)(pthread_cond_t *__cond ) __attribute__((__nothrow__)) ; -#line 1125 -extern int ( __attribute__((__nonnull__(1))) pthread_cond_broadcast)(pthread_cond_t *__cond ) __attribute__((__nothrow__)) ; -#line 1133 -extern int ( __attribute__((__nonnull__(1,2))) pthread_cond_wait)(pthread_cond_t * __restrict __cond , - pthread_mutex_t * __restrict __mutex ) ; -#line 1145 -extern int ( __attribute__((__nonnull__(1,2,3))) pthread_cond_timedwait)(pthread_cond_t * __restrict __cond , - pthread_mutex_t * __restrict __mutex , - struct timespec const * __restrict __abstime ) ; -#line 1194 -extern int ( __attribute__((__nonnull__(1), __leaf__)) pthread_condattr_init)(pthread_condattr_t *__attr ) __attribute__((__nothrow__)) ; -#line 1198 -extern int ( __attribute__((__nonnull__(1), __leaf__)) pthread_condattr_destroy)(pthread_condattr_t *__attr ) __attribute__((__nothrow__)) ; -#line 1202 -extern int ( __attribute__((__nonnull__(1,2), __leaf__)) pthread_condattr_getpshared)(pthread_condattr_t const * __restrict __attr , - int * __restrict __pshared ) __attribute__((__nothrow__)) ; -#line 1208 -extern int ( __attribute__((__nonnull__(1), __leaf__)) pthread_condattr_setpshared)(pthread_condattr_t *__attr , - int __pshared ) __attribute__((__nothrow__)) ; -#line 1213 -extern int ( __attribute__((__nonnull__(1,2), __leaf__)) pthread_condattr_getclock)(pthread_condattr_t const * __restrict __attr , - __clockid_t * __restrict __clock_id ) __attribute__((__nothrow__)) ; -#line 1219 -extern int ( __attribute__((__nonnull__(1), __leaf__)) pthread_condattr_setclock)(pthread_condattr_t *__attr , - __clockid_t __clock_id ) __attribute__((__nothrow__)) ; -#line 1230 -extern int ( __attribute__((__nonnull__(1), __leaf__)) pthread_spin_init)(pthread_spinlock_t *__lock , - int __pshared ) __attribute__((__nothrow__)) ; -#line 1234 -extern int ( __attribute__((__nonnull__(1), __leaf__)) pthread_spin_destroy)(pthread_spinlock_t *__lock ) __attribute__((__nothrow__)) ; -#line 1238 -extern int ( __attribute__((__nonnull__(1))) pthread_spin_lock)(pthread_spinlock_t *__lock ) __attribute__((__nothrow__)) ; -#line 1242 -extern int ( __attribute__((__nonnull__(1))) pthread_spin_trylock)(pthread_spinlock_t *__lock ) __attribute__((__nothrow__)) ; -#line 1246 -extern int ( __attribute__((__nonnull__(1))) pthread_spin_unlock)(pthread_spinlock_t *__lock ) __attribute__((__nothrow__)) ; -#line 1254 -extern int ( __attribute__((__nonnull__(1), __leaf__)) pthread_barrier_init)(pthread_barrier_t * __restrict __barrier , - pthread_barrierattr_t const * __restrict __attr , - unsigned int __count ) __attribute__((__nothrow__)) ; -#line 1260 -extern int ( __attribute__((__nonnull__(1), __leaf__)) pthread_barrier_destroy)(pthread_barrier_t *__barrier ) __attribute__((__nothrow__)) ; -#line 1264 -extern int ( __attribute__((__nonnull__(1))) pthread_barrier_wait)(pthread_barrier_t *__barrier ) __attribute__((__nothrow__)) ; -#line 1269 -extern int ( __attribute__((__nonnull__(1), __leaf__)) pthread_barrierattr_init)(pthread_barrierattr_t *__attr ) __attribute__((__nothrow__)) ; -#line 1273 -extern int ( __attribute__((__nonnull__(1), __leaf__)) pthread_barrierattr_destroy)(pthread_barrierattr_t *__attr ) __attribute__((__nothrow__)) ; -#line 1277 -extern int ( __attribute__((__nonnull__(1,2), __leaf__)) pthread_barrierattr_getpshared)(pthread_barrierattr_t const * __restrict __attr , - int * __restrict __pshared ) __attribute__((__nothrow__)) ; -#line 1283 -extern int ( __attribute__((__nonnull__(1), __leaf__)) pthread_barrierattr_setpshared)(pthread_barrierattr_t *__attr , - int __pshared ) __attribute__((__nothrow__)) ; -#line 1297 -extern int ( __attribute__((__nonnull__(1), __leaf__)) pthread_key_create)(pthread_key_t *__key , - void (*__destr_function)(void * ) ) __attribute__((__nothrow__)) ; -#line 1302 -extern int ( __attribute__((__leaf__)) pthread_key_delete)(pthread_key_t __key ) __attribute__((__nothrow__)) ; -#line 1305 -extern void *( __attribute__((__leaf__)) pthread_getspecific)(pthread_key_t __key ) __attribute__((__nothrow__)) ; -#line 1308 -extern int ( __attribute__((__leaf__)) pthread_setspecific)(pthread_key_t __key , - void const *__pointer ) __attribute__((__nothrow__)) ; -#line 1315 -extern int ( __attribute__((__nonnull__(2), __leaf__)) pthread_getcpuclockid)(pthread_t __thread_id , - __clockid_t *__clock_id ) __attribute__((__nothrow__)) ; -#line 1332 -extern int ( __attribute__((__leaf__)) pthread_atfork)(void (*__prepare)(void) , void (*__parent)(void) , - void (*__child)(void) ) __attribute__((__nothrow__)) ; -#line 5 "lib/libc/stub/src/pthread.c" -int ( __attribute__((__nonnull__(1,2))) pthread_once)(pthread_once_t *once_control , - void (*init_routine)(void) ) __attribute__((__goblint_stub__)) ; -#line 5 "lib/libc/stub/src/pthread.c" -int ( __attribute__((__nonnull__(1,2))) pthread_once)(pthread_once_t *once_control , - void (*init_routine)(void) ) -{ - int top ; - - { -#line 8 - (*init_routine)(); -#line 9 - return (top); -} -} -#line 6 "lib/libc/stub/src/stdlib.c" -void qsort(void *ptr , size_t count , size_t size , int (*comp)(void const * , void const * ) ) __attribute__((__goblint_stub__)) ; -#line 7 -void qsort(void *ptr , size_t count , size_t size , int (*comp)(void const * , void const * ) ) __attribute__((__goblint_stub__)) ; -#line 7 "lib/libc/stub/src/stdlib.c" -void qsort(void *ptr , size_t count , size_t size , int (*comp)(void const * , void const * ) ) -{ - size_t i ; - size_t j ; - size_t i___0 ; - size_t j___0 ; - int r ; - size_t k ; - char *a ; - char *b ; - char c ; - int term10_5-file_stdlib ; - int term9_3-file_stdlib ; - int term21_9-file_stdlib ; - int term17_5-file_stdlib ; - int term16_3-file_stdlib ; - - { -#line 9 - i = (size_t )0; - { -#line 9 - term9_3-file_stdlib = 0; - { -#line 9 - while (1) { - while_continue: /* CIL Label */ ; -#line 9 - if (! (i < count)) { -#line 9 - goto while_break; - } -#line 9 - term9_3-file_stdlib ++; -#line 10 - j = (size_t )0; - { -#line 10 - term10_5-file_stdlib = 0; - { -#line 10 - while (1) { - while_continue___0: /* CIL Label */ ; -#line 10 - if (! (j < count)) { -#line 10 - goto while_break___0; - } -#line 10 - term10_5-file_stdlib ++; -#line 11 - (*comp)((void const *)(ptr + i * size), (void const *)(ptr + j * size)); -#line 10 - j ++; - } - while_break___0: /* CIL Label */ ; - } -#line 10 - term_exit- = term10_5-file_stdlib; - } -#line 9 - i ++; - } - while_break: /* CIL Label */ ; - } -#line 9 - term_exit- = term9_3-file_stdlib; - } -#line 16 - i___0 = (size_t )0; - { -#line 16 - term16_3-file_stdlib = 0; - { -#line 16 - while (1) { - while_continue___1: /* CIL Label */ ; -#line 16 - if (! (i___0 < count)) { -#line 16 - goto while_break___1; - } -#line 16 - term16_3-file_stdlib ++; -#line 17 - j___0 = (size_t )0; - { -#line 17 - term17_5-file_stdlib = 0; - { -#line 17 - while (1) { - while_continue___2: /* CIL Label */ ; -#line 17 - if (! (j___0 < count)) { -#line 17 - goto while_break___2; - } -#line 17 - term17_5-file_stdlib ++; -#line 19 - if (r) { -#line 21 - k = (size_t )0; - { -#line 21 - term21_9-file_stdlib = 0; - { -#line 21 - while (1) { - while_continue___3: /* CIL Label */ ; -#line 21 - if (! (k < size)) { -#line 21 - goto while_break___3; - } -#line 21 - term21_9-file_stdlib ++; -#line 22 - a = (char *)((ptr + i___0 * size) + k); -#line 23 - b = (char *)((ptr + j___0 * size) + k); -#line 24 - c = *a; -#line 25 - *a = *b; -#line 26 - *b = c; -#line 21 - k ++; - } - while_break___3: /* CIL Label */ ; - } -#line 21 - term_exit- = term21_9-file_stdlib; - } - } -#line 17 - j___0 ++; - } - while_break___2: /* CIL Label */ ; - } -#line 17 - term_exit- = term17_5-file_stdlib; - } -#line 16 - i___0 ++; - } - while_break___1: /* CIL Label */ ; - } -#line 16 - term_exit- = term16_3-file_stdlib; - } -#line 33 - return; -} -} -#line 37 -void *bsearch(void const *key , void const *ptr , size_t count , size_t size , - int (*comp)(void const * , void const * ) ) __attribute__((__goblint_stub__)) ; -#line 38 -void *bsearch(void const *key , void const *ptr , size_t count , size_t size , - int (*comp)(void const * , void const * ) ) __attribute__((__goblint_stub__)) ; -#line 38 "lib/libc/stub/src/stdlib.c" -void *bsearch(void const *key , void const *ptr , size_t count , size_t size , - int (*comp)(void const * , void const * ) ) -{ - size_t i ; - void const *a ; - int tmp ; - int term40_3-file_stdlib ; - - { -#line 40 - i = (size_t )0; - { -#line 40 - term40_3-file_stdlib = 0; - { -#line 40 - while (1) { - while_continue: /* CIL Label */ ; -#line 40 - if (! (i < count)) { -#line 40 - goto while_break; - } -#line 40 - term40_3-file_stdlib ++; -#line 41 - a = ptr + i * size; -#line 42 - tmp = (*comp)(key, a); -#line 42 - if (tmp == 0) { -#line 43 - return ((void *)a); - } -#line 40 - i ++; - } - while_break: /* CIL Label */ ; - } -#line 40 - term_exit- = term40_3-file_stdlib; - } -#line 47 - return ((void *)0); -} -} diff --git a/runningGob.sh b/runningGob.sh index fcb5417192..0e43ee45c5 100755 --- a/runningGob.sh +++ b/runningGob.sh @@ -8,7 +8,7 @@ options_apron="--set ana.activated[+] apron --enable ana.int.interval --set ana. options_signs="--set "ana.activated[+]" signs --enable warn.debug" options_term="--set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra" -cfile_loops="tests/regression/55-loop-unrolling/01-simple-cases.c" +cfile_loops="tests/regression/00-sanity/36-strict-loop-dead.c" cfile_signs="tests/regression/99-tutorials/01-first.c" cfile_goto="tests/incremental/02-cfg-comparison/01-added-return-stmt.c" From 2b75972e9f60087a5558d8b8794652e7084d77d1 Mon Sep 17 00:00:00 2001 From: Johanna Schinabeck Date: Tue, 20 Jun 2023 16:13:57 +0200 Subject: [PATCH 129/327] added weird test case --- .../55-loop-unrolling/01-simple-cases.c | 26 +++++++++++++++++-- 1 file changed, 24 insertions(+), 2 deletions(-) diff --git a/tests/regression/55-loop-unrolling/01-simple-cases.c b/tests/regression/55-loop-unrolling/01-simple-cases.c index 0073717187..98e8e34ff0 100644 --- a/tests/regression/55-loop-unrolling/01-simple-cases.c +++ b/tests/regression/55-loop-unrolling/01-simple-cases.c @@ -3,6 +3,27 @@ int global; +int f(int x); +int g(int x); + +int f(int x) +{ +if (x <= 0) return 0; +else return g(x) + g(x + 1); +} + +int g(int x) +{ +if (x <= 0) return 0; +else return f(x - 1) + f(x - 2); +} + +int main() { +int x = __VERIFIER_nondet_int(); +g(x); +} + +/* int main(void) { example1(); @@ -16,7 +37,7 @@ int main(void) example9(); example10(); return 0; -} +}*/ // Simple example void example1(void) @@ -30,7 +51,8 @@ void example1(void) } __goblint_check(a[0] == 0); // UNKNOWN - __goblint_check(a[3] == 3); // UNKNOWN + lab:__goblint_check(a[3] == 3); // UNKNOWN + goto lab; } // Do-while loop simple example From c6f37b2cada18c5cc8d8ca70cf0c39ef6bfda201 Mon Sep 17 00:00:00 2001 From: Johanna Schinabeck Date: Tue, 20 Jun 2023 16:20:19 +0200 Subject: [PATCH 130/327] added weird test case + merging --- runningGob.sh | 2 +- tests/regression/55-loop-unrolling/01-simple-cases.c | 3 ++- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/runningGob.sh b/runningGob.sh index 0e43ee45c5..fcb5417192 100755 --- a/runningGob.sh +++ b/runningGob.sh @@ -8,7 +8,7 @@ options_apron="--set ana.activated[+] apron --enable ana.int.interval --set ana. options_signs="--set "ana.activated[+]" signs --enable warn.debug" options_term="--set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra" -cfile_loops="tests/regression/00-sanity/36-strict-loop-dead.c" +cfile_loops="tests/regression/55-loop-unrolling/01-simple-cases.c" cfile_signs="tests/regression/99-tutorials/01-first.c" cfile_goto="tests/incremental/02-cfg-comparison/01-added-return-stmt.c" diff --git a/tests/regression/55-loop-unrolling/01-simple-cases.c b/tests/regression/55-loop-unrolling/01-simple-cases.c index 98e8e34ff0..9bf8d98683 100644 --- a/tests/regression/55-loop-unrolling/01-simple-cases.c +++ b/tests/regression/55-loop-unrolling/01-simple-cases.c @@ -37,7 +37,7 @@ int main(void) example9(); example10(); return 0; -}*/ +} // Simple example void example1(void) @@ -216,3 +216,4 @@ void example10(void) } return 0; } +*/ \ No newline at end of file From 566ae50925db871301039150ec3c50e3b9e8d537 Mon Sep 17 00:00:00 2001 From: Alexander Schlenga Date: Tue, 20 Jun 2023 22:08:05 +0200 Subject: [PATCH 131/327] Fix indentation --- src/framework/analyses.ml | 10 +++++----- src/framework/constraints.ml | 12 ++++++------ 2 files changed, 11 insertions(+), 11 deletions(-) diff --git a/src/framework/analyses.ml b/src/framework/analyses.ml index 1d1972ac45..6f53fa098d 100644 --- a/src/framework/analyses.ml +++ b/src/framework/analyses.ml @@ -159,18 +159,18 @@ struct | `Bot -> G.bot () | `Lifted1 x -> x | _ -> failwith "GVarG.spec" - let contexts = function + let contexts = function | `Bot -> CSet.bot () | `Lifted2 x -> x | _ -> failwith "GVarG.contexts" - let create_spec spec = `Lifted1 spec - let create_contexts contexts = `Lifted2 contexts + let create_spec spec = `Lifted1 spec + let create_contexts contexts = `Lifted2 contexts - let printXml f = function + let printXml f = function | `Lifted1 x -> G.printXml f x | `Lifted2 x -> BatPrintf.fprintf f "%a" CSet.printXml x | x -> BatPrintf.fprintf f "%a" printXml x -*) + *) end exception Deadcode diff --git a/src/framework/constraints.ml b/src/framework/constraints.ml index 07750122a5..d66d95d229 100644 --- a/src/framework/constraints.ml +++ b/src/framework/constraints.ml @@ -563,7 +563,7 @@ struct let side_context sideg f c = if !AnalysisState.postsolving then sideg (GVar.contexts f) (G.create_contexts (G.CSet.singleton c)) - + let common_ctx var edge prev_node pval (getl:lv -> ld) sidel getg sideg : (D.t, S.G.t, S.C.t, S.V.t) ctx * D.t list ref * (lval option * varinfo * exp list * D.t) list ref = let r = ref [] in let spawns = ref [] in @@ -1127,7 +1127,7 @@ struct | `Lifted2 d -> LH.replace l' x d (* | `Bot -> () *) (* Since Verify2 is broken and only checks existing keys, add it with local bottom value. - This works around some cases, where Verify2 would not detect a problem due to completely missing variable. *) + This works around some cases, where Verify2 would not detect a problem due to completely missing variable. *) | `Bot -> LH.replace l' x (S.D.bot ()) | `Top -> failwith "GlobConstrSolFromEqConstrSolBase.split_vars: local variable has top value" | `Lifted1 _ -> failwith "GlobConstrSolFromEqConstrSolBase.split_vars: local variable has global value" @@ -1764,10 +1764,10 @@ struct in PP.iter f h1; (* let k1 = Set.of_enum @@ PP.keys h1 in - let k2 = Set.of_enum @@ PP.keys h2 in - let o1 = Set.cardinal @@ Set.diff k1 k2 in - let o2 = Set.cardinal @@ Set.diff k2 k1 in - Printf.printf "locals: \tequal = %d\tleft = %d[%d]\tright = %d[%d]\tincomparable = %d\n" !eq !le o1 !gr o2 !uk *) + let k2 = Set.of_enum @@ PP.keys h2 in + let o1 = Set.cardinal @@ Set.diff k1 k2 in + let o2 = Set.cardinal @@ Set.diff k2 k1 in + Printf.printf "locals: \tequal = %d\tleft = %d[%d]\tright = %d[%d]\tincomparable = %d\n" !eq !le o1 !gr o2 !uk *) Printf.printf "locals: \tequal = %d\tleft = %d\tright = %d\tincomparable = %d\n" !eq !le !gr !uk let compare_locals_ctx h1 h2 = From 6cf3d129291481c6f899b9b395353b1fa7a23be1 Mon Sep 17 00:00:00 2001 From: Alexander Schlenga Date: Tue, 20 Jun 2023 22:28:49 +0200 Subject: [PATCH 132/327] Small changes Direct empty list comparison instead of checking length = 0. Make loop_heads a function with argument (). --- src/analyses/termination_new.ml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/analyses/termination_new.ml b/src/analyses/termination_new.ml index f062030820..a3aa3aef92 100644 --- a/src/analyses/termination_new.ml +++ b/src/analyses/termination_new.ml @@ -6,7 +6,7 @@ open TerminationPreprocessing exception PreProcessing of string -let loop_heads = +let loop_heads () = let module FileCfg = struct let file = !Cilfacade.current_file @@ -31,7 +31,7 @@ let is_loop_exit_indicator (x : varinfo) = x = !loop_exit let no_upjumping_gotos () = - List.length upjumping_gotos.contents = 0 + upjumping_gotos.contents = [] (** Checks whether a variable can be bounded *) let check_bounded ctx varinfo = From cfaf4178e38eb1247cb25d974e52b3be6683ba49 Mon Sep 17 00:00:00 2001 From: Isidor Zweckstetter Date: Tue, 20 Jun 2023 22:53:50 +0200 Subject: [PATCH 133/327] added location to recursion Warning --- runningGob.sh | 2 +- src/framework/constraints.ml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/runningGob.sh b/runningGob.sh index 0e43ee45c5..fcb5417192 100755 --- a/runningGob.sh +++ b/runningGob.sh @@ -8,7 +8,7 @@ options_apron="--set ana.activated[+] apron --enable ana.int.interval --set ana. options_signs="--set "ana.activated[+]" signs --enable warn.debug" options_term="--set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra" -cfile_loops="tests/regression/00-sanity/36-strict-loop-dead.c" +cfile_loops="tests/regression/55-loop-unrolling/01-simple-cases.c" cfile_signs="tests/regression/99-tutorials/01-first.c" cfile_goto="tests/incremental/02-cfg-comparison/01-added-return-stmt.c" diff --git a/src/framework/constraints.ml b/src/framework/constraints.ml index 48dab4e84c..b998ab9629 100644 --- a/src/framework/constraints.ml +++ b/src/framework/constraints.ml @@ -1738,7 +1738,7 @@ struct (*Cycle found*) let msgs = [ - (Pretty.dprintf "The program might not terminate! (Fundec %a is contained in a call graph cycle)\n" CilType.Fundec.pretty fundec_e, Some (M.Location.CilLocation locUnknown)); + (Pretty.dprintf "The program might not terminate! (Fundec %a is contained in a call graph cycle)\n" CilType.Fundec.pretty fundec_e, Some (M.Location.CilLocation fundec_e.svar.vdecl)); ] in M.msg_group Warning ~category:NonTerminating "Recursion cycle" msgs) else if not (LH.mem global_visited_calls call) then begin From a4991e0093f739aa1fc190d7cae40c1d93a1971d Mon Sep 17 00:00:00 2001 From: Thomas Lagemann Date: Wed, 21 Jun 2023 05:51:55 +0200 Subject: [PATCH 134/327] Adapted update_suite.rb and tests to termination output --- scripts/update_suite.rb | 71 ++++++++++--------- .../01-simple-loop-terminating.c | 4 +- .../02-simple-loop-nonterminating.c | 4 +- .../03-nested-loop-terminating.c | 6 +- .../04-nested-loop-nonterminating.c | 6 +- .../80-termination/05-for-loop-terminating.c | 4 +- .../06-for-loop-nonterminating.c | 4 +- .../07-nested-for-loop-terminating.c | 6 +- .../08-nested-for-loop-nonterminating.c | 6 +- .../09-complex-for-loop-terminating.c | 24 +++---- .../10-complex-loop-terminating.c | 24 +++---- .../80-termination/11-loopless-termination.c | 2 +- .../12-do-while-instant-terminating.c | 4 +- .../80-termination/13-do-while-terminating.c | 4 +- .../14-do-while-nonterminating.c | 4 +- .../15-complex-loop-combination-terminating.c | 34 ++++----- ...16-nested-loop-nontrivial-nonterminating.c | 6 +- .../80-termination/17-goto-terminating.c | 4 +- .../80-termination/18-goto-nonterminating.c | 4 +- .../80-termination/19-rand-terminating.c | 6 +- .../80-termination/20-rand-nonterminating.c | 6 +- .../21-no-exit-on-rand-unproofable.c | 3 +- .../22-exit-on-rand-unproofable.c | 3 +- .../23-exit-on-rand-terminating.c | 2 +- .../24-upjumping-goto-loopless-terminating.c | 2 +- .../25-leave-loop-goto-terminating.c | 2 +- .../26-enter-loop-goto-terminating.c | 2 +- .../27-upjumping-goto-nonterminating.c | 2 +- .../81-recursion/01-simple-terminating.c | 2 +- .../81-recursion/02-simple-nonterminating.c | 2 +- .../81-recursion/03-nested-terminating.c | 2 +- .../81-recursion/04-nested-nonterminating.c | 2 +- 32 files changed, 133 insertions(+), 124 deletions(-) diff --git a/scripts/update_suite.rb b/scripts/update_suite.rb index dead6cd8f1..69b3bae485 100755 --- a/scripts/update_suite.rb +++ b/scripts/update_suite.rb @@ -147,31 +147,30 @@ def collect_warnings @vars = $1 @evals = $2 end + if l =~ /\[NonTerminating\]/ then warnings[-2] = "non_local_term" end # Get NonTerminating warning next unless l =~ /(.*)\(.*?\:(\d+)(?:\:\d+)?(?:-(?:\d+)(?:\:\d+)?)?\)/ obj,i = $1,$2.to_i - ranking = ["other", "warn", "race", "norace", "deadlock", "nodeadlock", "success", "fail", "unknown", "term", "noterm"] - thiswarn = case obj - when /\(conf\. \d+\)/ then "race" - when /Deadlock/ then "deadlock" - when /lock (before|after):/ then "deadlock" - when /Assertion .* will fail/ then "fail" - when /Assertion .* will succeed/ then "success" - when /Assertion .* is unknown/ then "unknown" - when /invariant confirmed/ then "success" - when /invariant unconfirmed/ then "unknown" - when /invariant refuted/ then "fail" - when /^\[Warning\]/ then "warn" - when /^\[Error\]/ then "warn" - when /^\[Info\]/ then "warn" - when /^\[Success\]/ then "success" - when /^\[Terminating\]/ then "term" - when /^\[Nonterminating\]/ then "noterm" - when /\[Debug\]/ then next # debug "warnings" shouldn't count as other warnings (against NOWARN) - when /^ on line \d+ $/ then next # dead line warnings shouldn't count (used for unreachability with NOWARN) - when /^ on lines \d+..\d+ $/ then next # dead line warnings shouldn't count (used for unreachability with NOWARN) - else "other" - end + ranking = ["other", "warn", "local_term", "non_local_term", "race", "norace", "deadlock", "nodeadlock", "success", "fail", "unknown", "term", "noterm"] + thiswarn = case obj + when /\(conf\. \d+\)/ then "race" + when /Deadlock/ then "deadlock" + when /lock (before|after):/ then "deadlock" + when /Assertion .* will fail/ then "fail" + when /Assertion .* will succeed/ then "success" + when /Assertion .* is unknown/ then "unknown" + when /invariant confirmed/ then "success" + when /invariant unconfirmed/ then "unknown" + when /invariant refuted/ then "fail" + when /^\[Warning\]/ then "warn" + when /^\[Error\]/ then "warn" + when /^\[Info\]/ then "warn" + when /^\[Success\]/ then "success" + when /\[Debug\]/ then next # debug "warnings" shouldn't count as other warnings (against NOWARN) + when /^ on line \d+ $/ then next # dead line warnings shouldn't count (used for unreachability with NOWARN) + when /^ on lines \d+..\d+ $/ then next # dead line warnings shouldn't count (used for unreachability with NOWARN) + else "other" + end oldwarn = warnings[i] if oldwarn.nil? then warnings[i] = thiswarn @@ -189,17 +188,23 @@ def compare_warnings # full p.path is too long and p.name does not allow click to open in terminal if todo.include? idx then puts "Excellent: ignored check on #{relpath(p.path).to_s.cyan}:#{idx.to_s.blue} is now passing!" end else - if todo.include? idx then @ignored += 1 else - puts "Expected #{type.yellow}, but registered #{(warnings[idx] or "nothing").yellow} on #{p.name.cyan}:#{idx.to_s.blue}" - puts tests_line[idx].rstrip.gray - ferr = idx if ferr.nil? or idx < ferr + if todo.include? idx then + @ignored += 1 + else + if idx < 0 # When non line specific keywords were used don't print a line + puts "Expected #{type.yellow}, but registered #{(warnings[idx] or "nothing").yellow} on #{p.name.cyan}" + else + puts "Expected #{type.yellow}, but registered #{(warnings[idx] or "nothing").yellow} on #{p.name.cyan}:#{idx.to_s.blue}" + puts tests_line[idx].rstrip.gray + ferr = idx if ferr.nil? or idx < ferr + end end end } case type - when "deadlock", "race", "fail", "noterm", "unknown", "term", "warn" + when "deadlock", "race", "fail", "noterm", "unknown", "term", "warn", "non_local_term" check.call warnings[idx] == type - when "nowarn" + when "nowarn", "local_term" check.call warnings[idx].nil? when "assert", "success" check.call warnings[idx] == "success" @@ -300,10 +305,6 @@ def parse_tests (lines) tests[i] = "fail" elsif obj =~ /UNKNOWN/ then tests[i] = "unknown" - elsif obj =~ /NON?TERM/ then - tests[i] = "noterm" - elsif obj =~ /TERM/ then - tests[i] = "term" elsif obj =~ /(assert|__goblint_check).*\(/ then if obj =~ /FAIL/ then tests[i] = "fail" @@ -315,6 +316,12 @@ def parse_tests (lines) end end case lines[0] + when /NON_LOCAL_TERM/ + # covers "TERM" as keyword but a combined use of NON_LOCAL_TERM (loop termination) and TERM would be pointless + tests[-2] = "non_local_term" + when /LOCAL_TERM/ + # covers "TERM" as keyword but a combined use of NON_LOCAL_TERM (loop termination) and TERM would be pointless + tests[-2] = "local_term" when /NON?TERM/ tests[-1] = "noterm" when /TERM/ diff --git a/tests/regression/80-termination/01-simple-loop-terminating.c b/tests/regression/80-termination/01-simple-loop-terminating.c index 931b125171..a517d0d608 100644 --- a/tests/regression/80-termination/01-simple-loop-terminating.c +++ b/tests/regression/80-termination/01-simple-loop-terminating.c @@ -1,11 +1,11 @@ -// PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra +// LOCAL_TERM PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra #include int main() { int i = 1; - while (i <= 10) // TERM + while (i <= 10) { printf("%d\n", i); i++; diff --git a/tests/regression/80-termination/02-simple-loop-nonterminating.c b/tests/regression/80-termination/02-simple-loop-nonterminating.c index 520a4a82e0..bcb9909f80 100644 --- a/tests/regression/80-termination/02-simple-loop-nonterminating.c +++ b/tests/regression/80-termination/02-simple-loop-nonterminating.c @@ -1,9 +1,9 @@ -// PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra +// NON_LOCAL_TERM PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra #include int main() { - while (1) // NOTERM + while (1) { continue; } diff --git a/tests/regression/80-termination/03-nested-loop-terminating.c b/tests/regression/80-termination/03-nested-loop-terminating.c index 172827af42..366cbaeea5 100644 --- a/tests/regression/80-termination/03-nested-loop-terminating.c +++ b/tests/regression/80-termination/03-nested-loop-terminating.c @@ -1,4 +1,4 @@ -// PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra +// LOCAL_TERM PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra #include int main() @@ -9,12 +9,12 @@ int main() // Outer while loop for rows while (i <= rows) - { // TERM + { int j = 1; // Inner while loop for columns while (j <= columns) - { // TERM + { printf("(%d, %d) ", i, j); j++; } diff --git a/tests/regression/80-termination/04-nested-loop-nonterminating.c b/tests/regression/80-termination/04-nested-loop-nonterminating.c index 37af9ed6fb..ee2aa4a8c4 100644 --- a/tests/regression/80-termination/04-nested-loop-nonterminating.c +++ b/tests/regression/80-termination/04-nested-loop-nonterminating.c @@ -1,15 +1,15 @@ -// PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra +// NON_LOCAL_TERM PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra #include int main() { int outerCount = 1; - while (outerCount <= 3) // NOTERM + while (outerCount <= 3) { int innerCount = 1; - while (1) // NOTERM + while (1) { printf("(%d, %d) ", outerCount, innerCount); innerCount++; diff --git a/tests/regression/80-termination/05-for-loop-terminating.c b/tests/regression/80-termination/05-for-loop-terminating.c index ab286a6dd4..2a16184f6d 100644 --- a/tests/regression/80-termination/05-for-loop-terminating.c +++ b/tests/regression/80-termination/05-for-loop-terminating.c @@ -1,11 +1,11 @@ -// PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra +// LOCAL_TERM PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra #include int main() { int i; - for (i = 1; i <= 10; i++) // TERM + for (i = 1; i <= 10; i++) { printf("%d\n", i); } diff --git a/tests/regression/80-termination/06-for-loop-nonterminating.c b/tests/regression/80-termination/06-for-loop-nonterminating.c index 466001e6e5..b8f30361d1 100644 --- a/tests/regression/80-termination/06-for-loop-nonterminating.c +++ b/tests/regression/80-termination/06-for-loop-nonterminating.c @@ -1,8 +1,8 @@ -// PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra +// NON_LOCAL_TERM PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra #include int main() { - for (;;) { // NOTERM + for (;;) { printf("This loop does not terminate.\n"); } diff --git a/tests/regression/80-termination/07-nested-for-loop-terminating.c b/tests/regression/80-termination/07-nested-for-loop-terminating.c index eec4dda908..def0787d39 100644 --- a/tests/regression/80-termination/07-nested-for-loop-terminating.c +++ b/tests/regression/80-termination/07-nested-for-loop-terminating.c @@ -1,4 +1,4 @@ -// PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra +// LOCAL_TERM PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra #include int main() @@ -7,9 +7,9 @@ int main() int columns = 4; // Nested loop to iterate over rows and columns - for (int i = 1; i <= rows; i++) // TERM + for (int i = 1; i <= rows; i++) { - for (int j = 1; j <= columns; j++) // TERM + for (int j = 1; j <= columns; j++) { printf("(%d, %d) ", i, j); } diff --git a/tests/regression/80-termination/08-nested-for-loop-nonterminating.c b/tests/regression/80-termination/08-nested-for-loop-nonterminating.c index 3f7bcb4f07..0368120b13 100644 --- a/tests/regression/80-termination/08-nested-for-loop-nonterminating.c +++ b/tests/regression/80-termination/08-nested-for-loop-nonterminating.c @@ -1,13 +1,13 @@ -// PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra +// NON_LOCAL_TERM PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra #include int main() { int outerCount, innerCount; - for (outerCount = 1; outerCount <= 3; outerCount++) // NOTERM + for (outerCount = 1; outerCount <= 3; outerCount++) { - for (innerCount = 1;; innerCount++) // NOTERM + for (innerCount = 1;; innerCount++) { printf("(%d, %d) ", outerCount, innerCount); } diff --git a/tests/regression/80-termination/09-complex-for-loop-terminating.c b/tests/regression/80-termination/09-complex-for-loop-terminating.c index ed28fa9b43..ae68b11575 100644 --- a/tests/regression/80-termination/09-complex-for-loop-terminating.c +++ b/tests/regression/80-termination/09-complex-for-loop-terminating.c @@ -1,4 +1,4 @@ -// PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra +// LOCAL_TERM PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra #include int main() @@ -6,17 +6,17 @@ int main() int i, j, k; // Outer loop - for (i = 1; i <= 5; i++) // TERM + for (i = 1; i <= 5; i++) { // Inner loop 1 - for (j = 1; j <= i; j++) // TERM + for (j = 1; j <= i; j++) { printf("%d ", j); } printf("\n"); // Inner loop 2 - for (k = i; k >= 1; k--) // TERM + for (k = i; k >= 1; k--) { printf("%d ", k); } @@ -24,9 +24,9 @@ int main() } // Additional loop - for (i = 5; i >= 1; i--) // TERM + for (i = 5; i >= 1; i--) { - for (j = i; j >= 1; j--) // TERM + for (j = i; j >= 1; j--) { printf("%d ", j); } @@ -34,7 +34,7 @@ int main() } // Loop with conditions - for (i = 1; i <= 10; i++) // TERM + for (i = 1; i <= 10; i++) { if (i % 2 == 0) { @@ -47,7 +47,7 @@ int main() } // Loop with nested conditions - for (i = 1; i <= 10; i++) // TERM + for (i = 1; i <= 10; i++) { printf("Number: %d - ", i); if (i < 5) @@ -65,7 +65,7 @@ int main() } // Loop with a break statement - for (i = 1; i <= 10; i++) // TERM + for (i = 1; i <= 10; i++) { printf("%d ", i); if (i == 5) @@ -76,7 +76,7 @@ int main() printf("\n"); // Loop with a continue statement - for (i = 1; i <= 10; i++) // TERM + for (i = 1; i <= 10; i++) { if (i % 2 == 0) { @@ -87,7 +87,7 @@ int main() printf("\n"); // Loop with complex conditions - for (i = 1; i <= 10; i++) // TERM + for (i = 1; i <= 10; i++) { if (i > 5 && i % 2 == 0) { @@ -98,7 +98,7 @@ int main() // Loop with multiple variables int a, b, c; - for (a = 1, b = 2, c = 3; a <= 10; a++, b += 2, c += 3) // TERM + for (a = 1, b = 2, c = 3; a <= 10; a++, b += 2, c += 3) { printf("%d %d %d\n", a, b, c); } diff --git a/tests/regression/80-termination/10-complex-loop-terminating.c b/tests/regression/80-termination/10-complex-loop-terminating.c index 3a19f17bee..eb79338078 100644 --- a/tests/regression/80-termination/10-complex-loop-terminating.c +++ b/tests/regression/80-termination/10-complex-loop-terminating.c @@ -1,4 +1,4 @@ -// PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra +// LOCAL_TERM PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra #include int main() @@ -8,10 +8,10 @@ int main() int k = 5; // Outer while loop - while (i <= 5) // TERM + while (i <= 5) { // Inner while loop 1 - while (j <= i) // TERM + while (j <= i) { printf("%d ", j); j++; @@ -20,7 +20,7 @@ int main() j = 1; // Inner while loop 2 - while (k >= 1) // TERM + while (k >= 1) { printf("%d ", k); k--; @@ -33,10 +33,10 @@ int main() // Additional while loop i = 5; - while (i >= 1) // TERM + while (i >= 1) { j = i; - while (j >= 1) // TERM + while (j >= 1) { printf("%d ", j); j--; @@ -47,7 +47,7 @@ int main() // Loop with conditions i = 1; - while (i <= 10) // TERM + while (i <= 10) { if (i % 2 == 0) { @@ -62,7 +62,7 @@ int main() // Loop with nested conditions i = 1; - while (i <= 10) // TERM + while (i <= 10) { printf("Number: %d - ", i); if (i < 5) @@ -82,7 +82,7 @@ int main() // Loop with a break statement i = 1; - while (i <= 10) // TERM + while (i <= 10) { printf("%d ", i); if (i == 5) @@ -95,7 +95,7 @@ int main() // Loop with a continue statement i = 1; - while (i <= 10) // TERM + while (i <= 10) { if (i % 2 == 0) { @@ -109,7 +109,7 @@ int main() // Loop with complex conditions i = 1; - while (i <= 10) // TERM + while (i <= 10) { if (i > 5 && i % 2 == 0) { @@ -123,7 +123,7 @@ int main() int a = 1; int b = 2; int c = 3; - while (a <= 10) // TERM + while (a <= 10) { printf("%d %d %d\n", a, b, c); a++; diff --git a/tests/regression/80-termination/11-loopless-termination.c b/tests/regression/80-termination/11-loopless-termination.c index 7aeed0145d..86a300f18e 100644 --- a/tests/regression/80-termination/11-loopless-termination.c +++ b/tests/regression/80-termination/11-loopless-termination.c @@ -1,4 +1,4 @@ -// PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra +// LOCAL_TERM PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra #include int main() { diff --git a/tests/regression/80-termination/12-do-while-instant-terminating.c b/tests/regression/80-termination/12-do-while-instant-terminating.c index cc3cc41edc..15032b7b4f 100644 --- a/tests/regression/80-termination/12-do-while-instant-terminating.c +++ b/tests/regression/80-termination/12-do-while-instant-terminating.c @@ -1,11 +1,11 @@ -// PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra +// LOCAL_TERM PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra #include int main() { int i = 0; - do // TERM + do { printf("Inside the do-while loop\n"); } while (i > 0); diff --git a/tests/regression/80-termination/13-do-while-terminating.c b/tests/regression/80-termination/13-do-while-terminating.c index 05fe270f04..2e04f3e393 100644 --- a/tests/regression/80-termination/13-do-while-terminating.c +++ b/tests/regression/80-termination/13-do-while-terminating.c @@ -1,11 +1,11 @@ -// PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra +// LOCAL_TERM PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra #include int main() { int i = 1; - do // TERM + do { printf("Inside the do-while loop\n"); i++; diff --git a/tests/regression/80-termination/14-do-while-nonterminating.c b/tests/regression/80-termination/14-do-while-nonterminating.c index 1c70d4fc76..5ed18175e9 100644 --- a/tests/regression/80-termination/14-do-while-nonterminating.c +++ b/tests/regression/80-termination/14-do-while-nonterminating.c @@ -1,11 +1,11 @@ -// PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra +// NON_LOCAL_TERM PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra #include int main() { int i = 1; - do // NOTERM + do { printf("Inside the do-while loop\n"); i++; diff --git a/tests/regression/80-termination/15-complex-loop-combination-terminating.c b/tests/regression/80-termination/15-complex-loop-combination-terminating.c index e5383aed66..f3a08f4139 100644 --- a/tests/regression/80-termination/15-complex-loop-combination-terminating.c +++ b/tests/regression/80-termination/15-complex-loop-combination-terminating.c @@ -1,4 +1,4 @@ -// PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra +// LOCAL_TERM PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra #include int main() @@ -7,14 +7,14 @@ int main() int i; // for loop - for (i = 1; i <= 10; i++) // TERM + for (i = 1; i <= 10; i++) { printf("For loop iteration: %d\n", i); } // while loop int j = 1; - while (j <= 10) // TERM + while (j <= 10) { printf("While loop iteration: %d\n", j); j++; @@ -22,7 +22,7 @@ int main() // do-while loop int k = 1; - do // TERM + do { printf("Do-While loop iteration: %d\n", k); k++; @@ -32,10 +32,10 @@ int main() int a, b; // Nested for and while loop - for (a = 1; a <= 5; a++) // TERM + for (a = 1; a <= 5; a++) { int c = 1; - while (c <= a) // TERM + while (c <= a) { printf("Nested For-While loop: %d\n", c); c++; @@ -44,10 +44,10 @@ int main() // Nested while and do-while loop int x = 1; - while (x <= 5) // TERM + while (x <= 5) { int y = 1; - do // TERM + do { printf("Nested While-Do-While loop: %d\n", y); y++; @@ -57,9 +57,9 @@ int main() // Nested do-while and for loop int p = 1; - do // TERM + do { - for (int q = 1; q <= p; q++) // TERM + for (int q = 1; q <= p; q++) { printf("Nested Do-While-For loop: %d\n", q); } @@ -71,11 +71,11 @@ int main() // Nested while loop with a break statement int n = 1; - while (n <= 5) // TERM + while (n <= 5) { printf("Outer While loop iteration: %d\n", n); m = 1; - while (1) // TERM + while (1) { printf("Inner While loop iteration: %d\n", m); m++; @@ -88,7 +88,7 @@ int main() } // Loop with a continue statement - for (int r = 1; r <= 10; r++) // TERM + for (int r = 1; r <= 10; r++) { if (r % 3 == 0) { @@ -99,7 +99,7 @@ int main() // Loop with multiple conditions int s = 1; - while (s <= 10 && s % 2 == 0) // TERM + while (s <= 10 && s % 2 == 0) { printf("Loop with Multiple Conditions: %d\n", s); s++; @@ -107,13 +107,13 @@ int main() // Loop with multiple variables int t, u; - for (t = 1, u = 10; t <= 5 && u >= 5; t++, u--) // TERM + for (t = 1, u = 10; t <= 5 && u >= 5; t++, u--) { printf("Loop with Multiple Variables: %d %d\n", t, u); } // Loop with nested conditions - for (int v = 1; v <= 10; v++) // TERM + for (int v = 1; v <= 10; v++) { printf("Loop with Nested Conditions: %d - ", v); if (v < 5) @@ -137,7 +137,7 @@ int main() { printf("Loop with Label and Goto: %d\n", w); w++; - goto start; // TERM + goto start; } return 0; diff --git a/tests/regression/80-termination/16-nested-loop-nontrivial-nonterminating.c b/tests/regression/80-termination/16-nested-loop-nontrivial-nonterminating.c index 855fbd0dca..5ff890e461 100644 --- a/tests/regression/80-termination/16-nested-loop-nontrivial-nonterminating.c +++ b/tests/regression/80-termination/16-nested-loop-nontrivial-nonterminating.c @@ -1,15 +1,15 @@ -// PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra +// NON_LOCAL_TERM PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra #include int main() { int outerCount = 1; - while (outerCount <= 3) // NOTERM + while (outerCount <= 3) { int innerCount = 1; - while (outerCount < 3 || innerCount > 0) // NOTERM + while (outerCount < 3 || innerCount > 0) { printf("(%d, %d) ", outerCount, innerCount); innerCount++; diff --git a/tests/regression/80-termination/17-goto-terminating.c b/tests/regression/80-termination/17-goto-terminating.c index dcf72552bc..b66fbe57ea 100644 --- a/tests/regression/80-termination/17-goto-terminating.c +++ b/tests/regression/80-termination/17-goto-terminating.c @@ -1,11 +1,11 @@ -// PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra +// LOCAL_TERM PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra #include int main() { int num = 1; -loop: // TERM +loop: printf("Current number: %d\n", num); num++; diff --git a/tests/regression/80-termination/18-goto-nonterminating.c b/tests/regression/80-termination/18-goto-nonterminating.c index 672128e009..cfe5ab481d 100644 --- a/tests/regression/80-termination/18-goto-nonterminating.c +++ b/tests/regression/80-termination/18-goto-nonterminating.c @@ -1,11 +1,11 @@ -// PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra +// NON_LOCAL_TERM PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra #include int main() { int num = 1; -loop: // NOTERM +loop: printf("Current number: %d\n", num); num++; diff --git a/tests/regression/80-termination/19-rand-terminating.c b/tests/regression/80-termination/19-rand-terminating.c index 879ae3748a..426c5cdcca 100644 --- a/tests/regression/80-termination/19-rand-terminating.c +++ b/tests/regression/80-termination/19-rand-terminating.c @@ -1,4 +1,4 @@ -// PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra +// LOCAL_TERM PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra #include #include #include @@ -11,7 +11,7 @@ int main() if (rand()) { // Loop inside the if part - for (int i = 1; i <= 5; i++) // TERM + for (int i = 1; i <= 5; i++) { printf("Loop inside if part: %d\n", i); } @@ -20,7 +20,7 @@ int main() { // Loop inside the else part int j = 1; - while (j <= 5) // TERM + while (j <= 5) { printf("Loop inside else part: %d\n", j); j++; diff --git a/tests/regression/80-termination/20-rand-nonterminating.c b/tests/regression/80-termination/20-rand-nonterminating.c index 27c3f2c388..7c21538612 100644 --- a/tests/regression/80-termination/20-rand-nonterminating.c +++ b/tests/regression/80-termination/20-rand-nonterminating.c @@ -1,4 +1,4 @@ -// PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra +// NON_LOCAL_TERM PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra #include #include #include @@ -11,7 +11,7 @@ int main() if (rand()) { // Loop inside the if part - for (int i = 1; i >= 0; i++) // NOTERM + for (int i = 1; i >= 0; i++) { printf("Loop inside if part: %d\n", i); } @@ -20,7 +20,7 @@ int main() { // Loop inside the else part int j = 1; - while (j > 0) // NOTERM + while (j > 0) { printf("Loop inside else part: %d\n", j); } diff --git a/tests/regression/80-termination/21-no-exit-on-rand-unproofable.c b/tests/regression/80-termination/21-no-exit-on-rand-unproofable.c index 0edafe0f65..f54af1da7c 100644 --- a/tests/regression/80-termination/21-no-exit-on-rand-unproofable.c +++ b/tests/regression/80-termination/21-no-exit-on-rand-unproofable.c @@ -1,10 +1,11 @@ -// PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra +// NON_LOCAL_TERM PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra #include int main() { int forever, i = 0; +// This loop is not provable, therefore it should throw a warning while (i < 4 || forever == 1) { i++; diff --git a/tests/regression/80-termination/22-exit-on-rand-unproofable.c b/tests/regression/80-termination/22-exit-on-rand-unproofable.c index 5c270f3b2a..1bc104258d 100644 --- a/tests/regression/80-termination/22-exit-on-rand-unproofable.c +++ b/tests/regression/80-termination/22-exit-on-rand-unproofable.c @@ -1,10 +1,11 @@ -// PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra +// NON_LOCAL_TERM PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra #include int main() { int forever = 1; +// This loop is not provable, therefore it should throw a warning while (forever == 1) { if (rand()) //May exit, may not diff --git a/tests/regression/80-termination/23-exit-on-rand-terminating.c b/tests/regression/80-termination/23-exit-on-rand-terminating.c index 228fc3b15e..9d000069e1 100644 --- a/tests/regression/80-termination/23-exit-on-rand-terminating.c +++ b/tests/regression/80-termination/23-exit-on-rand-terminating.c @@ -1,4 +1,4 @@ -// PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra +// LOCAL_TERM PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra #include #include diff --git a/tests/regression/80-termination/24-upjumping-goto-loopless-terminating.c b/tests/regression/80-termination/24-upjumping-goto-loopless-terminating.c index f4b6b8fbe2..a774f70457 100644 --- a/tests/regression/80-termination/24-upjumping-goto-loopless-terminating.c +++ b/tests/regression/80-termination/24-upjumping-goto-loopless-terminating.c @@ -1,4 +1,4 @@ -// PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra +// LOCAL_TERM PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra #include int main() { diff --git a/tests/regression/80-termination/25-leave-loop-goto-terminating.c b/tests/regression/80-termination/25-leave-loop-goto-terminating.c index c30e65f44b..28d8824535 100644 --- a/tests/regression/80-termination/25-leave-loop-goto-terminating.c +++ b/tests/regression/80-termination/25-leave-loop-goto-terminating.c @@ -1,4 +1,4 @@ -// PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra +// LOCAL_TERM PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra #include int main() { diff --git a/tests/regression/80-termination/26-enter-loop-goto-terminating.c b/tests/regression/80-termination/26-enter-loop-goto-terminating.c index 5d34e5c523..41bf44c44e 100644 --- a/tests/regression/80-termination/26-enter-loop-goto-terminating.c +++ b/tests/regression/80-termination/26-enter-loop-goto-terminating.c @@ -1,4 +1,4 @@ -// PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra +// LOCAL_TERM PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra #include int main() { diff --git a/tests/regression/80-termination/27-upjumping-goto-nonterminating.c b/tests/regression/80-termination/27-upjumping-goto-nonterminating.c index 6e4432dc5e..a230827356 100644 --- a/tests/regression/80-termination/27-upjumping-goto-nonterminating.c +++ b/tests/regression/80-termination/27-upjumping-goto-nonterminating.c @@ -1,4 +1,4 @@ -// PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra +// NON_LOCAL_TERM PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra #include int main() { diff --git a/tests/regression/81-recursion/01-simple-terminating.c b/tests/regression/81-recursion/01-simple-terminating.c index 1c52faec68..4f09950025 100644 --- a/tests/regression/81-recursion/01-simple-terminating.c +++ b/tests/regression/81-recursion/01-simple-terminating.c @@ -1,4 +1,4 @@ -// PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra +// LOCAL_TERM PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra #include void recursiveFunction(int n) { diff --git a/tests/regression/81-recursion/02-simple-nonterminating.c b/tests/regression/81-recursion/02-simple-nonterminating.c index a6d6b3ab17..3ed0b75a0d 100644 --- a/tests/regression/81-recursion/02-simple-nonterminating.c +++ b/tests/regression/81-recursion/02-simple-nonterminating.c @@ -1,4 +1,4 @@ -// PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra +// NON_LOCAL_TERM PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra #include void recursiveFunction(int n) { diff --git a/tests/regression/81-recursion/03-nested-terminating.c b/tests/regression/81-recursion/03-nested-terminating.c index 096a1b0121..23bedef644 100644 --- a/tests/regression/81-recursion/03-nested-terminating.c +++ b/tests/regression/81-recursion/03-nested-terminating.c @@ -1,4 +1,4 @@ -// PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra +// LOCAL_TERM PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra #include void innerRecursiveFunction(int n) { diff --git a/tests/regression/81-recursion/04-nested-nonterminating.c b/tests/regression/81-recursion/04-nested-nonterminating.c index ab5e35d80f..d28685e139 100644 --- a/tests/regression/81-recursion/04-nested-nonterminating.c +++ b/tests/regression/81-recursion/04-nested-nonterminating.c @@ -1,4 +1,4 @@ -// PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra +// NON_LOCAL_TERM PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra #include void innerRecursiveFunction() { From 7a6b18cbe37d21f9cff1ca0797b2cbc5088da804 Mon Sep 17 00:00:00 2001 From: Johanna Schinabeck Date: Wed, 21 Jun 2023 14:07:23 +0200 Subject: [PATCH 135/327] reverted test case --- output.txt | 464 ++++++++++++++++++++++++++--------------------------- 1 file changed, 231 insertions(+), 233 deletions(-) diff --git a/output.txt b/output.txt index d751966836..37eb310726 100644 --- a/output.txt +++ b/output.txt @@ -131,7 +131,7 @@ typedef long __intptr_t; typedef unsigned int __socklen_t; #line 215 "/usr/include/x86_64-linux-gnu/bits/types.h" typedef int __sig_atomic_t; -#line 209 "/usr/lib/gcc/x86_64-linux-gnu/10/include/stddef.h" +#line 209 "/usr/lib/gcc/x86_64-linux-gnu/11/include/stddef.h" typedef unsigned long size_t; #line 10 "/usr/include/x86_64-linux-gnu/bits/types/time_t.h" typedef __time_t time_t; @@ -201,12 +201,12 @@ struct __anonstruct___value32_817613185 { unsigned int __high ; }; #line 25 "/usr/include/x86_64-linux-gnu/bits/atomic_wide_counter.h" -union __anonunion___atomic_wide_counter_1044835921 { +union __anonunion___atomic_wide_counter_316368393 { unsigned long long __value64 ; struct __anonstruct___value32_817613185 __value32 ; }; #line 25 "/usr/include/x86_64-linux-gnu/bits/atomic_wide_counter.h" -typedef union __anonunion___atomic_wide_counter_1044835921 __atomic_wide_counter; +typedef union __anonunion___atomic_wide_counter_316368393 __atomic_wide_counter; #line 51 "/usr/include/x86_64-linux-gnu/bits/thread-shared-types.h" struct __pthread_internal_list { struct __pthread_internal_list *__prev ; @@ -261,11 +261,11 @@ typedef unsigned int __tss_t; #line 106 "/usr/include/x86_64-linux-gnu/bits/thread-shared-types.h" typedef unsigned long __thrd_t; #line 108 "/usr/include/x86_64-linux-gnu/bits/thread-shared-types.h" -struct __anonstruct___once_flag_1044835922 { +struct __anonstruct___once_flag_826868709 { int __data ; }; #line 108 "/usr/include/x86_64-linux-gnu/bits/thread-shared-types.h" -typedef struct __anonstruct___once_flag_1044835922 __once_flag; +typedef struct __anonstruct___once_flag_826868709 __once_flag; #line 27 "/usr/include/x86_64-linux-gnu/bits/pthreadtypes.h" typedef unsigned long pthread_t; #line 32 "/usr/include/x86_64-linux-gnu/bits/pthreadtypes.h" @@ -441,16 +441,16 @@ struct __pthread_cleanup_frame { int __do_it ; int __cancel_type ; }; -#line 143 "/usr/lib/gcc/x86_64-linux-gnu/10/include/stddef.h" +#line 143 "/usr/lib/gcc/x86_64-linux-gnu/11/include/stddef.h" typedef long ptrdiff_t; -#line 321 "/usr/lib/gcc/x86_64-linux-gnu/10/include/stddef.h" +#line 321 "/usr/lib/gcc/x86_64-linux-gnu/11/include/stddef.h" typedef int wchar_t; -#line 415 "/usr/lib/gcc/x86_64-linux-gnu/10/include/stddef.h" +#line 415 "/usr/lib/gcc/x86_64-linux-gnu/11/include/stddef.h" struct __anonstruct_max_align_t_896270833 { long long __max_align_ll __attribute__((__aligned__(__alignof__(long long )))) ; long double __max_align_ld __attribute__((__aligned__(__alignof__(long double )))) ; }; -#line 415 "/usr/lib/gcc/x86_64-linux-gnu/10/include/stddef.h" +#line 415 "/usr/lib/gcc/x86_64-linux-gnu/11/include/stddef.h" typedef struct __anonstruct_max_align_t_896270833 max_align_t; /* compiler builtin: void __builtin_va_copy(__builtin_va_list , __builtin_va_list ) ; */ @@ -1115,496 +1115,494 @@ void example1(void) } #line 27 term27_5-file_01-simple-cases ++; +#line 27 + term_exit- = term27_5-file_01-simple-cases; #line 28 a[i] = i; -#line 29 - i ++; } while_break: /* CIL Label */ ; } -#line 27 - term_exit- = term27_5-file_01-simple-cases; } -#line 32 +#line 31 __goblint_check(a[0] == 0); -#line 33 +#line 32 __goblint_check(a[3] == 3); -#line 34 +#line 33 return; } } -#line 37 "tests/regression/55-loop-unrolling/01-simple-cases.c" +#line 36 "tests/regression/55-loop-unrolling/01-simple-cases.c" void example2(void) { int a[5] ; int i ; - int term42_5-file_01-simple-cases ; + int term41_5-file_01-simple-cases ; { -#line 40 +#line 39 i = 0; { -#line 42 - term42_5-file_01-simple-cases = 0; +#line 41 + term41_5-file_01-simple-cases = 0; { -#line 42 +#line 41 while (1) { while_continue: /* CIL Label */ ; -#line 43 +#line 42 a[i] = i; -#line 44 +#line 43 i ++; -#line 42 - term42_5-file_01-simple-cases ++; -#line 42 +#line 41 + term41_5-file_01-simple-cases ++; +#line 41 + term_exit- = term41_5-file_01-simple-cases; +#line 41 if (! (i <= 5)) { -#line 42 +#line 41 goto while_break; } } while_break: /* CIL Label */ ; } -#line 42 - term_exit- = term42_5-file_01-simple-cases; } -#line 47 +#line 46 __goblint_check(a[0] == 0); -#line 48 +#line 47 __goblint_check(a[3] == 3); -#line 49 +#line 48 return; } } -#line 52 "tests/regression/55-loop-unrolling/01-simple-cases.c" +#line 51 "tests/regression/55-loop-unrolling/01-simple-cases.c" void example3(void) { int a[10] ; int i ; - int term57_5-file_01-simple-cases ; + int term56_5-file_01-simple-cases ; { -#line 55 +#line 54 i = 0; { -#line 57 - term57_5-file_01-simple-cases = 0; +#line 56 + term56_5-file_01-simple-cases = 0; { -#line 57 +#line 56 while (1) { while_continue: /* CIL Label */ ; -#line 57 +#line 56 if (! (i < 5)) { -#line 57 +#line 56 goto while_break; } +#line 56 + term56_5-file_01-simple-cases ++; +#line 56 + term_exit- = term56_5-file_01-simple-cases; #line 57 - term57_5-file_01-simple-cases ++; -#line 58 a[i] = i; -#line 59 +#line 58 i ++; } while_break: /* CIL Label */ ; } -#line 57 - term_exit- = term57_5-file_01-simple-cases; } -#line 62 +#line 61 __goblint_check(a[0] == 0); -#line 63 +#line 62 __goblint_check(a[3] == 0); -#line 64 +#line 63 __goblint_check(a[7] == 0); -#line 65 +#line 64 return; } } -#line 68 "tests/regression/55-loop-unrolling/01-simple-cases.c" +#line 67 "tests/regression/55-loop-unrolling/01-simple-cases.c" void example4(void) { int a[10] ; int i ; int first_iteration ; - int term74_5-file_01-simple-cases ; + int term73_5-file_01-simple-cases ; { -#line 71 +#line 70 i = 0; -#line 72 +#line 71 first_iteration = 1; { -#line 74 - term74_5-file_01-simple-cases = 0; +#line 73 + term73_5-file_01-simple-cases = 0; { -#line 74 +#line 73 while (1) { while_continue: /* CIL Label */ ; -#line 74 +#line 73 if (! (i < 10)) { -#line 74 +#line 73 goto while_break; } +#line 73 + term73_5-file_01-simple-cases ++; +#line 73 + term_exit- = term73_5-file_01-simple-cases; #line 74 - term74_5-file_01-simple-cases ++; -#line 75 if (first_iteration == 1) { -#line 75 +#line 74 __goblint_check(i == 0); } else -#line 76 +#line 75 if (i > 5) { -#line 76 +#line 75 __goblint_check(i == 6); } -#line 77 +#line 76 first_iteration = 0; -#line 78 +#line 77 a[i] = 0; -#line 79 +#line 78 i ++; } while_break: /* CIL Label */ ; } -#line 74 - term_exit- = term74_5-file_01-simple-cases; } -#line 82 +#line 81 __goblint_check(a[0] == 0); -#line 83 +#line 82 __goblint_check(first_iteration == 0); -#line 84 +#line 83 return; } } -#line 89 "tests/regression/55-loop-unrolling/01-simple-cases.c" +#line 88 "tests/regression/55-loop-unrolling/01-simple-cases.c" void example5(void) { int a[4] ; int i ; int top ; - int term95_5-file_01-simple-cases ; + int term94_5-file_01-simple-cases ; { -#line 92 +#line 91 i = 0; -#line 93 +#line 92 top = 0; { -#line 95 - term95_5-file_01-simple-cases = 0; +#line 94 + term94_5-file_01-simple-cases = 0; { -#line 95 +#line 94 while (1) { while_continue: /* CIL Label */ ; -#line 95 +#line 94 if (! (i < 4)) { -#line 95 +#line 94 goto while_break; } +#line 94 + term94_5-file_01-simple-cases ++; +#line 94 + term_exit- = term94_5-file_01-simple-cases; #line 95 - term95_5-file_01-simple-cases ++; -#line 96 a[i] = 0; -#line 97 +#line 96 top += i; -#line 98 +#line 97 if (i == 2) { -#line 99 +#line 98 __goblint_check(top == 3); } else { -#line 102 +#line 101 __goblint_check(top == 3); } -#line 104 +#line 103 i ++; } while_break: /* CIL Label */ ; } -#line 95 - term_exit- = term95_5-file_01-simple-cases; } -#line 107 +#line 106 __goblint_check(a[0] == 0); -#line 108 +#line 107 __goblint_check(a[3] == 0); -#line 109 +#line 108 __goblint_check(top == 6); -#line 110 +#line 109 return; } } -#line 113 "tests/regression/55-loop-unrolling/01-simple-cases.c" +#line 112 "tests/regression/55-loop-unrolling/01-simple-cases.c" void example6(void) { int a[5] ; int i ; int top ; - int term119_5-file_01-simple-cases ; + int term118_5-file_01-simple-cases ; { -#line 116 +#line 115 i = 0; -#line 117 +#line 116 top = 0; { -#line 119 - term119_5-file_01-simple-cases = 0; +#line 118 + term118_5-file_01-simple-cases = 0; { -#line 119 +#line 118 while (1) { while_continue: /* CIL Label */ ; -#line 119 +#line 118 if (! (i < 3)) { -#line 119 +#line 118 goto while_break; } +#line 118 + term118_5-file_01-simple-cases ++; +#line 118 + term_exit- = term118_5-file_01-simple-cases; #line 119 - term119_5-file_01-simple-cases ++; -#line 120 a[i] = 0; -#line 121 +#line 120 __goblint_check(a[0] == 0); -#line 122 +#line 121 i ++; } while_break: /* CIL Label */ ; } -#line 119 - term_exit- = term119_5-file_01-simple-cases; } -#line 125 +#line 124 __goblint_check(a[0] == 0); -#line 126 +#line 125 __goblint_check(a[3] == 0); -#line 127 +#line 126 __goblint_check(top == 6); -#line 128 +#line 127 return; } } -#line 131 "tests/regression/55-loop-unrolling/01-simple-cases.c" +#line 130 "tests/regression/55-loop-unrolling/01-simple-cases.c" int update(int i ) { { -#line 132 +#line 131 if (i > 5) { -#line 133 +#line 132 return (0); } else { -#line 136 +#line 135 return (1); } } } -#line 139 "tests/regression/55-loop-unrolling/01-simple-cases.c" +#line 138 "tests/regression/55-loop-unrolling/01-simple-cases.c" void example7(void) { int a[10] ; int i ; int tmp ; - int term143_2-file_01-simple-cases ; + int term142_2-file_01-simple-cases ; { -#line 142 +#line 141 i = 0; { -#line 143 - term143_2-file_01-simple-cases = 0; +#line 142 + term142_2-file_01-simple-cases = 0; { -#line 143 +#line 142 while (1) { while_continue: /* CIL Label */ ; -#line 143 +#line 142 tmp = update(i); -#line 143 - term143_2-file_01-simple-cases ++; -#line 143 +#line 142 + term142_2-file_01-simple-cases ++; +#line 142 + term_exit- = term142_2-file_01-simple-cases; +#line 142 if (! tmp) { -#line 143 +#line 142 goto while_break; } -#line 144 +#line 143 a[i] = i; -#line 145 +#line 144 i ++; } while_break: /* CIL Label */ ; } -#line 143 - term_exit- = term143_2-file_01-simple-cases; } -#line 147 +#line 146 __goblint_check(a[0] == 0); -#line 148 +#line 147 __goblint_check(a[6] == 0); -#line 149 +#line 148 return; } } -#line 152 "tests/regression/55-loop-unrolling/01-simple-cases.c" +#line 151 "tests/regression/55-loop-unrolling/01-simple-cases.c" void example8(void) { int a[5] ; int b[5] ; int i ; int j ; - int term160_9-file_01-simple-cases ; - int term157_2-file_01-simple-cases ; + int term159_9-file_01-simple-cases ; + int term156_2-file_01-simple-cases ; { -#line 155 +#line 154 b[0] = 0; -#line 155 +#line 154 b[1] = 0; -#line 155 +#line 154 b[2] = 0; -#line 155 +#line 154 b[3] = 0; -#line 155 +#line 154 b[4] = 0; -#line 156 +#line 155 i = 0; { -#line 157 - term157_2-file_01-simple-cases = 0; +#line 156 + term156_2-file_01-simple-cases = 0; { -#line 157 +#line 156 while (1) { while_continue: /* CIL Label */ ; -#line 157 +#line 156 if (! (i < 5)) { -#line 157 +#line 156 goto while_break; } +#line 156 + term156_2-file_01-simple-cases ++; +#line 156 + term_exit- = term156_2-file_01-simple-cases; #line 157 - term157_2-file_01-simple-cases ++; -#line 158 a[i] = i; -#line 159 +#line 158 j = 0; { -#line 160 - term160_9-file_01-simple-cases = 0; +#line 159 + term159_9-file_01-simple-cases = 0; { -#line 160 +#line 159 while (1) { while_continue___0: /* CIL Label */ ; -#line 160 +#line 159 if (! (j < 5)) { -#line 160 +#line 159 goto while_break___0; } +#line 159 + term159_9-file_01-simple-cases ++; +#line 159 + term_exit- = term159_9-file_01-simple-cases; #line 160 - term160_9-file_01-simple-cases ++; -#line 161 b[j] += a[i]; -#line 162 +#line 161 j ++; } while_break___0: /* CIL Label */ ; } -#line 160 - term_exit- = term160_9-file_01-simple-cases; } -#line 164 +#line 163 i ++; } while_break: /* CIL Label */ ; } -#line 157 - term_exit- = term157_2-file_01-simple-cases; } -#line 166 +#line 165 return; } } -#line 170 "tests/regression/55-loop-unrolling/01-simple-cases.c" +#line 169 "tests/regression/55-loop-unrolling/01-simple-cases.c" void example9(void) { int a[5] ; int i ; - int term174_2-file_01-simple-cases ; + int term173_2-file_01-simple-cases ; { -#line 173 +#line 172 i = 0; { -#line 174 - term174_2-file_01-simple-cases = 0; +#line 173 + term173_2-file_01-simple-cases = 0; { -#line 174 +#line 173 while (1) { while_continue: /* CIL Label */ ; -#line 174 +#line 173 if (! 1) { -#line 174 +#line 173 goto while_break; } +#line 173 + term173_2-file_01-simple-cases ++; +#line 173 + term_exit- = term173_2-file_01-simple-cases; #line 174 - term174_2-file_01-simple-cases ++; -#line 175 a[i] = i; -#line 176 +#line 175 i ++; -#line 177 +#line 176 if (i == 5) { -#line 177 +#line 176 goto while_break; } } while_break: /* CIL Label */ ; } -#line 174 - term_exit- = term174_2-file_01-simple-cases; } -#line 179 +#line 178 return; } } -#line 183 "tests/regression/55-loop-unrolling/01-simple-cases.c" +#line 182 "tests/regression/55-loop-unrolling/01-simple-cases.c" void example10(void) { int a[5] ; int i ; - int term187_2-file_01-simple-cases ; + int term186_2-file_01-simple-cases ; { -#line 186 +#line 185 i = 0; { -#line 187 - term187_2-file_01-simple-cases = 0; +#line 186 + term186_2-file_01-simple-cases = 0; { -#line 187 +#line 186 while (1) { while_continue: /* CIL Label */ ; -#line 187 +#line 186 if (! (i < 5)) { -#line 187 +#line 186 goto while_break; } +#line 186 + term186_2-file_01-simple-cases ++; +#line 186 + term_exit- = term186_2-file_01-simple-cases; #line 187 - term187_2-file_01-simple-cases ++; -#line 188 if (i == 3) { -#line 189 +#line 188 i ++; -#line 190 +#line 189 goto while_continue; } -#line 192 +#line 191 a[i] = i; -#line 193 +#line 192 i ++; } while_break: /* CIL Label */ ; } -#line 187 - term_exit- = term187_2-file_01-simple-cases; } -#line 195 +#line 194 return; } } @@ -1683,42 +1681,40 @@ extern void ( __attribute__((__leaf__)) tzset)(void) __attribute__((__nothrow__ extern int daylight ; #line 233 extern long timezone ; -#line 246 +#line 249 extern time_t ( __attribute__((__leaf__)) timegm)(struct tm *__tp ) __attribute__((__nothrow__)) ; -#line 263 +#line 251 extern time_t ( __attribute__((__leaf__)) timelocal)(struct tm *__tp ) __attribute__((__nothrow__)) ; -#line 271 +#line 262 extern int ( __attribute__((__leaf__)) dysize)(int __year ) __attribute__((__nothrow__, __const__)) ; -#line 281 +#line 272 extern int nanosleep(struct timespec const *__requested_time , struct timespec *__remaining ) ; -#line 285 +#line 276 extern int ( __attribute__((__leaf__)) clock_getres)(clockid_t __clock_id , struct timespec *__res ) __attribute__((__nothrow__)) ; -#line 288 -extern int ( __attribute__((__nonnull__(2), __leaf__)) clock_gettime)(clockid_t __clock_id , - struct timespec *__tp ) __attribute__((__nothrow__)) ; -#line 292 -extern int ( __attribute__((__nonnull__(2), __leaf__)) clock_settime)(clockid_t __clock_id , - struct timespec const *__tp ) __attribute__((__nothrow__)) ; -#line 323 +#line 279 +extern int ( __attribute__((__leaf__)) clock_gettime)(clockid_t __clock_id , struct timespec *__tp ) __attribute__((__nothrow__)) ; +#line 282 +extern int ( __attribute__((__leaf__)) clock_settime)(clockid_t __clock_id , struct timespec const *__tp ) __attribute__((__nothrow__)) ; +#line 311 extern int clock_nanosleep(clockid_t __clock_id , int __flags , struct timespec const *__req , struct timespec *__rem ) ; -#line 338 +#line 326 extern int ( __attribute__((__leaf__)) clock_getcpuclockid)(pid_t __pid , clockid_t *__clock_id ) __attribute__((__nothrow__)) ; -#line 343 +#line 331 extern int ( __attribute__((__leaf__)) timer_create)(clockid_t __clock_id , struct sigevent * __restrict __evp , timer_t * __restrict __timerid ) __attribute__((__nothrow__)) ; -#line 348 +#line 336 extern int ( __attribute__((__leaf__)) timer_delete)(timer_t __timerid ) __attribute__((__nothrow__)) ; -#line 352 +#line 340 extern int ( __attribute__((__leaf__)) timer_settime)(timer_t __timerid , int __flags , struct itimerspec const * __restrict __value , struct itimerspec * __restrict __ovalue ) __attribute__((__nothrow__)) ; -#line 357 +#line 345 extern int ( __attribute__((__leaf__)) timer_gettime)(timer_t __timerid , struct itimerspec *__value ) __attribute__((__nothrow__)) ; -#line 376 +#line 364 extern int ( __attribute__((__leaf__)) timer_getoverrun)(timer_t __timerid ) __attribute__((__nothrow__)) ; -#line 383 +#line 371 extern int ( __attribute__((__nonnull__(1), __leaf__)) timespec_get)(struct timespec *__ts , int __base ) __attribute__((__nothrow__)) ; #line 202 "/usr/include/pthread.h" @@ -1829,8 +1825,9 @@ extern void __pthread_unregister_cancel(__pthread_unwind_buf_t *__buf ) ; #line 750 extern void __pthread_unwind_next(__pthread_unwind_buf_t *__buf ) __attribute__((__weak__, __noreturn__)) ; -#line 773 -extern int __sigsetjmp(struct __jmp_buf_tag *__env , int __savemask ) __attribute__((__nothrow__)) ; +#line 766 +extern int __sigsetjmp_cancel(struct __cancel_jmp_buf_tag *__env , int __savemask ) __asm__("__sigsetjmp") __attribute__((__returns_twice__, +__nothrow__)) ; #line 781 extern int ( __attribute__((__nonnull__(1), __leaf__)) pthread_mutex_init)(pthread_mutex_t *__mutex , pthread_mutexattr_t const *__mutexattr ) __attribute__((__nothrow__)) ; @@ -1995,7 +1992,8 @@ extern int ( __attribute__((__leaf__)) pthread_key_delete)(pthread_key_t __key ) extern void *( __attribute__((__leaf__)) pthread_getspecific)(pthread_key_t __key ) __attribute__((__nothrow__)) ; #line 1308 extern int ( __attribute__((__leaf__)) pthread_setspecific)(pthread_key_t __key , - void const *__pointer ) __attribute__((__nothrow__)) ; + void const *__pointer ) __attribute__((__nothrow__, +__access__(__none__,2))) ; #line 1315 extern int ( __attribute__((__nonnull__(2), __leaf__)) pthread_getcpuclockid)(pthread_t __thread_id , __clockid_t *__clock_id ) __attribute__((__nothrow__)) ; @@ -2057,6 +2055,8 @@ void qsort(void *ptr , size_t count , size_t size , int (*comp)(void const * , } #line 9 term9_3-file_stdlib ++; +#line 9 + term_exit- = term9_3-file_stdlib; #line 10 j = (size_t )0; { @@ -2073,6 +2073,8 @@ void qsort(void *ptr , size_t count , size_t size , int (*comp)(void const * , } #line 10 term10_5-file_stdlib ++; +#line 10 + term_exit- = term10_5-file_stdlib; #line 11 (*comp)((void const *)(ptr + i * size), (void const *)(ptr + j * size)); #line 10 @@ -2080,16 +2082,12 @@ void qsort(void *ptr , size_t count , size_t size , int (*comp)(void const * , } while_break___0: /* CIL Label */ ; } -#line 10 - term_exit- = term10_5-file_stdlib; } #line 9 i ++; } while_break: /* CIL Label */ ; } -#line 9 - term_exit- = term9_3-file_stdlib; } #line 16 i___0 = (size_t )0; @@ -2107,6 +2105,8 @@ void qsort(void *ptr , size_t count , size_t size , int (*comp)(void const * , } #line 16 term16_3-file_stdlib ++; +#line 16 + term_exit- = term16_3-file_stdlib; #line 17 j___0 = (size_t )0; { @@ -2123,6 +2123,8 @@ void qsort(void *ptr , size_t count , size_t size , int (*comp)(void const * , } #line 17 term17_5-file_stdlib ++; +#line 17 + term_exit- = term17_5-file_stdlib; #line 19 if (r) { #line 21 @@ -2141,6 +2143,8 @@ void qsort(void *ptr , size_t count , size_t size , int (*comp)(void const * , } #line 21 term21_9-file_stdlib ++; +#line 21 + term_exit- = term21_9-file_stdlib; #line 22 a = (char *)((ptr + i___0 * size) + k); #line 23 @@ -2156,8 +2160,6 @@ void qsort(void *ptr , size_t count , size_t size , int (*comp)(void const * , } while_break___3: /* CIL Label */ ; } -#line 21 - term_exit- = term21_9-file_stdlib; } } #line 17 @@ -2165,16 +2167,12 @@ void qsort(void *ptr , size_t count , size_t size , int (*comp)(void const * , } while_break___2: /* CIL Label */ ; } -#line 17 - term_exit- = term17_5-file_stdlib; } #line 16 i___0 ++; } while_break___1: /* CIL Label */ ; } -#line 16 - term_exit- = term16_3-file_stdlib; } #line 33 return; @@ -2212,6 +2210,8 @@ void *bsearch(void const *key , void const *ptr , size_t count , size_t size } #line 40 term40_3-file_stdlib ++; +#line 40 + term_exit- = term40_3-file_stdlib; #line 41 a = ptr + i * size; #line 42 @@ -2226,8 +2226,6 @@ void *bsearch(void const *key , void const *ptr , size_t count , size_t size } while_break: /* CIL Label */ ; } -#line 40 - term_exit- = term40_3-file_stdlib; } #line 47 return ((void *)0); From 4a402ca5373f2fe6eeb8e5dcc357368fd4f7b118 Mon Sep 17 00:00:00 2001 From: Johanna Schinabeck Date: Wed, 21 Jun 2023 14:10:44 +0200 Subject: [PATCH 136/327] reverted test case --- .../55-loop-unrolling/01-simple-cases.c | 24 +------------------ 1 file changed, 1 insertion(+), 23 deletions(-) diff --git a/tests/regression/55-loop-unrolling/01-simple-cases.c b/tests/regression/55-loop-unrolling/01-simple-cases.c index 9bf8d98683..3d5ce1b4e4 100644 --- a/tests/regression/55-loop-unrolling/01-simple-cases.c +++ b/tests/regression/55-loop-unrolling/01-simple-cases.c @@ -3,27 +3,6 @@ int global; -int f(int x); -int g(int x); - -int f(int x) -{ -if (x <= 0) return 0; -else return g(x) + g(x + 1); -} - -int g(int x) -{ -if (x <= 0) return 0; -else return f(x - 1) + f(x - 2); -} - -int main() { -int x = __VERIFIER_nondet_int(); -g(x); -} - -/* int main(void) { example1(); @@ -215,5 +194,4 @@ void example10(void) ++i; } return 0; -} -*/ \ No newline at end of file +} \ No newline at end of file From 79ac4ba84bdf5b02d643e73993a187f1282a8d38 Mon Sep 17 00:00:00 2001 From: Johanna Schinabeck Date: Wed, 21 Jun 2023 14:39:49 +0200 Subject: [PATCH 137/327] fixed error that for only one function the analysis was not executed: pulled check for result of loop analysis outside --- src/framework/constraints.ml | 23 +++++++++++------------ 1 file changed, 11 insertions(+), 12 deletions(-) diff --git a/src/framework/constraints.ml b/src/framework/constraints.ml index f0ae87acef..48196425f0 100644 --- a/src/framework/constraints.ml +++ b/src/framework/constraints.ml @@ -1764,24 +1764,23 @@ struct ) gmap (* try all fundec + context pairs that are in the map *) with Invalid_argument _ -> () (* path ended: no cycle*) - let checkTerminating ctx v v' = - (*Check if the loops terminated*) - if ctx.ask Queries.MustTermProg - then (cycleDetection ctx v v') - else (let msgs = - [ - (Pretty.dprintf "The program might not terminate! (Loop analysis)\n", Some (M.Location.CilLocation locUnknown)); - ] in - M.msg_group Warning ~category:NonTerminating "Possibly non terminating loops" msgs) - let query ctx (type a) (q: a Queries.t): a Queries.result = match q with | WarnGlobal v -> + let ret = ctx.ask Queries.MustTermProg in + (* check result of loop analysis *) + if not ret then + (let msgs = + [ + (Pretty.dprintf "The program might not terminate! (Loop analysis)\n", Some (M.Location.CilLocation locUnknown)); + ] in + M.msg_group Warning ~category:NonTerminating "Possibly non terminating loops" msgs + ); let v: V.t = Obj.obj v in begin match v with | `Left v' -> - S.query (conv ctx) (WarnGlobal (Obj.repr v')) - | `Right v' -> checkTerminating ctx v v' + S.query (conv ctx) (WarnGlobal (Obj.repr v')) + | `Right v' -> if ret then (cycleDetection ctx v v') (* Only analyze if the recursion terminates if the loops terminated *) end | InvariantGlobal v -> let v: V.t = Obj.obj v in From 6a4105df8671cc6fc9a74e19b14257e2672b2543 Mon Sep 17 00:00:00 2001 From: Thomas Lagemann Date: Wed, 21 Jun 2023 14:48:04 +0200 Subject: [PATCH 138/327] Added SKIP/TODO functionality for loop termination --- scripts/update_suite.rb | 23 ++++++++++++++++--- .../02-simple-loop-nonterminating.c | 2 +- .../04-nested-loop-nonterminating.c | 2 +- .../06-for-loop-nonterminating.c | 2 +- .../08-nested-for-loop-nonterminating.c | 2 +- .../14-do-while-nonterminating.c | 2 +- ...16-nested-loop-nontrivial-nonterminating.c | 2 +- .../80-termination/18-goto-nonterminating.c | 2 +- .../80-termination/20-rand-nonterminating.c | 2 +- .../21-no-exit-on-rand-unproofable.c | 2 +- .../22-exit-on-rand-unproofable.c | 2 +- .../27-upjumping-goto-nonterminating.c | 2 +- .../81-recursion/02-simple-nonterminating.c | 2 +- 13 files changed, 32 insertions(+), 15 deletions(-) diff --git a/scripts/update_suite.rb b/scripts/update_suite.rb index 69b3bae485..d85acfc1d8 100755 --- a/scripts/update_suite.rb +++ b/scripts/update_suite.rb @@ -186,9 +186,15 @@ def compare_warnings if cond then @correct += 1 # full p.path is too long and p.name does not allow click to open in terminal - if todo.include? idx then puts "Excellent: ignored check on #{relpath(p.path).to_s.cyan}:#{idx.to_s.blue} is now passing!" end + if todo.include? idx + if idx < 0 + puts "Excellent: ignored check on #{relpath(p.path).to_s.cyan} for #{type.yellow} is now passing!" + else + puts "Excellent: ignored check on #{relpath(p.path).to_s.cyan}:#{idx.to_s.blue} is now passing!" + end + end else - if todo.include? idx then + if todo.include? idx @ignored += 1 else if idx < 0 # When non line specific keywords were used don't print a line @@ -202,7 +208,9 @@ def compare_warnings end } case type - when "deadlock", "race", "fail", "noterm", "unknown", "term", "warn", "non_local_term" + when "deadlock", "race", "fail", "noterm", "unknown", "term", "warn" + check.call warnings[idx] == type + when "non_local_term" check.call warnings[idx] == type when "nowarn", "local_term" check.call warnings[idx].nil? @@ -316,6 +324,15 @@ def parse_tests (lines) end end case lines[0] + when /TODO|SKIP/ + case lines[0] + when /NON_LOCAL_TERM/ + tests[-2] = "non_local_term" # Not sure if -2 is allowed or undefined in Ruby but it seems to work correctly + todo << -2 + when /LOCAL_TERM/ + tests[-2] = "local_term" + todo << -2 + end when /NON_LOCAL_TERM/ # covers "TERM" as keyword but a combined use of NON_LOCAL_TERM (loop termination) and TERM would be pointless tests[-2] = "non_local_term" diff --git a/tests/regression/80-termination/02-simple-loop-nonterminating.c b/tests/regression/80-termination/02-simple-loop-nonterminating.c index bcb9909f80..8c4c63ffab 100644 --- a/tests/regression/80-termination/02-simple-loop-nonterminating.c +++ b/tests/regression/80-termination/02-simple-loop-nonterminating.c @@ -1,4 +1,4 @@ -// NON_LOCAL_TERM PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra +// TODO NON_LOCAL_TERM PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra #include int main() diff --git a/tests/regression/80-termination/04-nested-loop-nonterminating.c b/tests/regression/80-termination/04-nested-loop-nonterminating.c index ee2aa4a8c4..5a7ac43f70 100644 --- a/tests/regression/80-termination/04-nested-loop-nonterminating.c +++ b/tests/regression/80-termination/04-nested-loop-nonterminating.c @@ -1,4 +1,4 @@ -// NON_LOCAL_TERM PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra +// TODO NON_LOCAL_TERM PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra #include int main() diff --git a/tests/regression/80-termination/06-for-loop-nonterminating.c b/tests/regression/80-termination/06-for-loop-nonterminating.c index b8f30361d1..73a8b8c6fd 100644 --- a/tests/regression/80-termination/06-for-loop-nonterminating.c +++ b/tests/regression/80-termination/06-for-loop-nonterminating.c @@ -1,4 +1,4 @@ -// NON_LOCAL_TERM PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra +// TODO NON_LOCAL_TERM PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra #include int main() { diff --git a/tests/regression/80-termination/08-nested-for-loop-nonterminating.c b/tests/regression/80-termination/08-nested-for-loop-nonterminating.c index 0368120b13..8b451e56dd 100644 --- a/tests/regression/80-termination/08-nested-for-loop-nonterminating.c +++ b/tests/regression/80-termination/08-nested-for-loop-nonterminating.c @@ -1,4 +1,4 @@ -// NON_LOCAL_TERM PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra +// TODO NON_LOCAL_TERM PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra #include int main() diff --git a/tests/regression/80-termination/14-do-while-nonterminating.c b/tests/regression/80-termination/14-do-while-nonterminating.c index 5ed18175e9..c242e9a87c 100644 --- a/tests/regression/80-termination/14-do-while-nonterminating.c +++ b/tests/regression/80-termination/14-do-while-nonterminating.c @@ -1,4 +1,4 @@ -// NON_LOCAL_TERM PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra +// TODO NON_LOCAL_TERM PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra #include int main() diff --git a/tests/regression/80-termination/16-nested-loop-nontrivial-nonterminating.c b/tests/regression/80-termination/16-nested-loop-nontrivial-nonterminating.c index 5ff890e461..9d51c17216 100644 --- a/tests/regression/80-termination/16-nested-loop-nontrivial-nonterminating.c +++ b/tests/regression/80-termination/16-nested-loop-nontrivial-nonterminating.c @@ -1,4 +1,4 @@ -// NON_LOCAL_TERM PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra +// TODO NON_LOCAL_TERM PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra #include int main() diff --git a/tests/regression/80-termination/18-goto-nonterminating.c b/tests/regression/80-termination/18-goto-nonterminating.c index cfe5ab481d..ab85ccf8de 100644 --- a/tests/regression/80-termination/18-goto-nonterminating.c +++ b/tests/regression/80-termination/18-goto-nonterminating.c @@ -1,4 +1,4 @@ -// NON_LOCAL_TERM PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra +// TODO NON_LOCAL_TERM PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra #include int main() diff --git a/tests/regression/80-termination/20-rand-nonterminating.c b/tests/regression/80-termination/20-rand-nonterminating.c index 7c21538612..fb1f336349 100644 --- a/tests/regression/80-termination/20-rand-nonterminating.c +++ b/tests/regression/80-termination/20-rand-nonterminating.c @@ -1,4 +1,4 @@ -// NON_LOCAL_TERM PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra +// TODO NON_LOCAL_TERM PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra #include #include #include diff --git a/tests/regression/80-termination/21-no-exit-on-rand-unproofable.c b/tests/regression/80-termination/21-no-exit-on-rand-unproofable.c index f54af1da7c..ce0fbb78ff 100644 --- a/tests/regression/80-termination/21-no-exit-on-rand-unproofable.c +++ b/tests/regression/80-termination/21-no-exit-on-rand-unproofable.c @@ -1,4 +1,4 @@ -// NON_LOCAL_TERM PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra +// TODO NON_LOCAL_TERM PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra #include int main() diff --git a/tests/regression/80-termination/22-exit-on-rand-unproofable.c b/tests/regression/80-termination/22-exit-on-rand-unproofable.c index 1bc104258d..db79588945 100644 --- a/tests/regression/80-termination/22-exit-on-rand-unproofable.c +++ b/tests/regression/80-termination/22-exit-on-rand-unproofable.c @@ -1,4 +1,4 @@ -// NON_LOCAL_TERM PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra +// TODO NON_LOCAL_TERM PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra #include int main() diff --git a/tests/regression/80-termination/27-upjumping-goto-nonterminating.c b/tests/regression/80-termination/27-upjumping-goto-nonterminating.c index a230827356..165a53fccf 100644 --- a/tests/regression/80-termination/27-upjumping-goto-nonterminating.c +++ b/tests/regression/80-termination/27-upjumping-goto-nonterminating.c @@ -1,4 +1,4 @@ -// NON_LOCAL_TERM PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra +// TODO NON_LOCAL_TERM PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra #include int main() { diff --git a/tests/regression/81-recursion/02-simple-nonterminating.c b/tests/regression/81-recursion/02-simple-nonterminating.c index 3ed0b75a0d..ef530f95d8 100644 --- a/tests/regression/81-recursion/02-simple-nonterminating.c +++ b/tests/regression/81-recursion/02-simple-nonterminating.c @@ -1,4 +1,4 @@ -// NON_LOCAL_TERM PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra +// TODO NON_LOCAL_TERM PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra #include void recursiveFunction(int n) { From 6f3921876d5408062d0289a33f7343431044a7fe Mon Sep 17 00:00:00 2001 From: Thomas Lagemann Date: Wed, 21 Jun 2023 15:09:41 +0200 Subject: [PATCH 139/327] Adapted TODO comments to current state --- tests/regression/80-termination/02-simple-loop-nonterminating.c | 2 +- tests/regression/80-termination/04-nested-loop-nonterminating.c | 2 +- .../regression/80-termination/09-complex-for-loop-terminating.c | 2 +- tests/regression/80-termination/10-complex-loop-terminating.c | 2 +- tests/regression/80-termination/14-do-while-nonterminating.c | 2 +- .../80-termination/15-complex-loop-combination-terminating.c | 2 +- .../80-termination/16-nested-loop-nontrivial-nonterminating.c | 2 +- tests/regression/80-termination/17-goto-terminating.c | 2 +- tests/regression/80-termination/18-goto-nonterminating.c | 2 +- tests/regression/80-termination/20-rand-nonterminating.c | 2 +- .../regression/80-termination/21-no-exit-on-rand-unproofable.c | 2 +- tests/regression/80-termination/22-exit-on-rand-unproofable.c | 2 +- tests/regression/80-termination/23-exit-on-rand-terminating.c | 2 +- .../80-termination/24-upjumping-goto-loopless-terminating.c | 2 +- .../regression/80-termination/25-leave-loop-goto-terminating.c | 2 +- .../regression/80-termination/26-enter-loop-goto-terminating.c | 2 +- .../80-termination/27-upjumping-goto-nonterminating.c | 2 +- 17 files changed, 17 insertions(+), 17 deletions(-) diff --git a/tests/regression/80-termination/02-simple-loop-nonterminating.c b/tests/regression/80-termination/02-simple-loop-nonterminating.c index 8c4c63ffab..bcb9909f80 100644 --- a/tests/regression/80-termination/02-simple-loop-nonterminating.c +++ b/tests/regression/80-termination/02-simple-loop-nonterminating.c @@ -1,4 +1,4 @@ -// TODO NON_LOCAL_TERM PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra +// NON_LOCAL_TERM PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra #include int main() diff --git a/tests/regression/80-termination/04-nested-loop-nonterminating.c b/tests/regression/80-termination/04-nested-loop-nonterminating.c index 5a7ac43f70..ee2aa4a8c4 100644 --- a/tests/regression/80-termination/04-nested-loop-nonterminating.c +++ b/tests/regression/80-termination/04-nested-loop-nonterminating.c @@ -1,4 +1,4 @@ -// TODO NON_LOCAL_TERM PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra +// NON_LOCAL_TERM PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra #include int main() diff --git a/tests/regression/80-termination/09-complex-for-loop-terminating.c b/tests/regression/80-termination/09-complex-for-loop-terminating.c index ae68b11575..c4cad58bff 100644 --- a/tests/regression/80-termination/09-complex-for-loop-terminating.c +++ b/tests/regression/80-termination/09-complex-for-loop-terminating.c @@ -1,4 +1,4 @@ -// LOCAL_TERM PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra +// TODO LOCAL_TERM PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra #include int main() diff --git a/tests/regression/80-termination/10-complex-loop-terminating.c b/tests/regression/80-termination/10-complex-loop-terminating.c index eb79338078..9a5a4429de 100644 --- a/tests/regression/80-termination/10-complex-loop-terminating.c +++ b/tests/regression/80-termination/10-complex-loop-terminating.c @@ -1,4 +1,4 @@ -// LOCAL_TERM PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra +// TODO LOCAL_TERM PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra #include int main() diff --git a/tests/regression/80-termination/14-do-while-nonterminating.c b/tests/regression/80-termination/14-do-while-nonterminating.c index c242e9a87c..5ed18175e9 100644 --- a/tests/regression/80-termination/14-do-while-nonterminating.c +++ b/tests/regression/80-termination/14-do-while-nonterminating.c @@ -1,4 +1,4 @@ -// TODO NON_LOCAL_TERM PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra +// NON_LOCAL_TERM PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra #include int main() diff --git a/tests/regression/80-termination/15-complex-loop-combination-terminating.c b/tests/regression/80-termination/15-complex-loop-combination-terminating.c index f3a08f4139..e0307cc53c 100644 --- a/tests/regression/80-termination/15-complex-loop-combination-terminating.c +++ b/tests/regression/80-termination/15-complex-loop-combination-terminating.c @@ -1,4 +1,4 @@ -// LOCAL_TERM PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra +// TODO LOCAL_TERM PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra #include int main() diff --git a/tests/regression/80-termination/16-nested-loop-nontrivial-nonterminating.c b/tests/regression/80-termination/16-nested-loop-nontrivial-nonterminating.c index 9d51c17216..5ff890e461 100644 --- a/tests/regression/80-termination/16-nested-loop-nontrivial-nonterminating.c +++ b/tests/regression/80-termination/16-nested-loop-nontrivial-nonterminating.c @@ -1,4 +1,4 @@ -// TODO NON_LOCAL_TERM PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra +// NON_LOCAL_TERM PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra #include int main() diff --git a/tests/regression/80-termination/17-goto-terminating.c b/tests/regression/80-termination/17-goto-terminating.c index b66fbe57ea..e988926359 100644 --- a/tests/regression/80-termination/17-goto-terminating.c +++ b/tests/regression/80-termination/17-goto-terminating.c @@ -1,4 +1,4 @@ -// LOCAL_TERM PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra +// TODO LOCAL_TERM PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra #include int main() diff --git a/tests/regression/80-termination/18-goto-nonterminating.c b/tests/regression/80-termination/18-goto-nonterminating.c index ab85ccf8de..cfe5ab481d 100644 --- a/tests/regression/80-termination/18-goto-nonterminating.c +++ b/tests/regression/80-termination/18-goto-nonterminating.c @@ -1,4 +1,4 @@ -// TODO NON_LOCAL_TERM PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra +// NON_LOCAL_TERM PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra #include int main() diff --git a/tests/regression/80-termination/20-rand-nonterminating.c b/tests/regression/80-termination/20-rand-nonterminating.c index fb1f336349..7c21538612 100644 --- a/tests/regression/80-termination/20-rand-nonterminating.c +++ b/tests/regression/80-termination/20-rand-nonterminating.c @@ -1,4 +1,4 @@ -// TODO NON_LOCAL_TERM PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra +// NON_LOCAL_TERM PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra #include #include #include diff --git a/tests/regression/80-termination/21-no-exit-on-rand-unproofable.c b/tests/regression/80-termination/21-no-exit-on-rand-unproofable.c index ce0fbb78ff..f54af1da7c 100644 --- a/tests/regression/80-termination/21-no-exit-on-rand-unproofable.c +++ b/tests/regression/80-termination/21-no-exit-on-rand-unproofable.c @@ -1,4 +1,4 @@ -// TODO NON_LOCAL_TERM PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra +// NON_LOCAL_TERM PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra #include int main() diff --git a/tests/regression/80-termination/22-exit-on-rand-unproofable.c b/tests/regression/80-termination/22-exit-on-rand-unproofable.c index db79588945..1bc104258d 100644 --- a/tests/regression/80-termination/22-exit-on-rand-unproofable.c +++ b/tests/regression/80-termination/22-exit-on-rand-unproofable.c @@ -1,4 +1,4 @@ -// TODO NON_LOCAL_TERM PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra +// NON_LOCAL_TERM PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra #include int main() diff --git a/tests/regression/80-termination/23-exit-on-rand-terminating.c b/tests/regression/80-termination/23-exit-on-rand-terminating.c index 9d000069e1..253d38c5df 100644 --- a/tests/regression/80-termination/23-exit-on-rand-terminating.c +++ b/tests/regression/80-termination/23-exit-on-rand-terminating.c @@ -1,4 +1,4 @@ -// LOCAL_TERM PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra +// TODO LOCAL_TERM PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra #include #include diff --git a/tests/regression/80-termination/24-upjumping-goto-loopless-terminating.c b/tests/regression/80-termination/24-upjumping-goto-loopless-terminating.c index a774f70457..01bffde383 100644 --- a/tests/regression/80-termination/24-upjumping-goto-loopless-terminating.c +++ b/tests/regression/80-termination/24-upjumping-goto-loopless-terminating.c @@ -1,4 +1,4 @@ -// LOCAL_TERM PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra +// TODO LOCAL_TERM PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra #include int main() { diff --git a/tests/regression/80-termination/25-leave-loop-goto-terminating.c b/tests/regression/80-termination/25-leave-loop-goto-terminating.c index 28d8824535..fed0e218ac 100644 --- a/tests/regression/80-termination/25-leave-loop-goto-terminating.c +++ b/tests/regression/80-termination/25-leave-loop-goto-terminating.c @@ -1,4 +1,4 @@ -// LOCAL_TERM PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra +// TODO LOCAL_TERM PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra #include int main() { diff --git a/tests/regression/80-termination/26-enter-loop-goto-terminating.c b/tests/regression/80-termination/26-enter-loop-goto-terminating.c index 41bf44c44e..2a43933758 100644 --- a/tests/regression/80-termination/26-enter-loop-goto-terminating.c +++ b/tests/regression/80-termination/26-enter-loop-goto-terminating.c @@ -1,4 +1,4 @@ -// LOCAL_TERM PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra +// TODO LOCAL_TERM PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra #include int main() { diff --git a/tests/regression/80-termination/27-upjumping-goto-nonterminating.c b/tests/regression/80-termination/27-upjumping-goto-nonterminating.c index 165a53fccf..a230827356 100644 --- a/tests/regression/80-termination/27-upjumping-goto-nonterminating.c +++ b/tests/regression/80-termination/27-upjumping-goto-nonterminating.c @@ -1,4 +1,4 @@ -// TODO NON_LOCAL_TERM PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra +// NON_LOCAL_TERM PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra #include int main() { From 0f3dbdc607d0f0e4f0ae20176195728b1baf2bc7 Mon Sep 17 00:00:00 2001 From: Alexander Schlenga Date: Wed, 21 Jun 2023 15:16:13 +0200 Subject: [PATCH 140/327] Comment out unused loop_heads function --- src/analyses/termination_new.ml | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/analyses/termination_new.ml b/src/analyses/termination_new.ml index a3aa3aef92..7f2aa8357c 100644 --- a/src/analyses/termination_new.ml +++ b/src/analyses/termination_new.ml @@ -6,6 +6,7 @@ open TerminationPreprocessing exception PreProcessing of string +(* let loop_heads () = let module FileCfg = struct @@ -13,7 +14,8 @@ let loop_heads () = module Cfg = (val !MyCFG.current_cfg) end in let module WitnessInvariant = WitnessUtil.Invariant (FileCfg) in - WitnessInvariant.loop_heads (* TODO: Use this *) + WitnessInvariant.loop_heads (* TODO: Unused *) +*) (** Contains all loop counter variables (varinfo) and maps them to their corresponding loop statement. *) let loop_counters : stmt VarToStmt.t ref = ref VarToStmt.empty From 1a0905791df38fb6ce2c72ff02de875004d0c201 Mon Sep 17 00:00:00 2001 From: Alexander Schlenga Date: Wed, 21 Jun 2023 15:26:31 +0200 Subject: [PATCH 141/327] Answer queries with false when multi-threaded --- src/analyses/termination_new.ml | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/src/analyses/termination_new.ml b/src/analyses/termination_new.ml index 7f2aa8357c..cd4b652f65 100644 --- a/src/analyses/termination_new.ml +++ b/src/analyses/termination_new.ml @@ -96,6 +96,11 @@ struct (* TODO: Implement check for our special loop exit indicator function *) ctx.local + (** Checks whether a new thread was spawned some time. We want to discard + * any knowledge about termination then (see query function) *) + let must_be_single_threaded_since_start ctx = + ctx.ask (Queries.MustBeSingleThreaded {since_start = true}) + (** Provides information to Goblint *) let query ctx (type a) (q: a Queries.t): a Queries.result = match q with @@ -103,9 +108,11 @@ struct (match G.find_opt (`Lifted loop_statement) (ctx.global ()) with Some b -> b | None -> false) + && must_be_single_threaded_since_start ctx | Queries.MustTermProg -> G.for_all (fun _ term_info -> term_info) (ctx.global ()) && no_upjumping_gotos () + && must_be_single_threaded_since_start ctx | _ -> Queries.Result.top q end From 524f0cb6c55f1b840198a399df65f8cca90a9096 Mon Sep 17 00:00:00 2001 From: Alexander Schlenga Date: Wed, 21 Jun 2023 15:28:55 +0200 Subject: [PATCH 142/327] Change comments --- src/analyses/termination_new.ml | 10 +--------- 1 file changed, 1 insertion(+), 9 deletions(-) diff --git a/src/analyses/termination_new.ml b/src/analyses/termination_new.ml index cd4b652f65..7ecb11a12c 100644 --- a/src/analyses/termination_new.ml +++ b/src/analyses/termination_new.ml @@ -75,17 +75,9 @@ struct let assign ctx (lval : lval) (rval : exp) = (* Detect assignment to loop counter variable *) match lval, rval with - (* - (Var x, NoOffset), _ when is_loop_counter_var x -> - (* Assume that the following loop does not terminate *) - let loop_statement = VarToStmt.find x !loop_counters in - let () = ctx.sideg () (G.add (`Lifted loop_statement) false ctx.local) in - let () = print_endline ("Added FALSE for " ^ x.vname) in - D.add (`Lifted loop_statement) false ctx.local - *) (Var y, NoOffset), Lval (Var x, NoOffset) when is_loop_exit_indicator y -> (* Loop exit: Check whether loop counter variable is bounded *) - (* TODO: Move *) + (* TODO: Move to special *) let is_bounded = check_bounded ctx x in let loop_statement = VarToStmt.find x !loop_counters in let () = ctx.sideg () (G.add (`Lifted loop_statement) is_bounded (ctx.global ())) in From 72062a6fee57f95a814226685014288248fdd87a Mon Sep 17 00:00:00 2001 From: Thomas Lagemann Date: Wed, 21 Jun 2023 16:01:57 +0200 Subject: [PATCH 143/327] Added requested test cases --- .../28-do-while-continue-terminating.c | 21 +++++++++++ .../29-do-while-continue-nonterminating.c | 21 +++++++++++ .../30-goto-out-of-inner-loop-terminating.c | 22 ++++++++++++ ...31-goto-out-of-inner-loop-nonterminating.c | 23 ++++++++++++ .../32-multithread-terminating.c | 27 ++++++++++++++ .../33-multithread-nonterminating.c | 36 +++++++++++++++++++ 6 files changed, 150 insertions(+) create mode 100644 tests/regression/80-termination/28-do-while-continue-terminating.c create mode 100644 tests/regression/80-termination/29-do-while-continue-nonterminating.c create mode 100644 tests/regression/80-termination/30-goto-out-of-inner-loop-terminating.c create mode 100644 tests/regression/80-termination/31-goto-out-of-inner-loop-nonterminating.c create mode 100644 tests/regression/80-termination/32-multithread-terminating.c create mode 100644 tests/regression/80-termination/33-multithread-nonterminating.c diff --git a/tests/regression/80-termination/28-do-while-continue-terminating.c b/tests/regression/80-termination/28-do-while-continue-terminating.c new file mode 100644 index 0000000000..5989c61fed --- /dev/null +++ b/tests/regression/80-termination/28-do-while-continue-terminating.c @@ -0,0 +1,21 @@ +// TODO LOCAL_TERM PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra +#include + +int main() +{ + int i = 1; + + do + { + i++; + printf("Inside the do-while loop\n"); + if (i % 2 == 0) { + + printf("Skipping %i is even\n", i); + continue; + } + } while (i <= 5); + + printf("Exited the loop\n"); + return 0; +} diff --git a/tests/regression/80-termination/29-do-while-continue-nonterminating.c b/tests/regression/80-termination/29-do-while-continue-nonterminating.c new file mode 100644 index 0000000000..806456e887 --- /dev/null +++ b/tests/regression/80-termination/29-do-while-continue-nonterminating.c @@ -0,0 +1,21 @@ +// NON_LOCAL_TERM PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra +#include + +int main() +{ + int i = 1; + + do + { + printf("Inside the do-while loop\n"); + i++; + + if(i%2) { + printf("Continue as %i is odd\n", i); + continue; + } + } while (i >= 2); + + printf("Exited the loop\n"); + return 0; +} diff --git a/tests/regression/80-termination/30-goto-out-of-inner-loop-terminating.c b/tests/regression/80-termination/30-goto-out-of-inner-loop-terminating.c new file mode 100644 index 0000000000..76c272a654 --- /dev/null +++ b/tests/regression/80-termination/30-goto-out-of-inner-loop-terminating.c @@ -0,0 +1,22 @@ +// TODO LOCAL_TERM PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra +#include + +int main() { + int rows = 5; + int columns = 5; + + // Outer loop for rows + for (int i = 1; i <= rows; i++) { + // Inner loop for columns + for (int j = 1; j <= columns; j++) { + if (j == 3) { + goto outer_loop; // Jump to the label "outer_loop" + } + printf("(%d, %d) ", i, j); + } + printf("\n"); + outer_loop:; // Label for the outer loop + } + + return 0; +} diff --git a/tests/regression/80-termination/31-goto-out-of-inner-loop-nonterminating.c b/tests/regression/80-termination/31-goto-out-of-inner-loop-nonterminating.c new file mode 100644 index 0000000000..c1824227d0 --- /dev/null +++ b/tests/regression/80-termination/31-goto-out-of-inner-loop-nonterminating.c @@ -0,0 +1,23 @@ +// NON_LOCAL_TERM PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra +#include + +int main() { + int rows = 5; + int columns = 5; + + // Outer loop for rows + for (int i = 1; 1; i++) { + // Inner loop for columns + for (int j = 1; j <= columns; j++) { + if (j == 3) { + printf("Goto as continue for outer loop\n"); + goto outer_loop; // Jump to the label "outer_loop" + } + printf("(%d, %d) ", i, j); + } + printf("\n"); + outer_loop:; // Label for the outer loop + } + + return 0; +} diff --git a/tests/regression/80-termination/32-multithread-terminating.c b/tests/regression/80-termination/32-multithread-terminating.c new file mode 100644 index 0000000000..a08fe01398 --- /dev/null +++ b/tests/regression/80-termination/32-multithread-terminating.c @@ -0,0 +1,27 @@ +// LOCAL_TERM PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra +#include +#include +#include + +// Thread function +void* printPID(void* arg) { + pid_t pid = getpid(); + pthread_t tid = pthread_self(); + printf("Thread ID: %lu, Process ID: %d\n", (unsigned long)tid, pid); + return NULL; +} + +int main() { + // Create three threads + pthread_t thread1, thread2, thread3; + pthread_create(&thread1, NULL, printPID, NULL); + pthread_create(&thread2, NULL, printPID, NULL); + pthread_create(&thread3, NULL, printPID, NULL); + + // Wait for all threads to finish + pthread_join(thread1, NULL); + pthread_join(thread2, NULL); + pthread_join(thread3, NULL); + + return 0; +} diff --git a/tests/regression/80-termination/33-multithread-nonterminating.c b/tests/regression/80-termination/33-multithread-nonterminating.c new file mode 100644 index 0000000000..77cd2aafe6 --- /dev/null +++ b/tests/regression/80-termination/33-multithread-nonterminating.c @@ -0,0 +1,36 @@ +// NON_LOCAL_TERM PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra +#include +#include +#include +#include +#include + +// Thread function +void* printPID(void* arg) { + pid_t pid = getpid(); + pthread_t tid = pthread_self(); + while(1) { + printf("Thread ID: %lu, Process ID: %d\n", (unsigned long)tid, pid); + struct timespec sleepTime; + sleepTime.tv_sec = 1; // Seconds + sleepTime.tv_nsec = 100000000 + (rand() % 200000000); // Nanoseconds (0.1 seconds + rand) + printf("Sleep for %ld nsec\n", sleepTime.tv_nsec); + nanosleep(&sleepTime, NULL); + } + return NULL; +} + +int main() { + // Create three threads + pthread_t thread1, thread2, thread3; + pthread_create(&thread1, NULL, printPID, NULL); + pthread_create(&thread2, NULL, printPID, NULL); + pthread_create(&thread3, NULL, printPID, NULL); + + // Wait for all threads to finish + pthread_join(thread1, NULL); + pthread_join(thread2, NULL); + pthread_join(thread3, NULL); + + return 0; +} From 2f9f697f4e53e8324a62844839fed5b2f478dcef Mon Sep 17 00:00:00 2001 From: Thomas Lagemann Date: Thu, 22 Jun 2023 13:32:39 +0200 Subject: [PATCH 144/327] Skip crashing tests --- .../regression/80-termination/09-complex-for-loop-terminating.c | 2 +- tests/regression/80-termination/10-complex-loop-terminating.c | 2 +- .../80-termination/15-complex-loop-combination-terminating.c | 2 +- tests/regression/81-recursion/02-simple-nonterminating.c | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/tests/regression/80-termination/09-complex-for-loop-terminating.c b/tests/regression/80-termination/09-complex-for-loop-terminating.c index c4cad58bff..8951924c06 100644 --- a/tests/regression/80-termination/09-complex-for-loop-terminating.c +++ b/tests/regression/80-termination/09-complex-for-loop-terminating.c @@ -1,4 +1,4 @@ -// TODO LOCAL_TERM PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra +// SKIP LOCAL_TERM PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra #include int main() diff --git a/tests/regression/80-termination/10-complex-loop-terminating.c b/tests/regression/80-termination/10-complex-loop-terminating.c index 9a5a4429de..dbce2a6b5b 100644 --- a/tests/regression/80-termination/10-complex-loop-terminating.c +++ b/tests/regression/80-termination/10-complex-loop-terminating.c @@ -1,4 +1,4 @@ -// TODO LOCAL_TERM PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra +// SKIP LOCAL_TERM PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra #include int main() diff --git a/tests/regression/80-termination/15-complex-loop-combination-terminating.c b/tests/regression/80-termination/15-complex-loop-combination-terminating.c index e0307cc53c..7daa9b98fe 100644 --- a/tests/regression/80-termination/15-complex-loop-combination-terminating.c +++ b/tests/regression/80-termination/15-complex-loop-combination-terminating.c @@ -1,4 +1,4 @@ -// TODO LOCAL_TERM PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra +// SKIP LOCAL_TERM PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval #include int main() diff --git a/tests/regression/81-recursion/02-simple-nonterminating.c b/tests/regression/81-recursion/02-simple-nonterminating.c index ef530f95d8..c7902e2e7f 100644 --- a/tests/regression/81-recursion/02-simple-nonterminating.c +++ b/tests/regression/81-recursion/02-simple-nonterminating.c @@ -1,4 +1,4 @@ -// TODO NON_LOCAL_TERM PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra +// SKIP NON_LOCAL_TERM PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra #include void recursiveFunction(int n) { From e250557c958d60fa1d8e48b1b678ad600ace27ef Mon Sep 17 00:00:00 2001 From: Johanna Schinabeck Date: Thu, 22 Jun 2023 13:35:33 +0200 Subject: [PATCH 145/327] reverted test case 55 01 --- tests/regression/55-loop-unrolling/01-simple-cases.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/tests/regression/55-loop-unrolling/01-simple-cases.c b/tests/regression/55-loop-unrolling/01-simple-cases.c index 3d5ce1b4e4..add8c6a8dd 100644 --- a/tests/regression/55-loop-unrolling/01-simple-cases.c +++ b/tests/regression/55-loop-unrolling/01-simple-cases.c @@ -30,8 +30,7 @@ void example1(void) } __goblint_check(a[0] == 0); // UNKNOWN - lab:__goblint_check(a[3] == 3); // UNKNOWN - goto lab; + __goblint_check(a[3] == 3); // UNKNOWN } // Do-while loop simple example From 4e66fd2bf3118fad23d2944400234da6fc869956 Mon Sep 17 00:00:00 2001 From: Johanna Schinabeck Date: Thu, 22 Jun 2023 16:05:13 +0200 Subject: [PATCH 146/327] make recursion analysis optional (depending if loop ana is activated) --- src/framework/constraints.ml | 5 ++--- src/framework/control.ml | 3 ++- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/framework/constraints.ml b/src/framework/constraints.ml index 48196425f0..e57570eb35 100644 --- a/src/framework/constraints.ml +++ b/src/framework/constraints.ml @@ -1767,9 +1767,8 @@ struct let query ctx (type a) (q: a Queries.t): a Queries.result = match q with | WarnGlobal v -> - let ret = ctx.ask Queries.MustTermProg in (* check result of loop analysis *) - if not ret then + if not (ctx.ask Queries.MustTermProg) then (let msgs = [ (Pretty.dprintf "The program might not terminate! (Loop analysis)\n", Some (M.Location.CilLocation locUnknown)); @@ -1780,7 +1779,7 @@ struct begin match v with | `Left v' -> S.query (conv ctx) (WarnGlobal (Obj.repr v')) - | `Right v' -> if ret then (cycleDetection ctx v v') (* Only analyze if the recursion terminates if the loops terminated *) + | `Right v' -> cycleDetection ctx v v' (* Note: to make it more efficient, one could only execute the cycle detection in case the loop analysis returns true, because otherwise the program will probably not terminate anyway*) end | InvariantGlobal v -> let v: V.t = Obj.obj v in diff --git a/src/framework/control.ml b/src/framework/control.ml index 6261329e18..b157a2e81a 100644 --- a/src/framework/control.ml +++ b/src/framework/control.ml @@ -15,6 +15,7 @@ module type S2S = functor (X : Spec) -> Spec let spec_module: (module Spec) Lazy.t = lazy ( GobConfig.building_spec := true; let arg_enabled = get_bool "ana.sv-comp.enabled" || get_bool "exp.arg" in + let arg_termination = List.mem "termination" (get_string_list "ana.activated") in (* check if loop termination analysis is enabled*) let open Batteries in (* apply functor F on module X if opt is true *) let lift opt (module F : S2S) (module X : Spec) = (module (val if opt then (module F (X)) else (module X) : Spec) : Spec) in @@ -36,7 +37,7 @@ let spec_module: (module Spec) Lazy.t = lazy ( Also must be outside of deadcode, because deadcode splits (like mutex lock event) don't pass on tokens. *) |> lift (get_bool "ana.widen.tokens") (module WideningTokens.Lifter) |> lift true (module LongjmpLifter) - |> lift true (module RecursionTermLifter)(*TODO: should we really always evaluate it???*) + |> lift arg_termination (module RecursionTermLifter) (* Always activate the recursion termination analysis, when the loop termination analysis is activated*) ) in GobConfig.building_spec := false; ControlSpecC.control_spec_c := (module S1.C); From 4b4be5b8d0bce38f15b07cfd95d4f48a6fc41d3f Mon Sep 17 00:00:00 2001 From: Isidor Zweckstetter Date: Thu, 22 Jun 2023 16:27:14 +0200 Subject: [PATCH 147/327] work-in-progress on svcomp integration --- src/analyses/apron/apronAnalysis.apron.ml | 2 -- src/autoTune.ml | 1 + src/framework/analysisState.ml | 3 +++ src/framework/constraints.ml | 7 ++++--- src/witness/svcomp.ml | 1 + src/witness/svcompSpec.ml | 4 ++++ src/witness/witness.ml | 17 +++++++++++++++++ .../55-loop-unrolling/01-simple-cases.c | 3 +-- 8 files changed, 31 insertions(+), 7 deletions(-) diff --git a/src/analyses/apron/apronAnalysis.apron.ml b/src/analyses/apron/apronAnalysis.apron.ml index 789701d37c..1ac88c66ee 100644 --- a/src/analyses/apron/apronAnalysis.apron.ml +++ b/src/analyses/apron/apronAnalysis.apron.ml @@ -1,7 +1,5 @@ (** Analysis using Apron for integer variables. *) open Analyses -open TerminationPreprocessing -open Cilfacade include RelationAnalysis let spec_module: (module MCPSpec) Lazy.t = diff --git a/src/autoTune.ml b/src/autoTune.ml index a267c3bf9b..4fb8a1db5e 100644 --- a/src/autoTune.ml +++ b/src/autoTune.ml @@ -216,6 +216,7 @@ let focusOnSpecification () = | NoDataRace -> (*enable all thread analyses*) print_endline @@ "Specification: NoDataRace -> enabling thread analyses \"" ^ (String.concat ", " notNeccessaryThreadAnalyses) ^ "\""; enableAnalyses notNeccessaryThreadAnalyses; + | NoTermination -> () | NoOverflow -> (*We focus on integer analysis*) set_bool "ana.int.def_exc" true; set_bool "ana.int.interval" true diff --git a/src/framework/analysisState.ml b/src/framework/analysisState.ml index 0f3a9f55bc..ddecf1752a 100644 --- a/src/framework/analysisState.ml +++ b/src/framework/analysisState.ml @@ -7,6 +7,9 @@ let should_warn = ref false (** Whether signed overflow or underflow happened *) let svcomp_may_overflow = ref false +(** TODO:**) +let svcomp_must_terminate = ref true + (** A hack to see if we are currently doing global inits *) let global_initialization = ref false diff --git a/src/framework/constraints.ml b/src/framework/constraints.ml index 48196425f0..865b0405ee 100644 --- a/src/framework/constraints.ml +++ b/src/framework/constraints.ml @@ -1716,7 +1716,7 @@ struct module G = GVarGSet (S.G) (S.C) (T (CilType.Fundec) (S.C)) - let name () = "RecursionTerm (" ^ S.name () ^ ")" + let name () = "termination" let conv (ctx: (_, G.t, _, V.t) ctx): (_, S.G.t, _, S.V.t) ctx = { ctx with @@ -1734,7 +1734,7 @@ struct let rec iter_call (path_visited_calls: LS.t) (call:T (CilType.Fundec) (S.C).t) = let ((fundec_e:fundec), (context_e: C.t)) = call in (*unpack tuple for later use*) if LS.mem call path_visited_calls then ( - + AnalysisState.svcomp_must_terminate := false; (*Cycle found*) let msgs = [ @@ -1770,7 +1770,8 @@ struct let ret = ctx.ask Queries.MustTermProg in (* check result of loop analysis *) if not ret then - (let msgs = + (AnalysisState.svcomp_must_terminate := false; + let msgs = [ (Pretty.dprintf "The program might not terminate! (Loop analysis)\n", Some (M.Location.CilLocation locUnknown)); ] in diff --git a/src/witness/svcomp.ml b/src/witness/svcomp.ml index a5a572d1c2..a164448210 100644 --- a/src/witness/svcomp.ml +++ b/src/witness/svcomp.ml @@ -52,6 +52,7 @@ struct | UnreachCall _ -> "unreach-call" | NoOverflow -> "no-overflow" | NoDataRace -> "no-data-race" (* not yet in SV-COMP/Benchexec *) + | NoTermination -> "no-termination" in "false(" ^ result_spec ^ ")" | Unknown -> "unknown" diff --git a/src/witness/svcompSpec.ml b/src/witness/svcompSpec.ml index 464c170251..eec667c5a6 100644 --- a/src/witness/svcompSpec.ml +++ b/src/witness/svcompSpec.ml @@ -6,6 +6,7 @@ type t = | UnreachCall of string | NoDataRace | NoOverflow + | NoTermination let of_string s = let s = String.strip s in @@ -16,6 +17,8 @@ let of_string s = NoDataRace else if global_not = "overflow" then NoOverflow + else if global_not = "termination" then (*TODO: does this even work?*) + NoTermination else let call_regex = Str.regexp "call(\\(.*\\)())" in if Str.string_match call_regex global_not 0 then @@ -42,5 +45,6 @@ let to_string spec = | UnreachCall f -> "call(" ^ f ^ "())" | NoDataRace -> "data-race" | NoOverflow -> "overflow" + | NoTermination -> "termination" in "CHECK( init(main()), LTL(G ! " ^ global_not ^ ") )" diff --git a/src/witness/witness.ml b/src/witness/witness.ml index aff9a01383..04bcb1867b 100644 --- a/src/witness/witness.ml +++ b/src/witness/witness.ml @@ -442,6 +442,23 @@ struct in (module TaskResult:WitnessTaskResult) ) + | NoTermination -> (* TODO: implement this properly*) + let module TrivialArg = + struct + include Arg + let next _ = [] + end + in + let module TaskResult = + struct + module Arg = TrivialArg + let result = Result.Unknown + let invariant _ = Invariant.none + let is_violation _ = false + let is_sink _ = false + end + in + (module TaskResult:WitnessTaskResult) | NoOverflow -> let module TrivialArg = struct diff --git a/tests/regression/55-loop-unrolling/01-simple-cases.c b/tests/regression/55-loop-unrolling/01-simple-cases.c index 3d5ce1b4e4..add8c6a8dd 100644 --- a/tests/regression/55-loop-unrolling/01-simple-cases.c +++ b/tests/regression/55-loop-unrolling/01-simple-cases.c @@ -30,8 +30,7 @@ void example1(void) } __goblint_check(a[0] == 0); // UNKNOWN - lab:__goblint_check(a[3] == 3); // UNKNOWN - goto lab; + __goblint_check(a[3] == 3); // UNKNOWN } // Do-while loop simple example From 62d260fc915aefe9155a952d4a326b974c9d9fb8 Mon Sep 17 00:00:00 2001 From: Johanna Schinabeck Date: Thu, 22 Jun 2023 16:30:04 +0200 Subject: [PATCH 148/327] handled warnings during make --- output.txt | 2233 --------------------- src/analyses/apron/apronAnalysis.apron.ml | 2 - 2 files changed, 2235 deletions(-) delete mode 100644 output.txt diff --git a/output.txt b/output.txt deleted file mode 100644 index 37eb310726..0000000000 --- a/output.txt +++ /dev/null @@ -1,2233 +0,0 @@ -/* Generated by CIL v. 2.0.1-48-g4df989f */ -/* print_CIL_Input is true */ - -#line 31 "/usr/include/x86_64-linux-gnu/bits/types.h" -typedef unsigned char __u_char; -#line 32 "/usr/include/x86_64-linux-gnu/bits/types.h" -typedef unsigned short __u_short; -#line 33 "/usr/include/x86_64-linux-gnu/bits/types.h" -typedef unsigned int __u_int; -#line 34 "/usr/include/x86_64-linux-gnu/bits/types.h" -typedef unsigned long __u_long; -#line 37 "/usr/include/x86_64-linux-gnu/bits/types.h" -typedef signed char __int8_t; -#line 38 "/usr/include/x86_64-linux-gnu/bits/types.h" -typedef unsigned char __uint8_t; -#line 39 "/usr/include/x86_64-linux-gnu/bits/types.h" -typedef short __int16_t; -#line 40 "/usr/include/x86_64-linux-gnu/bits/types.h" -typedef unsigned short __uint16_t; -#line 41 "/usr/include/x86_64-linux-gnu/bits/types.h" -typedef int __int32_t; -#line 42 "/usr/include/x86_64-linux-gnu/bits/types.h" -typedef unsigned int __uint32_t; -#line 44 "/usr/include/x86_64-linux-gnu/bits/types.h" -typedef long __int64_t; -#line 45 "/usr/include/x86_64-linux-gnu/bits/types.h" -typedef unsigned long __uint64_t; -#line 52 "/usr/include/x86_64-linux-gnu/bits/types.h" -typedef __int8_t __int_least8_t; -#line 53 "/usr/include/x86_64-linux-gnu/bits/types.h" -typedef __uint8_t __uint_least8_t; -#line 54 "/usr/include/x86_64-linux-gnu/bits/types.h" -typedef __int16_t __int_least16_t; -#line 55 "/usr/include/x86_64-linux-gnu/bits/types.h" -typedef __uint16_t __uint_least16_t; -#line 56 "/usr/include/x86_64-linux-gnu/bits/types.h" -typedef __int32_t __int_least32_t; -#line 57 "/usr/include/x86_64-linux-gnu/bits/types.h" -typedef __uint32_t __uint_least32_t; -#line 58 "/usr/include/x86_64-linux-gnu/bits/types.h" -typedef __int64_t __int_least64_t; -#line 59 "/usr/include/x86_64-linux-gnu/bits/types.h" -typedef __uint64_t __uint_least64_t; -#line 63 "/usr/include/x86_64-linux-gnu/bits/types.h" -typedef long __quad_t; -#line 64 "/usr/include/x86_64-linux-gnu/bits/types.h" -typedef unsigned long __u_quad_t; -#line 72 "/usr/include/x86_64-linux-gnu/bits/types.h" -typedef long __intmax_t; -#line 73 "/usr/include/x86_64-linux-gnu/bits/types.h" -typedef unsigned long __uintmax_t; -#line 145 "/usr/include/x86_64-linux-gnu/bits/types.h" -typedef unsigned long __dev_t; -#line 146 "/usr/include/x86_64-linux-gnu/bits/types.h" -typedef unsigned int __uid_t; -#line 147 "/usr/include/x86_64-linux-gnu/bits/types.h" -typedef unsigned int __gid_t; -#line 148 "/usr/include/x86_64-linux-gnu/bits/types.h" -typedef unsigned long __ino_t; -#line 149 "/usr/include/x86_64-linux-gnu/bits/types.h" -typedef unsigned long __ino64_t; -#line 150 "/usr/include/x86_64-linux-gnu/bits/types.h" -typedef unsigned int __mode_t; -#line 151 "/usr/include/x86_64-linux-gnu/bits/types.h" -typedef unsigned long __nlink_t; -#line 152 "/usr/include/x86_64-linux-gnu/bits/types.h" -typedef long __off_t; -#line 153 "/usr/include/x86_64-linux-gnu/bits/types.h" -typedef long __off64_t; -#line 154 "/usr/include/x86_64-linux-gnu/bits/types.h" -typedef int __pid_t; -#line 155 "/usr/include/x86_64-linux-gnu/bits/types.h" -struct __anonstruct___fsid_t_109580352 { - int __val[2] ; -}; -#line 155 "/usr/include/x86_64-linux-gnu/bits/types.h" -typedef struct __anonstruct___fsid_t_109580352 __fsid_t; -#line 156 "/usr/include/x86_64-linux-gnu/bits/types.h" -typedef long __clock_t; -#line 157 "/usr/include/x86_64-linux-gnu/bits/types.h" -typedef unsigned long __rlim_t; -#line 158 "/usr/include/x86_64-linux-gnu/bits/types.h" -typedef unsigned long __rlim64_t; -#line 159 "/usr/include/x86_64-linux-gnu/bits/types.h" -typedef unsigned int __id_t; -#line 160 "/usr/include/x86_64-linux-gnu/bits/types.h" -typedef long __time_t; -#line 161 "/usr/include/x86_64-linux-gnu/bits/types.h" -typedef unsigned int __useconds_t; -#line 162 "/usr/include/x86_64-linux-gnu/bits/types.h" -typedef long __suseconds_t; -#line 163 "/usr/include/x86_64-linux-gnu/bits/types.h" -typedef long __suseconds64_t; -#line 165 "/usr/include/x86_64-linux-gnu/bits/types.h" -typedef int __daddr_t; -#line 166 "/usr/include/x86_64-linux-gnu/bits/types.h" -typedef int __key_t; -#line 169 "/usr/include/x86_64-linux-gnu/bits/types.h" -typedef int __clockid_t; -#line 172 "/usr/include/x86_64-linux-gnu/bits/types.h" -typedef void *__timer_t; -#line 175 "/usr/include/x86_64-linux-gnu/bits/types.h" -typedef long __blksize_t; -#line 180 "/usr/include/x86_64-linux-gnu/bits/types.h" -typedef long __blkcnt_t; -#line 181 "/usr/include/x86_64-linux-gnu/bits/types.h" -typedef long __blkcnt64_t; -#line 184 "/usr/include/x86_64-linux-gnu/bits/types.h" -typedef unsigned long __fsblkcnt_t; -#line 185 "/usr/include/x86_64-linux-gnu/bits/types.h" -typedef unsigned long __fsblkcnt64_t; -#line 188 "/usr/include/x86_64-linux-gnu/bits/types.h" -typedef unsigned long __fsfilcnt_t; -#line 189 "/usr/include/x86_64-linux-gnu/bits/types.h" -typedef unsigned long __fsfilcnt64_t; -#line 192 "/usr/include/x86_64-linux-gnu/bits/types.h" -typedef long __fsword_t; -#line 194 "/usr/include/x86_64-linux-gnu/bits/types.h" -typedef long __ssize_t; -#line 197 "/usr/include/x86_64-linux-gnu/bits/types.h" -typedef long __syscall_slong_t; -#line 199 "/usr/include/x86_64-linux-gnu/bits/types.h" -typedef unsigned long __syscall_ulong_t; -#line 203 "/usr/include/x86_64-linux-gnu/bits/types.h" -typedef __off64_t __loff_t; -#line 204 "/usr/include/x86_64-linux-gnu/bits/types.h" -typedef char *__caddr_t; -#line 207 "/usr/include/x86_64-linux-gnu/bits/types.h" -typedef long __intptr_t; -#line 210 "/usr/include/x86_64-linux-gnu/bits/types.h" -typedef unsigned int __socklen_t; -#line 215 "/usr/include/x86_64-linux-gnu/bits/types.h" -typedef int __sig_atomic_t; -#line 209 "/usr/lib/gcc/x86_64-linux-gnu/11/include/stddef.h" -typedef unsigned long size_t; -#line 10 "/usr/include/x86_64-linux-gnu/bits/types/time_t.h" -typedef __time_t time_t; -#line 11 "/usr/include/x86_64-linux-gnu/bits/types/struct_timespec.h" -struct timespec { - __time_t tv_sec ; - __syscall_slong_t tv_nsec ; -}; -#line 38 "/usr/include/sched.h" -typedef __pid_t pid_t; -#line 23 "/usr/include/x86_64-linux-gnu/bits/types/struct_sched_param.h" -struct sched_param { - int sched_priority ; -}; -#line 32 "/usr/include/x86_64-linux-gnu/bits/cpu-set.h" -typedef unsigned long __cpu_mask; -#line 39 "/usr/include/x86_64-linux-gnu/bits/cpu-set.h" -struct __anonstruct_cpu_set_t_826868708 { - __cpu_mask __bits[1024UL / (8UL * sizeof(__cpu_mask ))] ; -}; -#line 39 "/usr/include/x86_64-linux-gnu/bits/cpu-set.h" -typedef struct __anonstruct_cpu_set_t_826868708 cpu_set_t; -#line 7 "/usr/include/x86_64-linux-gnu/bits/types/clock_t.h" -typedef __clock_t clock_t; -#line 7 "/usr/include/x86_64-linux-gnu/bits/types/struct_tm.h" -struct tm { - int tm_sec ; - int tm_min ; - int tm_hour ; - int tm_mday ; - int tm_mon ; - int tm_year ; - int tm_wday ; - int tm_yday ; - int tm_isdst ; - long tm_gmtoff ; - char const *tm_zone ; -}; -#line 7 "/usr/include/x86_64-linux-gnu/bits/types/clockid_t.h" -typedef __clockid_t clockid_t; -#line 7 "/usr/include/x86_64-linux-gnu/bits/types/timer_t.h" -typedef __timer_t timer_t; -#line 8 "/usr/include/x86_64-linux-gnu/bits/types/struct_itimerspec.h" -struct itimerspec { - struct timespec it_interval ; - struct timespec it_value ; -}; -#line 49 "/usr/include/time.h" -struct sigevent ; -#line 27 "/usr/include/x86_64-linux-gnu/bits/types/__locale_t.h" -struct __locale_data ; -#line 27 "/usr/include/x86_64-linux-gnu/bits/types/__locale_t.h" -struct __locale_struct { - struct __locale_data *__locales[13] ; - unsigned short const *__ctype_b ; - int const *__ctype_tolower ; - int const *__ctype_toupper ; - char const *__names[13] ; -}; -#line 41 "/usr/include/x86_64-linux-gnu/bits/types/__locale_t.h" -typedef struct __locale_struct *__locale_t; -#line 24 "/usr/include/x86_64-linux-gnu/bits/types/locale_t.h" -typedef __locale_t locale_t; -#line 25 "/usr/include/x86_64-linux-gnu/bits/atomic_wide_counter.h" -struct __anonstruct___value32_817613185 { - unsigned int __low ; - unsigned int __high ; -}; -#line 25 "/usr/include/x86_64-linux-gnu/bits/atomic_wide_counter.h" -union __anonunion___atomic_wide_counter_316368393 { - unsigned long long __value64 ; - struct __anonstruct___value32_817613185 __value32 ; -}; -#line 25 "/usr/include/x86_64-linux-gnu/bits/atomic_wide_counter.h" -typedef union __anonunion___atomic_wide_counter_316368393 __atomic_wide_counter; -#line 51 "/usr/include/x86_64-linux-gnu/bits/thread-shared-types.h" -struct __pthread_internal_list { - struct __pthread_internal_list *__prev ; - struct __pthread_internal_list *__next ; -}; -#line 51 "/usr/include/x86_64-linux-gnu/bits/thread-shared-types.h" -typedef struct __pthread_internal_list __pthread_list_t; -#line 57 "/usr/include/x86_64-linux-gnu/bits/thread-shared-types.h" -struct __pthread_internal_slist { - struct __pthread_internal_slist *__next ; -}; -#line 57 "/usr/include/x86_64-linux-gnu/bits/thread-shared-types.h" -typedef struct __pthread_internal_slist __pthread_slist_t; -#line 22 "/usr/include/x86_64-linux-gnu/bits/struct_mutex.h" -struct __pthread_mutex_s { - int __lock ; - unsigned int __count ; - int __owner ; - unsigned int __nusers ; - int __kind ; - short __spins ; - short __elision ; - __pthread_list_t __list ; -}; -#line 23 "/usr/include/x86_64-linux-gnu/bits/struct_rwlock.h" -struct __pthread_rwlock_arch_t { - unsigned int __readers ; - unsigned int __writers ; - unsigned int __wrphase_futex ; - unsigned int __writers_futex ; - unsigned int __pad3 ; - unsigned int __pad4 ; - int __cur_writer ; - int __shared ; - signed char __rwelision ; - unsigned char __pad1[7] ; - unsigned long __pad2 ; - unsigned int __flags ; -}; -#line 94 "/usr/include/x86_64-linux-gnu/bits/thread-shared-types.h" -struct __pthread_cond_s { - __atomic_wide_counter __wseq ; - __atomic_wide_counter __g1_start ; - unsigned int __g_refs[2] ; - unsigned int __g_size[2] ; - unsigned int __g1_orig_size ; - unsigned int __wrefs ; - unsigned int __g_signals[2] ; -}; -#line 105 "/usr/include/x86_64-linux-gnu/bits/thread-shared-types.h" -typedef unsigned int __tss_t; -#line 106 "/usr/include/x86_64-linux-gnu/bits/thread-shared-types.h" -typedef unsigned long __thrd_t; -#line 108 "/usr/include/x86_64-linux-gnu/bits/thread-shared-types.h" -struct __anonstruct___once_flag_826868709 { - int __data ; -}; -#line 108 "/usr/include/x86_64-linux-gnu/bits/thread-shared-types.h" -typedef struct __anonstruct___once_flag_826868709 __once_flag; -#line 27 "/usr/include/x86_64-linux-gnu/bits/pthreadtypes.h" -typedef unsigned long pthread_t; -#line 32 "/usr/include/x86_64-linux-gnu/bits/pthreadtypes.h" -union __anonunion_pthread_mutexattr_t_488594144 { - char __size[4] ; - int __align ; -}; -#line 32 "/usr/include/x86_64-linux-gnu/bits/pthreadtypes.h" -typedef union __anonunion_pthread_mutexattr_t_488594144 pthread_mutexattr_t; -#line 41 "/usr/include/x86_64-linux-gnu/bits/pthreadtypes.h" -union __anonunion_pthread_condattr_t_488594145 { - char __size[4] ; - int __align ; -}; -#line 41 "/usr/include/x86_64-linux-gnu/bits/pthreadtypes.h" -typedef union __anonunion_pthread_condattr_t_488594145 pthread_condattr_t; -#line 49 "/usr/include/x86_64-linux-gnu/bits/pthreadtypes.h" -typedef unsigned int pthread_key_t; -#line 53 "/usr/include/x86_64-linux-gnu/bits/pthreadtypes.h" -typedef int pthread_once_t; -#line 56 "/usr/include/x86_64-linux-gnu/bits/pthreadtypes.h" -union pthread_attr_t { - char __size[56] ; - long __align ; -}; -#line 62 "/usr/include/x86_64-linux-gnu/bits/pthreadtypes.h" -typedef union pthread_attr_t pthread_attr_t; -#line 67 "/usr/include/x86_64-linux-gnu/bits/pthreadtypes.h" -union __anonunion_pthread_mutex_t_335460617 { - struct __pthread_mutex_s __data ; - char __size[40] ; - long __align ; -}; -#line 67 "/usr/include/x86_64-linux-gnu/bits/pthreadtypes.h" -typedef union __anonunion_pthread_mutex_t_335460617 pthread_mutex_t; -#line 75 "/usr/include/x86_64-linux-gnu/bits/pthreadtypes.h" -union __anonunion_pthread_cond_t_951761805 { - struct __pthread_cond_s __data ; - char __size[48] ; - long long __align ; -}; -#line 75 "/usr/include/x86_64-linux-gnu/bits/pthreadtypes.h" -typedef union __anonunion_pthread_cond_t_951761805 pthread_cond_t; -#line 86 "/usr/include/x86_64-linux-gnu/bits/pthreadtypes.h" -union __anonunion_pthread_rwlock_t_656928968 { - struct __pthread_rwlock_arch_t __data ; - char __size[56] ; - long __align ; -}; -#line 86 "/usr/include/x86_64-linux-gnu/bits/pthreadtypes.h" -typedef union __anonunion_pthread_rwlock_t_656928968 pthread_rwlock_t; -#line 93 "/usr/include/x86_64-linux-gnu/bits/pthreadtypes.h" -union __anonunion_pthread_rwlockattr_t_145707745 { - char __size[8] ; - long __align ; -}; -#line 93 "/usr/include/x86_64-linux-gnu/bits/pthreadtypes.h" -typedef union __anonunion_pthread_rwlockattr_t_145707745 pthread_rwlockattr_t; -#line 103 "/usr/include/x86_64-linux-gnu/bits/pthreadtypes.h" -typedef int volatile pthread_spinlock_t; -#line 108 "/usr/include/x86_64-linux-gnu/bits/pthreadtypes.h" -union __anonunion_pthread_barrier_t_145707746 { - char __size[32] ; - long __align ; -}; -#line 108 "/usr/include/x86_64-linux-gnu/bits/pthreadtypes.h" -typedef union __anonunion_pthread_barrier_t_145707746 pthread_barrier_t; -#line 114 "/usr/include/x86_64-linux-gnu/bits/pthreadtypes.h" -union __anonunion_pthread_barrierattr_t_951761806 { - char __size[4] ; - int __align ; -}; -#line 114 "/usr/include/x86_64-linux-gnu/bits/pthreadtypes.h" -typedef union __anonunion_pthread_barrierattr_t_951761806 pthread_barrierattr_t; -#line 31 "/usr/include/x86_64-linux-gnu/bits/setjmp.h" -typedef long __jmp_buf[8]; -#line 5 "/usr/include/x86_64-linux-gnu/bits/types/__sigset_t.h" -struct __anonstruct___sigset_t_764561023 { - unsigned long __val[1024UL / (8UL * sizeof(unsigned long ))] ; -}; -#line 5 "/usr/include/x86_64-linux-gnu/bits/types/__sigset_t.h" -typedef struct __anonstruct___sigset_t_764561023 __sigset_t; -#line 26 "/usr/include/x86_64-linux-gnu/bits/types/struct___jmp_buf_tag.h" -struct __jmp_buf_tag { - __jmp_buf __jmpbuf ; - int __mask_was_saved ; - __sigset_t __saved_mask ; -}; -#line 37 "/usr/include/pthread.h" -enum __anonenum_34415463 { - PTHREAD_CREATE_JOINABLE = 0, - PTHREAD_CREATE_DETACHED = 1 -} ; -#line 47 -enum __anonenum_508643754 { - PTHREAD_MUTEX_TIMED_NP = 0, - PTHREAD_MUTEX_RECURSIVE_NP = 1, - PTHREAD_MUTEX_ERRORCHECK_NP = 2, - PTHREAD_MUTEX_ADAPTIVE_NP = 3, - PTHREAD_MUTEX_NORMAL = 0, - PTHREAD_MUTEX_RECURSIVE = 1, - PTHREAD_MUTEX_ERRORCHECK = 2, - PTHREAD_MUTEX_DEFAULT = 0 -} ; -#line 69 -enum __anonenum_931900394 { - PTHREAD_MUTEX_STALLED = 0, - PTHREAD_MUTEX_STALLED_NP = 0, - PTHREAD_MUTEX_ROBUST = 1, - PTHREAD_MUTEX_ROBUST_NP = 1 -} ; -#line 81 -enum __anonenum_205214487 { - PTHREAD_PRIO_NONE = 0, - PTHREAD_PRIO_INHERIT = 1, - PTHREAD_PRIO_PROTECT = 2 -} ; -#line 104 -enum __anonenum_25043950 { - PTHREAD_RWLOCK_PREFER_READER_NP = 0, - PTHREAD_RWLOCK_PREFER_WRITER_NP = 1, - PTHREAD_RWLOCK_PREFER_WRITER_NONRECURSIVE_NP = 2, - PTHREAD_RWLOCK_DEFAULT_NP = 0 -} ; -#line 124 -enum __anonenum_436439511 { - PTHREAD_INHERIT_SCHED = 0, - PTHREAD_EXPLICIT_SCHED = 1 -} ; -#line 134 -enum __anonenum_998661166 { - PTHREAD_SCOPE_SYSTEM = 0, - PTHREAD_SCOPE_PROCESS = 1 -} ; -#line 144 -enum __anonenum_146137331 { - PTHREAD_PROCESS_PRIVATE = 0, - PTHREAD_PROCESS_SHARED = 1 -} ; -#line 159 "/usr/include/pthread.h" -struct _pthread_cleanup_buffer { - void (*__routine)(void * ) ; - void *__arg ; - int __canceltype ; - struct _pthread_cleanup_buffer *__prev ; -}; -#line 168 -enum __anonenum_53396917 { - PTHREAD_CANCEL_ENABLE = 0, - PTHREAD_CANCEL_DISABLE = 1 -} ; -#line 175 -enum __anonenum_904563783 { - PTHREAD_CANCEL_DEFERRED = 0, - PTHREAD_CANCEL_ASYNCHRONOUS = 1 -} ; -#line 538 "/usr/include/pthread.h" -struct __cancel_jmp_buf_tag { - __jmp_buf __cancel_jmp_buf ; - int __mask_was_saved ; -}; -#line 544 "/usr/include/pthread.h" -struct __anonstruct___pthread_unwind_buf_t_530692248 { - struct __cancel_jmp_buf_tag __cancel_jmp_buf[1] ; - void *__pad[4] ; -}; -#line 544 "/usr/include/pthread.h" -typedef struct __anonstruct___pthread_unwind_buf_t_530692248 __attribute__((__aligned__)) __pthread_unwind_buf_t; -#line 557 "/usr/include/pthread.h" -struct __pthread_cleanup_frame { - void (*__cancel_routine)(void * ) ; - void *__cancel_arg ; - int __do_it ; - int __cancel_type ; -}; -#line 143 "/usr/lib/gcc/x86_64-linux-gnu/11/include/stddef.h" -typedef long ptrdiff_t; -#line 321 "/usr/lib/gcc/x86_64-linux-gnu/11/include/stddef.h" -typedef int wchar_t; -#line 415 "/usr/lib/gcc/x86_64-linux-gnu/11/include/stddef.h" -struct __anonstruct_max_align_t_896270833 { - long long __max_align_ll __attribute__((__aligned__(__alignof__(long long )))) ; - long double __max_align_ld __attribute__((__aligned__(__alignof__(long double )))) ; -}; -#line 415 "/usr/lib/gcc/x86_64-linux-gnu/11/include/stddef.h" -typedef struct __anonstruct_max_align_t_896270833 max_align_t; -/* compiler builtin: - void __builtin_va_copy(__builtin_va_list , __builtin_va_list ) ; */ -/* compiler builtin: - void *__builtin_frob_return_address(void * ) ; */ -/* compiler builtin: - void __attribute__((__overloaded__)) __sync_and_and_fetch(...) ; */ -/* compiler builtin: - void __attribute__((__overloaded__)) __sync_fetch_and_or(...) ; */ -/* compiler builtin: - int __builtin_popcountll(unsigned long long ) ; */ -/* compiler builtin: - void __attribute__((__overloaded__)) __atomic_or_fetch(...) ; */ -/* compiler builtin: - float __builtin_atanf(float ) ; */ -/* compiler builtin: - float __attribute__((____vector_size____(16))) __builtin_ia32_addps(float __attribute__((____vector_size____(16))) , - float __attribute__((____vector_size____(16))) ) ; */ -/* compiler builtin: - unsigned long __builtin_strcspn(char const * , char const * ) ; */ -/* compiler builtin: - float __builtin_asinf(float ) ; */ -/* compiler builtin: - float __attribute__((____vector_size____(16))) __builtin_ia32_maxps(float __attribute__((____vector_size____(16))) , - float __attribute__((____vector_size____(16))) ) ; */ -/* compiler builtin: - float __attribute__((____vector_size____(16))) __builtin_ia32_unpckhps(float __attribute__((____vector_size____(16))) , - float __attribute__((____vector_size____(16))) ) ; */ -/* compiler builtin: - double __builtin_acos(double ) ; */ -/* compiler builtin: - int __builtin___sprintf_chk(char * , int , unsigned long , char const * , ...) ; */ -/* compiler builtin: - void __attribute__((__overloaded__)) __atomic_nand_fetch_8(...) ; */ -/* compiler builtin: - void __attribute__((__overloaded__)) __atomic_fetch_and(...) ; */ -/* compiler builtin: - void __attribute__((__overloaded__)) __atomic_xor_fetch_16(...) ; */ -/* compiler builtin: - double __builtin_cosh(double ) ; */ -/* compiler builtin: - float __builtin_tanhf(float ) ; */ -/* compiler builtin: - void __attribute__((__overloaded__)) __atomic_fetch_nand_16(...) ; */ -/* compiler builtin: - void *__builtin_mempcpy(void * , void const * , unsigned long ) ; */ -/* compiler builtin: - void __attribute__((__overloaded__)) __atomic_sub_fetch_1(...) ; */ -/* compiler builtin: - long double __builtin_sqrtl(long double ) ; */ -/* compiler builtin: - int __builtin_parity(unsigned int ) ; */ -/* compiler builtin: - void __attribute__((__overloaded__)) __atomic_fetch_or(...) ; */ -/* compiler builtin: - long double __builtin_coshl(long double ) ; */ -/* compiler builtin: - long double __builtin_cosl(long double ) ; */ -/* compiler builtin: - float __builtin_cosf(float ) ; */ -/* compiler builtin: - void __sync_synchronize(...) ; */ -/* compiler builtin: - long double __builtin_acosl(long double ) ; */ -/* compiler builtin: - void *__builtin___mempcpy_chk(void * , void const * , unsigned long , unsigned long ) ; */ -/* compiler builtin: - void __attribute__((__overloaded__)) __sync_or_and_fetch(...) ; */ -/* compiler builtin: - int __builtin_clz(unsigned int ) ; */ -/* compiler builtin: - void __attribute__((__overloaded__)) __atomic_nand_fetch_4(...) ; */ -/* compiler builtin: - double __builtin_log10(double ) ; */ -/* compiler builtin: - char *__builtin___strcat_chk(char * , char const * , unsigned long ) ; */ -/* compiler builtin: - float __builtin_modff(float , float * ) ; */ -/* compiler builtin: - void __attribute__((__overloaded__)) __atomic_sub_fetch_4(...) ; */ -/* compiler builtin: - _Bool __atomic_compare_exchange_n(...) ; */ -/* compiler builtin: - double __builtin_sin(double ) ; */ -/* compiler builtin: - double __builtin_frexp(double , int * ) ; */ -/* compiler builtin: - float __builtin_acosf(float ) ; */ -/* compiler builtin: - void __attribute__((__overloaded__)) __sync_add_and_fetch(...) ; */ -/* compiler builtin: - long double __builtin_sinhl(long double ) ; */ -/* compiler builtin: - char *__builtin___stpcpy_chk(char * , char const * , unsigned long ) ; */ -/* compiler builtin: - void __atomic_signal_fence(int ) ; */ -/* compiler builtin: - double __builtin_fabs(double ) ; */ -/* compiler builtin: - void __attribute__((__overloaded__)) __atomic_fetch_nand_1(...) ; */ -/* compiler builtin: - void __attribute__((__overloaded__)) __atomic_and_fetch_16(...) ; */ -/* compiler builtin: - void __attribute__((__overloaded__)) __sync_fetch_and_nand(...) ; */ -/* compiler builtin: - void __attribute__((__overloaded__)) __atomic_xor_fetch_8(...) ; */ -/* compiler builtin: - void __attribute__((__overloaded__)) __atomic_xor_fetch_2(...) ; */ -/* compiler builtin: - void __atomic_thread_fence(int ) ; */ -/* compiler builtin: - void __atomic_store_16(...) ; */ -/* compiler builtin: - void __builtin_va_start(__builtin_va_list ) ; */ -/* compiler builtin: - void __attribute__((__overloaded__)) __atomic_fetch_and_8(...) ; */ -/* compiler builtin: - short __builtin_bswap16(short ) ; */ -/* compiler builtin: - void __attribute__((__overloaded__)) __atomic_and_fetch_2(...) ; */ -/* compiler builtin: - _Bool __atomic_test_and_set(void * , int ) ; */ -/* compiler builtin: - void __attribute__((__overloaded__)) __atomic_fetch_add_8(...) ; */ -/* compiler builtin: - int __builtin_ctz(unsigned int ) ; */ -/* compiler builtin: - char *__builtin_strpbrk(char const * , char const * ) ; */ -/* compiler builtin: - char *__builtin_strcpy(char * , char const * ) ; */ -/* compiler builtin: - double __builtin_sqrt(double ) ; */ -/* compiler builtin: - __builtin_va_list __builtin_next_arg(void) ; */ -/* compiler builtin: - void __attribute__((__overloaded__)) __atomic_fetch_nand(...) ; */ -/* compiler builtin: - void __attribute__((__overloaded__)) __atomic_exchange_16(...) ; */ -/* compiler builtin: - void __atomic_clear(_Bool * , int ) ; */ -/* compiler builtin: - void __atomic_store(...) ; */ -/* compiler builtin: - void __attribute__((__overloaded__)) __atomic_add_fetch_2(...) ; */ -/* compiler builtin: - float __builtin_log10f(float ) ; */ -/* compiler builtin: - long double __builtin_fabsl(long double ) ; */ -/* compiler builtin: - long double __builtin_floorl(long double ) ; */ -/* compiler builtin: - void __attribute__((__overloaded__)) __atomic_fetch_xor_1(...) ; */ -/* compiler builtin: - void __attribute__((__overloaded__)) __atomic_and_fetch(...) ; */ -/* compiler builtin: - float __builtin_floorf(float ) ; */ -/* compiler builtin: - _Bool __atomic_compare_exchange_4(...) ; */ -/* compiler builtin: - void *__builtin_memcpy(void * , void const * , unsigned long ) ; */ -/* compiler builtin: - void __attribute__((__overloaded__)) __sync_sub_and_fetch(...) ; */ -/* compiler builtin: - void __attribute__((__overloaded__)) __sync_nand_and_fetch(...) ; */ -/* compiler builtin: - void __attribute__((__overloaded__)) __atomic_load_16(...) ; */ -/* compiler builtin: - float __attribute__((____vector_size____(16))) __builtin_ia32_subps(float __attribute__((____vector_size____(16))) , - float __attribute__((____vector_size____(16))) ) ; */ -/* compiler builtin: - int __builtin_parityll(unsigned long long ) ; */ -/* compiler builtin: - void __builtin_va_end(__builtin_va_list ) ; */ -/* compiler builtin: - void __builtin_bzero(void * , unsigned long ) ; */ -/* compiler builtin: - _Bool __atomic_always_lock_free(unsigned long , void * ) ; */ -/* compiler builtin: - int __builtin_strncmp(char const * , char const * , unsigned long ) ; */ -/* compiler builtin: - void __attribute__((__overloaded__)) __atomic_nand_fetch_16(...) ; */ -/* compiler builtin: - void __attribute__((__overloaded__)) __sync_xor_and_fetch(...) ; */ -/* compiler builtin: - int __builtin___vsprintf_chk(char * , int , unsigned long , char const * , - __builtin_va_list ) ; */ -/* compiler builtin: - float __builtin_sqrtf(float ) ; */ -/* compiler builtin: - double __builtin_nans(char const * ) ; */ -/* compiler builtin: - void __attribute__((__overloaded__)) __atomic_fetch_xor_8(...) ; */ -/* compiler builtin: - double __builtin_exp(double ) ; */ -/* compiler builtin: - void __attribute__((__overloaded__)) __atomic_exchange_8(...) ; */ -/* compiler builtin: - void __attribute__((__overloaded__)) __atomic_exchange_1(...) ; */ -/* compiler builtin: - int __builtin_strcmp(char const * , char const * ) ; */ -/* compiler builtin: - float __builtin_ldexpf(float , int ) ; */ -/* compiler builtin: - float __builtin_powif(float , int ) ; */ -/* compiler builtin: - long double __builtin_log10l(long double ) ; */ -/* compiler builtin: - void *__builtin___memmove_chk(void * , void const * , unsigned long , unsigned long ) ; */ -/* compiler builtin: - void __attribute__((__overloaded__)) __sync_fetch_and_and(...) ; */ -/* compiler builtin: - void *__builtin_return_address(unsigned int ) ; */ -/* compiler builtin: - void __atomic_feraiseexcept(int ) ; */ -/* compiler builtin: - void __attribute__((__overloaded__)) __atomic_and_fetch_4(...) ; */ -/* compiler builtin: - float __builtin_fabsf(float ) ; */ -/* compiler builtin: - void __attribute__((__overloaded__)) __atomic_or_fetch_8(...) ; */ -/* compiler builtin: - void __attribute__((__overloaded__)) __atomic_or_fetch_4(...) ; */ -/* compiler builtin: - void __attribute__((__overloaded__)) __atomic_or_fetch_1(...) ; */ -/* compiler builtin: - unsigned long __builtin_object_size(void * , int ) ; */ -/* compiler builtin: - void *__builtin_alloca(unsigned long ) ; */ -/* compiler builtin: - int __builtin_va_arg_pack_len(void) ; */ -/* compiler builtin: - long double __builtin_tanl(long double ) ; */ -/* compiler builtin: - void __attribute__((__overloaded__)) __atomic_fetch_and_2(...) ; */ -/* compiler builtin: - void __sync_lock_release(...) ; */ -/* compiler builtin: - long double __builtin_modfl(long double , long double * ) ; */ -/* compiler builtin: - void __attribute__((__overloaded__)) __atomic_fetch_nand_8(...) ; */ -/* compiler builtin: - char *__builtin_stpcpy(char * , char const * ) ; */ -/* compiler builtin: - long double __builtin_sinl(long double ) ; */ -/* compiler builtin: - double __builtin_asin(double ) ; */ -/* compiler builtin: - float __builtin_sinhf(float ) ; */ -/* compiler builtin: - int __builtin_ctzl(unsigned long ) ; */ -/* compiler builtin: - long double __builtin_tanhl(long double ) ; */ -/* compiler builtin: - void __attribute__((__overloaded__)) __atomic_fetch_add(...) ; */ -/* compiler builtin: - long __builtin_bswap64(long ) ; */ -/* compiler builtin: - void __attribute__((__overloaded__)) __atomic_nand_fetch_1(...) ; */ -/* compiler builtin: - void __attribute__((__overloaded__)) __atomic_fetch_nand_2(...) ; */ -/* compiler builtin: - float __attribute__((____vector_size____(16))) __builtin_ia32_mulps(float __attribute__((____vector_size____(16))) , - float __attribute__((____vector_size____(16))) ) ; */ -/* compiler builtin: - double __builtin_tan(double ) ; */ -/* compiler builtin: - char *__builtin_strncpy(char * , char const * , unsigned long ) ; */ -/* compiler builtin: - float __builtin_inff(void) ; */ -/* compiler builtin: - void *__builtin___memset_chk(void * , int , unsigned long , unsigned long ) ; */ -/* compiler builtin: - void __attribute__((__overloaded__)) __atomic_load_n(...) ; */ -/* compiler builtin: - double __builtin_huge_val(void) ; */ -/* compiler builtin: - int __builtin_clzl(unsigned long ) ; */ -/* compiler builtin: - _Bool __atomic_compare_exchange_16(...) ; */ -/* compiler builtin: - float __builtin_frexpf(float , int * ) ; */ -/* compiler builtin: - void __attribute__((__overloaded__)) __atomic_exchange_n(...) ; */ -/* compiler builtin: - void __attribute__((__overloaded__)) __atomic_fetch_or_1(...) ; */ -/* compiler builtin: - long double __builtin_fmodl(long double ) ; */ -/* compiler builtin: - double __builtin_atan(double ) ; */ -/* compiler builtin: - int __builtin___fprintf_chk(void * , int , char const * , ...) ; */ -/* compiler builtin: - float __builtin_ceilf(float ) ; */ -/* compiler builtin: - void __attribute__((__overloaded__)) __atomic_fetch_or_8(...) ; */ -/* compiler builtin: - void __attribute__((__overloaded__)) __atomic_fetch_add_1(...) ; */ -/* compiler builtin: - void __builtin_return(void const * ) ; */ -/* compiler builtin: - long double __builtin_asinl(long double ) ; */ -/* compiler builtin: - int __builtin_ffsll(unsigned long long ) ; */ -/* compiler builtin: - void __attribute__((__overloaded__)) __atomic_fetch_sub_1(...) ; */ -/* compiler builtin: - int __builtin_va_arg_pack(void) ; */ -/* compiler builtin: - void __attribute__((__overloaded__)) __atomic_fetch_or_4(...) ; */ -/* compiler builtin: - char *__builtin___strncpy_chk(char * , char const * , unsigned long , unsigned long ) ; */ -/* compiler builtin: - double __builtin_powi(double , int ) ; */ -/* compiler builtin: - void __attribute__((__overloaded__)) __atomic_load_2(...) ; */ -/* compiler builtin: - char *__builtin_strchr(char * , int ) ; */ -/* compiler builtin: - char *__builtin___strncat_chk(char * , char const * , unsigned long , unsigned long ) ; */ -/* compiler builtin: - void __atomic_store_2(...) ; */ -/* compiler builtin: - long double __builtin_huge_vall(void) ; */ -/* compiler builtin: - int __builtin_ffsl(unsigned long ) ; */ -/* compiler builtin: - int __builtin___vprintf_chk(int , char const * , __builtin_va_list ) ; */ -/* compiler builtin: - float __attribute__((____vector_size____(16))) __builtin_ia32_unpcklps(float __attribute__((____vector_size____(16))) , - float __attribute__((____vector_size____(16))) ) ; */ -/* compiler builtin: - char *__builtin_strncat(char * , char const * , unsigned long ) ; */ -/* compiler builtin: - int __builtin_ctzll(unsigned long long ) ; */ -/* compiler builtin: - void __builtin_stdarg_start(__builtin_va_list ) ; */ -/* compiler builtin: - void __attribute__((__overloaded__)) __atomic_exchange_4(...) ; */ -/* compiler builtin: - void __attribute__((__overloaded__)) __sync_fetch_and_xor(...) ; */ -/* compiler builtin: - void __attribute__((__overloaded__)) __atomic_fetch_sub_4(...) ; */ -/* compiler builtin: - void __attribute__((__overloaded__)) __atomic_fetch_and_4(...) ; */ -/* compiler builtin: - long double __builtin_frexpl(long double , int * ) ; */ -/* compiler builtin: - _Bool __atomic_compare_exchange(...) ; */ -/* compiler builtin: - float __builtin_tanf(float ) ; */ -/* compiler builtin: - long double __builtin_logl(long double ) ; */ -/* compiler builtin: - void __builtin_va_arg(__builtin_va_list , unsigned long , void * ) ; */ -/* compiler builtin: - long __builtin_expect(long , long ) ; */ -/* compiler builtin: - void __attribute__((__overloaded__)) __atomic_load_1(...) ; */ -/* compiler builtin: - _Bool __atomic_compare_exchange_1(...) ; */ -/* compiler builtin: - int __builtin___printf_chk(int , char const * , ...) ; */ -/* compiler builtin: - void __attribute__((__overloaded__)) __atomic_fetch_xor_2(...) ; */ -/* compiler builtin: - int __builtin___vfprintf_chk(void * , int , char const * , __builtin_va_list ) ; */ -/* compiler builtin: - void __builtin_prefetch(void const * , ...) ; */ -/* compiler builtin: - long double __builtin_nansl(char const * ) ; */ -/* compiler builtin: - double __builtin_fmod(double ) ; */ -/* compiler builtin: - void __atomic_load(...) ; */ -/* compiler builtin: - void __attribute__((__overloaded__)) __atomic_or_fetch_16(...) ; */ -/* compiler builtin: - void __attribute__((__overloaded__)) __atomic_add_fetch_16(...) ; */ -/* compiler builtin: - void __attribute__((__overloaded__)) __sync_val_compare_and_swap(...) ; */ -/* compiler builtin: - void __atomic_store_4(...) ; */ -/* compiler builtin: - double __builtin_tanh(double ) ; */ -/* compiler builtin: - void __attribute__((__overloaded__)) __atomic_fetch_and_1(...) ; */ -/* compiler builtin: - void __attribute__((__overloaded__)) __atomic_fetch_nand_4(...) ; */ -/* compiler builtin: - void __attribute__((__overloaded__)) __atomic_fetch_add_16(...) ; */ -/* compiler builtin: - void __builtin_unreachable(void) ; */ -/* compiler builtin: - _Bool __atomic_compare_exchange_2(...) ; */ -/* compiler builtin: - long double __builtin_ldexpl(long double , int ) ; */ -/* compiler builtin: - void *__builtin_apply(void (*)() , void * , unsigned long ) ; */ -/* compiler builtin: - float __builtin_sinf(float ) ; */ -/* compiler builtin: - double __builtin_ceil(double ) ; */ -/* compiler builtin: - void __atomic_exchange(...) ; */ -/* compiler builtin: - long double __builtin_powil(long double , int ) ; */ -/* compiler builtin: - void __attribute__((__overloaded__)) __atomic_sub_fetch_8(...) ; */ -/* compiler builtin: - long double __builtin_expl(long double ) ; */ -/* compiler builtin: - int __builtin_constant_p(int ) ; */ -/* compiler builtin: - void __attribute__((__overloaded__)) __atomic_fetch_sub_16(...) ; */ -/* compiler builtin: - double __builtin_log(double ) ; */ -/* compiler builtin: - float __builtin_expf(float ) ; */ -/* compiler builtin: - int __builtin_types_compatible_p(unsigned long , unsigned long ) ; */ -/* compiler builtin: - long double __builtin_atan2l(long double , long double ) ; */ -/* compiler builtin: - void *__builtin_apply_args(void) ; */ -/* compiler builtin: - void __attribute__((__overloaded__)) __atomic_exchange_2(...) ; */ -/* compiler builtin: - float __builtin_logf(float ) ; */ -/* compiler builtin: - void __attribute__((__overloaded__)) __atomic_sub_fetch_2(...) ; */ -/* compiler builtin: - unsigned long __builtin_strlen(char const * ) ; */ -/* compiler builtin: - int __builtin_ffs(unsigned int ) ; */ -/* compiler builtin: - void __attribute__((__overloaded__)) __atomic_fetch_xor_16(...) ; */ -/* compiler builtin: - double __builtin_inf(void) ; */ -/* compiler builtin: - void __attribute__((__overloaded__)) __atomic_fetch_or_16(...) ; */ -/* compiler builtin: - void *__builtin___memcpy_chk(void * , void const * , unsigned long , unsigned long ) ; */ -/* compiler builtin: - void __attribute__((__overloaded__)) __atomic_load_4(...) ; */ -/* compiler builtin: - void __atomic_store_n(...) ; */ -/* compiler builtin: - void __builtin_trap(void) ; */ -/* compiler builtin: - void __attribute__((__overloaded__)) __atomic_fetch_add_4(...) ; */ -/* compiler builtin: - int __builtin_parityl(unsigned long ) ; */ -/* compiler builtin: - void __attribute__((__overloaded__)) __atomic_nand_fetch_2(...) ; */ -/* compiler builtin: - void __attribute__((__overloaded__)) __sync_lock_test_and_set(...) ; */ -/* compiler builtin: - unsigned long __builtin_strspn(char const * , char const * ) ; */ -/* compiler builtin: - void __builtin_varargs_start(__builtin_va_list ) ; */ -/* compiler builtin: - void __attribute__((__overloaded__)) __atomic_sub_fetch(...) ; */ -/* compiler builtin: - void __attribute__((__overloaded__)) __atomic_fetch_and_16(...) ; */ -/* compiler builtin: - _Bool __atomic_compare_exchange_8(...) ; */ -/* compiler builtin: - void __attribute__((__overloaded__)) __atomic_nand_fetch(...) ; */ -/* compiler builtin: - double __builtin_nan(char const * ) ; */ -/* compiler builtin: - void __attribute__((__overloaded__)) __atomic_load_8(...) ; */ -/* compiler builtin: - int __builtin___snprintf_chk(char * , unsigned long , int , unsigned long , - char const * , ...) ; */ -/* compiler builtin: - void __attribute__((__overloaded__)) __atomic_xor_fetch_4(...) ; */ -/* compiler builtin: - void __attribute__((__overloaded__)) __atomic_fetch_sub_2(...) ; */ -/* compiler builtin: - void __attribute__((__overloaded__)) __atomic_add_fetch(...) ; */ -/* compiler builtin: - long double __builtin_atanl(long double ) ; */ -/* compiler builtin: - int __builtin_clzll(unsigned long long ) ; */ -/* compiler builtin: - float __builtin_huge_valf(void) ; */ -/* compiler builtin: - float __builtin_coshf(float ) ; */ -/* compiler builtin: - float __builtin_nansf(char const * ) ; */ -/* compiler builtin: - void __atomic_store_8(...) ; */ -/* compiler builtin: - void __attribute__((__overloaded__)) __atomic_xor_fetch(...) ; */ -/* compiler builtin: - void __attribute__((__overloaded__)) __sync_fetch_and_add(...) ; */ -/* compiler builtin: - int __builtin___vsnprintf_chk(char * , unsigned long , int , unsigned long , - char const * , __builtin_va_list ) ; */ -/* compiler builtin: - float __builtin_nanf(char const * ) ; */ -/* compiler builtin: - void __attribute__((__overloaded__)) __atomic_or_fetch_2(...) ; */ -/* compiler builtin: - void __attribute__((__overloaded__)) __atomic_add_fetch_1(...) ; */ -/* compiler builtin: - void __attribute__((__overloaded__)) __atomic_fetch_xor(...) ; */ -/* compiler builtin: - void __attribute__((__overloaded__)) __atomic_add_fetch_8(...) ; */ -/* compiler builtin: - void __attribute__((__overloaded__)) __atomic_fetch_xor_4(...) ; */ -/* compiler builtin: - void __attribute__((__overloaded__)) __atomic_fetch_sub_8(...) ; */ -/* compiler builtin: - _Bool __sync_bool_compare_and_swap(...) ; */ -/* compiler builtin: - double __builtin_atan2(double , double ) ; */ -/* compiler builtin: - void __attribute__((__overloaded__)) __builtin_tgmath(...) ; */ -/* compiler builtin: - int __builtin_popcountl(unsigned long ) ; */ -/* compiler builtin: - void __attribute__((__overloaded__)) __atomic_and_fetch_1(...) ; */ -/* compiler builtin: - long double __builtin_ceill(long double ) ; */ -/* compiler builtin: - void __atomic_store_1(...) ; */ -/* compiler builtin: - char *__builtin___strcpy_chk(char * , char const * , unsigned long ) ; */ -/* compiler builtin: - void __attribute__((__overloaded__)) __atomic_xor_fetch_1(...) ; */ -/* compiler builtin: - void __attribute__((__overloaded__)) __atomic_fetch_or_2(...) ; */ -/* compiler builtin: - void __attribute__((__overloaded__)) __atomic_sub_fetch_16(...) ; */ -/* compiler builtin: - double __builtin_floor(double ) ; */ -/* compiler builtin: - double __builtin_cos(double ) ; */ -/* compiler builtin: - void __attribute__((__overloaded__)) __sync_fetch_and_sub(...) ; */ -/* compiler builtin: - void *__builtin_memset(void * , int , int ) ; */ -/* compiler builtin: - void __attribute__((__overloaded__)) __atomic_fetch_add_2(...) ; */ -/* compiler builtin: - long double __builtin_nanl(char const * ) ; */ -/* compiler builtin: - float __builtin_atan2f(float , float ) ; */ -/* compiler builtin: - _Bool __atomic_is_lock_free(unsigned long , void * ) ; */ -/* compiler builtin: - int __builtin_popcount(unsigned int ) ; */ -/* compiler builtin: - double __builtin_sinh(double ) ; */ -/* compiler builtin: - void __builtin_bcopy(void const * , void * , unsigned long ) ; */ -/* compiler builtin: - void __attribute__((__overloaded__)) __atomic_and_fetch_8(...) ; */ -/* compiler builtin: - void __attribute__((__overloaded__)) __atomic_fetch_sub(...) ; */ -/* compiler builtin: - void *__builtin_extract_return_addr(void * ) ; */ -/* compiler builtin: - int __builtin_bswap32(int ) ; */ -/* compiler builtin: - double __builtin_ldexp(double , int ) ; */ -/* compiler builtin: - long double __builtin_infl(void) ; */ -/* compiler builtin: - float __builtin_fmodf(float ) ; */ -/* compiler builtin: - void __attribute__((__overloaded__)) __atomic_add_fetch_4(...) ; */ -/* compiler builtin: - void *__builtin_frame_address(unsigned int ) ; */ -#line 1 "lib/goblint/runtime/include/goblint.h" -extern void __goblint_check(int exp ) ; -#line 2 -extern void __goblint_assume(int exp ) ; -#line 3 -extern void __goblint_assert(int exp ) ; -#line 5 -extern void __goblint_assume_join() ; -#line 7 -extern void __goblint_split_begin(int exp ) ; -#line 8 -extern void __goblint_split_end(int exp ) ; -#line 4 "tests/regression/55-loop-unrolling/01-simple-cases.c" -int global ; -#line 8 -void example1(void) ; -#line 9 -void example2(void) ; -#line 10 -void example3(void) ; -#line 11 -void example4(void) ; -#line 12 -void example5(void) ; -#line 13 -void example6(void) ; -#line 14 -void example7(void) ; -#line 15 -void example8(void) ; -#line 16 -void example9(void) ; -#line 17 -void example10(void) ; -#line 6 "tests/regression/55-loop-unrolling/01-simple-cases.c" -int main(void) -{ - - - { -#line 8 - example1(); -#line 9 - example2(); -#line 10 - example3(); -#line 11 - example4(); -#line 12 - example5(); -#line 13 - example6(); -#line 14 - example7(); -#line 15 - example8(); -#line 16 - example9(); -#line 17 - example10(); -#line 18 - return (0); -} -} -#line 22 "tests/regression/55-loop-unrolling/01-simple-cases.c" -void example1(void) -{ - int a[5] ; - int i ; - int term27_5-file_01-simple-cases ; - - { -#line 25 - i = 0; - { -#line 27 - term27_5-file_01-simple-cases = 0; - { -#line 27 - while (1) { - while_continue: /* CIL Label */ ; -#line 27 - if (! (i < 5)) { -#line 27 - goto while_break; - } -#line 27 - term27_5-file_01-simple-cases ++; -#line 27 - term_exit- = term27_5-file_01-simple-cases; -#line 28 - a[i] = i; - } - while_break: /* CIL Label */ ; - } - } -#line 31 - __goblint_check(a[0] == 0); -#line 32 - __goblint_check(a[3] == 3); -#line 33 - return; -} -} -#line 36 "tests/regression/55-loop-unrolling/01-simple-cases.c" -void example2(void) -{ - int a[5] ; - int i ; - int term41_5-file_01-simple-cases ; - - { -#line 39 - i = 0; - { -#line 41 - term41_5-file_01-simple-cases = 0; - { -#line 41 - while (1) { - while_continue: /* CIL Label */ ; -#line 42 - a[i] = i; -#line 43 - i ++; -#line 41 - term41_5-file_01-simple-cases ++; -#line 41 - term_exit- = term41_5-file_01-simple-cases; -#line 41 - if (! (i <= 5)) { -#line 41 - goto while_break; - } - } - while_break: /* CIL Label */ ; - } - } -#line 46 - __goblint_check(a[0] == 0); -#line 47 - __goblint_check(a[3] == 3); -#line 48 - return; -} -} -#line 51 "tests/regression/55-loop-unrolling/01-simple-cases.c" -void example3(void) -{ - int a[10] ; - int i ; - int term56_5-file_01-simple-cases ; - - { -#line 54 - i = 0; - { -#line 56 - term56_5-file_01-simple-cases = 0; - { -#line 56 - while (1) { - while_continue: /* CIL Label */ ; -#line 56 - if (! (i < 5)) { -#line 56 - goto while_break; - } -#line 56 - term56_5-file_01-simple-cases ++; -#line 56 - term_exit- = term56_5-file_01-simple-cases; -#line 57 - a[i] = i; -#line 58 - i ++; - } - while_break: /* CIL Label */ ; - } - } -#line 61 - __goblint_check(a[0] == 0); -#line 62 - __goblint_check(a[3] == 0); -#line 63 - __goblint_check(a[7] == 0); -#line 64 - return; -} -} -#line 67 "tests/regression/55-loop-unrolling/01-simple-cases.c" -void example4(void) -{ - int a[10] ; - int i ; - int first_iteration ; - int term73_5-file_01-simple-cases ; - - { -#line 70 - i = 0; -#line 71 - first_iteration = 1; - { -#line 73 - term73_5-file_01-simple-cases = 0; - { -#line 73 - while (1) { - while_continue: /* CIL Label */ ; -#line 73 - if (! (i < 10)) { -#line 73 - goto while_break; - } -#line 73 - term73_5-file_01-simple-cases ++; -#line 73 - term_exit- = term73_5-file_01-simple-cases; -#line 74 - if (first_iteration == 1) { -#line 74 - __goblint_check(i == 0); - } else -#line 75 - if (i > 5) { -#line 75 - __goblint_check(i == 6); - } -#line 76 - first_iteration = 0; -#line 77 - a[i] = 0; -#line 78 - i ++; - } - while_break: /* CIL Label */ ; - } - } -#line 81 - __goblint_check(a[0] == 0); -#line 82 - __goblint_check(first_iteration == 0); -#line 83 - return; -} -} -#line 88 "tests/regression/55-loop-unrolling/01-simple-cases.c" -void example5(void) -{ - int a[4] ; - int i ; - int top ; - int term94_5-file_01-simple-cases ; - - { -#line 91 - i = 0; -#line 92 - top = 0; - { -#line 94 - term94_5-file_01-simple-cases = 0; - { -#line 94 - while (1) { - while_continue: /* CIL Label */ ; -#line 94 - if (! (i < 4)) { -#line 94 - goto while_break; - } -#line 94 - term94_5-file_01-simple-cases ++; -#line 94 - term_exit- = term94_5-file_01-simple-cases; -#line 95 - a[i] = 0; -#line 96 - top += i; -#line 97 - if (i == 2) { -#line 98 - __goblint_check(top == 3); - } else { -#line 101 - __goblint_check(top == 3); - } -#line 103 - i ++; - } - while_break: /* CIL Label */ ; - } - } -#line 106 - __goblint_check(a[0] == 0); -#line 107 - __goblint_check(a[3] == 0); -#line 108 - __goblint_check(top == 6); -#line 109 - return; -} -} -#line 112 "tests/regression/55-loop-unrolling/01-simple-cases.c" -void example6(void) -{ - int a[5] ; - int i ; - int top ; - int term118_5-file_01-simple-cases ; - - { -#line 115 - i = 0; -#line 116 - top = 0; - { -#line 118 - term118_5-file_01-simple-cases = 0; - { -#line 118 - while (1) { - while_continue: /* CIL Label */ ; -#line 118 - if (! (i < 3)) { -#line 118 - goto while_break; - } -#line 118 - term118_5-file_01-simple-cases ++; -#line 118 - term_exit- = term118_5-file_01-simple-cases; -#line 119 - a[i] = 0; -#line 120 - __goblint_check(a[0] == 0); -#line 121 - i ++; - } - while_break: /* CIL Label */ ; - } - } -#line 124 - __goblint_check(a[0] == 0); -#line 125 - __goblint_check(a[3] == 0); -#line 126 - __goblint_check(top == 6); -#line 127 - return; -} -} -#line 130 "tests/regression/55-loop-unrolling/01-simple-cases.c" -int update(int i ) -{ - - - { -#line 131 - if (i > 5) { -#line 132 - return (0); - } else { -#line 135 - return (1); - } -} -} -#line 138 "tests/regression/55-loop-unrolling/01-simple-cases.c" -void example7(void) -{ - int a[10] ; - int i ; - int tmp ; - int term142_2-file_01-simple-cases ; - - { -#line 141 - i = 0; - { -#line 142 - term142_2-file_01-simple-cases = 0; - { -#line 142 - while (1) { - while_continue: /* CIL Label */ ; -#line 142 - tmp = update(i); -#line 142 - term142_2-file_01-simple-cases ++; -#line 142 - term_exit- = term142_2-file_01-simple-cases; -#line 142 - if (! tmp) { -#line 142 - goto while_break; - } -#line 143 - a[i] = i; -#line 144 - i ++; - } - while_break: /* CIL Label */ ; - } - } -#line 146 - __goblint_check(a[0] == 0); -#line 147 - __goblint_check(a[6] == 0); -#line 148 - return; -} -} -#line 151 "tests/regression/55-loop-unrolling/01-simple-cases.c" -void example8(void) -{ - int a[5] ; - int b[5] ; - int i ; - int j ; - int term159_9-file_01-simple-cases ; - int term156_2-file_01-simple-cases ; - - { -#line 154 - b[0] = 0; -#line 154 - b[1] = 0; -#line 154 - b[2] = 0; -#line 154 - b[3] = 0; -#line 154 - b[4] = 0; -#line 155 - i = 0; - { -#line 156 - term156_2-file_01-simple-cases = 0; - { -#line 156 - while (1) { - while_continue: /* CIL Label */ ; -#line 156 - if (! (i < 5)) { -#line 156 - goto while_break; - } -#line 156 - term156_2-file_01-simple-cases ++; -#line 156 - term_exit- = term156_2-file_01-simple-cases; -#line 157 - a[i] = i; -#line 158 - j = 0; - { -#line 159 - term159_9-file_01-simple-cases = 0; - { -#line 159 - while (1) { - while_continue___0: /* CIL Label */ ; -#line 159 - if (! (j < 5)) { -#line 159 - goto while_break___0; - } -#line 159 - term159_9-file_01-simple-cases ++; -#line 159 - term_exit- = term159_9-file_01-simple-cases; -#line 160 - b[j] += a[i]; -#line 161 - j ++; - } - while_break___0: /* CIL Label */ ; - } - } -#line 163 - i ++; - } - while_break: /* CIL Label */ ; - } - } -#line 165 - return; -} -} -#line 169 "tests/regression/55-loop-unrolling/01-simple-cases.c" -void example9(void) -{ - int a[5] ; - int i ; - int term173_2-file_01-simple-cases ; - - { -#line 172 - i = 0; - { -#line 173 - term173_2-file_01-simple-cases = 0; - { -#line 173 - while (1) { - while_continue: /* CIL Label */ ; -#line 173 - if (! 1) { -#line 173 - goto while_break; - } -#line 173 - term173_2-file_01-simple-cases ++; -#line 173 - term_exit- = term173_2-file_01-simple-cases; -#line 174 - a[i] = i; -#line 175 - i ++; -#line 176 - if (i == 5) { -#line 176 - goto while_break; - } - } - while_break: /* CIL Label */ ; - } - } -#line 178 - return; -} -} -#line 182 "tests/regression/55-loop-unrolling/01-simple-cases.c" -void example10(void) -{ - int a[5] ; - int i ; - int term186_2-file_01-simple-cases ; - - { -#line 185 - i = 0; - { -#line 186 - term186_2-file_01-simple-cases = 0; - { -#line 186 - while (1) { - while_continue: /* CIL Label */ ; -#line 186 - if (! (i < 5)) { -#line 186 - goto while_break; - } -#line 186 - term186_2-file_01-simple-cases ++; -#line 186 - term_exit- = term186_2-file_01-simple-cases; -#line 187 - if (i == 3) { -#line 188 - i ++; -#line 189 - goto while_continue; - } -#line 191 - a[i] = i; -#line 192 - i ++; - } - while_break: /* CIL Label */ ; - } - } -#line 194 - return; -} -} -#line 117 "/usr/include/x86_64-linux-gnu/bits/cpu-set.h" -extern int ( __attribute__((__leaf__)) __sched_cpucount)(size_t __setsize , cpu_set_t const *__setp ) __attribute__((__nothrow__)) ; -#line 119 -extern cpu_set_t *( __attribute__((__leaf__)) __sched_cpualloc)(size_t __count ) __attribute__((__nothrow__)) ; -#line 120 -extern void ( __attribute__((__leaf__)) __sched_cpufree)(cpu_set_t *__set ) __attribute__((__nothrow__)) ; -#line 54 "/usr/include/sched.h" -extern int ( __attribute__((__leaf__)) sched_setparam)(__pid_t __pid , struct sched_param const *__param ) __attribute__((__nothrow__)) ; -#line 58 -extern int ( __attribute__((__leaf__)) sched_getparam)(__pid_t __pid , struct sched_param *__param ) __attribute__((__nothrow__)) ; -#line 61 -extern int ( __attribute__((__leaf__)) sched_setscheduler)(__pid_t __pid , int __policy , - struct sched_param const *__param ) __attribute__((__nothrow__)) ; -#line 65 -extern int ( __attribute__((__leaf__)) sched_getscheduler)(__pid_t __pid ) __attribute__((__nothrow__)) ; -#line 68 -extern int ( __attribute__((__leaf__)) sched_yield)(void) __attribute__((__nothrow__)) ; -#line 71 -extern int ( __attribute__((__leaf__)) sched_get_priority_max)(int __algorithm ) __attribute__((__nothrow__)) ; -#line 74 -extern int ( __attribute__((__leaf__)) sched_get_priority_min)(int __algorithm ) __attribute__((__nothrow__)) ; -#line 78 -extern int ( __attribute__((__leaf__)) sched_rr_get_interval)(__pid_t __pid , struct timespec *__t ) __attribute__((__nothrow__)) ; -#line 72 "/usr/include/time.h" -extern clock_t ( __attribute__((__leaf__)) clock)(void) __attribute__((__nothrow__)) ; -#line 76 -extern time_t ( __attribute__((__leaf__)) time)(time_t *__timer ) __attribute__((__nothrow__)) ; -#line 79 -extern double ( __attribute__((__leaf__)) difftime)(time_t __time1 , time_t __time0 ) __attribute__((__nothrow__, -__const__)) ; -#line 83 -extern time_t ( __attribute__((__leaf__)) mktime)(struct tm *__tp ) __attribute__((__nothrow__)) ; -#line 100 -extern size_t ( __attribute__((__leaf__)) strftime)(char * __restrict __s , size_t __maxsize , - char const * __restrict __format , - struct tm const * __restrict __tp ) __attribute__((__nothrow__)) ; -#line 116 -extern size_t ( __attribute__((__leaf__)) strftime_l)(char * __restrict __s , size_t __maxsize , - char const * __restrict __format , - struct tm const * __restrict __tp , - locale_t __loc ) __attribute__((__nothrow__)) ; -#line 132 -extern struct tm *( __attribute__((__leaf__)) gmtime)(time_t const *__timer ) __attribute__((__nothrow__)) ; -#line 136 -extern struct tm *( __attribute__((__leaf__)) localtime)(time_t const *__timer ) __attribute__((__nothrow__)) ; -#line 154 -extern struct tm *( __attribute__((__leaf__)) gmtime_r)(time_t const * __restrict __timer , - struct tm * __restrict __tp ) __attribute__((__nothrow__)) ; -#line 159 -extern struct tm *( __attribute__((__leaf__)) localtime_r)(time_t const * __restrict __timer , - struct tm * __restrict __tp ) __attribute__((__nothrow__)) ; -#line 179 -extern char *( __attribute__((__leaf__)) asctime)(struct tm const *__tp ) __attribute__((__nothrow__)) ; -#line 183 -extern char *( __attribute__((__leaf__)) ctime)(time_t const *__timer ) __attribute__((__nothrow__)) ; -#line 197 -extern char *( __attribute__((__leaf__)) asctime_r)(struct tm const * __restrict __tp , - char * __restrict __buf ) __attribute__((__nothrow__)) ; -#line 202 -extern char *( __attribute__((__leaf__)) ctime_r)(time_t const * __restrict __timer , - char * __restrict __buf ) __attribute__((__nothrow__)) ; -#line 217 -extern char *__tzname[2] ; -#line 218 -extern int __daylight ; -#line 219 -extern long __timezone ; -#line 224 -extern char *tzname[2] ; -#line 228 -extern void ( __attribute__((__leaf__)) tzset)(void) __attribute__((__nothrow__)) ; -#line 232 -extern int daylight ; -#line 233 -extern long timezone ; -#line 249 -extern time_t ( __attribute__((__leaf__)) timegm)(struct tm *__tp ) __attribute__((__nothrow__)) ; -#line 251 -extern time_t ( __attribute__((__leaf__)) timelocal)(struct tm *__tp ) __attribute__((__nothrow__)) ; -#line 262 -extern int ( __attribute__((__leaf__)) dysize)(int __year ) __attribute__((__nothrow__, -__const__)) ; -#line 272 -extern int nanosleep(struct timespec const *__requested_time , struct timespec *__remaining ) ; -#line 276 -extern int ( __attribute__((__leaf__)) clock_getres)(clockid_t __clock_id , struct timespec *__res ) __attribute__((__nothrow__)) ; -#line 279 -extern int ( __attribute__((__leaf__)) clock_gettime)(clockid_t __clock_id , struct timespec *__tp ) __attribute__((__nothrow__)) ; -#line 282 -extern int ( __attribute__((__leaf__)) clock_settime)(clockid_t __clock_id , struct timespec const *__tp ) __attribute__((__nothrow__)) ; -#line 311 -extern int clock_nanosleep(clockid_t __clock_id , int __flags , struct timespec const *__req , - struct timespec *__rem ) ; -#line 326 -extern int ( __attribute__((__leaf__)) clock_getcpuclockid)(pid_t __pid , clockid_t *__clock_id ) __attribute__((__nothrow__)) ; -#line 331 -extern int ( __attribute__((__leaf__)) timer_create)(clockid_t __clock_id , struct sigevent * __restrict __evp , - timer_t * __restrict __timerid ) __attribute__((__nothrow__)) ; -#line 336 -extern int ( __attribute__((__leaf__)) timer_delete)(timer_t __timerid ) __attribute__((__nothrow__)) ; -#line 340 -extern int ( __attribute__((__leaf__)) timer_settime)(timer_t __timerid , int __flags , - struct itimerspec const * __restrict __value , - struct itimerspec * __restrict __ovalue ) __attribute__((__nothrow__)) ; -#line 345 -extern int ( __attribute__((__leaf__)) timer_gettime)(timer_t __timerid , struct itimerspec *__value ) __attribute__((__nothrow__)) ; -#line 364 -extern int ( __attribute__((__leaf__)) timer_getoverrun)(timer_t __timerid ) __attribute__((__nothrow__)) ; -#line 371 -extern int ( __attribute__((__nonnull__(1), __leaf__)) timespec_get)(struct timespec *__ts , - int __base ) __attribute__((__nothrow__)) ; -#line 202 "/usr/include/pthread.h" -extern int ( __attribute__((__nonnull__(1,3))) pthread_create)(pthread_t * __restrict __newthread , - pthread_attr_t const * __restrict __attr , - void *(*__start_routine)(void * ) , - void * __restrict __arg ) __attribute__((__nothrow__)) ; -#line 211 -extern void pthread_exit(void *__retval ) __attribute__((__noreturn__)) ; -#line 219 -extern int pthread_join(pthread_t __th , void **__thread_return ) ; -#line 269 -extern int ( __attribute__((__leaf__)) pthread_detach)(pthread_t __th ) __attribute__((__nothrow__)) ; -#line 273 -extern pthread_t ( __attribute__((__leaf__)) pthread_self)(void) __attribute__((__nothrow__, -__const__)) ; -#line 276 -extern int ( __attribute__((__leaf__)) pthread_equal)(pthread_t __thread1 , pthread_t __thread2 ) __attribute__((__nothrow__, -__const__)) ; -#line 285 -extern int ( __attribute__((__nonnull__(1), __leaf__)) pthread_attr_init)(pthread_attr_t *__attr ) __attribute__((__nothrow__)) ; -#line 288 -extern int ( __attribute__((__nonnull__(1), __leaf__)) pthread_attr_destroy)(pthread_attr_t *__attr ) __attribute__((__nothrow__)) ; -#line 292 -extern int ( __attribute__((__nonnull__(1,2), __leaf__)) pthread_attr_getdetachstate)(pthread_attr_t const *__attr , - int *__detachstate ) __attribute__((__nothrow__)) ; -#line 297 -extern int ( __attribute__((__nonnull__(1), __leaf__)) pthread_attr_setdetachstate)(pthread_attr_t *__attr , - int __detachstate ) __attribute__((__nothrow__)) ; -#line 303 -extern int ( __attribute__((__nonnull__(1,2), __leaf__)) pthread_attr_getguardsize)(pthread_attr_t const *__attr , - size_t *__guardsize ) __attribute__((__nothrow__)) ; -#line 308 -extern int ( __attribute__((__nonnull__(1), __leaf__)) pthread_attr_setguardsize)(pthread_attr_t *__attr , - size_t __guardsize ) __attribute__((__nothrow__)) ; -#line 314 -extern int ( __attribute__((__nonnull__(1,2), __leaf__)) pthread_attr_getschedparam)(pthread_attr_t const * __restrict __attr , - struct sched_param * __restrict __param ) __attribute__((__nothrow__)) ; -#line 319 -extern int ( __attribute__((__nonnull__(1,2), __leaf__)) pthread_attr_setschedparam)(pthread_attr_t * __restrict __attr , - struct sched_param const * __restrict __param ) __attribute__((__nothrow__)) ; -#line 324 -extern int ( __attribute__((__nonnull__(1,2), __leaf__)) pthread_attr_getschedpolicy)(pthread_attr_t const * __restrict __attr , - int * __restrict __policy ) __attribute__((__nothrow__)) ; -#line 329 -extern int ( __attribute__((__nonnull__(1), __leaf__)) pthread_attr_setschedpolicy)(pthread_attr_t *__attr , - int __policy ) __attribute__((__nothrow__)) ; -#line 333 -extern int ( __attribute__((__nonnull__(1,2), __leaf__)) pthread_attr_getinheritsched)(pthread_attr_t const * __restrict __attr , - int * __restrict __inherit ) __attribute__((__nothrow__)) ; -#line 338 -extern int ( __attribute__((__nonnull__(1), __leaf__)) pthread_attr_setinheritsched)(pthread_attr_t *__attr , - int __inherit ) __attribute__((__nothrow__)) ; -#line 344 -extern int ( __attribute__((__nonnull__(1,2), __leaf__)) pthread_attr_getscope)(pthread_attr_t const * __restrict __attr , - int * __restrict __scope ) __attribute__((__nothrow__)) ; -#line 349 -extern int ( __attribute__((__nonnull__(1), __leaf__)) pthread_attr_setscope)(pthread_attr_t *__attr , - int __scope ) __attribute__((__nothrow__)) ; -#line 353 -extern int ( __attribute__((__nonnull__(1,2), __leaf__)) pthread_attr_getstackaddr)(pthread_attr_t const * __restrict __attr , - void ** __restrict __stackaddr ) __attribute__((__nothrow__, -__deprecated__)) ; -#line 361 -extern int ( __attribute__((__nonnull__(1), __leaf__)) pthread_attr_setstackaddr)(pthread_attr_t *__attr , - void *__stackaddr ) __attribute__((__nothrow__, -__deprecated__)) ; -#line 366 -extern int ( __attribute__((__nonnull__(1,2), __leaf__)) pthread_attr_getstacksize)(pthread_attr_t const * __restrict __attr , - size_t * __restrict __stacksize ) __attribute__((__nothrow__)) ; -#line 373 -extern int ( __attribute__((__nonnull__(1), __leaf__)) pthread_attr_setstacksize)(pthread_attr_t *__attr , - size_t __stacksize ) __attribute__((__nothrow__)) ; -#line 379 -extern int ( __attribute__((__nonnull__(1,2,3), __leaf__)) pthread_attr_getstack)(pthread_attr_t const * __restrict __attr , - void ** __restrict __stackaddr , - size_t * __restrict __stacksize ) __attribute__((__nothrow__)) ; -#line 387 -extern int ( __attribute__((__nonnull__(1), __leaf__)) pthread_attr_setstack)(pthread_attr_t *__attr , - void *__stackaddr , - size_t __stacksize ) __attribute__((__nothrow__)) ; -#line 441 -extern int ( __attribute__((__nonnull__(3), __leaf__)) pthread_setschedparam)(pthread_t __target_thread , - int __policy , - struct sched_param const *__param ) __attribute__((__nothrow__)) ; -#line 446 -extern int ( __attribute__((__nonnull__(2,3), __leaf__)) pthread_getschedparam)(pthread_t __target_thread , - int * __restrict __policy , - struct sched_param * __restrict __param ) __attribute__((__nothrow__)) ; -#line 452 -extern int ( __attribute__((__leaf__)) pthread_setschedprio)(pthread_t __target_thread , - int __prio ) __attribute__((__nothrow__)) ; -#line 509 -int ( __attribute__((__nonnull__(1,2))) pthread_once)(pthread_once_t *once_control , - void (*init_routine)(void) ) __attribute__((__goblint_stub__)) ; -#line 521 -extern int pthread_setcancelstate(int __state , int *__oldstate ) ; -#line 525 -extern int pthread_setcanceltype(int __type , int *__oldtype ) ; -#line 528 -extern int pthread_cancel(pthread_t __th ) ; -#line 533 -extern void pthread_testcancel(void) ; -#line 697 -extern void __pthread_register_cancel(__pthread_unwind_buf_t *__buf ) ; -#line 709 -extern void __pthread_unregister_cancel(__pthread_unwind_buf_t *__buf ) ; -#line 750 -extern void __pthread_unwind_next(__pthread_unwind_buf_t *__buf ) __attribute__((__weak__, -__noreturn__)) ; -#line 766 -extern int __sigsetjmp_cancel(struct __cancel_jmp_buf_tag *__env , int __savemask ) __asm__("__sigsetjmp") __attribute__((__returns_twice__, -__nothrow__)) ; -#line 781 -extern int ( __attribute__((__nonnull__(1), __leaf__)) pthread_mutex_init)(pthread_mutex_t *__mutex , - pthread_mutexattr_t const *__mutexattr ) __attribute__((__nothrow__)) ; -#line 786 -extern int ( __attribute__((__nonnull__(1), __leaf__)) pthread_mutex_destroy)(pthread_mutex_t *__mutex ) __attribute__((__nothrow__)) ; -#line 790 -extern int ( __attribute__((__nonnull__(1))) pthread_mutex_trylock)(pthread_mutex_t *__mutex ) __attribute__((__nothrow__)) ; -#line 794 -extern int ( __attribute__((__nonnull__(1))) pthread_mutex_lock)(pthread_mutex_t *__mutex ) __attribute__((__nothrow__)) ; -#line 800 -extern int ( __attribute__((__nonnull__(1,2))) pthread_mutex_timedlock)(pthread_mutex_t * __restrict __mutex , - struct timespec const * __restrict __abstime ) __attribute__((__nothrow__)) ; -#line 835 -extern int ( __attribute__((__nonnull__(1))) pthread_mutex_unlock)(pthread_mutex_t *__mutex ) __attribute__((__nothrow__)) ; -#line 840 -extern int ( __attribute__((__nonnull__(1,2), __leaf__)) pthread_mutex_getprioceiling)(pthread_mutex_t const * __restrict __mutex , - int * __restrict __prioceiling ) __attribute__((__nothrow__)) ; -#line 847 -extern int ( __attribute__((__nonnull__(1,3), __leaf__)) pthread_mutex_setprioceiling)(pthread_mutex_t * __restrict __mutex , - int __prioceiling , - int * __restrict __old_ceiling ) __attribute__((__nothrow__)) ; -#line 855 -extern int ( __attribute__((__nonnull__(1), __leaf__)) pthread_mutex_consistent)(pthread_mutex_t *__mutex ) __attribute__((__nothrow__)) ; -#line 874 -extern int ( __attribute__((__nonnull__(1), __leaf__)) pthread_mutexattr_init)(pthread_mutexattr_t *__attr ) __attribute__((__nothrow__)) ; -#line 878 -extern int ( __attribute__((__nonnull__(1), __leaf__)) pthread_mutexattr_destroy)(pthread_mutexattr_t *__attr ) __attribute__((__nothrow__)) ; -#line 882 -extern int ( __attribute__((__nonnull__(1,2), __leaf__)) pthread_mutexattr_getpshared)(pthread_mutexattr_t const * __restrict __attr , - int * __restrict __pshared ) __attribute__((__nothrow__)) ; -#line 888 -extern int ( __attribute__((__nonnull__(1), __leaf__)) pthread_mutexattr_setpshared)(pthread_mutexattr_t *__attr , - int __pshared ) __attribute__((__nothrow__)) ; -#line 894 -extern int ( __attribute__((__nonnull__(1,2), __leaf__)) pthread_mutexattr_gettype)(pthread_mutexattr_t const * __restrict __attr , - int * __restrict __kind ) __attribute__((__nothrow__)) ; -#line 901 -extern int ( __attribute__((__nonnull__(1), __leaf__)) pthread_mutexattr_settype)(pthread_mutexattr_t *__attr , - int __kind ) __attribute__((__nothrow__)) ; -#line 906 -extern int ( __attribute__((__nonnull__(1,2), __leaf__)) pthread_mutexattr_getprotocol)(pthread_mutexattr_t const * __restrict __attr , - int * __restrict __protocol ) __attribute__((__nothrow__)) ; -#line 913 -extern int ( __attribute__((__nonnull__(1), __leaf__)) pthread_mutexattr_setprotocol)(pthread_mutexattr_t *__attr , - int __protocol ) __attribute__((__nothrow__)) ; -#line 918 -extern int ( __attribute__((__nonnull__(1,2), __leaf__)) pthread_mutexattr_getprioceiling)(pthread_mutexattr_t const * __restrict __attr , - int * __restrict __prioceiling ) __attribute__((__nothrow__)) ; -#line 924 -extern int ( __attribute__((__nonnull__(1), __leaf__)) pthread_mutexattr_setprioceiling)(pthread_mutexattr_t *__attr , - int __prioceiling ) __attribute__((__nothrow__)) ; -#line 930 -extern int ( __attribute__((__nonnull__(1,2), __leaf__)) pthread_mutexattr_getrobust)(pthread_mutexattr_t const *__attr , - int *__robustness ) __attribute__((__nothrow__)) ; -#line 946 -extern int ( __attribute__((__nonnull__(1), __leaf__)) pthread_mutexattr_setrobust)(pthread_mutexattr_t *__attr , - int __robustness ) __attribute__((__nothrow__)) ; -#line 967 -extern int ( __attribute__((__nonnull__(1), __leaf__)) pthread_rwlock_init)(pthread_rwlock_t * __restrict __rwlock , - pthread_rwlockattr_t const * __restrict __attr ) __attribute__((__nothrow__)) ; -#line 972 -extern int ( __attribute__((__nonnull__(1), __leaf__)) pthread_rwlock_destroy)(pthread_rwlock_t *__rwlock ) __attribute__((__nothrow__)) ; -#line 976 -extern int ( __attribute__((__nonnull__(1))) pthread_rwlock_rdlock)(pthread_rwlock_t *__rwlock ) __attribute__((__nothrow__)) ; -#line 980 -extern int ( __attribute__((__nonnull__(1))) pthread_rwlock_tryrdlock)(pthread_rwlock_t *__rwlock ) __attribute__((__nothrow__)) ; -#line 986 -extern int ( __attribute__((__nonnull__(1,2))) pthread_rwlock_timedrdlock)(pthread_rwlock_t * __restrict __rwlock , - struct timespec const * __restrict __abstime ) __attribute__((__nothrow__)) ; -#line 1023 -extern int ( __attribute__((__nonnull__(1))) pthread_rwlock_wrlock)(pthread_rwlock_t *__rwlock ) __attribute__((__nothrow__)) ; -#line 1027 -extern int ( __attribute__((__nonnull__(1))) pthread_rwlock_trywrlock)(pthread_rwlock_t *__rwlock ) __attribute__((__nothrow__)) ; -#line 1033 -extern int ( __attribute__((__nonnull__(1,2))) pthread_rwlock_timedwrlock)(pthread_rwlock_t * __restrict __rwlock , - struct timespec const * __restrict __abstime ) __attribute__((__nothrow__)) ; -#line 1071 -extern int ( __attribute__((__nonnull__(1))) pthread_rwlock_unlock)(pthread_rwlock_t *__rwlock ) __attribute__((__nothrow__)) ; -#line 1078 -extern int ( __attribute__((__nonnull__(1), __leaf__)) pthread_rwlockattr_init)(pthread_rwlockattr_t *__attr ) __attribute__((__nothrow__)) ; -#line 1082 -extern int ( __attribute__((__nonnull__(1), __leaf__)) pthread_rwlockattr_destroy)(pthread_rwlockattr_t *__attr ) __attribute__((__nothrow__)) ; -#line 1086 -extern int ( __attribute__((__nonnull__(1,2), __leaf__)) pthread_rwlockattr_getpshared)(pthread_rwlockattr_t const * __restrict __attr , - int * __restrict __pshared ) __attribute__((__nothrow__)) ; -#line 1092 -extern int ( __attribute__((__nonnull__(1), __leaf__)) pthread_rwlockattr_setpshared)(pthread_rwlockattr_t *__attr , - int __pshared ) __attribute__((__nothrow__)) ; -#line 1097 -extern int ( __attribute__((__nonnull__(1,2), __leaf__)) pthread_rwlockattr_getkind_np)(pthread_rwlockattr_t const * __restrict __attr , - int * __restrict __pref ) __attribute__((__nothrow__)) ; -#line 1103 -extern int ( __attribute__((__nonnull__(1), __leaf__)) pthread_rwlockattr_setkind_np)(pthread_rwlockattr_t *__attr , - int __pref ) __attribute__((__nothrow__)) ; -#line 1112 -extern int ( __attribute__((__nonnull__(1), __leaf__)) pthread_cond_init)(pthread_cond_t * __restrict __cond , - pthread_condattr_t const * __restrict __cond_attr ) __attribute__((__nothrow__)) ; -#line 1117 -extern int ( __attribute__((__nonnull__(1), __leaf__)) pthread_cond_destroy)(pthread_cond_t *__cond ) __attribute__((__nothrow__)) ; -#line 1121 -extern int ( __attribute__((__nonnull__(1))) pthread_cond_signal)(pthread_cond_t *__cond ) __attribute__((__nothrow__)) ; -#line 1125 -extern int ( __attribute__((__nonnull__(1))) pthread_cond_broadcast)(pthread_cond_t *__cond ) __attribute__((__nothrow__)) ; -#line 1133 -extern int ( __attribute__((__nonnull__(1,2))) pthread_cond_wait)(pthread_cond_t * __restrict __cond , - pthread_mutex_t * __restrict __mutex ) ; -#line 1145 -extern int ( __attribute__((__nonnull__(1,2,3))) pthread_cond_timedwait)(pthread_cond_t * __restrict __cond , - pthread_mutex_t * __restrict __mutex , - struct timespec const * __restrict __abstime ) ; -#line 1194 -extern int ( __attribute__((__nonnull__(1), __leaf__)) pthread_condattr_init)(pthread_condattr_t *__attr ) __attribute__((__nothrow__)) ; -#line 1198 -extern int ( __attribute__((__nonnull__(1), __leaf__)) pthread_condattr_destroy)(pthread_condattr_t *__attr ) __attribute__((__nothrow__)) ; -#line 1202 -extern int ( __attribute__((__nonnull__(1,2), __leaf__)) pthread_condattr_getpshared)(pthread_condattr_t const * __restrict __attr , - int * __restrict __pshared ) __attribute__((__nothrow__)) ; -#line 1208 -extern int ( __attribute__((__nonnull__(1), __leaf__)) pthread_condattr_setpshared)(pthread_condattr_t *__attr , - int __pshared ) __attribute__((__nothrow__)) ; -#line 1213 -extern int ( __attribute__((__nonnull__(1,2), __leaf__)) pthread_condattr_getclock)(pthread_condattr_t const * __restrict __attr , - __clockid_t * __restrict __clock_id ) __attribute__((__nothrow__)) ; -#line 1219 -extern int ( __attribute__((__nonnull__(1), __leaf__)) pthread_condattr_setclock)(pthread_condattr_t *__attr , - __clockid_t __clock_id ) __attribute__((__nothrow__)) ; -#line 1230 -extern int ( __attribute__((__nonnull__(1), __leaf__)) pthread_spin_init)(pthread_spinlock_t *__lock , - int __pshared ) __attribute__((__nothrow__)) ; -#line 1234 -extern int ( __attribute__((__nonnull__(1), __leaf__)) pthread_spin_destroy)(pthread_spinlock_t *__lock ) __attribute__((__nothrow__)) ; -#line 1238 -extern int ( __attribute__((__nonnull__(1))) pthread_spin_lock)(pthread_spinlock_t *__lock ) __attribute__((__nothrow__)) ; -#line 1242 -extern int ( __attribute__((__nonnull__(1))) pthread_spin_trylock)(pthread_spinlock_t *__lock ) __attribute__((__nothrow__)) ; -#line 1246 -extern int ( __attribute__((__nonnull__(1))) pthread_spin_unlock)(pthread_spinlock_t *__lock ) __attribute__((__nothrow__)) ; -#line 1254 -extern int ( __attribute__((__nonnull__(1), __leaf__)) pthread_barrier_init)(pthread_barrier_t * __restrict __barrier , - pthread_barrierattr_t const * __restrict __attr , - unsigned int __count ) __attribute__((__nothrow__)) ; -#line 1260 -extern int ( __attribute__((__nonnull__(1), __leaf__)) pthread_barrier_destroy)(pthread_barrier_t *__barrier ) __attribute__((__nothrow__)) ; -#line 1264 -extern int ( __attribute__((__nonnull__(1))) pthread_barrier_wait)(pthread_barrier_t *__barrier ) __attribute__((__nothrow__)) ; -#line 1269 -extern int ( __attribute__((__nonnull__(1), __leaf__)) pthread_barrierattr_init)(pthread_barrierattr_t *__attr ) __attribute__((__nothrow__)) ; -#line 1273 -extern int ( __attribute__((__nonnull__(1), __leaf__)) pthread_barrierattr_destroy)(pthread_barrierattr_t *__attr ) __attribute__((__nothrow__)) ; -#line 1277 -extern int ( __attribute__((__nonnull__(1,2), __leaf__)) pthread_barrierattr_getpshared)(pthread_barrierattr_t const * __restrict __attr , - int * __restrict __pshared ) __attribute__((__nothrow__)) ; -#line 1283 -extern int ( __attribute__((__nonnull__(1), __leaf__)) pthread_barrierattr_setpshared)(pthread_barrierattr_t *__attr , - int __pshared ) __attribute__((__nothrow__)) ; -#line 1297 -extern int ( __attribute__((__nonnull__(1), __leaf__)) pthread_key_create)(pthread_key_t *__key , - void (*__destr_function)(void * ) ) __attribute__((__nothrow__)) ; -#line 1302 -extern int ( __attribute__((__leaf__)) pthread_key_delete)(pthread_key_t __key ) __attribute__((__nothrow__)) ; -#line 1305 -extern void *( __attribute__((__leaf__)) pthread_getspecific)(pthread_key_t __key ) __attribute__((__nothrow__)) ; -#line 1308 -extern int ( __attribute__((__leaf__)) pthread_setspecific)(pthread_key_t __key , - void const *__pointer ) __attribute__((__nothrow__, -__access__(__none__,2))) ; -#line 1315 -extern int ( __attribute__((__nonnull__(2), __leaf__)) pthread_getcpuclockid)(pthread_t __thread_id , - __clockid_t *__clock_id ) __attribute__((__nothrow__)) ; -#line 1332 -extern int ( __attribute__((__leaf__)) pthread_atfork)(void (*__prepare)(void) , void (*__parent)(void) , - void (*__child)(void) ) __attribute__((__nothrow__)) ; -#line 5 "lib/libc/stub/src/pthread.c" -int ( __attribute__((__nonnull__(1,2))) pthread_once)(pthread_once_t *once_control , - void (*init_routine)(void) ) __attribute__((__goblint_stub__)) ; -#line 5 "lib/libc/stub/src/pthread.c" -int ( __attribute__((__nonnull__(1,2))) pthread_once)(pthread_once_t *once_control , - void (*init_routine)(void) ) -{ - int top ; - - { -#line 8 - (*init_routine)(); -#line 9 - return (top); -} -} -#line 6 "lib/libc/stub/src/stdlib.c" -void qsort(void *ptr , size_t count , size_t size , int (*comp)(void const * , void const * ) ) __attribute__((__goblint_stub__)) ; -#line 7 -void qsort(void *ptr , size_t count , size_t size , int (*comp)(void const * , void const * ) ) __attribute__((__goblint_stub__)) ; -#line 7 "lib/libc/stub/src/stdlib.c" -void qsort(void *ptr , size_t count , size_t size , int (*comp)(void const * , void const * ) ) -{ - size_t i ; - size_t j ; - size_t i___0 ; - size_t j___0 ; - int r ; - size_t k ; - char *a ; - char *b ; - char c ; - int term10_5-file_stdlib ; - int term9_3-file_stdlib ; - int term21_9-file_stdlib ; - int term17_5-file_stdlib ; - int term16_3-file_stdlib ; - - { -#line 9 - i = (size_t )0; - { -#line 9 - term9_3-file_stdlib = 0; - { -#line 9 - while (1) { - while_continue: /* CIL Label */ ; -#line 9 - if (! (i < count)) { -#line 9 - goto while_break; - } -#line 9 - term9_3-file_stdlib ++; -#line 9 - term_exit- = term9_3-file_stdlib; -#line 10 - j = (size_t )0; - { -#line 10 - term10_5-file_stdlib = 0; - { -#line 10 - while (1) { - while_continue___0: /* CIL Label */ ; -#line 10 - if (! (j < count)) { -#line 10 - goto while_break___0; - } -#line 10 - term10_5-file_stdlib ++; -#line 10 - term_exit- = term10_5-file_stdlib; -#line 11 - (*comp)((void const *)(ptr + i * size), (void const *)(ptr + j * size)); -#line 10 - j ++; - } - while_break___0: /* CIL Label */ ; - } - } -#line 9 - i ++; - } - while_break: /* CIL Label */ ; - } - } -#line 16 - i___0 = (size_t )0; - { -#line 16 - term16_3-file_stdlib = 0; - { -#line 16 - while (1) { - while_continue___1: /* CIL Label */ ; -#line 16 - if (! (i___0 < count)) { -#line 16 - goto while_break___1; - } -#line 16 - term16_3-file_stdlib ++; -#line 16 - term_exit- = term16_3-file_stdlib; -#line 17 - j___0 = (size_t )0; - { -#line 17 - term17_5-file_stdlib = 0; - { -#line 17 - while (1) { - while_continue___2: /* CIL Label */ ; -#line 17 - if (! (j___0 < count)) { -#line 17 - goto while_break___2; - } -#line 17 - term17_5-file_stdlib ++; -#line 17 - term_exit- = term17_5-file_stdlib; -#line 19 - if (r) { -#line 21 - k = (size_t )0; - { -#line 21 - term21_9-file_stdlib = 0; - { -#line 21 - while (1) { - while_continue___3: /* CIL Label */ ; -#line 21 - if (! (k < size)) { -#line 21 - goto while_break___3; - } -#line 21 - term21_9-file_stdlib ++; -#line 21 - term_exit- = term21_9-file_stdlib; -#line 22 - a = (char *)((ptr + i___0 * size) + k); -#line 23 - b = (char *)((ptr + j___0 * size) + k); -#line 24 - c = *a; -#line 25 - *a = *b; -#line 26 - *b = c; -#line 21 - k ++; - } - while_break___3: /* CIL Label */ ; - } - } - } -#line 17 - j___0 ++; - } - while_break___2: /* CIL Label */ ; - } - } -#line 16 - i___0 ++; - } - while_break___1: /* CIL Label */ ; - } - } -#line 33 - return; -} -} -#line 37 -void *bsearch(void const *key , void const *ptr , size_t count , size_t size , - int (*comp)(void const * , void const * ) ) __attribute__((__goblint_stub__)) ; -#line 38 -void *bsearch(void const *key , void const *ptr , size_t count , size_t size , - int (*comp)(void const * , void const * ) ) __attribute__((__goblint_stub__)) ; -#line 38 "lib/libc/stub/src/stdlib.c" -void *bsearch(void const *key , void const *ptr , size_t count , size_t size , - int (*comp)(void const * , void const * ) ) -{ - size_t i ; - void const *a ; - int tmp ; - int term40_3-file_stdlib ; - - { -#line 40 - i = (size_t )0; - { -#line 40 - term40_3-file_stdlib = 0; - { -#line 40 - while (1) { - while_continue: /* CIL Label */ ; -#line 40 - if (! (i < count)) { -#line 40 - goto while_break; - } -#line 40 - term40_3-file_stdlib ++; -#line 40 - term_exit- = term40_3-file_stdlib; -#line 41 - a = ptr + i * size; -#line 42 - tmp = (*comp)(key, a); -#line 42 - if (tmp == 0) { -#line 43 - return ((void *)a); - } -#line 40 - i ++; - } - while_break: /* CIL Label */ ; - } - } -#line 47 - return ((void *)0); -} -} diff --git a/src/analyses/apron/apronAnalysis.apron.ml b/src/analyses/apron/apronAnalysis.apron.ml index 789701d37c..1ac88c66ee 100644 --- a/src/analyses/apron/apronAnalysis.apron.ml +++ b/src/analyses/apron/apronAnalysis.apron.ml @@ -1,7 +1,5 @@ (** Analysis using Apron for integer variables. *) open Analyses -open TerminationPreprocessing -open Cilfacade include RelationAnalysis let spec_module: (module MCPSpec) Lazy.t = From 3707652189843f261fb6d12a8cb2abf59e6d107a Mon Sep 17 00:00:00 2001 From: Johanna Schinabeck Date: Thu, 22 Jun 2023 16:47:16 +0200 Subject: [PATCH 149/327] indentation --- src/analyses/apron/apronAnalysis.apron.ml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/analyses/apron/apronAnalysis.apron.ml b/src/analyses/apron/apronAnalysis.apron.ml index 1ac88c66ee..1c31e975f2 100644 --- a/src/analyses/apron/apronAnalysis.apron.ml +++ b/src/analyses/apron/apronAnalysis.apron.ml @@ -1,5 +1,7 @@ (** Analysis using Apron for integer variables. *) + open Analyses + include RelationAnalysis let spec_module: (module MCPSpec) Lazy.t = From f7dab71875d61ae7c24f3221fb5643b7b372e345 Mon Sep 17 00:00:00 2001 From: Johanna Schinabeck Date: Thu, 22 Jun 2023 16:56:26 +0200 Subject: [PATCH 150/327] indentation --- src/analyses/apron/apronAnalysis.apron.ml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/analyses/apron/apronAnalysis.apron.ml b/src/analyses/apron/apronAnalysis.apron.ml index 1c31e975f2..62ae96f400 100644 --- a/src/analyses/apron/apronAnalysis.apron.ml +++ b/src/analyses/apron/apronAnalysis.apron.ml @@ -1,9 +1,10 @@ -(** Analysis using Apron for integer variables. *) +(** {{!RelationAnalysis} Relational integer value analysis} using {!Apron} domains ([apron]). *) open Analyses include RelationAnalysis + let spec_module: (module MCPSpec) Lazy.t = lazy ( let module Man = (val ApronDomain.get_manager ()) in From 5b0d72ff32fd06809751696b5713a5a5aab897dc Mon Sep 17 00:00:00 2001 From: Thomas Lagemann Date: Thu, 22 Jun 2023 18:16:03 +0200 Subject: [PATCH 151/327] Indentation with ocp-indent --- src/analyses/apron/apronAnalysis.apron.ml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/analyses/apron/apronAnalysis.apron.ml b/src/analyses/apron/apronAnalysis.apron.ml index 62ae96f400..bec0c4ec57 100644 --- a/src/analyses/apron/apronAnalysis.apron.ml +++ b/src/analyses/apron/apronAnalysis.apron.ml @@ -36,7 +36,7 @@ let after_config () = let module Spec = (val get_spec ()) in MCP.register_analysis (module Spec : MCPSpec); GobConfig.set_string "ana.path_sens[+]" (Spec.name ()) - + let _ = AfterConfig.register after_config From 8a320eb3a9f5f8cd26fe4414ec5d26f95b4e16f6 Mon Sep 17 00:00:00 2001 From: Isidor Zweckstetter Date: Thu, 22 Jun 2023 21:08:00 +0200 Subject: [PATCH 152/327] added sv-comp compatability --- src/framework/analysisState.ml | 2 +- src/framework/constraints.ml | 4 ++-- src/util/options.schema.json | 4 ++-- src/witness/svcompSpec.ml | 2 +- src/witness/witness.ml | 33 +++++++++++++++++++++++---------- 5 files changed, 29 insertions(+), 16 deletions(-) diff --git a/src/framework/analysisState.ml b/src/framework/analysisState.ml index ddecf1752a..3f577d79f4 100644 --- a/src/framework/analysisState.ml +++ b/src/framework/analysisState.ml @@ -8,7 +8,7 @@ let should_warn = ref false let svcomp_may_overflow = ref false (** TODO:**) -let svcomp_must_terminate = ref true +let svcomp_may_not_terminate = ref false (** A hack to see if we are currently doing global inits *) let global_initialization = ref false diff --git a/src/framework/constraints.ml b/src/framework/constraints.ml index 865b0405ee..f6d920d74f 100644 --- a/src/framework/constraints.ml +++ b/src/framework/constraints.ml @@ -1734,7 +1734,7 @@ struct let rec iter_call (path_visited_calls: LS.t) (call:T (CilType.Fundec) (S.C).t) = let ((fundec_e:fundec), (context_e: C.t)) = call in (*unpack tuple for later use*) if LS.mem call path_visited_calls then ( - AnalysisState.svcomp_must_terminate := false; + AnalysisState.svcomp_may_not_terminate := true; (*Cycle found*) let msgs = [ @@ -1770,7 +1770,7 @@ struct let ret = ctx.ask Queries.MustTermProg in (* check result of loop analysis *) if not ret then - (AnalysisState.svcomp_must_terminate := false; + (AnalysisState.svcomp_may_not_terminate := true; let msgs = [ (Pretty.dprintf "The program might not terminate! (Loop analysis)\n", Some (M.Location.CilLocation locUnknown)); diff --git a/src/util/options.schema.json b/src/util/options.schema.json index 3efaef2e83..8ec398b3ad 100644 --- a/src/util/options.schema.json +++ b/src/util/options.schema.json @@ -566,7 +566,7 @@ "title": "ana.sv-comp.enabled", "description": "SV-COMP mode", "type": "boolean", - "default": false + "default": true }, "functions": { "title": "ana.sv-comp.functions", @@ -581,7 +581,7 @@ "title": "ana.specification", "description": "SV-COMP specification (path or string)", "type": "string", - "default": "" + "default": "/home/isidor/goblint/goblint-analyzer/tests/sv-comp/no-termination.prp" }, "wp": { "title": "ana.wp", diff --git a/src/witness/svcompSpec.ml b/src/witness/svcompSpec.ml index eec667c5a6..f8791d065e 100644 --- a/src/witness/svcompSpec.ml +++ b/src/witness/svcompSpec.ml @@ -17,7 +17,7 @@ let of_string s = NoDataRace else if global_not = "overflow" then NoOverflow - else if global_not = "termination" then (*TODO: does this even work?*) + else if global_not = "termination" then NoTermination else let call_regex = Str.regexp "call(\\(.*\\)())" in diff --git a/src/witness/witness.ml b/src/witness/witness.ml index 04bcb1867b..f0e2f0f799 100644 --- a/src/witness/witness.ml +++ b/src/witness/witness.ml @@ -449,16 +449,29 @@ struct let next _ = [] end in - let module TaskResult = - struct - module Arg = TrivialArg - let result = Result.Unknown - let invariant _ = Invariant.none - let is_violation _ = false - let is_sink _ = false - end - in - (module TaskResult:WitnessTaskResult) + if not !AnalysisState.svcomp_may_not_terminate then + let module TaskResult = + struct + module Arg = Arg + let result = Result.True + let invariant = find_invariant + let is_violation _ = false + let is_sink _ = false + end + in + (module TaskResult:WitnessTaskResult) + else ( + let module TaskResult = + struct + module Arg = TrivialArg + let result = Result.Unknown + let invariant _ = Invariant.none + let is_violation _ = false + let is_sink _ = false + end + in + (module TaskResult:WitnessTaskResult) + ) | NoOverflow -> let module TrivialArg = struct From 5d3f25cba243f67a14e8446fc6211faec2500116 Mon Sep 17 00:00:00 2001 From: Alexander Schlenga Date: Thu, 22 Jun 2023 22:01:03 +0200 Subject: [PATCH 153/327] Fix indentation --- src/framework/constraints.ml | 78 ++++++++++++++++++------------------ src/witness/witness.ml | 44 ++++++++++---------- 2 files changed, 61 insertions(+), 61 deletions(-) diff --git a/src/framework/constraints.ml b/src/framework/constraints.ml index ab6931bf70..ce3ecadc1e 100644 --- a/src/framework/constraints.ml +++ b/src/framework/constraints.ml @@ -1698,19 +1698,19 @@ end (** Add cycle detection in the function call graph to a analysis *) module RecursionTermLifter (S: Spec) : Spec with module D = S.D - and module C = S.C + and module C = S.C = (*global invariants: - - V -> G - - fundec -> Map (S.C) (Set (fundec * S.C)) + - V -> G + - fundec -> Map (S.C) (Set (fundec * S.C)) Therefore: g -> {c' -> {(f, c)}} in case f, c --> g, c' *) struct include S - module V = - struct + module V = + struct include GVarF(S.V) end @@ -1718,17 +1718,17 @@ struct let name () = "termination" - let conv (ctx: (_, G.t, _, V.t) ctx): (_, S.G.t, _, S.V.t) ctx = + let conv (ctx: (_, G.t, _, V.t) ctx): (_, S.G.t, _, S.V.t) ctx = { ctx with global = (fun v -> G.s (ctx.global (V.spec v))); sideg = (fun v g -> ctx.sideg (V.spec v) (G.create_s g)); } - let cycleDetection ctx v v' = - let module LH = Hashtbl.Make (T (CilType.Fundec) (S.C)) in - let module LS = Set.Make (T (CilType.Fundec) (S.C)) in + let cycleDetection ctx v v' = + let module LH = Hashtbl.Make (T (CilType.Fundec) (S.C)) in + let module LS = Set.Make (T (CilType.Fundec) (S.C)) in (* find all cycles/SCCs *) - let global_visited_calls = LH.create 100 in + let global_visited_calls = LH.create 100 in (* DFS *) let rec iter_call (path_visited_calls: LS.t) (call:T (CilType.Fundec) (S.C).t) = @@ -1736,7 +1736,7 @@ struct if LS.mem call path_visited_calls then ( AnalysisState.svcomp_may_not_terminate := true; (*Cycle found*) - let msgs = + let msgs = [ (Pretty.dprintf "The program might not terminate! (Fundec %a is contained in a call graph cycle)\n" CilType.Fundec.pretty fundec_e, Some (M.Location.CilLocation fundec_e.svar.vdecl)); ] in @@ -1744,25 +1744,25 @@ struct else if not (LH.mem global_visited_calls call) then begin try LH.replace global_visited_calls call (); - let new_path_visited_calls = LS.add call path_visited_calls in - let fundec_e_typeV: V.t = V.relift (`Right fundec_e) in - let gmap_opt = G.base2 (ctx.global (fundec_e_typeV)) in + let new_path_visited_calls = LS.add call path_visited_calls in + let fundec_e_typeV: V.t = V.relift (`Right fundec_e) in + let gmap_opt = G.base2 (ctx.global (fundec_e_typeV)) in let gmap = Option.get (gmap_opt) in (*might be empty*) - let callers: G.CSet.t = G.CMap.find (context_e) gmap in + let callers: G.CSet.t = G.CMap.find (context_e) gmap in G.CSet.iter (fun to_call -> iter_call new_path_visited_calls to_call ) callers; with Invalid_argument _ -> () (* path ended: no cycle*) - end + end in - try - let gmap_opt = G.base2 (ctx.global (v)) in - let gmap = Option.get (gmap_opt) in - G.CMap.iter(fun key value -> - let call = (v', key) in - iter_call LS.empty call - ) gmap (* try all fundec + context pairs that are in the map *) - with Invalid_argument _ -> () (* path ended: no cycle*) + try + let gmap_opt = G.base2 (ctx.global (v)) in + let gmap = Option.get (gmap_opt) in + G.CMap.iter(fun key value -> + let call = (v', key) in + iter_call LS.empty call + ) gmap (* try all fundec + context pairs that are in the map *) + with Invalid_argument _ -> () (* path ended: no cycle*) let query ctx (type a) (q: a Queries.t): a Queries.result = match q with @@ -1770,18 +1770,18 @@ struct (* check result of loop analysis *) if not (ctx.ask Queries.MustTermProg) then (AnalysisState.svcomp_may_not_terminate := true; - let msgs = - [ - (Pretty.dprintf "The program might not terminate! (Loop analysis)\n", Some (M.Location.CilLocation locUnknown)); - ] in - M.msg_group Warning ~category:NonTerminating "Possibly non terminating loops" msgs - ); + let msgs = + [ + (Pretty.dprintf "The program might not terminate! (Loop analysis)\n", Some (M.Location.CilLocation locUnknown)); + ] in + M.msg_group Warning ~category:NonTerminating "Possibly non terminating loops" msgs + ); let v: V.t = Obj.obj v in begin match v with | `Left v' -> - S.query (conv ctx) (WarnGlobal (Obj.repr v')) + S.query (conv ctx) (WarnGlobal (Obj.repr v')) | `Right v' -> cycleDetection ctx v v' (* Note: to make it more efficient, one could only execute the cycle detection in case the loop analysis returns true, because otherwise the program will probably not terminate anyway*) - end + end | InvariantGlobal v -> let v: V.t = Obj.obj v in begin match v with @@ -1795,30 +1795,30 @@ struct let branch ctx = S.branch (conv ctx) let assign ctx = S.assign (conv ctx) let vdecl ctx = S.vdecl (conv ctx) - + (* c = context t = set of tuples (fundec * context) *) let side_context sideg f c t = if !AnalysisState.postsolving then sideg (V.contexts f) (G.create_contexts (G.CMap.singleton (c) (t))) - - let enter ctx = S.enter (conv ctx) + + let enter ctx = S.enter (conv ctx) let paths_as_set ctx = S.paths_as_set (conv ctx) let body ctx = S.body (conv ctx) let return ctx = S.return (conv ctx) - let combine_env ctx r fe f args fc es f_ask = + let combine_env ctx r fe f args fc es f_ask = if !AnalysisState.postsolving then let c_r: S.C.t = ctx.context () in (*Caller context*) let nodeF = ctx.node in let fd_r : fundec = Node.find_fundec nodeF in (*Caller fundec*) let c_e: S.C.t = Option.get fc in (*Callee context*) let fd_e : fundec = f in (*Callee fundec*) - let tup: (fundec * S.C.t) = (fd_r, c_r) in - let t = G.CSet.singleton (tup) in + let tup: (fundec * S.C.t) = (fd_r, c_r) in + let t = G.CSet.singleton (tup) in side_context ctx.sideg fd_e (c_e) t; S.combine_env (conv ctx) r fe f args fc es f_ask - else + else S.combine_env (conv ctx) r fe f args fc es f_ask let combine_assign ctx = S.combine_assign (conv ctx) let special ctx = S.special (conv ctx) diff --git a/src/witness/witness.ml b/src/witness/witness.ml index f0e2f0f799..b62b2b54cd 100644 --- a/src/witness/witness.ml +++ b/src/witness/witness.ml @@ -23,7 +23,7 @@ let write_file filename (module Task:Task) (module TaskResult:WitnessTaskResult) let module IsInteresting = struct (* type node = N.t - type edge = TaskResult.Arg.Edge.t *) + type edge = TaskResult.Arg.Edge.t *) let minwitness = get_bool "witness.minimize" let is_interesting_real from_node edge to_node = (* TODO: don't duplicate this logic with write_node, write_edge *) @@ -59,11 +59,11 @@ let write_file filename (module Task:Task) (module TaskResult:WitnessTaskResult) let module GML = XmlGraphMlWriter in let module GML = (val match get_string "witness.id" with - | "node" -> - (module ArgNodeGraphMlWriter (N) (GML) : GraphMlWriter with type node = N.t) - | "enumerate" -> - (module EnumerateNodeGraphMlWriter (N) (GML)) - | _ -> failwith "witness.id: illegal value" + | "node" -> + (module ArgNodeGraphMlWriter (N) (GML) : GraphMlWriter with type node = N.t) + | "enumerate" -> + (module EnumerateNodeGraphMlWriter (N) (GML)) + | _ -> failwith "witness.id: illegal value" ) in let module GML = DeDupGraphMlWriter (N) (GML) in @@ -107,16 +107,16 @@ let write_file filename (module Task:Task) (module TaskResult:WitnessTaskResult) GML.write_key g "edge" "goblintLine" "string" None; (* TODO: remove *) (* GML.write_key g "edge" "enterFunction2" "string" None; - GML.write_key g "edge" "returnFromFunction2" "string" None; *) + GML.write_key g "edge" "returnFromFunction2" "string" None; *) GML.start_graph g; GML.write_metadata g "witness-type" ( - match TaskResult.result with - | Result.True -> "correctness_witness" - | Result.False _ -> "violation_witness" - | Result.Unknown -> "unknown_witness" - ); + match TaskResult.result with + | Result.True -> "correctness_witness" + | Result.False _ -> "violation_witness" + | Result.Unknown -> "unknown_witness" + ); GML.write_metadata g "sourcecodelang" "C"; GML.write_metadata g "producer" (Printf.sprintf "Goblint (%s)" Version.goblint); GML.write_metadata g "specification" (Svcomp.Specification.to_string Task.specification); @@ -141,7 +141,7 @@ let write_file filename (module Task:Task) (module TaskResult:WitnessTaskResult) | Statement _, `Lifted i -> let i = InvariantCil.exp_replace_original_name i in [("invariant", CilType.Exp.show i); - ("invariant.scope", (Node.find_fundec cfgnode).svar.vname)] + ("invariant.scope", (Node.find_fundec cfgnode).svar.vname)] | _ -> (* ignore entry and return invariants, variables of wrong scopes *) (* TODO: don't? fix scopes? *) @@ -150,10 +150,10 @@ let write_file filename (module Task:Task) (module TaskResult:WitnessTaskResult) [] end; (* begin match cfgnode with - | Statement s -> + | Statement s -> [("sourcecode", GobPretty.sprint Basetype.CilStmt.pretty s)] (* TODO: sourcecode not official? especially on node? *) - | _ -> [] - end; *) + | _ -> [] + end; *) (* violation actually only allowed in violation witness *) (* maybe should appear on from_node of entry edge instead *) begin if TaskResult.is_violation node then @@ -170,7 +170,7 @@ let write_file filename (module Task:Task) (module TaskResult:WitnessTaskResult) | Statement stmt -> Printf.sprintf "s%d" stmt.sid | Function f -> Printf.sprintf "ret%d%s" f.vid f.vname | FunctionEntry f -> Printf.sprintf "fun%d%s" f.vid f.vname - )] *) + )] *) (* [("goblintNode", N.to_string node)] *) ]) in @@ -213,9 +213,9 @@ let write_file filename (module Task:Task) (module TaskResult:WitnessTaskResult) (* enter and return on other side of nodes, more correct loc (startline) but had some scope problem? *) (* | MyARG.CFGEdge (Entry f) -> - [("enterFunction2", f.svar.vname)] - | MyARG.CFGEdge (Ret (_, f)) -> - [("returnFromFunction2", f.svar.vname)] *) + [("enterFunction2", f.svar.vname)] + | MyARG.CFGEdge (Ret (_, f)) -> + [("returnFromFunction2", f.svar.vname)] *) | _ -> [] end; [("goblintEdge", Arg.Edge.to_string edge)] @@ -394,12 +394,12 @@ struct struct let path = observer_path end - ) + ) in MCP.register_analysis (module Spec); (* TODO: don't modify JSON but have ref vars for these instead *) (* GobConfig.set_list "ana.activated" (Json.Build.string (Spec.name ()) :: GobConfig.get_list "ana.activated"); - GobConfig.set_list "ana.path_sens" (Json.Build.string (Spec.name ()) :: GobConfig.get_list "ana.path_sens"); *) + GobConfig.set_list "ana.path_sens" (Json.Build.string (Spec.name ()) :: GobConfig.get_list "ana.path_sens"); *) (* TODO: don't append to end; currently done to get observer order to be nice *) GobConfig.set_list "ana.activated" (GobConfig.get_list "ana.activated" @ [`String (Spec.name ())]); GobConfig.set_list "ana.path_sens" (GobConfig.get_list "ana.path_sens" @ [`String (Spec.name ())]); From 86031779609876e6b713ac2d5a4640831b3dcc15 Mon Sep 17 00:00:00 2001 From: Alexander Schlenga Date: Wed, 28 Jun 2023 11:27:10 +0200 Subject: [PATCH 154/327] Fix indentation --- src/framework/control.ml | 118 +++++++++++++++++++-------------------- src/util/cilfacade.ml | 14 ++--- 2 files changed, 66 insertions(+), 66 deletions(-) diff --git a/src/framework/control.ml b/src/framework/control.ml index 6a25283687..9a717e2f67 100644 --- a/src/framework/control.ml +++ b/src/framework/control.ml @@ -20,25 +20,25 @@ let spec_module: (module Spec) Lazy.t = lazy ( (* apply functor F on module X if opt is true *) let lift opt (module F : S2S) (module X : Spec) = (module (val if opt then (module F (X)) else (module X) : Spec) : Spec) in let module S1 = (val - (module MCP.MCP2 : Spec) - |> lift true (module WidenContextLifterSide) (* option checked in functor *) - (* hashcons before witness to reduce duplicates, because witness re-uses contexts in domain and requires tag for PathSensitive3 *) - |> lift (get_bool "ana.opt.hashcons" || arg_enabled) (module HashconsContextLifter) - |> lift arg_enabled (module HashconsLifter) - |> lift arg_enabled (module WitnessConstraints.PathSensitive3) - |> lift (not arg_enabled) (module PathSensitive2) - |> lift (get_bool "ana.dead-code.branches") (module DeadBranchLifter) - |> lift true (module DeadCodeLifter) - |> lift (get_bool "dbg.slice.on") (module LevelSliceLifter) - |> lift (get_int "dbg.limit.widen" > 0) (module LimitLifter) - |> lift (get_bool "ana.opt.equal" && not (get_bool "ana.opt.hashcons")) (module OptEqual) - |> lift (get_bool "ana.opt.hashcons") (module HashconsLifter) - (* Widening tokens must be outside of hashcons, because widening token domain ignores token sets for identity, so hashcons doesn't allow adding tokens. - Also must be outside of deadcode, because deadcode splits (like mutex lock event) don't pass on tokens. *) - |> lift (get_bool "ana.widen.tokens") (module WideningTokens.Lifter) - |> lift true (module LongjmpLifter) - |> lift arg_termination (module RecursionTermLifter) (* Always activate the recursion termination analysis, when the loop termination analysis is activated*) - ) in + (module MCP.MCP2 : Spec) + |> lift true (module WidenContextLifterSide) (* option checked in functor *) + (* hashcons before witness to reduce duplicates, because witness re-uses contexts in domain and requires tag for PathSensitive3 *) + |> lift (get_bool "ana.opt.hashcons" || arg_enabled) (module HashconsContextLifter) + |> lift arg_enabled (module HashconsLifter) + |> lift arg_enabled (module WitnessConstraints.PathSensitive3) + |> lift (not arg_enabled) (module PathSensitive2) + |> lift (get_bool "ana.dead-code.branches") (module DeadBranchLifter) + |> lift true (module DeadCodeLifter) + |> lift (get_bool "dbg.slice.on") (module LevelSliceLifter) + |> lift (get_int "dbg.limit.widen" > 0) (module LimitLifter) + |> lift (get_bool "ana.opt.equal" && not (get_bool "ana.opt.hashcons")) (module OptEqual) + |> lift (get_bool "ana.opt.hashcons") (module HashconsLifter) + (* Widening tokens must be outside of hashcons, because widening token domain ignores token sets for identity, so hashcons doesn't allow adding tokens. + Also must be outside of deadcode, because deadcode splits (like mutex lock event) don't pass on tokens. *) + |> lift (get_bool "ana.widen.tokens") (module WideningTokens.Lifter) + |> lift true (module LongjmpLifter) + |> lift arg_termination (module RecursionTermLifter) (* Always activate the recursion termination analysis, when the loop termination analysis is activated*) + ) in GobConfig.building_spec := false; ControlSpecC.control_spec_c := (module S1.C); (module S1) @@ -303,10 +303,10 @@ struct | MyCFG.Assign (lval,exp) -> if M.tracing then M.trace "global_inits" "Assign %a = %a\n" d_lval lval d_exp exp; (match lval, exp with - | (Var v,o), (AddrOf (Var f,NoOffset)) - when v.vstorage <> Static && isFunctionType f.vtype -> - (try funs := Cilfacade.find_varinfo_fundec f :: !funs with Not_found -> ()) - | _ -> () + | (Var v,o), (AddrOf (Var f,NoOffset)) + when v.vstorage <> Static && isFunctionType f.vtype -> + (try funs := Cilfacade.find_varinfo_fundec f :: !funs with Not_found -> ()) + | _ -> () ); let res = Spec.assign {ctx with local = st} lval exp in (* Needed for privatizations (e.g. None) that do not side immediately *) @@ -530,9 +530,9 @@ struct GobSys.mkdir_or_exists save_run; GobConfig.write_file config; let module Meta = struct - type t = { command : string; version: string; timestamp : float; localtime : string } [@@deriving to_yojson] - let json = to_yojson { command = GobSys.command_line; version = Version.goblint; timestamp = Unix.time (); localtime = GobUnix.localtime () } - end + type t = { command : string; version: string; timestamp : float; localtime : string } [@@deriving to_yojson] + let json = to_yojson { command = GobSys.command_line; version = Version.goblint; timestamp = Unix.time (); localtime = GobUnix.localtime () } + end in (* Yojson.Safe.to_file meta Meta.json; *) Yojson.Safe.pretty_to_channel (Stdlib.open_out (Fpath.to_string meta)) Meta.json; (* the above is compact, this is pretty-printed *) @@ -584,10 +584,10 @@ struct in let print_and_calculate_uncalled = function | GFun (fn, loc) when is_bad_uncalled fn.svar loc-> - let cnt = Cilfacade.countLoc fn in - uncalled_dead := !uncalled_dead + cnt; - if get_bool "ana.dead-code.functions" then - M.warn ~loc:(CilLocation loc) ~category:Deadcode "Function '%a' is uncalled: %d LLoC" CilType.Fundec.pretty fn cnt (* CilLocation is fine because always printed from scratch *) + let cnt = Cilfacade.countLoc fn in + uncalled_dead := !uncalled_dead + cnt; + if get_bool "ana.dead-code.functions" then + M.warn ~loc:(CilLocation loc) ~category:Deadcode "Function '%a' is uncalled: %d LLoC" CilType.Fundec.pretty fn cnt (* CilLocation is fine because always printed from scratch *) | _ -> () in List.iter print_and_calculate_uncalled file.globals; @@ -619,35 +619,35 @@ struct NodeH.modify_opt node join by_node; ); by_loc, by_node - in - - let ask ?(node = MyCFG.dummy_node) loc = - let f (type a) (q : a Queries.t) : a = - match Hashtbl.find_option joined_by_loc loc with - | None -> Queries.Result.bot q - | Some local -> Query.ask_local_node gh node local q - in - ({ f } : Queries.ask) - in - - (* A node is dead when its abstract value is bottom in all contexts; - it holds that: bottom in all contexts iff. bottom in the join of all contexts. - Therefore, we just answer whether the (stored) join is bottom. *) - let must_be_dead node = - NodeH.find_option joined_by_node node - (* nodes that didn't make it into the result are definitely dead (hence for_all) *) - |> GobOption.for_all Spec.D.is_bot - in - - let must_be_uncalled fd = not @@ BatSet.Int.mem fd.svar.vid calledFuns in - - let skipped_statements from_node edge to_node = - CfgTools.CfgEdgeH.find_default skippedByEdge (from_node, edge, to_node) [] - in - - Transform.run_transformations file active_transformations - { ask ; must_be_dead ; must_be_uncalled ; - cfg_forward = Cfg.next ; cfg_backward = Cfg.prev ; skipped_statements }; + in + + let ask ?(node = MyCFG.dummy_node) loc = + let f (type a) (q : a Queries.t) : a = + match Hashtbl.find_option joined_by_loc loc with + | None -> Queries.Result.bot q + | Some local -> Query.ask_local_node gh node local q + in + ({ f } : Queries.ask) + in + + (* A node is dead when its abstract value is bottom in all contexts; + it holds that: bottom in all contexts iff. bottom in the join of all contexts. + Therefore, we just answer whether the (stored) join is bottom. *) + let must_be_dead node = + NodeH.find_option joined_by_node node + (* nodes that didn't make it into the result are definitely dead (hence for_all) *) + |> GobOption.for_all Spec.D.is_bot + in + + let must_be_uncalled fd = not @@ BatSet.Int.mem fd.svar.vid calledFuns in + + let skipped_statements from_node edge to_node = + CfgTools.CfgEdgeH.find_default skippedByEdge (from_node, edge, to_node) [] + in + + Transform.run_transformations file active_transformations + { ask ; must_be_dead ; must_be_uncalled ; + cfg_forward = Cfg.next ; cfg_backward = Cfg.prev ; skipped_statements }; ); lh, gh diff --git a/src/util/cilfacade.ml b/src/util/cilfacade.ml index 2043a94ed0..2a81444e41 100644 --- a/src/util/cilfacade.ml +++ b/src/util/cilfacade.ml @@ -89,14 +89,14 @@ let visitors_cil = ref [] (* does exactly the same as register_preprocess but it is executed earlier, before the CFG is created*) let register_preprocess_cil name visitor_fun = visitors_cil := !visitors_cil @ [name, visitor_fun] - + let do_preprocess_cil ast = - let f fd (name, visitor_fun) = - (* this has to be done here, since the settings aren't available when register_preprocess is called *) - if List.mem name (get_string_list "ana.activated") then - ignore @@ visitCilFunction (visitor_fun fd) fd - in - iterGlobals ast (function GFun (fd,_) -> List.iter (f fd) !visitors_cil | _ -> ()) + let f fd (name, visitor_fun) = + (* this has to be done here, since the settings aren't available when register_preprocess is called *) + if List.mem name (get_string_list "ana.activated") then + ignore @@ visitCilFunction (visitor_fun fd) fd + in + iterGlobals ast (function GFun (fd,_) -> List.iter (f fd) !visitors_cil | _ -> ()) (** @raise GoblintCil.FrontC.ParseError @raise GoblintCil.Errormsg.Error *) From d987f1a151e481a7dcd9fd50b1dc0b5a53b51f19 Mon Sep 17 00:00:00 2001 From: Alexander Schlenga Date: Wed, 28 Jun 2023 11:34:44 +0200 Subject: [PATCH 155/327] Restore signs analysis tutorial --- src/analyses/tutorials/signs.ml | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/analyses/tutorials/signs.ml b/src/analyses/tutorials/signs.ml index 9ae48f8626..31168df86a 100644 --- a/src/analyses/tutorials/signs.ml +++ b/src/analyses/tutorials/signs.ml @@ -23,12 +23,12 @@ struct (* TODO: An attempt to abstract integers, but it's just a little wrong... *) let of_int i = - if Z.compare i Z.zero < 0 then Neg - else if Z.compare i Z.zero > 0 then Pos + if Z.compare i Z.zero < 0 then Zero + else if Z.compare i Z.zero > 0 then Zero else Zero let lt x y = match x, y with - | Neg, Pos | Neg, Zero | Pos, Zero -> true (* TODO: Maybe something missing? *) + | Neg, Pos | Neg, Zero -> true (* TODO: Maybe something missing? *) | _ -> false end @@ -59,7 +59,7 @@ struct (* This should now evaluate expressions. *) let eval (d: D.t) (exp: exp): SL.t = match exp with - | Const (CInt (i, _, _)) -> SL.of_int i (* TODO: Fix me! *) + | Const (CInt (i, _, _)) -> SL.top () (* TODO: Fix me! *) | Lval (Var x, NoOffset) -> D.find x d | _ -> SL.top () From b1930abaf634e8a9a6c4f34186b41a5bdf5a9206 Mon Sep 17 00:00:00 2001 From: serenita <33780257+serenita@users.noreply.github.com> Date: Wed, 28 Jun 2023 11:39:48 +0200 Subject: [PATCH 156/327] Simplify src/framework/analyses.ml Co-authored-by: Julian Erhard --- src/framework/analyses.ml | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/src/framework/analyses.ml b/src/framework/analyses.ml index 20727aaf23..cae9d6f782 100644 --- a/src/framework/analyses.ml +++ b/src/framework/analyses.ml @@ -154,11 +154,7 @@ module GVarGSet (G: Lattice.S) (C: Printable.S) (Base: Printable.S) = struct module CSet = struct - include SetDomain.Make ( - struct - include (Base) (* Set of Tuples*) - end - ) + include SetDomain.Make (Base) (* Set of Tuples*) let name () = "contexts" let printXml f a = BatPrintf.fprintf f "\n"; From a3fd8d0977a9217838037972d4bb6337422a0961 Mon Sep 17 00:00:00 2001 From: Alexander Schlenga Date: Wed, 28 Jun 2023 11:55:10 +0200 Subject: [PATCH 157/327] Fix indentation --- src/framework/analyses.ml | 40 +++++++++++++++++++-------------------- 1 file changed, 20 insertions(+), 20 deletions(-) diff --git a/src/framework/analyses.ml b/src/framework/analyses.ml index cae9d6f782..1c3d596cc2 100644 --- a/src/framework/analyses.ml +++ b/src/framework/analyses.ml @@ -119,19 +119,19 @@ struct end (* Tuple of fundec and S.C*) -module T (Base1: Printable.S) (Base2: Printable.S) = -struct +module T (Base1: Printable.S) (Base2: Printable.S) = +struct include Printable.Std type t = (Base1.t * Base2.t) let fundec (a,_) = a let context (_,b) = b let equal (a1, b1) (a2, b2) = if (Base1.equal a1 a2 && Base2.equal b1 b2) then true else false - let show (a,b) = (Base1.show a) ^ (Base2.show b) + let show (a,b) = (Base1.show a) ^ (Base2.show b) let name () = "Tuple" let to_yojson x = `String (show x) let relift (a,b) = (a,b) (*Todo: is this correct?*) - let printXml f (a,b) = + let printXml f (a,b) = BatPrintf.fprintf f "\n Tuple:\n\n caller_fundec\n%a\n\n @@ -139,13 +139,13 @@ struct \n" Base1.printXml a Base2.printXml b let compare (a1,b1) (a2,b2) = (*Todo: is this ok?*) - if equal (a1, b1) (a2, b2) then 0 + if equal (a1, b1) (a2, b2) then 0 else( let val_a a = if (a > 0) then 1 else -1 in let val_b b = if (b > 0) then 3 else -3 in val_a (Base1.compare a1 a2) + val_b (Base2.compare b1 b2) - ) - + ) + let pretty () x = text (show x) let hash (a,b) = Hashtbl.hash (Base1.hash a * Base2.hash b) (*Todo: is this ok?*) end @@ -156,24 +156,24 @@ struct struct include SetDomain.Make (Base) (* Set of Tuples*) let name () = "contexts" - let printXml f a = + let printXml f a = BatPrintf.fprintf f "\n"; iter (Base.printXml f) a; BatPrintf.fprintf f "\n\n" end (* Make the given module Goupable*) - module C_Printable (C: Printable.S) = - struct - include C - include Printable.Std (* To make it Groupable *) - let printXml f c = BatPrintf.fprintf f - "\n + module C_Printable (C: Printable.S) = + struct + include C + include Printable.Std (* To make it Groupable *) + let printXml f c = BatPrintf.fprintf f + "\n callee_context\n%a\n\n " printXml c - end + end - module CMap = + module CMap = struct include MapDomain.MapBot (C_Printable (C)) (CSet) let printXml f c = BatPrintf.fprintf f " @@ -188,14 +188,14 @@ struct | `Bot -> G.bot () | `Lifted1 x -> x | _ -> failwith "GVarGSet.spec" - let contexts = function + let contexts = function | `Bot -> CSet.bot () | `Lifted2 x -> x | _ -> failwith "GVarGSet.contexts" - let create_spec spec = `Lifted1 spec - let create_contexts contexts = `Lifted2 contexts + let create_spec spec = `Lifted1 spec + let create_contexts contexts = `Lifted2 contexts - let printXml f = function + let printXml f = function | `Lifted1 x -> G.printXml f x | `Lifted2 x -> BatPrintf.fprintf f "%a" CMap.printXml x | x -> BatPrintf.fprintf f "%a" printXml x From ba596d77282c549e29678885ba718ce592fc42eb Mon Sep 17 00:00:00 2001 From: Alexander Schlenga Date: Wed, 28 Jun 2023 16:31:35 +0200 Subject: [PATCH 158/327] Remove build_testing.yml --- .github/workflows/build_testing.yml | 35 ----------------------------- 1 file changed, 35 deletions(-) delete mode 100644 .github/workflows/build_testing.yml diff --git a/.github/workflows/build_testing.yml b/.github/workflows/build_testing.yml deleted file mode 100644 index 1b464043c7..0000000000 --- a/.github/workflows/build_testing.yml +++ /dev/null @@ -1,35 +0,0 @@ -name: build_testing - -on: - - push - - pull_request - -jobs: - tests: - strategy: - fail-fast: false - matrix: - os: - - macos-latest - - ubuntu-latest - ocaml-compiler: - - 4.12.0 - - runs-on: ${{ matrix.os }} - - steps: - - name: Checkout code - uses: actions/checkout@v2 - - - name: Setup OCaml ${{ matrix.ocaml-compiler }} - env: - OPAMLOCKED: locked - uses: ocaml/setup-ocaml@v2 - with: - ocaml-compiler: ${{ matrix.ocaml-compiler }} - - - name: Install opam dependencies - run: opam install . --deps-only --locked - - - name: Build - run: ./make.sh nat From fbef2088d75d627084e442c3648386c7d23ce419 Mon Sep 17 00:00:00 2001 From: Thomas Lagemann Date: Thu, 29 Jun 2023 12:24:33 +0200 Subject: [PATCH 159/327] No skipping --- .../regression/80-termination/09-complex-for-loop-terminating.c | 2 +- tests/regression/80-termination/10-complex-loop-terminating.c | 2 +- .../80-termination/15-complex-loop-combination-terminating.c | 2 +- tests/regression/81-recursion/02-simple-nonterminating.c | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/tests/regression/80-termination/09-complex-for-loop-terminating.c b/tests/regression/80-termination/09-complex-for-loop-terminating.c index 8951924c06..7fcd5c5eba 100644 --- a/tests/regression/80-termination/09-complex-for-loop-terminating.c +++ b/tests/regression/80-termination/09-complex-for-loop-terminating.c @@ -1,4 +1,4 @@ -// SKIP LOCAL_TERM PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra +// LOCAL_TERM PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra #include int main() diff --git a/tests/regression/80-termination/10-complex-loop-terminating.c b/tests/regression/80-termination/10-complex-loop-terminating.c index dbce2a6b5b..def1786937 100644 --- a/tests/regression/80-termination/10-complex-loop-terminating.c +++ b/tests/regression/80-termination/10-complex-loop-terminating.c @@ -1,4 +1,4 @@ -// SKIP LOCAL_TERM PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra +// LOCAL_TERM PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra #include int main() diff --git a/tests/regression/80-termination/15-complex-loop-combination-terminating.c b/tests/regression/80-termination/15-complex-loop-combination-terminating.c index 7daa9b98fe..9ab04745e8 100644 --- a/tests/regression/80-termination/15-complex-loop-combination-terminating.c +++ b/tests/regression/80-termination/15-complex-loop-combination-terminating.c @@ -1,4 +1,4 @@ -// SKIP LOCAL_TERM PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval +// LOCAL_TERM PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval #include int main() diff --git a/tests/regression/81-recursion/02-simple-nonterminating.c b/tests/regression/81-recursion/02-simple-nonterminating.c index c7902e2e7f..37c4bbd801 100644 --- a/tests/regression/81-recursion/02-simple-nonterminating.c +++ b/tests/regression/81-recursion/02-simple-nonterminating.c @@ -1,4 +1,4 @@ -// SKIP NON_LOCAL_TERM PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra +// NON_LOCAL_TERM PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra #include void recursiveFunction(int n) { From 13f369acdb55b89378c9768edb07723091c724b7 Mon Sep 17 00:00:00 2001 From: Thomas Lagemann Date: Thu, 29 Jun 2023 12:31:36 +0200 Subject: [PATCH 160/327] New non terminating for loop --- .../34-nested-for-loop-nonterminating.c | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) create mode 100644 tests/regression/80-termination/34-nested-for-loop-nonterminating.c diff --git a/tests/regression/80-termination/34-nested-for-loop-nonterminating.c b/tests/regression/80-termination/34-nested-for-loop-nonterminating.c new file mode 100644 index 0000000000..1f68f3c0a5 --- /dev/null +++ b/tests/regression/80-termination/34-nested-for-loop-nonterminating.c @@ -0,0 +1,19 @@ +// TODO NON_LOCAL_TERM PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra +#include + +int main() +{ + int outerCount, innerCount; + + for (outerCount = 1; outerCount <= 3; outerCount++) + { + for (innerCount = 1; innerCount > 0; innerCount++) + { + printf("(%d, %d) ", outerCount, innerCount); + } + + printf("\n"); + } + + return 0; +} From d681158d9bc6d37afd3a16ffa100336782311f97 Mon Sep 17 00:00:00 2001 From: Thomas Lagemann Date: Thu, 29 Jun 2023 12:34:13 +0200 Subject: [PATCH 161/327] Folder Renaming --- .../01-simple-loop-terminating.c | 0 .../02-simple-loop-nonterminating.c | 0 .../03-nested-loop-terminating.c | 0 .../04-nested-loop-nonterminating.c | 0 .../05-for-loop-terminating.c | 0 .../06-for-loop-nonterminating.c | 0 .../07-nested-for-loop-terminating.c | 0 .../08-nested-for-loop-nonterminating.c | 0 .../09-complex-for-loop-terminating.c | 0 .../10-complex-loop-terminating.c | 0 .../11-loopless-termination.c | 0 .../12-do-while-instant-terminating.c | 0 .../13-do-while-terminating.c | 0 .../14-do-while-nonterminating.c | 0 .../15-complex-loop-combination-terminating.c | 0 .../16-nested-loop-nontrivial-nonterminating.c | 0 .../{80-termination => 74-loop_termination}/17-goto-terminating.c | 0 .../18-goto-nonterminating.c | 0 .../{80-termination => 74-loop_termination}/19-rand-terminating.c | 0 .../20-rand-nonterminating.c | 0 .../21-no-exit-on-rand-unproofable.c | 0 .../22-exit-on-rand-unproofable.c | 0 .../23-exit-on-rand-terminating.c | 0 .../24-upjumping-goto-loopless-terminating.c | 0 .../25-leave-loop-goto-terminating.c | 0 .../26-enter-loop-goto-terminating.c | 0 .../27-upjumping-goto-nonterminating.c | 0 .../28-do-while-continue-terminating.c | 0 .../29-do-while-continue-nonterminating.c | 0 .../30-goto-out-of-inner-loop-terminating.c | 0 .../31-goto-out-of-inner-loop-nonterminating.c | 0 .../32-multithread-terminating.c | 0 .../33-multithread-nonterminating.c | 0 .../34-nested-for-loop-nonterminating.c | 0 .../01-simple-terminating.c | 0 .../02-simple-nonterminating.c | 0 .../03-nested-terminating.c | 0 .../04-nested-nonterminating.c | 0 38 files changed, 0 insertions(+), 0 deletions(-) rename tests/regression/{80-termination => 74-loop_termination}/01-simple-loop-terminating.c (100%) rename tests/regression/{80-termination => 74-loop_termination}/02-simple-loop-nonterminating.c (100%) rename tests/regression/{80-termination => 74-loop_termination}/03-nested-loop-terminating.c (100%) rename tests/regression/{80-termination => 74-loop_termination}/04-nested-loop-nonterminating.c (100%) rename tests/regression/{80-termination => 74-loop_termination}/05-for-loop-terminating.c (100%) rename tests/regression/{80-termination => 74-loop_termination}/06-for-loop-nonterminating.c (100%) rename tests/regression/{80-termination => 74-loop_termination}/07-nested-for-loop-terminating.c (100%) rename tests/regression/{80-termination => 74-loop_termination}/08-nested-for-loop-nonterminating.c (100%) rename tests/regression/{80-termination => 74-loop_termination}/09-complex-for-loop-terminating.c (100%) rename tests/regression/{80-termination => 74-loop_termination}/10-complex-loop-terminating.c (100%) rename tests/regression/{80-termination => 74-loop_termination}/11-loopless-termination.c (100%) rename tests/regression/{80-termination => 74-loop_termination}/12-do-while-instant-terminating.c (100%) rename tests/regression/{80-termination => 74-loop_termination}/13-do-while-terminating.c (100%) rename tests/regression/{80-termination => 74-loop_termination}/14-do-while-nonterminating.c (100%) rename tests/regression/{80-termination => 74-loop_termination}/15-complex-loop-combination-terminating.c (100%) rename tests/regression/{80-termination => 74-loop_termination}/16-nested-loop-nontrivial-nonterminating.c (100%) rename tests/regression/{80-termination => 74-loop_termination}/17-goto-terminating.c (100%) rename tests/regression/{80-termination => 74-loop_termination}/18-goto-nonterminating.c (100%) rename tests/regression/{80-termination => 74-loop_termination}/19-rand-terminating.c (100%) rename tests/regression/{80-termination => 74-loop_termination}/20-rand-nonterminating.c (100%) rename tests/regression/{80-termination => 74-loop_termination}/21-no-exit-on-rand-unproofable.c (100%) rename tests/regression/{80-termination => 74-loop_termination}/22-exit-on-rand-unproofable.c (100%) rename tests/regression/{80-termination => 74-loop_termination}/23-exit-on-rand-terminating.c (100%) rename tests/regression/{80-termination => 74-loop_termination}/24-upjumping-goto-loopless-terminating.c (100%) rename tests/regression/{80-termination => 74-loop_termination}/25-leave-loop-goto-terminating.c (100%) rename tests/regression/{80-termination => 74-loop_termination}/26-enter-loop-goto-terminating.c (100%) rename tests/regression/{80-termination => 74-loop_termination}/27-upjumping-goto-nonterminating.c (100%) rename tests/regression/{80-termination => 74-loop_termination}/28-do-while-continue-terminating.c (100%) rename tests/regression/{80-termination => 74-loop_termination}/29-do-while-continue-nonterminating.c (100%) rename tests/regression/{80-termination => 74-loop_termination}/30-goto-out-of-inner-loop-terminating.c (100%) rename tests/regression/{80-termination => 74-loop_termination}/31-goto-out-of-inner-loop-nonterminating.c (100%) rename tests/regression/{80-termination => 74-loop_termination}/32-multithread-terminating.c (100%) rename tests/regression/{80-termination => 74-loop_termination}/33-multithread-nonterminating.c (100%) rename tests/regression/{80-termination => 74-loop_termination}/34-nested-for-loop-nonterminating.c (100%) rename tests/regression/{81-recursion => 75-recursion_termination}/01-simple-terminating.c (100%) rename tests/regression/{81-recursion => 75-recursion_termination}/02-simple-nonterminating.c (100%) rename tests/regression/{81-recursion => 75-recursion_termination}/03-nested-terminating.c (100%) rename tests/regression/{81-recursion => 75-recursion_termination}/04-nested-nonterminating.c (100%) diff --git a/tests/regression/80-termination/01-simple-loop-terminating.c b/tests/regression/74-loop_termination/01-simple-loop-terminating.c similarity index 100% rename from tests/regression/80-termination/01-simple-loop-terminating.c rename to tests/regression/74-loop_termination/01-simple-loop-terminating.c diff --git a/tests/regression/80-termination/02-simple-loop-nonterminating.c b/tests/regression/74-loop_termination/02-simple-loop-nonterminating.c similarity index 100% rename from tests/regression/80-termination/02-simple-loop-nonterminating.c rename to tests/regression/74-loop_termination/02-simple-loop-nonterminating.c diff --git a/tests/regression/80-termination/03-nested-loop-terminating.c b/tests/regression/74-loop_termination/03-nested-loop-terminating.c similarity index 100% rename from tests/regression/80-termination/03-nested-loop-terminating.c rename to tests/regression/74-loop_termination/03-nested-loop-terminating.c diff --git a/tests/regression/80-termination/04-nested-loop-nonterminating.c b/tests/regression/74-loop_termination/04-nested-loop-nonterminating.c similarity index 100% rename from tests/regression/80-termination/04-nested-loop-nonterminating.c rename to tests/regression/74-loop_termination/04-nested-loop-nonterminating.c diff --git a/tests/regression/80-termination/05-for-loop-terminating.c b/tests/regression/74-loop_termination/05-for-loop-terminating.c similarity index 100% rename from tests/regression/80-termination/05-for-loop-terminating.c rename to tests/regression/74-loop_termination/05-for-loop-terminating.c diff --git a/tests/regression/80-termination/06-for-loop-nonterminating.c b/tests/regression/74-loop_termination/06-for-loop-nonterminating.c similarity index 100% rename from tests/regression/80-termination/06-for-loop-nonterminating.c rename to tests/regression/74-loop_termination/06-for-loop-nonterminating.c diff --git a/tests/regression/80-termination/07-nested-for-loop-terminating.c b/tests/regression/74-loop_termination/07-nested-for-loop-terminating.c similarity index 100% rename from tests/regression/80-termination/07-nested-for-loop-terminating.c rename to tests/regression/74-loop_termination/07-nested-for-loop-terminating.c diff --git a/tests/regression/80-termination/08-nested-for-loop-nonterminating.c b/tests/regression/74-loop_termination/08-nested-for-loop-nonterminating.c similarity index 100% rename from tests/regression/80-termination/08-nested-for-loop-nonterminating.c rename to tests/regression/74-loop_termination/08-nested-for-loop-nonterminating.c diff --git a/tests/regression/80-termination/09-complex-for-loop-terminating.c b/tests/regression/74-loop_termination/09-complex-for-loop-terminating.c similarity index 100% rename from tests/regression/80-termination/09-complex-for-loop-terminating.c rename to tests/regression/74-loop_termination/09-complex-for-loop-terminating.c diff --git a/tests/regression/80-termination/10-complex-loop-terminating.c b/tests/regression/74-loop_termination/10-complex-loop-terminating.c similarity index 100% rename from tests/regression/80-termination/10-complex-loop-terminating.c rename to tests/regression/74-loop_termination/10-complex-loop-terminating.c diff --git a/tests/regression/80-termination/11-loopless-termination.c b/tests/regression/74-loop_termination/11-loopless-termination.c similarity index 100% rename from tests/regression/80-termination/11-loopless-termination.c rename to tests/regression/74-loop_termination/11-loopless-termination.c diff --git a/tests/regression/80-termination/12-do-while-instant-terminating.c b/tests/regression/74-loop_termination/12-do-while-instant-terminating.c similarity index 100% rename from tests/regression/80-termination/12-do-while-instant-terminating.c rename to tests/regression/74-loop_termination/12-do-while-instant-terminating.c diff --git a/tests/regression/80-termination/13-do-while-terminating.c b/tests/regression/74-loop_termination/13-do-while-terminating.c similarity index 100% rename from tests/regression/80-termination/13-do-while-terminating.c rename to tests/regression/74-loop_termination/13-do-while-terminating.c diff --git a/tests/regression/80-termination/14-do-while-nonterminating.c b/tests/regression/74-loop_termination/14-do-while-nonterminating.c similarity index 100% rename from tests/regression/80-termination/14-do-while-nonterminating.c rename to tests/regression/74-loop_termination/14-do-while-nonterminating.c diff --git a/tests/regression/80-termination/15-complex-loop-combination-terminating.c b/tests/regression/74-loop_termination/15-complex-loop-combination-terminating.c similarity index 100% rename from tests/regression/80-termination/15-complex-loop-combination-terminating.c rename to tests/regression/74-loop_termination/15-complex-loop-combination-terminating.c diff --git a/tests/regression/80-termination/16-nested-loop-nontrivial-nonterminating.c b/tests/regression/74-loop_termination/16-nested-loop-nontrivial-nonterminating.c similarity index 100% rename from tests/regression/80-termination/16-nested-loop-nontrivial-nonterminating.c rename to tests/regression/74-loop_termination/16-nested-loop-nontrivial-nonterminating.c diff --git a/tests/regression/80-termination/17-goto-terminating.c b/tests/regression/74-loop_termination/17-goto-terminating.c similarity index 100% rename from tests/regression/80-termination/17-goto-terminating.c rename to tests/regression/74-loop_termination/17-goto-terminating.c diff --git a/tests/regression/80-termination/18-goto-nonterminating.c b/tests/regression/74-loop_termination/18-goto-nonterminating.c similarity index 100% rename from tests/regression/80-termination/18-goto-nonterminating.c rename to tests/regression/74-loop_termination/18-goto-nonterminating.c diff --git a/tests/regression/80-termination/19-rand-terminating.c b/tests/regression/74-loop_termination/19-rand-terminating.c similarity index 100% rename from tests/regression/80-termination/19-rand-terminating.c rename to tests/regression/74-loop_termination/19-rand-terminating.c diff --git a/tests/regression/80-termination/20-rand-nonterminating.c b/tests/regression/74-loop_termination/20-rand-nonterminating.c similarity index 100% rename from tests/regression/80-termination/20-rand-nonterminating.c rename to tests/regression/74-loop_termination/20-rand-nonterminating.c diff --git a/tests/regression/80-termination/21-no-exit-on-rand-unproofable.c b/tests/regression/74-loop_termination/21-no-exit-on-rand-unproofable.c similarity index 100% rename from tests/regression/80-termination/21-no-exit-on-rand-unproofable.c rename to tests/regression/74-loop_termination/21-no-exit-on-rand-unproofable.c diff --git a/tests/regression/80-termination/22-exit-on-rand-unproofable.c b/tests/regression/74-loop_termination/22-exit-on-rand-unproofable.c similarity index 100% rename from tests/regression/80-termination/22-exit-on-rand-unproofable.c rename to tests/regression/74-loop_termination/22-exit-on-rand-unproofable.c diff --git a/tests/regression/80-termination/23-exit-on-rand-terminating.c b/tests/regression/74-loop_termination/23-exit-on-rand-terminating.c similarity index 100% rename from tests/regression/80-termination/23-exit-on-rand-terminating.c rename to tests/regression/74-loop_termination/23-exit-on-rand-terminating.c diff --git a/tests/regression/80-termination/24-upjumping-goto-loopless-terminating.c b/tests/regression/74-loop_termination/24-upjumping-goto-loopless-terminating.c similarity index 100% rename from tests/regression/80-termination/24-upjumping-goto-loopless-terminating.c rename to tests/regression/74-loop_termination/24-upjumping-goto-loopless-terminating.c diff --git a/tests/regression/80-termination/25-leave-loop-goto-terminating.c b/tests/regression/74-loop_termination/25-leave-loop-goto-terminating.c similarity index 100% rename from tests/regression/80-termination/25-leave-loop-goto-terminating.c rename to tests/regression/74-loop_termination/25-leave-loop-goto-terminating.c diff --git a/tests/regression/80-termination/26-enter-loop-goto-terminating.c b/tests/regression/74-loop_termination/26-enter-loop-goto-terminating.c similarity index 100% rename from tests/regression/80-termination/26-enter-loop-goto-terminating.c rename to tests/regression/74-loop_termination/26-enter-loop-goto-terminating.c diff --git a/tests/regression/80-termination/27-upjumping-goto-nonterminating.c b/tests/regression/74-loop_termination/27-upjumping-goto-nonterminating.c similarity index 100% rename from tests/regression/80-termination/27-upjumping-goto-nonterminating.c rename to tests/regression/74-loop_termination/27-upjumping-goto-nonterminating.c diff --git a/tests/regression/80-termination/28-do-while-continue-terminating.c b/tests/regression/74-loop_termination/28-do-while-continue-terminating.c similarity index 100% rename from tests/regression/80-termination/28-do-while-continue-terminating.c rename to tests/regression/74-loop_termination/28-do-while-continue-terminating.c diff --git a/tests/regression/80-termination/29-do-while-continue-nonterminating.c b/tests/regression/74-loop_termination/29-do-while-continue-nonterminating.c similarity index 100% rename from tests/regression/80-termination/29-do-while-continue-nonterminating.c rename to tests/regression/74-loop_termination/29-do-while-continue-nonterminating.c diff --git a/tests/regression/80-termination/30-goto-out-of-inner-loop-terminating.c b/tests/regression/74-loop_termination/30-goto-out-of-inner-loop-terminating.c similarity index 100% rename from tests/regression/80-termination/30-goto-out-of-inner-loop-terminating.c rename to tests/regression/74-loop_termination/30-goto-out-of-inner-loop-terminating.c diff --git a/tests/regression/80-termination/31-goto-out-of-inner-loop-nonterminating.c b/tests/regression/74-loop_termination/31-goto-out-of-inner-loop-nonterminating.c similarity index 100% rename from tests/regression/80-termination/31-goto-out-of-inner-loop-nonterminating.c rename to tests/regression/74-loop_termination/31-goto-out-of-inner-loop-nonterminating.c diff --git a/tests/regression/80-termination/32-multithread-terminating.c b/tests/regression/74-loop_termination/32-multithread-terminating.c similarity index 100% rename from tests/regression/80-termination/32-multithread-terminating.c rename to tests/regression/74-loop_termination/32-multithread-terminating.c diff --git a/tests/regression/80-termination/33-multithread-nonterminating.c b/tests/regression/74-loop_termination/33-multithread-nonterminating.c similarity index 100% rename from tests/regression/80-termination/33-multithread-nonterminating.c rename to tests/regression/74-loop_termination/33-multithread-nonterminating.c diff --git a/tests/regression/80-termination/34-nested-for-loop-nonterminating.c b/tests/regression/74-loop_termination/34-nested-for-loop-nonterminating.c similarity index 100% rename from tests/regression/80-termination/34-nested-for-loop-nonterminating.c rename to tests/regression/74-loop_termination/34-nested-for-loop-nonterminating.c diff --git a/tests/regression/81-recursion/01-simple-terminating.c b/tests/regression/75-recursion_termination/01-simple-terminating.c similarity index 100% rename from tests/regression/81-recursion/01-simple-terminating.c rename to tests/regression/75-recursion_termination/01-simple-terminating.c diff --git a/tests/regression/81-recursion/02-simple-nonterminating.c b/tests/regression/75-recursion_termination/02-simple-nonterminating.c similarity index 100% rename from tests/regression/81-recursion/02-simple-nonterminating.c rename to tests/regression/75-recursion_termination/02-simple-nonterminating.c diff --git a/tests/regression/81-recursion/03-nested-terminating.c b/tests/regression/75-recursion_termination/03-nested-terminating.c similarity index 100% rename from tests/regression/81-recursion/03-nested-terminating.c rename to tests/regression/75-recursion_termination/03-nested-terminating.c diff --git a/tests/regression/81-recursion/04-nested-nonterminating.c b/tests/regression/75-recursion_termination/04-nested-nonterminating.c similarity index 100% rename from tests/regression/81-recursion/04-nested-nonterminating.c rename to tests/regression/75-recursion_termination/04-nested-nonterminating.c From 541e49b1484fed17376bce8237c54054a85882b9 Mon Sep 17 00:00:00 2001 From: Thomas Lagemann Date: Thu, 29 Jun 2023 12:49:43 +0200 Subject: [PATCH 162/327] Enable polyhedra; Removed unnecessary TODOs --- .../15-complex-loop-combination-terminating.c | 2 +- .../74-loop_termination/34-nested-for-loop-nonterminating.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/regression/74-loop_termination/15-complex-loop-combination-terminating.c b/tests/regression/74-loop_termination/15-complex-loop-combination-terminating.c index 9ab04745e8..ec6b50512e 100644 --- a/tests/regression/74-loop_termination/15-complex-loop-combination-terminating.c +++ b/tests/regression/74-loop_termination/15-complex-loop-combination-terminating.c @@ -1,4 +1,4 @@ -// LOCAL_TERM PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval +// LOCAL_TERM PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra #include int main() diff --git a/tests/regression/74-loop_termination/34-nested-for-loop-nonterminating.c b/tests/regression/74-loop_termination/34-nested-for-loop-nonterminating.c index 1f68f3c0a5..d8aa9d487d 100644 --- a/tests/regression/74-loop_termination/34-nested-for-loop-nonterminating.c +++ b/tests/regression/74-loop_termination/34-nested-for-loop-nonterminating.c @@ -1,4 +1,4 @@ -// TODO NON_LOCAL_TERM PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra +// NON_LOCAL_TERM PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra #include int main() From 1b5db9c80811fcc083b90ac66554f03fb70dd9ab Mon Sep 17 00:00:00 2001 From: Isidor Zweckstetter Date: Thu, 29 Jun 2023 12:59:03 +0200 Subject: [PATCH 163/327] patched loop termination check position to right after the loop head --- src/util/terminationPreprocessing.ml | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/util/terminationPreprocessing.ml b/src/util/terminationPreprocessing.ml index 45794b56cc..abc0bd36ef 100644 --- a/src/util/terminationPreprocessing.ml +++ b/src/util/terminationPreprocessing.ml @@ -35,8 +35,10 @@ class loopCounterVisitor lc lg le (fd : fundec) = object(self) let inc_stmt = mkStmtOneInstr @@ Set (var v, increm (Lval (var v)) 1, loc, eloc) in let check_stmt = mkStmtOneInstr @@ Set ((var !le), (Lval (var v)), loc, eloc) in (match b.bstmts with - | cont :: cond :: ss -> - b.bstmts <- cont :: inc_stmt :: check_stmt :: cond :: ss; (*cont :: cond :: inc_stmt :: ss = it is also possible, but for loops with cond at the end, inc is also at the end*) + | ss -> + b.bstmts <- inc_stmt :: check_stmt :: ss; (*cont :: cond :: inc_stmt :: ss = it is also possible, but for loops with cond at the end, inc is also at the end*) + (*| cont :: ss -> + b.bstmts <- cont :: inc_stmt :: check_stmt :: ss;*) | _ -> ()); lc := VarToStmt.add (v: varinfo) (s: stmt) !lc; let nb = mkBlock [init_stmt; mkStmt s.skind] in From e6ba5597dd0138b773ac21621d445b6eeca7e372 Mon Sep 17 00:00:00 2001 From: Isidor Zweckstetter Date: Thu, 29 Jun 2023 12:59:49 +0200 Subject: [PATCH 164/327] removed temporary comment --- src/util/terminationPreprocessing.ml | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/util/terminationPreprocessing.ml b/src/util/terminationPreprocessing.ml index abc0bd36ef..480bede358 100644 --- a/src/util/terminationPreprocessing.ml +++ b/src/util/terminationPreprocessing.ml @@ -37,8 +37,6 @@ class loopCounterVisitor lc lg le (fd : fundec) = object(self) (match b.bstmts with | ss -> b.bstmts <- inc_stmt :: check_stmt :: ss; (*cont :: cond :: inc_stmt :: ss = it is also possible, but for loops with cond at the end, inc is also at the end*) - (*| cont :: ss -> - b.bstmts <- cont :: inc_stmt :: check_stmt :: ss;*) | _ -> ()); lc := VarToStmt.add (v: varinfo) (s: stmt) !lc; let nb = mkBlock [init_stmt; mkStmt s.skind] in From 16b8c375d77934e572c7cd9576dcb115bfcfa4f2 Mon Sep 17 00:00:00 2001 From: Isidor Zweckstetter Date: Thu, 29 Jun 2023 13:01:43 +0200 Subject: [PATCH 165/327] removed outdated code --- src/util/terminationPreprocessing.ml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/util/terminationPreprocessing.ml b/src/util/terminationPreprocessing.ml index 480bede358..6e29c48917 100644 --- a/src/util/terminationPreprocessing.ml +++ b/src/util/terminationPreprocessing.ml @@ -36,8 +36,8 @@ class loopCounterVisitor lc lg le (fd : fundec) = object(self) let check_stmt = mkStmtOneInstr @@ Set ((var !le), (Lval (var v)), loc, eloc) in (match b.bstmts with | ss -> - b.bstmts <- inc_stmt :: check_stmt :: ss; (*cont :: cond :: inc_stmt :: ss = it is also possible, but for loops with cond at the end, inc is also at the end*) - | _ -> ()); + b.bstmts <- inc_stmt :: check_stmt :: ss; + ); lc := VarToStmt.add (v: varinfo) (s: stmt) !lc; let nb = mkBlock [init_stmt; mkStmt s.skind] in s.skind <- Block nb; From 1cefa964032e3d2e39c9380efcfd7c59f9f65517 Mon Sep 17 00:00:00 2001 From: Thomas Lagemann Date: Thu, 29 Jun 2023 13:04:25 +0200 Subject: [PATCH 166/327] Removed unnecessary TODOs --- .../regression/74-loop_termination/06-for-loop-nonterminating.c | 2 +- .../74-loop_termination/08-nested-for-loop-nonterminating.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/regression/74-loop_termination/06-for-loop-nonterminating.c b/tests/regression/74-loop_termination/06-for-loop-nonterminating.c index 73a8b8c6fd..b8f30361d1 100644 --- a/tests/regression/74-loop_termination/06-for-loop-nonterminating.c +++ b/tests/regression/74-loop_termination/06-for-loop-nonterminating.c @@ -1,4 +1,4 @@ -// TODO NON_LOCAL_TERM PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra +// NON_LOCAL_TERM PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra #include int main() { diff --git a/tests/regression/74-loop_termination/08-nested-for-loop-nonterminating.c b/tests/regression/74-loop_termination/08-nested-for-loop-nonterminating.c index 8b451e56dd..0368120b13 100644 --- a/tests/regression/74-loop_termination/08-nested-for-loop-nonterminating.c +++ b/tests/regression/74-loop_termination/08-nested-for-loop-nonterminating.c @@ -1,4 +1,4 @@ -// TODO NON_LOCAL_TERM PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra +// NON_LOCAL_TERM PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra #include int main() From 2430f3fc9a798d37025f50e80fc5000551e5b45f Mon Sep 17 00:00:00 2001 From: Thomas Lagemann Date: Thu, 29 Jun 2023 13:17:23 +0200 Subject: [PATCH 167/327] Renamed LOCAL_TERM to TERM --- scripts/update_suite.rb | 26 +++++++++---------- .../01-simple-loop-terminating.c | 2 +- .../02-simple-loop-nonterminating.c | 2 +- .../03-nested-loop-terminating.c | 2 +- .../04-nested-loop-nonterminating.c | 2 +- .../05-for-loop-terminating.c | 2 +- .../06-for-loop-nonterminating.c | 2 +- .../07-nested-for-loop-terminating.c | 2 +- .../08-nested-for-loop-nonterminating.c | 2 +- .../09-complex-for-loop-terminating.c | 2 +- .../10-complex-loop-terminating.c | 2 +- .../11-loopless-termination.c | 2 +- .../12-do-while-instant-terminating.c | 2 +- .../13-do-while-terminating.c | 2 +- .../14-do-while-nonterminating.c | 2 +- .../15-complex-loop-combination-terminating.c | 2 +- ...16-nested-loop-nontrivial-nonterminating.c | 2 +- .../74-loop_termination/17-goto-terminating.c | 2 +- .../18-goto-nonterminating.c | 2 +- .../74-loop_termination/19-rand-terminating.c | 2 +- .../20-rand-nonterminating.c | 2 +- .../21-no-exit-on-rand-unproofable.c | 2 +- .../22-exit-on-rand-unproofable.c | 2 +- .../23-exit-on-rand-terminating.c | 2 +- .../24-upjumping-goto-loopless-terminating.c | 2 +- .../25-leave-loop-goto-terminating.c | 2 +- .../26-enter-loop-goto-terminating.c | 2 +- .../27-upjumping-goto-nonterminating.c | 2 +- .../28-do-while-continue-terminating.c | 2 +- .../29-do-while-continue-nonterminating.c | 2 +- .../30-goto-out-of-inner-loop-terminating.c | 2 +- ...31-goto-out-of-inner-loop-nonterminating.c | 2 +- .../32-multithread-terminating.c | 2 +- .../33-multithread-nonterminating.c | 2 +- .../34-nested-for-loop-nonterminating.c | 2 +- .../01-simple-terminating.c | 2 +- .../02-simple-nonterminating.c | 2 +- .../03-nested-terminating.c | 2 +- .../04-nested-nonterminating.c | 2 +- 39 files changed, 50 insertions(+), 52 deletions(-) diff --git a/scripts/update_suite.rb b/scripts/update_suite.rb index 98eff124af..8841ecea88 100755 --- a/scripts/update_suite.rb +++ b/scripts/update_suite.rb @@ -145,11 +145,11 @@ def collect_warnings @vars = $1 @evals = $2 end - if l =~ /\[NonTerminating\]/ then warnings[-1] = "non_local_term" end # Get NonTerminating warning + if l =~ /\[NonTerminating\]/ then warnings[-1] = "nonterm" end # Get NonTerminating warning next unless l =~ /(.*)\(.*?\:(\d+)(?:\:\d+)?(?:-(?:\d+)(?:\:\d+)?)?\)/ obj,i = $1,$2.to_i - ranking = ["other", "warn", "local_term", "non_local_term", "race", "norace", "deadlock", "nodeadlock", "success", "fail", "unknown"] + ranking = ["other", "warn", "term", "nonterm", "race", "norace", "deadlock", "nodeadlock", "success", "fail", "unknown"] thiswarn = case obj when /\(conf\. \d+\)/ then "race" when /Deadlock/ then "deadlock" @@ -208,9 +208,9 @@ def compare_warnings case type when "deadlock", "race", "fail", "unknown", "warn" check.call warnings[idx] == type - when "non_local_term" + when "nonterm" check.call warnings[idx] == type - when "nowarn", "local_term" + when "nowarn", "term" check.call warnings[idx].nil? when "assert", "success" check.call warnings[idx] == "success" @@ -324,19 +324,17 @@ def parse_tests (lines) case lines[0] when /TODO|SKIP/ case lines[0] - when /NON_LOCAL_TERM/ - tests[-1] = "non_local_term" + when /NONTERM/ + tests[-1] = "nonterm" todo << -1 - when /LOCAL_TERM/ - tests[-1] = "local_term" + when /TERM/ + tests[-1] = "term" todo << -1 end - when /NON_LOCAL_TERM/ - # covers "TERM" as keyword but a combined use of NON_LOCAL_TERM (loop termination) and TERM would be pointless - tests[-1] = "non_local_term" - when /LOCAL_TERM/ - # covers "TERM" as keyword but a combined use of NON_LOCAL_TERM (loop termination) and TERM would be pointless - tests[-1] = "local_term" + when /NONTERM/ + tests[-1] = "nonterm" + when /TERM/ + tests[-1] = "term" end Tests.new(self, tests, tests_line, todo) end diff --git a/tests/regression/74-loop_termination/01-simple-loop-terminating.c b/tests/regression/74-loop_termination/01-simple-loop-terminating.c index a517d0d608..a80084868a 100644 --- a/tests/regression/74-loop_termination/01-simple-loop-terminating.c +++ b/tests/regression/74-loop_termination/01-simple-loop-terminating.c @@ -1,4 +1,4 @@ -// LOCAL_TERM PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra +// TERM PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra #include int main() diff --git a/tests/regression/74-loop_termination/02-simple-loop-nonterminating.c b/tests/regression/74-loop_termination/02-simple-loop-nonterminating.c index bcb9909f80..eef9f81ea3 100644 --- a/tests/regression/74-loop_termination/02-simple-loop-nonterminating.c +++ b/tests/regression/74-loop_termination/02-simple-loop-nonterminating.c @@ -1,4 +1,4 @@ -// NON_LOCAL_TERM PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra +// NONTERM PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra #include int main() diff --git a/tests/regression/74-loop_termination/03-nested-loop-terminating.c b/tests/regression/74-loop_termination/03-nested-loop-terminating.c index 366cbaeea5..5e72ec3284 100644 --- a/tests/regression/74-loop_termination/03-nested-loop-terminating.c +++ b/tests/regression/74-loop_termination/03-nested-loop-terminating.c @@ -1,4 +1,4 @@ -// LOCAL_TERM PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra +// TERM PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra #include int main() diff --git a/tests/regression/74-loop_termination/04-nested-loop-nonterminating.c b/tests/regression/74-loop_termination/04-nested-loop-nonterminating.c index ee2aa4a8c4..1fb5ada507 100644 --- a/tests/regression/74-loop_termination/04-nested-loop-nonterminating.c +++ b/tests/regression/74-loop_termination/04-nested-loop-nonterminating.c @@ -1,4 +1,4 @@ -// NON_LOCAL_TERM PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra +// NONTERM PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra #include int main() diff --git a/tests/regression/74-loop_termination/05-for-loop-terminating.c b/tests/regression/74-loop_termination/05-for-loop-terminating.c index 2a16184f6d..cf71fa5135 100644 --- a/tests/regression/74-loop_termination/05-for-loop-terminating.c +++ b/tests/regression/74-loop_termination/05-for-loop-terminating.c @@ -1,4 +1,4 @@ -// LOCAL_TERM PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra +// TERM PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra #include int main() diff --git a/tests/regression/74-loop_termination/06-for-loop-nonterminating.c b/tests/regression/74-loop_termination/06-for-loop-nonterminating.c index b8f30361d1..8c1500cfb1 100644 --- a/tests/regression/74-loop_termination/06-for-loop-nonterminating.c +++ b/tests/regression/74-loop_termination/06-for-loop-nonterminating.c @@ -1,4 +1,4 @@ -// NON_LOCAL_TERM PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra +// NONTERM PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra #include int main() { diff --git a/tests/regression/74-loop_termination/07-nested-for-loop-terminating.c b/tests/regression/74-loop_termination/07-nested-for-loop-terminating.c index def0787d39..4b3395bd11 100644 --- a/tests/regression/74-loop_termination/07-nested-for-loop-terminating.c +++ b/tests/regression/74-loop_termination/07-nested-for-loop-terminating.c @@ -1,4 +1,4 @@ -// LOCAL_TERM PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra +// TERM PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra #include int main() diff --git a/tests/regression/74-loop_termination/08-nested-for-loop-nonterminating.c b/tests/regression/74-loop_termination/08-nested-for-loop-nonterminating.c index 0368120b13..818146e456 100644 --- a/tests/regression/74-loop_termination/08-nested-for-loop-nonterminating.c +++ b/tests/regression/74-loop_termination/08-nested-for-loop-nonterminating.c @@ -1,4 +1,4 @@ -// NON_LOCAL_TERM PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra +// NONTERM PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra #include int main() diff --git a/tests/regression/74-loop_termination/09-complex-for-loop-terminating.c b/tests/regression/74-loop_termination/09-complex-for-loop-terminating.c index 7fcd5c5eba..c26fde710f 100644 --- a/tests/regression/74-loop_termination/09-complex-for-loop-terminating.c +++ b/tests/regression/74-loop_termination/09-complex-for-loop-terminating.c @@ -1,4 +1,4 @@ -// LOCAL_TERM PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra +// TERM PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra #include int main() diff --git a/tests/regression/74-loop_termination/10-complex-loop-terminating.c b/tests/regression/74-loop_termination/10-complex-loop-terminating.c index def1786937..017c10b8a4 100644 --- a/tests/regression/74-loop_termination/10-complex-loop-terminating.c +++ b/tests/regression/74-loop_termination/10-complex-loop-terminating.c @@ -1,4 +1,4 @@ -// LOCAL_TERM PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra +// TERM PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra #include int main() diff --git a/tests/regression/74-loop_termination/11-loopless-termination.c b/tests/regression/74-loop_termination/11-loopless-termination.c index 86a300f18e..01f9a953e0 100644 --- a/tests/regression/74-loop_termination/11-loopless-termination.c +++ b/tests/regression/74-loop_termination/11-loopless-termination.c @@ -1,4 +1,4 @@ -// LOCAL_TERM PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra +// TERM PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra #include int main() { diff --git a/tests/regression/74-loop_termination/12-do-while-instant-terminating.c b/tests/regression/74-loop_termination/12-do-while-instant-terminating.c index 15032b7b4f..b34dff3f5f 100644 --- a/tests/regression/74-loop_termination/12-do-while-instant-terminating.c +++ b/tests/regression/74-loop_termination/12-do-while-instant-terminating.c @@ -1,4 +1,4 @@ -// LOCAL_TERM PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra +// TERM PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra #include int main() diff --git a/tests/regression/74-loop_termination/13-do-while-terminating.c b/tests/regression/74-loop_termination/13-do-while-terminating.c index 2e04f3e393..651acb8fd8 100644 --- a/tests/regression/74-loop_termination/13-do-while-terminating.c +++ b/tests/regression/74-loop_termination/13-do-while-terminating.c @@ -1,4 +1,4 @@ -// LOCAL_TERM PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra +// TERM PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra #include int main() diff --git a/tests/regression/74-loop_termination/14-do-while-nonterminating.c b/tests/regression/74-loop_termination/14-do-while-nonterminating.c index 5ed18175e9..1e05e2be6e 100644 --- a/tests/regression/74-loop_termination/14-do-while-nonterminating.c +++ b/tests/regression/74-loop_termination/14-do-while-nonterminating.c @@ -1,4 +1,4 @@ -// NON_LOCAL_TERM PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra +// NONTERM PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra #include int main() diff --git a/tests/regression/74-loop_termination/15-complex-loop-combination-terminating.c b/tests/regression/74-loop_termination/15-complex-loop-combination-terminating.c index ec6b50512e..07fbe38cfd 100644 --- a/tests/regression/74-loop_termination/15-complex-loop-combination-terminating.c +++ b/tests/regression/74-loop_termination/15-complex-loop-combination-terminating.c @@ -1,4 +1,4 @@ -// LOCAL_TERM PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra +// TERM PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra #include int main() diff --git a/tests/regression/74-loop_termination/16-nested-loop-nontrivial-nonterminating.c b/tests/regression/74-loop_termination/16-nested-loop-nontrivial-nonterminating.c index 5ff890e461..b9ccea76af 100644 --- a/tests/regression/74-loop_termination/16-nested-loop-nontrivial-nonterminating.c +++ b/tests/regression/74-loop_termination/16-nested-loop-nontrivial-nonterminating.c @@ -1,4 +1,4 @@ -// NON_LOCAL_TERM PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra +// NONTERM PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra #include int main() diff --git a/tests/regression/74-loop_termination/17-goto-terminating.c b/tests/regression/74-loop_termination/17-goto-terminating.c index e988926359..b11b5b3da9 100644 --- a/tests/regression/74-loop_termination/17-goto-terminating.c +++ b/tests/regression/74-loop_termination/17-goto-terminating.c @@ -1,4 +1,4 @@ -// TODO LOCAL_TERM PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra +// TODO TERM PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra #include int main() diff --git a/tests/regression/74-loop_termination/18-goto-nonterminating.c b/tests/regression/74-loop_termination/18-goto-nonterminating.c index cfe5ab481d..aab37803aa 100644 --- a/tests/regression/74-loop_termination/18-goto-nonterminating.c +++ b/tests/regression/74-loop_termination/18-goto-nonterminating.c @@ -1,4 +1,4 @@ -// NON_LOCAL_TERM PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra +// NONTERM PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra #include int main() diff --git a/tests/regression/74-loop_termination/19-rand-terminating.c b/tests/regression/74-loop_termination/19-rand-terminating.c index 426c5cdcca..5d3cde9f3d 100644 --- a/tests/regression/74-loop_termination/19-rand-terminating.c +++ b/tests/regression/74-loop_termination/19-rand-terminating.c @@ -1,4 +1,4 @@ -// LOCAL_TERM PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra +// TERM PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra #include #include #include diff --git a/tests/regression/74-loop_termination/20-rand-nonterminating.c b/tests/regression/74-loop_termination/20-rand-nonterminating.c index 7c21538612..124a19d0f8 100644 --- a/tests/regression/74-loop_termination/20-rand-nonterminating.c +++ b/tests/regression/74-loop_termination/20-rand-nonterminating.c @@ -1,4 +1,4 @@ -// NON_LOCAL_TERM PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra +// NONTERM PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra #include #include #include diff --git a/tests/regression/74-loop_termination/21-no-exit-on-rand-unproofable.c b/tests/regression/74-loop_termination/21-no-exit-on-rand-unproofable.c index f54af1da7c..3bf479b6f9 100644 --- a/tests/regression/74-loop_termination/21-no-exit-on-rand-unproofable.c +++ b/tests/regression/74-loop_termination/21-no-exit-on-rand-unproofable.c @@ -1,4 +1,4 @@ -// NON_LOCAL_TERM PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra +// NONTERM PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra #include int main() diff --git a/tests/regression/74-loop_termination/22-exit-on-rand-unproofable.c b/tests/regression/74-loop_termination/22-exit-on-rand-unproofable.c index 1bc104258d..1f1a9bbd89 100644 --- a/tests/regression/74-loop_termination/22-exit-on-rand-unproofable.c +++ b/tests/regression/74-loop_termination/22-exit-on-rand-unproofable.c @@ -1,4 +1,4 @@ -// NON_LOCAL_TERM PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra +// NONTERM PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra #include int main() diff --git a/tests/regression/74-loop_termination/23-exit-on-rand-terminating.c b/tests/regression/74-loop_termination/23-exit-on-rand-terminating.c index 253d38c5df..4b9aacd0fd 100644 --- a/tests/regression/74-loop_termination/23-exit-on-rand-terminating.c +++ b/tests/regression/74-loop_termination/23-exit-on-rand-terminating.c @@ -1,4 +1,4 @@ -// TODO LOCAL_TERM PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra +// TODO TERM PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra #include #include diff --git a/tests/regression/74-loop_termination/24-upjumping-goto-loopless-terminating.c b/tests/regression/74-loop_termination/24-upjumping-goto-loopless-terminating.c index 01bffde383..3c4fffdc8a 100644 --- a/tests/regression/74-loop_termination/24-upjumping-goto-loopless-terminating.c +++ b/tests/regression/74-loop_termination/24-upjumping-goto-loopless-terminating.c @@ -1,4 +1,4 @@ -// TODO LOCAL_TERM PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra +// TODO TERM PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra #include int main() { diff --git a/tests/regression/74-loop_termination/25-leave-loop-goto-terminating.c b/tests/regression/74-loop_termination/25-leave-loop-goto-terminating.c index fed0e218ac..380e98ded0 100644 --- a/tests/regression/74-loop_termination/25-leave-loop-goto-terminating.c +++ b/tests/regression/74-loop_termination/25-leave-loop-goto-terminating.c @@ -1,4 +1,4 @@ -// TODO LOCAL_TERM PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra +// TODO TERM PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra #include int main() { diff --git a/tests/regression/74-loop_termination/26-enter-loop-goto-terminating.c b/tests/regression/74-loop_termination/26-enter-loop-goto-terminating.c index 2a43933758..b676ca6985 100644 --- a/tests/regression/74-loop_termination/26-enter-loop-goto-terminating.c +++ b/tests/regression/74-loop_termination/26-enter-loop-goto-terminating.c @@ -1,4 +1,4 @@ -// TODO LOCAL_TERM PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra +// TODO TERM PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra #include int main() { diff --git a/tests/regression/74-loop_termination/27-upjumping-goto-nonterminating.c b/tests/regression/74-loop_termination/27-upjumping-goto-nonterminating.c index a230827356..52ad7ea820 100644 --- a/tests/regression/74-loop_termination/27-upjumping-goto-nonterminating.c +++ b/tests/regression/74-loop_termination/27-upjumping-goto-nonterminating.c @@ -1,4 +1,4 @@ -// NON_LOCAL_TERM PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra +// NONTERM PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra #include int main() { diff --git a/tests/regression/74-loop_termination/28-do-while-continue-terminating.c b/tests/regression/74-loop_termination/28-do-while-continue-terminating.c index 5989c61fed..aa215a502a 100644 --- a/tests/regression/74-loop_termination/28-do-while-continue-terminating.c +++ b/tests/regression/74-loop_termination/28-do-while-continue-terminating.c @@ -1,4 +1,4 @@ -// TODO LOCAL_TERM PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra +// TODO TERM PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra #include int main() diff --git a/tests/regression/74-loop_termination/29-do-while-continue-nonterminating.c b/tests/regression/74-loop_termination/29-do-while-continue-nonterminating.c index 806456e887..896d8fea95 100644 --- a/tests/regression/74-loop_termination/29-do-while-continue-nonterminating.c +++ b/tests/regression/74-loop_termination/29-do-while-continue-nonterminating.c @@ -1,4 +1,4 @@ -// NON_LOCAL_TERM PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra +// NONTERM PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra #include int main() diff --git a/tests/regression/74-loop_termination/30-goto-out-of-inner-loop-terminating.c b/tests/regression/74-loop_termination/30-goto-out-of-inner-loop-terminating.c index 76c272a654..0526e20bb4 100644 --- a/tests/regression/74-loop_termination/30-goto-out-of-inner-loop-terminating.c +++ b/tests/regression/74-loop_termination/30-goto-out-of-inner-loop-terminating.c @@ -1,4 +1,4 @@ -// TODO LOCAL_TERM PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra +// TODO TERM PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra #include int main() { diff --git a/tests/regression/74-loop_termination/31-goto-out-of-inner-loop-nonterminating.c b/tests/regression/74-loop_termination/31-goto-out-of-inner-loop-nonterminating.c index c1824227d0..722694eb88 100644 --- a/tests/regression/74-loop_termination/31-goto-out-of-inner-loop-nonterminating.c +++ b/tests/regression/74-loop_termination/31-goto-out-of-inner-loop-nonterminating.c @@ -1,4 +1,4 @@ -// NON_LOCAL_TERM PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra +// NONTERM PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra #include int main() { diff --git a/tests/regression/74-loop_termination/32-multithread-terminating.c b/tests/regression/74-loop_termination/32-multithread-terminating.c index a08fe01398..1f98b88eee 100644 --- a/tests/regression/74-loop_termination/32-multithread-terminating.c +++ b/tests/regression/74-loop_termination/32-multithread-terminating.c @@ -1,4 +1,4 @@ -// LOCAL_TERM PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra +// TERM PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra #include #include #include diff --git a/tests/regression/74-loop_termination/33-multithread-nonterminating.c b/tests/regression/74-loop_termination/33-multithread-nonterminating.c index 77cd2aafe6..007af3b57b 100644 --- a/tests/regression/74-loop_termination/33-multithread-nonterminating.c +++ b/tests/regression/74-loop_termination/33-multithread-nonterminating.c @@ -1,4 +1,4 @@ -// NON_LOCAL_TERM PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra +// NONTERM PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra #include #include #include diff --git a/tests/regression/74-loop_termination/34-nested-for-loop-nonterminating.c b/tests/regression/74-loop_termination/34-nested-for-loop-nonterminating.c index d8aa9d487d..29e4ff3835 100644 --- a/tests/regression/74-loop_termination/34-nested-for-loop-nonterminating.c +++ b/tests/regression/74-loop_termination/34-nested-for-loop-nonterminating.c @@ -1,4 +1,4 @@ -// NON_LOCAL_TERM PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra +// NONTERM PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra #include int main() diff --git a/tests/regression/75-recursion_termination/01-simple-terminating.c b/tests/regression/75-recursion_termination/01-simple-terminating.c index 4f09950025..583f8ccca1 100644 --- a/tests/regression/75-recursion_termination/01-simple-terminating.c +++ b/tests/regression/75-recursion_termination/01-simple-terminating.c @@ -1,4 +1,4 @@ -// LOCAL_TERM PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra +// TERM PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra #include void recursiveFunction(int n) { diff --git a/tests/regression/75-recursion_termination/02-simple-nonterminating.c b/tests/regression/75-recursion_termination/02-simple-nonterminating.c index 37c4bbd801..41a2b7b678 100644 --- a/tests/regression/75-recursion_termination/02-simple-nonterminating.c +++ b/tests/regression/75-recursion_termination/02-simple-nonterminating.c @@ -1,4 +1,4 @@ -// NON_LOCAL_TERM PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra +// NONTERM PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra #include void recursiveFunction(int n) { diff --git a/tests/regression/75-recursion_termination/03-nested-terminating.c b/tests/regression/75-recursion_termination/03-nested-terminating.c index 23bedef644..4cede747f2 100644 --- a/tests/regression/75-recursion_termination/03-nested-terminating.c +++ b/tests/regression/75-recursion_termination/03-nested-terminating.c @@ -1,4 +1,4 @@ -// LOCAL_TERM PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra +// TERM PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra #include void innerRecursiveFunction(int n) { diff --git a/tests/regression/75-recursion_termination/04-nested-nonterminating.c b/tests/regression/75-recursion_termination/04-nested-nonterminating.c index d28685e139..2d3239f371 100644 --- a/tests/regression/75-recursion_termination/04-nested-nonterminating.c +++ b/tests/regression/75-recursion_termination/04-nested-nonterminating.c @@ -1,4 +1,4 @@ -// NON_LOCAL_TERM PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra +// NONTERM PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra #include void innerRecursiveFunction() { From 2c7394861d6070f96e8287b24c1b94887e9dd608 Mon Sep 17 00:00:00 2001 From: Thomas Lagemann Date: Thu, 29 Jun 2023 13:42:29 +0200 Subject: [PATCH 168/327] Reformat --- .../75-recursion_termination/02-simple-nonterminating.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/regression/75-recursion_termination/02-simple-nonterminating.c b/tests/regression/75-recursion_termination/02-simple-nonterminating.c index 41a2b7b678..0dc3cbcf63 100644 --- a/tests/regression/75-recursion_termination/02-simple-nonterminating.c +++ b/tests/regression/75-recursion_termination/02-simple-nonterminating.c @@ -1,4 +1,4 @@ -// NONTERM PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra +// NONTERM PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra #include void recursiveFunction(int n) { From 7f484cb2abf7f438313e7730951dfa1a73ebd928 Mon Sep 17 00:00:00 2001 From: Thomas Lagemann Date: Thu, 29 Jun 2023 13:43:41 +0200 Subject: [PATCH 169/327] Skip crashing tests --- .../74-loop_termination/09-complex-for-loop-terminating.c | 2 +- .../74-loop_termination/10-complex-loop-terminating.c | 2 +- .../15-complex-loop-combination-terminating.c | 2 +- .../75-recursion_termination/04-nested-nonterminating.c | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/tests/regression/74-loop_termination/09-complex-for-loop-terminating.c b/tests/regression/74-loop_termination/09-complex-for-loop-terminating.c index c26fde710f..7fb9262aab 100644 --- a/tests/regression/74-loop_termination/09-complex-for-loop-terminating.c +++ b/tests/regression/74-loop_termination/09-complex-for-loop-terminating.c @@ -1,4 +1,4 @@ -// TERM PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra +// SKIP TERM PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra #include int main() diff --git a/tests/regression/74-loop_termination/10-complex-loop-terminating.c b/tests/regression/74-loop_termination/10-complex-loop-terminating.c index 017c10b8a4..e39613b563 100644 --- a/tests/regression/74-loop_termination/10-complex-loop-terminating.c +++ b/tests/regression/74-loop_termination/10-complex-loop-terminating.c @@ -1,4 +1,4 @@ -// TERM PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra +// SKIP TERM PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra #include int main() diff --git a/tests/regression/74-loop_termination/15-complex-loop-combination-terminating.c b/tests/regression/74-loop_termination/15-complex-loop-combination-terminating.c index 07fbe38cfd..ad64a9a5f9 100644 --- a/tests/regression/74-loop_termination/15-complex-loop-combination-terminating.c +++ b/tests/regression/74-loop_termination/15-complex-loop-combination-terminating.c @@ -1,4 +1,4 @@ -// TERM PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra +// SKIP TERM PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra #include int main() diff --git a/tests/regression/75-recursion_termination/04-nested-nonterminating.c b/tests/regression/75-recursion_termination/04-nested-nonterminating.c index 2d3239f371..5299544a70 100644 --- a/tests/regression/75-recursion_termination/04-nested-nonterminating.c +++ b/tests/regression/75-recursion_termination/04-nested-nonterminating.c @@ -1,4 +1,4 @@ -// NONTERM PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra +// SKIP NONTERM PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra #include void innerRecursiveFunction() { From a91e716de0d7bcdce098b31babe6333ee32111dd Mon Sep 17 00:00:00 2001 From: Alexander Schlenga Date: Thu, 29 Jun 2023 13:45:31 +0200 Subject: [PATCH 170/327] Rename loop termination analysis --- src/analyses/{termination_new.ml => loop_termination.ml} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename src/analyses/{termination_new.ml => loop_termination.ml} (100%) diff --git a/src/analyses/termination_new.ml b/src/analyses/loop_termination.ml similarity index 100% rename from src/analyses/termination_new.ml rename to src/analyses/loop_termination.ml From 8483cece62310439d56da7a373781ca74e9de848 Mon Sep 17 00:00:00 2001 From: Thomas Lagemann Date: Thu, 29 Jun 2023 14:06:34 +0200 Subject: [PATCH 171/327] Removed Todos --- tests/regression/74-loop_termination/17-goto-terminating.c | 2 +- .../74-loop_termination/23-exit-on-rand-terminating.c | 2 +- .../24-upjumping-goto-loopless-terminating.c | 2 +- .../74-loop_termination/25-leave-loop-goto-terminating.c | 2 +- .../74-loop_termination/26-enter-loop-goto-terminating.c | 2 +- .../74-loop_termination/28-do-while-continue-terminating.c | 2 +- .../74-loop_termination/30-goto-out-of-inner-loop-terminating.c | 2 +- .../75-recursion_termination/02-simple-nonterminating.c | 2 +- .../75-recursion_termination/04-nested-nonterminating.c | 2 +- 9 files changed, 9 insertions(+), 9 deletions(-) diff --git a/tests/regression/74-loop_termination/17-goto-terminating.c b/tests/regression/74-loop_termination/17-goto-terminating.c index b11b5b3da9..1e4c1e719e 100644 --- a/tests/regression/74-loop_termination/17-goto-terminating.c +++ b/tests/regression/74-loop_termination/17-goto-terminating.c @@ -1,4 +1,4 @@ -// TODO TERM PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra +// TERM PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra #include int main() diff --git a/tests/regression/74-loop_termination/23-exit-on-rand-terminating.c b/tests/regression/74-loop_termination/23-exit-on-rand-terminating.c index 4b9aacd0fd..94e47d5d9a 100644 --- a/tests/regression/74-loop_termination/23-exit-on-rand-terminating.c +++ b/tests/regression/74-loop_termination/23-exit-on-rand-terminating.c @@ -1,4 +1,4 @@ -// TODO TERM PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra +// TERM PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra #include #include diff --git a/tests/regression/74-loop_termination/24-upjumping-goto-loopless-terminating.c b/tests/regression/74-loop_termination/24-upjumping-goto-loopless-terminating.c index 3c4fffdc8a..e5c4f10f0d 100644 --- a/tests/regression/74-loop_termination/24-upjumping-goto-loopless-terminating.c +++ b/tests/regression/74-loop_termination/24-upjumping-goto-loopless-terminating.c @@ -1,4 +1,4 @@ -// TODO TERM PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra +// TERM PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra #include int main() { diff --git a/tests/regression/74-loop_termination/25-leave-loop-goto-terminating.c b/tests/regression/74-loop_termination/25-leave-loop-goto-terminating.c index 380e98ded0..ea353eb466 100644 --- a/tests/regression/74-loop_termination/25-leave-loop-goto-terminating.c +++ b/tests/regression/74-loop_termination/25-leave-loop-goto-terminating.c @@ -1,4 +1,4 @@ -// TODO TERM PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra +// TERM PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra #include int main() { diff --git a/tests/regression/74-loop_termination/26-enter-loop-goto-terminating.c b/tests/regression/74-loop_termination/26-enter-loop-goto-terminating.c index b676ca6985..8c2f3da4a2 100644 --- a/tests/regression/74-loop_termination/26-enter-loop-goto-terminating.c +++ b/tests/regression/74-loop_termination/26-enter-loop-goto-terminating.c @@ -1,4 +1,4 @@ -// TODO TERM PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra +// TERM PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra #include int main() { diff --git a/tests/regression/74-loop_termination/28-do-while-continue-terminating.c b/tests/regression/74-loop_termination/28-do-while-continue-terminating.c index aa215a502a..7f91ecc149 100644 --- a/tests/regression/74-loop_termination/28-do-while-continue-terminating.c +++ b/tests/regression/74-loop_termination/28-do-while-continue-terminating.c @@ -1,4 +1,4 @@ -// TODO TERM PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra +// TERM PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra #include int main() diff --git a/tests/regression/74-loop_termination/30-goto-out-of-inner-loop-terminating.c b/tests/regression/74-loop_termination/30-goto-out-of-inner-loop-terminating.c index 0526e20bb4..45cadb583f 100644 --- a/tests/regression/74-loop_termination/30-goto-out-of-inner-loop-terminating.c +++ b/tests/regression/74-loop_termination/30-goto-out-of-inner-loop-terminating.c @@ -1,4 +1,4 @@ -// TODO TERM PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra +// TERM PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra #include int main() { diff --git a/tests/regression/75-recursion_termination/02-simple-nonterminating.c b/tests/regression/75-recursion_termination/02-simple-nonterminating.c index 0dc3cbcf63..26f30e726b 100644 --- a/tests/regression/75-recursion_termination/02-simple-nonterminating.c +++ b/tests/regression/75-recursion_termination/02-simple-nonterminating.c @@ -1,4 +1,4 @@ -// NONTERM PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra +// SKIP NONTERM PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra #include void recursiveFunction(int n) { diff --git a/tests/regression/75-recursion_termination/04-nested-nonterminating.c b/tests/regression/75-recursion_termination/04-nested-nonterminating.c index 5299544a70..2d3239f371 100644 --- a/tests/regression/75-recursion_termination/04-nested-nonterminating.c +++ b/tests/regression/75-recursion_termination/04-nested-nonterminating.c @@ -1,4 +1,4 @@ -// SKIP NONTERM PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra +// NONTERM PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra #include void innerRecursiveFunction() { From 91f18efe32ca4f7ddc4c163d156b715e4e56685b Mon Sep 17 00:00:00 2001 From: Thomas Lagemann Date: Thu, 29 Jun 2023 14:26:45 +0200 Subject: [PATCH 172/327] Adapted tests to current state --- tests/regression/74-loop_termination/17-goto-terminating.c | 4 ++-- .../74-loop_termination/23-exit-on-rand-terminating.c | 4 ++-- .../24-upjumping-goto-loopless-terminating.c | 4 ++-- .../74-loop_termination/25-leave-loop-goto-terminating.c | 4 ++-- .../74-loop_termination/26-enter-loop-goto-terminating.c | 4 ++-- .../30-goto-out-of-inner-loop-terminating.c | 4 ++-- 6 files changed, 12 insertions(+), 12 deletions(-) diff --git a/tests/regression/74-loop_termination/17-goto-terminating.c b/tests/regression/74-loop_termination/17-goto-terminating.c index 1e4c1e719e..c4ba717784 100644 --- a/tests/regression/74-loop_termination/17-goto-terminating.c +++ b/tests/regression/74-loop_termination/17-goto-terminating.c @@ -1,4 +1,4 @@ -// TERM PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra +// TODO TERM PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra #include int main() @@ -11,7 +11,7 @@ int main() if (num <= 10) { - goto loop; + goto loop; // We are not able to detect up-jumping gotos as terminating, we just warn about them might being nonterminating. } return 0; diff --git a/tests/regression/74-loop_termination/23-exit-on-rand-terminating.c b/tests/regression/74-loop_termination/23-exit-on-rand-terminating.c index 94e47d5d9a..226f46b16e 100644 --- a/tests/regression/74-loop_termination/23-exit-on-rand-terminating.c +++ b/tests/regression/74-loop_termination/23-exit-on-rand-terminating.c @@ -1,4 +1,4 @@ -// TERM PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra +// TODO TERM PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra #include #include @@ -6,7 +6,7 @@ int main() { int short_run, i = 0; - while (i < 90 && short_run != 1) + while (i < 90 && short_run != 1) // Currently not able to detect this as terminating { i++; if (rand()) diff --git a/tests/regression/74-loop_termination/24-upjumping-goto-loopless-terminating.c b/tests/regression/74-loop_termination/24-upjumping-goto-loopless-terminating.c index e5c4f10f0d..e256df9986 100644 --- a/tests/regression/74-loop_termination/24-upjumping-goto-loopless-terminating.c +++ b/tests/regression/74-loop_termination/24-upjumping-goto-loopless-terminating.c @@ -1,7 +1,7 @@ -// TERM PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra +// TODO TERM PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra #include -int main() { +int main() { // Currently not able to detect this as terminating goto mark2; mark1: diff --git a/tests/regression/74-loop_termination/25-leave-loop-goto-terminating.c b/tests/regression/74-loop_termination/25-leave-loop-goto-terminating.c index ea353eb466..cbbb115868 100644 --- a/tests/regression/74-loop_termination/25-leave-loop-goto-terminating.c +++ b/tests/regression/74-loop_termination/25-leave-loop-goto-terminating.c @@ -1,4 +1,4 @@ -// TERM PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra +// TODO TERM PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra #include int main() { @@ -13,7 +13,7 @@ int main() { printf("Result: %d\n", result); // Condition to terminate the loop - if (result >= 10) { + if (result >= 10) { // Apron is not able to detect this goto end; } } diff --git a/tests/regression/74-loop_termination/26-enter-loop-goto-terminating.c b/tests/regression/74-loop_termination/26-enter-loop-goto-terminating.c index 8c2f3da4a2..17220a589b 100644 --- a/tests/regression/74-loop_termination/26-enter-loop-goto-terminating.c +++ b/tests/regression/74-loop_termination/26-enter-loop-goto-terminating.c @@ -1,4 +1,4 @@ -// TERM PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra +// TODO TERM PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra #include int main() { @@ -16,7 +16,7 @@ int main() { printf("Result: %d\n", result); // Condition to terminate the loop - if (result >= 10) { + if (result >= 10) { // Apron is not able to detect this goto end; } } diff --git a/tests/regression/74-loop_termination/30-goto-out-of-inner-loop-terminating.c b/tests/regression/74-loop_termination/30-goto-out-of-inner-loop-terminating.c index 45cadb583f..6b36919c2d 100644 --- a/tests/regression/74-loop_termination/30-goto-out-of-inner-loop-terminating.c +++ b/tests/regression/74-loop_termination/30-goto-out-of-inner-loop-terminating.c @@ -1,4 +1,4 @@ -// TERM PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra +// TODO TERM PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra #include int main() { @@ -9,7 +9,7 @@ int main() { for (int i = 1; i <= rows; i++) { // Inner loop for columns for (int j = 1; j <= columns; j++) { - if (j == 3) { + if (j == 3) { // Apron is not able to detect this goto outer_loop; // Jump to the label "outer_loop" } printf("(%d, %d) ", i, j); From 1c430398152499f9b7450100c563c2295a4f61e3 Mon Sep 17 00:00:00 2001 From: Thomas Lagemann Date: Thu, 29 Jun 2023 14:32:01 +0200 Subject: [PATCH 173/327] Adapted tests to current state --- .../74-loop_termination/25-leave-loop-goto-terminating.c | 2 +- .../74-loop_termination/26-enter-loop-goto-terminating.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/regression/74-loop_termination/25-leave-loop-goto-terminating.c b/tests/regression/74-loop_termination/25-leave-loop-goto-terminating.c index cbbb115868..ce11a73060 100644 --- a/tests/regression/74-loop_termination/25-leave-loop-goto-terminating.c +++ b/tests/regression/74-loop_termination/25-leave-loop-goto-terminating.c @@ -1,4 +1,4 @@ -// TODO TERM PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra +// TODO TERM PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain octagon #include int main() { diff --git a/tests/regression/74-loop_termination/26-enter-loop-goto-terminating.c b/tests/regression/74-loop_termination/26-enter-loop-goto-terminating.c index 17220a589b..355c1ebf00 100644 --- a/tests/regression/74-loop_termination/26-enter-loop-goto-terminating.c +++ b/tests/regression/74-loop_termination/26-enter-loop-goto-terminating.c @@ -1,4 +1,4 @@ -// TODO TERM PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra +// TERM PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra #include int main() { From c890d5b3cb9649a0a46eb505bbe56178f15f8aaf Mon Sep 17 00:00:00 2001 From: Thomas Lagemann Date: Thu, 29 Jun 2023 12:24:33 +0200 Subject: [PATCH 174/327] No skipping --- .../regression/80-termination/09-complex-for-loop-terminating.c | 2 +- tests/regression/80-termination/10-complex-loop-terminating.c | 2 +- .../80-termination/15-complex-loop-combination-terminating.c | 2 +- tests/regression/81-recursion/02-simple-nonterminating.c | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/tests/regression/80-termination/09-complex-for-loop-terminating.c b/tests/regression/80-termination/09-complex-for-loop-terminating.c index 8951924c06..7fcd5c5eba 100644 --- a/tests/regression/80-termination/09-complex-for-loop-terminating.c +++ b/tests/regression/80-termination/09-complex-for-loop-terminating.c @@ -1,4 +1,4 @@ -// SKIP LOCAL_TERM PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra +// LOCAL_TERM PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra #include int main() diff --git a/tests/regression/80-termination/10-complex-loop-terminating.c b/tests/regression/80-termination/10-complex-loop-terminating.c index dbce2a6b5b..def1786937 100644 --- a/tests/regression/80-termination/10-complex-loop-terminating.c +++ b/tests/regression/80-termination/10-complex-loop-terminating.c @@ -1,4 +1,4 @@ -// SKIP LOCAL_TERM PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra +// LOCAL_TERM PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra #include int main() diff --git a/tests/regression/80-termination/15-complex-loop-combination-terminating.c b/tests/regression/80-termination/15-complex-loop-combination-terminating.c index 7daa9b98fe..9ab04745e8 100644 --- a/tests/regression/80-termination/15-complex-loop-combination-terminating.c +++ b/tests/regression/80-termination/15-complex-loop-combination-terminating.c @@ -1,4 +1,4 @@ -// SKIP LOCAL_TERM PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval +// LOCAL_TERM PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval #include int main() diff --git a/tests/regression/81-recursion/02-simple-nonterminating.c b/tests/regression/81-recursion/02-simple-nonterminating.c index c7902e2e7f..37c4bbd801 100644 --- a/tests/regression/81-recursion/02-simple-nonterminating.c +++ b/tests/regression/81-recursion/02-simple-nonterminating.c @@ -1,4 +1,4 @@ -// SKIP NON_LOCAL_TERM PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra +// NON_LOCAL_TERM PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra #include void recursiveFunction(int n) { From 569fefdc111e23eb159b51076e36de9c0be794e6 Mon Sep 17 00:00:00 2001 From: Thomas Lagemann Date: Thu, 29 Jun 2023 12:31:36 +0200 Subject: [PATCH 175/327] New non terminating for loop --- .../34-nested-for-loop-nonterminating.c | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) create mode 100644 tests/regression/80-termination/34-nested-for-loop-nonterminating.c diff --git a/tests/regression/80-termination/34-nested-for-loop-nonterminating.c b/tests/regression/80-termination/34-nested-for-loop-nonterminating.c new file mode 100644 index 0000000000..1f68f3c0a5 --- /dev/null +++ b/tests/regression/80-termination/34-nested-for-loop-nonterminating.c @@ -0,0 +1,19 @@ +// TODO NON_LOCAL_TERM PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra +#include + +int main() +{ + int outerCount, innerCount; + + for (outerCount = 1; outerCount <= 3; outerCount++) + { + for (innerCount = 1; innerCount > 0; innerCount++) + { + printf("(%d, %d) ", outerCount, innerCount); + } + + printf("\n"); + } + + return 0; +} From aca1ec58c0a8cab65883b19ad963fdad6826b927 Mon Sep 17 00:00:00 2001 From: Thomas Lagemann Date: Thu, 29 Jun 2023 12:34:13 +0200 Subject: [PATCH 176/327] Folder Renaming --- .../01-simple-loop-terminating.c | 0 .../02-simple-loop-nonterminating.c | 0 .../03-nested-loop-terminating.c | 0 .../04-nested-loop-nonterminating.c | 0 .../05-for-loop-terminating.c | 0 .../06-for-loop-nonterminating.c | 0 .../07-nested-for-loop-terminating.c | 0 .../08-nested-for-loop-nonterminating.c | 0 .../09-complex-for-loop-terminating.c | 0 .../10-complex-loop-terminating.c | 0 .../11-loopless-termination.c | 0 .../12-do-while-instant-terminating.c | 0 .../13-do-while-terminating.c | 0 .../14-do-while-nonterminating.c | 0 .../15-complex-loop-combination-terminating.c | 0 .../16-nested-loop-nontrivial-nonterminating.c | 0 .../{80-termination => 74-loop_termination}/17-goto-terminating.c | 0 .../18-goto-nonterminating.c | 0 .../{80-termination => 74-loop_termination}/19-rand-terminating.c | 0 .../20-rand-nonterminating.c | 0 .../21-no-exit-on-rand-unproofable.c | 0 .../22-exit-on-rand-unproofable.c | 0 .../23-exit-on-rand-terminating.c | 0 .../24-upjumping-goto-loopless-terminating.c | 0 .../25-leave-loop-goto-terminating.c | 0 .../26-enter-loop-goto-terminating.c | 0 .../27-upjumping-goto-nonterminating.c | 0 .../28-do-while-continue-terminating.c | 0 .../29-do-while-continue-nonterminating.c | 0 .../30-goto-out-of-inner-loop-terminating.c | 0 .../31-goto-out-of-inner-loop-nonterminating.c | 0 .../32-multithread-terminating.c | 0 .../33-multithread-nonterminating.c | 0 .../34-nested-for-loop-nonterminating.c | 0 .../01-simple-terminating.c | 0 .../02-simple-nonterminating.c | 0 .../03-nested-terminating.c | 0 .../04-nested-nonterminating.c | 0 38 files changed, 0 insertions(+), 0 deletions(-) rename tests/regression/{80-termination => 74-loop_termination}/01-simple-loop-terminating.c (100%) rename tests/regression/{80-termination => 74-loop_termination}/02-simple-loop-nonterminating.c (100%) rename tests/regression/{80-termination => 74-loop_termination}/03-nested-loop-terminating.c (100%) rename tests/regression/{80-termination => 74-loop_termination}/04-nested-loop-nonterminating.c (100%) rename tests/regression/{80-termination => 74-loop_termination}/05-for-loop-terminating.c (100%) rename tests/regression/{80-termination => 74-loop_termination}/06-for-loop-nonterminating.c (100%) rename tests/regression/{80-termination => 74-loop_termination}/07-nested-for-loop-terminating.c (100%) rename tests/regression/{80-termination => 74-loop_termination}/08-nested-for-loop-nonterminating.c (100%) rename tests/regression/{80-termination => 74-loop_termination}/09-complex-for-loop-terminating.c (100%) rename tests/regression/{80-termination => 74-loop_termination}/10-complex-loop-terminating.c (100%) rename tests/regression/{80-termination => 74-loop_termination}/11-loopless-termination.c (100%) rename tests/regression/{80-termination => 74-loop_termination}/12-do-while-instant-terminating.c (100%) rename tests/regression/{80-termination => 74-loop_termination}/13-do-while-terminating.c (100%) rename tests/regression/{80-termination => 74-loop_termination}/14-do-while-nonterminating.c (100%) rename tests/regression/{80-termination => 74-loop_termination}/15-complex-loop-combination-terminating.c (100%) rename tests/regression/{80-termination => 74-loop_termination}/16-nested-loop-nontrivial-nonterminating.c (100%) rename tests/regression/{80-termination => 74-loop_termination}/17-goto-terminating.c (100%) rename tests/regression/{80-termination => 74-loop_termination}/18-goto-nonterminating.c (100%) rename tests/regression/{80-termination => 74-loop_termination}/19-rand-terminating.c (100%) rename tests/regression/{80-termination => 74-loop_termination}/20-rand-nonterminating.c (100%) rename tests/regression/{80-termination => 74-loop_termination}/21-no-exit-on-rand-unproofable.c (100%) rename tests/regression/{80-termination => 74-loop_termination}/22-exit-on-rand-unproofable.c (100%) rename tests/regression/{80-termination => 74-loop_termination}/23-exit-on-rand-terminating.c (100%) rename tests/regression/{80-termination => 74-loop_termination}/24-upjumping-goto-loopless-terminating.c (100%) rename tests/regression/{80-termination => 74-loop_termination}/25-leave-loop-goto-terminating.c (100%) rename tests/regression/{80-termination => 74-loop_termination}/26-enter-loop-goto-terminating.c (100%) rename tests/regression/{80-termination => 74-loop_termination}/27-upjumping-goto-nonterminating.c (100%) rename tests/regression/{80-termination => 74-loop_termination}/28-do-while-continue-terminating.c (100%) rename tests/regression/{80-termination => 74-loop_termination}/29-do-while-continue-nonterminating.c (100%) rename tests/regression/{80-termination => 74-loop_termination}/30-goto-out-of-inner-loop-terminating.c (100%) rename tests/regression/{80-termination => 74-loop_termination}/31-goto-out-of-inner-loop-nonterminating.c (100%) rename tests/regression/{80-termination => 74-loop_termination}/32-multithread-terminating.c (100%) rename tests/regression/{80-termination => 74-loop_termination}/33-multithread-nonterminating.c (100%) rename tests/regression/{80-termination => 74-loop_termination}/34-nested-for-loop-nonterminating.c (100%) rename tests/regression/{81-recursion => 75-recursion_termination}/01-simple-terminating.c (100%) rename tests/regression/{81-recursion => 75-recursion_termination}/02-simple-nonterminating.c (100%) rename tests/regression/{81-recursion => 75-recursion_termination}/03-nested-terminating.c (100%) rename tests/regression/{81-recursion => 75-recursion_termination}/04-nested-nonterminating.c (100%) diff --git a/tests/regression/80-termination/01-simple-loop-terminating.c b/tests/regression/74-loop_termination/01-simple-loop-terminating.c similarity index 100% rename from tests/regression/80-termination/01-simple-loop-terminating.c rename to tests/regression/74-loop_termination/01-simple-loop-terminating.c diff --git a/tests/regression/80-termination/02-simple-loop-nonterminating.c b/tests/regression/74-loop_termination/02-simple-loop-nonterminating.c similarity index 100% rename from tests/regression/80-termination/02-simple-loop-nonterminating.c rename to tests/regression/74-loop_termination/02-simple-loop-nonterminating.c diff --git a/tests/regression/80-termination/03-nested-loop-terminating.c b/tests/regression/74-loop_termination/03-nested-loop-terminating.c similarity index 100% rename from tests/regression/80-termination/03-nested-loop-terminating.c rename to tests/regression/74-loop_termination/03-nested-loop-terminating.c diff --git a/tests/regression/80-termination/04-nested-loop-nonterminating.c b/tests/regression/74-loop_termination/04-nested-loop-nonterminating.c similarity index 100% rename from tests/regression/80-termination/04-nested-loop-nonterminating.c rename to tests/regression/74-loop_termination/04-nested-loop-nonterminating.c diff --git a/tests/regression/80-termination/05-for-loop-terminating.c b/tests/regression/74-loop_termination/05-for-loop-terminating.c similarity index 100% rename from tests/regression/80-termination/05-for-loop-terminating.c rename to tests/regression/74-loop_termination/05-for-loop-terminating.c diff --git a/tests/regression/80-termination/06-for-loop-nonterminating.c b/tests/regression/74-loop_termination/06-for-loop-nonterminating.c similarity index 100% rename from tests/regression/80-termination/06-for-loop-nonterminating.c rename to tests/regression/74-loop_termination/06-for-loop-nonterminating.c diff --git a/tests/regression/80-termination/07-nested-for-loop-terminating.c b/tests/regression/74-loop_termination/07-nested-for-loop-terminating.c similarity index 100% rename from tests/regression/80-termination/07-nested-for-loop-terminating.c rename to tests/regression/74-loop_termination/07-nested-for-loop-terminating.c diff --git a/tests/regression/80-termination/08-nested-for-loop-nonterminating.c b/tests/regression/74-loop_termination/08-nested-for-loop-nonterminating.c similarity index 100% rename from tests/regression/80-termination/08-nested-for-loop-nonterminating.c rename to tests/regression/74-loop_termination/08-nested-for-loop-nonterminating.c diff --git a/tests/regression/80-termination/09-complex-for-loop-terminating.c b/tests/regression/74-loop_termination/09-complex-for-loop-terminating.c similarity index 100% rename from tests/regression/80-termination/09-complex-for-loop-terminating.c rename to tests/regression/74-loop_termination/09-complex-for-loop-terminating.c diff --git a/tests/regression/80-termination/10-complex-loop-terminating.c b/tests/regression/74-loop_termination/10-complex-loop-terminating.c similarity index 100% rename from tests/regression/80-termination/10-complex-loop-terminating.c rename to tests/regression/74-loop_termination/10-complex-loop-terminating.c diff --git a/tests/regression/80-termination/11-loopless-termination.c b/tests/regression/74-loop_termination/11-loopless-termination.c similarity index 100% rename from tests/regression/80-termination/11-loopless-termination.c rename to tests/regression/74-loop_termination/11-loopless-termination.c diff --git a/tests/regression/80-termination/12-do-while-instant-terminating.c b/tests/regression/74-loop_termination/12-do-while-instant-terminating.c similarity index 100% rename from tests/regression/80-termination/12-do-while-instant-terminating.c rename to tests/regression/74-loop_termination/12-do-while-instant-terminating.c diff --git a/tests/regression/80-termination/13-do-while-terminating.c b/tests/regression/74-loop_termination/13-do-while-terminating.c similarity index 100% rename from tests/regression/80-termination/13-do-while-terminating.c rename to tests/regression/74-loop_termination/13-do-while-terminating.c diff --git a/tests/regression/80-termination/14-do-while-nonterminating.c b/tests/regression/74-loop_termination/14-do-while-nonterminating.c similarity index 100% rename from tests/regression/80-termination/14-do-while-nonterminating.c rename to tests/regression/74-loop_termination/14-do-while-nonterminating.c diff --git a/tests/regression/80-termination/15-complex-loop-combination-terminating.c b/tests/regression/74-loop_termination/15-complex-loop-combination-terminating.c similarity index 100% rename from tests/regression/80-termination/15-complex-loop-combination-terminating.c rename to tests/regression/74-loop_termination/15-complex-loop-combination-terminating.c diff --git a/tests/regression/80-termination/16-nested-loop-nontrivial-nonterminating.c b/tests/regression/74-loop_termination/16-nested-loop-nontrivial-nonterminating.c similarity index 100% rename from tests/regression/80-termination/16-nested-loop-nontrivial-nonterminating.c rename to tests/regression/74-loop_termination/16-nested-loop-nontrivial-nonterminating.c diff --git a/tests/regression/80-termination/17-goto-terminating.c b/tests/regression/74-loop_termination/17-goto-terminating.c similarity index 100% rename from tests/regression/80-termination/17-goto-terminating.c rename to tests/regression/74-loop_termination/17-goto-terminating.c diff --git a/tests/regression/80-termination/18-goto-nonterminating.c b/tests/regression/74-loop_termination/18-goto-nonterminating.c similarity index 100% rename from tests/regression/80-termination/18-goto-nonterminating.c rename to tests/regression/74-loop_termination/18-goto-nonterminating.c diff --git a/tests/regression/80-termination/19-rand-terminating.c b/tests/regression/74-loop_termination/19-rand-terminating.c similarity index 100% rename from tests/regression/80-termination/19-rand-terminating.c rename to tests/regression/74-loop_termination/19-rand-terminating.c diff --git a/tests/regression/80-termination/20-rand-nonterminating.c b/tests/regression/74-loop_termination/20-rand-nonterminating.c similarity index 100% rename from tests/regression/80-termination/20-rand-nonterminating.c rename to tests/regression/74-loop_termination/20-rand-nonterminating.c diff --git a/tests/regression/80-termination/21-no-exit-on-rand-unproofable.c b/tests/regression/74-loop_termination/21-no-exit-on-rand-unproofable.c similarity index 100% rename from tests/regression/80-termination/21-no-exit-on-rand-unproofable.c rename to tests/regression/74-loop_termination/21-no-exit-on-rand-unproofable.c diff --git a/tests/regression/80-termination/22-exit-on-rand-unproofable.c b/tests/regression/74-loop_termination/22-exit-on-rand-unproofable.c similarity index 100% rename from tests/regression/80-termination/22-exit-on-rand-unproofable.c rename to tests/regression/74-loop_termination/22-exit-on-rand-unproofable.c diff --git a/tests/regression/80-termination/23-exit-on-rand-terminating.c b/tests/regression/74-loop_termination/23-exit-on-rand-terminating.c similarity index 100% rename from tests/regression/80-termination/23-exit-on-rand-terminating.c rename to tests/regression/74-loop_termination/23-exit-on-rand-terminating.c diff --git a/tests/regression/80-termination/24-upjumping-goto-loopless-terminating.c b/tests/regression/74-loop_termination/24-upjumping-goto-loopless-terminating.c similarity index 100% rename from tests/regression/80-termination/24-upjumping-goto-loopless-terminating.c rename to tests/regression/74-loop_termination/24-upjumping-goto-loopless-terminating.c diff --git a/tests/regression/80-termination/25-leave-loop-goto-terminating.c b/tests/regression/74-loop_termination/25-leave-loop-goto-terminating.c similarity index 100% rename from tests/regression/80-termination/25-leave-loop-goto-terminating.c rename to tests/regression/74-loop_termination/25-leave-loop-goto-terminating.c diff --git a/tests/regression/80-termination/26-enter-loop-goto-terminating.c b/tests/regression/74-loop_termination/26-enter-loop-goto-terminating.c similarity index 100% rename from tests/regression/80-termination/26-enter-loop-goto-terminating.c rename to tests/regression/74-loop_termination/26-enter-loop-goto-terminating.c diff --git a/tests/regression/80-termination/27-upjumping-goto-nonterminating.c b/tests/regression/74-loop_termination/27-upjumping-goto-nonterminating.c similarity index 100% rename from tests/regression/80-termination/27-upjumping-goto-nonterminating.c rename to tests/regression/74-loop_termination/27-upjumping-goto-nonterminating.c diff --git a/tests/regression/80-termination/28-do-while-continue-terminating.c b/tests/regression/74-loop_termination/28-do-while-continue-terminating.c similarity index 100% rename from tests/regression/80-termination/28-do-while-continue-terminating.c rename to tests/regression/74-loop_termination/28-do-while-continue-terminating.c diff --git a/tests/regression/80-termination/29-do-while-continue-nonterminating.c b/tests/regression/74-loop_termination/29-do-while-continue-nonterminating.c similarity index 100% rename from tests/regression/80-termination/29-do-while-continue-nonterminating.c rename to tests/regression/74-loop_termination/29-do-while-continue-nonterminating.c diff --git a/tests/regression/80-termination/30-goto-out-of-inner-loop-terminating.c b/tests/regression/74-loop_termination/30-goto-out-of-inner-loop-terminating.c similarity index 100% rename from tests/regression/80-termination/30-goto-out-of-inner-loop-terminating.c rename to tests/regression/74-loop_termination/30-goto-out-of-inner-loop-terminating.c diff --git a/tests/regression/80-termination/31-goto-out-of-inner-loop-nonterminating.c b/tests/regression/74-loop_termination/31-goto-out-of-inner-loop-nonterminating.c similarity index 100% rename from tests/regression/80-termination/31-goto-out-of-inner-loop-nonterminating.c rename to tests/regression/74-loop_termination/31-goto-out-of-inner-loop-nonterminating.c diff --git a/tests/regression/80-termination/32-multithread-terminating.c b/tests/regression/74-loop_termination/32-multithread-terminating.c similarity index 100% rename from tests/regression/80-termination/32-multithread-terminating.c rename to tests/regression/74-loop_termination/32-multithread-terminating.c diff --git a/tests/regression/80-termination/33-multithread-nonterminating.c b/tests/regression/74-loop_termination/33-multithread-nonterminating.c similarity index 100% rename from tests/regression/80-termination/33-multithread-nonterminating.c rename to tests/regression/74-loop_termination/33-multithread-nonterminating.c diff --git a/tests/regression/80-termination/34-nested-for-loop-nonterminating.c b/tests/regression/74-loop_termination/34-nested-for-loop-nonterminating.c similarity index 100% rename from tests/regression/80-termination/34-nested-for-loop-nonterminating.c rename to tests/regression/74-loop_termination/34-nested-for-loop-nonterminating.c diff --git a/tests/regression/81-recursion/01-simple-terminating.c b/tests/regression/75-recursion_termination/01-simple-terminating.c similarity index 100% rename from tests/regression/81-recursion/01-simple-terminating.c rename to tests/regression/75-recursion_termination/01-simple-terminating.c diff --git a/tests/regression/81-recursion/02-simple-nonterminating.c b/tests/regression/75-recursion_termination/02-simple-nonterminating.c similarity index 100% rename from tests/regression/81-recursion/02-simple-nonterminating.c rename to tests/regression/75-recursion_termination/02-simple-nonterminating.c diff --git a/tests/regression/81-recursion/03-nested-terminating.c b/tests/regression/75-recursion_termination/03-nested-terminating.c similarity index 100% rename from tests/regression/81-recursion/03-nested-terminating.c rename to tests/regression/75-recursion_termination/03-nested-terminating.c diff --git a/tests/regression/81-recursion/04-nested-nonterminating.c b/tests/regression/75-recursion_termination/04-nested-nonterminating.c similarity index 100% rename from tests/regression/81-recursion/04-nested-nonterminating.c rename to tests/regression/75-recursion_termination/04-nested-nonterminating.c From 70bad4c386e3c7bbaa45ff3aec86e618901fd063 Mon Sep 17 00:00:00 2001 From: Thomas Lagemann Date: Thu, 29 Jun 2023 12:49:43 +0200 Subject: [PATCH 177/327] Enable polyhedra; Removed unnecessary TODOs --- .../15-complex-loop-combination-terminating.c | 2 +- .../74-loop_termination/34-nested-for-loop-nonterminating.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/regression/74-loop_termination/15-complex-loop-combination-terminating.c b/tests/regression/74-loop_termination/15-complex-loop-combination-terminating.c index 9ab04745e8..ec6b50512e 100644 --- a/tests/regression/74-loop_termination/15-complex-loop-combination-terminating.c +++ b/tests/regression/74-loop_termination/15-complex-loop-combination-terminating.c @@ -1,4 +1,4 @@ -// LOCAL_TERM PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval +// LOCAL_TERM PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra #include int main() diff --git a/tests/regression/74-loop_termination/34-nested-for-loop-nonterminating.c b/tests/regression/74-loop_termination/34-nested-for-loop-nonterminating.c index 1f68f3c0a5..d8aa9d487d 100644 --- a/tests/regression/74-loop_termination/34-nested-for-loop-nonterminating.c +++ b/tests/regression/74-loop_termination/34-nested-for-loop-nonterminating.c @@ -1,4 +1,4 @@ -// TODO NON_LOCAL_TERM PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra +// NON_LOCAL_TERM PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra #include int main() From e70761c567064f43ebdd1b36bf13e34621a4d50f Mon Sep 17 00:00:00 2001 From: Thomas Lagemann Date: Thu, 29 Jun 2023 13:04:25 +0200 Subject: [PATCH 178/327] Removed unnecessary TODOs --- .../regression/74-loop_termination/06-for-loop-nonterminating.c | 2 +- .../74-loop_termination/08-nested-for-loop-nonterminating.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/regression/74-loop_termination/06-for-loop-nonterminating.c b/tests/regression/74-loop_termination/06-for-loop-nonterminating.c index 73a8b8c6fd..b8f30361d1 100644 --- a/tests/regression/74-loop_termination/06-for-loop-nonterminating.c +++ b/tests/regression/74-loop_termination/06-for-loop-nonterminating.c @@ -1,4 +1,4 @@ -// TODO NON_LOCAL_TERM PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra +// NON_LOCAL_TERM PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra #include int main() { diff --git a/tests/regression/74-loop_termination/08-nested-for-loop-nonterminating.c b/tests/regression/74-loop_termination/08-nested-for-loop-nonterminating.c index 8b451e56dd..0368120b13 100644 --- a/tests/regression/74-loop_termination/08-nested-for-loop-nonterminating.c +++ b/tests/regression/74-loop_termination/08-nested-for-loop-nonterminating.c @@ -1,4 +1,4 @@ -// TODO NON_LOCAL_TERM PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra +// NON_LOCAL_TERM PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra #include int main() From ee9392942d4df2d43cfab49e4002394b2d42fd33 Mon Sep 17 00:00:00 2001 From: Thomas Lagemann Date: Thu, 29 Jun 2023 13:17:23 +0200 Subject: [PATCH 179/327] Renamed LOCAL_TERM to TERM --- scripts/update_suite.rb | 26 +++++++++---------- .../01-simple-loop-terminating.c | 2 +- .../02-simple-loop-nonterminating.c | 2 +- .../03-nested-loop-terminating.c | 2 +- .../04-nested-loop-nonterminating.c | 2 +- .../05-for-loop-terminating.c | 2 +- .../06-for-loop-nonterminating.c | 2 +- .../07-nested-for-loop-terminating.c | 2 +- .../08-nested-for-loop-nonterminating.c | 2 +- .../09-complex-for-loop-terminating.c | 2 +- .../10-complex-loop-terminating.c | 2 +- .../11-loopless-termination.c | 2 +- .../12-do-while-instant-terminating.c | 2 +- .../13-do-while-terminating.c | 2 +- .../14-do-while-nonterminating.c | 2 +- .../15-complex-loop-combination-terminating.c | 2 +- ...16-nested-loop-nontrivial-nonterminating.c | 2 +- .../74-loop_termination/17-goto-terminating.c | 2 +- .../18-goto-nonterminating.c | 2 +- .../74-loop_termination/19-rand-terminating.c | 2 +- .../20-rand-nonterminating.c | 2 +- .../21-no-exit-on-rand-unproofable.c | 2 +- .../22-exit-on-rand-unproofable.c | 2 +- .../23-exit-on-rand-terminating.c | 2 +- .../24-upjumping-goto-loopless-terminating.c | 2 +- .../25-leave-loop-goto-terminating.c | 2 +- .../26-enter-loop-goto-terminating.c | 2 +- .../27-upjumping-goto-nonterminating.c | 2 +- .../28-do-while-continue-terminating.c | 2 +- .../29-do-while-continue-nonterminating.c | 2 +- .../30-goto-out-of-inner-loop-terminating.c | 2 +- ...31-goto-out-of-inner-loop-nonterminating.c | 2 +- .../32-multithread-terminating.c | 2 +- .../33-multithread-nonterminating.c | 2 +- .../34-nested-for-loop-nonterminating.c | 2 +- .../01-simple-terminating.c | 2 +- .../02-simple-nonterminating.c | 2 +- .../03-nested-terminating.c | 2 +- .../04-nested-nonterminating.c | 2 +- 39 files changed, 50 insertions(+), 52 deletions(-) diff --git a/scripts/update_suite.rb b/scripts/update_suite.rb index 98eff124af..8841ecea88 100755 --- a/scripts/update_suite.rb +++ b/scripts/update_suite.rb @@ -145,11 +145,11 @@ def collect_warnings @vars = $1 @evals = $2 end - if l =~ /\[NonTerminating\]/ then warnings[-1] = "non_local_term" end # Get NonTerminating warning + if l =~ /\[NonTerminating\]/ then warnings[-1] = "nonterm" end # Get NonTerminating warning next unless l =~ /(.*)\(.*?\:(\d+)(?:\:\d+)?(?:-(?:\d+)(?:\:\d+)?)?\)/ obj,i = $1,$2.to_i - ranking = ["other", "warn", "local_term", "non_local_term", "race", "norace", "deadlock", "nodeadlock", "success", "fail", "unknown"] + ranking = ["other", "warn", "term", "nonterm", "race", "norace", "deadlock", "nodeadlock", "success", "fail", "unknown"] thiswarn = case obj when /\(conf\. \d+\)/ then "race" when /Deadlock/ then "deadlock" @@ -208,9 +208,9 @@ def compare_warnings case type when "deadlock", "race", "fail", "unknown", "warn" check.call warnings[idx] == type - when "non_local_term" + when "nonterm" check.call warnings[idx] == type - when "nowarn", "local_term" + when "nowarn", "term" check.call warnings[idx].nil? when "assert", "success" check.call warnings[idx] == "success" @@ -324,19 +324,17 @@ def parse_tests (lines) case lines[0] when /TODO|SKIP/ case lines[0] - when /NON_LOCAL_TERM/ - tests[-1] = "non_local_term" + when /NONTERM/ + tests[-1] = "nonterm" todo << -1 - when /LOCAL_TERM/ - tests[-1] = "local_term" + when /TERM/ + tests[-1] = "term" todo << -1 end - when /NON_LOCAL_TERM/ - # covers "TERM" as keyword but a combined use of NON_LOCAL_TERM (loop termination) and TERM would be pointless - tests[-1] = "non_local_term" - when /LOCAL_TERM/ - # covers "TERM" as keyword but a combined use of NON_LOCAL_TERM (loop termination) and TERM would be pointless - tests[-1] = "local_term" + when /NONTERM/ + tests[-1] = "nonterm" + when /TERM/ + tests[-1] = "term" end Tests.new(self, tests, tests_line, todo) end diff --git a/tests/regression/74-loop_termination/01-simple-loop-terminating.c b/tests/regression/74-loop_termination/01-simple-loop-terminating.c index a517d0d608..a80084868a 100644 --- a/tests/regression/74-loop_termination/01-simple-loop-terminating.c +++ b/tests/regression/74-loop_termination/01-simple-loop-terminating.c @@ -1,4 +1,4 @@ -// LOCAL_TERM PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra +// TERM PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra #include int main() diff --git a/tests/regression/74-loop_termination/02-simple-loop-nonterminating.c b/tests/regression/74-loop_termination/02-simple-loop-nonterminating.c index bcb9909f80..eef9f81ea3 100644 --- a/tests/regression/74-loop_termination/02-simple-loop-nonterminating.c +++ b/tests/regression/74-loop_termination/02-simple-loop-nonterminating.c @@ -1,4 +1,4 @@ -// NON_LOCAL_TERM PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra +// NONTERM PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra #include int main() diff --git a/tests/regression/74-loop_termination/03-nested-loop-terminating.c b/tests/regression/74-loop_termination/03-nested-loop-terminating.c index 366cbaeea5..5e72ec3284 100644 --- a/tests/regression/74-loop_termination/03-nested-loop-terminating.c +++ b/tests/regression/74-loop_termination/03-nested-loop-terminating.c @@ -1,4 +1,4 @@ -// LOCAL_TERM PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra +// TERM PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra #include int main() diff --git a/tests/regression/74-loop_termination/04-nested-loop-nonterminating.c b/tests/regression/74-loop_termination/04-nested-loop-nonterminating.c index ee2aa4a8c4..1fb5ada507 100644 --- a/tests/regression/74-loop_termination/04-nested-loop-nonterminating.c +++ b/tests/regression/74-loop_termination/04-nested-loop-nonterminating.c @@ -1,4 +1,4 @@ -// NON_LOCAL_TERM PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra +// NONTERM PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra #include int main() diff --git a/tests/regression/74-loop_termination/05-for-loop-terminating.c b/tests/regression/74-loop_termination/05-for-loop-terminating.c index 2a16184f6d..cf71fa5135 100644 --- a/tests/regression/74-loop_termination/05-for-loop-terminating.c +++ b/tests/regression/74-loop_termination/05-for-loop-terminating.c @@ -1,4 +1,4 @@ -// LOCAL_TERM PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra +// TERM PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra #include int main() diff --git a/tests/regression/74-loop_termination/06-for-loop-nonterminating.c b/tests/regression/74-loop_termination/06-for-loop-nonterminating.c index b8f30361d1..8c1500cfb1 100644 --- a/tests/regression/74-loop_termination/06-for-loop-nonterminating.c +++ b/tests/regression/74-loop_termination/06-for-loop-nonterminating.c @@ -1,4 +1,4 @@ -// NON_LOCAL_TERM PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra +// NONTERM PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra #include int main() { diff --git a/tests/regression/74-loop_termination/07-nested-for-loop-terminating.c b/tests/regression/74-loop_termination/07-nested-for-loop-terminating.c index def0787d39..4b3395bd11 100644 --- a/tests/regression/74-loop_termination/07-nested-for-loop-terminating.c +++ b/tests/regression/74-loop_termination/07-nested-for-loop-terminating.c @@ -1,4 +1,4 @@ -// LOCAL_TERM PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra +// TERM PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra #include int main() diff --git a/tests/regression/74-loop_termination/08-nested-for-loop-nonterminating.c b/tests/regression/74-loop_termination/08-nested-for-loop-nonterminating.c index 0368120b13..818146e456 100644 --- a/tests/regression/74-loop_termination/08-nested-for-loop-nonterminating.c +++ b/tests/regression/74-loop_termination/08-nested-for-loop-nonterminating.c @@ -1,4 +1,4 @@ -// NON_LOCAL_TERM PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra +// NONTERM PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra #include int main() diff --git a/tests/regression/74-loop_termination/09-complex-for-loop-terminating.c b/tests/regression/74-loop_termination/09-complex-for-loop-terminating.c index 7fcd5c5eba..c26fde710f 100644 --- a/tests/regression/74-loop_termination/09-complex-for-loop-terminating.c +++ b/tests/regression/74-loop_termination/09-complex-for-loop-terminating.c @@ -1,4 +1,4 @@ -// LOCAL_TERM PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra +// TERM PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra #include int main() diff --git a/tests/regression/74-loop_termination/10-complex-loop-terminating.c b/tests/regression/74-loop_termination/10-complex-loop-terminating.c index def1786937..017c10b8a4 100644 --- a/tests/regression/74-loop_termination/10-complex-loop-terminating.c +++ b/tests/regression/74-loop_termination/10-complex-loop-terminating.c @@ -1,4 +1,4 @@ -// LOCAL_TERM PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra +// TERM PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra #include int main() diff --git a/tests/regression/74-loop_termination/11-loopless-termination.c b/tests/regression/74-loop_termination/11-loopless-termination.c index 86a300f18e..01f9a953e0 100644 --- a/tests/regression/74-loop_termination/11-loopless-termination.c +++ b/tests/regression/74-loop_termination/11-loopless-termination.c @@ -1,4 +1,4 @@ -// LOCAL_TERM PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra +// TERM PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra #include int main() { diff --git a/tests/regression/74-loop_termination/12-do-while-instant-terminating.c b/tests/regression/74-loop_termination/12-do-while-instant-terminating.c index 15032b7b4f..b34dff3f5f 100644 --- a/tests/regression/74-loop_termination/12-do-while-instant-terminating.c +++ b/tests/regression/74-loop_termination/12-do-while-instant-terminating.c @@ -1,4 +1,4 @@ -// LOCAL_TERM PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra +// TERM PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra #include int main() diff --git a/tests/regression/74-loop_termination/13-do-while-terminating.c b/tests/regression/74-loop_termination/13-do-while-terminating.c index 2e04f3e393..651acb8fd8 100644 --- a/tests/regression/74-loop_termination/13-do-while-terminating.c +++ b/tests/regression/74-loop_termination/13-do-while-terminating.c @@ -1,4 +1,4 @@ -// LOCAL_TERM PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra +// TERM PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra #include int main() diff --git a/tests/regression/74-loop_termination/14-do-while-nonterminating.c b/tests/regression/74-loop_termination/14-do-while-nonterminating.c index 5ed18175e9..1e05e2be6e 100644 --- a/tests/regression/74-loop_termination/14-do-while-nonterminating.c +++ b/tests/regression/74-loop_termination/14-do-while-nonterminating.c @@ -1,4 +1,4 @@ -// NON_LOCAL_TERM PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra +// NONTERM PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra #include int main() diff --git a/tests/regression/74-loop_termination/15-complex-loop-combination-terminating.c b/tests/regression/74-loop_termination/15-complex-loop-combination-terminating.c index ec6b50512e..07fbe38cfd 100644 --- a/tests/regression/74-loop_termination/15-complex-loop-combination-terminating.c +++ b/tests/regression/74-loop_termination/15-complex-loop-combination-terminating.c @@ -1,4 +1,4 @@ -// LOCAL_TERM PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra +// TERM PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra #include int main() diff --git a/tests/regression/74-loop_termination/16-nested-loop-nontrivial-nonterminating.c b/tests/regression/74-loop_termination/16-nested-loop-nontrivial-nonterminating.c index 5ff890e461..b9ccea76af 100644 --- a/tests/regression/74-loop_termination/16-nested-loop-nontrivial-nonterminating.c +++ b/tests/regression/74-loop_termination/16-nested-loop-nontrivial-nonterminating.c @@ -1,4 +1,4 @@ -// NON_LOCAL_TERM PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra +// NONTERM PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra #include int main() diff --git a/tests/regression/74-loop_termination/17-goto-terminating.c b/tests/regression/74-loop_termination/17-goto-terminating.c index e988926359..b11b5b3da9 100644 --- a/tests/regression/74-loop_termination/17-goto-terminating.c +++ b/tests/regression/74-loop_termination/17-goto-terminating.c @@ -1,4 +1,4 @@ -// TODO LOCAL_TERM PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra +// TODO TERM PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra #include int main() diff --git a/tests/regression/74-loop_termination/18-goto-nonterminating.c b/tests/regression/74-loop_termination/18-goto-nonterminating.c index cfe5ab481d..aab37803aa 100644 --- a/tests/regression/74-loop_termination/18-goto-nonterminating.c +++ b/tests/regression/74-loop_termination/18-goto-nonterminating.c @@ -1,4 +1,4 @@ -// NON_LOCAL_TERM PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra +// NONTERM PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra #include int main() diff --git a/tests/regression/74-loop_termination/19-rand-terminating.c b/tests/regression/74-loop_termination/19-rand-terminating.c index 426c5cdcca..5d3cde9f3d 100644 --- a/tests/regression/74-loop_termination/19-rand-terminating.c +++ b/tests/regression/74-loop_termination/19-rand-terminating.c @@ -1,4 +1,4 @@ -// LOCAL_TERM PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra +// TERM PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra #include #include #include diff --git a/tests/regression/74-loop_termination/20-rand-nonterminating.c b/tests/regression/74-loop_termination/20-rand-nonterminating.c index 7c21538612..124a19d0f8 100644 --- a/tests/regression/74-loop_termination/20-rand-nonterminating.c +++ b/tests/regression/74-loop_termination/20-rand-nonterminating.c @@ -1,4 +1,4 @@ -// NON_LOCAL_TERM PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra +// NONTERM PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra #include #include #include diff --git a/tests/regression/74-loop_termination/21-no-exit-on-rand-unproofable.c b/tests/regression/74-loop_termination/21-no-exit-on-rand-unproofable.c index f54af1da7c..3bf479b6f9 100644 --- a/tests/regression/74-loop_termination/21-no-exit-on-rand-unproofable.c +++ b/tests/regression/74-loop_termination/21-no-exit-on-rand-unproofable.c @@ -1,4 +1,4 @@ -// NON_LOCAL_TERM PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra +// NONTERM PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra #include int main() diff --git a/tests/regression/74-loop_termination/22-exit-on-rand-unproofable.c b/tests/regression/74-loop_termination/22-exit-on-rand-unproofable.c index 1bc104258d..1f1a9bbd89 100644 --- a/tests/regression/74-loop_termination/22-exit-on-rand-unproofable.c +++ b/tests/regression/74-loop_termination/22-exit-on-rand-unproofable.c @@ -1,4 +1,4 @@ -// NON_LOCAL_TERM PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra +// NONTERM PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra #include int main() diff --git a/tests/regression/74-loop_termination/23-exit-on-rand-terminating.c b/tests/regression/74-loop_termination/23-exit-on-rand-terminating.c index 253d38c5df..4b9aacd0fd 100644 --- a/tests/regression/74-loop_termination/23-exit-on-rand-terminating.c +++ b/tests/regression/74-loop_termination/23-exit-on-rand-terminating.c @@ -1,4 +1,4 @@ -// TODO LOCAL_TERM PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra +// TODO TERM PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra #include #include diff --git a/tests/regression/74-loop_termination/24-upjumping-goto-loopless-terminating.c b/tests/regression/74-loop_termination/24-upjumping-goto-loopless-terminating.c index 01bffde383..3c4fffdc8a 100644 --- a/tests/regression/74-loop_termination/24-upjumping-goto-loopless-terminating.c +++ b/tests/regression/74-loop_termination/24-upjumping-goto-loopless-terminating.c @@ -1,4 +1,4 @@ -// TODO LOCAL_TERM PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra +// TODO TERM PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra #include int main() { diff --git a/tests/regression/74-loop_termination/25-leave-loop-goto-terminating.c b/tests/regression/74-loop_termination/25-leave-loop-goto-terminating.c index fed0e218ac..380e98ded0 100644 --- a/tests/regression/74-loop_termination/25-leave-loop-goto-terminating.c +++ b/tests/regression/74-loop_termination/25-leave-loop-goto-terminating.c @@ -1,4 +1,4 @@ -// TODO LOCAL_TERM PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra +// TODO TERM PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra #include int main() { diff --git a/tests/regression/74-loop_termination/26-enter-loop-goto-terminating.c b/tests/regression/74-loop_termination/26-enter-loop-goto-terminating.c index 2a43933758..b676ca6985 100644 --- a/tests/regression/74-loop_termination/26-enter-loop-goto-terminating.c +++ b/tests/regression/74-loop_termination/26-enter-loop-goto-terminating.c @@ -1,4 +1,4 @@ -// TODO LOCAL_TERM PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra +// TODO TERM PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra #include int main() { diff --git a/tests/regression/74-loop_termination/27-upjumping-goto-nonterminating.c b/tests/regression/74-loop_termination/27-upjumping-goto-nonterminating.c index a230827356..52ad7ea820 100644 --- a/tests/regression/74-loop_termination/27-upjumping-goto-nonterminating.c +++ b/tests/regression/74-loop_termination/27-upjumping-goto-nonterminating.c @@ -1,4 +1,4 @@ -// NON_LOCAL_TERM PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra +// NONTERM PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra #include int main() { diff --git a/tests/regression/74-loop_termination/28-do-while-continue-terminating.c b/tests/regression/74-loop_termination/28-do-while-continue-terminating.c index 5989c61fed..aa215a502a 100644 --- a/tests/regression/74-loop_termination/28-do-while-continue-terminating.c +++ b/tests/regression/74-loop_termination/28-do-while-continue-terminating.c @@ -1,4 +1,4 @@ -// TODO LOCAL_TERM PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra +// TODO TERM PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra #include int main() diff --git a/tests/regression/74-loop_termination/29-do-while-continue-nonterminating.c b/tests/regression/74-loop_termination/29-do-while-continue-nonterminating.c index 806456e887..896d8fea95 100644 --- a/tests/regression/74-loop_termination/29-do-while-continue-nonterminating.c +++ b/tests/regression/74-loop_termination/29-do-while-continue-nonterminating.c @@ -1,4 +1,4 @@ -// NON_LOCAL_TERM PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra +// NONTERM PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra #include int main() diff --git a/tests/regression/74-loop_termination/30-goto-out-of-inner-loop-terminating.c b/tests/regression/74-loop_termination/30-goto-out-of-inner-loop-terminating.c index 76c272a654..0526e20bb4 100644 --- a/tests/regression/74-loop_termination/30-goto-out-of-inner-loop-terminating.c +++ b/tests/regression/74-loop_termination/30-goto-out-of-inner-loop-terminating.c @@ -1,4 +1,4 @@ -// TODO LOCAL_TERM PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra +// TODO TERM PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra #include int main() { diff --git a/tests/regression/74-loop_termination/31-goto-out-of-inner-loop-nonterminating.c b/tests/regression/74-loop_termination/31-goto-out-of-inner-loop-nonterminating.c index c1824227d0..722694eb88 100644 --- a/tests/regression/74-loop_termination/31-goto-out-of-inner-loop-nonterminating.c +++ b/tests/regression/74-loop_termination/31-goto-out-of-inner-loop-nonterminating.c @@ -1,4 +1,4 @@ -// NON_LOCAL_TERM PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra +// NONTERM PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra #include int main() { diff --git a/tests/regression/74-loop_termination/32-multithread-terminating.c b/tests/regression/74-loop_termination/32-multithread-terminating.c index a08fe01398..1f98b88eee 100644 --- a/tests/regression/74-loop_termination/32-multithread-terminating.c +++ b/tests/regression/74-loop_termination/32-multithread-terminating.c @@ -1,4 +1,4 @@ -// LOCAL_TERM PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra +// TERM PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra #include #include #include diff --git a/tests/regression/74-loop_termination/33-multithread-nonterminating.c b/tests/regression/74-loop_termination/33-multithread-nonterminating.c index 77cd2aafe6..007af3b57b 100644 --- a/tests/regression/74-loop_termination/33-multithread-nonterminating.c +++ b/tests/regression/74-loop_termination/33-multithread-nonterminating.c @@ -1,4 +1,4 @@ -// NON_LOCAL_TERM PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra +// NONTERM PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra #include #include #include diff --git a/tests/regression/74-loop_termination/34-nested-for-loop-nonterminating.c b/tests/regression/74-loop_termination/34-nested-for-loop-nonterminating.c index d8aa9d487d..29e4ff3835 100644 --- a/tests/regression/74-loop_termination/34-nested-for-loop-nonterminating.c +++ b/tests/regression/74-loop_termination/34-nested-for-loop-nonterminating.c @@ -1,4 +1,4 @@ -// NON_LOCAL_TERM PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra +// NONTERM PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra #include int main() diff --git a/tests/regression/75-recursion_termination/01-simple-terminating.c b/tests/regression/75-recursion_termination/01-simple-terminating.c index 4f09950025..583f8ccca1 100644 --- a/tests/regression/75-recursion_termination/01-simple-terminating.c +++ b/tests/regression/75-recursion_termination/01-simple-terminating.c @@ -1,4 +1,4 @@ -// LOCAL_TERM PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra +// TERM PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra #include void recursiveFunction(int n) { diff --git a/tests/regression/75-recursion_termination/02-simple-nonterminating.c b/tests/regression/75-recursion_termination/02-simple-nonterminating.c index 37c4bbd801..41a2b7b678 100644 --- a/tests/regression/75-recursion_termination/02-simple-nonterminating.c +++ b/tests/regression/75-recursion_termination/02-simple-nonterminating.c @@ -1,4 +1,4 @@ -// NON_LOCAL_TERM PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra +// NONTERM PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra #include void recursiveFunction(int n) { diff --git a/tests/regression/75-recursion_termination/03-nested-terminating.c b/tests/regression/75-recursion_termination/03-nested-terminating.c index 23bedef644..4cede747f2 100644 --- a/tests/regression/75-recursion_termination/03-nested-terminating.c +++ b/tests/regression/75-recursion_termination/03-nested-terminating.c @@ -1,4 +1,4 @@ -// LOCAL_TERM PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra +// TERM PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra #include void innerRecursiveFunction(int n) { diff --git a/tests/regression/75-recursion_termination/04-nested-nonterminating.c b/tests/regression/75-recursion_termination/04-nested-nonterminating.c index d28685e139..2d3239f371 100644 --- a/tests/regression/75-recursion_termination/04-nested-nonterminating.c +++ b/tests/regression/75-recursion_termination/04-nested-nonterminating.c @@ -1,4 +1,4 @@ -// NON_LOCAL_TERM PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra +// NONTERM PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra #include void innerRecursiveFunction() { From d05da3a797473c9ee813b331900513366d0e2a3a Mon Sep 17 00:00:00 2001 From: Thomas Lagemann Date: Thu, 29 Jun 2023 13:42:29 +0200 Subject: [PATCH 180/327] Reformat --- .../75-recursion_termination/02-simple-nonterminating.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/regression/75-recursion_termination/02-simple-nonterminating.c b/tests/regression/75-recursion_termination/02-simple-nonterminating.c index 41a2b7b678..0dc3cbcf63 100644 --- a/tests/regression/75-recursion_termination/02-simple-nonterminating.c +++ b/tests/regression/75-recursion_termination/02-simple-nonterminating.c @@ -1,4 +1,4 @@ -// NONTERM PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra +// NONTERM PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra #include void recursiveFunction(int n) { From 036dd175358dbdb2ef1748aed2ca253b28385d32 Mon Sep 17 00:00:00 2001 From: Thomas Lagemann Date: Thu, 29 Jun 2023 13:43:41 +0200 Subject: [PATCH 181/327] Skip crashing tests --- .../74-loop_termination/09-complex-for-loop-terminating.c | 2 +- .../74-loop_termination/10-complex-loop-terminating.c | 2 +- .../15-complex-loop-combination-terminating.c | 2 +- .../75-recursion_termination/04-nested-nonterminating.c | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/tests/regression/74-loop_termination/09-complex-for-loop-terminating.c b/tests/regression/74-loop_termination/09-complex-for-loop-terminating.c index c26fde710f..7fb9262aab 100644 --- a/tests/regression/74-loop_termination/09-complex-for-loop-terminating.c +++ b/tests/regression/74-loop_termination/09-complex-for-loop-terminating.c @@ -1,4 +1,4 @@ -// TERM PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra +// SKIP TERM PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra #include int main() diff --git a/tests/regression/74-loop_termination/10-complex-loop-terminating.c b/tests/regression/74-loop_termination/10-complex-loop-terminating.c index 017c10b8a4..e39613b563 100644 --- a/tests/regression/74-loop_termination/10-complex-loop-terminating.c +++ b/tests/regression/74-loop_termination/10-complex-loop-terminating.c @@ -1,4 +1,4 @@ -// TERM PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra +// SKIP TERM PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra #include int main() diff --git a/tests/regression/74-loop_termination/15-complex-loop-combination-terminating.c b/tests/regression/74-loop_termination/15-complex-loop-combination-terminating.c index 07fbe38cfd..ad64a9a5f9 100644 --- a/tests/regression/74-loop_termination/15-complex-loop-combination-terminating.c +++ b/tests/regression/74-loop_termination/15-complex-loop-combination-terminating.c @@ -1,4 +1,4 @@ -// TERM PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra +// SKIP TERM PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra #include int main() diff --git a/tests/regression/75-recursion_termination/04-nested-nonterminating.c b/tests/regression/75-recursion_termination/04-nested-nonterminating.c index 2d3239f371..5299544a70 100644 --- a/tests/regression/75-recursion_termination/04-nested-nonterminating.c +++ b/tests/regression/75-recursion_termination/04-nested-nonterminating.c @@ -1,4 +1,4 @@ -// NONTERM PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra +// SKIP NONTERM PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra #include void innerRecursiveFunction() { From 4cb5da0fb3afca195cdad847f848dd15f0e3cded Mon Sep 17 00:00:00 2001 From: Thomas Lagemann Date: Thu, 29 Jun 2023 14:06:34 +0200 Subject: [PATCH 182/327] Removed Todos --- tests/regression/74-loop_termination/17-goto-terminating.c | 2 +- .../74-loop_termination/23-exit-on-rand-terminating.c | 2 +- .../24-upjumping-goto-loopless-terminating.c | 2 +- .../74-loop_termination/25-leave-loop-goto-terminating.c | 2 +- .../74-loop_termination/26-enter-loop-goto-terminating.c | 2 +- .../74-loop_termination/28-do-while-continue-terminating.c | 2 +- .../74-loop_termination/30-goto-out-of-inner-loop-terminating.c | 2 +- .../75-recursion_termination/02-simple-nonterminating.c | 2 +- .../75-recursion_termination/04-nested-nonterminating.c | 2 +- 9 files changed, 9 insertions(+), 9 deletions(-) diff --git a/tests/regression/74-loop_termination/17-goto-terminating.c b/tests/regression/74-loop_termination/17-goto-terminating.c index b11b5b3da9..1e4c1e719e 100644 --- a/tests/regression/74-loop_termination/17-goto-terminating.c +++ b/tests/regression/74-loop_termination/17-goto-terminating.c @@ -1,4 +1,4 @@ -// TODO TERM PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra +// TERM PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra #include int main() diff --git a/tests/regression/74-loop_termination/23-exit-on-rand-terminating.c b/tests/regression/74-loop_termination/23-exit-on-rand-terminating.c index 4b9aacd0fd..94e47d5d9a 100644 --- a/tests/regression/74-loop_termination/23-exit-on-rand-terminating.c +++ b/tests/regression/74-loop_termination/23-exit-on-rand-terminating.c @@ -1,4 +1,4 @@ -// TODO TERM PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra +// TERM PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra #include #include diff --git a/tests/regression/74-loop_termination/24-upjumping-goto-loopless-terminating.c b/tests/regression/74-loop_termination/24-upjumping-goto-loopless-terminating.c index 3c4fffdc8a..e5c4f10f0d 100644 --- a/tests/regression/74-loop_termination/24-upjumping-goto-loopless-terminating.c +++ b/tests/regression/74-loop_termination/24-upjumping-goto-loopless-terminating.c @@ -1,4 +1,4 @@ -// TODO TERM PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra +// TERM PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra #include int main() { diff --git a/tests/regression/74-loop_termination/25-leave-loop-goto-terminating.c b/tests/regression/74-loop_termination/25-leave-loop-goto-terminating.c index 380e98ded0..ea353eb466 100644 --- a/tests/regression/74-loop_termination/25-leave-loop-goto-terminating.c +++ b/tests/regression/74-loop_termination/25-leave-loop-goto-terminating.c @@ -1,4 +1,4 @@ -// TODO TERM PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra +// TERM PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra #include int main() { diff --git a/tests/regression/74-loop_termination/26-enter-loop-goto-terminating.c b/tests/regression/74-loop_termination/26-enter-loop-goto-terminating.c index b676ca6985..8c2f3da4a2 100644 --- a/tests/regression/74-loop_termination/26-enter-loop-goto-terminating.c +++ b/tests/regression/74-loop_termination/26-enter-loop-goto-terminating.c @@ -1,4 +1,4 @@ -// TODO TERM PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra +// TERM PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra #include int main() { diff --git a/tests/regression/74-loop_termination/28-do-while-continue-terminating.c b/tests/regression/74-loop_termination/28-do-while-continue-terminating.c index aa215a502a..7f91ecc149 100644 --- a/tests/regression/74-loop_termination/28-do-while-continue-terminating.c +++ b/tests/regression/74-loop_termination/28-do-while-continue-terminating.c @@ -1,4 +1,4 @@ -// TODO TERM PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra +// TERM PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra #include int main() diff --git a/tests/regression/74-loop_termination/30-goto-out-of-inner-loop-terminating.c b/tests/regression/74-loop_termination/30-goto-out-of-inner-loop-terminating.c index 0526e20bb4..45cadb583f 100644 --- a/tests/regression/74-loop_termination/30-goto-out-of-inner-loop-terminating.c +++ b/tests/regression/74-loop_termination/30-goto-out-of-inner-loop-terminating.c @@ -1,4 +1,4 @@ -// TODO TERM PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra +// TERM PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra #include int main() { diff --git a/tests/regression/75-recursion_termination/02-simple-nonterminating.c b/tests/regression/75-recursion_termination/02-simple-nonterminating.c index 0dc3cbcf63..26f30e726b 100644 --- a/tests/regression/75-recursion_termination/02-simple-nonterminating.c +++ b/tests/regression/75-recursion_termination/02-simple-nonterminating.c @@ -1,4 +1,4 @@ -// NONTERM PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra +// SKIP NONTERM PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra #include void recursiveFunction(int n) { diff --git a/tests/regression/75-recursion_termination/04-nested-nonterminating.c b/tests/regression/75-recursion_termination/04-nested-nonterminating.c index 5299544a70..2d3239f371 100644 --- a/tests/regression/75-recursion_termination/04-nested-nonterminating.c +++ b/tests/regression/75-recursion_termination/04-nested-nonterminating.c @@ -1,4 +1,4 @@ -// SKIP NONTERM PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra +// NONTERM PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra #include void innerRecursiveFunction() { From fec0d6266469ca2e114c606d7e7c4602018428f2 Mon Sep 17 00:00:00 2001 From: Thomas Lagemann Date: Thu, 29 Jun 2023 14:26:45 +0200 Subject: [PATCH 183/327] Adapted tests to current state --- tests/regression/74-loop_termination/17-goto-terminating.c | 4 ++-- .../74-loop_termination/23-exit-on-rand-terminating.c | 4 ++-- .../24-upjumping-goto-loopless-terminating.c | 4 ++-- .../74-loop_termination/25-leave-loop-goto-terminating.c | 4 ++-- .../74-loop_termination/26-enter-loop-goto-terminating.c | 4 ++-- .../30-goto-out-of-inner-loop-terminating.c | 4 ++-- 6 files changed, 12 insertions(+), 12 deletions(-) diff --git a/tests/regression/74-loop_termination/17-goto-terminating.c b/tests/regression/74-loop_termination/17-goto-terminating.c index 1e4c1e719e..c4ba717784 100644 --- a/tests/regression/74-loop_termination/17-goto-terminating.c +++ b/tests/regression/74-loop_termination/17-goto-terminating.c @@ -1,4 +1,4 @@ -// TERM PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra +// TODO TERM PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra #include int main() @@ -11,7 +11,7 @@ int main() if (num <= 10) { - goto loop; + goto loop; // We are not able to detect up-jumping gotos as terminating, we just warn about them might being nonterminating. } return 0; diff --git a/tests/regression/74-loop_termination/23-exit-on-rand-terminating.c b/tests/regression/74-loop_termination/23-exit-on-rand-terminating.c index 94e47d5d9a..226f46b16e 100644 --- a/tests/regression/74-loop_termination/23-exit-on-rand-terminating.c +++ b/tests/regression/74-loop_termination/23-exit-on-rand-terminating.c @@ -1,4 +1,4 @@ -// TERM PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra +// TODO TERM PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra #include #include @@ -6,7 +6,7 @@ int main() { int short_run, i = 0; - while (i < 90 && short_run != 1) + while (i < 90 && short_run != 1) // Currently not able to detect this as terminating { i++; if (rand()) diff --git a/tests/regression/74-loop_termination/24-upjumping-goto-loopless-terminating.c b/tests/regression/74-loop_termination/24-upjumping-goto-loopless-terminating.c index e5c4f10f0d..e256df9986 100644 --- a/tests/regression/74-loop_termination/24-upjumping-goto-loopless-terminating.c +++ b/tests/regression/74-loop_termination/24-upjumping-goto-loopless-terminating.c @@ -1,7 +1,7 @@ -// TERM PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra +// TODO TERM PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra #include -int main() { +int main() { // Currently not able to detect this as terminating goto mark2; mark1: diff --git a/tests/regression/74-loop_termination/25-leave-loop-goto-terminating.c b/tests/regression/74-loop_termination/25-leave-loop-goto-terminating.c index ea353eb466..cbbb115868 100644 --- a/tests/regression/74-loop_termination/25-leave-loop-goto-terminating.c +++ b/tests/regression/74-loop_termination/25-leave-loop-goto-terminating.c @@ -1,4 +1,4 @@ -// TERM PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra +// TODO TERM PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra #include int main() { @@ -13,7 +13,7 @@ int main() { printf("Result: %d\n", result); // Condition to terminate the loop - if (result >= 10) { + if (result >= 10) { // Apron is not able to detect this goto end; } } diff --git a/tests/regression/74-loop_termination/26-enter-loop-goto-terminating.c b/tests/regression/74-loop_termination/26-enter-loop-goto-terminating.c index 8c2f3da4a2..17220a589b 100644 --- a/tests/regression/74-loop_termination/26-enter-loop-goto-terminating.c +++ b/tests/regression/74-loop_termination/26-enter-loop-goto-terminating.c @@ -1,4 +1,4 @@ -// TERM PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra +// TODO TERM PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra #include int main() { @@ -16,7 +16,7 @@ int main() { printf("Result: %d\n", result); // Condition to terminate the loop - if (result >= 10) { + if (result >= 10) { // Apron is not able to detect this goto end; } } diff --git a/tests/regression/74-loop_termination/30-goto-out-of-inner-loop-terminating.c b/tests/regression/74-loop_termination/30-goto-out-of-inner-loop-terminating.c index 45cadb583f..6b36919c2d 100644 --- a/tests/regression/74-loop_termination/30-goto-out-of-inner-loop-terminating.c +++ b/tests/regression/74-loop_termination/30-goto-out-of-inner-loop-terminating.c @@ -1,4 +1,4 @@ -// TERM PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra +// TODO TERM PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra #include int main() { @@ -9,7 +9,7 @@ int main() { for (int i = 1; i <= rows; i++) { // Inner loop for columns for (int j = 1; j <= columns; j++) { - if (j == 3) { + if (j == 3) { // Apron is not able to detect this goto outer_loop; // Jump to the label "outer_loop" } printf("(%d, %d) ", i, j); From 68b01aff36092ad7727383249d81fe26cf4374a7 Mon Sep 17 00:00:00 2001 From: Thomas Lagemann Date: Thu, 29 Jun 2023 14:32:01 +0200 Subject: [PATCH 184/327] Adapted tests to current state --- .../74-loop_termination/25-leave-loop-goto-terminating.c | 2 +- .../74-loop_termination/26-enter-loop-goto-terminating.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/regression/74-loop_termination/25-leave-loop-goto-terminating.c b/tests/regression/74-loop_termination/25-leave-loop-goto-terminating.c index cbbb115868..ce11a73060 100644 --- a/tests/regression/74-loop_termination/25-leave-loop-goto-terminating.c +++ b/tests/regression/74-loop_termination/25-leave-loop-goto-terminating.c @@ -1,4 +1,4 @@ -// TODO TERM PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra +// TODO TERM PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain octagon #include int main() { diff --git a/tests/regression/74-loop_termination/26-enter-loop-goto-terminating.c b/tests/regression/74-loop_termination/26-enter-loop-goto-terminating.c index 17220a589b..355c1ebf00 100644 --- a/tests/regression/74-loop_termination/26-enter-loop-goto-terminating.c +++ b/tests/regression/74-loop_termination/26-enter-loop-goto-terminating.c @@ -1,4 +1,4 @@ -// TODO TERM PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra +// TERM PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra #include int main() { From b7c6ec5493b90eb400522f8663efad91b25e9ef4 Mon Sep 17 00:00:00 2001 From: Alexander Schlenga Date: Thu, 29 Jun 2023 17:23:34 +0200 Subject: [PATCH 185/327] Restore apronAnalysis.apron.ml --- src/analyses/apron/apronAnalysis.apron.ml | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/src/analyses/apron/apronAnalysis.apron.ml b/src/analyses/apron/apronAnalysis.apron.ml index bec0c4ec57..29e295a662 100644 --- a/src/analyses/apron/apronAnalysis.apron.ml +++ b/src/analyses/apron/apronAnalysis.apron.ml @@ -4,7 +4,6 @@ open Analyses include RelationAnalysis - let spec_module: (module MCPSpec) Lazy.t = lazy ( let module Man = (val ApronDomain.get_manager ()) in @@ -35,8 +34,7 @@ let get_spec (): (module MCPSpec) = let after_config () = let module Spec = (val get_spec ()) in MCP.register_analysis (module Spec : MCPSpec); - GobConfig.set_string "ana.path_sens[+]" (Spec.name ()) - + GobConfig.set_string "ana.path_sens[+]" (Spec.name ()) let _ = AfterConfig.register after_config From 432e92d7e1e542b63e38d52b84942f2a3470f7f8 Mon Sep 17 00:00:00 2001 From: Alexander Schlenga Date: Thu, 29 Jun 2023 17:39:48 +0200 Subject: [PATCH 186/327] Explicitly use () as the abstract local state --- src/analyses/loop_termination.ml | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/analyses/loop_termination.ml b/src/analyses/loop_termination.ml index 7ecb11a12c..6aed200192 100644 --- a/src/analyses/loop_termination.ml +++ b/src/analyses/loop_termination.ml @@ -69,7 +69,7 @@ struct module V = UnitV module G = MapDomain.MapBot (Statements) (BoolDomain.MustBool) - let startstate _ = D.bot () + let startstate _ = () let exitstate = startstate let assign ctx (lval : lval) (rval : exp) = @@ -81,12 +81,12 @@ struct let is_bounded = check_bounded ctx x in let loop_statement = VarToStmt.find x !loop_counters in let () = ctx.sideg () (G.add (`Lifted loop_statement) is_bounded (ctx.global ())) in - ctx.local - | _ -> ctx.local + () + | _ -> () let special ctx (lval : lval option) (f : varinfo) (arglist : exp list) = (* TODO: Implement check for our special loop exit indicator function *) - ctx.local + () (** Checks whether a new thread was spawned some time. We want to discard * any knowledge about termination then (see query function) *) From 29532421f232de013f95da615820af7e4d944a44 Mon Sep 17 00:00:00 2001 From: Alexander Schlenga Date: Thu, 29 Jun 2023 17:44:30 +0200 Subject: [PATCH 187/327] Change let-in clause to sequential statements --- src/analyses/loop_termination.ml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/analyses/loop_termination.ml b/src/analyses/loop_termination.ml index 6aed200192..1d6a7db262 100644 --- a/src/analyses/loop_termination.ml +++ b/src/analyses/loop_termination.ml @@ -80,7 +80,7 @@ struct (* TODO: Move to special *) let is_bounded = check_bounded ctx x in let loop_statement = VarToStmt.find x !loop_counters in - let () = ctx.sideg () (G.add (`Lifted loop_statement) is_bounded (ctx.global ())) in + ctx.sideg () (G.add (`Lifted loop_statement) is_bounded (ctx.global ())); () | _ -> () From c2c69cf1bc3e8e6f8a9978d9769786a0f44669b1 Mon Sep 17 00:00:00 2001 From: serenita <33780257+serenita@users.noreply.github.com> Date: Thu, 29 Jun 2023 18:17:01 +0200 Subject: [PATCH 188/327] Update src/framework/constraints.ml Make comment more precise Co-authored-by: Michael Schwarz --- src/framework/constraints.ml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/framework/constraints.ml b/src/framework/constraints.ml index ce3ecadc1e..ccee950a7d 100644 --- a/src/framework/constraints.ml +++ b/src/framework/constraints.ml @@ -1695,7 +1695,7 @@ struct end -(** Add cycle detection in the function call graph to a analysis *) +(** Add cycle detection in the context-sensitive dynamic function call graph to an analysis *) module RecursionTermLifter (S: Spec) : Spec with module D = S.D and module C = S.C From d18d8fe8a32a613ac7a0b4dc27c9d6747c2b9295 Mon Sep 17 00:00:00 2001 From: serenita <33780257+serenita@users.noreply.github.com> Date: Thu, 29 Jun 2023 18:18:45 +0200 Subject: [PATCH 189/327] Update src/framework/constraints.ml Co-authored-by: Michael Schwarz --- src/framework/constraints.ml | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/src/framework/constraints.ml b/src/framework/constraints.ml index ccee950a7d..bd65dd5ba4 100644 --- a/src/framework/constraints.ml +++ b/src/framework/constraints.ml @@ -1709,10 +1709,7 @@ module RecursionTermLifter (S: Spec) struct include S - module V = - struct - include GVarF(S.V) - end + module V = GVarF(S.V) module G = GVarGSet (S.G) (S.C) (T (CilType.Fundec) (S.C)) From 0d77172c0933d6044c83cee065737200730277ac Mon Sep 17 00:00:00 2001 From: serenita <33780257+serenita@users.noreply.github.com> Date: Thu, 29 Jun 2023 18:22:29 +0200 Subject: [PATCH 190/327] Remove unnecessary semicola Co-authored-by: Michael Schwarz --- src/util/terminationPreprocessing.ml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/util/terminationPreprocessing.ml b/src/util/terminationPreprocessing.ml index 6e29c48917..47a17575c4 100644 --- a/src/util/terminationPreprocessing.ml +++ b/src/util/terminationPreprocessing.ml @@ -1,7 +1,7 @@ open GoblintCil include Printf -module VarToStmt = Map.Make(CilType.Varinfo);; (* maps varinfos (= loop counter variable) to the statement of the corresponding loop*) +module VarToStmt = Map.Make(CilType.Varinfo) (* maps varinfos (= loop counter variable) to the statement of the corresponding loop*) let extract_file_name s = (*There still may be a need to filter more chars*) let ls = String.split_on_char '/' s in (*Assuming '/' as path seperator*) From 76230f473ef68c940f117d221393cfbf515a7505 Mon Sep 17 00:00:00 2001 From: Alexander Schlenga Date: Thu, 29 Jun 2023 18:31:30 +0200 Subject: [PATCH 191/327] Restore 01-simple-cases.c from white space change --- tests/regression/55-loop-unrolling/01-simple-cases.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/regression/55-loop-unrolling/01-simple-cases.c b/tests/regression/55-loop-unrolling/01-simple-cases.c index add8c6a8dd..0073717187 100644 --- a/tests/regression/55-loop-unrolling/01-simple-cases.c +++ b/tests/regression/55-loop-unrolling/01-simple-cases.c @@ -193,4 +193,4 @@ void example10(void) ++i; } return 0; -} \ No newline at end of file +} From 6e620417fd57bbdd6b7e9c05c6e7ad6b69bab4de Mon Sep 17 00:00:00 2001 From: Johanna Schinabeck Date: Fri, 30 Jun 2023 11:05:32 +0200 Subject: [PATCH 192/327] adapted changes from pull request: 1. using a module for tuple; 2. deleted dublicated method; 3. removed the arg from the arg_termination variable --- src/framework/analyses.ml | 39 ------------------------------------ src/framework/constraints.ml | 12 +++++------ src/framework/control.ml | 4 ++-- 3 files changed, 8 insertions(+), 47 deletions(-) diff --git a/src/framework/analyses.ml b/src/framework/analyses.ml index 1c3d596cc2..712399d619 100644 --- a/src/framework/analyses.ml +++ b/src/framework/analyses.ml @@ -118,38 +118,6 @@ struct | x -> BatPrintf.fprintf f "%a" printXml x end -(* Tuple of fundec and S.C*) -module T (Base1: Printable.S) (Base2: Printable.S) = -struct - include Printable.Std - type t = (Base1.t * Base2.t) - - let fundec (a,_) = a - let context (_,b) = b - let equal (a1, b1) (a2, b2) = if (Base1.equal a1 a2 && Base2.equal b1 b2) then true else false - let show (a,b) = (Base1.show a) ^ (Base2.show b) - let name () = "Tuple" - let to_yojson x = `String (show x) - let relift (a,b) = (a,b) (*Todo: is this correct?*) - let printXml f (a,b) = - BatPrintf.fprintf f "\n - Tuple:\n\n - caller_fundec\n%a\n\n - caller_context\n%a\n\n - \n" Base1.printXml a Base2.printXml b - - let compare (a1,b1) (a2,b2) = (*Todo: is this ok?*) - if equal (a1, b1) (a2, b2) then 0 - else( - let val_a a = if (a > 0) then 1 else -1 in - let val_b b = if (b > 0) then 3 else -3 in - val_a (Base1.compare a1 a2) + val_b (Base2.compare b1 b2) - ) - - let pretty () x = text (show x) - let hash (a,b) = Hashtbl.hash (Base1.hash a * Base2.hash b) (*Todo: is this ok?*) -end - module GVarGSet (G: Lattice.S) (C: Printable.S) (Base: Printable.S) = struct module CSet = @@ -200,13 +168,6 @@ struct | `Lifted2 x -> BatPrintf.fprintf f "%a" CMap.printXml x | x -> BatPrintf.fprintf f "%a" printXml x - let s = function - | `Bot -> G.bot () - | `Lifted1 x -> x - | _ -> failwith "RecursionTerm.s" - - let create_s s = `Lifted1 s - let base2 instance = match instance with | `Lifted2 n -> Some n diff --git a/src/framework/constraints.ml b/src/framework/constraints.ml index bd65dd5ba4..c60f84d5e8 100644 --- a/src/framework/constraints.ml +++ b/src/framework/constraints.ml @@ -1711,24 +1711,24 @@ struct include S module V = GVarF(S.V) - module G = GVarGSet (S.G) (S.C) (T (CilType.Fundec) (S.C)) + module G = GVarGSet (S.G) (S.C) (Printable.Prod (CilType.Fundec) (S.C)) let name () = "termination" let conv (ctx: (_, G.t, _, V.t) ctx): (_, S.G.t, _, S.V.t) ctx = { ctx with - global = (fun v -> G.s (ctx.global (V.spec v))); - sideg = (fun v g -> ctx.sideg (V.spec v) (G.create_s g)); + global = (fun v -> G.spec (ctx.global (V.spec v))); + sideg = (fun v g -> ctx.sideg (V.spec v) (G.create_spec g)); } let cycleDetection ctx v v' = - let module LH = Hashtbl.Make (T (CilType.Fundec) (S.C)) in - let module LS = Set.Make (T (CilType.Fundec) (S.C)) in + let module LH = Hashtbl.Make (Printable.Prod (CilType.Fundec) (S.C)) in + let module LS = Set.Make (Printable.Prod (CilType.Fundec) (S.C)) in (* find all cycles/SCCs *) let global_visited_calls = LH.create 100 in (* DFS *) - let rec iter_call (path_visited_calls: LS.t) (call:T (CilType.Fundec) (S.C).t) = + let rec iter_call (path_visited_calls: LS.t) (call:Printable.Prod (CilType.Fundec) (S.C).t) = let ((fundec_e:fundec), (context_e: C.t)) = call in (*unpack tuple for later use*) if LS.mem call path_visited_calls then ( AnalysisState.svcomp_may_not_terminate := true; diff --git a/src/framework/control.ml b/src/framework/control.ml index 9a717e2f67..e408aab76a 100644 --- a/src/framework/control.ml +++ b/src/framework/control.ml @@ -15,7 +15,7 @@ module type S2S = functor (X : Spec) -> Spec let spec_module: (module Spec) Lazy.t = lazy ( GobConfig.building_spec := true; let arg_enabled = get_bool "ana.sv-comp.enabled" || get_bool "exp.arg" in - let arg_termination = List.mem "termination" (get_string_list "ana.activated") in (* check if loop termination analysis is enabled*) + let termination = List.mem "termination" (get_string_list "ana.activated") in (* check if loop termination analysis is enabled*) let open Batteries in (* apply functor F on module X if opt is true *) let lift opt (module F : S2S) (module X : Spec) = (module (val if opt then (module F (X)) else (module X) : Spec) : Spec) in @@ -37,7 +37,7 @@ let spec_module: (module Spec) Lazy.t = lazy ( Also must be outside of deadcode, because deadcode splits (like mutex lock event) don't pass on tokens. *) |> lift (get_bool "ana.widen.tokens") (module WideningTokens.Lifter) |> lift true (module LongjmpLifter) - |> lift arg_termination (module RecursionTermLifter) (* Always activate the recursion termination analysis, when the loop termination analysis is activated*) + |> lift termination (module RecursionTermLifter) (* Always activate the recursion termination analysis, when the loop termination analysis is activated*) ) in GobConfig.building_spec := false; ControlSpecC.control_spec_c := (module S1.C); From 9c8d1283e4e5ad9a1fc13c318d8dcb44e11b3d44 Mon Sep 17 00:00:00 2001 From: Johanna Schinabeck Date: Fri, 30 Jun 2023 11:38:20 +0200 Subject: [PATCH 193/327] changed the order in C_Printable --- src/framework/analyses.ml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/framework/analyses.ml b/src/framework/analyses.ml index 712399d619..9f25a67a0d 100644 --- a/src/framework/analyses.ml +++ b/src/framework/analyses.ml @@ -133,8 +133,8 @@ struct (* Make the given module Goupable*) module C_Printable (C: Printable.S) = struct - include C include Printable.Std (* To make it Groupable *) + include C let printXml f c = BatPrintf.fprintf f "\n callee_context\n%a\n\n From c776d8cd82def2ba48f1402f179f7af90f092b94 Mon Sep 17 00:00:00 2001 From: Isidor Zweckstetter Date: Sat, 1 Jul 2023 11:30:47 +0200 Subject: [PATCH 194/327] changed naming for SV-Comp specification from NoTermination to Termination, to meet naming conventions --- src/autoTune.ml | 2 +- src/witness/svcomp.ml | 2 +- src/witness/svcompSpec.ml | 8 ++++---- src/witness/witness.ml | 2 +- 4 files changed, 7 insertions(+), 7 deletions(-) diff --git a/src/autoTune.ml b/src/autoTune.ml index 4fb8a1db5e..9468d1d366 100644 --- a/src/autoTune.ml +++ b/src/autoTune.ml @@ -216,7 +216,7 @@ let focusOnSpecification () = | NoDataRace -> (*enable all thread analyses*) print_endline @@ "Specification: NoDataRace -> enabling thread analyses \"" ^ (String.concat ", " notNeccessaryThreadAnalyses) ^ "\""; enableAnalyses notNeccessaryThreadAnalyses; - | NoTermination -> () + | Termination -> () | NoOverflow -> (*We focus on integer analysis*) set_bool "ana.int.def_exc" true; set_bool "ana.int.interval" true diff --git a/src/witness/svcomp.ml b/src/witness/svcomp.ml index a164448210..2fcb32fff9 100644 --- a/src/witness/svcomp.ml +++ b/src/witness/svcomp.ml @@ -52,7 +52,7 @@ struct | UnreachCall _ -> "unreach-call" | NoOverflow -> "no-overflow" | NoDataRace -> "no-data-race" (* not yet in SV-COMP/Benchexec *) - | NoTermination -> "no-termination" + | Termination -> "termination" in "false(" ^ result_spec ^ ")" | Unknown -> "unknown" diff --git a/src/witness/svcompSpec.ml b/src/witness/svcompSpec.ml index f8791d065e..946093bfc0 100644 --- a/src/witness/svcompSpec.ml +++ b/src/witness/svcompSpec.ml @@ -6,7 +6,7 @@ type t = | UnreachCall of string | NoDataRace | NoOverflow - | NoTermination + | Termination let of_string s = let s = String.strip s in @@ -17,8 +17,8 @@ let of_string s = NoDataRace else if global_not = "overflow" then NoOverflow - else if global_not = "termination" then - NoTermination + else if global_not = "no-termination" then + Termination else let call_regex = Str.regexp "call(\\(.*\\)())" in if Str.string_match call_regex global_not 0 then @@ -45,6 +45,6 @@ let to_string spec = | UnreachCall f -> "call(" ^ f ^ "())" | NoDataRace -> "data-race" | NoOverflow -> "overflow" - | NoTermination -> "termination" + | Termination -> "no-termination" in "CHECK( init(main()), LTL(G ! " ^ global_not ^ ") )" diff --git a/src/witness/witness.ml b/src/witness/witness.ml index b62b2b54cd..94ffea0a0a 100644 --- a/src/witness/witness.ml +++ b/src/witness/witness.ml @@ -442,7 +442,7 @@ struct in (module TaskResult:WitnessTaskResult) ) - | NoTermination -> (* TODO: implement this properly*) + | Termination -> (* TODO: implement this properly*) let module TrivialArg = struct include Arg From b1da8e26a684bbe03c0e60fc41a0ade7b0cd6414 Mon Sep 17 00:00:00 2001 From: Johanna Schinabeck Date: Sun, 2 Jul 2023 10:49:46 +0200 Subject: [PATCH 195/327] renamed termination in control to termination_enabled; added comment for global invariant in RecursionTermLifter --- src/framework/constraints.ml | 12 ++++++++---- src/framework/control.ml | 4 ++-- 2 files changed, 10 insertions(+), 6 deletions(-) diff --git a/src/framework/constraints.ml b/src/framework/constraints.ml index c60f84d5e8..55763c5852 100644 --- a/src/framework/constraints.ml +++ b/src/framework/constraints.ml @@ -1700,12 +1700,16 @@ module RecursionTermLifter (S: Spec) : Spec with module D = S.D and module C = S.C = -(*global invariants: +(* two global invariants: - V -> G + Needed to store the previously built global invariants - fundec -> Map (S.C) (Set (fundec * S.C)) - Therefore: - g -> {c' -> {(f, c)}} - in case f, c --> g, c' *) + The second global invariant maps from the callee fundec to a map, containing the callee context and the caller fundec and context. + This structure therefore stores the context-sensitive call graph. + For example: + let the function f in context c call function g in context c'. + In the global invariant structure it would be stored like this: g -> {c' -> {(f, c)}} +*) struct include S diff --git a/src/framework/control.ml b/src/framework/control.ml index e408aab76a..5bd815634c 100644 --- a/src/framework/control.ml +++ b/src/framework/control.ml @@ -15,7 +15,7 @@ module type S2S = functor (X : Spec) -> Spec let spec_module: (module Spec) Lazy.t = lazy ( GobConfig.building_spec := true; let arg_enabled = get_bool "ana.sv-comp.enabled" || get_bool "exp.arg" in - let termination = List.mem "termination" (get_string_list "ana.activated") in (* check if loop termination analysis is enabled*) + let termination_enabled = List.mem "termination" (get_string_list "ana.activated") in (* check if loop termination analysis is enabled*) let open Batteries in (* apply functor F on module X if opt is true *) let lift opt (module F : S2S) (module X : Spec) = (module (val if opt then (module F (X)) else (module X) : Spec) : Spec) in @@ -37,7 +37,7 @@ let spec_module: (module Spec) Lazy.t = lazy ( Also must be outside of deadcode, because deadcode splits (like mutex lock event) don't pass on tokens. *) |> lift (get_bool "ana.widen.tokens") (module WideningTokens.Lifter) |> lift true (module LongjmpLifter) - |> lift termination (module RecursionTermLifter) (* Always activate the recursion termination analysis, when the loop termination analysis is activated*) + |> lift termination_enabled (module RecursionTermLifter) (* Always activate the recursion termination analysis, when the loop termination analysis is activated*) ) in GobConfig.building_spec := false; ControlSpecC.control_spec_c := (module S1.C); From 1ace9d69f036db3878b5f449736775a41b9fba58 Mon Sep 17 00:00:00 2001 From: Alexander Schlenga Date: Mon, 3 Jul 2023 12:24:33 +0200 Subject: [PATCH 196/327] Add description to loop/goto termination analysis --- src/analyses/loop_termination.ml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/analyses/loop_termination.ml b/src/analyses/loop_termination.ml index 1d6a7db262..f066fbbab6 100644 --- a/src/analyses/loop_termination.ml +++ b/src/analyses/loop_termination.ml @@ -1,4 +1,4 @@ -(** Work in progress *) +(** Termination analysis for loops and [goto] statements ([termination]). *) open Analyses open GoblintCil From 30b03ce2fe2892272470d38898bc6e4297dc9ac4 Mon Sep 17 00:00:00 2001 From: Alexander Schlenga Date: Mon, 3 Jul 2023 12:32:51 +0200 Subject: [PATCH 197/327] Introduce isEverMultiThreaded analysis Does not work properly yet. Need to fix query function. --- src/analyses/everMultiThreaded.ml | 46 +++++++++++++++++++++++++++++++ src/domains/queries.ml | 5 ++++ 2 files changed, 51 insertions(+) create mode 100644 src/analyses/everMultiThreaded.ml diff --git a/src/analyses/everMultiThreaded.ml b/src/analyses/everMultiThreaded.ml new file mode 100644 index 0000000000..c98f173624 --- /dev/null +++ b/src/analyses/everMultiThreaded.ml @@ -0,0 +1,46 @@ +(** Work in progress *) + +open Analyses + +module UnitV = +struct + include Printable.Unit + include StdV +end + +module Spec : Analyses.MCPSpec = +struct + + (** Provides some default implementations *) + include Analyses.IdentitySpec + + let name () = "evermultithreaded" + + module D = Lattice.Unit + module C = D + module V = UnitV + module G = BoolDomain.MayBool + + let startstate _ = () + let exitstate = startstate + + (** Sets the global invariant to true when a thread is spawned *) + let threadspawn ctx lval f args fctx = + ctx.sideg () true; + () + + let query ctx (type a) (q: a Queries.t) : a Queries.result = + match q with + | Queries.IsEverMultiThreaded -> + (* + ctx.global () + *) + Queries.Result.top q (* TODO *) + | _ -> + Queries.Result.top q + +end + +let () = + (* Register this analysis within the master control program *) + MCP.register_analysis (module Spec : MCPSpec) diff --git a/src/domains/queries.ml b/src/domains/queries.ml index c5d7d729b6..2810f07342 100644 --- a/src/domains/queries.ml +++ b/src/domains/queries.ml @@ -119,6 +119,7 @@ type _ t = | MayBeModifiedSinceSetjmp: JmpBufDomain.BufferEntry.t -> VS.t t | MustTermLoop: stmt -> MustBool.t t | MustTermProg: MustBool.t t + | IsEverMultiThreaded: MayBool.t t type 'a result = 'a @@ -185,6 +186,7 @@ struct | MayBeModifiedSinceSetjmp _ -> (module VS) | MustTermLoop _ -> (module MustBool) | MustTermProg -> (module MustBool) + | IsEverMultiThreaded -> (module MayBool) (** Get bottom result for query. *) let bot (type a) (q: a t): a result = @@ -250,6 +252,7 @@ struct | MayBeModifiedSinceSetjmp _ -> VS.top () | MustTermLoop _ -> MustBool.top () | MustTermProg -> MustBool.top () + | IsEverMultiThreaded -> MayBool.top () end (* The type any_query can't be directly defined in Any as t, @@ -312,6 +315,7 @@ struct | Any ThreadsJoinedCleanly -> 52 | Any (MustTermLoop _) -> 53 | Any MustTermProg -> 54 + | Any IsEverMultiThreaded -> 55 let rec compare a b = let r = Stdlib.compare (order a) (order b) in @@ -456,6 +460,7 @@ struct | Any MayBeModifiedSinceSetjmp buf -> Pretty.dprintf "MayBeModifiedSinceSetjmp %a" JmpBufDomain.BufferEntry.pretty buf | Any (MustTermLoop s) -> Pretty.dprintf "MustTermLoop %a" CilType.Stmt.pretty s | Any MustTermProg -> Pretty.dprintf "MustTermProg" + | Any IsEverMultiThreaded -> Pretty.dprintf "IsEverMultiThreaded" end let to_value_domain_ask (ask: ask) = From e8aec04aeb4f550ca4822efc20878ec33674cb60 Mon Sep 17 00:00:00 2001 From: Alexander Schlenga Date: Mon, 3 Jul 2023 12:59:34 +0200 Subject: [PATCH 198/327] Finish and use everMultiThreaded analysis Used by the termination analysis --- src/analyses/everMultiThreaded.ml | 9 +++++---- src/analyses/loop_termination.ml | 2 +- src/autoTune.ml | 2 +- 3 files changed, 7 insertions(+), 6 deletions(-) diff --git a/src/analyses/everMultiThreaded.ml b/src/analyses/everMultiThreaded.ml index c98f173624..5567ef1223 100644 --- a/src/analyses/everMultiThreaded.ml +++ b/src/analyses/everMultiThreaded.ml @@ -32,10 +32,11 @@ struct let query ctx (type a) (q: a Queries.t) : a Queries.result = match q with | Queries.IsEverMultiThreaded -> - (* - ctx.global () - *) - Queries.Result.top q (* TODO *) + (match ctx.global () with + (* I don't know why this wrapping in a match construct is necessary. + * Without it, the compiler throws an error. *) + true -> true + | false -> false) | _ -> Queries.Result.top q diff --git a/src/analyses/loop_termination.ml b/src/analyses/loop_termination.ml index f066fbbab6..4b658071be 100644 --- a/src/analyses/loop_termination.ml +++ b/src/analyses/loop_termination.ml @@ -91,7 +91,7 @@ struct (** Checks whether a new thread was spawned some time. We want to discard * any knowledge about termination then (see query function) *) let must_be_single_threaded_since_start ctx = - ctx.ask (Queries.MustBeSingleThreaded {since_start = true}) + not (ctx.ask Queries.IsEverMultiThreaded) (** Provides information to Goblint *) let query ctx (type a) (q: a Queries.t): a Queries.result = diff --git a/src/autoTune.ml b/src/autoTune.ml index 9468d1d366..9c4fb8f742 100644 --- a/src/autoTune.ml +++ b/src/autoTune.ml @@ -180,7 +180,7 @@ let enableAnalyses anas = List.iter (GobConfig.set_auto "ana.activated[+]") anas (*If only one thread is used in the program, we can disable most thread analyses*) -(*The exceptions are analyses that are depended on by others: base -> mutex -> mutexEvents, access*) +(*The exceptions are analyses that are depended on by others: base -> mutex -> mutexEvents, access; termination -> isEverMultiThreaded *) (*escape is also still enabled, because otherwise we get a warning*) (*does not consider dynamic calls!*) From f8fa8e314339abd704c07421570503ae45206948 Mon Sep 17 00:00:00 2001 From: Alexander Schlenga Date: Mon, 3 Jul 2023 13:35:45 +0200 Subject: [PATCH 199/327] Revert whitespace change --- src/cdomains/intDomain.ml | 1 - 1 file changed, 1 deletion(-) diff --git a/src/cdomains/intDomain.ml b/src/cdomains/intDomain.ml index df0a4c0507..589239810f 100644 --- a/src/cdomains/intDomain.ml +++ b/src/cdomains/intDomain.ml @@ -3263,7 +3263,6 @@ struct let refine_with_incl_list ik a b = a let project ik p t = t - end module SOverflowLifter (D : S) : SOverflow with type int_t = D.int_t and type t = D.t = struct From 4f60156593453f3dac2e86a41b62ad03d0ad4509 Mon Sep 17 00:00:00 2001 From: Isidor Zweckstetter Date: Mon, 3 Jul 2023 16:32:17 +0200 Subject: [PATCH 200/327] added missing __goblint_bounded implementations --- lib/goblint/runtime/include/goblint.h | 2 ++ lib/goblint/runtime/src/goblint.c | 2 +- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/lib/goblint/runtime/include/goblint.h b/lib/goblint/runtime/include/goblint.h index b0af41616e..3c1abae838 100644 --- a/lib/goblint/runtime/include/goblint.h +++ b/lib/goblint/runtime/include/goblint.h @@ -6,3 +6,5 @@ void __goblint_assume_join(/* pthread_t thread */); // undeclared argument to av void __goblint_split_begin(int exp); void __goblint_split_end(int exp); + +void __goblint_bounded(int exp); \ No newline at end of file diff --git a/lib/goblint/runtime/src/goblint.c b/lib/goblint/runtime/src/goblint.c index 39c18c5b8e..7929fcf37a 100644 --- a/lib/goblint/runtime/src/goblint.c +++ b/lib/goblint/runtime/src/goblint.c @@ -29,6 +29,6 @@ void __goblint_split_end(int exp) { } -void __goblint_bounded() { +void __goblint_bounded(int exp) { } \ No newline at end of file From 21f2f3428a6be6c62d3d89e794eecb143d7084e9 Mon Sep 17 00:00:00 2001 From: Alexander Schlenga Date: Mon, 3 Jul 2023 16:38:11 +0200 Subject: [PATCH 201/327] Temp. revert must_be_single_threaded_since_start --- src/analyses/loop_termination.ml | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/analyses/loop_termination.ml b/src/analyses/loop_termination.ml index 4b658071be..7341bcd349 100644 --- a/src/analyses/loop_termination.ml +++ b/src/analyses/loop_termination.ml @@ -91,7 +91,10 @@ struct (** Checks whether a new thread was spawned some time. We want to discard * any knowledge about termination then (see query function) *) let must_be_single_threaded_since_start ctx = + (* not (ctx.ask Queries.IsEverMultiThreaded) + *) + ctx.ask (Queries.MustBeSingleThreaded {since_start = true}) (** Provides information to Goblint *) let query ctx (type a) (q: a Queries.t): a Queries.result = From 048de26d949bde76ebf5ffe597bde7654e675e21 Mon Sep 17 00:00:00 2001 From: Isidor Zweckstetter Date: Wed, 5 Jul 2023 18:04:28 +0200 Subject: [PATCH 202/327] Patched inconsistency with nested loops --- runningGob.sh | 2 +- src/util/terminationPreprocessing.ml | 3 +++ 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/runningGob.sh b/runningGob.sh index fcb5417192..11173bee1f 100755 --- a/runningGob.sh +++ b/runningGob.sh @@ -8,7 +8,7 @@ options_apron="--set ana.activated[+] apron --enable ana.int.interval --set ana. options_signs="--set "ana.activated[+]" signs --enable warn.debug" options_term="--set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra" -cfile_loops="tests/regression/55-loop-unrolling/01-simple-cases.c" +cfile_loops="tests/regression/74-loop_termination/03-nested-loop-terminating.c" cfile_signs="tests/regression/99-tutorials/01-first.c" cfile_goto="tests/incremental/02-cfg-comparison/01-added-return-stmt.c" diff --git a/src/util/terminationPreprocessing.ml b/src/util/terminationPreprocessing.ml index 47a17575c4..4043c6d256 100644 --- a/src/util/terminationPreprocessing.ml +++ b/src/util/terminationPreprocessing.ml @@ -34,7 +34,10 @@ class loopCounterVisitor lc lg le (fd : fundec) = object(self) let init_stmt = mkStmtOneInstr @@ Set (var v, zero, loc, eloc) in let inc_stmt = mkStmtOneInstr @@ Set (var v, increm (Lval (var v)) 1, loc, eloc) in let check_stmt = mkStmtOneInstr @@ Set ((var !le), (Lval (var v)), loc, eloc) in + let inc_stmt2 = mkStmtOneInstr @@ Set (var v, increm (Lval (var v)) 1, loc, eloc) in (match b.bstmts with + | s :: ss -> (*duplicate increment statement here to fix inconsistencies in nested loops*) + b.bstmts <- inc_stmt :: check_stmt :: s :: inc_stmt2 :: ss; | ss -> b.bstmts <- inc_stmt :: check_stmt :: ss; ); From b67eacdbead591b054783c99dde36e1bdd391673 Mon Sep 17 00:00:00 2001 From: Alexander Schlenga Date: Thu, 6 Jul 2023 12:09:01 +0200 Subject: [PATCH 203/327] Rename loop termation analysis Keep camelCase naming convention --- src/analyses/{loop_termination.ml => loopTermination.ml} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename src/analyses/{loop_termination.ml => loopTermination.ml} (100%) diff --git a/src/analyses/loop_termination.ml b/src/analyses/loopTermination.ml similarity index 100% rename from src/analyses/loop_termination.ml rename to src/analyses/loopTermination.ml From 22efd120cd7f59b882b7a68a78b56e784cea96c3 Mon Sep 17 00:00:00 2001 From: Johanna Schinabeck Date: Thu, 6 Jul 2023 12:10:27 +0200 Subject: [PATCH 204/327] changed name --- src/framework/constraints.ml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/framework/constraints.ml b/src/framework/constraints.ml index 55763c5852..d744937d53 100644 --- a/src/framework/constraints.ml +++ b/src/framework/constraints.ml @@ -1717,7 +1717,7 @@ struct module G = GVarGSet (S.G) (S.C) (Printable.Prod (CilType.Fundec) (S.C)) - let name () = "termination" + let name () = "RecursionTermLifter (" ^ S.name () ^ ")" let conv (ctx: (_, G.t, _, V.t) ctx): (_, S.G.t, _, S.V.t) ctx = { ctx with From c5fe485c0de7dbcfce0100f5819d7c2150a90c4e Mon Sep 17 00:00:00 2001 From: Alexander Schlenga Date: Thu, 6 Jul 2023 12:14:22 +0200 Subject: [PATCH 205/327] Remove unused code --- src/analyses/loopTermination.ml | 11 ----------- 1 file changed, 11 deletions(-) diff --git a/src/analyses/loopTermination.ml b/src/analyses/loopTermination.ml index 7341bcd349..d9f8df2f48 100644 --- a/src/analyses/loopTermination.ml +++ b/src/analyses/loopTermination.ml @@ -6,17 +6,6 @@ open TerminationPreprocessing exception PreProcessing of string -(* -let loop_heads () = - let module FileCfg = - struct - let file = !Cilfacade.current_file - module Cfg = (val !MyCFG.current_cfg) - end in - let module WitnessInvariant = WitnessUtil.Invariant (FileCfg) in - WitnessInvariant.loop_heads (* TODO: Unused *) -*) - (** Contains all loop counter variables (varinfo) and maps them to their corresponding loop statement. *) let loop_counters : stmt VarToStmt.t ref = ref VarToStmt.empty From b9a5c361cddce214db5217c3298cf68d56f200ee Mon Sep 17 00:00:00 2001 From: Thomas Lagemann Date: Thu, 6 Jul 2023 12:53:58 +0200 Subject: [PATCH 206/327] Tests adapted and new test 74/35 --- .../09-complex-for-loop-terminating.c | 1 + .../10-complex-loop-terminating.c | 1 + .../15-complex-loop-combination-terminating.c | 1 + .../24-upjumping-goto-loopless-terminating.c | 2 +- .../25-leave-loop-goto-terminating.c | 2 +- .../26-enter-loop-goto-terminating.c | 2 +- .../28-do-while-continue-terminating.c | 4 ++-- .../30-goto-out-of-inner-loop-terminating.c | 3 ++- ...out-of-inner-loop-with-print-terminating.c | 22 +++++++++++++++++++ .../02-simple-nonterminating.c | 2 +- 10 files changed, 33 insertions(+), 7 deletions(-) create mode 100644 tests/regression/74-loop_termination/35-goto-out-of-inner-loop-with-print-terminating.c diff --git a/tests/regression/74-loop_termination/09-complex-for-loop-terminating.c b/tests/regression/74-loop_termination/09-complex-for-loop-terminating.c index 7fb9262aab..30ca32a70a 100644 --- a/tests/regression/74-loop_termination/09-complex-for-loop-terminating.c +++ b/tests/regression/74-loop_termination/09-complex-for-loop-terminating.c @@ -1,4 +1,5 @@ // SKIP TERM PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra +// Goblint does not finish this test #include int main() diff --git a/tests/regression/74-loop_termination/10-complex-loop-terminating.c b/tests/regression/74-loop_termination/10-complex-loop-terminating.c index e39613b563..8970223c6e 100644 --- a/tests/regression/74-loop_termination/10-complex-loop-terminating.c +++ b/tests/regression/74-loop_termination/10-complex-loop-terminating.c @@ -1,4 +1,5 @@ // SKIP TERM PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra +// Goblint does not finish this test #include int main() diff --git a/tests/regression/74-loop_termination/15-complex-loop-combination-terminating.c b/tests/regression/74-loop_termination/15-complex-loop-combination-terminating.c index ad64a9a5f9..099203d13f 100644 --- a/tests/regression/74-loop_termination/15-complex-loop-combination-terminating.c +++ b/tests/regression/74-loop_termination/15-complex-loop-combination-terminating.c @@ -1,4 +1,5 @@ // SKIP TERM PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra +// Goblint does not finish this test #include int main() diff --git a/tests/regression/74-loop_termination/24-upjumping-goto-loopless-terminating.c b/tests/regression/74-loop_termination/24-upjumping-goto-loopless-terminating.c index e256df9986..1dc261d06a 100644 --- a/tests/regression/74-loop_termination/24-upjumping-goto-loopless-terminating.c +++ b/tests/regression/74-loop_termination/24-upjumping-goto-loopless-terminating.c @@ -1,7 +1,7 @@ // TODO TERM PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra #include -int main() { // Currently not able to detect this as terminating +int main() { // Currently not able to detect up-jumping loop free gotos goto mark2; mark1: diff --git a/tests/regression/74-loop_termination/25-leave-loop-goto-terminating.c b/tests/regression/74-loop_termination/25-leave-loop-goto-terminating.c index ce11a73060..cbbb115868 100644 --- a/tests/regression/74-loop_termination/25-leave-loop-goto-terminating.c +++ b/tests/regression/74-loop_termination/25-leave-loop-goto-terminating.c @@ -1,4 +1,4 @@ -// TODO TERM PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain octagon +// TODO TERM PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra #include int main() { diff --git a/tests/regression/74-loop_termination/26-enter-loop-goto-terminating.c b/tests/regression/74-loop_termination/26-enter-loop-goto-terminating.c index 355c1ebf00..17220a589b 100644 --- a/tests/regression/74-loop_termination/26-enter-loop-goto-terminating.c +++ b/tests/regression/74-loop_termination/26-enter-loop-goto-terminating.c @@ -1,4 +1,4 @@ -// TERM PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra +// TODO TERM PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra #include int main() { diff --git a/tests/regression/74-loop_termination/28-do-while-continue-terminating.c b/tests/regression/74-loop_termination/28-do-while-continue-terminating.c index 7f91ecc149..7756b51071 100644 --- a/tests/regression/74-loop_termination/28-do-while-continue-terminating.c +++ b/tests/regression/74-loop_termination/28-do-while-continue-terminating.c @@ -1,4 +1,4 @@ -// TERM PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra +// TODO TERM PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra #include int main() @@ -12,7 +12,7 @@ int main() if (i % 2 == 0) { printf("Skipping %i is even\n", i); - continue; + continue; // This is handled as an goto to line 8 and there an up-jumping goto } } while (i <= 5); diff --git a/tests/regression/74-loop_termination/30-goto-out-of-inner-loop-terminating.c b/tests/regression/74-loop_termination/30-goto-out-of-inner-loop-terminating.c index 6b36919c2d..5662e31dc1 100644 --- a/tests/regression/74-loop_termination/30-goto-out-of-inner-loop-terminating.c +++ b/tests/regression/74-loop_termination/30-goto-out-of-inner-loop-terminating.c @@ -14,8 +14,9 @@ int main() { } printf("(%d, %d) ", i, j); } - printf("\n"); + printf("Not Skipped?\n"); outer_loop:; // Label for the outer loop + printf("Skipped!\n"); } return 0; diff --git a/tests/regression/74-loop_termination/35-goto-out-of-inner-loop-with-print-terminating.c b/tests/regression/74-loop_termination/35-goto-out-of-inner-loop-with-print-terminating.c new file mode 100644 index 0000000000..b418257c56 --- /dev/null +++ b/tests/regression/74-loop_termination/35-goto-out-of-inner-loop-with-print-terminating.c @@ -0,0 +1,22 @@ +// TODO TERM PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra +#include + +int main() { + int rows = 5; + int columns = 5; + + // Outer loop for rows + for (int i = 1; i <= rows; i++) { + // Inner loop for columns + for (int j = 1; j <= columns; j++) { + if (j == 3) { // Apron is not able to detect this + goto outer_loop; // Jump to the label "outer_loop" + } + printf("(%d, %d) ", i, j); + } + outer_loop:; // Label for the outer loop + printf("\n"); + } + + return 0; +} diff --git a/tests/regression/75-recursion_termination/02-simple-nonterminating.c b/tests/regression/75-recursion_termination/02-simple-nonterminating.c index 26f30e726b..0dc3cbcf63 100644 --- a/tests/regression/75-recursion_termination/02-simple-nonterminating.c +++ b/tests/regression/75-recursion_termination/02-simple-nonterminating.c @@ -1,4 +1,4 @@ -// SKIP NONTERM PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra +// NONTERM PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra #include void recursiveFunction(int n) { From 7e12cb506a8897f39f6549251883d3f6d663adae Mon Sep 17 00:00:00 2001 From: Thomas Lagemann Date: Thu, 6 Jul 2023 12:56:06 +0200 Subject: [PATCH 207/327] Tests is now passing --- .../74-loop_termination/30-goto-out-of-inner-loop-terminating.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/regression/74-loop_termination/30-goto-out-of-inner-loop-terminating.c b/tests/regression/74-loop_termination/30-goto-out-of-inner-loop-terminating.c index 5662e31dc1..090f3830d5 100644 --- a/tests/regression/74-loop_termination/30-goto-out-of-inner-loop-terminating.c +++ b/tests/regression/74-loop_termination/30-goto-out-of-inner-loop-terminating.c @@ -1,4 +1,4 @@ -// TODO TERM PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra +// TERM PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra #include int main() { From bc7bef754340c0a35db3c15fc366c88959c150ce Mon Sep 17 00:00:00 2001 From: Alexander Schlenga Date: Thu, 6 Jul 2023 13:14:18 +0200 Subject: [PATCH 208/327] Restrict boundedness checking to postsolving --- src/analyses/loopTermination.ml | 21 +++++++++++---------- 1 file changed, 11 insertions(+), 10 deletions(-) diff --git a/src/analyses/loopTermination.ml b/src/analyses/loopTermination.ml index d9f8df2f48..00c7591ad2 100644 --- a/src/analyses/loopTermination.ml +++ b/src/analyses/loopTermination.ml @@ -62,16 +62,17 @@ struct let exitstate = startstate let assign ctx (lval : lval) (rval : exp) = - (* Detect assignment to loop counter variable *) - match lval, rval with - (Var y, NoOffset), Lval (Var x, NoOffset) when is_loop_exit_indicator y -> - (* Loop exit: Check whether loop counter variable is bounded *) - (* TODO: Move to special *) - let is_bounded = check_bounded ctx x in - let loop_statement = VarToStmt.find x !loop_counters in - ctx.sideg () (G.add (`Lifted loop_statement) is_bounded (ctx.global ())); - () - | _ -> () + if !AnalysisState.postsolving then + (* Detect assignment to loop counter variable *) + match lval, rval with + (Var y, NoOffset), Lval (Var x, NoOffset) when is_loop_exit_indicator y -> + (* Loop exit: Check whether loop counter variable is bounded *) + (* TODO: Move to special *) + let is_bounded = check_bounded ctx x in + let loop_statement = VarToStmt.find x !loop_counters in + ctx.sideg () (G.add (`Lifted loop_statement) is_bounded (ctx.global ())); + () + | _ -> () let special ctx (lval : lval option) (f : varinfo) (arglist : exp list) = (* TODO: Implement check for our special loop exit indicator function *) From 08ad8d0595e52ef49643b1745a86b573468eafdc Mon Sep 17 00:00:00 2001 From: Alexander Schlenga Date: Thu, 6 Jul 2023 13:27:58 +0200 Subject: [PATCH 209/327] Revert "Restrict boundedness checking to postsolving" This reverts commit bc7bef754340c0a35db3c15fc366c88959c150ce. --- src/analyses/loopTermination.ml | 21 ++++++++++----------- 1 file changed, 10 insertions(+), 11 deletions(-) diff --git a/src/analyses/loopTermination.ml b/src/analyses/loopTermination.ml index 00c7591ad2..d9f8df2f48 100644 --- a/src/analyses/loopTermination.ml +++ b/src/analyses/loopTermination.ml @@ -62,17 +62,16 @@ struct let exitstate = startstate let assign ctx (lval : lval) (rval : exp) = - if !AnalysisState.postsolving then - (* Detect assignment to loop counter variable *) - match lval, rval with - (Var y, NoOffset), Lval (Var x, NoOffset) when is_loop_exit_indicator y -> - (* Loop exit: Check whether loop counter variable is bounded *) - (* TODO: Move to special *) - let is_bounded = check_bounded ctx x in - let loop_statement = VarToStmt.find x !loop_counters in - ctx.sideg () (G.add (`Lifted loop_statement) is_bounded (ctx.global ())); - () - | _ -> () + (* Detect assignment to loop counter variable *) + match lval, rval with + (Var y, NoOffset), Lval (Var x, NoOffset) when is_loop_exit_indicator y -> + (* Loop exit: Check whether loop counter variable is bounded *) + (* TODO: Move to special *) + let is_bounded = check_bounded ctx x in + let loop_statement = VarToStmt.find x !loop_counters in + ctx.sideg () (G.add (`Lifted loop_statement) is_bounded (ctx.global ())); + () + | _ -> () let special ctx (lval : lval option) (f : varinfo) (arglist : exp list) = (* TODO: Implement check for our special loop exit indicator function *) From 2e05e9e5710b9a70be84776527906e901ed3b7dd Mon Sep 17 00:00:00 2001 From: Alexander Schlenga Date: Thu, 6 Jul 2023 13:40:51 +0200 Subject: [PATCH 210/327] Restrict boundedness checking to postsolving (fix) --- src/analyses/loopTermination.ml | 39 ++++++++++++++++++++++----------- 1 file changed, 26 insertions(+), 13 deletions(-) diff --git a/src/analyses/loopTermination.ml b/src/analyses/loopTermination.ml index d9f8df2f48..921aef28ee 100644 --- a/src/analyses/loopTermination.ml +++ b/src/analyses/loopTermination.ml @@ -36,7 +36,7 @@ let check_bounded ctx varinfo = module UnitV = struct include Printable.Unit - include StdV + let is_write_only _ = true end (** We want to record termination information of loops and use the loop @@ -62,20 +62,33 @@ struct let exitstate = startstate let assign ctx (lval : lval) (rval : exp) = - (* Detect assignment to loop counter variable *) - match lval, rval with - (Var y, NoOffset), Lval (Var x, NoOffset) when is_loop_exit_indicator y -> - (* Loop exit: Check whether loop counter variable is bounded *) - (* TODO: Move to special *) - let is_bounded = check_bounded ctx x in - let loop_statement = VarToStmt.find x !loop_counters in - ctx.sideg () (G.add (`Lifted loop_statement) is_bounded (ctx.global ())); - () - | _ -> () + if !AnalysisState.postsolving then + (* Detect assignment to loop counter variable *) + match lval, rval with + (Var y, NoOffset), Lval (Var x, NoOffset) when is_loop_exit_indicator y -> + (* Loop exit: Check whether loop counter variable is bounded *) + (* TODO: Move to special *) + let is_bounded = check_bounded ctx x in + let loop_statement = VarToStmt.find x !loop_counters in + ctx.sideg () (G.add (`Lifted loop_statement) is_bounded (ctx.global ())); + () + | _ -> () + else () + (* let special ctx (lval : lval option) (f : varinfo) (arglist : exp list) = - (* TODO: Implement check for our special loop exit indicator function *) - () + (* TODO: Implement check for our special loop exit indicator function *) + if !AnalysisState.postsolving then + match f.vname, arglist with + "__goblint_bounded", [Lval (Var x, NoOffset)] -> + let () = print_endline "schpecial" in + let is_bounded = check_bounded ctx x in + let loop_statement = VarToStmt.find x !loop_counters in + ctx.sideg () (G.add (`Lifted loop_statement) is_bounded (ctx.global ())); + () + | _ -> () + else () + *) (** Checks whether a new thread was spawned some time. We want to discard * any knowledge about termination then (see query function) *) From 0d79d2ace1a5d38931d8204e58a6e844637e96cf Mon Sep 17 00:00:00 2001 From: Thomas Lagemann Date: Thu, 6 Jul 2023 14:06:17 +0200 Subject: [PATCH 211/327] Widen recursion test --- .../75-recursion_termination/02-simple-nonterminating.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/regression/75-recursion_termination/02-simple-nonterminating.c b/tests/regression/75-recursion_termination/02-simple-nonterminating.c index 0dc3cbcf63..d20adea294 100644 --- a/tests/regression/75-recursion_termination/02-simple-nonterminating.c +++ b/tests/regression/75-recursion_termination/02-simple-nonterminating.c @@ -1,4 +1,4 @@ -// NONTERM PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra +// NONTERM PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra --enable ana.context.widen #include void recursiveFunction(int n) { From 1190d63212e2a887633438651e6b4844e6669340 Mon Sep 17 00:00:00 2001 From: Thomas Lagemann Date: Thu, 6 Jul 2023 14:23:36 +0200 Subject: [PATCH 212/327] Adapted test parameter --- .../30-goto-out-of-inner-loop-terminating.c | 2 +- .../35-goto-out-of-inner-loop-with-print-terminating.c | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/tests/regression/74-loop_termination/30-goto-out-of-inner-loop-terminating.c b/tests/regression/74-loop_termination/30-goto-out-of-inner-loop-terminating.c index 090f3830d5..15ce6e395e 100644 --- a/tests/regression/74-loop_termination/30-goto-out-of-inner-loop-terminating.c +++ b/tests/regression/74-loop_termination/30-goto-out-of-inner-loop-terminating.c @@ -9,7 +9,7 @@ int main() { for (int i = 1; i <= rows; i++) { // Inner loop for columns for (int j = 1; j <= columns; j++) { - if (j == 3) { // Apron is not able to detect this + if (j == 3) { goto outer_loop; // Jump to the label "outer_loop" } printf("(%d, %d) ", i, j); diff --git a/tests/regression/74-loop_termination/35-goto-out-of-inner-loop-with-print-terminating.c b/tests/regression/74-loop_termination/35-goto-out-of-inner-loop-with-print-terminating.c index b418257c56..29a8033fdb 100644 --- a/tests/regression/74-loop_termination/35-goto-out-of-inner-loop-with-print-terminating.c +++ b/tests/regression/74-loop_termination/35-goto-out-of-inner-loop-with-print-terminating.c @@ -1,4 +1,4 @@ -// TODO TERM PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra +// TERM PARAM: --set "ana.activated[+]" termination --enable warn.debug --set "ana.activated[+]" apron --enable ana.int.interval --set ana.apron.domain polyhedra --set sem.int.signed_overflow assume_none #include int main() { @@ -9,7 +9,7 @@ int main() { for (int i = 1; i <= rows; i++) { // Inner loop for columns for (int j = 1; j <= columns; j++) { - if (j == 3) { // Apron is not able to detect this + if (j == 3) { goto outer_loop; // Jump to the label "outer_loop" } printf("(%d, %d) ", i, j); From dbe3684a53f6a70367289673a95c9e2529f93b67 Mon Sep 17 00:00:00 2001 From: Johanna Schinabeck Date: Sun, 9 Jul 2023 13:53:55 +0200 Subject: [PATCH 213/327] inlined Groupable C to Map --- runningGob.sh | 11 ++++++++--- src/framework/analyses.ml | 22 ++++++++++------------ 2 files changed, 18 insertions(+), 15 deletions(-) diff --git a/runningGob.sh b/runningGob.sh index 11173bee1f..61dbad53b6 100755 --- a/runningGob.sh +++ b/runningGob.sh @@ -8,7 +8,12 @@ options_apron="--set ana.activated[+] apron --enable ana.int.interval --set ana. options_signs="--set "ana.activated[+]" signs --enable warn.debug" options_term="--set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra" -cfile_loops="tests/regression/74-loop_termination/03-nested-loop-terminating.c" +cfile_loop30="tests/regression/74-loop_termination/30-goto-out-of-inner-loop-terminating.c" +cfile_loop26="tests/regression/74-loop_termination/26-enter-loop-goto-terminating.c" +cfile_loop28="tests/regression/74-loop_termination/28-do-while-continue-terminating.c" +cfile_loop7="tests/regression/74-loop_termination/07-nested-for-loop-terminating.c" +cfile_loop5="tests/regression/74-loop_termination/05-for-loop-terminating.c" +cfile_loop1="tests/regression/74-loop_termination/01-simple-loop-terminating.c" cfile_signs="tests/regression/99-tutorials/01-first.c" cfile_goto="tests/incremental/02-cfg-comparison/01-added-return-stmt.c" @@ -17,8 +22,8 @@ cfile_goto="tests/incremental/02-cfg-comparison/01-added-return-stmt.c" #./goblint $cfile_loops $options_apron --html # run analysis, write cil output to file and enable visualization via html -#./goblint -v $cfile_loops $options_term --enable justcil > output.txt -./goblint $cfile_loops $options_term --html +./goblint $cfile_loop30 $options_term --enable justcil > output.txt +./goblint -v $cfile_loop30 $options_term --html # set up server to see visualizatino python3 -m http.server --directory result 8080 diff --git a/src/framework/analyses.ml b/src/framework/analyses.ml index 9f25a67a0d..faf7c456ca 100644 --- a/src/framework/analyses.ml +++ b/src/framework/analyses.ml @@ -130,20 +130,18 @@ struct BatPrintf.fprintf f "\n\n" end - (* Make the given module Goupable*) - module C_Printable (C: Printable.S) = - struct - include Printable.Std (* To make it Groupable *) - include C - let printXml f c = BatPrintf.fprintf f - "\n - callee_context\n%a\n\n - " printXml c - end - module CMap = struct - include MapDomain.MapBot (C_Printable (C)) (CSet) + include MapDomain.MapBot ( + struct + include Printable.Std (* To make it Groupable *) + include C + let printXml f c = BatPrintf.fprintf f + "\n + callee_context\n%a\n\n + " printXml c + end + ) (CSet) let printXml f c = BatPrintf.fprintf f " ContextTupleMap\n %a\n\n From 68bf1031e9efef23fb5605c79ae8473207b55bda Mon Sep 17 00:00:00 2001 From: Alexander Schlenga Date: Sun, 9 Jul 2023 17:05:53 +0200 Subject: [PATCH 214/327] Rename query MustTermProg to MustTermAllLoops I find the name MustTermProg confusing because it does not consider recursion. --- src/analyses/loopTermination.ml | 2 +- src/domains/queries.ml | 10 +++++----- src/framework/constraints.ml | 16 ++++++++-------- 3 files changed, 14 insertions(+), 14 deletions(-) diff --git a/src/analyses/loopTermination.ml b/src/analyses/loopTermination.ml index 921aef28ee..38823d3039 100644 --- a/src/analyses/loopTermination.ml +++ b/src/analyses/loopTermination.ml @@ -106,7 +106,7 @@ struct Some b -> b | None -> false) && must_be_single_threaded_since_start ctx - | Queries.MustTermProg -> + | Queries.MustTermAllLoops -> G.for_all (fun _ term_info -> term_info) (ctx.global ()) && no_upjumping_gotos () && must_be_single_threaded_since_start ctx diff --git a/src/domains/queries.ml b/src/domains/queries.ml index 2810f07342..8ff37b6d2c 100644 --- a/src/domains/queries.ml +++ b/src/domains/queries.ml @@ -118,7 +118,7 @@ type _ t = | MayBeTainted: LS.t t | MayBeModifiedSinceSetjmp: JmpBufDomain.BufferEntry.t -> VS.t t | MustTermLoop: stmt -> MustBool.t t - | MustTermProg: MustBool.t t + | MustTermAllLoops: MustBool.t t | IsEverMultiThreaded: MayBool.t t type 'a result = 'a @@ -185,7 +185,7 @@ struct | MayBeTainted -> (module LS) | MayBeModifiedSinceSetjmp _ -> (module VS) | MustTermLoop _ -> (module MustBool) - | MustTermProg -> (module MustBool) + | MustTermAllLoops -> (module MustBool) | IsEverMultiThreaded -> (module MayBool) (** Get bottom result for query. *) @@ -251,7 +251,7 @@ struct | MayBeTainted -> LS.top () | MayBeModifiedSinceSetjmp _ -> VS.top () | MustTermLoop _ -> MustBool.top () - | MustTermProg -> MustBool.top () + | MustTermAllLoops -> MustBool.top () | IsEverMultiThreaded -> MayBool.top () end @@ -314,7 +314,7 @@ struct | Any ThreadCreateIndexedNode -> 51 | Any ThreadsJoinedCleanly -> 52 | Any (MustTermLoop _) -> 53 - | Any MustTermProg -> 54 + | Any MustTermAllLoops -> 54 | Any IsEverMultiThreaded -> 55 let rec compare a b = @@ -459,7 +459,7 @@ struct | Any DYojson -> Pretty.dprintf "DYojson" | Any MayBeModifiedSinceSetjmp buf -> Pretty.dprintf "MayBeModifiedSinceSetjmp %a" JmpBufDomain.BufferEntry.pretty buf | Any (MustTermLoop s) -> Pretty.dprintf "MustTermLoop %a" CilType.Stmt.pretty s - | Any MustTermProg -> Pretty.dprintf "MustTermProg" + | Any MustTermAllLoops -> Pretty.dprintf "MustTermAllLoops" | Any IsEverMultiThreaded -> Pretty.dprintf "IsEverMultiThreaded" end diff --git a/src/framework/constraints.ml b/src/framework/constraints.ml index 55763c5852..27edc4f520 100644 --- a/src/framework/constraints.ml +++ b/src/framework/constraints.ml @@ -1701,13 +1701,13 @@ module RecursionTermLifter (S: Spec) and module C = S.C = (* two global invariants: - - V -> G - Needed to store the previously built global invariants - - fundec -> Map (S.C) (Set (fundec * S.C)) - The second global invariant maps from the callee fundec to a map, containing the callee context and the caller fundec and context. - This structure therefore stores the context-sensitive call graph. - For example: - let the function f in context c call function g in context c'. + - V -> G + Needed to store the previously built global invariants + - fundec -> Map (S.C) (Set (fundec * S.C)) + The second global invariant maps from the callee fundec to a map, containing the callee context and the caller fundec and context. + This structure therefore stores the context-sensitive call graph. + For example: + let the function f in context c call function g in context c'. In the global invariant structure it would be stored like this: g -> {c' -> {(f, c)}} *) @@ -1769,7 +1769,7 @@ struct match q with | WarnGlobal v -> (* check result of loop analysis *) - if not (ctx.ask Queries.MustTermProg) then + if not (ctx.ask Queries.MustTermAllLoops) then (AnalysisState.svcomp_may_not_terminate := true; let msgs = [ From fbc2966201c3af0648d36c71b1e09f7597a7a791 Mon Sep 17 00:00:00 2001 From: Thomas Lagemann Date: Sun, 9 Jul 2023 18:16:57 +0200 Subject: [PATCH 215/327] Test moved and renamed --- .../01-simple-loop-terminating.c | 0 .../02-simple-loop-nonterminating.c | 0 .../03-nested-loop-terminating.c | 0 .../04-nested-loop-nonterminating.c | 0 .../05-for-loop-terminating.c | 0 .../06-for-loop-nonterminating.c | 0 .../07-nested-for-loop-terminating.c | 0 .../08-nested-for-loop-nonterminating.c | 0 .../09-complex-for-loop-terminating.c | 0 .../10-complex-loop-terminating.c | 0 .../11-loopless-termination.c | 0 .../12-do-while-instant-terminating.c | 0 .../13-do-while-terminating.c | 0 .../14-do-while-nonterminating.c | 0 .../15-complex-loop-combination-terminating.c | 0 .../16-nested-loop-nontrivial-nonterminating.c | 0 .../{74-loop_termination => 75-termination}/17-goto-terminating.c | 0 .../18-goto-nonterminating.c | 0 .../{74-loop_termination => 75-termination}/19-rand-terminating.c | 0 .../20-rand-nonterminating.c | 0 .../21-no-exit-on-rand-unproofable.c | 0 .../22-exit-on-rand-unproofable.c | 0 .../23-exit-on-rand-terminating.c | 0 .../24-upjumping-goto-loopless-terminating.c | 0 .../25-leave-loop-goto-terminating.c | 0 .../26-enter-loop-goto-terminating.c | 0 .../27-upjumping-goto-nonterminating.c | 0 .../28-do-while-continue-terminating.c | 0 .../29-do-while-continue-nonterminating.c | 0 .../30-goto-out-of-inner-loop-terminating.c | 0 .../31-goto-out-of-inner-loop-nonterminating.c | 0 .../32-multithread-terminating.c | 0 .../33-multithread-nonterminating.c | 0 .../34-nested-for-loop-nonterminating.c | 0 .../35-goto-out-of-inner-loop-with-print-terminating.c | 0 .../36-recursion-terminating.c} | 0 .../37-recursion-nonterminating.c} | 0 .../38-recursion-nested-terminating.c} | 0 .../39-recursion-nested-nonterminating.c} | 0 39 files changed, 0 insertions(+), 0 deletions(-) rename tests/regression/{74-loop_termination => 75-termination}/01-simple-loop-terminating.c (100%) rename tests/regression/{74-loop_termination => 75-termination}/02-simple-loop-nonterminating.c (100%) rename tests/regression/{74-loop_termination => 75-termination}/03-nested-loop-terminating.c (100%) rename tests/regression/{74-loop_termination => 75-termination}/04-nested-loop-nonterminating.c (100%) rename tests/regression/{74-loop_termination => 75-termination}/05-for-loop-terminating.c (100%) rename tests/regression/{74-loop_termination => 75-termination}/06-for-loop-nonterminating.c (100%) rename tests/regression/{74-loop_termination => 75-termination}/07-nested-for-loop-terminating.c (100%) rename tests/regression/{74-loop_termination => 75-termination}/08-nested-for-loop-nonterminating.c (100%) rename tests/regression/{74-loop_termination => 75-termination}/09-complex-for-loop-terminating.c (100%) rename tests/regression/{74-loop_termination => 75-termination}/10-complex-loop-terminating.c (100%) rename tests/regression/{74-loop_termination => 75-termination}/11-loopless-termination.c (100%) rename tests/regression/{74-loop_termination => 75-termination}/12-do-while-instant-terminating.c (100%) rename tests/regression/{74-loop_termination => 75-termination}/13-do-while-terminating.c (100%) rename tests/regression/{74-loop_termination => 75-termination}/14-do-while-nonterminating.c (100%) rename tests/regression/{74-loop_termination => 75-termination}/15-complex-loop-combination-terminating.c (100%) rename tests/regression/{74-loop_termination => 75-termination}/16-nested-loop-nontrivial-nonterminating.c (100%) rename tests/regression/{74-loop_termination => 75-termination}/17-goto-terminating.c (100%) rename tests/regression/{74-loop_termination => 75-termination}/18-goto-nonterminating.c (100%) rename tests/regression/{74-loop_termination => 75-termination}/19-rand-terminating.c (100%) rename tests/regression/{74-loop_termination => 75-termination}/20-rand-nonterminating.c (100%) rename tests/regression/{74-loop_termination => 75-termination}/21-no-exit-on-rand-unproofable.c (100%) rename tests/regression/{74-loop_termination => 75-termination}/22-exit-on-rand-unproofable.c (100%) rename tests/regression/{74-loop_termination => 75-termination}/23-exit-on-rand-terminating.c (100%) rename tests/regression/{74-loop_termination => 75-termination}/24-upjumping-goto-loopless-terminating.c (100%) rename tests/regression/{74-loop_termination => 75-termination}/25-leave-loop-goto-terminating.c (100%) rename tests/regression/{74-loop_termination => 75-termination}/26-enter-loop-goto-terminating.c (100%) rename tests/regression/{74-loop_termination => 75-termination}/27-upjumping-goto-nonterminating.c (100%) rename tests/regression/{74-loop_termination => 75-termination}/28-do-while-continue-terminating.c (100%) rename tests/regression/{74-loop_termination => 75-termination}/29-do-while-continue-nonterminating.c (100%) rename tests/regression/{74-loop_termination => 75-termination}/30-goto-out-of-inner-loop-terminating.c (100%) rename tests/regression/{74-loop_termination => 75-termination}/31-goto-out-of-inner-loop-nonterminating.c (100%) rename tests/regression/{74-loop_termination => 75-termination}/32-multithread-terminating.c (100%) rename tests/regression/{74-loop_termination => 75-termination}/33-multithread-nonterminating.c (100%) rename tests/regression/{74-loop_termination => 75-termination}/34-nested-for-loop-nonterminating.c (100%) rename tests/regression/{74-loop_termination => 75-termination}/35-goto-out-of-inner-loop-with-print-terminating.c (100%) rename tests/regression/{75-recursion_termination/01-simple-terminating.c => 75-termination/36-recursion-terminating.c} (100%) rename tests/regression/{75-recursion_termination/02-simple-nonterminating.c => 75-termination/37-recursion-nonterminating.c} (100%) rename tests/regression/{75-recursion_termination/03-nested-terminating.c => 75-termination/38-recursion-nested-terminating.c} (100%) rename tests/regression/{75-recursion_termination/04-nested-nonterminating.c => 75-termination/39-recursion-nested-nonterminating.c} (100%) diff --git a/tests/regression/74-loop_termination/01-simple-loop-terminating.c b/tests/regression/75-termination/01-simple-loop-terminating.c similarity index 100% rename from tests/regression/74-loop_termination/01-simple-loop-terminating.c rename to tests/regression/75-termination/01-simple-loop-terminating.c diff --git a/tests/regression/74-loop_termination/02-simple-loop-nonterminating.c b/tests/regression/75-termination/02-simple-loop-nonterminating.c similarity index 100% rename from tests/regression/74-loop_termination/02-simple-loop-nonterminating.c rename to tests/regression/75-termination/02-simple-loop-nonterminating.c diff --git a/tests/regression/74-loop_termination/03-nested-loop-terminating.c b/tests/regression/75-termination/03-nested-loop-terminating.c similarity index 100% rename from tests/regression/74-loop_termination/03-nested-loop-terminating.c rename to tests/regression/75-termination/03-nested-loop-terminating.c diff --git a/tests/regression/74-loop_termination/04-nested-loop-nonterminating.c b/tests/regression/75-termination/04-nested-loop-nonterminating.c similarity index 100% rename from tests/regression/74-loop_termination/04-nested-loop-nonterminating.c rename to tests/regression/75-termination/04-nested-loop-nonterminating.c diff --git a/tests/regression/74-loop_termination/05-for-loop-terminating.c b/tests/regression/75-termination/05-for-loop-terminating.c similarity index 100% rename from tests/regression/74-loop_termination/05-for-loop-terminating.c rename to tests/regression/75-termination/05-for-loop-terminating.c diff --git a/tests/regression/74-loop_termination/06-for-loop-nonterminating.c b/tests/regression/75-termination/06-for-loop-nonterminating.c similarity index 100% rename from tests/regression/74-loop_termination/06-for-loop-nonterminating.c rename to tests/regression/75-termination/06-for-loop-nonterminating.c diff --git a/tests/regression/74-loop_termination/07-nested-for-loop-terminating.c b/tests/regression/75-termination/07-nested-for-loop-terminating.c similarity index 100% rename from tests/regression/74-loop_termination/07-nested-for-loop-terminating.c rename to tests/regression/75-termination/07-nested-for-loop-terminating.c diff --git a/tests/regression/74-loop_termination/08-nested-for-loop-nonterminating.c b/tests/regression/75-termination/08-nested-for-loop-nonterminating.c similarity index 100% rename from tests/regression/74-loop_termination/08-nested-for-loop-nonterminating.c rename to tests/regression/75-termination/08-nested-for-loop-nonterminating.c diff --git a/tests/regression/74-loop_termination/09-complex-for-loop-terminating.c b/tests/regression/75-termination/09-complex-for-loop-terminating.c similarity index 100% rename from tests/regression/74-loop_termination/09-complex-for-loop-terminating.c rename to tests/regression/75-termination/09-complex-for-loop-terminating.c diff --git a/tests/regression/74-loop_termination/10-complex-loop-terminating.c b/tests/regression/75-termination/10-complex-loop-terminating.c similarity index 100% rename from tests/regression/74-loop_termination/10-complex-loop-terminating.c rename to tests/regression/75-termination/10-complex-loop-terminating.c diff --git a/tests/regression/74-loop_termination/11-loopless-termination.c b/tests/regression/75-termination/11-loopless-termination.c similarity index 100% rename from tests/regression/74-loop_termination/11-loopless-termination.c rename to tests/regression/75-termination/11-loopless-termination.c diff --git a/tests/regression/74-loop_termination/12-do-while-instant-terminating.c b/tests/regression/75-termination/12-do-while-instant-terminating.c similarity index 100% rename from tests/regression/74-loop_termination/12-do-while-instant-terminating.c rename to tests/regression/75-termination/12-do-while-instant-terminating.c diff --git a/tests/regression/74-loop_termination/13-do-while-terminating.c b/tests/regression/75-termination/13-do-while-terminating.c similarity index 100% rename from tests/regression/74-loop_termination/13-do-while-terminating.c rename to tests/regression/75-termination/13-do-while-terminating.c diff --git a/tests/regression/74-loop_termination/14-do-while-nonterminating.c b/tests/regression/75-termination/14-do-while-nonterminating.c similarity index 100% rename from tests/regression/74-loop_termination/14-do-while-nonterminating.c rename to tests/regression/75-termination/14-do-while-nonterminating.c diff --git a/tests/regression/74-loop_termination/15-complex-loop-combination-terminating.c b/tests/regression/75-termination/15-complex-loop-combination-terminating.c similarity index 100% rename from tests/regression/74-loop_termination/15-complex-loop-combination-terminating.c rename to tests/regression/75-termination/15-complex-loop-combination-terminating.c diff --git a/tests/regression/74-loop_termination/16-nested-loop-nontrivial-nonterminating.c b/tests/regression/75-termination/16-nested-loop-nontrivial-nonterminating.c similarity index 100% rename from tests/regression/74-loop_termination/16-nested-loop-nontrivial-nonterminating.c rename to tests/regression/75-termination/16-nested-loop-nontrivial-nonterminating.c diff --git a/tests/regression/74-loop_termination/17-goto-terminating.c b/tests/regression/75-termination/17-goto-terminating.c similarity index 100% rename from tests/regression/74-loop_termination/17-goto-terminating.c rename to tests/regression/75-termination/17-goto-terminating.c diff --git a/tests/regression/74-loop_termination/18-goto-nonterminating.c b/tests/regression/75-termination/18-goto-nonterminating.c similarity index 100% rename from tests/regression/74-loop_termination/18-goto-nonterminating.c rename to tests/regression/75-termination/18-goto-nonterminating.c diff --git a/tests/regression/74-loop_termination/19-rand-terminating.c b/tests/regression/75-termination/19-rand-terminating.c similarity index 100% rename from tests/regression/74-loop_termination/19-rand-terminating.c rename to tests/regression/75-termination/19-rand-terminating.c diff --git a/tests/regression/74-loop_termination/20-rand-nonterminating.c b/tests/regression/75-termination/20-rand-nonterminating.c similarity index 100% rename from tests/regression/74-loop_termination/20-rand-nonterminating.c rename to tests/regression/75-termination/20-rand-nonterminating.c diff --git a/tests/regression/74-loop_termination/21-no-exit-on-rand-unproofable.c b/tests/regression/75-termination/21-no-exit-on-rand-unproofable.c similarity index 100% rename from tests/regression/74-loop_termination/21-no-exit-on-rand-unproofable.c rename to tests/regression/75-termination/21-no-exit-on-rand-unproofable.c diff --git a/tests/regression/74-loop_termination/22-exit-on-rand-unproofable.c b/tests/regression/75-termination/22-exit-on-rand-unproofable.c similarity index 100% rename from tests/regression/74-loop_termination/22-exit-on-rand-unproofable.c rename to tests/regression/75-termination/22-exit-on-rand-unproofable.c diff --git a/tests/regression/74-loop_termination/23-exit-on-rand-terminating.c b/tests/regression/75-termination/23-exit-on-rand-terminating.c similarity index 100% rename from tests/regression/74-loop_termination/23-exit-on-rand-terminating.c rename to tests/regression/75-termination/23-exit-on-rand-terminating.c diff --git a/tests/regression/74-loop_termination/24-upjumping-goto-loopless-terminating.c b/tests/regression/75-termination/24-upjumping-goto-loopless-terminating.c similarity index 100% rename from tests/regression/74-loop_termination/24-upjumping-goto-loopless-terminating.c rename to tests/regression/75-termination/24-upjumping-goto-loopless-terminating.c diff --git a/tests/regression/74-loop_termination/25-leave-loop-goto-terminating.c b/tests/regression/75-termination/25-leave-loop-goto-terminating.c similarity index 100% rename from tests/regression/74-loop_termination/25-leave-loop-goto-terminating.c rename to tests/regression/75-termination/25-leave-loop-goto-terminating.c diff --git a/tests/regression/74-loop_termination/26-enter-loop-goto-terminating.c b/tests/regression/75-termination/26-enter-loop-goto-terminating.c similarity index 100% rename from tests/regression/74-loop_termination/26-enter-loop-goto-terminating.c rename to tests/regression/75-termination/26-enter-loop-goto-terminating.c diff --git a/tests/regression/74-loop_termination/27-upjumping-goto-nonterminating.c b/tests/regression/75-termination/27-upjumping-goto-nonterminating.c similarity index 100% rename from tests/regression/74-loop_termination/27-upjumping-goto-nonterminating.c rename to tests/regression/75-termination/27-upjumping-goto-nonterminating.c diff --git a/tests/regression/74-loop_termination/28-do-while-continue-terminating.c b/tests/regression/75-termination/28-do-while-continue-terminating.c similarity index 100% rename from tests/regression/74-loop_termination/28-do-while-continue-terminating.c rename to tests/regression/75-termination/28-do-while-continue-terminating.c diff --git a/tests/regression/74-loop_termination/29-do-while-continue-nonterminating.c b/tests/regression/75-termination/29-do-while-continue-nonterminating.c similarity index 100% rename from tests/regression/74-loop_termination/29-do-while-continue-nonterminating.c rename to tests/regression/75-termination/29-do-while-continue-nonterminating.c diff --git a/tests/regression/74-loop_termination/30-goto-out-of-inner-loop-terminating.c b/tests/regression/75-termination/30-goto-out-of-inner-loop-terminating.c similarity index 100% rename from tests/regression/74-loop_termination/30-goto-out-of-inner-loop-terminating.c rename to tests/regression/75-termination/30-goto-out-of-inner-loop-terminating.c diff --git a/tests/regression/74-loop_termination/31-goto-out-of-inner-loop-nonterminating.c b/tests/regression/75-termination/31-goto-out-of-inner-loop-nonterminating.c similarity index 100% rename from tests/regression/74-loop_termination/31-goto-out-of-inner-loop-nonterminating.c rename to tests/regression/75-termination/31-goto-out-of-inner-loop-nonterminating.c diff --git a/tests/regression/74-loop_termination/32-multithread-terminating.c b/tests/regression/75-termination/32-multithread-terminating.c similarity index 100% rename from tests/regression/74-loop_termination/32-multithread-terminating.c rename to tests/regression/75-termination/32-multithread-terminating.c diff --git a/tests/regression/74-loop_termination/33-multithread-nonterminating.c b/tests/regression/75-termination/33-multithread-nonterminating.c similarity index 100% rename from tests/regression/74-loop_termination/33-multithread-nonterminating.c rename to tests/regression/75-termination/33-multithread-nonterminating.c diff --git a/tests/regression/74-loop_termination/34-nested-for-loop-nonterminating.c b/tests/regression/75-termination/34-nested-for-loop-nonterminating.c similarity index 100% rename from tests/regression/74-loop_termination/34-nested-for-loop-nonterminating.c rename to tests/regression/75-termination/34-nested-for-loop-nonterminating.c diff --git a/tests/regression/74-loop_termination/35-goto-out-of-inner-loop-with-print-terminating.c b/tests/regression/75-termination/35-goto-out-of-inner-loop-with-print-terminating.c similarity index 100% rename from tests/regression/74-loop_termination/35-goto-out-of-inner-loop-with-print-terminating.c rename to tests/regression/75-termination/35-goto-out-of-inner-loop-with-print-terminating.c diff --git a/tests/regression/75-recursion_termination/01-simple-terminating.c b/tests/regression/75-termination/36-recursion-terminating.c similarity index 100% rename from tests/regression/75-recursion_termination/01-simple-terminating.c rename to tests/regression/75-termination/36-recursion-terminating.c diff --git a/tests/regression/75-recursion_termination/02-simple-nonterminating.c b/tests/regression/75-termination/37-recursion-nonterminating.c similarity index 100% rename from tests/regression/75-recursion_termination/02-simple-nonterminating.c rename to tests/regression/75-termination/37-recursion-nonterminating.c diff --git a/tests/regression/75-recursion_termination/03-nested-terminating.c b/tests/regression/75-termination/38-recursion-nested-terminating.c similarity index 100% rename from tests/regression/75-recursion_termination/03-nested-terminating.c rename to tests/regression/75-termination/38-recursion-nested-terminating.c diff --git a/tests/regression/75-recursion_termination/04-nested-nonterminating.c b/tests/regression/75-termination/39-recursion-nested-nonterminating.c similarity index 100% rename from tests/regression/75-recursion_termination/04-nested-nonterminating.c rename to tests/regression/75-termination/39-recursion-nested-nonterminating.c From 4a6714c1662a26f4aa639c2203bc3c65512f0c88 Mon Sep 17 00:00:00 2001 From: Johanna Schinabeck Date: Sun, 9 Jul 2023 18:18:48 +0200 Subject: [PATCH 216/327] added comments to explain why test 74/28 does fail and why 30 and 35 might behave differently; also restructured module G in the recursionTermLifter --- src/framework/analyses.ml | 54 -------------- src/framework/constraints.ml | 74 +++++++++++++++++-- .../28-do-while-continue-terminating.c | 72 ++++++++++++++++++ .../30-goto-out-of-inner-loop-terminating.c | 8 ++ ...out-of-inner-loop-with-print-terminating.c | 12 +++ 5 files changed, 160 insertions(+), 60 deletions(-) diff --git a/src/framework/analyses.ml b/src/framework/analyses.ml index faf7c456ca..cd611a9faf 100644 --- a/src/framework/analyses.ml +++ b/src/framework/analyses.ml @@ -118,60 +118,6 @@ struct | x -> BatPrintf.fprintf f "%a" printXml x end -module GVarGSet (G: Lattice.S) (C: Printable.S) (Base: Printable.S) = -struct - module CSet = - struct - include SetDomain.Make (Base) (* Set of Tuples*) - let name () = "contexts" - let printXml f a = - BatPrintf.fprintf f "\n"; - iter (Base.printXml f) a; - BatPrintf.fprintf f "\n\n" - end - - module CMap = - struct - include MapDomain.MapBot ( - struct - include Printable.Std (* To make it Groupable *) - include C - let printXml f c = BatPrintf.fprintf f - "\n - callee_context\n%a\n\n - " printXml c - end - ) (CSet) - let printXml f c = BatPrintf.fprintf f " - ContextTupleMap\n - %a\n\n - " printXml c - end - - include Lattice.Lift2 (G) (CMap) (Printable.DefaultNames) - - let spec = function - | `Bot -> G.bot () - | `Lifted1 x -> x - | _ -> failwith "GVarGSet.spec" - let contexts = function - | `Bot -> CSet.bot () - | `Lifted2 x -> x - | _ -> failwith "GVarGSet.contexts" - let create_spec spec = `Lifted1 spec - let create_contexts contexts = `Lifted2 contexts - - let printXml f = function - | `Lifted1 x -> G.printXml f x - | `Lifted2 x -> BatPrintf.fprintf f "%a" CMap.printXml x - | x -> BatPrintf.fprintf f "%a" printXml x - - let base2 instance = - match instance with - | `Lifted2 n -> Some n - | _ -> None -end - exception Deadcode (** [Dom (D)] produces D lifted where bottom means dead-code *) diff --git a/src/framework/constraints.ml b/src/framework/constraints.ml index d744937d53..047bdf7e38 100644 --- a/src/framework/constraints.ml +++ b/src/framework/constraints.ml @@ -1713,9 +1713,71 @@ module RecursionTermLifter (S: Spec) struct include S + + (* contains all the callee fundecs*) module V = GVarF(S.V) - module G = GVarGSet (S.G) (S.C) (Printable.Prod (CilType.Fundec) (S.C)) + (* Tuple containing the fundec and context of the caller *) + module CallGraphTuple = + struct + include Printable.Prod (CilType.Fundec) (S.C) + end + + (* Set containing multiple caller tuples *) + module CallGraphSet = + struct + include SetDomain.Make (CallGraphTuple) + let name () = "callerInfo" + let printXml f a = + BatPrintf.fprintf f "\n"; + iter (CallGraphTuple.printXml f) a; + BatPrintf.fprintf f "\n\n" + end + + (* Mapping from the callee context to the set of all caller tuples*) + module CallGraphMap = + struct + include MapDomain.MapBot ( + struct + include Printable.Std (* To make it Groupable *) + include S.C + let printXml f c = BatPrintf.fprintf f + "\n + callee_context\n%a\n\n + " printXml c + end + ) (CallGraphSet) + let printXml f c = BatPrintf.fprintf f " + ContextTupleMap\n + %a\n\n + " printXml c + end + + module G = + struct + include Lattice.Lift2 (G) (CallGraphMap) (Printable.DefaultNames) + + let spec = function + | `Bot -> G.bot () + | `Lifted1 x -> x + | _ -> failwith "RecursionTermLifter.spec" + let callGraph = function + | `Bot -> CallGraphMap.bot () + | `Lifted2 x -> x + | _ -> failwith "RecursionTermLifter.callGraph" + let create_spec spec = `Lifted1 spec + let create_callGraph callGraph = `Lifted2 callGraph + + let printXml f = function + | `Lifted1 x -> G.printXml f x + | `Lifted2 x -> BatPrintf.fprintf f "%a" CallGraphMap.printXml x + | x -> BatPrintf.fprintf f "%a" printXml x + + let base2 instance = + match instance with + | `Lifted2 n -> Some n + | _ -> None + end let name () = "RecursionTermLifter (" ^ S.name () ^ ")" @@ -1749,8 +1811,8 @@ struct let fundec_e_typeV: V.t = V.relift (`Right fundec_e) in let gmap_opt = G.base2 (ctx.global (fundec_e_typeV)) in let gmap = Option.get (gmap_opt) in (*might be empty*) - let callers: G.CSet.t = G.CMap.find (context_e) gmap in - G.CSet.iter (fun to_call -> + let callers: CallGraphSet.t = CallGraphMap.find (context_e) gmap in + CallGraphSet.iter (fun to_call -> iter_call new_path_visited_calls to_call ) callers; with Invalid_argument _ -> () (* path ended: no cycle*) @@ -1759,7 +1821,7 @@ struct try let gmap_opt = G.base2 (ctx.global (v)) in let gmap = Option.get (gmap_opt) in - G.CMap.iter(fun key value -> + CallGraphMap.iter(fun key value -> let call = (v', key) in iter_call LS.empty call ) gmap (* try all fundec + context pairs that are in the map *) @@ -1802,7 +1864,7 @@ struct *) let side_context sideg f c t = if !AnalysisState.postsolving then - sideg (V.contexts f) (G.create_contexts (G.CMap.singleton (c) (t))) + sideg (V.contexts f) (G.create_callGraph (CallGraphMap.singleton (c) (t))) let enter ctx = S.enter (conv ctx) let paths_as_set ctx = S.paths_as_set (conv ctx) @@ -1816,7 +1878,7 @@ struct let c_e: S.C.t = Option.get fc in (*Callee context*) let fd_e : fundec = f in (*Callee fundec*) let tup: (fundec * S.C.t) = (fd_r, c_r) in - let t = G.CSet.singleton (tup) in + let t = CallGraphSet.singleton (tup) in side_context ctx.sideg fd_e (c_e) t; S.combine_env (conv ctx) r fe f args fc es f_ask else diff --git a/tests/regression/74-loop_termination/28-do-while-continue-terminating.c b/tests/regression/74-loop_termination/28-do-while-continue-terminating.c index 7756b51071..f05fa4f315 100644 --- a/tests/regression/74-loop_termination/28-do-while-continue-terminating.c +++ b/tests/regression/74-loop_termination/28-do-while-continue-terminating.c @@ -19,3 +19,75 @@ int main() printf("Exited the loop\n"); return 0; } + +/* +NOTE: +Test 28: does not terminate but should terminate (test case "28-do-while-continue-terminating.c") +Reason: upjumping goto + +If one has a look at the generated CIL output (attached at the bottom of this file), one can see that the "continue" is +translated in a "goto" with a corresponding label "__Cont". This label points to the loop-exit condition. Since the condition +is part of the loop, its location is evaluated to 8-17. +The location of the goto "goto __Cont" is located in line 15. +To provide soundness for the analysis, the preprocessing detects upjumping gotos with the help of its location. +In case such a goto is detected, the program is classified as non-terminating. +Due to this inserted goto (which is a result of the "continue"), an upjumping goto is located, which makes this program non-terminating. + +It should be noted that this issue happens when "do while"-loops and "continues" are combined. +If one combines "while"-loops and "continues", the analysis can still classify the loop as terminating. +The reason for that can be seen in the second CIL output, where the "do while"-loop is replaced by a "while"-loop. +Instead of creating a new label, the "while-continue" label of the loop is reused. Also, this goto statement is not specified as a goto, +but as a Continue statement. Hence, it is not analyzed for the upjumping gotos, which does not lead to the problem as with the "do while". + + +------------------- SHORTENED CIL output for Test 28 (DO WHILE): ------------------- +int main(void) +{{{{ + #line 8 + while (1) { + while_continue: ; + #line 12 + if (i % 2 == 0) { + #line 15 + goto __Cont; + } + __Cont: + #line 8 + if (! (i <= 5)) { + #line 8 + goto while_break; + } + } + + while_break: + }} + #line 20 + return (0); +}} + + +------------------- SHORTENED CIL output for Test 28 (WHILE): ------------------- +Test 28: replacing DO WHILE with WHILE: +int main(void) +{{{{ + #line 8 + while (1) { + while_continue: ; + #line 8 + if (! (i <= 5)) { + #line 8 + goto while_break; + } + #line 12 + if (i % 2 == 0) { + #line 15 + goto while_continue; + } + } + while_break: ; + }} + #line 20 + return (0); +}} + +*/ diff --git a/tests/regression/74-loop_termination/30-goto-out-of-inner-loop-terminating.c b/tests/regression/74-loop_termination/30-goto-out-of-inner-loop-terminating.c index 15ce6e395e..a92dcd2bc8 100644 --- a/tests/regression/74-loop_termination/30-goto-out-of-inner-loop-terminating.c +++ b/tests/regression/74-loop_termination/30-goto-out-of-inner-loop-terminating.c @@ -21,3 +21,11 @@ int main() { return 0; } + +/* +NOTE: In case we do NOT assume no-overflow: +Test 30: terminates (test case "30-goto-out-of-inner-loop-terminating.c") +Test 35: does not terminate (test case "35-goto-out-of-inner-loop-with-print-terminating.c") + +The reason is explained in "35-goto-out-of-inner-loop-with-print-terminating.c" +*/ diff --git a/tests/regression/74-loop_termination/35-goto-out-of-inner-loop-with-print-terminating.c b/tests/regression/74-loop_termination/35-goto-out-of-inner-loop-with-print-terminating.c index 29a8033fdb..bb8bbacbf0 100644 --- a/tests/regression/74-loop_termination/35-goto-out-of-inner-loop-with-print-terminating.c +++ b/tests/regression/74-loop_termination/35-goto-out-of-inner-loop-with-print-terminating.c @@ -20,3 +20,15 @@ int main() { return 0; } + +/* +NOTE: In case we do NOT assume no-overflow: +Test 30: terminates (test case "30-goto-out-of-inner-loop-terminating.c") +Test 35: does not terminate (test case "35-goto-out-of-inner-loop-with-print-terminating.c") + +The only difference between Test 30 and Test 35 is line 17. Test 30 has an additional statement, and Test 35 continues already with the label. +This difference in Test 35 leads to an overflow in line 11, and hence to the non-termination. +This overflow is created by a WPoint Issue. By enabling the no-overflow option this issue can be fixed and, both test cases are correctly detected as terminating. + +(The overflow also happens without the termination analysis enabled.) +*/ From cb13d1497b77e26595bac26017afb5ec627bd39c Mon Sep 17 00:00:00 2001 From: Thomas Lagemann Date: Sun, 9 Jul 2023 18:25:33 +0200 Subject: [PATCH 217/327] Tests moved --- .../09-complex-for-loop-terminating.c | 0 .../10-complex-loop-terminating.c | 0 .../15-complex-loop-combination-terminating.c | 0 3 files changed, 0 insertions(+), 0 deletions(-) rename tests/regression/{75-termination => 76-termination-complex-cases}/09-complex-for-loop-terminating.c (100%) rename tests/regression/{75-termination => 76-termination-complex-cases}/10-complex-loop-terminating.c (100%) rename tests/regression/{75-termination => 76-termination-complex-cases}/15-complex-loop-combination-terminating.c (100%) diff --git a/tests/regression/75-termination/09-complex-for-loop-terminating.c b/tests/regression/76-termination-complex-cases/09-complex-for-loop-terminating.c similarity index 100% rename from tests/regression/75-termination/09-complex-for-loop-terminating.c rename to tests/regression/76-termination-complex-cases/09-complex-for-loop-terminating.c diff --git a/tests/regression/75-termination/10-complex-loop-terminating.c b/tests/regression/76-termination-complex-cases/10-complex-loop-terminating.c similarity index 100% rename from tests/regression/75-termination/10-complex-loop-terminating.c rename to tests/regression/76-termination-complex-cases/10-complex-loop-terminating.c diff --git a/tests/regression/75-termination/15-complex-loop-combination-terminating.c b/tests/regression/76-termination-complex-cases/15-complex-loop-combination-terminating.c similarity index 100% rename from tests/regression/75-termination/15-complex-loop-combination-terminating.c rename to tests/regression/76-termination-complex-cases/15-complex-loop-combination-terminating.c From c6e36e4cbad76128d5a1de1eb601e74653bbdd7a Mon Sep 17 00:00:00 2001 From: Johanna Schinabeck Date: Sun, 9 Jul 2023 18:39:11 +0200 Subject: [PATCH 218/327] cleaned module G from an unnecessary function; addded missing comment to analysisState --- src/framework/analysisState.ml | 2 +- src/framework/constraints.ml | 40 +++++++++++++--------------------- 2 files changed, 16 insertions(+), 26 deletions(-) diff --git a/src/framework/analysisState.ml b/src/framework/analysisState.ml index 3f577d79f4..c2d977af9c 100644 --- a/src/framework/analysisState.ml +++ b/src/framework/analysisState.ml @@ -7,7 +7,7 @@ let should_warn = ref false (** Whether signed overflow or underflow happened *) let svcomp_may_overflow = ref false -(** TODO:**) +(** Whether the termination analysis detectes the program as non-terminating**) let svcomp_may_not_terminate = ref false (** A hack to see if we are currently doing global inits *) diff --git a/src/framework/constraints.ml b/src/framework/constraints.ml index 6aa0fc01e2..e99f39bd8f 100644 --- a/src/framework/constraints.ml +++ b/src/framework/constraints.ml @@ -1773,10 +1773,6 @@ struct | `Lifted2 x -> BatPrintf.fprintf f "%a" CallGraphMap.printXml x | x -> BatPrintf.fprintf f "%a" printXml x - let base2 instance = - match instance with - | `Lifted2 n -> Some n - | _ -> None end let name () = "RecursionTermLifter (" ^ S.name () ^ ")" @@ -1797,35 +1793,29 @@ struct let rec iter_call (path_visited_calls: LS.t) (call:Printable.Prod (CilType.Fundec) (S.C).t) = let ((fundec_e:fundec), (context_e: C.t)) = call in (*unpack tuple for later use*) if LS.mem call path_visited_calls then ( - AnalysisState.svcomp_may_not_terminate := true; + AnalysisState.svcomp_may_not_terminate := true; (*set the indicator for a non-terminating program for the sv comp*) (*Cycle found*) let msgs = [ (Pretty.dprintf "The program might not terminate! (Fundec %a is contained in a call graph cycle)\n" CilType.Fundec.pretty fundec_e, Some (M.Location.CilLocation fundec_e.svar.vdecl)); ] in - M.msg_group Warning ~category:NonTerminating "Recursion cycle" msgs) + M.msg_group Warning ~category:NonTerminating "Recursion cycle" msgs) (* output a warning for non-termination*) else if not (LH.mem global_visited_calls call) then begin - try - LH.replace global_visited_calls call (); - let new_path_visited_calls = LS.add call path_visited_calls in - let fundec_e_typeV: V.t = V.relift (`Right fundec_e) in - let gmap_opt = G.base2 (ctx.global (fundec_e_typeV)) in - let gmap = Option.get (gmap_opt) in (*might be empty*) - let callers: CallGraphSet.t = CallGraphMap.find (context_e) gmap in - CallGraphSet.iter (fun to_call -> - iter_call new_path_visited_calls to_call - ) callers; - with Invalid_argument _ -> () (* path ended: no cycle*) + LH.replace global_visited_calls call (); + let new_path_visited_calls = LS.add call path_visited_calls in + let fundec_e_typeV: V.t = V.relift (`Right fundec_e) in + let gmap = G.callGraph (ctx.global (fundec_e_typeV)) in + let callers: CallGraphSet.t = CallGraphMap.find (context_e) gmap in + CallGraphSet.iter (fun to_call -> + iter_call new_path_visited_calls to_call + ) callers; end in - try - let gmap_opt = G.base2 (ctx.global (v)) in - let gmap = Option.get (gmap_opt) in - CallGraphMap.iter(fun key value -> - let call = (v', key) in - iter_call LS.empty call - ) gmap (* try all fundec + context pairs that are in the map *) - with Invalid_argument _ -> () (* path ended: no cycle*) + let gmap = G.callGraph (ctx.global (v)) in + CallGraphMap.iter(fun key value -> + let call = (v', key) in + iter_call LS.empty call + ) gmap (* try all fundec + context pairs that are in the map *) let query ctx (type a) (q: a Queries.t): a Queries.result = match q with From 9d6684666060ffc5d5bb9d427a3da846c60040b2 Mon Sep 17 00:00:00 2001 From: Thomas Lagemann Date: Sun, 9 Jul 2023 20:09:08 +0200 Subject: [PATCH 219/327] Complex test adapted --- .../09-complex-for-loop-terminating.c | 23 +---------- .../10-complex-loop-terminating.c | 14 +------ .../15-complex-loop-combination-terminating.c | 37 +----------------- .../75-termination/40-complex-conditions.c | 39 +++++++++++++++++++ .../regression/75-termination/41-more-tests.c | 30 ++++++++++++++ 5 files changed, 72 insertions(+), 71 deletions(-) rename tests/regression/{76-termination-complex-cases => 75-termination}/09-complex-for-loop-terminating.c (73%) rename tests/regression/{76-termination-complex-cases => 75-termination}/10-complex-loop-terminating.c (84%) rename tests/regression/{76-termination-complex-cases => 75-termination}/15-complex-loop-combination-terminating.c (68%) create mode 100644 tests/regression/75-termination/40-complex-conditions.c create mode 100644 tests/regression/75-termination/41-more-tests.c diff --git a/tests/regression/76-termination-complex-cases/09-complex-for-loop-terminating.c b/tests/regression/75-termination/09-complex-for-loop-terminating.c similarity index 73% rename from tests/regression/76-termination-complex-cases/09-complex-for-loop-terminating.c rename to tests/regression/75-termination/09-complex-for-loop-terminating.c index 30ca32a70a..90591c7554 100644 --- a/tests/regression/76-termination-complex-cases/09-complex-for-loop-terminating.c +++ b/tests/regression/75-termination/09-complex-for-loop-terminating.c @@ -1,4 +1,4 @@ -// SKIP TERM PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra +// TERM PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra --set sem.int.signed_overflow assume_none // Goblint does not finish this test #include @@ -76,27 +76,6 @@ int main() } printf("\n"); - // Loop with a continue statement - for (i = 1; i <= 10; i++) - { - if (i % 2 == 0) - { - continue; - } - printf("%d ", i); - } - printf("\n"); - - // Loop with complex conditions - for (i = 1; i <= 10; i++) - { - if (i > 5 && i % 2 == 0) - { - printf("%d ", i); - } - } - printf("\n"); - // Loop with multiple variables int a, b, c; for (a = 1, b = 2, c = 3; a <= 10; a++, b += 2, c += 3) diff --git a/tests/regression/76-termination-complex-cases/10-complex-loop-terminating.c b/tests/regression/75-termination/10-complex-loop-terminating.c similarity index 84% rename from tests/regression/76-termination-complex-cases/10-complex-loop-terminating.c rename to tests/regression/75-termination/10-complex-loop-terminating.c index 8970223c6e..e33139cced 100644 --- a/tests/regression/76-termination-complex-cases/10-complex-loop-terminating.c +++ b/tests/regression/75-termination/10-complex-loop-terminating.c @@ -1,4 +1,4 @@ -// SKIP TERM PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra +// TERM PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra --set sem.int.signed_overflow assume_none // Goblint does not finish this test #include @@ -108,18 +108,6 @@ int main() } printf("\n"); - // Loop with complex conditions - i = 1; - while (i <= 10) - { - if (i > 5 && i % 2 == 0) - { - printf("%d ", i); - } - i++; - } - printf("\n"); - // Loop with multiple variables int a = 1; int b = 2; diff --git a/tests/regression/76-termination-complex-cases/15-complex-loop-combination-terminating.c b/tests/regression/75-termination/15-complex-loop-combination-terminating.c similarity index 68% rename from tests/regression/76-termination-complex-cases/15-complex-loop-combination-terminating.c rename to tests/regression/75-termination/15-complex-loop-combination-terminating.c index 099203d13f..64afaf30e1 100644 --- a/tests/regression/76-termination-complex-cases/15-complex-loop-combination-terminating.c +++ b/tests/regression/75-termination/15-complex-loop-combination-terminating.c @@ -1,4 +1,4 @@ -// SKIP TERM PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra +// TERM PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra --set sem.int.signed_overflow assume_none // Goblint does not finish this test #include @@ -88,31 +88,6 @@ int main() n++; } - // Loop with a continue statement - for (int r = 1; r <= 10; r++) - { - if (r % 3 == 0) - { - continue; - } - printf("Loop with Continue: %d\n", r); - } - - // Loop with multiple conditions - int s = 1; - while (s <= 10 && s % 2 == 0) - { - printf("Loop with Multiple Conditions: %d\n", s); - s++; - } - - // Loop with multiple variables - int t, u; - for (t = 1, u = 10; t <= 5 && u >= 5; t++, u--) - { - printf("Loop with Multiple Variables: %d %d\n", t, u); - } - // Loop with nested conditions for (int v = 1; v <= 10; v++) { @@ -131,15 +106,5 @@ int main() } } - // Loop with a label and goto statement - int w = 1; -start: - if (w <= 5) - { - printf("Loop with Label and Goto: %d\n", w); - w++; - goto start; - } - return 0; } diff --git a/tests/regression/75-termination/40-complex-conditions.c b/tests/regression/75-termination/40-complex-conditions.c new file mode 100644 index 0000000000..2f342e89a0 --- /dev/null +++ b/tests/regression/75-termination/40-complex-conditions.c @@ -0,0 +1,39 @@ +// TODO TERM PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra +#include + +int main() { + int i; + + // Loop with a continue statement + for (i = 1; i <= 10; i++) + { + if (i % 2 == 0) + { + continue; + } + printf("%d ", i); + } + printf("\n"); + + // Loop with complex conditions + for (i = 1; i <= 10; i++) + { + if (i > 5 && i % 2 == 0) + { + printf("%d ", i); + } + } + printf("\n"); + + // Loop with complex conditions + i = 1; + while (i <= 10) + { + if (i > 5 && i % 2 == 0) + { + printf("%d ", i); + } + i++; + } + printf("\n"); +} \ No newline at end of file diff --git a/tests/regression/75-termination/41-more-tests.c b/tests/regression/75-termination/41-more-tests.c new file mode 100644 index 0000000000..112f95c3ee --- /dev/null +++ b/tests/regression/75-termination/41-more-tests.c @@ -0,0 +1,30 @@ +// TODO TERM PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra +#include + +int main() { + + // Loop with a continue statement + for (int r = 1; r <= 10; r++) + { + if (r % 3 == 0) + { + continue; + } + printf("Loop with Continue: %d\n", r); + } + + // Loop with multiple conditions + int s = 1; + while (s <= 10 && s % 2 == 0) + { + printf("Loop with Multiple Conditions: %d\n", s); + s++; + } + + // Loop with multiple variables + int t, u; + for (t = 1, u = 10; t <= 5 && u >= 5; t++, u--) + { + printf("Loop with Multiple Variables: %d %d\n", t, u); + } + } \ No newline at end of file From 09ee872f53413b4a7f0790bd2b58735878a8b5e1 Mon Sep 17 00:00:00 2001 From: Johanna Schinabeck Date: Mon, 10 Jul 2023 08:37:51 +0200 Subject: [PATCH 220/327] moved warnings to loop analysis --- src/analyses/loopTermination.ml | 16 ++++++++++++++++ src/framework/constraints.ml | 8 +------- 2 files changed, 17 insertions(+), 7 deletions(-) diff --git a/src/analyses/loopTermination.ml b/src/analyses/loopTermination.ml index 38823d3039..ecb48a5284 100644 --- a/src/analyses/loopTermination.ml +++ b/src/analyses/loopTermination.ml @@ -61,6 +61,17 @@ struct let startstate _ = () let exitstate = startstate + let finalize () = + if not (no_upjumping_gotos ()) then ( + List.iter + (fun x -> + let msgs = + [(Pretty.dprintf "The program might not terminate! (Upjumping Goto)\n", Some (M.Location.CilLocation x));] in + M.msg_group Warning ~category:NonTerminating "Possibly non terminating loops" msgs) + (!upjumping_gotos) + ); + () + let assign ctx (lval : lval) (rval : exp) = if !AnalysisState.postsolving then (* Detect assignment to loop counter variable *) @@ -71,6 +82,11 @@ struct let is_bounded = check_bounded ctx x in let loop_statement = VarToStmt.find x !loop_counters in ctx.sideg () (G.add (`Lifted loop_statement) is_bounded (ctx.global ())); + (* In case the loop is not bounded, a warning is created*) + if not (is_bounded) then ( + let msgs = + [(Pretty.dprintf "The program might not terminate! (Loop analysis)\n", Some (M.Location.CilLocation (Cilfacade.get_stmtLoc loop_statement)));] in + M.msg_group Warning ~category:NonTerminating "Possibly non terminating loops" msgs); () | _ -> () else () diff --git a/src/framework/constraints.ml b/src/framework/constraints.ml index e99f39bd8f..6114f30adb 100644 --- a/src/framework/constraints.ml +++ b/src/framework/constraints.ml @@ -1822,13 +1822,7 @@ struct | WarnGlobal v -> (* check result of loop analysis *) if not (ctx.ask Queries.MustTermAllLoops) then - (AnalysisState.svcomp_may_not_terminate := true; - let msgs = - [ - (Pretty.dprintf "The program might not terminate! (Loop analysis)\n", Some (M.Location.CilLocation locUnknown)); - ] in - M.msg_group Warning ~category:NonTerminating "Possibly non terminating loops" msgs - ); + AnalysisState.svcomp_may_not_terminate := true; let v: V.t = Obj.obj v in begin match v with | `Left v' -> From d6c11b63f8896d00c7eb14958b306efdc1536098 Mon Sep 17 00:00:00 2001 From: Thomas Lagemann Date: Mon, 10 Jul 2023 14:34:01 +0200 Subject: [PATCH 221/327] Test refactoring & parameter correction --- .../01-simple-loop-terminating.c | 18 +- .../02-simple-loop-nonterminating.c | 14 +- .../03-nested-loop-terminating.c | 37 ++-- .../04-nested-loop-nonterminating.c | 29 ++- .../75-termination/05-for-loop-terminating.c | 16 +- .../06-for-loop-nonterminating.c | 10 +- .../07-nested-for-loop-terminating.c | 25 +-- .../08-nested-for-loop-nonterminating.c | 23 +-- .../09-complex-for-loop-terminating.c | 122 +++++------ .../10-complex-loop-terminating.c | 190 ++++++++---------- .../75-termination/11-loopless-termination.c | 6 +- .../12-do-while-instant-terminating.c | 18 +- .../75-termination/13-do-while-terminating.c | 20 +- .../14-do-while-nonterminating.c | 20 +- .../15-complex-loop-combination-terminating.c | 166 +++++++-------- ...16-nested-loop-nontrivial-nonterminating.c | 29 ++- .../75-termination/17-goto-terminating.c | 21 +- .../75-termination/18-goto-nonterminating.c | 15 +- .../75-termination/19-rand-terminating.c | 38 ++-- .../75-termination/20-rand-nonterminating.c | 36 ++-- .../21-no-exit-on-rand-unproofable.c | 26 +-- .../22-exit-on-rand-unproofable.c | 18 +- .../23-exit-on-rand-terminating.c | 23 +-- .../24-upjumping-goto-loopless-terminating.c | 16 +- .../25-leave-loop-goto-terminating.c | 28 +-- .../26-enter-loop-goto-terminating.c | 32 +-- .../27-upjumping-goto-nonterminating.c | 18 +- .../28-do-while-continue-terminating.c | 76 +++---- .../29-do-while-continue-nonterminating.c | 28 ++- .../30-goto-out-of-inner-loop-terminating.c | 39 ++-- ...31-goto-out-of-inner-loop-nonterminating.c | 32 +-- .../32-multithread-terminating.c | 34 ++-- .../33-multithread-nonterminating.c | 53 ++--- .../34-nested-for-loop-nonterminating.c | 23 +-- ...out-of-inner-loop-with-print-terminating.c | 44 ++-- .../75-termination/36-recursion-terminating.c | 24 +-- .../37-recursion-nonterminating.c | 24 +-- .../38-recursion-nested-terminating.c | 40 ++-- .../39-recursion-nested-nonterminating.c | 24 +-- .../75-termination/40-complex-conditions.c | 52 +++-- .../regression/75-termination/41-more-tests.c | 44 ++-- 41 files changed, 718 insertions(+), 833 deletions(-) diff --git a/tests/regression/75-termination/01-simple-loop-terminating.c b/tests/regression/75-termination/01-simple-loop-terminating.c index a80084868a..66b6585f67 100644 --- a/tests/regression/75-termination/01-simple-loop-terminating.c +++ b/tests/regression/75-termination/01-simple-loop-terminating.c @@ -1,15 +1,13 @@ -// TERM PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra +// TERM PARAM: --set "ana.activated[+]" termination --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra #include -int main() -{ - int i = 1; +int main() { + int i = 1; - while (i <= 10) - { - printf("%d\n", i); - i++; - } + while (i <= 10) { + printf("%d\n", i); + i++; + } - return 0; + return 0; } diff --git a/tests/regression/75-termination/02-simple-loop-nonterminating.c b/tests/regression/75-termination/02-simple-loop-nonterminating.c index eef9f81ea3..6fe8816da4 100644 --- a/tests/regression/75-termination/02-simple-loop-nonterminating.c +++ b/tests/regression/75-termination/02-simple-loop-nonterminating.c @@ -1,12 +1,10 @@ -// NONTERM PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra +// NONTERM PARAM: --set "ana.activated[+]" termination --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra #include -int main() -{ - while (1) - { - continue; - } +int main() { + while (1) { + continue; + } - return 0; + return 0; } diff --git a/tests/regression/75-termination/03-nested-loop-terminating.c b/tests/regression/75-termination/03-nested-loop-terminating.c index 5e72ec3284..4e3fafabcf 100644 --- a/tests/regression/75-termination/03-nested-loop-terminating.c +++ b/tests/regression/75-termination/03-nested-loop-terminating.c @@ -1,27 +1,24 @@ -// TERM PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra +// TERM PARAM: --set "ana.activated[+]" termination --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra #include -int main() -{ - int rows = 3; - int columns = 4; - int i = 1; +int main() { + int rows = 3; + int columns = 4; + int i = 1; - // Outer while loop for rows - while (i <= rows) - { - int j = 1; + // Outer while loop for rows + while (i <= rows) { + int j = 1; - // Inner while loop for columns - while (j <= columns) - { - printf("(%d, %d) ", i, j); - j++; - } - - printf("\n"); - i++; + // Inner while loop for columns + while (j <= columns) { + printf("(%d, %d) ", i, j); + j++; } - return 0; + printf("\n"); + i++; + } + + return 0; } diff --git a/tests/regression/75-termination/04-nested-loop-nonterminating.c b/tests/regression/75-termination/04-nested-loop-nonterminating.c index 1fb5ada507..00c2554ed2 100644 --- a/tests/regression/75-termination/04-nested-loop-nonterminating.c +++ b/tests/regression/75-termination/04-nested-loop-nonterminating.c @@ -1,23 +1,20 @@ -// NONTERM PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra +// NONTERM PARAM: --set "ana.activated[+]" termination --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra #include -int main() -{ - int outerCount = 1; +int main() { + int outerCount = 1; - while (outerCount <= 3) - { - int innerCount = 1; + while (outerCount <= 3) { + int innerCount = 1; - while (1) - { - printf("(%d, %d) ", outerCount, innerCount); - innerCount++; - } - - printf("\n"); - outerCount++; + while (1) { + printf("(%d, %d) ", outerCount, innerCount); + innerCount++; } - return 0; + printf("\n"); + outerCount++; + } + + return 0; } diff --git a/tests/regression/75-termination/05-for-loop-terminating.c b/tests/regression/75-termination/05-for-loop-terminating.c index cf71fa5135..fe07200e5b 100644 --- a/tests/regression/75-termination/05-for-loop-terminating.c +++ b/tests/regression/75-termination/05-for-loop-terminating.c @@ -1,14 +1,12 @@ -// TERM PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra +// TERM PARAM: --set "ana.activated[+]" termination --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra #include -int main() -{ - int i; +int main() { + int i; - for (i = 1; i <= 10; i++) - { - printf("%d\n", i); - } + for (i = 1; i <= 10; i++) { + printf("%d\n", i); + } - return 0; + return 0; } diff --git a/tests/regression/75-termination/06-for-loop-nonterminating.c b/tests/regression/75-termination/06-for-loop-nonterminating.c index 8c1500cfb1..374cd3e59f 100644 --- a/tests/regression/75-termination/06-for-loop-nonterminating.c +++ b/tests/regression/75-termination/06-for-loop-nonterminating.c @@ -1,10 +1,10 @@ -// NONTERM PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra +// NONTERM PARAM: --set "ana.activated[+]" termination --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra #include int main() { - for (;;) { - printf("This loop does not terminate.\n"); - } + for (;;) { + printf("This loop does not terminate.\n"); + } - return 0; + return 0; } diff --git a/tests/regression/75-termination/07-nested-for-loop-terminating.c b/tests/regression/75-termination/07-nested-for-loop-terminating.c index 4b3395bd11..a94f3f360c 100644 --- a/tests/regression/75-termination/07-nested-for-loop-terminating.c +++ b/tests/regression/75-termination/07-nested-for-loop-terminating.c @@ -1,20 +1,17 @@ -// TERM PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra +// TERM PARAM: --set "ana.activated[+]" termination --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra #include -int main() -{ - int rows = 3; - int columns = 4; +int main() { + int rows = 3; + int columns = 4; - // Nested loop to iterate over rows and columns - for (int i = 1; i <= rows; i++) - { - for (int j = 1; j <= columns; j++) - { - printf("(%d, %d) ", i, j); - } - printf("\n"); + // Nested loop to iterate over rows and columns + for (int i = 1; i <= rows; i++) { + for (int j = 1; j <= columns; j++) { + printf("(%d, %d) ", i, j); } + printf("\n"); + } - return 0; + return 0; } diff --git a/tests/regression/75-termination/08-nested-for-loop-nonterminating.c b/tests/regression/75-termination/08-nested-for-loop-nonterminating.c index 818146e456..e78e819cc0 100644 --- a/tests/regression/75-termination/08-nested-for-loop-nonterminating.c +++ b/tests/regression/75-termination/08-nested-for-loop-nonterminating.c @@ -1,19 +1,16 @@ -// NONTERM PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra +// NONTERM PARAM: --set "ana.activated[+]" termination --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra #include -int main() -{ - int outerCount, innerCount; +int main() { + int outerCount, innerCount; - for (outerCount = 1; outerCount <= 3; outerCount++) - { - for (innerCount = 1;; innerCount++) - { - printf("(%d, %d) ", outerCount, innerCount); - } - - printf("\n"); + for (outerCount = 1; outerCount <= 3; outerCount++) { + for (innerCount = 1;; innerCount++) { + printf("(%d, %d) ", outerCount, innerCount); } - return 0; + printf("\n"); + } + + return 0; } diff --git a/tests/regression/75-termination/09-complex-for-loop-terminating.c b/tests/regression/75-termination/09-complex-for-loop-terminating.c index 90591c7554..018fba6822 100644 --- a/tests/regression/75-termination/09-complex-for-loop-terminating.c +++ b/tests/regression/75-termination/09-complex-for-loop-terminating.c @@ -1,87 +1,67 @@ -// TERM PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra --set sem.int.signed_overflow assume_none -// Goblint does not finish this test +// TERM PARAM: --set "ana.activated[+]" termination --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra --set sem.int.signed_overflow assume_none #include -int main() -{ - int i, j, k; +int main() { + int i, j, k; - // Outer loop - for (i = 1; i <= 5; i++) - { - // Inner loop 1 - for (j = 1; j <= i; j++) - { - printf("%d ", j); - } - printf("\n"); - - // Inner loop 2 - for (k = i; k >= 1; k--) - { - printf("%d ", k); - } - printf("\n"); + // Outer loop + for (i = 1; i <= 5; i++) { + // Inner loop 1 + for (j = 1; j <= i; j++) { + printf("%d ", j); } + printf("\n"); - // Additional loop - for (i = 5; i >= 1; i--) - { - for (j = i; j >= 1; j--) - { - printf("%d ", j); - } - printf("\n"); + // Inner loop 2 + for (k = i; k >= 1; k--) { + printf("%d ", k); } + printf("\n"); + } - // Loop with conditions - for (i = 1; i <= 10; i++) - { - if (i % 2 == 0) - { - printf("%d is even\n", i); - } - else - { - printf("%d is odd\n", i); - } + // Additional loop + for (i = 5; i >= 1; i--) { + for (j = i; j >= 1; j--) { + printf("%d ", j); } + printf("\n"); + } - // Loop with nested conditions - for (i = 1; i <= 10; i++) - { - printf("Number: %d - ", i); - if (i < 5) - { - printf("Less than 5\n"); - } - else if (i > 5) - { - printf("Greater than 5\n"); - } - else - { - printf("Equal to 5\n"); - } + // Loop with conditions + for (i = 1; i <= 10; i++) { + if (i % 2 == 0) { + printf("%d is even\n", i); + } else { + printf("%d is odd\n", i); } + } - // Loop with a break statement - for (i = 1; i <= 10; i++) - { - printf("%d ", i); - if (i == 5) - { - break; - } + // Loop with nested conditions + for (i = 1; i <= 10; i++) { + printf("Number: %d - ", i); + if (i < 5) { + printf("Less than 5\n"); + } else if (i > 5) { + printf("Greater than 5\n"); + } else { + printf("Equal to 5\n"); } - printf("\n"); + } - // Loop with multiple variables - int a, b, c; - for (a = 1, b = 2, c = 3; a <= 10; a++, b += 2, c += 3) - { - printf("%d %d %d\n", a, b, c); + // Loop with a break statement + for (i = 1; i <= 10; i++) { + printf("%d ", i); + if (i == 5) { + break; } + } + printf("\n"); + + // Loop with multiple variables + int a, b, c; + for (a = 1, b = 2, c = 3; a <= 10; a++, b += 2, c += 3) { + printf("%d %d %d\n", a, b, c); + } - return 0; + return 0; } diff --git a/tests/regression/75-termination/10-complex-loop-terminating.c b/tests/regression/75-termination/10-complex-loop-terminating.c index e33139cced..88bf6a4565 100644 --- a/tests/regression/75-termination/10-complex-loop-terminating.c +++ b/tests/regression/75-termination/10-complex-loop-terminating.c @@ -1,124 +1,102 @@ -// TERM PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra --set sem.int.signed_overflow assume_none -// Goblint does not finish this test +// TERM PARAM: --set "ana.activated[+]" termination --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra --set sem.int.signed_overflow assume_none #include -int main() -{ - int i = 1; - int j = 1; - int k = 5; +int main() { + int i = 1; + int j = 1; + int k = 5; - // Outer while loop - while (i <= 5) - { - // Inner while loop 1 - while (j <= i) - { - printf("%d ", j); - j++; - } - printf("\n"); - j = 1; - - // Inner while loop 2 - while (k >= 1) - { - printf("%d ", k); - k--; - } - printf("\n"); - k = 5; - - i++; + // Outer while loop + while (i <= 5) { + // Inner while loop 1 + while (j <= i) { + printf("%d ", j); + j++; } + printf("\n"); + j = 1; - // Additional while loop - i = 5; - while (i >= 1) - { - j = i; - while (j >= 1) - { - printf("%d ", j); - j--; - } - printf("\n"); - i--; + // Inner while loop 2 + while (k >= 1) { + printf("%d ", k); + k--; } + printf("\n"); + k = 5; + + i++; + } - // Loop with conditions - i = 1; - while (i <= 10) - { - if (i % 2 == 0) - { - printf("%d is even\n", i); - } - else - { - printf("%d is odd\n", i); - } - i++; + // Additional while loop + i = 5; + while (i >= 1) { + j = i; + while (j >= 1) { + printf("%d ", j); + j--; } + printf("\n"); + i--; + } - // Loop with nested conditions - i = 1; - while (i <= 10) - { - printf("Number: %d - ", i); - if (i < 5) - { - printf("Less than 5\n"); - } - else if (i > 5) - { - printf("Greater than 5\n"); - } - else - { - printf("Equal to 5\n"); - } - i++; + // Loop with conditions + i = 1; + while (i <= 10) { + if (i % 2 == 0) { + printf("%d is even\n", i); + } else { + printf("%d is odd\n", i); } + i++; + } - // Loop with a break statement - i = 1; - while (i <= 10) - { - printf("%d ", i); - if (i == 5) - { - break; - } - i++; + // Loop with nested conditions + i = 1; + while (i <= 10) { + printf("Number: %d - ", i); + if (i < 5) { + printf("Less than 5\n"); + } else if (i > 5) { + printf("Greater than 5\n"); + } else { + printf("Equal to 5\n"); } - printf("\n"); + i++; + } - // Loop with a continue statement - i = 1; - while (i <= 10) - { - if (i % 2 == 0) - { - i++; - continue; - } - printf("%d ", i); - i++; + // Loop with a break statement + i = 1; + while (i <= 10) { + printf("%d ", i); + if (i == 5) { + break; } - printf("\n"); + i++; + } + printf("\n"); - // Loop with multiple variables - int a = 1; - int b = 2; - int c = 3; - while (a <= 10) - { - printf("%d %d %d\n", a, b, c); - a++; - b += 2; - c += 3; + // Loop with a continue statement + i = 1; + while (i <= 10) { + if (i % 2 == 0) { + i++; + continue; } + printf("%d ", i); + i++; + } + printf("\n"); + + // Loop with multiple variables + int a = 1; + int b = 2; + int c = 3; + while (a <= 10) { + printf("%d %d %d\n", a, b, c); + a++; + b += 2; + c += 3; + } - return 0; + return 0; } diff --git a/tests/regression/75-termination/11-loopless-termination.c b/tests/regression/75-termination/11-loopless-termination.c index 01f9a953e0..a1846905fc 100644 --- a/tests/regression/75-termination/11-loopless-termination.c +++ b/tests/regression/75-termination/11-loopless-termination.c @@ -1,7 +1,7 @@ -// TERM PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra +// TERM PARAM: --set "ana.activated[+]" termination --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra #include int main() { - printf("Terminating code without a loop\n"); - return 0; + printf("Terminating code without a loop\n"); + return 0; } diff --git a/tests/regression/75-termination/12-do-while-instant-terminating.c b/tests/regression/75-termination/12-do-while-instant-terminating.c index b34dff3f5f..087b88f1f5 100644 --- a/tests/regression/75-termination/12-do-while-instant-terminating.c +++ b/tests/regression/75-termination/12-do-while-instant-terminating.c @@ -1,15 +1,13 @@ -// TERM PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra +// TERM PARAM: --set "ana.activated[+]" termination --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra #include -int main() -{ - int i = 0; +int main() { + int i = 0; - do - { - printf("Inside the do-while loop\n"); - } while (i > 0); + do { + printf("Inside the do-while loop\n"); + } while (i > 0); - printf("Exited the loop\n"); - return 0; + printf("Exited the loop\n"); + return 0; } diff --git a/tests/regression/75-termination/13-do-while-terminating.c b/tests/regression/75-termination/13-do-while-terminating.c index 651acb8fd8..34343d6ba6 100644 --- a/tests/regression/75-termination/13-do-while-terminating.c +++ b/tests/regression/75-termination/13-do-while-terminating.c @@ -1,16 +1,14 @@ -// TERM PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra +// TERM PARAM: --set "ana.activated[+]" termination --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra #include -int main() -{ - int i = 1; +int main() { + int i = 1; - do - { - printf("Inside the do-while loop\n"); - i++; - } while (i <= 5); + do { + printf("Inside the do-while loop\n"); + i++; + } while (i <= 5); - printf("Exited the loop\n"); - return 0; + printf("Exited the loop\n"); + return 0; } diff --git a/tests/regression/75-termination/14-do-while-nonterminating.c b/tests/regression/75-termination/14-do-while-nonterminating.c index 1e05e2be6e..6473fdc20d 100644 --- a/tests/regression/75-termination/14-do-while-nonterminating.c +++ b/tests/regression/75-termination/14-do-while-nonterminating.c @@ -1,16 +1,14 @@ -// NONTERM PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra +// NONTERM PARAM: --set "ana.activated[+]" termination --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra #include -int main() -{ - int i = 1; +int main() { + int i = 1; - do - { - printf("Inside the do-while loop\n"); - i++; - } while (i >= 2); + do { + printf("Inside the do-while loop\n"); + i++; + } while (i >= 2); - printf("Exited the loop\n"); - return 0; + printf("Exited the loop\n"); + return 0; } diff --git a/tests/regression/75-termination/15-complex-loop-combination-terminating.c b/tests/regression/75-termination/15-complex-loop-combination-terminating.c index 64afaf30e1..23282d24b1 100644 --- a/tests/regression/75-termination/15-complex-loop-combination-terminating.c +++ b/tests/regression/75-termination/15-complex-loop-combination-terminating.c @@ -1,110 +1,90 @@ -// TERM PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra --set sem.int.signed_overflow assume_none -// Goblint does not finish this test +// TERM PARAM: --set "ana.activated[+]" termination --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra --set sem.int.signed_overflow assume_none #include -int main() -{ - // Non-nested loops - int i; +int main() { + // Non-nested loops + int i; - // for loop - for (i = 1; i <= 10; i++) - { - printf("For loop iteration: %d\n", i); - } + // for loop + for (i = 1; i <= 10; i++) { + printf("For loop iteration: %d\n", i); + } - // while loop - int j = 1; - while (j <= 10) - { - printf("While loop iteration: %d\n", j); - j++; - } + // while loop + int j = 1; + while (j <= 10) { + printf("While loop iteration: %d\n", j); + j++; + } - // do-while loop - int k = 1; - do - { - printf("Do-While loop iteration: %d\n", k); - k++; - } while (k <= 10); + // do-while loop + int k = 1; + do { + printf("Do-While loop iteration: %d\n", k); + k++; + } while (k <= 10); - // Nested loops - int a, b; + // Nested loops + int a, b; - // Nested for and while loop - for (a = 1; a <= 5; a++) - { - int c = 1; - while (c <= a) - { - printf("Nested For-While loop: %d\n", c); - c++; - } + // Nested for and while loop + for (a = 1; a <= 5; a++) { + int c = 1; + while (c <= a) { + printf("Nested For-While loop: %d\n", c); + c++; } + } - // Nested while and do-while loop - int x = 1; - while (x <= 5) - { - int y = 1; - do - { - printf("Nested While-Do-While loop: %d\n", y); - y++; - } while (y <= x); - x++; - } + // Nested while and do-while loop + int x = 1; + while (x <= 5) { + int y = 1; + do { + printf("Nested While-Do-While loop: %d\n", y); + y++; + } while (y <= x); + x++; + } - // Nested do-while and for loop - int p = 1; - do - { - for (int q = 1; q <= p; q++) - { - printf("Nested Do-While-For loop: %d\n", q); - } - p++; - } while (p <= 5); + // Nested do-while and for loop + int p = 1; + do { + for (int q = 1; q <= p; q++) { + printf("Nested Do-While-For loop: %d\n", q); + } + p++; + } while (p <= 5); - // Additional loops - int m; + // Additional loops + int m; - // Nested while loop with a break statement - int n = 1; - while (n <= 5) - { - printf("Outer While loop iteration: %d\n", n); - m = 1; - while (1) - { - printf("Inner While loop iteration: %d\n", m); - m++; - if (m == 4) - { - break; - } - } - n++; + // Nested while loop with a break statement + int n = 1; + while (n <= 5) { + printf("Outer While loop iteration: %d\n", n); + m = 1; + while (1) { + printf("Inner While loop iteration: %d\n", m); + m++; + if (m == 4) { + break; + } } + n++; + } - // Loop with nested conditions - for (int v = 1; v <= 10; v++) - { - printf("Loop with Nested Conditions: %d - ", v); - if (v < 5) - { - printf("Less than 5\n"); - } - else if (v > 5) - { - printf("Greater than 5\n"); - } - else - { - printf("Equal to 5\n"); - } + // Loop with nested conditions + for (int v = 1; v <= 10; v++) { + printf("Loop with Nested Conditions: %d - ", v); + if (v < 5) { + printf("Less than 5\n"); + } else if (v > 5) { + printf("Greater than 5\n"); + } else { + printf("Equal to 5\n"); } + } - return 0; + return 0; } diff --git a/tests/regression/75-termination/16-nested-loop-nontrivial-nonterminating.c b/tests/regression/75-termination/16-nested-loop-nontrivial-nonterminating.c index b9ccea76af..f89e28d91a 100644 --- a/tests/regression/75-termination/16-nested-loop-nontrivial-nonterminating.c +++ b/tests/regression/75-termination/16-nested-loop-nontrivial-nonterminating.c @@ -1,23 +1,20 @@ -// NONTERM PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra +// NONTERM PARAM: --set "ana.activated[+]" termination --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra #include -int main() -{ - int outerCount = 1; +int main() { + int outerCount = 1; - while (outerCount <= 3) - { - int innerCount = 1; + while (outerCount <= 3) { + int innerCount = 1; - while (outerCount < 3 || innerCount > 0) - { - printf("(%d, %d) ", outerCount, innerCount); - innerCount++; - } - - printf("\n"); - outerCount++; + while (outerCount < 3 || innerCount > 0) { + printf("(%d, %d) ", outerCount, innerCount); + innerCount++; } - return 0; + printf("\n"); + outerCount++; + } + + return 0; } diff --git a/tests/regression/75-termination/17-goto-terminating.c b/tests/regression/75-termination/17-goto-terminating.c index c4ba717784..3ad01cbd79 100644 --- a/tests/regression/75-termination/17-goto-terminating.c +++ b/tests/regression/75-termination/17-goto-terminating.c @@ -1,18 +1,17 @@ -// TODO TERM PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra +// TODO TERM PARAM: --set "ana.activated[+]" termination --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra #include -int main() -{ - int num = 1; +int main() { + int num = 1; loop: - printf("Current number: %d\n", num); - num++; + printf("Current number: %d\n", num); + num++; - if (num <= 10) - { - goto loop; // We are not able to detect up-jumping gotos as terminating, we just warn about them might being nonterminating. - } + if (num <= 10) { + goto loop; // We are not able to detect up-jumping gotos as terminating, we + // just warn about them might being nonterminating. + } - return 0; + return 0; } diff --git a/tests/regression/75-termination/18-goto-nonterminating.c b/tests/regression/75-termination/18-goto-nonterminating.c index aab37803aa..e26f02ec11 100644 --- a/tests/regression/75-termination/18-goto-nonterminating.c +++ b/tests/regression/75-termination/18-goto-nonterminating.c @@ -1,15 +1,14 @@ -// NONTERM PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra +// NONTERM PARAM: --set "ana.activated[+]" termination --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra #include -int main() -{ - int num = 1; +int main() { + int num = 1; loop: - printf("Current number: %d\n", num); - num++; + printf("Current number: %d\n", num); + num++; - goto loop; + goto loop; - return 0; + return 0; } diff --git a/tests/regression/75-termination/19-rand-terminating.c b/tests/regression/75-termination/19-rand-terminating.c index 5d3cde9f3d..fc5d6ee7b7 100644 --- a/tests/regression/75-termination/19-rand-terminating.c +++ b/tests/regression/75-termination/19-rand-terminating.c @@ -1,31 +1,25 @@ -// TERM PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra +// TERM PARAM: --set "ana.activated[+]" termination --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra #include #include #include -int main() -{ - // Seed the random number generator - srand(time(NULL)); +int main() { + // Seed the random number generator + srand(time(NULL)); - if (rand()) - { - // Loop inside the if part - for (int i = 1; i <= 5; i++) - { - printf("Loop inside if part: %d\n", i); - } + if (rand()) { + // Loop inside the if part + for (int i = 1; i <= 5; i++) { + printf("Loop inside if part: %d\n", i); } - else - { - // Loop inside the else part - int j = 1; - while (j <= 5) - { - printf("Loop inside else part: %d\n", j); - j++; - } + } else { + // Loop inside the else part + int j = 1; + while (j <= 5) { + printf("Loop inside else part: %d\n", j); + j++; } + } - return 0; + return 0; } diff --git a/tests/regression/75-termination/20-rand-nonterminating.c b/tests/regression/75-termination/20-rand-nonterminating.c index 124a19d0f8..e74c15c948 100644 --- a/tests/regression/75-termination/20-rand-nonterminating.c +++ b/tests/regression/75-termination/20-rand-nonterminating.c @@ -1,30 +1,24 @@ -// NONTERM PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra +// NONTERM PARAM: --set "ana.activated[+]" termination --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra #include #include #include -int main() -{ - // Seed the random number generator - srand(time(NULL)); +int main() { + // Seed the random number generator + srand(time(NULL)); - if (rand()) - { - // Loop inside the if part - for (int i = 1; i >= 0; i++) - { - printf("Loop inside if part: %d\n", i); - } + if (rand()) { + // Loop inside the if part + for (int i = 1; i >= 0; i++) { + printf("Loop inside if part: %d\n", i); } - else - { - // Loop inside the else part - int j = 1; - while (j > 0) - { - printf("Loop inside else part: %d\n", j); - } + } else { + // Loop inside the else part + int j = 1; + while (j > 0) { + printf("Loop inside else part: %d\n", j); } + } - return 0; + return 0; } diff --git a/tests/regression/75-termination/21-no-exit-on-rand-unproofable.c b/tests/regression/75-termination/21-no-exit-on-rand-unproofable.c index 3bf479b6f9..10774e3420 100644 --- a/tests/regression/75-termination/21-no-exit-on-rand-unproofable.c +++ b/tests/regression/75-termination/21-no-exit-on-rand-unproofable.c @@ -1,20 +1,16 @@ -// NONTERM PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra +// NONTERM PARAM: --set "ana.activated[+]" termination --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra #include -int main() -{ - int forever, i = 0; +int main() { + int forever, i = 0; -// This loop is not provable, therefore it should throw a warning - while (i < 4 || forever == 1) - { - i++; - if (i == 4) - { - if (rand()) - { - forever = 1; - } - } + // This loop is not provable, therefore it should throw a warning + while (i < 4 || forever == 1) { + i++; + if (i == 4) { + if (rand()) { + forever = 1; + } } + } } \ No newline at end of file diff --git a/tests/regression/75-termination/22-exit-on-rand-unproofable.c b/tests/regression/75-termination/22-exit-on-rand-unproofable.c index 1f1a9bbd89..3f76f05aa9 100644 --- a/tests/regression/75-termination/22-exit-on-rand-unproofable.c +++ b/tests/regression/75-termination/22-exit-on-rand-unproofable.c @@ -1,16 +1,14 @@ -// NONTERM PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra +// NONTERM PARAM: --set "ana.activated[+]" termination --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra #include -int main() -{ - int forever = 1; +int main() { + int forever = 1; -// This loop is not provable, therefore it should throw a warning - while (forever == 1) + // This loop is not provable, therefore it should throw a warning + while (forever == 1) { + if (rand()) // May exit, may not { - if (rand()) //May exit, may not - { - forever = 0; - } + forever = 0; } + } } \ No newline at end of file diff --git a/tests/regression/75-termination/23-exit-on-rand-terminating.c b/tests/regression/75-termination/23-exit-on-rand-terminating.c index 226f46b16e..080b3c8871 100644 --- a/tests/regression/75-termination/23-exit-on-rand-terminating.c +++ b/tests/regression/75-termination/23-exit-on-rand-terminating.c @@ -1,17 +1,16 @@ -// TODO TERM PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra -#include +// TODO TERM PARAM: --set "ana.activated[+]" termination --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra #include +#include -int main() -{ - int short_run, i = 0; +int main() { + int short_run, i = 0; - while (i < 90 && short_run != 1) // Currently not able to detect this as terminating - { - i++; - if (rand()) - { - short_run = 1; - } + while (i < 90 && + short_run != 1) // Currently not able to detect this as terminating + { + i++; + if (rand()) { + short_run = 1; } + } } \ No newline at end of file diff --git a/tests/regression/75-termination/24-upjumping-goto-loopless-terminating.c b/tests/regression/75-termination/24-upjumping-goto-loopless-terminating.c index 1dc261d06a..1a4ef63ff7 100644 --- a/tests/regression/75-termination/24-upjumping-goto-loopless-terminating.c +++ b/tests/regression/75-termination/24-upjumping-goto-loopless-terminating.c @@ -1,19 +1,19 @@ -// TODO TERM PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra +// TODO TERM PARAM: --set "ana.activated[+]" termination --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra #include int main() { // Currently not able to detect up-jumping loop free gotos - goto mark2; + goto mark2; mark1: - printf("This is mark1\n"); - goto mark3; + printf("This is mark1\n"); + goto mark3; mark2: - printf("This is mark2\n"); - goto mark1; + printf("This is mark2\n"); + goto mark1; mark3: - printf("This is mark3\n"); + printf("This is mark3\n"); - return 0; + return 0; } diff --git a/tests/regression/75-termination/25-leave-loop-goto-terminating.c b/tests/regression/75-termination/25-leave-loop-goto-terminating.c index cbbb115868..35edf86938 100644 --- a/tests/regression/75-termination/25-leave-loop-goto-terminating.c +++ b/tests/regression/75-termination/25-leave-loop-goto-terminating.c @@ -1,25 +1,25 @@ -// TODO TERM PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra +// TODO TERM PARAM: --set "ana.activated[+]" termination --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra #include int main() { - int counter = 0; + int counter = 0; - while (1) { - counter++; + while (1) { + counter++; - // Dummy code - printf("Iteration %d\n", counter); - int result = counter * 2; - printf("Result: %d\n", result); + // Dummy code + printf("Iteration %d\n", counter); + int result = counter * 2; + printf("Result: %d\n", result); - // Condition to terminate the loop - if (result >= 10) { // Apron is not able to detect this - goto end; - } + // Condition to terminate the loop + if (result >= 10) { // Apron is not able to detect this + goto end; } + } end: - printf("Loop exited. Result is greater than or equal to 10.\n"); + printf("Loop exited. Result is greater than or equal to 10.\n"); - return 0; + return 0; } diff --git a/tests/regression/75-termination/26-enter-loop-goto-terminating.c b/tests/regression/75-termination/26-enter-loop-goto-terminating.c index 17220a589b..97b46f66ca 100644 --- a/tests/regression/75-termination/26-enter-loop-goto-terminating.c +++ b/tests/regression/75-termination/26-enter-loop-goto-terminating.c @@ -1,28 +1,28 @@ -// TODO TERM PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra +// TODO TERM PARAM: --set "ana.activated[+]" termination --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra #include int main() { - int counter = 0; + int counter = 0; - goto jump_point; + goto jump_point; - while (1) { - counter++; + while (1) { + counter++; - // Dummy code - printf("Iteration %d\n", counter); - int result = counter * 2; - jump_point: - printf("Result: %d\n", result); + // Dummy code + printf("Iteration %d\n", counter); + int result = counter * 2; + jump_point: + printf("Result: %d\n", result); - // Condition to terminate the loop - if (result >= 10) { // Apron is not able to detect this - goto end; - } + // Condition to terminate the loop + if (result >= 10) { // Apron is not able to detect this + goto end; } + } end: - printf("Loop exited. Result is greater than or equal to 10.\n"); + printf("Loop exited. Result is greater than or equal to 10.\n"); - return 0; + return 0; } diff --git a/tests/regression/75-termination/27-upjumping-goto-nonterminating.c b/tests/regression/75-termination/27-upjumping-goto-nonterminating.c index 52ad7ea820..a6621dd986 100644 --- a/tests/regression/75-termination/27-upjumping-goto-nonterminating.c +++ b/tests/regression/75-termination/27-upjumping-goto-nonterminating.c @@ -1,20 +1,20 @@ -// NONTERM PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra +// NONTERM PARAM: --set "ana.activated[+]" termination --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra #include int main() { - goto mark2; + goto mark2; mark1: - printf("This is mark1\n"); - goto mark3; + printf("This is mark1\n"); + goto mark3; mark2: - printf("This is mark2\n"); - goto mark1; + printf("This is mark2\n"); + goto mark1; mark3: - printf("This is mark3\n"); - goto mark1; + printf("This is mark3\n"); + goto mark1; - return 0; + return 0; } diff --git a/tests/regression/75-termination/28-do-while-continue-terminating.c b/tests/regression/75-termination/28-do-while-continue-terminating.c index f05fa4f315..b55aaf28c2 100644 --- a/tests/regression/75-termination/28-do-while-continue-terminating.c +++ b/tests/regression/75-termination/28-do-while-continue-terminating.c @@ -1,47 +1,52 @@ -// TODO TERM PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra +// TODO TERM PARAM: --set "ana.activated[+]" termination --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra #include -int main() -{ - int i = 1; +int main() { + int i = 1; - do - { - i++; - printf("Inside the do-while loop\n"); - if (i % 2 == 0) { + do { + i++; + printf("Inside the do-while loop\n"); + if (i % 2 == 0) { - printf("Skipping %i is even\n", i); - continue; // This is handled as an goto to line 8 and there an up-jumping goto - } - } while (i <= 5); + printf("Skipping %i is even\n", i); + continue; // This is handled as an goto to line 8 and there an up-jumping + // goto + } + } while (i <= 5); - printf("Exited the loop\n"); - return 0; + printf("Exited the loop\n"); + return 0; } /* -NOTE: -Test 28: does not terminate but should terminate (test case "28-do-while-continue-terminating.c") -Reason: upjumping goto +NOTE: +Test 28: does not terminate but should terminate (test case +"28-do-while-continue-terminating.c") Reason: upjumping goto -If one has a look at the generated CIL output (attached at the bottom of this file), one can see that the "continue" is -translated in a "goto" with a corresponding label "__Cont". This label points to the loop-exit condition. Since the condition -is part of the loop, its location is evaluated to 8-17. -The location of the goto "goto __Cont" is located in line 15. -To provide soundness for the analysis, the preprocessing detects upjumping gotos with the help of its location. -In case such a goto is detected, the program is classified as non-terminating. -Due to this inserted goto (which is a result of the "continue"), an upjumping goto is located, which makes this program non-terminating. +If one has a look at the generated CIL output (attached at the bottom of this +file), one can see that the "continue" is translated in a "goto" with a +corresponding label "__Cont". This label points to the loop-exit condition. +Since the condition is part of the loop, its location is evaluated to 8-17. The +location of the goto "goto __Cont" is located in line 15. To provide soundness +for the analysis, the preprocessing detects upjumping gotos with the help of its +location. In case such a goto is detected, the program is classified as +non-terminating. Due to this inserted goto (which is a result of the +"continue"), an upjumping goto is located, which makes this program +non-terminating. -It should be noted that this issue happens when "do while"-loops and "continues" are combined. -If one combines "while"-loops and "continues", the analysis can still classify the loop as terminating. -The reason for that can be seen in the second CIL output, where the "do while"-loop is replaced by a "while"-loop. -Instead of creating a new label, the "while-continue" label of the loop is reused. Also, this goto statement is not specified as a goto, -but as a Continue statement. Hence, it is not analyzed for the upjumping gotos, which does not lead to the problem as with the "do while". +It should be noted that this issue happens when "do while"-loops and "continues" +are combined. If one combines "while"-loops and "continues", the analysis can +still classify the loop as terminating. The reason for that can be seen in the +second CIL output, where the "do while"-loop is replaced by a "while"-loop. +Instead of creating a new label, the "while-continue" label of the loop is +reused. Also, this goto statement is not specified as a goto, but as a Continue +statement. Hence, it is not analyzed for the upjumping gotos, which does not +lead to the problem as with the "do while". -------------------- SHORTENED CIL output for Test 28 (DO WHILE): ------------------- -int main(void) +------------------- SHORTENED CIL output for Test 28 (DO WHILE): +------------------- int main(void) {{{{ #line 8 while (1) { @@ -51,7 +56,7 @@ int main(void) #line 15 goto __Cont; } - __Cont: + __Cont: #line 8 if (! (i <= 5)) { #line 8 @@ -66,9 +71,8 @@ int main(void) }} -------------------- SHORTENED CIL output for Test 28 (WHILE): ------------------- -Test 28: replacing DO WHILE with WHILE: -int main(void) +------------------- SHORTENED CIL output for Test 28 (WHILE): +------------------- Test 28: replacing DO WHILE with WHILE: int main(void) {{{{ #line 8 while (1) { diff --git a/tests/regression/75-termination/29-do-while-continue-nonterminating.c b/tests/regression/75-termination/29-do-while-continue-nonterminating.c index 896d8fea95..be3e7e12de 100644 --- a/tests/regression/75-termination/29-do-while-continue-nonterminating.c +++ b/tests/regression/75-termination/29-do-while-continue-nonterminating.c @@ -1,21 +1,19 @@ -// NONTERM PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra +// NONTERM PARAM: --set "ana.activated[+]" termination --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra #include -int main() -{ - int i = 1; +int main() { + int i = 1; - do - { - printf("Inside the do-while loop\n"); - i++; + do { + printf("Inside the do-while loop\n"); + i++; - if(i%2) { - printf("Continue as %i is odd\n", i); - continue; - } - } while (i >= 2); + if (i % 2) { + printf("Continue as %i is odd\n", i); + continue; + } + } while (i >= 2); - printf("Exited the loop\n"); - return 0; + printf("Exited the loop\n"); + return 0; } diff --git a/tests/regression/75-termination/30-goto-out-of-inner-loop-terminating.c b/tests/regression/75-termination/30-goto-out-of-inner-loop-terminating.c index a92dcd2bc8..e2eff29c8b 100644 --- a/tests/regression/75-termination/30-goto-out-of-inner-loop-terminating.c +++ b/tests/regression/75-termination/30-goto-out-of-inner-loop-terminating.c @@ -1,31 +1,32 @@ -// TERM PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra +// TERM PARAM: --set "ana.activated[+]" termination --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra #include int main() { - int rows = 5; - int columns = 5; + int rows = 5; + int columns = 5; - // Outer loop for rows - for (int i = 1; i <= rows; i++) { - // Inner loop for columns - for (int j = 1; j <= columns; j++) { - if (j == 3) { - goto outer_loop; // Jump to the label "outer_loop" - } - printf("(%d, %d) ", i, j); - } - printf("Not Skipped?\n"); - outer_loop:; // Label for the outer loop - printf("Skipped!\n"); + // Outer loop for rows + for (int i = 1; i <= rows; i++) { + // Inner loop for columns + for (int j = 1; j <= columns; j++) { + if (j == 3) { + goto outer_loop; // Jump to the label "outer_loop" + } + printf("(%d, %d) ", i, j); } + printf("Not Skipped?\n"); + outer_loop:; // Label for the outer loop + printf("Skipped!\n"); + } - return 0; + return 0; } -/* +/* NOTE: In case we do NOT assume no-overflow: Test 30: terminates (test case "30-goto-out-of-inner-loop-terminating.c") -Test 35: does not terminate (test case "35-goto-out-of-inner-loop-with-print-terminating.c") +Test 35: does not terminate (test case +"35-goto-out-of-inner-loop-with-print-terminating.c") -The reason is explained in "35-goto-out-of-inner-loop-with-print-terminating.c" +The reason is explained in "35-goto-out-of-inner-loop-with-print-terminating.c" */ diff --git a/tests/regression/75-termination/31-goto-out-of-inner-loop-nonterminating.c b/tests/regression/75-termination/31-goto-out-of-inner-loop-nonterminating.c index 722694eb88..756a93414b 100644 --- a/tests/regression/75-termination/31-goto-out-of-inner-loop-nonterminating.c +++ b/tests/regression/75-termination/31-goto-out-of-inner-loop-nonterminating.c @@ -1,23 +1,23 @@ -// NONTERM PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra +// NONTERM PARAM: --set "ana.activated[+]" termination --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra #include int main() { - int rows = 5; - int columns = 5; + int rows = 5; + int columns = 5; - // Outer loop for rows - for (int i = 1; 1; i++) { - // Inner loop for columns - for (int j = 1; j <= columns; j++) { - if (j == 3) { - printf("Goto as continue for outer loop\n"); - goto outer_loop; // Jump to the label "outer_loop" - } - printf("(%d, %d) ", i, j); - } - printf("\n"); - outer_loop:; // Label for the outer loop + // Outer loop for rows + for (int i = 1; 1; i++) { + // Inner loop for columns + for (int j = 1; j <= columns; j++) { + if (j == 3) { + printf("Goto as continue for outer loop\n"); + goto outer_loop; // Jump to the label "outer_loop" + } + printf("(%d, %d) ", i, j); } + printf("\n"); + outer_loop:; // Label for the outer loop + } - return 0; + return 0; } diff --git a/tests/regression/75-termination/32-multithread-terminating.c b/tests/regression/75-termination/32-multithread-terminating.c index 1f98b88eee..beab8564f5 100644 --- a/tests/regression/75-termination/32-multithread-terminating.c +++ b/tests/regression/75-termination/32-multithread-terminating.c @@ -1,27 +1,27 @@ -// TERM PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra -#include +// TERM PARAM: --set "ana.activated[+]" termination --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra #include +#include #include // Thread function -void* printPID(void* arg) { - pid_t pid = getpid(); - pthread_t tid = pthread_self(); - printf("Thread ID: %lu, Process ID: %d\n", (unsigned long)tid, pid); - return NULL; +void *printPID(void *arg) { + pid_t pid = getpid(); + pthread_t tid = pthread_self(); + printf("Thread ID: %lu, Process ID: %d\n", (unsigned long)tid, pid); + return NULL; } int main() { - // Create three threads - pthread_t thread1, thread2, thread3; - pthread_create(&thread1, NULL, printPID, NULL); - pthread_create(&thread2, NULL, printPID, NULL); - pthread_create(&thread3, NULL, printPID, NULL); + // Create three threads + pthread_t thread1, thread2, thread3; + pthread_create(&thread1, NULL, printPID, NULL); + pthread_create(&thread2, NULL, printPID, NULL); + pthread_create(&thread3, NULL, printPID, NULL); - // Wait for all threads to finish - pthread_join(thread1, NULL); - pthread_join(thread2, NULL); - pthread_join(thread3, NULL); + // Wait for all threads to finish + pthread_join(thread1, NULL); + pthread_join(thread2, NULL); + pthread_join(thread3, NULL); - return 0; + return 0; } diff --git a/tests/regression/75-termination/33-multithread-nonterminating.c b/tests/regression/75-termination/33-multithread-nonterminating.c index 007af3b57b..278c107821 100644 --- a/tests/regression/75-termination/33-multithread-nonterminating.c +++ b/tests/regression/75-termination/33-multithread-nonterminating.c @@ -1,36 +1,37 @@ -// NONTERM PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra -#include +// NONTERM PARAM: --set "ana.activated[+]" termination --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra #include -#include -#include +#include #include +#include +#include // Thread function -void* printPID(void* arg) { - pid_t pid = getpid(); - pthread_t tid = pthread_self(); - while(1) { - printf("Thread ID: %lu, Process ID: %d\n", (unsigned long)tid, pid); - struct timespec sleepTime; - sleepTime.tv_sec = 1; // Seconds - sleepTime.tv_nsec = 100000000 + (rand() % 200000000); // Nanoseconds (0.1 seconds + rand) - printf("Sleep for %ld nsec\n", sleepTime.tv_nsec); - nanosleep(&sleepTime, NULL); - } - return NULL; +void *printPID(void *arg) { + pid_t pid = getpid(); + pthread_t tid = pthread_self(); + while (1) { + printf("Thread ID: %lu, Process ID: %d\n", (unsigned long)tid, pid); + struct timespec sleepTime; + sleepTime.tv_sec = 1; // Seconds + sleepTime.tv_nsec = + 100000000 + (rand() % 200000000); // Nanoseconds (0.1 seconds + rand) + printf("Sleep for %ld nsec\n", sleepTime.tv_nsec); + nanosleep(&sleepTime, NULL); + } + return NULL; } int main() { - // Create three threads - pthread_t thread1, thread2, thread3; - pthread_create(&thread1, NULL, printPID, NULL); - pthread_create(&thread2, NULL, printPID, NULL); - pthread_create(&thread3, NULL, printPID, NULL); + // Create three threads + pthread_t thread1, thread2, thread3; + pthread_create(&thread1, NULL, printPID, NULL); + pthread_create(&thread2, NULL, printPID, NULL); + pthread_create(&thread3, NULL, printPID, NULL); - // Wait for all threads to finish - pthread_join(thread1, NULL); - pthread_join(thread2, NULL); - pthread_join(thread3, NULL); + // Wait for all threads to finish + pthread_join(thread1, NULL); + pthread_join(thread2, NULL); + pthread_join(thread3, NULL); - return 0; + return 0; } diff --git a/tests/regression/75-termination/34-nested-for-loop-nonterminating.c b/tests/regression/75-termination/34-nested-for-loop-nonterminating.c index 29e4ff3835..3384ed0f60 100644 --- a/tests/regression/75-termination/34-nested-for-loop-nonterminating.c +++ b/tests/regression/75-termination/34-nested-for-loop-nonterminating.c @@ -1,19 +1,16 @@ -// NONTERM PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra +// NONTERM PARAM: --set "ana.activated[+]" termination --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra #include -int main() -{ - int outerCount, innerCount; +int main() { + int outerCount, innerCount; - for (outerCount = 1; outerCount <= 3; outerCount++) - { - for (innerCount = 1; innerCount > 0; innerCount++) - { - printf("(%d, %d) ", outerCount, innerCount); - } - - printf("\n"); + for (outerCount = 1; outerCount <= 3; outerCount++) { + for (innerCount = 1; innerCount > 0; innerCount++) { + printf("(%d, %d) ", outerCount, innerCount); } - return 0; + printf("\n"); + } + + return 0; } diff --git a/tests/regression/75-termination/35-goto-out-of-inner-loop-with-print-terminating.c b/tests/regression/75-termination/35-goto-out-of-inner-loop-with-print-terminating.c index bb8bbacbf0..646f39111a 100644 --- a/tests/regression/75-termination/35-goto-out-of-inner-loop-with-print-terminating.c +++ b/tests/regression/75-termination/35-goto-out-of-inner-loop-with-print-terminating.c @@ -1,34 +1,38 @@ -// TERM PARAM: --set "ana.activated[+]" termination --enable warn.debug --set "ana.activated[+]" apron --enable ana.int.interval --set ana.apron.domain polyhedra --set sem.int.signed_overflow assume_none +// TERM PARAM: --set "ana.activated[+]" termination --set "ana.activated[+]" apron --enable ana.int.interval --set ana.apron.domain polyhedra --set sem.int.signed_overflow assume_none #include int main() { - int rows = 5; - int columns = 5; + int rows = 5; + int columns = 5; - // Outer loop for rows - for (int i = 1; i <= rows; i++) { - // Inner loop for columns - for (int j = 1; j <= columns; j++) { - if (j == 3) { - goto outer_loop; // Jump to the label "outer_loop" - } - printf("(%d, %d) ", i, j); - } - outer_loop:; // Label for the outer loop - printf("\n"); + // Outer loop for rows + for (int i = 1; i <= rows; i++) { + // Inner loop for columns + for (int j = 1; j <= columns; j++) { + if (j == 3) { + goto outer_loop; // Jump to the label "outer_loop" + } + printf("(%d, %d) ", i, j); } + outer_loop:; // Label for the outer loop + printf("\n"); + } - return 0; + return 0; } -/* +/* NOTE: In case we do NOT assume no-overflow: Test 30: terminates (test case "30-goto-out-of-inner-loop-terminating.c") -Test 35: does not terminate (test case "35-goto-out-of-inner-loop-with-print-terminating.c") +Test 35: does not terminate (test case +"35-goto-out-of-inner-loop-with-print-terminating.c") -The only difference between Test 30 and Test 35 is line 17. Test 30 has an additional statement, and Test 35 continues already with the label. -This difference in Test 35 leads to an overflow in line 11, and hence to the non-termination. -This overflow is created by a WPoint Issue. By enabling the no-overflow option this issue can be fixed and, both test cases are correctly detected as terminating. +The only difference between Test 30 and Test 35 is line 17. Test 30 has an +additional statement, and Test 35 continues already with the label. This +difference in Test 35 leads to an overflow in line 11, and hence to the +non-termination. This overflow is created by a WPoint Issue. By enabling the +no-overflow option this issue can be fixed and, both test cases are correctly +detected as terminating. (The overflow also happens without the termination analysis enabled.) */ diff --git a/tests/regression/75-termination/36-recursion-terminating.c b/tests/regression/75-termination/36-recursion-terminating.c index 583f8ccca1..533778332f 100644 --- a/tests/regression/75-termination/36-recursion-terminating.c +++ b/tests/regression/75-termination/36-recursion-terminating.c @@ -1,22 +1,22 @@ -// TERM PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra +// TERM PARAM: --set "ana.activated[+]" termination --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra #include void recursiveFunction(int n) { - // Base case: When n reaches 0, stop recursion - if (n == 0) { - printf("Terminating recursion\n"); - return; - } + // Base case: When n reaches 0, stop recursion + if (n == 0) { + printf("Terminating recursion\n"); + return; + } - printf("Recursive call with n = %d\n", n); + printf("Recursive call with n = %d\n", n); - // Recursive call: Decrement n and call the function again - recursiveFunction(n - 1); + // Recursive call: Decrement n and call the function again + recursiveFunction(n - 1); } int main() { - // Call the recursive function with an initial value - recursiveFunction(5); + // Call the recursive function with an initial value + recursiveFunction(5); - return 0; + return 0; } diff --git a/tests/regression/75-termination/37-recursion-nonterminating.c b/tests/regression/75-termination/37-recursion-nonterminating.c index d20adea294..089a4d3bcc 100644 --- a/tests/regression/75-termination/37-recursion-nonterminating.c +++ b/tests/regression/75-termination/37-recursion-nonterminating.c @@ -1,22 +1,22 @@ -// NONTERM PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra --enable ana.context.widen +// NONTERM PARAM: --set "ana.activated[+]" termination --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra --enable ana.context.widen #include void recursiveFunction(int n) { - // Base case: When n reaches 0, stop recursion - if (n == 30) { - printf("Terminating recursion\n"); - return; - } + // Base case: When n reaches 0, stop recursion + if (n == 30) { + printf("Terminating recursion\n"); + return; + } - printf("Recursive call with n = %d\n", n); + printf("Recursive call with n = %d\n", n); - // Recursive call: Decrement n and call the function again - recursiveFunction(n - 1); + // Recursive call: Decrement n and call the function again + recursiveFunction(n - 1); } int main() { - // Call the recursive function with an initial value - recursiveFunction(5); + // Call the recursive function with an initial value + recursiveFunction(5); - return 0; + return 0; } diff --git a/tests/regression/75-termination/38-recursion-nested-terminating.c b/tests/regression/75-termination/38-recursion-nested-terminating.c index 4cede747f2..eace365a44 100644 --- a/tests/regression/75-termination/38-recursion-nested-terminating.c +++ b/tests/regression/75-termination/38-recursion-nested-terminating.c @@ -1,36 +1,36 @@ -// TERM PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra +// TERM PARAM: --set "ana.activated[+]" termination --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra #include void innerRecursiveFunction(int n) { - if (n == 0) { - printf("Terminating inner recursion\n"); - return; - } + if (n == 0) { + printf("Terminating inner recursion\n"); + return; + } - printf("Inner recursive call with n = %d\n", n); + printf("Inner recursive call with n = %d\n", n); - // Recursive call to the innerRecursiveFunction - innerRecursiveFunction(n - 1); + // Recursive call to the innerRecursiveFunction + innerRecursiveFunction(n - 1); } void outerRecursiveFunction(int n) { - if (n == 0) { - printf("Terminating outer recursion\n"); - return; - } + if (n == 0) { + printf("Terminating outer recursion\n"); + return; + } - printf("Outer recursive call with n = %d\n", n); + printf("Outer recursive call with n = %d\n", n); - // Recursive call to the outerRecursiveFunction - outerRecursiveFunction(n - 1); + // Recursive call to the outerRecursiveFunction + outerRecursiveFunction(n - 1); - // Call to the innerRecursiveFunction - innerRecursiveFunction(n); + // Call to the innerRecursiveFunction + innerRecursiveFunction(n); } int main() { - // Call the outerRecursiveFunction with an initial value - outerRecursiveFunction(3); + // Call the outerRecursiveFunction with an initial value + outerRecursiveFunction(3); - return 0; + return 0; } diff --git a/tests/regression/75-termination/39-recursion-nested-nonterminating.c b/tests/regression/75-termination/39-recursion-nested-nonterminating.c index 2d3239f371..8b57f83857 100644 --- a/tests/regression/75-termination/39-recursion-nested-nonterminating.c +++ b/tests/regression/75-termination/39-recursion-nested-nonterminating.c @@ -1,26 +1,26 @@ -// NONTERM PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra +// NONTERM PARAM: --set "ana.activated[+]" termination --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra #include void innerRecursiveFunction() { - printf("Nested recursive call\n"); + printf("Nested recursive call\n"); - // Recursive call to the innerRecursiveFunction - innerRecursiveFunction(); + // Recursive call to the innerRecursiveFunction + innerRecursiveFunction(); } void outerRecursiveFunction() { - printf("Outer recursive call\n"); + printf("Outer recursive call\n"); - // Recursive call to the outerRecursiveFunction - outerRecursiveFunction(); + // Recursive call to the outerRecursiveFunction + outerRecursiveFunction(); - // Call to the innerRecursiveFunction - innerRecursiveFunction(); + // Call to the innerRecursiveFunction + innerRecursiveFunction(); } int main() { - // Call the outerRecursiveFunction - outerRecursiveFunction(); + // Call the outerRecursiveFunction + outerRecursiveFunction(); - return 0; + return 0; } diff --git a/tests/regression/75-termination/40-complex-conditions.c b/tests/regression/75-termination/40-complex-conditions.c index 2f342e89a0..d5fe6b808a 100644 --- a/tests/regression/75-termination/40-complex-conditions.c +++ b/tests/regression/75-termination/40-complex-conditions.c @@ -1,39 +1,33 @@ -// TODO TERM PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra +// TODO TERM PARAM: --set "ana.activated[+]" termination --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra #include int main() { - int i; + int i; - // Loop with a continue statement - for (i = 1; i <= 10; i++) - { - if (i % 2 == 0) - { - continue; - } - printf("%d ", i); + // Loop with a continue statement + for (i = 1; i <= 10; i++) { + if (i % 2 == 0) { + continue; } - printf("\n"); + printf("%d ", i); + } + printf("\n"); - // Loop with complex conditions - for (i = 1; i <= 10; i++) - { - if (i > 5 && i % 2 == 0) - { - printf("%d ", i); - } + // Loop with complex conditions + for (i = 1; i <= 10; i++) { + if (i > 5 && i % 2 == 0) { + printf("%d ", i); } - printf("\n"); + } + printf("\n"); - // Loop with complex conditions - i = 1; - while (i <= 10) - { - if (i > 5 && i % 2 == 0) - { - printf("%d ", i); - } - i++; + // Loop with complex conditions + i = 1; + while (i <= 10) { + if (i > 5 && i % 2 == 0) { + printf("%d ", i); } - printf("\n"); + i++; + } + printf("\n"); } \ No newline at end of file diff --git a/tests/regression/75-termination/41-more-tests.c b/tests/regression/75-termination/41-more-tests.c index 112f95c3ee..272be43293 100644 --- a/tests/regression/75-termination/41-more-tests.c +++ b/tests/regression/75-termination/41-more-tests.c @@ -1,30 +1,26 @@ -// TODO TERM PARAM: --set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra -#include +// TODO TERM PARAM: --set "ana.activated[+]" termination --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra +#include int main() { - // Loop with a continue statement - for (int r = 1; r <= 10; r++) - { - if (r % 3 == 0) - { - continue; - } - printf("Loop with Continue: %d\n", r); + // Loop with a continue statement + for (int r = 1; r <= 10; r++) { + if (r % 3 == 0) { + continue; } + printf("Loop with Continue: %d\n", r); + } - // Loop with multiple conditions - int s = 1; - while (s <= 10 && s % 2 == 0) - { - printf("Loop with Multiple Conditions: %d\n", s); - s++; - } + // Loop with multiple conditions + int s = 1; + while (s <= 10 && s % 2 == 0) { + printf("Loop with Multiple Conditions: %d\n", s); + s++; + } - // Loop with multiple variables - int t, u; - for (t = 1, u = 10; t <= 5 && u >= 5; t++, u--) - { - printf("Loop with Multiple Variables: %d %d\n", t, u); - } - } \ No newline at end of file + // Loop with multiple variables + int t, u; + for (t = 1, u = 10; t <= 5 && u >= 5; t++, u--) { + printf("Loop with Multiple Variables: %d %d\n", t, u); + } +} \ No newline at end of file From 1faf7290699344def397dbd6ade78da546e494d5 Mon Sep 17 00:00:00 2001 From: Isidor Zweckstetter Date: Mon, 10 Jul 2023 14:51:01 +0200 Subject: [PATCH 222/327] added autoTune for termination analysis in mainGoblint.ml --- src/maingoblint.ml | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/src/maingoblint.ml b/src/maingoblint.ml index 8944d87ea0..f9abd9637b 100644 --- a/src/maingoblint.ml +++ b/src/maingoblint.ml @@ -159,7 +159,12 @@ let check_arguments () = ^ String.concat " and " @@ List.map (fun s -> "'" ^ s ^ "'") imprecise_options) ); if get_bool "solvers.td3.space" && get_bool "solvers.td3.remove-wpoint" then fail "solvers.td3.space is incompatible with solvers.td3.remove-wpoint"; - if get_bool "solvers.td3.space" && get_string "solvers.td3.side_widen" = "sides-local" then fail "solvers.td3.space is incompatible with solvers.td3.side_widen = 'sides-local'" + if get_bool "solvers.td3.space" && get_string "solvers.td3.side_widen" = "sides-local" then fail "solvers.td3.space is incompatible with solvers.td3.side_widen = 'sides-local'"; + if List.mem "termination" @@ get_string_list "ana.activated" then ( + set_list "ana.activated" (GobConfig.get_list "ana.activated" @ [`String ("evermultithreaded")]); + set_string "sem.int.signed_overflow" "assume_none"; + warn "termination analysis implicitly activates evermultithreaded analysis and set sem.int.signed_overflow to assume_none" + ) (** Initialize some globals in other modules. *) let handle_flags () = From 43bf64daf294ad4c0798a63fd7738d6c32235c82 Mon Sep 17 00:00:00 2001 From: Isidor Zweckstetter Date: Mon, 10 Jul 2023 16:10:56 +0200 Subject: [PATCH 223/327] temporarly removed sem.int.signed_overflow assume_none autotuning --- src/maingoblint.ml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/maingoblint.ml b/src/maingoblint.ml index f9abd9637b..371deb989a 100644 --- a/src/maingoblint.ml +++ b/src/maingoblint.ml @@ -162,7 +162,7 @@ let check_arguments () = if get_bool "solvers.td3.space" && get_string "solvers.td3.side_widen" = "sides-local" then fail "solvers.td3.space is incompatible with solvers.td3.side_widen = 'sides-local'"; if List.mem "termination" @@ get_string_list "ana.activated" then ( set_list "ana.activated" (GobConfig.get_list "ana.activated" @ [`String ("evermultithreaded")]); - set_string "sem.int.signed_overflow" "assume_none"; + (*set_string "sem.int.signed_overflow" "assume_none";*) warn "termination analysis implicitly activates evermultithreaded analysis and set sem.int.signed_overflow to assume_none" ) From 5ef2664537eed087c99da0b8b70b7d9667fc21f5 Mon Sep 17 00:00:00 2001 From: Thomas Lagemann Date: Mon, 10 Jul 2023 16:12:13 +0200 Subject: [PATCH 224/327] Test indentation --- .../01-simple-loop-terminating.c | 6 +- .../02-simple-loop-nonterminating.c | 6 +- .../03-nested-loop-terminating.c | 9 ++- .../04-nested-loop-nonterminating.c | 9 ++- .../75-termination/05-for-loop-terminating.c | 6 +- .../06-for-loop-nonterminating.c | 6 +- .../07-nested-for-loop-terminating.c | 9 ++- .../08-nested-for-loop-nonterminating.c | 9 ++- .../09-complex-for-loop-terminating.c | 51 +++++++++++------ .../10-complex-loop-terminating.c | 57 +++++++++++++------ .../75-termination/11-loopless-termination.c | 3 +- .../12-do-while-instant-terminating.c | 6 +- .../75-termination/13-do-while-terminating.c | 6 +- .../14-do-while-nonterminating.c | 6 +- .../15-complex-loop-combination-terminating.c | 53 +++++++++++------ ...16-nested-loop-nontrivial-nonterminating.c | 9 ++- .../75-termination/17-goto-terminating.c | 6 +- .../75-termination/18-goto-nonterminating.c | 3 +- .../75-termination/19-rand-terminating.c | 16 ++++-- .../75-termination/20-rand-nonterminating.c | 16 ++++-- .../21-no-exit-on-rand-unproofable.c | 12 ++-- .../22-exit-on-rand-unproofable.c | 6 +- .../23-exit-on-rand-terminating.c | 6 +- .../24-upjumping-goto-loopless-terminating.c | 3 +- .../25-leave-loop-goto-terminating.c | 9 ++- .../26-enter-loop-goto-terminating.c | 9 ++- .../27-upjumping-goto-nonterminating.c | 3 +- .../28-do-while-continue-terminating.c | 9 ++- .../29-do-while-continue-nonterminating.c | 9 ++- .../30-goto-out-of-inner-loop-terminating.c | 12 ++-- ...31-goto-out-of-inner-loop-nonterminating.c | 12 ++-- .../32-multithread-terminating.c | 6 +- .../33-multithread-nonterminating.c | 9 ++- .../34-nested-for-loop-nonterminating.c | 9 ++- ...out-of-inner-loop-with-print-terminating.c | 12 ++-- .../75-termination/36-recursion-terminating.c | 9 ++- .../37-recursion-nonterminating.c | 9 ++- .../38-recursion-nested-terminating.c | 15 +++-- .../39-recursion-nested-nonterminating.c | 9 ++- .../75-termination/40-complex-conditions.c | 21 ++++--- .../regression/75-termination/41-more-tests.c | 15 +++-- 41 files changed, 334 insertions(+), 162 deletions(-) diff --git a/tests/regression/75-termination/01-simple-loop-terminating.c b/tests/regression/75-termination/01-simple-loop-terminating.c index 66b6585f67..aaa2a7a895 100644 --- a/tests/regression/75-termination/01-simple-loop-terminating.c +++ b/tests/regression/75-termination/01-simple-loop-terminating.c @@ -1,10 +1,12 @@ // TERM PARAM: --set "ana.activated[+]" termination --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra #include -int main() { +int main() +{ int i = 1; - while (i <= 10) { + while (i <= 10) + { printf("%d\n", i); i++; } diff --git a/tests/regression/75-termination/02-simple-loop-nonterminating.c b/tests/regression/75-termination/02-simple-loop-nonterminating.c index 6fe8816da4..51fb340f3b 100644 --- a/tests/regression/75-termination/02-simple-loop-nonterminating.c +++ b/tests/regression/75-termination/02-simple-loop-nonterminating.c @@ -1,8 +1,10 @@ // NONTERM PARAM: --set "ana.activated[+]" termination --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra #include -int main() { - while (1) { +int main() +{ + while (1) + { continue; } diff --git a/tests/regression/75-termination/03-nested-loop-terminating.c b/tests/regression/75-termination/03-nested-loop-terminating.c index 4e3fafabcf..70327c1016 100644 --- a/tests/regression/75-termination/03-nested-loop-terminating.c +++ b/tests/regression/75-termination/03-nested-loop-terminating.c @@ -1,17 +1,20 @@ // TERM PARAM: --set "ana.activated[+]" termination --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra #include -int main() { +int main() +{ int rows = 3; int columns = 4; int i = 1; // Outer while loop for rows - while (i <= rows) { + while (i <= rows) + { int j = 1; // Inner while loop for columns - while (j <= columns) { + while (j <= columns) + { printf("(%d, %d) ", i, j); j++; } diff --git a/tests/regression/75-termination/04-nested-loop-nonterminating.c b/tests/regression/75-termination/04-nested-loop-nonterminating.c index 00c2554ed2..fffc932f36 100644 --- a/tests/regression/75-termination/04-nested-loop-nonterminating.c +++ b/tests/regression/75-termination/04-nested-loop-nonterminating.c @@ -1,13 +1,16 @@ // NONTERM PARAM: --set "ana.activated[+]" termination --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra #include -int main() { +int main() +{ int outerCount = 1; - while (outerCount <= 3) { + while (outerCount <= 3) + { int innerCount = 1; - while (1) { + while (1) + { printf("(%d, %d) ", outerCount, innerCount); innerCount++; } diff --git a/tests/regression/75-termination/05-for-loop-terminating.c b/tests/regression/75-termination/05-for-loop-terminating.c index fe07200e5b..bf58408487 100644 --- a/tests/regression/75-termination/05-for-loop-terminating.c +++ b/tests/regression/75-termination/05-for-loop-terminating.c @@ -1,10 +1,12 @@ // TERM PARAM: --set "ana.activated[+]" termination --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra #include -int main() { +int main() +{ int i; - for (i = 1; i <= 10; i++) { + for (i = 1; i <= 10; i++) + { printf("%d\n", i); } diff --git a/tests/regression/75-termination/06-for-loop-nonterminating.c b/tests/regression/75-termination/06-for-loop-nonterminating.c index 374cd3e59f..be876c9741 100644 --- a/tests/regression/75-termination/06-for-loop-nonterminating.c +++ b/tests/regression/75-termination/06-for-loop-nonterminating.c @@ -1,8 +1,10 @@ // NONTERM PARAM: --set "ana.activated[+]" termination --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra #include -int main() { - for (;;) { +int main() +{ + for (;;) + { printf("This loop does not terminate.\n"); } diff --git a/tests/regression/75-termination/07-nested-for-loop-terminating.c b/tests/regression/75-termination/07-nested-for-loop-terminating.c index a94f3f360c..1c43eeaada 100644 --- a/tests/regression/75-termination/07-nested-for-loop-terminating.c +++ b/tests/regression/75-termination/07-nested-for-loop-terminating.c @@ -1,13 +1,16 @@ // TERM PARAM: --set "ana.activated[+]" termination --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra #include -int main() { +int main() +{ int rows = 3; int columns = 4; // Nested loop to iterate over rows and columns - for (int i = 1; i <= rows; i++) { - for (int j = 1; j <= columns; j++) { + for (int i = 1; i <= rows; i++) + { + for (int j = 1; j <= columns; j++) + { printf("(%d, %d) ", i, j); } printf("\n"); diff --git a/tests/regression/75-termination/08-nested-for-loop-nonterminating.c b/tests/regression/75-termination/08-nested-for-loop-nonterminating.c index e78e819cc0..e360d45d0a 100644 --- a/tests/regression/75-termination/08-nested-for-loop-nonterminating.c +++ b/tests/regression/75-termination/08-nested-for-loop-nonterminating.c @@ -1,11 +1,14 @@ // NONTERM PARAM: --set "ana.activated[+]" termination --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra #include -int main() { +int main() +{ int outerCount, innerCount; - for (outerCount = 1; outerCount <= 3; outerCount++) { - for (innerCount = 1;; innerCount++) { + for (outerCount = 1; outerCount <= 3; outerCount++) + { + for (innerCount = 1;; innerCount++) + { printf("(%d, %d) ", outerCount, innerCount); } diff --git a/tests/regression/75-termination/09-complex-for-loop-terminating.c b/tests/regression/75-termination/09-complex-for-loop-terminating.c index 018fba6822..9767b4bc1c 100644 --- a/tests/regression/75-termination/09-complex-for-loop-terminating.c +++ b/tests/regression/75-termination/09-complex-for-loop-terminating.c @@ -1,57 +1,75 @@ // TERM PARAM: --set "ana.activated[+]" termination --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra --set sem.int.signed_overflow assume_none #include -int main() { +int main() +{ int i, j, k; // Outer loop - for (i = 1; i <= 5; i++) { + for (i = 1; i <= 5; i++) + { // Inner loop 1 - for (j = 1; j <= i; j++) { + for (j = 1; j <= i; j++) + { printf("%d ", j); } printf("\n"); // Inner loop 2 - for (k = i; k >= 1; k--) { + for (k = i; k >= 1; k--) + { printf("%d ", k); } printf("\n"); } // Additional loop - for (i = 5; i >= 1; i--) { - for (j = i; j >= 1; j--) { + for (i = 5; i >= 1; i--) + { + for (j = i; j >= 1; j--) + { printf("%d ", j); } printf("\n"); } // Loop with conditions - for (i = 1; i <= 10; i++) { - if (i % 2 == 0) { + for (i = 1; i <= 10; i++) + { + if (i % 2 == 0) + { printf("%d is even\n", i); - } else { + } + else + { printf("%d is odd\n", i); } } // Loop with nested conditions - for (i = 1; i <= 10; i++) { + for (i = 1; i <= 10; i++) + { printf("Number: %d - ", i); - if (i < 5) { + if (i < 5) + { printf("Less than 5\n"); - } else if (i > 5) { + } + else if (i > 5) + { printf("Greater than 5\n"); - } else { + } + else + { printf("Equal to 5\n"); } } // Loop with a break statement - for (i = 1; i <= 10; i++) { + for (i = 1; i <= 10; i++) + { printf("%d ", i); - if (i == 5) { + if (i == 5) + { break; } } @@ -59,7 +77,8 @@ int main() { // Loop with multiple variables int a, b, c; - for (a = 1, b = 2, c = 3; a <= 10; a++, b += 2, c += 3) { + for (a = 1, b = 2, c = 3; a <= 10; a++, b += 2, c += 3) + { printf("%d %d %d\n", a, b, c); } diff --git a/tests/regression/75-termination/10-complex-loop-terminating.c b/tests/regression/75-termination/10-complex-loop-terminating.c index 88bf6a4565..19091b1033 100644 --- a/tests/regression/75-termination/10-complex-loop-terminating.c +++ b/tests/regression/75-termination/10-complex-loop-terminating.c @@ -1,15 +1,18 @@ // TERM PARAM: --set "ana.activated[+]" termination --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra --set sem.int.signed_overflow assume_none #include -int main() { +int main() +{ int i = 1; int j = 1; int k = 5; // Outer while loop - while (i <= 5) { + while (i <= 5) + { // Inner while loop 1 - while (j <= i) { + while (j <= i) + { printf("%d ", j); j++; } @@ -17,7 +20,8 @@ int main() { j = 1; // Inner while loop 2 - while (k >= 1) { + while (k >= 1) + { printf("%d ", k); k--; } @@ -29,9 +33,11 @@ int main() { // Additional while loop i = 5; - while (i >= 1) { + while (i >= 1) + { j = i; - while (j >= 1) { + while (j >= 1) + { printf("%d ", j); j--; } @@ -41,10 +47,14 @@ int main() { // Loop with conditions i = 1; - while (i <= 10) { - if (i % 2 == 0) { + while (i <= 10) + { + if (i % 2 == 0) + { printf("%d is even\n", i); - } else { + } + else + { printf("%d is odd\n", i); } i++; @@ -52,13 +62,19 @@ int main() { // Loop with nested conditions i = 1; - while (i <= 10) { + while (i <= 10) + { printf("Number: %d - ", i); - if (i < 5) { + if (i < 5) + { printf("Less than 5\n"); - } else if (i > 5) { + } + else if (i > 5) + { printf("Greater than 5\n"); - } else { + } + else + { printf("Equal to 5\n"); } i++; @@ -66,9 +82,11 @@ int main() { // Loop with a break statement i = 1; - while (i <= 10) { + while (i <= 10) + { printf("%d ", i); - if (i == 5) { + if (i == 5) + { break; } i++; @@ -77,8 +95,10 @@ int main() { // Loop with a continue statement i = 1; - while (i <= 10) { - if (i % 2 == 0) { + while (i <= 10) + { + if (i % 2 == 0) + { i++; continue; } @@ -91,7 +111,8 @@ int main() { int a = 1; int b = 2; int c = 3; - while (a <= 10) { + while (a <= 10) + { printf("%d %d %d\n", a, b, c); a++; b += 2; diff --git a/tests/regression/75-termination/11-loopless-termination.c b/tests/regression/75-termination/11-loopless-termination.c index a1846905fc..51c0605757 100644 --- a/tests/regression/75-termination/11-loopless-termination.c +++ b/tests/regression/75-termination/11-loopless-termination.c @@ -1,7 +1,8 @@ // TERM PARAM: --set "ana.activated[+]" termination --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra #include -int main() { +int main() +{ printf("Terminating code without a loop\n"); return 0; } diff --git a/tests/regression/75-termination/12-do-while-instant-terminating.c b/tests/regression/75-termination/12-do-while-instant-terminating.c index 087b88f1f5..3767430a51 100644 --- a/tests/regression/75-termination/12-do-while-instant-terminating.c +++ b/tests/regression/75-termination/12-do-while-instant-terminating.c @@ -1,10 +1,12 @@ // TERM PARAM: --set "ana.activated[+]" termination --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra #include -int main() { +int main() +{ int i = 0; - do { + do + { printf("Inside the do-while loop\n"); } while (i > 0); diff --git a/tests/regression/75-termination/13-do-while-terminating.c b/tests/regression/75-termination/13-do-while-terminating.c index 34343d6ba6..8faeec1e64 100644 --- a/tests/regression/75-termination/13-do-while-terminating.c +++ b/tests/regression/75-termination/13-do-while-terminating.c @@ -1,10 +1,12 @@ // TERM PARAM: --set "ana.activated[+]" termination --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra #include -int main() { +int main() +{ int i = 1; - do { + do + { printf("Inside the do-while loop\n"); i++; } while (i <= 5); diff --git a/tests/regression/75-termination/14-do-while-nonterminating.c b/tests/regression/75-termination/14-do-while-nonterminating.c index 6473fdc20d..30c8349bb5 100644 --- a/tests/regression/75-termination/14-do-while-nonterminating.c +++ b/tests/regression/75-termination/14-do-while-nonterminating.c @@ -1,10 +1,12 @@ // NONTERM PARAM: --set "ana.activated[+]" termination --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra #include -int main() { +int main() +{ int i = 1; - do { + do + { printf("Inside the do-while loop\n"); i++; } while (i >= 2); diff --git a/tests/regression/75-termination/15-complex-loop-combination-terminating.c b/tests/regression/75-termination/15-complex-loop-combination-terminating.c index 23282d24b1..d987397dd7 100644 --- a/tests/regression/75-termination/15-complex-loop-combination-terminating.c +++ b/tests/regression/75-termination/15-complex-loop-combination-terminating.c @@ -1,25 +1,29 @@ // TERM PARAM: --set "ana.activated[+]" termination --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra --set sem.int.signed_overflow assume_none #include -int main() { +int main() +{ // Non-nested loops int i; // for loop - for (i = 1; i <= 10; i++) { + for (i = 1; i <= 10; i++) + { printf("For loop iteration: %d\n", i); } // while loop int j = 1; - while (j <= 10) { + while (j <= 10) + { printf("While loop iteration: %d\n", j); j++; } // do-while loop int k = 1; - do { + do + { printf("Do-While loop iteration: %d\n", k); k++; } while (k <= 10); @@ -28,9 +32,11 @@ int main() { int a, b; // Nested for and while loop - for (a = 1; a <= 5; a++) { + for (a = 1; a <= 5; a++) + { int c = 1; - while (c <= a) { + while (c <= a) + { printf("Nested For-While loop: %d\n", c); c++; } @@ -38,9 +44,11 @@ int main() { // Nested while and do-while loop int x = 1; - while (x <= 5) { + while (x <= 5) + { int y = 1; - do { + do + { printf("Nested While-Do-While loop: %d\n", y); y++; } while (y <= x); @@ -49,8 +57,10 @@ int main() { // Nested do-while and for loop int p = 1; - do { - for (int q = 1; q <= p; q++) { + do + { + for (int q = 1; q <= p; q++) + { printf("Nested Do-While-For loop: %d\n", q); } p++; @@ -61,13 +71,16 @@ int main() { // Nested while loop with a break statement int n = 1; - while (n <= 5) { + while (n <= 5) + { printf("Outer While loop iteration: %d\n", n); m = 1; - while (1) { + while (1) + { printf("Inner While loop iteration: %d\n", m); m++; - if (m == 4) { + if (m == 4) + { break; } } @@ -75,13 +88,19 @@ int main() { } // Loop with nested conditions - for (int v = 1; v <= 10; v++) { + for (int v = 1; v <= 10; v++) + { printf("Loop with Nested Conditions: %d - ", v); - if (v < 5) { + if (v < 5) + { printf("Less than 5\n"); - } else if (v > 5) { + } + else if (v > 5) + { printf("Greater than 5\n"); - } else { + } + else + { printf("Equal to 5\n"); } } diff --git a/tests/regression/75-termination/16-nested-loop-nontrivial-nonterminating.c b/tests/regression/75-termination/16-nested-loop-nontrivial-nonterminating.c index f89e28d91a..87b4b82ed9 100644 --- a/tests/regression/75-termination/16-nested-loop-nontrivial-nonterminating.c +++ b/tests/regression/75-termination/16-nested-loop-nontrivial-nonterminating.c @@ -1,13 +1,16 @@ // NONTERM PARAM: --set "ana.activated[+]" termination --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra #include -int main() { +int main() +{ int outerCount = 1; - while (outerCount <= 3) { + while (outerCount <= 3) + { int innerCount = 1; - while (outerCount < 3 || innerCount > 0) { + while (outerCount < 3 || innerCount > 0) + { printf("(%d, %d) ", outerCount, innerCount); innerCount++; } diff --git a/tests/regression/75-termination/17-goto-terminating.c b/tests/regression/75-termination/17-goto-terminating.c index 3ad01cbd79..7624ae1ffc 100644 --- a/tests/regression/75-termination/17-goto-terminating.c +++ b/tests/regression/75-termination/17-goto-terminating.c @@ -1,14 +1,16 @@ // TODO TERM PARAM: --set "ana.activated[+]" termination --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra #include -int main() { +int main() +{ int num = 1; loop: printf("Current number: %d\n", num); num++; - if (num <= 10) { + if (num <= 10) + { goto loop; // We are not able to detect up-jumping gotos as terminating, we // just warn about them might being nonterminating. } diff --git a/tests/regression/75-termination/18-goto-nonterminating.c b/tests/regression/75-termination/18-goto-nonterminating.c index e26f02ec11..25f79e5b57 100644 --- a/tests/regression/75-termination/18-goto-nonterminating.c +++ b/tests/regression/75-termination/18-goto-nonterminating.c @@ -1,7 +1,8 @@ // NONTERM PARAM: --set "ana.activated[+]" termination --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra #include -int main() { +int main() +{ int num = 1; loop: diff --git a/tests/regression/75-termination/19-rand-terminating.c b/tests/regression/75-termination/19-rand-terminating.c index fc5d6ee7b7..06deac6c34 100644 --- a/tests/regression/75-termination/19-rand-terminating.c +++ b/tests/regression/75-termination/19-rand-terminating.c @@ -3,19 +3,25 @@ #include #include -int main() { +int main() +{ // Seed the random number generator srand(time(NULL)); - if (rand()) { + if (rand()) + { // Loop inside the if part - for (int i = 1; i <= 5; i++) { + for (int i = 1; i <= 5; i++) + { printf("Loop inside if part: %d\n", i); } - } else { + } + else + { // Loop inside the else part int j = 1; - while (j <= 5) { + while (j <= 5) + { printf("Loop inside else part: %d\n", j); j++; } diff --git a/tests/regression/75-termination/20-rand-nonterminating.c b/tests/regression/75-termination/20-rand-nonterminating.c index e74c15c948..83630ed6c4 100644 --- a/tests/regression/75-termination/20-rand-nonterminating.c +++ b/tests/regression/75-termination/20-rand-nonterminating.c @@ -3,19 +3,25 @@ #include #include -int main() { +int main() +{ // Seed the random number generator srand(time(NULL)); - if (rand()) { + if (rand()) + { // Loop inside the if part - for (int i = 1; i >= 0; i++) { + for (int i = 1; i >= 0; i++) + { printf("Loop inside if part: %d\n", i); } - } else { + } + else + { // Loop inside the else part int j = 1; - while (j > 0) { + while (j > 0) + { printf("Loop inside else part: %d\n", j); } } diff --git a/tests/regression/75-termination/21-no-exit-on-rand-unproofable.c b/tests/regression/75-termination/21-no-exit-on-rand-unproofable.c index 10774e3420..3e7a65dfd4 100644 --- a/tests/regression/75-termination/21-no-exit-on-rand-unproofable.c +++ b/tests/regression/75-termination/21-no-exit-on-rand-unproofable.c @@ -1,14 +1,18 @@ // NONTERM PARAM: --set "ana.activated[+]" termination --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra #include -int main() { +int main() +{ int forever, i = 0; // This loop is not provable, therefore it should throw a warning - while (i < 4 || forever == 1) { + while (i < 4 || forever == 1) + { i++; - if (i == 4) { - if (rand()) { + if (i == 4) + { + if (rand()) + { forever = 1; } } diff --git a/tests/regression/75-termination/22-exit-on-rand-unproofable.c b/tests/regression/75-termination/22-exit-on-rand-unproofable.c index 3f76f05aa9..b8d7992bd9 100644 --- a/tests/regression/75-termination/22-exit-on-rand-unproofable.c +++ b/tests/regression/75-termination/22-exit-on-rand-unproofable.c @@ -1,11 +1,13 @@ // NONTERM PARAM: --set "ana.activated[+]" termination --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra #include -int main() { +int main() +{ int forever = 1; // This loop is not provable, therefore it should throw a warning - while (forever == 1) { + while (forever == 1) + { if (rand()) // May exit, may not { forever = 0; diff --git a/tests/regression/75-termination/23-exit-on-rand-terminating.c b/tests/regression/75-termination/23-exit-on-rand-terminating.c index 080b3c8871..24d4980406 100644 --- a/tests/regression/75-termination/23-exit-on-rand-terminating.c +++ b/tests/regression/75-termination/23-exit-on-rand-terminating.c @@ -2,14 +2,16 @@ #include #include -int main() { +int main() +{ int short_run, i = 0; while (i < 90 && short_run != 1) // Currently not able to detect this as terminating { i++; - if (rand()) { + if (rand()) + { short_run = 1; } } diff --git a/tests/regression/75-termination/24-upjumping-goto-loopless-terminating.c b/tests/regression/75-termination/24-upjumping-goto-loopless-terminating.c index 1a4ef63ff7..be5698d1d8 100644 --- a/tests/regression/75-termination/24-upjumping-goto-loopless-terminating.c +++ b/tests/regression/75-termination/24-upjumping-goto-loopless-terminating.c @@ -1,7 +1,8 @@ // TODO TERM PARAM: --set "ana.activated[+]" termination --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra #include -int main() { // Currently not able to detect up-jumping loop free gotos +int main() +{ // Currently not able to detect up-jumping loop free gotos goto mark2; mark1: diff --git a/tests/regression/75-termination/25-leave-loop-goto-terminating.c b/tests/regression/75-termination/25-leave-loop-goto-terminating.c index 35edf86938..2cda3d3a03 100644 --- a/tests/regression/75-termination/25-leave-loop-goto-terminating.c +++ b/tests/regression/75-termination/25-leave-loop-goto-terminating.c @@ -1,10 +1,12 @@ // TODO TERM PARAM: --set "ana.activated[+]" termination --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra #include -int main() { +int main() +{ int counter = 0; - while (1) { + while (1) + { counter++; // Dummy code @@ -13,7 +15,8 @@ int main() { printf("Result: %d\n", result); // Condition to terminate the loop - if (result >= 10) { // Apron is not able to detect this + if (result >= 10) + { // Apron is not able to detect this goto end; } } diff --git a/tests/regression/75-termination/26-enter-loop-goto-terminating.c b/tests/regression/75-termination/26-enter-loop-goto-terminating.c index 97b46f66ca..0de9a95d6c 100644 --- a/tests/regression/75-termination/26-enter-loop-goto-terminating.c +++ b/tests/regression/75-termination/26-enter-loop-goto-terminating.c @@ -1,12 +1,14 @@ // TODO TERM PARAM: --set "ana.activated[+]" termination --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra #include -int main() { +int main() +{ int counter = 0; goto jump_point; - while (1) { + while (1) + { counter++; // Dummy code @@ -16,7 +18,8 @@ int main() { printf("Result: %d\n", result); // Condition to terminate the loop - if (result >= 10) { // Apron is not able to detect this + if (result >= 10) + { // Apron is not able to detect this goto end; } } diff --git a/tests/regression/75-termination/27-upjumping-goto-nonterminating.c b/tests/regression/75-termination/27-upjumping-goto-nonterminating.c index a6621dd986..e27d7161d5 100644 --- a/tests/regression/75-termination/27-upjumping-goto-nonterminating.c +++ b/tests/regression/75-termination/27-upjumping-goto-nonterminating.c @@ -1,7 +1,8 @@ // NONTERM PARAM: --set "ana.activated[+]" termination --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra #include -int main() { +int main() +{ goto mark2; mark1: diff --git a/tests/regression/75-termination/28-do-while-continue-terminating.c b/tests/regression/75-termination/28-do-while-continue-terminating.c index b55aaf28c2..ebd0395218 100644 --- a/tests/regression/75-termination/28-do-while-continue-terminating.c +++ b/tests/regression/75-termination/28-do-while-continue-terminating.c @@ -1,13 +1,16 @@ // TODO TERM PARAM: --set "ana.activated[+]" termination --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra #include -int main() { +int main() +{ int i = 1; - do { + do + { i++; printf("Inside the do-while loop\n"); - if (i % 2 == 0) { + if (i % 2 == 0) + { printf("Skipping %i is even\n", i); continue; // This is handled as an goto to line 8 and there an up-jumping diff --git a/tests/regression/75-termination/29-do-while-continue-nonterminating.c b/tests/regression/75-termination/29-do-while-continue-nonterminating.c index be3e7e12de..41f1dbd5bc 100644 --- a/tests/regression/75-termination/29-do-while-continue-nonterminating.c +++ b/tests/regression/75-termination/29-do-while-continue-nonterminating.c @@ -1,14 +1,17 @@ // NONTERM PARAM: --set "ana.activated[+]" termination --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra #include -int main() { +int main() +{ int i = 1; - do { + do + { printf("Inside the do-while loop\n"); i++; - if (i % 2) { + if (i % 2) + { printf("Continue as %i is odd\n", i); continue; } diff --git a/tests/regression/75-termination/30-goto-out-of-inner-loop-terminating.c b/tests/regression/75-termination/30-goto-out-of-inner-loop-terminating.c index e2eff29c8b..5cdadf4396 100644 --- a/tests/regression/75-termination/30-goto-out-of-inner-loop-terminating.c +++ b/tests/regression/75-termination/30-goto-out-of-inner-loop-terminating.c @@ -1,15 +1,19 @@ // TERM PARAM: --set "ana.activated[+]" termination --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra #include -int main() { +int main() +{ int rows = 5; int columns = 5; // Outer loop for rows - for (int i = 1; i <= rows; i++) { + for (int i = 1; i <= rows; i++) + { // Inner loop for columns - for (int j = 1; j <= columns; j++) { - if (j == 3) { + for (int j = 1; j <= columns; j++) + { + if (j == 3) + { goto outer_loop; // Jump to the label "outer_loop" } printf("(%d, %d) ", i, j); diff --git a/tests/regression/75-termination/31-goto-out-of-inner-loop-nonterminating.c b/tests/regression/75-termination/31-goto-out-of-inner-loop-nonterminating.c index 756a93414b..cb54b5dd2f 100644 --- a/tests/regression/75-termination/31-goto-out-of-inner-loop-nonterminating.c +++ b/tests/regression/75-termination/31-goto-out-of-inner-loop-nonterminating.c @@ -1,15 +1,19 @@ // NONTERM PARAM: --set "ana.activated[+]" termination --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra #include -int main() { +int main() +{ int rows = 5; int columns = 5; // Outer loop for rows - for (int i = 1; 1; i++) { + for (int i = 1; 1; i++) + { // Inner loop for columns - for (int j = 1; j <= columns; j++) { - if (j == 3) { + for (int j = 1; j <= columns; j++) + { + if (j == 3) + { printf("Goto as continue for outer loop\n"); goto outer_loop; // Jump to the label "outer_loop" } diff --git a/tests/regression/75-termination/32-multithread-terminating.c b/tests/regression/75-termination/32-multithread-terminating.c index beab8564f5..950eaaaa51 100644 --- a/tests/regression/75-termination/32-multithread-terminating.c +++ b/tests/regression/75-termination/32-multithread-terminating.c @@ -4,14 +4,16 @@ #include // Thread function -void *printPID(void *arg) { +void *printPID(void *arg) +{ pid_t pid = getpid(); pthread_t tid = pthread_self(); printf("Thread ID: %lu, Process ID: %d\n", (unsigned long)tid, pid); return NULL; } -int main() { +int main() +{ // Create three threads pthread_t thread1, thread2, thread3; pthread_create(&thread1, NULL, printPID, NULL); diff --git a/tests/regression/75-termination/33-multithread-nonterminating.c b/tests/regression/75-termination/33-multithread-nonterminating.c index 278c107821..dad62aa0f4 100644 --- a/tests/regression/75-termination/33-multithread-nonterminating.c +++ b/tests/regression/75-termination/33-multithread-nonterminating.c @@ -6,10 +6,12 @@ #include // Thread function -void *printPID(void *arg) { +void *printPID(void *arg) +{ pid_t pid = getpid(); pthread_t tid = pthread_self(); - while (1) { + while (1) + { printf("Thread ID: %lu, Process ID: %d\n", (unsigned long)tid, pid); struct timespec sleepTime; sleepTime.tv_sec = 1; // Seconds @@ -21,7 +23,8 @@ void *printPID(void *arg) { return NULL; } -int main() { +int main() +{ // Create three threads pthread_t thread1, thread2, thread3; pthread_create(&thread1, NULL, printPID, NULL); diff --git a/tests/regression/75-termination/34-nested-for-loop-nonterminating.c b/tests/regression/75-termination/34-nested-for-loop-nonterminating.c index 3384ed0f60..709960640f 100644 --- a/tests/regression/75-termination/34-nested-for-loop-nonterminating.c +++ b/tests/regression/75-termination/34-nested-for-loop-nonterminating.c @@ -1,11 +1,14 @@ // NONTERM PARAM: --set "ana.activated[+]" termination --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra #include -int main() { +int main() +{ int outerCount, innerCount; - for (outerCount = 1; outerCount <= 3; outerCount++) { - for (innerCount = 1; innerCount > 0; innerCount++) { + for (outerCount = 1; outerCount <= 3; outerCount++) + { + for (innerCount = 1; innerCount > 0; innerCount++) + { printf("(%d, %d) ", outerCount, innerCount); } diff --git a/tests/regression/75-termination/35-goto-out-of-inner-loop-with-print-terminating.c b/tests/regression/75-termination/35-goto-out-of-inner-loop-with-print-terminating.c index 646f39111a..f564354e51 100644 --- a/tests/regression/75-termination/35-goto-out-of-inner-loop-with-print-terminating.c +++ b/tests/regression/75-termination/35-goto-out-of-inner-loop-with-print-terminating.c @@ -1,15 +1,19 @@ // TERM PARAM: --set "ana.activated[+]" termination --set "ana.activated[+]" apron --enable ana.int.interval --set ana.apron.domain polyhedra --set sem.int.signed_overflow assume_none #include -int main() { +int main() +{ int rows = 5; int columns = 5; // Outer loop for rows - for (int i = 1; i <= rows; i++) { + for (int i = 1; i <= rows; i++) + { // Inner loop for columns - for (int j = 1; j <= columns; j++) { - if (j == 3) { + for (int j = 1; j <= columns; j++) + { + if (j == 3) + { goto outer_loop; // Jump to the label "outer_loop" } printf("(%d, %d) ", i, j); diff --git a/tests/regression/75-termination/36-recursion-terminating.c b/tests/regression/75-termination/36-recursion-terminating.c index 533778332f..7336417c91 100644 --- a/tests/regression/75-termination/36-recursion-terminating.c +++ b/tests/regression/75-termination/36-recursion-terminating.c @@ -1,9 +1,11 @@ // TERM PARAM: --set "ana.activated[+]" termination --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra #include -void recursiveFunction(int n) { +void recursiveFunction(int n) +{ // Base case: When n reaches 0, stop recursion - if (n == 0) { + if (n == 0) + { printf("Terminating recursion\n"); return; } @@ -14,7 +16,8 @@ void recursiveFunction(int n) { recursiveFunction(n - 1); } -int main() { +int main() +{ // Call the recursive function with an initial value recursiveFunction(5); diff --git a/tests/regression/75-termination/37-recursion-nonterminating.c b/tests/regression/75-termination/37-recursion-nonterminating.c index 089a4d3bcc..38aaf3de85 100644 --- a/tests/regression/75-termination/37-recursion-nonterminating.c +++ b/tests/regression/75-termination/37-recursion-nonterminating.c @@ -1,9 +1,11 @@ // NONTERM PARAM: --set "ana.activated[+]" termination --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra --enable ana.context.widen #include -void recursiveFunction(int n) { +void recursiveFunction(int n) +{ // Base case: When n reaches 0, stop recursion - if (n == 30) { + if (n == 30) + { printf("Terminating recursion\n"); return; } @@ -14,7 +16,8 @@ void recursiveFunction(int n) { recursiveFunction(n - 1); } -int main() { +int main() +{ // Call the recursive function with an initial value recursiveFunction(5); diff --git a/tests/regression/75-termination/38-recursion-nested-terminating.c b/tests/regression/75-termination/38-recursion-nested-terminating.c index eace365a44..bef05eb1a0 100644 --- a/tests/regression/75-termination/38-recursion-nested-terminating.c +++ b/tests/regression/75-termination/38-recursion-nested-terminating.c @@ -1,8 +1,10 @@ // TERM PARAM: --set "ana.activated[+]" termination --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra #include -void innerRecursiveFunction(int n) { - if (n == 0) { +void innerRecursiveFunction(int n) +{ + if (n == 0) + { printf("Terminating inner recursion\n"); return; } @@ -13,8 +15,10 @@ void innerRecursiveFunction(int n) { innerRecursiveFunction(n - 1); } -void outerRecursiveFunction(int n) { - if (n == 0) { +void outerRecursiveFunction(int n) +{ + if (n == 0) + { printf("Terminating outer recursion\n"); return; } @@ -28,7 +32,8 @@ void outerRecursiveFunction(int n) { innerRecursiveFunction(n); } -int main() { +int main() +{ // Call the outerRecursiveFunction with an initial value outerRecursiveFunction(3); diff --git a/tests/regression/75-termination/39-recursion-nested-nonterminating.c b/tests/regression/75-termination/39-recursion-nested-nonterminating.c index 8b57f83857..8311d9f573 100644 --- a/tests/regression/75-termination/39-recursion-nested-nonterminating.c +++ b/tests/regression/75-termination/39-recursion-nested-nonterminating.c @@ -1,14 +1,16 @@ // NONTERM PARAM: --set "ana.activated[+]" termination --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra #include -void innerRecursiveFunction() { +void innerRecursiveFunction() +{ printf("Nested recursive call\n"); // Recursive call to the innerRecursiveFunction innerRecursiveFunction(); } -void outerRecursiveFunction() { +void outerRecursiveFunction() +{ printf("Outer recursive call\n"); // Recursive call to the outerRecursiveFunction @@ -18,7 +20,8 @@ void outerRecursiveFunction() { innerRecursiveFunction(); } -int main() { +int main() +{ // Call the outerRecursiveFunction outerRecursiveFunction(); diff --git a/tests/regression/75-termination/40-complex-conditions.c b/tests/regression/75-termination/40-complex-conditions.c index d5fe6b808a..a74c863fb4 100644 --- a/tests/regression/75-termination/40-complex-conditions.c +++ b/tests/regression/75-termination/40-complex-conditions.c @@ -1,12 +1,15 @@ // TODO TERM PARAM: --set "ana.activated[+]" termination --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra #include -int main() { +int main() +{ int i; // Loop with a continue statement - for (i = 1; i <= 10; i++) { - if (i % 2 == 0) { + for (i = 1; i <= 10; i++) + { + if (i % 2 == 0) + { continue; } printf("%d ", i); @@ -14,8 +17,10 @@ int main() { printf("\n"); // Loop with complex conditions - for (i = 1; i <= 10; i++) { - if (i > 5 && i % 2 == 0) { + for (i = 1; i <= 10; i++) + { + if (i > 5 && i % 2 == 0) + { printf("%d ", i); } } @@ -23,8 +28,10 @@ int main() { // Loop with complex conditions i = 1; - while (i <= 10) { - if (i > 5 && i % 2 == 0) { + while (i <= 10) + { + if (i > 5 && i % 2 == 0) + { printf("%d ", i); } i++; diff --git a/tests/regression/75-termination/41-more-tests.c b/tests/regression/75-termination/41-more-tests.c index 272be43293..1fb9f83f5d 100644 --- a/tests/regression/75-termination/41-more-tests.c +++ b/tests/regression/75-termination/41-more-tests.c @@ -1,11 +1,14 @@ // TODO TERM PARAM: --set "ana.activated[+]" termination --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra #include -int main() { +int main() +{ // Loop with a continue statement - for (int r = 1; r <= 10; r++) { - if (r % 3 == 0) { + for (int r = 1; r <= 10; r++) + { + if (r % 3 == 0) + { continue; } printf("Loop with Continue: %d\n", r); @@ -13,14 +16,16 @@ int main() { // Loop with multiple conditions int s = 1; - while (s <= 10 && s % 2 == 0) { + while (s <= 10 && s % 2 == 0) + { printf("Loop with Multiple Conditions: %d\n", s); s++; } // Loop with multiple variables int t, u; - for (t = 1, u = 10; t <= 5 && u >= 5; t++, u--) { + for (t = 1, u = 10; t <= 5 && u >= 5; t++, u--) + { printf("Loop with Multiple Variables: %d %d\n", t, u); } } \ No newline at end of file From 71b1eb21eeaecc3bdebdd24fb11b966a5fbb84ff Mon Sep 17 00:00:00 2001 From: Thomas Lagemann Date: Mon, 10 Jul 2023 16:55:45 +0200 Subject: [PATCH 225/327] Execute termination tests in CI even if skipped. --- .github/workflows/locked.yml | 3 +++ 1 file changed, 3 insertions(+) diff --git a/.github/workflows/locked.yml b/.github/workflows/locked.yml index 751ade6880..48809d34c1 100644 --- a/.github/workflows/locked.yml +++ b/.github/workflows/locked.yml @@ -64,6 +64,9 @@ jobs: - name: Test apron regression (Mukherjee et. al SAS '17 paper') # skipped by default but CI has apron, so explicitly test group (which ignores skipping -- it's now a feature!) run: ruby scripts/update_suite.rb group apron-mukherjee -s + - name: Test apron termination regression # skipped by default but CI has apron, so explicitly test group (which ignores skipping -- it's now a feature!) + run: ruby scripts/update_suite.rb group termination -s + - name: Test regression cram run: opam exec -- dune runtest tests/regression From 472a76c77d7437e446fed001fac2184fb96bd4bb Mon Sep 17 00:00:00 2001 From: Johanna Schinabeck Date: Mon, 10 Jul 2023 17:29:28 +0200 Subject: [PATCH 226/327] added warning for multithreaded case --- src/analyses/loopTermination.ml | 26 +++++++++++-------- .../28-do-while-continue-terminating.c | 8 +++--- 2 files changed, 19 insertions(+), 15 deletions(-) diff --git a/src/analyses/loopTermination.ml b/src/analyses/loopTermination.ml index ecb48a5284..4242dd2b36 100644 --- a/src/analyses/loopTermination.ml +++ b/src/analyses/loopTermination.ml @@ -61,17 +61,6 @@ struct let startstate _ = () let exitstate = startstate - let finalize () = - if not (no_upjumping_gotos ()) then ( - List.iter - (fun x -> - let msgs = - [(Pretty.dprintf "The program might not terminate! (Upjumping Goto)\n", Some (M.Location.CilLocation x));] in - M.msg_group Warning ~category:NonTerminating "Possibly non terminating loops" msgs) - (!upjumping_gotos) - ); - () - let assign ctx (lval : lval) (rval : exp) = if !AnalysisState.postsolving then (* Detect assignment to loop counter variable *) @@ -126,6 +115,21 @@ struct G.for_all (fun _ term_info -> term_info) (ctx.global ()) && no_upjumping_gotos () && must_be_single_threaded_since_start ctx + | WarnGlobal v -> + (* warning for detected possible non-termination *) + (*upjumping gotos *) + if not (no_upjumping_gotos ()) then ( + List.iter + (fun x -> + let msgs = + [(Pretty.dprintf "The program might not terminate! (Upjumping Goto)\n", Some (M.Location.CilLocation x));] in + M.msg_group Warning ~category:NonTerminating "Possibly non terminating loops" msgs) + (!upjumping_gotos) + ); + (* multithreaded *) + if not (must_be_single_threaded_since_start ctx) then ( + M.warn ~category:NonTerminating "The program might not terminate! (Multithreaded)\n" + ); | _ -> Queries.Result.top q end diff --git a/tests/regression/75-termination/28-do-while-continue-terminating.c b/tests/regression/75-termination/28-do-while-continue-terminating.c index b55aaf28c2..495c6f30b1 100644 --- a/tests/regression/75-termination/28-do-while-continue-terminating.c +++ b/tests/regression/75-termination/28-do-while-continue-terminating.c @@ -45,8 +45,8 @@ statement. Hence, it is not analyzed for the upjumping gotos, which does not lead to the problem as with the "do while". -------------------- SHORTENED CIL output for Test 28 (DO WHILE): -------------------- int main(void) +----- SHORTENED CIL output for Test 28 (DO WHILE): ----- +int main(void) {{{{ #line 8 while (1) { @@ -71,8 +71,8 @@ lead to the problem as with the "do while". }} -------------------- SHORTENED CIL output for Test 28 (WHILE): -------------------- Test 28: replacing DO WHILE with WHILE: int main(void) +----- SHORTENED CIL output for Test 28 (WHILE): ----- +Test 28: replacing DO WHILE with WHILE: int main(void) {{{{ #line 8 while (1) { From 4af911a0c99939ea90dcdc357b0cffb61e2a1444 Mon Sep 17 00:00:00 2001 From: Johanna Schinabeck Date: Mon, 10 Jul 2023 19:55:19 +0200 Subject: [PATCH 227/327] Revert "added warning for multithreaded case" This reverts commit 472a76c77d7437e446fed001fac2184fb96bd4bb. --- src/analyses/loopTermination.ml | 26 ++++++++----------- .../28-do-while-continue-terminating.c | 8 +++--- 2 files changed, 15 insertions(+), 19 deletions(-) diff --git a/src/analyses/loopTermination.ml b/src/analyses/loopTermination.ml index 4242dd2b36..ecb48a5284 100644 --- a/src/analyses/loopTermination.ml +++ b/src/analyses/loopTermination.ml @@ -61,6 +61,17 @@ struct let startstate _ = () let exitstate = startstate + let finalize () = + if not (no_upjumping_gotos ()) then ( + List.iter + (fun x -> + let msgs = + [(Pretty.dprintf "The program might not terminate! (Upjumping Goto)\n", Some (M.Location.CilLocation x));] in + M.msg_group Warning ~category:NonTerminating "Possibly non terminating loops" msgs) + (!upjumping_gotos) + ); + () + let assign ctx (lval : lval) (rval : exp) = if !AnalysisState.postsolving then (* Detect assignment to loop counter variable *) @@ -115,21 +126,6 @@ struct G.for_all (fun _ term_info -> term_info) (ctx.global ()) && no_upjumping_gotos () && must_be_single_threaded_since_start ctx - | WarnGlobal v -> - (* warning for detected possible non-termination *) - (*upjumping gotos *) - if not (no_upjumping_gotos ()) then ( - List.iter - (fun x -> - let msgs = - [(Pretty.dprintf "The program might not terminate! (Upjumping Goto)\n", Some (M.Location.CilLocation x));] in - M.msg_group Warning ~category:NonTerminating "Possibly non terminating loops" msgs) - (!upjumping_gotos) - ); - (* multithreaded *) - if not (must_be_single_threaded_since_start ctx) then ( - M.warn ~category:NonTerminating "The program might not terminate! (Multithreaded)\n" - ); | _ -> Queries.Result.top q end diff --git a/tests/regression/75-termination/28-do-while-continue-terminating.c b/tests/regression/75-termination/28-do-while-continue-terminating.c index 495c6f30b1..b55aaf28c2 100644 --- a/tests/regression/75-termination/28-do-while-continue-terminating.c +++ b/tests/regression/75-termination/28-do-while-continue-terminating.c @@ -45,8 +45,8 @@ statement. Hence, it is not analyzed for the upjumping gotos, which does not lead to the problem as with the "do while". ------ SHORTENED CIL output for Test 28 (DO WHILE): ----- -int main(void) +------------------- SHORTENED CIL output for Test 28 (DO WHILE): +------------------- int main(void) {{{{ #line 8 while (1) { @@ -71,8 +71,8 @@ int main(void) }} ------ SHORTENED CIL output for Test 28 (WHILE): ----- -Test 28: replacing DO WHILE with WHILE: int main(void) +------------------- SHORTENED CIL output for Test 28 (WHILE): +------------------- Test 28: replacing DO WHILE with WHILE: int main(void) {{{{ #line 8 while (1) { From 32a654bbdbe411b91360149541d3c3532d42ecde Mon Sep 17 00:00:00 2001 From: Johanna Schinabeck Date: Mon, 10 Jul 2023 21:04:50 +0200 Subject: [PATCH 228/327] addedd the possibly non-terminating warning for multi threaded programs --- src/analyses/loopTermination.ml | 32 +++++++++++++------ .../28-do-while-continue-terminating.c | 8 ++--- 2 files changed, 27 insertions(+), 13 deletions(-) diff --git a/src/analyses/loopTermination.ml b/src/analyses/loopTermination.ml index ecb48a5284..bfcb364e87 100644 --- a/src/analyses/loopTermination.ml +++ b/src/analyses/loopTermination.ml @@ -6,6 +6,10 @@ open TerminationPreprocessing exception PreProcessing of string +(** Stores the result of the query if the program is single threaded or not + since finalize does not has ctx as an argument*) +let single_thread : bool ref = ref false + (** Contains all loop counter variables (varinfo) and maps them to their corresponding loop statement. *) let loop_counters : stmt VarToStmt.t ref = ref VarToStmt.empty @@ -62,15 +66,21 @@ struct let exitstate = startstate let finalize () = + (* warning for detected possible non-termination *) + (*upjumping gotos *) if not (no_upjumping_gotos ()) then ( List.iter (fun x -> let msgs = - [(Pretty.dprintf "The program might not terminate! (Upjumping Goto)\n", Some (M.Location.CilLocation x));] in - M.msg_group Warning ~category:NonTerminating "Possibly non terminating loops" msgs) + [(Pretty.dprintf "The program might not terminate! (Upjumping Goto)\n", Some (M.Location.CilLocation x));] in + M.msg_group Warning ~category:NonTerminating "Possibly non terminating loops" msgs) (!upjumping_gotos) - ); - () + ); + (* multithreaded *) + if not (!single_thread) then ( + M.warn ~category:NonTerminating "The program might not terminate! (Multithreaded)\n" + ) + let assign ctx (lval : lval) (rval : exp) = if !AnalysisState.postsolving then @@ -112,20 +122,24 @@ struct (* not (ctx.ask Queries.IsEverMultiThreaded) *) - ctx.ask (Queries.MustBeSingleThreaded {since_start = true}) + let single_threaded = ctx.ask (Queries.MustBeSingleThreaded {since_start = true}) in + single_thread := single_threaded; + single_threaded (** Provides information to Goblint *) let query ctx (type a) (q: a Queries.t): a Queries.result = match q with | Queries.MustTermLoop loop_statement -> - (match G.find_opt (`Lifted loop_statement) (ctx.global ()) with + must_be_single_threaded_since_start ctx + && (match G.find_opt (`Lifted loop_statement) (ctx.global ()) with Some b -> b | None -> false) - && must_be_single_threaded_since_start ctx | Queries.MustTermAllLoops -> - G.for_all (fun _ term_info -> term_info) (ctx.global ()) + must_be_single_threaded_since_start ctx (* must be the first to be evaluated! + This has the side effect that the single_Thread variable is set + In case of another order and due to lazy evaluation the correct value of single_Thread can otherwise not be guaranteed! *) && no_upjumping_gotos () - && must_be_single_threaded_since_start ctx + && G.for_all (fun _ term_info -> term_info) (ctx.global ()) | _ -> Queries.Result.top q end diff --git a/tests/regression/75-termination/28-do-while-continue-terminating.c b/tests/regression/75-termination/28-do-while-continue-terminating.c index b55aaf28c2..9e8cb7496b 100644 --- a/tests/regression/75-termination/28-do-while-continue-terminating.c +++ b/tests/regression/75-termination/28-do-while-continue-terminating.c @@ -45,8 +45,8 @@ statement. Hence, it is not analyzed for the upjumping gotos, which does not lead to the problem as with the "do while". -------------------- SHORTENED CIL output for Test 28 (DO WHILE): -------------------- int main(void) +------- SHORTENED CIL output for Test 28 (DO WHILE): ------- +int main(void) {{{{ #line 8 while (1) { @@ -71,8 +71,8 @@ lead to the problem as with the "do while". }} -------------------- SHORTENED CIL output for Test 28 (WHILE): -------------------- Test 28: replacing DO WHILE with WHILE: int main(void) +------- SHORTENED CIL output for Test 28 (WHILE): ------- +Test 28: replacing DO WHILE with WHILE: int main(void) {{{{ #line 8 while (1) { From 53c3c1ce32c78f9844d6d36b5ec73b1954bbf108 Mon Sep 17 00:00:00 2001 From: Alexander Schlenga Date: Wed, 12 Jul 2023 16:01:32 +0200 Subject: [PATCH 229/327] Enable use of everMultiThreaded analysis --- src/analyses/everMultiThreaded.ml | 2 +- src/analyses/loopTermination.ml | 40 +++++++++++++++---------------- 2 files changed, 20 insertions(+), 22 deletions(-) diff --git a/src/analyses/everMultiThreaded.ml b/src/analyses/everMultiThreaded.ml index 5567ef1223..f44aaffc93 100644 --- a/src/analyses/everMultiThreaded.ml +++ b/src/analyses/everMultiThreaded.ml @@ -1,4 +1,4 @@ -(** Work in progress *) +(** Analysis to register whether any additional thread has ever been spawned ([evermultithreaded]). *) open Analyses diff --git a/src/analyses/loopTermination.ml b/src/analyses/loopTermination.ml index bfcb364e87..f62eedcce4 100644 --- a/src/analyses/loopTermination.ml +++ b/src/analyses/loopTermination.ml @@ -6,7 +6,7 @@ open TerminationPreprocessing exception PreProcessing of string -(** Stores the result of the query if the program is single threaded or not +(** Stores the result of the query if the program is single threaded or not since finalize does not has ctx as an argument*) let single_thread : bool ref = ref false @@ -65,21 +65,21 @@ struct let startstate _ = () let exitstate = startstate - let finalize () = + let finalize () = (* warning for detected possible non-termination *) (*upjumping gotos *) if not (no_upjumping_gotos ()) then ( - List.iter - (fun x -> - let msgs = - [(Pretty.dprintf "The program might not terminate! (Upjumping Goto)\n", Some (M.Location.CilLocation x));] in - M.msg_group Warning ~category:NonTerminating "Possibly non terminating loops" msgs) - (!upjumping_gotos) - ); + List.iter + (fun x -> + let msgs = + [(Pretty.dprintf "The program might not terminate! (Upjumping Goto)\n", Some (M.Location.CilLocation x));] in + M.msg_group Warning ~category:NonTerminating "Possibly non terminating loops" msgs) + (!upjumping_gotos) + ); (* multithreaded *) if not (!single_thread) then ( - M.warn ~category:NonTerminating "The program might not terminate! (Multithreaded)\n" - ) + M.warn ~category:NonTerminating "The program might not terminate! (Multithreaded)\n" + ) let assign ctx (lval : lval) (rval : exp) = @@ -119,10 +119,7 @@ struct (** Checks whether a new thread was spawned some time. We want to discard * any knowledge about termination then (see query function) *) let must_be_single_threaded_since_start ctx = - (* - not (ctx.ask Queries.IsEverMultiThreaded) - *) - let single_threaded = ctx.ask (Queries.MustBeSingleThreaded {since_start = true}) in + let single_threaded = not (ctx.ask Queries.IsEverMultiThreaded) in single_thread := single_threaded; single_threaded @@ -130,14 +127,15 @@ struct let query ctx (type a) (q: a Queries.t): a Queries.result = match q with | Queries.MustTermLoop loop_statement -> - must_be_single_threaded_since_start ctx + must_be_single_threaded_since_start ctx && (match G.find_opt (`Lifted loop_statement) (ctx.global ()) with - Some b -> b - | None -> false) + Some b -> b + | None -> false) | Queries.MustTermAllLoops -> - must_be_single_threaded_since_start ctx (* must be the first to be evaluated! - This has the side effect that the single_Thread variable is set - In case of another order and due to lazy evaluation the correct value of single_Thread can otherwise not be guaranteed! *) + (* Must be the first to be evaluated! This has the side effect that + * single_thread is set. In case of another order and due to lazy + * evaluation the correct value of single_thread can not be guaranteed! *) + must_be_single_threaded_since_start ctx && no_upjumping_gotos () && G.for_all (fun _ term_info -> term_info) (ctx.global ()) | _ -> Queries.Result.top q From 76486c9a9c7bc08fd213cda8beb737c5861bfa8e Mon Sep 17 00:00:00 2001 From: Alexander Schlenga Date: Wed, 12 Jul 2023 16:04:20 +0200 Subject: [PATCH 230/327] Make struct for V anonymous --- src/analyses/loopTermination.ml | 12 +++++------- 1 file changed, 5 insertions(+), 7 deletions(-) diff --git a/src/analyses/loopTermination.ml b/src/analyses/loopTermination.ml index f62eedcce4..367c3a328c 100644 --- a/src/analyses/loopTermination.ml +++ b/src/analyses/loopTermination.ml @@ -37,12 +37,6 @@ let check_bounded ctx varinfo = | `Lifted v -> not (is_top_of (ikind v) v) | `Bot -> raise (PreProcessing "Loop variable is Bot") -module UnitV = -struct - include Printable.Unit - let is_write_only _ = true -end - (** We want to record termination information of loops and use the loop * statements for that. We use this lifting because we need to have a * lattice. *) @@ -59,7 +53,11 @@ struct module D = Lattice.Unit module C = D - module V = UnitV + module V = + struct + include Printable.Unit + let is_write_only _ = true + end module G = MapDomain.MapBot (Statements) (BoolDomain.MustBool) let startstate _ = () From ba9d35a9973a38f748bbbcba3cabd4284c6ac57f Mon Sep 17 00:00:00 2001 From: Johanna Schinabeck Date: Thu, 13 Jul 2023 12:19:12 +0200 Subject: [PATCH 231/327] indentation --- src/analyses/loopTermination.ml | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/analyses/loopTermination.ml b/src/analyses/loopTermination.ml index bfcb364e87..1dece04bbc 100644 --- a/src/analyses/loopTermination.ml +++ b/src/analyses/loopTermination.ml @@ -75,11 +75,11 @@ struct [(Pretty.dprintf "The program might not terminate! (Upjumping Goto)\n", Some (M.Location.CilLocation x));] in M.msg_group Warning ~category:NonTerminating "Possibly non terminating loops" msgs) (!upjumping_gotos) - ); + ); (* multithreaded *) if not (!single_thread) then ( - M.warn ~category:NonTerminating "The program might not terminate! (Multithreaded)\n" - ) + M.warn ~category:NonTerminating "The program might not terminate! (Multithreaded)\n" + ) let assign ctx (lval : lval) (rval : exp) = @@ -135,9 +135,9 @@ struct Some b -> b | None -> false) | Queries.MustTermAllLoops -> - must_be_single_threaded_since_start ctx (* must be the first to be evaluated! - This has the side effect that the single_Thread variable is set - In case of another order and due to lazy evaluation the correct value of single_Thread can otherwise not be guaranteed! *) + must_be_single_threaded_since_start ctx (* must be the first to be evaluated! *) + (*Reason: must_be_single_threaded_since_start has the side effect that the single_Thread variable is set + In case of another order and due to lazy evaluation the correct value of single_Thread can otherwise not be guaranteed! *) && no_upjumping_gotos () && G.for_all (fun _ term_info -> term_info) (ctx.global ()) | _ -> Queries.Result.top q From a98f503ed7c47e2d208b7031268e314f08680ade Mon Sep 17 00:00:00 2001 From: Thomas Lagemann Date: Thu, 13 Jul 2023 12:27:02 +0200 Subject: [PATCH 232/327] Test goal and comments changed --- .../75-termination/17-goto-terminating.c | 3 ++- .../24-upjumping-goto-loopless-terminating.c | 3 ++- .../28-do-while-continue-terminating.c | 3 +-- .../32-multithread-terminating.c | 3 ++- ...42-downjumping-goto-loopless-terminating.c | 19 +++++++++++++++++++ 5 files changed, 26 insertions(+), 5 deletions(-) create mode 100644 tests/regression/75-termination/42-downjumping-goto-loopless-terminating.c diff --git a/tests/regression/75-termination/17-goto-terminating.c b/tests/regression/75-termination/17-goto-terminating.c index 3ad01cbd79..8270f8c960 100644 --- a/tests/regression/75-termination/17-goto-terminating.c +++ b/tests/regression/75-termination/17-goto-terminating.c @@ -1,4 +1,5 @@ -// TODO TERM PARAM: --set "ana.activated[+]" termination --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra +// NONTERM PARAM: --set "ana.activated[+]" termination --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra +// The program terminates but the analysis is currently only meant to detect up-jumping gotos as potentially NonTerminating, therefore we expect an NonTerm #include int main() { diff --git a/tests/regression/75-termination/24-upjumping-goto-loopless-terminating.c b/tests/regression/75-termination/24-upjumping-goto-loopless-terminating.c index 1a4ef63ff7..88d8c8f418 100644 --- a/tests/regression/75-termination/24-upjumping-goto-loopless-terminating.c +++ b/tests/regression/75-termination/24-upjumping-goto-loopless-terminating.c @@ -1,4 +1,5 @@ -// TODO TERM PARAM: --set "ana.activated[+]" termination --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra +// NONTERM PARAM: --set "ana.activated[+]" termination --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra +// The program terminates but the analysis is currently only meant to detect up-jumping gotos as potentially NonTerminating, therefore we expect an NonTerm #include int main() { // Currently not able to detect up-jumping loop free gotos diff --git a/tests/regression/75-termination/28-do-while-continue-terminating.c b/tests/regression/75-termination/28-do-while-continue-terminating.c index 9e8cb7496b..402e744e2f 100644 --- a/tests/regression/75-termination/28-do-while-continue-terminating.c +++ b/tests/regression/75-termination/28-do-while-continue-terminating.c @@ -10,8 +10,7 @@ int main() { if (i % 2 == 0) { printf("Skipping %i is even\n", i); - continue; // This is handled as an goto to line 8 and there an up-jumping - // goto + continue; // This is handled as an goto to line 8 and therefore an up-jumping goto } } while (i <= 5); diff --git a/tests/regression/75-termination/32-multithread-terminating.c b/tests/regression/75-termination/32-multithread-terminating.c index beab8564f5..737b867cde 100644 --- a/tests/regression/75-termination/32-multithread-terminating.c +++ b/tests/regression/75-termination/32-multithread-terminating.c @@ -1,4 +1,5 @@ -// TERM PARAM: --set "ana.activated[+]" termination --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra +// NONTERM PARAM: --set "ana.activated[+]" termination --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra +// The program terminates but as the termination analysis is meant to not handle multithreaded programs we expect NonTerm here #include #include #include diff --git a/tests/regression/75-termination/42-downjumping-goto-loopless-terminating.c b/tests/regression/75-termination/42-downjumping-goto-loopless-terminating.c new file mode 100644 index 0000000000..54bcfdc508 --- /dev/null +++ b/tests/regression/75-termination/42-downjumping-goto-loopless-terminating.c @@ -0,0 +1,19 @@ +// TERM PARAM: --set "ana.activated[+]" termination --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra +#include + +int main() { // Currently not able to detect up-jumping loop free gotos + goto mark2; + +mark1: + printf("This is mark1\n"); + goto mark3; + +mark2: + printf("This is mark2\n"); + goto mark3; + +mark3: + printf("This is mark3\n"); + + return 0; +} From 98c062a2c28db2418adcd67fa5c540c75d2cfebf Mon Sep 17 00:00:00 2001 From: Thomas Lagemann Date: Mon, 10 Jul 2023 16:12:13 +0200 Subject: [PATCH 233/327] Test indentation --- .../01-simple-loop-terminating.c | 6 +- .../02-simple-loop-nonterminating.c | 6 +- .../03-nested-loop-terminating.c | 9 ++- .../04-nested-loop-nonterminating.c | 9 ++- .../75-termination/05-for-loop-terminating.c | 6 +- .../06-for-loop-nonterminating.c | 6 +- .../07-nested-for-loop-terminating.c | 9 ++- .../08-nested-for-loop-nonterminating.c | 9 ++- .../09-complex-for-loop-terminating.c | 51 +++++++++++------ .../10-complex-loop-terminating.c | 57 +++++++++++++------ .../75-termination/11-loopless-termination.c | 3 +- .../12-do-while-instant-terminating.c | 6 +- .../75-termination/13-do-while-terminating.c | 6 +- .../14-do-while-nonterminating.c | 6 +- .../15-complex-loop-combination-terminating.c | 53 +++++++++++------ ...16-nested-loop-nontrivial-nonterminating.c | 9 ++- .../75-termination/17-goto-terminating.c | 6 +- .../75-termination/18-goto-nonterminating.c | 3 +- .../75-termination/19-rand-terminating.c | 16 ++++-- .../75-termination/20-rand-nonterminating.c | 16 ++++-- .../21-no-exit-on-rand-unproofable.c | 12 ++-- .../22-exit-on-rand-unproofable.c | 6 +- .../23-exit-on-rand-terminating.c | 6 +- .../24-upjumping-goto-loopless-terminating.c | 3 +- .../25-leave-loop-goto-terminating.c | 9 ++- .../26-enter-loop-goto-terminating.c | 9 ++- .../27-upjumping-goto-nonterminating.c | 3 +- .../28-do-while-continue-terminating.c | 9 ++- .../29-do-while-continue-nonterminating.c | 9 ++- .../30-goto-out-of-inner-loop-terminating.c | 12 ++-- ...31-goto-out-of-inner-loop-nonterminating.c | 12 ++-- .../32-multithread-terminating.c | 6 +- .../33-multithread-nonterminating.c | 9 ++- .../34-nested-for-loop-nonterminating.c | 9 ++- ...out-of-inner-loop-with-print-terminating.c | 12 ++-- .../75-termination/36-recursion-terminating.c | 9 ++- .../37-recursion-nonterminating.c | 9 ++- .../38-recursion-nested-terminating.c | 15 +++-- .../39-recursion-nested-nonterminating.c | 9 ++- .../75-termination/40-complex-conditions.c | 21 ++++--- .../regression/75-termination/41-more-tests.c | 15 +++-- 41 files changed, 334 insertions(+), 162 deletions(-) diff --git a/tests/regression/75-termination/01-simple-loop-terminating.c b/tests/regression/75-termination/01-simple-loop-terminating.c index 66b6585f67..aaa2a7a895 100644 --- a/tests/regression/75-termination/01-simple-loop-terminating.c +++ b/tests/regression/75-termination/01-simple-loop-terminating.c @@ -1,10 +1,12 @@ // TERM PARAM: --set "ana.activated[+]" termination --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra #include -int main() { +int main() +{ int i = 1; - while (i <= 10) { + while (i <= 10) + { printf("%d\n", i); i++; } diff --git a/tests/regression/75-termination/02-simple-loop-nonterminating.c b/tests/regression/75-termination/02-simple-loop-nonterminating.c index 6fe8816da4..51fb340f3b 100644 --- a/tests/regression/75-termination/02-simple-loop-nonterminating.c +++ b/tests/regression/75-termination/02-simple-loop-nonterminating.c @@ -1,8 +1,10 @@ // NONTERM PARAM: --set "ana.activated[+]" termination --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra #include -int main() { - while (1) { +int main() +{ + while (1) + { continue; } diff --git a/tests/regression/75-termination/03-nested-loop-terminating.c b/tests/regression/75-termination/03-nested-loop-terminating.c index 4e3fafabcf..70327c1016 100644 --- a/tests/regression/75-termination/03-nested-loop-terminating.c +++ b/tests/regression/75-termination/03-nested-loop-terminating.c @@ -1,17 +1,20 @@ // TERM PARAM: --set "ana.activated[+]" termination --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra #include -int main() { +int main() +{ int rows = 3; int columns = 4; int i = 1; // Outer while loop for rows - while (i <= rows) { + while (i <= rows) + { int j = 1; // Inner while loop for columns - while (j <= columns) { + while (j <= columns) + { printf("(%d, %d) ", i, j); j++; } diff --git a/tests/regression/75-termination/04-nested-loop-nonterminating.c b/tests/regression/75-termination/04-nested-loop-nonterminating.c index 00c2554ed2..fffc932f36 100644 --- a/tests/regression/75-termination/04-nested-loop-nonterminating.c +++ b/tests/regression/75-termination/04-nested-loop-nonterminating.c @@ -1,13 +1,16 @@ // NONTERM PARAM: --set "ana.activated[+]" termination --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra #include -int main() { +int main() +{ int outerCount = 1; - while (outerCount <= 3) { + while (outerCount <= 3) + { int innerCount = 1; - while (1) { + while (1) + { printf("(%d, %d) ", outerCount, innerCount); innerCount++; } diff --git a/tests/regression/75-termination/05-for-loop-terminating.c b/tests/regression/75-termination/05-for-loop-terminating.c index fe07200e5b..bf58408487 100644 --- a/tests/regression/75-termination/05-for-loop-terminating.c +++ b/tests/regression/75-termination/05-for-loop-terminating.c @@ -1,10 +1,12 @@ // TERM PARAM: --set "ana.activated[+]" termination --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra #include -int main() { +int main() +{ int i; - for (i = 1; i <= 10; i++) { + for (i = 1; i <= 10; i++) + { printf("%d\n", i); } diff --git a/tests/regression/75-termination/06-for-loop-nonterminating.c b/tests/regression/75-termination/06-for-loop-nonterminating.c index 374cd3e59f..be876c9741 100644 --- a/tests/regression/75-termination/06-for-loop-nonterminating.c +++ b/tests/regression/75-termination/06-for-loop-nonterminating.c @@ -1,8 +1,10 @@ // NONTERM PARAM: --set "ana.activated[+]" termination --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra #include -int main() { - for (;;) { +int main() +{ + for (;;) + { printf("This loop does not terminate.\n"); } diff --git a/tests/regression/75-termination/07-nested-for-loop-terminating.c b/tests/regression/75-termination/07-nested-for-loop-terminating.c index a94f3f360c..1c43eeaada 100644 --- a/tests/regression/75-termination/07-nested-for-loop-terminating.c +++ b/tests/regression/75-termination/07-nested-for-loop-terminating.c @@ -1,13 +1,16 @@ // TERM PARAM: --set "ana.activated[+]" termination --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra #include -int main() { +int main() +{ int rows = 3; int columns = 4; // Nested loop to iterate over rows and columns - for (int i = 1; i <= rows; i++) { - for (int j = 1; j <= columns; j++) { + for (int i = 1; i <= rows; i++) + { + for (int j = 1; j <= columns; j++) + { printf("(%d, %d) ", i, j); } printf("\n"); diff --git a/tests/regression/75-termination/08-nested-for-loop-nonterminating.c b/tests/regression/75-termination/08-nested-for-loop-nonterminating.c index e78e819cc0..e360d45d0a 100644 --- a/tests/regression/75-termination/08-nested-for-loop-nonterminating.c +++ b/tests/regression/75-termination/08-nested-for-loop-nonterminating.c @@ -1,11 +1,14 @@ // NONTERM PARAM: --set "ana.activated[+]" termination --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra #include -int main() { +int main() +{ int outerCount, innerCount; - for (outerCount = 1; outerCount <= 3; outerCount++) { - for (innerCount = 1;; innerCount++) { + for (outerCount = 1; outerCount <= 3; outerCount++) + { + for (innerCount = 1;; innerCount++) + { printf("(%d, %d) ", outerCount, innerCount); } diff --git a/tests/regression/75-termination/09-complex-for-loop-terminating.c b/tests/regression/75-termination/09-complex-for-loop-terminating.c index 018fba6822..9767b4bc1c 100644 --- a/tests/regression/75-termination/09-complex-for-loop-terminating.c +++ b/tests/regression/75-termination/09-complex-for-loop-terminating.c @@ -1,57 +1,75 @@ // TERM PARAM: --set "ana.activated[+]" termination --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra --set sem.int.signed_overflow assume_none #include -int main() { +int main() +{ int i, j, k; // Outer loop - for (i = 1; i <= 5; i++) { + for (i = 1; i <= 5; i++) + { // Inner loop 1 - for (j = 1; j <= i; j++) { + for (j = 1; j <= i; j++) + { printf("%d ", j); } printf("\n"); // Inner loop 2 - for (k = i; k >= 1; k--) { + for (k = i; k >= 1; k--) + { printf("%d ", k); } printf("\n"); } // Additional loop - for (i = 5; i >= 1; i--) { - for (j = i; j >= 1; j--) { + for (i = 5; i >= 1; i--) + { + for (j = i; j >= 1; j--) + { printf("%d ", j); } printf("\n"); } // Loop with conditions - for (i = 1; i <= 10; i++) { - if (i % 2 == 0) { + for (i = 1; i <= 10; i++) + { + if (i % 2 == 0) + { printf("%d is even\n", i); - } else { + } + else + { printf("%d is odd\n", i); } } // Loop with nested conditions - for (i = 1; i <= 10; i++) { + for (i = 1; i <= 10; i++) + { printf("Number: %d - ", i); - if (i < 5) { + if (i < 5) + { printf("Less than 5\n"); - } else if (i > 5) { + } + else if (i > 5) + { printf("Greater than 5\n"); - } else { + } + else + { printf("Equal to 5\n"); } } // Loop with a break statement - for (i = 1; i <= 10; i++) { + for (i = 1; i <= 10; i++) + { printf("%d ", i); - if (i == 5) { + if (i == 5) + { break; } } @@ -59,7 +77,8 @@ int main() { // Loop with multiple variables int a, b, c; - for (a = 1, b = 2, c = 3; a <= 10; a++, b += 2, c += 3) { + for (a = 1, b = 2, c = 3; a <= 10; a++, b += 2, c += 3) + { printf("%d %d %d\n", a, b, c); } diff --git a/tests/regression/75-termination/10-complex-loop-terminating.c b/tests/regression/75-termination/10-complex-loop-terminating.c index 88bf6a4565..19091b1033 100644 --- a/tests/regression/75-termination/10-complex-loop-terminating.c +++ b/tests/regression/75-termination/10-complex-loop-terminating.c @@ -1,15 +1,18 @@ // TERM PARAM: --set "ana.activated[+]" termination --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra --set sem.int.signed_overflow assume_none #include -int main() { +int main() +{ int i = 1; int j = 1; int k = 5; // Outer while loop - while (i <= 5) { + while (i <= 5) + { // Inner while loop 1 - while (j <= i) { + while (j <= i) + { printf("%d ", j); j++; } @@ -17,7 +20,8 @@ int main() { j = 1; // Inner while loop 2 - while (k >= 1) { + while (k >= 1) + { printf("%d ", k); k--; } @@ -29,9 +33,11 @@ int main() { // Additional while loop i = 5; - while (i >= 1) { + while (i >= 1) + { j = i; - while (j >= 1) { + while (j >= 1) + { printf("%d ", j); j--; } @@ -41,10 +47,14 @@ int main() { // Loop with conditions i = 1; - while (i <= 10) { - if (i % 2 == 0) { + while (i <= 10) + { + if (i % 2 == 0) + { printf("%d is even\n", i); - } else { + } + else + { printf("%d is odd\n", i); } i++; @@ -52,13 +62,19 @@ int main() { // Loop with nested conditions i = 1; - while (i <= 10) { + while (i <= 10) + { printf("Number: %d - ", i); - if (i < 5) { + if (i < 5) + { printf("Less than 5\n"); - } else if (i > 5) { + } + else if (i > 5) + { printf("Greater than 5\n"); - } else { + } + else + { printf("Equal to 5\n"); } i++; @@ -66,9 +82,11 @@ int main() { // Loop with a break statement i = 1; - while (i <= 10) { + while (i <= 10) + { printf("%d ", i); - if (i == 5) { + if (i == 5) + { break; } i++; @@ -77,8 +95,10 @@ int main() { // Loop with a continue statement i = 1; - while (i <= 10) { - if (i % 2 == 0) { + while (i <= 10) + { + if (i % 2 == 0) + { i++; continue; } @@ -91,7 +111,8 @@ int main() { int a = 1; int b = 2; int c = 3; - while (a <= 10) { + while (a <= 10) + { printf("%d %d %d\n", a, b, c); a++; b += 2; diff --git a/tests/regression/75-termination/11-loopless-termination.c b/tests/regression/75-termination/11-loopless-termination.c index a1846905fc..51c0605757 100644 --- a/tests/regression/75-termination/11-loopless-termination.c +++ b/tests/regression/75-termination/11-loopless-termination.c @@ -1,7 +1,8 @@ // TERM PARAM: --set "ana.activated[+]" termination --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra #include -int main() { +int main() +{ printf("Terminating code without a loop\n"); return 0; } diff --git a/tests/regression/75-termination/12-do-while-instant-terminating.c b/tests/regression/75-termination/12-do-while-instant-terminating.c index 087b88f1f5..3767430a51 100644 --- a/tests/regression/75-termination/12-do-while-instant-terminating.c +++ b/tests/regression/75-termination/12-do-while-instant-terminating.c @@ -1,10 +1,12 @@ // TERM PARAM: --set "ana.activated[+]" termination --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra #include -int main() { +int main() +{ int i = 0; - do { + do + { printf("Inside the do-while loop\n"); } while (i > 0); diff --git a/tests/regression/75-termination/13-do-while-terminating.c b/tests/regression/75-termination/13-do-while-terminating.c index 34343d6ba6..8faeec1e64 100644 --- a/tests/regression/75-termination/13-do-while-terminating.c +++ b/tests/regression/75-termination/13-do-while-terminating.c @@ -1,10 +1,12 @@ // TERM PARAM: --set "ana.activated[+]" termination --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra #include -int main() { +int main() +{ int i = 1; - do { + do + { printf("Inside the do-while loop\n"); i++; } while (i <= 5); diff --git a/tests/regression/75-termination/14-do-while-nonterminating.c b/tests/regression/75-termination/14-do-while-nonterminating.c index 6473fdc20d..30c8349bb5 100644 --- a/tests/regression/75-termination/14-do-while-nonterminating.c +++ b/tests/regression/75-termination/14-do-while-nonterminating.c @@ -1,10 +1,12 @@ // NONTERM PARAM: --set "ana.activated[+]" termination --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra #include -int main() { +int main() +{ int i = 1; - do { + do + { printf("Inside the do-while loop\n"); i++; } while (i >= 2); diff --git a/tests/regression/75-termination/15-complex-loop-combination-terminating.c b/tests/regression/75-termination/15-complex-loop-combination-terminating.c index 23282d24b1..d987397dd7 100644 --- a/tests/regression/75-termination/15-complex-loop-combination-terminating.c +++ b/tests/regression/75-termination/15-complex-loop-combination-terminating.c @@ -1,25 +1,29 @@ // TERM PARAM: --set "ana.activated[+]" termination --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra --set sem.int.signed_overflow assume_none #include -int main() { +int main() +{ // Non-nested loops int i; // for loop - for (i = 1; i <= 10; i++) { + for (i = 1; i <= 10; i++) + { printf("For loop iteration: %d\n", i); } // while loop int j = 1; - while (j <= 10) { + while (j <= 10) + { printf("While loop iteration: %d\n", j); j++; } // do-while loop int k = 1; - do { + do + { printf("Do-While loop iteration: %d\n", k); k++; } while (k <= 10); @@ -28,9 +32,11 @@ int main() { int a, b; // Nested for and while loop - for (a = 1; a <= 5; a++) { + for (a = 1; a <= 5; a++) + { int c = 1; - while (c <= a) { + while (c <= a) + { printf("Nested For-While loop: %d\n", c); c++; } @@ -38,9 +44,11 @@ int main() { // Nested while and do-while loop int x = 1; - while (x <= 5) { + while (x <= 5) + { int y = 1; - do { + do + { printf("Nested While-Do-While loop: %d\n", y); y++; } while (y <= x); @@ -49,8 +57,10 @@ int main() { // Nested do-while and for loop int p = 1; - do { - for (int q = 1; q <= p; q++) { + do + { + for (int q = 1; q <= p; q++) + { printf("Nested Do-While-For loop: %d\n", q); } p++; @@ -61,13 +71,16 @@ int main() { // Nested while loop with a break statement int n = 1; - while (n <= 5) { + while (n <= 5) + { printf("Outer While loop iteration: %d\n", n); m = 1; - while (1) { + while (1) + { printf("Inner While loop iteration: %d\n", m); m++; - if (m == 4) { + if (m == 4) + { break; } } @@ -75,13 +88,19 @@ int main() { } // Loop with nested conditions - for (int v = 1; v <= 10; v++) { + for (int v = 1; v <= 10; v++) + { printf("Loop with Nested Conditions: %d - ", v); - if (v < 5) { + if (v < 5) + { printf("Less than 5\n"); - } else if (v > 5) { + } + else if (v > 5) + { printf("Greater than 5\n"); - } else { + } + else + { printf("Equal to 5\n"); } } diff --git a/tests/regression/75-termination/16-nested-loop-nontrivial-nonterminating.c b/tests/regression/75-termination/16-nested-loop-nontrivial-nonterminating.c index f89e28d91a..87b4b82ed9 100644 --- a/tests/regression/75-termination/16-nested-loop-nontrivial-nonterminating.c +++ b/tests/regression/75-termination/16-nested-loop-nontrivial-nonterminating.c @@ -1,13 +1,16 @@ // NONTERM PARAM: --set "ana.activated[+]" termination --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra #include -int main() { +int main() +{ int outerCount = 1; - while (outerCount <= 3) { + while (outerCount <= 3) + { int innerCount = 1; - while (outerCount < 3 || innerCount > 0) { + while (outerCount < 3 || innerCount > 0) + { printf("(%d, %d) ", outerCount, innerCount); innerCount++; } diff --git a/tests/regression/75-termination/17-goto-terminating.c b/tests/regression/75-termination/17-goto-terminating.c index 8270f8c960..45e92f32e8 100644 --- a/tests/regression/75-termination/17-goto-terminating.c +++ b/tests/regression/75-termination/17-goto-terminating.c @@ -2,14 +2,16 @@ // The program terminates but the analysis is currently only meant to detect up-jumping gotos as potentially NonTerminating, therefore we expect an NonTerm #include -int main() { +int main() +{ int num = 1; loop: printf("Current number: %d\n", num); num++; - if (num <= 10) { + if (num <= 10) + { goto loop; // We are not able to detect up-jumping gotos as terminating, we // just warn about them might being nonterminating. } diff --git a/tests/regression/75-termination/18-goto-nonterminating.c b/tests/regression/75-termination/18-goto-nonterminating.c index e26f02ec11..25f79e5b57 100644 --- a/tests/regression/75-termination/18-goto-nonterminating.c +++ b/tests/regression/75-termination/18-goto-nonterminating.c @@ -1,7 +1,8 @@ // NONTERM PARAM: --set "ana.activated[+]" termination --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra #include -int main() { +int main() +{ int num = 1; loop: diff --git a/tests/regression/75-termination/19-rand-terminating.c b/tests/regression/75-termination/19-rand-terminating.c index fc5d6ee7b7..06deac6c34 100644 --- a/tests/regression/75-termination/19-rand-terminating.c +++ b/tests/regression/75-termination/19-rand-terminating.c @@ -3,19 +3,25 @@ #include #include -int main() { +int main() +{ // Seed the random number generator srand(time(NULL)); - if (rand()) { + if (rand()) + { // Loop inside the if part - for (int i = 1; i <= 5; i++) { + for (int i = 1; i <= 5; i++) + { printf("Loop inside if part: %d\n", i); } - } else { + } + else + { // Loop inside the else part int j = 1; - while (j <= 5) { + while (j <= 5) + { printf("Loop inside else part: %d\n", j); j++; } diff --git a/tests/regression/75-termination/20-rand-nonterminating.c b/tests/regression/75-termination/20-rand-nonterminating.c index e74c15c948..83630ed6c4 100644 --- a/tests/regression/75-termination/20-rand-nonterminating.c +++ b/tests/regression/75-termination/20-rand-nonterminating.c @@ -3,19 +3,25 @@ #include #include -int main() { +int main() +{ // Seed the random number generator srand(time(NULL)); - if (rand()) { + if (rand()) + { // Loop inside the if part - for (int i = 1; i >= 0; i++) { + for (int i = 1; i >= 0; i++) + { printf("Loop inside if part: %d\n", i); } - } else { + } + else + { // Loop inside the else part int j = 1; - while (j > 0) { + while (j > 0) + { printf("Loop inside else part: %d\n", j); } } diff --git a/tests/regression/75-termination/21-no-exit-on-rand-unproofable.c b/tests/regression/75-termination/21-no-exit-on-rand-unproofable.c index 10774e3420..3e7a65dfd4 100644 --- a/tests/regression/75-termination/21-no-exit-on-rand-unproofable.c +++ b/tests/regression/75-termination/21-no-exit-on-rand-unproofable.c @@ -1,14 +1,18 @@ // NONTERM PARAM: --set "ana.activated[+]" termination --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra #include -int main() { +int main() +{ int forever, i = 0; // This loop is not provable, therefore it should throw a warning - while (i < 4 || forever == 1) { + while (i < 4 || forever == 1) + { i++; - if (i == 4) { - if (rand()) { + if (i == 4) + { + if (rand()) + { forever = 1; } } diff --git a/tests/regression/75-termination/22-exit-on-rand-unproofable.c b/tests/regression/75-termination/22-exit-on-rand-unproofable.c index 3f76f05aa9..b8d7992bd9 100644 --- a/tests/regression/75-termination/22-exit-on-rand-unproofable.c +++ b/tests/regression/75-termination/22-exit-on-rand-unproofable.c @@ -1,11 +1,13 @@ // NONTERM PARAM: --set "ana.activated[+]" termination --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra #include -int main() { +int main() +{ int forever = 1; // This loop is not provable, therefore it should throw a warning - while (forever == 1) { + while (forever == 1) + { if (rand()) // May exit, may not { forever = 0; diff --git a/tests/regression/75-termination/23-exit-on-rand-terminating.c b/tests/regression/75-termination/23-exit-on-rand-terminating.c index 080b3c8871..24d4980406 100644 --- a/tests/regression/75-termination/23-exit-on-rand-terminating.c +++ b/tests/regression/75-termination/23-exit-on-rand-terminating.c @@ -2,14 +2,16 @@ #include #include -int main() { +int main() +{ int short_run, i = 0; while (i < 90 && short_run != 1) // Currently not able to detect this as terminating { i++; - if (rand()) { + if (rand()) + { short_run = 1; } } diff --git a/tests/regression/75-termination/24-upjumping-goto-loopless-terminating.c b/tests/regression/75-termination/24-upjumping-goto-loopless-terminating.c index 88d8c8f418..3dbff9d7ea 100644 --- a/tests/regression/75-termination/24-upjumping-goto-loopless-terminating.c +++ b/tests/regression/75-termination/24-upjumping-goto-loopless-terminating.c @@ -2,7 +2,8 @@ // The program terminates but the analysis is currently only meant to detect up-jumping gotos as potentially NonTerminating, therefore we expect an NonTerm #include -int main() { // Currently not able to detect up-jumping loop free gotos +int main() +{ // Currently not able to detect up-jumping loop free gotos goto mark2; mark1: diff --git a/tests/regression/75-termination/25-leave-loop-goto-terminating.c b/tests/regression/75-termination/25-leave-loop-goto-terminating.c index 35edf86938..2cda3d3a03 100644 --- a/tests/regression/75-termination/25-leave-loop-goto-terminating.c +++ b/tests/regression/75-termination/25-leave-loop-goto-terminating.c @@ -1,10 +1,12 @@ // TODO TERM PARAM: --set "ana.activated[+]" termination --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra #include -int main() { +int main() +{ int counter = 0; - while (1) { + while (1) + { counter++; // Dummy code @@ -13,7 +15,8 @@ int main() { printf("Result: %d\n", result); // Condition to terminate the loop - if (result >= 10) { // Apron is not able to detect this + if (result >= 10) + { // Apron is not able to detect this goto end; } } diff --git a/tests/regression/75-termination/26-enter-loop-goto-terminating.c b/tests/regression/75-termination/26-enter-loop-goto-terminating.c index 97b46f66ca..0de9a95d6c 100644 --- a/tests/regression/75-termination/26-enter-loop-goto-terminating.c +++ b/tests/regression/75-termination/26-enter-loop-goto-terminating.c @@ -1,12 +1,14 @@ // TODO TERM PARAM: --set "ana.activated[+]" termination --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra #include -int main() { +int main() +{ int counter = 0; goto jump_point; - while (1) { + while (1) + { counter++; // Dummy code @@ -16,7 +18,8 @@ int main() { printf("Result: %d\n", result); // Condition to terminate the loop - if (result >= 10) { // Apron is not able to detect this + if (result >= 10) + { // Apron is not able to detect this goto end; } } diff --git a/tests/regression/75-termination/27-upjumping-goto-nonterminating.c b/tests/regression/75-termination/27-upjumping-goto-nonterminating.c index a6621dd986..e27d7161d5 100644 --- a/tests/regression/75-termination/27-upjumping-goto-nonterminating.c +++ b/tests/regression/75-termination/27-upjumping-goto-nonterminating.c @@ -1,7 +1,8 @@ // NONTERM PARAM: --set "ana.activated[+]" termination --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra #include -int main() { +int main() +{ goto mark2; mark1: diff --git a/tests/regression/75-termination/28-do-while-continue-terminating.c b/tests/regression/75-termination/28-do-while-continue-terminating.c index 402e744e2f..61bd578dcf 100644 --- a/tests/regression/75-termination/28-do-while-continue-terminating.c +++ b/tests/regression/75-termination/28-do-while-continue-terminating.c @@ -1,13 +1,16 @@ // TODO TERM PARAM: --set "ana.activated[+]" termination --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra #include -int main() { +int main() +{ int i = 1; - do { + do + { i++; printf("Inside the do-while loop\n"); - if (i % 2 == 0) { + if (i % 2 == 0) + { printf("Skipping %i is even\n", i); continue; // This is handled as an goto to line 8 and therefore an up-jumping goto diff --git a/tests/regression/75-termination/29-do-while-continue-nonterminating.c b/tests/regression/75-termination/29-do-while-continue-nonterminating.c index be3e7e12de..41f1dbd5bc 100644 --- a/tests/regression/75-termination/29-do-while-continue-nonterminating.c +++ b/tests/regression/75-termination/29-do-while-continue-nonterminating.c @@ -1,14 +1,17 @@ // NONTERM PARAM: --set "ana.activated[+]" termination --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra #include -int main() { +int main() +{ int i = 1; - do { + do + { printf("Inside the do-while loop\n"); i++; - if (i % 2) { + if (i % 2) + { printf("Continue as %i is odd\n", i); continue; } diff --git a/tests/regression/75-termination/30-goto-out-of-inner-loop-terminating.c b/tests/regression/75-termination/30-goto-out-of-inner-loop-terminating.c index e2eff29c8b..5cdadf4396 100644 --- a/tests/regression/75-termination/30-goto-out-of-inner-loop-terminating.c +++ b/tests/regression/75-termination/30-goto-out-of-inner-loop-terminating.c @@ -1,15 +1,19 @@ // TERM PARAM: --set "ana.activated[+]" termination --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra #include -int main() { +int main() +{ int rows = 5; int columns = 5; // Outer loop for rows - for (int i = 1; i <= rows; i++) { + for (int i = 1; i <= rows; i++) + { // Inner loop for columns - for (int j = 1; j <= columns; j++) { - if (j == 3) { + for (int j = 1; j <= columns; j++) + { + if (j == 3) + { goto outer_loop; // Jump to the label "outer_loop" } printf("(%d, %d) ", i, j); diff --git a/tests/regression/75-termination/31-goto-out-of-inner-loop-nonterminating.c b/tests/regression/75-termination/31-goto-out-of-inner-loop-nonterminating.c index 756a93414b..cb54b5dd2f 100644 --- a/tests/regression/75-termination/31-goto-out-of-inner-loop-nonterminating.c +++ b/tests/regression/75-termination/31-goto-out-of-inner-loop-nonterminating.c @@ -1,15 +1,19 @@ // NONTERM PARAM: --set "ana.activated[+]" termination --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra #include -int main() { +int main() +{ int rows = 5; int columns = 5; // Outer loop for rows - for (int i = 1; 1; i++) { + for (int i = 1; 1; i++) + { // Inner loop for columns - for (int j = 1; j <= columns; j++) { - if (j == 3) { + for (int j = 1; j <= columns; j++) + { + if (j == 3) + { printf("Goto as continue for outer loop\n"); goto outer_loop; // Jump to the label "outer_loop" } diff --git a/tests/regression/75-termination/32-multithread-terminating.c b/tests/regression/75-termination/32-multithread-terminating.c index 737b867cde..fbac273776 100644 --- a/tests/regression/75-termination/32-multithread-terminating.c +++ b/tests/regression/75-termination/32-multithread-terminating.c @@ -5,14 +5,16 @@ #include // Thread function -void *printPID(void *arg) { +void *printPID(void *arg) +{ pid_t pid = getpid(); pthread_t tid = pthread_self(); printf("Thread ID: %lu, Process ID: %d\n", (unsigned long)tid, pid); return NULL; } -int main() { +int main() +{ // Create three threads pthread_t thread1, thread2, thread3; pthread_create(&thread1, NULL, printPID, NULL); diff --git a/tests/regression/75-termination/33-multithread-nonterminating.c b/tests/regression/75-termination/33-multithread-nonterminating.c index 278c107821..dad62aa0f4 100644 --- a/tests/regression/75-termination/33-multithread-nonterminating.c +++ b/tests/regression/75-termination/33-multithread-nonterminating.c @@ -6,10 +6,12 @@ #include // Thread function -void *printPID(void *arg) { +void *printPID(void *arg) +{ pid_t pid = getpid(); pthread_t tid = pthread_self(); - while (1) { + while (1) + { printf("Thread ID: %lu, Process ID: %d\n", (unsigned long)tid, pid); struct timespec sleepTime; sleepTime.tv_sec = 1; // Seconds @@ -21,7 +23,8 @@ void *printPID(void *arg) { return NULL; } -int main() { +int main() +{ // Create three threads pthread_t thread1, thread2, thread3; pthread_create(&thread1, NULL, printPID, NULL); diff --git a/tests/regression/75-termination/34-nested-for-loop-nonterminating.c b/tests/regression/75-termination/34-nested-for-loop-nonterminating.c index 3384ed0f60..709960640f 100644 --- a/tests/regression/75-termination/34-nested-for-loop-nonterminating.c +++ b/tests/regression/75-termination/34-nested-for-loop-nonterminating.c @@ -1,11 +1,14 @@ // NONTERM PARAM: --set "ana.activated[+]" termination --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra #include -int main() { +int main() +{ int outerCount, innerCount; - for (outerCount = 1; outerCount <= 3; outerCount++) { - for (innerCount = 1; innerCount > 0; innerCount++) { + for (outerCount = 1; outerCount <= 3; outerCount++) + { + for (innerCount = 1; innerCount > 0; innerCount++) + { printf("(%d, %d) ", outerCount, innerCount); } diff --git a/tests/regression/75-termination/35-goto-out-of-inner-loop-with-print-terminating.c b/tests/regression/75-termination/35-goto-out-of-inner-loop-with-print-terminating.c index 646f39111a..f564354e51 100644 --- a/tests/regression/75-termination/35-goto-out-of-inner-loop-with-print-terminating.c +++ b/tests/regression/75-termination/35-goto-out-of-inner-loop-with-print-terminating.c @@ -1,15 +1,19 @@ // TERM PARAM: --set "ana.activated[+]" termination --set "ana.activated[+]" apron --enable ana.int.interval --set ana.apron.domain polyhedra --set sem.int.signed_overflow assume_none #include -int main() { +int main() +{ int rows = 5; int columns = 5; // Outer loop for rows - for (int i = 1; i <= rows; i++) { + for (int i = 1; i <= rows; i++) + { // Inner loop for columns - for (int j = 1; j <= columns; j++) { - if (j == 3) { + for (int j = 1; j <= columns; j++) + { + if (j == 3) + { goto outer_loop; // Jump to the label "outer_loop" } printf("(%d, %d) ", i, j); diff --git a/tests/regression/75-termination/36-recursion-terminating.c b/tests/regression/75-termination/36-recursion-terminating.c index 533778332f..7336417c91 100644 --- a/tests/regression/75-termination/36-recursion-terminating.c +++ b/tests/regression/75-termination/36-recursion-terminating.c @@ -1,9 +1,11 @@ // TERM PARAM: --set "ana.activated[+]" termination --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra #include -void recursiveFunction(int n) { +void recursiveFunction(int n) +{ // Base case: When n reaches 0, stop recursion - if (n == 0) { + if (n == 0) + { printf("Terminating recursion\n"); return; } @@ -14,7 +16,8 @@ void recursiveFunction(int n) { recursiveFunction(n - 1); } -int main() { +int main() +{ // Call the recursive function with an initial value recursiveFunction(5); diff --git a/tests/regression/75-termination/37-recursion-nonterminating.c b/tests/regression/75-termination/37-recursion-nonterminating.c index 089a4d3bcc..38aaf3de85 100644 --- a/tests/regression/75-termination/37-recursion-nonterminating.c +++ b/tests/regression/75-termination/37-recursion-nonterminating.c @@ -1,9 +1,11 @@ // NONTERM PARAM: --set "ana.activated[+]" termination --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra --enable ana.context.widen #include -void recursiveFunction(int n) { +void recursiveFunction(int n) +{ // Base case: When n reaches 0, stop recursion - if (n == 30) { + if (n == 30) + { printf("Terminating recursion\n"); return; } @@ -14,7 +16,8 @@ void recursiveFunction(int n) { recursiveFunction(n - 1); } -int main() { +int main() +{ // Call the recursive function with an initial value recursiveFunction(5); diff --git a/tests/regression/75-termination/38-recursion-nested-terminating.c b/tests/regression/75-termination/38-recursion-nested-terminating.c index eace365a44..bef05eb1a0 100644 --- a/tests/regression/75-termination/38-recursion-nested-terminating.c +++ b/tests/regression/75-termination/38-recursion-nested-terminating.c @@ -1,8 +1,10 @@ // TERM PARAM: --set "ana.activated[+]" termination --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra #include -void innerRecursiveFunction(int n) { - if (n == 0) { +void innerRecursiveFunction(int n) +{ + if (n == 0) + { printf("Terminating inner recursion\n"); return; } @@ -13,8 +15,10 @@ void innerRecursiveFunction(int n) { innerRecursiveFunction(n - 1); } -void outerRecursiveFunction(int n) { - if (n == 0) { +void outerRecursiveFunction(int n) +{ + if (n == 0) + { printf("Terminating outer recursion\n"); return; } @@ -28,7 +32,8 @@ void outerRecursiveFunction(int n) { innerRecursiveFunction(n); } -int main() { +int main() +{ // Call the outerRecursiveFunction with an initial value outerRecursiveFunction(3); diff --git a/tests/regression/75-termination/39-recursion-nested-nonterminating.c b/tests/regression/75-termination/39-recursion-nested-nonterminating.c index 8b57f83857..8311d9f573 100644 --- a/tests/regression/75-termination/39-recursion-nested-nonterminating.c +++ b/tests/regression/75-termination/39-recursion-nested-nonterminating.c @@ -1,14 +1,16 @@ // NONTERM PARAM: --set "ana.activated[+]" termination --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra #include -void innerRecursiveFunction() { +void innerRecursiveFunction() +{ printf("Nested recursive call\n"); // Recursive call to the innerRecursiveFunction innerRecursiveFunction(); } -void outerRecursiveFunction() { +void outerRecursiveFunction() +{ printf("Outer recursive call\n"); // Recursive call to the outerRecursiveFunction @@ -18,7 +20,8 @@ void outerRecursiveFunction() { innerRecursiveFunction(); } -int main() { +int main() +{ // Call the outerRecursiveFunction outerRecursiveFunction(); diff --git a/tests/regression/75-termination/40-complex-conditions.c b/tests/regression/75-termination/40-complex-conditions.c index d5fe6b808a..a74c863fb4 100644 --- a/tests/regression/75-termination/40-complex-conditions.c +++ b/tests/regression/75-termination/40-complex-conditions.c @@ -1,12 +1,15 @@ // TODO TERM PARAM: --set "ana.activated[+]" termination --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra #include -int main() { +int main() +{ int i; // Loop with a continue statement - for (i = 1; i <= 10; i++) { - if (i % 2 == 0) { + for (i = 1; i <= 10; i++) + { + if (i % 2 == 0) + { continue; } printf("%d ", i); @@ -14,8 +17,10 @@ int main() { printf("\n"); // Loop with complex conditions - for (i = 1; i <= 10; i++) { - if (i > 5 && i % 2 == 0) { + for (i = 1; i <= 10; i++) + { + if (i > 5 && i % 2 == 0) + { printf("%d ", i); } } @@ -23,8 +28,10 @@ int main() { // Loop with complex conditions i = 1; - while (i <= 10) { - if (i > 5 && i % 2 == 0) { + while (i <= 10) + { + if (i > 5 && i % 2 == 0) + { printf("%d ", i); } i++; diff --git a/tests/regression/75-termination/41-more-tests.c b/tests/regression/75-termination/41-more-tests.c index 272be43293..1fb9f83f5d 100644 --- a/tests/regression/75-termination/41-more-tests.c +++ b/tests/regression/75-termination/41-more-tests.c @@ -1,11 +1,14 @@ // TODO TERM PARAM: --set "ana.activated[+]" termination --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra #include -int main() { +int main() +{ // Loop with a continue statement - for (int r = 1; r <= 10; r++) { - if (r % 3 == 0) { + for (int r = 1; r <= 10; r++) + { + if (r % 3 == 0) + { continue; } printf("Loop with Continue: %d\n", r); @@ -13,14 +16,16 @@ int main() { // Loop with multiple conditions int s = 1; - while (s <= 10 && s % 2 == 0) { + while (s <= 10 && s % 2 == 0) + { printf("Loop with Multiple Conditions: %d\n", s); s++; } // Loop with multiple variables int t, u; - for (t = 1, u = 10; t <= 5 && u >= 5; t++, u--) { + for (t = 1, u = 10; t <= 5 && u >= 5; t++, u--) + { printf("Loop with Multiple Variables: %d %d\n", t, u); } } \ No newline at end of file From 4dd330ce4c530b68f1b2f4722c89c3e44c289a1f Mon Sep 17 00:00:00 2001 From: Thomas Lagemann Date: Mon, 10 Jul 2023 16:55:45 +0200 Subject: [PATCH 234/327] Execute termination tests in CI even if skipped. --- .github/workflows/locked.yml | 3 +++ 1 file changed, 3 insertions(+) diff --git a/.github/workflows/locked.yml b/.github/workflows/locked.yml index 751ade6880..48809d34c1 100644 --- a/.github/workflows/locked.yml +++ b/.github/workflows/locked.yml @@ -64,6 +64,9 @@ jobs: - name: Test apron regression (Mukherjee et. al SAS '17 paper') # skipped by default but CI has apron, so explicitly test group (which ignores skipping -- it's now a feature!) run: ruby scripts/update_suite.rb group apron-mukherjee -s + - name: Test apron termination regression # skipped by default but CI has apron, so explicitly test group (which ignores skipping -- it's now a feature!) + run: ruby scripts/update_suite.rb group termination -s + - name: Test regression cram run: opam exec -- dune runtest tests/regression From 5f984170bd0de91e79d972be599896a637037a84 Mon Sep 17 00:00:00 2001 From: Thomas Lagemann Date: Thu, 13 Jul 2023 20:51:13 +0200 Subject: [PATCH 235/327] Test explanation && new test case termination 43 --- ...-multi-expression-conditions-terminating.c | 44 +++++++++++++++++++ ...itions.c => 41-for-continue-terminating.c} | 25 +++-------- .../regression/75-termination/41-more-tests.c | 31 ------------- .../43-return-from-endless-loop-terminating.c | 14 ++++++ 4 files changed, 64 insertions(+), 50 deletions(-) create mode 100644 tests/regression/75-termination/40-multi-expression-conditions-terminating.c rename tests/regression/75-termination/{40-complex-conditions.c => 41-for-continue-terminating.c} (52%) delete mode 100644 tests/regression/75-termination/41-more-tests.c create mode 100644 tests/regression/75-termination/43-return-from-endless-loop-terminating.c diff --git a/tests/regression/75-termination/40-multi-expression-conditions-terminating.c b/tests/regression/75-termination/40-multi-expression-conditions-terminating.c new file mode 100644 index 0000000000..8e7b4e273d --- /dev/null +++ b/tests/regression/75-termination/40-multi-expression-conditions-terminating.c @@ -0,0 +1,44 @@ +// TODO TERM PARAM: --set "ana.activated[+]" termination --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra +#include + +int main() +{ + int i; + + // Loop with complex conditions + for (i = 1; i <= 10; i++) + { + if (i > 5 && i % 2 == 0) // CIL defines new jump labels to default location (-1) + { + printf("%d ", i); + } + } + printf("\n"); + + // Loop with complex conditions + i = 1; + while (i <= 10) + { + if (i > 5 && i % 2 == 0) // CIL defines new jump labels to default location (-1) + { + printf("%d ", i); + } + i++; + } + printf("\n"); + + // Loop with multiple conditions + int s = 1; + while (s <= 10 && s % 2 == 0) // CIL defines new jump labels to default location (-1) + { + printf("Loop with Multiple Conditions: %d\n", s); + s++; + } + + // Loop with multiple variables + int t, u; + for (t = 1, u = 10; t <= 5 && u >= 5; t++, u--) // CIL defines new jump labels to default location (-1) + { + printf("Loop with Multiple Variables: %d %d\n", t, u); + } +} \ No newline at end of file diff --git a/tests/regression/75-termination/40-complex-conditions.c b/tests/regression/75-termination/41-for-continue-terminating.c similarity index 52% rename from tests/regression/75-termination/40-complex-conditions.c rename to tests/regression/75-termination/41-for-continue-terminating.c index a74c863fb4..1d109c4ee7 100644 --- a/tests/regression/75-termination/40-complex-conditions.c +++ b/tests/regression/75-termination/41-for-continue-terminating.c @@ -3,38 +3,25 @@ int main() { - int i; - // Loop with a continue statement for (i = 1; i <= 10; i++) { if (i % 2 == 0) { - continue; + continue; // Converted to an goto to "for" in line 7 } printf("%d ", i); } printf("\n"); - // Loop with complex conditions - for (i = 1; i <= 10; i++) - { - if (i > 5 && i % 2 == 0) - { - printf("%d ", i); - } - } - printf("\n"); - // Loop with complex conditions - i = 1; - while (i <= 10) + // Loop with a continue statement + for (int r = 1; r <= 10; r++) { - if (i > 5 && i % 2 == 0) + if (r % 3 == 0) { - printf("%d ", i); + continue; // Converted to an goto to "for" in line 19 } - i++; + printf("Loop with Continue: %d\n", r); } - printf("\n"); } \ No newline at end of file diff --git a/tests/regression/75-termination/41-more-tests.c b/tests/regression/75-termination/41-more-tests.c deleted file mode 100644 index 1fb9f83f5d..0000000000 --- a/tests/regression/75-termination/41-more-tests.c +++ /dev/null @@ -1,31 +0,0 @@ -// TODO TERM PARAM: --set "ana.activated[+]" termination --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra -#include - -int main() -{ - - // Loop with a continue statement - for (int r = 1; r <= 10; r++) - { - if (r % 3 == 0) - { - continue; - } - printf("Loop with Continue: %d\n", r); - } - - // Loop with multiple conditions - int s = 1; - while (s <= 10 && s % 2 == 0) - { - printf("Loop with Multiple Conditions: %d\n", s); - s++; - } - - // Loop with multiple variables - int t, u; - for (t = 1, u = 10; t <= 5 && u >= 5; t++, u--) - { - printf("Loop with Multiple Variables: %d %d\n", t, u); - } -} \ No newline at end of file diff --git a/tests/regression/75-termination/43-return-from-endless-loop-terminating.c b/tests/regression/75-termination/43-return-from-endless-loop-terminating.c new file mode 100644 index 0000000000..06bda24bd7 --- /dev/null +++ b/tests/regression/75-termination/43-return-from-endless-loop-terminating.c @@ -0,0 +1,14 @@ +// TERM PARAM: --set "ana.activated[+]" termination --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra +#include + +int main() { + int i = 1; + + while (i != 0) { + printf("%d\n", i); + i++; + if (i>10) { + return 0; + } + } +} From 76f540ffea9d19b7c9dc711047774900892c850d Mon Sep 17 00:00:00 2001 From: Thomas Lagemann Date: Thu, 13 Jul 2023 20:58:17 +0200 Subject: [PATCH 236/327] Test explanation && new test case termination 43 --- tests/regression/75-termination/41-for-continue-terminating.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/regression/75-termination/41-for-continue-terminating.c b/tests/regression/75-termination/41-for-continue-terminating.c index 1d109c4ee7..1d3b96fcf8 100644 --- a/tests/regression/75-termination/41-for-continue-terminating.c +++ b/tests/regression/75-termination/41-for-continue-terminating.c @@ -4,7 +4,7 @@ int main() { // Loop with a continue statement - for (i = 1; i <= 10; i++) + for (int i = 1; i <= 10; i++) { if (i % 2 == 0) { From 40ea15c5a2d3691bfa047701e09e45bcec161799 Mon Sep 17 00:00:00 2001 From: Isidor Zweckstetter Date: Thu, 13 Jul 2023 22:27:45 +0200 Subject: [PATCH 237/327] Added special function --Still work in progress --- src/analyses/libraryDesc.ml | 1 + src/util/terminationPreprocessing.ml | 18 ++++++++++++++++-- 2 files changed, 17 insertions(+), 2 deletions(-) diff --git a/src/analyses/libraryDesc.ml b/src/analyses/libraryDesc.ml index 8b90553e95..0ac3e87f96 100644 --- a/src/analyses/libraryDesc.ml +++ b/src/analyses/libraryDesc.ml @@ -72,6 +72,7 @@ type special = | Identity of Cil.exp (** Identity function. Some compiler optimization annotation functions map to this. *) | Setjmp of { env: Cil.exp; } | Longjmp of { env: Cil.exp; value: Cil.exp; } + | Bounded of { var: Cil.exp} | Unknown (** Anything not belonging to other types. *) (* TODO: rename to Other? *) diff --git a/src/util/terminationPreprocessing.ml b/src/util/terminationPreprocessing.ml index 4043c6d256..1aa78ccae7 100644 --- a/src/util/terminationPreprocessing.ml +++ b/src/util/terminationPreprocessing.ml @@ -3,6 +3,19 @@ include Printf module VarToStmt = Map.Make(CilType.Varinfo) (* maps varinfos (= loop counter variable) to the statement of the corresponding loop*) +let specialFunction name = + print_endline @@ "specialfunction done"; + { svar = makeGlobalVar name (TFun(voidType, Some [("exp", intType, [])], false,[])); + smaxid = 0; + slocals = []; + sformals = []; + sbody = mkBlock []; + smaxstmtid = None; + sallstmts = []; + } + +let f_bounded = Lval (var (specialFunction "__goblint_bounded").svar) + let extract_file_name s = (*There still may be a need to filter more chars*) let ls = String.split_on_char '/' s in (*Assuming '/' as path seperator*) let ls = List.rev ls in @@ -35,11 +48,12 @@ class loopCounterVisitor lc lg le (fd : fundec) = object(self) let inc_stmt = mkStmtOneInstr @@ Set (var v, increm (Lval (var v)) 1, loc, eloc) in let check_stmt = mkStmtOneInstr @@ Set ((var !le), (Lval (var v)), loc, eloc) in let inc_stmt2 = mkStmtOneInstr @@ Set (var v, increm (Lval (var v)) 1, loc, eloc) in + let exit_stmt = mkStmtOneInstr @@ Call (None, f_bounded, [Lval (var v)], loc, locUnknown) in (match b.bstmts with | s :: ss -> (*duplicate increment statement here to fix inconsistencies in nested loops*) - b.bstmts <- inc_stmt :: check_stmt :: s :: inc_stmt2 :: ss; + b.bstmts <- inc_stmt :: check_stmt :: exit_stmt :: s :: inc_stmt2 :: ss; | ss -> - b.bstmts <- inc_stmt :: check_stmt :: ss; + b.bstmts <- inc_stmt :: check_stmt :: exit_stmt :: ss; ); lc := VarToStmt.add (v: varinfo) (s: stmt) !lc; let nb = mkBlock [init_stmt; mkStmt s.skind] in From 30692fc5d626c99c5b120502009e7e88c546d14e Mon Sep 17 00:00:00 2001 From: Thomas Lagemann Date: Thu, 13 Jul 2023 22:47:22 +0200 Subject: [PATCH 238/327] Test for code line detection --- scripts/update_suite.rb | 45 +++++++++++-------- src/analyses/loopTermination.ml | 6 +-- src/framework/constraints.ml | 2 +- .../02-simple-loop-nonterminating.c | 2 +- .../04-nested-loop-nonterminating.c | 2 +- .../06-for-loop-nonterminating.c | 2 +- .../08-nested-for-loop-nonterminating.c | 2 +- .../14-do-while-nonterminating.c | 2 +- ...16-nested-loop-nontrivial-nonterminating.c | 2 +- .../75-termination/17-goto-terminating.c | 3 +- .../75-termination/18-goto-nonterminating.c | 2 +- .../75-termination/20-rand-nonterminating.c | 4 +- .../21-no-exit-on-rand-unproofable.c | 2 +- .../22-exit-on-rand-unproofable.c | 2 +- .../23-exit-on-rand-terminating.c | 5 +-- .../24-upjumping-goto-loopless-terminating.c | 2 +- .../27-upjumping-goto-nonterminating.c | 4 +- .../29-do-while-continue-nonterminating.c | 2 +- ...31-goto-out-of-inner-loop-nonterminating.c | 4 +- .../34-nested-for-loop-nonterminating.c | 2 +- .../37-recursion-nonterminating.c | 2 +- .../39-recursion-nested-nonterminating.c | 4 +- 22 files changed, 56 insertions(+), 47 deletions(-) diff --git a/scripts/update_suite.rb b/scripts/update_suite.rb index 8841ecea88..60a7ec06be 100755 --- a/scripts/update_suite.rb +++ b/scripts/update_suite.rb @@ -149,24 +149,27 @@ def collect_warnings next unless l =~ /(.*)\(.*?\:(\d+)(?:\:\d+)?(?:-(?:\d+)(?:\:\d+)?)?\)/ obj,i = $1,$2.to_i - ranking = ["other", "warn", "term", "nonterm", "race", "norace", "deadlock", "nodeadlock", "success", "fail", "unknown"] + ranking = ["other", "warn", "goto", "fundec", "loop", "term", "nonterm", "race", "norace", "deadlock", "nodeadlock", "success", "fail", "unknown"] thiswarn = case obj - when /\(conf\. \d+\)/ then "race" - when /Deadlock/ then "deadlock" - when /lock (before|after):/ then "deadlock" - when /Assertion .* will fail/ then "fail" - when /Assertion .* will succeed/ then "success" - when /Assertion .* is unknown/ then "unknown" - when /invariant confirmed/ then "success" - when /invariant unconfirmed/ then "unknown" - when /invariant refuted/ then "fail" - when /^\[Warning\]/ then "warn" - when /^\[Error\]/ then "warn" - when /^\[Info\]/ then "warn" - when /^\[Success\]/ then "success" - when /\[Debug\]/ then next # debug "warnings" shouldn't count as other warnings (against NOWARN) - when /^ on line \d+ $/ then next # dead line warnings shouldn't count (used for unreachability with NOWARN) - when /^ on lines \d+..\d+ $/ then next # dead line warnings shouldn't count (used for unreachability with NOWARN) + when /\(conf\. \d+\)/ then "race" + when /Deadlock/ then "deadlock" + when /lock (before|after):/ then "deadlock" + when /Assertion .* will fail/ then "fail" + when /Assertion .* will succeed/ then "success" + when /Assertion .* is unknown/ then "unknown" + when /invariant confirmed/ then "success" + when /invariant unconfirmed/ then "unknown" + when /invariant refuted/ then "fail" + when /^\[Warning\]/ then "warn" + when /^\[Error\]/ then "warn" + when /^\[Info\]/ then "warn" + when /^\[Success\]/ then "success" + when /(Upjumping Goto)/ then "goto" + when /(Fundec \w+ is contained in a call graph cycle)/ then "fundec" + when /(Loop analysis)/ then "loop" + when /\[Debug\]/ then next # debug "warnings" shouldn't count as other warnings (against NOWARN) + when /^ on line \d+ $/ then next # dead line warnings shouldn't count (used for unreachability with NOWARN) + when /^ on lines \d+..\d+ $/ then next # dead line warnings shouldn't count (used for unreachability with NOWARN) else "other" end oldwarn = warnings[i] @@ -206,7 +209,7 @@ def compare_warnings end } case type - when "deadlock", "race", "fail", "unknown", "warn" + when "goto", "fundec", "loop", "deadlock", "race", "fail", "unknown", "warn" check.call warnings[idx] == type when "nonterm" check.call warnings[idx] == type @@ -309,6 +312,12 @@ def parse_tests (lines) tests[i] = "success" elsif obj =~ /FAIL/ then tests[i] = "fail" + elsif obj =~ /NONTERMLOOP/ then + tests[i] = "loop" + elsif obj =~ /NONTERMGOTO/ then + tests[i] = "goto" + elsif obj =~ /NONTERMFUNDEC/ then + tests[i] = "fundec" elsif obj =~ /UNKNOWN/ then tests[i] = "unknown" elsif obj =~ /(assert|__goblint_check).*\(/ then diff --git a/src/analyses/loopTermination.ml b/src/analyses/loopTermination.ml index 367c3a328c..44caf5c90a 100644 --- a/src/analyses/loopTermination.ml +++ b/src/analyses/loopTermination.ml @@ -70,13 +70,13 @@ struct List.iter (fun x -> let msgs = - [(Pretty.dprintf "The program might not terminate! (Upjumping Goto)\n", Some (M.Location.CilLocation x));] in + [(Pretty.dprintf "The program might not terminate! (Upjumping Goto)", Some (M.Location.CilLocation x));] in M.msg_group Warning ~category:NonTerminating "Possibly non terminating loops" msgs) (!upjumping_gotos) ); (* multithreaded *) if not (!single_thread) then ( - M.warn ~category:NonTerminating "The program might not terminate! (Multithreaded)\n" + M.warn ~category:NonTerminating "The program might not terminate! (Multithreaded)" ) @@ -93,7 +93,7 @@ struct (* In case the loop is not bounded, a warning is created*) if not (is_bounded) then ( let msgs = - [(Pretty.dprintf "The program might not terminate! (Loop analysis)\n", Some (M.Location.CilLocation (Cilfacade.get_stmtLoc loop_statement)));] in + [(Pretty.dprintf "The program might not terminate! (Loop analysis)", Some (M.Location.CilLocation (Cilfacade.get_stmtLoc loop_statement)));] in M.msg_group Warning ~category:NonTerminating "Possibly non terminating loops" msgs); () | _ -> () diff --git a/src/framework/constraints.ml b/src/framework/constraints.ml index 6114f30adb..3d10248885 100644 --- a/src/framework/constraints.ml +++ b/src/framework/constraints.ml @@ -1797,7 +1797,7 @@ struct (*Cycle found*) let msgs = [ - (Pretty.dprintf "The program might not terminate! (Fundec %a is contained in a call graph cycle)\n" CilType.Fundec.pretty fundec_e, Some (M.Location.CilLocation fundec_e.svar.vdecl)); + (Pretty.dprintf "The program might not terminate! (Fundec %a is contained in a call graph cycle)" CilType.Fundec.pretty fundec_e, Some (M.Location.CilLocation fundec_e.svar.vdecl)); ] in M.msg_group Warning ~category:NonTerminating "Recursion cycle" msgs) (* output a warning for non-termination*) else if not (LH.mem global_visited_calls call) then begin diff --git a/tests/regression/75-termination/02-simple-loop-nonterminating.c b/tests/regression/75-termination/02-simple-loop-nonterminating.c index 51fb340f3b..c6e1c6c8d6 100644 --- a/tests/regression/75-termination/02-simple-loop-nonterminating.c +++ b/tests/regression/75-termination/02-simple-loop-nonterminating.c @@ -3,7 +3,7 @@ int main() { - while (1) + while (1) // NONTERMLOOP termination analysis shall mark beginning of while as non-terminating loop { continue; } diff --git a/tests/regression/75-termination/04-nested-loop-nonterminating.c b/tests/regression/75-termination/04-nested-loop-nonterminating.c index fffc932f36..21a6d47051 100644 --- a/tests/regression/75-termination/04-nested-loop-nonterminating.c +++ b/tests/regression/75-termination/04-nested-loop-nonterminating.c @@ -9,7 +9,7 @@ int main() { int innerCount = 1; - while (1) + while (1) // NONTERMLOOP termination analysis shall mark beginning of while as non-terminating loop { printf("(%d, %d) ", outerCount, innerCount); innerCount++; diff --git a/tests/regression/75-termination/06-for-loop-nonterminating.c b/tests/regression/75-termination/06-for-loop-nonterminating.c index be876c9741..0f96209e35 100644 --- a/tests/regression/75-termination/06-for-loop-nonterminating.c +++ b/tests/regression/75-termination/06-for-loop-nonterminating.c @@ -3,7 +3,7 @@ int main() { - for (;;) + for (;;) // NONTERMLOOP termination analysis shall mark beginning of for as non-terminating loop { printf("This loop does not terminate.\n"); } diff --git a/tests/regression/75-termination/08-nested-for-loop-nonterminating.c b/tests/regression/75-termination/08-nested-for-loop-nonterminating.c index e360d45d0a..ec76f31534 100644 --- a/tests/regression/75-termination/08-nested-for-loop-nonterminating.c +++ b/tests/regression/75-termination/08-nested-for-loop-nonterminating.c @@ -7,7 +7,7 @@ int main() for (outerCount = 1; outerCount <= 3; outerCount++) { - for (innerCount = 1;; innerCount++) + for (innerCount = 1;; innerCount++) // NONTERMLOOP termination analysis shall mark beginning of for as non-terminating loop { printf("(%d, %d) ", outerCount, innerCount); } diff --git a/tests/regression/75-termination/14-do-while-nonterminating.c b/tests/regression/75-termination/14-do-while-nonterminating.c index 30c8349bb5..5522b61d88 100644 --- a/tests/regression/75-termination/14-do-while-nonterminating.c +++ b/tests/regression/75-termination/14-do-while-nonterminating.c @@ -9,7 +9,7 @@ int main() { printf("Inside the do-while loop\n"); i++; - } while (i >= 2); + } while (i >= 2); // NONTERMLOOP termination analysis shall mark while as non-terminating loop printf("Exited the loop\n"); return 0; diff --git a/tests/regression/75-termination/16-nested-loop-nontrivial-nonterminating.c b/tests/regression/75-termination/16-nested-loop-nontrivial-nonterminating.c index 87b4b82ed9..bded788a90 100644 --- a/tests/regression/75-termination/16-nested-loop-nontrivial-nonterminating.c +++ b/tests/regression/75-termination/16-nested-loop-nontrivial-nonterminating.c @@ -9,7 +9,7 @@ int main() { int innerCount = 1; - while (outerCount < 3 || innerCount > 0) + while (outerCount < 3 || innerCount > 0) // NONTERMLOOP termination analysis shall mark beginning of while as non-terminating loop { printf("(%d, %d) ", outerCount, innerCount); innerCount++; diff --git a/tests/regression/75-termination/17-goto-terminating.c b/tests/regression/75-termination/17-goto-terminating.c index 45e92f32e8..941db0c601 100644 --- a/tests/regression/75-termination/17-goto-terminating.c +++ b/tests/regression/75-termination/17-goto-terminating.c @@ -12,7 +12,8 @@ int main() if (num <= 10) { - goto loop; // We are not able to detect up-jumping gotos as terminating, we + goto loop; // NONTERMGOTO termination analysis shall mark goto statement up-jumping goto + // We are not able to detect up-jumping gotos as terminating, we // just warn about them might being nonterminating. } diff --git a/tests/regression/75-termination/18-goto-nonterminating.c b/tests/regression/75-termination/18-goto-nonterminating.c index 25f79e5b57..f88088ad12 100644 --- a/tests/regression/75-termination/18-goto-nonterminating.c +++ b/tests/regression/75-termination/18-goto-nonterminating.c @@ -9,7 +9,7 @@ int main() printf("Current number: %d\n", num); num++; - goto loop; + goto loop; // NONTERMGOTO termination analysis shall mark goto statement up-jumping goto return 0; } diff --git a/tests/regression/75-termination/20-rand-nonterminating.c b/tests/regression/75-termination/20-rand-nonterminating.c index 83630ed6c4..394bce7709 100644 --- a/tests/regression/75-termination/20-rand-nonterminating.c +++ b/tests/regression/75-termination/20-rand-nonterminating.c @@ -11,7 +11,7 @@ int main() if (rand()) { // Loop inside the if part - for (int i = 1; i >= 0; i++) + for (int i = 1; i >= 0; i++) // NONTERMLOOP termination analysis shall mark beginning of while as non-terminating loop { printf("Loop inside if part: %d\n", i); } @@ -20,7 +20,7 @@ int main() { // Loop inside the else part int j = 1; - while (j > 0) + while (j > 0) // NONTERMLOOP termination analysis shall mark beginning of while as non-terminating loop { printf("Loop inside else part: %d\n", j); } diff --git a/tests/regression/75-termination/21-no-exit-on-rand-unproofable.c b/tests/regression/75-termination/21-no-exit-on-rand-unproofable.c index 3e7a65dfd4..902ef2a4e2 100644 --- a/tests/regression/75-termination/21-no-exit-on-rand-unproofable.c +++ b/tests/regression/75-termination/21-no-exit-on-rand-unproofable.c @@ -6,7 +6,7 @@ int main() int forever, i = 0; // This loop is not provable, therefore it should throw a warning - while (i < 4 || forever == 1) + while (i < 4 || forever == 1) // NONTERMLOOP termination analysis shall mark beginning of while as non-terminating loop { i++; if (i == 4) diff --git a/tests/regression/75-termination/22-exit-on-rand-unproofable.c b/tests/regression/75-termination/22-exit-on-rand-unproofable.c index b8d7992bd9..f14f7d4e3f 100644 --- a/tests/regression/75-termination/22-exit-on-rand-unproofable.c +++ b/tests/regression/75-termination/22-exit-on-rand-unproofable.c @@ -6,7 +6,7 @@ int main() int forever = 1; // This loop is not provable, therefore it should throw a warning - while (forever == 1) + while (forever == 1) // NONTERMLOOP termination analysis shall mark beginning of while as non-terminating loop { if (rand()) // May exit, may not { diff --git a/tests/regression/75-termination/23-exit-on-rand-terminating.c b/tests/regression/75-termination/23-exit-on-rand-terminating.c index 24d4980406..013aff2dd5 100644 --- a/tests/regression/75-termination/23-exit-on-rand-terminating.c +++ b/tests/regression/75-termination/23-exit-on-rand-terminating.c @@ -5,9 +5,8 @@ int main() { int short_run, i = 0; - - while (i < 90 && - short_run != 1) // Currently not able to detect this as terminating + // Currently not able to detect this as terminating due to multiple conditions + while (i < 90 && short_run != 1) { i++; if (rand()) diff --git a/tests/regression/75-termination/24-upjumping-goto-loopless-terminating.c b/tests/regression/75-termination/24-upjumping-goto-loopless-terminating.c index 3dbff9d7ea..3f4e115445 100644 --- a/tests/regression/75-termination/24-upjumping-goto-loopless-terminating.c +++ b/tests/regression/75-termination/24-upjumping-goto-loopless-terminating.c @@ -12,7 +12,7 @@ int main() mark2: printf("This is mark2\n"); - goto mark1; + goto mark1; // NONTERMGOTO termination analysis shall mark goto statement up-jumping goto mark3: printf("This is mark3\n"); diff --git a/tests/regression/75-termination/27-upjumping-goto-nonterminating.c b/tests/regression/75-termination/27-upjumping-goto-nonterminating.c index e27d7161d5..5ce295872c 100644 --- a/tests/regression/75-termination/27-upjumping-goto-nonterminating.c +++ b/tests/regression/75-termination/27-upjumping-goto-nonterminating.c @@ -11,11 +11,11 @@ int main() mark2: printf("This is mark2\n"); - goto mark1; + goto mark1; // NONTERMGOTO termination analysis shall mark goto statement up-jumping goto mark3: printf("This is mark3\n"); - goto mark1; + goto mark1; // NONTERMGOTO termination analysis shall mark goto statement up-jumping goto return 0; } diff --git a/tests/regression/75-termination/29-do-while-continue-nonterminating.c b/tests/regression/75-termination/29-do-while-continue-nonterminating.c index 41f1dbd5bc..34766ab2e7 100644 --- a/tests/regression/75-termination/29-do-while-continue-nonterminating.c +++ b/tests/regression/75-termination/29-do-while-continue-nonterminating.c @@ -15,7 +15,7 @@ int main() printf("Continue as %i is odd\n", i); continue; } - } while (i >= 2); + } while (i >= 2); // NONTERMLOOP termination analysis shall mark beginning of while as non-terminating loop printf("Exited the loop\n"); return 0; diff --git a/tests/regression/75-termination/31-goto-out-of-inner-loop-nonterminating.c b/tests/regression/75-termination/31-goto-out-of-inner-loop-nonterminating.c index cb54b5dd2f..d7ff329396 100644 --- a/tests/regression/75-termination/31-goto-out-of-inner-loop-nonterminating.c +++ b/tests/regression/75-termination/31-goto-out-of-inner-loop-nonterminating.c @@ -7,7 +7,7 @@ int main() int columns = 5; // Outer loop for rows - for (int i = 1; 1; i++) + for (int i = 1; 1; i++) // NONTERMLOOP termination analysis shall mark beginning of for as non-terminating loop { // Inner loop for columns for (int j = 1; j <= columns; j++) @@ -15,7 +15,7 @@ int main() if (j == 3) { printf("Goto as continue for outer loop\n"); - goto outer_loop; // Jump to the label "outer_loop" + goto outer_loop; } printf("(%d, %d) ", i, j); } diff --git a/tests/regression/75-termination/34-nested-for-loop-nonterminating.c b/tests/regression/75-termination/34-nested-for-loop-nonterminating.c index 709960640f..24605ad478 100644 --- a/tests/regression/75-termination/34-nested-for-loop-nonterminating.c +++ b/tests/regression/75-termination/34-nested-for-loop-nonterminating.c @@ -7,7 +7,7 @@ int main() for (outerCount = 1; outerCount <= 3; outerCount++) { - for (innerCount = 1; innerCount > 0; innerCount++) + for (innerCount = 1; innerCount > 0; innerCount++) // NONTERMLOOP termination analysis shall mark beginning of for as non-terminating loop { printf("(%d, %d) ", outerCount, innerCount); } diff --git a/tests/regression/75-termination/37-recursion-nonterminating.c b/tests/regression/75-termination/37-recursion-nonterminating.c index 38aaf3de85..21316de9bd 100644 --- a/tests/regression/75-termination/37-recursion-nonterminating.c +++ b/tests/regression/75-termination/37-recursion-nonterminating.c @@ -1,7 +1,7 @@ // NONTERM PARAM: --set "ana.activated[+]" termination --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra --enable ana.context.widen #include -void recursiveFunction(int n) +void recursiveFunction(int n) // NONTERMFUNDEC termination analysis shall mark fundec of non-terminating function { // Base case: When n reaches 0, stop recursion if (n == 30) diff --git a/tests/regression/75-termination/39-recursion-nested-nonterminating.c b/tests/regression/75-termination/39-recursion-nested-nonterminating.c index 8311d9f573..b3aa8bf21b 100644 --- a/tests/regression/75-termination/39-recursion-nested-nonterminating.c +++ b/tests/regression/75-termination/39-recursion-nested-nonterminating.c @@ -1,7 +1,7 @@ // NONTERM PARAM: --set "ana.activated[+]" termination --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra #include -void innerRecursiveFunction() +void innerRecursiveFunction() // TODO NONTERMFUNDEC termination analysis shall mark fundec of non-terminating function { printf("Nested recursive call\n"); @@ -9,7 +9,7 @@ void innerRecursiveFunction() innerRecursiveFunction(); } -void outerRecursiveFunction() +void outerRecursiveFunction() // NONTERMFUNDEC termination analysis shall mark fundec of non-terminating function { printf("Outer recursive call\n"); From dc0a284ccc4c6337db5458882345a6aa126cf3bc Mon Sep 17 00:00:00 2001 From: Isidor Zweckstetter Date: Thu, 13 Jul 2023 23:42:13 +0200 Subject: [PATCH 239/327] changed __goblint_bounded constructor from Assert to Bounded --- src/analyses/libraryDesc.ml | 2 +- src/analyses/libraryFunctions.ml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/analyses/libraryDesc.ml b/src/analyses/libraryDesc.ml index 0ac3e87f96..3896e74574 100644 --- a/src/analyses/libraryDesc.ml +++ b/src/analyses/libraryDesc.ml @@ -72,7 +72,7 @@ type special = | Identity of Cil.exp (** Identity function. Some compiler optimization annotation functions map to this. *) | Setjmp of { env: Cil.exp; } | Longjmp of { env: Cil.exp; value: Cil.exp; } - | Bounded of { var: Cil.exp} + | Bounded of { exp: Cil.exp} | Unknown (** Anything not belonging to other types. *) (* TODO: rename to Other? *) diff --git a/src/analyses/libraryFunctions.ml b/src/analyses/libraryFunctions.ml index 5d65cf9cb3..045268ca4d 100644 --- a/src/analyses/libraryFunctions.ml +++ b/src/analyses/libraryFunctions.ml @@ -303,7 +303,7 @@ let goblint_descs_list: (string * LibraryDesc.t) list = LibraryDsl.[ ("__goblint_assert", special [__ "exp" []] @@ fun exp -> Assert { exp; check = true; refine = get_bool "sem.assert.refine" }); ("__goblint_split_begin", unknown [drop "exp" []]); ("__goblint_split_end", unknown [drop "exp" []]); - ("__goblint_bounded", special [__ "exp"[]] @@ fun exp -> Assert { exp; check = true; refine = false }); + ("__goblint_bounded", special [__ "exp"[]] @@ fun exp -> Bounded { exp }); ] (** zstd functions. From 1f499e99f91a5345105fd873f08fc00758336e5d Mon Sep 17 00:00:00 2001 From: Alexander Schlenga Date: Fri, 14 Jul 2023 14:31:05 +0200 Subject: [PATCH 240/327] Use special function instead of variable indicator We now use __goblint_bounded to mark the place where the value of the loop counter variable shall be checked for being bounded. Before, we used a variable called loop exit indicator for that. --- src/analyses/loopTermination.ml | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/src/analyses/loopTermination.ml b/src/analyses/loopTermination.ml index 367c3a328c..307e76211d 100644 --- a/src/analyses/loopTermination.ml +++ b/src/analyses/loopTermination.ml @@ -4,6 +4,7 @@ open Analyses open GoblintCil open TerminationPreprocessing +(* TODO: Remove *) exception PreProcessing of string (** Stores the result of the query if the program is single threaded or not @@ -40,7 +41,7 @@ let check_bounded ctx varinfo = (** We want to record termination information of loops and use the loop * statements for that. We use this lifting because we need to have a * lattice. *) -module Statements = Lattice.Flat (CilType.Stmt) (Printable.DefaultNames) (* TODO: Use Basetype.CilStmt instead? *) +module Statements = Lattice.Flat (CilType.Stmt) (Printable.DefaultNames) (** The termination analysis considering loops and gotos *) module Spec : Analyses.MCPSpec = @@ -79,7 +80,7 @@ struct M.warn ~category:NonTerminating "The program might not terminate! (Multithreaded)\n" ) - + (* let assign ctx (lval : lval) (rval : exp) = if !AnalysisState.postsolving then (* Detect assignment to loop counter variable *) @@ -98,21 +99,23 @@ struct () | _ -> () else () + *) - (* let special ctx (lval : lval option) (f : varinfo) (arglist : exp list) = - (* TODO: Implement check for our special loop exit indicator function *) if !AnalysisState.postsolving then match f.vname, arglist with "__goblint_bounded", [Lval (Var x, NoOffset)] -> - let () = print_endline "schpecial" in let is_bounded = check_bounded ctx x in let loop_statement = VarToStmt.find x !loop_counters in ctx.sideg () (G.add (`Lifted loop_statement) is_bounded (ctx.global ())); + (* In case the loop is not bounded, a warning is created*) + if not (is_bounded) then ( + let msgs = + [(Pretty.dprintf "The program might not terminate! (Loop analysis)\n", Some (M.Location.CilLocation (Cilfacade.get_stmtLoc loop_statement)));] in + M.msg_group Warning ~category:NonTerminating "Possibly non terminating loops" msgs); () | _ -> () else () - *) (** Checks whether a new thread was spawned some time. We want to discard * any knowledge about termination then (see query function) *) From b9a5b3fdda1cc2a216937206cd60d89d6a6849a0 Mon Sep 17 00:00:00 2001 From: Alexander Schlenga Date: Fri, 14 Jul 2023 14:44:28 +0200 Subject: [PATCH 241/327] Clean up, make things look nicer --- src/analyses/loopTermination.ml | 42 ++++++++++----------------------- 1 file changed, 12 insertions(+), 30 deletions(-) diff --git a/src/analyses/loopTermination.ml b/src/analyses/loopTermination.ml index 307e76211d..beb1cbfd06 100644 --- a/src/analyses/loopTermination.ml +++ b/src/analyses/loopTermination.ml @@ -23,9 +23,6 @@ let loop_exit : varinfo ref = ref (makeVarinfo false "-error" Cil.intType) let is_loop_counter_var (x : varinfo) = VarToStmt.mem x !loop_counters -let is_loop_exit_indicator (x : varinfo) = - x = !loop_exit - let no_upjumping_gotos () = upjumping_gotos.contents = [] @@ -65,42 +62,24 @@ struct let exitstate = startstate let finalize () = - (* warning for detected possible non-termination *) - (*upjumping gotos *) + (* Warning for detected possible non-termination *) + (* Upjumping gotos *) if not (no_upjumping_gotos ()) then ( List.iter (fun x -> let msgs = - [(Pretty.dprintf "The program might not terminate! (Upjumping Goto)\n", Some (M.Location.CilLocation x));] in + [(Pretty.dprintf + "The program might not terminate! (Upjumping Goto)\n", + Some (M.Location.CilLocation x) + );] in M.msg_group Warning ~category:NonTerminating "Possibly non terminating loops" msgs) (!upjumping_gotos) ); - (* multithreaded *) + (* Multithreaded *) if not (!single_thread) then ( M.warn ~category:NonTerminating "The program might not terminate! (Multithreaded)\n" ) - (* - let assign ctx (lval : lval) (rval : exp) = - if !AnalysisState.postsolving then - (* Detect assignment to loop counter variable *) - match lval, rval with - (Var y, NoOffset), Lval (Var x, NoOffset) when is_loop_exit_indicator y -> - (* Loop exit: Check whether loop counter variable is bounded *) - (* TODO: Move to special *) - let is_bounded = check_bounded ctx x in - let loop_statement = VarToStmt.find x !loop_counters in - ctx.sideg () (G.add (`Lifted loop_statement) is_bounded (ctx.global ())); - (* In case the loop is not bounded, a warning is created*) - if not (is_bounded) then ( - let msgs = - [(Pretty.dprintf "The program might not terminate! (Loop analysis)\n", Some (M.Location.CilLocation (Cilfacade.get_stmtLoc loop_statement)));] in - M.msg_group Warning ~category:NonTerminating "Possibly non terminating loops" msgs); - () - | _ -> () - else () - *) - let special ctx (lval : lval option) (f : varinfo) (arglist : exp list) = if !AnalysisState.postsolving then match f.vname, arglist with @@ -108,10 +87,13 @@ struct let is_bounded = check_bounded ctx x in let loop_statement = VarToStmt.find x !loop_counters in ctx.sideg () (G.add (`Lifted loop_statement) is_bounded (ctx.global ())); - (* In case the loop is not bounded, a warning is created*) + (* In case the loop is not bounded, a warning is created. *) if not (is_bounded) then ( let msgs = - [(Pretty.dprintf "The program might not terminate! (Loop analysis)\n", Some (M.Location.CilLocation (Cilfacade.get_stmtLoc loop_statement)));] in + [(Pretty.dprintf + "The program might not terminate! (Loop analysis)\n", + Some (M.Location.CilLocation (Cilfacade.get_stmtLoc loop_statement)) + );] in M.msg_group Warning ~category:NonTerminating "Possibly non terminating loops" msgs); () | _ -> () From 6146c760cbf6279e7055448820ab4f5c787ecc4a Mon Sep 17 00:00:00 2001 From: Alexander Schlenga Date: Fri, 14 Jul 2023 14:54:19 +0200 Subject: [PATCH 242/327] Wrap always_single_threaded in let-in clause --- src/analyses/loopTermination.ml | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/analyses/loopTermination.ml b/src/analyses/loopTermination.ml index beb1cbfd06..0211cc9cb5 100644 --- a/src/analyses/loopTermination.ml +++ b/src/analyses/loopTermination.ml @@ -115,10 +115,12 @@ struct Some b -> b | None -> false) | Queries.MustTermAllLoops -> + let always_single_threaded = must_be_single_threaded_since_start ctx in (* Must be the first to be evaluated! This has the side effect that * single_thread is set. In case of another order and due to lazy - * evaluation the correct value of single_thread can not be guaranteed! *) - must_be_single_threaded_since_start ctx + * evaluation, the correct value of single_thread can not be guaranteed! + * Therefore, we use a let-in clause here. *) + always_single_threaded && no_upjumping_gotos () && G.for_all (fun _ term_info -> term_info) (ctx.global ()) | _ -> Queries.Result.top q From 847ea368bc746551371286a36bb4c3263294f962 Mon Sep 17 00:00:00 2001 From: Alexander Schlenga Date: Fri, 14 Jul 2023 15:55:43 +0200 Subject: [PATCH 243/327] Remove PreProcessing exception --- src/analyses/loopTermination.ml | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/src/analyses/loopTermination.ml b/src/analyses/loopTermination.ml index 0211cc9cb5..942d38c0f3 100644 --- a/src/analyses/loopTermination.ml +++ b/src/analyses/loopTermination.ml @@ -4,9 +4,6 @@ open Analyses open GoblintCil open TerminationPreprocessing -(* TODO: Remove *) -exception PreProcessing of string - (** Stores the result of the query if the program is single threaded or not since finalize does not has ctx as an argument*) let single_thread : bool ref = ref false @@ -33,7 +30,7 @@ let check_bounded ctx varinfo = match ctx.ask (EvalInt exp) with | `Top -> false | `Lifted v -> not (is_top_of (ikind v) v) - | `Bot -> raise (PreProcessing "Loop variable is Bot") + | `Bot -> failwith "Loop counter variable is Bot." (** We want to record termination information of loops and use the loop * statements for that. We use this lifting because we need to have a From 0a9c5d432888750cf0d860a6568fcb887cedc12f Mon Sep 17 00:00:00 2001 From: Alexander Schlenga Date: Sat, 15 Jul 2023 14:54:57 +0200 Subject: [PATCH 244/327] Fix indentation --- src/analyses/base.ml | 578 +++++++++++++++++++++---------------------- 1 file changed, 289 insertions(+), 289 deletions(-) diff --git a/src/analyses/base.ml b/src/analyses/base.ml index 3a231ea396..fa45a7c38d 100644 --- a/src/analyses/base.ml +++ b/src/analyses/base.ml @@ -2064,307 +2064,307 @@ struct s1_a, s1_typ, VD.top_value (unrollType s1_typ) in let st = match desc.special args, f.vname with - | Memset { dest; ch; count; }, _ -> - (* TODO: check count *) - let eval_ch = eval_rv (Analyses.ask_of_ctx ctx) gs st ch in - let dest_a, dest_typ = addr_type_of_exp dest in - let value = - match eval_ch with - | Int i when ID.to_int i = Some Z.zero -> - VD.zero_init_value dest_typ - | _ -> - VD.top_value dest_typ - in - set ~ctx (Analyses.ask_of_ctx ctx) gs st dest_a dest_typ value - | Bzero { dest; count; }, _ -> - (* TODO: share something with memset special case? *) - (* TODO: check count *) - let dest_a, dest_typ = addr_type_of_exp dest in - let value = VD.zero_init_value dest_typ in - set ~ctx (Analyses.ask_of_ctx ctx) gs st dest_a dest_typ value - | Memcpy { dest = dst; src }, _ -> - memory_copying dst src - (* strcpy(dest, src); *) - | Strcpy { dest = dst; src; n = None }, _ -> - let dest_a, dest_typ = addr_type_of_exp dst in - (* when dest surely isn't a string literal, try copying src to dest *) - if AD.string_writing_defined dest_a then - memory_copying dst src - else - (* else return top (after a warning was issued) *) - set ~ctx (Analyses.ask_of_ctx ctx) gs st dest_a dest_typ (VD.top_value (unrollType dest_typ)) - (* strncpy(dest, src, n); *) - | Strcpy { dest = dst; src; n }, _ -> - begin match eval_n n with - | Some num -> - let dest_a, dest_typ, value = string_manipulation dst src None false None in - set ~ctx (Analyses.ask_of_ctx ctx) gs st dest_a dest_typ value - | None -> failwith "already handled in case above" - end - | Strcat { dest = dst; src; n }, _ -> - let dest_a, dest_typ, value = string_manipulation dst src None false None in - set ~ctx (Analyses.ask_of_ctx ctx) gs st dest_a dest_typ value - | Strlen s, _ -> - begin match lv with - | Some lv_val -> - let dest_a = eval_lv (Analyses.ask_of_ctx ctx) gs st lv_val in - let dest_typ = Cilfacade.typeOfLval lv_val in - let lval = mkMem ~addr:(Cil.stripCasts s) ~off:NoOffset in - let address = eval_lv (Analyses.ask_of_ctx ctx) gs st lval in - let (value:value) = Int(AD.to_string_length address) in - set ~ctx (Analyses.ask_of_ctx ctx) gs st dest_a dest_typ value - | None -> st - end - | Strstr { haystack; needle }, _ -> - begin match lv with - | Some _ -> - (* when haystack, needle and dest type coincide, check if needle is a substring of haystack: - if that is the case, assign the substring of haystack starting at the first occurrence of needle to dest, - else use top *) - let dest_a, dest_typ, value = string_manipulation haystack needle lv true (Some (fun h_a n_a -> Address(AD.substring_extraction h_a n_a))) in - set ~ctx (Analyses.ask_of_ctx ctx) gs st dest_a dest_typ value - | None -> st - end - | Strcmp { s1; s2; n }, _ -> - begin match lv with - | Some _ -> - (* when s1 and s2 type coincide, compare both both strings completely or their first n characters, otherwise use top *) - let dest_a, dest_typ, value = string_manipulation s1 s2 lv false (Some (fun s1_a s2_a -> Int(AD.string_comparison s1_a s2_a (eval_n n)))) in - set ~ctx (Analyses.ask_of_ctx ctx) gs st dest_a dest_typ value - | None -> st - end - | Abort, _ -> raise Deadcode - | ThreadExit { ret_val = exp }, _ -> - begin match ThreadId.get_current (Analyses.ask_of_ctx ctx) with - | `Lifted tid -> - ( - let rv = eval_rv (Analyses.ask_of_ctx ctx) ctx.global ctx.local exp in - ctx.sideg (V.thread tid) (G.create_thread rv); - (* TODO: emit thread return event so other analyses are aware? *) - (* TODO: publish still needed? *) - publish_all ctx `Return; (* like normal return *) - match ThreadId.get_current (Analyses.ask_of_ctx ctx) with - | `Lifted tid when ThreadReturn.is_current (Analyses.ask_of_ctx ctx) -> - ignore @@ Priv.thread_return (Analyses.ask_of_ctx ctx) (priv_getg ctx.global) (priv_sideg ctx.sideg) tid st - | _ -> ()) - | _ -> () - end; - raise Deadcode - | MutexAttrSetType {attr = attr; typ = mtyp}, _ -> - begin - let get_type lval = - let address = eval_lv (Analyses.ask_of_ctx ctx) gs st lval in - AD.type_of address + | Memset { dest; ch; count; }, _ -> + (* TODO: check count *) + let eval_ch = eval_rv (Analyses.ask_of_ctx ctx) gs st ch in + let dest_a, dest_typ = addr_type_of_exp dest in + let value = + match eval_ch with + | Int i when ID.to_int i = Some Z.zero -> + VD.zero_init_value dest_typ + | _ -> + VD.top_value dest_typ in - let dst_lval = mkMem ~addr:(Cil.stripCasts attr) ~off:NoOffset in - let dest_typ = get_type dst_lval in - let dest_a = eval_lv (Analyses.ask_of_ctx ctx) gs st dst_lval in - match eval_rv (Analyses.ask_of_ctx ctx) gs st mtyp with - | Int x -> - begin - match ID.to_int x with - | Some z -> - if M.tracing then M.tracel "attr" "setting\n"; - set ~ctx (Analyses.ask_of_ctx ctx) gs st dest_a dest_typ (MutexAttr (ValueDomain.MutexAttr.of_int z)) - | None -> set ~ctx (Analyses.ask_of_ctx ctx) gs st dest_a dest_typ (MutexAttr (ValueDomain.MutexAttr.top ())) - end - | _ -> set ~ctx (Analyses.ask_of_ctx ctx) gs st dest_a dest_typ (MutexAttr (ValueDomain.MutexAttr.top ())) - end - | Identity e, _ -> - begin match lv with - | Some x -> assign ctx x e - | None -> ctx.local - end - (**Floating point classification and trigonometric functions defined in c99*) - | Math { fun_args; }, _ -> - let apply_unary fk float_fun x = - let eval_x = eval_rv (Analyses.ask_of_ctx ctx) gs st x in - begin match eval_x with - | Float float_x -> float_fun (FD.cast_to fk float_x) - | _ -> failwith ("non-floating-point argument in call to function "^f.vname) + set ~ctx (Analyses.ask_of_ctx ctx) gs st dest_a dest_typ value + | Bzero { dest; count; }, _ -> + (* TODO: share something with memset special case? *) + (* TODO: check count *) + let dest_a, dest_typ = addr_type_of_exp dest in + let value = VD.zero_init_value dest_typ in + set ~ctx (Analyses.ask_of_ctx ctx) gs st dest_a dest_typ value + | Memcpy { dest = dst; src }, _ -> + memory_copying dst src + (* strcpy(dest, src); *) + | Strcpy { dest = dst; src; n = None }, _ -> + let dest_a, dest_typ = addr_type_of_exp dst in + (* when dest surely isn't a string literal, try copying src to dest *) + if AD.string_writing_defined dest_a then + memory_copying dst src + else + (* else return top (after a warning was issued) *) + set ~ctx (Analyses.ask_of_ctx ctx) gs st dest_a dest_typ (VD.top_value (unrollType dest_typ)) + (* strncpy(dest, src, n); *) + | Strcpy { dest = dst; src; n }, _ -> + begin match eval_n n with + | Some num -> + let dest_a, dest_typ, value = string_manipulation dst src None false None in + set ~ctx (Analyses.ask_of_ctx ctx) gs st dest_a dest_typ value + | None -> failwith "already handled in case above" end - in - let apply_binary fk float_fun x y = - let eval_x = eval_rv (Analyses.ask_of_ctx ctx) gs st x in - let eval_y = eval_rv (Analyses.ask_of_ctx ctx) gs st y in - begin match eval_x, eval_y with - | Float float_x, Float float_y -> float_fun (FD.cast_to fk float_x) (FD.cast_to fk float_y) - | _ -> failwith ("non-floating-point argument in call to function "^f.vname) + | Strcat { dest = dst; src; n }, _ -> + let dest_a, dest_typ, value = string_manipulation dst src None false None in + set ~ctx (Analyses.ask_of_ctx ctx) gs st dest_a dest_typ value + | Strlen s, _ -> + begin match lv with + | Some lv_val -> + let dest_a = eval_lv (Analyses.ask_of_ctx ctx) gs st lv_val in + let dest_typ = Cilfacade.typeOfLval lv_val in + let lval = mkMem ~addr:(Cil.stripCasts s) ~off:NoOffset in + let address = eval_lv (Analyses.ask_of_ctx ctx) gs st lval in + let (value:value) = Int(AD.to_string_length address) in + set ~ctx (Analyses.ask_of_ctx ctx) gs st dest_a dest_typ value + | None -> st end - in - let result:value = - begin match fun_args with - | Nan (fk, str) when Cil.isPointerType (Cilfacade.typeOf str) -> Float (FD.nan_of fk) - | Nan _ -> failwith ("non-pointer argument in call to function "^f.vname) - | Inf fk -> Float (FD.inf_of fk) - | Isfinite x -> Int (ID.cast_to IInt (apply_unary FDouble FD.isfinite x)) - | Isinf x -> Int (ID.cast_to IInt (apply_unary FDouble FD.isinf x)) - | Isnan x -> Int (ID.cast_to IInt (apply_unary FDouble FD.isnan x)) - | Isnormal x -> Int (ID.cast_to IInt (apply_unary FDouble FD.isnormal x)) - | Signbit x -> Int (ID.cast_to IInt (apply_unary FDouble FD.signbit x)) - | Ceil (fk,x) -> Float (apply_unary fk FD.ceil x) - | Floor (fk,x) -> Float (apply_unary fk FD.floor x) - | Fabs (fk, x) -> Float (apply_unary fk FD.fabs x) - | Acos (fk, x) -> Float (apply_unary fk FD.acos x) - | Asin (fk, x) -> Float (apply_unary fk FD.asin x) - | Atan (fk, x) -> Float (apply_unary fk FD.atan x) - | Atan2 (fk, y, x) -> Float (apply_binary fk (fun y' x' -> FD.atan (FD.div y' x')) y x) - | Cos (fk, x) -> Float (apply_unary fk FD.cos x) - | Sin (fk, x) -> Float (apply_unary fk FD.sin x) - | Tan (fk, x) -> Float (apply_unary fk FD.tan x) - | Isgreater (x,y) -> Int(ID.cast_to IInt (apply_binary FDouble FD.gt x y)) - | Isgreaterequal (x,y) -> Int(ID.cast_to IInt (apply_binary FDouble FD.ge x y)) - | Isless (x,y) -> Int(ID.cast_to IInt (apply_binary FDouble FD.lt x y)) - | Islessequal (x,y) -> Int(ID.cast_to IInt (apply_binary FDouble FD.le x y)) - | Islessgreater (x,y) -> Int(ID.logor (ID.cast_to IInt (apply_binary FDouble FD.lt x y)) (ID.cast_to IInt (apply_binary FDouble FD.gt x y))) - | Isunordered (x,y) -> Int(ID.cast_to IInt (apply_binary FDouble FD.unordered x y)) - | Fmax (fd, x ,y) -> Float (apply_binary fd FD.fmax x y) - | Fmin (fd, x ,y) -> Float (apply_binary fd FD.fmin x y) + | Strstr { haystack; needle }, _ -> + begin match lv with + | Some _ -> + (* when haystack, needle and dest type coincide, check if needle is a substring of haystack: + if that is the case, assign the substring of haystack starting at the first occurrence of needle to dest, + else use top *) + let dest_a, dest_typ, value = string_manipulation haystack needle lv true (Some (fun h_a n_a -> Address(AD.substring_extraction h_a n_a))) in + set ~ctx (Analyses.ask_of_ctx ctx) gs st dest_a dest_typ value + | None -> st end - in - begin match lv with - | Some lv_val -> set ~ctx (Analyses.ask_of_ctx ctx) gs st (eval_lv (Analyses.ask_of_ctx ctx) ctx.global st lv_val) (Cilfacade.typeOfLval lv_val) result - | None -> st - end - (* handling thread creations *) - | ThreadCreate _, _ -> - invalidate_ret_lv ctx.local (* actual results joined via threadspawn *) - (* handling thread joins... sort of *) - | ThreadJoin { thread = id; ret_var }, _ -> - let st' = - match (eval_rv (Analyses.ask_of_ctx ctx) gs st ret_var) with - | Int n when GobOption.exists (BI.equal BI.zero) (ID.to_int n) -> st - | Address ret_a -> - begin match eval_rv (Analyses.ask_of_ctx ctx) gs st id with - | Thread a -> - let v = List.fold VD.join (VD.bot ()) (List.map (fun x -> G.thread (ctx.global (V.thread x))) (ValueDomain.Threads.elements a)) in - (* TODO: is this type right? *) - set ~ctx (Analyses.ask_of_ctx ctx) gs st ret_a (Cilfacade.typeOf ret_var) v - | _ -> invalidate ~ctx (Analyses.ask_of_ctx ctx) gs st [ret_var] - end - | _ -> invalidate ~ctx (Analyses.ask_of_ctx ctx) gs st [ret_var] - in - let st' = invalidate_ret_lv st' in - Priv.thread_join (Analyses.ask_of_ctx ctx) (priv_getg ctx.global) id st' - | Unknown, "__goblint_assume_join" -> - let id = List.hd args in - Priv.thread_join ~force:true (Analyses.ask_of_ctx ctx) (priv_getg ctx.global) id st - | Malloc size, _ -> begin - match lv with - | Some lv -> - let heap_var = - if (get_bool "sem.malloc.fail") - then AD.join (AD.of_var (heap_var ctx)) AD.null_ptr - else AD.of_var (heap_var ctx) - in - (* ignore @@ printf "malloc will allocate %a bytes\n" ID.pretty (eval_int ctx.ask gs st size); *) - set_many ~ctx (Analyses.ask_of_ctx ctx) gs st [(heap_var, TVoid [], Blob (VD.bot (), eval_int (Analyses.ask_of_ctx ctx) gs st size, true)); - (eval_lv (Analyses.ask_of_ctx ctx) gs st lv, (Cilfacade.typeOfLval lv), Address heap_var)] - | _ -> st - end - | Calloc { count = n; size }, _ -> - begin match lv with - | Some lv -> (* array length is set to one, as num*size is done when turning into `Calloc *) - let heap_var = heap_var ctx in - let add_null addr = - if get_bool "sem.malloc.fail" - then AD.join addr AD.null_ptr (* calloc can fail and return NULL *) - else addr in - let ik = Cilfacade.ptrdiff_ikind () in - let blobsize = ID.mul (ID.cast_to ik @@ eval_int (Analyses.ask_of_ctx ctx) gs st size) (ID.cast_to ik @@ eval_int (Analyses.ask_of_ctx ctx) gs st n) in - (* the memory that was allocated by calloc is set to bottom, but we keep track that it originated from calloc, so when bottom is read from memory allocated by calloc it is turned to zero *) - set_many ~ctx (Analyses.ask_of_ctx ctx) gs st [(add_null (AD.of_var heap_var), TVoid [], Array (CArrays.make (IdxDom.of_int (Cilfacade.ptrdiff_ikind ()) BI.one) (Blob (VD.bot (), blobsize, false)))); - (eval_lv (Analyses.ask_of_ctx ctx) gs st lv, (Cilfacade.typeOfLval lv), Address (add_null (AD.of_mval (heap_var, `Index (IdxDom.of_int (Cilfacade.ptrdiff_ikind ()) BI.zero, `NoOffset)))))] - | _ -> st - end - | Realloc { ptr = p; size }, _ -> - begin match lv with - | Some lv -> - let ask = Analyses.ask_of_ctx ctx in - let p_rv = eval_rv ask gs st p in - let p_addr = - match p_rv with - | Address a -> a - (* TODO: don't we already have logic for this? *) - | Int i when ID.to_int i = Some BI.zero -> AD.null_ptr - | Int i -> AD.top_ptr - | _ -> AD.top_ptr (* TODO: why does this ever happen? *) - in - let p_addr' = AD.remove NullPtr p_addr in (* realloc with NULL is same as malloc, remove to avoid unknown value from NullPtr access *) - let p_addr_get = get ask gs st p_addr' None in (* implicitly includes join of malloc value (VD.bot) *) - let size_int = eval_int ask gs st size in - let heap_val:value = Blob (p_addr_get, size_int, true) in (* copy old contents with new size *) - let heap_addr = AD.of_var (heap_var ctx) in - let heap_addr' = - if get_bool "sem.malloc.fail" then - AD.join heap_addr AD.null_ptr - else - heap_addr + | Strcmp { s1; s2; n }, _ -> + begin match lv with + | Some _ -> + (* when s1 and s2 type coincide, compare both both strings completely or their first n characters, otherwise use top *) + let dest_a, dest_typ, value = string_manipulation s1 s2 lv false (Some (fun s1_a s2_a -> Int(AD.string_comparison s1_a s2_a (eval_n n)))) in + set ~ctx (Analyses.ask_of_ctx ctx) gs st dest_a dest_typ value + | None -> st + end + | Abort, _ -> raise Deadcode + | ThreadExit { ret_val = exp }, _ -> + begin match ThreadId.get_current (Analyses.ask_of_ctx ctx) with + | `Lifted tid -> + ( + let rv = eval_rv (Analyses.ask_of_ctx ctx) ctx.global ctx.local exp in + ctx.sideg (V.thread tid) (G.create_thread rv); + (* TODO: emit thread return event so other analyses are aware? *) + (* TODO: publish still needed? *) + publish_all ctx `Return; (* like normal return *) + match ThreadId.get_current (Analyses.ask_of_ctx ctx) with + | `Lifted tid when ThreadReturn.is_current (Analyses.ask_of_ctx ctx) -> + ignore @@ Priv.thread_return (Analyses.ask_of_ctx ctx) (priv_getg ctx.global) (priv_sideg ctx.sideg) tid st + | _ -> ()) + | _ -> () + end; + raise Deadcode + | MutexAttrSetType {attr = attr; typ = mtyp}, _ -> + begin + let get_type lval = + let address = eval_lv (Analyses.ask_of_ctx ctx) gs st lval in + AD.type_of address in - let lv_addr = eval_lv ask gs st lv in - set_many ~ctx ask gs st [ - (heap_addr, TVoid [], heap_val); - (lv_addr, Cilfacade.typeOfLval lv, Address heap_addr'); - ] (* TODO: free (i.e. invalidate) old blob if successful? *) - | None -> - st - end - | Assert { exp; refine; _ }, _ -> assert_fn ctx exp refine - | Setjmp { env }, _ -> - let ask = Analyses.ask_of_ctx ctx in - let st' = match eval_rv ask gs st env with - | Address jmp_buf -> - let value = VD.JmpBuf (ValueDomain.JmpBufs.Bufs.singleton (Target (ctx.prev_node, ctx.control_context ())), false) in - let r = set ~ctx ask gs st jmp_buf (Cilfacade.typeOf env) value in - if M.tracing then M.tracel "setjmp" "setting setjmp %a on %a -> %a\n" d_exp env D.pretty st D.pretty r; - r - | _ -> failwith "problem?!" - in - begin match lv with - | Some lv -> - set ~ctx ask gs st' (eval_lv ask ctx.global st lv) (Cilfacade.typeOfLval lv) (Int (ID.of_int IInt BI.zero)) - | None -> st' - end - | Longjmp {env; value}, _ -> - let ask = Analyses.ask_of_ctx ctx in - let ensure_not_zero (rv:value) = match rv with - | Int i -> - begin match ID.to_bool i with - | Some true -> rv - | Some false -> - M.error "Must: Longjmp with a value of 0 is silently changed to 1"; - Int (ID.of_int (ID.ikind i) Z.one) - | None -> - M.warn "May: Longjmp with a value of 0 is silently changed to 1"; - let ik = ID.ikind i in - Int (ID.join (ID.meet i (ID.of_excl_list ik [Z.zero])) (ID.of_int ik Z.one)) + let dst_lval = mkMem ~addr:(Cil.stripCasts attr) ~off:NoOffset in + let dest_typ = get_type dst_lval in + let dest_a = eval_lv (Analyses.ask_of_ctx ctx) gs st dst_lval in + match eval_rv (Analyses.ask_of_ctx ctx) gs st mtyp with + | Int x -> + begin + match ID.to_int x with + | Some z -> + if M.tracing then M.tracel "attr" "setting\n"; + set ~ctx (Analyses.ask_of_ctx ctx) gs st dest_a dest_typ (MutexAttr (ValueDomain.MutexAttr.of_int z)) + | None -> set ~ctx (Analyses.ask_of_ctx ctx) gs st dest_a dest_typ (MutexAttr (ValueDomain.MutexAttr.top ())) + end + | _ -> set ~ctx (Analyses.ask_of_ctx ctx) gs st dest_a dest_typ (MutexAttr (ValueDomain.MutexAttr.top ())) + end + | Identity e, _ -> + begin match lv with + | Some x -> assign ctx x e + | None -> ctx.local + end + (**Floating point classification and trigonometric functions defined in c99*) + | Math { fun_args; }, _ -> + let apply_unary fk float_fun x = + let eval_x = eval_rv (Analyses.ask_of_ctx ctx) gs st x in + begin match eval_x with + | Float float_x -> float_fun (FD.cast_to fk float_x) + | _ -> failwith ("non-floating-point argument in call to function "^f.vname) end - | _ -> - M.warn ~category:Program "Arguments to longjmp are strange!"; - rv - in - let rv = ensure_not_zero @@ eval_rv ask ctx.global ctx.local value in - let t = Cilfacade.typeOf value in - set ~ctx ~t_override:t ask ctx.global ctx.local (AD.of_var !longjmp_return) t rv (* Not raising Deadcode here, deadcode is raised at a higher level! *) - | Rand, _ -> - begin match lv with - | Some x -> - let result:value = (Int (ID.starting IInt Z.zero)) in - set ~ctx (Analyses.ask_of_ctx ctx) gs st (eval_lv (Analyses.ask_of_ctx ctx) ctx.global st x) (Cilfacade.typeOfLval x) result - | None -> st - end - | _, _ -> - let st = - special_unknown_invalidate ctx (Analyses.ask_of_ctx ctx) gs st f args + in + let apply_binary fk float_fun x y = + let eval_x = eval_rv (Analyses.ask_of_ctx ctx) gs st x in + let eval_y = eval_rv (Analyses.ask_of_ctx ctx) gs st y in + begin match eval_x, eval_y with + | Float float_x, Float float_y -> float_fun (FD.cast_to fk float_x) (FD.cast_to fk float_y) + | _ -> failwith ("non-floating-point argument in call to function "^f.vname) + end + in + let result:value = + begin match fun_args with + | Nan (fk, str) when Cil.isPointerType (Cilfacade.typeOf str) -> Float (FD.nan_of fk) + | Nan _ -> failwith ("non-pointer argument in call to function "^f.vname) + | Inf fk -> Float (FD.inf_of fk) + | Isfinite x -> Int (ID.cast_to IInt (apply_unary FDouble FD.isfinite x)) + | Isinf x -> Int (ID.cast_to IInt (apply_unary FDouble FD.isinf x)) + | Isnan x -> Int (ID.cast_to IInt (apply_unary FDouble FD.isnan x)) + | Isnormal x -> Int (ID.cast_to IInt (apply_unary FDouble FD.isnormal x)) + | Signbit x -> Int (ID.cast_to IInt (apply_unary FDouble FD.signbit x)) + | Ceil (fk,x) -> Float (apply_unary fk FD.ceil x) + | Floor (fk,x) -> Float (apply_unary fk FD.floor x) + | Fabs (fk, x) -> Float (apply_unary fk FD.fabs x) + | Acos (fk, x) -> Float (apply_unary fk FD.acos x) + | Asin (fk, x) -> Float (apply_unary fk FD.asin x) + | Atan (fk, x) -> Float (apply_unary fk FD.atan x) + | Atan2 (fk, y, x) -> Float (apply_binary fk (fun y' x' -> FD.atan (FD.div y' x')) y x) + | Cos (fk, x) -> Float (apply_unary fk FD.cos x) + | Sin (fk, x) -> Float (apply_unary fk FD.sin x) + | Tan (fk, x) -> Float (apply_unary fk FD.tan x) + | Isgreater (x,y) -> Int(ID.cast_to IInt (apply_binary FDouble FD.gt x y)) + | Isgreaterequal (x,y) -> Int(ID.cast_to IInt (apply_binary FDouble FD.ge x y)) + | Isless (x,y) -> Int(ID.cast_to IInt (apply_binary FDouble FD.lt x y)) + | Islessequal (x,y) -> Int(ID.cast_to IInt (apply_binary FDouble FD.le x y)) + | Islessgreater (x,y) -> Int(ID.logor (ID.cast_to IInt (apply_binary FDouble FD.lt x y)) (ID.cast_to IInt (apply_binary FDouble FD.gt x y))) + | Isunordered (x,y) -> Int(ID.cast_to IInt (apply_binary FDouble FD.unordered x y)) + | Fmax (fd, x ,y) -> Float (apply_binary fd FD.fmax x y) + | Fmin (fd, x ,y) -> Float (apply_binary fd FD.fmin x y) + end + in + begin match lv with + | Some lv_val -> set ~ctx (Analyses.ask_of_ctx ctx) gs st (eval_lv (Analyses.ask_of_ctx ctx) ctx.global st lv_val) (Cilfacade.typeOfLval lv_val) result + | None -> st + end + (* handling thread creations *) + | ThreadCreate _, _ -> + invalidate_ret_lv ctx.local (* actual results joined via threadspawn *) + (* handling thread joins... sort of *) + | ThreadJoin { thread = id; ret_var }, _ -> + let st' = + match (eval_rv (Analyses.ask_of_ctx ctx) gs st ret_var) with + | Int n when GobOption.exists (BI.equal BI.zero) (ID.to_int n) -> st + | Address ret_a -> + begin match eval_rv (Analyses.ask_of_ctx ctx) gs st id with + | Thread a -> + let v = List.fold VD.join (VD.bot ()) (List.map (fun x -> G.thread (ctx.global (V.thread x))) (ValueDomain.Threads.elements a)) in + (* TODO: is this type right? *) + set ~ctx (Analyses.ask_of_ctx ctx) gs st ret_a (Cilfacade.typeOf ret_var) v + | _ -> invalidate ~ctx (Analyses.ask_of_ctx ctx) gs st [ret_var] + end + | _ -> invalidate ~ctx (Analyses.ask_of_ctx ctx) gs st [ret_var] + in + let st' = invalidate_ret_lv st' in + Priv.thread_join (Analyses.ask_of_ctx ctx) (priv_getg ctx.global) id st' + | Unknown, "__goblint_assume_join" -> + let id = List.hd args in + Priv.thread_join ~force:true (Analyses.ask_of_ctx ctx) (priv_getg ctx.global) id st + | Malloc size, _ -> begin + match lv with + | Some lv -> + let heap_var = + if (get_bool "sem.malloc.fail") + then AD.join (AD.of_var (heap_var ctx)) AD.null_ptr + else AD.of_var (heap_var ctx) + in + (* ignore @@ printf "malloc will allocate %a bytes\n" ID.pretty (eval_int ctx.ask gs st size); *) + set_many ~ctx (Analyses.ask_of_ctx ctx) gs st [(heap_var, TVoid [], Blob (VD.bot (), eval_int (Analyses.ask_of_ctx ctx) gs st size, true)); + (eval_lv (Analyses.ask_of_ctx ctx) gs st lv, (Cilfacade.typeOfLval lv), Address heap_var)] + | _ -> st + end + | Calloc { count = n; size }, _ -> + begin match lv with + | Some lv -> (* array length is set to one, as num*size is done when turning into `Calloc *) + let heap_var = heap_var ctx in + let add_null addr = + if get_bool "sem.malloc.fail" + then AD.join addr AD.null_ptr (* calloc can fail and return NULL *) + else addr in + let ik = Cilfacade.ptrdiff_ikind () in + let blobsize = ID.mul (ID.cast_to ik @@ eval_int (Analyses.ask_of_ctx ctx) gs st size) (ID.cast_to ik @@ eval_int (Analyses.ask_of_ctx ctx) gs st n) in + (* the memory that was allocated by calloc is set to bottom, but we keep track that it originated from calloc, so when bottom is read from memory allocated by calloc it is turned to zero *) + set_many ~ctx (Analyses.ask_of_ctx ctx) gs st [(add_null (AD.of_var heap_var), TVoid [], Array (CArrays.make (IdxDom.of_int (Cilfacade.ptrdiff_ikind ()) BI.one) (Blob (VD.bot (), blobsize, false)))); + (eval_lv (Analyses.ask_of_ctx ctx) gs st lv, (Cilfacade.typeOfLval lv), Address (add_null (AD.of_mval (heap_var, `Index (IdxDom.of_int (Cilfacade.ptrdiff_ikind ()) BI.zero, `NoOffset)))))] + | _ -> st + end + | Realloc { ptr = p; size }, _ -> + begin match lv with + | Some lv -> + let ask = Analyses.ask_of_ctx ctx in + let p_rv = eval_rv ask gs st p in + let p_addr = + match p_rv with + | Address a -> a + (* TODO: don't we already have logic for this? *) + | Int i when ID.to_int i = Some BI.zero -> AD.null_ptr + | Int i -> AD.top_ptr + | _ -> AD.top_ptr (* TODO: why does this ever happen? *) + in + let p_addr' = AD.remove NullPtr p_addr in (* realloc with NULL is same as malloc, remove to avoid unknown value from NullPtr access *) + let p_addr_get = get ask gs st p_addr' None in (* implicitly includes join of malloc value (VD.bot) *) + let size_int = eval_int ask gs st size in + let heap_val:value = Blob (p_addr_get, size_int, true) in (* copy old contents with new size *) + let heap_addr = AD.of_var (heap_var ctx) in + let heap_addr' = + if get_bool "sem.malloc.fail" then + AD.join heap_addr AD.null_ptr + else + heap_addr + in + let lv_addr = eval_lv ask gs st lv in + set_many ~ctx ask gs st [ + (heap_addr, TVoid [], heap_val); + (lv_addr, Cilfacade.typeOfLval lv, Address heap_addr'); + ] (* TODO: free (i.e. invalidate) old blob if successful? *) + | None -> + st + end + | Assert { exp; refine; _ }, _ -> assert_fn ctx exp refine + | Setjmp { env }, _ -> + let ask = Analyses.ask_of_ctx ctx in + let st' = match eval_rv ask gs st env with + | Address jmp_buf -> + let value = VD.JmpBuf (ValueDomain.JmpBufs.Bufs.singleton (Target (ctx.prev_node, ctx.control_context ())), false) in + let r = set ~ctx ask gs st jmp_buf (Cilfacade.typeOf env) value in + if M.tracing then M.tracel "setjmp" "setting setjmp %a on %a -> %a\n" d_exp env D.pretty st D.pretty r; + r + | _ -> failwith "problem?!" + in + begin match lv with + | Some lv -> + set ~ctx ask gs st' (eval_lv ask ctx.global st lv) (Cilfacade.typeOfLval lv) (Int (ID.of_int IInt BI.zero)) + | None -> st' + end + | Longjmp {env; value}, _ -> + let ask = Analyses.ask_of_ctx ctx in + let ensure_not_zero (rv:value) = match rv with + | Int i -> + begin match ID.to_bool i with + | Some true -> rv + | Some false -> + M.error "Must: Longjmp with a value of 0 is silently changed to 1"; + Int (ID.of_int (ID.ikind i) Z.one) + | None -> + M.warn "May: Longjmp with a value of 0 is silently changed to 1"; + let ik = ID.ikind i in + Int (ID.join (ID.meet i (ID.of_excl_list ik [Z.zero])) (ID.of_int ik Z.one)) + end + | _ -> + M.warn ~category:Program "Arguments to longjmp are strange!"; + rv + in + let rv = ensure_not_zero @@ eval_rv ask ctx.global ctx.local value in + let t = Cilfacade.typeOf value in + set ~ctx ~t_override:t ask ctx.global ctx.local (AD.of_var !longjmp_return) t rv (* Not raising Deadcode here, deadcode is raised at a higher level! *) + | Rand, _ -> + begin match lv with + | Some x -> + let result:value = (Int (ID.starting IInt Z.zero)) in + set ~ctx (Analyses.ask_of_ctx ctx) gs st (eval_lv (Analyses.ask_of_ctx ctx) ctx.global st x) (Cilfacade.typeOfLval x) result + | None -> st + end + | _, _ -> + let st = + special_unknown_invalidate ctx (Analyses.ask_of_ctx ctx) gs st f args (* * TODO: invalidate vars reachable via args * publish globals * if single-threaded: *call f*, privatize globals * else: spawn f *) - in - (* invalidate lhs in case of assign *) - invalidate_ret_lv st + in + (* invalidate lhs in case of assign *) + invalidate_ret_lv st in if get_bool "sem.noreturn.dead_code" && Cil.hasAttribute "noreturn" f.vattr then raise Deadcode else st From 10260bde16acbb131cd2053eefe0099cf4ca03b2 Mon Sep 17 00:00:00 2001 From: Thomas Lagemann Date: Sun, 16 Jul 2023 11:59:32 +0200 Subject: [PATCH 245/327] Added more recursive tests --- ...recursion-multiple-functions-terminating.c | 40 +++++++++++++++++++ ...ursion-multiple-functions-nonterminating.c | 40 +++++++++++++++++++ ...-recursion-different-context-terminating.c | 32 +++++++++++++++ ...cursion-different-context-nonterminating.c | 32 +++++++++++++++ 4 files changed, 144 insertions(+) create mode 100644 tests/regression/75-termination/44-recursion-multiple-functions-terminating.c create mode 100644 tests/regression/75-termination/45-recursion-multiple-functions-nonterminating.c create mode 100644 tests/regression/75-termination/46-recursion-different-context-terminating.c create mode 100644 tests/regression/75-termination/47-recursion-different-context-nonterminating.c diff --git a/tests/regression/75-termination/44-recursion-multiple-functions-terminating.c b/tests/regression/75-termination/44-recursion-multiple-functions-terminating.c new file mode 100644 index 0000000000..c112c72a73 --- /dev/null +++ b/tests/regression/75-termination/44-recursion-multiple-functions-terminating.c @@ -0,0 +1,40 @@ +// TERM PARAM: --set "ana.activated[+]" termination --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra +#include + +void functionB(int n); +void functionC(int n); +void functionD(int n); + +void functionA(int n) { + if (n > 0) { + printf("Function A: %d\n", n); + functionB(n - 1); + } +} + +void functionB(int n) { + if (n > 0) { + printf("Function B: %d\n", n); + functionC(n - 1); + } +} + +void functionC(int n) { + if (n > 0) { + printf("Function C: %d\n", n); + functionD(n - 1); + } +} + +void functionD(int n) { + if (n > 0) { + printf("Function D: %d\n", n); + functionA(n - 1); + } +} + +int main() { + int n = 15; + functionA(n); + return 0; +} diff --git a/tests/regression/75-termination/45-recursion-multiple-functions-nonterminating.c b/tests/regression/75-termination/45-recursion-multiple-functions-nonterminating.c new file mode 100644 index 0000000000..47c13c0dca --- /dev/null +++ b/tests/regression/75-termination/45-recursion-multiple-functions-nonterminating.c @@ -0,0 +1,40 @@ +// NONTERM PARAM: --set "ana.activated[+]" termination --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra +#include + +void functionB(int n); +void functionC(int n); +void functionD(int n); + +void functionA(int n) { + if (n > 0) { + printf("Function A: %d\n", n); + functionB(n - 1); + } +} + +void functionB(int n) { + if (n > 0) { + printf("Function B: %d\n", n); + functionC(n - 1); + } +} + +void functionC(int n) { + if (n > 0) { + printf("Function C: %d\n", n); + functionD(n + 1); + } +} + +void functionD(int n) { + if (n > 0) { + printf("Function D: %d\n", n); + functionA(n + 1); + } +} + +int main() { + int n = 15; + functionA(n); + return 0; +} diff --git a/tests/regression/75-termination/46-recursion-different-context-terminating.c b/tests/regression/75-termination/46-recursion-different-context-terminating.c new file mode 100644 index 0000000000..4c5dd13035 --- /dev/null +++ b/tests/regression/75-termination/46-recursion-different-context-terminating.c @@ -0,0 +1,32 @@ +// TERM PARAM: --set "ana.activated[+]" termination --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra +#include + +void functionC(int n); + +void functionA(int n) { + if (n > 0) { + printf("Function A: %d\n", n); + functionC(n - 1); + } +} + +void functionB(int n) { + if (n > 0) { + printf("Function B: %d\n", n); + functionC(n - 1); + } +} + +void functionC(int n) { + if (n > 0) { + printf("Function C: %d\n", n); + functionC(n - 1); + } +} + +int main() { + int n = 5; + functionA(n + 1); + functionB(n + 7); + return 0; +} diff --git a/tests/regression/75-termination/47-recursion-different-context-nonterminating.c b/tests/regression/75-termination/47-recursion-different-context-nonterminating.c new file mode 100644 index 0000000000..3216275748 --- /dev/null +++ b/tests/regression/75-termination/47-recursion-different-context-nonterminating.c @@ -0,0 +1,32 @@ +// NONTERM PARAM: --set "ana.activated[+]" termination --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra +#include + +void functionC(int n); + +void functionA(int n) { + if (n > 0) { + printf("Function A: %d\n", n); + functionC(n - 1); + } +} + +void functionB(int n) { + if (n > 0) { + printf("Function B: %d\n", n); + functionC(n - 1); + } +} + +void functionC(int n) { + if (n > 0) { + printf("Function C: %d\n", n); + functionC(n); + } +} + +int main() { + int n = 5; + functionA(n + 1); + functionB(n + 7); + return 0; +} From 4e365110bde212326e7d06867eef1801be85e732 Mon Sep 17 00:00:00 2001 From: Isidor Zweckstetter Date: Sun, 16 Jul 2023 18:36:02 +0200 Subject: [PATCH 246/327] removed exit-indikator variable --- src/analyses/libraryDesc.ml | 2 +- src/analyses/loopTermination.ml | 5 +---- src/util/terminationPreprocessing.ml | 15 +++------------ 3 files changed, 5 insertions(+), 17 deletions(-) diff --git a/src/analyses/libraryDesc.ml b/src/analyses/libraryDesc.ml index c3c8d0f85b..0557dc28a2 100644 --- a/src/analyses/libraryDesc.ml +++ b/src/analyses/libraryDesc.ml @@ -72,7 +72,7 @@ type special = | Identity of Cil.exp (** Identity function. Some compiler optimization annotation functions map to this. *) | Setjmp of { env: Cil.exp; } | Longjmp of { env: Cil.exp; value: Cil.exp; } - | Bounded of { exp: Cil.exp} + | Bounded of { exp: Cil.exp} (** Used to check for bounds for termination analysis. *) | Rand | Unknown (** Anything not belonging to other types. *) (* TODO: rename to Other? *) diff --git a/src/analyses/loopTermination.ml b/src/analyses/loopTermination.ml index 72743444b0..b07fb143b4 100644 --- a/src/analyses/loopTermination.ml +++ b/src/analyses/loopTermination.ml @@ -14,9 +14,6 @@ let loop_counters : stmt VarToStmt.t ref = ref VarToStmt.empty (** Contains the locations of the upjumping gotos *) let upjumping_gotos : location list ref = ref [] -(** Indicates the place in the code, right after a loop is exited. *) -let loop_exit : varinfo ref = ref (makeVarinfo false "-error" Cil.intType) - let is_loop_counter_var (x : varinfo) = VarToStmt.mem x !loop_counters @@ -126,6 +123,6 @@ end let () = (* Register the preprocessing *) - Cilfacade.register_preprocess_cil (Spec.name ()) (new loopCounterVisitor loop_counters upjumping_gotos loop_exit); + Cilfacade.register_preprocess_cil (Spec.name ()) (new loopCounterVisitor loop_counters upjumping_gotos); (* Register this analysis within the master control program *) MCP.register_analysis (module Spec : MCPSpec) diff --git a/src/util/terminationPreprocessing.ml b/src/util/terminationPreprocessing.ml index 1aa78ccae7..1432a2da98 100644 --- a/src/util/terminationPreprocessing.ml +++ b/src/util/terminationPreprocessing.ml @@ -1,5 +1,4 @@ open GoblintCil -include Printf module VarToStmt = Map.Make(CilType.Varinfo) (* maps varinfos (= loop counter variable) to the statement of the corresponding loop*) @@ -29,15 +28,8 @@ let extract_file_name s = (*There still may be a need to filt let show_location_id l = string_of_int l.line ^ "_" ^ string_of_int l.column ^ "-file" ^ "_" ^ extract_file_name l.file -class loopCounterVisitor lc lg le (fd : fundec) = object(self) +class loopCounterVisitor lc lg (fd : fundec) = object(self) inherit nopCilVisitor - method! vfunc (f:fundec) = - if !le.vname <> "term_exit-" then begin - let exit_name = "term_exit-" in - let typ = Cil.intType in - le := Cil.makeGlobalVar exit_name typ; - end; - DoChildren; (* function definition *) method! vstmt s = let action s = match s.skind with | Loop (b, loc, eloc, _, _) -> @@ -46,14 +38,13 @@ class loopCounterVisitor lc lg le (fd : fundec) = object(self) let v = (Cil.makeLocalVar fd name typ) in (*Not tested for incremental mode*) let init_stmt = mkStmtOneInstr @@ Set (var v, zero, loc, eloc) in let inc_stmt = mkStmtOneInstr @@ Set (var v, increm (Lval (var v)) 1, loc, eloc) in - let check_stmt = mkStmtOneInstr @@ Set ((var !le), (Lval (var v)), loc, eloc) in let inc_stmt2 = mkStmtOneInstr @@ Set (var v, increm (Lval (var v)) 1, loc, eloc) in let exit_stmt = mkStmtOneInstr @@ Call (None, f_bounded, [Lval (var v)], loc, locUnknown) in (match b.bstmts with | s :: ss -> (*duplicate increment statement here to fix inconsistencies in nested loops*) - b.bstmts <- inc_stmt :: check_stmt :: exit_stmt :: s :: inc_stmt2 :: ss; + b.bstmts <- inc_stmt :: exit_stmt :: s :: inc_stmt2 :: ss; | ss -> - b.bstmts <- inc_stmt :: check_stmt :: exit_stmt :: ss; + b.bstmts <- inc_stmt :: exit_stmt :: ss; ); lc := VarToStmt.add (v: varinfo) (s: stmt) !lc; let nb = mkBlock [init_stmt; mkStmt s.skind] in From d47e88e795b453c8453d75526f6b6f6cb59de0a8 Mon Sep 17 00:00:00 2001 From: Isidor Zweckstetter Date: Mon, 17 Jul 2023 14:09:02 +0200 Subject: [PATCH 247/327] removed debug print; Might solve cram tests --- src/util/terminationPreprocessing.ml | 25 ++++++++++++++----------- 1 file changed, 14 insertions(+), 11 deletions(-) diff --git a/src/util/terminationPreprocessing.ml b/src/util/terminationPreprocessing.ml index 1432a2da98..e20ee9b375 100644 --- a/src/util/terminationPreprocessing.ml +++ b/src/util/terminationPreprocessing.ml @@ -2,18 +2,7 @@ open GoblintCil module VarToStmt = Map.Make(CilType.Varinfo) (* maps varinfos (= loop counter variable) to the statement of the corresponding loop*) -let specialFunction name = - print_endline @@ "specialfunction done"; - { svar = makeGlobalVar name (TFun(voidType, Some [("exp", intType, [])], false,[])); - smaxid = 0; - slocals = []; - sformals = []; - sbody = mkBlock []; - smaxstmtid = None; - sallstmts = []; - } -let f_bounded = Lval (var (specialFunction "__goblint_bounded").svar) let extract_file_name s = (*There still may be a need to filter more chars*) let ls = String.split_on_char '/' s in (*Assuming '/' as path seperator*) @@ -30,7 +19,21 @@ let show_location_id l = class loopCounterVisitor lc lg (fd : fundec) = object(self) inherit nopCilVisitor + method! vstmt s = + + let specialFunction name = + { svar = makeGlobalVar name (TFun(voidType, Some [("exp", intType, [])], false,[])); + smaxid = 0; + slocals = []; + sformals = []; + sbody = mkBlock []; + smaxstmtid = None; + sallstmts = []; + } in + + let f_bounded = Lval (var (specialFunction "__goblint_bounded").svar) in + let action s = match s.skind with | Loop (b, loc, eloc, _, _) -> let name = "term"^show_location_id loc in From 021ddaddbd44c0498324439a0672b42efb2dbd1e Mon Sep 17 00:00:00 2001 From: Alexander Schlenga Date: Mon, 17 Jul 2023 14:28:27 +0200 Subject: [PATCH 248/327] Remove debug output --- src/util/terminationPreprocessing.ml | 97 ++++++++++++++-------------- 1 file changed, 48 insertions(+), 49 deletions(-) diff --git a/src/util/terminationPreprocessing.ml b/src/util/terminationPreprocessing.ml index 1432a2da98..c3c6e0500c 100644 --- a/src/util/terminationPreprocessing.ml +++ b/src/util/terminationPreprocessing.ml @@ -3,60 +3,59 @@ open GoblintCil module VarToStmt = Map.Make(CilType.Varinfo) (* maps varinfos (= loop counter variable) to the statement of the corresponding loop*) let specialFunction name = - print_endline @@ "specialfunction done"; - { svar = makeGlobalVar name (TFun(voidType, Some [("exp", intType, [])], false,[])); - smaxid = 0; - slocals = []; - sformals = []; - sbody = mkBlock []; - smaxstmtid = None; - sallstmts = []; - } + { svar = makeGlobalVar name (TFun(voidType, Some [("exp", intType, [])], false,[])); + smaxid = 0; + slocals = []; + sformals = []; + sbody = mkBlock []; + smaxstmtid = None; + sallstmts = []; + } let f_bounded = Lval (var (specialFunction "__goblint_bounded").svar) let extract_file_name s = (*There still may be a need to filter more chars*) - let ls = String.split_on_char '/' s in (*Assuming '/' as path seperator*) - let ls = List.rev ls in - let s' = List.nth ls 0 in - let ls = String.split_on_char '.' s' in - let s' = List.nth ls 0 in - let without_spaces = String.split_on_char ' ' s' in - let s' = String.concat "" without_spaces in - s' + let ls = String.split_on_char '/' s in (*Assuming '/' as path seperator*) + let ls = List.rev ls in + let s' = List.nth ls 0 in + let ls = String.split_on_char '.' s' in + let s' = List.nth ls 0 in + let without_spaces = String.split_on_char ' ' s' in + let s' = String.concat "" without_spaces in + s' let show_location_id l = - string_of_int l.line ^ "_" ^ string_of_int l.column ^ "-file" ^ "_" ^ extract_file_name l.file + string_of_int l.line ^ "_" ^ string_of_int l.column ^ "-file" ^ "_" ^ extract_file_name l.file class loopCounterVisitor lc lg (fd : fundec) = object(self) - inherit nopCilVisitor - method! vstmt s = - let action s = match s.skind with - | Loop (b, loc, eloc, _, _) -> - let name = "term"^show_location_id loc in - let typ = Cil.intType in - let v = (Cil.makeLocalVar fd name typ) in (*Not tested for incremental mode*) - let init_stmt = mkStmtOneInstr @@ Set (var v, zero, loc, eloc) in - let inc_stmt = mkStmtOneInstr @@ Set (var v, increm (Lval (var v)) 1, loc, eloc) in - let inc_stmt2 = mkStmtOneInstr @@ Set (var v, increm (Lval (var v)) 1, loc, eloc) in - let exit_stmt = mkStmtOneInstr @@ Call (None, f_bounded, [Lval (var v)], loc, locUnknown) in - (match b.bstmts with - | s :: ss -> (*duplicate increment statement here to fix inconsistencies in nested loops*) - b.bstmts <- inc_stmt :: exit_stmt :: s :: inc_stmt2 :: ss; - | ss -> - b.bstmts <- inc_stmt :: exit_stmt :: ss; - ); - lc := VarToStmt.add (v: varinfo) (s: stmt) !lc; - let nb = mkBlock [init_stmt; mkStmt s.skind] in - s.skind <- Block nb; - s - | Goto (sref, l) -> - let goto_jmp_stmt = sref.contents.skind in - let loc_stmt = get_stmtLoc goto_jmp_stmt in - if CilType.Location.compare l loc_stmt >= 0 (*is pos if first loc is greater -> below the second loc*) - then - lg := List.append !lg ([l] : location list); (*problem: the program might not terminate!*) - s - | _ -> s - in ChangeDoChildrenPost (s, action); - end \ No newline at end of file + inherit nopCilVisitor + method! vstmt s = + let action s = match s.skind with + | Loop (b, loc, eloc, _, _) -> + let name = "term"^show_location_id loc in + let typ = Cil.intType in + let v = (Cil.makeLocalVar fd name typ) in (*Not tested for incremental mode*) + let init_stmt = mkStmtOneInstr @@ Set (var v, zero, loc, eloc) in + let inc_stmt = mkStmtOneInstr @@ Set (var v, increm (Lval (var v)) 1, loc, eloc) in + let inc_stmt2 = mkStmtOneInstr @@ Set (var v, increm (Lval (var v)) 1, loc, eloc) in + let exit_stmt = mkStmtOneInstr @@ Call (None, f_bounded, [Lval (var v)], loc, locUnknown) in + (match b.bstmts with + | s :: ss -> (*duplicate increment statement here to fix inconsistencies in nested loops*) + b.bstmts <- inc_stmt :: exit_stmt :: s :: inc_stmt2 :: ss; + | ss -> + b.bstmts <- inc_stmt :: exit_stmt :: ss; + ); + lc := VarToStmt.add (v: varinfo) (s: stmt) !lc; + let nb = mkBlock [init_stmt; mkStmt s.skind] in + s.skind <- Block nb; + s + | Goto (sref, l) -> + let goto_jmp_stmt = sref.contents.skind in + let loc_stmt = get_stmtLoc goto_jmp_stmt in + if CilType.Location.compare l loc_stmt >= 0 (*is pos if first loc is greater -> below the second loc*) + then + lg := List.append !lg ([l] : location list); (*problem: the program might not terminate!*) + s + | _ -> s + in ChangeDoChildrenPost (s, action); +end From 47440a3ec68a72e60e4597a679c8362807406584 Mon Sep 17 00:00:00 2001 From: Thomas Lagemann Date: Mon, 17 Jul 2023 14:55:13 +0200 Subject: [PATCH 249/327] Code style optimization --- .../35-goto-out-of-inner-loop-with-print-terminating.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/regression/75-termination/35-goto-out-of-inner-loop-with-print-terminating.c b/tests/regression/75-termination/35-goto-out-of-inner-loop-with-print-terminating.c index f564354e51..3bd6e53d2d 100644 --- a/tests/regression/75-termination/35-goto-out-of-inner-loop-with-print-terminating.c +++ b/tests/regression/75-termination/35-goto-out-of-inner-loop-with-print-terminating.c @@ -18,7 +18,7 @@ int main() } printf("(%d, %d) ", i, j); } - outer_loop:; // Label for the outer loop + outer_loop: // Label for the outer loop printf("\n"); } From 91d331d588bae35c973b5c238a0dfe3a19a24f3b Mon Sep 17 00:00:00 2001 From: Thomas Lagemann Date: Mon, 17 Jul 2023 16:10:51 +0200 Subject: [PATCH 250/327] Indentation --- src/framework/constraints.ml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/framework/constraints.ml b/src/framework/constraints.ml index 2217fab707..ad05bbbcc6 100644 --- a/src/framework/constraints.ml +++ b/src/framework/constraints.ml @@ -1719,7 +1719,7 @@ struct (* Tuple containing the fundec and context of the caller *) module CallGraphTuple = Printable.Prod (CilType.Fundec) (S.C) - + (* Set containing multiple caller tuples *) module CallGraphSet = SetDomain.Make (CallGraphTuple) From fc427bc264800660f1dd250230fdb0b70803a279 Mon Sep 17 00:00:00 2001 From: Alexander Schlenga Date: Mon, 17 Jul 2023 16:18:23 +0200 Subject: [PATCH 251/327] Fix indentation --- src/framework/constraints.ml | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/framework/constraints.ml b/src/framework/constraints.ml index 2217fab707..6883cc72d9 100644 --- a/src/framework/constraints.ml +++ b/src/framework/constraints.ml @@ -1718,16 +1718,16 @@ struct module V = GVarF(S.V) (* Tuple containing the fundec and context of the caller *) - module CallGraphTuple = Printable.Prod (CilType.Fundec) (S.C) - + module CallGraphTuple = Printable.Prod (CilType.Fundec) (S.C) + (* Set containing multiple caller tuples *) module CallGraphSet = SetDomain.Make (CallGraphTuple) (* Mapping from the callee context to the set of all caller tuples*) module CallGraphMap = MapDomain.MapBot (S.C) (CallGraphSet) - module G = - struct + module G = + struct include Lattice.Lift2 (G) (CallGraphMap) (Printable.DefaultNames) let spec = function From 3fb5d1442335772e389e4a4a9b8e17342b0a52dc Mon Sep 17 00:00:00 2001 From: Thomas Lagemann Date: Mon, 17 Jul 2023 17:45:23 +0200 Subject: [PATCH 252/327] Test case 48 --- .../48-dynamic-recursion-nonterminating.c | 10 ++++++++++ 1 file changed, 10 insertions(+) create mode 100644 tests/regression/75-termination/48-dynamic-recursion-nonterminating.c diff --git a/tests/regression/75-termination/48-dynamic-recursion-nonterminating.c b/tests/regression/75-termination/48-dynamic-recursion-nonterminating.c new file mode 100644 index 0000000000..066c2f51b1 --- /dev/null +++ b/tests/regression/75-termination/48-dynamic-recursion-nonterminating.c @@ -0,0 +1,10 @@ +// NONTERM PARAM: --set "ana.activated[+]" termination --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra +void troll(void (*f) ()) +{ + f(f); +} + +int main() +{ + troll(troll); +} From 601698fa8bf3c25a0f1b739e38ac2c6b9eac7bdf Mon Sep 17 00:00:00 2001 From: Alexander Schlenga Date: Tue, 18 Jul 2023 15:37:07 +0200 Subject: [PATCH 253/327] Remove unused code; introduce basic error-handling --- src/analyses/loopTermination.ml | 32 +++++++++++++++++--------------- 1 file changed, 17 insertions(+), 15 deletions(-) diff --git a/src/analyses/loopTermination.ml b/src/analyses/loopTermination.ml index b07fb143b4..afd86fc483 100644 --- a/src/analyses/loopTermination.ml +++ b/src/analyses/loopTermination.ml @@ -14,9 +14,6 @@ let loop_counters : stmt VarToStmt.t ref = ref VarToStmt.empty (** Contains the locations of the upjumping gotos *) let upjumping_gotos : location list ref = ref [] -let is_loop_counter_var (x : varinfo) = - VarToStmt.mem x !loop_counters - let no_upjumping_gotos () = upjumping_gotos.contents = [] @@ -78,18 +75,23 @@ struct if !AnalysisState.postsolving then match f.vname, arglist with "__goblint_bounded", [Lval (Var x, NoOffset)] -> - let is_bounded = check_bounded ctx x in - let loop_statement = VarToStmt.find x !loop_counters in - ctx.sideg () (G.add (`Lifted loop_statement) is_bounded (ctx.global ())); - (* In case the loop is not bounded, a warning is created. *) - if not (is_bounded) then ( - let msgs = - [(Pretty.dprintf - "The program might not terminate! (Loop analysis)", - Some (M.Location.CilLocation (Cilfacade.get_stmtLoc loop_statement)) - );] in - M.msg_group Warning ~category:NonTerminating "Possibly non terminating loops" msgs); - () + (try + let loop_statement = VarToStmt.find x !loop_counters in + let is_bounded = check_bounded ctx x in + ctx.sideg () (G.add (`Lifted loop_statement) is_bounded (ctx.global ())); + (* In case the loop is not bounded, a warning is created. *) + if not (is_bounded) then ( + let msgs = + [(Pretty.dprintf + "The program might not terminate! (Loop analysis)", + Some (M.Location.CilLocation (Cilfacade.get_stmtLoc loop_statement)) + );] in + M.msg_group Warning ~category:NonTerminating "Possibly non terminating loops" msgs); + () + with Not_found -> + (* This should not happen as long as __goblint_bounded is only used + * for this analysis. *) + ()) | _ -> () else () From 66115b1da109bf028bf6648ebb2724af95ab1fcb Mon Sep 17 00:00:00 2001 From: Thomas Lagemann Date: Mon, 24 Jul 2023 13:34:35 +0200 Subject: [PATCH 254/327] Annotate tests with skip as Apron ist used --- tests/regression/75-termination/01-simple-loop-terminating.c | 2 +- .../regression/75-termination/02-simple-loop-nonterminating.c | 2 +- tests/regression/75-termination/03-nested-loop-terminating.c | 2 +- .../regression/75-termination/04-nested-loop-nonterminating.c | 2 +- tests/regression/75-termination/05-for-loop-terminating.c | 2 +- tests/regression/75-termination/06-for-loop-nonterminating.c | 2 +- .../75-termination/07-nested-for-loop-terminating.c | 2 +- .../75-termination/08-nested-for-loop-nonterminating.c | 2 +- .../75-termination/09-complex-for-loop-terminating.c | 2 +- tests/regression/75-termination/10-complex-loop-terminating.c | 2 +- tests/regression/75-termination/11-loopless-termination.c | 2 +- .../75-termination/12-do-while-instant-terminating.c | 2 +- tests/regression/75-termination/13-do-while-terminating.c | 2 +- tests/regression/75-termination/14-do-while-nonterminating.c | 2 +- .../75-termination/15-complex-loop-combination-terminating.c | 2 +- .../75-termination/16-nested-loop-nontrivial-nonterminating.c | 2 +- tests/regression/75-termination/17-goto-terminating.c | 2 +- tests/regression/75-termination/18-goto-nonterminating.c | 2 +- tests/regression/75-termination/19-rand-terminating.c | 2 +- tests/regression/75-termination/20-rand-nonterminating.c | 2 +- .../75-termination/21-no-exit-on-rand-unproofable.c | 2 +- tests/regression/75-termination/22-exit-on-rand-unproofable.c | 2 +- tests/regression/75-termination/23-exit-on-rand-terminating.c | 2 +- .../75-termination/24-upjumping-goto-loopless-terminating.c | 2 +- .../75-termination/25-leave-loop-goto-terminating.c | 2 +- .../75-termination/26-enter-loop-goto-terminating.c | 2 +- .../75-termination/27-upjumping-goto-nonterminating.c | 2 +- .../75-termination/28-do-while-continue-terminating.c | 2 +- .../75-termination/29-do-while-continue-nonterminating.c | 2 +- .../75-termination/30-goto-out-of-inner-loop-terminating.c | 2 +- .../75-termination/31-goto-out-of-inner-loop-nonterminating.c | 2 +- tests/regression/75-termination/32-multithread-terminating.c | 2 +- .../regression/75-termination/33-multithread-nonterminating.c | 2 +- .../75-termination/34-nested-for-loop-nonterminating.c | 2 +- .../35-goto-out-of-inner-loop-with-print-terminating.c | 2 +- tests/regression/75-termination/36-recursion-terminating.c | 2 +- tests/regression/75-termination/37-recursion-nonterminating.c | 2 +- .../75-termination/38-recursion-nested-terminating.c | 2 +- .../75-termination/39-recursion-nested-nonterminating.c | 4 ++-- .../40-multi-expression-conditions-terminating.c | 2 +- tests/regression/75-termination/41-for-continue-terminating.c | 2 +- .../75-termination/42-downjumping-goto-loopless-terminating.c | 2 +- .../75-termination/43-return-from-endless-loop-terminating.c | 2 +- .../44-recursion-multiple-functions-terminating.c | 2 +- .../45-recursion-multiple-functions-nonterminating.c | 2 +- .../46-recursion-different-context-terminating.c | 2 +- .../47-recursion-different-context-nonterminating.c | 2 +- .../75-termination/48-dynamic-recursion-nonterminating.c | 2 +- 48 files changed, 49 insertions(+), 49 deletions(-) diff --git a/tests/regression/75-termination/01-simple-loop-terminating.c b/tests/regression/75-termination/01-simple-loop-terminating.c index aaa2a7a895..8ca4610057 100644 --- a/tests/regression/75-termination/01-simple-loop-terminating.c +++ b/tests/regression/75-termination/01-simple-loop-terminating.c @@ -1,4 +1,4 @@ -// TERM PARAM: --set "ana.activated[+]" termination --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra +// SKIP TERM PARAM: --set "ana.activated[+]" termination --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra #include int main() diff --git a/tests/regression/75-termination/02-simple-loop-nonterminating.c b/tests/regression/75-termination/02-simple-loop-nonterminating.c index c6e1c6c8d6..d8847e2b74 100644 --- a/tests/regression/75-termination/02-simple-loop-nonterminating.c +++ b/tests/regression/75-termination/02-simple-loop-nonterminating.c @@ -1,4 +1,4 @@ -// NONTERM PARAM: --set "ana.activated[+]" termination --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra +// SKIP NONTERM PARAM: --set "ana.activated[+]" termination --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra #include int main() diff --git a/tests/regression/75-termination/03-nested-loop-terminating.c b/tests/regression/75-termination/03-nested-loop-terminating.c index 70327c1016..fd1ee14f39 100644 --- a/tests/regression/75-termination/03-nested-loop-terminating.c +++ b/tests/regression/75-termination/03-nested-loop-terminating.c @@ -1,4 +1,4 @@ -// TERM PARAM: --set "ana.activated[+]" termination --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra +// SKIP TERM PARAM: --set "ana.activated[+]" termination --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra #include int main() diff --git a/tests/regression/75-termination/04-nested-loop-nonterminating.c b/tests/regression/75-termination/04-nested-loop-nonterminating.c index 21a6d47051..21b6014509 100644 --- a/tests/regression/75-termination/04-nested-loop-nonterminating.c +++ b/tests/regression/75-termination/04-nested-loop-nonterminating.c @@ -1,4 +1,4 @@ -// NONTERM PARAM: --set "ana.activated[+]" termination --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra +// SKIP NONTERM PARAM: --set "ana.activated[+]" termination --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra #include int main() diff --git a/tests/regression/75-termination/05-for-loop-terminating.c b/tests/regression/75-termination/05-for-loop-terminating.c index bf58408487..7a2b789496 100644 --- a/tests/regression/75-termination/05-for-loop-terminating.c +++ b/tests/regression/75-termination/05-for-loop-terminating.c @@ -1,4 +1,4 @@ -// TERM PARAM: --set "ana.activated[+]" termination --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra +// SKIP TERM PARAM: --set "ana.activated[+]" termination --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra #include int main() diff --git a/tests/regression/75-termination/06-for-loop-nonterminating.c b/tests/regression/75-termination/06-for-loop-nonterminating.c index 0f96209e35..6c6123251c 100644 --- a/tests/regression/75-termination/06-for-loop-nonterminating.c +++ b/tests/regression/75-termination/06-for-loop-nonterminating.c @@ -1,4 +1,4 @@ -// NONTERM PARAM: --set "ana.activated[+]" termination --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra +// SKIP NONTERM PARAM: --set "ana.activated[+]" termination --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra #include int main() diff --git a/tests/regression/75-termination/07-nested-for-loop-terminating.c b/tests/regression/75-termination/07-nested-for-loop-terminating.c index 1c43eeaada..f1dde17dc5 100644 --- a/tests/regression/75-termination/07-nested-for-loop-terminating.c +++ b/tests/regression/75-termination/07-nested-for-loop-terminating.c @@ -1,4 +1,4 @@ -// TERM PARAM: --set "ana.activated[+]" termination --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra +// SKIP TERM PARAM: --set "ana.activated[+]" termination --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra #include int main() diff --git a/tests/regression/75-termination/08-nested-for-loop-nonterminating.c b/tests/regression/75-termination/08-nested-for-loop-nonterminating.c index ec76f31534..cb65a0d267 100644 --- a/tests/regression/75-termination/08-nested-for-loop-nonterminating.c +++ b/tests/regression/75-termination/08-nested-for-loop-nonterminating.c @@ -1,4 +1,4 @@ -// NONTERM PARAM: --set "ana.activated[+]" termination --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra +// SKIP NONTERM PARAM: --set "ana.activated[+]" termination --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra #include int main() diff --git a/tests/regression/75-termination/09-complex-for-loop-terminating.c b/tests/regression/75-termination/09-complex-for-loop-terminating.c index 9767b4bc1c..264c08f6ed 100644 --- a/tests/regression/75-termination/09-complex-for-loop-terminating.c +++ b/tests/regression/75-termination/09-complex-for-loop-terminating.c @@ -1,4 +1,4 @@ -// TERM PARAM: --set "ana.activated[+]" termination --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra --set sem.int.signed_overflow assume_none +// SKIP TERM PARAM: --set "ana.activated[+]" termination --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra --set sem.int.signed_overflow assume_none #include int main() diff --git a/tests/regression/75-termination/10-complex-loop-terminating.c b/tests/regression/75-termination/10-complex-loop-terminating.c index 19091b1033..90317d5209 100644 --- a/tests/regression/75-termination/10-complex-loop-terminating.c +++ b/tests/regression/75-termination/10-complex-loop-terminating.c @@ -1,4 +1,4 @@ -// TERM PARAM: --set "ana.activated[+]" termination --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra --set sem.int.signed_overflow assume_none +// SKIP TERM PARAM: --set "ana.activated[+]" termination --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra --set sem.int.signed_overflow assume_none #include int main() diff --git a/tests/regression/75-termination/11-loopless-termination.c b/tests/regression/75-termination/11-loopless-termination.c index 51c0605757..9f1a7e0f13 100644 --- a/tests/regression/75-termination/11-loopless-termination.c +++ b/tests/regression/75-termination/11-loopless-termination.c @@ -1,4 +1,4 @@ -// TERM PARAM: --set "ana.activated[+]" termination --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra +// SKIP TERM PARAM: --set "ana.activated[+]" termination --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra #include int main() diff --git a/tests/regression/75-termination/12-do-while-instant-terminating.c b/tests/regression/75-termination/12-do-while-instant-terminating.c index 3767430a51..5bc18902b3 100644 --- a/tests/regression/75-termination/12-do-while-instant-terminating.c +++ b/tests/regression/75-termination/12-do-while-instant-terminating.c @@ -1,4 +1,4 @@ -// TERM PARAM: --set "ana.activated[+]" termination --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra +// SKIP TERM PARAM: --set "ana.activated[+]" termination --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra #include int main() diff --git a/tests/regression/75-termination/13-do-while-terminating.c b/tests/regression/75-termination/13-do-while-terminating.c index 8faeec1e64..6ac6946495 100644 --- a/tests/regression/75-termination/13-do-while-terminating.c +++ b/tests/regression/75-termination/13-do-while-terminating.c @@ -1,4 +1,4 @@ -// TERM PARAM: --set "ana.activated[+]" termination --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra +// SKIP TERM PARAM: --set "ana.activated[+]" termination --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra #include int main() diff --git a/tests/regression/75-termination/14-do-while-nonterminating.c b/tests/regression/75-termination/14-do-while-nonterminating.c index 5522b61d88..0a9df3421f 100644 --- a/tests/regression/75-termination/14-do-while-nonterminating.c +++ b/tests/regression/75-termination/14-do-while-nonterminating.c @@ -1,4 +1,4 @@ -// NONTERM PARAM: --set "ana.activated[+]" termination --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra +// SKIP NONTERM PARAM: --set "ana.activated[+]" termination --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra #include int main() diff --git a/tests/regression/75-termination/15-complex-loop-combination-terminating.c b/tests/regression/75-termination/15-complex-loop-combination-terminating.c index d987397dd7..c2ab718200 100644 --- a/tests/regression/75-termination/15-complex-loop-combination-terminating.c +++ b/tests/regression/75-termination/15-complex-loop-combination-terminating.c @@ -1,4 +1,4 @@ -// TERM PARAM: --set "ana.activated[+]" termination --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra --set sem.int.signed_overflow assume_none +// SKIP TERM PARAM: --set "ana.activated[+]" termination --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra --set sem.int.signed_overflow assume_none #include int main() diff --git a/tests/regression/75-termination/16-nested-loop-nontrivial-nonterminating.c b/tests/regression/75-termination/16-nested-loop-nontrivial-nonterminating.c index bded788a90..267a2d2fd8 100644 --- a/tests/regression/75-termination/16-nested-loop-nontrivial-nonterminating.c +++ b/tests/regression/75-termination/16-nested-loop-nontrivial-nonterminating.c @@ -1,4 +1,4 @@ -// NONTERM PARAM: --set "ana.activated[+]" termination --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra +// SKIP NONTERM PARAM: --set "ana.activated[+]" termination --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra #include int main() diff --git a/tests/regression/75-termination/17-goto-terminating.c b/tests/regression/75-termination/17-goto-terminating.c index 941db0c601..2f678d294b 100644 --- a/tests/regression/75-termination/17-goto-terminating.c +++ b/tests/regression/75-termination/17-goto-terminating.c @@ -1,4 +1,4 @@ -// NONTERM PARAM: --set "ana.activated[+]" termination --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra +// SKIP NONTERM PARAM: --set "ana.activated[+]" termination --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra // The program terminates but the analysis is currently only meant to detect up-jumping gotos as potentially NonTerminating, therefore we expect an NonTerm #include diff --git a/tests/regression/75-termination/18-goto-nonterminating.c b/tests/regression/75-termination/18-goto-nonterminating.c index f88088ad12..6de80effd7 100644 --- a/tests/regression/75-termination/18-goto-nonterminating.c +++ b/tests/regression/75-termination/18-goto-nonterminating.c @@ -1,4 +1,4 @@ -// NONTERM PARAM: --set "ana.activated[+]" termination --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra +// SKIP NONTERM PARAM: --set "ana.activated[+]" termination --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra #include int main() diff --git a/tests/regression/75-termination/19-rand-terminating.c b/tests/regression/75-termination/19-rand-terminating.c index 06deac6c34..a5b6c22941 100644 --- a/tests/regression/75-termination/19-rand-terminating.c +++ b/tests/regression/75-termination/19-rand-terminating.c @@ -1,4 +1,4 @@ -// TERM PARAM: --set "ana.activated[+]" termination --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra +// SKIP TERM PARAM: --set "ana.activated[+]" termination --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra #include #include #include diff --git a/tests/regression/75-termination/20-rand-nonterminating.c b/tests/regression/75-termination/20-rand-nonterminating.c index 394bce7709..21b25ed9dd 100644 --- a/tests/regression/75-termination/20-rand-nonterminating.c +++ b/tests/regression/75-termination/20-rand-nonterminating.c @@ -1,4 +1,4 @@ -// NONTERM PARAM: --set "ana.activated[+]" termination --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra +// SKIP NONTERM PARAM: --set "ana.activated[+]" termination --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra #include #include #include diff --git a/tests/regression/75-termination/21-no-exit-on-rand-unproofable.c b/tests/regression/75-termination/21-no-exit-on-rand-unproofable.c index 902ef2a4e2..5f82d91079 100644 --- a/tests/regression/75-termination/21-no-exit-on-rand-unproofable.c +++ b/tests/regression/75-termination/21-no-exit-on-rand-unproofable.c @@ -1,4 +1,4 @@ -// NONTERM PARAM: --set "ana.activated[+]" termination --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra +// SKIP NONTERM PARAM: --set "ana.activated[+]" termination --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra #include int main() diff --git a/tests/regression/75-termination/22-exit-on-rand-unproofable.c b/tests/regression/75-termination/22-exit-on-rand-unproofable.c index f14f7d4e3f..33838ca83d 100644 --- a/tests/regression/75-termination/22-exit-on-rand-unproofable.c +++ b/tests/regression/75-termination/22-exit-on-rand-unproofable.c @@ -1,4 +1,4 @@ -// NONTERM PARAM: --set "ana.activated[+]" termination --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra +// SKIP NONTERM PARAM: --set "ana.activated[+]" termination --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra #include int main() diff --git a/tests/regression/75-termination/23-exit-on-rand-terminating.c b/tests/regression/75-termination/23-exit-on-rand-terminating.c index 013aff2dd5..e65c064c40 100644 --- a/tests/regression/75-termination/23-exit-on-rand-terminating.c +++ b/tests/regression/75-termination/23-exit-on-rand-terminating.c @@ -1,4 +1,4 @@ -// TODO TERM PARAM: --set "ana.activated[+]" termination --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra +// SKIP TODO TERM PARAM: --set "ana.activated[+]" termination --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra #include #include diff --git a/tests/regression/75-termination/24-upjumping-goto-loopless-terminating.c b/tests/regression/75-termination/24-upjumping-goto-loopless-terminating.c index 3f4e115445..ce257d11ef 100644 --- a/tests/regression/75-termination/24-upjumping-goto-loopless-terminating.c +++ b/tests/regression/75-termination/24-upjumping-goto-loopless-terminating.c @@ -1,4 +1,4 @@ -// NONTERM PARAM: --set "ana.activated[+]" termination --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra +// SKIP NONTERM PARAM: --set "ana.activated[+]" termination --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra // The program terminates but the analysis is currently only meant to detect up-jumping gotos as potentially NonTerminating, therefore we expect an NonTerm #include diff --git a/tests/regression/75-termination/25-leave-loop-goto-terminating.c b/tests/regression/75-termination/25-leave-loop-goto-terminating.c index 2cda3d3a03..b882759bff 100644 --- a/tests/regression/75-termination/25-leave-loop-goto-terminating.c +++ b/tests/regression/75-termination/25-leave-loop-goto-terminating.c @@ -1,4 +1,4 @@ -// TODO TERM PARAM: --set "ana.activated[+]" termination --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra +// SKIP TODO TERM PARAM: --set "ana.activated[+]" termination --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra #include int main() diff --git a/tests/regression/75-termination/26-enter-loop-goto-terminating.c b/tests/regression/75-termination/26-enter-loop-goto-terminating.c index 0de9a95d6c..aa85f22b3e 100644 --- a/tests/regression/75-termination/26-enter-loop-goto-terminating.c +++ b/tests/regression/75-termination/26-enter-loop-goto-terminating.c @@ -1,4 +1,4 @@ -// TODO TERM PARAM: --set "ana.activated[+]" termination --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra +// SKIP TODO TERM PARAM: --set "ana.activated[+]" termination --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra #include int main() diff --git a/tests/regression/75-termination/27-upjumping-goto-nonterminating.c b/tests/regression/75-termination/27-upjumping-goto-nonterminating.c index 5ce295872c..e0eb633b11 100644 --- a/tests/regression/75-termination/27-upjumping-goto-nonterminating.c +++ b/tests/regression/75-termination/27-upjumping-goto-nonterminating.c @@ -1,4 +1,4 @@ -// NONTERM PARAM: --set "ana.activated[+]" termination --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra +// SKIP NONTERM PARAM: --set "ana.activated[+]" termination --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra #include int main() diff --git a/tests/regression/75-termination/28-do-while-continue-terminating.c b/tests/regression/75-termination/28-do-while-continue-terminating.c index 61bd578dcf..a61174d295 100644 --- a/tests/regression/75-termination/28-do-while-continue-terminating.c +++ b/tests/regression/75-termination/28-do-while-continue-terminating.c @@ -1,4 +1,4 @@ -// TODO TERM PARAM: --set "ana.activated[+]" termination --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra +// SKIP TODO TERM PARAM: --set "ana.activated[+]" termination --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra #include int main() diff --git a/tests/regression/75-termination/29-do-while-continue-nonterminating.c b/tests/regression/75-termination/29-do-while-continue-nonterminating.c index 34766ab2e7..dd931c012f 100644 --- a/tests/regression/75-termination/29-do-while-continue-nonterminating.c +++ b/tests/regression/75-termination/29-do-while-continue-nonterminating.c @@ -1,4 +1,4 @@ -// NONTERM PARAM: --set "ana.activated[+]" termination --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra +// SKIP NONTERM PARAM: --set "ana.activated[+]" termination --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra #include int main() diff --git a/tests/regression/75-termination/30-goto-out-of-inner-loop-terminating.c b/tests/regression/75-termination/30-goto-out-of-inner-loop-terminating.c index 5cdadf4396..999ee6d3fd 100644 --- a/tests/regression/75-termination/30-goto-out-of-inner-loop-terminating.c +++ b/tests/regression/75-termination/30-goto-out-of-inner-loop-terminating.c @@ -1,4 +1,4 @@ -// TERM PARAM: --set "ana.activated[+]" termination --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra +// SKIP TERM PARAM: --set "ana.activated[+]" termination --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra #include int main() diff --git a/tests/regression/75-termination/31-goto-out-of-inner-loop-nonterminating.c b/tests/regression/75-termination/31-goto-out-of-inner-loop-nonterminating.c index d7ff329396..f9b9275620 100644 --- a/tests/regression/75-termination/31-goto-out-of-inner-loop-nonterminating.c +++ b/tests/regression/75-termination/31-goto-out-of-inner-loop-nonterminating.c @@ -1,4 +1,4 @@ -// NONTERM PARAM: --set "ana.activated[+]" termination --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra +// SKIP NONTERM PARAM: --set "ana.activated[+]" termination --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra #include int main() diff --git a/tests/regression/75-termination/32-multithread-terminating.c b/tests/regression/75-termination/32-multithread-terminating.c index fbac273776..eb8b796a47 100644 --- a/tests/regression/75-termination/32-multithread-terminating.c +++ b/tests/regression/75-termination/32-multithread-terminating.c @@ -1,4 +1,4 @@ -// NONTERM PARAM: --set "ana.activated[+]" termination --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra +// SKIP NONTERM PARAM: --set "ana.activated[+]" termination --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra // The program terminates but as the termination analysis is meant to not handle multithreaded programs we expect NonTerm here #include #include diff --git a/tests/regression/75-termination/33-multithread-nonterminating.c b/tests/regression/75-termination/33-multithread-nonterminating.c index dad62aa0f4..8a6274c7ab 100644 --- a/tests/regression/75-termination/33-multithread-nonterminating.c +++ b/tests/regression/75-termination/33-multithread-nonterminating.c @@ -1,4 +1,4 @@ -// NONTERM PARAM: --set "ana.activated[+]" termination --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra +// SKIP NONTERM PARAM: --set "ana.activated[+]" termination --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra #include #include #include diff --git a/tests/regression/75-termination/34-nested-for-loop-nonterminating.c b/tests/regression/75-termination/34-nested-for-loop-nonterminating.c index 24605ad478..2f21f9e996 100644 --- a/tests/regression/75-termination/34-nested-for-loop-nonterminating.c +++ b/tests/regression/75-termination/34-nested-for-loop-nonterminating.c @@ -1,4 +1,4 @@ -// NONTERM PARAM: --set "ana.activated[+]" termination --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra +// SKIP NONTERM PARAM: --set "ana.activated[+]" termination --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra #include int main() diff --git a/tests/regression/75-termination/35-goto-out-of-inner-loop-with-print-terminating.c b/tests/regression/75-termination/35-goto-out-of-inner-loop-with-print-terminating.c index 3bd6e53d2d..0554a0bc25 100644 --- a/tests/regression/75-termination/35-goto-out-of-inner-loop-with-print-terminating.c +++ b/tests/regression/75-termination/35-goto-out-of-inner-loop-with-print-terminating.c @@ -1,4 +1,4 @@ -// TERM PARAM: --set "ana.activated[+]" termination --set "ana.activated[+]" apron --enable ana.int.interval --set ana.apron.domain polyhedra --set sem.int.signed_overflow assume_none +// SKIP TERM PARAM: --set "ana.activated[+]" termination --set "ana.activated[+]" apron --enable ana.int.interval --set ana.apron.domain polyhedra --set sem.int.signed_overflow assume_none #include int main() diff --git a/tests/regression/75-termination/36-recursion-terminating.c b/tests/regression/75-termination/36-recursion-terminating.c index 7336417c91..179efabeea 100644 --- a/tests/regression/75-termination/36-recursion-terminating.c +++ b/tests/regression/75-termination/36-recursion-terminating.c @@ -1,4 +1,4 @@ -// TERM PARAM: --set "ana.activated[+]" termination --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra +// SKIP TERM PARAM: --set "ana.activated[+]" termination --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra #include void recursiveFunction(int n) diff --git a/tests/regression/75-termination/37-recursion-nonterminating.c b/tests/regression/75-termination/37-recursion-nonterminating.c index 21316de9bd..c47fbcdd49 100644 --- a/tests/regression/75-termination/37-recursion-nonterminating.c +++ b/tests/regression/75-termination/37-recursion-nonterminating.c @@ -1,4 +1,4 @@ -// NONTERM PARAM: --set "ana.activated[+]" termination --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra --enable ana.context.widen +// SKIP NONTERM PARAM: --set "ana.activated[+]" termination --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra --enable ana.context.widen #include void recursiveFunction(int n) // NONTERMFUNDEC termination analysis shall mark fundec of non-terminating function diff --git a/tests/regression/75-termination/38-recursion-nested-terminating.c b/tests/regression/75-termination/38-recursion-nested-terminating.c index bef05eb1a0..a471cfc386 100644 --- a/tests/regression/75-termination/38-recursion-nested-terminating.c +++ b/tests/regression/75-termination/38-recursion-nested-terminating.c @@ -1,4 +1,4 @@ -// TERM PARAM: --set "ana.activated[+]" termination --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra +// SKIP TERM PARAM: --set "ana.activated[+]" termination --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra #include void innerRecursiveFunction(int n) diff --git a/tests/regression/75-termination/39-recursion-nested-nonterminating.c b/tests/regression/75-termination/39-recursion-nested-nonterminating.c index b3aa8bf21b..a8d7107442 100644 --- a/tests/regression/75-termination/39-recursion-nested-nonterminating.c +++ b/tests/regression/75-termination/39-recursion-nested-nonterminating.c @@ -1,7 +1,7 @@ -// NONTERM PARAM: --set "ana.activated[+]" termination --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra +// SKIP NONTERM PARAM: --set "ana.activated[+]" termination --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra #include -void innerRecursiveFunction() // TODO NONTERMFUNDEC termination analysis shall mark fundec of non-terminating function +void innerRecursiveFunction() // TODO NONTERMFUNDEC termination analysis shall mark fundec of non-terminating function but can not as dead code is not analysed { printf("Nested recursive call\n"); diff --git a/tests/regression/75-termination/40-multi-expression-conditions-terminating.c b/tests/regression/75-termination/40-multi-expression-conditions-terminating.c index 8e7b4e273d..80f8c5a1e8 100644 --- a/tests/regression/75-termination/40-multi-expression-conditions-terminating.c +++ b/tests/regression/75-termination/40-multi-expression-conditions-terminating.c @@ -1,4 +1,4 @@ -// TODO TERM PARAM: --set "ana.activated[+]" termination --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra +// SKIP TODO TERM PARAM: --set "ana.activated[+]" termination --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra #include int main() diff --git a/tests/regression/75-termination/41-for-continue-terminating.c b/tests/regression/75-termination/41-for-continue-terminating.c index 1d3b96fcf8..d87a705868 100644 --- a/tests/regression/75-termination/41-for-continue-terminating.c +++ b/tests/regression/75-termination/41-for-continue-terminating.c @@ -1,4 +1,4 @@ -// TODO TERM PARAM: --set "ana.activated[+]" termination --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra +// SKIP TODO TERM PARAM: --set "ana.activated[+]" termination --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra #include int main() diff --git a/tests/regression/75-termination/42-downjumping-goto-loopless-terminating.c b/tests/regression/75-termination/42-downjumping-goto-loopless-terminating.c index 54bcfdc508..48864883f7 100644 --- a/tests/regression/75-termination/42-downjumping-goto-loopless-terminating.c +++ b/tests/regression/75-termination/42-downjumping-goto-loopless-terminating.c @@ -1,4 +1,4 @@ -// TERM PARAM: --set "ana.activated[+]" termination --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra +// SKIP TERM PARAM: --set "ana.activated[+]" termination --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra #include int main() { // Currently not able to detect up-jumping loop free gotos diff --git a/tests/regression/75-termination/43-return-from-endless-loop-terminating.c b/tests/regression/75-termination/43-return-from-endless-loop-terminating.c index 06bda24bd7..fb48e1cdbe 100644 --- a/tests/regression/75-termination/43-return-from-endless-loop-terminating.c +++ b/tests/regression/75-termination/43-return-from-endless-loop-terminating.c @@ -1,4 +1,4 @@ -// TERM PARAM: --set "ana.activated[+]" termination --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra +// SKIP TERM PARAM: --set "ana.activated[+]" termination --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra #include int main() { diff --git a/tests/regression/75-termination/44-recursion-multiple-functions-terminating.c b/tests/regression/75-termination/44-recursion-multiple-functions-terminating.c index c112c72a73..7f9b63527e 100644 --- a/tests/regression/75-termination/44-recursion-multiple-functions-terminating.c +++ b/tests/regression/75-termination/44-recursion-multiple-functions-terminating.c @@ -1,4 +1,4 @@ -// TERM PARAM: --set "ana.activated[+]" termination --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra +// SKIP TERM PARAM: --set "ana.activated[+]" termination --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra #include void functionB(int n); diff --git a/tests/regression/75-termination/45-recursion-multiple-functions-nonterminating.c b/tests/regression/75-termination/45-recursion-multiple-functions-nonterminating.c index 47c13c0dca..be47fde704 100644 --- a/tests/regression/75-termination/45-recursion-multiple-functions-nonterminating.c +++ b/tests/regression/75-termination/45-recursion-multiple-functions-nonterminating.c @@ -1,4 +1,4 @@ -// NONTERM PARAM: --set "ana.activated[+]" termination --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra +// SKIP NONTERM PARAM: --set "ana.activated[+]" termination --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra #include void functionB(int n); diff --git a/tests/regression/75-termination/46-recursion-different-context-terminating.c b/tests/regression/75-termination/46-recursion-different-context-terminating.c index 4c5dd13035..2fa42f58fc 100644 --- a/tests/regression/75-termination/46-recursion-different-context-terminating.c +++ b/tests/regression/75-termination/46-recursion-different-context-terminating.c @@ -1,4 +1,4 @@ -// TERM PARAM: --set "ana.activated[+]" termination --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra +// SKIP TERM PARAM: --set "ana.activated[+]" termination --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra #include void functionC(int n); diff --git a/tests/regression/75-termination/47-recursion-different-context-nonterminating.c b/tests/regression/75-termination/47-recursion-different-context-nonterminating.c index 3216275748..b0e44bce92 100644 --- a/tests/regression/75-termination/47-recursion-different-context-nonterminating.c +++ b/tests/regression/75-termination/47-recursion-different-context-nonterminating.c @@ -1,4 +1,4 @@ -// NONTERM PARAM: --set "ana.activated[+]" termination --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra +// SKIP NONTERM PARAM: --set "ana.activated[+]" termination --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra #include void functionC(int n); diff --git a/tests/regression/75-termination/48-dynamic-recursion-nonterminating.c b/tests/regression/75-termination/48-dynamic-recursion-nonterminating.c index 066c2f51b1..d54c49fb43 100644 --- a/tests/regression/75-termination/48-dynamic-recursion-nonterminating.c +++ b/tests/regression/75-termination/48-dynamic-recursion-nonterminating.c @@ -1,4 +1,4 @@ -// NONTERM PARAM: --set "ana.activated[+]" termination --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra +// SKIP NONTERM PARAM: --set "ana.activated[+]" termination --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra void troll(void (*f) ()) { f(f); From 3c31cb7846582c9f37e62a32ba04b2ec4a4a0c59 Mon Sep 17 00:00:00 2001 From: Thomas Lagemann Date: Mon, 24 Jul 2023 17:34:55 +0200 Subject: [PATCH 255/327] Revert src/analyses/termination.ml --- src/analyses/termination.ml | 169 +++++++++--------------------------- 1 file changed, 43 insertions(+), 126 deletions(-) diff --git a/src/analyses/termination.ml b/src/analyses/termination.ml index 6112eb0eaf..6da9225d3f 100644 --- a/src/analyses/termination.ml +++ b/src/analyses/termination.ml @@ -5,8 +5,6 @@ open GoblintCil open Analyses module M = Messages -(* J: returns if a and b contain a value - if yes: return this x, otherwise nothing *) let (||?) a b = match a,b with Some x,_ | _, Some x -> Some x | _ -> None module TermDomain = struct @@ -14,22 +12,15 @@ module TermDomain = struct end (* some kind of location string suitable for variable names? *) -(* J: returns a string_ "lineNr_columnNr" *) -(* J: for location (10,5) it evaluates to: 10_5*) let show_location_id l = string_of_int l.line ^ "_" ^ string_of_int l.column -(* J: the new variable is created here and inserted into the code - in the code the variable is set to 0 (before the loop) and incremented (after the loop) - is it ever checked if the newly created variable is really new???*) -(* J: ??? Who defines the Loop, what are the variables*) class loopCounterVisitor (fd : fundec) = object(self) inherit nopCilVisitor method! vstmt s = let action s = match s.skind with | Loop (b, loc, eloc, _, _) -> (* insert loop counter variable *) - (* J: for location (10,5) it evaluates to: term10_5*) let name = "term"^show_location_id loc in let typ = intType in (* TODO the type should be the same as the one of the original loop counter *) let v = Cilfacade.create_var (makeLocalVar fd name ~init:(SingleInit zero) typ) in @@ -38,20 +29,14 @@ class loopCounterVisitor (fd : fundec) = object(self) (* increment it every iteration *) let inc_stmt = mkStmtOneInstr @@ Set (var v, increm (Lval (var v)) 1, loc, eloc) in b.bstmts <- inc_stmt :: b.bstmts; - let nb = mkBlock [init_stmt; mkStmt s.skind] in (* J: s.kind = Loop(b, loc, eloc, ...)*) + let nb = mkBlock [init_stmt; mkStmt s.skind] in s.skind <- Block nb; s | _ -> s in ChangeDoChildrenPost (s, action) end -(* J: creates a new hash table with size 13 for loop breaks*) -(* J: int: is a number which is unique in a function*) -(* J: ??? Why 13*) let loopBreaks : (int, location) Hashtbl.t = Hashtbl.create 13 (* break stmt sid -> corresponding loop *) -(* J: if there is some break associated with the loop (?) we add this break to the hash table - key = break.sid - data = location *) class loopBreaksVisitor (fd : fundec) = object(self) inherit nopCilVisitor method! vstmt s = @@ -63,15 +48,10 @@ class loopBreaksVisitor (fd : fundec) = object(self) end (* if the given block contains a goto while_break.* we have the termination condition for a loop *) -(* J: returns binding from loopBreaks hash table associated with a number which is uniquely identifie with the statement - if there is a Goto, otherwise nothing*) -(* J: stmt.sid = A number (>= 0) that is unique in a function. *) -(* J: ???*) let exits = function | { bstmts = [{ skind = Goto (stmt, loc); _ }]; _ } -> Hashtbl.find_option loopBreaks !stmt.sid | _ -> None (* TODO handle return (need to find out what loop we are in) *) -(* J: ???*) let lvals_of_expr = let rec f a = function | Const _ | SizeOf _ | SizeOfStr _ | AlignOf _ | AddrOfLabel _ -> a @@ -81,187 +61,125 @@ let lvals_of_expr = | Question (c,t,e,_) -> f a c @ f a t @ f a e in f [] -(* J: create hash table of size 13 for variables*) let loopVars : (location, lval) Hashtbl.t = Hashtbl.create 13 (* loop location -> lval used for exit *) -(* J: adds the location and left varibale to the loopVars, if one block of the if statement contains a goto block*) class loopVarsVisitor (fd : fundec) = object inherit nopCilVisitor method! vstmt s = let add_exit_cond e loc = match lvals_of_expr e with - (* J: ??? Same as when isArithmeticType Cilfacade.typeOf e*) | [lval] when Cilfacade.typeOf e |> isArithmeticType -> Hashtbl.add loopVars loc lval - (* J : add lval to hash table when the expression on location loc is of arithmetic type*) | _ -> () in (match s.skind with - (* J: map_default f x (Some v) returns f v and map_default f x None returns x.*) - (* J: If there exists a goto statement: call add_exit_cond e (SOME exits tb ||? exits fb) - If e is of arithmetic type: add the location to the loopVars hash table *) | If (e, tb, fb, loc, eloc) -> Option.map_default (add_exit_cond e) () (exits tb ||? exits fb) | _ -> ()); DoChildren end -(* J: ??? visits the expression e and removes all casts from the expression*) let stripCastsDeep e = let v = object inherit nopCilVisitor - (* J: ChangeTo: Replace the expression with the given one*) - (* J: Removes casts from this expression, but ignores casts within other expression constructs. - So we delete the (A) and (B) casts from "(A)(B)(x + (C)y)", but leave the (C) cast.*) method! vexpr e = ChangeTo (stripCasts e) end in visitCilExpr v e (* keep the enclosing loop for statements *) -(* J: store pointer pointing to Nothing for loops*) let cur_loop = ref None (* current loop *) let cur_loop' = ref None (* for nested loops *) -(* J: searches if the variable name___ for the given location is present in the function definition - if not: the variable is created and initialized to 0*) let makeVar fd loc name = - (* J: for location = (10,5) and name = "hi" the id evaluates to: hi__10_5*) let id = name ^ "__" ^ show_location_id loc in - (* J: fd.slocals = Locals of the function definition*) - (* J: returns the first element which is a local and which name is id (for example hi__10_5)*) try List.find (fun v -> v.vname = id) fd.slocals - (* J: when the variable is not found in the function definition then it is newly created and initialized with 0*) with Not_found -> let typ = intType in (* TODO the type should be the same as the one of the original loop counter *) Cilfacade.create_var (makeLocalVar fd id ~init:(SingleInit zero) typ) -(* J: creates an empty function with name "__goblint_assume" and makes a lvalue out of it*) let f_assume = Lval (var (emptyFunction "__goblint_assume").svar) -(* J: creates an empty function with name "__goblint_check" and makes a lvalue out of it*) let f_check = Lval (var (emptyFunction "__goblint_check").svar) -(* J: ??? Loop pointer handling: Why do we fist set cur_loop' = cur_loop and then reverse this operation???*) -(* J: inserts new variable t with init and increment and adds a check if t is bounded*) class loopInstrVisitor (fd : fundec) = object(self) inherit nopCilVisitor method! vstmt s = (* TODO: use Loop eloc? *) (match s.skind with - (* J: if the statement is a loop adjust the loop pointer*) | Loop (_, loc, eloc, _, _) -> - cur_loop' := !cur_loop; (* J: set the nested loop to the current loop*) - cur_loop := Some loc (* J: set the newly found loop as current loop*) + cur_loop' := !cur_loop; + cur_loop := Some loc | _ -> ()); - (* J: adds the variable t to the loop, increments it and checks after the loop if it is bounded - adds also the variables d1 and d2, with incrementation, which affects t - depending on the structure, d1 and d2 are set differently*) let action s = (* first, restore old cur_loop *) - (* J: if the statement is a loop set the nested loop as the current loop*) (match s.skind with | Loop (_, loc, eloc, _, _) -> - cur_loop := !cur_loop'; (* J: current loop is the nested loop*) + cur_loop := !cur_loop'; | _ -> ()); - (* J: true if the current loop variable is set and this variable is bound in the hash table*) let in_loop () = Option.is_some !cur_loop && Hashtbl.mem loopVars (Option.get !cur_loop) in - (* J: t is the new variable which should be bounded - if there is a loop with bounded variable: add code for init and increment (for t, d1, d2) - if there is a loop with unbounded variable: do nothing - if a loop ended: check if t is bounded - if there is an instruction with an assignment: increment d1 and d2 if the assignment affects the loop var - do this recursively for all children*) match s.skind with - (* J: if the statement is a loop, and when the location is bound in the hash table: - - add the creational and initializational code for t, d1, d2 before the loop - - add the incrementational code for t, d1, d2 in the loop - *) | Loop (b, loc, eloc, Some continue, Some break) when Hashtbl.mem loopVars loc -> (* find loop var for current loop *) let x = Hashtbl.find loopVars loc in (* insert loop counter and diff to loop var *) - (* J: create variables t, d1, d2 with names: t___, d1___, d2___*) let t = var @@ makeVar fd loc "t" in let d1 = var @@ makeVar fd loc "d1" in let d2 = var @@ makeVar fd loc "d2" in (* make init stmts *) - (* J: set t=0, d1, d2 = lvalue of x = value in the hashtable associated with the loop variable*) let t_init = mkStmtOneInstr @@ Set (t, zero, loc, eloc) in let d1_init = mkStmtOneInstr @@ Set (d1, Lval x, loc, eloc) in let d2_init = mkStmtOneInstr @@ Set (d2, Lval x, loc, eloc) in (* increment/decrement in every iteration *) - (* J: increment t and d2, decrement d1*) - let t_inc = mkStmtOneInstr @@ Set (t, increm (Lval t) 1, loc, eloc) in (* J: t = t + 1*) - let d1_inc = mkStmtOneInstr @@ Set (d1, increm (Lval d1) (-1), loc, eloc) in (* J: d1 = d1 - 1*) - let d2_inc = mkStmtOneInstr @@ Set (d2, increm (Lval d2) 1 , loc, eloc) in (* J: d2 = d2 + 1*) - let typ = intType in (* J: Note: x is the loop variable*) - let e1 = BinOp (Eq, Lval t, BinOp (MinusA, Lval x, Lval d1, typ), typ) in (* J: t = (x - d1) *) - let e2 = BinOp (Eq, Lval t, BinOp (MinusA, Lval d2, Lval x, typ), typ) in (* J: t = (d2 - x) *) - (* J: make a statement for e1 and e2*) - (* J: ??? what happens with the call*) + let t_inc = mkStmtOneInstr @@ Set (t, increm (Lval t) 1, loc, eloc) in + let d1_inc = mkStmtOneInstr @@ Set (d1, increm (Lval d1) (-1), loc, eloc) in + let d2_inc = mkStmtOneInstr @@ Set (d2, increm (Lval d2) 1 , loc, eloc) in + let typ = intType in + let e1 = BinOp (Eq, Lval t, BinOp (MinusA, Lval x, Lval d1, typ), typ) in + let e2 = BinOp (Eq, Lval t, BinOp (MinusA, Lval d2, Lval x, typ), typ) in let inv1 = mkStmtOneInstr @@ Call (None, f_assume, [e1], loc, eloc) in let inv2 = mkStmtOneInstr @@ Call (None, f_assume, [e2], loc, eloc) in - (match b.bstmts with (* J: we are still in a loop*) + (match b.bstmts with | cont :: cond :: ss -> (* changing succs/preds directly doesn't work -> need to replace whole stmts *) - (* from: cont :: cond :: ss - to: cont :: - cond :: - t = (x - d1) :: t = (d2 - x) :: (??? Is this correct with the call???) - d1 = d1 - 1 :: d2 = d2 + 1 :: t = t + 1 :: - ss - *) - b.bstmts <- cont :: cond :: inv1 :: inv2 :: d1_inc :: d2_inc :: t_inc :: ss; (* J: in the loop*) - let nb = mkBlock [t_init; d1_init; d2_init; mkStmt s.skind] in (* J: make a block out of the init statements before the loop*) + b.bstmts <- cont :: cond :: inv1 :: inv2 :: d1_inc :: d2_inc :: t_inc :: ss; + let nb = mkBlock [t_init; d1_init; d2_init; mkStmt s.skind] in s.skind <- Block nb; | _ -> ()); - s (* J: return s with added code for init and increment*) - (* J: if the variable in the loops is not bounded, it is not possible to continue*) + s | Loop (b, loc, eloc, Some continue, Some break) -> print_endline @@ "WARN: Could not determine loop variable for loop at " ^ CilType.Location.show loc; s - (* J: when the statement is not a loop and a loop ended: - - add t >= 0 in the code after the loop*) | _ when Hashtbl.mem loopBreaks s.sid -> (* after a loop, we check that t is bounded/positive (no overflow happened) *) - let loc = Hashtbl.find loopBreaks s.sid in (* J: holds the current binding of the number of the current function in the hash table*) - let t = var @@ makeVar fd loc "t" in (* J: get the name for variable t = t___*) - let e3 = BinOp (Ge, Lval t, zero, intType) in (* J: t >= 0*) - let inv3 = mkStmtOneInstr @@ Call (None, f_check, [e3], loc, locUnknown) in (* J: make a statement to check t >= 0*) - let nb = mkBlock [mkStmt s.skind; inv3] in (* J: add the statement to the block*) + let loc = Hashtbl.find loopBreaks s.sid in + let t = var @@ makeVar fd loc "t" in + let e3 = BinOp (Ge, Lval t, zero, intType) in + let inv3 = mkStmtOneInstr @@ Call (None, f_check, [e3], loc, locUnknown) in + let nb = mkBlock [mkStmt s.skind; inv3] in s.skind <- Block nb; - s (* J: return s with the added check*) - (* J: If there is an instruction (containing an assignment) and it is in a loop: - If the loop variable and lvalue of Set are structural unequal - Do nothing - else - add an incrementation step for d1 and d2 (depending on the binOp)*) + s | Instr [Set (lval, e, loc, eloc)] when in_loop () -> (* find loop var for current loop *) let cur_loop = Option.get !cur_loop in - let x = Hashtbl.find loopVars cur_loop in (* J: holds the current binding of the number of the current function in the hash table*) - if x <> lval then (* J: x and lval are structural unequal*) + let x = Hashtbl.find loopVars cur_loop in + if x <> lval then s else (* we only care about the loop var *) - (* J: create the variables d1 and d2 with name: d1___, d2___*) let d1 = makeVar fd cur_loop "d1" in let d2 = makeVar fd cur_loop "d2" in (match stripCastsDeep e with - (* J: if x' + e2 or x' - e2 with x' = x and the type arithmetic:- adds incrementation for d1 and d2 to the code*) - (* J: if the loopVar is changed*) | BinOp (op, Lval x', e2, typ) when (op = PlusA || op = MinusA) && x' = x && isArithmeticType typ -> (* TODO x = 1 + x, MinusA! *) (* increase diff by same expr *) - let d1_inc = mkStmtOneInstr @@ Set (var d1, BinOp (PlusA, Lval (var d1), e2, typ), loc, eloc) in (* J: d1 = d1 + e2*) - let d2_inc = mkStmtOneInstr @@ Set (var d2, BinOp (PlusA, Lval (var d2), e2, typ), loc, eloc) in (* J: d2 = d2 + e2*) - let nb = mkBlock [d1_inc; d2_inc; mkStmt s.skind] in (* J: add the incrementation steps at the front*) + let d1_inc = mkStmtOneInstr @@ Set (var d1, BinOp (PlusA, Lval (var d1), e2, typ), loc, eloc) in + let d2_inc = mkStmtOneInstr @@ Set (var d2, BinOp (PlusA, Lval (var d2), e2, typ), loc, eloc) in + let nb = mkBlock [d1_inc; d2_inc; mkStmt s.skind] in s.skind <- Block nb; - s (* J: return s with the added incrementation*) + s | _ -> (* otherwise diff is e - counter *) - let t = makeVar fd cur_loop "t" in (* J: varibale name for t*) - let te = Cilfacade.typeOf e in (* J: type of e*) - let dt1 = mkStmtOneInstr @@ Set (var d1, BinOp (MinusA, Lval x, Lval (var t), te), loc, eloc) in (* J: d1 = x - t*) - let dt2 = mkStmtOneInstr @@ Set (var d2, BinOp (MinusA, Lval x, Lval (var t), te), loc, eloc) in (* J: d2 = x - t*) - let nb = mkBlock [mkStmt s.skind; dt1; dt2] in (* J: add the incrementation steps at the end*) + let t = makeVar fd cur_loop "t" in + let te = Cilfacade.typeOf e in + let dt1 = mkStmtOneInstr @@ Set (var d1, BinOp (MinusA, Lval x, Lval (var t), te), loc, eloc) in + let dt2 = mkStmtOneInstr @@ Set (var d2, BinOp (MinusA, Lval x, Lval (var t), te), loc, eloc) in + let nb = mkBlock [mkStmt s.skind; dt1; dt2] in s.skind <- Block nb; s ) | _ -> s in - (* J: *) - ChangeDoChildrenPost (s, action) (* J: continue with the children*) + ChangeDoChildrenPost (s, action) end @@ -298,25 +216,24 @@ struct (* ctx.local *) (* | _ -> ctx.local *) - let startstate v = D.bot () (* J: start with bottom*) - let threadenter ctx lval f args = [D.bot ()] (* J: enter threads with bottom*) + let startstate v = D.bot () + let threadenter ctx lval f args = [D.bot ()] let exitstate v = D.bot () end class recomputeVisitor (fd : fundec) = object(self) inherit nopCilVisitor method! vfunc fd = - computeCFGInfo fd true; (* J: make the cfg and return a list of statements with global statement number*) - SkipChildren (* J: don't visit children*) + computeCFGInfo fd true; + SkipChildren end let _ = (* Cilfacade.register_preprocess Spec.name (new loopCounterVisitor); *) - Cilfacade.register_preprocess (Spec.name ()) (new loopBreaksVisitor); (* J: fill hash table loopBreaks: containing breaks ?*) - Cilfacade.register_preprocess (Spec.name ()) (new loopVarsVisitor); (* J: fill hash table loopVars: containing varibales identified with loops ?*) - Cilfacade.register_preprocess (Spec.name ()) (new loopInstrVisitor); (* J: inserts new variable with init, increment, and bounded check to code*) - Cilfacade.register_preprocess (Spec.name ()) (new recomputeVisitor); (* J: ??? *) - Hashtbl.clear loopBreaks; (* because the sids are now different *) (* J: delete entries in loopBreaks*) - Cilfacade.register_preprocess (Spec.name ()) (new loopBreaksVisitor); (* J: newly set hash table loopBreaks with goto statements*) - MCP.register_analysis (module Spec : MCPSpec) (* A: register this (termination) analysis withing the master control program, which - collects all active analyses and represents the combination of them as a new, single analysis to FromSpec *) + Cilfacade.register_preprocess (Spec.name ()) (new loopBreaksVisitor); + Cilfacade.register_preprocess (Spec.name ()) (new loopVarsVisitor); + Cilfacade.register_preprocess (Spec.name ()) (new loopInstrVisitor); + Cilfacade.register_preprocess (Spec.name ()) (new recomputeVisitor); + Hashtbl.clear loopBreaks; (* because the sids are now different *) + Cilfacade.register_preprocess (Spec.name ()) (new loopBreaksVisitor); + MCP.register_analysis (module Spec : MCPSpec) From a9c9c7d2f84d10945ec0031f2433048dd0ad0cb8 Mon Sep 17 00:00:00 2001 From: Isidor Zweckstetter Date: Tue, 25 Jul 2023 19:46:48 +0200 Subject: [PATCH 256/327] changed initial value of lcv to min int; swaped sequence of increment and special function call, to retain top of intdomain at special function call --- runningGob.sh | 8 ++++---- src/maingoblint.ml | 2 +- src/util/terminationPreprocessing.ml | 10 ++++++---- 3 files changed, 11 insertions(+), 9 deletions(-) diff --git a/runningGob.sh b/runningGob.sh index 61dbad53b6..e70b34af7c 100755 --- a/runningGob.sh +++ b/runningGob.sh @@ -13,7 +13,7 @@ cfile_loop26="tests/regression/74-loop_termination/26-enter-loop-goto-terminatin cfile_loop28="tests/regression/74-loop_termination/28-do-while-continue-terminating.c" cfile_loop7="tests/regression/74-loop_termination/07-nested-for-loop-terminating.c" cfile_loop5="tests/regression/74-loop_termination/05-for-loop-terminating.c" -cfile_loop1="tests/regression/74-loop_termination/01-simple-loop-terminating.c" +cfile_loop1="tests/regression/75-termination/02-simple-loop-nonterminating.c" cfile_signs="tests/regression/99-tutorials/01-first.c" cfile_goto="tests/incremental/02-cfg-comparison/01-added-return-stmt.c" @@ -22,10 +22,10 @@ cfile_goto="tests/incremental/02-cfg-comparison/01-added-return-stmt.c" #./goblint $cfile_loops $options_apron --html # run analysis, write cil output to file and enable visualization via html -./goblint $cfile_loop30 $options_term --enable justcil > output.txt -./goblint -v $cfile_loop30 $options_term --html +./goblint $cfile_loop1 $options_term --enable justcil > output.txt +./goblint $cfile_loop1 $options_term --html # set up server to see visualizatino -python3 -m http.server --directory result 8080 +python3 -m http.server --directory result 8082 #./goblint --enable dbg.debug tests/regression/55-loop-unrolling/01-simple-cases.c --enable ana.int.interval --set "ana.activated[+]" signs --enable justcil > output.txt diff --git a/src/maingoblint.ml b/src/maingoblint.ml index 371deb989a..f9abd9637b 100644 --- a/src/maingoblint.ml +++ b/src/maingoblint.ml @@ -162,7 +162,7 @@ let check_arguments () = if get_bool "solvers.td3.space" && get_string "solvers.td3.side_widen" = "sides-local" then fail "solvers.td3.space is incompatible with solvers.td3.side_widen = 'sides-local'"; if List.mem "termination" @@ get_string_list "ana.activated" then ( set_list "ana.activated" (GobConfig.get_list "ana.activated" @ [`String ("evermultithreaded")]); - (*set_string "sem.int.signed_overflow" "assume_none";*) + set_string "sem.int.signed_overflow" "assume_none"; warn "termination analysis implicitly activates evermultithreaded analysis and set sem.int.signed_overflow to assume_none" ) diff --git a/src/util/terminationPreprocessing.ml b/src/util/terminationPreprocessing.ml index 0ff459718a..768dac0df9 100644 --- a/src/util/terminationPreprocessing.ml +++ b/src/util/terminationPreprocessing.ml @@ -31,7 +31,9 @@ class loopCounterVisitor lc lg (fd : fundec) = object(self) smaxstmtid = None; sallstmts = []; } in - + + let min_int_exp = Const(CInt(Cilint.shift_left_cilint Cilint.mone_cilint ((bytesSizeOfInt IInt)*8-1), IInt, None)) in + let f_bounded = Lval (var (specialFunction "__goblint_bounded").svar) in let action s = match s.skind with @@ -39,15 +41,15 @@ class loopCounterVisitor lc lg (fd : fundec) = object(self) let name = "term"^show_location_id loc in let typ = Cil.intType in let v = (Cil.makeLocalVar fd name typ) in (*Not tested for incremental mode*) - let init_stmt = mkStmtOneInstr @@ Set (var v, zero, loc, eloc) in + let init_stmt = mkStmtOneInstr @@ Set (var v, min_int_exp, loc, eloc) in let inc_stmt = mkStmtOneInstr @@ Set (var v, increm (Lval (var v)) 1, loc, eloc) in let inc_stmt2 = mkStmtOneInstr @@ Set (var v, increm (Lval (var v)) 1, loc, eloc) in let exit_stmt = mkStmtOneInstr @@ Call (None, f_bounded, [Lval (var v)], loc, locUnknown) in (match b.bstmts with | s :: ss -> (*duplicate increment statement here to fix inconsistencies in nested loops*) - b.bstmts <- inc_stmt :: exit_stmt :: s :: inc_stmt2 :: ss; + b.bstmts <- exit_stmt :: inc_stmt :: s :: inc_stmt2 :: ss; | ss -> - b.bstmts <- inc_stmt :: exit_stmt :: ss; + b.bstmts <- exit_stmt :: inc_stmt :: ss; ); lc := VarToStmt.add (v: varinfo) (s: stmt) !lc; let nb = mkBlock [init_stmt; mkStmt s.skind] in From 782b21c4a65521e0104f789df853e4bf140669f1 Mon Sep 17 00:00:00 2001 From: Alexander Schlenga Date: Tue, 25 Jul 2023 21:31:18 +0200 Subject: [PATCH 257/327] Fix indentation --- src/util/terminationPreprocessing.ml | 90 ++++++++++++++-------------- 1 file changed, 45 insertions(+), 45 deletions(-) diff --git a/src/util/terminationPreprocessing.ml b/src/util/terminationPreprocessing.ml index 768dac0df9..74aca11824 100644 --- a/src/util/terminationPreprocessing.ml +++ b/src/util/terminationPreprocessing.ml @@ -18,50 +18,50 @@ let show_location_id l = string_of_int l.line ^ "_" ^ string_of_int l.column ^ "-file" ^ "_" ^ extract_file_name l.file class loopCounterVisitor lc lg (fd : fundec) = object(self) - inherit nopCilVisitor - - method! vstmt s = + inherit nopCilVisitor - let specialFunction name = - { svar = makeGlobalVar name (TFun(voidType, Some [("exp", intType, [])], false,[])); - smaxid = 0; - slocals = []; - sformals = []; - sbody = mkBlock []; - smaxstmtid = None; - sallstmts = []; - } in + method! vstmt s = - let min_int_exp = Const(CInt(Cilint.shift_left_cilint Cilint.mone_cilint ((bytesSizeOfInt IInt)*8-1), IInt, None)) in - - let f_bounded = Lval (var (specialFunction "__goblint_bounded").svar) in - - let action s = match s.skind with - | Loop (b, loc, eloc, _, _) -> - let name = "term"^show_location_id loc in - let typ = Cil.intType in - let v = (Cil.makeLocalVar fd name typ) in (*Not tested for incremental mode*) - let init_stmt = mkStmtOneInstr @@ Set (var v, min_int_exp, loc, eloc) in - let inc_stmt = mkStmtOneInstr @@ Set (var v, increm (Lval (var v)) 1, loc, eloc) in - let inc_stmt2 = mkStmtOneInstr @@ Set (var v, increm (Lval (var v)) 1, loc, eloc) in - let exit_stmt = mkStmtOneInstr @@ Call (None, f_bounded, [Lval (var v)], loc, locUnknown) in - (match b.bstmts with - | s :: ss -> (*duplicate increment statement here to fix inconsistencies in nested loops*) - b.bstmts <- exit_stmt :: inc_stmt :: s :: inc_stmt2 :: ss; - | ss -> - b.bstmts <- exit_stmt :: inc_stmt :: ss; - ); - lc := VarToStmt.add (v: varinfo) (s: stmt) !lc; - let nb = mkBlock [init_stmt; mkStmt s.skind] in - s.skind <- Block nb; - s - | Goto (sref, l) -> - let goto_jmp_stmt = sref.contents.skind in - let loc_stmt = get_stmtLoc goto_jmp_stmt in - if CilType.Location.compare l loc_stmt >= 0 (*is pos if first loc is greater -> below the second loc*) - then - lg := List.append !lg ([l] : location list); (*problem: the program might not terminate!*) - s - | _ -> s - in ChangeDoChildrenPost (s, action); - end \ No newline at end of file + let specialFunction name = + { svar = makeGlobalVar name (TFun(voidType, Some [("exp", intType, [])], false,[])); + smaxid = 0; + slocals = []; + sformals = []; + sbody = mkBlock []; + smaxstmtid = None; + sallstmts = []; + } in + + let min_int_exp = Const(CInt(Cilint.shift_left_cilint Cilint.mone_cilint ((bytesSizeOfInt IInt)*8-1), IInt, None)) in + + let f_bounded = Lval (var (specialFunction "__goblint_bounded").svar) in + + let action s = match s.skind with + | Loop (b, loc, eloc, _, _) -> + let name = "term"^show_location_id loc in + let typ = Cil.intType in + let v = (Cil.makeLocalVar fd name typ) in (*Not tested for incremental mode*) + let init_stmt = mkStmtOneInstr @@ Set (var v, min_int_exp, loc, eloc) in + let inc_stmt = mkStmtOneInstr @@ Set (var v, increm (Lval (var v)) 1, loc, eloc) in + let inc_stmt2 = mkStmtOneInstr @@ Set (var v, increm (Lval (var v)) 1, loc, eloc) in + let exit_stmt = mkStmtOneInstr @@ Call (None, f_bounded, [Lval (var v)], loc, locUnknown) in + (match b.bstmts with + | s :: ss -> (*duplicate increment statement here to fix inconsistencies in nested loops*) + b.bstmts <- exit_stmt :: inc_stmt :: s :: inc_stmt2 :: ss; + | ss -> + b.bstmts <- exit_stmt :: inc_stmt :: ss; + ); + lc := VarToStmt.add (v: varinfo) (s: stmt) !lc; + let nb = mkBlock [init_stmt; mkStmt s.skind] in + s.skind <- Block nb; + s + | Goto (sref, l) -> + let goto_jmp_stmt = sref.contents.skind in + let loc_stmt = get_stmtLoc goto_jmp_stmt in + if CilType.Location.compare l loc_stmt >= 0 (*is pos if first loc is greater -> below the second loc*) + then + lg := List.append !lg ([l] : location list); (*problem: the program might not terminate!*) + s + | _ -> s + in ChangeDoChildrenPost (s, action); +end From c53f0b84d29dc077d9eeddf354dd10acb572b826 Mon Sep 17 00:00:00 2001 From: Alexander Schlenga Date: Wed, 26 Jul 2023 14:38:32 +0200 Subject: [PATCH 258/327] Polish comments --- src/analyses/loopTermination.ml | 20 +++++++++----------- 1 file changed, 9 insertions(+), 11 deletions(-) diff --git a/src/analyses/loopTermination.ml b/src/analyses/loopTermination.ml index afd86fc483..89976b7627 100644 --- a/src/analyses/loopTermination.ml +++ b/src/analyses/loopTermination.ml @@ -4,20 +4,20 @@ open Analyses open GoblintCil open TerminationPreprocessing -(** Stores the result of the query if the program is single threaded or not - since finalize does not has ctx as an argument*) +(** Stores the result of the query whether the program is single threaded or not + since finalize does not have access to ctx. *) let single_thread : bool ref = ref false (** Contains all loop counter variables (varinfo) and maps them to their corresponding loop statement. *) let loop_counters : stmt VarToStmt.t ref = ref VarToStmt.empty -(** Contains the locations of the upjumping gotos *) +(** Contains the locations of the upjumping gotos. *) let upjumping_gotos : location list ref = ref [] let no_upjumping_gotos () = upjumping_gotos.contents = [] -(** Checks whether a variable can be bounded *) +(** Checks whether a variable can be bounded. *) let check_bounded ctx varinfo = let open IntDomain.IntDomTuple in let exp = Lval (Var varinfo, NoOffset) in @@ -35,7 +35,6 @@ module Statements = Lattice.Flat (CilType.Stmt) (Printable.DefaultNames) module Spec : Analyses.MCPSpec = struct - (** Provides some default implementations *) include Analyses.IdentitySpec let name () = "termination" @@ -52,8 +51,8 @@ struct let startstate _ = () let exitstate = startstate + (** Warnings for detected possible non-termination *) let finalize () = - (* Warning for detected possible non-termination *) (* Upjumping gotos *) if not (no_upjumping_gotos ()) then ( List.iter @@ -71,6 +70,8 @@ struct M.warn ~category:NonTerminating "The program might not terminate! (Multithreaded)\n" ) + (** Recognizes a call of [__goblint_bounded] to check the EvalInt of the + * respective loop counter variable at that position. *) let special ctx (lval : lval option) (f : varinfo) (arglist : exp list) = if !AnalysisState.postsolving then match f.vname, arglist with @@ -95,14 +96,13 @@ struct | _ -> () else () - (** Checks whether a new thread was spawned some time. We want to discard - * any knowledge about termination then (see query function) *) + (** Checks whether a new thread was spawned some time. We want to always + * assume non-termination then (see query function). *) let must_be_single_threaded_since_start ctx = let single_threaded = not (ctx.ask Queries.IsEverMultiThreaded) in single_thread := single_threaded; single_threaded - (** Provides information to Goblint *) let query ctx (type a) (q: a Queries.t): a Queries.result = match q with | Queries.MustTermLoop loop_statement -> @@ -124,7 +124,5 @@ struct end let () = - (* Register the preprocessing *) Cilfacade.register_preprocess_cil (Spec.name ()) (new loopCounterVisitor loop_counters upjumping_gotos); - (* Register this analysis within the master control program *) MCP.register_analysis (module Spec : MCPSpec) From c52cf476cf170a9b1374adf03ef31283e1565435 Mon Sep 17 00:00:00 2001 From: Alexander Schlenga Date: Wed, 26 Jul 2023 14:58:27 +0200 Subject: [PATCH 259/327] Remove runningGob.sh --- runningGob.sh | 31 ------------------------------- 1 file changed, 31 deletions(-) delete mode 100755 runningGob.sh diff --git a/runningGob.sh b/runningGob.sh deleted file mode 100755 index e70b34af7c..0000000000 --- a/runningGob.sh +++ /dev/null @@ -1,31 +0,0 @@ -#!/bin/bash -make -make install -clear - -# set options and file for apron execution -options_apron="--set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra --enable warn.debug" #note: preprocessing first needs to be added to apron -options_signs="--set "ana.activated[+]" signs --enable warn.debug" -options_term="--set "ana.activated[+]" termination --enable warn.debug --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra" - -cfile_loop30="tests/regression/74-loop_termination/30-goto-out-of-inner-loop-terminating.c" -cfile_loop26="tests/regression/74-loop_termination/26-enter-loop-goto-terminating.c" -cfile_loop28="tests/regression/74-loop_termination/28-do-while-continue-terminating.c" -cfile_loop7="tests/regression/74-loop_termination/07-nested-for-loop-terminating.c" -cfile_loop5="tests/regression/74-loop_termination/05-for-loop-terminating.c" -cfile_loop1="tests/regression/75-termination/02-simple-loop-nonterminating.c" -cfile_signs="tests/regression/99-tutorials/01-first.c" -cfile_goto="tests/incremental/02-cfg-comparison/01-added-return-stmt.c" - -# run analysis, write cil output to file and enable visualization via html -#./goblint $cfile_loops $options_apron --enable justcil > output.txt -#./goblint $cfile_loops $options_apron --html - -# run analysis, write cil output to file and enable visualization via html -./goblint $cfile_loop1 $options_term --enable justcil > output.txt -./goblint $cfile_loop1 $options_term --html - -# set up server to see visualizatino -python3 -m http.server --directory result 8082 -#./goblint --enable dbg.debug tests/regression/55-loop-unrolling/01-simple-cases.c --enable ana.int.interval --set "ana.activated[+]" signs --enable justcil > output.txt - From 867e6ca5e408a973a2c5150395132deb032b8d24 Mon Sep 17 00:00:00 2001 From: Alexander Schlenga Date: Wed, 26 Jul 2023 16:33:53 +0200 Subject: [PATCH 260/327] Restore indentation; remove unused include Printf NOTE: This commit makes the indendation of several files wrong again on purpose! --- src/cdomains/intDomain.mli | 10 +-- src/framework/analyses.ml | 2 + src/framework/constraints.ml | 12 ++-- src/framework/control.ml | 118 +++++++++++++++++------------------ src/util/cilCfg.ml | 5 +- src/witness/witness.ml | 44 ++++++------- 6 files changed, 95 insertions(+), 96 deletions(-) diff --git a/src/cdomains/intDomain.mli b/src/cdomains/intDomain.mli index c7b59e4c23..a853c8acca 100644 --- a/src/cdomains/intDomain.mli +++ b/src/cdomains/intDomain.mli @@ -232,7 +232,7 @@ sig val invariant: Cil.exp -> t -> Invariant.t end (** Interface of IntDomain implementations that do not take ikinds for arithmetic operations yet. - TODO: Should be ported to S in the future. *) + TODO: Should be ported to S in the future. *) module type S = sig @@ -412,10 +412,10 @@ module IntervalSetFunctor(Ints_t : IntOps.IntOps): SOverflow with type int_t = I module Interval32 :Y with (* type t = (IntOps.Int64Ops.t * IntOps.Int64Ops.t) option and *) type int_t = IntOps.Int64Ops.t module BigInt: -sig - include Printable.S with type t = Z.t (* TODO: why doesn't this have a more useful signature like IntOps.BigIntOps? *) - val cast_to: Cil.ikind -> Z.t -> Z.t -end + sig + include Printable.S with type t = Z.t (* TODO: why doesn't this have a more useful signature like IntOps.BigIntOps? *) + val cast_to: Cil.ikind -> Z.t -> Z.t + end module Interval : SOverflow with type int_t = IntOps.BigIntOps.t diff --git a/src/framework/analyses.ml b/src/framework/analyses.ml index 23b75a4097..dd57f40c70 100644 --- a/src/framework/analyses.ml +++ b/src/framework/analyses.ml @@ -42,6 +42,7 @@ struct let var_id = Node.show_id end + module VarF (LD: Printable.S) = struct type t = Node.t * LD.t [@@deriving eq, ord, hash] @@ -118,6 +119,7 @@ struct | x -> BatPrintf.fprintf f "%a" printXml x end + exception Deadcode (** [Dom (D)] produces D lifted where bottom means dead-code *) diff --git a/src/framework/constraints.ml b/src/framework/constraints.ml index 6883cc72d9..5e99720364 100644 --- a/src/framework/constraints.ml +++ b/src/framework/constraints.ml @@ -6,7 +6,6 @@ open GoblintCil open MyCFG open Analyses open GobConfig -include Printf module M = Messages @@ -1127,7 +1126,7 @@ struct | `Lifted2 d -> LH.replace l' x d (* | `Bot -> () *) (* Since Verify2 is broken and only checks existing keys, add it with local bottom value. - This works around some cases, where Verify2 would not detect a problem due to completely missing variable. *) + This works around some cases, where Verify2 would not detect a problem due to completely missing variable. *) | `Bot -> LH.replace l' x (S.D.bot ()) | `Top -> failwith "GlobConstrSolFromEqConstrSolBase.split_vars: local variable has top value" | `Lifted1 _ -> failwith "GlobConstrSolFromEqConstrSolBase.split_vars: local variable has global value" @@ -1457,7 +1456,6 @@ struct let event ctx e octx = S.event (conv ctx) e (conv octx) end - module LongjmpLifter (S: Spec): Spec = struct include S @@ -1920,10 +1918,10 @@ struct in PP.iter f h1; (* let k1 = Set.of_enum @@ PP.keys h1 in - let k2 = Set.of_enum @@ PP.keys h2 in - let o1 = Set.cardinal @@ Set.diff k1 k2 in - let o2 = Set.cardinal @@ Set.diff k2 k1 in - Printf.printf "locals: \tequal = %d\tleft = %d[%d]\tright = %d[%d]\tincomparable = %d\n" !eq !le o1 !gr o2 !uk *) + let k2 = Set.of_enum @@ PP.keys h2 in + let o1 = Set.cardinal @@ Set.diff k1 k2 in + let o2 = Set.cardinal @@ Set.diff k2 k1 in + Printf.printf "locals: \tequal = %d\tleft = %d[%d]\tright = %d[%d]\tincomparable = %d\n" !eq !le o1 !gr o2 !uk *) Printf.printf "locals: \tequal = %d\tleft = %d\tright = %d\tincomparable = %d\n" !eq !le !gr !uk let compare_locals_ctx h1 h2 = diff --git a/src/framework/control.ml b/src/framework/control.ml index b98ec20e8d..69cdf1bdac 100644 --- a/src/framework/control.ml +++ b/src/framework/control.ml @@ -20,25 +20,25 @@ let spec_module: (module Spec) Lazy.t = lazy ( (* apply functor F on module X if opt is true *) let lift opt (module F : S2S) (module X : Spec) = (module (val if opt then (module F (X)) else (module X) : Spec) : Spec) in let module S1 = (val - (module MCP.MCP2 : Spec) - |> lift true (module WidenContextLifterSide) (* option checked in functor *) - (* hashcons before witness to reduce duplicates, because witness re-uses contexts in domain and requires tag for PathSensitive3 *) - |> lift (get_bool "ana.opt.hashcons" || arg_enabled) (module HashconsContextLifter) - |> lift arg_enabled (module HashconsLifter) - |> lift arg_enabled (module WitnessConstraints.PathSensitive3) - |> lift (not arg_enabled) (module PathSensitive2) - |> lift (get_bool "ana.dead-code.branches") (module DeadBranchLifter) - |> lift true (module DeadCodeLifter) - |> lift (get_bool "dbg.slice.on") (module LevelSliceLifter) - |> lift (get_int "dbg.limit.widen" > 0) (module LimitLifter) - |> lift (get_bool "ana.opt.equal" && not (get_bool "ana.opt.hashcons")) (module OptEqual) - |> lift (get_bool "ana.opt.hashcons") (module HashconsLifter) - (* Widening tokens must be outside of hashcons, because widening token domain ignores token sets for identity, so hashcons doesn't allow adding tokens. - Also must be outside of deadcode, because deadcode splits (like mutex lock event) don't pass on tokens. *) - |> lift (get_bool "ana.widen.tokens") (module WideningTokens.Lifter) - |> lift true (module LongjmpLifter) - |> lift termination_enabled (module RecursionTermLifter) (* Always activate the recursion termination analysis, when the loop termination analysis is activated*) - ) in + (module MCP.MCP2 : Spec) + |> lift true (module WidenContextLifterSide) (* option checked in functor *) + (* hashcons before witness to reduce duplicates, because witness re-uses contexts in domain and requires tag for PathSensitive3 *) + |> lift (get_bool "ana.opt.hashcons" || arg_enabled) (module HashconsContextLifter) + |> lift arg_enabled (module HashconsLifter) + |> lift arg_enabled (module WitnessConstraints.PathSensitive3) + |> lift (not arg_enabled) (module PathSensitive2) + |> lift (get_bool "ana.dead-code.branches") (module DeadBranchLifter) + |> lift true (module DeadCodeLifter) + |> lift (get_bool "dbg.slice.on") (module LevelSliceLifter) + |> lift (get_int "dbg.limit.widen" > 0) (module LimitLifter) + |> lift (get_bool "ana.opt.equal" && not (get_bool "ana.opt.hashcons")) (module OptEqual) + |> lift (get_bool "ana.opt.hashcons") (module HashconsLifter) + (* Widening tokens must be outside of hashcons, because widening token domain ignores token sets for identity, so hashcons doesn't allow adding tokens. + Also must be outside of deadcode, because deadcode splits (like mutex lock event) don't pass on tokens. *) + |> lift (get_bool "ana.widen.tokens") (module WideningTokens.Lifter) + |> lift true (module LongjmpLifter) + |> lift termination_enabled (module RecursionTermLifter) (* Always activate the recursion termination analysis, when the loop termination analysis is activated*) + ) in GobConfig.building_spec := false; ControlSpecC.control_spec_c := (module S1.C); (module S1) @@ -303,10 +303,10 @@ struct | MyCFG.Assign (lval,exp) -> if M.tracing then M.trace "global_inits" "Assign %a = %a\n" d_lval lval d_exp exp; (match lval, exp with - | (Var v,o), (AddrOf (Var f,NoOffset)) - when v.vstorage <> Static && isFunctionType f.vtype -> - (try funs := Cilfacade.find_varinfo_fundec f :: !funs with Not_found -> ()) - | _ -> () + | (Var v,o), (AddrOf (Var f,NoOffset)) + when v.vstorage <> Static && isFunctionType f.vtype -> + (try funs := Cilfacade.find_varinfo_fundec f :: !funs with Not_found -> ()) + | _ -> () ); let res = Spec.assign {ctx with local = st} lval exp in (* Needed for privatizations (e.g. None) that do not side immediately *) @@ -530,9 +530,9 @@ struct GobSys.mkdir_or_exists save_run; GobConfig.write_file config; let module Meta = struct - type t = { command : string; version: string; timestamp : float; localtime : string } [@@deriving to_yojson] - let json = to_yojson { command = GobSys.command_line; version = Version.goblint; timestamp = Unix.time (); localtime = GobUnix.localtime () } - end + type t = { command : string; version: string; timestamp : float; localtime : string } [@@deriving to_yojson] + let json = to_yojson { command = GobSys.command_line; version = Version.goblint; timestamp = Unix.time (); localtime = GobUnix.localtime () } + end in (* Yojson.Safe.to_file meta Meta.json; *) Yojson.Safe.pretty_to_channel (Stdlib.open_out (Fpath.to_string meta)) Meta.json; (* the above is compact, this is pretty-printed *) @@ -584,10 +584,10 @@ struct in let print_and_calculate_uncalled = function | GFun (fn, loc) when is_bad_uncalled fn.svar loc-> - let cnt = Cilfacade.countLoc fn in - uncalled_dead := !uncalled_dead + cnt; - if get_bool "ana.dead-code.functions" then - M.warn ~loc:(CilLocation loc) ~category:Deadcode "Function '%a' is uncalled: %d LLoC" CilType.Fundec.pretty fn cnt (* CilLocation is fine because always printed from scratch *) + let cnt = Cilfacade.countLoc fn in + uncalled_dead := !uncalled_dead + cnt; + if get_bool "ana.dead-code.functions" then + M.warn ~loc:(CilLocation loc) ~category:Deadcode "Function '%a' is uncalled: %d LLoC" CilType.Fundec.pretty fn cnt (* CilLocation is fine because always printed from scratch *) | _ -> () in List.iter print_and_calculate_uncalled file.globals; @@ -619,35 +619,35 @@ struct NodeH.modify_opt node join by_node; ); by_loc, by_node - in - - let ask ?(node = MyCFG.dummy_node) loc = - let f (type a) (q : a Queries.t) : a = - match Hashtbl.find_option joined_by_loc loc with - | None -> Queries.Result.bot q - | Some local -> Query.ask_local_node gh node local q - in - ({ f } : Queries.ask) - in - - (* A node is dead when its abstract value is bottom in all contexts; - it holds that: bottom in all contexts iff. bottom in the join of all contexts. - Therefore, we just answer whether the (stored) join is bottom. *) - let must_be_dead node = - NodeH.find_option joined_by_node node - (* nodes that didn't make it into the result are definitely dead (hence for_all) *) - |> GobOption.for_all Spec.D.is_bot - in - - let must_be_uncalled fd = not @@ BatSet.Int.mem fd.svar.vid calledFuns in - - let skipped_statements from_node edge to_node = - CfgTools.CfgEdgeH.find_default skippedByEdge (from_node, edge, to_node) [] - in - - Transform.run_transformations file active_transformations - { ask ; must_be_dead ; must_be_uncalled ; - cfg_forward = Cfg.next ; cfg_backward = Cfg.prev ; skipped_statements }; + in + + let ask ?(node = MyCFG.dummy_node) loc = + let f (type a) (q : a Queries.t) : a = + match Hashtbl.find_option joined_by_loc loc with + | None -> Queries.Result.bot q + | Some local -> Query.ask_local_node gh node local q + in + ({ f } : Queries.ask) + in + + (* A node is dead when its abstract value is bottom in all contexts; + it holds that: bottom in all contexts iff. bottom in the join of all contexts. + Therefore, we just answer whether the (stored) join is bottom. *) + let must_be_dead node = + NodeH.find_option joined_by_node node + (* nodes that didn't make it into the result are definitely dead (hence for_all) *) + |> GobOption.for_all Spec.D.is_bot + in + + let must_be_uncalled fd = not @@ BatSet.Int.mem fd.svar.vid calledFuns in + + let skipped_statements from_node edge to_node = + CfgTools.CfgEdgeH.find_default skippedByEdge (from_node, edge, to_node) [] + in + + Transform.run_transformations file active_transformations + { ask ; must_be_dead ; must_be_uncalled ; + cfg_forward = Cfg.next ; cfg_backward = Cfg.prev ; skipped_statements }; ); lh, gh diff --git a/src/util/cilCfg.ml b/src/util/cilCfg.ml index 0d4d5f3a1e..0d1f06da01 100644 --- a/src/util/cilCfg.ml +++ b/src/util/cilCfg.ml @@ -42,7 +42,6 @@ let loopCount file = let createCFG (fileAST: file) = - (* The analyzer keeps values only for blocks. So if you want a value for every program point, each instruction *) (* needs to be in its own block. end_basic_blocks does that. *) (* After adding support for VLAs, there are new VarDecl instructions at the point where a variable was declared and *) @@ -59,7 +58,7 @@ let createCFG (fileAST: file) = * See https://github.com/goblint/cil/issues/31#issuecomment-824939793. *) let loops = loopCount fileAST in - + iterGlobals fileAST (fun glob -> match glob with | GFun(fd,_) -> @@ -70,5 +69,5 @@ let createCFG (fileAST: file) = | _ -> () ); - if get_bool "dbg.run_cil_check" then assert (Check.checkFile [] fileAST); + if get_bool "dbg.run_cil_check" then assert (Check.checkFile [] fileAST); Cilfacade.do_preprocess fileAST diff --git a/src/witness/witness.ml b/src/witness/witness.ml index 94ffea0a0a..ae6b80b3cb 100644 --- a/src/witness/witness.ml +++ b/src/witness/witness.ml @@ -23,7 +23,7 @@ let write_file filename (module Task:Task) (module TaskResult:WitnessTaskResult) let module IsInteresting = struct (* type node = N.t - type edge = TaskResult.Arg.Edge.t *) + type edge = TaskResult.Arg.Edge.t *) let minwitness = get_bool "witness.minimize" let is_interesting_real from_node edge to_node = (* TODO: don't duplicate this logic with write_node, write_edge *) @@ -59,11 +59,11 @@ let write_file filename (module Task:Task) (module TaskResult:WitnessTaskResult) let module GML = XmlGraphMlWriter in let module GML = (val match get_string "witness.id" with - | "node" -> - (module ArgNodeGraphMlWriter (N) (GML) : GraphMlWriter with type node = N.t) - | "enumerate" -> - (module EnumerateNodeGraphMlWriter (N) (GML)) - | _ -> failwith "witness.id: illegal value" + | "node" -> + (module ArgNodeGraphMlWriter (N) (GML) : GraphMlWriter with type node = N.t) + | "enumerate" -> + (module EnumerateNodeGraphMlWriter (N) (GML)) + | _ -> failwith "witness.id: illegal value" ) in let module GML = DeDupGraphMlWriter (N) (GML) in @@ -107,16 +107,16 @@ let write_file filename (module Task:Task) (module TaskResult:WitnessTaskResult) GML.write_key g "edge" "goblintLine" "string" None; (* TODO: remove *) (* GML.write_key g "edge" "enterFunction2" "string" None; - GML.write_key g "edge" "returnFromFunction2" "string" None; *) + GML.write_key g "edge" "returnFromFunction2" "string" None; *) GML.start_graph g; GML.write_metadata g "witness-type" ( - match TaskResult.result with - | Result.True -> "correctness_witness" - | Result.False _ -> "violation_witness" - | Result.Unknown -> "unknown_witness" - ); + match TaskResult.result with + | Result.True -> "correctness_witness" + | Result.False _ -> "violation_witness" + | Result.Unknown -> "unknown_witness" + ); GML.write_metadata g "sourcecodelang" "C"; GML.write_metadata g "producer" (Printf.sprintf "Goblint (%s)" Version.goblint); GML.write_metadata g "specification" (Svcomp.Specification.to_string Task.specification); @@ -141,7 +141,7 @@ let write_file filename (module Task:Task) (module TaskResult:WitnessTaskResult) | Statement _, `Lifted i -> let i = InvariantCil.exp_replace_original_name i in [("invariant", CilType.Exp.show i); - ("invariant.scope", (Node.find_fundec cfgnode).svar.vname)] + ("invariant.scope", (Node.find_fundec cfgnode).svar.vname)] | _ -> (* ignore entry and return invariants, variables of wrong scopes *) (* TODO: don't? fix scopes? *) @@ -150,10 +150,10 @@ let write_file filename (module Task:Task) (module TaskResult:WitnessTaskResult) [] end; (* begin match cfgnode with - | Statement s -> + | Statement s -> [("sourcecode", GobPretty.sprint Basetype.CilStmt.pretty s)] (* TODO: sourcecode not official? especially on node? *) - | _ -> [] - end; *) + | _ -> [] + end; *) (* violation actually only allowed in violation witness *) (* maybe should appear on from_node of entry edge instead *) begin if TaskResult.is_violation node then @@ -170,7 +170,7 @@ let write_file filename (module Task:Task) (module TaskResult:WitnessTaskResult) | Statement stmt -> Printf.sprintf "s%d" stmt.sid | Function f -> Printf.sprintf "ret%d%s" f.vid f.vname | FunctionEntry f -> Printf.sprintf "fun%d%s" f.vid f.vname - )] *) + )] *) (* [("goblintNode", N.to_string node)] *) ]) in @@ -213,9 +213,9 @@ let write_file filename (module Task:Task) (module TaskResult:WitnessTaskResult) (* enter and return on other side of nodes, more correct loc (startline) but had some scope problem? *) (* | MyARG.CFGEdge (Entry f) -> - [("enterFunction2", f.svar.vname)] - | MyARG.CFGEdge (Ret (_, f)) -> - [("returnFromFunction2", f.svar.vname)] *) + [("enterFunction2", f.svar.vname)] + | MyARG.CFGEdge (Ret (_, f)) -> + [("returnFromFunction2", f.svar.vname)] *) | _ -> [] end; [("goblintEdge", Arg.Edge.to_string edge)] @@ -394,12 +394,12 @@ struct struct let path = observer_path end - ) + ) in MCP.register_analysis (module Spec); (* TODO: don't modify JSON but have ref vars for these instead *) (* GobConfig.set_list "ana.activated" (Json.Build.string (Spec.name ()) :: GobConfig.get_list "ana.activated"); - GobConfig.set_list "ana.path_sens" (Json.Build.string (Spec.name ()) :: GobConfig.get_list "ana.path_sens"); *) + GobConfig.set_list "ana.path_sens" (Json.Build.string (Spec.name ()) :: GobConfig.get_list "ana.path_sens"); *) (* TODO: don't append to end; currently done to get observer order to be nice *) GobConfig.set_list "ana.activated" (GobConfig.get_list "ana.activated" @ [`String (Spec.name ())]); GobConfig.set_list "ana.path_sens" (GobConfig.get_list "ana.path_sens" @ [`String (Spec.name ())]); From 0f94aaa98f2b463963f113a17e1a5e1fdf208ff0 Mon Sep 17 00:00:00 2001 From: Alexander Schlenga Date: Wed, 26 Jul 2023 16:41:58 +0200 Subject: [PATCH 261/327] More indentation restoring --- src/util/cilCfg.ml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/util/cilCfg.ml b/src/util/cilCfg.ml index 0d1f06da01..72143e97d7 100644 --- a/src/util/cilCfg.ml +++ b/src/util/cilCfg.ml @@ -68,6 +68,6 @@ let createCFG (fileAST: file) = computeCFGInfo fd true | _ -> () ); - if get_bool "dbg.run_cil_check" then assert (Check.checkFile [] fileAST); + Cilfacade.do_preprocess fileAST From f4fd0c22d3bf65e16bfbfcb15d6063bbd5ed0af3 Mon Sep 17 00:00:00 2001 From: Alexander Schlenga Date: Wed, 26 Jul 2023 16:48:30 +0200 Subject: [PATCH 262/327] Fix a typo --- src/framework/analysisState.ml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/framework/analysisState.ml b/src/framework/analysisState.ml index c2d977af9c..913fe88a4e 100644 --- a/src/framework/analysisState.ml +++ b/src/framework/analysisState.ml @@ -7,7 +7,7 @@ let should_warn = ref false (** Whether signed overflow or underflow happened *) let svcomp_may_overflow = ref false -(** Whether the termination analysis detectes the program as non-terminating**) +(** Whether the termination analysis detects the program as non-terminating *) let svcomp_may_not_terminate = ref false (** A hack to see if we are currently doing global inits *) From 1be8c9c94ae7c4c83064b858cb8147ea674fead8 Mon Sep 17 00:00:00 2001 From: Alexander Schlenga Date: Wed, 26 Jul 2023 17:58:08 +0200 Subject: [PATCH 263/327] Remove goto stuff from loopTermination analysis --- src/analyses/loopTermination.ml | 21 +-------------------- src/util/terminationPreprocessing.ml | 4 +++- 2 files changed, 4 insertions(+), 21 deletions(-) diff --git a/src/analyses/loopTermination.ml b/src/analyses/loopTermination.ml index 89976b7627..563d6574bb 100644 --- a/src/analyses/loopTermination.ml +++ b/src/analyses/loopTermination.ml @@ -11,12 +11,6 @@ let single_thread : bool ref = ref false (** Contains all loop counter variables (varinfo) and maps them to their corresponding loop statement. *) let loop_counters : stmt VarToStmt.t ref = ref VarToStmt.empty -(** Contains the locations of the upjumping gotos. *) -let upjumping_gotos : location list ref = ref [] - -let no_upjumping_gotos () = - upjumping_gotos.contents = [] - (** Checks whether a variable can be bounded. *) let check_bounded ctx varinfo = let open IntDomain.IntDomTuple in @@ -53,18 +47,6 @@ struct (** Warnings for detected possible non-termination *) let finalize () = - (* Upjumping gotos *) - if not (no_upjumping_gotos ()) then ( - List.iter - (fun x -> - let msgs = - [(Pretty.dprintf - "The program might not terminate! (Upjumping Goto)", - Some (M.Location.CilLocation x) - );] in - M.msg_group Warning ~category:NonTerminating "Possibly non terminating loops" msgs) - (!upjumping_gotos) - ); (* Multithreaded *) if not (!single_thread) then ( M.warn ~category:NonTerminating "The program might not terminate! (Multithreaded)\n" @@ -117,12 +99,11 @@ struct * evaluation, the correct value of single_thread can not be guaranteed! * Therefore, we use a let-in clause here. *) always_single_threaded - && no_upjumping_gotos () && G.for_all (fun _ term_info -> term_info) (ctx.global ()) | _ -> Queries.Result.top q end let () = - Cilfacade.register_preprocess_cil (Spec.name ()) (new loopCounterVisitor loop_counters upjumping_gotos); + Cilfacade.register_preprocess_cil (Spec.name ()) (new loopCounterVisitor loop_counters); MCP.register_analysis (module Spec : MCPSpec) diff --git a/src/util/terminationPreprocessing.ml b/src/util/terminationPreprocessing.ml index 74aca11824..f5e520104b 100644 --- a/src/util/terminationPreprocessing.ml +++ b/src/util/terminationPreprocessing.ml @@ -17,7 +17,7 @@ let extract_file_name s = (*There still may be a need to filt let show_location_id l = string_of_int l.line ^ "_" ^ string_of_int l.column ^ "-file" ^ "_" ^ extract_file_name l.file -class loopCounterVisitor lc lg (fd : fundec) = object(self) +class loopCounterVisitor lc (fd : fundec) = object(self) inherit nopCilVisitor method! vstmt s = @@ -55,6 +55,7 @@ class loopCounterVisitor lc lg (fd : fundec) = object(self) let nb = mkBlock [init_stmt; mkStmt s.skind] in s.skind <- Block nb; s + (* | Goto (sref, l) -> let goto_jmp_stmt = sref.contents.skind in let loc_stmt = get_stmtLoc goto_jmp_stmt in @@ -62,6 +63,7 @@ class loopCounterVisitor lc lg (fd : fundec) = object(self) then lg := List.append !lg ([l] : location list); (*problem: the program might not terminate!*) s + *) | _ -> s in ChangeDoChildrenPost (s, action); end From cf594b66a11bcef2fe12892fb54c1ae385c9d07d Mon Sep 17 00:00:00 2001 From: Alexander Schlenga Date: Wed, 26 Jul 2023 18:03:56 +0200 Subject: [PATCH 264/327] Add goto-fundec list in cilfacade.ml --- src/util/cilfacade.ml | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/util/cilfacade.ml b/src/util/cilfacade.ml index 2a81444e41..284c01a76c 100644 --- a/src/util/cilfacade.ml +++ b/src/util/cilfacade.ml @@ -606,3 +606,7 @@ let add_function_declarations (file: Cil.file): unit = let fun_decls = List.filter_map declaration_from_GFun functions in let globals = upto_last_type @ fun_decls @ non_types @ functions in file.globals <- globals + +(** Contains the locations of the upjumping gotos and the respective functions + * they are being called in. *) +let upjumping_gotos : (location * fundec) list ref = ref [] From eabf6b7888911d862d8ab745903a9e8bb4f7ae14 Mon Sep 17 00:00:00 2001 From: Isidor Zweckstetter Date: Wed, 26 Jul 2023 19:05:17 +0200 Subject: [PATCH 265/327] add gotos with their respective function to new list in Cilfacade --- src/util/terminationPreprocessing.ml | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/src/util/terminationPreprocessing.ml b/src/util/terminationPreprocessing.ml index f5e520104b..32a9468233 100644 --- a/src/util/terminationPreprocessing.ml +++ b/src/util/terminationPreprocessing.ml @@ -2,8 +2,6 @@ open GoblintCil module VarToStmt = Map.Make(CilType.Varinfo) (* maps varinfos (= loop counter variable) to the statement of the corresponding loop*) - - let extract_file_name s = (*There still may be a need to filter more chars*) let ls = String.split_on_char '/' s in (*Assuming '/' as path seperator*) let ls = List.rev ls in @@ -55,15 +53,13 @@ class loopCounterVisitor lc (fd : fundec) = object(self) let nb = mkBlock [init_stmt; mkStmt s.skind] in s.skind <- Block nb; s - (* | Goto (sref, l) -> let goto_jmp_stmt = sref.contents.skind in - let loc_stmt = get_stmtLoc goto_jmp_stmt in + let loc_stmt = Cil.get_stmtLoc goto_jmp_stmt in if CilType.Location.compare l loc_stmt >= 0 (*is pos if first loc is greater -> below the second loc*) then - lg := List.append !lg ([l] : location list); (*problem: the program might not terminate!*) + Cilfacade.upjumping_gotos := List.append !Cilfacade.upjumping_gotos ([(l, fd)] : (location * fundec) list); (*problem: the program might not terminate!*) s - *) | _ -> s in ChangeDoChildrenPost (s, action); end From 19addab0d94f75486291e2bef9b9dff7e644a1a8 Mon Sep 17 00:00:00 2001 From: Johanna Schinabeck Date: Wed, 26 Jul 2023 19:14:06 +0200 Subject: [PATCH 266/327] added code for control to only print upjumping goto message when goto is not in dead code function --- src/framework/control.ml | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/src/framework/control.ml b/src/framework/control.ml index 69cdf1bdac..dfb0859438 100644 --- a/src/framework/control.ml +++ b/src/framework/control.ml @@ -136,6 +136,25 @@ struct try StringMap.find fn (StringMap.find file !live_lines) with Not_found -> BatISet.empty in + (*check if we have upjumping gotos*) + List.iter + (fun x -> + let ((l: location), (fd: fundec)) = x in (*unpack tuple for later use*) + let fname = fd.svar.vname in + StringMap.iter + (fun fi _ -> + let fundec_live = live fi fname in + if (not (BatISet.is_empty fundec_live)) then ( + let msgs = + [(Pretty.dprintf + "The program might not terminate! (Upjumping Goto)", + Some (M.Location.CilLocation l) + );] in + M.msg_group Warning ~category:NonTerminating "Possibly non terminating loops" msgs); + ) + (!dead_lines)) + (!Cilfacade.upjumping_gotos); + dead_lines := StringMap.mapi (fun fi -> StringMap.mapi (fun fu ded -> BatISet.diff ded (live fi fu))) !dead_lines; dead_lines := StringMap.map (StringMap.filter (fun _ x -> not (BatISet.is_empty x))) !dead_lines; dead_lines := StringMap.filter (fun _ x -> not (StringMap.is_empty x)) !dead_lines; From 72e2e22b62f026693c404b6edf3b41930fef7e18 Mon Sep 17 00:00:00 2001 From: Johanna Schinabeck Date: Wed, 26 Jul 2023 19:29:17 +0200 Subject: [PATCH 267/327] now everything should work :), now iterating over live_lines --- src/framework/control.ml | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/src/framework/control.ml b/src/framework/control.ml index dfb0859438..b2125ef9a7 100644 --- a/src/framework/control.ml +++ b/src/framework/control.ml @@ -139,12 +139,15 @@ struct (*check if we have upjumping gotos*) List.iter (fun x -> + print_endline @@ "halloooo"; let ((l: location), (fd: fundec)) = x in (*unpack tuple for later use*) - let fname = fd.svar.vname in + let fname = fd.svar.vname in + print_endline @@ "halloooo2"; StringMap.iter (fun fi _ -> let fundec_live = live fi fname in - if (not (BatISet.is_empty fundec_live)) then ( + print_endline @@ "halloooo3"; + if ( not (BatISet.is_empty fundec_live)) then ( let msgs = [(Pretty.dprintf "The program might not terminate! (Upjumping Goto)", @@ -152,9 +155,8 @@ struct );] in M.msg_group Warning ~category:NonTerminating "Possibly non terminating loops" msgs); ) - (!dead_lines)) + (!live_lines)) (!Cilfacade.upjumping_gotos); - dead_lines := StringMap.mapi (fun fi -> StringMap.mapi (fun fu ded -> BatISet.diff ded (live fi fu))) !dead_lines; dead_lines := StringMap.map (StringMap.filter (fun _ x -> not (BatISet.is_empty x))) !dead_lines; dead_lines := StringMap.filter (fun _ x -> not (StringMap.is_empty x)) !dead_lines; From 6090c62b650696aa9ddb915cd4ab6da494e5e23b Mon Sep 17 00:00:00 2001 From: Johanna Schinabeck Date: Wed, 26 Jul 2023 19:31:05 +0200 Subject: [PATCH 268/327] now without prints :))) --- src/framework/control.ml | 3 --- 1 file changed, 3 deletions(-) diff --git a/src/framework/control.ml b/src/framework/control.ml index b2125ef9a7..8185dc6053 100644 --- a/src/framework/control.ml +++ b/src/framework/control.ml @@ -139,14 +139,11 @@ struct (*check if we have upjumping gotos*) List.iter (fun x -> - print_endline @@ "halloooo"; let ((l: location), (fd: fundec)) = x in (*unpack tuple for later use*) let fname = fd.svar.vname in - print_endline @@ "halloooo2"; StringMap.iter (fun fi _ -> let fundec_live = live fi fname in - print_endline @@ "halloooo3"; if ( not (BatISet.is_empty fundec_live)) then ( let msgs = [(Pretty.dprintf From e96433b1ab65970da5aa1d4388d88676c0aedef5 Mon Sep 17 00:00:00 2001 From: Thomas Lagemann Date: Wed, 26 Jul 2023 20:52:56 +0200 Subject: [PATCH 269/327] Handle skipped (NON-)TERM-Tests other than TODO --- scripts/update_suite.rb | 2 +- .../75-termination/09-complex-for-loop-terminating.c | 3 ++- tests/regression/75-termination/10-complex-loop-terminating.c | 3 ++- .../75-termination/15-complex-loop-combination-terminating.c | 3 ++- .../regression/75-termination/25-leave-loop-goto-terminating.c | 2 +- 5 files changed, 8 insertions(+), 5 deletions(-) diff --git a/scripts/update_suite.rb b/scripts/update_suite.rb index 60a7ec06be..313b6b75f9 100755 --- a/scripts/update_suite.rb +++ b/scripts/update_suite.rb @@ -331,7 +331,7 @@ def parse_tests (lines) end end case lines[0] - when /TODO|SKIP/ + when /TODO/ case lines[0] when /NONTERM/ tests[-1] = "nonterm" diff --git a/tests/regression/75-termination/09-complex-for-loop-terminating.c b/tests/regression/75-termination/09-complex-for-loop-terminating.c index 264c08f6ed..fb2acaf569 100644 --- a/tests/regression/75-termination/09-complex-for-loop-terminating.c +++ b/tests/regression/75-termination/09-complex-for-loop-terminating.c @@ -1,4 +1,5 @@ -// SKIP TERM PARAM: --set "ana.activated[+]" termination --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra --set sem.int.signed_overflow assume_none +// SKIP TODO TERM PARAM: --set "ana.activated[+]" termination --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra --set sem.int.signed_overflow assume_none +// Apron is not precise enough for some nested loops #include int main() diff --git a/tests/regression/75-termination/10-complex-loop-terminating.c b/tests/regression/75-termination/10-complex-loop-terminating.c index 90317d5209..738fe78683 100644 --- a/tests/regression/75-termination/10-complex-loop-terminating.c +++ b/tests/regression/75-termination/10-complex-loop-terminating.c @@ -1,4 +1,5 @@ -// SKIP TERM PARAM: --set "ana.activated[+]" termination --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra --set sem.int.signed_overflow assume_none +// SKIP TODO TERM PARAM: --set "ana.activated[+]" termination --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra --set sem.int.signed_overflow assume_none +// Apron is not precise enough for some nested loops #include int main() diff --git a/tests/regression/75-termination/15-complex-loop-combination-terminating.c b/tests/regression/75-termination/15-complex-loop-combination-terminating.c index c2ab718200..1365611410 100644 --- a/tests/regression/75-termination/15-complex-loop-combination-terminating.c +++ b/tests/regression/75-termination/15-complex-loop-combination-terminating.c @@ -1,4 +1,5 @@ -// SKIP TERM PARAM: --set "ana.activated[+]" termination --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra --set sem.int.signed_overflow assume_none +// SKIP TODO TERM PARAM: --set "ana.activated[+]" termination --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra --set sem.int.signed_overflow assume_none +// Apron is not precise enough for some nested loops #include int main() diff --git a/tests/regression/75-termination/25-leave-loop-goto-terminating.c b/tests/regression/75-termination/25-leave-loop-goto-terminating.c index b882759bff..61c8b8f58d 100644 --- a/tests/regression/75-termination/25-leave-loop-goto-terminating.c +++ b/tests/regression/75-termination/25-leave-loop-goto-terminating.c @@ -1,4 +1,4 @@ -// SKIP TODO TERM PARAM: --set "ana.activated[+]" termination --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra +// SKIP TERM PARAM: --set "ana.activated[+]" termination --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra #include int main() From e1f8319a7e72aab0e4ec57a11a3998105448fc4d Mon Sep 17 00:00:00 2001 From: Michael Schwarz Date: Wed, 30 Aug 2023 17:54:10 +0200 Subject: [PATCH 270/327] Set sv-comp flag for upjumping gotos --- src/framework/control.ml | 1 + 1 file changed, 1 insertion(+) diff --git a/src/framework/control.ml b/src/framework/control.ml index 8185dc6053..32e0a8c038 100644 --- a/src/framework/control.ml +++ b/src/framework/control.ml @@ -145,6 +145,7 @@ struct (fun fi _ -> let fundec_live = live fi fname in if ( not (BatISet.is_empty fundec_live)) then ( + AnalysisState.svcomp_may_not_terminate := true; let msgs = [(Pretty.dprintf "The program might not terminate! (Upjumping Goto)", From b832f31cb647ac0f632bbc335a89817564b140dd Mon Sep 17 00:00:00 2001 From: Julian Erhard Date: Fri, 1 Sep 2023 15:42:17 +0200 Subject: [PATCH 271/327] Increase indentation in switch-case in update_suite.rb. --- scripts/update_suite.rb | 42 ++++++++++++++++++++--------------------- 1 file changed, 21 insertions(+), 21 deletions(-) diff --git a/scripts/update_suite.rb b/scripts/update_suite.rb index 313b6b75f9..e91b1d116a 100755 --- a/scripts/update_suite.rb +++ b/scripts/update_suite.rb @@ -151,27 +151,27 @@ def collect_warnings ranking = ["other", "warn", "goto", "fundec", "loop", "term", "nonterm", "race", "norace", "deadlock", "nodeadlock", "success", "fail", "unknown"] thiswarn = case obj - when /\(conf\. \d+\)/ then "race" - when /Deadlock/ then "deadlock" - when /lock (before|after):/ then "deadlock" - when /Assertion .* will fail/ then "fail" - when /Assertion .* will succeed/ then "success" - when /Assertion .* is unknown/ then "unknown" - when /invariant confirmed/ then "success" - when /invariant unconfirmed/ then "unknown" - when /invariant refuted/ then "fail" - when /^\[Warning\]/ then "warn" - when /^\[Error\]/ then "warn" - when /^\[Info\]/ then "warn" - when /^\[Success\]/ then "success" - when /(Upjumping Goto)/ then "goto" - when /(Fundec \w+ is contained in a call graph cycle)/ then "fundec" - when /(Loop analysis)/ then "loop" - when /\[Debug\]/ then next # debug "warnings" shouldn't count as other warnings (against NOWARN) - when /^ on line \d+ $/ then next # dead line warnings shouldn't count (used for unreachability with NOWARN) - when /^ on lines \d+..\d+ $/ then next # dead line warnings shouldn't count (used for unreachability with NOWARN) - else "other" - end + when /\(conf\. \d+\)/ then "race" + when /Deadlock/ then "deadlock" + when /lock (before|after):/ then "deadlock" + when /Assertion .* will fail/ then "fail" + when /Assertion .* will succeed/ then "success" + when /Assertion .* is unknown/ then "unknown" + when /invariant confirmed/ then "success" + when /invariant unconfirmed/ then "unknown" + when /invariant refuted/ then "fail" + when /^\[Warning\]/ then "warn" + when /^\[Error\]/ then "warn" + when /^\[Info\]/ then "warn" + when /^\[Success\]/ then "success" + when /(Upjumping Goto)/ then "goto" + when /(Fundec \w+ is contained in a call graph cycle)/ then "fundec" + when /(Loop analysis)/ then "loop" + when /\[Debug\]/ then next # debug "warnings" shouldn't count as other warnings (against NOWARN) + when /^ on line \d+ $/ then next # dead line warnings shouldn't count (used for unreachability with NOWARN) + when /^ on lines \d+..\d+ $/ then next # dead line warnings shouldn't count (used for unreachability with NOWARN) + else "other" + end oldwarn = warnings[i] if oldwarn.nil? then warnings[i] = thiswarn From a6e4af4083db6751e35f996d374b6fa5fa229016 Mon Sep 17 00:00:00 2001 From: Julian Erhard Date: Fri, 1 Sep 2023 15:56:15 +0200 Subject: [PATCH 272/327] Rename must_be_single_threaded_since_start to must_always_be_single_threaded --- src/analyses/loopTermination.ml | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/analyses/loopTermination.ml b/src/analyses/loopTermination.ml index 563d6574bb..bfc600f830 100644 --- a/src/analyses/loopTermination.ml +++ b/src/analyses/loopTermination.ml @@ -78,9 +78,9 @@ struct | _ -> () else () - (** Checks whether a new thread was spawned some time. We want to always - * assume non-termination then (see query function). *) - let must_be_single_threaded_since_start ctx = + (* Checks whether the program always remains single-threaded. + If the program does not remain single-threaded, we assume non-termination (see query function). *) + let must_always_be_single_threaded ctx = let single_threaded = not (ctx.ask Queries.IsEverMultiThreaded) in single_thread := single_threaded; single_threaded @@ -88,12 +88,12 @@ struct let query ctx (type a) (q: a Queries.t): a Queries.result = match q with | Queries.MustTermLoop loop_statement -> - must_be_single_threaded_since_start ctx + must_always_be_single_threaded ctx && (match G.find_opt (`Lifted loop_statement) (ctx.global ()) with Some b -> b | None -> false) | Queries.MustTermAllLoops -> - let always_single_threaded = must_be_single_threaded_since_start ctx in + let always_single_threaded = must_always_be_single_threaded ctx in (* Must be the first to be evaluated! This has the side effect that * single_thread is set. In case of another order and due to lazy * evaluation, the correct value of single_thread can not be guaranteed! From 44b44928668346c722ca23fb448c6da73f471276 Mon Sep 17 00:00:00 2001 From: Michael Schwarz Date: Thu, 12 Oct 2023 15:37:25 +0200 Subject: [PATCH 273/327] Issue non-termination warning for `longjmp` calls --- src/framework/constraints.ml | 9 +++++++++ tests/regression/78-termination/49-longjmp.c | 11 +++++++++++ 2 files changed, 20 insertions(+) create mode 100644 tests/regression/78-termination/49-longjmp.c diff --git a/src/framework/constraints.ml b/src/framework/constraints.ml index 924794b9ce..cf439f2c45 100644 --- a/src/framework/constraints.ml +++ b/src/framework/constraints.ml @@ -1684,6 +1684,15 @@ struct ) in List.iter handle_path (S.paths_as_set conv_ctx); + if !AnalysisState.should_warn && List.mem "termination" @@ get_string_list "ana.activated" then ( + AnalysisState.svcomp_may_not_terminate := true; + let msgs = + [(Pretty.dprintf + "The program might not terminate! (Longjmp)", + None + );] in + M.msg_group Warning ~category:NonTerminating "Possibly non terminating loops" msgs + ); S.D.bot () | _ -> S.special conv_ctx lv f args let threadenter ctx = S.threadenter (conv ctx) diff --git a/tests/regression/78-termination/49-longjmp.c b/tests/regression/78-termination/49-longjmp.c new file mode 100644 index 0000000000..be13cb286c --- /dev/null +++ b/tests/regression/78-termination/49-longjmp.c @@ -0,0 +1,11 @@ +// SKIP NONTERM PARAM: --set "ana.activated[+]" termination --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra +#include +jmp_buf buf; +int main() +{ + if(setjmp(buf)) { + + } + + longjmp(buf, 1); +} From ea38918e9e3247c622d8d1acf754f7ea021e6f9c Mon Sep 17 00:00:00 2001 From: Michael Schwarz Date: Thu, 12 Oct 2023 15:42:42 +0200 Subject: [PATCH 274/327] Include termination tests into `coverage` and `unlocked` --- .github/workflows/coverage.yml | 3 +++ .github/workflows/unlocked.yml | 3 +++ 2 files changed, 6 insertions(+) diff --git a/.github/workflows/coverage.yml b/.github/workflows/coverage.yml index 5635ebbeea..0208af7c7a 100644 --- a/.github/workflows/coverage.yml +++ b/.github/workflows/coverage.yml @@ -65,6 +65,9 @@ jobs: - name: Test apron regression (Mukherjee et. al SAS '17 paper') # skipped by default but CI has apron, so explicitly test group (which ignores skipping -- it's now a feature!) run: ruby scripts/update_suite.rb group apron-mukherjee -s + - name: Test apron termination regression # skipped by default but CI has apron, so explicitly test group (which ignores skipping -- it's now a feature!) + run: ruby scripts/update_suite.rb group termination -s + - name: Test regression cram run: opam exec -- dune runtest tests/regression diff --git a/.github/workflows/unlocked.yml b/.github/workflows/unlocked.yml index 6c23c7cdd4..22e1417ea4 100644 --- a/.github/workflows/unlocked.yml +++ b/.github/workflows/unlocked.yml @@ -92,6 +92,9 @@ jobs: if: ${{ matrix.apron }} run: ruby scripts/update_suite.rb group apron-mukherjee -s + - name: Test apron termination regression # skipped by default but CI has apron, so explicitly test group (which ignores skipping -- it's now a feature!) + run: ruby scripts/update_suite.rb group termination -s + - name: Test regression cram run: opam exec -- dune runtest tests/regression From e28495363a932e40d4d0ec519e74e804aaaa55da Mon Sep 17 00:00:00 2001 From: Michael Schwarz Date: Thu, 12 Oct 2023 16:39:27 +0200 Subject: [PATCH 275/327] Simplify global invariant Co-authored-by: Simmo Saan --- src/framework/analyses.ml | 16 +++++++++ src/framework/constraints.ml | 70 ++++++++++++++++-------------------- 2 files changed, 47 insertions(+), 39 deletions(-) diff --git a/src/framework/analyses.ml b/src/framework/analyses.ml index bb2170509d..3426f98675 100644 --- a/src/framework/analyses.ml +++ b/src/framework/analyses.ml @@ -88,6 +88,22 @@ struct | `Right _ -> true end +module GVarFC (V:SpecSysVar) (C:Printable.S) = +struct + include Printable.Either (V) (Printable.Prod (CilType.Fundec) (C)) + let name () = "FromSpec" + let spec x = `Left x + let call (x, c) = `Right (x, c) + + (* from Basetype.Variables *) + let var_id = show + let node _ = MyCFG.Function Cil.dummyFunDec + let pretty_trace = pretty + let is_write_only = function + | `Left x -> V.is_write_only x + | `Right _ -> true +end + module GVarG (G: Lattice.S) (C: Printable.S) = struct module CSet = diff --git a/src/framework/constraints.ml b/src/framework/constraints.ml index cf439f2c45..038068ea0d 100644 --- a/src/framework/constraints.ml +++ b/src/framework/constraints.ml @@ -1723,36 +1723,35 @@ module RecursionTermLifter (S: Spec) struct include S - (* contains all the callee fundecs*) - module V = GVarF(S.V) + (* contains all the callee fundecs and contexts *) + module V = GVarFC(S.V)(S.C) - (* Tuple containing the fundec and context of the caller *) - module CallGraphTuple = Printable.Prod (CilType.Fundec) (S.C) + (* Tuple containing the fundec and context of a caller *) + module Call = Printable.Prod (CilType.Fundec) (S.C) (* Set containing multiple caller tuples *) - module CallGraphSet = SetDomain.Make (CallGraphTuple) - - (* Mapping from the callee context to the set of all caller tuples*) - module CallGraphMap = MapDomain.MapBot (S.C) (CallGraphSet) + module CallerSet = SetDomain.Make (Call) module G = struct - include Lattice.Lift2 (G) (CallGraphMap) (Printable.DefaultNames) + include Lattice.Lift2 (G) (CallerSet) (Printable.DefaultNames) let spec = function | `Bot -> G.bot () | `Lifted1 x -> x | _ -> failwith "RecursionTermLifter.spec" - let callGraph = function - | `Bot -> CallGraphMap.bot () + + let callers = function + | `Bot -> CallerSet.bot () | `Lifted2 x -> x | _ -> failwith "RecursionTermLifter.callGraph" + let create_spec spec = `Lifted1 spec - let create_callGraph callGraph = `Lifted2 callGraph + let create_singleton_caller caller = `Lifted2 (CallerSet.singleton caller) let printXml f = function | `Lifted1 x -> G.printXml f x - | `Lifted2 x -> BatPrintf.fprintf f "%a" CallGraphMap.printXml x + | `Lifted2 x -> BatPrintf.fprintf f "%a" CallerSet.printXml x | x -> BatPrintf.fprintf f "%a" printXml x end @@ -1785,19 +1784,15 @@ struct else if not (LH.mem global_visited_calls call) then begin LH.replace global_visited_calls call (); let new_path_visited_calls = LS.add call path_visited_calls in - let fundec_e_typeV: V.t = V.relift (`Right fundec_e) in - let gmap = G.callGraph (ctx.global (fundec_e_typeV)) in - let callers: CallGraphSet.t = CallGraphMap.find (context_e) gmap in - CallGraphSet.iter (fun to_call -> + let gvar = V.call (fundec_e, context_e) in + let callers = G.callers (ctx.global gvar) in + CallerSet.iter (fun to_call -> iter_call new_path_visited_calls to_call ) callers; end in - let gmap = G.callGraph (ctx.global (v)) in - CallGraphMap.iter(fun key value -> - let call = (v', key) in - iter_call LS.empty call - ) gmap (* try all fundec + context pairs that are in the map *) + let callers = G.callers (ctx.global v) in + CallerSet.iter (iter_call LS.empty) callers let query ctx (type a) (q: a Queries.t): a Queries.result = match q with @@ -1825,30 +1820,27 @@ struct let assign ctx = S.assign (conv ctx) let vdecl ctx = S.vdecl (conv ctx) - (* c = context - t = set of tuples (fundec * context) - *) - let side_context sideg f c t = - if !AnalysisState.postsolving then - sideg (V.contexts f) (G.create_callGraph (CallGraphMap.singleton (c) (t))) + + let record_call sideg callee caller = + sideg (V.call callee) (G.create_singleton_caller caller) let enter ctx = S.enter (conv ctx) let paths_as_set ctx = S.paths_as_set (conv ctx) let body ctx = S.body (conv ctx) let return ctx = S.return (conv ctx) let combine_env ctx r fe f args fc es f_ask = - if !AnalysisState.postsolving then - let c_r: S.C.t = ctx.context () in (*Caller context*) + if !AnalysisState.postsolving then ( + let c_r: S.C.t = ctx.context () in (* Caller context *) let nodeF = ctx.node in - let fd_r : fundec = Node.find_fundec nodeF in (*Caller fundec*) - let c_e: S.C.t = Option.get fc in (*Callee context*) - let fd_e : fundec = f in (*Callee fundec*) - let tup: (fundec * S.C.t) = (fd_r, c_r) in - let t = CallGraphSet.singleton (tup) in - side_context ctx.sideg fd_e (c_e) t; - S.combine_env (conv ctx) r fe f args fc es f_ask - else - S.combine_env (conv ctx) r fe f args fc es f_ask + let fd_r : fundec = Node.find_fundec nodeF in (* Caller fundec *) + let caller: (fundec * S.C.t) = (fd_r, c_r) in + let c_e: S.C.t = Option.get fc in (* Callee context *) + let fd_e : fundec = f in (* Callee fundec *) + let callee = (fd_e, c_e) in + record_call ctx.sideg callee caller + ); + S.combine_env (conv ctx) r fe f args fc es f_ask + let combine_assign ctx = S.combine_assign (conv ctx) let special ctx = S.special (conv ctx) let threadenter ctx = S.threadenter (conv ctx) From 7f3cadfaea69592fe03fb311613b14efc0cf4718 Mon Sep 17 00:00:00 2001 From: Michael Schwarz Date: Thu, 12 Oct 2023 16:42:09 +0200 Subject: [PATCH 276/327] Adapt comments to simplified global invariant --- src/framework/constraints.ml | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/framework/constraints.ml b/src/framework/constraints.ml index 038068ea0d..b4b72146d5 100644 --- a/src/framework/constraints.ml +++ b/src/framework/constraints.ml @@ -1710,14 +1710,14 @@ module RecursionTermLifter (S: Spec) and module C = S.C = (* two global invariants: - - V -> G + - S.V -> S.G Needed to store the previously built global invariants - - fundec -> Map (S.C) (Set (fundec * S.C)) - The second global invariant maps from the callee fundec to a map, containing the callee context and the caller fundec and context. + - fundec * S.C -> (Set (fundec * S.C)) + The second global invariant maps from the callee fundec and context to a set of caller fundecs and contexts. This structure therefore stores the context-sensitive call graph. For example: let the function f in context c call function g in context c'. - In the global invariant structure it would be stored like this: g -> {c' -> {(f, c)}} + In the global invariant structure it would be stored like this: (g,c') -> {(f, c)} *) struct From 515a8bd2f300fdfe2134d3608fab52c9ca56a6f4 Mon Sep 17 00:00:00 2001 From: Michael Schwarz Date: Thu, 12 Oct 2023 16:55:08 +0200 Subject: [PATCH 277/327] Simplify cycle detection --- src/framework/constraints.ml | 14 ++++++-------- 1 file changed, 6 insertions(+), 8 deletions(-) diff --git a/src/framework/constraints.ml b/src/framework/constraints.ml index b4b72146d5..ad35ef2633 100644 --- a/src/framework/constraints.ml +++ b/src/framework/constraints.ml @@ -1764,35 +1764,33 @@ struct sideg = (fun v g -> ctx.sideg (V.spec v) (G.create_spec g)); } - let cycleDetection ctx v v' = + let cycleDetection ctx call = let module LH = Hashtbl.Make (Printable.Prod (CilType.Fundec) (S.C)) in let module LS = Set.Make (Printable.Prod (CilType.Fundec) (S.C)) in (* find all cycles/SCCs *) let global_visited_calls = LH.create 100 in (* DFS *) - let rec iter_call (path_visited_calls: LS.t) (call:Printable.Prod (CilType.Fundec) (S.C).t) = - let ((fundec_e:fundec), (context_e: C.t)) = call in (*unpack tuple for later use*) + let rec iter_call (path_visited_calls: LS.t) ((fundec, _) as call) = if LS.mem call path_visited_calls then ( AnalysisState.svcomp_may_not_terminate := true; (*set the indicator for a non-terminating program for the sv comp*) (*Cycle found*) let msgs = [ - (Pretty.dprintf "The program might not terminate! (Fundec %a is contained in a call graph cycle)" CilType.Fundec.pretty fundec_e, Some (M.Location.CilLocation fundec_e.svar.vdecl)); + (Pretty.dprintf "The program might not terminate! (Fundec %a is contained in a call graph cycle)" CilType.Fundec.pretty fundec, Some (M.Location.CilLocation fundec.svar.vdecl)); ] in M.msg_group Warning ~category:NonTerminating "Recursion cycle" msgs) (* output a warning for non-termination*) else if not (LH.mem global_visited_calls call) then begin LH.replace global_visited_calls call (); let new_path_visited_calls = LS.add call path_visited_calls in - let gvar = V.call (fundec_e, context_e) in + let gvar = V.call call in let callers = G.callers (ctx.global gvar) in CallerSet.iter (fun to_call -> iter_call new_path_visited_calls to_call ) callers; end in - let callers = G.callers (ctx.global v) in - CallerSet.iter (iter_call LS.empty) callers + iter_call LS.empty call let query ctx (type a) (q: a Queries.t): a Queries.result = match q with @@ -1804,7 +1802,7 @@ struct begin match v with | `Left v' -> S.query (conv ctx) (WarnGlobal (Obj.repr v')) - | `Right v' -> cycleDetection ctx v v' (* Note: to make it more efficient, one could only execute the cycle detection in case the loop analysis returns true, because otherwise the program will probably not terminate anyway*) + | `Right call -> cycleDetection ctx call (* Note: to make it more efficient, one could only execute the cycle detection in case the loop analysis returns true, because otherwise the program will probably not terminate anyway*) end | InvariantGlobal v -> let v: V.t = Obj.obj v in From b3016ff054bd714d7c9f9527a25226b2a1f4f06b Mon Sep 17 00:00:00 2001 From: Michael Schwarz Date: Thu, 12 Oct 2023 17:05:15 +0200 Subject: [PATCH 278/327] Failwith meaningful message for invaliud calls to `__goblint_bounded` --- src/analyses/loopTermination.ml | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/src/analyses/loopTermination.ml b/src/analyses/loopTermination.ml index bfc600f830..61034a57c0 100644 --- a/src/analyses/loopTermination.ml +++ b/src/analyses/loopTermination.ml @@ -72,9 +72,7 @@ struct M.msg_group Warning ~category:NonTerminating "Possibly non terminating loops" msgs); () with Not_found -> - (* This should not happen as long as __goblint_bounded is only used - * for this analysis. *) - ()) + failwith "Encountered a call to __goblint_bounded with an unknown loop counter variable.") | _ -> () else () From 14c3ead5c61242b46be22b2c100082f66454d95e Mon Sep 17 00:00:00 2001 From: Michael Schwarz Date: Sat, 14 Oct 2023 11:19:33 +0200 Subject: [PATCH 279/327] Merge branch 'master' into term --- scripts/goblint-lib-modules.py | 26 ++- src/analyses/base.ml | 117 ++++++++++-- src/analyses/memLeak.ml | 16 +- src/analyses/memOutOfBounds.ml | 171 ++++++++++++++---- src/analyses/useAfterFree.ml | 43 ++--- src/autoTune.ml | 40 +++- src/cdomains/arrayDomain.ml | 5 + src/common/framework/analysisState.ml | 5 +- src/common/util/cilfacade.ml | 3 +- src/common/util/options.schema.json | 6 + src/goblint_lib.ml | 1 + src/maingoblint.ml | 3 + src/util/analysisStateUtil.ml | 13 ++ src/witness/svcomp.ml | 2 + src/witness/svcompSpec.ml | 26 ++- src/witness/witness.ml | 45 +---- .../01-oob-heap-simple.c | 0 .../02-conditional-uaf.c | 0 .../03-nested-ptr-uaf.c | 0 .../04-function-call-uaf.c | 0 .../05-oob-implicit-deref.c | 0 .../06-memset-oob.c | 0 .../07-memcpy-oob.c | 4 +- .../08-memset-memcpy-array.c | 7 +- .../09-juliet-uaf.c | 0 .../74-invalid_deref/10-oob-two-loops.c | 22 +++ .../74-invalid_deref/11-address-offset-oob.c | 16 ++ .../74-invalid_deref/12-memcpy-oob-src.c | 43 +++++ .../13-mem-oob-packed-struct.c | 33 ++++ .../14-alloca-uaf.c | 0 .../15-juliet-uaf-global-var.c | 22 +++ .../74-invalid_deref/16-uaf-packed-struct.c | 40 ++++ .../74-invalid_deref/17-scopes-no-static.c | 22 +++ .../18-simple-uaf.c} | 0 .../19-oob-stack-simple.c} | 0 .../74-invalid_deref/20-scopes-global-var.c | 29 +++ .../21-oob-loop.c} | 0 .../74-invalid_deref/22-scopes-static.c | 52 ++++++ .../23-oob-deref-after-ptr-arith.c} | 0 .../24-uaf-free-in-wrapper-fun.c} | 0 .../25-uaf-struct.c} | 0 .../26-memset-memcpy-addr-offs.c} | 0 .../27-wrapper-funs-uaf.c} | 0 .../28-multi-threaded-uaf.c} | 0 ...9-multi-threaded-uaf-with-joined-thread.c} | 0 .../01-invalid-dealloc-simple.c | 0 .../02-invalid-dealloc-struct.c | 0 .../03-invalid-dealloc-array.c | 0 .../04-invalid-realloc.c | 0 .../05-free-at-offset.c | 0 .../06-realloc-at-offset.c | 0 .../07-free-at-struct-offset.c | 0 .../08-itc-no-double-free.c | 0 .../09-juliet-invalid-dealloc-alloca.c | 0 .../10-invalid-dealloc-union.c | 42 +++++ .../11-itc-double-free.c} | 0 .../12-realloc-at-struct-offset.c} | 0 .../13-juliet-double-free.c} | 0 tests/sv-comp/valid-memcleanup.prp | 2 + 59 files changed, 707 insertions(+), 149 deletions(-) create mode 100644 src/util/analysisStateUtil.ml rename tests/regression/{77-mem-oob => 74-invalid_deref}/01-oob-heap-simple.c (100%) rename tests/regression/{74-use_after_free => 74-invalid_deref}/02-conditional-uaf.c (100%) rename tests/regression/{74-use_after_free => 74-invalid_deref}/03-nested-ptr-uaf.c (100%) rename tests/regression/{74-use_after_free => 74-invalid_deref}/04-function-call-uaf.c (100%) rename tests/regression/{77-mem-oob => 74-invalid_deref}/05-oob-implicit-deref.c (100%) rename tests/regression/{77-mem-oob => 74-invalid_deref}/06-memset-oob.c (100%) rename tests/regression/{77-mem-oob => 74-invalid_deref}/07-memcpy-oob.c (94%) rename tests/regression/{77-mem-oob => 74-invalid_deref}/08-memset-memcpy-array.c (96%) rename tests/regression/{74-use_after_free => 74-invalid_deref}/09-juliet-uaf.c (100%) create mode 100644 tests/regression/74-invalid_deref/10-oob-two-loops.c create mode 100644 tests/regression/74-invalid_deref/11-address-offset-oob.c create mode 100644 tests/regression/74-invalid_deref/12-memcpy-oob-src.c create mode 100644 tests/regression/74-invalid_deref/13-mem-oob-packed-struct.c rename tests/regression/{74-use_after_free => 74-invalid_deref}/14-alloca-uaf.c (100%) create mode 100644 tests/regression/74-invalid_deref/15-juliet-uaf-global-var.c create mode 100644 tests/regression/74-invalid_deref/16-uaf-packed-struct.c create mode 100644 tests/regression/74-invalid_deref/17-scopes-no-static.c rename tests/regression/{74-use_after_free/01-simple-uaf.c => 74-invalid_deref/18-simple-uaf.c} (100%) rename tests/regression/{77-mem-oob/02-oob-stack-simple.c => 74-invalid_deref/19-oob-stack-simple.c} (100%) create mode 100644 tests/regression/74-invalid_deref/20-scopes-global-var.c rename tests/regression/{77-mem-oob/03-oob-loop.c => 74-invalid_deref/21-oob-loop.c} (100%) create mode 100644 tests/regression/74-invalid_deref/22-scopes-static.c rename tests/regression/{77-mem-oob/04-oob-deref-after-ptr-arith.c => 74-invalid_deref/23-oob-deref-after-ptr-arith.c} (100%) rename tests/regression/{74-use_after_free/05-uaf-free-in-wrapper-fun.c => 74-invalid_deref/24-uaf-free-in-wrapper-fun.c} (100%) rename tests/regression/{74-use_after_free/06-uaf-struct.c => 74-invalid_deref/25-uaf-struct.c} (100%) rename tests/regression/{77-mem-oob/09-memset-memcpy-addr-offs.c => 74-invalid_deref/26-memset-memcpy-addr-offs.c} (100%) rename tests/regression/{74-use_after_free/11-wrapper-funs-uaf.c => 74-invalid_deref/27-wrapper-funs-uaf.c} (100%) rename tests/regression/{74-use_after_free/12-multi-threaded-uaf.c => 74-invalid_deref/28-multi-threaded-uaf.c} (100%) rename tests/regression/{74-use_after_free/13-multi-threaded-uaf-with-joined-thread.c => 74-invalid_deref/29-multi-threaded-uaf-with-joined-thread.c} (100%) rename tests/regression/{75-invalid_dealloc => 75-invalid_free}/01-invalid-dealloc-simple.c (100%) rename tests/regression/{75-invalid_dealloc => 75-invalid_free}/02-invalid-dealloc-struct.c (100%) rename tests/regression/{75-invalid_dealloc => 75-invalid_free}/03-invalid-dealloc-array.c (100%) rename tests/regression/{75-invalid_dealloc => 75-invalid_free}/04-invalid-realloc.c (100%) rename tests/regression/{75-invalid_dealloc => 75-invalid_free}/05-free-at-offset.c (100%) rename tests/regression/{75-invalid_dealloc => 75-invalid_free}/06-realloc-at-offset.c (100%) rename tests/regression/{75-invalid_dealloc => 75-invalid_free}/07-free-at-struct-offset.c (100%) rename tests/regression/{74-use_after_free => 75-invalid_free}/08-itc-no-double-free.c (100%) rename tests/regression/{75-invalid_dealloc => 75-invalid_free}/09-juliet-invalid-dealloc-alloca.c (100%) create mode 100644 tests/regression/75-invalid_free/10-invalid-dealloc-union.c rename tests/regression/{74-use_after_free/07-itc-double-free.c => 75-invalid_free/11-itc-double-free.c} (100%) rename tests/regression/{75-invalid_dealloc/08-realloc-at-struct-offset.c => 75-invalid_free/12-realloc-at-struct-offset.c} (100%) rename tests/regression/{74-use_after_free/10-juliet-double-free.c => 75-invalid_free/13-juliet-double-free.c} (100%) create mode 100644 tests/sv-comp/valid-memcleanup.prp diff --git a/scripts/goblint-lib-modules.py b/scripts/goblint-lib-modules.py index 342f9a76bd..5f02271616 100755 --- a/scripts/goblint-lib-modules.py +++ b/scripts/goblint-lib-modules.py @@ -6,16 +6,20 @@ src_root_path = Path("./src") -goblint_lib_path = src_root_path / "goblint_lib.ml" +goblint_lib_paths = [ + src_root_path / "goblint_lib.ml", + src_root_path / "util" / "std" / "goblint_std.ml", +] goblint_lib_modules = set() -with goblint_lib_path.open() as goblint_lib_file: - for line in goblint_lib_file: - line = line.strip() - m = re.match(r"module (.*) = .*", line) - if m is not None: - module_name = m.group(1) - goblint_lib_modules.add(module_name) +for goblint_lib_path in goblint_lib_paths: + with goblint_lib_path.open() as goblint_lib_file: + for line in goblint_lib_file: + line = line.strip() + m = re.match(r"module (.*) = .*", line) + if m is not None: + module_name = m.group(1) + goblint_lib_modules.add(module_name) src_vendor_path = src_root_path / "vendor" exclude_module_names = set([ @@ -29,15 +33,21 @@ "Mainspec", # libraries + "Goblint_std", "Goblint_timing", "Goblint_backtrace", "Goblint_sites", "Goblint_build_info", + "Dune_build_info", "MessageCategory", # included in Messages "PreValueDomain", # included in ValueDomain "SpecCore", # spec stuff "SpecUtil", # spec stuff + + "ConfigVersion", + "ConfigProfile", + "ConfigOcaml", ]) src_modules = set() diff --git a/src/analyses/base.ml b/src/analyses/base.ml index 7b87d3ff51..908dc88401 100644 --- a/src/analyses/base.ml +++ b/src/analyses/base.ml @@ -1043,10 +1043,24 @@ struct | Mem n, ofs -> begin match (eval_rv a gs st n) with | Address adr -> - (if AD.is_null adr - then M.error ~category:M.Category.Behavior.Undefined.nullpointer_dereference ~tags:[CWE 476] "Must dereference NULL pointer" - else if AD.may_be_null adr - then M.warn ~category:M.Category.Behavior.Undefined.nullpointer_dereference ~tags:[CWE 476] "May dereference NULL pointer"); + ( + if AD.is_null adr then ( + AnalysisStateUtil.set_mem_safety_flag InvalidDeref; + M.error ~category:M.Category.Behavior.Undefined.nullpointer_dereference ~tags:[CWE 476] "Must dereference NULL pointer" + ) + else if AD.may_be_null adr then ( + AnalysisStateUtil.set_mem_safety_flag InvalidDeref; + M.warn ~category:M.Category.Behavior.Undefined.nullpointer_dereference ~tags:[CWE 476] "May dereference NULL pointer" + ); + (* Warn if any of the addresses contains a non-local and non-global variable *) + if AD.exists (function + | AD.Addr.Addr (v, _) -> not (CPA.mem v st.cpa) && not (is_global a v) + | _ -> false + ) adr then ( + AnalysisStateUtil.set_mem_safety_flag InvalidDeref; + M.warn "lval %a points to a non-local variable. Invalid pointer dereference may occur" d_lval lval + ) + ); AD.map (add_offset_varinfo (convert_offset a gs st ofs)) adr | _ -> M.debug ~category:Analyzer "Failed evaluating %a to lvalue" d_lval lval; @@ -2023,14 +2037,78 @@ struct in match eval_rv_address (Analyses.ask_of_ctx ctx) ctx.global ctx.local ptr with | Address a -> - if AD.is_top a then + if AD.is_top a then ( + AnalysisStateUtil.set_mem_safety_flag InvalidFree; M.warn ~category:(Behavior (Undefined InvalidMemoryDeallocation)) ~tags:[CWE 590] "Points-to set for pointer %a in function %s is top. Potentially invalid memory deallocation may occur" d_exp ptr special_fn.vname - else if has_non_heap_var a then + ) else if has_non_heap_var a then ( + AnalysisStateUtil.set_mem_safety_flag InvalidFree; M.warn ~category:(Behavior (Undefined InvalidMemoryDeallocation)) ~tags:[CWE 590] "Free of non-dynamically allocated memory in function %s for pointer %a" special_fn.vname d_exp ptr - else if has_non_zero_offset a then + ) else if has_non_zero_offset a then ( + AnalysisStateUtil.set_mem_safety_flag InvalidFree; M.warn ~category:(Behavior (Undefined InvalidMemoryDeallocation)) ~tags:[CWE 761] "Free of memory not at start of buffer in function %s for pointer %a" special_fn.vname d_exp ptr - | _ -> M.warn ~category:MessageCategory.Analyzer "Pointer %a in function %s doesn't evaluate to a valid address." d_exp ptr special_fn.vname + ) + | _ -> + AnalysisStateUtil.set_mem_safety_flag InvalidFree; + M.warn ~category:(Behavior (Undefined InvalidMemoryDeallocation)) ~tags:[CWE 590] "Pointer %a in function %s doesn't evaluate to a valid address. Invalid memory deallocation may occur" d_exp ptr special_fn.vname + + let points_to_heap_only ctx ptr = + match ctx.ask (Queries.MayPointTo ptr) with + | a when not (Queries.AD.is_top a)-> + Queries.AD.for_all (function + | Addr (v, _) -> ctx.ask (Queries.IsHeapVar v) + | _ -> false + ) a + | _ -> false + let get_size_of_ptr_target ctx ptr = + let intdom_of_int x = + ID.of_int (Cilfacade.ptrdiff_ikind ()) (Z.of_int x) + in + let size_of_type_in_bytes typ = + let typ_size_in_bytes = (bitsSizeOf typ) / 8 in + intdom_of_int typ_size_in_bytes + in + if points_to_heap_only ctx ptr then + (* Ask for BlobSize from the base address (the second component being set to true) in order to avoid BlobSize giving us bot *) + ctx.ask (Queries.BlobSize {exp = ptr; base_address = true}) + else + match ctx.ask (Queries.MayPointTo ptr) with + | a when not (Queries.AD.is_top a) -> + let pts_list = Queries.AD.elements a in + let pts_elems_to_sizes (addr: Queries.AD.elt) = + begin match addr with + | Addr (v, _) -> + begin match v.vtype with + | TArray (item_typ, _, _) -> + let item_typ_size_in_bytes = size_of_type_in_bytes item_typ in + begin match ctx.ask (Queries.EvalLength ptr) with + | `Lifted arr_len -> + let arr_len_casted = ID.cast_to (Cilfacade.ptrdiff_ikind ()) arr_len in + begin + try `Lifted (ID.mul item_typ_size_in_bytes arr_len_casted) + with IntDomain.ArithmeticOnIntegerBot _ -> `Bot + end + | `Bot -> `Bot + | `Top -> `Top + end + | _ -> + let type_size_in_bytes = size_of_type_in_bytes v.vtype in + `Lifted type_size_in_bytes + end + | _ -> `Top + end + in + (* Map each points-to-set element to its size *) + let pts_sizes = List.map pts_elems_to_sizes pts_list in + (* Take the smallest of all sizes that ptr's contents may have *) + begin match pts_sizes with + | [] -> `Bot + | [x] -> x + | x::xs -> List.fold_left ValueDomainQueries.ID.join x xs + end + | _ -> + (M.warn "Pointer %a has a points-to-set of top. An invalid memory access might occur" d_exp ptr; + `Top) let special ctx (lv:lval option) (f: varinfo) (args: exp list) = let invalidate_ret_lv st = match lv with @@ -2050,13 +2128,28 @@ struct let st: store = ctx.local in let gs = ctx.global in let desc = LF.find f in - let memory_copying dst src = + let memory_copying dst src n = + let dest_size = get_size_of_ptr_target ctx dst in + let n_intdom = Option.map_default (fun exp -> ctx.ask (Queries.EvalInt exp)) `Bot n in + let dest_size_equal_n = + match dest_size, n_intdom with + | `Lifted ds, `Lifted n -> + let casted_ds = ID.cast_to (Cilfacade.ptrdiff_ikind ()) ds in + let casted_n = ID.cast_to (Cilfacade.ptrdiff_ikind ()) n in + let ds_eq_n = + begin try ID.eq casted_ds casted_n + with IntDomain.ArithmeticOnIntegerBot _ -> ID.top_of @@ Cilfacade.ptrdiff_ikind () + end + in + Option.default false (ID.to_bool ds_eq_n) + | _ -> false + in let dest_a, dest_typ = addr_type_of_exp dst in let src_lval = mkMem ~addr:(Cil.stripCasts src) ~off:NoOffset in let src_typ = eval_lv (Analyses.ask_of_ctx ctx) gs st src_lval |> AD.type_of in (* when src and destination type coincide, take value from the source, otherwise use top *) - let value = if typeSig dest_typ = typeSig src_typ then + let value = if (typeSig dest_typ = typeSig src_typ) && dest_size_equal_n then let src_cast_lval = mkMem ~addr:(Cilfacade.mkCast ~e:src ~newt:(TPtr (dest_typ, []))) ~off:NoOffset in eval_rv (Analyses.ask_of_ctx ctx) gs st (Lval src_cast_lval) else @@ -2117,13 +2210,13 @@ struct let value = VD.zero_init_value dest_typ in set ~ctx (Analyses.ask_of_ctx ctx) gs st dest_a dest_typ value | Memcpy { dest = dst; src; n; }, _ -> (* TODO: use n *) - memory_copying dst src + memory_copying dst src (Some n) (* strcpy(dest, src); *) | Strcpy { dest = dst; src; n = None }, _ -> let dest_a, dest_typ = addr_type_of_exp dst in (* when dest surely isn't a string literal, try copying src to dest *) if AD.string_writing_defined dest_a then - memory_copying dst src + memory_copying dst src None else (* else return top (after a warning was issued) *) set ~ctx (Analyses.ask_of_ctx ctx) gs st dest_a dest_typ (VD.top_value (unrollType dest_typ)) diff --git a/src/analyses/memLeak.ml b/src/analyses/memLeak.ml index 8576096dfe..dbaa2d69fc 100644 --- a/src/analyses/memLeak.ml +++ b/src/analyses/memLeak.ml @@ -3,6 +3,7 @@ open GoblintCil open Analyses open MessageCategory +open AnalysisStateUtil module ToppedVarInfoSet = SetDomain.ToppedSet(CilType.Varinfo)(struct let topname = "All Heap Variables" end) @@ -19,15 +20,24 @@ struct (* HELPER FUNCTIONS *) let warn_for_multi_threaded ctx = - if not (ctx.ask (Queries.MustBeSingleThreaded { since_start = true })) then + if not (ctx.ask (Queries.MustBeSingleThreaded { since_start = true })) then ( + set_mem_safety_flag InvalidMemTrack; + set_mem_safety_flag InvalidMemcleanup; M.warn ~category:(Behavior (Undefined MemoryLeak)) ~tags:[CWE 401] "Program isn't running in single-threaded mode. A memory leak might occur due to multi-threading" + ) let check_for_mem_leak ?(assert_exp_imprecise = false) ?(exp = None) ctx = let state = ctx.local in if not @@ D.is_empty state then match assert_exp_imprecise, exp with - | true, Some exp -> M.warn ~category:(Behavior (Undefined MemoryLeak)) ~tags:[CWE 401] "assert expression %a is unknown. Memory leak might possibly occur for heap variables: %a" d_exp exp D.pretty state - | _ -> M.warn ~category:(Behavior (Undefined MemoryLeak)) ~tags:[CWE 401] "Memory leak detected for heap variables: %a" D.pretty state + | true, Some exp -> + set_mem_safety_flag InvalidMemTrack; + set_mem_safety_flag InvalidMemcleanup; + M.warn ~category:(Behavior (Undefined MemoryLeak)) ~tags:[CWE 401] "assert expression %a is unknown. Memory leak might possibly occur for heap variables: %a" d_exp exp D.pretty state + | _ -> + set_mem_safety_flag InvalidMemTrack; + set_mem_safety_flag InvalidMemcleanup; + M.warn ~category:(Behavior (Undefined MemoryLeak)) ~tags:[CWE 401] "Memory leak detected for heap variables: %a" D.pretty state (* TRANSFER FUNCTIONS *) let return ctx (exp:exp option) (f:fundec) : D.t = diff --git a/src/analyses/memOutOfBounds.ml b/src/analyses/memOutOfBounds.ml index c715a1d2e7..fc60352298 100644 --- a/src/analyses/memOutOfBounds.ml +++ b/src/analyses/memOutOfBounds.ml @@ -3,6 +3,7 @@ open GoblintCil open Analyses open MessageCategory +open AnalysisStateUtil module AS = AnalysisState module VDQ = ValueDomainQueries @@ -88,6 +89,10 @@ struct let pts_elems_to_sizes (addr: Queries.AD.elt) = begin match addr with | Addr (v, _) -> + if hasAttribute "goblint_cil_nested" v.vattr then ( + set_mem_safety_flag InvalidDeref; + M.warn "Var %a is potentially accessed out-of-scope. Invalid memory access may occur" CilType.Varinfo.pretty v + ); begin match v.vtype with | TArray (item_typ, _, _) -> let item_typ_size_in_bytes = size_of_type_in_bytes item_typ in @@ -117,8 +122,9 @@ struct | x::xs -> List.fold_left VDQ.ID.join x xs end | _ -> - M.warn "Pointer %a has a points-to-set of top. An invalid memory access might occur" d_exp ptr; - `Top + (set_mem_safety_flag InvalidDeref; + M.warn "Pointer %a has a points-to-set of top. An invalid memory access might occur" d_exp ptr; + `Top) let get_ptr_deref_type ptr_typ = match ptr_typ with @@ -159,6 +165,50 @@ struct with IntDomain.ArithmeticOnIntegerBot _ -> ID.bot_of @@ Cilfacade.ptrdiff_ikind () end + let cil_offs_to_idx ctx typ offs = + (* TODO: Some duplication with convert_offset in base.ml, unclear how to immediately get more reuse *) + let rec convert_offset (ofs: offset) = + match ofs with + | NoOffset -> `NoOffset + | Field (fld, ofs) -> `Field (fld, convert_offset ofs) + | Index (exp, ofs) when CilType.Exp.equal exp Offset.Index.Exp.any -> (* special offset added by convertToQueryLval *) + `Index (ID.top (), convert_offset ofs) + | Index (exp, ofs) -> + let i = match ctx.ask (Queries.EvalInt exp) with + | `Lifted x -> x + | _ -> ID.top_of @@ Cilfacade.ptrdiff_ikind () + in + `Index (i, convert_offset ofs) + in + PreValueDomain.Offs.to_index (convert_offset offs) + + + let check_unknown_addr_deref ctx ptr = + let may_contain_unknown_addr = + match ctx.ask (Queries.EvalValue ptr) with + | a when not (Queries.VD.is_top a) -> + begin match a with + | Address a -> ValueDomain.AD.may_be_unknown a + | _ -> false + end + (* Intuition: if ptr evaluates to top, it could potentially evaluate to the unknown address *) + | _ -> true + in + if may_contain_unknown_addr then begin + set_mem_safety_flag InvalidDeref; + M.warn ~category:(Behavior (Undefined Other)) "Pointer %a contains an unknown address. Invalid dereference may occur" d_exp ptr + end + + let ptr_only_has_str_addr ctx ptr = + match ctx.ask (Queries.EvalValue ptr) with + | a when not (Queries.VD.is_top a) -> + begin match a with + | Address a -> ValueDomain.AD.for_all (fun addr -> match addr with | StrPtr _ -> true | _ -> false) a + | _ -> false + end + (* Intuition: if ptr evaluates to top, it could all sorts of things and not only string addresses *) + | _ -> false + let rec get_addr_offs ctx ptr = match ctx.ask (Queries.MayPointTo ptr) with | a when not (VDQ.AD.is_top a) -> @@ -174,22 +224,25 @@ struct | Addr (_, o) -> ID.is_bot @@ offs_to_idx t o | _ -> false ) a then ( - (* TODO: Uncomment once staging-memsafety branch changes are applied *) - (* set_mem_safety_flag InvalidDeref; *) + set_mem_safety_flag InvalidDeref; M.warn "Pointer %a has a bot address offset. An invalid memory access may occur" d_exp ptr ) else if VDQ.AD.exists (function - | Addr (_, o) -> ID.is_bot @@ offs_to_idx t o + | Addr (_, o) -> ID.is_top_of (Cilfacade.ptrdiff_ikind ()) (offs_to_idx t o) | _ -> false ) a then ( - (* TODO: Uncomment once staging-memsafety branch changes are applied *) - (* set_mem_safety_flag InvalidDeref; *) + set_mem_safety_flag InvalidDeref; M.warn "Pointer %a has a top address offset. An invalid memory access may occur" d_exp ptr ); - (* Offset should be the same for all elements in the points-to set *) - (* Hence, we can just pick one element and obtain its offset *) - begin match VDQ.AD.choose a with - | Addr (_, o) -> offs_to_idx t o - | _ -> ID.top_of @@ Cilfacade.ptrdiff_ikind () + (* Get the address offsets of all points-to set elements *) + let addr_offsets = + VDQ.AD.filter (function Addr (v, o) -> true | _ -> false) a + |> VDQ.AD.to_mval + |> List.map (fun (_, o) -> offs_to_idx t o) + in + begin match addr_offsets with + | [] -> ID.bot_of @@ Cilfacade.ptrdiff_ikind () + | [x] -> x + | x::xs -> List.fold_left ID.join x xs end end | None -> @@ -197,18 +250,55 @@ struct ID.top_of @@ Cilfacade.ptrdiff_ikind () end | _ -> + set_mem_safety_flag InvalidDeref; M.warn "Pointer %a has a points-to-set of top. An invalid memory access might occur" d_exp ptr; ID.top_of @@ Cilfacade.ptrdiff_ikind () and check_lval_for_oob_access ctx ?(is_implicitly_derefed = false) lval = - if not @@ lval_contains_a_ptr lval then () + (* If the lval does not contain a pointer or if it does contain a pointer, but only points to string addresses, then no need to WARN *) + if (not @@ lval_contains_a_ptr lval) || ptr_only_has_str_addr ctx (Lval lval) then () else (* If the lval doesn't indicate an explicit dereference, we still need to check for an implicit dereference *) (* An implicit dereference is, e.g., printf("%p", ptr), where ptr is a pointer *) match lval, is_implicitly_derefed with | (Var _, _), false -> () | (Var v, _), true -> check_no_binop_deref ctx (Lval lval) - | (Mem e, _), _ -> + | (Mem e, o), _ -> + let ptr_deref_type = get_ptr_deref_type @@ typeOf e in + let offs_intdom = begin match ptr_deref_type with + | Some t -> cil_offs_to_idx ctx t o + | None -> ID.bot_of @@ Cilfacade.ptrdiff_ikind () + end in + let e_size = get_size_of_ptr_target ctx e in + let () = begin match e_size with + | `Top -> + (set_mem_safety_flag InvalidDeref; + M.warn "Size of lval dereference expression %a is top. Out-of-bounds memory access may occur" d_exp e) + | `Bot -> + (set_mem_safety_flag InvalidDeref; + M.warn "Size of lval dereference expression %a is bot. Out-of-bounds memory access may occur" d_exp e) + | `Lifted es -> + let casted_es = ID.cast_to (Cilfacade.ptrdiff_ikind ()) es in + let one = intdom_of_int 1 in + let casted_es = ID.sub casted_es one in + let casted_offs = ID.cast_to (Cilfacade.ptrdiff_ikind ()) offs_intdom in + let ptr_size_lt_offs = + begin try ID.lt casted_es casted_offs + with IntDomain.ArithmeticOnIntegerBot _ -> ID.bot_of @@ Cilfacade.ptrdiff_ikind () + end + in + let behavior = Undefined MemoryOutOfBoundsAccess in + let cwe_number = 823 in + begin match ID.to_bool ptr_size_lt_offs with + | Some true -> + (set_mem_safety_flag InvalidDeref; + M.warn ~category:(Behavior behavior) ~tags:[CWE cwe_number] "Size of lval dereference expression is %a (in bytes). It is offset by %a (in bytes). Memory out-of-bounds access must occur" ID.pretty casted_es ID.pretty casted_offs) + | Some false -> () + | None -> + (set_mem_safety_flag InvalidDeref; + M.warn ~category:(Behavior behavior) ~tags:[CWE cwe_number] "Could not compare size of lval dereference expression (%a) (in bytes) with offset by (%a) (in bytes). Memory out-of-bounds access might occur" ID.pretty casted_es ID.pretty casted_offs) + end + end in begin match e with | Lval (Var v, _) as lval_exp -> check_no_binop_deref ctx lval_exp | BinOp (binop, e1, e2, t) when binop = PlusPI || binop = MinusPI || binop = IndexPI -> @@ -219,6 +309,7 @@ struct end and check_no_binop_deref ctx lval_exp = + check_unknown_addr_deref ctx lval_exp; let behavior = Undefined MemoryOutOfBoundsAccess in let cwe_number = 823 in let ptr_size = get_size_of_ptr_target ctx lval_exp in @@ -229,10 +320,10 @@ struct | Some t -> begin match ptr_size, addr_offs with | `Top, _ -> - AS.svcomp_may_invalid_deref := true; + set_mem_safety_flag InvalidDeref; M.warn ~category:(Behavior behavior) ~tags:[CWE cwe_number] "Size of pointer %a is top. Memory out-of-bounds access might occur due to pointer arithmetic" d_exp lval_exp | `Bot, _ -> - AS.svcomp_may_invalid_deref := true; + set_mem_safety_flag InvalidDeref; M.warn ~category:(Behavior behavior) ~tags:[CWE cwe_number] "Size of pointer %a is bot. Memory out-of-bounds access might occur due to pointer arithmetic" d_exp lval_exp | `Lifted ps, ao -> let casted_ps = ID.cast_to (Cilfacade.ptrdiff_ikind ()) ps in @@ -240,11 +331,11 @@ struct let ptr_size_lt_offs = ID.lt casted_ps casted_ao in begin match ID.to_bool ptr_size_lt_offs with | Some true -> - AnalysisState.svcomp_may_invalid_deref := true; + set_mem_safety_flag InvalidDeref; M.warn ~category:(Behavior behavior) ~tags:[CWE cwe_number] "Size of pointer is %a (in bytes). It is offset by %a (in bytes) due to pointer arithmetic. Memory out-of-bounds access must occur" ID.pretty casted_ps ID.pretty casted_ao | Some false -> () | None -> - AnalysisState.svcomp_may_invalid_deref := true; + set_mem_safety_flag InvalidDeref; M.warn ~category:(Behavior behavior) ~tags:[CWE cwe_number] "Could not compare size of pointer (%a) (in bytes) with offset by (%a) (in bytes). Memory out-of-bounds access might occur" ID.pretty casted_ps ID.pretty casted_ao end end @@ -275,6 +366,7 @@ struct | AddrOf lval -> check_lval_for_oob_access ctx ~is_implicitly_derefed lval and check_binop_exp ctx binop e1 e2 t = + check_unknown_addr_deref ctx e1; let binopexp = BinOp (binop, e1, e2, t) in let behavior = Undefined MemoryOutOfBoundsAccess in let cwe_number = 823 in @@ -303,16 +395,16 @@ struct in begin match ptr_size, offset_size_with_addr_size with | `Top, _ -> - AS.svcomp_may_invalid_deref := true; + set_mem_safety_flag InvalidDeref; M.warn ~category:(Behavior behavior) ~tags:[CWE cwe_number] "Size of pointer %a in expression %a is top. Memory out-of-bounds access might occur" d_exp e1 d_exp binopexp | _, `Top -> - AS.svcomp_may_invalid_deref := true; + set_mem_safety_flag InvalidDeref; M.warn ~category:(Behavior behavior) ~tags:[CWE cwe_number] "Operand value for pointer arithmetic in expression %a is top. Memory out-of-bounds access might occur" d_exp binopexp | `Bot, _ -> - AS.svcomp_may_invalid_deref := true; + set_mem_safety_flag InvalidDeref; M.warn ~category:(Behavior behavior) ~tags:[CWE cwe_number] "Size of pointer %a in expression %a is bottom. Memory out-of-bounds access might occur" d_exp e1 d_exp binopexp | _, `Bot -> - AS.svcomp_may_invalid_deref := true; + set_mem_safety_flag InvalidDeref; M.warn ~category:(Behavior behavior) ~tags:[CWE cwe_number] "Operand value for pointer arithmetic in expression %a is bottom. Memory out-of-bounds access might occur" d_exp binopexp | `Lifted ps, `Lifted o -> let casted_ps = ID.cast_to (Cilfacade.ptrdiff_ikind ()) ps in @@ -320,11 +412,11 @@ struct let ptr_size_lt_offs = ID.lt casted_ps casted_o in begin match ID.to_bool ptr_size_lt_offs with | Some true -> - AS.svcomp_may_invalid_deref := true; + set_mem_safety_flag InvalidDeref; M.warn ~category:(Behavior behavior) ~tags:[CWE cwe_number] "Size of pointer in expression %a is %a (in bytes). It is offset by %a (in bytes). Memory out-of-bounds access must occur" d_exp binopexp ID.pretty casted_ps ID.pretty casted_o | Some false -> () | None -> - AnalysisState.svcomp_may_invalid_deref := true; + set_mem_safety_flag InvalidDeref; M.warn ~category:(Behavior behavior) ~tags:[CWE cwe_number] "Could not compare pointer size (%a) with offset (%a). Memory out-of-bounds access may occur" ID.pretty casted_ps ID.pretty casted_o end end @@ -333,23 +425,24 @@ struct | _ -> () (* For memset() and memcpy() *) - let check_count ctx fun_name dest n = + let check_count ctx fun_name ptr n = let (behavior:MessageCategory.behavior) = Undefined MemoryOutOfBoundsAccess in let cwe_number = 823 in - let dest_size = get_size_of_ptr_target ctx dest in + let ptr_size = get_size_of_ptr_target ctx ptr in let eval_n = ctx.ask (Queries.EvalInt n) in - let addr_offs = get_addr_offs ctx dest in - match dest_size, eval_n with + let addr_offs = get_addr_offs ctx ptr in + match ptr_size, eval_n with | `Top, _ -> - AnalysisState.svcomp_may_invalid_deref := true; - M.warn ~category:(Behavior behavior) ~tags:[CWE cwe_number] "Size of dest %a in function %s is unknown. Memory out-of-bounds access might occur" d_exp dest fun_name + set_mem_safety_flag InvalidDeref; + M.warn ~category:(Behavior behavior) ~tags:[CWE cwe_number] "Size of dest %a in function %s is unknown. Memory out-of-bounds access might occur" d_exp ptr fun_name | _, `Top -> - AnalysisState.svcomp_may_invalid_deref := true; + set_mem_safety_flag InvalidDeref; M.warn ~category:(Behavior behavior) ~tags:[CWE cwe_number] "Count parameter, passed to function %s is unknown. Memory out-of-bounds access might occur" fun_name | `Bot, _ -> - AnalysisState.svcomp_may_invalid_deref := true; - M.warn ~category:(Behavior behavior) ~tags:[CWE cwe_number] "Size of dest %a in function %s is bottom. Memory out-of-bounds access might occur" d_exp dest fun_name + set_mem_safety_flag InvalidDeref; + M.warn ~category:(Behavior behavior) ~tags:[CWE cwe_number] "Size of dest %a in function %s is bottom. Memory out-of-bounds access might occur" d_exp ptr fun_name | _, `Bot -> + set_mem_safety_flag InvalidDeref; M.warn ~category:(Behavior behavior) ~tags:[CWE cwe_number] "Count parameter, passed to function %s is bottom" fun_name | `Lifted ds, `Lifted en -> let casted_ds = ID.cast_to (Cilfacade.ptrdiff_ikind ()) ds in @@ -358,11 +451,11 @@ struct let dest_size_lt_count = ID.lt casted_ds (ID.add casted_en casted_ao) in begin match ID.to_bool dest_size_lt_count with | Some true -> - AnalysisState.svcomp_may_invalid_deref := true; - M.warn ~category:(Behavior behavior) ~tags:[CWE cwe_number] "Size of dest in function %s is %a (in bytes) with an address offset of %a (in bytes). Count is %a (in bytes). Memory out-of-bounds access must occur" fun_name ID.pretty casted_ds ID.pretty casted_ao ID.pretty casted_en + set_mem_safety_flag InvalidDeref; + M.warn ~category:(Behavior behavior) ~tags:[CWE cwe_number] "Size of %a in function %s is %a (in bytes) with an address offset of %a (in bytes). Count is %a (in bytes). Memory out-of-bounds access must occur" d_exp ptr fun_name ID.pretty casted_ds ID.pretty casted_ao ID.pretty casted_en | Some false -> () | None -> - AnalysisState.svcomp_may_invalid_deref := true; + set_mem_safety_flag InvalidDeref; M.warn ~category:(Behavior behavior) ~tags:[CWE cwe_number] "Could not compare size of dest (%a) with address offset (%a) count (%a) in function %s. Memory out-of-bounds access may occur" ID.pretty casted_ds ID.pretty casted_ao ID.pretty casted_en fun_name end @@ -396,7 +489,9 @@ struct (* Check calls to memset and memcpy for out-of-bounds-accesses *) match desc.special arglist with | Memset { dest; ch; count; } -> check_count ctx f.vname dest count; - | Memcpy { dest; src; n = count; } -> check_count ctx f.vname dest count; + | Memcpy { dest; src; n = count; } -> + (check_count ctx f.vname src count; + check_count ctx f.vname dest count;) | _ -> ctx.local let enter ctx (lval: lval option) (f:fundec) (args:exp list) : (D.t * D.t) list = @@ -412,4 +507,4 @@ struct end let _ = - MCP.register_analysis (module Spec : MCPSpec) \ No newline at end of file + MCP.register_analysis (module Spec : MCPSpec) diff --git a/src/analyses/useAfterFree.ml b/src/analyses/useAfterFree.ml index 02231336c0..ef63ab3e91 100644 --- a/src/analyses/useAfterFree.ml +++ b/src/analyses/useAfterFree.ml @@ -3,6 +3,7 @@ open GoblintCil open Analyses open MessageCategory +open AnalysisStateUtil module AllocaVars = SetDomain.ToppedSet(CilType.Varinfo)(struct let topname = "All alloca() Variables" end) module HeapVars = SetDomain.ToppedSet(CilType.Varinfo)(struct let topname = "All Heap Variables" end) @@ -14,7 +15,7 @@ module ThreadIdToJoinedThreadsMap = MapDomain.MapBot(ThreadIdDomain.ThreadLifted module Spec : Analyses.MCPSpec = struct - include Analyses.DefaultSpec + include Analyses.IdentitySpec let name () = "useAfterFree" @@ -23,18 +24,11 @@ struct module G = ThreadIdToJoinedThreadsMap module V = VarinfoV - (** TODO: Try out later in benchmarks to see how we perform with and without context-sensititivty *) let context _ _ = () (* HELPER FUNCTIONS *) - let set_global_svcomp_var is_double_free = - if is_double_free then - AnalysisState.svcomp_may_invalid_free := true - else - AnalysisState.svcomp_may_invalid_deref := true - let get_current_threadid ctx = ctx.ask Queries.CurrentThreadId @@ -70,23 +64,23 @@ struct | `Lifted current -> let possibly_started = G.exists (possibly_started current) freeing_threads in if possibly_started then begin - set_global_svcomp_var is_double_free; + if is_double_free then set_mem_safety_flag InvalidFree else set_mem_safety_flag InvalidDeref; M.warn ~category:(Behavior behavior) ~tags:[CWE cwe_number] "There's a thread that's been started in parallel with the memory-freeing threads for heap variable %a. %s might occur" CilType.Varinfo.pretty heap_var bug_name end else begin let current_is_unique = ThreadId.Thread.is_unique current in let any_equal_current threads = G.exists (equal_current current) threads in if not current_is_unique && any_equal_current freeing_threads then begin - set_global_svcomp_var is_double_free; + if is_double_free then set_mem_safety_flag InvalidFree else set_mem_safety_flag InvalidDeref; M.warn ~category:(Behavior behavior) ~tags:[CWE cwe_number] "Current thread is not unique and a %s might occur for heap variable %a" bug_name CilType.Varinfo.pretty heap_var end else if HeapVars.mem heap_var (snd ctx.local) then begin - set_global_svcomp_var is_double_free; + if is_double_free then set_mem_safety_flag InvalidFree else set_mem_safety_flag InvalidDeref; M.warn ~category:(Behavior behavior) ~tags:[CWE cwe_number] "%s might occur in current unique thread %a for heap variable %a" bug_name ThreadIdDomain.FlagConfiguredTID.pretty current CilType.Varinfo.pretty heap_var end end | `Top -> - set_global_svcomp_var is_double_free; + if is_double_free then set_mem_safety_flag InvalidFree else set_mem_safety_flag InvalidDeref; M.warn ~category:(Behavior behavior) ~tags:[CWE cwe_number] "CurrentThreadId is top. %s might occur for heap variable %a" bug_name CilType.Varinfo.pretty heap_var | `Bot -> M.warn ~category:MessageCategory.Analyzer "CurrentThreadId is bottom" @@ -115,8 +109,10 @@ struct begin match ctx.ask (Queries.MayPointTo lval_to_query) with | ad when not (Queries.AD.is_top ad) -> let warn_for_heap_var v = - if HeapVars.mem v (snd state) then + if HeapVars.mem v (snd state) then begin + if is_double_free then set_mem_safety_flag InvalidFree else set_mem_safety_flag InvalidDeref; M.warn ~category:(Behavior undefined_behavior) ~tags:[CWE cwe_number] "lval (%s) in \"%s\" points to a maybe freed memory region" v.vname transfer_fn_name + end in let pointed_to_heap_vars = Queries.AD.fold (fun addr vars -> @@ -179,9 +175,6 @@ struct warn_exp_might_contain_freed "branch" ctx exp; ctx.local - let body ctx (f:fundec) : D.t = - ctx.local - let return ctx (exp:exp option) (f:fundec) : D.t = Option.iter (fun x -> warn_exp_might_contain_freed "return" ctx x) exp; ctx.local @@ -189,17 +182,10 @@ struct let enter ctx (lval:lval option) (f:fundec) (args:exp list) : (D.t * D.t) list = let caller_state = ctx.local in List.iter (fun arg -> warn_exp_might_contain_freed "enter" ctx arg) args; - if AllocaVars.is_empty (fst caller_state) && HeapVars.is_empty (snd caller_state) then - [caller_state, caller_state] - else ( - let reachable_from_args = List.fold_left (fun ad arg -> Queries.AD.join ad (ctx.ask (ReachableFrom arg))) (Queries.AD.empty ()) args in - if Queries.AD.is_top reachable_from_args || D.is_top caller_state then - [caller_state, caller_state] - else - let reachable_vars = Queries.AD.to_var_may reachable_from_args in - let callee_state = (AllocaVars.empty (), HeapVars.filter (fun var -> List.mem var reachable_vars) (snd caller_state)) in (* TODO: use AD.mem directly *) - [caller_state, callee_state] - ) + (* TODO: The 2nd component of the callee state needs to contain only the heap vars from the caller state which are reachable from: *) + (* * Global program variables *) + (* * The callee arguments *) + [caller_state, (AllocaVars.empty (), snd caller_state)] let combine_env ctx (lval:lval option) fexp (f:fundec) (args:exp list) fc (callee_local:D.t) (f_ask:Queries.ask) : D.t = let (caller_stack_state, caller_heap_state) = ctx.local in @@ -251,9 +237,6 @@ struct end | _ -> state - let threadenter ctx lval f args = [ctx.local] - let threadspawn ctx lval f args fctx = ctx.local - let startstate v = D.bot () let exitstate v = D.top () diff --git a/src/autoTune.ml b/src/autoTune.ml index e72764ceb6..9e89a18045 100644 --- a/src/autoTune.ml +++ b/src/autoTune.ml @@ -210,6 +210,38 @@ let activateLongjmpAnalysesWhenRequired () = enableAnalyses longjmpAnalyses; ) +let focusOnMemSafetySpecification () = + match Svcomp.Specification.of_option () with + | ValidFree -> (* Enable the useAfterFree analysis *) + let uafAna = ["useAfterFree"] in + print_endline @@ "Specification: ValidFree -> enabling useAfterFree analysis \"" ^ (String.concat ", " uafAna) ^ "\""; + enableAnalyses uafAna + | ValidDeref -> (* Enable the memOutOfBounds analysis *) + let memOobAna = ["memOutOfBounds"] in + print_endline "Setting \"cil.addNestedScopeAttr\" to true"; + set_bool "cil.addNestedScopeAttr" true; + print_endline @@ "Specification: ValidDeref -> enabling memOutOfBounds analysis \"" ^ (String.concat ", " memOobAna) ^ "\""; + enableAnalyses memOobAna + | ValidMemtrack + | ValidMemcleanup -> (* Enable the memLeak analysis *) + let memLeakAna = ["memLeak"] in + if (get_int "ana.malloc.unique_address_count") < 1 then ( + print_endline "Setting \"ana.malloc.unique_address_count\" to 1"; + set_int "ana.malloc.unique_address_count" 1; + ); + print_endline @@ "Specification: ValidMemtrack and ValidMemcleanup -> enabling memLeak analysis \"" ^ (String.concat ", " memLeakAna) ^ "\""; + enableAnalyses memLeakAna + | MemorySafety -> (* TODO: This is a temporary solution for the memory safety category *) + (print_endline "Setting \"cil.addNestedScopeAttr\" to true"; + set_bool "cil.addNestedScopeAttr" true; + if (get_int "ana.malloc.unique_address_count") < 1 then ( + print_endline "Setting \"ana.malloc.unique_address_count\" to 1"; + set_int "ana.malloc.unique_address_count" 1; + ); + let memSafetyAnas = ["memOutOfBounds"; "memLeak"; "useAfterFree";] in + enableAnalyses memSafetyAnas) + | _ -> () + let focusOnSpecification () = match Svcomp.Specification.of_option () with | UnreachCall s -> () @@ -220,13 +252,7 @@ let focusOnSpecification () = | NoOverflow -> (*We focus on integer analysis*) set_bool "ana.int.def_exc" true; set_bool "ana.int.interval" true - | ValidFree -> (* Enable the useAfterFree analysis *) - let uafAna = ["useAfterFree"] in - print_endline @@ "Specification: ValidFree -> enabling useAfterFree analysis \"" ^ (String.concat ", " uafAna) ^ "\""; - enableAnalyses uafAna - (* TODO: Finish these two below later *) - | ValidDeref - | ValidMemtrack -> () + | _ -> () (*Detect enumerations and enable the "ana.int.enums" option*) exception EnumFound diff --git a/src/cdomains/arrayDomain.ml b/src/cdomains/arrayDomain.ml index c099a94f96..2f91e47663 100644 --- a/src/cdomains/arrayDomain.ml +++ b/src/cdomains/arrayDomain.ml @@ -787,14 +787,19 @@ let array_oob_check ( type a ) (module Idx: IntDomain.Z with type t = a) (x, l) | Some true, Some true -> (* Certainly in bounds on both sides.*) () | Some true, Some false -> (* The following matching differentiates the must and may cases*) + AnalysisStateUtil.set_mem_safety_flag InvalidDeref; M.error ~category:M.Category.Behavior.Undefined.ArrayOutOfBounds.past_end "Must access array past end" | Some true, None -> + AnalysisStateUtil.set_mem_safety_flag InvalidDeref; M.warn ~category:M.Category.Behavior.Undefined.ArrayOutOfBounds.past_end "May access array past end" | Some false, Some true -> + AnalysisStateUtil.set_mem_safety_flag InvalidDeref; M.error ~category:M.Category.Behavior.Undefined.ArrayOutOfBounds.before_start "Must access array before start" | None, Some true -> + AnalysisStateUtil.set_mem_safety_flag InvalidDeref; M.warn ~category:M.Category.Behavior.Undefined.ArrayOutOfBounds.before_start "May access array before start" | _ -> + AnalysisStateUtil.set_mem_safety_flag InvalidDeref; M.warn ~category:M.Category.Behavior.Undefined.ArrayOutOfBounds.unknown "May access array out of bounds" else () diff --git a/src/common/framework/analysisState.ml b/src/common/framework/analysisState.ml index 19377520cd..fd76e1bb67 100644 --- a/src/common/framework/analysisState.ml +++ b/src/common/framework/analysisState.ml @@ -15,9 +15,12 @@ let svcomp_may_invalid_free = ref false (** Whether an invalid pointer dereference happened *) let svcomp_may_invalid_deref = ref false -(** Whether an invalid memtrack happened *) +(** Whether a memory leak occurred and there's no reference to the leaked memory *) let svcomp_may_invalid_memtrack = ref false +(** Whether a memory leak occurred *) +let svcomp_may_invalid_memcleanup = ref false + (** A hack to see if we are currently doing global inits *) let global_initialization = ref false diff --git a/src/common/util/cilfacade.ml b/src/common/util/cilfacade.ml index 52d5f52f25..2075cda890 100644 --- a/src/common/util/cilfacade.ml +++ b/src/common/util/cilfacade.ml @@ -40,7 +40,8 @@ let is_first_field x = match x.fcomp.cfields with let init_options () = Mergecil.merge_inlines := get_bool "cil.merge.inlines"; Cil.cstd := Cil.cstd_of_string (get_string "cil.cstd"); - Cil.gnu89inline := get_bool "cil.gnu89inline" + Cil.gnu89inline := get_bool "cil.gnu89inline"; + Cabs2cil.addNestedScopeAttr := get_bool "cil.addNestedScopeAttr" let init () = initCIL (); diff --git a/src/common/util/options.schema.json b/src/common/util/options.schema.json index 3dd43530bd..e8510e86f3 100644 --- a/src/common/util/options.schema.json +++ b/src/common/util/options.schema.json @@ -288,6 +288,12 @@ "type": "boolean", "description": "Indicates whether gnu89 semantic should be used for inline functions.", "default": false + }, + "addNestedScopeAttr": { + "title": "cil.addNestedScopeAttr", + "type": "boolean", + "description": "Indicates whether variables that CIL pulls out of their scope should be marked.", + "default": false } }, "additionalProperties": false diff --git a/src/goblint_lib.ml b/src/goblint_lib.ml index dadeb2cda1..a71a0c9684 100644 --- a/src/goblint_lib.ml +++ b/src/goblint_lib.ml @@ -23,6 +23,7 @@ module CfgTools = CfgTools module Analyses = Analyses module Constraints = Constraints module AnalysisState = AnalysisState +module AnalysisStateUtil = AnalysisStateUtil module ControlSpecC = ControlSpecC (** Master control program (MCP) is the analysis specification for the dynamic product of activated analyses. *) diff --git a/src/maingoblint.ml b/src/maingoblint.ml index e80ae12661..d187fc70f0 100644 --- a/src/maingoblint.ml +++ b/src/maingoblint.ml @@ -135,6 +135,7 @@ let check_arguments () = if get_bool "allfuns" && not (get_bool "exp.earlyglobs") then (set_bool "exp.earlyglobs" true; warn "allfuns enables exp.earlyglobs.\n"); if not @@ List.mem "escape" @@ get_string_list "ana.activated" then warn "Without thread escape analysis, every local variable whose address is taken is considered escaped, i.e., global!"; if List.mem "malloc_null" @@ get_string_list "ana.activated" && not @@ get_bool "sem.malloc.fail" then (set_bool "sem.malloc.fail" true; warn "The malloc_null analysis enables sem.malloc.fail."); + if List.mem "memOutOfBounds" @@ get_string_list "ana.activated" && not @@ get_bool "cil.addNestedScopeAttr" then (set_bool "cil.addNestedScopeAttr" true; warn "The memOutOfBounds analysis enables cil.addNestedScopeAttr."); if get_bool "ana.base.context.int" && not (get_bool "ana.base.context.non-ptr") then (set_bool "ana.base.context.int" false; warn "ana.base.context.int implicitly disabled by ana.base.context.non-ptr"); (* order matters: non-ptr=false, int=true -> int=false cascades to interval=false with warning *) if get_bool "ana.base.context.interval" && not (get_bool "ana.base.context.int") then (set_bool "ana.base.context.interval" false; warn "ana.base.context.interval implicitly disabled by ana.base.context.int"); @@ -190,6 +191,8 @@ let handle_options () = check_arguments (); AfterConfig.run (); Sys.set_signal (GobSys.signal_of_string (get_string "dbg.solver-signal")) Signal_ignore; (* Ignore solver-signal before solving (e.g. MyCFG), otherwise exceptions self-signal the default, which crashes instead of printing backtrace. *) + if AutoTune.isActivated "specification" && get_string "ana.specification" <> "" then + AutoTune.focusOnMemSafetySpecification (); Cilfacade.init_options (); handle_flags () diff --git a/src/util/analysisStateUtil.ml b/src/util/analysisStateUtil.ml new file mode 100644 index 0000000000..a34be33f18 --- /dev/null +++ b/src/util/analysisStateUtil.ml @@ -0,0 +1,13 @@ +type mem_safety_violation = + | InvalidFree + | InvalidDeref + | InvalidMemTrack + | InvalidMemcleanup + +let set_mem_safety_flag violation_type = + if !AnalysisState.postsolving then + match violation_type with + | InvalidFree -> AnalysisState.svcomp_may_invalid_free := true + | InvalidDeref -> AnalysisState.svcomp_may_invalid_deref := true + | InvalidMemTrack -> AnalysisState.svcomp_may_invalid_memtrack := true + | InvalidMemcleanup -> AnalysisState.svcomp_may_invalid_memcleanup := true \ No newline at end of file diff --git a/src/witness/svcomp.ml b/src/witness/svcomp.ml index 6c050aa5b1..2e29993e91 100644 --- a/src/witness/svcomp.ml +++ b/src/witness/svcomp.ml @@ -56,6 +56,8 @@ struct | ValidFree -> "valid-free" | ValidDeref -> "valid-deref" | ValidMemtrack -> "valid-memtrack" + | MemorySafety -> "memory-safety" (* TODO: Currently here only to complete the pattern match *) + | ValidMemcleanup -> "valid-memcleanup" in "false(" ^ result_spec ^ ")" | Unknown -> "unknown" diff --git a/src/witness/svcompSpec.ml b/src/witness/svcompSpec.ml index 39a42cebae..de2d7c5283 100644 --- a/src/witness/svcompSpec.ml +++ b/src/witness/svcompSpec.ml @@ -10,10 +10,13 @@ type t = | ValidFree | ValidDeref | ValidMemtrack + | MemorySafety (* Internal property for use in Goblint; serves as a summary for ValidFree, ValidDeref and ValidMemtrack *) + | ValidMemcleanup let of_string s = let s = String.strip s in - let regexp = Str.regexp "CHECK( init(main()), LTL(G \\(.*\\)) )" in + let regexp_multiple = Str.regexp "CHECK( init(main()), LTL(G \\(.*\\)) )\nCHECK( init(main()), LTL(G \\(.*\\)) )\nCHECK( init(main()), LTL(G \\(.*\\)) )" in + let regexp_single = Str.regexp "CHECK( init(main()), LTL(G \\(.*\\)) )" in let regexp_negated = Str.regexp "CHECK( init(main()), LTL(G ! \\(.*\\)) )" in if Str.string_match regexp_negated s 0 then let global_not = Str.matched_group 1 s in @@ -30,14 +33,19 @@ let of_string s = UnreachCall f else failwith "Svcomp.Specification.of_string: unknown global not expression" - else if Str.string_match regexp s 0 then + else if Str.string_match regexp_multiple s 0 then + let global1 = Str.matched_group 1 s in + let global2 = Str.matched_group 2 s in + let global3 = Str.matched_group 3 s in + let mem_safety_props = ["valid-free"; "valid-deref"; "valid-memtrack";] in + if (global1 <> global2 && global1 <> global3 && global2 <> global3) && List.for_all (fun x -> List.mem x mem_safety_props) [global1; global2; global3] then + MemorySafety + else + failwith "Svcomp.Specification.of_string: unknown global expression" + else if Str.string_match regexp_single s 0 then let global = Str.matched_group 1 s in - if global = "valid-free" then - ValidFree - else if global = "valid-deref" then - ValidDeref - else if global = "valid-memtrack" then - ValidMemtrack + if global = "valid-memcleanup" then + ValidMemcleanup else failwith "Svcomp.Specification.of_string: unknown global expression" else @@ -69,5 +77,7 @@ let to_string spec = | ValidDeref -> "valid-deref", false | ValidMemtrack -> "valid-memtrack", false | Termination -> "no-termination", true + | MemorySafety -> "memory-safety", false (* TODO: That's false, it's currently here just to complete the pattern match *) + | ValidMemcleanup -> "valid-memcleanup", false in print_output spec_str is_neg diff --git a/src/witness/witness.ml b/src/witness/witness.ml index 2031f266f4..08a796c307 100644 --- a/src/witness/witness.ml +++ b/src/witness/witness.ml @@ -535,14 +535,17 @@ struct in (module TaskResult:WitnessTaskResult) ) - | ValidFree -> + | ValidFree + | ValidDeref + | ValidMemtrack + | MemorySafety -> let module TrivialArg = struct include Arg let next _ = [] end in - if not !AnalysisState.svcomp_may_invalid_free then + if not !AnalysisState.svcomp_may_invalid_free && not !AnalysisState.svcomp_may_invalid_deref && not !AnalysisState.svcomp_may_invalid_memtrack then ( let module TaskResult = struct module Arg = Arg @@ -553,37 +556,7 @@ struct end in (module TaskResult:WitnessTaskResult) - else ( - let module TaskResult = - struct - module Arg = TrivialArg - let result = Result.Unknown - let invariant _ = Invariant.none - let is_violation _ = false - let is_sink _ = false - end - in - (module TaskResult:WitnessTaskResult) - ) - | ValidDeref -> - let module TrivialArg = - struct - include Arg - let next _ = [] - end - in - if not !AnalysisState.svcomp_may_invalid_deref then - let module TaskResult = - struct - module Arg = Arg - let result = Result.True - let invariant _ = Invariant.none - let is_violation _ = false - let is_sink _ = false - end - in - (module TaskResult:WitnessTaskResult) - else ( + ) else ( let module TaskResult = struct module Arg = TrivialArg @@ -595,14 +568,14 @@ struct in (module TaskResult:WitnessTaskResult) ) - | ValidMemtrack -> + | ValidMemcleanup -> let module TrivialArg = struct include Arg let next _ = [] end in - if not !AnalysisState.svcomp_may_invalid_memtrack then + if not !AnalysisState.svcomp_may_invalid_memcleanup then ( let module TaskResult = struct module Arg = Arg @@ -613,7 +586,7 @@ struct end in (module TaskResult:WitnessTaskResult) - else ( + ) else ( let module TaskResult = struct module Arg = TrivialArg diff --git a/tests/regression/77-mem-oob/01-oob-heap-simple.c b/tests/regression/74-invalid_deref/01-oob-heap-simple.c similarity index 100% rename from tests/regression/77-mem-oob/01-oob-heap-simple.c rename to tests/regression/74-invalid_deref/01-oob-heap-simple.c diff --git a/tests/regression/74-use_after_free/02-conditional-uaf.c b/tests/regression/74-invalid_deref/02-conditional-uaf.c similarity index 100% rename from tests/regression/74-use_after_free/02-conditional-uaf.c rename to tests/regression/74-invalid_deref/02-conditional-uaf.c diff --git a/tests/regression/74-use_after_free/03-nested-ptr-uaf.c b/tests/regression/74-invalid_deref/03-nested-ptr-uaf.c similarity index 100% rename from tests/regression/74-use_after_free/03-nested-ptr-uaf.c rename to tests/regression/74-invalid_deref/03-nested-ptr-uaf.c diff --git a/tests/regression/74-use_after_free/04-function-call-uaf.c b/tests/regression/74-invalid_deref/04-function-call-uaf.c similarity index 100% rename from tests/regression/74-use_after_free/04-function-call-uaf.c rename to tests/regression/74-invalid_deref/04-function-call-uaf.c diff --git a/tests/regression/77-mem-oob/05-oob-implicit-deref.c b/tests/regression/74-invalid_deref/05-oob-implicit-deref.c similarity index 100% rename from tests/regression/77-mem-oob/05-oob-implicit-deref.c rename to tests/regression/74-invalid_deref/05-oob-implicit-deref.c diff --git a/tests/regression/77-mem-oob/06-memset-oob.c b/tests/regression/74-invalid_deref/06-memset-oob.c similarity index 100% rename from tests/regression/77-mem-oob/06-memset-oob.c rename to tests/regression/74-invalid_deref/06-memset-oob.c diff --git a/tests/regression/77-mem-oob/07-memcpy-oob.c b/tests/regression/74-invalid_deref/07-memcpy-oob.c similarity index 94% rename from tests/regression/77-mem-oob/07-memcpy-oob.c rename to tests/regression/74-invalid_deref/07-memcpy-oob.c index 012f92996e..5605404a87 100644 --- a/tests/regression/77-mem-oob/07-memcpy-oob.c +++ b/tests/regression/74-invalid_deref/07-memcpy-oob.c @@ -31,13 +31,13 @@ int main(int argc, char const *argv[]) { memcpy(a, b, 40); //WARN memcpy(a, b, sizeof(a)); //WARN - memcpy(b, a, 60); //NOWARN + memcpy(b, a, 60); //WARN b += 1; memcpy(b, a, 60); //WARN s *s_ptr = malloc(sizeof(s)); - memcpy(s_ptr, a, sizeof(s)); //NOWARN + memcpy(s_ptr, a, sizeof(s)); //WARN memcpy(s_ptr->a, 0, sizeof(s)); //WARN memcpy(s_ptr->b, 0, sizeof(s)); //WARN diff --git a/tests/regression/77-mem-oob/08-memset-memcpy-array.c b/tests/regression/74-invalid_deref/08-memset-memcpy-array.c similarity index 96% rename from tests/regression/77-mem-oob/08-memset-memcpy-array.c rename to tests/regression/74-invalid_deref/08-memset-memcpy-array.c index f231ba2dc4..210a61d459 100644 --- a/tests/regression/77-mem-oob/08-memset-memcpy-array.c +++ b/tests/regression/74-invalid_deref/08-memset-memcpy-array.c @@ -6,13 +6,14 @@ int main(int argc, char const *argv[]) { int arr[42]; // Size should be 168 bytes (with 4 byte ints) int *b = arr; - + int random; + memset(b, 0, 168); //NOWARN memset(b, 0, sizeof(arr)); //NOWARN memset(b, 0, 169); //WARN memset(b, 0, sizeof(arr) + 1); //WARN - + int *c = malloc(sizeof(arr)); // Size should be 168 bytes (with 4 byte ints) memcpy(b, c, 168); //NOWARN memcpy(b, c, sizeof(arr)); //NOWARN @@ -26,7 +27,7 @@ int main(int argc, char const *argv[]) { memset(b, 0, 168); //WARN memcpy(b, c, 168); //WARN } else if (*(argv + 5)) { - int random = rand(); + random = rand(); b = &random; memset(b, 0, 168); //WARN memcpy(b, c, 168); //WARN diff --git a/tests/regression/74-use_after_free/09-juliet-uaf.c b/tests/regression/74-invalid_deref/09-juliet-uaf.c similarity index 100% rename from tests/regression/74-use_after_free/09-juliet-uaf.c rename to tests/regression/74-invalid_deref/09-juliet-uaf.c diff --git a/tests/regression/74-invalid_deref/10-oob-two-loops.c b/tests/regression/74-invalid_deref/10-oob-two-loops.c new file mode 100644 index 0000000000..303aac242e --- /dev/null +++ b/tests/regression/74-invalid_deref/10-oob-two-loops.c @@ -0,0 +1,22 @@ +// PARAM: --set ana.activated[+] memOutOfBounds --enable ana.int.interval --disable warn.info --set sem.int.signed_overflow assume_none +#include + +int main() { + int *p = malloc(1048 * sizeof(int)); + + for (int i = 0; i < 1048; ++i) { + p[i] = rand(); //NOWARN + } + + int *q = p; + + while (*q >= 0 && q < p + 1048 * sizeof(int)) { //WARN + if (rand()) { + q++; + } else { + (*q)--; //WARN + } + } + free(p); + return 0; +} diff --git a/tests/regression/74-invalid_deref/11-address-offset-oob.c b/tests/regression/74-invalid_deref/11-address-offset-oob.c new file mode 100644 index 0000000000..ba01a12873 --- /dev/null +++ b/tests/regression/74-invalid_deref/11-address-offset-oob.c @@ -0,0 +1,16 @@ +// PARAM: --set ana.activated[+] memOutOfBounds --enable ana.int.interval --disable warn.info --set sem.int.signed_overflow assume_none +int main() { + int *p = malloc(2 * sizeof(int)); + int *q = p; + int x; + + if (x) { + q++; + q++; + q++; + x = *q; //WARN + } + + x = *q; //WARN + return 0; +} diff --git a/tests/regression/74-invalid_deref/12-memcpy-oob-src.c b/tests/regression/74-invalid_deref/12-memcpy-oob-src.c new file mode 100644 index 0000000000..0f3a609fbe --- /dev/null +++ b/tests/regression/74-invalid_deref/12-memcpy-oob-src.c @@ -0,0 +1,43 @@ +// PARAM: --set ana.activated[+] memOutOfBounds --enable ana.int.interval --disable warn.info +// TODO: The "--disable warn.info" part is a temporary fix and needs to be removed once the MacOS CI job is fixed +#include +#include + +struct A { + unsigned char a; + unsigned char b:2; + unsigned char c:2; + unsigned char d:5; + unsigned char e; +} __attribute__((packed)); + +struct A d; +int main(void) +{ + struct A *p; + p = malloc(5); + d.a = 1; + d.b = 2; + d.c = 3; + d.d = 4; + d.e = 5; + // It's an OOB error, because sizeof(d) == 4 + memcpy(p, &d, 5); //WARN + if (p->a != 1) { + free(p); + } + if (p->b != 2) { + free(p); + } + if (p->c != 3) { + free(p); + } + if (p->d != 4) { + free(p); + } + if (p->e != 5) { + free(p); + } + free(p); +} + diff --git a/tests/regression/74-invalid_deref/13-mem-oob-packed-struct.c b/tests/regression/74-invalid_deref/13-mem-oob-packed-struct.c new file mode 100644 index 0000000000..552cd1bb0b --- /dev/null +++ b/tests/regression/74-invalid_deref/13-mem-oob-packed-struct.c @@ -0,0 +1,33 @@ +// PARAM: --set ana.activated[+] memOutOfBounds --enable ana.int.interval +#include + +struct A { + unsigned char a; + unsigned char b:2; + unsigned char c:2; + unsigned char d; +} __attribute__((packed)); + +int main(void) +{ + struct A *p; + p = malloc(2); + p->a = 1; + if (p->a != 1) { + free(p); + } + p->b = 2; + if (p->b != 2) { + free(p); + } + p->c = 3; + if (p->c != 3) { + free(p); + } + p->d = 4; //WARN + if (p->d != 4) {//WARN + free(p); + } + free(p); +} + diff --git a/tests/regression/74-use_after_free/14-alloca-uaf.c b/tests/regression/74-invalid_deref/14-alloca-uaf.c similarity index 100% rename from tests/regression/74-use_after_free/14-alloca-uaf.c rename to tests/regression/74-invalid_deref/14-alloca-uaf.c diff --git a/tests/regression/74-invalid_deref/15-juliet-uaf-global-var.c b/tests/regression/74-invalid_deref/15-juliet-uaf-global-var.c new file mode 100644 index 0000000000..cc9819950f --- /dev/null +++ b/tests/regression/74-invalid_deref/15-juliet-uaf-global-var.c @@ -0,0 +1,22 @@ +//PARAM: --set ana.activated[+] useAfterFree +#include + +int *global; + +void other(void) +{ + int *data = global; + free((void *)data); + return; +} + +int main(int argc, char **argv) +{ + int *data = (int *)malloc(400UL); + free((void *)data); + + global = data; + other(); + + return 0; +} \ No newline at end of file diff --git a/tests/regression/74-invalid_deref/16-uaf-packed-struct.c b/tests/regression/74-invalid_deref/16-uaf-packed-struct.c new file mode 100644 index 0000000000..e10aa28486 --- /dev/null +++ b/tests/regression/74-invalid_deref/16-uaf-packed-struct.c @@ -0,0 +1,40 @@ +// PARAM: --set ana.activated[+] useAfterFree +#include +#include + +struct A { + unsigned char a; + unsigned char b:2; + unsigned char c:2; + unsigned char pad1[2]; + unsigned int d; + unsigned char e; + unsigned char pad2[3]; +} __attribute__((packed)); + +struct A d; +int main(void) +{ + struct A *p; + p = malloc(12); + d.a = 1; + d.b = 2; + d.c = 3; + d.d = 4; + d.e = 5; + memcpy(p, &d, 4); + if (p->a != 1) { + free(p); + } + if (p->b != 2) {//WARN + free(p);//WARN + } + if (p->c != 3) {//WARN + free(p);//WARN + } + if (p->d != 4) { //WARN + free(p);//WARN + } + free(p);//WARN +} + diff --git a/tests/regression/74-invalid_deref/17-scopes-no-static.c b/tests/regression/74-invalid_deref/17-scopes-no-static.c new file mode 100644 index 0000000000..e0c4b47b73 --- /dev/null +++ b/tests/regression/74-invalid_deref/17-scopes-no-static.c @@ -0,0 +1,22 @@ +// PARAM: --set ana.activated[+] memOutOfBounds +// TODO: I haven't checked why, but we need memOutOfBounds for this case +extern int printf ( const char * format, ... ); + +int *foo2(void) +{ + int arr[1024]; + arr[194] = 13; + return arr + 1; +} + +int *foo(void) +{ + int arr[123]; + return foo2(); +} + +int main(void) { + int *a = foo(); + printf("%d\n", *a);//WARN + return 0; +} diff --git a/tests/regression/74-use_after_free/01-simple-uaf.c b/tests/regression/74-invalid_deref/18-simple-uaf.c similarity index 100% rename from tests/regression/74-use_after_free/01-simple-uaf.c rename to tests/regression/74-invalid_deref/18-simple-uaf.c diff --git a/tests/regression/77-mem-oob/02-oob-stack-simple.c b/tests/regression/74-invalid_deref/19-oob-stack-simple.c similarity index 100% rename from tests/regression/77-mem-oob/02-oob-stack-simple.c rename to tests/regression/74-invalid_deref/19-oob-stack-simple.c diff --git a/tests/regression/74-invalid_deref/20-scopes-global-var.c b/tests/regression/74-invalid_deref/20-scopes-global-var.c new file mode 100644 index 0000000000..9491e1c574 --- /dev/null +++ b/tests/regression/74-invalid_deref/20-scopes-global-var.c @@ -0,0 +1,29 @@ +int array[10]; + +// function returns array of numbers +int* getNumbers(void) { + for (int i = 0; i < 10; ++i) { + array[i] = i;//NOWARN + } + + return array; +} + +int* getNumbers2(void) { + int* numbers = getNumbers(); + // numbers2 is local + int numbers2[10]; + + for (int i = 0; i < 10; ++i) { + numbers2[i] = numbers[i];//NOWARN + } + + return numbers2; +} + +int main(void) { + int *numbers = getNumbers2(); + numbers[0] = 100;//WARN + + return 0; +} diff --git a/tests/regression/77-mem-oob/03-oob-loop.c b/tests/regression/74-invalid_deref/21-oob-loop.c similarity index 100% rename from tests/regression/77-mem-oob/03-oob-loop.c rename to tests/regression/74-invalid_deref/21-oob-loop.c diff --git a/tests/regression/74-invalid_deref/22-scopes-static.c b/tests/regression/74-invalid_deref/22-scopes-static.c new file mode 100644 index 0000000000..c13b665c84 --- /dev/null +++ b/tests/regression/74-invalid_deref/22-scopes-static.c @@ -0,0 +1,52 @@ +extern int printf (const char* format, ...); + +// function returns array of numbers +int* getNumbers() { + + static int array[10]; + + for (int i = 0; i < 10; ++i) { + array[i] = i;//NOWARN + } + + return array; +} + +int* getNumbers2() { + int* numbers = getNumbers(); + static int numbers2[10]; + for (int i = 0; i < 10; ++i) { + numbers2[i] = numbers[i];//NOWARN + } + return numbers2; +} + +int* getNumbers3() { + int* numbers = getNumbers2(); + int numbers3[10]; + for (int i = 0; i < 10; ++i) { + numbers3[i] = numbers[i];//NOWARN + } + + return numbers3; +} + +int* getNumbers4() { + int* numbers = getNumbers3(); + static int numbers4[10]; + for (int i = 0; i < 10; ++i) { + numbers4[i] = numbers[i];//WARN + } + return numbers4; +} + +int main (void) { + + int *numbers = getNumbers4(); + + for (int i = 0; i < 10; i++ ) { + printf( "%d\n", *(numbers + i));//NOWARN + } + + return 0; +} diff --git a/tests/regression/77-mem-oob/04-oob-deref-after-ptr-arith.c b/tests/regression/74-invalid_deref/23-oob-deref-after-ptr-arith.c similarity index 100% rename from tests/regression/77-mem-oob/04-oob-deref-after-ptr-arith.c rename to tests/regression/74-invalid_deref/23-oob-deref-after-ptr-arith.c diff --git a/tests/regression/74-use_after_free/05-uaf-free-in-wrapper-fun.c b/tests/regression/74-invalid_deref/24-uaf-free-in-wrapper-fun.c similarity index 100% rename from tests/regression/74-use_after_free/05-uaf-free-in-wrapper-fun.c rename to tests/regression/74-invalid_deref/24-uaf-free-in-wrapper-fun.c diff --git a/tests/regression/74-use_after_free/06-uaf-struct.c b/tests/regression/74-invalid_deref/25-uaf-struct.c similarity index 100% rename from tests/regression/74-use_after_free/06-uaf-struct.c rename to tests/regression/74-invalid_deref/25-uaf-struct.c diff --git a/tests/regression/77-mem-oob/09-memset-memcpy-addr-offs.c b/tests/regression/74-invalid_deref/26-memset-memcpy-addr-offs.c similarity index 100% rename from tests/regression/77-mem-oob/09-memset-memcpy-addr-offs.c rename to tests/regression/74-invalid_deref/26-memset-memcpy-addr-offs.c diff --git a/tests/regression/74-use_after_free/11-wrapper-funs-uaf.c b/tests/regression/74-invalid_deref/27-wrapper-funs-uaf.c similarity index 100% rename from tests/regression/74-use_after_free/11-wrapper-funs-uaf.c rename to tests/regression/74-invalid_deref/27-wrapper-funs-uaf.c diff --git a/tests/regression/74-use_after_free/12-multi-threaded-uaf.c b/tests/regression/74-invalid_deref/28-multi-threaded-uaf.c similarity index 100% rename from tests/regression/74-use_after_free/12-multi-threaded-uaf.c rename to tests/regression/74-invalid_deref/28-multi-threaded-uaf.c diff --git a/tests/regression/74-use_after_free/13-multi-threaded-uaf-with-joined-thread.c b/tests/regression/74-invalid_deref/29-multi-threaded-uaf-with-joined-thread.c similarity index 100% rename from tests/regression/74-use_after_free/13-multi-threaded-uaf-with-joined-thread.c rename to tests/regression/74-invalid_deref/29-multi-threaded-uaf-with-joined-thread.c diff --git a/tests/regression/75-invalid_dealloc/01-invalid-dealloc-simple.c b/tests/regression/75-invalid_free/01-invalid-dealloc-simple.c similarity index 100% rename from tests/regression/75-invalid_dealloc/01-invalid-dealloc-simple.c rename to tests/regression/75-invalid_free/01-invalid-dealloc-simple.c diff --git a/tests/regression/75-invalid_dealloc/02-invalid-dealloc-struct.c b/tests/regression/75-invalid_free/02-invalid-dealloc-struct.c similarity index 100% rename from tests/regression/75-invalid_dealloc/02-invalid-dealloc-struct.c rename to tests/regression/75-invalid_free/02-invalid-dealloc-struct.c diff --git a/tests/regression/75-invalid_dealloc/03-invalid-dealloc-array.c b/tests/regression/75-invalid_free/03-invalid-dealloc-array.c similarity index 100% rename from tests/regression/75-invalid_dealloc/03-invalid-dealloc-array.c rename to tests/regression/75-invalid_free/03-invalid-dealloc-array.c diff --git a/tests/regression/75-invalid_dealloc/04-invalid-realloc.c b/tests/regression/75-invalid_free/04-invalid-realloc.c similarity index 100% rename from tests/regression/75-invalid_dealloc/04-invalid-realloc.c rename to tests/regression/75-invalid_free/04-invalid-realloc.c diff --git a/tests/regression/75-invalid_dealloc/05-free-at-offset.c b/tests/regression/75-invalid_free/05-free-at-offset.c similarity index 100% rename from tests/regression/75-invalid_dealloc/05-free-at-offset.c rename to tests/regression/75-invalid_free/05-free-at-offset.c diff --git a/tests/regression/75-invalid_dealloc/06-realloc-at-offset.c b/tests/regression/75-invalid_free/06-realloc-at-offset.c similarity index 100% rename from tests/regression/75-invalid_dealloc/06-realloc-at-offset.c rename to tests/regression/75-invalid_free/06-realloc-at-offset.c diff --git a/tests/regression/75-invalid_dealloc/07-free-at-struct-offset.c b/tests/regression/75-invalid_free/07-free-at-struct-offset.c similarity index 100% rename from tests/regression/75-invalid_dealloc/07-free-at-struct-offset.c rename to tests/regression/75-invalid_free/07-free-at-struct-offset.c diff --git a/tests/regression/74-use_after_free/08-itc-no-double-free.c b/tests/regression/75-invalid_free/08-itc-no-double-free.c similarity index 100% rename from tests/regression/74-use_after_free/08-itc-no-double-free.c rename to tests/regression/75-invalid_free/08-itc-no-double-free.c diff --git a/tests/regression/75-invalid_dealloc/09-juliet-invalid-dealloc-alloca.c b/tests/regression/75-invalid_free/09-juliet-invalid-dealloc-alloca.c similarity index 100% rename from tests/regression/75-invalid_dealloc/09-juliet-invalid-dealloc-alloca.c rename to tests/regression/75-invalid_free/09-juliet-invalid-dealloc-alloca.c diff --git a/tests/regression/75-invalid_free/10-invalid-dealloc-union.c b/tests/regression/75-invalid_free/10-invalid-dealloc-union.c new file mode 100644 index 0000000000..be1eaa056d --- /dev/null +++ b/tests/regression/75-invalid_free/10-invalid-dealloc-union.c @@ -0,0 +1,42 @@ +extern void abort(void); +#include + +extern int __VERIFIER_nondet_int(void); + +int main() +{ + union { + void *p0; + + struct { + char c[2]; + int p1; + int p2; + } str; + + } data; + + // alloc 37B on heap + data.p0 = malloc(37U); + + // avoid introducing a memleak + void *ptr = data.p0; + + // this should be fine + if(__VERIFIER_nondet_int()) { + data.str.p2 = 20; + } else { + data.str.p2 = 30; + } + + if(25 > data.str.p2) { + // avoids memleak + data.str.c[1] = sizeof data.str.p1; + } + + // invalid free() + free(data.p0);//WARN + + free(ptr);//NOWARN + return 0; +} diff --git a/tests/regression/74-use_after_free/07-itc-double-free.c b/tests/regression/75-invalid_free/11-itc-double-free.c similarity index 100% rename from tests/regression/74-use_after_free/07-itc-double-free.c rename to tests/regression/75-invalid_free/11-itc-double-free.c diff --git a/tests/regression/75-invalid_dealloc/08-realloc-at-struct-offset.c b/tests/regression/75-invalid_free/12-realloc-at-struct-offset.c similarity index 100% rename from tests/regression/75-invalid_dealloc/08-realloc-at-struct-offset.c rename to tests/regression/75-invalid_free/12-realloc-at-struct-offset.c diff --git a/tests/regression/74-use_after_free/10-juliet-double-free.c b/tests/regression/75-invalid_free/13-juliet-double-free.c similarity index 100% rename from tests/regression/74-use_after_free/10-juliet-double-free.c rename to tests/regression/75-invalid_free/13-juliet-double-free.c diff --git a/tests/sv-comp/valid-memcleanup.prp b/tests/sv-comp/valid-memcleanup.prp new file mode 100644 index 0000000000..778c49e5dc --- /dev/null +++ b/tests/sv-comp/valid-memcleanup.prp @@ -0,0 +1,2 @@ +CHECK( init(main()), LTL(G valid-memcleanup) ) + From 58445527a7e46dfce695a36cd0d97e1e7840b9e3 Mon Sep 17 00:00:00 2001 From: Michael Schwarz Date: Sat, 14 Oct 2023 11:37:03 +0200 Subject: [PATCH 280/327] Cleanup termination property --- src/witness/svcompSpec.ml | 46 +++++++++++++++++++++++++-------------- 1 file changed, 30 insertions(+), 16 deletions(-) diff --git a/src/witness/svcompSpec.ml b/src/witness/svcompSpec.ml index de2d7c5283..ceedfcc8a9 100644 --- a/src/witness/svcompSpec.ml +++ b/src/witness/svcompSpec.ml @@ -18,14 +18,13 @@ let of_string s = let regexp_multiple = Str.regexp "CHECK( init(main()), LTL(G \\(.*\\)) )\nCHECK( init(main()), LTL(G \\(.*\\)) )\nCHECK( init(main()), LTL(G \\(.*\\)) )" in let regexp_single = Str.regexp "CHECK( init(main()), LTL(G \\(.*\\)) )" in let regexp_negated = Str.regexp "CHECK( init(main()), LTL(G ! \\(.*\\)) )" in + let regexp_finally = Str.regexp "CHECK( init(main()), LTL(F \\(.*\\)) )" in if Str.string_match regexp_negated s 0 then let global_not = Str.matched_group 1 s in if global_not = "data-race" then NoDataRace else if global_not = "overflow" then NoOverflow - else if global_not = "no-termination" then - Termination else let call_regex = Str.regexp "call(\\(.*\\)())" in if Str.string_match call_regex global_not 0 then @@ -48,6 +47,12 @@ let of_string s = ValidMemcleanup else failwith "Svcomp.Specification.of_string: unknown global expression" + else if Str.string_match regexp_finally s 0 then + let finally = Str.matched_group 1 s in + if finally = "end" then + Termination + else + failwith "Svcomp.Specification.of_string: unknown finally expression" else failwith "Svcomp.Specification.of_string: unknown expression" @@ -63,21 +68,30 @@ let of_option () = of_string s let to_string spec = - let print_output spec_str is_neg = + let module Prop = struct + type prop = F | G + let string_of_prop = function + | F -> "F" + | G -> "G" + end + in + let open Prop in + let print_output prop spec_str is_neg = + let prop = string_of_prop prop in if is_neg then - Printf.sprintf "CHECK( init(main()), LTL(G ! %s) )" spec_str + Printf.sprintf "CHECK( init(main()), LTL(%s ! %s) )" prop spec_str else - Printf.sprintf "CHECK( init(main()), LTL(G %s) )" spec_str + Printf.sprintf "CHECK( init(main()), LTL(%s %s) )" prop spec_str in - let spec_str, is_neg = match spec with - | UnreachCall f -> "call(" ^ f ^ "())", true - | NoDataRace -> "data-race", true - | NoOverflow -> "overflow", true - | ValidFree -> "valid-free", false - | ValidDeref -> "valid-deref", false - | ValidMemtrack -> "valid-memtrack", false - | Termination -> "no-termination", true - | MemorySafety -> "memory-safety", false (* TODO: That's false, it's currently here just to complete the pattern match *) - | ValidMemcleanup -> "valid-memcleanup", false + let prop, spec_str, is_neg = match spec with + | UnreachCall f -> G, "call(" ^ f ^ "())", true + | NoDataRace -> G, "data-race", true + | NoOverflow -> G, "overflow", true + | ValidFree -> G, "valid-free", false + | ValidDeref -> G, "valid-deref", false + | ValidMemtrack -> G, "valid-memtrack", false + | MemorySafety -> G, "memory-safety", false (* TODO: That's false, it's currently here just to complete the pattern match *) + | ValidMemcleanup -> G, "valid-memcleanup", false + | Termination -> F, "termination", false in - print_output spec_str is_neg + print_output prop spec_str is_neg From 7cca2cf595a506e6ab9865633c192d304d8c76f1 Mon Sep 17 00:00:00 2001 From: Michael Schwarz Date: Sat, 14 Oct 2023 11:39:26 +0200 Subject: [PATCH 281/327] LTL for termination is `F end` --- src/witness/svcompSpec.ml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/witness/svcompSpec.ml b/src/witness/svcompSpec.ml index ceedfcc8a9..e51e691154 100644 --- a/src/witness/svcompSpec.ml +++ b/src/witness/svcompSpec.ml @@ -92,6 +92,6 @@ let to_string spec = | ValidMemtrack -> G, "valid-memtrack", false | MemorySafety -> G, "memory-safety", false (* TODO: That's false, it's currently here just to complete the pattern match *) | ValidMemcleanup -> G, "valid-memcleanup", false - | Termination -> F, "termination", false + | Termination -> F, "end", false in print_output prop spec_str is_neg From a7d02c42ddcdb21c5042b28d0af7d39a0058a6cf Mon Sep 17 00:00:00 2001 From: Michael Schwarz Date: Wed, 1 Nov 2023 18:25:55 +0100 Subject: [PATCH 282/327] Simplify warning --- src/analyses/loopTermination.ml | 8 ++------ src/framework/constraints.ml | 14 +++----------- src/framework/control.ml | 7 +------ 3 files changed, 6 insertions(+), 23 deletions(-) diff --git a/src/analyses/loopTermination.ml b/src/analyses/loopTermination.ml index 61034a57c0..077615ad10 100644 --- a/src/analyses/loopTermination.ml +++ b/src/analyses/loopTermination.ml @@ -64,12 +64,8 @@ struct ctx.sideg () (G.add (`Lifted loop_statement) is_bounded (ctx.global ())); (* In case the loop is not bounded, a warning is created. *) if not (is_bounded) then ( - let msgs = - [(Pretty.dprintf - "The program might not terminate! (Loop analysis)", - Some (M.Location.CilLocation (Cilfacade.get_stmtLoc loop_statement)) - );] in - M.msg_group Warning ~category:NonTerminating "Possibly non terminating loops" msgs); + M.warn ~loc:(M.Location.CilLocation (Cilfacade.get_stmtLoc loop_statement)) ~category:NonTerminating "The program might not terminate! (Loop analysis)" + ); () with Not_found -> failwith "Encountered a call to __goblint_bounded with an unknown loop counter variable.") diff --git a/src/framework/constraints.ml b/src/framework/constraints.ml index 963e6e4996..307f6d0260 100644 --- a/src/framework/constraints.ml +++ b/src/framework/constraints.ml @@ -1688,12 +1688,7 @@ struct List.iter handle_path (S.paths_as_set conv_ctx); if !AnalysisState.should_warn && List.mem "termination" @@ get_string_list "ana.activated" then ( AnalysisState.svcomp_may_not_terminate := true; - let msgs = - [(Pretty.dprintf - "The program might not terminate! (Longjmp)", - None - );] in - M.msg_group Warning ~category:NonTerminating "Possibly non terminating loops" msgs + M.warn ~category:NonTerminating "The program might not terminate! (Longjmp)" ); S.D.bot () | _ -> S.special conv_ctx lv f args @@ -1777,11 +1772,8 @@ struct if LS.mem call path_visited_calls then ( AnalysisState.svcomp_may_not_terminate := true; (*set the indicator for a non-terminating program for the sv comp*) (*Cycle found*) - let msgs = - [ - (Pretty.dprintf "The program might not terminate! (Fundec %a is contained in a call graph cycle)" CilType.Fundec.pretty fundec, Some (M.Location.CilLocation fundec.svar.vdecl)); - ] in - M.msg_group Warning ~category:NonTerminating "Recursion cycle" msgs) (* output a warning for non-termination*) + let loc = M.Location.CilLocation fundec.svar.vdecl in + M.warn ~loc ~category:NonTerminating "The program might not terminate! (Fundec %a is contained in a call graph cycle)" CilType.Fundec.pretty fundec) (* output a warning for non-termination*) else if not (LH.mem global_visited_calls call) then begin LH.replace global_visited_calls call (); let new_path_visited_calls = LS.add call path_visited_calls in diff --git a/src/framework/control.ml b/src/framework/control.ml index 65eda50f03..8768fa00c9 100644 --- a/src/framework/control.ml +++ b/src/framework/control.ml @@ -146,12 +146,7 @@ struct let fundec_live = live fi fname in if ( not (BatISet.is_empty fundec_live)) then ( AnalysisState.svcomp_may_not_terminate := true; - let msgs = - [(Pretty.dprintf - "The program might not terminate! (Upjumping Goto)", - Some (M.Location.CilLocation l) - );] in - M.msg_group Warning ~category:NonTerminating "Possibly non terminating loops" msgs); + M.warn ~loc:(M.Location.CilLocation l) ~category:NonTerminating "The program might not terminate! (Upjumping Goto)"); ) (!live_lines)) (!Cilfacade.upjumping_gotos); From cf22550ceb4e9e0a70ec193f0d64294b0ce8d340 Mon Sep 17 00:00:00 2001 From: Michael Schwarz Date: Wed, 1 Nov 2023 18:36:03 +0100 Subject: [PATCH 283/327] Delete old termination analysis --- src/analyses/termination.ml | 239 ------------------------------------ 1 file changed, 239 deletions(-) delete mode 100644 src/analyses/termination.ml diff --git a/src/analyses/termination.ml b/src/analyses/termination.ml deleted file mode 100644 index 6da9225d3f..0000000000 --- a/src/analyses/termination.ml +++ /dev/null @@ -1,239 +0,0 @@ -(** Termination analysis of loops using counter variables ([term]). *) - -open Batteries -open GoblintCil -open Analyses - -module M = Messages -let (||?) a b = match a,b with Some x,_ | _, Some x -> Some x | _ -> None - -module TermDomain = struct - include SetDomain.ToppedSet (Basetype.Variables) (struct let topname = "All Variables" end) -end - -(* some kind of location string suitable for variable names? *) -let show_location_id l = - string_of_int l.line ^ "_" ^ string_of_int l.column - -class loopCounterVisitor (fd : fundec) = object(self) - inherit nopCilVisitor - method! vstmt s = - let action s = match s.skind with - | Loop (b, loc, eloc, _, _) -> - (* insert loop counter variable *) - let name = "term"^show_location_id loc in - let typ = intType in (* TODO the type should be the same as the one of the original loop counter *) - let v = Cilfacade.create_var (makeLocalVar fd name ~init:(SingleInit zero) typ) in - (* make an init stmt since the init above is apparently ignored *) - let init_stmt = mkStmtOneInstr @@ Set (var v, zero, loc, eloc) in - (* increment it every iteration *) - let inc_stmt = mkStmtOneInstr @@ Set (var v, increm (Lval (var v)) 1, loc, eloc) in - b.bstmts <- inc_stmt :: b.bstmts; - let nb = mkBlock [init_stmt; mkStmt s.skind] in - s.skind <- Block nb; - s - | _ -> s - in ChangeDoChildrenPost (s, action) -end - -let loopBreaks : (int, location) Hashtbl.t = Hashtbl.create 13 (* break stmt sid -> corresponding loop *) -class loopBreaksVisitor (fd : fundec) = object(self) - inherit nopCilVisitor - method! vstmt s = - (match s.skind with - | Loop (b, loc, eloc, Some continue, Some break) -> Hashtbl.add loopBreaks break.sid loc (* TODO: use eloc? *) - | Loop _ -> failwith "Termination.preprocess: every loop should have a break and continue stmt after prepareCFG" - | _ -> ()); - DoChildren -end - -(* if the given block contains a goto while_break.* we have the termination condition for a loop *) -let exits = function - | { bstmts = [{ skind = Goto (stmt, loc); _ }]; _ } -> Hashtbl.find_option loopBreaks !stmt.sid - | _ -> None (* TODO handle return (need to find out what loop we are in) *) - -let lvals_of_expr = - let rec f a = function - | Const _ | SizeOf _ | SizeOfStr _ | AlignOf _ | AddrOfLabel _ -> a - | Lval l | AddrOf l | StartOf l -> l :: a - | SizeOfE e | AlignOfE e | UnOp (_,e,_) | CastE (_,e) | Imag e | Real e -> f a e - | BinOp (_,e1,e2,_) -> f a e1 @ f a e2 - | Question (c,t,e,_) -> f a c @ f a t @ f a e - in f [] - -let loopVars : (location, lval) Hashtbl.t = Hashtbl.create 13 (* loop location -> lval used for exit *) -class loopVarsVisitor (fd : fundec) = object - inherit nopCilVisitor - method! vstmt s = - let add_exit_cond e loc = - match lvals_of_expr e with - | [lval] when Cilfacade.typeOf e |> isArithmeticType -> Hashtbl.add loopVars loc lval - | _ -> () - in - (match s.skind with - | If (e, tb, fb, loc, eloc) -> Option.map_default (add_exit_cond e) () (exits tb ||? exits fb) - | _ -> ()); - DoChildren -end - -let stripCastsDeep e = - let v = object - inherit nopCilVisitor - method! vexpr e = ChangeTo (stripCasts e) - end - in visitCilExpr v e - -(* keep the enclosing loop for statements *) -let cur_loop = ref None (* current loop *) -let cur_loop' = ref None (* for nested loops *) -let makeVar fd loc name = - let id = name ^ "__" ^ show_location_id loc in - try List.find (fun v -> v.vname = id) fd.slocals - with Not_found -> - let typ = intType in (* TODO the type should be the same as the one of the original loop counter *) - Cilfacade.create_var (makeLocalVar fd id ~init:(SingleInit zero) typ) -let f_assume = Lval (var (emptyFunction "__goblint_assume").svar) -let f_check = Lval (var (emptyFunction "__goblint_check").svar) -class loopInstrVisitor (fd : fundec) = object(self) - inherit nopCilVisitor - method! vstmt s = - (* TODO: use Loop eloc? *) - (match s.skind with - | Loop (_, loc, eloc, _, _) -> - cur_loop' := !cur_loop; - cur_loop := Some loc - | _ -> ()); - let action s = - (* first, restore old cur_loop *) - (match s.skind with - | Loop (_, loc, eloc, _, _) -> - cur_loop := !cur_loop'; - | _ -> ()); - let in_loop () = Option.is_some !cur_loop && Hashtbl.mem loopVars (Option.get !cur_loop) in - match s.skind with - | Loop (b, loc, eloc, Some continue, Some break) when Hashtbl.mem loopVars loc -> - (* find loop var for current loop *) - let x = Hashtbl.find loopVars loc in - (* insert loop counter and diff to loop var *) - let t = var @@ makeVar fd loc "t" in - let d1 = var @@ makeVar fd loc "d1" in - let d2 = var @@ makeVar fd loc "d2" in - (* make init stmts *) - let t_init = mkStmtOneInstr @@ Set (t, zero, loc, eloc) in - let d1_init = mkStmtOneInstr @@ Set (d1, Lval x, loc, eloc) in - let d2_init = mkStmtOneInstr @@ Set (d2, Lval x, loc, eloc) in - (* increment/decrement in every iteration *) - let t_inc = mkStmtOneInstr @@ Set (t, increm (Lval t) 1, loc, eloc) in - let d1_inc = mkStmtOneInstr @@ Set (d1, increm (Lval d1) (-1), loc, eloc) in - let d2_inc = mkStmtOneInstr @@ Set (d2, increm (Lval d2) 1 , loc, eloc) in - let typ = intType in - let e1 = BinOp (Eq, Lval t, BinOp (MinusA, Lval x, Lval d1, typ), typ) in - let e2 = BinOp (Eq, Lval t, BinOp (MinusA, Lval d2, Lval x, typ), typ) in - let inv1 = mkStmtOneInstr @@ Call (None, f_assume, [e1], loc, eloc) in - let inv2 = mkStmtOneInstr @@ Call (None, f_assume, [e2], loc, eloc) in - (match b.bstmts with - | cont :: cond :: ss -> - (* changing succs/preds directly doesn't work -> need to replace whole stmts *) - b.bstmts <- cont :: cond :: inv1 :: inv2 :: d1_inc :: d2_inc :: t_inc :: ss; - let nb = mkBlock [t_init; d1_init; d2_init; mkStmt s.skind] in - s.skind <- Block nb; - | _ -> ()); - s - | Loop (b, loc, eloc, Some continue, Some break) -> - print_endline @@ "WARN: Could not determine loop variable for loop at " ^ CilType.Location.show loc; - s - | _ when Hashtbl.mem loopBreaks s.sid -> (* after a loop, we check that t is bounded/positive (no overflow happened) *) - let loc = Hashtbl.find loopBreaks s.sid in - let t = var @@ makeVar fd loc "t" in - let e3 = BinOp (Ge, Lval t, zero, intType) in - let inv3 = mkStmtOneInstr @@ Call (None, f_check, [e3], loc, locUnknown) in - let nb = mkBlock [mkStmt s.skind; inv3] in - s.skind <- Block nb; - s - | Instr [Set (lval, e, loc, eloc)] when in_loop () -> - (* find loop var for current loop *) - let cur_loop = Option.get !cur_loop in - let x = Hashtbl.find loopVars cur_loop in - if x <> lval then - s - else (* we only care about the loop var *) - let d1 = makeVar fd cur_loop "d1" in - let d2 = makeVar fd cur_loop "d2" in - (match stripCastsDeep e with - | BinOp (op, Lval x', e2, typ) when (op = PlusA || op = MinusA) && x' = x && isArithmeticType typ -> (* TODO x = 1 + x, MinusA! *) - (* increase diff by same expr *) - let d1_inc = mkStmtOneInstr @@ Set (var d1, BinOp (PlusA, Lval (var d1), e2, typ), loc, eloc) in - let d2_inc = mkStmtOneInstr @@ Set (var d2, BinOp (PlusA, Lval (var d2), e2, typ), loc, eloc) in - let nb = mkBlock [d1_inc; d2_inc; mkStmt s.skind] in - s.skind <- Block nb; - s - | _ -> - (* otherwise diff is e - counter *) - let t = makeVar fd cur_loop "t" in - let te = Cilfacade.typeOf e in - let dt1 = mkStmtOneInstr @@ Set (var d1, BinOp (MinusA, Lval x, Lval (var t), te), loc, eloc) in - let dt2 = mkStmtOneInstr @@ Set (var d2, BinOp (MinusA, Lval x, Lval (var t), te), loc, eloc) in - let nb = mkBlock [mkStmt s.skind; dt1; dt2] in - s.skind <- Block nb; - s - ) - | _ -> s - in - ChangeDoChildrenPost (s, action) -end - - -module Spec = -struct - include Analyses.IdentitySpec - - let name () = "term" - module D = TermDomain - module C = TermDomain - - (* queries *) - (*let query ctx (q:Queries.t) : Queries.Result.t =*) - (*match q with*) - (*| Queries.MustTerm loc -> `Bool (D.mem v ctx.local)*) - (*| _ -> Queries.Result.top ()*) - - (* transfer functions *) - - let branch ctx (exp:exp) (tv:bool) : D.t = - ctx.local - (* if the then-block contains a goto while_break.* we have the termination condition for a loop *) - (* match !MyCFG.current_node with *) - (* | Some (MyCFG.Statement({ skind = If (e, tb, fb, loc) })) -> *) - (* let str_exit b = match exits b with Some loc -> string_of_int loc.line | None -> "None" in *) - (* M.debug @@ *) - (* "\nCil-exp: " ^ sprint d_exp e *) - (* (*^ "; Goblint-exp: " ^ sprint d_exp exp*) *) - (* ^ "; Goblint: " ^ sprint Queries.Result.pretty (ctx.ask (Queries.EvalInt exp)) *) - (* ^ "\nCurrent block: " ^ (if tv then "Then" else "Else") *) - (* ^ "\nThen block (exits " ^ str_exit tb ^ "): " ^ sprint d_block tb *) - (* ^ "\nElse block (exits " ^ str_exit fb ^ "): " ^ sprint d_block fb *) - (* ; *) - (* ctx.local *) - (* | _ -> ctx.local *) - - let startstate v = D.bot () - let threadenter ctx lval f args = [D.bot ()] - let exitstate v = D.bot () -end - -class recomputeVisitor (fd : fundec) = object(self) - inherit nopCilVisitor - method! vfunc fd = - computeCFGInfo fd true; - SkipChildren -end - -let _ = - (* Cilfacade.register_preprocess Spec.name (new loopCounterVisitor); *) - Cilfacade.register_preprocess (Spec.name ()) (new loopBreaksVisitor); - Cilfacade.register_preprocess (Spec.name ()) (new loopVarsVisitor); - Cilfacade.register_preprocess (Spec.name ()) (new loopInstrVisitor); - Cilfacade.register_preprocess (Spec.name ()) (new recomputeVisitor); - Hashtbl.clear loopBreaks; (* because the sids are now different *) - Cilfacade.register_preprocess (Spec.name ()) (new loopBreaksVisitor); - MCP.register_analysis (module Spec : MCPSpec) From 67cc037057a69e446bc35e906e256a5c63621138 Mon Sep 17 00:00:00 2001 From: Michael Schwarz Date: Wed, 1 Nov 2023 18:36:59 +0100 Subject: [PATCH 284/327] Rm old Termination also from `goblint_lib.ml` --- src/goblint_lib.ml | 1 - 1 file changed, 1 deletion(-) diff --git a/src/goblint_lib.ml b/src/goblint_lib.ml index a71a0c9684..e1087f8fc9 100644 --- a/src/goblint_lib.ml +++ b/src/goblint_lib.ml @@ -149,7 +149,6 @@ module UnitAnalysis = UnitAnalysis module Assert = Assert module FileUse = FileUse module Uninit = Uninit -module Termination = Termination module Expsplit = Expsplit module StackTrace = StackTrace module Spec = Spec From dff7be0446336b3e9ac8810fce326004f767a293 Mon Sep 17 00:00:00 2001 From: Michael Schwarz Date: Wed, 1 Nov 2023 18:54:43 +0100 Subject: [PATCH 285/327] Make `do_preprocess_cil` more efficient --- src/common/util/cilfacade.ml | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/src/common/util/cilfacade.ml b/src/common/util/cilfacade.ml index 2075cda890..47cf6d6210 100644 --- a/src/common/util/cilfacade.ml +++ b/src/common/util/cilfacade.ml @@ -93,12 +93,13 @@ let register_preprocess_cil name visitor_fun = visitors_cil := !visitors_cil @ [name, visitor_fun] let do_preprocess_cil ast = - let f fd (name, visitor_fun) = - (* this has to be done here, since the settings aren't available when register_preprocess is called *) - if List.mem name (get_string_list "ana.activated") then - ignore @@ visitCilFunction (visitor_fun fd) fd - in - iterGlobals ast (function GFun (fd,_) -> List.iter (f fd) !visitors_cil | _ -> ()) + (* this has to be done here, since the settings aren't available when register_preprocess is called *) + let active_visitors = List.filter_map (fun (name, visitor_fun) -> if List.mem name (get_string_list "ana.activated") then Some visitor_fun else None) !visitors_cil in + let f fd visitor_fun = ignore @@ visitCilFunction (visitor_fun fd) fd in + if active_visitors <> [] then + iterGlobals ast (function GFun (fd,_) -> List.iter (f fd) active_visitors | _ -> ()) + else + () (** @raise GoblintCil.FrontC.ParseError @raise GoblintCil.Errormsg.Error *) From 2d8fe096da4f54d585ce65748a28cf06de18d124 Mon Sep 17 00:00:00 2001 From: Michael Schwarz Date: Wed, 1 Nov 2023 18:59:03 +0100 Subject: [PATCH 286/327] Remove outdated TODO --- src/witness/witness.ml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/witness/witness.ml b/src/witness/witness.ml index 08a796c307..1612667a30 100644 --- a/src/witness/witness.ml +++ b/src/witness/witness.ml @@ -475,7 +475,7 @@ struct in (module TaskResult:WitnessTaskResult) ) - | Termination -> (* TODO: implement this properly*) + | Termination -> let module TrivialArg = struct include Arg From e690d9ad81291ee34360e72fd2aceb33742c5d2d Mon Sep 17 00:00:00 2001 From: Michael Schwarz Date: Thu, 2 Nov 2023 16:11:18 +0100 Subject: [PATCH 287/327] Prioritze termination warnings in `update_suite.rb` --- scripts/update_suite.rb | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/scripts/update_suite.rb b/scripts/update_suite.rb index 28d6ddb52d..a7d60b5c21 100755 --- a/scripts/update_suite.rb +++ b/scripts/update_suite.rb @@ -160,13 +160,13 @@ def collect_warnings when /invariant confirmed/ then "success" when /invariant unconfirmed/ then "unknown" when /invariant refuted/ then "fail" + when /(Upjumping Goto)/ then "goto" + when /(Fundec \w+ is contained in a call graph cycle)/ then "fundec" + when /(Loop analysis)/ then "loop" when /^\[Warning\]/ then "warn" when /^\[Error\]/ then "warn" when /^\[Info\]/ then "warn" when /^\[Success\]/ then "success" - when /(Upjumping Goto)/ then "goto" - when /(Fundec \w+ is contained in a call graph cycle)/ then "fundec" - when /(Loop analysis)/ then "loop" when /\[Debug\]/ then next # debug "warnings" shouldn't count as other warnings (against NOWARN) when /^ on line \d+ $/ then next # dead line warnings shouldn't count (used for unreachability with NOWARN) when /^ on lines \d+..\d+ $/ then next # dead line warnings shouldn't count (used for unreachability with NOWARN) From fb92abc2904021e5ec3f7bf075b25bf305a97c14 Mon Sep 17 00:00:00 2001 From: Michael Schwarz Date: Fri, 10 Nov 2023 19:24:20 +0100 Subject: [PATCH 288/327] Rename NonTerminating -> Termination --- scripts/update_suite.rb | 2 +- src/analyses/loopTermination.ml | 4 ++-- src/common/util/messageCategory.ml | 10 +++++----- src/common/util/options.schema.json | 6 +++--- src/framework/constraints.ml | 4 ++-- src/framework/control.ml | 2 +- 6 files changed, 14 insertions(+), 14 deletions(-) diff --git a/scripts/update_suite.rb b/scripts/update_suite.rb index a7d60b5c21..bbf1a71a9d 100755 --- a/scripts/update_suite.rb +++ b/scripts/update_suite.rb @@ -145,7 +145,7 @@ def collect_warnings @vars = $1 @evals = $2 end - if l =~ /\[NonTerminating\]/ then warnings[-1] = "nonterm" end # Get NonTerminating warning + if l =~ /\[Termination\]/ then warnings[-1] = "nonterm" end # Get Termination warning next unless l =~ /(.*)\(.*?\:(\d+)(?:\:\d+)?(?:-(?:\d+)(?:\:\d+)?)?\)/ obj,i = $1,$2.to_i diff --git a/src/analyses/loopTermination.ml b/src/analyses/loopTermination.ml index 077615ad10..f4db165795 100644 --- a/src/analyses/loopTermination.ml +++ b/src/analyses/loopTermination.ml @@ -49,7 +49,7 @@ struct let finalize () = (* Multithreaded *) if not (!single_thread) then ( - M.warn ~category:NonTerminating "The program might not terminate! (Multithreaded)\n" + M.warn ~category:Termination "The program might not terminate! (Multithreaded)\n" ) (** Recognizes a call of [__goblint_bounded] to check the EvalInt of the @@ -64,7 +64,7 @@ struct ctx.sideg () (G.add (`Lifted loop_statement) is_bounded (ctx.global ())); (* In case the loop is not bounded, a warning is created. *) if not (is_bounded) then ( - M.warn ~loc:(M.Location.CilLocation (Cilfacade.get_stmtLoc loop_statement)) ~category:NonTerminating "The program might not terminate! (Loop analysis)" + M.warn ~loc:(M.Location.CilLocation (Cilfacade.get_stmtLoc loop_statement)) ~category:Termination "The program might not terminate! (Loop analysis)" ); () with Not_found -> diff --git a/src/common/util/messageCategory.ml b/src/common/util/messageCategory.ml index ba589db8d0..41c9bc08e1 100644 --- a/src/common/util/messageCategory.ml +++ b/src/common/util/messageCategory.ml @@ -46,7 +46,7 @@ type category = | Imprecise | Witness | Program - | NonTerminating + | Termination [@@deriving eq, ord, hash] type t = category [@@deriving eq, ord, hash] @@ -205,7 +205,7 @@ let should_warn e = | Imprecise -> "imprecise" | Witness -> "witness" | Program -> "program" - | NonTerminating -> "nonTerminating" + | Termination -> "termination" (* Don't forget to add option to schema! *) in get_bool ("warn." ^ (to_string e)) @@ -226,7 +226,7 @@ let path_show e = | Imprecise -> ["Imprecise"] | Witness -> ["Witness"] | Program -> ["Program"] - | NonTerminating -> ["NonTerminating"] + | Termination -> ["Termination"] let show x = String.concat " > " (path_show x) @@ -266,7 +266,7 @@ let categoryName = function | Overflow -> "Overflow"; | DivByZero -> "DivByZero") | Float -> "Float" - | NonTerminating -> "NonTerminating" + | Termination -> "Termination" let from_string_list (s: string list) = @@ -287,7 +287,7 @@ let from_string_list (s: string list) = | "imprecise" -> Imprecise | "witness" -> Witness | "program" -> Program - | "nonTerminating" -> NonTerminating + | "termination" -> Termination | _ -> Unknown let to_yojson x = `List (List.map (fun x -> `String x) (path_show x)) diff --git a/src/common/util/options.schema.json b/src/common/util/options.schema.json index c6e00d3da3..0b6f8b649f 100644 --- a/src/common/util/options.schema.json +++ b/src/common/util/options.schema.json @@ -2105,9 +2105,9 @@ "type": "boolean", "default": true }, - "nonTerminating": { - "title": "warn.nonTerminating", - "description": "Non Termination warning", + "termination": { + "title": "warn.termination", + "description": "Non-Termination warning", "type": "boolean", "default": true }, diff --git a/src/framework/constraints.ml b/src/framework/constraints.ml index 6ba31488de..b1bbc73660 100644 --- a/src/framework/constraints.ml +++ b/src/framework/constraints.ml @@ -1689,7 +1689,7 @@ struct List.iter handle_path (S.paths_as_set conv_ctx); if !AnalysisState.should_warn && List.mem "termination" @@ get_string_list "ana.activated" then ( AnalysisState.svcomp_may_not_terminate := true; - M.warn ~category:NonTerminating "The program might not terminate! (Longjmp)" + M.warn ~category:Termination "The program might not terminate! (Longjmp)" ); S.D.bot () | _ -> S.special conv_ctx lv f args @@ -1774,7 +1774,7 @@ struct AnalysisState.svcomp_may_not_terminate := true; (*set the indicator for a non-terminating program for the sv comp*) (*Cycle found*) let loc = M.Location.CilLocation fundec.svar.vdecl in - M.warn ~loc ~category:NonTerminating "The program might not terminate! (Fundec %a is contained in a call graph cycle)" CilType.Fundec.pretty fundec) (* output a warning for non-termination*) + M.warn ~loc ~category:Termination "The program might not terminate! (Fundec %a is contained in a call graph cycle)" CilType.Fundec.pretty fundec) (* output a warning for non-termination*) else if not (LH.mem global_visited_calls call) then begin LH.replace global_visited_calls call (); let new_path_visited_calls = LS.add call path_visited_calls in diff --git a/src/framework/control.ml b/src/framework/control.ml index ae1cb3e2b3..a78f125eae 100644 --- a/src/framework/control.ml +++ b/src/framework/control.ml @@ -146,7 +146,7 @@ struct let fundec_live = live fi fname in if ( not (BatISet.is_empty fundec_live)) then ( AnalysisState.svcomp_may_not_terminate := true; - M.warn ~loc:(M.Location.CilLocation l) ~category:NonTerminating "The program might not terminate! (Upjumping Goto)"); + M.warn ~loc:(M.Location.CilLocation l) ~category:Termination "The program might not terminate! (Upjumping Goto)"); ) (!live_lines)) (!Cilfacade.upjumping_gotos); From aad465cf1803bc9ee0d10373e90397e4f0809321 Mon Sep 17 00:00:00 2001 From: Michael Schwarz Date: Fri, 10 Nov 2023 19:33:35 +0100 Subject: [PATCH 289/327] Autotune for Termination --- src/autoTune.ml | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/src/autoTune.ml b/src/autoTune.ml index 8300241bac..c756b17eb2 100644 --- a/src/autoTune.ml +++ b/src/autoTune.ml @@ -243,7 +243,14 @@ let focusOnSpecification (spec: Svcomp.Specification.t) = | NoDataRace -> (*enable all thread analyses*) print_endline @@ "Specification: NoDataRace -> enabling thread analyses \"" ^ (String.concat ", " notNeccessaryThreadAnalyses) ^ "\""; enableAnalyses notNeccessaryThreadAnalyses; - | Termination -> () + | Termination -> + let terminationAnas = ["termination"; "isEverMultiThreaded"; "apron"] in + print_endline @@ "Specification: Termination -> enabling termination analyses \"" ^ (String.concat ", " terminationAnas) ^ "\""; + enableAnalyses terminationAnas; + set_string "sem.int.signed_overflow" "assume_none"; + set_bool "ana.int.interval" true; + set_string "ana.apron.domain" "polyhedra"; (* TODO: Needed? *) + () | NoOverflow -> (*We focus on integer analysis*) set_bool "ana.int.def_exc" true; set_bool "ana.int.interval" true From 2ff979bb14dd41896e1ad3f2c3dff6f1af574241 Mon Sep 17 00:00:00 2001 From: Michael Schwarz Date: Fri, 10 Nov 2023 19:54:35 +0100 Subject: [PATCH 290/327] Simplify variable names --- src/util/terminationPreprocessing.ml | 26 ++++++++++---------------- 1 file changed, 10 insertions(+), 16 deletions(-) diff --git a/src/util/terminationPreprocessing.ml b/src/util/terminationPreprocessing.ml index 32a9468233..8070438943 100644 --- a/src/util/terminationPreprocessing.ml +++ b/src/util/terminationPreprocessing.ml @@ -2,22 +2,16 @@ open GoblintCil module VarToStmt = Map.Make(CilType.Varinfo) (* maps varinfos (= loop counter variable) to the statement of the corresponding loop*) -let extract_file_name s = (*There still may be a need to filter more chars*) - let ls = String.split_on_char '/' s in (*Assuming '/' as path seperator*) - let ls = List.rev ls in - let s' = List.nth ls 0 in - let ls = String.split_on_char '.' s' in - let s' = List.nth ls 0 in - let without_spaces = String.split_on_char ' ' s' in - let s' = String.concat "" without_spaces in - s' - -let show_location_id l = - string_of_int l.line ^ "_" ^ string_of_int l.column ^ "-file" ^ "_" ^ extract_file_name l.file - class loopCounterVisitor lc (fd : fundec) = object(self) inherit nopCilVisitor + (* Counter of variables inserted for termination *) + val mutable vcounter = ref 0 + + method! vfunc _ = + vcounter := 0; + DoChildren + method! vstmt s = let specialFunction name = @@ -36,9 +30,9 @@ class loopCounterVisitor lc (fd : fundec) = object(self) let action s = match s.skind with | Loop (b, loc, eloc, _, _) -> - let name = "term"^show_location_id loc in - let typ = Cil.intType in - let v = (Cil.makeLocalVar fd name typ) in (*Not tested for incremental mode*) + let vname = "term" ^ string_of_int loc.line ^ "_" ^ string_of_int loc.column ^ "-id" ^ (string_of_int !vcounter) in + incr vcounter; + let v = Cil.makeLocalVar fd vname Cil.intType in (*Not tested for incremental mode*) let init_stmt = mkStmtOneInstr @@ Set (var v, min_int_exp, loc, eloc) in let inc_stmt = mkStmtOneInstr @@ Set (var v, increm (Lval (var v)) 1, loc, eloc) in let inc_stmt2 = mkStmtOneInstr @@ Set (var v, increm (Lval (var v)) 1, loc, eloc) in From b49356c2451d2576b73d2d42813aad01c37c5eaa Mon Sep 17 00:00:00 2001 From: Michael Schwarz Date: Fri, 10 Nov 2023 20:02:52 +0100 Subject: [PATCH 291/327] Deduplicate preprocessing --- src/analyses/loopTermination.ml | 2 +- src/common/util/cilfacade.ml | 16 +--------------- src/util/cilCfg.ml | 6 ++---- 3 files changed, 4 insertions(+), 20 deletions(-) diff --git a/src/analyses/loopTermination.ml b/src/analyses/loopTermination.ml index f4db165795..312bcfd9b9 100644 --- a/src/analyses/loopTermination.ml +++ b/src/analyses/loopTermination.ml @@ -99,5 +99,5 @@ struct end let () = - Cilfacade.register_preprocess_cil (Spec.name ()) (new loopCounterVisitor loop_counters); + Cilfacade.register_preprocess (Spec.name ()) (new loopCounterVisitor loop_counters); MCP.register_analysis (module Spec : MCPSpec) diff --git a/src/common/util/cilfacade.ml b/src/common/util/cilfacade.ml index 47cf6d6210..d645fd949d 100644 --- a/src/common/util/cilfacade.ml +++ b/src/common/util/cilfacade.ml @@ -74,27 +74,13 @@ let print (fileAST: file) = let rmTemps fileAST = RmUnused.removeUnused fileAST - let visitors = ref [] let register_preprocess name visitor_fun = visitors := !visitors @ [name, visitor_fun] let do_preprocess ast = - let f fd (name, visitor_fun) = - (* this has to be done here, since the settings aren't available when register_preprocess is called *) - if List.mem name (get_string_list "ana.activated") then - ignore @@ visitCilFunction (visitor_fun fd) fd - in - iterGlobals ast (function GFun (fd,_) -> List.iter (f fd) !visitors | _ -> ()) - -let visitors_cil = ref [] -(* does exactly the same as register_preprocess but it is executed earlier, before the CFG is created*) -let register_preprocess_cil name visitor_fun = - visitors_cil := !visitors_cil @ [name, visitor_fun] - -let do_preprocess_cil ast = (* this has to be done here, since the settings aren't available when register_preprocess is called *) - let active_visitors = List.filter_map (fun (name, visitor_fun) -> if List.mem name (get_string_list "ana.activated") then Some visitor_fun else None) !visitors_cil in + let active_visitors = List.filter_map (fun (name, visitor_fun) -> if List.mem name (get_string_list "ana.activated") then Some visitor_fun else None) !visitors in let f fd visitor_fun = ignore @@ visitCilFunction (visitor_fun fd) fd in if active_visitors <> [] then iterGlobals ast (function GFun (fd,_) -> List.iter (f fd) active_visitors | _ -> ()) diff --git a/src/util/cilCfg.ml b/src/util/cilCfg.ml index 72143e97d7..923cf7600b 100644 --- a/src/util/cilCfg.ml +++ b/src/util/cilCfg.ml @@ -42,6 +42,7 @@ let loopCount file = let createCFG (fileAST: file) = + Cilfacade.do_preprocess fileAST; (* The analyzer keeps values only for blocks. So if you want a value for every program point, each instruction *) (* needs to be in its own block. end_basic_blocks does that. *) (* After adding support for VLAs, there are new VarDecl instructions at the point where a variable was declared and *) @@ -50,7 +51,6 @@ let createCFG (fileAST: file) = (* Since we want the output of justcil to compile, we do not run allBB visitor if justcil is enable, regardless of *) (* exp.basic-blocks. This does not matter, as we will not run any analysis anyway, when justcil is enabled. *) (* the preprocessing must be done here, to add the changes of CIL to the CFG*) - Cilfacade.do_preprocess_cil fileAST; if not (get_bool "exp.basic-blocks") && not (get_bool "justcil") then end_basic_blocks fileAST; (* We used to renumber vids but CIL already generates them fresh, so no need. @@ -68,6 +68,4 @@ let createCFG (fileAST: file) = computeCFGInfo fd true | _ -> () ); - if get_bool "dbg.run_cil_check" then assert (Check.checkFile [] fileAST); - - Cilfacade.do_preprocess fileAST + if get_bool "dbg.run_cil_check" then assert (Check.checkFile [] fileAST); \ No newline at end of file From 490203df2dcf64cb8a9ccfcbd8286bc50f85e37a Mon Sep 17 00:00:00 2001 From: Michael Schwarz Date: Fri, 10 Nov 2023 20:21:51 +0100 Subject: [PATCH 292/327] Move `everMultiThreaded` to `threadflag` --- src/analyses/everMultiThreaded.ml | 47 ------------------------------- src/analyses/threadFlag.ml | 4 +++ src/autoTune.ml | 4 +-- src/framework/analyses.ml | 6 ++++ src/maingoblint.ml | 4 +-- 5 files changed, 14 insertions(+), 51 deletions(-) delete mode 100644 src/analyses/everMultiThreaded.ml diff --git a/src/analyses/everMultiThreaded.ml b/src/analyses/everMultiThreaded.ml deleted file mode 100644 index 2ab203887c..0000000000 --- a/src/analyses/everMultiThreaded.ml +++ /dev/null @@ -1,47 +0,0 @@ -(** Analysis to register whether any additional thread has ever been spawned ([evermultithreaded]). *) - -open Analyses - -module UnitV = -struct - include Printable.Unit - include StdV -end - -module Spec : Analyses.MCPSpec = -struct - - (** Provides some default implementations *) - include Analyses.IdentitySpec - - let name () = "evermultithreaded" - - module D = Lattice.Unit - module C = D - module V = UnitV - module G = BoolDomain.MayBool - - let startstate _ = () - let exitstate = startstate - - (** Sets the global invariant to true when a thread is spawned *) - let threadspawn ctx ~multiple lval f args fctx = - ctx.sideg () true; - () - - let query ctx (type a) (q: a Queries.t) : a Queries.result = - match q with - | Queries.IsEverMultiThreaded -> - (match ctx.global () with - (* I don't know why this wrapping in a match construct is necessary. - * Without it, the compiler throws an error. *) - true -> true - | false -> false) - | _ -> - Queries.Result.top q - -end - -let () = - (* Register this analysis within the master control program *) - MCP.register_analysis (module Spec : MCPSpec) diff --git a/src/analyses/threadFlag.ml b/src/analyses/threadFlag.ml index 6bd466caef..a751ae074a 100644 --- a/src/analyses/threadFlag.ml +++ b/src/analyses/threadFlag.ml @@ -21,6 +21,8 @@ struct module D = Flag module C = Flag module P = IdentityP (D) + module V = UnitV + module G = BoolDomain.MayBool let name () = "threadflag" @@ -44,6 +46,7 @@ struct match x with | Queries.MustBeSingleThreaded _ -> not (Flag.is_multi ctx.local) (* If this analysis can tell, it is the case since the start *) | Queries.MustBeUniqueThread -> not (Flag.is_not_main ctx.local) + | Queries.IsEverMultiThreaded -> (ctx.global () : bool) (* requires annotation to compile *) (* This used to be in base but also commented out. *) (* | Queries.MayBePublic _ -> Flag.is_multi ctx.local *) | _ -> Queries.Result.top x @@ -64,6 +67,7 @@ struct [create_tid f] let threadspawn ctx ~multiple lval f args fctx = + ctx.sideg () true; if not (has_ever_been_multi (Analyses.ask_of_ctx ctx)) then ctx.emit Events.EnterMultiThreaded; D.join ctx.local (Flag.get_main ()) diff --git a/src/autoTune.ml b/src/autoTune.ml index c756b17eb2..51e4ea412e 100644 --- a/src/autoTune.ml +++ b/src/autoTune.ml @@ -180,7 +180,7 @@ let enableAnalyses anas = List.iter (GobConfig.set_auto "ana.activated[+]") anas (*If only one thread is used in the program, we can disable most thread analyses*) -(*The exceptions are analyses that are depended on by others: base -> mutex -> mutexEvents, access; termination -> isEverMultiThreaded *) +(*The exceptions are analyses that are depended on by others: base -> mutex -> mutexEvents, access; termination -> threadflag *) (*escape is also still enabled, because otherwise we get a warning*) (*does not consider dynamic calls!*) @@ -244,7 +244,7 @@ let focusOnSpecification (spec: Svcomp.Specification.t) = print_endline @@ "Specification: NoDataRace -> enabling thread analyses \"" ^ (String.concat ", " notNeccessaryThreadAnalyses) ^ "\""; enableAnalyses notNeccessaryThreadAnalyses; | Termination -> - let terminationAnas = ["termination"; "isEverMultiThreaded"; "apron"] in + let terminationAnas = ["termination"; "threadflag"; "apron"] in print_endline @@ "Specification: Termination -> enabling termination analyses \"" ^ (String.concat ", " terminationAnas) ^ "\""; enableAnalyses terminationAnas; set_string "sem.int.signed_overflow" "assume_none"; diff --git a/src/framework/analyses.ml b/src/framework/analyses.ml index 5fb09546cb..a37a3043c2 100644 --- a/src/framework/analyses.ml +++ b/src/framework/analyses.ml @@ -612,6 +612,12 @@ struct let is_write_only _ = false end +module UnitV = +struct + include Printable.Unit + include StdV +end + module VarinfoV = struct include CilType.Varinfo (* TODO: or Basetype.Variables? *) diff --git a/src/maingoblint.ml b/src/maingoblint.ml index b9cc6c7e47..937c646d47 100644 --- a/src/maingoblint.ml +++ b/src/maingoblint.ml @@ -162,9 +162,9 @@ let check_arguments () = if get_bool "solvers.td3.space" && get_bool "solvers.td3.remove-wpoint" then fail "solvers.td3.space is incompatible with solvers.td3.remove-wpoint"; if get_bool "solvers.td3.space" && get_string "solvers.td3.side_widen" = "sides-local" then fail "solvers.td3.space is incompatible with solvers.td3.side_widen = 'sides-local'"; if List.mem "termination" @@ get_string_list "ana.activated" then ( - set_list "ana.activated" (GobConfig.get_list "ana.activated" @ [`String ("evermultithreaded")]); + set_list "ana.activated" (GobConfig.get_list "ana.activated" @ [`String ("threadflag")]); set_string "sem.int.signed_overflow" "assume_none"; - warn "termination analysis implicitly activates evermultithreaded analysis and set sem.int.signed_overflow to assume_none" + warn "termination analysis implicitly activates threadflag analysis and set sem.int.signed_overflow to assume_none" ); if not (get_bool "ana.sv-comp.enabled") && get_bool "witness.graphml.enabled" then fail "witness.graphml.enabled: cannot generate GraphML witness without SV-COMP mode (ana.sv-comp.enabled)" From e25b708198ab19972677c3a4f7f4de5ca0243209 Mon Sep 17 00:00:00 2001 From: Michael Schwarz Date: Fri, 10 Nov 2023 20:40:24 +0100 Subject: [PATCH 293/327] Simplify `loopTermination` --- src/analyses/loopTermination.ml | 40 ++++++++------------------------- 1 file changed, 9 insertions(+), 31 deletions(-) diff --git a/src/analyses/loopTermination.ml b/src/analyses/loopTermination.ml index 312bcfd9b9..e24b321d05 100644 --- a/src/analyses/loopTermination.ml +++ b/src/analyses/loopTermination.ml @@ -4,10 +4,6 @@ open Analyses open GoblintCil open TerminationPreprocessing -(** Stores the result of the query whether the program is single threaded or not - since finalize does not have access to ctx. *) -let single_thread : bool ref = ref false - (** Contains all loop counter variables (varinfo) and maps them to their corresponding loop statement. *) let loop_counters : stmt VarToStmt.t ref = ref VarToStmt.empty @@ -35,23 +31,12 @@ struct module D = Lattice.Unit module C = D - module V = - struct - include Printable.Unit - let is_write_only _ = true - end + module V = UnitV module G = MapDomain.MapBot (Statements) (BoolDomain.MustBool) let startstate _ = () let exitstate = startstate - (** Warnings for detected possible non-termination *) - let finalize () = - (* Multithreaded *) - if not (!single_thread) then ( - M.warn ~category:Termination "The program might not terminate! (Multithreaded)\n" - ) - (** Recognizes a call of [__goblint_bounded] to check the EvalInt of the * respective loop counter variable at that position. *) let special ctx (lval : lval option) (f : varinfo) (arglist : exp list) = @@ -72,28 +57,21 @@ struct | _ -> () else () - (* Checks whether the program always remains single-threaded. - If the program does not remain single-threaded, we assume non-termination (see query function). *) - let must_always_be_single_threaded ctx = - let single_threaded = not (ctx.ask Queries.IsEverMultiThreaded) in - single_thread := single_threaded; - single_threaded - let query ctx (type a) (q: a Queries.t): a Queries.result = match q with | Queries.MustTermLoop loop_statement -> - must_always_be_single_threaded ctx + let multithreaded = ctx.ask Queries.IsEverMultiThreaded in + (not multithreaded) && (match G.find_opt (`Lifted loop_statement) (ctx.global ()) with Some b -> b | None -> false) | Queries.MustTermAllLoops -> - let always_single_threaded = must_always_be_single_threaded ctx in - (* Must be the first to be evaluated! This has the side effect that - * single_thread is set. In case of another order and due to lazy - * evaluation, the correct value of single_thread can not be guaranteed! - * Therefore, we use a let-in clause here. *) - always_single_threaded - && G.for_all (fun _ term_info -> term_info) (ctx.global ()) + let multithreaded = ctx.ask Queries.IsEverMultiThreaded in + if multithreaded then ( + M.warn ~category:Termination "The program might not terminate! (Multithreaded)\n"; + false) + else + G.for_all (fun _ term_info -> term_info) (ctx.global ()) | _ -> Queries.Result.top q end From d4ab699b1717ba1b52d86ef609c6f8800f552e13 Mon Sep 17 00:00:00 2001 From: Michael Schwarz Date: Fri, 10 Nov 2023 20:46:37 +0100 Subject: [PATCH 294/327] Fail when `termination` is active and incremental analysis is enabled --- src/maingoblint.ml | 1 + 1 file changed, 1 insertion(+) diff --git a/src/maingoblint.ml b/src/maingoblint.ml index 937c646d47..878e68dcf5 100644 --- a/src/maingoblint.ml +++ b/src/maingoblint.ml @@ -162,6 +162,7 @@ let check_arguments () = if get_bool "solvers.td3.space" && get_bool "solvers.td3.remove-wpoint" then fail "solvers.td3.space is incompatible with solvers.td3.remove-wpoint"; if get_bool "solvers.td3.space" && get_string "solvers.td3.side_widen" = "sides-local" then fail "solvers.td3.space is incompatible with solvers.td3.side_widen = 'sides-local'"; if List.mem "termination" @@ get_string_list "ana.activated" then ( + if GobConfig.get_bool "incremental.load" || GobConfig.get_bool "incremental.save" then fail "termination analysis is not compatible with incremental analysis"; set_list "ana.activated" (GobConfig.get_list "ana.activated" @ [`String ("threadflag")]); set_string "sem.int.signed_overflow" "assume_none"; warn "termination analysis implicitly activates threadflag analysis and set sem.int.signed_overflow to assume_none" From 47d0f5d258c493a8ee05691a29cdcee5dce55c32 Mon Sep 17 00:00:00 2001 From: Michael Schwarz Date: Fri, 10 Nov 2023 20:55:07 +0100 Subject: [PATCH 295/327] Termination: set `is_write_only` --- src/analyses/loopTermination.ml | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/analyses/loopTermination.ml b/src/analyses/loopTermination.ml index e24b321d05..7cde0cb9c6 100644 --- a/src/analyses/loopTermination.ml +++ b/src/analyses/loopTermination.ml @@ -31,7 +31,10 @@ struct module D = Lattice.Unit module C = D - module V = UnitV + module V = struct + include UnitV + let is_write_only _ = true + end module G = MapDomain.MapBot (Statements) (BoolDomain.MustBool) let startstate _ = () From 4417b9c8f02fb349184e27342e1a8b981f01cb18 Mon Sep 17 00:00:00 2001 From: Michael Schwarz Date: Fri, 10 Nov 2023 21:01:26 +0100 Subject: [PATCH 296/327] Reset `upjumping_gotos` --- src/common/util/cilfacade.ml | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/src/common/util/cilfacade.ml b/src/common/util/cilfacade.ml index d645fd949d..8b55c0a1ba 100644 --- a/src/common/util/cilfacade.ml +++ b/src/common/util/cilfacade.ml @@ -667,6 +667,10 @@ let find_stmt_sid sid = with Not_found -> IntH.find (ResettableLazy.force stmt_sids) sid +(** Contains the locations of the upjumping gotos and the respective functions + * they are being called in. *) +let upjumping_gotos : (location * fundec) list ref = ref [] + let reset_lazy () = StmtH.clear pseudo_return_to_fun; ResettableLazy.reset stmt_fundecs; @@ -674,7 +678,8 @@ let reset_lazy () = ResettableLazy.reset name_fundecs; ResettableLazy.reset varinfo_roles; ResettableLazy.reset original_names; - ResettableLazy.reset stmt_sids + ResettableLazy.reset stmt_sids; + upjumping_gotos := [] let stmt_pretty_short () x = @@ -699,8 +704,4 @@ let add_function_declarations (file: Cil.file): unit = in let fun_decls = List.filter_map declaration_from_GFun functions in let globals = upto_last_type @ fun_decls @ non_types @ functions in - file.globals <- globals - -(** Contains the locations of the upjumping gotos and the respective functions - * they are being called in. *) -let upjumping_gotos : (location * fundec) list ref = ref [] + file.globals <- globals \ No newline at end of file From de416eeb01e12df4874679da3437358e11405a74 Mon Sep 17 00:00:00 2001 From: Michael Schwarz Date: Fri, 10 Nov 2023 22:09:47 +0100 Subject: [PATCH 297/327] Cleanup upjumping_gotos --- src/common/util/cilfacade.ml | 10 +++++---- src/framework/control.ml | 32 ++++++++++++++++------------ src/maingoblint.ml | 2 +- src/util/terminationPreprocessing.ml | 12 ++++++++--- 4 files changed, 34 insertions(+), 22 deletions(-) diff --git a/src/common/util/cilfacade.ml b/src/common/util/cilfacade.ml index 8b55c0a1ba..26a2f082a4 100644 --- a/src/common/util/cilfacade.ml +++ b/src/common/util/cilfacade.ml @@ -666,20 +666,22 @@ let find_stmt_sid sid = try IntH.find pseudo_return_stmt_sids sid with Not_found -> IntH.find (ResettableLazy.force stmt_sids) sid +module FunLocH = Hashtbl.Make(CilType.Fundec) +module LocSet = Hashtbl.Make(CilType.Location) (** Contains the locations of the upjumping gotos and the respective functions * they are being called in. *) -let upjumping_gotos : (location * fundec) list ref = ref [] +let funs_with_upjumping_gotos: unit LocSet.t FunLocH.t = FunLocH.create 13 -let reset_lazy () = +let reset_lazy ?(keepupjumpinggotos=false) () = StmtH.clear pseudo_return_to_fun; + if not keepupjumpinggotos then FunLocH.clear funs_with_upjumping_gotos; ResettableLazy.reset stmt_fundecs; ResettableLazy.reset varinfo_fundecs; ResettableLazy.reset name_fundecs; ResettableLazy.reset varinfo_roles; ResettableLazy.reset original_names; - ResettableLazy.reset stmt_sids; - upjumping_gotos := [] + ResettableLazy.reset stmt_sids let stmt_pretty_short () x = diff --git a/src/framework/control.ml b/src/framework/control.ml index a78f125eae..0c9b61739b 100644 --- a/src/framework/control.ml +++ b/src/framework/control.ml @@ -105,6 +105,8 @@ struct let module StringMap = BatMap.Make (String) in let live_lines = ref StringMap.empty in let dead_lines = ref StringMap.empty in + let module FunSet = Hashtbl.Make (CilType.Fundec) in + let live_funs: unit FunSet.t = FunSet.create 13 in let add_one n v = match n with | Statement s when Cilfacade.(StmtH.mem pseudo_return_to_fun s) -> @@ -115,6 +117,7 @@ struct See: https://github.com/goblint/analyzer/issues/290#issuecomment-881258091. *) let l = UpdateCil.getLoc n in let f = Node.find_fundec n in + FunSet.replace live_funs f (); let add_fun = BatISet.add l.line in let add_file = StringMap.modify_def BatISet.empty f.svar.vname add_fun in let is_dead = LT.for_all (fun (_,x,f) -> Spec.D.is_bot x) v in @@ -136,20 +139,21 @@ struct try StringMap.find fn (StringMap.find file !live_lines) with Not_found -> BatISet.empty in - (*check if we have upjumping gotos*) - List.iter - (fun x -> - let ((l: location), (fd: fundec)) = x in (*unpack tuple for later use*) - let fname = fd.svar.vname in - StringMap.iter - (fun fi _ -> - let fundec_live = live fi fname in - if ( not (BatISet.is_empty fundec_live)) then ( - AnalysisState.svcomp_may_not_terminate := true; - M.warn ~loc:(M.Location.CilLocation l) ~category:Termination "The program might not terminate! (Upjumping Goto)"); - ) - (!live_lines)) - (!Cilfacade.upjumping_gotos); + if List.mem "termination" @@ get_string_list "ana.activated" then ( + (* check if we have upjumping gotos *) + let open Cilfacade in + let warn_for_upjumps fundec gotos = + if FunSet.mem live_funs fundec then ( + (* set nortermiantion flag *) + AnalysisState.svcomp_may_not_terminate := true; + (* iterate through locations to produce warnings *) + LocSet.iter (fun l _ -> + M.warn ~loc:(M.Location.CilLocation l) ~category:Termination "The program might not terminate! (Upjumping Goto)" + ) gotos + ) + in + FunLocH.iter warn_for_upjumps funs_with_upjumping_gotos + ); dead_lines := StringMap.mapi (fun fi -> StringMap.mapi (fun fu ded -> BatISet.diff ded (live fi fu))) !dead_lines; dead_lines := StringMap.map (StringMap.filter (fun _ x -> not (BatISet.is_empty x))) !dead_lines; dead_lines := StringMap.filter (fun _ x -> not (StringMap.is_empty x)) !dead_lines; diff --git a/src/maingoblint.ml b/src/maingoblint.ml index 878e68dcf5..c44a6d9360 100644 --- a/src/maingoblint.ml +++ b/src/maingoblint.ml @@ -493,7 +493,7 @@ let merge_parsed parsed = Cilfacade.current_file := merged_AST; (* Set before createCFG, so Cilfacade maps can be computed for loop unrolling. *) CilCfg.createCFG merged_AST; (* Create CIL CFG from CIL AST. *) - Cilfacade.reset_lazy (); (* Reset Cilfacade maps, which need to be recomputer after loop unrolling. *) + Cilfacade.reset_lazy ~keepupjumpinggotos:true (); (* Reset Cilfacade maps, which need to be recomputer after loop unrolling but keep gotos. *) merged_AST let preprocess_parse_merge () = diff --git a/src/util/terminationPreprocessing.ml b/src/util/terminationPreprocessing.ml index 8070438943..4674a0ca10 100644 --- a/src/util/terminationPreprocessing.ml +++ b/src/util/terminationPreprocessing.ml @@ -50,9 +50,15 @@ class loopCounterVisitor lc (fd : fundec) = object(self) | Goto (sref, l) -> let goto_jmp_stmt = sref.contents.skind in let loc_stmt = Cil.get_stmtLoc goto_jmp_stmt in - if CilType.Location.compare l loc_stmt >= 0 (*is pos if first loc is greater -> below the second loc*) - then - Cilfacade.upjumping_gotos := List.append !Cilfacade.upjumping_gotos ([(l, fd)] : (location * fundec) list); (*problem: the program might not terminate!*) + if CilType.Location.compare l loc_stmt >= 0 then ( + (* is pos if first loc is greater -> below the second loc *) + (* problem: the program might not terminate! *) + let open Cilfacade in + let current = FunLocH.find_opt funs_with_upjumping_gotos fd in + let current = BatOption.default (LocSet.create 13) current in + LocSet.replace current l (); + FunLocH.replace funs_with_upjumping_gotos fd current; + ); s | _ -> s in ChangeDoChildrenPost (s, action); From e66cf56afc8473c3bc76494a8f104ced4aa1c0ee Mon Sep 17 00:00:00 2001 From: Julian Erhard Date: Thu, 9 Nov 2023 18:12:21 +0100 Subject: [PATCH 298/327] Make type of variables used for loop termination analysis more easily exchangable. --- src/util/terminationPreprocessing.ml | 23 +++++++++++++++++------ 1 file changed, 17 insertions(+), 6 deletions(-) diff --git a/src/util/terminationPreprocessing.ml b/src/util/terminationPreprocessing.ml index 4674a0ca10..a0065caabc 100644 --- a/src/util/terminationPreprocessing.ml +++ b/src/util/terminationPreprocessing.ml @@ -2,6 +2,11 @@ open GoblintCil module VarToStmt = Map.Make(CilType.Varinfo) (* maps varinfos (= loop counter variable) to the statement of the corresponding loop*) +let counter_ikind = IInt +let counter_typ = TInt (counter_ikind, []) +let min_int_exp = Const(CInt(Cilint.zero_cilint, counter_ikind, None)) +let min_int_exp = Const(CInt(Cilint.shift_left_cilint Cilint.mone_cilint ((bytesSizeOfInt counter_ikind)*8-1), IInt, None)) + class loopCounterVisitor lc (fd : fundec) = object(self) inherit nopCilVisitor @@ -15,7 +20,7 @@ class loopCounterVisitor lc (fd : fundec) = object(self) method! vstmt s = let specialFunction name = - { svar = makeGlobalVar name (TFun(voidType, Some [("exp", intType, [])], false,[])); + { svar = makeGlobalVar name (TFun(voidType, Some [("exp", counter_typ, [])], false,[])); smaxid = 0; slocals = []; sformals = []; @@ -24,7 +29,12 @@ class loopCounterVisitor lc (fd : fundec) = object(self) sallstmts = []; } in - let min_int_exp = Const(CInt(Cilint.shift_left_cilint Cilint.mone_cilint ((bytesSizeOfInt IInt)*8-1), IInt, None)) in + + let increment_expression lval = + let et = typeOf lval in + let bop = PlusA in + let one = Const (CInt (Cilint.one_cilint, counter_ikind, None)) in + constFold false (BinOp(bop, lval, one, et)) in let f_bounded = Lval (var (specialFunction "__goblint_bounded").svar) in @@ -32,11 +42,12 @@ class loopCounterVisitor lc (fd : fundec) = object(self) | Loop (b, loc, eloc, _, _) -> let vname = "term" ^ string_of_int loc.line ^ "_" ^ string_of_int loc.column ^ "-id" ^ (string_of_int !vcounter) in incr vcounter; - let v = Cil.makeLocalVar fd vname Cil.intType in (*Not tested for incremental mode*) + let v = Cil.makeLocalVar fd vname counter_typ in (*Not tested for incremental mode*) + let lval = Lval (Var v, NoOffset) in let init_stmt = mkStmtOneInstr @@ Set (var v, min_int_exp, loc, eloc) in - let inc_stmt = mkStmtOneInstr @@ Set (var v, increm (Lval (var v)) 1, loc, eloc) in - let inc_stmt2 = mkStmtOneInstr @@ Set (var v, increm (Lval (var v)) 1, loc, eloc) in - let exit_stmt = mkStmtOneInstr @@ Call (None, f_bounded, [Lval (var v)], loc, locUnknown) in + let inc_stmt = mkStmtOneInstr @@ Set (var v, increment_expression lval, loc, eloc) in + let inc_stmt2 = mkStmtOneInstr @@ Set (var v, increment_expression lval, loc, eloc) in + let exit_stmt = mkStmtOneInstr @@ Call (None, f_bounded, [lval], loc, locUnknown) in (match b.bstmts with | s :: ss -> (*duplicate increment statement here to fix inconsistencies in nested loops*) b.bstmts <- exit_stmt :: inc_stmt :: s :: inc_stmt2 :: ss; From e02801a1dd0c33aa12917a7ec3380cd01b4ef866 Mon Sep 17 00:00:00 2001 From: Julian Erhard Date: Fri, 10 Nov 2023 10:58:41 +0100 Subject: [PATCH 299/327] Remove redundant code for setting todo variable --- scripts/update_suite.rb | 12 +++--------- 1 file changed, 3 insertions(+), 9 deletions(-) diff --git a/scripts/update_suite.rb b/scripts/update_suite.rb index bbf1a71a9d..258626422e 100755 --- a/scripts/update_suite.rb +++ b/scripts/update_suite.rb @@ -331,20 +331,14 @@ def parse_tests (lines) end end case lines[0] - when /TODO/ - case lines[0] - when /NONTERM/ - tests[-1] = "nonterm" - todo << -1 - when /TERM/ - tests[-1] = "term" - todo << -1 - end when /NONTERM/ tests[-1] = "nonterm" when /TERM/ tests[-1] = "term" end + if lines[0] =~ /TODO/ then + todo << -1 + end Tests.new(self, tests, tests_line, todo) end From 3d3c06956f787ba0f8f98278d33a647749b3da68 Mon Sep 17 00:00:00 2001 From: Julian Erhard Date: Mon, 13 Nov 2023 11:14:45 +0100 Subject: [PATCH 300/327] Add define min_int_exp depending on the signedness of the counter variable introduced. Also remove custom definition for incrementing expression by one. --- src/util/terminationPreprocessing.ml | 19 ++++++++----------- 1 file changed, 8 insertions(+), 11 deletions(-) diff --git a/src/util/terminationPreprocessing.ml b/src/util/terminationPreprocessing.ml index a0065caabc..9605484af3 100644 --- a/src/util/terminationPreprocessing.ml +++ b/src/util/terminationPreprocessing.ml @@ -4,8 +4,12 @@ module VarToStmt = Map.Make(CilType.Varinfo) (* maps varinfos (= loop counter va let counter_ikind = IInt let counter_typ = TInt (counter_ikind, []) -let min_int_exp = Const(CInt(Cilint.zero_cilint, counter_ikind, None)) -let min_int_exp = Const(CInt(Cilint.shift_left_cilint Cilint.mone_cilint ((bytesSizeOfInt counter_ikind)*8-1), IInt, None)) +let min_int_exp = + (* Currently only tested for IInt type, which is signed *) + if Cil.isSigned counter_ikind then + Const(CInt(Cilint.shift_left_cilint Cilint.mone_cilint ((bytesSizeOfInt counter_ikind)*8-1), IInt, None)) + else + Const(CInt(Cilint.zero_cilint, counter_ikind, None)) class loopCounterVisitor lc (fd : fundec) = object(self) inherit nopCilVisitor @@ -29,13 +33,6 @@ class loopCounterVisitor lc (fd : fundec) = object(self) sallstmts = []; } in - - let increment_expression lval = - let et = typeOf lval in - let bop = PlusA in - let one = Const (CInt (Cilint.one_cilint, counter_ikind, None)) in - constFold false (BinOp(bop, lval, one, et)) in - let f_bounded = Lval (var (specialFunction "__goblint_bounded").svar) in let action s = match s.skind with @@ -45,8 +42,8 @@ class loopCounterVisitor lc (fd : fundec) = object(self) let v = Cil.makeLocalVar fd vname counter_typ in (*Not tested for incremental mode*) let lval = Lval (Var v, NoOffset) in let init_stmt = mkStmtOneInstr @@ Set (var v, min_int_exp, loc, eloc) in - let inc_stmt = mkStmtOneInstr @@ Set (var v, increment_expression lval, loc, eloc) in - let inc_stmt2 = mkStmtOneInstr @@ Set (var v, increment_expression lval, loc, eloc) in + let inc_stmt = mkStmtOneInstr @@ Set (var v, increm lval 1, loc, eloc) in + let inc_stmt2 = mkStmtOneInstr @@ Set (var v, increm lval 1, loc, eloc) in let exit_stmt = mkStmtOneInstr @@ Call (None, f_bounded, [lval], loc, locUnknown) in (match b.bstmts with | s :: ss -> (*duplicate increment statement here to fix inconsistencies in nested loops*) From 46b0f672b2dc1a28a1c3eff6001de0b71a4f52ca Mon Sep 17 00:00:00 2001 From: Julian Erhard Date: Mon, 13 Nov 2023 11:48:18 +0100 Subject: [PATCH 301/327] Change indentation in update_suite.rb back to reduce number of lines changed. --- scripts/update_suite.rb | 36 ++++++++++++++++++------------------ 1 file changed, 18 insertions(+), 18 deletions(-) diff --git a/scripts/update_suite.rb b/scripts/update_suite.rb index 258626422e..ab2aeea53f 100755 --- a/scripts/update_suite.rb +++ b/scripts/update_suite.rb @@ -151,25 +151,25 @@ def collect_warnings ranking = ["other", "warn", "goto", "fundec", "loop", "term", "nonterm", "race", "norace", "deadlock", "nodeadlock", "success", "fail", "unknown"] thiswarn = case obj - when /\(conf\. \d+\)/ then "race" - when /Deadlock/ then "deadlock" - when /lock (before|after):/ then "deadlock" - when /Assertion .* will fail/ then "fail" - when /Assertion .* will succeed/ then "success" - when /Assertion .* is unknown/ then "unknown" - when /invariant confirmed/ then "success" - when /invariant unconfirmed/ then "unknown" - when /invariant refuted/ then "fail" - when /(Upjumping Goto)/ then "goto" + when /\(conf\. \d+\)/ then "race" + when /Deadlock/ then "deadlock" + when /lock (before|after):/ then "deadlock" + when /Assertion .* will fail/ then "fail" + when /Assertion .* will succeed/ then "success" + when /Assertion .* is unknown/ then "unknown" + when /invariant confirmed/ then "success" + when /invariant unconfirmed/ then "unknown" + when /invariant refuted/ then "fail" + when /(Upjumping Goto)/ then "goto" when /(Fundec \w+ is contained in a call graph cycle)/ then "fundec" - when /(Loop analysis)/ then "loop" - when /^\[Warning\]/ then "warn" - when /^\[Error\]/ then "warn" - when /^\[Info\]/ then "warn" - when /^\[Success\]/ then "success" - when /\[Debug\]/ then next # debug "warnings" shouldn't count as other warnings (against NOWARN) - when /^ on line \d+ $/ then next # dead line warnings shouldn't count (used for unreachability with NOWARN) - when /^ on lines \d+..\d+ $/ then next # dead line warnings shouldn't count (used for unreachability with NOWARN) + when /(Loop analysis)/ then "loop" + when /^\[Warning\]/ then "warn" + when /^\[Error\]/ then "warn" + when /^\[Info\]/ then "warn" + when /^\[Success\]/ then "success" + when /\[Debug\]/ then next # debug "warnings" shouldn't count as other warnings (against NOWARN) + when /^ on line \d+ $/ then next # dead line warnings shouldn't count (used for unreachability with NOWARN) + when /^ on lines \d+..\d+ $/ then next # dead line warnings shouldn't count (used for unreachability with NOWARN) else "other" end oldwarn = warnings[i] From 21d405db4814cff6eafbdc059412282530f87377 Mon Sep 17 00:00:00 2001 From: Julian Erhard Date: Mon, 13 Nov 2023 11:49:49 +0100 Subject: [PATCH 302/327] Change indentatation back. --- scripts/update_suite.rb | 42 ++++++++++++++++++++--------------------- 1 file changed, 21 insertions(+), 21 deletions(-) diff --git a/scripts/update_suite.rb b/scripts/update_suite.rb index ab2aeea53f..8817ef599a 100755 --- a/scripts/update_suite.rb +++ b/scripts/update_suite.rb @@ -150,27 +150,27 @@ def collect_warnings obj,i = $1,$2.to_i ranking = ["other", "warn", "goto", "fundec", "loop", "term", "nonterm", "race", "norace", "deadlock", "nodeadlock", "success", "fail", "unknown"] - thiswarn = case obj - when /\(conf\. \d+\)/ then "race" - when /Deadlock/ then "deadlock" - when /lock (before|after):/ then "deadlock" - when /Assertion .* will fail/ then "fail" - when /Assertion .* will succeed/ then "success" - when /Assertion .* is unknown/ then "unknown" - when /invariant confirmed/ then "success" - when /invariant unconfirmed/ then "unknown" - when /invariant refuted/ then "fail" - when /(Upjumping Goto)/ then "goto" - when /(Fundec \w+ is contained in a call graph cycle)/ then "fundec" - when /(Loop analysis)/ then "loop" - when /^\[Warning\]/ then "warn" - when /^\[Error\]/ then "warn" - when /^\[Info\]/ then "warn" - when /^\[Success\]/ then "success" - when /\[Debug\]/ then next # debug "warnings" shouldn't count as other warnings (against NOWARN) - when /^ on line \d+ $/ then next # dead line warnings shouldn't count (used for unreachability with NOWARN) - when /^ on lines \d+..\d+ $/ then next # dead line warnings shouldn't count (used for unreachability with NOWARN) - else "other" + thiswarn = case obj + when /\(conf\. \d+\)/ then "race" + when /Deadlock/ then "deadlock" + when /lock (before|after):/ then "deadlock" + when /Assertion .* will fail/ then "fail" + when /Assertion .* will succeed/ then "success" + when /Assertion .* is unknown/ then "unknown" + when /invariant confirmed/ then "success" + when /invariant unconfirmed/ then "unknown" + when /invariant refuted/ then "fail" + when /(Upjumping Goto)/ then "goto" + when /(Fundec \w+ is contained in a call graph cycle)/ then "fundec" + when /(Loop analysis)/ then "loop" + when /^\[Warning\]/ then "warn" + when /^\[Error\]/ then "warn" + when /^\[Info\]/ then "warn" + when /^\[Success\]/ then "success" + when /\[Debug\]/ then next # debug "warnings" shouldn't count as other warnings (against NOWARN) + when /^ on line \d+ $/ then next # dead line warnings shouldn't count (used for unreachability with NOWARN) + when /^ on lines \d+..\d+ $/ then next # dead line warnings shouldn't count (used for unreachability with NOWARN) + else "other" end oldwarn = warnings[i] if oldwarn.nil? then From bc126fabf558024b61fd7eee6bb5613daaab9818 Mon Sep 17 00:00:00 2001 From: Julian Erhard Date: Mon, 13 Nov 2023 11:50:46 +0100 Subject: [PATCH 303/327] Fix indentation of line. --- scripts/update_suite.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scripts/update_suite.rb b/scripts/update_suite.rb index 8817ef599a..2722b3ddb5 100755 --- a/scripts/update_suite.rb +++ b/scripts/update_suite.rb @@ -171,7 +171,7 @@ def collect_warnings when /^ on line \d+ $/ then next # dead line warnings shouldn't count (used for unreachability with NOWARN) when /^ on lines \d+..\d+ $/ then next # dead line warnings shouldn't count (used for unreachability with NOWARN) else "other" - end + end oldwarn = warnings[i] if oldwarn.nil? then warnings[i] = thiswarn From 0e0986a974c9ae86f7af188b5d604d7c264fb593 Mon Sep 17 00:00:00 2001 From: Julian Erhard Date: Mon, 13 Nov 2023 13:24:04 +0100 Subject: [PATCH 304/327] Use Z instead of Cilint --- src/util/terminationPreprocessing.ml | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/util/terminationPreprocessing.ml b/src/util/terminationPreprocessing.ml index 9605484af3..4e25f232e3 100644 --- a/src/util/terminationPreprocessing.ml +++ b/src/util/terminationPreprocessing.ml @@ -1,4 +1,5 @@ open GoblintCil +(* module Z = Big_int_Z *) module VarToStmt = Map.Make(CilType.Varinfo) (* maps varinfos (= loop counter variable) to the statement of the corresponding loop*) @@ -7,9 +8,9 @@ let counter_typ = TInt (counter_ikind, []) let min_int_exp = (* Currently only tested for IInt type, which is signed *) if Cil.isSigned counter_ikind then - Const(CInt(Cilint.shift_left_cilint Cilint.mone_cilint ((bytesSizeOfInt counter_ikind)*8-1), IInt, None)) + Const(CInt(Z.shift_left Cilint.mone_cilint ((bytesSizeOfInt counter_ikind)*8-1), IInt, None)) else - Const(CInt(Cilint.zero_cilint, counter_ikind, None)) + Const(CInt(Z.zero, counter_ikind, None)) class loopCounterVisitor lc (fd : fundec) = object(self) inherit nopCilVisitor From f18fe581d6d06e674106eaec9c6c26d136aa68eb Mon Sep 17 00:00:00 2001 From: Julian Erhard Date: Mon, 13 Nov 2023 13:51:31 +0100 Subject: [PATCH 305/327] Change - to _ in name of variable introduced in terminationPreprocessing. - is not a legal part of a variable. --- src/util/terminationPreprocessing.ml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/util/terminationPreprocessing.ml b/src/util/terminationPreprocessing.ml index 4e25f232e3..919de3e5d9 100644 --- a/src/util/terminationPreprocessing.ml +++ b/src/util/terminationPreprocessing.ml @@ -38,7 +38,7 @@ class loopCounterVisitor lc (fd : fundec) = object(self) let action s = match s.skind with | Loop (b, loc, eloc, _, _) -> - let vname = "term" ^ string_of_int loc.line ^ "_" ^ string_of_int loc.column ^ "-id" ^ (string_of_int !vcounter) in + let vname = "term" ^ string_of_int loc.line ^ "_" ^ string_of_int loc.column ^ "_id" ^ (string_of_int !vcounter) in incr vcounter; let v = Cil.makeLocalVar fd vname counter_typ in (*Not tested for incremental mode*) let lval = Lval (Var v, NoOffset) in From aef46ce9c6ea20e5f50b9725abe92dd7f4a0d84e Mon Sep 17 00:00:00 2001 From: Julian Erhard Date: Mon, 13 Nov 2023 14:39:08 +0100 Subject: [PATCH 306/327] Add LoopTermination and TerminationPreprocessing to goblint_lib --- src/goblint_lib.ml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/goblint_lib.ml b/src/goblint_lib.ml index e1087f8fc9..e06f5fd245 100644 --- a/src/goblint_lib.ml +++ b/src/goblint_lib.ml @@ -124,6 +124,7 @@ module RelationPriv = RelationPriv module ThreadEscape = ThreadEscape module PthreadSignals = PthreadSignals module ExtractPthread = ExtractPthread +module LoopTermination = LoopTermination (** {2 Longjmp} @@ -338,6 +339,7 @@ module Tracing = Tracing module Preprocessor = Preprocessor module CompilationDatabase = CompilationDatabase module MakefileUtil = MakefileUtil +module TerminationPreprocessing = TerminationPreprocessing (** {2 Witnesses} From 72c14e208fab17f89fa325cb704317929bd8e739 Mon Sep 17 00:00:00 2001 From: Julian Erhard Date: Mon, 13 Nov 2023 15:33:12 +0100 Subject: [PATCH 307/327] Extract function find_loop, given a loop_counter. --- src/analyses/loopTermination.ml | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/src/analyses/loopTermination.ml b/src/analyses/loopTermination.ml index 7cde0cb9c6..5fac2e9e1a 100644 --- a/src/analyses/loopTermination.ml +++ b/src/analyses/loopTermination.ml @@ -31,7 +31,7 @@ struct module D = Lattice.Unit module C = D - module V = struct + module V = struct include UnitV let is_write_only _ = true end @@ -40,6 +40,9 @@ struct let startstate _ = () let exitstate = startstate + let find_loop ~loop_counter = + VarToStmt.find loop_counter !loop_counters + (** Recognizes a call of [__goblint_bounded] to check the EvalInt of the * respective loop counter variable at that position. *) let special ctx (lval : lval option) (f : varinfo) (arglist : exp list) = @@ -47,7 +50,7 @@ struct match f.vname, arglist with "__goblint_bounded", [Lval (Var x, NoOffset)] -> (try - let loop_statement = VarToStmt.find x !loop_counters in + let loop_statement = find_loop ~loop_counter:x in let is_bounded = check_bounded ctx x in ctx.sideg () (G.add (`Lifted loop_statement) is_bounded (ctx.global ())); (* In case the loop is not bounded, a warning is created. *) @@ -70,7 +73,7 @@ struct | None -> false) | Queries.MustTermAllLoops -> let multithreaded = ctx.ask Queries.IsEverMultiThreaded in - if multithreaded then ( + if multithreaded then ( M.warn ~category:Termination "The program might not terminate! (Multithreaded)\n"; false) else From ddfcaea7430c74b08103b243f19ec07305a1d422 Mon Sep 17 00:00:00 2001 From: Julian Erhard Date: Mon, 13 Nov 2023 15:34:34 +0100 Subject: [PATCH 308/327] Rename x to loop_counter. --- src/analyses/loopTermination.ml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/analyses/loopTermination.ml b/src/analyses/loopTermination.ml index 5fac2e9e1a..10e0f5c5f4 100644 --- a/src/analyses/loopTermination.ml +++ b/src/analyses/loopTermination.ml @@ -48,10 +48,10 @@ struct let special ctx (lval : lval option) (f : varinfo) (arglist : exp list) = if !AnalysisState.postsolving then match f.vname, arglist with - "__goblint_bounded", [Lval (Var x, NoOffset)] -> + "__goblint_bounded", [Lval (Var loop_counter, NoOffset)] -> (try - let loop_statement = find_loop ~loop_counter:x in - let is_bounded = check_bounded ctx x in + let loop_statement = find_loop ~loop_counter in + let is_bounded = check_bounded ctx loop_counter in ctx.sideg () (G.add (`Lifted loop_statement) is_bounded (ctx.global ())); (* In case the loop is not bounded, a warning is created. *) if not (is_bounded) then ( From 72413249dd0cfb5c72d052d4f44110f20f4a2af3 Mon Sep 17 00:00:00 2001 From: Julian Erhard Date: Mon, 13 Nov 2023 16:34:17 +0100 Subject: [PATCH 309/327] Use increment_expression that takes the ikind of the counter variable into account. --- src/util/terminationPreprocessing.ml | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/src/util/terminationPreprocessing.ml b/src/util/terminationPreprocessing.ml index 919de3e5d9..b6ffc12c14 100644 --- a/src/util/terminationPreprocessing.ml +++ b/src/util/terminationPreprocessing.ml @@ -36,6 +36,14 @@ class loopCounterVisitor lc (fd : fundec) = object(self) let f_bounded = Lval (var (specialFunction "__goblint_bounded").svar) in + (* Yields increment expression e + 1 where the added "1" that has the same type as the expression [e]. + Using Cil.increm instead does not work for non-[IInt] ikinds. *) + let increment_expression e = + let et = typeOf e in + let bop = PlusA in + let one = Const (CInt (Cilint.one_cilint, counter_ikind, None)) in + constFold false (BinOp(bop, e, one, et)) in + let action s = match s.skind with | Loop (b, loc, eloc, _, _) -> let vname = "term" ^ string_of_int loc.line ^ "_" ^ string_of_int loc.column ^ "_id" ^ (string_of_int !vcounter) in @@ -43,8 +51,8 @@ class loopCounterVisitor lc (fd : fundec) = object(self) let v = Cil.makeLocalVar fd vname counter_typ in (*Not tested for incremental mode*) let lval = Lval (Var v, NoOffset) in let init_stmt = mkStmtOneInstr @@ Set (var v, min_int_exp, loc, eloc) in - let inc_stmt = mkStmtOneInstr @@ Set (var v, increm lval 1, loc, eloc) in - let inc_stmt2 = mkStmtOneInstr @@ Set (var v, increm lval 1, loc, eloc) in + let inc_stmt = mkStmtOneInstr @@ Set (var v, increment_expression lval, loc, eloc) in + let inc_stmt2 = mkStmtOneInstr @@ Set (var v, increment_expression lval, loc, eloc) in let exit_stmt = mkStmtOneInstr @@ Call (None, f_bounded, [lval], loc, locUnknown) in (match b.bstmts with | s :: ss -> (*duplicate increment statement here to fix inconsistencies in nested loops*) From 76751d4947cc013c5c439e9b79b9733b9676fc19 Mon Sep 17 00:00:00 2001 From: Julian Erhard Date: Mon, 13 Nov 2023 17:59:28 +0100 Subject: [PATCH 310/327] Termination analysis: Insert only one increment statement, do not set assume no overflow. --- src/maingoblint.ml | 3 +-- src/util/terminationPreprocessing.ml | 8 +------- 2 files changed, 2 insertions(+), 9 deletions(-) diff --git a/src/maingoblint.ml b/src/maingoblint.ml index c44a6d9360..3d9959ba6c 100644 --- a/src/maingoblint.ml +++ b/src/maingoblint.ml @@ -164,8 +164,7 @@ let check_arguments () = if List.mem "termination" @@ get_string_list "ana.activated" then ( if GobConfig.get_bool "incremental.load" || GobConfig.get_bool "incremental.save" then fail "termination analysis is not compatible with incremental analysis"; set_list "ana.activated" (GobConfig.get_list "ana.activated" @ [`String ("threadflag")]); - set_string "sem.int.signed_overflow" "assume_none"; - warn "termination analysis implicitly activates threadflag analysis and set sem.int.signed_overflow to assume_none" + warn "termination analysis implicitly activates threadflag analysis." ); if not (get_bool "ana.sv-comp.enabled") && get_bool "witness.graphml.enabled" then fail "witness.graphml.enabled: cannot generate GraphML witness without SV-COMP mode (ana.sv-comp.enabled)" diff --git a/src/util/terminationPreprocessing.ml b/src/util/terminationPreprocessing.ml index b6ffc12c14..eb950b1dbb 100644 --- a/src/util/terminationPreprocessing.ml +++ b/src/util/terminationPreprocessing.ml @@ -52,14 +52,8 @@ class loopCounterVisitor lc (fd : fundec) = object(self) let lval = Lval (Var v, NoOffset) in let init_stmt = mkStmtOneInstr @@ Set (var v, min_int_exp, loc, eloc) in let inc_stmt = mkStmtOneInstr @@ Set (var v, increment_expression lval, loc, eloc) in - let inc_stmt2 = mkStmtOneInstr @@ Set (var v, increment_expression lval, loc, eloc) in let exit_stmt = mkStmtOneInstr @@ Call (None, f_bounded, [lval], loc, locUnknown) in - (match b.bstmts with - | s :: ss -> (*duplicate increment statement here to fix inconsistencies in nested loops*) - b.bstmts <- exit_stmt :: inc_stmt :: s :: inc_stmt2 :: ss; - | ss -> - b.bstmts <- exit_stmt :: inc_stmt :: ss; - ); + b.bstmts <- exit_stmt :: inc_stmt :: b.bstmts; lc := VarToStmt.add (v: varinfo) (s: stmt) !lc; let nb = mkBlock [init_stmt; mkStmt s.skind] in s.skind <- Block nb; From 5d5482726f5464605e59a5ac2263830a03358002 Mon Sep 17 00:00:00 2001 From: Julian Erhard Date: Mon, 13 Nov 2023 18:01:02 +0100 Subject: [PATCH 311/327] Set regresion tests to todo that are now imprecise. --- tests/regression/78-termination/03-nested-loop-terminating.c | 2 +- .../regression/78-termination/07-nested-for-loop-terminating.c | 2 +- .../regression/78-termination/25-leave-loop-goto-terminating.c | 2 +- .../78-termination/30-goto-out-of-inner-loop-terminating.c | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/tests/regression/78-termination/03-nested-loop-terminating.c b/tests/regression/78-termination/03-nested-loop-terminating.c index fd1ee14f39..6b31204567 100644 --- a/tests/regression/78-termination/03-nested-loop-terminating.c +++ b/tests/regression/78-termination/03-nested-loop-terminating.c @@ -1,4 +1,4 @@ -// SKIP TERM PARAM: --set "ana.activated[+]" termination --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra +// SKIP TODO TERM PARAM: --set "ana.activated[+]" termination --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra #include int main() diff --git a/tests/regression/78-termination/07-nested-for-loop-terminating.c b/tests/regression/78-termination/07-nested-for-loop-terminating.c index f1dde17dc5..3293a1fa2c 100644 --- a/tests/regression/78-termination/07-nested-for-loop-terminating.c +++ b/tests/regression/78-termination/07-nested-for-loop-terminating.c @@ -1,4 +1,4 @@ -// SKIP TERM PARAM: --set "ana.activated[+]" termination --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra +// SKIP TODO TERM PARAM: --set "ana.activated[+]" termination --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra #include int main() diff --git a/tests/regression/78-termination/25-leave-loop-goto-terminating.c b/tests/regression/78-termination/25-leave-loop-goto-terminating.c index 61c8b8f58d..b882759bff 100644 --- a/tests/regression/78-termination/25-leave-loop-goto-terminating.c +++ b/tests/regression/78-termination/25-leave-loop-goto-terminating.c @@ -1,4 +1,4 @@ -// SKIP TERM PARAM: --set "ana.activated[+]" termination --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra +// SKIP TODO TERM PARAM: --set "ana.activated[+]" termination --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra #include int main() diff --git a/tests/regression/78-termination/30-goto-out-of-inner-loop-terminating.c b/tests/regression/78-termination/30-goto-out-of-inner-loop-terminating.c index 999ee6d3fd..c07b558d07 100644 --- a/tests/regression/78-termination/30-goto-out-of-inner-loop-terminating.c +++ b/tests/regression/78-termination/30-goto-out-of-inner-loop-terminating.c @@ -1,4 +1,4 @@ -// SKIP TERM PARAM: --set "ana.activated[+]" termination --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra +// SKIP TODO TERM PARAM: --set "ana.activated[+]" termination --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain polyhedra #include int main() From f81ca2c0346716ada6abfc51f09dbf9143dc34c1 Mon Sep 17 00:00:00 2001 From: Julian Erhard Date: Mon, 13 Nov 2023 23:15:40 +0100 Subject: [PATCH 312/327] Termination: Use unsigned long long for counter variables; reactivate assume no overflow when termination analysis is activated. --- lib/goblint/runtime/include/goblint.h | 2 +- lib/goblint/runtime/src/goblint.c | 4 ++-- src/maingoblint.ml | 3 ++- src/util/terminationPreprocessing.ml | 2 +- 4 files changed, 6 insertions(+), 5 deletions(-) diff --git a/lib/goblint/runtime/include/goblint.h b/lib/goblint/runtime/include/goblint.h index 3c1abae838..af87035d33 100644 --- a/lib/goblint/runtime/include/goblint.h +++ b/lib/goblint/runtime/include/goblint.h @@ -7,4 +7,4 @@ void __goblint_assume_join(/* pthread_t thread */); // undeclared argument to av void __goblint_split_begin(int exp); void __goblint_split_end(int exp); -void __goblint_bounded(int exp); \ No newline at end of file +void __goblint_bounded(unsigned long long exp); \ No newline at end of file diff --git a/lib/goblint/runtime/src/goblint.c b/lib/goblint/runtime/src/goblint.c index 7929fcf37a..cbcb7cf505 100644 --- a/lib/goblint/runtime/src/goblint.c +++ b/lib/goblint/runtime/src/goblint.c @@ -29,6 +29,6 @@ void __goblint_split_end(int exp) { } -void __goblint_bounded(int exp) { - +void __goblint_bounded(unsigned long long exp) { + } \ No newline at end of file diff --git a/src/maingoblint.ml b/src/maingoblint.ml index 3d9959ba6c..82a19aa4ae 100644 --- a/src/maingoblint.ml +++ b/src/maingoblint.ml @@ -164,7 +164,8 @@ let check_arguments () = if List.mem "termination" @@ get_string_list "ana.activated" then ( if GobConfig.get_bool "incremental.load" || GobConfig.get_bool "incremental.save" then fail "termination analysis is not compatible with incremental analysis"; set_list "ana.activated" (GobConfig.get_list "ana.activated" @ [`String ("threadflag")]); - warn "termination analysis implicitly activates threadflag analysis." + set_string "sem.int.signed_overflow" "assume_none"; + warn "termination analysis implicitly activates threadflag analysis and set sem.int.signed_overflow to assume_none"; ); if not (get_bool "ana.sv-comp.enabled") && get_bool "witness.graphml.enabled" then fail "witness.graphml.enabled: cannot generate GraphML witness without SV-COMP mode (ana.sv-comp.enabled)" diff --git a/src/util/terminationPreprocessing.ml b/src/util/terminationPreprocessing.ml index eb950b1dbb..9023a68f8a 100644 --- a/src/util/terminationPreprocessing.ml +++ b/src/util/terminationPreprocessing.ml @@ -3,7 +3,7 @@ open GoblintCil module VarToStmt = Map.Make(CilType.Varinfo) (* maps varinfos (= loop counter variable) to the statement of the corresponding loop*) -let counter_ikind = IInt +let counter_ikind = IULongLong let counter_typ = TInt (counter_ikind, []) let min_int_exp = (* Currently only tested for IInt type, which is signed *) From 2728c2a56c87808e367b1b18841bed6a7e5744c3 Mon Sep 17 00:00:00 2001 From: Julian Erhard Date: Tue, 14 Nov 2023 10:19:58 +0100 Subject: [PATCH 313/327] Termination: Update verdict to TODO for 78/35. Case can no longer be handled when no longer using signed integers and assuming no-overflow. --- .../35-goto-out-of-inner-loop-with-print-terminating.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/regression/78-termination/35-goto-out-of-inner-loop-with-print-terminating.c b/tests/regression/78-termination/35-goto-out-of-inner-loop-with-print-terminating.c index 0554a0bc25..4c738e1173 100644 --- a/tests/regression/78-termination/35-goto-out-of-inner-loop-with-print-terminating.c +++ b/tests/regression/78-termination/35-goto-out-of-inner-loop-with-print-terminating.c @@ -1,4 +1,4 @@ -// SKIP TERM PARAM: --set "ana.activated[+]" termination --set "ana.activated[+]" apron --enable ana.int.interval --set ana.apron.domain polyhedra --set sem.int.signed_overflow assume_none +// SKIP TODO TERM PARAM: --set "ana.activated[+]" termination --set "ana.activated[+]" apron --enable ana.int.interval --set ana.apron.domain polyhedra --set sem.int.signed_overflow assume_none #include int main() From 8934a2133c009059738063f0851ed483f74d6276 Mon Sep 17 00:00:00 2001 From: Julian Erhard Date: Tue, 14 Nov 2023 14:10:00 +0100 Subject: [PATCH 314/327] Autotuner: Activate termination analysis in autotuner. --- conf/svcomp23.json | 3 ++- src/autoTune.ml | 17 ++++++++++++++--- 2 files changed, 16 insertions(+), 4 deletions(-) diff --git a/conf/svcomp23.json b/conf/svcomp23.json index af584f1593..f46ae13e86 100644 --- a/conf/svcomp23.json +++ b/conf/svcomp23.json @@ -70,7 +70,8 @@ "congruence", "octagon", "wideningThresholds", - "loopUnrollHeuristic" + "loopUnrollHeuristic", + "termination" ] } }, diff --git a/src/autoTune.ml b/src/autoTune.ml index 51e4ea412e..672d71b7ba 100644 --- a/src/autoTune.ml +++ b/src/autoTune.ml @@ -243,7 +243,7 @@ let focusOnSpecification (spec: Svcomp.Specification.t) = | NoDataRace -> (*enable all thread analyses*) print_endline @@ "Specification: NoDataRace -> enabling thread analyses \"" ^ (String.concat ", " notNeccessaryThreadAnalyses) ^ "\""; enableAnalyses notNeccessaryThreadAnalyses; - | Termination -> + | Termination -> let terminationAnas = ["termination"; "threadflag"; "apron"] in print_endline @@ "Specification: Termination -> enabling termination analyses \"" ^ (String.concat ", " terminationAnas) ^ "\""; enableAnalyses terminationAnas; @@ -466,6 +466,11 @@ let wideningOption factors file = print_endline "Enabled widening thresholds"; } +let activateTerminationAnalysis () = + enableAnalyses ["termination"; "apron"]; + set_string "sem.int.signed_overflow" "assume_none"; + set_string "ana.apron.domain" "polyhedra"; + set_bool "ana.int.interval_threshold_widening" true let estimateComplexity factors file = let pathsEstimate = factors.loops + factors.controlFlowStatements / 90 in @@ -495,6 +500,8 @@ let chooseFromOptions costTarget options = let isActivated a = get_bool "ana.autotune.enabled" && List.mem a @@ get_string_list "ana.autotune.activated" +let isTerminationTask () = List.mem Svcomp.Specification.Termination (Svcomp.Specification.of_option ()) + let chooseConfig file = let factors = collectFactors visitCilFileSameGlobals file in let fileCompplexity = estimateComplexity factors file in @@ -528,10 +535,14 @@ let chooseConfig file = let options = [] in let options = if isActivated "congruence" then (congruenceOption factors file)::options else options in - let options = if isActivated "octagon" then (apronOctagonOption factors file)::options else options in + + (* Termination analysis uses apron in a different configuration. *) + let options = if isActivated "octagon" && not (isTerminationTask ()) then (apronOctagonOption factors file)::options else options in let options = if isActivated "wideningThresholds" then (wideningOption factors file)::options else options in - List.iter (fun o -> o.activate ()) @@ chooseFromOptions (totalTarget - fileCompplexity) options + List.iter (fun o -> o.activate ()) @@ chooseFromOptions (totalTarget - fileCompplexity) options; + if isActivated "termination" && isTerminationTask () then + activateTerminationAnalysis () let reset_lazy () = ResettableLazy.reset functionCallMaps From d5662c5455290e166d5023724d843f0b3a92ef07 Mon Sep 17 00:00:00 2001 From: Julian Erhard Date: Wed, 15 Nov 2023 13:13:12 +0100 Subject: [PATCH 315/327] Indicate that termination analysis is activated. --- src/autoTune.ml | 1 + 1 file changed, 1 insertion(+) diff --git a/src/autoTune.ml b/src/autoTune.ml index 672d71b7ba..c1e982aace 100644 --- a/src/autoTune.ml +++ b/src/autoTune.ml @@ -467,6 +467,7 @@ let wideningOption factors file = } let activateTerminationAnalysis () = + print_endline "Enabling termination analysis"; enableAnalyses ["termination"; "apron"]; set_string "sem.int.signed_overflow" "assume_none"; set_string "ana.apron.domain" "polyhedra"; From 245b438a5c9e313d78391fae6be93579b8b4a5bb Mon Sep 17 00:00:00 2001 From: Julian Erhard Date: Wed, 15 Nov 2023 15:19:20 +0100 Subject: [PATCH 316/327] Change wording from enabling to enabled for consistency. --- src/autoTune.ml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/autoTune.ml b/src/autoTune.ml index c1e982aace..645fcfcf84 100644 --- a/src/autoTune.ml +++ b/src/autoTune.ml @@ -467,11 +467,11 @@ let wideningOption factors file = } let activateTerminationAnalysis () = - print_endline "Enabling termination analysis"; enableAnalyses ["termination"; "apron"]; set_string "sem.int.signed_overflow" "assume_none"; set_string "ana.apron.domain" "polyhedra"; - set_bool "ana.int.interval_threshold_widening" true + set_bool "ana.int.interval_threshold_widening" true; + print_endline "Enabled termination analysis" let estimateComplexity factors file = let pathsEstimate = factors.loops + factors.controlFlowStatements / 90 in From cbe4ad0cb57f57b19e6f009c30c033cc9f5b0eb8 Mon Sep 17 00:00:00 2001 From: Julian Erhard Date: Wed, 15 Nov 2023 15:21:39 +0100 Subject: [PATCH 317/327] Add termination to autotune for svcomp.json, but remove it from svcomp23.json. --- conf/svcomp.json | 3 ++- conf/svcomp23.json | 3 +-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/conf/svcomp.json b/conf/svcomp.json index 73f99500b9..107c59994c 100644 --- a/conf/svcomp.json +++ b/conf/svcomp.json @@ -71,7 +71,8 @@ "octagon", "wideningThresholds", "loopUnrollHeuristic", - "memsafetySpecification" + "memsafetySpecification", + "termination" ] } }, diff --git a/conf/svcomp23.json b/conf/svcomp23.json index f46ae13e86..af584f1593 100644 --- a/conf/svcomp23.json +++ b/conf/svcomp23.json @@ -70,8 +70,7 @@ "congruence", "octagon", "wideningThresholds", - "loopUnrollHeuristic", - "termination" + "loopUnrollHeuristic" ] } }, From a466650aa752cd83655dded84cd56c52e8b1d0a0 Mon Sep 17 00:00:00 2001 From: Julian Erhard Date: Wed, 15 Nov 2023 15:26:44 +0100 Subject: [PATCH 318/327] Move LoopTermination in Goblint_lib to analyses/other section. --- src/goblint_lib.ml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/goblint_lib.ml b/src/goblint_lib.ml index e06f5fd245..cb18ad0dd7 100644 --- a/src/goblint_lib.ml +++ b/src/goblint_lib.ml @@ -124,7 +124,6 @@ module RelationPriv = RelationPriv module ThreadEscape = ThreadEscape module PthreadSignals = PthreadSignals module ExtractPthread = ExtractPthread -module LoopTermination = LoopTermination (** {2 Longjmp} @@ -149,6 +148,7 @@ module UnitAnalysis = UnitAnalysis module Assert = Assert module FileUse = FileUse +module LoopTermination = LoopTermination module Uninit = Uninit module Expsplit = Expsplit module StackTrace = StackTrace From b57b9e4589dccfba5810f841728355a4f72c205b Mon Sep 17 00:00:00 2001 From: Julian Erhard Date: Wed, 15 Nov 2023 15:54:14 +0100 Subject: [PATCH 319/327] Extract some loops into functions; this reduces runtime of analysis. --- .../15-complex-loop-combination-terminating.c | 84 ++++++++++--------- 1 file changed, 46 insertions(+), 38 deletions(-) diff --git a/tests/regression/78-termination/15-complex-loop-combination-terminating.c b/tests/regression/78-termination/15-complex-loop-combination-terminating.c index 1365611410..9b97d4051b 100644 --- a/tests/regression/78-termination/15-complex-loop-combination-terminating.c +++ b/tests/regression/78-termination/15-complex-loop-combination-terminating.c @@ -2,6 +2,49 @@ // Apron is not precise enough for some nested loops #include +int nested_while_loop_with_break(){ + int m; + + // Nested while loop with a break statement + int n = 1; + while (n <= 5) + { + printf("Outer While loop iteration: %d\n", n); + m = 1; + while (1) + { + printf("Inner While loop iteration: %d\n", m); + m++; + if (m == 4) + { + break; + } + } + n++; + } + return 0; +} + +int nested_loop_with_conditions(){ + // Loop with nested conditions + for (int v = 1; v <= 10; v++) + { + printf("Loop with Nested Conditions: %d - ", v); + if (v < 5) + { + printf("Less than 5\n"); + } + else if (v > 5) + { + printf("Greater than 5\n"); + } + else + { + printf("Equal to 5\n"); + } + } +} + int main() { // Non-nested loops @@ -67,44 +110,9 @@ int main() p++; } while (p <= 5); - // Additional loops - int m; - - // Nested while loop with a break statement - int n = 1; - while (n <= 5) - { - printf("Outer While loop iteration: %d\n", n); - m = 1; - while (1) - { - printf("Inner While loop iteration: %d\n", m); - m++; - if (m == 4) - { - break; - } - } - n++; - } - - // Loop with nested conditions - for (int v = 1; v <= 10; v++) - { - printf("Loop with Nested Conditions: %d - ", v); - if (v < 5) - { - printf("Less than 5\n"); - } - else if (v > 5) - { - printf("Greater than 5\n"); - } - else - { - printf("Equal to 5\n"); - } - } + // Additional nested loops + nested_while_loop_with_break(); + nested_loop_with_conditions(); return 0; } From 70ef2d293a647b8ddcd477789054e87e18eeff4f Mon Sep 17 00:00:00 2001 From: Julian Erhard Date: Wed, 15 Nov 2023 18:11:08 +0100 Subject: [PATCH 320/327] RelationalAnalysis: Assert type-bounds also for signed types when no-overflow is assumed. --- src/analyses/apron/relationAnalysis.apron.ml | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/analyses/apron/relationAnalysis.apron.ml b/src/analyses/apron/relationAnalysis.apron.ml index 13f549fc44..8ac55ca323 100644 --- a/src/analyses/apron/relationAnalysis.apron.ml +++ b/src/analyses/apron/relationAnalysis.apron.ml @@ -196,7 +196,7 @@ struct let assert_type_bounds ask rel x = assert (RD.Tracked.varinfo_tracked x); match Cilfacade.get_ikind x.vtype with - | ik when not (IntDomain.should_ignore_overflow ik) -> (* don't add type bounds for signed when assume_none *) + | ik -> (* don't add type bounds for signed when assume_none *) let (type_min, type_max) = IntDomain.Size.range ik in (* TODO: don't go through CIL exp? *) let e1 = BinOp (Le, Lval (Cil.var x), (Cil.kintegerCilint ik type_max), intType) in @@ -204,7 +204,6 @@ struct let rel = RD.assert_inv rel e1 false (no_overflow ask e1) in (* TODO: how can be overflow when asserting type bounds? *) let rel = RD.assert_inv rel e2 false (no_overflow ask e2) in rel - | _ | exception Invalid_argument _ -> rel From 8141869487223039bddcfce8e9215632a9db60bb Mon Sep 17 00:00:00 2001 From: Julian Erhard Date: Thu, 16 Nov 2023 17:44:58 +0100 Subject: [PATCH 321/327] Termination distribute loops into multiple functions to make analysis terminate faster. --- .../09-complex-for-loop-terminating.c | 15 ++- .../10-complex-loop-terminating.c | 98 ++++++++++++++++- .../15-complex-loop-combination-terminating.c | 100 ++++++++++-------- 3 files changed, 163 insertions(+), 50 deletions(-) diff --git a/tests/regression/78-termination/09-complex-for-loop-terminating.c b/tests/regression/78-termination/09-complex-for-loop-terminating.c index fb2acaf569..74ee41eae8 100644 --- a/tests/regression/78-termination/09-complex-for-loop-terminating.c +++ b/tests/regression/78-termination/09-complex-for-loop-terminating.c @@ -2,8 +2,7 @@ // Apron is not precise enough for some nested loops #include -int main() -{ +int loops0(){ int i, j, k; // Outer loop @@ -33,6 +32,11 @@ int main() } printf("\n"); } + return 0; +} + +int loops1(){ + int i, j, k; // Loop with conditions for (i = 1; i <= 10; i++) @@ -82,6 +86,13 @@ int main() { printf("%d %d %d\n", a, b, c); } + return 0; +} + +int main() +{ + loops0(); + loops1(); return 0; } diff --git a/tests/regression/78-termination/10-complex-loop-terminating.c b/tests/regression/78-termination/10-complex-loop-terminating.c index 738fe78683..96253c445f 100644 --- a/tests/regression/78-termination/10-complex-loop-terminating.c +++ b/tests/regression/78-termination/10-complex-loop-terminating.c @@ -2,7 +2,87 @@ // Apron is not precise enough for some nested loops #include -int main() +int loops0(){ + int i = 1; + int j = 1; + int k = 5; + + // Outer while loop + while (i <= 5) + { + // Inner while loop 1 + while (j <= i) + { + printf("%d ", j); + j++; + } + printf("\n"); + j = 1; + + // Inner while loop 2 + while (k >= 1) + { + printf("%d ", k); + k--; + } + printf("\n"); + k = 5; + + i++; + } + + // Additional while loop + i = 5; + while (i >= 1) + { + j = i; + while (j >= 1) + { + printf("%d ", j); + j--; + } + printf("\n"); + i--; + } + + // Loop with conditions + i = 1; + while (i <= 10) + { + if (i % 2 == 0) + { + printf("%d is even\n", i); + } + else + { + printf("%d is odd\n", i); + } + i++; + } + + // Loop with nested conditions + i = 1; + while (i <= 10) + { + printf("Number: %d - ", i); + if (i < 5) + { + printf("Less than 5\n"); + } + else if (i > 5) + { + printf("Greater than 5\n"); + } + else + { + printf("Equal to 5\n"); + } + i++; + } + return 0; +} + +int loops1() { int i = 1; int j = 1; @@ -61,6 +141,14 @@ int main() i++; } + return 0; +} + +int loops2(){ + int i = 1; + int j = 1; + int k = 5; + // Loop with nested conditions i = 1; while (i <= 10) @@ -119,6 +207,12 @@ int main() b += 2; c += 3; } - return 0; } + +int main(){ + loops0(); + loops1(); + loops2(); + return 0; +} \ No newline at end of file diff --git a/tests/regression/78-termination/15-complex-loop-combination-terminating.c b/tests/regression/78-termination/15-complex-loop-combination-terminating.c index 9b97d4051b..4912bbb1f2 100644 --- a/tests/regression/78-termination/15-complex-loop-combination-terminating.c +++ b/tests/regression/78-termination/15-complex-loop-combination-terminating.c @@ -2,51 +2,7 @@ // Apron is not precise enough for some nested loops #include -int nested_while_loop_with_break(){ - int m; - - // Nested while loop with a break statement - int n = 1; - while (n <= 5) - { - printf("Outer While loop iteration: %d\n", n); - m = 1; - while (1) - { - printf("Inner While loop iteration: %d\n", m); - m++; - if (m == 4) - { - break; - } - } - n++; - } - return 0; -} - -int nested_loop_with_conditions(){ - // Loop with nested conditions - for (int v = 1; v <= 10; v++) - { - printf("Loop with Nested Conditions: %d - ", v); - if (v < 5) - { - printf("Less than 5\n"); - } - else if (v > 5) - { - printf("Greater than 5\n"); - } - else - { - printf("Equal to 5\n"); - } - } -} - -int main() -{ +int non_nested_loops(){ // Non-nested loops int i; @@ -71,8 +27,11 @@ int main() printf("Do-While loop iteration: %d\n", k); k++; } while (k <= 10); + return 0; +} - // Nested loops +int nested_loops(){ + // Nested loops int a, b; // Nested for and while loop @@ -109,7 +68,56 @@ int main() } p++; } while (p <= 5); + return 0; +} + +int nested_while_loop_with_break(){ + int m; + // Nested while loop with a break statement + int n = 1; + while (n <= 5) + { + printf("Outer While loop iteration: %d\n", n); + m = 1; + while (1) + { + printf("Inner While loop iteration: %d\n", m); + m++; + if (m == 4) + { + break; + } + } + n++; + } + return 0; +} + +int nested_loop_with_conditions(){ + // Loop with nested conditions + for (int v = 1; v <= 10; v++) + { + printf("Loop with Nested Conditions: %d - ", v); + if (v < 5) + { + printf("Less than 5\n"); + } + else if (v > 5) + { + printf("Greater than 5\n"); + } + else + { + printf("Equal to 5\n"); + } + } +} + +int main() +{ + non_nested_loops(); + nested_loops(); // Additional nested loops nested_while_loop_with_break(); nested_loop_with_conditions(); From 1ef011c6b675d78b25f4928cbbac64b07edee740 Mon Sep 17 00:00:00 2001 From: Julian Erhard Date: Thu, 16 Nov 2023 17:48:19 +0100 Subject: [PATCH 322/327] Add test case that did not work when not asserting the type bounds for signed types when sem.int.signed_overflow was set to assume_none. --- .../78-termination/50-decreasing-signed-int.c | 13 +++++++++++++ 1 file changed, 13 insertions(+) create mode 100644 tests/regression/78-termination/50-decreasing-signed-int.c diff --git a/tests/regression/78-termination/50-decreasing-signed-int.c b/tests/regression/78-termination/50-decreasing-signed-int.c new file mode 100644 index 0000000000..01daa5ee21 --- /dev/null +++ b/tests/regression/78-termination/50-decreasing-signed-int.c @@ -0,0 +1,13 @@ +// SKIP TERM PARAM: --set "ana.activated[+]" termination --set ana.activated[+] apron --enable ana.int.interval --set ana.apron.domain octagon +int main() +{ + int x; + + if(x <= 0){ + return 0; + } + while (x > 0) { + x = x - 1; + } + return 0; +} From d9f39105b35e4c65ac01b457cdb19ab82ac17c87 Mon Sep 17 00:00:00 2001 From: Julian Erhard Date: Thu, 16 Nov 2023 17:49:31 +0100 Subject: [PATCH 323/327] Remove outdated comment. --- src/analyses/apron/relationAnalysis.apron.ml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/analyses/apron/relationAnalysis.apron.ml b/src/analyses/apron/relationAnalysis.apron.ml index 8ac55ca323..8b128eb271 100644 --- a/src/analyses/apron/relationAnalysis.apron.ml +++ b/src/analyses/apron/relationAnalysis.apron.ml @@ -196,7 +196,7 @@ struct let assert_type_bounds ask rel x = assert (RD.Tracked.varinfo_tracked x); match Cilfacade.get_ikind x.vtype with - | ik -> (* don't add type bounds for signed when assume_none *) + | ik -> let (type_min, type_max) = IntDomain.Size.range ik in (* TODO: don't go through CIL exp? *) let e1 = BinOp (Le, Lval (Cil.var x), (Cil.kintegerCilint ik type_max), intType) in From 26d8012e63f2c161a21146ce6e22480d1e4e930b Mon Sep 17 00:00:00 2001 From: Julian Erhard Date: Fri, 17 Nov 2023 15:18:32 +0100 Subject: [PATCH 324/327] Autotuner: Remove activateTerminationAnalysis, as there is already other code for it. --- src/autoTune.ml | 13 +------------ 1 file changed, 1 insertion(+), 12 deletions(-) diff --git a/src/autoTune.ml b/src/autoTune.ml index 645fcfcf84..cc1af59940 100644 --- a/src/autoTune.ml +++ b/src/autoTune.ml @@ -466,13 +466,6 @@ let wideningOption factors file = print_endline "Enabled widening thresholds"; } -let activateTerminationAnalysis () = - enableAnalyses ["termination"; "apron"]; - set_string "sem.int.signed_overflow" "assume_none"; - set_string "ana.apron.domain" "polyhedra"; - set_bool "ana.int.interval_threshold_widening" true; - print_endline "Enabled termination analysis" - let estimateComplexity factors file = let pathsEstimate = factors.loops + factors.controlFlowStatements / 90 in let operationEstimate = factors.instructions + (factors.expressions / 60) in @@ -536,14 +529,10 @@ let chooseConfig file = let options = [] in let options = if isActivated "congruence" then (congruenceOption factors file)::options else options in - (* Termination analysis uses apron in a different configuration. *) let options = if isActivated "octagon" && not (isTerminationTask ()) then (apronOctagonOption factors file)::options else options in let options = if isActivated "wideningThresholds" then (wideningOption factors file)::options else options in - List.iter (fun o -> o.activate ()) @@ chooseFromOptions (totalTarget - fileCompplexity) options; - - if isActivated "termination" && isTerminationTask () then - activateTerminationAnalysis () + List.iter (fun o -> o.activate ()) @@ chooseFromOptions (totalTarget - fileCompplexity) options let reset_lazy () = ResettableLazy.reset functionCallMaps From 28dca49ca7256db0af6415df2dfcf7345f502ef0 Mon Sep 17 00:00:00 2001 From: Julian Erhard Date: Fri, 17 Nov 2023 17:46:03 +0100 Subject: [PATCH 325/327] Add specification to activated settings for autotuner. --- conf/svcomp.json | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/conf/svcomp.json b/conf/svcomp.json index 107c59994c..cc6d1e303a 100644 --- a/conf/svcomp.json +++ b/conf/svcomp.json @@ -72,7 +72,8 @@ "wideningThresholds", "loopUnrollHeuristic", "memsafetySpecification", - "termination" + "termination", + "specification" ] } }, From a4adabd819b4e116a220976223efba85296fb833 Mon Sep 17 00:00:00 2001 From: Julian Erhard Date: Fri, 17 Nov 2023 17:52:31 +0100 Subject: [PATCH 326/327] Call Autotune.focusOnSpecification before preprocessing, as terminatino analysis needs to be activated before preprocessing to work. --- src/autoTune.ml | 7 +++++-- src/goblint.ml | 2 ++ 2 files changed, 7 insertions(+), 2 deletions(-) diff --git a/src/autoTune.ml b/src/autoTune.ml index cc1af59940..4b959749a7 100644 --- a/src/autoTune.ml +++ b/src/autoTune.ml @@ -496,6 +496,9 @@ let isActivated a = get_bool "ana.autotune.enabled" && List.mem a @@ get_string_ let isTerminationTask () = List.mem Svcomp.Specification.Termination (Svcomp.Specification.of_option ()) +let specificationIsActivated () = + isActivated "specification" && get_string "ana.specification" <> "" + let chooseConfig file = let factors = collectFactors visitCilFileSameGlobals file in let fileCompplexity = estimateComplexity factors file in @@ -515,8 +518,8 @@ let chooseConfig file = if isActivated "mallocWrappers" then findMallocWrappers (); - if isActivated "specification" && get_string "ana.specification" <> "" then - focusOnSpecification (); + (* if specificationIsActivated () then + focusOnSpecification (); *) if isActivated "enums" && hasEnums file then set_bool "ana.int.enums" true; diff --git a/src/goblint.ml b/src/goblint.ml index 4ea3a3d242..6c5a2df33d 100644 --- a/src/goblint.ml +++ b/src/goblint.ml @@ -38,6 +38,8 @@ let main () = print_endline (GobUnix.localtime ()); print_endline GobSys.command_line; ); + (* When analyzing a termination specification, activate the termination analysis before pre-processing. *) + if get_bool "ana.autotune.enabled" && AutoTune.specificationIsActivated () then AutoTune.focusOnSpecification (); let file = lazy (Fun.protect ~finally:GoblintDir.finalize preprocess_parse_merge) in if get_bool "server.enabled" then ( let file = From 41ee060fc81f1719b7834f53cf6213c85df358ef Mon Sep 17 00:00:00 2001 From: Julian Erhard Date: Fri, 17 Nov 2023 18:37:45 +0100 Subject: [PATCH 327/327] Do loop unrolling for loops with boundedness check. --- src/util/loopUnrolling.ml | 1 + 1 file changed, 1 insertion(+) diff --git a/src/util/loopUnrolling.ml b/src/util/loopUnrolling.ml index 4ce8fc06b4..e1a8ad542b 100644 --- a/src/util/loopUnrolling.ml +++ b/src/util/loopUnrolling.ml @@ -320,6 +320,7 @@ class loopUnrollingCallVisitor = object | Unlock _ | ThreadCreate _ | Assert _ + | Bounded _ | ThreadJoin _ -> raise Found; | _ ->