diff --git a/src/plugins/alias/.gitattributes b/src/plugins/alias/.gitattributes
new file mode 100644
index 0000000000000000000000000000000000000000..71a6c8afbd063a189a98779343b9c0195dadbbd7
--- /dev/null
+++ b/src/plugins/alias/.gitattributes
@@ -0,0 +1,76 @@
+################
+# MERGE: union #
+################
+
+Changelog merge=union
+
+##################################################
+# BINARY/CHECK-SYNTAX/INDENT/EOL-EOF: set/-unset #
+##################################################
+
+# note: "binary" is a built-in macro that also
+#       unsets the "text" and "diff" attributes
+
+# note: set "check-eoleof" and "check-utf8" by default to all files
+* check-eoleof check-utf8
+
+# note: unset "-check-eoleof" and "-check-utf8" for "binary"
+*.jpg binary -check-eoleof -check-utf8
+*.pdf binary -check-eoleof -check-utf8
+
+###########################################
+# CHECK-SYNTAX/INDENT/EOL-EOF: set/-unset #
+###########################################
+
+*.ml  check-syntax check-indent -check-eoleof
+*.mli check-syntax check-indent -check-eoleof
+
+################################
+# HEADER_SPEC: LICENSE.Alias #
+################################
+
+dune-project header_spec=LICENSE.Alias
+dune header_spec=LICENSE.Alias
+dune-workspace header_spec=LICENSE.Alias
+
+Make* header_spec=LICENSE.Alias
+
+*.ml header_spec=LICENSE.Alias
+*.mli header_spec=LICENSE.Alias
+
+########################
+# HEADER_SPEC: .ignore #
+########################
+
+# CI
+
+/.gitlab-ci.yml header_spec=.ignore
+/nix/ci.sh  header_spec=.ignore
+/nix/*.nix header_spec=.ignore
+
+# Doc
+
+/Changelog header_spec=.ignore
+README* header_spec=.ignore
+
+# Git
+
+.gitattributes header_spec=.ignore
+.gitignore header_spec=.ignore
+.gitkeep header_spec=.ignore
+.git-blame-ignore-revs header_spec=.ignore
+
+# Headers
+
+/LICENSE.Alias header_spec=.ignore
+/headers/open-source/* header_spec=.ignore
+/headers/close-source/* header_spec=.ignore
+
+# OCaml
+
+/*.opam* header_spec=.ignore
+/.ocp-indent header_spec=.ignore
+
+#Tests
+
+/tests/**/* header_spec=.ignore
diff --git a/src/plugins/alias/.gitignore b/src/plugins/alias/.gitignore
new file mode 100644
index 0000000000000000000000000000000000000000..bf8b4fea7803f726f79270ec0f26987cc09914f7
--- /dev/null
+++ b/src/plugins/alias/.gitignore
@@ -0,0 +1,3 @@
+/_build
+tests/**/result
+tests/*/oracle/dune
diff --git a/src/plugins/alias/.gitlab-ci.yml b/src/plugins/alias/.gitlab-ci.yml
new file mode 100644
index 0000000000000000000000000000000000000000..d4c9ff04cbd35981d073e8a999033b0bb70289c7
--- /dev/null
+++ b/src/plugins/alias/.gitlab-ci.yml
@@ -0,0 +1,40 @@
+################################################################################
+### STAGES
+
+stages:
+  - tests
+
+################################################################################
+### DEFAULT JOB PARAMETERS
+
+default:
+  tags: [nix-v2]
+
+################################################################################
+### VARIABLES
+
+variables:
+  DEFAULT: "master"
+  OCAML: "4.11"
+
+################################################################################
+### TESTS
+
+build-and-test:
+  stage: tests
+  script:
+    - ./nix/ci.sh
+
+check-headers:
+  stage: tests
+  variables:
+    CI_MODE: "check-headers"
+  script:
+    - ./nix/ci.sh
+
+lint:
+  stage: tests
+  variables:
+    CI_MODE: "lint"
+  script:
+    - ./nix/ci.sh
diff --git a/src/plugins/alias/.ocp-indent b/src/plugins/alias/.ocp-indent
new file mode 100644
index 0000000000000000000000000000000000000000..31dcc35bf57a9873077570a3776515be93e129d9
--- /dev/null
+++ b/src/plugins/alias/.ocp-indent
@@ -0,0 +1 @@
+normal
diff --git a/src/plugins/alias/API.ml b/src/plugins/alias/API.ml
new file mode 100644
index 0000000000000000000000000000000000000000..2b77720334f40c9d71c2a9bb80d2ea4437f51698
--- /dev/null
+++ b/src/plugins/alias/API.ml
@@ -0,0 +1,126 @@
+(**************************************************************************)
+(*                                                                        *)
+(*  This file is part of the Frama-C plug-in 'Alias' (alias).             *)
+(*                                                                        *)
+(*  Copyright (C) 2022-2023                                               *)
+(*    CEA (Commissariat à l'énergie atomique et aux énergies              *)
+(*         alternatives)                                                  *)
+(*                                                                        *)
+(*  you can redistribute it and/or modify it under the terms of the GNU   *)
+(*  Lesser General Public License as published by the Free Software       *)
+(*  Foundation, version 2.1.                                              *)
+(*                                                                        *)
+(*  It is distributed in the hope that it will be useful,                 *)
+(*  but WITHOUT ANY WARRANTY; without even the implied warranty of        *)
+(*  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *)
+(*  GNU Lesser General Public License for more details.                   *)
+(*                                                                        *)
+(*  See the GNU Lesser General Public License version 2.1                 *)
+(*  for more details (enclosed in the file LICENSE)                       *)
+(*                                                                        *)
+(**************************************************************************)
+
+open Cil_types
+
+open Simplified
+
+(** Points-to graphs datastructure. *)
+module G = Abstract_state.G
+
+module LSet = Simplified_lset
+
+module Abstract_state = Abstract_state
+
+let check_computed () =
+  if not (Analysis.is_computed ())
+  then
+    Options.abort "Static analysis must be called before any function of the API can be called"
+
+
+let fold_aliases_stmt (f_fold : 'a -> lval -> 'a) (acc: 'a) (kf: kernel_function)  (s:stmt) (lv: lval) : 'a =
+  check_computed ();
+  match Analysis.get_state_before_stmt kf s with
+    None -> acc
+  | Some state ->
+    let set_aliases = Abstract_state.find_all_aliases lv state in
+    LSet.fold_lval (fun e a -> f_fold a e) set_aliases acc
+
+let fold_new_aliases_stmt (f_fold: 'a -> lval -> 'a) (acc: 'a) (kf:kernel_function) (s:stmt) (lv:lval) : 'a =
+  check_computed ();
+  match Analysis.get_state_before_stmt kf s with
+    None -> acc
+  | Some state ->
+    let new_state = Analysis.do_stmt state s in
+    let set_aliases = Abstract_state.find_all_aliases lv new_state in
+    LSet.fold_lval (fun e a -> f_fold a e) set_aliases acc
+
+let fold_aliases_kf (f_fold: 'a -> lval -> 'a) (acc: 'a) (kf:kernel_function) (lv:lval) : 'a =
+  check_computed ();
+  if Kernel_function.has_definition kf
+  then
+    let s = Kernel_function.find_return kf in
+    fold_new_aliases_stmt f_fold acc kf s lv
+  else
+    Options.abort "fold_aliases_kf: function %a has no definition" Kernel_function.pretty kf
+
+let fold_fundec_stmts (f_fold: 'a -> stmt -> lval -> 'a) (acc: 'a) (kf:kernel_function) (lv:lval) : 'a =
+  check_computed ();
+  if Kernel_function.has_definition kf
+  then
+    let f_dec = Kernel_function.get_definition kf in
+    let list_stmt = f_dec.sallstmts in
+    List.fold_left
+      (fun acc s ->
+         fold_new_aliases_stmt
+           (fun a lv -> f_fold a s lv)
+           acc
+           kf
+           s
+           lv
+      )
+      acc
+      list_stmt
+  else
+    Options.abort "fold_fundec_stmts: function %a has no definition" Kernel_function.pretty kf
+
+let are_aliased (kf: kernel_function) (s:stmt) (lv1: lval) (lv2:lval) : bool =
+  check_computed ();
+  match Analysis.get_state_before_stmt kf s with
+    None -> false
+  | Some state ->
+    let setv1 = Abstract_state.find_all_aliases lv1 state in
+    LSet.mem (BLval lv2) setv1
+
+let fold_vertex   (f_fold : 'a -> G.V.t -> lval -> 'a) (acc: 'a) (kf: kernel_function)  (s:stmt) (lv: lval) : 'a =
+  check_computed ();
+  match Analysis.get_state_before_stmt kf s with
+    None -> acc
+  | Some state ->
+    let v : G.V.t = Abstract_state.find_vertex lv state in
+    let set_aliases = Abstract_state.find_aliases lv state in
+    LSet.fold_lval (fun lv a-> f_fold a v lv) set_aliases acc
+
+let fold_vertex_closure  (f_fold : 'a -> G.V.t -> lval -> 'a) (acc: 'a) (kf: kernel_function)  (s:stmt) (lv: lval) : 'a =
+  check_computed ();
+  match Analysis.get_state_before_stmt kf s with
+    None -> acc
+  | Some state ->
+    let list_closure : (G.V.t * LSet.t) list = Abstract_state.find_transitive_closure lv state in
+    List.fold_left
+      (fun acc (i,s) -> LSet.fold_lval (fun lv a -> f_fold a i lv) s acc)
+      acc
+      list_closure
+
+let get_state_before_stmt =
+  Analysis.get_state_before_stmt
+
+let call_function a f res args =
+  match Analysis.get_summary f with
+    None -> None
+  | Some su -> Some(Abstract_state.call a res args su)
+
+
+let simplify_lval (lv:lval) : lval =
+  match Simplified.Simplified_lval.from_lval lv with
+    BLval lv -> lv
+  | _ -> Options.fatal "This should not happen"
diff --git a/src/plugins/alias/API.mli b/src/plugins/alias/API.mli
new file mode 100644
index 0000000000000000000000000000000000000000..ca429be02ec70ee7ff6836ea9ec6794b867da0f6
--- /dev/null
+++ b/src/plugins/alias/API.mli
@@ -0,0 +1,93 @@
+(**************************************************************************)
+(*                                                                        *)
+(*  This file is part of the Frama-C plug-in 'Alias' (alias).             *)
+(*                                                                        *)
+(*  Copyright (C) 2022-2023                                               *)
+(*    CEA (Commissariat à l'énergie atomique et aux énergies              *)
+(*         alternatives)                                                  *)
+(*                                                                        *)
+(*  you can redistribute it and/or modify it under the terms of the GNU   *)
+(*  Lesser General Public License as published by the Free Software       *)
+(*  Foundation, version 2.1.                                              *)
+(*                                                                        *)
+(*  It is distributed in the hope that it will be useful,                 *)
+(*  but WITHOUT ANY WARRANTY; without even the implied warranty of        *)
+(*  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *)
+(*  GNU Lesser General Public License for more details.                   *)
+(*                                                                        *)
+(*  See the GNU Lesser General Public License version 2.1                 *)
+(*  for more details (enclosed in the file LICENSE)                       *)
+(*                                                                        *)
+(**************************************************************************)
+
+(** External API of the plugin Alias *)
+
+open Cil_types
+
+(** Points-to graphs datastructure. *)
+module G: Graph.Sig.G
+
+(** NB : do the analysis BEFORE using any of those functions *)
+
+(* previously get_class_before_statement *)
+(** [fold_aliases_stmt f acc kf s lv] folds [f acc] over all the aliases of the
+    given lval [lv] right before stmt [s] in function [kf]. *)
+val fold_aliases_stmt:
+  ('a -> lval -> 'a) -> 'a -> kernel_function -> stmt -> lval -> 'a
+
+(* previously get_class_after_statment *)
+(** [fold_new_aliases_stmt f acc kf s lv] folds [f acc] over all the aliases of
+    the given lval [lv] created by stmt [s] in function [kf]. *)
+val fold_new_aliases_stmt:
+  ('a -> lval -> 'a) -> 'a -> kernel_function -> stmt -> lval -> 'a
+
+(* previously get_class_fundec *)
+(** [fold_aliases_kf f acc kf lv] folds [f acc] over all the aliases of lval
+    [lv] at the end of function [kf]. *)
+val fold_aliases_kf:
+  ('a -> lval -> 'a) -> 'a -> kernel_function -> lval -> 'a
+
+(** [fold_fundec_stmts f acc kf v] folds [f acc s e] on the list of
+    pairs [s, e] where [e] is the set of lval aliased to [v] after statement [s]
+    in function [kf]. *)
+val fold_fundec_stmts:
+  ('a -> stmt -> lval -> 'a) -> 'a -> kernel_function -> lval -> 'a
+
+(** [are_aliased kf s lv1 lv2] returns true if and only if the two
+    lvals [lv1] and [lv2] are aliased before stmt [s] in function
+    [kf]. *)
+val are_aliased: kernel_function -> stmt -> lval -> lval -> bool
+
+(** [fold_vertex f acc kf s v] folds [f acc i lv] to all [lv] in [i], where [i] is
+    the vertex that represents the equivalence class of [v] before statement [s] in function [kf]. *)
+val fold_vertex:
+  ('a -> G.V.t -> lval -> 'a) -> 'a  -> kernel_function -> stmt -> lval  -> 'a
+
+(** [fold_vertex_closure f acc kf s v] is the transitive closure of function
+    [fold_vertex]. *)
+val fold_vertex_closure:
+  ('a -> G.V.t -> lval -> 'a) -> 'a  -> kernel_function -> stmt -> lval  -> 'a
+
+
+(** direct access to the abstract state. See Abstract_state.mli *)
+
+module Abstract_state : Abstract_state.S
+
+(** [get_state_before_stmt f s] gets the abstract state computed after
+    statement [s] in function [f]. Returns [None] if
+    the abstract state is bottom or not computed. *)
+val get_state_before_stmt :  kernel_function -> stmt -> Abstract_state.t option
+
+
+(** [call_function a f Some(res) args] computes the abstract state
+    after the instruction res=f(args) where res is a lval. [a] is the
+    abstract state before the call. If function [f] returns no value,
+    use [call_function a f None args] instead. Returns [None] if
+    the abstract state [a] is bottom or not computed. *)
+val call_function: Abstract_state.t -> kernel_function -> lval option -> exp list -> Abstract_state.t option
+
+
+(** [simplify_lval lv] returns a lval where every index of an array is
+    replaced by 0, evey pointer arithmetic is simplified to an access
+    to an array *)
+val simplify_lval: lval -> lval
diff --git a/src/plugins/alias/Alias.ml b/src/plugins/alias/Alias.ml
new file mode 100644
index 0000000000000000000000000000000000000000..0d38459c28ab0731dfc4ba3486309aed13df9030
--- /dev/null
+++ b/src/plugins/alias/Alias.ml
@@ -0,0 +1,36 @@
+(**************************************************************************)
+(*                                                                        *)
+(*  This file is part of the Frama-C plug-in 'Alias' (alias).             *)
+(*                                                                        *)
+(*  Copyright (C) 2022-2023                                               *)
+(*    CEA (Commissariat à l'énergie atomique et aux énergies              *)
+(*         alternatives)                                                  *)
+(*                                                                        *)
+(*  you can redistribute it and/or modify it under the terms of the GNU   *)
+(*  Lesser General Public License as published by the Free Software       *)
+(*  Foundation, version 2.1.                                              *)
+(*                                                                        *)
+(*  It is distributed in the hope that it will be useful,                 *)
+(*  but WITHOUT ANY WARRANTY; without even the implied warranty of        *)
+(*  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *)
+(*  GNU Lesser General Public License for more details.                   *)
+(*                                                                        *)
+(*  See the GNU Lesser General Public License version 2.1                 *)
+(*  for more details (enclosed in the file LICENSE)                       *)
+(*                                                                        *)
+(**************************************************************************)
+
+
+module Analysis = Analysis
+
+module API = API
+
+let main () =
+  if Options.Enabled.get() then
+    begin
+      Analysis.compute ();
+      Options.debug "Analysis complete";
+    end
+
+let () =
+  Db.Main.extend main
diff --git a/src/plugins/alias/Alias.mli b/src/plugins/alias/Alias.mli
new file mode 100644
index 0000000000000000000000000000000000000000..96a5e0094acff8b7eca10c4ad525dc3b15fa98b8
--- /dev/null
+++ b/src/plugins/alias/Alias.mli
@@ -0,0 +1,32 @@
+(**************************************************************************)
+(*                                                                        *)
+(*  This file is part of the Frama-C plug-in 'Alias' (alias).             *)
+(*                                                                        *)
+(*  Copyright (C) 2022-2023                                               *)
+(*    CEA (Commissariat à l'énergie atomique et aux énergies              *)
+(*         alternatives)                                                  *)
+(*                                                                        *)
+(*  you can redistribute it and/or modify it under the terms of the GNU   *)
+(*  Lesser General Public License as published by the Free Software       *)
+(*  Foundation, version 2.1.                                              *)
+(*                                                                        *)
+(*  It is distributed in the hope that it will be useful,                 *)
+(*  but WITHOUT ANY WARRANTY; without even the implied warranty of        *)
+(*  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *)
+(*  GNU Lesser General Public License for more details.                   *)
+(*                                                                        *)
+(*  See the GNU Lesser General Public License version 2.1                 *)
+(*  for more details (enclosed in the file LICENSE)                       *)
+(*                                                                        *)
+(**************************************************************************)
+
+(** Interface for the Alias plug-in. *)
+
+module Analysis: sig
+  (** see file analysis.mli for documentation *)
+  val compute : unit -> unit
+  val clear : unit -> unit
+end
+
+
+module API = API
diff --git a/src/plugins/alias/LICENSE.Alias b/src/plugins/alias/LICENSE.Alias
new file mode 100644
index 0000000000000000000000000000000000000000..57a2745d01d2fc7935756153dc194f934af4ebf5
--- /dev/null
+++ b/src/plugins/alias/LICENSE.Alias
@@ -0,0 +1,19 @@
+
+This file is part of the Frama-C plug-in 'Alias' (alias).
+
+Copyright (C) 2022-2023
+  CEA (Commissariat à l'énergie atomique et aux énergies
+       alternatives)
+
+you can redistribute it and/or modify it under the terms of the GNU
+Lesser General Public License as published by the Free Software
+Foundation, version 2.1.
+
+It is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+GNU Lesser General Public License for more details.
+
+See the GNU Lesser General Public License version 2.1
+for more details (enclosed in the file LICENSE)
+
diff --git a/src/plugins/alias/Makefile b/src/plugins/alias/Makefile
new file mode 100644
index 0000000000000000000000000000000000000000..f2765fe084bff0f5fee2ce7f5154e368be87ed9d
--- /dev/null
+++ b/src/plugins/alias/Makefile
@@ -0,0 +1,76 @@
+##########################################################################
+#                                                                        #
+#  This file is part of the Frama-C plug-in 'Alias' (alias).             #
+#                                                                        #
+#  Copyright (C) 2022-2023                                               #
+#    CEA (Commissariat à l'énergie atomique et aux énergies              #
+#         alternatives)                                                  #
+#                                                                        #
+#  you can redistribute it and/or modify it under the terms of the GNU   #
+#  Lesser General Public License as published by the Free Software       #
+#  Foundation, version 2.1.                                              #
+#                                                                        #
+#  It is distributed in the hope that it will be useful,                 #
+#  but WITHOUT ANY WARRANTY; without even the implied warranty of        #
+#  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         #
+#  GNU Lesser General Public License for more details.                   #
+#                                                                        #
+#  See the GNU Lesser General Public License version 2.1                 #
+#  for more details (enclosed in the file LICENSE)                       #
+#                                                                        #
+##########################################################################
+
+.PHONY: all build-profiling build clean
+
+FRAMAC_SHARE:=$(shell frama-c -print-share-path)
+
+sinclude ${FRAMAC_SHARE}/Makefile.common
+
+##########################################################################
+# Build
+
+all:: build frama-c-alias.opam
+
+frama-c-alias.opam: frama-c-alias.opam.template dune-project
+	rm -f $@
+	dune build $@
+
+build::
+	dune build @install
+
+build-profiling::
+	dune build --instrument-with landmarks @install
+
+clean:: purge-tests
+	dune clean
+	rm -rf _build .merlin
+
+##########################################################################
+# Tests
+
+include ${FRAMAC_SHARE}/Makefile.testing
+
+##########################################################################
+# Install
+
+include ${FRAMAC_SHARE}/Makefile.installation
+
+##########################################################################
+# Headers
+
+HDRCK_EXTRA:=-headache-config-file ${FRAMAC_SHARE}/headache_config.txt
+include ${FRAMAC_SHARE}/Makefile.headers
+
+SHORT_NAME:=alias
+LONG_NAME:=Alias
+PLUGIN_NAME:=Alias
+FROM_YEAR:=2022
+
+include headers/Makefile.generate-headers
+
+##########################################################################
+# Linting
+
+include ${FRAMAC_SHARE}/Makefile.linting
+
+##########################################################################
diff --git a/src/plugins/alias/README.md b/src/plugins/alias/README.md
new file mode 100644
index 0000000000000000000000000000000000000000..7c9694c4dd98c788a5ad01cf6acd1524a6db0990
--- /dev/null
+++ b/src/plugins/alias/README.md
@@ -0,0 +1,22 @@
+# MERCE
+
+GIT project for our collaboration with MERCE
+
+
+## Project Members
+
+Allan Blanchard
+Loïc Correnson
+Tristan Le Gall
+Jan Rochel
+Julien Signoles
+
+## Building
+
+This plug-in requires the library 'unionFind' that can be installed as follows:
+  opam install unionFind
+
+To build with profiling install the package landmarks-ppx and run:
+  dune build --instrument-with landmarks
+
+Using the plugin will then echo profiling information to stderr.
diff --git a/src/plugins/alias/abstract_state.ml b/src/plugins/alias/abstract_state.ml
new file mode 100644
index 0000000000000000000000000000000000000000..081e221dac1947625cb8195ae4dfe84eb53a214d
--- /dev/null
+++ b/src/plugins/alias/abstract_state.ml
@@ -0,0 +1,1031 @@
+(**************************************************************************)
+(*                                                                        *)
+(*  This file is part of the Frama-C plug-in 'Alias' (alias).             *)
+(*                                                                        *)
+(*  Copyright (C) 2022-2023                                               *)
+(*    CEA (Commissariat à l'énergie atomique et aux énergies              *)
+(*         alternatives)                                                  *)
+(*                                                                        *)
+(*  you can redistribute it and/or modify it under the terms of the GNU   *)
+(*  Lesser General Public License as published by the Free Software       *)
+(*  Foundation, version 2.1.                                              *)
+(*                                                                        *)
+(*  It is distributed in the hope that it will be useful,                 *)
+(*  but WITHOUT ANY WARRANTY; without even the implied warranty of        *)
+(*  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *)
+(*  GNU Lesser General Public License for more details.                   *)
+(*                                                                        *)
+(*  See the GNU Lesser General Public License version 2.1                 *)
+(*  for more details (enclosed in the file LICENSE)                       *)
+(*                                                                        *)
+(**************************************************************************)
+
+open Graph
+
+open Cil_types
+
+open Cil_datatype
+
+open Simplified
+
+module VSet = Datatype.Int.Set
+module VMap = Datatype.Int.Map
+
+module Lval = Simplified.Simplified_lval
+module LSet = Simplified.Simplified_lset
+module LMap = Simplified.Simplified_lmap
+
+module G = Persistent.Digraph.ConcreteBidirectional(Datatype.Int)
+
+module V = G.V
+
+(* like LMap, but organized with offset and specialized functions *)
+module LLMap =
+struct
+  module OMap = Offset.Map
+  (* each t is a map (lhost,NoOffset) -> offset -> V.t *)
+  type t = (V.t OMap.t) LMap.t
+
+  let empty : t = LMap.empty
+
+  let mem (lv:Lval.t) (m:t) =
+    let lv, off = Lval.removeOffsetLval lv in
+    try
+      OMap.mem off (LMap.find lv m)
+    with
+      Not_found -> false
+
+  let find (lv:Lval.t) (m:t) : V.t =
+    let lv, off = Lval.removeOffsetLval lv in
+    OMap.find off (LMap.find lv m)
+
+  let add (lv:Lval.t) (v:V.t) (m:t) :t  =
+    let lv, off = Lval.removeOffsetLval lv in
+    let mo = try LMap.find lv m with Not_found -> OMap.empty in
+    LMap.add lv (OMap.add off v mo) m
+
+  let remove (lv:Lval.t) (m:t) :t =
+    let lv, off = Lval.removeOffsetLval lv in
+    let mo = try LMap.find lv m with Not_found -> OMap.empty in
+    let res = OMap.remove off mo in
+    if OMap.is_empty res
+    then
+      LMap.remove lv m
+    else
+      LMap.add lv res m
+
+  let iter (f_iter: Lval.t -> V.t -> unit) (m:t) : unit =
+    LMap.iter
+      (fun lv mo ->
+         OMap.iter
+           (fun o v ->
+              let lv = Lval.addOffsetLval o lv in
+              f_iter lv v
+           )
+           mo
+      )
+      m
+
+  let map (f_map: V.t -> V.t ) (m:t) : 'a =
+    LMap.map
+      (fun mo ->
+         OMap.map
+           f_map
+           mo
+      )
+      m
+
+  let pretty fmt (m:t) =
+    let is_first = ref true in
+    LMap.iter
+      (fun lv mo ->
+         OMap.iter
+           (fun o v -> let lv =  Lval.addOffsetLval o lv in
+             if !is_first then is_first := false else Format.fprintf fmt "@;<3>";
+             Format.fprintf fmt "@ @[%a:%d@]" Lval.pretty lv v)
+           mo
+      )
+      m
+
+  (* left-biased *)
+  let union = LMap.union @@ fun _ l r -> Some (OMap.union (fun _ l _r -> Some l) l r)
+
+  let intersect =
+    let intersect_omap l r = match l, r with
+      | Some l, Some r -> Some (l,r)
+      | _ -> None
+    in
+    let intersect_lmap l r = match l, r with
+      | Some l, Some r ->
+        let omap = OMap.merge (fun _ -> intersect_omap) l r in
+        if OMap.is_empty omap then None else Some omap
+      | _ -> None
+    in
+    LMap.merge @@ fun _ -> intersect_lmap
+
+  let to_seq m = LMap.fold (fun lv omap s -> OMap.fold (fun o v s -> Seq.cons (lv,o,v) s) omap s) m Seq.empty
+
+  (* specialized functions *)
+  let rec is_sub_offset o1 o2 =
+    match (o1,o2) with
+      NoOffset, _ -> true
+    | Index (e1,o1), Index (e2,o2) when Cil_datatype.ExpStructEq.equal e1 e2 -> is_sub_offset o1 o2
+    | Field (f1,o1), Field (f2,o2) when Fieldinfo.equal f1 f2 ->  is_sub_offset o1 o2
+    | _ -> false
+
+  (* finds all the lval lv1 apearing in [m] such as there exists an offset o1 and lv1 + o1 = lv *)
+  let find_upper_offsets (lv:Lval.t) (m:t) : V.t LMap.t =
+    let lv, off = Lval.removeOffsetLval lv in
+    let mo = try LMap.find lv m with Not_found -> OMap.empty in
+    let f_filter o _v = is_sub_offset o off in
+    let mo = OMap.filter f_filter mo in
+    OMap.fold
+      (fun o v acc -> let lv = Lval.addOffsetLval o lv in LMap.add lv v acc)
+      mo
+      LMap.empty
+
+end
+
+module type S =
+sig
+
+  (* see .mli for coments *)
+  type t
+
+  val get_graph: t -> G.t
+
+  val get_lval_set : G.V.t -> t -> LSet.t
+
+  val pretty : ?debug:bool -> Format.formatter -> t -> unit
+
+  val print_dot : string -> t -> unit
+
+  val find_vertex : lval -> t -> G.V.t
+
+  val find_aliases : lval -> t -> LSet.t
+
+  val find_all_aliases : lval -> t -> LSet.t
+
+  val find_transitive_closure : lval -> t -> (G.V.t * LSet.t) list
+
+  val is_included : t -> t -> bool
+
+end
+
+type t = {
+  graph : G.t;
+  lmap : LLMap.t ; (* lmap(lv) is a table [offset->v] where the vertex v corresponding to lval (lv+offset), in other words (lv+offset) is in label(v) *)
+  vmap : LSet.t VMap.t ;(* reverse of lmap *)
+}
+
+let node_counter = ref 0
+let fresh_node_id () =
+  let id = !node_counter in
+  node_counter := !node_counter + 1;
+  id
+
+(* find functions *)
+let find_lset (v:V.t) (x:t) : LSet.t =
+  try VMap.find v x.vmap
+  with Not_found -> LSet.empty
+
+let find_aliases (lv:lval) (x:t) =
+  let lv : Lval.t = Lval.from_lval lv in
+  try
+    let v = LLMap.find lv x.lmap in
+    find_lset v x
+  with Not_found -> LSet.empty
+
+let rec get_points_to (v:V.t) (x:t) : LSet.t =
+  assert (G.mem_vertex x.graph v);
+  let set_predecessors =
+    List.fold_left
+      (fun acc v -> LSet.union acc (get_points_to v x))
+      LSet.empty
+      (G.pred x.graph v)
+  in
+  LSet.union
+    (find_lset v x)
+    (LSet.map Lval.points_to set_predecessors)
+
+let aliases_of_vertex (v:V.t) (x:t) : LSet.t =
+  assert (G.mem_vertex x.graph v);
+  let list_pred = G.pred x.graph v in
+  List.fold_left
+    (fun acc v -> LSet.union acc (get_points_to v x))
+    LSet.empty
+    list_pred
+
+let find_all_aliases (lv:lval) (x:t) : LSet.t =
+  let lv : Lval.t = Lval.from_lval lv in
+  try
+    begin
+      let v = LLMap.find lv x.lmap in
+      match G.succ x.graph v with
+        [] -> find_lset v x
+      | [succ_v] ->
+        aliases_of_vertex succ_v x
+      | _ -> Options.fatal "invariant violated (more than 1 successor)"
+    end
+  with Not_found -> LSet.empty
+
+let get_graph (x:t) = x.graph
+
+(* renamed for the interface *)
+let get_lval_set = find_lset
+
+
+(* printing functions *)
+
+let print_debug fmt (x:t) =
+  Format.fprintf fmt "@[<v>";
+  Format.fprintf fmt "@[Edges:";
+  G.iter_edges (fun v1 v2 -> Format.fprintf fmt "@;<3 2>@[%d → %d@]" v1 v2) x.graph;
+  Format.fprintf fmt "@]@;<6>";
+  Format.fprintf fmt "@[LMap:@;<3 2>";
+  LLMap.pretty fmt x.lmap;
+  Format.fprintf fmt "@]@;<6>";
+  Format.fprintf fmt "@[VMap:@;<2>";
+  VMap.iter (fun v ls -> Format.fprintf fmt "@;<2 2>@[%d:%a@]" v LSet.pretty ls) x.vmap;
+  Format.fprintf fmt "@]";
+  Format.fprintf fmt "@]"
+
+let print_graph fmt (x:t) =
+  let is_first = ref true in
+  let print_edge v1 v2 =
+    if !is_first then is_first := false else Format.fprintf fmt "@;<3>";
+    let print_node v fmt lset = Format.fprintf fmt "%d:%a" v LSet.pretty lset in
+    Format.fprintf fmt "@[%a@] → @[%a@]"
+      (print_node v1) (VMap.find v1 x.vmap)
+      (print_node v2) (VMap.find v2 x.vmap)
+  in
+  if G.nb_edges x.graph = 0
+  then Format.fprintf fmt "<empty>"
+  else G.iter_edges print_edge x.graph
+
+let print_aliases fmt (x:t) =
+  let is_first = ref true in
+  let print_alias_set _ set_lv =
+    if !is_first then is_first := false else Format.fprintf fmt "@;<2>";
+    LSet.pretty fmt set_lv
+  in
+  let alias_set_of_vertex i _ =
+    let aliases = aliases_of_vertex i x in
+    if LSet.cardinal aliases >= 2 then Some aliases else None
+  in
+  let alias_sets = VMap.filter_map alias_set_of_vertex x.vmap in
+  if VMap.is_empty alias_sets
+  then Format.fprintf fmt "<none>"
+  else VMap.iter print_alias_set alias_sets
+
+(** invariants of type t must be true before and after each functon call *)
+let assert_invariants (x:t) : unit =
+  (* check that all vertex of the graph have entries in vmap,
+     and are integer between 0 and node_counter, and have at most 1 successor *)
+  assert (!node_counter >= 0);
+  let assert_vertex (v:V.t) =
+    assert (v >= 0);
+    assert (v < !node_counter);
+    assert (VMap.mem v x.vmap);
+    assert (List.length (G.succ x.graph v) <= 1)
+  in
+  G.iter_vertex assert_vertex x.graph;
+  let assert_edge v1 v2 =
+    assert (v1 <> v2);
+    assert (G.mem_vertex x.graph v1);
+    assert (G.mem_vertex x.graph v2)
+  in
+  G.iter_edges assert_edge x.graph;
+  let assert_lmap (lv:Lval.t) (v:V.t) =
+    assert (G.mem_vertex x.graph v);
+    assert (LSet.mem lv (VMap.find v x.vmap))
+  in
+  LLMap.iter assert_lmap x.lmap;
+  let assert_vmap (v:V.t) (ls:LSet.t) =
+    assert (G.mem_vertex x.graph v);
+    (* TODO: we removed the invariant because of OSCS*)
+    (* if not (LSet.is_empty ls)
+     * then
+     *   begin
+     *     let lv = LSet.choose ls in
+     *     let is_ptr_lv = Lval.is_pointer lv in
+     *     assert (LSet.for_all (fun x -> Lval.is_pointer x = is_ptr_lv) ls)
+     *   end; *)
+    assert (LSet.fold (fun lv acc -> acc && V.equal (LLMap.find lv x.lmap) v) ls true)
+  in
+  VMap.iter assert_vmap x.vmap
+
+(* Ensure that assert_invariants is not executed if the -noassert flag is supplied. *)
+let assert_invariants x = assert (assert_invariants x; true)
+
+let pretty ?(debug = false) fmt (x:t) =
+  if debug then
+    try
+      assert_invariants x;
+      print_graph fmt x
+    with Assert_failure _ -> print_debug fmt x
+  else
+    print_aliases fmt x
+
+(** .dot printing functions*)
+let find_vertex_name_ref = Extlib.mk_fun "find_vertex_name"
+
+let lset_to_string (s: LSet.t) : string =
+  let fmt = Format.str_formatter in
+  Format.fprintf fmt "\"%a\"" LSet.pretty s;
+  Format.flush_str_formatter ()
+
+module Dot = Graphviz.Dot (struct
+    include G
+    let edge_attributes _ = []
+    let default_edge_attributes _ = []
+    let get_subgraph _ = None
+    let vertex_attributes _ = [`Shape `Box]
+    let vertex_name (v:V.t) =
+      let lset = !find_vertex_name_ref v in
+      lset_to_string lset
+    let default_vertex_attributes _ = []
+    let graph_attributes _ = []
+  end)
+
+let print_dot filename (a:t) =
+  let file = open_out filename in
+  find_vertex_name_ref :=
+    (fun v -> find_lset v a
+    );
+  Dot.output_graph file a.graph;
+  close_out file
+
+(* find functions, part 2 *)
+let rec closure_find_lset (v:V.t) (x:t) : (V.t * LSet.t) list =
+  match G.succ x.graph v with
+    [] -> [v, find_lset v x]
+  | [v_next] -> (v, find_lset v x)::(closure_find_lset v_next x)
+  | _ -> Options.fatal ("this shall not happen (invariant broken)")
+
+let find_transitive_closure  (lv:lval) (x:t) : (G.V.t * LSet.t) list =
+  let lv: Lval.t = Lval.from_lval lv in
+  assert_invariants x;
+  try
+    let v = (LLMap.find lv x.lmap) in
+    closure_find_lset v x
+  with
+    Not_found -> []
+(* TODO : what about offsets ? *)
+
+(* NOTE on "constant vertex": a constant vertex represents an unamed
+   scalar value (type bottom in steensgaard's paper), or the address
+   of a variable. It means that in [vmap], its associated LSet is
+   empty.  By definition, constant vertex cannot be associated to a
+   lval in [lmap] *)
+let create_cst_vertex (x:t) : V.t * t =
+  let new_v = fresh_node_id () in
+  let new_g = G.add_vertex x.graph new_v in
+  let new_lmap = x.lmap in
+  let new_vmap = VMap.add new_v LSet.empty x.vmap in
+  new_v ,
+  {
+    graph = new_g ;
+    lmap = new_lmap ;
+    vmap = new_vmap ;
+  }
+
+(* find all the aliases of lv1 in x, for create_vertex *)
+let find_all_aliases_of_offset (lv1: Lval.t) (x: t) : LSet.t =
+
+  let list_of_lval_to_be_searched : (Lval.t*offset) list =
+    decompose_lval lv1
+  in
+  (* for each lval, find the set of aliases *)
+  let f_map (lv,o) =
+    try (VMap.find (LLMap.find lv x.lmap) x.vmap, o)
+    with
+      Not_found -> (LSet.empty,o)
+  in
+  Options.debug ~level:9 "decompose_lval %a : [@[<hov 2>" Lval.pretty lv1;
+  List.iter (fun (x, o) -> Options.debug ~level:9 " (%a,%a) " Lval.pretty x Offset.pretty o) list_of_lval_to_be_searched;
+  Options.debug ~level:9 "@]]";
+  let list_of_aliases : (LSet.t*offset) list =
+    List.map f_map list_of_lval_to_be_searched
+  in
+  (*  for each lval of the Lset, add the offset and add it to the resulting set *)
+  let f_fold_left (acc:LSet.t) (ls,o) =
+    LSet.fold
+      (fun lv acc -> let lv = Lval.addOffsetLval o lv in LSet.add lv acc)
+      ls
+      acc
+  in
+  List.fold_left
+    f_fold_left
+    (LSet.singleton lv1)
+    list_of_aliases
+
+(* returns the new vertex and the new graph *)
+(* only for function find_or_create vertex *)
+let create_vertex_simple (lv:Lval.t) (x:t) : V.t * t =
+  let new_v = fresh_node_id () in
+  let new_g = G.add_vertex x.graph new_v in
+  (* find all the alias of lv (because of offset) *)
+  let set_of_aliases : LSet.t = find_all_aliases_of_offset lv x in
+  (* add all these aliases *)
+  Options.debug ~level:9 "all_aliases of %a : %a " Lval.pretty lv LSet.pretty set_of_aliases;
+  let new_lmap =
+    LSet.fold
+      (fun lv acc -> assert (not (LLMap.mem lv x.lmap)); LLMap.add lv new_v acc)
+      set_of_aliases
+      x.lmap
+  in
+  let new_vmap = VMap.add new_v set_of_aliases x.vmap in
+
+  let new_x =
+    {
+      graph = new_g ;
+      lmap = new_lmap ;
+      vmap = new_vmap ;
+    }
+  in
+  assert_invariants new_x;
+  match lv with
+  | BLval (Var v, NoOffset) ->
+    begin
+      match v.vtype with
+        TPtr _ ->
+        (* then add a constant vertex *)
+        let another_v, new_x = create_cst_vertex new_x in
+        let new_g = G.add_edge new_x.graph new_v another_v in
+        new_v, {new_x with graph = new_g}
+      | _ ->   new_v ,new_x
+    end
+  | _ ->
+    new_v , new_x
+
+(* only for function find_or_create_vertex *)
+let create_vertex_addr (lv:lval) (v:V.t) (x:t) : V.t *t =
+  let va, x = create_vertex_simple (BAddrOf lv) x in
+  let new_g =  G.add_edge x.graph va v in
+  va, { x with graph = new_g}
+
+let diff_offset (lv1:Lval.t) (lv2:Lval.t) =
+  let rec f_diff_offset o1 o2 =
+    match o1, o2 with
+      NoOffset, _ -> o2
+    | Field (_,o1), Field (_,o2) -> f_diff_offset o1 o2
+    | Index (_,o1), Index (_,o2) -> f_diff_offset o1 o2
+    | _ -> Options.fatal "%s: unexpected case" __LOC__
+  in
+  let _, o1 = Lval.removeOffsetLval lv1
+  and _, o2 = Lval.removeOffsetLval lv2
+  in
+  assert (LLMap.is_sub_offset o1 o2);
+  f_diff_offset o1 o2
+
+(* create_vertex_lval shall only be called by find_or_create_vertex *)
+(* creates a new vertex for a lval, assuming it is not already present
+   in the graph. If it is present, there will be bugs *)
+let rec create_vertex_lval (blv:Lval.t) (x:t) : V.t * t =
+  assert (not (LLMap.mem blv x.lmap));
+  Options.debug ~level:9 "creating a vertex for %a" Lval.pretty blv;
+  match blv with
+  | BLval lv ->
+    begin
+      match lv with
+        (Mem e, NoOffset) ->
+        (* special case, when we also add another vertex and a points-to edge*)
+        begin
+          (* first find the vertex corresponding to e *)
+          match Lval.from_exp e with
+          | None -> Options.fatal "unexpected result: Lval.from (%a) = None" Exp.pretty e
+          | Some (BLval lv1) ->
+            (* find the vertex *)
+            let v1, x = find_or_create_vertex (BLval lv1) x in
+            (* then creates a vertex for bvl ONLY IF there is no successor *)
+            begin
+              match G.succ x.graph v1 with
+                [] ->
+                let v2, x = create_vertex_simple blv x in
+                (* finally add a points-to edge between v1 and v2 *)
+                let new_graph = G.add_edge x.graph v1 v2 in
+                v2, {x with graph = new_graph }
+              | [succ_v1] ->
+                (* if there is a successor, update lmap and vmap to add blv to that successor's set *)
+                let new_lmap = LLMap.add blv succ_v1 x.lmap in
+                let new_vmap = VMap.add succ_v1 (LSet.add blv (VMap.find succ_v1 x.vmap)) x.vmap in
+                succ_v1, {x with lmap = new_lmap ; vmap = new_vmap }
+              | _ -> Options.fatal " Invariant violated : more than 1 successor"
+            end
+          | Some (BAddrOf lv) -> find_or_create_vertex (BLval lv) x
+        end
+      | _ -> create_vertex_simple blv x
+    end
+  | BAddrOf lv ->
+    let v1, x = find_or_create_vertex (BLval lv) x in
+    create_vertex_addr lv v1 x
+
+(* find the vertex of an lval *)
+and find_or_create_vertex (lv:Lval.t) (x:t) : V.t * t =
+  try  (LLMap.find lv x.lmap, x)
+  with
+    Not_found ->
+    begin
+      (* try to find if an alias already exists in x *)
+      let map_predecessors :V.t LMap.t =  LLMap.find_upper_offsets lv x.lmap in
+      (* for any predecessor, find all its aliases and then look for potential existing vertex *)
+      let f_fold_lmap lvx vx acc =
+        let set_aliases = VMap.find vx x.vmap in
+        Options.debug ~level:9 "looking for aliases of %a in set %a" Lval.pretty lv LSet.pretty set_aliases;
+        if LSet.cardinal set_aliases > 1
+        then
+          let off = diff_offset lvx lv in
+          let f_fold_lset lvs acc =
+            try
+              let lvs = Lval.addOffsetLval off lvs in
+              VSet.add (LLMap.find lvs x.lmap) acc
+            with
+              Not_found -> acc
+          in
+          LSet.fold
+            f_fold_lset
+            set_aliases
+            acc
+        else
+          acc
+      in
+      (* set of all existing aliases *)
+      let vset_res =
+        LMap.fold
+          f_fold_lmap
+          map_predecessors
+          VSet.empty
+      in
+      Options.debug ~level:9 "found aliases of %a : %a" Lval.pretty lv VSet.pretty vset_res;
+      if VSet.is_empty vset_res
+      then create_vertex_lval lv x
+      else
+        begin
+          assert (VSet.cardinal vset_res = 1);
+          let v_res = VSet.choose vset_res in
+          (* vertex found, update the tables *)
+          let new_lmap = LLMap.add lv v_res x.lmap in
+          let new_vmap = VMap.add v_res (LSet.add lv (VMap.find v_res x.vmap)) x.vmap in
+          v_res, {x with lmap = new_lmap; vmap = new_vmap}
+        end
+    end
+
+(* TODO is there a better way to do it ? *)
+let find_vertex lv x =
+  let lv = Lval.from_lval lv in
+  let v,x1 = find_or_create_vertex lv x in
+  if x == x1
+  (* if x has not been modified, then the vertex was found, not created *)
+  then v
+  else raise Not_found
+
+(* remove a lval from a graph*)
+let remove_lval (x:t)  (lv:Lval.t) :t =
+  assert_invariants x;
+  try
+    let v = LLMap.find lv x.lmap in
+    let setv = VMap.find v x.vmap in
+    let new_lmap = LLMap.remove lv x.lmap in
+    let new_vmap = VMap.add v (LSet.remove lv setv) x.vmap in
+    let result = {x with lmap = new_lmap; vmap = new_vmap} in
+    assert_invariants result;
+    result
+  with
+    Not_found -> x
+
+(* merge of two vertices; the first vertex carries both sets, the second is removed from the graph and from lmap and vmap *)
+let merge x v1 v2 =
+  if (V.equal v1 v2) || not (G.mem_vertex x.graph v1) || not (G.mem_vertex x.graph v2)
+  then x
+  else
+    let set1 = find_lset v1 x in
+    let set2 = find_lset v2 x in
+
+    let new_set = LSet.union set1 set2 in
+    (* update lmap : every lval in v2 must now be associated with v1*)
+    let new_lmap = LSet.fold (fun lv2 m -> LLMap.add lv2 v1 m) set2 x.lmap in
+
+    (* update vmap *)
+    let new_vmap = VMap.add v1 new_set (VMap.remove v2 x.vmap) in
+    (* update the graph *)
+    let f_fold_succ v_succ (g:G.t) : G.t =
+      G.add_edge g v1 v_succ
+    and f_fold_pred v_pred (g:G.t) : G.t =
+      G.add_edge g v_pred v1
+    in
+    let g = x.graph in
+    (* adds all new edges *)
+    let g = G.fold_succ f_fold_succ g v2 g in
+    let g = G.fold_pred f_fold_pred g v2 g in
+    (* remove v2 *)
+    let g =  G.remove_vertex g v2 in
+    {graph = g; lmap = new_lmap; vmap = new_vmap}
+
+(* functions join and unify-pointer of steensgaard's paper *)
+let rec join_without_check (x:t) (v1:V.t) (v2:V.t) : t =
+  if (V.equal v1 v2) || not (G.mem_vertex x.graph v1 && G.mem_vertex x.graph v2)
+  then
+    x
+  else
+    let pt1 = G.succ x.graph v1 in (* TODO ask frama-c type instead of looking in the graph *)
+    let pt2 = G.succ x.graph v2 in
+    let x = merge x v1 v2 in
+    assert (not (G.mem_vertex x.graph v2));
+    match (pt1, pt2) with
+    | [], _ -> x
+    | _, [] -> x
+    | [succ_v1],[succ_v2] ->
+      assert (succ_v1 <> v2);
+      assert (succ_v2 <> v1);
+      join_without_check x succ_v1 succ_v2
+    | _, _ ->
+      Options.fatal "invariant broken"
+
+(* since the recursive version of join, unify, unify2 and merge may break the invariants *)
+let join (x:t) (v1:V.t) (v2:V.t) : t =
+  Options.debug ~level:7 "graph before join(%d,%d):@;<2>@[%a@]" v1 v2 print_debug x;
+  assert_invariants x;
+  let res = join_without_check x v1 v2 in
+  Options.debug ~level:7 "graph after join(%d,%d):@;<2>@[%a@]" v1 v2 print_debug res;
+  begin
+    try assert_invariants res
+    with Assert_failure _ ->
+      Options.debug "join(%d,%d) failed" v1 v2;
+      Options.debug "graph before join(%d,%d):@;<2>@[%a@]" v1 v2 print_debug x;
+      Options.debug "graph after join(%d,%d):@;<2>@[ %a@]" v1 v2 print_debug res;
+      assert_invariants res
+  end;
+  res
+
+let merge_set (x:t) (vs:VSet.t) : V.t * t =
+  let v0 = VSet.choose vs in
+  if VSet.cardinal vs < 2 then v0, x else begin
+    Options.debug ~level:7 "graph before merge_set %a:@;<2>@[%a@]" VSet.pretty vs print_debug x;
+    assert (G.mem_vertex x.graph v0);
+    let result = VSet.fold (fun v acc -> merge acc v0 v) vs x in
+    Options.debug ~level:7 "graph after merge_set %a:@;<2>@[%a@]" VSet.pretty vs print_debug result;
+    v0, result
+  end
+
+let rec join_succs (x:t) v =
+  Options.debug ~level:8 "joining successors of %d" v;
+  if not @@ G.mem_vertex x.graph v then x else
+    match G.succ x.graph v with
+    | [] | [_] -> x
+    | succs ->
+      let v0, x = merge_set x @@ VSet.of_list succs in
+      join_succs x v0
+
+(* in Steensgard's paper, this is written settype(v1,ref(v2,bot)) *)
+let set_type (x:t) (v1:V.t) (v2:V.t) : t =
+  assert_invariants x;
+  (* if v1 points to another node, suppress current outgoing edge (and the node if it is a constant node) *)
+  let g, new_vmap =
+    match G.succ x.graph v1 with
+      [] -> x.graph, x.vmap
+    | [v2] ->
+      (* if v2 is a constant node supress it directly *)
+      if LSet.is_empty (VMap.find v2 x.vmap)
+      then (G.remove_vertex x.graph v2, VMap.remove v2 x.vmap)
+      else (G.remove_edge x.graph v1 v2, x.vmap)
+    | _ -> Options.fatal "too many outgoing edges in set_type"
+  in
+  let new_g = G.add_edge g v1 v2 in
+  let new_x = {x with graph = new_g ; vmap = new_vmap} in
+  assert_invariants new_x ; new_x
+
+let assignment (a:t) (lv:lval) (e:exp) : t =
+  assert_invariants a;
+  if Cil.isPointerType (Cil.typeOf e)
+  then
+    let x = Lval.from_lval lv in
+    match Lval.from_exp e with
+    | None -> a
+    | Some y ->
+      let (v1,a) = find_or_create_vertex x a in
+      let (v2,a) = find_or_create_vertex y a in
+      if List.mem v2 (G.succ a.graph v1) || List.mem v1 (G.succ a.graph v2)
+      then
+        let () =
+          Options.warning ~source:(fst e.eloc)
+            "ignoring assignment of the form: %a = %a"
+            Printer.pp_lval lv Printer.pp_exp e;
+        in a
+      else
+        let a = join a v1 v2 in
+        let a = match y with
+          | BAddrOf blv -> remove_lval a (BAddrOf blv)
+          | _ -> a
+        in
+        let () = assert_invariants a in
+        a
+  else
+    a
+
+(* assignment x = allocate(y) *)
+let assignment_x_allocate_y (a:t) (lv:lval) : t =
+  assert_invariants a;
+  let x = Lval.from_lval lv in
+  let (v1,a) = find_or_create_vertex x a in
+  match G.succ a.graph v1 with
+    [] ->
+    begin
+      let (v2,a) = create_cst_vertex a in
+      let new_a : t = set_type a v1 v2 in
+      assert_invariants new_a ; new_a
+    end
+  | [_v2] -> a
+  | _ -> Options.fatal "this should not hapen (invariant broken)"
+
+let is_included (a1:t) (a2:t) =
+  (* tests if a1 is included in a2, at least as the nodes with lval *)
+  assert_invariants a1;
+  assert_invariants a2;
+  Options.debug ~level:8 "testing equal %a AND à.%a" (pretty ~debug:true) a1 (pretty ~debug:true) a2;
+  let exception Not_included in
+  try
+    let iter_lmap (lv:Lval.t) (v1:V.t): unit =
+      let v2 : V.t = try LLMap.find lv a2.lmap with Not_found -> raise Not_included in
+      match G.succ a1.graph v1, G.succ a2.graph v2 with
+        [], _ -> ()
+      | [_], [] -> raise Not_included
+      | [v1p], [v2p] ->
+        if LSet.subset (VMap.find v1p a1.vmap) (VMap.find v2p a2.vmap)
+        then
+          ()
+        else
+          raise Not_included
+      | _ -> Options.fatal "this should not hapen (invariant broken)"
+    in
+    LLMap.iter iter_lmap a1.lmap; true
+  with
+    Not_included -> false
+
+let empty :t =
+  {graph = G.empty; lmap = LLMap.empty; vmap = VMap.empty}
+
+let is_empty s =
+  compare s empty = 0
+
+(* add an int to all vertex values *)
+let shift (a : t) : t =
+  assert_invariants a;
+  if is_empty a then a else
+    let () = Options.debug ~level:8 "before shift: node_counter=%d@.%a" !node_counter print_debug a in
+    let max_idx = G.fold_vertex max a.graph 0 in
+    let min_idx = G.fold_vertex min a.graph max_idx in
+    let offset = !node_counter - min_idx in
+    let shift x = x + offset in
+    let shift_vmap shift_elem vmap =
+      VMap.of_seq @@ Stdlib.Seq.map shift_elem @@ VMap.to_seq vmap
+    in
+    let {graph; lmap; vmap} = a in
+    node_counter := max_idx + offset + 1;
+    let result =
+      {graph = G.map_vertex shift graph;
+       lmap = LLMap.map shift lmap;
+       vmap = shift_vmap (fun (key, l) -> (shift key, l)) vmap}
+    in
+    let () = Options.debug ~level:8 "after shift: node_counter=%d@.%a" !node_counter print_debug result in
+    assert_invariants result;
+    result
+
+let union_find vmap intersections =
+  let module Store : UnionFind.STORE = UnionFind.StoreMap.Make (VMap) in
+  let module UF = UnionFind.Make (Store) in
+  let uf = UF.new_store () in
+  let refs = VMap.mapi (fun i _ -> UF.make uf i) vmap in
+  let put_into_uf (v1,v2) =
+    let r1 = VMap.find v1 refs in
+    let r2 = VMap.find v2 refs in
+    ignore @@ UF.union uf r1 r2
+  in
+  let _vs = Seq.iter put_into_uf intersections in
+  let sets_to_be_joined =
+    let add_to_map i r sets =
+      let repr = UF.find uf r in
+      let add_to_set = function
+        | None -> Some (VSet.singleton i)
+        | Some set -> Some (VSet.add i set)
+      in
+      VMap.update (UF.get uf repr) add_to_set sets
+    in
+    VMap.fold add_to_map refs VMap.empty in
+  sets_to_be_joined
+
+let union (a1:t) (a2:t) :t =
+  (* naive algorithm :
+     1 merge the graph and the vmap (by doing union of sets)
+     2 for any node present in both a1.graph and a2.graph, merge/join them
+     3 for any lval [lv] that are has an entry in both a1.lmap and a2.lmap, merge the two vertex a1.lmap[lv]
+       and a2.lmap[lv]
+
+     I am not confident about this function, there are too many potential bugs and inefficiencies
+  *)
+  assert_invariants a1;
+  assert_invariants a2;
+
+  Options.debug ~level:4 "Union: First graph:%a" print_graph a1;
+  Options.debug ~level:5 "Union: First graph:%a" print_debug a1;
+  Options.debug ~level:4 "Union: Second graph:%a" print_graph a2;
+  Options.debug ~level:5 "Union: Second graph:%a" print_debug a2;
+  let new_graph =
+    G.fold_vertex
+      (fun v2 g -> G.add_vertex g v2)
+      a2.graph
+      a1.graph
+  in
+  let new_graph =
+    G.fold_edges
+      (fun v2a v2b g -> G.add_edge g v2a v2b)
+      a2.graph
+      new_graph
+  in
+  let new_vmap =
+    VMap.union (fun _ lset1 lset2 -> Option.some @@ LSet.union lset1 lset2)
+      a2.vmap
+      a1.vmap
+  in
+  let sets_to_be_joined =
+    let intersections = LLMap.to_seq @@ LLMap.intersect a1.lmap a2.lmap in
+    union_find new_vmap @@ Seq.map (fun (_,_,x) -> x) intersections
+  in
+  let new_lmap = LLMap.union a1.lmap a2.lmap in
+  Options.debug ~level:7 "Union: sets to be joined:@[";
+  VMap.iter (fun _ set -> Options.debug ~level:7 "%a" VSet.pretty set) sets_to_be_joined;
+  Options.debug ~level:7 "@]";
+  let new_a = {graph = new_graph; lmap = new_lmap; vmap = new_vmap} in
+  let merged_nodes, new_a =
+    VMap.fold
+      (fun _ set (merged_nodes, x) -> let v0, x = merge_set x set in (v0 :: merged_nodes), x)
+      sets_to_be_joined
+      ([], new_a)
+  in
+  let new_a = List.fold_left join_succs new_a merged_nodes in
+  Options.debug ~level:4 "Union: Result graph:%a" print_graph new_a;
+  Options.debug ~level:5 "Union: Result graph:%a" print_debug new_a;
+  begin
+    try assert_invariants new_a
+    with Assert_failure _ ->
+      Options.debug "union failed";
+      Options.debug "Union: First graph:%a" print_graph a1;
+      Options.debug "Union: First graph:%a" print_debug a1;
+      Options.debug "Union: Second graph:%a" print_graph a2;
+      Options.debug "Union: Second graph:%a" print_debug a2;
+      Options.debug "Union: Result graph:%a" print_graph new_a;
+      Options.debug "Union: Result graph:%a" print_debug new_a;
+      assert_invariants new_a
+  end;
+  new_a
+
+(** a type for summaries of functions *)
+type summary =
+  {
+    state : t option;
+    formals: lval list;
+    locals: lval list;
+    return : exp option
+  }
+
+let make_summary (s : t) (kf : kernel_function) =
+  let exp_return : exp option =
+    if Kernel_function.has_definition kf then
+      let return_stmt = Kernel_function.find_return kf in
+      match return_stmt.skind with
+        Return (e, _) -> e
+      | _ -> Options.fatal "this should not happen"
+    else
+      None
+  in
+  let s =
+    match exp_return with
+      None -> s
+    | Some e ->
+      begin
+        match s, Lval.from_exp e with
+          _, None -> s
+        | s, Some lv ->
+          let _, new_s = find_or_create_vertex lv s in
+          new_s
+      end
+  in
+  {
+    state = Some s;
+    formals = List.map (fun v -> (Var v,NoOffset)) (Kernel_function.get_formals kf);
+    locals = List.map (fun v -> (Var v,NoOffset))  (Kernel_function.get_locals kf);
+    return = exp_return
+  }
+
+let pretty_summary ?(debug=false) fmt s =
+  let print_list_lval fmt (l: lval list) =
+    let is_first = ref true in
+    let print_elem x =
+      if !is_first then is_first := false else Format.fprintf fmt "@ ";
+      Format.fprintf fmt "%a" Cil_datatype.Lval.pretty x
+    in
+    List.iter print_elem l
+  in
+  let print_option pp fmt x =
+    match x with
+    | Some x -> pp fmt x
+    | None -> Format.fprintf fmt "<none>"
+  in
+  match s.state with
+  | None -> if debug then Format.fprintf fmt "not found"
+  | Some s when is_empty s -> if debug then Format.fprintf fmt "empty"
+  | _ ->
+    begin
+      Format.fprintf fmt "@[formals: @[%a@]@;<3>locals: @[%a@]@;<3>returns: @[%a@]@;<3>state: @[%a@] "
+        print_list_lval s.formals
+        print_list_lval s.locals
+        (print_option Exp.pretty) s.return
+        (print_option @@ pretty ~debug) s.state;
+    end
+
+(* the algorithm:
+   - unify the two graphs dropping all the variables from the summary
+   - pair arguments with formals assigning the formal's successor as the argument's successor
+*)
+let call (state:t) (res:lval option) (args:exp list) (summary:summary) :t =
+  assert_invariants state;
+  let formals = summary.formals in
+  assert (List.length args = List.length formals);
+  let sum_state = shift @@ Option.get summary.state in
+
+  (* pair up formals and their corresponding arguments,
+     as well as the bound result with the returned value *)
+  let arg_formal_pairs =
+    let res_ret = match res, summary.return with
+      | None, None -> []
+      | Some res, Some ret ->
+        [Simplified_lval.from_lval res, Option.get @@ Simplified_lval.from_exp ret]
+      | None, Some _ -> []
+      | Some _, None -> (* Shouldn't happen: Frama-C adds missing returns *)
+        Options.fatal "unexpected case: result without return"
+    in
+    let simplify_both (arg, formal) =
+      try
+        match Lval.from_exp arg with
+        | None -> None
+        | Some lv -> Some (lv, Simplified_lval.from_lval formal)
+      with Explicit_pointer_address loc ->
+        Options.warning ~source:(fst loc) ~wkey:Options.Warn.unsupported_address
+          "unsupported feature: explicit pointer address: %a; analysis may be unsound"
+          Printer.pp_exp arg;
+        None
+    in
+    res_ret @ List.filter_map simplify_both @@ List.combine args formals
+  in
+
+  (* for each pair (lv1,lv2) find (or create) the corresponding vertices *)
+  let state, vertex_pairs =
+    let state = ref state in
+    let find_vertex (lv1, lv2) =
+      try
+        let v2 = LLMap.find lv2 sum_state.lmap in
+        let v1, new_state = find_or_create_vertex lv1 !state in
+        state := new_state;
+        Some (v1, v2)
+      with Not_found -> None
+    in
+    !state, List.filter_map find_vertex arg_formal_pairs
+  in
+
+  (* merge the function graph;
+     for every arg/formal vertex pair (v1,v2) and every edge v2→v create edge v1→v. *)
+  let g =
+    let transfer_succs (g : G.t) (v1,v2) =
+      let v2_succs = G.succ sum_state.graph v2 in
+      assert (List.length v2_succs < 2);
+      List.fold_left (fun g succ -> G.add_edge g v1 succ) g v2_succs
+    in
+    let g = state.graph in
+    let g = G.fold_vertex (fun i g -> G.add_vertex g i) sum_state.graph g in
+    let g = G.fold_edges (fun i j g -> G.add_edge g i j) sum_state.graph g in
+    List.fold_left transfer_succs g vertex_pairs
+  in
+
+  (* garbage collect: remove leaf vertices from g that originate from sum_state *)
+  let vertices_to_add_to_g, g =
+    let g = ref g in
+    let remove_if_leaf v _ =
+      if G.in_degree sum_state.graph v = 0
+      then let () = g := G.remove_vertex !g v in None
+      else Some LSet.empty
+    in
+    let remaining_vertices = VMap.filter_map remove_if_leaf sum_state.vmap in
+    remaining_vertices, !g
+  in
+
+  let state = {
+    graph = g;
+    lmap = state.lmap;
+    vmap =
+      let left_bias _ l _ = Some l in
+      VMap.union left_bias state.vmap vertices_to_add_to_g}
+  in
+
+  let state = List.fold_left join_succs state (List.map fst vertex_pairs) in
+  assert_invariants state;
+  state
diff --git a/src/plugins/alias/abstract_state.mli b/src/plugins/alias/abstract_state.mli
new file mode 100644
index 0000000000000000000000000000000000000000..1faf7e9cf19ebc7661ec34bc3911413acf6c34d3
--- /dev/null
+++ b/src/plugins/alias/abstract_state.mli
@@ -0,0 +1,126 @@
+(**************************************************************************)
+(*                                                                        *)
+(*  This file is part of the Frama-C plug-in 'Alias' (alias).             *)
+(*                                                                        *)
+(*  Copyright (C) 2022-2023                                               *)
+(*    CEA (Commissariat à l'énergie atomique et aux énergies              *)
+(*         alternatives)                                                  *)
+(*                                                                        *)
+(*  you can redistribute it and/or modify it under the terms of the GNU   *)
+(*  Lesser General Public License as published by the Free Software       *)
+(*  Foundation, version 2.1.                                              *)
+(*                                                                        *)
+(*  It is distributed in the hope that it will be useful,                 *)
+(*  but WITHOUT ANY WARRANTY; without even the implied warranty of        *)
+(*  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *)
+(*  GNU Lesser General Public License for more details.                   *)
+(*                                                                        *)
+(*  See the GNU Lesser General Public License version 2.1                 *)
+(*  for more details (enclosed in the file LICENSE)                       *)
+(*                                                                        *)
+(**************************************************************************)
+
+(** Module abstract_state *)
+
+open Cil_types
+
+(** Points-to graphs datastructure. *)
+module G: Graph.Sig.G
+
+(** NB : type Lval.t is not the same as type lval !! *)
+module LSet = Simplified.Simplified_lset
+
+
+(** external signature *)
+module type S =
+sig
+
+  (** Type denothing an abstract state of the analysis. It is a graph containing
+      all aliases and points-to information. *)
+  type t
+
+  (** access to the points-to graph *)
+  val get_graph: t -> G.t
+
+  (** set of lvals stored in a vertex *)
+  val get_lval_set : G.V.t -> t -> LSet.t
+
+  (** pretty printer; debug=true prints the graph, debug = false only
+      prints aliased variables *)
+  val pretty : ?debug:bool -> Format.formatter -> t -> unit
+
+  (** dot printer; first argument is a file name *)
+  val print_dot : string -> t -> unit
+
+  (** finds the vertex corresponding to a lval. May raise @Not_found
+  *)
+  val find_vertex : lval -> t -> G.V.t
+
+  (** same as previous function, but return a set of lval. Cannot
+      raise an exception but may return an empty set if the lval is not
+      in the graph *)
+  val find_aliases : lval -> t -> LSet.t
+
+  (** similar to the previous functions, but does not only give the
+      equivalence class of lv, but also all lv that are aliases in
+      other vertex of the graph *)
+  val find_all_aliases : lval -> t -> LSet.t
+
+  (** find_aliases, then recursively finds other sets of lvals. We
+      have the property (if lval [lv] is in abstract state [x]) :
+      List.hd (find_transitive_closure lv x) = (find_vertex lv x,
+      find_aliases lv x) *)
+  val find_transitive_closure : lval -> t -> (G.V.t * LSet.t) list
+
+  (** inclusion test; [is_included a1 a2] tests if, for any lvl
+      present in a1 (associated to a vertex v1), that it is also
+      present in a2 (associated to a vertex v2) and that
+      get_lval_set(succ(v1) is included in get_lval_set(succ(v2)) *)
+  val is_included : t -> t -> bool
+
+end
+
+
+include S
+
+(** check all the invariants that must be true on an abstract value
+      before and after each function call or transformation of the graph)  *)
+val assert_invariants : t -> unit
+
+(** Functions for Steensgaard's algorithm, see the paper *)
+val join : t -> G.V.t -> G.V.t -> t
+
+(** transfert functions for different kinds of assignments *)
+val assignment : t -> lval -> exp -> t
+
+(** transfert function for malloc calls *)
+val assignment_x_allocate_y : t -> lval -> t
+
+
+(** inclusion test; [is_included a1 a2] tests if, for any lvl present
+    in a1 (associated to a vertex v1), that it is also present in a2
+    (associated to a vertex v2) and that set(succ(v1) is included in
+    set(succ(v2)) *)
+val is_included : t -> t -> bool
+
+(** union of two abstract values ; ensures that if 2 lval are
+    aliased in one of the two input graph (or in a points-to
+    relationship), then they will also be aliased/points-to in the
+    result *)
+val union : t -> t -> t
+
+(** empty graph *)
+val empty : t
+
+(** Type denoting summaries of functions *)
+type summary
+
+(** creates a summary from a state and a function *)
+val make_summary : t -> kernel_function -> summary
+
+(** pretty printer *)
+val pretty_summary :  ?debug:bool -> Format.formatter -> summary -> unit
+
+(** [call a res args s] computes the abstract state after the
+    instruction res=f(args), with f summarized by [s]. [a] is the abstract state before the call *)
+val call: t -> lval option -> exp list -> summary -> t
diff --git a/src/plugins/alias/analysis.ml b/src/plugins/alias/analysis.ml
new file mode 100644
index 0000000000000000000000000000000000000000..8583500ff435d1dddeed6e2578b278baac1a2ab7
--- /dev/null
+++ b/src/plugins/alias/analysis.ml
@@ -0,0 +1,332 @@
+(**************************************************************************)
+(*                                                                        *)
+(*  This file is part of the Frama-C plug-in 'Alias' (alias).             *)
+(*                                                                        *)
+(*  Copyright (C) 2022-2023                                               *)
+(*    CEA (Commissariat à l'énergie atomique et aux énergies              *)
+(*         alternatives)                                                  *)
+(*                                                                        *)
+(*  you can redistribute it and/or modify it under the terms of the GNU   *)
+(*  Lesser General Public License as published by the Free Software       *)
+(*  Foundation, version 2.1.                                              *)
+(*                                                                        *)
+(*  It is distributed in the hope that it will be useful,                 *)
+(*  but WITHOUT ANY WARRANTY; without even the implied warranty of        *)
+(*  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *)
+(*  GNU Lesser General Public License for more details.                   *)
+(*                                                                        *)
+(*  See the GNU Lesser General Public License version 2.1                 *)
+(*  for more details (enclosed in the file LICENSE)                       *)
+(*                                                                        *)
+(**************************************************************************)
+
+open Cil_types
+open Cil_datatype
+
+module Dataflow = Dataflow2
+
+module type Table = sig
+  type key
+  type value
+  val find: key -> value
+  (** @raise Not_found if the key is not in the table. *)
+end
+
+module type InternalTable = sig
+  include Table
+  val add : key -> value -> unit
+  val iter : (key -> value -> unit) -> unit
+end
+
+module Make_table (H: Hashtbl.S) (V: sig type t val size : int end)
+  : InternalTable with type key = H.key and type value = V.t = struct
+  type key = H.key
+  type value = V.t
+  let tbl = H.create V.size
+  let add = H.replace tbl
+  let find = H.find tbl
+  let iter f = H.iter f tbl
+end
+
+(* In Function_table, value None means the function has no definition *)
+module Function_table = Make_table (Kernel_function.Hashtbl) (struct
+    type t = Abstract_state.summary option
+    let size = 7
+  end)
+
+let function_compute_ref = Extlib.mk_fun "function_compute"
+
+(* In Stmt_table, value None means abstract state = Bottom *)
+module Stmt_table = struct
+  include Dataflow.StartData (struct
+      type t = Abstract_state.t option
+      let size = 7
+    end)
+  type key = stmt
+  type value = data
+end
+
+let warn_unsupported_explicit_pointer pp_obj obj loc =
+  Options.warning ~source:(fst loc) ~wkey:Options.Warn.unsupported_address
+    "unsupported feature: explicit pointer address: %a; analysis may be unsound" pp_obj obj
+
+let do_assignment (lv:lval) (exp:exp) (a:Abstract_state.t) : Abstract_state.t =
+  try Abstract_state.assignment a lv exp
+  with Simplified.Explicit_pointer_address loc ->
+    warn_unsupported_explicit_pointer  Printer.pp_exp exp loc;
+    a
+
+let rec do_init (lv:lval) (init:init) state =
+  match init with
+  | SingleInit e -> Option.map (do_assignment lv e) state
+  | CompoundInit (_, l) ->
+    List.fold_left (fun state (o, init) -> do_init (Cil.addOffsetLval o lv) init state) state l
+
+let doFunction f = !function_compute_ref f
+
+let do_function_call (stmt:stmt) state (res : lval option) (ef : exp) (args: exp list) loc =
+  let is_malloc (s:string) : bool =
+    (s = "malloc") || (s = "calloc") (* todo : add all function names *)
+  in
+  match ef with
+  | {enode=Lval (Var v, _);_}  when is_malloc v.vname ->
+    begin
+      (* special case for malloc *)
+      match (state,res) with
+        (None, _) -> None
+      | (Some a, None) -> (Options.warning "Memory allocation not stored (ignored)"; Some a)
+      | (Some a, Some lv) ->
+        try Some (Abstract_state.assignment_x_allocate_y a lv)
+        with Simplified.Explicit_pointer_address loc ->
+          warn_unsupported_explicit_pointer Printer.pp_stmt stmt loc;
+          Some a
+    end
+  | _ ->
+    begin
+      (* general case *)
+      let summary =
+        match Kernel_function.get_called ef with
+        | Some kf when Kernel_function.is_main kf -> None
+        | Some kf -> begin
+            try Function_table.find kf
+            with Not_found -> doFunction kf
+          end
+        | None ->
+          Options.warning ~wkey:Options.Warn.unsupported_function ~source:(fst loc)
+            "unsupported feature: call to function pointer: %a" Exp.pretty ef;
+          None
+      in
+      match (state, summary) with
+        (None, _) -> None
+      | (Some a, Some summary) ->
+        Some (Abstract_state.call a res args summary)
+      | (Some a, None) ->
+        Options.warning ~wkey:Options.Warn.undefined_function ~once:true ~source:(fst loc)
+          "function %a has no definition" Exp.pretty ef;
+        Some a
+    end
+
+let do_cons_init (s:stmt) (v:varinfo) f arg t loc state =
+  Cil.treat_constructor_as_func (do_function_call s state) v f arg t loc
+
+let analyse_instr (s:stmt)  (i:instr) (a:Abstract_state.t option) : Abstract_state.t option =
+  match i with
+    Set (lv,exp,_) -> Option.map (do_assignment lv exp) a
+  | Local_init (v,AssignInit i,_) -> do_init (Var v, NoOffset) i a
+  | Local_init (v,ConsInit (f,arg,t),loc) -> do_cons_init s v f arg t loc a
+  | Code_annot _ -> a
+  | Skip _ -> a
+  | Call (res,ef,es,loc) -> (* !function_compute_ref ef *)
+    do_function_call s a res ef es loc
+  | Asm (_,_,_,loc) ->
+    Options.warning
+      ~source:(fst loc) ~wkey:Options.Warn.unsupported_asm
+      "unsupported feature: assembler code; skipping";
+    a
+
+let pp_abstract_state_opt ?(debug=false) fmt v =
+  match v with
+  | None -> Format.fprintf fmt "⊥"
+  | Some a -> Abstract_state.pretty ~debug fmt a
+
+let do_instr (s:stmt)  (i:instr) (a:Abstract_state.t option) : Abstract_state.t option =
+  Options.feedback ~level:3 "@[analysing instruction:@ %a@]" Printer.pp_stmt s;
+  let result = analyse_instr s i a in
+  Options.feedback ~level:3 "@[May-aliases after instruction@;<2>@[%a@]@;<2>are@;<2>@[%a@]@]"
+    Printer.pp_stmt s (pp_abstract_state_opt ~debug:false) result;
+  Options.debug ~level:3 "@[May-alias graph after instruction@;<2>@[%a@]@;<2>is@;<4>@[%a@]@]"
+    Printer.pp_stmt s (pp_abstract_state_opt ~debug:true) result;
+  result
+
+module T = struct
+  let name = "alias"
+
+  let debug = true (* TODO see options *)
+
+  type t = Abstract_state.t option
+
+  module StmtStartData = Stmt_table
+
+  let copy x = x (* we only have persistant data *)
+
+  let pretty fmt a =
+    match a with
+      None -> Format.fprintf fmt "<No abstract state>"
+    | Some a -> Abstract_state.pretty fmt a
+
+  let computeFirstPredecessor _ a = a
+
+  let combinePredecessors _stmt ~old state =
+    match old, state with
+    | _, None -> assert false
+    | None, Some _ -> Some state (* [old] already included in [state] *)
+    | Some old, Some new_ ->
+      if Abstract_state.is_included new_ old then
+        None
+      else
+        Some (Some (Abstract_state.union old new_))
+
+  let doInstr = do_instr
+
+  let doGuard _ _ a =
+    Dataflow.GUse a, Dataflow.GUse a
+
+  let doStmt _ _ = Dataflow.SDefault
+
+  let doEdge _ _ a = a
+end
+
+module F = Dataflow.Forwards (T)
+
+let do_stmt (a: Abstract_state.t) (s:stmt) :  Abstract_state.t =
+  match s.skind with
+    Instr i ->
+    begin
+      match do_instr s i (Some a) with
+        None -> Options.fatal "problem here"
+      | Some a -> a
+    end
+  | _ -> a
+
+let analyse_function (kf:kernel_function) =
+  Options.feedback ~level:2 "analysing function: %a" Kernel_function.pretty kf;
+  if Kernel_function.has_definition kf then
+    begin
+      let first_stmt =
+        try Kernel_function.find_first_stmt kf
+        with Kernel_function.No_Statement -> assert false
+      in
+      T.StmtStartData.add first_stmt (Some Abstract_state.empty);
+      F.compute [first_stmt];
+      let return_stmt = Kernel_function.find_return kf in
+      try Stmt_table.find return_stmt
+      with Not_found ->
+        begin
+          let source, _ = Kernel_function.get_location kf in
+          Options.warning ~source ~wkey:Options.Warn.no_return_stmt
+            "function %a does not return; analysis may be unsound"
+            Kernel_function.pretty kf;
+          Some Abstract_state.empty
+        end
+    end
+  else
+    None
+
+let doFunction (kf:kernel_function) =
+  let final_state = analyse_function kf in
+  let level = if Kernel_function.is_main kf then 1 else 2 in
+  Options.feedback ~level "@[May-aliases at the end of function %a:@ @[%a@]"
+    Kernel_function.pretty kf
+    (pp_abstract_state_opt ~debug:false) final_state;
+  Options.debug ~level "May-alias graph at the end of function %a:@;<4>@[%a@]"
+    Kernel_function.pretty kf
+    (pp_abstract_state_opt ~debug:true) final_state;
+  let result =
+    match final_state with
+    (* final state is None if kf has no definition *)
+      None -> None
+    | Some fs ->
+      let summary = Abstract_state.make_summary fs kf in
+      Options.debug ~level:2 "Summary of function %a:@ @[%a@]"
+        Kernel_function.pretty kf
+        (Abstract_state.pretty_summary ~debug:false) summary;
+      Some summary
+  in
+  if Kernel_function.is_main kf then
+    let f_name = Options.Dot_output.get () in
+    begin match f_name, final_state with
+      | "", _ -> ()
+      | _, None -> ()
+      | _, Some final_state -> Abstract_state.print_dot f_name final_state
+    end;
+    None
+  else
+    (Function_table.add kf result; result)
+
+let () = function_compute_ref := doFunction
+
+let make_summary (state:Abstract_state.t) (kf:kernel_function) =
+  try
+    begin
+      match Function_table.find kf with
+        Some s -> (state, s)
+      | None -> Options.fatal "not implemented"
+    end
+  with
+    Not_found ->
+    begin
+      match doFunction kf with
+        Some s -> (state, s)
+      | None -> Options.fatal "not implemented"
+    end
+
+let computed_flag = ref false
+
+let is_computed () = !computed_flag
+
+let print_stmt_table_elt fmt k v :unit =
+  let print_key = Stmt.pretty in
+  let print_value fmt v =
+    match v with
+    | None -> Format.fprintf fmt "<Bot>"
+    | Some a -> Abstract_state.pretty ~debug:(Options.DebugTable.get ()) fmt a
+  in
+  Format.fprintf fmt "Before statement %a :@[<hov 2> %a@]" print_key k print_value v
+
+let print_function_table_elt fmt kf s : unit =
+  let function_name = Kernel_function.get_name kf in
+  match s with
+  | None -> Options.debug "function %s -> None" function_name
+  | Some s ->
+    Format.fprintf fmt "Summary of function %s:@;<5 2>@[%a@]@."
+      function_name
+      (Abstract_state.pretty_summary ~debug:(Options.DebugTable.get ())) s
+
+let compute () =
+  Ast.compute ();
+  Globals.Functions.iter (fun kf -> ignore @@ doFunction kf);
+  computed_flag := true;
+  if Options.ShowStmtTable.get () then
+    Stmt_table.iter (print_stmt_table_elt Format.std_formatter);
+  if Options.ShowFunctionTable.get () then
+    Function_table.iter (print_function_table_elt Format.std_formatter)
+
+let clear () =
+  computed_flag := false;
+  Stmt_table.clear ()
+
+let get_state_before_stmt _kf stmt =
+  if is_computed ()
+  then
+    try Stmt_table.find stmt with
+      Not_found -> None
+  else
+    None
+
+let get_summary kf =
+  if is_computed ()
+  then
+    try Function_table.find kf with
+      Not_found -> None
+  else
+    None
diff --git a/src/plugins/alias/analysis.mli b/src/plugins/alias/analysis.mli
new file mode 100644
index 0000000000000000000000000000000000000000..e68e807f4c52960915b5a6f1c0b1be5085a22348
--- /dev/null
+++ b/src/plugins/alias/analysis.mli
@@ -0,0 +1,68 @@
+(**************************************************************************)
+(*                                                                        *)
+(*  This file is part of the Frama-C plug-in 'Alias' (alias).             *)
+(*                                                                        *)
+(*  Copyright (C) 2022-2023                                               *)
+(*    CEA (Commissariat à l'énergie atomique et aux énergies              *)
+(*         alternatives)                                                  *)
+(*                                                                        *)
+(*  you can redistribute it and/or modify it under the terms of the GNU   *)
+(*  Lesser General Public License as published by the Free Software       *)
+(*  Foundation, version 2.1.                                              *)
+(*                                                                        *)
+(*  It is distributed in the hope that it will be useful,                 *)
+(*  but WITHOUT ANY WARRANTY; without even the implied warranty of        *)
+(*  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *)
+(*  GNU Lesser General Public License for more details.                   *)
+(*                                                                        *)
+(*  See the GNU Lesser General Public License version 2.1                 *)
+(*  for more details (enclosed in the file LICENSE)                       *)
+(*                                                                        *)
+(**************************************************************************)
+
+open Cil_types
+
+open Abstract_state
+
+module type Table = sig
+  type key
+  type value
+  val find: key -> value
+  (** @raise Not_found if the key is not in the table. *)
+end
+
+(** Store the graph at each statement. *)
+module Stmt_table: Table with type key = stmt and type value = Abstract_state.t option
+
+
+(** Store the summary of each function. *)
+module Function_table:
+  Table with type key = kernel_function and type value = Abstract_state.summary option
+
+(** [do_stmt a s] computes the abstract state after statement s. This
+    function does NOT store the result in Stmt_table.  *)
+val do_stmt: t -> stmt -> t
+
+(** [make_summary a f] computes the summary of a function (and the
+    next abstract state if needed) and stores the summary in
+    [Function_table]. *)
+val make_summary: t -> kernel_function -> t * summary
+
+(** main analysis functions *)
+
+(** [compute ()] performs the may-alias analysis. It must be done once
+    before using functions defined in API.ml *)
+val compute : unit -> unit
+
+(** [is_computed ()] returns true iff an analysis was done previously *)
+val is_computed : unit -> bool
+
+(** [clear()] clears caches and imperative structures that are used by
+    the analysis. All accumulated data are lost. *)
+val clear : unit -> unit
+
+(** see API.mli *)
+val get_state_before_stmt :  kernel_function -> stmt -> Abstract_state.t option
+
+(** see API.mli *)
+val get_summary : kernel_function -> Abstract_state.summary option
diff --git a/src/plugins/alias/dune b/src/plugins/alias/dune
new file mode 100644
index 0000000000000000000000000000000000000000..240d498857ac6b2f95d76cde22adb19290d839b7
--- /dev/null
+++ b/src/plugins/alias/dune
@@ -0,0 +1,51 @@
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;;                                                                        ;;
+;;  This file is part of the Frama-C plug-in 'Alias' (alias).             ;;
+;;                                                                        ;;
+;;  Copyright (C) 2022-2023                                               ;;
+;;    CEA (Commissariat à l'énergie atomique et aux énergies              ;;
+;;         alternatives)                                                  ;;
+;;                                                                        ;;
+;;  you can redistribute it and/or modify it under the terms of the GNU   ;;
+;;  Lesser General Public License as published by the Free Software       ;;
+;;  Foundation, version 2.1.                                              ;;
+;;                                                                        ;;
+;;  It is distributed in the hope that it will be useful,                 ;;
+;;  but WITHOUT ANY WARRANTY; without even the implied warranty of        ;;
+;;  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         ;;
+;;  GNU Lesser General Public License for more details.                   ;;
+;;                                                                        ;;
+;;  See the GNU Lesser General Public License version 2.1                 ;;
+;;  for more details (enclosed in the file LICENSE)                       ;;
+;;                                                                        ;;
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+
+( rule
+  (alias frama-c-configure)
+  (deps (universe))
+  (action ( progn
+            (echo "Alias:" %{lib-available:frama-c-alias.core} "\n")
+            (echo " - Frama-C:" %{lib-available:frama-c.kernel} "\n")
+          )
+  )
+)
+
+( env
+  (release (flags -noassert))
+  (_ (flags (:standard -w @a-4)))
+)
+
+( library
+  (name Alias)
+  (public_name frama-c-alias.core)
+  (flags -open Frama_c_kernel :standard)
+  (libraries frama-c.kernel ocamlgraph unionFind)
+  (instrumentation (backend landmarks))
+)
+
+( plugin
+  (optional)
+  (name alias)
+  (libraries frama-c-alias.core)
+  (site (frama-c plugins))
+)
diff --git a/src/plugins/alias/dune-project b/src/plugins/alias/dune-project
new file mode 100644
index 0000000000000000000000000000000000000000..ebb133d3d744d00b3aaa9e2385079173551e2c64
--- /dev/null
+++ b/src/plugins/alias/dune-project
@@ -0,0 +1,35 @@
+(lang dune 3.2)
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;;                                                                        ;;
+;;  This file is part of the Frama-C plug-in 'Alias' (alias).             ;;
+;;                                                                        ;;
+;;  Copyright (C) 2022-2023                                               ;;
+;;    CEA (Commissariat à l'énergie atomique et aux énergies              ;;
+;;         alternatives)                                                  ;;
+;;                                                                        ;;
+;;  you can redistribute it and/or modify it under the terms of the GNU   ;;
+;;  Lesser General Public License as published by the Free Software       ;;
+;;  Foundation, version 2.1.                                              ;;
+;;                                                                        ;;
+;;  It is distributed in the hope that it will be useful,                 ;;
+;;  but WITHOUT ANY WARRANTY; without even the implied warranty of        ;;
+;;  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         ;;
+;;  GNU Lesser General Public License for more details.                   ;;
+;;                                                                        ;;
+;;  See the GNU Lesser General Public License version 2.1                 ;;
+;;  for more details (enclosed in the file LICENSE)                       ;;
+;;                                                                        ;;
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+
+
+(using dune_site 0.1)
+(generate_opam_files true)
+
+(name frama-c-alias)
+
+(package (name frama-c-alias)
+ (depends
+  ("frama-c" (and (>= 25.0) (< 27.0)))
+  ("unionFind" (= 20220122))
+ )
+)
diff --git a/src/plugins/alias/dune-workspace b/src/plugins/alias/dune-workspace
new file mode 100644
index 0000000000000000000000000000000000000000..68bfa1b7e2477ba9cc2372df3840f3a32a209c71
--- /dev/null
+++ b/src/plugins/alias/dune-workspace
@@ -0,0 +1,27 @@
+(lang dune 3.2)
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;;                                                                        ;;
+;;  This file is part of the Frama-C plug-in 'Alias' (alias).             ;;
+;;                                                                        ;;
+;;  Copyright (C) 2022-2023                                               ;;
+;;    CEA (Commissariat à l'énergie atomique et aux énergies              ;;
+;;         alternatives)                                                  ;;
+;;                                                                        ;;
+;;  you can redistribute it and/or modify it under the terms of the GNU   ;;
+;;  Lesser General Public License as published by the Free Software       ;;
+;;  Foundation, version 2.1.                                              ;;
+;;                                                                        ;;
+;;  It is distributed in the hope that it will be useful,                 ;;
+;;  but WITHOUT ANY WARRANTY; without even the implied warranty of        ;;
+;;  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         ;;
+;;  GNU Lesser General Public License for more details.                   ;;
+;;                                                                        ;;
+;;  See the GNU Lesser General Public License version 2.1                 ;;
+;;  for more details (enclosed in the file LICENSE)                       ;;
+;;                                                                        ;;
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+
+(context
+ (default
+  (env (_ (env-vars ("OCAML_LANDMARKS" "auto")))))
+)
diff --git a/src/plugins/alias/frama-c-alias.opam b/src/plugins/alias/frama-c-alias.opam
new file mode 100644
index 0000000000000000000000000000000000000000..d6fe954c9b693364a13646be14d8c9d363058dd8
--- /dev/null
+++ b/src/plugins/alias/frama-c-alias.opam
@@ -0,0 +1,38 @@
+# This file is generated by dune, edit dune-project instead
+opam-version: "2.0"
+depends: [
+  "dune" {>= "3.2"}
+  "frama-c" {>= "25.0" & < "27.0"}
+  "unionFind" {= "20220122"}
+  "odoc" {with-doc}
+]
+build: [
+  ["dune" "subst"] {dev}
+  [
+    "dune"
+    "build"
+    "-p"
+    name
+    "-j"
+    jobs
+    "--promote-install-files=false"
+    "@install"
+    "@runtest" {with-test}
+    "@doc" {with-doc}
+  ]
+  ["dune" "install" "-p" name "--create-install-files" name]
+]
+name: "frama-c-alias"
+version: "26"
+synopsis: "A Frama-C plug-in for Alias Analysis"
+description: """
+  A Frama-C plug-in for Alias Analysis
+"""
+maintainer: "https://git.frama-c.com/pub/frama-c"
+authors: [
+  "Tristan Le Gall"
+  "Jan Rochel"
+]
+license: "Copyright (C) 2022-2022 CEA LIST, All rights reserved. Contact CEA LIST for licensing."
+homepage: "http://frama-c.com/"
+bug-reports: "https://git.frama-c.com/pub/frama-c"
diff --git a/src/plugins/alias/frama-c-alias.opam.template b/src/plugins/alias/frama-c-alias.opam.template
new file mode 100644
index 0000000000000000000000000000000000000000..6e90e5eaa83d540d889fa0c3de6147ceeb7db967
--- /dev/null
+++ b/src/plugins/alias/frama-c-alias.opam.template
@@ -0,0 +1,14 @@
+name: "frama-c-alias"
+version: "26"
+synopsis: "A Frama-C plug-in for Alias Analysis"
+description: """
+  A Frama-C plug-in for Alias Analysis
+"""
+maintainer: "https://git.frama-c.com/pub/frama-c"
+authors: [
+  "Tristan Le Gall"
+  "Jan Rochel"
+]
+license: "Copyright (C) 2022-2022 CEA LIST, All rights reserved. Contact CEA LIST for licensing."
+homepage: "http://frama-c.com/"
+bug-reports: "https://git.frama-c.com/pub/frama-c"
diff --git a/src/plugins/alias/headers/Makefile.generate-headers b/src/plugins/alias/headers/Makefile.generate-headers
new file mode 100644
index 0000000000000000000000000000000000000000..54abb31b1f519ceb23ef75f65dd97ebd80eb6908
--- /dev/null
+++ b/src/plugins/alias/headers/Makefile.generate-headers
@@ -0,0 +1,48 @@
+##########################################################################
+#                                                                        #
+#  This file is part of the Frama-C plug-in 'Alias' (alias).             #
+#                                                                        #
+#  Copyright (C) 2022-2023                                               #
+#    CEA (Commissariat à l'énergie atomique et aux énergies              #
+#         alternatives)                                                  #
+#                                                                        #
+#  you can redistribute it and/or modify it under the terms of the GNU   #
+#  Lesser General Public License as published by the Free Software       #
+#  Foundation, version 2.1.                                              #
+#                                                                        #
+#  It is distributed in the hope that it will be useful,                 #
+#  but WITHOUT ANY WARRANTY; without even the implied warranty of        #
+#  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         #
+#  GNU Lesser General Public License for more details.                   #
+#                                                                        #
+#  See the GNU Lesser General Public License version 2.1                 #
+#  for more details (enclosed in the file LICENSE)                       #
+#                                                                        #
+##########################################################################
+
+YEAR:=$(shell date +%Y)
+
+ifeq (${HEADER_OPEN_SOURCE},yes)
+DEFAULT_HEADER_DIR:=headers/open-source
+else
+DEFAULT_HEADER_DIR:=headers/close-source
+endif
+
+headers/%/LICENSE.${PLUGIN_NAME}: headers/%/LICENSE.template FORCE_LICENSES
+	@sed -e "s/@SHORT_NAME@/${SHORT_NAME}/" \
+			 -e "s/@LONG_NAME@/${LONG_NAME}/" \
+			 -e "s/@FROM_YEAR@/${FROM_YEAR}/" \
+			 -e "s/@YEAR@/${YEAR}/" \
+			 $< > $@
+
+LICENSE.${PLUGIN_NAME}: ${DEFAULT_HEADER_DIR}/LICENSE.${PLUGIN_NAME} FORCE_LICENSES
+	cp $< $@
+
+.PHONY: FORCE_LICENSES
+FORCE_LICENSES:
+
+# Extend headers rule dependencies, make sure to update all license files
+headers: \
+	headers/open-source/LICENSE.${PLUGIN_NAME} \
+	headers/close-source/LICENSE.${PLUGIN_NAME} \
+	LICENSE.${PLUGIN_NAME}
diff --git a/src/plugins/alias/headers/close-source/LICENSE.Alias b/src/plugins/alias/headers/close-source/LICENSE.Alias
new file mode 100644
index 0000000000000000000000000000000000000000..c95856054e39110c49f28537befb0feffebcde37
--- /dev/null
+++ b/src/plugins/alias/headers/close-source/LICENSE.Alias
@@ -0,0 +1,10 @@
+
+This file is part of the Frama-C plug-in 'Alias' (alias).
+
+Copyright (C) 2022-2023
+  CEA (Commissariat à l'énergie atomique et aux énergies
+       alternatives)
+
+All rights reserved.
+Contact CEA LIST for licensing.
+
diff --git a/src/plugins/alias/headers/close-source/LICENSE.template b/src/plugins/alias/headers/close-source/LICENSE.template
new file mode 100755
index 0000000000000000000000000000000000000000..674cd9bba33d1a8f21bd6faf01c90c6943d00413
--- /dev/null
+++ b/src/plugins/alias/headers/close-source/LICENSE.template
@@ -0,0 +1,10 @@
+
+This file is part of the Frama-C plug-in '@LONG_NAME@' (@SHORT_NAME@).
+
+Copyright (C) @FROM_YEAR@-@YEAR@
+  CEA (Commissariat à l'énergie atomique et aux énergies
+       alternatives)
+
+All rights reserved.
+Contact CEA LIST for licensing.
+
diff --git a/src/plugins/alias/headers/open-source/LICENSE.Alias b/src/plugins/alias/headers/open-source/LICENSE.Alias
new file mode 100644
index 0000000000000000000000000000000000000000..57a2745d01d2fc7935756153dc194f934af4ebf5
--- /dev/null
+++ b/src/plugins/alias/headers/open-source/LICENSE.Alias
@@ -0,0 +1,19 @@
+
+This file is part of the Frama-C plug-in 'Alias' (alias).
+
+Copyright (C) 2022-2023
+  CEA (Commissariat à l'énergie atomique et aux énergies
+       alternatives)
+
+you can redistribute it and/or modify it under the terms of the GNU
+Lesser General Public License as published by the Free Software
+Foundation, version 2.1.
+
+It is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+GNU Lesser General Public License for more details.
+
+See the GNU Lesser General Public License version 2.1
+for more details (enclosed in the file LICENSE)
+
diff --git a/src/plugins/alias/headers/open-source/LICENSE.template b/src/plugins/alias/headers/open-source/LICENSE.template
new file mode 100644
index 0000000000000000000000000000000000000000..80fe4ef40c50d17af0e98eddc038f98ea6e0b3e8
--- /dev/null
+++ b/src/plugins/alias/headers/open-source/LICENSE.template
@@ -0,0 +1,19 @@
+
+This file is part of the Frama-C plug-in '@LONG_NAME@' (@SHORT_NAME@).
+
+Copyright (C) @FROM_YEAR@-@YEAR@
+  CEA (Commissariat à l'énergie atomique et aux énergies
+       alternatives)
+
+you can redistribute it and/or modify it under the terms of the GNU
+Lesser General Public License as published by the Free Software
+Foundation, version 2.1.
+
+It is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+GNU Lesser General Public License for more details.
+
+See the GNU Lesser General Public License version 2.1
+for more details (enclosed in the file LICENSE)
+
diff --git a/src/plugins/alias/nix/alias.nix b/src/plugins/alias/nix/alias.nix
new file mode 100644
index 0000000000000000000000000000000000000000..59e4b01d4972e571bbaf558237829d8cb4cfc445
--- /dev/null
+++ b/src/plugins/alias/nix/alias.nix
@@ -0,0 +1,10 @@
+{ mk_plugin,
+  unionFind }:
+
+mk_plugin {
+  plugin-name = "alias" ;
+  plugin-src = fetchGit { shallow=true ; url=./.. ; } ;
+  additional-build-inputs = [
+    unionFind
+  ] ;
+}
diff --git a/src/plugins/alias/nix/ci.sh b/src/plugins/alias/nix/ci.sh
new file mode 100755
index 0000000000000000000000000000000000000000..698565a0b4dfec45351389ca9ddc54c6c3efa703
--- /dev/null
+++ b/src/plugins/alias/nix/ci.sh
@@ -0,0 +1,42 @@
+#!/usr/bin/env bash
+
+set -euxo pipefail
+
+DEFAULT=${DEFAULT:-master}
+NIX_TARGET="alias"
+#           <plugin>   /nix       /ci.sh
+PLUGIN_DIR="$(dirname "$(dirname "$(readlink -f "$0")")")"
+
+CURRENT_BRANCH="${CI_MERGE_REQUEST_SOURCE_BRANCH_NAME:-}"
+: "${CURRENT_BRANCH:="${CI_COMMIT_REF_NAME:-}"}"
+: "${CURRENT_BRANCH:="$(git branch --show-current)"}"
+
+# prints
+# - "$CURRENT_BRANCH" if it is a branch name in remote $1,
+# - else "$DEFAULT" if it is set and $DEFAULT is a branch name in remote $1,
+# - else master
+get_matching_branch () {
+  if   git ls-remote --quiet --exit-code "$1" "$CURRENT_BRANCH" >/dev/null 2>/dev/null;
+  then echo "$CURRENT_BRANCH"
+  elif git ls-remote --quiet --exit-code "$1" "$DEFAULT" >/dev/null 2>/dev/null;
+  then echo "$DEFAULT"
+  else echo master
+  fi
+}
+
+TMP_DIR="$(mktemp -d)"
+
+cleanup () {
+  rm -rf $TMP_DIR
+}
+
+trap cleanup EXIT
+
+mkdir -p $TMP_DIR/frama-ci
+frama_ci_repo="$(readlink -f $TMP_DIR/frama-ci)"
+frama_ci_url="git@git.frama-c.com:frama-c/Frama-CI.git"
+frama_ci_branch="$(get_matching_branch "$frama_ci_url")"
+echo "using branch $frama_ci_branch of Frama-CI repo at $frama_ci_repo"
+git clone --depth=1 --branch="$frama_ci_branch" "$frama_ci_url" "$frama_ci_repo"
+
+source $frama_ci_repo/common-plugin-ci.sh
diff --git a/src/plugins/alias/nix/pkgs.nix b/src/plugins/alias/nix/pkgs.nix
new file mode 100644
index 0000000000000000000000000000000000000000..fd59e529bc8b0d037e1c2e668e603ca433633985
--- /dev/null
+++ b/src/plugins/alias/nix/pkgs.nix
@@ -0,0 +1,16 @@
+{ frama-c-repo ? builtins.trace "alias: defaulting frama-c-repo to ${toString ../../frama-c}" ../../frama-c }:
+let
+  ocamlOverlay = oself: osuper: {
+    alias = oself.callPackage ./alias.nix {};
+  };
+  overlay = self: super: {
+    ocaml-ng = super.lib.mapAttrs (
+      name: value:
+        if builtins.hasAttr "overrideScope'" value
+        then value.overrideScope' ocamlOverlay
+        else value
+    ) super.ocaml-ng;
+  };
+  pkgs = (import (frama-c-repo + "/nix/pkgs.nix")).appendOverlays [ overlay ];
+in
+pkgs
diff --git a/src/plugins/alias/options.ml b/src/plugins/alias/options.ml
new file mode 100644
index 0000000000000000000000000000000000000000..2f70a980efbec330d5124899c0070f6b9b86f612
--- /dev/null
+++ b/src/plugins/alias/options.ml
@@ -0,0 +1,82 @@
+(**************************************************************************)
+(*                                                                        *)
+(*  This file is part of the Frama-C plug-in 'Alias' (alias).             *)
+(*                                                                        *)
+(*  Copyright (C) 2022-2023                                               *)
+(*    CEA (Commissariat à l'énergie atomique et aux énergies              *)
+(*         alternatives)                                                  *)
+(*                                                                        *)
+(*  you can redistribute it and/or modify it under the terms of the GNU   *)
+(*  Lesser General Public License as published by the Free Software       *)
+(*  Foundation, version 2.1.                                              *)
+(*                                                                        *)
+(*  It is distributed in the hope that it will be useful,                 *)
+(*  but WITHOUT ANY WARRANTY; without even the implied warranty of        *)
+(*  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *)
+(*  GNU Lesser General Public License for more details.                   *)
+(*                                                                        *)
+(*  See the GNU Lesser General Public License version 2.1                 *)
+(*  for more details (enclosed in the file LICENSE)                       *)
+(*                                                                        *)
+(**************************************************************************)
+
+(* -------------------------------------------------------------------------- *)
+(* --- Plugin Registration                                                --- *)
+(* -------------------------------------------------------------------------- *)
+
+include Plugin.Register
+    (struct
+      let name = "Alias Analysis"
+      let help = "Lightweight May-Alias Analysis"
+      let shortname = "alias"
+    end)
+
+
+module Enabled = False
+    (struct
+      let option_name = "-alias"
+      let help = "Allows May-Alias Analyzer"
+    end)
+
+
+module ShowFunctionTable = False
+    (struct
+      let option_name = "-alias-show-function-table"
+      let help = "Displays the table [function -> summary] at the end of the analysis"
+    end)
+
+
+module ShowStmtTable = False
+    (struct
+      let option_name = "-alias-show-stmt-table"
+      let help = "Displays the table [stmt -> abstract state] at the end of the analysis"
+    end)
+
+
+module DebugTable = False
+    (struct
+      let option_name = "-alias-debug-table"
+      let help = "switch to debug mode when printing Statement or Function Tables (with options -alias-show-stmt-table and -alias-show-function-table)"
+    end)
+
+
+module Dot_output =
+  Empty_string
+    (struct
+      let option_name = "-alias-dot-output"
+      let arg_name = "f"
+      let help = "Displays the final abstract state in Dot File <f>"
+    end)
+
+module Warn = struct
+  let no_return_stmt = register_warn_category "no-return"
+  let undefined_function = register_warn_category "undefined:fn"
+  let unsupported_address = register_warn_category "unsupported:addr"
+  let unsupported_asm = register_warn_category "unsupported:asm"
+  let unsupported_function = register_warn_category "unsupported:fn"
+  let unsafe_cast = register_warn_category "unsafe-cast"
+end
+
+module DebugKeys = struct
+  let lvals = register_category "lvals"
+end
diff --git a/src/plugins/alias/options.mli b/src/plugins/alias/options.mli
new file mode 100644
index 0000000000000000000000000000000000000000..1a5dd44638c084c430049a9b2c81dc85dc3dd199
--- /dev/null
+++ b/src/plugins/alias/options.mli
@@ -0,0 +1,55 @@
+(**************************************************************************)
+(*                                                                        *)
+(*  This file is part of the Frama-C plug-in 'Alias' (alias).             *)
+(*                                                                        *)
+(*  Copyright (C) 2022-2023                                               *)
+(*    CEA (Commissariat à l'énergie atomique et aux énergies              *)
+(*         alternatives)                                                  *)
+(*                                                                        *)
+(*  you can redistribute it and/or modify it under the terms of the GNU   *)
+(*  Lesser General Public License as published by the Free Software       *)
+(*  Foundation, version 2.1.                                              *)
+(*                                                                        *)
+(*  It is distributed in the hope that it will be useful,                 *)
+(*  but WITHOUT ANY WARRANTY; without even the implied warranty of        *)
+(*  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *)
+(*  GNU Lesser General Public License for more details.                   *)
+(*                                                                        *)
+(*  See the GNU Lesser General Public License version 2.1                 *)
+(*  for more details (enclosed in the file LICENSE)                       *)
+(*                                                                        *)
+(**************************************************************************)
+
+(* -------------------------------------------------------------------------- *)
+(* --- Plugin Registration                                                --- *)
+(* -------------------------------------------------------------------------- *)
+
+include Plugin.S
+
+(** Module activation *)
+module Enabled : Parameter_sig.Bool
+
+(** Displays the table [function -> summary] at the end of the analysis *)
+module ShowFunctionTable : Parameter_sig.Bool
+
+(** Displays the table [statement -> state] at the end of the analysis *)
+module ShowStmtTable : Parameter_sig.Bool
+
+(** Switch to debug mode when displaying tables *)
+module DebugTable : Parameter_sig.Bool
+
+(** Displays the final abstract state in Dot File <f> *)
+module Dot_output : Parameter_sig.String
+
+module Warn : sig
+  val no_return_stmt : warn_category
+  val undefined_function : warn_category
+  val unsupported_address : warn_category
+  val unsupported_asm : warn_category
+  val unsupported_function : warn_category
+  val unsafe_cast : warn_category
+end
+
+module DebugKeys : sig
+  val lvals : category
+end
diff --git a/src/plugins/alias/simplified.ml b/src/plugins/alias/simplified.ml
new file mode 100644
index 0000000000000000000000000000000000000000..3a639dee7bd54b6bb7535091a5a45eec5170cf04
--- /dev/null
+++ b/src/plugins/alias/simplified.ml
@@ -0,0 +1,236 @@
+(**************************************************************************)
+(*                                                                        *)
+(*  This file is part of the Frama-C plug-in 'Alias' (alias).             *)
+(*                                                                        *)
+(*  Copyright (C) 2022-2023                                               *)
+(*    CEA (Commissariat à l'énergie atomique et aux énergies              *)
+(*         alternatives)                                                  *)
+(*                                                                        *)
+(*  you can redistribute it and/or modify it under the terms of the GNU   *)
+(*  Lesser General Public License as published by the Free Software       *)
+(*  Foundation, version 2.1.                                              *)
+(*                                                                        *)
+(*  It is distributed in the hope that it will be useful,                 *)
+(*  but WITHOUT ANY WARRANTY; without even the implied warranty of        *)
+(*  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *)
+(*  GNU Lesser General Public License for more details.                   *)
+(*                                                                        *)
+(*  See the GNU Lesser General Public License version 2.1                 *)
+(*  for more details (enclosed in the file LICENSE)                       *)
+(*                                                                        *)
+(**************************************************************************)
+
+open Cil_types
+
+open Cil_datatype
+
+let nul_exp=
+  let loc = Location.unknown in
+  Cil.zero ~loc
+
+let is_nul_exp = Cil_datatype.ExpStructEq.equal nul_exp
+
+module HL = Lval.Hashtbl
+
+module HE = Exp.Hashtbl
+
+let cached_lval = HL.create 23
+
+let cached_exp = HE.create 37
+
+let clear_cache () =
+  HL.clear cached_lval;
+  HE.clear cached_exp
+
+exception Explicit_pointer_address of location
+
+let check_cast_compatibility e typ =
+  let type_of_e = Cil.typeOf e in
+  (* emit a warning for unsafe casts, but not for the NULL pointer *)
+  if Cil.need_cast typ type_of_e && not (Cil.isZero e) then
+    Options.warning
+      ~once:true
+      ~source:(fst @@ e.eloc)
+      ~wkey:Options.Warn.unsafe_cast
+      "unsafe cast from %a to %a"
+      Printer.pp_typ type_of_e Printer.pp_typ typ
+
+let rec simplify_lval (h,o) =
+  try HL.find cached_lval (h,o)
+  with Not_found ->
+    let res = (simplify_host h, simplify_offset o) in
+    HL.add cached_lval (h,o) res;
+    res
+
+and simplify_host h =
+  match h with
+  | Var _ -> h
+  | Mem e ->
+    let simp_e = simplify_exp e in
+    if is_nul_exp simp_e
+    then raise (Explicit_pointer_address e.eloc)
+    else Mem simp_e
+
+and simplify_offset o =
+  match o with
+  | NoOffset -> NoOffset
+  | Field(f,o) -> Field(f, simplify_offset o)
+  | Index(_e,o) -> Index(nul_exp, simplify_offset o)
+
+and simplify_exp e =
+  try
+    HE.find cached_exp e
+  with Not_found ->
+    let res =
+      match e.enode with
+      | CastE (typ, e) ->
+        check_cast_compatibility e typ;
+        simplify_exp e
+      | Lval lv -> {e with enode = Lval (simplify_lval lv)}
+      | AddrOf lv | StartOf lv -> {e with enode = AddrOf (simplify_lval lv)}
+      | BinOp(PlusPI, e1, _, _) | BinOp(MinusPI, e1, _, _) ->
+        begin
+          match (simplify_exp e1).enode with
+          | Lval _ | AddrOf _ as node -> {e with enode = node}
+          | _ -> raise (Explicit_pointer_address e1.eloc)
+        end
+      | _ -> e
+    in
+    HE.add cached_exp e res;
+    res
+
+type simplified_lval =
+  | BLval of lval
+  | BAddrOf of lval
+
+module Simplified_lval = struct
+
+  type t = simplified_lval
+
+  let from_lval lv =
+    BLval (simplify_lval lv)
+
+  let from_exp e =
+    let e = simplify_exp e in
+    match e.enode with
+      Lval lv -> Some (BLval lv)
+    | AddrOf lv -> Some (BAddrOf lv)
+    | _ -> None
+
+  let compare x1 x2 =
+    match (x1,x2) with
+    | (BLval lv1, BLval lv2) -> Cil_datatype.LvalStructEq.compare lv1 lv2
+    | (BLval _, _) -> -1
+    | (_, BLval _) -> 1
+    | (BAddrOf lv1, BAddrOf lv2) -> Cil_datatype.LvalStructEq.compare lv1 lv2
+
+  let print f fmt x =
+    match x with
+    | BLval lv -> f fmt lv
+    | BAddrOf lv -> Format.fprintf fmt "&%a" f lv
+
+  let pretty l =
+    if Options.is_debug_key_enabled Options.DebugKeys.lvals
+    then print Cil_types_debug.pp_lval l
+    else print Printer.pp_lval l
+
+  let removeOffsetLval x =
+    match x with
+    | BLval lv -> let lv,o = Cil.removeOffsetLval lv in BLval lv, o
+    | BAddrOf lv -> let lv,o = Cil.removeOffsetLval lv in BAddrOf lv, o
+
+  let addOffsetLval o x =
+    match x with
+    | BLval lv -> let lv = Cil.addOffsetLval o lv in BLval lv
+    | BAddrOf lv -> let lv = Cil.addOffsetLval o lv in BAddrOf lv
+
+  let points_to x =
+    match x with
+    | BAddrOf lv -> BLval lv
+    | BLval lv ->
+      BLval (Mem (Cil.dummy_exp (Lval lv)), NoOffset)
+
+  let is_pointer x =
+    match x with
+    | BAddrOf _ -> true
+    | BLval lv ->
+      let t = Cil.typeOfLval lv in
+      match Cil.unrollType t with
+        TPtr _ | TArray _ -> true
+      | _ -> false
+end
+
+module Simplified_lmap =
+struct
+  include Map.Make (Simplified_lval)
+
+  let print (f_key: Format.formatter -> key -> unit) (f_val : Format.formatter -> 'a -> unit) fmt (m: 'a t) =
+    let is_first = ref true in
+    Format.fprintf fmt "{@[<hov 2>";
+    iter (fun k v ->
+        if not !is_first
+        then
+          Format.fprintf fmt ",@,"
+        else
+          is_first := false;
+        Format.fprintf fmt " %a -> %a" f_key k f_val v
+      )
+      m;
+    Format.fprintf fmt " @]}"
+
+  let pretty f fmt m = print Simplified_lval.pretty f fmt m
+end
+
+module Simplified_lset =
+struct
+  include Set.Make (Simplified_lval)
+
+  let print (f_elt: Format.formatter -> elt -> unit) fmt (m: t) =
+    let is_first = ref true in
+    Format.fprintf fmt "{@[";
+    iter (fun e ->
+        if !is_first
+        then
+          is_first := false
+        else
+          Format.fprintf fmt ",@ ";
+        Format.fprintf fmt "%a" f_elt e
+      )
+      m;
+    Format.fprintf fmt "@]}"
+
+  let pretty fmt s = print Simplified_lval.pretty fmt s
+
+  let fold_lval f s init =
+    let f_fold lv acc =
+      match lv with
+      | BLval lv -> f lv acc
+      | BAddrOf lv -> f lv acc
+    in
+    fold f_fold s init
+end
+
+let decompose_lval (lv1: Simplified_lval.t) : (Simplified_lval.t*offset) list =
+  let rec list_of_offset (o: offset) : (offset*offset) list =
+    match o with
+      NoOffset -> [NoOffset,o]
+    | Index(e,ofs) ->
+      let li =
+        List.map
+          (fun (o1,o2) -> (Index(e,o1),o2))
+          (list_of_offset ofs)
+      in
+      (NoOffset,o)::li
+    | Field(f, ofs) ->
+      let li =
+        List.map
+          (fun (o1,o2) -> (Field(f,o1),o2))
+          (list_of_offset ofs)
+      in
+      (NoOffset,o)::li
+  in
+  let lv, off = Simplified_lval.removeOffsetLval lv1 in
+  List.map
+    (fun (o1,o2) -> (Simplified_lval.addOffsetLval o1 lv,o2))
+    (list_of_offset off)
+
diff --git a/src/plugins/alias/simplified.mli b/src/plugins/alias/simplified.mli
new file mode 100644
index 0000000000000000000000000000000000000000..3757c46d4f21d6a78b1fb615f5c8569f6904f3e2
--- /dev/null
+++ b/src/plugins/alias/simplified.mli
@@ -0,0 +1,83 @@
+(**************************************************************************)
+(*                                                                        *)
+(*  This file is part of the Frama-C plug-in 'Alias' (alias).             *)
+(*                                                                        *)
+(*  Copyright (C) 2022-2023                                               *)
+(*    CEA (Commissariat à l'énergie atomique et aux énergies              *)
+(*         alternatives)                                                  *)
+(*                                                                        *)
+(*  you can redistribute it and/or modify it under the terms of the GNU   *)
+(*  Lesser General Public License as published by the Free Software       *)
+(*  Foundation, version 2.1.                                              *)
+(*                                                                        *)
+(*  It is distributed in the hope that it will be useful,                 *)
+(*  but WITHOUT ANY WARRANTY; without even the implied warranty of        *)
+(*  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *)
+(*  GNU Lesser General Public License for more details.                   *)
+(*                                                                        *)
+(*  See the GNU Lesser General Public License version 2.1                 *)
+(*  for more details (enclosed in the file LICENSE)                       *)
+(*                                                                        *)
+(**************************************************************************)
+
+open Cil_types
+
+type simplified_lval =
+  | BLval of lval (* lval *)
+  | BAddrOf of lval (* address *)
+
+(* exception raised when the program tries to access a memory location directly. *)
+exception Explicit_pointer_address of location
+
+module Simplified_lval:
+sig
+  type t = simplified_lval
+
+  val compare: t -> t -> int
+
+  (* result stored in cache. May raise Explicit_pointer_address *)
+  val from_lval: lval -> t
+
+  (* result stored in cache. May raise Explicit_pointer_address *)
+  val from_exp: exp -> t option
+
+  val pretty: Format.formatter -> t -> unit
+
+  (* maps !Cil.removeOffsetLval to simplified_lval *)
+  val removeOffsetLval : t -> t * offset
+
+  (* maps !Cil.addOffsetLval to simplified_lval *)
+  val addOffsetLval : offset -> t -> t
+
+  (* (points_to x) = *x and (points_to &x) = x. Raise
+     Explicit_pointer_address when applied to BNone *)
+  val points_to : t -> t
+
+  (* true if x is assimilable to a pointer type (explicit pointer or
+     memory adress or array *)
+  val is_pointer : t -> bool
+end
+
+module Simplified_lmap:
+sig
+  include Map.S with type key = Simplified_lval.t
+
+  val pretty: (Format.formatter -> 'a -> unit) -> Format.formatter -> 'a t -> unit
+end
+
+module Simplified_lset:
+sig
+  include Set.S with type elt = Simplified_lval.t
+
+  val pretty: Format.formatter -> t -> unit
+
+  (* special fold *)
+  val fold_lval : (lval -> 'a -> 'a) -> t -> 'a -> 'a
+
+end
+
+val  decompose_lval : Simplified_lval.t -> (Simplified_lval.t*offset) list
+
+(** clear the two caches *)
+val clear_cache : unit -> unit
+
diff --git a/src/plugins/alias/tests/basic/addrof.c b/src/plugins/alias/tests/basic/addrof.c
new file mode 100644
index 0000000000000000000000000000000000000000..838b4527950aea8619e4674e3e121b8d31439bd1
--- /dev/null
+++ b/src/plugins/alias/tests/basic/addrof.c
@@ -0,0 +1,11 @@
+int main () {
+  int **a, ***b, **y, *x, *z, p;
+  a = &x;
+  b = &y;
+  if (p)
+    y = &z;
+  else
+    *y = x;
+
+  return 0;
+}
diff --git a/src/plugins/alias/tests/basic/assignment1.c b/src/plugins/alias/tests/basic/assignment1.c
new file mode 100644
index 0000000000000000000000000000000000000000..2851d98907fe53177b4139ba9868a78f6201cf74
--- /dev/null
+++ b/src/plugins/alias/tests/basic/assignment1.c
@@ -0,0 +1,11 @@
+// single pointer assignment
+// {a, b, c, d} are aliased
+
+int main () {
+
+  int *a=0, *b=0, *c=0, *d=0;
+  a = b;
+  b = c;
+  a = d;
+  return 0;
+}
diff --git a/src/plugins/alias/tests/basic/assignment2.c b/src/plugins/alias/tests/basic/assignment2.c
new file mode 100644
index 0000000000000000000000000000000000000000..ba0a8dc53e64428a841d94466d52a9f6cfda563a
--- /dev/null
+++ b/src/plugins/alias/tests/basic/assignment2.c
@@ -0,0 +1,13 @@
+// double pointer assignment
+//  {a, c} are aliased
+//  {*a, *c, b, d} are aliased
+
+
+int main () {
+
+  int **a=0, *b=0, **c=0, *d=0;
+  *a = b;
+  *c = d;
+  a = c;
+  return 0;
+}
diff --git a/src/plugins/alias/tests/basic/assignment3.c b/src/plugins/alias/tests/basic/assignment3.c
new file mode 100644
index 0000000000000000000000000000000000000000..203e93650c145bd0ee2a10cf547852a24551c02f
--- /dev/null
+++ b/src/plugins/alias/tests/basic/assignment3.c
@@ -0,0 +1,10 @@
+// address assignment
+// {a, c} are aliased
+
+int main () {
+
+  int *a=0, b=0, *c=0;
+  a = &b;
+  c = &b;
+  return 0;
+}
diff --git a/src/plugins/alias/tests/basic/assignment4.c b/src/plugins/alias/tests/basic/assignment4.c
new file mode 100644
index 0000000000000000000000000000000000000000..136a763cb531aa5b7ac9db937a41a49d60ca5041
--- /dev/null
+++ b/src/plugins/alias/tests/basic/assignment4.c
@@ -0,0 +1,13 @@
+// double pointer assignment
+//  {a, c} are aliased
+//  {*a, *c, b, d} are aliased
+
+
+int main () {
+
+  int **a=0, *b=0, **c=0, *d=0;
+  *a = b;
+  *c = d;
+  b = d;
+  return 0;
+}
diff --git a/src/plugins/alias/tests/basic/assignment5.c b/src/plugins/alias/tests/basic/assignment5.c
new file mode 100644
index 0000000000000000000000000000000000000000..03ccff7f6bf62d8eb127a9ff487c1b3bb0ecd6c4
--- /dev/null
+++ b/src/plugins/alias/tests/basic/assignment5.c
@@ -0,0 +1,12 @@
+// triple pointer assignment with some tricky alias
+//   {*a, b} are aliased
+//   {*(*a), *b, c, d} are aliased
+
+int main () {
+
+  int ***a=0, **b=0, *c=0, *d=0;
+  *a = b;
+  *b = c;
+  d = **a;
+  return 0;
+}
diff --git a/src/plugins/alias/tests/basic/cast1.c b/src/plugins/alias/tests/basic/cast1.c
new file mode 100644
index 0000000000000000000000000000000000000000..4a0713d879d9ae2d319aba0c359a3d8f8dedc102
--- /dev/null
+++ b/src/plugins/alias/tests/basic/cast1.c
@@ -0,0 +1,14 @@
+// homogeneous cast
+//  {a, c} are aliased
+//  {b, d} are aliased
+
+
+int main () {
+
+  int *a=0, *b=0;
+  float *c=0, *d=0;
+  a = (int*) c;
+  d = (float*) b;
+  
+  return 0;
+}
diff --git a/src/plugins/alias/tests/basic/conditional1.c b/src/plugins/alias/tests/basic/conditional1.c
new file mode 100644
index 0000000000000000000000000000000000000000..a668cd7d083a810096ccde023c6fa83985ad2105
--- /dev/null
+++ b/src/plugins/alias/tests/basic/conditional1.c
@@ -0,0 +1,15 @@
+// conditional cfg
+//  {a, b, c} are aliased
+
+int main () {
+
+  int *a=0, *b=0, *c=0;
+  if (a) {
+    a = b;
+  }
+  else {
+    a = c;
+  }
+  *a = 4;  
+  return 0;
+}
diff --git a/src/plugins/alias/tests/basic/conditional2.c b/src/plugins/alias/tests/basic/conditional2.c
new file mode 100644
index 0000000000000000000000000000000000000000..7243bebdbde9675572b75eaa0c134bd65bd65fe1
--- /dev/null
+++ b/src/plugins/alias/tests/basic/conditional2.c
@@ -0,0 +1,20 @@
+// conditional cfg
+//  {*a, *b, c} are aliased
+//  {*(*a), *(*b), *c, d} are aliased
+//  {a, b} are aliased
+
+
+int main () {
+
+  int ***a, ***b, **c, *d, e;
+  b = &c;
+  c = &d;
+  d = &e;
+  if (a) {
+    a = b;
+  }
+  else {
+    a = &c;
+  }
+  return 0;
+}
diff --git a/src/plugins/alias/tests/basic/conditional3.c b/src/plugins/alias/tests/basic/conditional3.c
new file mode 100644
index 0000000000000000000000000000000000000000..06d7dfbc131d38402a4ddbd96245cd579a4c1d44
--- /dev/null
+++ b/src/plugins/alias/tests/basic/conditional3.c
@@ -0,0 +1,26 @@
+// conditional with multiple levels of indirection
+//  {a, b, c} are aliased
+//  {*a, *b, *c, i, j} are aliased
+//  {*(*a), *(*b), *(*c), *i, *j, x, y} are aliased
+//  {*(*(*a)), *(*(*b)), *(*(*c)), *(*i), *(*j), *x, *y, t, u} are aliased
+
+
+
+int main () {
+  int ****a, ****b, ****c, ***i, ***j, **x, **y, *t, *u, p;
+  if (p) {
+    a=b;
+    b=&i;
+    i=&x;
+    x=&t;
+  }
+  else {
+    a=c;
+    c=&j;
+    j=&y;
+    y=&u;
+  }
+  p=0;
+
+  return 0;
+}
diff --git a/src/plugins/alias/tests/basic/function1.c b/src/plugins/alias/tests/basic/function1.c
new file mode 100644
index 0000000000000000000000000000000000000000..63bc345a7f779fd9c10517e951607731a896436b
--- /dev/null
+++ b/src/plugins/alias/tests/basic/function1.c
@@ -0,0 +1,20 @@
+// function with no return
+//  {a, b} are aliased
+//  {c, d} are aliased
+
+
+void swap(int *x, int* y) {
+  int*z=0;
+  z=x;
+  x=y;
+  y=z;
+}
+
+
+int main(void)
+{
+  int *a=0, *b=0, *c=0, *d=0;
+  swap(a,b);
+  swap(c,d);
+  return 0;
+}
diff --git a/src/plugins/alias/tests/basic/function2.c b/src/plugins/alias/tests/basic/function2.c
new file mode 100644
index 0000000000000000000000000000000000000000..e4411348cb39b56e76064ab07e3b5488281ed455
--- /dev/null
+++ b/src/plugins/alias/tests/basic/function2.c
@@ -0,0 +1,18 @@
+// malloc
+// no alias
+
+#include <stdlib.h>
+
+int* my_malloc(int size) {
+  int* res=0;
+  res = malloc(size);
+  return res;
+}
+
+int main(void)
+{
+  int *a=0, *b=0;
+  a=my_malloc(2);
+  b=my_malloc(3);
+  return 0;
+}
diff --git a/src/plugins/alias/tests/basic/function3.c b/src/plugins/alias/tests/basic/function3.c
new file mode 100644
index 0000000000000000000000000000000000000000..2142dcd0adefbce2ee3397a11d0c13efbb286ae2
--- /dev/null
+++ b/src/plugins/alias/tests/basic/function3.c
@@ -0,0 +1,23 @@
+// function with a loop inside
+//  {a, b} are aliased
+//  {c, d} are aliased
+
+void *f1(int *x, int* y)
+{
+  int *tmp = x;
+
+  while (1) {
+    x=y;
+    y=tmp;
+    break;
+  }
+  return (void *) 0;
+}
+
+int main(void)
+{
+  int *a=0, *b=0, *c=0, *d=0;
+  f1(a,b);
+  f1(c,d);
+  return 0;
+}
diff --git a/src/plugins/alias/tests/basic/function4.c b/src/plugins/alias/tests/basic/function4.c
new file mode 100644
index 0000000000000000000000000000000000000000..806b68cc3c364ead33143a0ad0a85e0cd9802a94
--- /dev/null
+++ b/src/plugins/alias/tests/basic/function4.c
@@ -0,0 +1,15 @@
+// funxtion with address agument
+//  {a, b} are aliased
+
+int * addr(int* x)
+{
+    return x;
+}
+
+int main(void)
+{
+  int *a=0, *b=0, c=0;
+  a = addr(&c);
+  b = &c;
+  return 0;
+}
diff --git a/src/plugins/alias/tests/basic/function5.c b/src/plugins/alias/tests/basic/function5.c
new file mode 100644
index 0000000000000000000000000000000000000000..94247a286c146fc451f4f7107846146d9a43d995
--- /dev/null
+++ b/src/plugins/alias/tests/basic/function5.c
@@ -0,0 +1,19 @@
+// function with multiple returns
+//  {a, b, c} are aliased
+
+
+int * choice(int* x, int* y)
+{
+  int c=0;
+  if (c)
+    return x;
+  else
+    return y;
+}
+
+int main(void)
+{
+  int *a=0, *b=0, *c=0;
+  c = choice(a,b);
+  return 0;
+}
diff --git a/src/plugins/alias/tests/basic/function6.c b/src/plugins/alias/tests/basic/function6.c
new file mode 100644
index 0000000000000000000000000000000000000000..416136692b9b58787dbd32ad55e216c24b5c4ad7
--- /dev/null
+++ b/src/plugins/alias/tests/basic/function6.c
@@ -0,0 +1,19 @@
+// function with no return
+// no alias
+
+
+void swap(int *x, int* y) {
+  int z=0;
+  z=*x;
+  *x=*y;
+  *y=z;
+}
+
+
+int main(void)
+{
+  int *a=0, *b=0, *c=0, *d=0;
+  swap(a,b);
+  swap(c,d);
+  return 0;
+}
diff --git a/src/plugins/alias/tests/basic/globctr.c b/src/plugins/alias/tests/basic/globctr.c
new file mode 100644
index 0000000000000000000000000000000000000000..5b399b157aef468a2f7824d7cf13b636a4570036
--- /dev/null
+++ b/src/plugins/alias/tests/basic/globctr.c
@@ -0,0 +1,12 @@
+void f(int *x) {
+  int y = 0;
+  *x = y;
+}
+
+int main(void)
+{
+  int *a=0, *b=0;
+  f(a);
+  f(b);
+  return 0;
+}
diff --git a/src/plugins/alias/tests/basic/loop.c b/src/plugins/alias/tests/basic/loop.c
new file mode 100644
index 0000000000000000000000000000000000000000..1b8f58d53345c679b86556995b74d7b37bdd9ea1
--- /dev/null
+++ b/src/plugins/alias/tests/basic/loop.c
@@ -0,0 +1,15 @@
+// used to lead to a loop in the graph - fixed
+// no alias since there is an infinite loop
+
+int main()
+{
+  while (1) {
+    int l[1] = {0};
+    int *n_0 = & l[1];
+    n_0 = & l[1] + 0;
+    int w = 0;
+    if (w)
+      l[0] = *(& l[1] + 0);
+  }
+  return 0;
+}
diff --git a/src/plugins/alias/tests/basic/oracle/addrof.res.oracle b/src/plugins/alias/tests/basic/oracle/addrof.res.oracle
new file mode 100644
index 0000000000000000000000000000000000000000..8b2b579be28d8eee2dbeedad41454f7dcba4fbe9
--- /dev/null
+++ b/src/plugins/alias/tests/basic/oracle/addrof.res.oracle
@@ -0,0 +1,15 @@
+[kernel] Parsing addrof.c (with preprocessing)
+[alias] analysing function: main
+[alias] analysing instruction: a = & x;
+[alias] May-aliases after instruction  a = & x;  are  {*a, x}
+[alias] analysing instruction: b = & y;
+[alias] May-aliases after instruction  b = & y;  are  {*a, x}  {*b, y}
+[alias] analysing instruction: y = & z;
+[alias] May-aliases after instruction  y = & z;  are
+  {*a, x}  {*b, y}  {*(*b), *y, z}
+[alias] analysing instruction: *y = x;
+[alias] May-aliases after instruction  *y = x;  are  {*(*b), *a, *y, x}  {*b, a, y}
+[alias] analysing instruction: __retres = 0;
+[alias] May-aliases after instruction  __retres = 0;  are
+  {*b, a, y}  {*(*b), *a, *y, x, z}
+[alias] May-aliases at the end of function main: {*b, a, y}  {*(*b), *a, *y, x, z}
diff --git a/src/plugins/alias/tests/basic/oracle/assignment1.res.oracle b/src/plugins/alias/tests/basic/oracle/assignment1.res.oracle
new file mode 100644
index 0000000000000000000000000000000000000000..3c262c6c2ce8463df14d5cf6c6d31fadae384515
--- /dev/null
+++ b/src/plugins/alias/tests/basic/oracle/assignment1.res.oracle
@@ -0,0 +1,19 @@
+[kernel] Parsing assignment1.c (with preprocessing)
+[alias] analysing function: main
+[alias] analysing instruction: int *a = (int *)0;
+[alias] May-aliases after instruction  int *a = (int *)0;  are  <none>
+[alias] analysing instruction: int *b = (int *)0;
+[alias] May-aliases after instruction  int *b = (int *)0;  are  <none>
+[alias] analysing instruction: int *c = (int *)0;
+[alias] May-aliases after instruction  int *c = (int *)0;  are  <none>
+[alias] analysing instruction: int *d = (int *)0;
+[alias] May-aliases after instruction  int *d = (int *)0;  are  <none>
+[alias] analysing instruction: a = b;
+[alias] May-aliases after instruction  a = b;  are  {a, b}
+[alias] analysing instruction: b = c;
+[alias] May-aliases after instruction  b = c;  are  {a, b, c}
+[alias] analysing instruction: a = d;
+[alias] May-aliases after instruction  a = d;  are  {a, b, c, d}
+[alias] analysing instruction: __retres = 0;
+[alias] May-aliases after instruction  __retres = 0;  are  {a, b, c, d}
+[alias] May-aliases at the end of function main: {a, b, c, d}
diff --git a/src/plugins/alias/tests/basic/oracle/assignment2.res.oracle b/src/plugins/alias/tests/basic/oracle/assignment2.res.oracle
new file mode 100644
index 0000000000000000000000000000000000000000..0ad4f006ba3b3cf35f8fae1b61a40345b12f4143
--- /dev/null
+++ b/src/plugins/alias/tests/basic/oracle/assignment2.res.oracle
@@ -0,0 +1,19 @@
+[kernel] Parsing assignment2.c (with preprocessing)
+[alias] analysing function: main
+[alias] analysing instruction: int **a = (int **)0;
+[alias] May-aliases after instruction  int **a = (int **)0;  are  <none>
+[alias] analysing instruction: int *b = (int *)0;
+[alias] May-aliases after instruction  int *b = (int *)0;  are  <none>
+[alias] analysing instruction: int **c = (int **)0;
+[alias] May-aliases after instruction  int **c = (int **)0;  are  <none>
+[alias] analysing instruction: int *d = (int *)0;
+[alias] May-aliases after instruction  int *d = (int *)0;  are  <none>
+[alias] analysing instruction: *a = b;
+[alias] May-aliases after instruction  *a = b;  are  {*a, b}
+[alias] analysing instruction: *c = d;
+[alias] May-aliases after instruction  *c = d;  are  {*a, b}  {*c, d}
+[alias] analysing instruction: a = c;
+[alias] May-aliases after instruction  a = c;  are  {a, c}  {*a, *c, b, d}
+[alias] analysing instruction: __retres = 0;
+[alias] May-aliases after instruction  __retres = 0;  are  {a, c}  {*a, *c, b, d}
+[alias] May-aliases at the end of function main: {a, c}  {*a, *c, b, d}
diff --git a/src/plugins/alias/tests/basic/oracle/assignment3.res.oracle b/src/plugins/alias/tests/basic/oracle/assignment3.res.oracle
new file mode 100644
index 0000000000000000000000000000000000000000..65a7c76ee2a2b772a961b9574d747983a02c03a3
--- /dev/null
+++ b/src/plugins/alias/tests/basic/oracle/assignment3.res.oracle
@@ -0,0 +1,15 @@
+[kernel] Parsing assignment3.c (with preprocessing)
+[alias] analysing function: main
+[alias] analysing instruction: int *a = (int *)0;
+[alias] May-aliases after instruction  int *a = (int *)0;  are  <none>
+[alias] analysing instruction: int b = 0;
+[alias] May-aliases after instruction  int b = 0;  are  <none>
+[alias] analysing instruction: int *c = (int *)0;
+[alias] May-aliases after instruction  int *c = (int *)0;  are  <none>
+[alias] analysing instruction: a = & b;
+[alias] May-aliases after instruction  a = & b;  are  <none>
+[alias] analysing instruction: c = & b;
+[alias] May-aliases after instruction  c = & b;  are  {a, c}
+[alias] analysing instruction: __retres = 0;
+[alias] May-aliases after instruction  __retres = 0;  are  {a, c}
+[alias] May-aliases at the end of function main: {a, c}
diff --git a/src/plugins/alias/tests/basic/oracle/assignment4.res.oracle b/src/plugins/alias/tests/basic/oracle/assignment4.res.oracle
new file mode 100644
index 0000000000000000000000000000000000000000..c422587f1a0662ac753d85d13b48ce30d9779b0d
--- /dev/null
+++ b/src/plugins/alias/tests/basic/oracle/assignment4.res.oracle
@@ -0,0 +1,19 @@
+[kernel] Parsing assignment4.c (with preprocessing)
+[alias] analysing function: main
+[alias] analysing instruction: int **a = (int **)0;
+[alias] May-aliases after instruction  int **a = (int **)0;  are  <none>
+[alias] analysing instruction: int *b = (int *)0;
+[alias] May-aliases after instruction  int *b = (int *)0;  are  <none>
+[alias] analysing instruction: int **c = (int **)0;
+[alias] May-aliases after instruction  int **c = (int **)0;  are  <none>
+[alias] analysing instruction: int *d = (int *)0;
+[alias] May-aliases after instruction  int *d = (int *)0;  are  <none>
+[alias] analysing instruction: *a = b;
+[alias] May-aliases after instruction  *a = b;  are  {*a, b}
+[alias] analysing instruction: *c = d;
+[alias] May-aliases after instruction  *c = d;  are  {*a, b}  {*c, d}
+[alias] analysing instruction: b = d;
+[alias] May-aliases after instruction  b = d;  are  {a, c}  {*a, *c, b, d}
+[alias] analysing instruction: __retres = 0;
+[alias] May-aliases after instruction  __retres = 0;  are  {a, c}  {*a, *c, b, d}
+[alias] May-aliases at the end of function main: {a, c}  {*a, *c, b, d}
diff --git a/src/plugins/alias/tests/basic/oracle/assignment5.res.oracle b/src/plugins/alias/tests/basic/oracle/assignment5.res.oracle
new file mode 100644
index 0000000000000000000000000000000000000000..fc9d35993fc2fd1d3228b9f1888ccc80efc11155
--- /dev/null
+++ b/src/plugins/alias/tests/basic/oracle/assignment5.res.oracle
@@ -0,0 +1,19 @@
+[kernel] Parsing assignment5.c (with preprocessing)
+[alias] analysing function: main
+[alias] analysing instruction: int ***a = (int ***)0;
+[alias] May-aliases after instruction  int ***a = (int ***)0;  are  <none>
+[alias] analysing instruction: int **b = (int **)0;
+[alias] May-aliases after instruction  int **b = (int **)0;  are  <none>
+[alias] analysing instruction: int *c = (int *)0;
+[alias] May-aliases after instruction  int *c = (int *)0;  are  <none>
+[alias] analysing instruction: int *d = (int *)0;
+[alias] May-aliases after instruction  int *d = (int *)0;  are  <none>
+[alias] analysing instruction: *a = b;
+[alias] May-aliases after instruction  *a = b;  are  {*a, b}
+[alias] analysing instruction: *b = c;
+[alias] May-aliases after instruction  *b = c;  are  {*a, b}  {*(*a), *b, c}
+[alias] analysing instruction: d = *(*a);
+[alias] May-aliases after instruction  d = *(*a);  are  {*a, b}  {*(*a), *b, c, d}
+[alias] analysing instruction: __retres = 0;
+[alias] May-aliases after instruction  __retres = 0;  are  {*a, b}  {*(*a), *b, c, d}
+[alias] May-aliases at the end of function main: {*a, b}  {*(*a), *b, c, d}
diff --git a/src/plugins/alias/tests/basic/oracle/cast1.res.oracle b/src/plugins/alias/tests/basic/oracle/cast1.res.oracle
new file mode 100644
index 0000000000000000000000000000000000000000..efb26a239fe217242d96a035e5f532512856f69e
--- /dev/null
+++ b/src/plugins/alias/tests/basic/oracle/cast1.res.oracle
@@ -0,0 +1,19 @@
+[kernel] Parsing cast1.c (with preprocessing)
+[alias] analysing function: main
+[alias] analysing instruction: int *a = (int *)0;
+[alias] May-aliases after instruction  int *a = (int *)0;  are  <none>
+[alias] analysing instruction: int *b = (int *)0;
+[alias] May-aliases after instruction  int *b = (int *)0;  are  <none>
+[alias] analysing instruction: float *c = (float *)0;
+[alias] May-aliases after instruction  float *c = (float *)0;  are  <none>
+[alias] analysing instruction: float *d = (float *)0;
+[alias] May-aliases after instruction  float *d = (float *)0;  are  <none>
+[alias] analysing instruction: a = (int *)c;
+[alias:unsafe-cast] cast1.c:10: Warning: unsafe cast from float * to int *
+[alias] May-aliases after instruction  a = (int *)c;  are  {a, c}
+[alias] analysing instruction: d = (float *)b;
+[alias:unsafe-cast] cast1.c:11: Warning: unsafe cast from int * to float *
+[alias] May-aliases after instruction  d = (float *)b;  are  {a, c}  {b, d}
+[alias] analysing instruction: __retres = 0;
+[alias] May-aliases after instruction  __retres = 0;  are  {a, c}  {b, d}
+[alias] May-aliases at the end of function main: {a, c}  {b, d}
diff --git a/src/plugins/alias/tests/basic/oracle/conditional1.res.oracle b/src/plugins/alias/tests/basic/oracle/conditional1.res.oracle
new file mode 100644
index 0000000000000000000000000000000000000000..c903b74f5fe55bbca3300a508bb311813cbdd43c
--- /dev/null
+++ b/src/plugins/alias/tests/basic/oracle/conditional1.res.oracle
@@ -0,0 +1,17 @@
+[kernel] Parsing conditional1.c (with preprocessing)
+[alias] analysing function: main
+[alias] analysing instruction: int *a = (int *)0;
+[alias] May-aliases after instruction  int *a = (int *)0;  are  <none>
+[alias] analysing instruction: int *b = (int *)0;
+[alias] May-aliases after instruction  int *b = (int *)0;  are  <none>
+[alias] analysing instruction: int *c = (int *)0;
+[alias] May-aliases after instruction  int *c = (int *)0;  are  <none>
+[alias] analysing instruction: a = b;
+[alias] May-aliases after instruction  a = b;  are  {a, b}
+[alias] analysing instruction: a = c;
+[alias] May-aliases after instruction  a = c;  are  {a, c}
+[alias] analysing instruction: *a = 4;
+[alias] May-aliases after instruction  *a = 4;  are  {a, b, c}
+[alias] analysing instruction: __retres = 0;
+[alias] May-aliases after instruction  __retres = 0;  are  {a, b, c}
+[alias] May-aliases at the end of function main: {a, b, c}
diff --git a/src/plugins/alias/tests/basic/oracle/conditional2.res.oracle b/src/plugins/alias/tests/basic/oracle/conditional2.res.oracle
new file mode 100644
index 0000000000000000000000000000000000000000..6088f9fb04df624989e4038e8fc723c7f40e880e
--- /dev/null
+++ b/src/plugins/alias/tests/basic/oracle/conditional2.res.oracle
@@ -0,0 +1,19 @@
+[kernel] Parsing conditional2.c (with preprocessing)
+[alias] analysing function: main
+[alias] analysing instruction: b = & c;
+[alias] May-aliases after instruction  b = & c;  are  {*b, c}
+[alias] analysing instruction: c = & d;
+[alias] May-aliases after instruction  c = & d;  are  {*b, c}  {*(*b), *c, d}
+[alias] analysing instruction: d = & e;
+[alias] May-aliases after instruction  d = & e;  are  {*b, c}  {*(*b), *c, d}
+[alias] analysing instruction: a = b;
+[alias] May-aliases after instruction  a = b;  are
+  {*a, *b, c}  {*(*a), *(*b), *c, d}  {a, b}
+[alias] analysing instruction: a = & c;
+[alias] May-aliases after instruction  a = & c;  are
+  {*a, *b, c}  {*(*a), *(*b), *c, d}  {a, b}
+[alias] analysing instruction: __retres = 0;
+[alias] May-aliases after instruction  __retres = 0;  are
+  {*a, *b, c}  {*(*a), *(*b), *c, d}  {a, b}
+[alias] May-aliases at the end of function main:
+  {*a, *b, c}  {*(*a), *(*b), *c, d}  {a, b}
diff --git a/src/plugins/alias/tests/basic/oracle/conditional3.res.oracle b/src/plugins/alias/tests/basic/oracle/conditional3.res.oracle
new file mode 100644
index 0000000000000000000000000000000000000000..19088629ddb2ab448d832017d538ed52f23d0a08
--- /dev/null
+++ b/src/plugins/alias/tests/basic/oracle/conditional3.res.oracle
@@ -0,0 +1,35 @@
+[kernel] Parsing conditional3.c (with preprocessing)
+[alias] analysing function: main
+[alias] analysing instruction: a = b;
+[alias] May-aliases after instruction  a = b;  are  {a, b}
+[alias] analysing instruction: b = & i;
+[alias] May-aliases after instruction  b = & i;  are  {a, b}  {*a, *b, i}
+[alias] analysing instruction: i = & x;
+[alias] May-aliases after instruction  i = & x;  are
+  {a, b}  {*a, *b, i}  {*(*a), *(*b), *i, x}
+[alias] analysing instruction: x = & t;
+[alias] May-aliases after instruction  x = & t;  are
+  {a, b}  {*a, *b, i}  {*(*a), *(*b), *i, x}
+  {*(*(*a)), *(*(*b)), *(*i), *x, t}
+[alias] analysing instruction: a = c;
+[alias] May-aliases after instruction  a = c;  are  {a, c}
+[alias] analysing instruction: c = & j;
+[alias] May-aliases after instruction  c = & j;  are  {a, c}  {*a, *c, j}
+[alias] analysing instruction: j = & y;
+[alias] May-aliases after instruction  j = & y;  are
+  {a, c}  {*a, *c, j}  {*(*a), *(*c), *j, y}
+[alias] analysing instruction: y = & u;
+[alias] May-aliases after instruction  y = & u;  are
+  {a, c}  {*a, *c, j}  {*(*a), *(*c), *j, y}
+  {*(*(*a)), *(*(*c)), *(*j), *y, u}
+[alias] analysing instruction: p = 0;
+[alias] May-aliases after instruction  p = 0;  are
+  {a, b, c}  {*a, *b, *c, i, j}  {*(*a), *(*b), *(*c), *i, *j, x, y}
+  {*(*(*a)), *(*(*b)), *(*(*c)), *(*i), *(*j), *x, *y, t, u}
+[alias] analysing instruction: __retres = 0;
+[alias] May-aliases after instruction  __retres = 0;  are
+  {a, b, c}  {*a, *b, *c, i, j}  {*(*a), *(*b), *(*c), *i, *j, x, y}
+  {*(*(*a)), *(*(*b)), *(*(*c)), *(*i), *(*j), *x, *y, t, u}
+[alias] May-aliases at the end of function main:
+  {a, b, c}  {*a, *b, *c, i, j}  {*(*a), *(*b), *(*c), *i, *j, x, y}
+  {*(*(*a)), *(*(*b)), *(*(*c)), *(*i), *(*j), *x, *y, t, u}
diff --git a/src/plugins/alias/tests/basic/oracle/function1.res.oracle b/src/plugins/alias/tests/basic/oracle/function1.res.oracle
new file mode 100644
index 0000000000000000000000000000000000000000..a22d297fdc0acd740dd01e992ac832c4051e6257
--- /dev/null
+++ b/src/plugins/alias/tests/basic/oracle/function1.res.oracle
@@ -0,0 +1,31 @@
+[kernel] Parsing function1.c (with preprocessing)
+[alias] analysing function: main
+[alias] analysing instruction: int *a = (int *)0;
+[alias] May-aliases after instruction  int *a = (int *)0;  are  <none>
+[alias] analysing instruction: int *b = (int *)0;
+[alias] May-aliases after instruction  int *b = (int *)0;  are  <none>
+[alias] analysing instruction: int *c = (int *)0;
+[alias] May-aliases after instruction  int *c = (int *)0;  are  <none>
+[alias] analysing instruction: int *d = (int *)0;
+[alias] May-aliases after instruction  int *d = (int *)0;  are  <none>
+[alias] analysing instruction: swap(a,b);
+[alias] analysing function: swap
+[alias] analysing instruction: int *z = (int *)0;
+[alias] May-aliases after instruction  int *z = (int *)0;  are  <none>
+[alias] analysing instruction: z = x;
+[alias] May-aliases after instruction  z = x;  are  {x, z}
+[alias] analysing instruction: x = y;
+[alias] May-aliases after instruction  x = y;  are  {x, y, z}
+[alias] analysing instruction: y = z;
+[alias] May-aliases after instruction  y = z;  are  {x, y, z}
+[alias] May-aliases at the end of function swap: {x, y, z}
+[alias] May-aliases after instruction  swap(a,b);  are  {a, b}
+[alias] analysing instruction: swap(c,d);
+[alias] May-aliases after instruction  swap(c,d);  are  {a, b}  {c, d}
+[alias] analysing instruction: __retres = 0;
+[alias] May-aliases after instruction  __retres = 0;  are  {a, b}  {c, d}
+[alias] May-aliases at the end of function main: {a, b}  {c, d}
+[alias] analysing function: swap
+[alias] analysing instruction: int *z = (int *)0;
+[alias] May-aliases after instruction  int *z = (int *)0;  are  <none>
+[alias] May-aliases at the end of function swap: {x, y, z}
diff --git a/src/plugins/alias/tests/basic/oracle/function2.res.oracle b/src/plugins/alias/tests/basic/oracle/function2.res.oracle
new file mode 100644
index 0000000000000000000000000000000000000000..1e4decb3e431ddaeca4ca82775f8bc469b5f9756
--- /dev/null
+++ b/src/plugins/alias/tests/basic/oracle/function2.res.oracle
@@ -0,0 +1,136 @@
+[kernel] Parsing function2.c (with preprocessing)
+[alias] analysing function: _Exit
+[alias] May-aliases at the end of function _Exit: ⊥
+[alias] analysing function: abort
+[alias] May-aliases at the end of function abort: ⊥
+[alias] analysing function: abs
+[alias] May-aliases at the end of function abs: ⊥
+[alias] analysing function: at_quick_exit
+[alias] May-aliases at the end of function at_quick_exit: ⊥
+[alias] analysing function: atexit
+[alias] May-aliases at the end of function atexit: ⊥
+[alias] analysing function: atof
+[alias] May-aliases at the end of function atof: ⊥
+[alias] analysing function: atoi
+[alias] May-aliases at the end of function atoi: ⊥
+[alias] analysing function: atol
+[alias] May-aliases at the end of function atol: ⊥
+[alias] analysing function: atoll
+[alias] May-aliases at the end of function atoll: ⊥
+[alias] analysing function: bsearch
+[alias] May-aliases at the end of function bsearch: ⊥
+[alias] analysing function: calloc
+[alias] May-aliases at the end of function calloc: ⊥
+[alias] analysing function: div
+[alias] May-aliases at the end of function div: ⊥
+[alias] analysing function: drand48
+[alias] May-aliases at the end of function drand48: ⊥
+[alias] analysing function: erand48
+[alias] May-aliases at the end of function erand48: ⊥
+[alias] analysing function: exit
+[alias] May-aliases at the end of function exit: ⊥
+[alias] analysing function: free
+[alias] May-aliases at the end of function free: ⊥
+[alias] analysing function: getenv
+[alias] May-aliases at the end of function getenv: ⊥
+[alias] analysing function: jrand48
+[alias] May-aliases at the end of function jrand48: ⊥
+[alias] analysing function: labs
+[alias] May-aliases at the end of function labs: ⊥
+[alias] analysing function: lcong48
+[alias] May-aliases at the end of function lcong48: ⊥
+[alias] analysing function: ldiv
+[alias] May-aliases at the end of function ldiv: ⊥
+[alias] analysing function: llabs
+[alias] May-aliases at the end of function llabs: ⊥
+[alias] analysing function: lldiv
+[alias] May-aliases at the end of function lldiv: ⊥
+[alias] analysing function: lrand48
+[alias] May-aliases at the end of function lrand48: ⊥
+[alias] analysing function: main
+[alias] analysing instruction: int *a = (int *)0;
+[alias] May-aliases after instruction  int *a = (int *)0;  are  <none>
+[alias] analysing instruction: int *b = (int *)0;
+[alias] May-aliases after instruction  int *b = (int *)0;  are  <none>
+[alias] analysing instruction: a = my_malloc(2);
+[alias] analysing function: my_malloc
+[alias] analysing instruction: int *res = (int *)0;
+[alias] May-aliases after instruction  int *res = (int *)0;  are  <none>
+[alias] analysing instruction: res = (int *)malloc((size_t)size);
+[alias] May-aliases after instruction  res = (int *)malloc((size_t)size);  are
+  <none>
+[alias] May-aliases at the end of function my_malloc: <none>
+[alias] May-aliases after instruction  a = my_malloc(2);  are  <none>
+[alias] analysing instruction: b = my_malloc(3);
+[alias] May-aliases after instruction  b = my_malloc(3);  are  <none>
+[alias] analysing instruction: __retres = 0;
+[alias] May-aliases after instruction  __retres = 0;  are  <none>
+[alias] May-aliases at the end of function main: <none>
+[alias] analysing function: malloc
+[alias] May-aliases at the end of function malloc: ⊥
+[alias] analysing function: mblen
+[alias] May-aliases at the end of function mblen: ⊥
+[alias] analysing function: mbstowcs
+[alias] May-aliases at the end of function mbstowcs: ⊥
+[alias] analysing function: mbtowc
+[alias] May-aliases at the end of function mbtowc: ⊥
+[alias] analysing function: mkstemp
+[alias] May-aliases at the end of function mkstemp: ⊥
+[alias] analysing function: mkstemps
+[alias] May-aliases at the end of function mkstemps: ⊥
+[alias] analysing function: mrand48
+[alias] May-aliases at the end of function mrand48: ⊥
+[alias] analysing function: my_malloc
+[alias] analysing instruction: int *res = (int *)0;
+[alias] May-aliases after instruction  int *res = (int *)0;  are  <none>
+[alias] May-aliases at the end of function my_malloc: <none>
+[alias] analysing function: nrand48
+[alias] May-aliases at the end of function nrand48: ⊥
+[alias] analysing function: posix_memalign
+[alias] May-aliases at the end of function posix_memalign: ⊥
+[alias] analysing function: putenv
+[alias] May-aliases at the end of function putenv: ⊥
+[alias] analysing function: qsort
+[alias] May-aliases at the end of function qsort: ⊥
+[alias] analysing function: quick_exit
+[alias] May-aliases at the end of function quick_exit: ⊥
+[alias] analysing function: rand
+[alias] May-aliases at the end of function rand: ⊥
+[alias] analysing function: random
+[alias] May-aliases at the end of function random: ⊥
+[alias] analysing function: realloc
+[alias] May-aliases at the end of function realloc: ⊥
+[alias] analysing function: reallocarray
+[alias] May-aliases at the end of function reallocarray: ⊥
+[alias] analysing function: seed48
+[alias] May-aliases at the end of function seed48: ⊥
+[alias] analysing function: setenv
+[alias] May-aliases at the end of function setenv: ⊥
+[alias] analysing function: srand
+[alias] May-aliases at the end of function srand: ⊥
+[alias] analysing function: srand48
+[alias] May-aliases at the end of function srand48: ⊥
+[alias] analysing function: srandom
+[alias] May-aliases at the end of function srandom: ⊥
+[alias] analysing function: strtod
+[alias] May-aliases at the end of function strtod: ⊥
+[alias] analysing function: strtof
+[alias] May-aliases at the end of function strtof: ⊥
+[alias] analysing function: strtol
+[alias] May-aliases at the end of function strtol: ⊥
+[alias] analysing function: strtold
+[alias] May-aliases at the end of function strtold: ⊥
+[alias] analysing function: strtoll
+[alias] May-aliases at the end of function strtoll: ⊥
+[alias] analysing function: strtoul
+[alias] May-aliases at the end of function strtoul: ⊥
+[alias] analysing function: strtoull
+[alias] May-aliases at the end of function strtoull: ⊥
+[alias] analysing function: system
+[alias] May-aliases at the end of function system: ⊥
+[alias] analysing function: unsetenv
+[alias] May-aliases at the end of function unsetenv: ⊥
+[alias] analysing function: wcstombs
+[alias] May-aliases at the end of function wcstombs: ⊥
+[alias] analysing function: wctomb
+[alias] May-aliases at the end of function wctomb: ⊥
diff --git a/src/plugins/alias/tests/basic/oracle/function3.res.oracle b/src/plugins/alias/tests/basic/oracle/function3.res.oracle
new file mode 100644
index 0000000000000000000000000000000000000000..d32eba5759924636897ce753d362cec982b56a90
--- /dev/null
+++ b/src/plugins/alias/tests/basic/oracle/function3.res.oracle
@@ -0,0 +1,27 @@
+[kernel] Parsing function3.c (with preprocessing)
+[alias] analysing function: f1
+[alias] analysing instruction: int *tmp = x;
+[alias] May-aliases after instruction  int *tmp = x;  are  {x, tmp}
+[alias] analysing instruction: x = y;
+[alias] May-aliases after instruction  x = y;  are  {x, y, tmp}
+[alias] analysing instruction: y = tmp;
+[alias] May-aliases after instruction  y = tmp;  are  {x, y, tmp}
+[alias] analysing instruction: __retres = (void *)0;
+[alias] May-aliases after instruction  __retres = (void *)0;  are  {x, y, tmp}
+[alias] May-aliases at the end of function f1: {x, y, tmp}
+[alias] analysing function: main
+[alias] analysing instruction: int *a = (int *)0;
+[alias] May-aliases after instruction  int *a = (int *)0;  are  <none>
+[alias] analysing instruction: int *b = (int *)0;
+[alias] May-aliases after instruction  int *b = (int *)0;  are  <none>
+[alias] analysing instruction: int *c = (int *)0;
+[alias] May-aliases after instruction  int *c = (int *)0;  are  <none>
+[alias] analysing instruction: int *d = (int *)0;
+[alias] May-aliases after instruction  int *d = (int *)0;  are  <none>
+[alias] analysing instruction: f1(a,b);
+[alias] May-aliases after instruction  f1(a,b);  are  {a, b}
+[alias] analysing instruction: f1(c,d);
+[alias] May-aliases after instruction  f1(c,d);  are  {a, b}  {c, d}
+[alias] analysing instruction: __retres = 0;
+[alias] May-aliases after instruction  __retres = 0;  are  {a, b}  {c, d}
+[alias] May-aliases at the end of function main: {a, b}  {c, d}
diff --git a/src/plugins/alias/tests/basic/oracle/function4.res.oracle b/src/plugins/alias/tests/basic/oracle/function4.res.oracle
new file mode 100644
index 0000000000000000000000000000000000000000..45fcb1233288f772757cf41cb588a61287b17484
--- /dev/null
+++ b/src/plugins/alias/tests/basic/oracle/function4.res.oracle
@@ -0,0 +1,17 @@
+[kernel] Parsing function4.c (with preprocessing)
+[alias] analysing function: addr
+[alias] May-aliases at the end of function addr: <none>
+[alias] analysing function: main
+[alias] analysing instruction: int *a = (int *)0;
+[alias] May-aliases after instruction  int *a = (int *)0;  are  <none>
+[alias] analysing instruction: int *b = (int *)0;
+[alias] May-aliases after instruction  int *b = (int *)0;  are  <none>
+[alias] analysing instruction: int c = 0;
+[alias] May-aliases after instruction  int c = 0;  are  <none>
+[alias] analysing instruction: a = addr(& c);
+[alias] May-aliases after instruction  a = addr(& c);  are  {a, &c}
+[alias] analysing instruction: b = & c;
+[alias] May-aliases after instruction  b = & c;  are  {a, b}
+[alias] analysing instruction: __retres = 0;
+[alias] May-aliases after instruction  __retres = 0;  are  {a, b}
+[alias] May-aliases at the end of function main: {a, b}
diff --git a/src/plugins/alias/tests/basic/oracle/function5.res.oracle b/src/plugins/alias/tests/basic/oracle/function5.res.oracle
new file mode 100644
index 0000000000000000000000000000000000000000..300762d6f2d441f3222d3ca79dcda3f7e0b4fd0d
--- /dev/null
+++ b/src/plugins/alias/tests/basic/oracle/function5.res.oracle
@@ -0,0 +1,21 @@
+[kernel] Parsing function5.c (with preprocessing)
+[alias] analysing function: choice
+[alias] analysing instruction: int c = 0;
+[alias] May-aliases after instruction  int c = 0;  are  <none>
+[alias] analysing instruction: __retres = x;
+[alias] May-aliases after instruction  __retres = x;  are  {x, __retres}
+[alias] analysing instruction: __retres = y;
+[alias] May-aliases after instruction  __retres = y;  are  {y, __retres}
+[alias] May-aliases at the end of function choice: {x, y, __retres}
+[alias] analysing function: main
+[alias] analysing instruction: int *a = (int *)0;
+[alias] May-aliases after instruction  int *a = (int *)0;  are  <none>
+[alias] analysing instruction: int *b = (int *)0;
+[alias] May-aliases after instruction  int *b = (int *)0;  are  <none>
+[alias] analysing instruction: int *c = (int *)0;
+[alias] May-aliases after instruction  int *c = (int *)0;  are  <none>
+[alias] analysing instruction: c = choice(a,b);
+[alias] May-aliases after instruction  c = choice(a,b);  are  {a, b, c}
+[alias] analysing instruction: __retres = 0;
+[alias] May-aliases after instruction  __retres = 0;  are  {a, b, c}
+[alias] May-aliases at the end of function main: {a, b, c}
diff --git a/src/plugins/alias/tests/basic/oracle/function6.res.oracle b/src/plugins/alias/tests/basic/oracle/function6.res.oracle
new file mode 100644
index 0000000000000000000000000000000000000000..4d8f8fa4a01fce5e95e6b5afdc4c4f24aec1c045
--- /dev/null
+++ b/src/plugins/alias/tests/basic/oracle/function6.res.oracle
@@ -0,0 +1,31 @@
+[kernel] Parsing function6.c (with preprocessing)
+[alias] analysing function: main
+[alias] analysing instruction: int *a = (int *)0;
+[alias] May-aliases after instruction  int *a = (int *)0;  are  <none>
+[alias] analysing instruction: int *b = (int *)0;
+[alias] May-aliases after instruction  int *b = (int *)0;  are  <none>
+[alias] analysing instruction: int *c = (int *)0;
+[alias] May-aliases after instruction  int *c = (int *)0;  are  <none>
+[alias] analysing instruction: int *d = (int *)0;
+[alias] May-aliases after instruction  int *d = (int *)0;  are  <none>
+[alias] analysing instruction: swap(a,b);
+[alias] analysing function: swap
+[alias] analysing instruction: int z = 0;
+[alias] May-aliases after instruction  int z = 0;  are  <none>
+[alias] analysing instruction: z = *x;
+[alias] May-aliases after instruction  z = *x;  are  <none>
+[alias] analysing instruction: *x = *y;
+[alias] May-aliases after instruction  *x = *y;  are  <none>
+[alias] analysing instruction: *y = z;
+[alias] May-aliases after instruction  *y = z;  are  <none>
+[alias] May-aliases at the end of function swap: <none>
+[alias] May-aliases after instruction  swap(a,b);  are  <none>
+[alias] analysing instruction: swap(c,d);
+[alias] May-aliases after instruction  swap(c,d);  are  <none>
+[alias] analysing instruction: __retres = 0;
+[alias] May-aliases after instruction  __retres = 0;  are  <none>
+[alias] May-aliases at the end of function main: <none>
+[alias] analysing function: swap
+[alias] analysing instruction: int z = 0;
+[alias] May-aliases after instruction  int z = 0;  are  <none>
+[alias] May-aliases at the end of function swap: <none>
diff --git a/src/plugins/alias/tests/basic/oracle/globctr.res.oracle b/src/plugins/alias/tests/basic/oracle/globctr.res.oracle
new file mode 100644
index 0000000000000000000000000000000000000000..64f2826db29bf339219770a5cf558ec4f579b092
--- /dev/null
+++ b/src/plugins/alias/tests/basic/oracle/globctr.res.oracle
@@ -0,0 +1,19 @@
+[kernel] Parsing globctr.c (with preprocessing)
+[alias] analysing function: f
+[alias] analysing instruction: int y = 0;
+[alias] May-aliases after instruction  int y = 0;  are  <none>
+[alias] analysing instruction: *x = y;
+[alias] May-aliases after instruction  *x = y;  are  <none>
+[alias] May-aliases at the end of function f: <none>
+[alias] analysing function: main
+[alias] analysing instruction: int *a = (int *)0;
+[alias] May-aliases after instruction  int *a = (int *)0;  are  <none>
+[alias] analysing instruction: int *b = (int *)0;
+[alias] May-aliases after instruction  int *b = (int *)0;  are  <none>
+[alias] analysing instruction: f(a);
+[alias] May-aliases after instruction  f(a);  are  <none>
+[alias] analysing instruction: f(b);
+[alias] May-aliases after instruction  f(b);  are  <none>
+[alias] analysing instruction: __retres = 0;
+[alias] May-aliases after instruction  __retres = 0;  are  <none>
+[alias] May-aliases at the end of function main: <none>
diff --git a/src/plugins/alias/tests/basic/oracle/loop.res.oracle b/src/plugins/alias/tests/basic/oracle/loop.res.oracle
new file mode 100644
index 0000000000000000000000000000000000000000..9ef827f6daf8c1920926e31460dc19ab04c72bac
--- /dev/null
+++ b/src/plugins/alias/tests/basic/oracle/loop.res.oracle
@@ -0,0 +1,19 @@
+[kernel] Parsing loop.c (with preprocessing)
+[alias] analysing function: main
+[alias] analysing instruction: int l[1] = {0};
+[alias] May-aliases after instruction  int l[1] = {0};  are  <none>
+[alias] analysing instruction: int *n_0 = & l[1];
+[alias] May-aliases after instruction  int *n_0 = & l[1];  are  <none>
+[alias] analysing instruction: n_0 = & l[1] + 0;
+[alias] May-aliases after instruction  n_0 = & l[1] + 0;  are  <none>
+[alias] analysing instruction: int w = 0;
+[alias] May-aliases after instruction  int w = 0;  are  <none>
+[alias] analysing instruction: l[0] = *(& l[1] + 0);
+[alias] May-aliases after instruction  l[0] = *(& l[1] + 0);  are  <none>
+[alias] analysing instruction: int l[1] = {0};
+[alias] May-aliases after instruction  int l[1] = {0};  are  <none>
+[alias] analysing instruction: int *n_0 = & l[1];
+[alias] May-aliases after instruction  int *n_0 = & l[1];  are  <none>
+[alias:no-return] loop.c:4: Warning: 
+  function main does not return; analysis may be unsound
+[alias] May-aliases at the end of function main: <none>
diff --git a/src/plugins/alias/tests/basic/oracle/steensgaard.res.oracle b/src/plugins/alias/tests/basic/oracle/steensgaard.res.oracle
new file mode 100644
index 0000000000000000000000000000000000000000..7b9c15f79cba40c1eb3120b93a10733bee758d1e
--- /dev/null
+++ b/src/plugins/alias/tests/basic/oracle/steensgaard.res.oracle
@@ -0,0 +1,17 @@
+[kernel] Parsing steensgaard.c (with preprocessing)
+[alias] analysing function: main
+[alias] analysing instruction: a = & x;
+[alias] May-aliases after instruction  a = & x;  are  <none>
+[alias] analysing instruction: b = & y;
+[alias] May-aliases after instruction  b = & y;  are  {*b, y}
+[alias] analysing instruction: y = & z;
+[alias] May-aliases after instruction  y = & z;  are  {*b, y}
+[alias] analysing instruction: y = & x;
+[alias] May-aliases after instruction  y = & x;  are  {*b, a, y}
+[alias] analysing instruction: c = & y;
+[alias] May-aliases after instruction  c = & y;  are  {*b, *c, a, y}  {b, c}
+[alias] analysing instruction: *y = 4;
+[alias] May-aliases after instruction  *y = 4;  are  {*b, *c, a, y}  {b, c}
+[alias] analysing instruction: __retres = 0;
+[alias] May-aliases after instruction  __retres = 0;  are  {*b, *c, a, y}  {b, c}
+[alias] May-aliases at the end of function main: {*b, *c, a, y}  {b, c}
diff --git a/src/plugins/alias/tests/basic/oracle/switch1.res.oracle b/src/plugins/alias/tests/basic/oracle/switch1.res.oracle
new file mode 100644
index 0000000000000000000000000000000000000000..0819df147033b71a430fa6c56a9b42583ed83fa6
--- /dev/null
+++ b/src/plugins/alias/tests/basic/oracle/switch1.res.oracle
@@ -0,0 +1,19 @@
+[kernel] Parsing switch1.c (with preprocessing)
+[alias] analysing function: main
+[alias] analysing instruction: int *a = (int *)0;
+[alias] May-aliases after instruction  int *a = (int *)0;  are  <none>
+[alias] analysing instruction: int *b = (int *)0;
+[alias] May-aliases after instruction  int *b = (int *)0;  are  <none>
+[alias] analysing instruction: int *c = (int *)0;
+[alias] May-aliases after instruction  int *c = (int *)0;  are  <none>
+[alias] analysing instruction: int *d = (int *)0;
+[alias] May-aliases after instruction  int *d = (int *)0;  are  <none>
+[alias] analysing instruction: int e = 0;
+[alias] May-aliases after instruction  int e = 0;  are  <none>
+[alias] analysing instruction: case 1: a = d;
+[alias] May-aliases after instruction  case 1: a = d;  are  {a, d}
+[alias] analysing instruction: case 2: b = d;
+[alias] May-aliases after instruction  case 2: b = d;  are  {b, d}
+[alias] analysing instruction: __retres = 0;
+[alias] May-aliases after instruction  __retres = 0;  are  {a, b, d}
+[alias] May-aliases at the end of function main: {a, b, d}
diff --git a/src/plugins/alias/tests/basic/oracle/switch2.res.oracle b/src/plugins/alias/tests/basic/oracle/switch2.res.oracle
new file mode 100644
index 0000000000000000000000000000000000000000..40e0e801215e67cf06dfbc103ea1341b897bd96a
--- /dev/null
+++ b/src/plugins/alias/tests/basic/oracle/switch2.res.oracle
@@ -0,0 +1,21 @@
+[kernel] Parsing switch2.c (with preprocessing)
+[alias] analysing function: main
+[alias] analysing instruction: int *a = (int *)0;
+[alias] May-aliases after instruction  int *a = (int *)0;  are  <none>
+[alias] analysing instruction: int *b = (int *)0;
+[alias] May-aliases after instruction  int *b = (int *)0;  are  <none>
+[alias] analysing instruction: int *c = (int *)0;
+[alias] May-aliases after instruction  int *c = (int *)0;  are  <none>
+[alias] analysing instruction: int *d = (int *)0;
+[alias] May-aliases after instruction  int *d = (int *)0;  are  <none>
+[alias] analysing instruction: int e = 0;
+[alias] May-aliases after instruction  int e = 0;  are  <none>
+[alias] analysing instruction: case 1: a = d;
+[alias] May-aliases after instruction  case 1: a = d;  are  {a, d}
+[alias] analysing instruction: case 2: b = d;
+[alias] May-aliases after instruction  case 2: b = d;  are  {b, d}
+[alias] analysing instruction: default: c = d;
+[alias] May-aliases after instruction  default: c = d;  are  {c, d}
+[alias] analysing instruction: __retres = 0;
+[alias] May-aliases after instruction  __retres = 0;  are  {a, b, c, d}
+[alias] May-aliases at the end of function main: {a, b, c, d}
diff --git a/src/plugins/alias/tests/basic/oracle/while_for1.res.oracle b/src/plugins/alias/tests/basic/oracle/while_for1.res.oracle
new file mode 100644
index 0000000000000000000000000000000000000000..228274eef6fbd1b252d69ecb7bf0cf0c763c528e
--- /dev/null
+++ b/src/plugins/alias/tests/basic/oracle/while_for1.res.oracle
@@ -0,0 +1,127 @@
+[kernel] Parsing while_for1.c (with preprocessing)
+[alias] analysing function: _Exit
+[alias] May-aliases at the end of function _Exit: ⊥
+[alias] analysing function: abort
+[alias] May-aliases at the end of function abort: ⊥
+[alias] analysing function: abs
+[alias] May-aliases at the end of function abs: ⊥
+[alias] analysing function: at_quick_exit
+[alias] May-aliases at the end of function at_quick_exit: ⊥
+[alias] analysing function: atexit
+[alias] May-aliases at the end of function atexit: ⊥
+[alias] analysing function: atof
+[alias] May-aliases at the end of function atof: ⊥
+[alias] analysing function: atoi
+[alias] May-aliases at the end of function atoi: ⊥
+[alias] analysing function: atol
+[alias] May-aliases at the end of function atol: ⊥
+[alias] analysing function: atoll
+[alias] May-aliases at the end of function atoll: ⊥
+[alias] analysing function: bsearch
+[alias] May-aliases at the end of function bsearch: ⊥
+[alias] analysing function: calloc
+[alias] May-aliases at the end of function calloc: ⊥
+[alias] analysing function: div
+[alias] May-aliases at the end of function div: ⊥
+[alias] analysing function: drand48
+[alias] May-aliases at the end of function drand48: ⊥
+[alias] analysing function: erand48
+[alias] May-aliases at the end of function erand48: ⊥
+[alias] analysing function: exit
+[alias] May-aliases at the end of function exit: ⊥
+[alias] analysing function: free
+[alias] May-aliases at the end of function free: ⊥
+[alias] analysing function: getenv
+[alias] May-aliases at the end of function getenv: ⊥
+[alias] analysing function: jrand48
+[alias] May-aliases at the end of function jrand48: ⊥
+[alias] analysing function: labs
+[alias] May-aliases at the end of function labs: ⊥
+[alias] analysing function: lcong48
+[alias] May-aliases at the end of function lcong48: ⊥
+[alias] analysing function: ldiv
+[alias] May-aliases at the end of function ldiv: ⊥
+[alias] analysing function: llabs
+[alias] May-aliases at the end of function llabs: ⊥
+[alias] analysing function: lldiv
+[alias] May-aliases at the end of function lldiv: ⊥
+[alias] analysing function: lrand48
+[alias] May-aliases at the end of function lrand48: ⊥
+[alias] analysing function: main
+[alias] analysing instruction: int *s = (int *)0;
+[alias] May-aliases after instruction  int *s = (int *)0;  are  <none>
+[alias] analysing instruction: int idx = 0;
+[alias] May-aliases after instruction  int idx = 0;  are  <none>
+[alias] analysing instruction: s = (int *)malloc((size_t)idx);
+[alias] May-aliases after instruction  s = (int *)malloc((size_t)idx);  are  <none>
+[alias] analysing instruction: idx ++;
+[alias] May-aliases after instruction  idx ++;  are  <none>
+[alias] analysing instruction: s = (int *)malloc((size_t)idx);
+[alias] May-aliases after instruction  s = (int *)malloc((size_t)idx);  are  <none>
+[alias] analysing instruction: __retres = 0;
+[alias] May-aliases after instruction  __retres = 0;  are  <none>
+[alias] May-aliases at the end of function main: <none>
+[alias] analysing function: malloc
+[alias] May-aliases at the end of function malloc: ⊥
+[alias] analysing function: mblen
+[alias] May-aliases at the end of function mblen: ⊥
+[alias] analysing function: mbstowcs
+[alias] May-aliases at the end of function mbstowcs: ⊥
+[alias] analysing function: mbtowc
+[alias] May-aliases at the end of function mbtowc: ⊥
+[alias] analysing function: mkstemp
+[alias] May-aliases at the end of function mkstemp: ⊥
+[alias] analysing function: mkstemps
+[alias] May-aliases at the end of function mkstemps: ⊥
+[alias] analysing function: mrand48
+[alias] May-aliases at the end of function mrand48: ⊥
+[alias] analysing function: nrand48
+[alias] May-aliases at the end of function nrand48: ⊥
+[alias] analysing function: posix_memalign
+[alias] May-aliases at the end of function posix_memalign: ⊥
+[alias] analysing function: putenv
+[alias] May-aliases at the end of function putenv: ⊥
+[alias] analysing function: qsort
+[alias] May-aliases at the end of function qsort: ⊥
+[alias] analysing function: quick_exit
+[alias] May-aliases at the end of function quick_exit: ⊥
+[alias] analysing function: rand
+[alias] May-aliases at the end of function rand: ⊥
+[alias] analysing function: random
+[alias] May-aliases at the end of function random: ⊥
+[alias] analysing function: realloc
+[alias] May-aliases at the end of function realloc: ⊥
+[alias] analysing function: reallocarray
+[alias] May-aliases at the end of function reallocarray: ⊥
+[alias] analysing function: seed48
+[alias] May-aliases at the end of function seed48: ⊥
+[alias] analysing function: setenv
+[alias] May-aliases at the end of function setenv: ⊥
+[alias] analysing function: srand
+[alias] May-aliases at the end of function srand: ⊥
+[alias] analysing function: srand48
+[alias] May-aliases at the end of function srand48: ⊥
+[alias] analysing function: srandom
+[alias] May-aliases at the end of function srandom: ⊥
+[alias] analysing function: strtod
+[alias] May-aliases at the end of function strtod: ⊥
+[alias] analysing function: strtof
+[alias] May-aliases at the end of function strtof: ⊥
+[alias] analysing function: strtol
+[alias] May-aliases at the end of function strtol: ⊥
+[alias] analysing function: strtold
+[alias] May-aliases at the end of function strtold: ⊥
+[alias] analysing function: strtoll
+[alias] May-aliases at the end of function strtoll: ⊥
+[alias] analysing function: strtoul
+[alias] May-aliases at the end of function strtoul: ⊥
+[alias] analysing function: strtoull
+[alias] May-aliases at the end of function strtoull: ⊥
+[alias] analysing function: system
+[alias] May-aliases at the end of function system: ⊥
+[alias] analysing function: unsetenv
+[alias] May-aliases at the end of function unsetenv: ⊥
+[alias] analysing function: wcstombs
+[alias] May-aliases at the end of function wcstombs: ⊥
+[alias] analysing function: wctomb
+[alias] May-aliases at the end of function wctomb: ⊥
diff --git a/src/plugins/alias/tests/basic/oracle/while_for2.res.oracle b/src/plugins/alias/tests/basic/oracle/while_for2.res.oracle
new file mode 100644
index 0000000000000000000000000000000000000000..3986565e550a94827f115749244cece16be1b6ce
--- /dev/null
+++ b/src/plugins/alias/tests/basic/oracle/while_for2.res.oracle
@@ -0,0 +1,13 @@
+[kernel] Parsing while_for2.c (with preprocessing)
+[alias] analysing function: main
+[alias] analysing instruction: int *a = (int *)0;
+[alias] May-aliases after instruction  int *a = (int *)0;  are  <none>
+[alias] analysing instruction: int *b = (int *)0;
+[alias] May-aliases after instruction  int *b = (int *)0;  are  <none>
+[alias] analysing instruction: int *c = (int *)0;
+[alias] May-aliases after instruction  int *c = (int *)0;  are  <none>
+[alias] analysing instruction: a = b;
+[alias] May-aliases after instruction  a = b;  are  {a, b}
+[alias] analysing instruction: __retres = 0;
+[alias] May-aliases after instruction  __retres = 0;  are  {a, b}
+[alias] May-aliases at the end of function main: {a, b}
diff --git a/src/plugins/alias/tests/basic/oracle/while_for3.res.oracle b/src/plugins/alias/tests/basic/oracle/while_for3.res.oracle
new file mode 100644
index 0000000000000000000000000000000000000000..382069e577e43db211419f390f12de9f17a9da35
--- /dev/null
+++ b/src/plugins/alias/tests/basic/oracle/while_for3.res.oracle
@@ -0,0 +1,19 @@
+[kernel] Parsing while_for3.c (with preprocessing)
+[alias] analysing function: main
+[alias] analysing instruction: int *a = (int *)0;
+[alias] May-aliases after instruction  int *a = (int *)0;  are  <none>
+[alias] analysing instruction: int *b = (int *)0;
+[alias] May-aliases after instruction  int *b = (int *)0;  are  <none>
+[alias] analysing instruction: int *c = (int *)0;
+[alias] May-aliases after instruction  int *c = (int *)0;  are  <none>
+[alias] analysing instruction: int i = 0;
+[alias] May-aliases after instruction  int i = 0;  are  <none>
+[alias] analysing instruction: a = b;
+[alias] May-aliases after instruction  a = b;  are  {a, b}
+[alias] analysing instruction: __Cont: i ++;
+[alias] May-aliases after instruction  __Cont: i ++;  are  {a, b}
+[alias] analysing instruction: a = b;
+[alias] May-aliases after instruction  a = b;  are  {a, b}
+[alias] analysing instruction: __retres = 0;
+[alias] May-aliases after instruction  __retres = 0;  are  {a, b}
+[alias] May-aliases at the end of function main: {a, b}
diff --git a/src/plugins/alias/tests/basic/steensgaard.c b/src/plugins/alias/tests/basic/steensgaard.c
new file mode 100644
index 0000000000000000000000000000000000000000..7afb87e247941e9aa1206c86324763ac77867c17
--- /dev/null
+++ b/src/plugins/alias/tests/basic/steensgaard.c
@@ -0,0 +1,19 @@
+// from steensgaard's paper
+//  {*b, *c, a, y} are aliased
+//  {b, c} are aliased
+
+
+int main () {
+  int *a, **b, **c, *y, x, z, p;
+  a = &x;
+  b = &y;
+  if (p)
+    y = &z;
+  else
+    y = &x;
+  c = &y;
+  *y = 4;
+  return 0;
+}
+
+
diff --git a/src/plugins/alias/tests/basic/switch1.c b/src/plugins/alias/tests/basic/switch1.c
new file mode 100644
index 0000000000000000000000000000000000000000..c0b97a18180983bda26f3439f939f604cc58624d
--- /dev/null
+++ b/src/plugins/alias/tests/basic/switch1.c
@@ -0,0 +1,17 @@
+// switch
+//  {a, b, d} are aliased
+
+int main ()
+{
+  int *a=0, *b=0, *c=0, *d=0, e=0;
+  switch (e) {
+  case 1:
+    a=d;
+    break;
+  case 2:
+    b=d;
+    break;
+  }
+    
+  return 0;
+}
diff --git a/src/plugins/alias/tests/basic/switch2.c b/src/plugins/alias/tests/basic/switch2.c
new file mode 100644
index 0000000000000000000000000000000000000000..05d162bd67a0dd14fb8010af75281c989425e705
--- /dev/null
+++ b/src/plugins/alias/tests/basic/switch2.c
@@ -0,0 +1,19 @@
+// switch with default
+//  {a, b, c, d} are aliased
+
+int main ()
+{
+  int *a=0, *b=0, *c=0, *d=0, e=0;
+  switch (e) {
+  case 1:
+    a=d;
+    break;
+  case 2:
+    b=d;
+    break;
+  default:
+    c=d;
+  }
+    
+  return 0;
+}
diff --git a/src/plugins/alias/tests/basic/while_for1.c b/src/plugins/alias/tests/basic/while_for1.c
new file mode 100644
index 0000000000000000000000000000000000000000..06ef79f5f89d2573152cf3035a59fa55d2e8baad
--- /dev/null
+++ b/src/plugins/alias/tests/basic/while_for1.c
@@ -0,0 +1,13 @@
+// for loop
+// no alias
+
+#include <stdlib.h>
+
+int main ()
+{
+  int* s = 0;
+  for (int idx = 0; idx < 10; idx++) {
+    s = malloc(idx);
+  }
+  return 0;
+}
diff --git a/src/plugins/alias/tests/basic/while_for2.c b/src/plugins/alias/tests/basic/while_for2.c
new file mode 100644
index 0000000000000000000000000000000000000000..f98677716b7e80a6f746b6e7033a61c4069b4c7f
--- /dev/null
+++ b/src/plugins/alias/tests/basic/while_for2.c
@@ -0,0 +1,17 @@
+// while loops with trivial conditions
+//  {a, b} are aliased
+
+int main ()
+{
+  int *a=0, *b=0, *c=0;
+  while (1) {
+    a = b;
+    break;
+  }
+
+   while (0) {
+    a = c;
+    break;
+  }
+  return 0;
+}
diff --git a/src/plugins/alias/tests/basic/while_for3.c b/src/plugins/alias/tests/basic/while_for3.c
new file mode 100644
index 0000000000000000000000000000000000000000..e7ffb9f39523ca14abdc8ba00b84fd55699e195b
--- /dev/null
+++ b/src/plugins/alias/tests/basic/while_for3.c
@@ -0,0 +1,16 @@
+// continue
+//  {a, b} are aliased
+
+int main ()
+{
+  int *a=0, *b=0, *c=0;
+  for (int i=0; i<10 ;i++) {
+    if (1) {
+      a = b;
+      continue;
+    }
+    a = c;
+  }
+
+  return 0;
+}
diff --git a/src/plugins/alias/tests/fixed_bugs/empty_nodes.c b/src/plugins/alias/tests/fixed_bugs/empty_nodes.c
new file mode 100644
index 0000000000000000000000000000000000000000..004a207da7443ec4a3ee2c1c21913e53641ccd0b
--- /dev/null
+++ b/src/plugins/alias/tests/fixed_bugs/empty_nodes.c
@@ -0,0 +1,12 @@
+void f(char **x, char **y, char **z)
+{
+  char *t;
+  *y = t + (*y - *x);
+  *z = t + (*z - *x);
+  *x = t;
+}
+
+void g(char **a)
+{
+  f(a,a,a);
+}
diff --git a/src/plugins/alias/tests/fixed_bugs/gzip124.c b/src/plugins/alias/tests/fixed_bugs/gzip124.c
new file mode 100644
index 0000000000000000000000000000000000000000..70a9cc2955966f21c8ea856531bf467464e66355
--- /dev/null
+++ b/src/plugins/alias/tests/fixed_bugs/gzip124.c
@@ -0,0 +1,12 @@
+int main(void)
+{
+  int __retres;
+  short prev[1];
+  short *p;
+  short tmp_0 = (short)0;
+  *(& prev[1] + 0) = tmp_0;
+  prev[0] = (short)0;
+  if (0 + 0) p = & prev[1] + (int)*p; else p = & prev[*p];
+  __retres = 0;
+  return __retres;
+}
diff --git a/src/plugins/alias/tests/fixed_bugs/oracle/empty_nodes.res.oracle b/src/plugins/alias/tests/fixed_bugs/oracle/empty_nodes.res.oracle
new file mode 100644
index 0000000000000000000000000000000000000000..970b25bd3ea518640e4cdca331963fd23ab641f8
--- /dev/null
+++ b/src/plugins/alias/tests/fixed_bugs/oracle/empty_nodes.res.oracle
@@ -0,0 +1,13 @@
+[kernel] Parsing empty_nodes.c (with preprocessing)
+[alias] analysing function: f
+[alias] analysing instruction: *y = t + (*y - *x);
+[alias] May-aliases after instruction  *y = t + (*y - *x);  are  {*y, t}
+[alias] analysing instruction: *z = t + (*z - *x);
+[alias] May-aliases after instruction  *z = t + (*z - *x);  are  {*y, *z, t}  {y, z}
+[alias] analysing instruction: *x = t;
+[alias] May-aliases after instruction  *x = t;  are  {*x, *y, *z, t}  {x, y, z}
+[alias] May-aliases at the end of function f: {*x, *y, *z, t}  {x, y, z}
+[alias] analysing function: g
+[alias] analysing instruction: f(a,a,a);
+[alias] May-aliases after instruction  f(a,a,a);  are  <none>
+[alias] May-aliases at the end of function g: <none>
diff --git a/src/plugins/alias/tests/fixed_bugs/oracle/gzip124.res.oracle b/src/plugins/alias/tests/fixed_bugs/oracle/gzip124.res.oracle
new file mode 100644
index 0000000000000000000000000000000000000000..fd9878fef65bf1ea35de5b51eef9ccfe7b40d5a0
--- /dev/null
+++ b/src/plugins/alias/tests/fixed_bugs/oracle/gzip124.res.oracle
@@ -0,0 +1,15 @@
+[kernel] Parsing gzip124.c (with preprocessing)
+[alias] analysing function: main
+[alias] analysing instruction: short tmp_0 = (short)0;
+[alias] May-aliases after instruction  short tmp_0 = (short)0;  are  <none>
+[alias] analysing instruction: *(& prev[1] + 0) = tmp_0;
+[alias] May-aliases after instruction  *(& prev[1] + 0) = tmp_0;  are  <none>
+[alias] analysing instruction: prev[0] = (short)0;
+[alias] May-aliases after instruction  prev[0] = (short)0;  are  <none>
+[alias] analysing instruction: p = & prev[1] + (int)*p;
+[alias] May-aliases after instruction  p = & prev[1] + (int)*p;  are  <none>
+[alias] analysing instruction: p = & prev[*p];
+[alias] May-aliases after instruction  p = & prev[*p];  are  <none>
+[alias] analysing instruction: __retres = 0;
+[alias] May-aliases after instruction  __retres = 0;  are  <none>
+[alias] May-aliases at the end of function main: <none>
diff --git a/src/plugins/alias/tests/fixed_bugs/oracle/semver.res.oracle b/src/plugins/alias/tests/fixed_bugs/oracle/semver.res.oracle
new file mode 100644
index 0000000000000000000000000000000000000000..bdc3f9de65441a71704fe3c6c2faf4b5d51f684b
--- /dev/null
+++ b/src/plugins/alias/tests/fixed_bugs/oracle/semver.res.oracle
@@ -0,0 +1,12 @@
+[kernel] Parsing semver.c (with preprocessing)
+[alias] analysing function: f
+[alias] May-aliases at the end of function f: <none>
+[alias] analysing function: main
+[alias] analysing instruction: f((int *)*("1" + 2));
+[alias:unsafe-cast] semver.c:6: Warning: unsafe cast from char to int *
+[alias:unsupported:addr] semver.c:6: Warning: 
+  unsupported feature: explicit pointer address: (int *)*("1" + 2); analysis may be unsound
+[alias] May-aliases after instruction  f((int *)*("1" + 2));  are  <none>
+[alias] analysing instruction: __retres = 0;
+[alias] May-aliases after instruction  __retres = 0;  are  <none>
+[alias] May-aliases at the end of function main: <none>
diff --git a/src/plugins/alias/tests/fixed_bugs/oracle/tkn-2.res.oracle b/src/plugins/alias/tests/fixed_bugs/oracle/tkn-2.res.oracle
new file mode 100644
index 0000000000000000000000000000000000000000..7843cab155742b5e87b1d4e3c6fd67107fca9412
--- /dev/null
+++ b/src/plugins/alias/tests/fixed_bugs/oracle/tkn-2.res.oracle
@@ -0,0 +1,9 @@
+[kernel] Parsing tkn-2.c (with preprocessing)
+[alias] analysing function: main
+[alias] analysing instruction: a = (int *)(& a);
+[alias:unsafe-cast] tkn-2.c:6: Warning: unsafe cast from int ** to int *
+[alias] tkn-2.c:6: Warning: ignoring assignment of the form: a = (int *)(& a)
+[alias] May-aliases after instruction  a = (int *)(& a);  are  <none>
+[alias] analysing instruction: __retres = *a;
+[alias] May-aliases after instruction  __retres = *a;  are  <none>
+[alias] May-aliases at the end of function main: <none>
diff --git a/src/plugins/alias/tests/fixed_bugs/oracle/union_vmap.res.oracle b/src/plugins/alias/tests/fixed_bugs/oracle/union_vmap.res.oracle
new file mode 100644
index 0000000000000000000000000000000000000000..606169550d1d780734a260fb8b0af502e57a26c5
--- /dev/null
+++ b/src/plugins/alias/tests/fixed_bugs/oracle/union_vmap.res.oracle
@@ -0,0 +1,21 @@
+[kernel] Parsing union_vmap.c (with preprocessing)
+[alias] analysing function: CPS_ParseKey
+[alias] analysing instruction: char *s2 = CPS_SplitWord((char *)"a");
+[alias] analysing function: CPS_SplitWord
+[alias] May-aliases at the end of function CPS_SplitWord: <none>
+[alias:unsafe-cast] union_vmap.c:11: Warning: 
+  unsafe cast from char const * to char *
+[alias] May-aliases after instruction  char *s2 = CPS_SplitWord((char *)"a");  are
+  <none>
+[alias] analysing instruction: char *s3 = CPS_SplitWord((char *)"b");
+[alias:unsafe-cast] union_vmap.c:12: Warning: 
+  unsafe cast from char const * to char *
+[alias] May-aliases after instruction  char *s3 = CPS_SplitWord((char *)"b");  are
+  <none>
+[alias] analysing instruction: *key = s3;
+[alias] May-aliases after instruction  *key = s3;  are  {*key, s3}
+[alias] analysing instruction: *key = s2;
+[alias] May-aliases after instruction  *key = s2;  are  {*key, s2}
+[alias] May-aliases at the end of function CPS_ParseKey: {*key, s2, s3}
+[alias] analysing function: CPS_SplitWord
+[alias] May-aliases at the end of function CPS_SplitWord: <none>
diff --git a/src/plugins/alias/tests/fixed_bugs/semver.c b/src/plugins/alias/tests/fixed_bugs/semver.c
new file mode 100644
index 0000000000000000000000000000000000000000..d93edc0b90eb1d95415b0dd17453a639414a8d4e
--- /dev/null
+++ b/src/plugins/alias/tests/fixed_bugs/semver.c
@@ -0,0 +1,8 @@
+void f (int* x) {
+}
+
+int main(void)
+{
+	f ((int*)*("1" + 2));
+	return 0;
+}
diff --git a/src/plugins/alias/tests/fixed_bugs/tkn-2.c b/src/plugins/alias/tests/fixed_bugs/tkn-2.c
new file mode 100644
index 0000000000000000000000000000000000000000..97ee64b4f9aa53e56ec9766877bad8dae52f260e
--- /dev/null
+++ b/src/plugins/alias/tests/fixed_bugs/tkn-2.c
@@ -0,0 +1,8 @@
+// leads to a loop; taken from open-source-case-studies/cerberus
+
+int main()
+{
+  int* a;
+  a = (int*)(& a);
+  return *a;
+}
diff --git a/src/plugins/alias/tests/fixed_bugs/union_vmap.c b/src/plugins/alias/tests/fixed_bugs/union_vmap.c
new file mode 100644
index 0000000000000000000000000000000000000000..5bf04ceddf9510e34cf3465710a71896ed841990
--- /dev/null
+++ b/src/plugins/alias/tests/fixed_bugs/union_vmap.c
@@ -0,0 +1,21 @@
+// from open-source-case-studies/chrony
+
+char* CPS_SplitWord(char *line)
+{
+  return line;
+}
+
+void CPS_ParseKey()
+{
+	char **key;
+  char *s2 = CPS_SplitWord("a");
+  char *s3 = CPS_SplitWord("b");
+  if (*s3) {
+    *key = s3;
+  }
+  else {
+    *key = s2;
+  }
+}
+
+
diff --git a/src/plugins/alias/tests/offsets/array1.c b/src/plugins/alias/tests/offsets/array1.c
new file mode 100644
index 0000000000000000000000000000000000000000..34518455ecb6fae2be23331c1a9a3a1ba0251135
--- /dev/null
+++ b/src/plugins/alias/tests/offsets/array1.c
@@ -0,0 +1,15 @@
+// simple array
+//  {x, y} are aliased
+
+int main () {
+  int tab[4];
+  tab[0] = 0;
+  tab[1] = 1;
+  tab[2] = tab[1] +1;
+
+  int* x = &tab[1];
+  int* y = &tab[2];
+  tab[3] = *x + *y;
+
+  return 0;
+}
diff --git a/src/plugins/alias/tests/offsets/array2.c b/src/plugins/alias/tests/offsets/array2.c
new file mode 100644
index 0000000000000000000000000000000000000000..0ba4d222f6a4642288f2c53cfd8fcfb1d1e7b036
--- /dev/null
+++ b/src/plugins/alias/tests/offsets/array2.c
@@ -0,0 +1,17 @@
+// matrices (this example may be not a valid c program)
+//  no alias
+
+int main () {
+  int mat[4][4];
+  mat[0][0] = 0;
+  mat[0][1] = 1;
+
+  int **x;
+  *x = mat[1];
+
+  int* y;
+  *y = *x[0];
+
+  
+  return 0;
+}
diff --git a/src/plugins/alias/tests/offsets/array3.c b/src/plugins/alias/tests/offsets/array3.c
new file mode 100644
index 0000000000000000000000000000000000000000..09bd2e67a51be84ef8a466417a95f88709ef8b3d
--- /dev/null
+++ b/src/plugins/alias/tests/offsets/array3.c
@@ -0,0 +1,15 @@
+// matrices
+//  {x, y} are aliased
+ 
+#include <stdlib.h>
+
+
+int main () {
+  int mat[4][4];
+  int* x = malloc (4* sizeof(int));
+  int* y = malloc (4* sizeof(int));
+  x = mat[0];
+  y = mat[1];
+
+  return 0;
+}
diff --git a/src/plugins/alias/tests/offsets/collapse1.c b/src/plugins/alias/tests/offsets/collapse1.c
new file mode 100644
index 0000000000000000000000000000000000000000..624f42c3af68819390dbbaf141ef0452f9ba3c75
--- /dev/null
+++ b/src/plugins/alias/tests/offsets/collapse1.c
@@ -0,0 +1,14 @@
+
+
+int main () {
+  int tab[4];
+  tab[0] = 0;
+  tab[1] = 1;
+  tab[2] = tab[1] +1;
+  int x =0;
+  
+  for (int i=0;i<2;i++)
+    x = tab[i];
+  
+  return 0;
+}
diff --git a/src/plugins/alias/tests/offsets/collapse2.c b/src/plugins/alias/tests/offsets/collapse2.c
new file mode 100644
index 0000000000000000000000000000000000000000..9c00bd24e3b5297f9d18a9fe99922e4a5d543802
--- /dev/null
+++ b/src/plugins/alias/tests/offsets/collapse2.c
@@ -0,0 +1,15 @@
+// matrices
+
+int main () {
+  int mat[4][4];
+  mat[0][0] = 0;
+  mat[0][1] = 1;
+
+  int i=2;
+  mat[1][i]=i;
+
+  i=i+1;
+  mat[1][i]=2;
+  
+  return 0;
+}
diff --git a/src/plugins/alias/tests/offsets/collapse3.c b/src/plugins/alias/tests/offsets/collapse3.c
new file mode 100644
index 0000000000000000000000000000000000000000..8540638c809a74ad632b46ec6ce12342b30906e6
--- /dev/null
+++ b/src/plugins/alias/tests/offsets/collapse3.c
@@ -0,0 +1,15 @@
+// matrices
+
+int main () {
+  int mat[4][4];
+  mat[0][0] = 0;
+  mat[0][1] = 1;
+
+  int i=2;
+  mat[i][1]=i;
+
+  i=i+1;
+  mat[i][1]=2;
+  
+  return 0;
+}
diff --git a/src/plugins/alias/tests/offsets/nested1.c b/src/plugins/alias/tests/offsets/nested1.c
new file mode 100644
index 0000000000000000000000000000000000000000..06c14b9512b4ee4d15c4451f2d22382c2703f49c
--- /dev/null
+++ b/src/plugins/alias/tests/offsets/nested1.c
@@ -0,0 +1,56 @@
+// nested structures and arrays
+//  {z1->s, z2->s, tab_y[0]} are aliased
+//  {t->t, z1} are aliased
+//  {z1->c, t->d, a} are aliased
+//  {z2->c, b} are aliased
+
+
+#include <stdlib.h>
+
+typedef struct
+{       
+    int   a;
+    int   b;
+} st_1_t;
+
+typedef struct
+{       
+    struct struct_1_t*  s;
+    int*   c;
+} st_2_t;
+
+
+typedef struct
+{       
+    struct struct_2_t*  t;
+    int*   d;
+} st_3_t;
+
+
+
+int main () {
+
+  st_1_t x1 = {0,1};
+  st_1_t x2 = {1,2};
+  st_1_t *tab_y [2];
+
+  tab_y[0] = &x1;
+  tab_y[1] = &x2;
+  st_2_t *z1 = malloc(sizeof(st_2_t));
+  st_2_t *z2 = malloc(sizeof(st_2_t));
+  st_3_t *t = malloc(sizeof(st_3_t));
+  int* a = malloc(sizeof(int));
+  int* b = malloc(sizeof(int));
+  
+  *a = 0;
+  *b = 5;
+  z1->s = tab_y[0];
+  z2->s = tab_y[1];
+  z1->c = a;
+  z2->c = b;
+  t->t = z1;
+  t->d = a;
+  
+
+  return 0;
+}
diff --git a/src/plugins/alias/tests/offsets/nested2.c b/src/plugins/alias/tests/offsets/nested2.c
new file mode 100644
index 0000000000000000000000000000000000000000..193bdd1adba16542da95e964e384c3651c373379
--- /dev/null
+++ b/src/plugins/alias/tests/offsets/nested2.c
@@ -0,0 +1,50 @@
+// nested structures and arrays
+//  {t->t, z1} are aliased
+//  {z1->c, t->d, a} are aliased
+
+
+#include <stdlib.h>
+
+typedef struct
+{       
+    int   a;
+    int   b;
+} st_1_t;
+
+typedef struct
+{       
+    struct struct_1_t*  s [2];
+    int*   c;
+} st_2_t;
+
+
+typedef struct
+{       
+    struct struct_2_t*  t;
+    int*   d;
+} st_3_t;
+
+
+
+
+
+int main () {
+
+  st_1_t x1 = {0,1};
+  st_1_t x2 = {2,3};
+
+  st_2_t *z1 = malloc(sizeof(st_2_t));
+
+  st_3_t *t = malloc(sizeof(st_3_t));
+  int* a = malloc(sizeof(int));
+  
+  *a = 0;
+  z1->s[0] = &x1;
+  z1->s[1] = &x2;
+  z1->c = a;
+  t->t = z1;
+  t->d = a;
+  
+
+  return 0;
+}
diff --git a/src/plugins/alias/tests/offsets/oracle/array1.res.oracle b/src/plugins/alias/tests/offsets/oracle/array1.res.oracle
new file mode 100644
index 0000000000000000000000000000000000000000..d6bdf7ba016ca2bf534ccbde0c2f7b0fe9f36f76
--- /dev/null
+++ b/src/plugins/alias/tests/offsets/oracle/array1.res.oracle
@@ -0,0 +1,17 @@
+[kernel] Parsing array1.c (with preprocessing)
+[alias] analysing function: main
+[alias] analysing instruction: tab[0] = 0;
+[alias] May-aliases after instruction  tab[0] = 0;  are  <none>
+[alias] analysing instruction: tab[1] = 1;
+[alias] May-aliases after instruction  tab[1] = 1;  are  <none>
+[alias] analysing instruction: tab[2] = tab[1] + 1;
+[alias] May-aliases after instruction  tab[2] = tab[1] + 1;  are  <none>
+[alias] analysing instruction: int *x = & tab[1];
+[alias] May-aliases after instruction  int *x = & tab[1];  are  <none>
+[alias] analysing instruction: int *y = & tab[2];
+[alias] May-aliases after instruction  int *y = & tab[2];  are  {x, y}
+[alias] analysing instruction: tab[3] = *x + *y;
+[alias] May-aliases after instruction  tab[3] = *x + *y;  are  {x, y}
+[alias] analysing instruction: __retres = 0;
+[alias] May-aliases after instruction  __retres = 0;  are  {x, y}
+[alias] May-aliases at the end of function main: {x, y}
diff --git a/src/plugins/alias/tests/offsets/oracle/array2.res.oracle b/src/plugins/alias/tests/offsets/oracle/array2.res.oracle
new file mode 100644
index 0000000000000000000000000000000000000000..69f16a022f8b05688a9a9eb66a4180354fdcf323
--- /dev/null
+++ b/src/plugins/alias/tests/offsets/oracle/array2.res.oracle
@@ -0,0 +1,13 @@
+[kernel] Parsing array2.c (with preprocessing)
+[alias] analysing function: main
+[alias] analysing instruction: mat[0][0] = 0;
+[alias] May-aliases after instruction  mat[0][0] = 0;  are  <none>
+[alias] analysing instruction: mat[0][1] = 1;
+[alias] May-aliases after instruction  mat[0][1] = 1;  are  <none>
+[alias] analysing instruction: *x = mat[1];
+[alias] May-aliases after instruction  *x = mat[1];  are  <none>
+[alias] analysing instruction: *y = *(*(x + 0));
+[alias] May-aliases after instruction  *y = *(*(x + 0));  are  <none>
+[alias] analysing instruction: __retres = 0;
+[alias] May-aliases after instruction  __retres = 0;  are  <none>
+[alias] May-aliases at the end of function main: <none>
diff --git a/src/plugins/alias/tests/offsets/oracle/array3.res.oracle b/src/plugins/alias/tests/offsets/oracle/array3.res.oracle
new file mode 100644
index 0000000000000000000000000000000000000000..6b6a66a4677d71e520481483aaa137fa7dd8529c
--- /dev/null
+++ b/src/plugins/alias/tests/offsets/oracle/array3.res.oracle
@@ -0,0 +1,127 @@
+[kernel] Parsing array3.c (with preprocessing)
+[alias] analysing function: _Exit
+[alias] May-aliases at the end of function _Exit: ⊥
+[alias] analysing function: abort
+[alias] May-aliases at the end of function abort: ⊥
+[alias] analysing function: abs
+[alias] May-aliases at the end of function abs: ⊥
+[alias] analysing function: at_quick_exit
+[alias] May-aliases at the end of function at_quick_exit: ⊥
+[alias] analysing function: atexit
+[alias] May-aliases at the end of function atexit: ⊥
+[alias] analysing function: atof
+[alias] May-aliases at the end of function atof: ⊥
+[alias] analysing function: atoi
+[alias] May-aliases at the end of function atoi: ⊥
+[alias] analysing function: atol
+[alias] May-aliases at the end of function atol: ⊥
+[alias] analysing function: atoll
+[alias] May-aliases at the end of function atoll: ⊥
+[alias] analysing function: bsearch
+[alias] May-aliases at the end of function bsearch: ⊥
+[alias] analysing function: calloc
+[alias] May-aliases at the end of function calloc: ⊥
+[alias] analysing function: div
+[alias] May-aliases at the end of function div: ⊥
+[alias] analysing function: drand48
+[alias] May-aliases at the end of function drand48: ⊥
+[alias] analysing function: erand48
+[alias] May-aliases at the end of function erand48: ⊥
+[alias] analysing function: exit
+[alias] May-aliases at the end of function exit: ⊥
+[alias] analysing function: free
+[alias] May-aliases at the end of function free: ⊥
+[alias] analysing function: getenv
+[alias] May-aliases at the end of function getenv: ⊥
+[alias] analysing function: jrand48
+[alias] May-aliases at the end of function jrand48: ⊥
+[alias] analysing function: labs
+[alias] May-aliases at the end of function labs: ⊥
+[alias] analysing function: lcong48
+[alias] May-aliases at the end of function lcong48: ⊥
+[alias] analysing function: ldiv
+[alias] May-aliases at the end of function ldiv: ⊥
+[alias] analysing function: llabs
+[alias] May-aliases at the end of function llabs: ⊥
+[alias] analysing function: lldiv
+[alias] May-aliases at the end of function lldiv: ⊥
+[alias] analysing function: lrand48
+[alias] May-aliases at the end of function lrand48: ⊥
+[alias] analysing function: main
+[alias] analysing instruction: int *x = malloc((unsigned long)4 * sizeof(int));
+[alias] May-aliases after instruction
+  int *x = malloc((unsigned long)4 * sizeof(int));  are  <none>
+[alias] analysing instruction: int *y = malloc((unsigned long)4 * sizeof(int));
+[alias] May-aliases after instruction
+  int *y = malloc((unsigned long)4 * sizeof(int));  are  <none>
+[alias] analysing instruction: x = mat[0];
+[alias] May-aliases after instruction  x = mat[0];  are  <none>
+[alias] analysing instruction: y = mat[1];
+[alias] May-aliases after instruction  y = mat[1];  are  {x, y}
+[alias] analysing instruction: __retres = 0;
+[alias] May-aliases after instruction  __retres = 0;  are  {x, y}
+[alias] May-aliases at the end of function main: {x, y}
+[alias] analysing function: malloc
+[alias] May-aliases at the end of function malloc: ⊥
+[alias] analysing function: mblen
+[alias] May-aliases at the end of function mblen: ⊥
+[alias] analysing function: mbstowcs
+[alias] May-aliases at the end of function mbstowcs: ⊥
+[alias] analysing function: mbtowc
+[alias] May-aliases at the end of function mbtowc: ⊥
+[alias] analysing function: mkstemp
+[alias] May-aliases at the end of function mkstemp: ⊥
+[alias] analysing function: mkstemps
+[alias] May-aliases at the end of function mkstemps: ⊥
+[alias] analysing function: mrand48
+[alias] May-aliases at the end of function mrand48: ⊥
+[alias] analysing function: nrand48
+[alias] May-aliases at the end of function nrand48: ⊥
+[alias] analysing function: posix_memalign
+[alias] May-aliases at the end of function posix_memalign: ⊥
+[alias] analysing function: putenv
+[alias] May-aliases at the end of function putenv: ⊥
+[alias] analysing function: qsort
+[alias] May-aliases at the end of function qsort: ⊥
+[alias] analysing function: quick_exit
+[alias] May-aliases at the end of function quick_exit: ⊥
+[alias] analysing function: rand
+[alias] May-aliases at the end of function rand: ⊥
+[alias] analysing function: random
+[alias] May-aliases at the end of function random: ⊥
+[alias] analysing function: realloc
+[alias] May-aliases at the end of function realloc: ⊥
+[alias] analysing function: reallocarray
+[alias] May-aliases at the end of function reallocarray: ⊥
+[alias] analysing function: seed48
+[alias] May-aliases at the end of function seed48: ⊥
+[alias] analysing function: setenv
+[alias] May-aliases at the end of function setenv: ⊥
+[alias] analysing function: srand
+[alias] May-aliases at the end of function srand: ⊥
+[alias] analysing function: srand48
+[alias] May-aliases at the end of function srand48: ⊥
+[alias] analysing function: srandom
+[alias] May-aliases at the end of function srandom: ⊥
+[alias] analysing function: strtod
+[alias] May-aliases at the end of function strtod: ⊥
+[alias] analysing function: strtof
+[alias] May-aliases at the end of function strtof: ⊥
+[alias] analysing function: strtol
+[alias] May-aliases at the end of function strtol: ⊥
+[alias] analysing function: strtold
+[alias] May-aliases at the end of function strtold: ⊥
+[alias] analysing function: strtoll
+[alias] May-aliases at the end of function strtoll: ⊥
+[alias] analysing function: strtoul
+[alias] May-aliases at the end of function strtoul: ⊥
+[alias] analysing function: strtoull
+[alias] May-aliases at the end of function strtoull: ⊥
+[alias] analysing function: system
+[alias] May-aliases at the end of function system: ⊥
+[alias] analysing function: unsetenv
+[alias] May-aliases at the end of function unsetenv: ⊥
+[alias] analysing function: wcstombs
+[alias] May-aliases at the end of function wcstombs: ⊥
+[alias] analysing function: wctomb
+[alias] May-aliases at the end of function wctomb: ⊥
diff --git a/src/plugins/alias/tests/offsets/oracle/collapse1.res.oracle b/src/plugins/alias/tests/offsets/oracle/collapse1.res.oracle
new file mode 100644
index 0000000000000000000000000000000000000000..9b588f2f8f2484f894680dae6ca6129528811125
--- /dev/null
+++ b/src/plugins/alias/tests/offsets/oracle/collapse1.res.oracle
@@ -0,0 +1,19 @@
+[kernel] Parsing collapse1.c (with preprocessing)
+[alias] analysing function: main
+[alias] analysing instruction: tab[0] = 0;
+[alias] May-aliases after instruction  tab[0] = 0;  are  <none>
+[alias] analysing instruction: tab[1] = 1;
+[alias] May-aliases after instruction  tab[1] = 1;  are  <none>
+[alias] analysing instruction: tab[2] = tab[1] + 1;
+[alias] May-aliases after instruction  tab[2] = tab[1] + 1;  are  <none>
+[alias] analysing instruction: int x = 0;
+[alias] May-aliases after instruction  int x = 0;  are  <none>
+[alias] analysing instruction: int i = 0;
+[alias] May-aliases after instruction  int i = 0;  are  <none>
+[alias] analysing instruction: x = tab[i];
+[alias] May-aliases after instruction  x = tab[i];  are  <none>
+[alias] analysing instruction: i ++;
+[alias] May-aliases after instruction  i ++;  are  <none>
+[alias] analysing instruction: __retres = 0;
+[alias] May-aliases after instruction  __retres = 0;  are  <none>
+[alias] May-aliases at the end of function main: <none>
diff --git a/src/plugins/alias/tests/offsets/oracle/collapse2.res.oracle b/src/plugins/alias/tests/offsets/oracle/collapse2.res.oracle
new file mode 100644
index 0000000000000000000000000000000000000000..34b8bd11975081e1acc6cd63c7d0011d1f3b57e3
--- /dev/null
+++ b/src/plugins/alias/tests/offsets/oracle/collapse2.res.oracle
@@ -0,0 +1,17 @@
+[kernel] Parsing collapse2.c (with preprocessing)
+[alias] analysing function: main
+[alias] analysing instruction: mat[0][0] = 0;
+[alias] May-aliases after instruction  mat[0][0] = 0;  are  <none>
+[alias] analysing instruction: mat[0][1] = 1;
+[alias] May-aliases after instruction  mat[0][1] = 1;  are  <none>
+[alias] analysing instruction: int i = 2;
+[alias] May-aliases after instruction  int i = 2;  are  <none>
+[alias] analysing instruction: mat[1][i] = i;
+[alias] May-aliases after instruction  mat[1][i] = i;  are  <none>
+[alias] analysing instruction: i ++;
+[alias] May-aliases after instruction  i ++;  are  <none>
+[alias] analysing instruction: mat[1][i] = 2;
+[alias] May-aliases after instruction  mat[1][i] = 2;  are  <none>
+[alias] analysing instruction: __retres = 0;
+[alias] May-aliases after instruction  __retres = 0;  are  <none>
+[alias] May-aliases at the end of function main: <none>
diff --git a/src/plugins/alias/tests/offsets/oracle/collapse3.res.oracle b/src/plugins/alias/tests/offsets/oracle/collapse3.res.oracle
new file mode 100644
index 0000000000000000000000000000000000000000..4193c3f90a212238b3a6f1452d58e097c1ae1bd1
--- /dev/null
+++ b/src/plugins/alias/tests/offsets/oracle/collapse3.res.oracle
@@ -0,0 +1,17 @@
+[kernel] Parsing collapse3.c (with preprocessing)
+[alias] analysing function: main
+[alias] analysing instruction: mat[0][0] = 0;
+[alias] May-aliases after instruction  mat[0][0] = 0;  are  <none>
+[alias] analysing instruction: mat[0][1] = 1;
+[alias] May-aliases after instruction  mat[0][1] = 1;  are  <none>
+[alias] analysing instruction: int i = 2;
+[alias] May-aliases after instruction  int i = 2;  are  <none>
+[alias] analysing instruction: mat[i][1] = i;
+[alias] May-aliases after instruction  mat[i][1] = i;  are  <none>
+[alias] analysing instruction: i ++;
+[alias] May-aliases after instruction  i ++;  are  <none>
+[alias] analysing instruction: mat[i][1] = 2;
+[alias] May-aliases after instruction  mat[i][1] = 2;  are  <none>
+[alias] analysing instruction: __retres = 0;
+[alias] May-aliases after instruction  __retres = 0;  are  <none>
+[alias] May-aliases at the end of function main: <none>
diff --git a/src/plugins/alias/tests/offsets/oracle/nested1.res.oracle b/src/plugins/alias/tests/offsets/oracle/nested1.res.oracle
new file mode 100644
index 0000000000000000000000000000000000000000..e26a96622ddd53633ec3d0978ac43635f1dc1e4f
--- /dev/null
+++ b/src/plugins/alias/tests/offsets/oracle/nested1.res.oracle
@@ -0,0 +1,168 @@
+[kernel] Parsing nested1.c (with preprocessing)
+[alias] analysing function: _Exit
+[alias] May-aliases at the end of function _Exit: ⊥
+[alias] analysing function: abort
+[alias] May-aliases at the end of function abort: ⊥
+[alias] analysing function: abs
+[alias] May-aliases at the end of function abs: ⊥
+[alias] analysing function: at_quick_exit
+[alias] May-aliases at the end of function at_quick_exit: ⊥
+[alias] analysing function: atexit
+[alias] May-aliases at the end of function atexit: ⊥
+[alias] analysing function: atof
+[alias] May-aliases at the end of function atof: ⊥
+[alias] analysing function: atoi
+[alias] May-aliases at the end of function atoi: ⊥
+[alias] analysing function: atol
+[alias] May-aliases at the end of function atol: ⊥
+[alias] analysing function: atoll
+[alias] May-aliases at the end of function atoll: ⊥
+[alias] analysing function: bsearch
+[alias] May-aliases at the end of function bsearch: ⊥
+[alias] analysing function: calloc
+[alias] May-aliases at the end of function calloc: ⊥
+[alias] analysing function: div
+[alias] May-aliases at the end of function div: ⊥
+[alias] analysing function: drand48
+[alias] May-aliases at the end of function drand48: ⊥
+[alias] analysing function: erand48
+[alias] May-aliases at the end of function erand48: ⊥
+[alias] analysing function: exit
+[alias] May-aliases at the end of function exit: ⊥
+[alias] analysing function: free
+[alias] May-aliases at the end of function free: ⊥
+[alias] analysing function: getenv
+[alias] May-aliases at the end of function getenv: ⊥
+[alias] analysing function: jrand48
+[alias] May-aliases at the end of function jrand48: ⊥
+[alias] analysing function: labs
+[alias] May-aliases at the end of function labs: ⊥
+[alias] analysing function: lcong48
+[alias] May-aliases at the end of function lcong48: ⊥
+[alias] analysing function: ldiv
+[alias] May-aliases at the end of function ldiv: ⊥
+[alias] analysing function: llabs
+[alias] May-aliases at the end of function llabs: ⊥
+[alias] analysing function: lldiv
+[alias] May-aliases at the end of function lldiv: ⊥
+[alias] analysing function: lrand48
+[alias] May-aliases at the end of function lrand48: ⊥
+[alias] analysing function: main
+[alias] analysing instruction: st_1_t x1 = {.a = 0, .b = 1};
+[alias] May-aliases after instruction  st_1_t x1 = {.a = 0, .b = 1};  are  <none>
+[alias] analysing instruction: st_1_t x2 = {.a = 1, .b = 2};
+[alias] May-aliases after instruction  st_1_t x2 = {.a = 1, .b = 2};  are  <none>
+[alias] analysing instruction: tab_y[0] = & x1;
+[alias] May-aliases after instruction  tab_y[0] = & x1;  are  <none>
+[alias] analysing instruction: tab_y[1] = & x2;
+[alias] May-aliases after instruction  tab_y[1] = & x2;  are  <none>
+[alias] analysing instruction: st_2_t *z1 = malloc(sizeof(st_2_t));
+[alias] May-aliases after instruction  st_2_t *z1 = malloc(sizeof(st_2_t));  are
+  <none>
+[alias] analysing instruction: st_2_t *z2 = malloc(sizeof(st_2_t));
+[alias] May-aliases after instruction  st_2_t *z2 = malloc(sizeof(st_2_t));  are
+  <none>
+[alias] analysing instruction: st_3_t *t = malloc(sizeof(st_3_t));
+[alias] May-aliases after instruction  st_3_t *t = malloc(sizeof(st_3_t));  are
+  <none>
+[alias] analysing instruction: int *a = malloc(sizeof(int));
+[alias] May-aliases after instruction  int *a = malloc(sizeof(int));  are  <none>
+[alias] analysing instruction: int *b = malloc(sizeof(int));
+[alias] May-aliases after instruction  int *b = malloc(sizeof(int));  are  <none>
+[alias] analysing instruction: *a = 0;
+[alias] May-aliases after instruction  *a = 0;  are  <none>
+[alias] analysing instruction: *b = 5;
+[alias] May-aliases after instruction  *b = 5;  are  <none>
+[alias] analysing instruction: z1->s = (struct struct_1_t *)tab_y[0];
+[alias:unsafe-cast] nested1.c:47: Warning: 
+  unsafe cast from st_1_t * to struct struct_1_t *
+[alias] May-aliases after instruction  z1->s = (struct struct_1_t *)tab_y[0];  are
+  {z1->s, tab_y[0]}
+[alias] analysing instruction: z2->s = (struct struct_1_t *)tab_y[1];
+[alias:unsafe-cast] nested1.c:48: Warning: 
+  unsafe cast from st_1_t * to struct struct_1_t *
+[alias] May-aliases after instruction  z2->s = (struct struct_1_t *)tab_y[1];  are
+  {z1->s, z2->s, tab_y[0]}
+[alias] analysing instruction: z1->c = a;
+[alias] May-aliases after instruction  z1->c = a;  are
+  {z1->s, z2->s, tab_y[0]}  {z1->c, a}
+[alias] analysing instruction: z2->c = b;
+[alias] May-aliases after instruction  z2->c = b;  are
+  {z1->s, z2->s, tab_y[0]}  {z1->c, a}  {z2->c, b}
+[alias] analysing instruction: t->t = (struct struct_2_t *)z1;
+[alias:unsafe-cast] nested1.c:51: Warning: 
+  unsafe cast from st_2_t * to struct struct_2_t *
+[alias] May-aliases after instruction  t->t = (struct struct_2_t *)z1;  are
+  {z1->s, z2->s, tab_y[0]}  {t->t, z1}  {z1->c, a}  {z2->c, b}
+[alias] analysing instruction: t->d = a;
+[alias] May-aliases after instruction  t->d = a;  are
+  {z1->s, z2->s, tab_y[0]}  {t->t, z1}  {z1->c, t->d, a}  {z2->c, b}
+[alias] analysing instruction: __retres = 0;
+[alias] May-aliases after instruction  __retres = 0;  are
+  {z1->s, z2->s, tab_y[0]}  {t->t, z1}  {z1->c, t->d, a}  {z2->c, b}
+[alias] May-aliases at the end of function main:
+  {z1->s, z2->s, tab_y[0]}  {t->t, z1}  {z1->c, t->d, a}  {z2->c, b}
+[alias] analysing function: malloc
+[alias] May-aliases at the end of function malloc: ⊥
+[alias] analysing function: mblen
+[alias] May-aliases at the end of function mblen: ⊥
+[alias] analysing function: mbstowcs
+[alias] May-aliases at the end of function mbstowcs: ⊥
+[alias] analysing function: mbtowc
+[alias] May-aliases at the end of function mbtowc: ⊥
+[alias] analysing function: mkstemp
+[alias] May-aliases at the end of function mkstemp: ⊥
+[alias] analysing function: mkstemps
+[alias] May-aliases at the end of function mkstemps: ⊥
+[alias] analysing function: mrand48
+[alias] May-aliases at the end of function mrand48: ⊥
+[alias] analysing function: nrand48
+[alias] May-aliases at the end of function nrand48: ⊥
+[alias] analysing function: posix_memalign
+[alias] May-aliases at the end of function posix_memalign: ⊥
+[alias] analysing function: putenv
+[alias] May-aliases at the end of function putenv: ⊥
+[alias] analysing function: qsort
+[alias] May-aliases at the end of function qsort: ⊥
+[alias] analysing function: quick_exit
+[alias] May-aliases at the end of function quick_exit: ⊥
+[alias] analysing function: rand
+[alias] May-aliases at the end of function rand: ⊥
+[alias] analysing function: random
+[alias] May-aliases at the end of function random: ⊥
+[alias] analysing function: realloc
+[alias] May-aliases at the end of function realloc: ⊥
+[alias] analysing function: reallocarray
+[alias] May-aliases at the end of function reallocarray: ⊥
+[alias] analysing function: seed48
+[alias] May-aliases at the end of function seed48: ⊥
+[alias] analysing function: setenv
+[alias] May-aliases at the end of function setenv: ⊥
+[alias] analysing function: srand
+[alias] May-aliases at the end of function srand: ⊥
+[alias] analysing function: srand48
+[alias] May-aliases at the end of function srand48: ⊥
+[alias] analysing function: srandom
+[alias] May-aliases at the end of function srandom: ⊥
+[alias] analysing function: strtod
+[alias] May-aliases at the end of function strtod: ⊥
+[alias] analysing function: strtof
+[alias] May-aliases at the end of function strtof: ⊥
+[alias] analysing function: strtol
+[alias] May-aliases at the end of function strtol: ⊥
+[alias] analysing function: strtold
+[alias] May-aliases at the end of function strtold: ⊥
+[alias] analysing function: strtoll
+[alias] May-aliases at the end of function strtoll: ⊥
+[alias] analysing function: strtoul
+[alias] May-aliases at the end of function strtoul: ⊥
+[alias] analysing function: strtoull
+[alias] May-aliases at the end of function strtoull: ⊥
+[alias] analysing function: system
+[alias] May-aliases at the end of function system: ⊥
+[alias] analysing function: unsetenv
+[alias] May-aliases at the end of function unsetenv: ⊥
+[alias] analysing function: wcstombs
+[alias] May-aliases at the end of function wcstombs: ⊥
+[alias] analysing function: wctomb
+[alias] May-aliases at the end of function wctomb: ⊥
diff --git a/src/plugins/alias/tests/offsets/oracle/nested2.res.oracle b/src/plugins/alias/tests/offsets/oracle/nested2.res.oracle
new file mode 100644
index 0000000000000000000000000000000000000000..7167c4aebae1c65a02d1333dd738a7c9cccc658c
--- /dev/null
+++ b/src/plugins/alias/tests/offsets/oracle/nested2.res.oracle
@@ -0,0 +1,151 @@
+[kernel] Parsing nested2.c (with preprocessing)
+[alias] analysing function: _Exit
+[alias] May-aliases at the end of function _Exit: ⊥
+[alias] analysing function: abort
+[alias] May-aliases at the end of function abort: ⊥
+[alias] analysing function: abs
+[alias] May-aliases at the end of function abs: ⊥
+[alias] analysing function: at_quick_exit
+[alias] May-aliases at the end of function at_quick_exit: ⊥
+[alias] analysing function: atexit
+[alias] May-aliases at the end of function atexit: ⊥
+[alias] analysing function: atof
+[alias] May-aliases at the end of function atof: ⊥
+[alias] analysing function: atoi
+[alias] May-aliases at the end of function atoi: ⊥
+[alias] analysing function: atol
+[alias] May-aliases at the end of function atol: ⊥
+[alias] analysing function: atoll
+[alias] May-aliases at the end of function atoll: ⊥
+[alias] analysing function: bsearch
+[alias] May-aliases at the end of function bsearch: ⊥
+[alias] analysing function: calloc
+[alias] May-aliases at the end of function calloc: ⊥
+[alias] analysing function: div
+[alias] May-aliases at the end of function div: ⊥
+[alias] analysing function: drand48
+[alias] May-aliases at the end of function drand48: ⊥
+[alias] analysing function: erand48
+[alias] May-aliases at the end of function erand48: ⊥
+[alias] analysing function: exit
+[alias] May-aliases at the end of function exit: ⊥
+[alias] analysing function: free
+[alias] May-aliases at the end of function free: ⊥
+[alias] analysing function: getenv
+[alias] May-aliases at the end of function getenv: ⊥
+[alias] analysing function: jrand48
+[alias] May-aliases at the end of function jrand48: ⊥
+[alias] analysing function: labs
+[alias] May-aliases at the end of function labs: ⊥
+[alias] analysing function: lcong48
+[alias] May-aliases at the end of function lcong48: ⊥
+[alias] analysing function: ldiv
+[alias] May-aliases at the end of function ldiv: ⊥
+[alias] analysing function: llabs
+[alias] May-aliases at the end of function llabs: ⊥
+[alias] analysing function: lldiv
+[alias] May-aliases at the end of function lldiv: ⊥
+[alias] analysing function: lrand48
+[alias] May-aliases at the end of function lrand48: ⊥
+[alias] analysing function: main
+[alias] analysing instruction: st_1_t x1 = {.a = 0, .b = 1};
+[alias] May-aliases after instruction  st_1_t x1 = {.a = 0, .b = 1};  are  <none>
+[alias] analysing instruction: st_1_t x2 = {.a = 2, .b = 3};
+[alias] May-aliases after instruction  st_1_t x2 = {.a = 2, .b = 3};  are  <none>
+[alias] analysing instruction: st_2_t *z1 = malloc(sizeof(st_2_t));
+[alias] May-aliases after instruction  st_2_t *z1 = malloc(sizeof(st_2_t));  are
+  <none>
+[alias] analysing instruction: st_3_t *t = malloc(sizeof(st_3_t));
+[alias] May-aliases after instruction  st_3_t *t = malloc(sizeof(st_3_t));  are
+  <none>
+[alias] analysing instruction: int *a = malloc(sizeof(int));
+[alias] May-aliases after instruction  int *a = malloc(sizeof(int));  are  <none>
+[alias] analysing instruction: *a = 0;
+[alias] May-aliases after instruction  *a = 0;  are  <none>
+[alias] analysing instruction: z1->s[0] = (struct struct_1_t *)(& x1);
+[alias:unsafe-cast] nested2.c:42: Warning: 
+  unsafe cast from st_1_t * to struct struct_1_t *
+[alias] May-aliases after instruction  z1->s[0] = (struct struct_1_t *)(& x1);  are
+  <none>
+[alias] analysing instruction: z1->s[1] = (struct struct_1_t *)(& x2);
+[alias:unsafe-cast] nested2.c:43: Warning: 
+  unsafe cast from st_1_t * to struct struct_1_t *
+[alias] May-aliases after instruction  z1->s[1] = (struct struct_1_t *)(& x2);  are
+  <none>
+[alias] analysing instruction: z1->c = a;
+[alias] May-aliases after instruction  z1->c = a;  are  {z1->c, a}
+[alias] analysing instruction: t->t = (struct struct_2_t *)z1;
+[alias:unsafe-cast] nested2.c:45: Warning: 
+  unsafe cast from st_2_t * to struct struct_2_t *
+[alias] May-aliases after instruction  t->t = (struct struct_2_t *)z1;  are
+  {t->t, z1}  {z1->c, a}
+[alias] analysing instruction: t->d = a;
+[alias] May-aliases after instruction  t->d = a;  are  {t->t, z1}  {z1->c, t->d, a}
+[alias] analysing instruction: __retres = 0;
+[alias] May-aliases after instruction  __retres = 0;  are
+  {t->t, z1}  {z1->c, t->d, a}
+[alias] May-aliases at the end of function main: {t->t, z1}  {z1->c, t->d, a}
+[alias] analysing function: malloc
+[alias] May-aliases at the end of function malloc: ⊥
+[alias] analysing function: mblen
+[alias] May-aliases at the end of function mblen: ⊥
+[alias] analysing function: mbstowcs
+[alias] May-aliases at the end of function mbstowcs: ⊥
+[alias] analysing function: mbtowc
+[alias] May-aliases at the end of function mbtowc: ⊥
+[alias] analysing function: mkstemp
+[alias] May-aliases at the end of function mkstemp: ⊥
+[alias] analysing function: mkstemps
+[alias] May-aliases at the end of function mkstemps: ⊥
+[alias] analysing function: mrand48
+[alias] May-aliases at the end of function mrand48: ⊥
+[alias] analysing function: nrand48
+[alias] May-aliases at the end of function nrand48: ⊥
+[alias] analysing function: posix_memalign
+[alias] May-aliases at the end of function posix_memalign: ⊥
+[alias] analysing function: putenv
+[alias] May-aliases at the end of function putenv: ⊥
+[alias] analysing function: qsort
+[alias] May-aliases at the end of function qsort: ⊥
+[alias] analysing function: quick_exit
+[alias] May-aliases at the end of function quick_exit: ⊥
+[alias] analysing function: rand
+[alias] May-aliases at the end of function rand: ⊥
+[alias] analysing function: random
+[alias] May-aliases at the end of function random: ⊥
+[alias] analysing function: realloc
+[alias] May-aliases at the end of function realloc: ⊥
+[alias] analysing function: reallocarray
+[alias] May-aliases at the end of function reallocarray: ⊥
+[alias] analysing function: seed48
+[alias] May-aliases at the end of function seed48: ⊥
+[alias] analysing function: setenv
+[alias] May-aliases at the end of function setenv: ⊥
+[alias] analysing function: srand
+[alias] May-aliases at the end of function srand: ⊥
+[alias] analysing function: srand48
+[alias] May-aliases at the end of function srand48: ⊥
+[alias] analysing function: srandom
+[alias] May-aliases at the end of function srandom: ⊥
+[alias] analysing function: strtod
+[alias] May-aliases at the end of function strtod: ⊥
+[alias] analysing function: strtof
+[alias] May-aliases at the end of function strtof: ⊥
+[alias] analysing function: strtol
+[alias] May-aliases at the end of function strtol: ⊥
+[alias] analysing function: strtold
+[alias] May-aliases at the end of function strtold: ⊥
+[alias] analysing function: strtoll
+[alias] May-aliases at the end of function strtoll: ⊥
+[alias] analysing function: strtoul
+[alias] May-aliases at the end of function strtoul: ⊥
+[alias] analysing function: strtoull
+[alias] May-aliases at the end of function strtoull: ⊥
+[alias] analysing function: system
+[alias] May-aliases at the end of function system: ⊥
+[alias] analysing function: unsetenv
+[alias] May-aliases at the end of function unsetenv: ⊥
+[alias] analysing function: wcstombs
+[alias] May-aliases at the end of function wcstombs: ⊥
+[alias] analysing function: wctomb
+[alias] May-aliases at the end of function wctomb: ⊥
diff --git a/src/plugins/alias/tests/offsets/oracle/structure1.res.oracle b/src/plugins/alias/tests/offsets/oracle/structure1.res.oracle
new file mode 100644
index 0000000000000000000000000000000000000000..6fab8c1f99d32876d28e448212a5a4a026a7809c
--- /dev/null
+++ b/src/plugins/alias/tests/offsets/oracle/structure1.res.oracle
@@ -0,0 +1,19 @@
+[kernel] Parsing structure1.c (with preprocessing)
+[alias] analysing function: main
+[alias] analysing instruction: st_1_t x = {.a = 0, .b = 1};
+[alias] May-aliases after instruction  st_1_t x = {.a = 0, .b = 1};  are  <none>
+[alias] analysing instruction: st_2_t y = {.a = 3, .c = 4};
+[alias] May-aliases after instruction  st_2_t y = {.a = 3, .c = 4};  are  <none>
+[alias] analysing instruction: st_1_t *p_x = & x;
+[alias] May-aliases after instruction  st_1_t *p_x = & x;  are  <none>
+[alias] analysing instruction: st_2_t *p_y = & y;
+[alias] May-aliases after instruction  st_2_t *p_y = & y;  are  <none>
+[alias] analysing instruction: p_x->a = 3;
+[alias] May-aliases after instruction  p_x->a = 3;  are  <none>
+[alias] analysing instruction: p_x = (st_1_t *)p_y;
+[alias:unsafe-cast] structure1.c:28: Warning: 
+  unsafe cast from st_2_t * to st_1_t *
+[alias] May-aliases after instruction  p_x = (st_1_t *)p_y;  are  {p_x, p_y}
+[alias] analysing instruction: __retres = 0;
+[alias] May-aliases after instruction  __retres = 0;  are  {p_x, p_y}
+[alias] May-aliases at the end of function main: {p_x, p_y}
diff --git a/src/plugins/alias/tests/offsets/oracle/structure2.res.oracle b/src/plugins/alias/tests/offsets/oracle/structure2.res.oracle
new file mode 100644
index 0000000000000000000000000000000000000000..2b2f7ecd4e531f1ec02f3d115396b6b6f0de27d0
--- /dev/null
+++ b/src/plugins/alias/tests/offsets/oracle/structure2.res.oracle
@@ -0,0 +1,19 @@
+[kernel] Parsing structure2.c (with preprocessing)
+[alias] analysing function: main
+[alias] analysing instruction: st_1_t x1 = {.a = 0, .b = 1};
+[alias] May-aliases after instruction  st_1_t x1 = {.a = 0, .b = 1};  are  <none>
+[alias] analysing instruction: st_1_t x2 = {.a = 1, .b = 2};
+[alias] May-aliases after instruction  st_1_t x2 = {.a = 1, .b = 2};  are  <none>
+[alias] analysing instruction: st_2_t y = {.s = (struct struct_1_t *)(& x1), .c = 4};
+[alias:unsafe-cast] structure2.c:21: Warning: 
+  unsafe cast from st_1_t * to struct struct_1_t *
+[alias] May-aliases after instruction
+  st_2_t y = {.s = (struct struct_1_t *)(& x1), .c = 4};  are  <none>
+[alias] analysing instruction: y.s = (struct struct_1_t *)(& x2);
+[alias:unsafe-cast] structure2.c:23: Warning: 
+  unsafe cast from st_1_t * to struct struct_1_t *
+[alias] May-aliases after instruction  y.s = (struct struct_1_t *)(& x2);  are
+  <none>
+[alias] analysing instruction: __retres = 0;
+[alias] May-aliases after instruction  __retres = 0;  are  <none>
+[alias] May-aliases at the end of function main: <none>
diff --git a/src/plugins/alias/tests/offsets/oracle/structure3.res.oracle b/src/plugins/alias/tests/offsets/oracle/structure3.res.oracle
new file mode 100644
index 0000000000000000000000000000000000000000..7ec86d402cb6980ff01296b3901039b234b94464
--- /dev/null
+++ b/src/plugins/alias/tests/offsets/oracle/structure3.res.oracle
@@ -0,0 +1,33 @@
+[kernel] Parsing structure3.c (with preprocessing)
+[alias] analysing function: main
+[alias] analysing instruction: st_1_t x1 = {.a = 0, .b = 1};
+[alias] May-aliases after instruction  st_1_t x1 = {.a = 0, .b = 1};  are  <none>
+[alias] analysing instruction: st_1_t x2 = {.a = 1, .b = 2};
+[alias] May-aliases after instruction  st_1_t x2 = {.a = 1, .b = 2};  are  <none>
+[alias] analysing instruction:
+  st_2_t y1 = {.s = (struct struct_1_t *)(& x1), .c = 3};
+[alias:unsafe-cast] structure3.c:31: Warning: 
+  unsafe cast from st_1_t * to struct struct_1_t *
+[alias] May-aliases after instruction
+  st_2_t y1 = {.s = (struct struct_1_t *)(& x1), .c = 3};  are  <none>
+[alias] analysing instruction:
+  st_2_t y2 = {.s = (struct struct_1_t *)(& x2), .c = 4};
+[alias:unsafe-cast] structure3.c:32: Warning: 
+  unsafe cast from st_1_t * to struct struct_1_t *
+[alias] May-aliases after instruction
+  st_2_t y2 = {.s = (struct struct_1_t *)(& x2), .c = 4};  are  <none>
+[alias] analysing instruction: st_3_t z = {.t = (struct struct_2_t *)(& y1), .d = 5};
+[alias:unsafe-cast] structure3.c:33: Warning: 
+  unsafe cast from st_2_t * to struct struct_2_t *
+[alias] May-aliases after instruction
+  st_3_t z = {.t = (struct struct_2_t *)(& y1), .d = 5};  are  <none>
+[alias] analysing instruction: z.t = (struct struct_2_t *)(& y2);
+[alias:unsafe-cast] structure3.c:35: Warning: 
+  unsafe cast from st_2_t * to struct struct_2_t *
+[alias] May-aliases after instruction  z.t = (struct struct_2_t *)(& y2);  are
+  <none>
+[alias] analysing instruction: y1.c = z.d;
+[alias] May-aliases after instruction  y1.c = z.d;  are  <none>
+[alias] analysing instruction: __retres = 0;
+[alias] May-aliases after instruction  __retres = 0;  are  <none>
+[alias] May-aliases at the end of function main: <none>
diff --git a/src/plugins/alias/tests/offsets/oracle/structure4.res.oracle b/src/plugins/alias/tests/offsets/oracle/structure4.res.oracle
new file mode 100644
index 0000000000000000000000000000000000000000..17d462a32e0c6ec88e3c3c03b6c82ae0b907a465
--- /dev/null
+++ b/src/plugins/alias/tests/offsets/oracle/structure4.res.oracle
@@ -0,0 +1,136 @@
+[kernel] Parsing structure4.c (with preprocessing)
+[alias] analysing function: _Exit
+[alias] May-aliases at the end of function _Exit: ⊥
+[alias] analysing function: abort
+[alias] May-aliases at the end of function abort: ⊥
+[alias] analysing function: abs
+[alias] May-aliases at the end of function abs: ⊥
+[alias] analysing function: at_quick_exit
+[alias] May-aliases at the end of function at_quick_exit: ⊥
+[alias] analysing function: atexit
+[alias] May-aliases at the end of function atexit: ⊥
+[alias] analysing function: atof
+[alias] May-aliases at the end of function atof: ⊥
+[alias] analysing function: atoi
+[alias] May-aliases at the end of function atoi: ⊥
+[alias] analysing function: atol
+[alias] May-aliases at the end of function atol: ⊥
+[alias] analysing function: atoll
+[alias] May-aliases at the end of function atoll: ⊥
+[alias] analysing function: bsearch
+[alias] May-aliases at the end of function bsearch: ⊥
+[alias] analysing function: calloc
+[alias] May-aliases at the end of function calloc: ⊥
+[alias] analysing function: div
+[alias] May-aliases at the end of function div: ⊥
+[alias] analysing function: drand48
+[alias] May-aliases at the end of function drand48: ⊥
+[alias] analysing function: erand48
+[alias] May-aliases at the end of function erand48: ⊥
+[alias] analysing function: exit
+[alias] May-aliases at the end of function exit: ⊥
+[alias] analysing function: free
+[alias] May-aliases at the end of function free: ⊥
+[alias] analysing function: getenv
+[alias] May-aliases at the end of function getenv: ⊥
+[alias] analysing function: jrand48
+[alias] May-aliases at the end of function jrand48: ⊥
+[alias] analysing function: labs
+[alias] May-aliases at the end of function labs: ⊥
+[alias] analysing function: lcong48
+[alias] May-aliases at the end of function lcong48: ⊥
+[alias] analysing function: ldiv
+[alias] May-aliases at the end of function ldiv: ⊥
+[alias] analysing function: llabs
+[alias] May-aliases at the end of function llabs: ⊥
+[alias] analysing function: lldiv
+[alias] May-aliases at the end of function lldiv: ⊥
+[alias] analysing function: lrand48
+[alias] May-aliases at the end of function lrand48: ⊥
+[alias] analysing function: main
+[alias] analysing instruction: st_1_t x1 = {.a = 0, .b = 1};
+[alias] May-aliases after instruction  st_1_t x1 = {.a = 0, .b = 1};  are  <none>
+[alias] analysing instruction: st_1_t x2 = {.a = 1, .b = 2};
+[alias] May-aliases after instruction  st_1_t x2 = {.a = 1, .b = 2};  are  <none>
+[alias] analysing instruction: st_1_t *y1 = malloc(sizeof(st_1_t));
+[alias] May-aliases after instruction  st_1_t *y1 = malloc(sizeof(st_1_t));  are
+  <none>
+[alias] analysing instruction: st_2_t *z = malloc(sizeof(st_2_t));
+[alias] May-aliases after instruction  st_2_t *z = malloc(sizeof(st_2_t));  are
+  <none>
+[alias] analysing instruction: y1 = & x1;
+[alias] May-aliases after instruction  y1 = & x1;  are  <none>
+[alias] analysing instruction: z->s = (struct struct_1_t *)y1;
+[alias:unsafe-cast] structure4.c:37: Warning: 
+  unsafe cast from st_1_t * to struct struct_1_t *
+[alias] May-aliases after instruction  z->s = (struct struct_1_t *)y1;  are
+  {z->s, y1}
+[alias] analysing instruction: z->c = 6;
+[alias] May-aliases after instruction  z->c = 6;  are  {z->s, y1}
+[alias] analysing instruction: __retres = 0;
+[alias] May-aliases after instruction  __retres = 0;  are  {z->s, y1}
+[alias] May-aliases at the end of function main: {z->s, y1}
+[alias] analysing function: malloc
+[alias] May-aliases at the end of function malloc: ⊥
+[alias] analysing function: mblen
+[alias] May-aliases at the end of function mblen: ⊥
+[alias] analysing function: mbstowcs
+[alias] May-aliases at the end of function mbstowcs: ⊥
+[alias] analysing function: mbtowc
+[alias] May-aliases at the end of function mbtowc: ⊥
+[alias] analysing function: mkstemp
+[alias] May-aliases at the end of function mkstemp: ⊥
+[alias] analysing function: mkstemps
+[alias] May-aliases at the end of function mkstemps: ⊥
+[alias] analysing function: mrand48
+[alias] May-aliases at the end of function mrand48: ⊥
+[alias] analysing function: nrand48
+[alias] May-aliases at the end of function nrand48: ⊥
+[alias] analysing function: posix_memalign
+[alias] May-aliases at the end of function posix_memalign: ⊥
+[alias] analysing function: putenv
+[alias] May-aliases at the end of function putenv: ⊥
+[alias] analysing function: qsort
+[alias] May-aliases at the end of function qsort: ⊥
+[alias] analysing function: quick_exit
+[alias] May-aliases at the end of function quick_exit: ⊥
+[alias] analysing function: rand
+[alias] May-aliases at the end of function rand: ⊥
+[alias] analysing function: random
+[alias] May-aliases at the end of function random: ⊥
+[alias] analysing function: realloc
+[alias] May-aliases at the end of function realloc: ⊥
+[alias] analysing function: reallocarray
+[alias] May-aliases at the end of function reallocarray: ⊥
+[alias] analysing function: seed48
+[alias] May-aliases at the end of function seed48: ⊥
+[alias] analysing function: setenv
+[alias] May-aliases at the end of function setenv: ⊥
+[alias] analysing function: srand
+[alias] May-aliases at the end of function srand: ⊥
+[alias] analysing function: srand48
+[alias] May-aliases at the end of function srand48: ⊥
+[alias] analysing function: srandom
+[alias] May-aliases at the end of function srandom: ⊥
+[alias] analysing function: strtod
+[alias] May-aliases at the end of function strtod: ⊥
+[alias] analysing function: strtof
+[alias] May-aliases at the end of function strtof: ⊥
+[alias] analysing function: strtol
+[alias] May-aliases at the end of function strtol: ⊥
+[alias] analysing function: strtold
+[alias] May-aliases at the end of function strtold: ⊥
+[alias] analysing function: strtoll
+[alias] May-aliases at the end of function strtoll: ⊥
+[alias] analysing function: strtoul
+[alias] May-aliases at the end of function strtoul: ⊥
+[alias] analysing function: strtoull
+[alias] May-aliases at the end of function strtoull: ⊥
+[alias] analysing function: system
+[alias] May-aliases at the end of function system: ⊥
+[alias] analysing function: unsetenv
+[alias] May-aliases at the end of function unsetenv: ⊥
+[alias] analysing function: wcstombs
+[alias] May-aliases at the end of function wcstombs: ⊥
+[alias] analysing function: wctomb
+[alias] May-aliases at the end of function wctomb: ⊥
diff --git a/src/plugins/alias/tests/offsets/oracle/structure5.res.oracle b/src/plugins/alias/tests/offsets/oracle/structure5.res.oracle
new file mode 100644
index 0000000000000000000000000000000000000000..6ab3b8478904bba3396ee4bf1314b90cb372fb45
--- /dev/null
+++ b/src/plugins/alias/tests/offsets/oracle/structure5.res.oracle
@@ -0,0 +1,153 @@
+[kernel] Parsing structure5.c (with preprocessing)
+[alias] analysing function: _Exit
+[alias] May-aliases at the end of function _Exit: ⊥
+[alias] analysing function: abort
+[alias] May-aliases at the end of function abort: ⊥
+[alias] analysing function: abs
+[alias] May-aliases at the end of function abs: ⊥
+[alias] analysing function: at_quick_exit
+[alias] May-aliases at the end of function at_quick_exit: ⊥
+[alias] analysing function: atexit
+[alias] May-aliases at the end of function atexit: ⊥
+[alias] analysing function: atof
+[alias] May-aliases at the end of function atof: ⊥
+[alias] analysing function: atoi
+[alias] May-aliases at the end of function atoi: ⊥
+[alias] analysing function: atol
+[alias] May-aliases at the end of function atol: ⊥
+[alias] analysing function: atoll
+[alias] May-aliases at the end of function atoll: ⊥
+[alias] analysing function: bsearch
+[alias] May-aliases at the end of function bsearch: ⊥
+[alias] analysing function: calloc
+[alias] May-aliases at the end of function calloc: ⊥
+[alias] analysing function: div
+[alias] May-aliases at the end of function div: ⊥
+[alias] analysing function: drand48
+[alias] May-aliases at the end of function drand48: ⊥
+[alias] analysing function: erand48
+[alias] May-aliases at the end of function erand48: ⊥
+[alias] analysing function: exit
+[alias] May-aliases at the end of function exit: ⊥
+[alias] analysing function: free
+[alias] May-aliases at the end of function free: ⊥
+[alias] analysing function: getenv
+[alias] May-aliases at the end of function getenv: ⊥
+[alias] analysing function: jrand48
+[alias] May-aliases at the end of function jrand48: ⊥
+[alias] analysing function: labs
+[alias] May-aliases at the end of function labs: ⊥
+[alias] analysing function: lcong48
+[alias] May-aliases at the end of function lcong48: ⊥
+[alias] analysing function: ldiv
+[alias] May-aliases at the end of function ldiv: ⊥
+[alias] analysing function: llabs
+[alias] May-aliases at the end of function llabs: ⊥
+[alias] analysing function: lldiv
+[alias] May-aliases at the end of function lldiv: ⊥
+[alias] analysing function: lrand48
+[alias] May-aliases at the end of function lrand48: ⊥
+[alias] analysing function: main
+[alias] analysing instruction: st_1_t x1 = {.a = 0, .b = 1};
+[alias] May-aliases after instruction  st_1_t x1 = {.a = 0, .b = 1};  are  <none>
+[alias] analysing instruction: st_1_t x2 = {.a = 1, .b = 2};
+[alias] May-aliases after instruction  st_1_t x2 = {.a = 1, .b = 2};  are  <none>
+[alias] analysing instruction: st_1_t *y1 = malloc(sizeof(st_1_t));
+[alias] May-aliases after instruction  st_1_t *y1 = malloc(sizeof(st_1_t));  are
+  <none>
+[alias] analysing instruction: st_2_t *z = malloc(sizeof(st_2_t));
+[alias] May-aliases after instruction  st_2_t *z = malloc(sizeof(st_2_t));  are
+  <none>
+[alias] analysing instruction: st_3_t *t = malloc(sizeof(st_3_t));
+[alias] May-aliases after instruction  st_3_t *t = malloc(sizeof(st_3_t));  are
+  <none>
+[alias] analysing instruction: int *a = malloc(sizeof(int));
+[alias] May-aliases after instruction  int *a = malloc(sizeof(int));  are  <none>
+[alias] analysing instruction: *a = 0;
+[alias] May-aliases after instruction  *a = 0;  are  <none>
+[alias] analysing instruction: y1 = & x1;
+[alias] May-aliases after instruction  y1 = & x1;  are  <none>
+[alias] analysing instruction: z->s = (struct struct_1_t *)y1;
+[alias:unsafe-cast] structure5.c:41: Warning: 
+  unsafe cast from st_1_t * to struct struct_1_t *
+[alias] May-aliases after instruction  z->s = (struct struct_1_t *)y1;  are
+  {z->s, y1}
+[alias] analysing instruction: z->c = a;
+[alias] May-aliases after instruction  z->c = a;  are  {z->s, y1}  {z->c, a}
+[alias] analysing instruction: t->t = (struct struct_2_t *)z;
+[alias:unsafe-cast] structure5.c:43: Warning: 
+  unsafe cast from st_2_t * to struct struct_2_t *
+[alias] May-aliases after instruction  t->t = (struct struct_2_t *)z;  are
+  {z->s, y1}  {t->t, z}  {z->c, a}
+[alias] analysing instruction: t->d = a;
+[alias] May-aliases after instruction  t->d = a;  are
+  {z->s, y1}  {t->t, z}  {z->c, t->d, a}
+[alias] analysing instruction: __retres = 0;
+[alias] May-aliases after instruction  __retres = 0;  are
+  {z->s, y1}  {t->t, z}  {z->c, t->d, a}
+[alias] May-aliases at the end of function main:
+  {z->s, y1}  {t->t, z}  {z->c, t->d, a}
+[alias] analysing function: malloc
+[alias] May-aliases at the end of function malloc: ⊥
+[alias] analysing function: mblen
+[alias] May-aliases at the end of function mblen: ⊥
+[alias] analysing function: mbstowcs
+[alias] May-aliases at the end of function mbstowcs: ⊥
+[alias] analysing function: mbtowc
+[alias] May-aliases at the end of function mbtowc: ⊥
+[alias] analysing function: mkstemp
+[alias] May-aliases at the end of function mkstemp: ⊥
+[alias] analysing function: mkstemps
+[alias] May-aliases at the end of function mkstemps: ⊥
+[alias] analysing function: mrand48
+[alias] May-aliases at the end of function mrand48: ⊥
+[alias] analysing function: nrand48
+[alias] May-aliases at the end of function nrand48: ⊥
+[alias] analysing function: posix_memalign
+[alias] May-aliases at the end of function posix_memalign: ⊥
+[alias] analysing function: putenv
+[alias] May-aliases at the end of function putenv: ⊥
+[alias] analysing function: qsort
+[alias] May-aliases at the end of function qsort: ⊥
+[alias] analysing function: quick_exit
+[alias] May-aliases at the end of function quick_exit: ⊥
+[alias] analysing function: rand
+[alias] May-aliases at the end of function rand: ⊥
+[alias] analysing function: random
+[alias] May-aliases at the end of function random: ⊥
+[alias] analysing function: realloc
+[alias] May-aliases at the end of function realloc: ⊥
+[alias] analysing function: reallocarray
+[alias] May-aliases at the end of function reallocarray: ⊥
+[alias] analysing function: seed48
+[alias] May-aliases at the end of function seed48: ⊥
+[alias] analysing function: setenv
+[alias] May-aliases at the end of function setenv: ⊥
+[alias] analysing function: srand
+[alias] May-aliases at the end of function srand: ⊥
+[alias] analysing function: srand48
+[alias] May-aliases at the end of function srand48: ⊥
+[alias] analysing function: srandom
+[alias] May-aliases at the end of function srandom: ⊥
+[alias] analysing function: strtod
+[alias] May-aliases at the end of function strtod: ⊥
+[alias] analysing function: strtof
+[alias] May-aliases at the end of function strtof: ⊥
+[alias] analysing function: strtol
+[alias] May-aliases at the end of function strtol: ⊥
+[alias] analysing function: strtold
+[alias] May-aliases at the end of function strtold: ⊥
+[alias] analysing function: strtoll
+[alias] May-aliases at the end of function strtoll: ⊥
+[alias] analysing function: strtoul
+[alias] May-aliases at the end of function strtoul: ⊥
+[alias] analysing function: strtoull
+[alias] May-aliases at the end of function strtoull: ⊥
+[alias] analysing function: system
+[alias] May-aliases at the end of function system: ⊥
+[alias] analysing function: unsetenv
+[alias] May-aliases at the end of function unsetenv: ⊥
+[alias] analysing function: wcstombs
+[alias] May-aliases at the end of function wcstombs: ⊥
+[alias] analysing function: wctomb
+[alias] May-aliases at the end of function wctomb: ⊥
diff --git a/src/plugins/alias/tests/offsets/structure1.c b/src/plugins/alias/tests/offsets/structure1.c
new file mode 100644
index 0000000000000000000000000000000000000000..95cf272878359073767764d7340b0546eb21f65c
--- /dev/null
+++ b/src/plugins/alias/tests/offsets/structure1.c
@@ -0,0 +1,30 @@
+// simple structure
+//  {p_x, p_y} are aliased
+
+
+typedef struct
+{       
+    int   a;
+    int   b;
+} st_1_t;
+
+typedef struct
+{       
+    int   a;
+    int   c;
+} st_2_t;
+
+
+int main () {
+
+  st_1_t x = {0,1};
+  st_2_t y = {3,4};
+
+  st_1_t * p_x = &x;
+  st_2_t * p_y = &y;
+
+  
+  p_x->a = 3;
+  p_x = p_y; 
+  return 0;
+}
diff --git a/src/plugins/alias/tests/offsets/structure2.c b/src/plugins/alias/tests/offsets/structure2.c
new file mode 100644
index 0000000000000000000000000000000000000000..92ff3a41783f5e35b94622b1ebe1553946938e7a
--- /dev/null
+++ b/src/plugins/alias/tests/offsets/structure2.c
@@ -0,0 +1,26 @@
+// structure with initialisation and pointer
+//  no alias
+
+typedef struct
+{       
+    int   a;
+    int   b;
+} st_1_t;
+
+typedef struct
+{       
+    struct struct_1_t*  s;
+    int   c;
+} st_2_t;
+
+
+int main () {
+
+  st_1_t x1 = {0,1};
+  st_1_t x2 = {1,2};
+  st_2_t y = {&x1,4};
+
+  y.s = &x2;
+
+  return 0;
+}
diff --git a/src/plugins/alias/tests/offsets/structure3.c b/src/plugins/alias/tests/offsets/structure3.c
new file mode 100644
index 0000000000000000000000000000000000000000..9582ccd3f86dfe6b9b186213836c29aee37a600f
--- /dev/null
+++ b/src/plugins/alias/tests/offsets/structure3.c
@@ -0,0 +1,39 @@
+// double structure with initialisation and pointer
+//  no alias
+
+typedef struct
+{       
+    int   a;
+    int   b;
+} st_1_t;
+
+typedef struct
+{       
+    struct struct_1_t*  s;
+    int   c;
+} st_2_t;
+
+
+typedef struct
+{       
+    struct struct_2_t*  t;
+    int   d;
+} st_3_t;
+
+
+
+
+
+int main () {
+
+  st_1_t x1 = {0,1};
+  st_1_t x2 = {1,2};
+  st_2_t y1 = {&x1,3};
+  st_2_t y2 = {&x2,4};
+  st_3_t z = {&y1,5};
+  
+  z.t = &y2;
+  y1.c = z.d;
+
+  return 0;
+}
diff --git a/src/plugins/alias/tests/offsets/structure4.c b/src/plugins/alias/tests/offsets/structure4.c
new file mode 100644
index 0000000000000000000000000000000000000000..c33bce757fec2a73fa1a55d075081c9955fa14a7
--- /dev/null
+++ b/src/plugins/alias/tests/offsets/structure4.c
@@ -0,0 +1,41 @@
+// structure with malloc
+//  {z->s, y1} are aliased
+
+#include <stdlib.h>
+
+typedef struct
+{       
+    int   a;
+    int   b;
+} st_1_t;
+
+typedef struct
+{       
+    struct struct_1_t*  s;
+    int   c;
+} st_2_t;
+
+
+typedef struct
+{       
+    struct struct_2_t*  t;
+    int   d;
+} st_3_t;
+
+
+
+
+
+int main () {
+
+  st_1_t x1 = {0,1};
+  st_1_t x2 = {1,2};
+  st_1_t *y1 = malloc(sizeof(st_1_t));
+  st_2_t *z = malloc(sizeof(st_2_t));
+
+  y1 = &x1;
+  z->s = y1;
+  z->c = 6;
+
+  return 0;
+}
diff --git a/src/plugins/alias/tests/offsets/structure5.c b/src/plugins/alias/tests/offsets/structure5.c
new file mode 100644
index 0000000000000000000000000000000000000000..eeeefafd63d3518a65fbc88f0f96bb456104f94d
--- /dev/null
+++ b/src/plugins/alias/tests/offsets/structure5.c
@@ -0,0 +1,48 @@
+// another structure, more complex
+//  {z->s, y1} are aliased
+//  {t->t, z} are aliased
+//  {z->c, t->d, a} are aliased
+
+
+#include <stdlib.h>
+
+typedef struct
+{       
+    int   a;
+    int   b;
+} st_1_t;
+
+typedef struct
+{       
+    struct struct_1_t*  s;
+    int*   c;
+} st_2_t;
+
+
+typedef struct
+{       
+    struct struct_2_t*  t;
+    int*   d;
+} st_3_t;
+
+
+
+int main () {
+
+  st_1_t x1 = {0,1};
+  st_1_t x2 = {1,2};
+  st_1_t *y1 = malloc(sizeof(st_1_t));
+  st_2_t *z = malloc(sizeof(st_2_t));
+  st_3_t *t = malloc(sizeof(st_3_t));
+  int* a = malloc(sizeof(int));
+  
+  *a = 0;
+  y1 = &x1;
+  z->s = y1;
+  z->c = a;
+  t->t = z;
+  t->d = a;
+  
+
+  return 0;
+}
diff --git a/src/plugins/alias/tests/ptests_config b/src/plugins/alias/tests/ptests_config
new file mode 100644
index 0000000000000000000000000000000000000000..364f24e63e59237f7800393fbdf9829fc9330471
--- /dev/null
+++ b/src/plugins/alias/tests/ptests_config
@@ -0,0 +1 @@
+DEFAULT_SUITES=basic real_world offsets fixed_bugs
diff --git a/src/plugins/alias/tests/real_world/example1.c b/src/plugins/alias/tests/real_world/example1.c
new file mode 100644
index 0000000000000000000000000000000000000000..a3709a6736725db096563ff80de05329276ef3aa
--- /dev/null
+++ b/src/plugins/alias/tests/real_world/example1.c
@@ -0,0 +1,108 @@
+// real world example
+//  {a->t1[0], b->t1[0]} are aliased
+//  {a->t2[0], b->t2[0]} are aliased
+//  {a->n1, b->n1} are aliased
+//  {a->n2, b->n2} are aliased
+
+
+#include <stdlib.h>
+#include <math.h>
+
+typedef struct {
+  double *t1[2];
+  double *t2[2];
+  int *n1;
+  int *n2;
+} ty;
+
+void swap(int *n)
+{
+  if ((*n) == 1) {
+    (*n) = 0;
+  }
+  else {
+    (*n)++;
+  }
+}
+
+
+void *f1(ty *x)
+{
+  ty *tmp = x;
+  double *idata;
+  double *odata;
+  int idx;
+
+  idata = (double *)malloc(10 * sizeof(double));
+
+  while (1) {
+
+    idata = tmp->t2[*tmp->n2];
+
+    odata = tmp->t1[*tmp->n1];
+
+    for (idx = 0; idx < 10; idx++) {
+      odata[idx] = 0.5*sin(idata[idx]);
+    }
+    swap(tmp->n1);
+  }
+  return (void *) NULL;
+}
+
+
+void *f2(ty *x)
+{
+  ty *tmp = x;
+  int idx;
+  double *idata;
+  double *odata;
+
+  idata = (double*)malloc(10* sizeof(double));
+
+  while (1) {
+
+    idata = tmp->t1[*tmp->n1];
+
+    odata = tmp->t2[*tmp->n2];
+
+    for (idx = 0; idx < 10; idx++) {
+          odata[idx] = 3*idata[idx] + 1;
+    }
+    swap(tmp->n2);
+  }
+
+  return (void *) NULL;
+}
+
+
+int main(void)
+{
+  ty *a;
+  ty *b;
+
+  a = (ty *)malloc(sizeof(ty));
+  b = (ty *)malloc(sizeof(ty));
+
+  int i;
+  for (i = 0; i < 2; i++) {
+      a->t1[i] = (double *)malloc(10 * sizeof(double));
+      a->t2[i] = (double *)malloc(10 * sizeof(double));
+  }
+
+  a->n1 = (int *)malloc(sizeof(int));
+  a->n2 = (int *)malloc(sizeof(int));
+  *a->n1 = 1;
+  *a->n2 = 1;
+
+  for (i = 0; i < 2; i++) {
+    b->t1[i] = a->t1[i];
+    b->t2[i] = a->t2[i];
+  }
+  b->n1 = a->n1;
+  b->n2 = a->n2;
+
+  f1(a);
+  f2(b);
+
+  return 0;
+}
diff --git a/src/plugins/alias/tests/real_world/example2.c b/src/plugins/alias/tests/real_world/example2.c
new file mode 100644
index 0000000000000000000000000000000000000000..18e08504e7c44a69853a32bf94ed52404942a5ec
--- /dev/null
+++ b/src/plugins/alias/tests/real_world/example2.c
@@ -0,0 +1,108 @@
+// real world example
+//  {a->t1[0], b->t1[0]} are aliased
+//  {a->t2[0], b->t2[0]} are aliased
+//  {a->n1, b->n1} are aliased
+//  {a->n2, b->n2} are aliased
+
+
+#include <stdlib.h>
+#include <math.h>
+
+typedef struct {
+  double *t1[2];
+  double *t2[2];
+  int *n1;
+  int *n2;
+} ty;
+
+void swap(int *n)
+{
+  if ((*n) == 1) {
+    (*n) = 0;
+  }
+  else {
+    (*n)++;
+  }
+}
+
+
+void *f1(ty *x)
+{
+  ty *tmp = x;
+  double *idata;
+  double *odata;
+  int idx;
+
+  idata = (double *)malloc(10 * sizeof(double));
+
+  for (int i = 0; i < 2; i++) {
+
+    idata = tmp->t2[*tmp->n2];
+
+    odata = tmp->t1[*tmp->n1];
+
+    for (idx = 0; idx < 10; idx++) {
+      odata[idx] = 0.5*sin(idata[idx]);
+    }
+    swap(tmp->n1);
+  }
+  return (void *) NULL;
+}
+
+
+void *f2(ty *x)
+{
+  ty *tmp = x;
+  int idx;
+  double *idata;
+  double *odata;
+
+  idata = (double*)malloc(10* sizeof(double));
+
+  for (int i = 0; i < 2; i++) {
+
+    idata = tmp->t1[*tmp->n1];
+
+    odata = tmp->t2[*tmp->n2];
+
+    for (idx = 0; idx < 10; idx++) {
+          odata[idx] = 3*idata[idx] + 1;
+    }
+    swap(tmp->n2);
+  }
+
+  return (void *) NULL;
+}
+
+
+int main(void)
+{
+  ty *a;
+  ty *b;
+
+  a = (ty *)malloc(sizeof(ty));
+  b = (ty *)malloc(sizeof(ty));
+
+  int i;
+  for (i = 0; i < 2; i++) {
+      a->t1[i] = (double *)malloc(10 * sizeof(double));
+      a->t2[i] = (double *)malloc(10 * sizeof(double));
+  }
+
+  a->n1 = (int *)malloc(sizeof(int));
+  a->n2 = (int *)malloc(sizeof(int));
+  *a->n1 = 1;
+  *a->n2 = 1;
+
+  for (i = 0; i < 2; i++) {
+    b->t1[i] = a->t1[i];
+    b->t2[i] = a->t2[i];
+  }
+  b->n1 = a->n1;
+  b->n2 = a->n2;
+
+  f1(a);
+  f2(b);
+
+  return 0;
+}
diff --git a/src/plugins/alias/tests/real_world/function1_v2.c b/src/plugins/alias/tests/real_world/function1_v2.c
new file mode 100644
index 0000000000000000000000000000000000000000..3187998b7574e374a2a14dfa89ff10f8f6342763
--- /dev/null
+++ b/src/plugins/alias/tests/real_world/function1_v2.c
@@ -0,0 +1,26 @@
+// function with no return
+//  {a, b} are aliased
+//  {c, d} are aliased
+//#include <stdio.h>
+#include <stdlib.h>
+
+void alias(int **x, int **y) {
+  *x = *y;
+}
+
+
+int main(void)
+{
+  int *a = malloc(sizeof(int));
+  *a = 0;
+  int *b = malloc(sizeof(int));;
+  *b = 42;
+  
+  alias(&a,&b);
+
+  *a = 7;
+  //printf("a = %d && b = %d\n",*a,*b);
+
+
+  return 0;
+}
diff --git a/src/plugins/alias/tests/real_world/oracle/example1.res.old b/src/plugins/alias/tests/real_world/oracle/example1.res.old
new file mode 100644
index 0000000000000000000000000000000000000000..97708d154b7fc3fc196c5926743747fe2f6276d9
--- /dev/null
+++ b/src/plugins/alias/tests/real_world/oracle/example1.res.old
@@ -0,0 +1,403 @@
+[kernel] Parsing example1.c (with preprocessing)
+[alias] Parsing done
+[alias] Skipping assignment idata = tmp->t2[*(tmp->n2)] (not implemented)
+[alias] Skipping assignment odata = tmp->t1[*(tmp->n1)] (not implemented)
+[alias] In a function call, parameter (x <- *(idata + idx)) is ignored)
+[alias] Warning: a function with no return is employed in an assignment
+[alias] Skipping assignment *(odata + idx) = 0.5 * tmp_1 (BUG do_assignment 2)
+[alias] In a function call, parameter (x <- *(idata + idx)) is ignored)
+[alias] Warning: a function with no return is employed in an assignment
+[alias] Skipping assignment *(odata + idx) = 0.5 * tmp_1 (BUG do_assignment 2)
+[alias] Skipping assignment idata = tmp->t2[*(tmp->n2)] (not implemented)
+[alias] Skipping assignment odata = tmp->t1[*(tmp->n1)] (not implemented)
+[alias] Warning: DEBUG return stmt of f1 not in table
+[alias] Warning: Analysis is continuing but will not be sound
+[alias] Skipping assignment idata = tmp->t1[*(tmp->n1)] (not implemented)
+[alias] Skipping assignment odata = tmp->t2[*(tmp->n2)] (not implemented)
+[alias] Skipping assignment *(odata + idx) = (double)3 * *(idata + idx) + (double)1 (BUG do_assignment 2)
+[alias] Skipping assignment *(odata + idx) = (double)3 * *(idata + idx) + (double)1 (BUG do_assignment 2)
+[alias] Skipping assignment idata = tmp->t1[*(tmp->n1)] (not implemented)
+[alias] Skipping assignment odata = tmp->t2[*(tmp->n2)] (not implemented)
+[alias] Warning: DEBUG return stmt of f2 not in table
+[alias] Warning: Analysis is continuing but will not be sound
+[alias] Skipping assignment a->t1[i] = malloc() (not implemented)
+[alias] Skipping assignment a->t2[i] = malloc() (not implemented)
+[alias] Skipping assignment a->t1[i] = malloc() (not implemented)
+[alias] Skipping assignment a->t2[i] = malloc() (not implemented)
+[alias] Skipping assignment a->n1 = malloc() (not implemented)
+[alias] Skipping assignment a->n2 = malloc() (not implemented)
+[alias] May-aliases at the end of function main:
+  <list of may-alias>
+  {b.n1; b; } are aliased
+  {b.n1; b.n2; b; } are aliased
+  {*a; *b.t1[i]; *b.t2[i]; *b.n1; *b.n2; *b; } are aliased
+  <end of list>
+[alias] Functions done
+Before statement b->t1[i] = a->t1[i]; :
+ <list of may-alias>
+{*a; *b.t1[i]; *b.t2[i]; } are aliased
+<end of list>
+
+Before statement idx = 0; :
+ <list of may-alias>
+{x; tmp; } are aliased
+<end of list>
+
+Before statement b->t2[i] = a->t2[i]; :
+ <list of may-alias>
+{*a; *b.t1[i]; *b.t2[i]; } are aliased
+<end of list>
+
+Before statement while (idx < 10) {
+                   *(odata + idx) = (double)3 * *(idata + idx) + (double)1;
+                   idx ++;
+                 } :
+ <list of may-alias>
+{x; tmp; } are aliased
+<end of list>
+
+Before statement if (*n == 1) *n = 0; else (*n) ++; :
+ <list of may-alias>
+<end of list>
+
+Before statement i ++; :
+ <list of may-alias>
+{*a; *b.t1[i]; *b.t2[i]; } are aliased
+<end of list>
+
+Before statement if (*n == 1) *n = 0; else (*n) ++; :
+ <list of may-alias>
+<end of list>
+
+Before statement b->n1 = a->n1; :
+ <list of may-alias>
+{*a; *b.t1[i]; *b.t2[i]; } are aliased
+<end of list>
+
+Before statement if (! (idx < 10)) break; :
+ <list of may-alias>
+{x; tmp; } are aliased
+<end of list>
+
+Before statement *n = 0; :
+ <list of may-alias>
+<end of list>
+
+Before statement b->n2 = a->n2; :
+ <list of may-alias>
+{*a; *b.t1[i]; *b.t2[i]; *b.n1; *b; } are aliased
+{b.n1; b; } are aliased
+<end of list>
+
+Before statement break; :
+ <list of may-alias>
+{x; tmp; } are aliased
+<end of list>
+
+Before statement (*n) ++; :
+ <list of may-alias>
+<end of list>
+
+Before statement f1(a); :
+ <list of may-alias>
+{*a; *b.t1[i]; *b.t2[i]; *b.n1; *b.n2; *b; } are aliased
+{b.n1; b; } are aliased
+{b.n1; b.n2; b; } are aliased
+<end of list>
+
+Before statement *(odata + idx) = (double)3 * *(idata + idx) + (double)1; :
+ <list of may-alias>
+{x; tmp; } are aliased
+<end of list>
+
+Before statement f2(b); :
+ <list of may-alias>
+{b.n1; b; } are aliased
+{b.n1; b.n2; b; } are aliased
+{*a; *b.t1[i]; *b.t2[i]; *b.n1; *b.n2; *b; } are aliased
+<end of list>
+
+Before statement *(odata + idx) = (double)3 * *(idata + idx) + (double)1; :
+ <list of may-alias>
+{x; tmp; } are aliased
+<end of list>
+
+Before statement __retres = 0; :
+ <list of may-alias>
+{b.n1; b; } are aliased
+{b.n1; b.n2; b; } are aliased
+{*a; *b.t1[i]; *b.t2[i]; *b.n1; *b.n2; *b; } are aliased
+<end of list>
+
+Before statement idx ++; :
+ <list of may-alias>
+{x; tmp; } are aliased
+<end of list>
+
+Before statement ty *tmp = x; :
+ <list of may-alias>
+<end of list>
+
+Before statement swap(tmp->n2); :
+ <list of may-alias>
+{x; tmp; } are aliased
+<end of list>
+
+Before statement idata = (double *)malloc((unsigned long)10 * sizeof(double)); :
+ <list of may-alias>
+{x; tmp; } are aliased
+<end of list>
+
+Before statement return; :
+ <list of may-alias>
+<end of list>
+
+Before statement while (1) {
+                   idata = tmp->t2[*(tmp->n2)];
+                   odata = tmp->t1[*(tmp->n1)];
+                   idx = 0;
+                   while (idx < 10) {
+                     {
+                       double tmp_1;
+                       tmp_1 = sin(*(idata + idx));
+                       *(odata + idx) = 0.5 * tmp_1;
+                     }
+                     idx ++;
+                   }
+                   swap(tmp->n1);
+                 } :
+ <list of may-alias>
+{x; tmp; } are aliased
+<end of list>
+
+Before statement idata = tmp->t2[*(tmp->n2)];
+                 odata = tmp->t1[*(tmp->n1)];
+                 idx = 0;
+                 while (idx < 10) {
+                   {
+                     double tmp_1;
+                     tmp_1 = sin(*(idata + idx));
+                     *(odata + idx) = 0.5 * tmp_1;
+                   }
+                   idx ++;
+                 }
+                 swap(tmp->n1); :
+ <list of may-alias>
+{x; tmp; } are aliased
+<end of list>
+
+Before statement a = (ty *)malloc(sizeof(ty)); :
+ <list of may-alias>
+<end of list>
+
+Before statement idata = tmp->t2[*(tmp->n2)]; :
+ <list of may-alias>
+{x; tmp; } are aliased
+<end of list>
+
+Before statement b = (ty *)malloc(sizeof(ty)); :
+ <list of may-alias>
+<end of list>
+
+Before statement odata = tmp->t1[*(tmp->n1)]; :
+ <list of may-alias>
+{x; tmp; } are aliased
+<end of list>
+
+Before statement i = 0; :
+ <list of may-alias>
+<end of list>
+
+Before statement idx = 0; :
+ <list of may-alias>
+{x; tmp; } are aliased
+<end of list>
+
+Before statement while (i < 2) {
+                   a->t1[i] = (double *)malloc((unsigned long)10 * sizeof(double));
+                   a->t2[i] = (double *)malloc((unsigned long)10 * sizeof(double));
+                   i ++;
+                 } :
+ <list of may-alias>
+<end of list>
+
+Before statement while (idx < 10) {
+                   {
+                     double tmp_1;
+                     tmp_1 = sin(*(idata + idx));
+                     *(odata + idx) = 0.5 * tmp_1;
+                   }
+                   idx ++;
+                 } :
+ <list of may-alias>
+{x; tmp; } are aliased
+<end of list>
+
+Before statement return __retres; :
+ <list of may-alias>
+{b.n1; b; } are aliased
+{b.n1; b.n2; b; } are aliased
+{*a; *b.t1[i]; *b.t2[i]; *b.n1; *b.n2; *b; } are aliased
+<end of list>
+
+Before statement if (! (i < 2)) break; :
+ <list of may-alias>
+<end of list>
+
+Before statement if (! (idx < 10)) break; :
+ <list of may-alias>
+{x; tmp; } are aliased
+<end of list>
+
+Before statement break; :
+ <list of may-alias>
+<end of list>
+
+Before statement break; :
+ <list of may-alias>
+{x; tmp; } are aliased
+<end of list>
+
+Before statement a->t1[i] = (double *)malloc((unsigned long)10 * sizeof(double));
+                 a->t2[i] = (double *)malloc((unsigned long)10 * sizeof(double)); :
+ <list of may-alias>
+<end of list>
+
+Before statement {
+                   double tmp_1;
+                   tmp_1 = sin(*(idata + idx));
+                   *(odata + idx) = 0.5 * tmp_1;
+                 } :
+ <list of may-alias>
+{x; tmp; } are aliased
+<end of list>
+
+Before statement a->t1[i] = (double *)malloc((unsigned long)10 * sizeof(double)); :
+ <list of may-alias>
+<end of list>
+
+Before statement tmp_1 = sin(*(idata + idx));
+                 *(odata + idx) = 0.5 * tmp_1; :
+ <list of may-alias>
+{x; tmp; } are aliased
+<end of list>
+
+Before statement a->t2[i] = (double *)malloc((unsigned long)10 * sizeof(double)); :
+ <list of may-alias>
+<end of list>
+
+Before statement tmp_1 = sin(*(idata + idx)); :
+ <list of may-alias>
+{x; tmp; } are aliased
+<end of list>
+
+Before statement i ++; :
+ <list of may-alias>
+<end of list>
+
+Before statement *(odata + idx) = 0.5 * tmp_1; :
+ <list of may-alias>
+{x; tmp; } are aliased
+<end of list>
+
+Before statement a->n1 = (int *)malloc(sizeof(int)); :
+ <list of may-alias>
+<end of list>
+
+Before statement idx ++; :
+ <list of may-alias>
+{x; tmp; } are aliased
+<end of list>
+
+Before statement a->n2 = (int *)malloc(sizeof(int)); :
+ <list of may-alias>
+<end of list>
+
+Before statement swap(tmp->n1); :
+ <list of may-alias>
+{x; tmp; } are aliased
+<end of list>
+
+Before statement *(a->n1) = 1; :
+ <list of may-alias>
+<end of list>
+
+Before statement *(a->n2) = 1; :
+ <list of may-alias>
+<end of list>
+
+Before statement i = 0; :
+ <list of may-alias>
+<end of list>
+
+Before statement ty *tmp = x; :
+ <list of may-alias>
+<end of list>
+
+Before statement while (i < 2) {
+                   b->t1[i] = a->t1[i];
+                   b->t2[i] = a->t2[i];
+                   i ++;
+                 } :
+ <list of may-alias>
+{*a; *b.t1[i]; *b.t2[i]; } are aliased
+<end of list>
+
+Before statement idata = (double *)malloc((unsigned long)10 * sizeof(double)); :
+ <list of may-alias>
+{x; tmp; } are aliased
+<end of list>
+
+Before statement while (1) {
+                   idata = tmp->t1[*(tmp->n1)];
+                   odata = tmp->t2[*(tmp->n2)];
+                   idx = 0;
+                   while (idx < 10) {
+                     *(odata + idx) = (double)3 * *(idata + idx) + (double)1;
+                     idx ++;
+                   }
+                   swap(tmp->n2);
+                 } :
+ <list of may-alias>
+{x; tmp; } are aliased
+<end of list>
+
+Before statement if (! (i < 2)) break; :
+ <list of may-alias>
+{*a; *b.t1[i]; *b.t2[i]; } are aliased
+<end of list>
+
+Before statement idata = tmp->t1[*(tmp->n1)];
+                 odata = tmp->t2[*(tmp->n2)];
+                 idx = 0;
+                 while (idx < 10) {
+                   *(odata + idx) = (double)3 * *(idata + idx) + (double)1;
+                   idx ++;
+                 }
+                 swap(tmp->n2); :
+ <list of may-alias>
+{x; tmp; } are aliased
+<end of list>
+
+Before statement break; :
+ <list of may-alias>
+{*a; *b.t1[i]; *b.t2[i]; } are aliased
+<end of list>
+
+Before statement idata = tmp->t1[*(tmp->n1)]; :
+ <list of may-alias>
+{x; tmp; } are aliased
+<end of list>
+
+Before statement b->t1[i] = a->t1[i];
+                 b->t2[i] = a->t2[i]; :
+ <list of may-alias>
+{*a; *b.t1[i]; *b.t2[i]; } are aliased
+<end of list>
+
+Before statement odata = tmp->t2[*(tmp->n2)]; :
+ <list of may-alias>
+{x; tmp; } are aliased
+<end of list>
+
+[alias] Analysis complete
diff --git a/src/plugins/alias/tests/real_world/oracle/example1.res.oracle b/src/plugins/alias/tests/real_world/oracle/example1.res.oracle
new file mode 100644
index 0000000000000000000000000000000000000000..2184e66ef66ccd9e68cdee8db84944dbaa773d5f
--- /dev/null
+++ b/src/plugins/alias/tests/real_world/oracle/example1.res.oracle
@@ -0,0 +1,412 @@
+[kernel] Parsing example1.c (with preprocessing)
+[alias] analysing function: _Exit
+[alias] May-aliases at the end of function _Exit: ⊥
+[alias] analysing function: __fc_fpclassify
+[alias] May-aliases at the end of function __fc_fpclassify: ⊥
+[alias] analysing function: __fc_fpclassifyf
+[alias] May-aliases at the end of function __fc_fpclassifyf: ⊥
+[alias] analysing function: __fc_infinity
+[alias] May-aliases at the end of function __fc_infinity: ⊥
+[alias] analysing function: __fc_nan
+[alias] May-aliases at the end of function __fc_nan: ⊥
+[alias] analysing function: __finite
+[alias] May-aliases at the end of function __finite: ⊥
+[alias] analysing function: __finitef
+[alias] May-aliases at the end of function __finitef: ⊥
+[alias] analysing function: abort
+[alias] May-aliases at the end of function abort: ⊥
+[alias] analysing function: abs
+[alias] May-aliases at the end of function abs: ⊥
+[alias] analysing function: acos
+[alias] May-aliases at the end of function acos: ⊥
+[alias] analysing function: acosf
+[alias] May-aliases at the end of function acosf: ⊥
+[alias] analysing function: acosh
+[alias] May-aliases at the end of function acosh: ⊥
+[alias] analysing function: acoshf
+[alias] May-aliases at the end of function acoshf: ⊥
+[alias] analysing function: acoshl
+[alias] May-aliases at the end of function acoshl: ⊥
+[alias] analysing function: acosl
+[alias] May-aliases at the end of function acosl: ⊥
+[alias] analysing function: asin
+[alias] May-aliases at the end of function asin: ⊥
+[alias] analysing function: asinf
+[alias] May-aliases at the end of function asinf: ⊥
+[alias] analysing function: asinl
+[alias] May-aliases at the end of function asinl: ⊥
+[alias] analysing function: at_quick_exit
+[alias] May-aliases at the end of function at_quick_exit: ⊥
+[alias] analysing function: atan
+[alias] May-aliases at the end of function atan: ⊥
+[alias] analysing function: atan2
+[alias] May-aliases at the end of function atan2: ⊥
+[alias] analysing function: atan2f
+[alias] May-aliases at the end of function atan2f: ⊥
+[alias] analysing function: atan2l
+[alias] May-aliases at the end of function atan2l: ⊥
+[alias] analysing function: atanf
+[alias] May-aliases at the end of function atanf: ⊥
+[alias] analysing function: atanl
+[alias] May-aliases at the end of function atanl: ⊥
+[alias] analysing function: atexit
+[alias] May-aliases at the end of function atexit: ⊥
+[alias] analysing function: atof
+[alias] May-aliases at the end of function atof: ⊥
+[alias] analysing function: atoi
+[alias] May-aliases at the end of function atoi: ⊥
+[alias] analysing function: atol
+[alias] May-aliases at the end of function atol: ⊥
+[alias] analysing function: atoll
+[alias] May-aliases at the end of function atoll: ⊥
+[alias] analysing function: bsearch
+[alias] May-aliases at the end of function bsearch: ⊥
+[alias] analysing function: calloc
+[alias] May-aliases at the end of function calloc: ⊥
+[alias] analysing function: ceil
+[alias] May-aliases at the end of function ceil: ⊥
+[alias] analysing function: ceilf
+[alias] May-aliases at the end of function ceilf: ⊥
+[alias] analysing function: ceill
+[alias] May-aliases at the end of function ceill: ⊥
+[alias] analysing function: cos
+[alias] May-aliases at the end of function cos: ⊥
+[alias] analysing function: cosf
+[alias] May-aliases at the end of function cosf: ⊥
+[alias] analysing function: cosl
+[alias] May-aliases at the end of function cosl: ⊥
+[alias] analysing function: div
+[alias] May-aliases at the end of function div: ⊥
+[alias] analysing function: drand48
+[alias] May-aliases at the end of function drand48: ⊥
+[alias] analysing function: erand48
+[alias] May-aliases at the end of function erand48: ⊥
+[alias] analysing function: exit
+[alias] May-aliases at the end of function exit: ⊥
+[alias] analysing function: exp
+[alias] May-aliases at the end of function exp: ⊥
+[alias] analysing function: expf
+[alias] May-aliases at the end of function expf: ⊥
+[alias] analysing function: f1
+[alias] analysing instruction: ty *tmp = x;
+[alias] May-aliases after instruction  ty *tmp = x;  are  {x, tmp}
+[alias] analysing instruction:
+  idata = (double *)malloc((unsigned long)10 * sizeof(double));
+[alias] May-aliases after instruction
+  idata = (double *)malloc((unsigned long)10 * sizeof(double));  are  {x, tmp}
+[alias] analysing instruction: idata = tmp->t2[*(tmp->n2)];
+[alias] May-aliases after instruction  idata = tmp->t2[*(tmp->n2)];  are
+  {x, tmp}  {tmp->t2[0], idata}
+[alias] analysing instruction: odata = tmp->t1[*(tmp->n1)];
+[alias] May-aliases after instruction  odata = tmp->t1[*(tmp->n1)];  are
+  {x, tmp}  {tmp->t2[0], idata}  {tmp->t1[0], odata}
+[alias] analysing instruction: idx = 0;
+[alias] May-aliases after instruction  idx = 0;  are
+  {x, tmp}  {tmp->t2[0], idata}  {tmp->t1[0], odata}
+[alias] analysing instruction: tmp_1 = sin(*(idata + idx));
+[alias] analysing function: sin
+[alias] May-aliases at the end of function sin: ⊥
+[alias:undefined:fn] example1.c:45: Warning: function sin has no definition
+[alias] May-aliases after instruction  tmp_1 = sin(*(idata + idx));  are
+  {x, tmp}  {tmp->t2[0], idata}  {tmp->t1[0], odata}
+[alias] analysing instruction: *(odata + idx) = 0.5 * tmp_1;
+[alias] May-aliases after instruction  *(odata + idx) = 0.5 * tmp_1;  are
+  {x, tmp}  {tmp->t2[0], idata}  {tmp->t1[0], odata}
+[alias] analysing instruction: idx ++;
+[alias] May-aliases after instruction  idx ++;  are
+  {x, tmp}  {tmp->t2[0], idata}  {tmp->t1[0], odata}
+[alias] analysing instruction: swap(tmp->n1);
+[alias] analysing function: swap
+[alias] analysing instruction: *n = 0;
+[alias] May-aliases after instruction  *n = 0;  are  <none>
+[alias] analysing instruction: (*n) ++;
+[alias] May-aliases after instruction  (*n) ++;  are  <none>
+[alias] May-aliases at the end of function swap: <none>
+[alias] May-aliases after instruction  swap(tmp->n1);  are
+  {x, tmp}  {tmp->t2[0], idata}  {tmp->t1[0], odata}
+[alias] analysing instruction: idata = tmp->t2[*(tmp->n2)];
+[alias] May-aliases after instruction  idata = tmp->t2[*(tmp->n2)];  are
+  {x, tmp}  {tmp->t2[0], idata}  {tmp->t1[0], odata}
+[alias] analysing instruction: odata = tmp->t1[*(tmp->n1)];
+[alias] May-aliases after instruction  odata = tmp->t1[*(tmp->n1)];  are
+  {x, tmp}  {tmp->t2[0], idata}  {tmp->t1[0], odata}
+[alias:no-return] example1.c:29: Warning: 
+  function f1 does not return; analysis may be unsound
+[alias] May-aliases at the end of function f1: <none>
+[alias] analysing function: f2
+[alias] analysing instruction: ty *tmp = x;
+[alias] May-aliases after instruction  ty *tmp = x;  are  {x, tmp}
+[alias] analysing instruction:
+  idata = (double *)malloc((unsigned long)10 * sizeof(double));
+[alias] May-aliases after instruction
+  idata = (double *)malloc((unsigned long)10 * sizeof(double));  are  {x, tmp}
+[alias] analysing instruction: idata = tmp->t1[*(tmp->n1)];
+[alias] May-aliases after instruction  idata = tmp->t1[*(tmp->n1)];  are
+  {x, tmp}  {tmp->t1[0], idata}
+[alias] analysing instruction: odata = tmp->t2[*(tmp->n2)];
+[alias] May-aliases after instruction  odata = tmp->t2[*(tmp->n2)];  are
+  {x, tmp}  {tmp->t1[0], idata}  {tmp->t2[0], odata}
+[alias] analysing instruction: idx = 0;
+[alias] May-aliases after instruction  idx = 0;  are
+  {x, tmp}  {tmp->t1[0], idata}  {tmp->t2[0], odata}
+[alias] analysing instruction:
+  *(odata + idx) = (double)3 * *(idata + idx) + (double)1;
+[alias] May-aliases after instruction
+  *(odata + idx) = (double)3 * *(idata + idx) + (double)1;  are
+  {x, tmp}  {tmp->t1[0], idata}  {tmp->t2[0], odata}
+[alias] analysing instruction: idx ++;
+[alias] May-aliases after instruction  idx ++;  are
+  {x, tmp}  {tmp->t1[0], idata}  {tmp->t2[0], odata}
+[alias] analysing instruction: swap(tmp->n2);
+[alias] May-aliases after instruction  swap(tmp->n2);  are
+  {x, tmp}  {tmp->t1[0], idata}  {tmp->t2[0], odata}
+[alias] analysing instruction: idata = tmp->t1[*(tmp->n1)];
+[alias] May-aliases after instruction  idata = tmp->t1[*(tmp->n1)];  are
+  {x, tmp}  {tmp->t1[0], idata}  {tmp->t2[0], odata}
+[alias] analysing instruction: odata = tmp->t2[*(tmp->n2)];
+[alias] May-aliases after instruction  odata = tmp->t2[*(tmp->n2)];  are
+  {x, tmp}  {tmp->t1[0], idata}  {tmp->t2[0], odata}
+[alias:no-return] example1.c:53: Warning: 
+  function f2 does not return; analysis may be unsound
+[alias] May-aliases at the end of function f2: <none>
+[alias] analysing function: fabs
+[alias] May-aliases at the end of function fabs: ⊥
+[alias] analysing function: fabsf
+[alias] May-aliases at the end of function fabsf: ⊥
+[alias] analysing function: fabsl
+[alias] May-aliases at the end of function fabsl: ⊥
+[alias] analysing function: floor
+[alias] May-aliases at the end of function floor: ⊥
+[alias] analysing function: floorf
+[alias] May-aliases at the end of function floorf: ⊥
+[alias] analysing function: floorl
+[alias] May-aliases at the end of function floorl: ⊥
+[alias] analysing function: fmod
+[alias] May-aliases at the end of function fmod: ⊥
+[alias] analysing function: fmodf
+[alias] May-aliases at the end of function fmodf: ⊥
+[alias] analysing function: free
+[alias] May-aliases at the end of function free: ⊥
+[alias] analysing function: frexp
+[alias] May-aliases at the end of function frexp: ⊥
+[alias] analysing function: frexpf
+[alias] May-aliases at the end of function frexpf: ⊥
+[alias] analysing function: frexpl
+[alias] May-aliases at the end of function frexpl: ⊥
+[alias] analysing function: getenv
+[alias] May-aliases at the end of function getenv: ⊥
+[alias] analysing function: jrand48
+[alias] May-aliases at the end of function jrand48: ⊥
+[alias] analysing function: labs
+[alias] May-aliases at the end of function labs: ⊥
+[alias] analysing function: lcong48
+[alias] May-aliases at the end of function lcong48: ⊥
+[alias] analysing function: ldexp
+[alias] May-aliases at the end of function ldexp: ⊥
+[alias] analysing function: ldexpf
+[alias] May-aliases at the end of function ldexpf: ⊥
+[alias] analysing function: ldiv
+[alias] May-aliases at the end of function ldiv: ⊥
+[alias] analysing function: llabs
+[alias] May-aliases at the end of function llabs: ⊥
+[alias] analysing function: lldiv
+[alias] May-aliases at the end of function lldiv: ⊥
+[alias] analysing function: log
+[alias] May-aliases at the end of function log: ⊥
+[alias] analysing function: log10
+[alias] May-aliases at the end of function log10: ⊥
+[alias] analysing function: log10f
+[alias] May-aliases at the end of function log10f: ⊥
+[alias] analysing function: log10l
+[alias] May-aliases at the end of function log10l: ⊥
+[alias] analysing function: log2
+[alias] May-aliases at the end of function log2: ⊥
+[alias] analysing function: log2f
+[alias] May-aliases at the end of function log2f: ⊥
+[alias] analysing function: log2l
+[alias] May-aliases at the end of function log2l: ⊥
+[alias] analysing function: logf
+[alias] May-aliases at the end of function logf: ⊥
+[alias] analysing function: logl
+[alias] May-aliases at the end of function logl: ⊥
+[alias] analysing function: lrand48
+[alias] May-aliases at the end of function lrand48: ⊥
+[alias] analysing function: main
+[alias] analysing instruction: a = (ty *)malloc(sizeof(ty));
+[alias] May-aliases after instruction  a = (ty *)malloc(sizeof(ty));  are  <none>
+[alias] analysing instruction: b = (ty *)malloc(sizeof(ty));
+[alias] May-aliases after instruction  b = (ty *)malloc(sizeof(ty));  are  <none>
+[alias] analysing instruction: i = 0;
+[alias] May-aliases after instruction  i = 0;  are  <none>
+[alias] analysing instruction:
+  a->t1[i] = (double *)malloc((unsigned long)10 * sizeof(double));
+[alias] May-aliases after instruction
+  a->t1[i] = (double *)malloc((unsigned long)10 * sizeof(double));  are  
+  <none>
+[alias] analysing instruction:
+  a->t2[i] = (double *)malloc((unsigned long)10 * sizeof(double));
+[alias] May-aliases after instruction
+  a->t2[i] = (double *)malloc((unsigned long)10 * sizeof(double));  are  
+  <none>
+[alias] analysing instruction: i ++;
+[alias] May-aliases after instruction  i ++;  are  <none>
+[alias] analysing instruction:
+  a->t1[i] = (double *)malloc((unsigned long)10 * sizeof(double));
+[alias] May-aliases after instruction
+  a->t1[i] = (double *)malloc((unsigned long)10 * sizeof(double));  are  
+  <none>
+[alias] analysing instruction:
+  a->t2[i] = (double *)malloc((unsigned long)10 * sizeof(double));
+[alias] May-aliases after instruction
+  a->t2[i] = (double *)malloc((unsigned long)10 * sizeof(double));  are  
+  <none>
+[alias] analysing instruction: a->n1 = (int *)malloc(sizeof(int));
+[alias] May-aliases after instruction  a->n1 = (int *)malloc(sizeof(int));  are
+  <none>
+[alias] analysing instruction: a->n2 = (int *)malloc(sizeof(int));
+[alias] May-aliases after instruction  a->n2 = (int *)malloc(sizeof(int));  are
+  <none>
+[alias] analysing instruction: *(a->n1) = 1;
+[alias] May-aliases after instruction  *(a->n1) = 1;  are  <none>
+[alias] analysing instruction: *(a->n2) = 1;
+[alias] May-aliases after instruction  *(a->n2) = 1;  are  <none>
+[alias] analysing instruction: i = 0;
+[alias] May-aliases after instruction  i = 0;  are  <none>
+[alias] analysing instruction: b->t1[i] = a->t1[i];
+[alias] May-aliases after instruction  b->t1[i] = a->t1[i];  are
+  {a->t1[0], b->t1[0]}
+[alias] analysing instruction: b->t2[i] = a->t2[i];
+[alias] May-aliases after instruction  b->t2[i] = a->t2[i];  are
+  {a->t1[0], b->t1[0]}  {a->t2[0], b->t2[0]}
+[alias] analysing instruction: i ++;
+[alias] May-aliases after instruction  i ++;  are
+  {a->t1[0], b->t1[0]}  {a->t2[0], b->t2[0]}
+[alias] analysing instruction: b->t1[i] = a->t1[i];
+[alias] May-aliases after instruction  b->t1[i] = a->t1[i];  are
+  {a->t1[0], b->t1[0]}  {a->t2[0], b->t2[0]}
+[alias] analysing instruction: b->t2[i] = a->t2[i];
+[alias] May-aliases after instruction  b->t2[i] = a->t2[i];  are
+  {a->t1[0], b->t1[0]}  {a->t2[0], b->t2[0]}
+[alias] analysing instruction: b->n1 = a->n1;
+[alias] May-aliases after instruction  b->n1 = a->n1;  are
+  {a->t1[0], b->t1[0]}  {a->t2[0], b->t2[0]}  {a->n1, b->n1}
+[alias] analysing instruction: b->n2 = a->n2;
+[alias] May-aliases after instruction  b->n2 = a->n2;  are
+  {a->t1[0], b->t1[0]}  {a->t2[0], b->t2[0]}  {a->n1, b->n1}  {a->n2, b->n2}
+[alias] analysing instruction: f1(a);
+[alias] May-aliases after instruction  f1(a);  are
+  {a->t1[0], b->t1[0]}  {a->t2[0], b->t2[0]}  {a->n1, b->n1}  {a->n2, b->n2}
+[alias] analysing instruction: f2(b);
+[alias] May-aliases after instruction  f2(b);  are
+  {a->t1[0], b->t1[0]}  {a->t2[0], b->t2[0]}  {a->n1, b->n1}  {a->n2, b->n2}
+[alias] analysing instruction: __retres = 0;
+[alias] May-aliases after instruction  __retres = 0;  are
+  {a->t1[0], b->t1[0]}  {a->t2[0], b->t2[0]}  {a->n1, b->n1}  {a->n2, b->n2}
+[alias] May-aliases at the end of function main:
+  {a->t1[0], b->t1[0]}  {a->t2[0], b->t2[0]}  {a->n1, b->n1}  {a->n2, b->n2}
+[alias] analysing function: malloc
+[alias] May-aliases at the end of function malloc: ⊥
+[alias] analysing function: mblen
+[alias] May-aliases at the end of function mblen: ⊥
+[alias] analysing function: mbstowcs
+[alias] May-aliases at the end of function mbstowcs: ⊥
+[alias] analysing function: mbtowc
+[alias] May-aliases at the end of function mbtowc: ⊥
+[alias] analysing function: mkstemp
+[alias] May-aliases at the end of function mkstemp: ⊥
+[alias] analysing function: mkstemps
+[alias] May-aliases at the end of function mkstemps: ⊥
+[alias] analysing function: mrand48
+[alias] May-aliases at the end of function mrand48: ⊥
+[alias] analysing function: nan
+[alias] May-aliases at the end of function nan: ⊥
+[alias] analysing function: nanf
+[alias] May-aliases at the end of function nanf: ⊥
+[alias] analysing function: nanl
+[alias] May-aliases at the end of function nanl: ⊥
+[alias] analysing function: nrand48
+[alias] May-aliases at the end of function nrand48: ⊥
+[alias] analysing function: posix_memalign
+[alias] May-aliases at the end of function posix_memalign: ⊥
+[alias] analysing function: pow
+[alias] May-aliases at the end of function pow: ⊥
+[alias] analysing function: powf
+[alias] May-aliases at the end of function powf: ⊥
+[alias] analysing function: putenv
+[alias] May-aliases at the end of function putenv: ⊥
+[alias] analysing function: qsort
+[alias] May-aliases at the end of function qsort: ⊥
+[alias] analysing function: quick_exit
+[alias] May-aliases at the end of function quick_exit: ⊥
+[alias] analysing function: rand
+[alias] May-aliases at the end of function rand: ⊥
+[alias] analysing function: random
+[alias] May-aliases at the end of function random: ⊥
+[alias] analysing function: realloc
+[alias] May-aliases at the end of function realloc: ⊥
+[alias] analysing function: reallocarray
+[alias] May-aliases at the end of function reallocarray: ⊥
+[alias] analysing function: round
+[alias] May-aliases at the end of function round: ⊥
+[alias] analysing function: roundf
+[alias] May-aliases at the end of function roundf: ⊥
+[alias] analysing function: roundl
+[alias] May-aliases at the end of function roundl: ⊥
+[alias] analysing function: seed48
+[alias] May-aliases at the end of function seed48: ⊥
+[alias] analysing function: setenv
+[alias] May-aliases at the end of function setenv: ⊥
+[alias] analysing function: sin
+[alias] May-aliases at the end of function sin: ⊥
+[alias] analysing function: sinf
+[alias] May-aliases at the end of function sinf: ⊥
+[alias] analysing function: sinl
+[alias] May-aliases at the end of function sinl: ⊥
+[alias] analysing function: sqrt
+[alias] May-aliases at the end of function sqrt: ⊥
+[alias] analysing function: sqrtf
+[alias] May-aliases at the end of function sqrtf: ⊥
+[alias] analysing function: sqrtl
+[alias] May-aliases at the end of function sqrtl: ⊥
+[alias] analysing function: srand
+[alias] May-aliases at the end of function srand: ⊥
+[alias] analysing function: srand48
+[alias] May-aliases at the end of function srand48: ⊥
+[alias] analysing function: srandom
+[alias] May-aliases at the end of function srandom: ⊥
+[alias] analysing function: strtod
+[alias] May-aliases at the end of function strtod: ⊥
+[alias] analysing function: strtof
+[alias] May-aliases at the end of function strtof: ⊥
+[alias] analysing function: strtol
+[alias] May-aliases at the end of function strtol: ⊥
+[alias] analysing function: strtold
+[alias] May-aliases at the end of function strtold: ⊥
+[alias] analysing function: strtoll
+[alias] May-aliases at the end of function strtoll: ⊥
+[alias] analysing function: strtoul
+[alias] May-aliases at the end of function strtoul: ⊥
+[alias] analysing function: strtoull
+[alias] May-aliases at the end of function strtoull: ⊥
+[alias] analysing function: swap
+[alias] May-aliases at the end of function swap: <none>
+[alias] analysing function: system
+[alias] May-aliases at the end of function system: ⊥
+[alias] analysing function: tan
+[alias] May-aliases at the end of function tan: ⊥
+[alias] analysing function: tanf
+[alias] May-aliases at the end of function tanf: ⊥
+[alias] analysing function: tanl
+[alias] May-aliases at the end of function tanl: ⊥
+[alias] analysing function: trunc
+[alias] May-aliases at the end of function trunc: ⊥
+[alias] analysing function: truncf
+[alias] May-aliases at the end of function truncf: ⊥
+[alias] analysing function: truncl
+[alias] May-aliases at the end of function truncl: ⊥
+[alias] analysing function: unsetenv
+[alias] May-aliases at the end of function unsetenv: ⊥
+[alias] analysing function: wcstombs
+[alias] May-aliases at the end of function wcstombs: ⊥
+[alias] analysing function: wctomb
+[alias] May-aliases at the end of function wctomb: ⊥
diff --git a/src/plugins/alias/tests/real_world/oracle/example2.res.oracle b/src/plugins/alias/tests/real_world/oracle/example2.res.oracle
new file mode 100644
index 0000000000000000000000000000000000000000..21f8829b4dc8c670f933cedca6281dd899cd434f
--- /dev/null
+++ b/src/plugins/alias/tests/real_world/oracle/example2.res.oracle
@@ -0,0 +1,426 @@
+[kernel] Parsing example2.c (with preprocessing)
+[alias] analysing function: _Exit
+[alias] May-aliases at the end of function _Exit: ⊥
+[alias] analysing function: __fc_fpclassify
+[alias] May-aliases at the end of function __fc_fpclassify: ⊥
+[alias] analysing function: __fc_fpclassifyf
+[alias] May-aliases at the end of function __fc_fpclassifyf: ⊥
+[alias] analysing function: __fc_infinity
+[alias] May-aliases at the end of function __fc_infinity: ⊥
+[alias] analysing function: __fc_nan
+[alias] May-aliases at the end of function __fc_nan: ⊥
+[alias] analysing function: __finite
+[alias] May-aliases at the end of function __finite: ⊥
+[alias] analysing function: __finitef
+[alias] May-aliases at the end of function __finitef: ⊥
+[alias] analysing function: abort
+[alias] May-aliases at the end of function abort: ⊥
+[alias] analysing function: abs
+[alias] May-aliases at the end of function abs: ⊥
+[alias] analysing function: acos
+[alias] May-aliases at the end of function acos: ⊥
+[alias] analysing function: acosf
+[alias] May-aliases at the end of function acosf: ⊥
+[alias] analysing function: acosh
+[alias] May-aliases at the end of function acosh: ⊥
+[alias] analysing function: acoshf
+[alias] May-aliases at the end of function acoshf: ⊥
+[alias] analysing function: acoshl
+[alias] May-aliases at the end of function acoshl: ⊥
+[alias] analysing function: acosl
+[alias] May-aliases at the end of function acosl: ⊥
+[alias] analysing function: asin
+[alias] May-aliases at the end of function asin: ⊥
+[alias] analysing function: asinf
+[alias] May-aliases at the end of function asinf: ⊥
+[alias] analysing function: asinl
+[alias] May-aliases at the end of function asinl: ⊥
+[alias] analysing function: at_quick_exit
+[alias] May-aliases at the end of function at_quick_exit: ⊥
+[alias] analysing function: atan
+[alias] May-aliases at the end of function atan: ⊥
+[alias] analysing function: atan2
+[alias] May-aliases at the end of function atan2: ⊥
+[alias] analysing function: atan2f
+[alias] May-aliases at the end of function atan2f: ⊥
+[alias] analysing function: atan2l
+[alias] May-aliases at the end of function atan2l: ⊥
+[alias] analysing function: atanf
+[alias] May-aliases at the end of function atanf: ⊥
+[alias] analysing function: atanl
+[alias] May-aliases at the end of function atanl: ⊥
+[alias] analysing function: atexit
+[alias] May-aliases at the end of function atexit: ⊥
+[alias] analysing function: atof
+[alias] May-aliases at the end of function atof: ⊥
+[alias] analysing function: atoi
+[alias] May-aliases at the end of function atoi: ⊥
+[alias] analysing function: atol
+[alias] May-aliases at the end of function atol: ⊥
+[alias] analysing function: atoll
+[alias] May-aliases at the end of function atoll: ⊥
+[alias] analysing function: bsearch
+[alias] May-aliases at the end of function bsearch: ⊥
+[alias] analysing function: calloc
+[alias] May-aliases at the end of function calloc: ⊥
+[alias] analysing function: ceil
+[alias] May-aliases at the end of function ceil: ⊥
+[alias] analysing function: ceilf
+[alias] May-aliases at the end of function ceilf: ⊥
+[alias] analysing function: ceill
+[alias] May-aliases at the end of function ceill: ⊥
+[alias] analysing function: cos
+[alias] May-aliases at the end of function cos: ⊥
+[alias] analysing function: cosf
+[alias] May-aliases at the end of function cosf: ⊥
+[alias] analysing function: cosl
+[alias] May-aliases at the end of function cosl: ⊥
+[alias] analysing function: div
+[alias] May-aliases at the end of function div: ⊥
+[alias] analysing function: drand48
+[alias] May-aliases at the end of function drand48: ⊥
+[alias] analysing function: erand48
+[alias] May-aliases at the end of function erand48: ⊥
+[alias] analysing function: exit
+[alias] May-aliases at the end of function exit: ⊥
+[alias] analysing function: exp
+[alias] May-aliases at the end of function exp: ⊥
+[alias] analysing function: expf
+[alias] May-aliases at the end of function expf: ⊥
+[alias] analysing function: f1
+[alias] analysing instruction: ty *tmp = x;
+[alias] May-aliases after instruction  ty *tmp = x;  are  {x, tmp}
+[alias] analysing instruction:
+  idata = (double *)malloc((unsigned long)10 * sizeof(double));
+[alias] May-aliases after instruction
+  idata = (double *)malloc((unsigned long)10 * sizeof(double));  are  {x, tmp}
+[alias] analysing instruction: int i = 0;
+[alias] May-aliases after instruction  int i = 0;  are  {x, tmp}
+[alias] analysing instruction: idata = tmp->t2[*(tmp->n2)];
+[alias] May-aliases after instruction  idata = tmp->t2[*(tmp->n2)];  are
+  {x, tmp}  {tmp->t2[0], idata}
+[alias] analysing instruction: odata = tmp->t1[*(tmp->n1)];
+[alias] May-aliases after instruction  odata = tmp->t1[*(tmp->n1)];  are
+  {x, tmp}  {tmp->t2[0], idata}  {tmp->t1[0], odata}
+[alias] analysing instruction: idx = 0;
+[alias] May-aliases after instruction  idx = 0;  are
+  {x, tmp}  {tmp->t2[0], idata}  {tmp->t1[0], odata}
+[alias] analysing instruction: tmp_1 = sin(*(idata + idx));
+[alias] analysing function: sin
+[alias] May-aliases at the end of function sin: ⊥
+[alias:undefined:fn] example2.c:45: Warning: function sin has no definition
+[alias] May-aliases after instruction  tmp_1 = sin(*(idata + idx));  are
+  {x, tmp}  {tmp->t2[0], idata}  {tmp->t1[0], odata}
+[alias] analysing instruction: *(odata + idx) = 0.5 * tmp_1;
+[alias] May-aliases after instruction  *(odata + idx) = 0.5 * tmp_1;  are
+  {x, tmp}  {tmp->t2[0], idata}  {tmp->t1[0], odata}
+[alias] analysing instruction: idx ++;
+[alias] May-aliases after instruction  idx ++;  are
+  {x, tmp}  {tmp->t2[0], idata}  {tmp->t1[0], odata}
+[alias] analysing instruction: swap(tmp->n1);
+[alias] analysing function: swap
+[alias] analysing instruction: *n = 0;
+[alias] May-aliases after instruction  *n = 0;  are  <none>
+[alias] analysing instruction: (*n) ++;
+[alias] May-aliases after instruction  (*n) ++;  are  <none>
+[alias] May-aliases at the end of function swap: <none>
+[alias] May-aliases after instruction  swap(tmp->n1);  are
+  {x, tmp}  {tmp->t2[0], idata}  {tmp->t1[0], odata}
+[alias] analysing instruction: i ++;
+[alias] May-aliases after instruction  i ++;  are
+  {x, tmp}  {tmp->t2[0], idata}  {tmp->t1[0], odata}
+[alias] analysing instruction: idata = tmp->t2[*(tmp->n2)];
+[alias] May-aliases after instruction  idata = tmp->t2[*(tmp->n2)];  are
+  {x, tmp}  {tmp->t2[0], idata}  {tmp->t1[0], odata}
+[alias] analysing instruction: odata = tmp->t1[*(tmp->n1)];
+[alias] May-aliases after instruction  odata = tmp->t1[*(tmp->n1)];  are
+  {x, tmp}  {tmp->t2[0], idata}  {tmp->t1[0], odata}
+[alias] analysing instruction: __retres = (void *)0;
+[alias] May-aliases after instruction  __retres = (void *)0;  are
+  {x, tmp}  {tmp->t2[0], idata}  {tmp->t1[0], odata}
+[alias] May-aliases at the end of function f1:
+  {x, tmp}  {tmp->t2[0], idata}  {tmp->t1[0], odata}
+[alias] analysing function: f2
+[alias] analysing instruction: ty *tmp = x;
+[alias] May-aliases after instruction  ty *tmp = x;  are  {x, tmp}
+[alias] analysing instruction:
+  idata = (double *)malloc((unsigned long)10 * sizeof(double));
+[alias] May-aliases after instruction
+  idata = (double *)malloc((unsigned long)10 * sizeof(double));  are  {x, tmp}
+[alias] analysing instruction: int i = 0;
+[alias] May-aliases after instruction  int i = 0;  are  {x, tmp}
+[alias] analysing instruction: idata = tmp->t1[*(tmp->n1)];
+[alias] May-aliases after instruction  idata = tmp->t1[*(tmp->n1)];  are
+  {x, tmp}  {tmp->t1[0], idata}
+[alias] analysing instruction: odata = tmp->t2[*(tmp->n2)];
+[alias] May-aliases after instruction  odata = tmp->t2[*(tmp->n2)];  are
+  {x, tmp}  {tmp->t1[0], idata}  {tmp->t2[0], odata}
+[alias] analysing instruction: idx = 0;
+[alias] May-aliases after instruction  idx = 0;  are
+  {x, tmp}  {tmp->t1[0], idata}  {tmp->t2[0], odata}
+[alias] analysing instruction:
+  *(odata + idx) = (double)3 * *(idata + idx) + (double)1;
+[alias] May-aliases after instruction
+  *(odata + idx) = (double)3 * *(idata + idx) + (double)1;  are
+  {x, tmp}  {tmp->t1[0], idata}  {tmp->t2[0], odata}
+[alias] analysing instruction: idx ++;
+[alias] May-aliases after instruction  idx ++;  are
+  {x, tmp}  {tmp->t1[0], idata}  {tmp->t2[0], odata}
+[alias] analysing instruction: swap(tmp->n2);
+[alias] May-aliases after instruction  swap(tmp->n2);  are
+  {x, tmp}  {tmp->t1[0], idata}  {tmp->t2[0], odata}
+[alias] analysing instruction: i ++;
+[alias] May-aliases after instruction  i ++;  are
+  {x, tmp}  {tmp->t1[0], idata}  {tmp->t2[0], odata}
+[alias] analysing instruction: idata = tmp->t1[*(tmp->n1)];
+[alias] May-aliases after instruction  idata = tmp->t1[*(tmp->n1)];  are
+  {x, tmp}  {tmp->t1[0], idata}  {tmp->t2[0], odata}
+[alias] analysing instruction: odata = tmp->t2[*(tmp->n2)];
+[alias] May-aliases after instruction  odata = tmp->t2[*(tmp->n2)];  are
+  {x, tmp}  {tmp->t1[0], idata}  {tmp->t2[0], odata}
+[alias] analysing instruction: __retres = (void *)0;
+[alias] May-aliases after instruction  __retres = (void *)0;  are
+  {x, tmp}  {tmp->t1[0], idata}  {tmp->t2[0], odata}
+[alias] May-aliases at the end of function f2:
+  {x, tmp}  {tmp->t1[0], idata}  {tmp->t2[0], odata}
+[alias] analysing function: fabs
+[alias] May-aliases at the end of function fabs: ⊥
+[alias] analysing function: fabsf
+[alias] May-aliases at the end of function fabsf: ⊥
+[alias] analysing function: fabsl
+[alias] May-aliases at the end of function fabsl: ⊥
+[alias] analysing function: floor
+[alias] May-aliases at the end of function floor: ⊥
+[alias] analysing function: floorf
+[alias] May-aliases at the end of function floorf: ⊥
+[alias] analysing function: floorl
+[alias] May-aliases at the end of function floorl: ⊥
+[alias] analysing function: fmod
+[alias] May-aliases at the end of function fmod: ⊥
+[alias] analysing function: fmodf
+[alias] May-aliases at the end of function fmodf: ⊥
+[alias] analysing function: free
+[alias] May-aliases at the end of function free: ⊥
+[alias] analysing function: frexp
+[alias] May-aliases at the end of function frexp: ⊥
+[alias] analysing function: frexpf
+[alias] May-aliases at the end of function frexpf: ⊥
+[alias] analysing function: frexpl
+[alias] May-aliases at the end of function frexpl: ⊥
+[alias] analysing function: getenv
+[alias] May-aliases at the end of function getenv: ⊥
+[alias] analysing function: jrand48
+[alias] May-aliases at the end of function jrand48: ⊥
+[alias] analysing function: labs
+[alias] May-aliases at the end of function labs: ⊥
+[alias] analysing function: lcong48
+[alias] May-aliases at the end of function lcong48: ⊥
+[alias] analysing function: ldexp
+[alias] May-aliases at the end of function ldexp: ⊥
+[alias] analysing function: ldexpf
+[alias] May-aliases at the end of function ldexpf: ⊥
+[alias] analysing function: ldiv
+[alias] May-aliases at the end of function ldiv: ⊥
+[alias] analysing function: llabs
+[alias] May-aliases at the end of function llabs: ⊥
+[alias] analysing function: lldiv
+[alias] May-aliases at the end of function lldiv: ⊥
+[alias] analysing function: log
+[alias] May-aliases at the end of function log: ⊥
+[alias] analysing function: log10
+[alias] May-aliases at the end of function log10: ⊥
+[alias] analysing function: log10f
+[alias] May-aliases at the end of function log10f: ⊥
+[alias] analysing function: log10l
+[alias] May-aliases at the end of function log10l: ⊥
+[alias] analysing function: log2
+[alias] May-aliases at the end of function log2: ⊥
+[alias] analysing function: log2f
+[alias] May-aliases at the end of function log2f: ⊥
+[alias] analysing function: log2l
+[alias] May-aliases at the end of function log2l: ⊥
+[alias] analysing function: logf
+[alias] May-aliases at the end of function logf: ⊥
+[alias] analysing function: logl
+[alias] May-aliases at the end of function logl: ⊥
+[alias] analysing function: lrand48
+[alias] May-aliases at the end of function lrand48: ⊥
+[alias] analysing function: main
+[alias] analysing instruction: a = (ty *)malloc(sizeof(ty));
+[alias] May-aliases after instruction  a = (ty *)malloc(sizeof(ty));  are  <none>
+[alias] analysing instruction: b = (ty *)malloc(sizeof(ty));
+[alias] May-aliases after instruction  b = (ty *)malloc(sizeof(ty));  are  <none>
+[alias] analysing instruction: i = 0;
+[alias] May-aliases after instruction  i = 0;  are  <none>
+[alias] analysing instruction:
+  a->t1[i] = (double *)malloc((unsigned long)10 * sizeof(double));
+[alias] May-aliases after instruction
+  a->t1[i] = (double *)malloc((unsigned long)10 * sizeof(double));  are  
+  <none>
+[alias] analysing instruction:
+  a->t2[i] = (double *)malloc((unsigned long)10 * sizeof(double));
+[alias] May-aliases after instruction
+  a->t2[i] = (double *)malloc((unsigned long)10 * sizeof(double));  are  
+  <none>
+[alias] analysing instruction: i ++;
+[alias] May-aliases after instruction  i ++;  are  <none>
+[alias] analysing instruction:
+  a->t1[i] = (double *)malloc((unsigned long)10 * sizeof(double));
+[alias] May-aliases after instruction
+  a->t1[i] = (double *)malloc((unsigned long)10 * sizeof(double));  are  
+  <none>
+[alias] analysing instruction:
+  a->t2[i] = (double *)malloc((unsigned long)10 * sizeof(double));
+[alias] May-aliases after instruction
+  a->t2[i] = (double *)malloc((unsigned long)10 * sizeof(double));  are  
+  <none>
+[alias] analysing instruction: a->n1 = (int *)malloc(sizeof(int));
+[alias] May-aliases after instruction  a->n1 = (int *)malloc(sizeof(int));  are
+  <none>
+[alias] analysing instruction: a->n2 = (int *)malloc(sizeof(int));
+[alias] May-aliases after instruction  a->n2 = (int *)malloc(sizeof(int));  are
+  <none>
+[alias] analysing instruction: *(a->n1) = 1;
+[alias] May-aliases after instruction  *(a->n1) = 1;  are  <none>
+[alias] analysing instruction: *(a->n2) = 1;
+[alias] May-aliases after instruction  *(a->n2) = 1;  are  <none>
+[alias] analysing instruction: i = 0;
+[alias] May-aliases after instruction  i = 0;  are  <none>
+[alias] analysing instruction: b->t1[i] = a->t1[i];
+[alias] May-aliases after instruction  b->t1[i] = a->t1[i];  are
+  {a->t1[0], b->t1[0]}
+[alias] analysing instruction: b->t2[i] = a->t2[i];
+[alias] May-aliases after instruction  b->t2[i] = a->t2[i];  are
+  {a->t1[0], b->t1[0]}  {a->t2[0], b->t2[0]}
+[alias] analysing instruction: i ++;
+[alias] May-aliases after instruction  i ++;  are
+  {a->t1[0], b->t1[0]}  {a->t2[0], b->t2[0]}
+[alias] analysing instruction: b->t1[i] = a->t1[i];
+[alias] May-aliases after instruction  b->t1[i] = a->t1[i];  are
+  {a->t1[0], b->t1[0]}  {a->t2[0], b->t2[0]}
+[alias] analysing instruction: b->t2[i] = a->t2[i];
+[alias] May-aliases after instruction  b->t2[i] = a->t2[i];  are
+  {a->t1[0], b->t1[0]}  {a->t2[0], b->t2[0]}
+[alias] analysing instruction: b->n1 = a->n1;
+[alias] May-aliases after instruction  b->n1 = a->n1;  are
+  {a->t1[0], b->t1[0]}  {a->t2[0], b->t2[0]}  {a->n1, b->n1}
+[alias] analysing instruction: b->n2 = a->n2;
+[alias] May-aliases after instruction  b->n2 = a->n2;  are
+  {a->t1[0], b->t1[0]}  {a->t2[0], b->t2[0]}  {a->n1, b->n1}  {a->n2, b->n2}
+[alias] analysing instruction: f1(a);
+[alias] May-aliases after instruction  f1(a);  are
+  {a->t1[0], b->t1[0]}  {a->t2[0], b->t2[0]}  {a->n1, b->n1}  {a->n2, b->n2}
+[alias] analysing instruction: f2(b);
+[alias] May-aliases after instruction  f2(b);  are
+  {a->t1[0], b->t1[0]}  {a->t2[0], b->t2[0]}  {a->n1, b->n1}  {a->n2, b->n2}
+[alias] analysing instruction: __retres = 0;
+[alias] May-aliases after instruction  __retres = 0;  are
+  {a->t1[0], b->t1[0]}  {a->t2[0], b->t2[0]}  {a->n1, b->n1}  {a->n2, b->n2}
+[alias] May-aliases at the end of function main:
+  {a->t1[0], b->t1[0]}  {a->t2[0], b->t2[0]}  {a->n1, b->n1}  {a->n2, b->n2}
+[alias] analysing function: malloc
+[alias] May-aliases at the end of function malloc: ⊥
+[alias] analysing function: mblen
+[alias] May-aliases at the end of function mblen: ⊥
+[alias] analysing function: mbstowcs
+[alias] May-aliases at the end of function mbstowcs: ⊥
+[alias] analysing function: mbtowc
+[alias] May-aliases at the end of function mbtowc: ⊥
+[alias] analysing function: mkstemp
+[alias] May-aliases at the end of function mkstemp: ⊥
+[alias] analysing function: mkstemps
+[alias] May-aliases at the end of function mkstemps: ⊥
+[alias] analysing function: mrand48
+[alias] May-aliases at the end of function mrand48: ⊥
+[alias] analysing function: nan
+[alias] May-aliases at the end of function nan: ⊥
+[alias] analysing function: nanf
+[alias] May-aliases at the end of function nanf: ⊥
+[alias] analysing function: nanl
+[alias] May-aliases at the end of function nanl: ⊥
+[alias] analysing function: nrand48
+[alias] May-aliases at the end of function nrand48: ⊥
+[alias] analysing function: posix_memalign
+[alias] May-aliases at the end of function posix_memalign: ⊥
+[alias] analysing function: pow
+[alias] May-aliases at the end of function pow: ⊥
+[alias] analysing function: powf
+[alias] May-aliases at the end of function powf: ⊥
+[alias] analysing function: putenv
+[alias] May-aliases at the end of function putenv: ⊥
+[alias] analysing function: qsort
+[alias] May-aliases at the end of function qsort: ⊥
+[alias] analysing function: quick_exit
+[alias] May-aliases at the end of function quick_exit: ⊥
+[alias] analysing function: rand
+[alias] May-aliases at the end of function rand: ⊥
+[alias] analysing function: random
+[alias] May-aliases at the end of function random: ⊥
+[alias] analysing function: realloc
+[alias] May-aliases at the end of function realloc: ⊥
+[alias] analysing function: reallocarray
+[alias] May-aliases at the end of function reallocarray: ⊥
+[alias] analysing function: round
+[alias] May-aliases at the end of function round: ⊥
+[alias] analysing function: roundf
+[alias] May-aliases at the end of function roundf: ⊥
+[alias] analysing function: roundl
+[alias] May-aliases at the end of function roundl: ⊥
+[alias] analysing function: seed48
+[alias] May-aliases at the end of function seed48: ⊥
+[alias] analysing function: setenv
+[alias] May-aliases at the end of function setenv: ⊥
+[alias] analysing function: sin
+[alias] May-aliases at the end of function sin: ⊥
+[alias] analysing function: sinf
+[alias] May-aliases at the end of function sinf: ⊥
+[alias] analysing function: sinl
+[alias] May-aliases at the end of function sinl: ⊥
+[alias] analysing function: sqrt
+[alias] May-aliases at the end of function sqrt: ⊥
+[alias] analysing function: sqrtf
+[alias] May-aliases at the end of function sqrtf: ⊥
+[alias] analysing function: sqrtl
+[alias] May-aliases at the end of function sqrtl: ⊥
+[alias] analysing function: srand
+[alias] May-aliases at the end of function srand: ⊥
+[alias] analysing function: srand48
+[alias] May-aliases at the end of function srand48: ⊥
+[alias] analysing function: srandom
+[alias] May-aliases at the end of function srandom: ⊥
+[alias] analysing function: strtod
+[alias] May-aliases at the end of function strtod: ⊥
+[alias] analysing function: strtof
+[alias] May-aliases at the end of function strtof: ⊥
+[alias] analysing function: strtol
+[alias] May-aliases at the end of function strtol: ⊥
+[alias] analysing function: strtold
+[alias] May-aliases at the end of function strtold: ⊥
+[alias] analysing function: strtoll
+[alias] May-aliases at the end of function strtoll: ⊥
+[alias] analysing function: strtoul
+[alias] May-aliases at the end of function strtoul: ⊥
+[alias] analysing function: strtoull
+[alias] May-aliases at the end of function strtoull: ⊥
+[alias] analysing function: swap
+[alias] May-aliases at the end of function swap: <none>
+[alias] analysing function: system
+[alias] May-aliases at the end of function system: ⊥
+[alias] analysing function: tan
+[alias] May-aliases at the end of function tan: ⊥
+[alias] analysing function: tanf
+[alias] May-aliases at the end of function tanf: ⊥
+[alias] analysing function: tanl
+[alias] May-aliases at the end of function tanl: ⊥
+[alias] analysing function: trunc
+[alias] May-aliases at the end of function trunc: ⊥
+[alias] analysing function: truncf
+[alias] May-aliases at the end of function truncf: ⊥
+[alias] analysing function: truncl
+[alias] May-aliases at the end of function truncl: ⊥
+[alias] analysing function: unsetenv
+[alias] May-aliases at the end of function unsetenv: ⊥
+[alias] analysing function: wcstombs
+[alias] May-aliases at the end of function wcstombs: ⊥
+[alias] analysing function: wctomb
+[alias] May-aliases at the end of function wctomb: ⊥
diff --git a/src/plugins/alias/tests/real_world/oracle/function1_v2.res.oracle b/src/plugins/alias/tests/real_world/oracle/function1_v2.res.oracle
new file mode 100644
index 0000000000000000000000000000000000000000..5a63a549c73983681d3129eca2bb7d2d3191a2a3
--- /dev/null
+++ b/src/plugins/alias/tests/real_world/oracle/function1_v2.res.oracle
@@ -0,0 +1,133 @@
+[kernel] Parsing function1_v2.c (with preprocessing)
+[alias] analysing function: _Exit
+[alias] May-aliases at the end of function _Exit: ⊥
+[alias] analysing function: abort
+[alias] May-aliases at the end of function abort: ⊥
+[alias] analysing function: abs
+[alias] May-aliases at the end of function abs: ⊥
+[alias] analysing function: alias
+[alias] analysing instruction: *x = *y;
+[alias] May-aliases after instruction  *x = *y;  are  {x, y}
+[alias] May-aliases at the end of function alias: {x, y}
+[alias] analysing function: at_quick_exit
+[alias] May-aliases at the end of function at_quick_exit: ⊥
+[alias] analysing function: atexit
+[alias] May-aliases at the end of function atexit: ⊥
+[alias] analysing function: atof
+[alias] May-aliases at the end of function atof: ⊥
+[alias] analysing function: atoi
+[alias] May-aliases at the end of function atoi: ⊥
+[alias] analysing function: atol
+[alias] May-aliases at the end of function atol: ⊥
+[alias] analysing function: atoll
+[alias] May-aliases at the end of function atoll: ⊥
+[alias] analysing function: bsearch
+[alias] May-aliases at the end of function bsearch: ⊥
+[alias] analysing function: calloc
+[alias] May-aliases at the end of function calloc: ⊥
+[alias] analysing function: div
+[alias] May-aliases at the end of function div: ⊥
+[alias] analysing function: drand48
+[alias] May-aliases at the end of function drand48: ⊥
+[alias] analysing function: erand48
+[alias] May-aliases at the end of function erand48: ⊥
+[alias] analysing function: exit
+[alias] May-aliases at the end of function exit: ⊥
+[alias] analysing function: free
+[alias] May-aliases at the end of function free: ⊥
+[alias] analysing function: getenv
+[alias] May-aliases at the end of function getenv: ⊥
+[alias] analysing function: jrand48
+[alias] May-aliases at the end of function jrand48: ⊥
+[alias] analysing function: labs
+[alias] May-aliases at the end of function labs: ⊥
+[alias] analysing function: lcong48
+[alias] May-aliases at the end of function lcong48: ⊥
+[alias] analysing function: ldiv
+[alias] May-aliases at the end of function ldiv: ⊥
+[alias] analysing function: llabs
+[alias] May-aliases at the end of function llabs: ⊥
+[alias] analysing function: lldiv
+[alias] May-aliases at the end of function lldiv: ⊥
+[alias] analysing function: lrand48
+[alias] May-aliases at the end of function lrand48: ⊥
+[alias] analysing function: main
+[alias] analysing instruction: int *a = malloc(sizeof(int));
+[alias] May-aliases after instruction  int *a = malloc(sizeof(int));  are  <none>
+[alias] analysing instruction: *a = 0;
+[alias] May-aliases after instruction  *a = 0;  are  <none>
+[alias] analysing instruction: int *b = malloc(sizeof(int));
+[alias] May-aliases after instruction  int *b = malloc(sizeof(int));  are  <none>
+[alias] analysing instruction: *b = 42;
+[alias] May-aliases after instruction  *b = 42;  are  <none>
+[alias] analysing instruction: alias(& a,& b);
+[alias] May-aliases after instruction  alias(& a,& b);  are  {&a, &b}  {a, b}
+[alias] analysing instruction: *a = 7;
+[alias] May-aliases after instruction  *a = 7;  are  {&a, &b}  {a, b}
+[alias] analysing instruction: __retres = 0;
+[alias] May-aliases after instruction  __retres = 0;  are  {&a, &b}  {a, b}
+[alias] May-aliases at the end of function main: {&a, &b}  {a, b}
+[alias] analysing function: malloc
+[alias] May-aliases at the end of function malloc: ⊥
+[alias] analysing function: mblen
+[alias] May-aliases at the end of function mblen: ⊥
+[alias] analysing function: mbstowcs
+[alias] May-aliases at the end of function mbstowcs: ⊥
+[alias] analysing function: mbtowc
+[alias] May-aliases at the end of function mbtowc: ⊥
+[alias] analysing function: mkstemp
+[alias] May-aliases at the end of function mkstemp: ⊥
+[alias] analysing function: mkstemps
+[alias] May-aliases at the end of function mkstemps: ⊥
+[alias] analysing function: mrand48
+[alias] May-aliases at the end of function mrand48: ⊥
+[alias] analysing function: nrand48
+[alias] May-aliases at the end of function nrand48: ⊥
+[alias] analysing function: posix_memalign
+[alias] May-aliases at the end of function posix_memalign: ⊥
+[alias] analysing function: putenv
+[alias] May-aliases at the end of function putenv: ⊥
+[alias] analysing function: qsort
+[alias] May-aliases at the end of function qsort: ⊥
+[alias] analysing function: quick_exit
+[alias] May-aliases at the end of function quick_exit: ⊥
+[alias] analysing function: rand
+[alias] May-aliases at the end of function rand: ⊥
+[alias] analysing function: random
+[alias] May-aliases at the end of function random: ⊥
+[alias] analysing function: realloc
+[alias] May-aliases at the end of function realloc: ⊥
+[alias] analysing function: reallocarray
+[alias] May-aliases at the end of function reallocarray: ⊥
+[alias] analysing function: seed48
+[alias] May-aliases at the end of function seed48: ⊥
+[alias] analysing function: setenv
+[alias] May-aliases at the end of function setenv: ⊥
+[alias] analysing function: srand
+[alias] May-aliases at the end of function srand: ⊥
+[alias] analysing function: srand48
+[alias] May-aliases at the end of function srand48: ⊥
+[alias] analysing function: srandom
+[alias] May-aliases at the end of function srandom: ⊥
+[alias] analysing function: strtod
+[alias] May-aliases at the end of function strtod: ⊥
+[alias] analysing function: strtof
+[alias] May-aliases at the end of function strtof: ⊥
+[alias] analysing function: strtol
+[alias] May-aliases at the end of function strtol: ⊥
+[alias] analysing function: strtold
+[alias] May-aliases at the end of function strtold: ⊥
+[alias] analysing function: strtoll
+[alias] May-aliases at the end of function strtoll: ⊥
+[alias] analysing function: strtoul
+[alias] May-aliases at the end of function strtoul: ⊥
+[alias] analysing function: strtoull
+[alias] May-aliases at the end of function strtoull: ⊥
+[alias] analysing function: system
+[alias] May-aliases at the end of function system: ⊥
+[alias] analysing function: unsetenv
+[alias] May-aliases at the end of function unsetenv: ⊥
+[alias] analysing function: wcstombs
+[alias] May-aliases at the end of function wcstombs: ⊥
+[alias] analysing function: wctomb
+[alias] May-aliases at the end of function wctomb: ⊥
diff --git a/src/plugins/alias/tests/test_config b/src/plugins/alias/tests/test_config
new file mode 100644
index 0000000000000000000000000000000000000000..e14c0a6d24720b60c9a29eb36a4bb4cd432e5b55
--- /dev/null
+++ b/src/plugins/alias/tests/test_config
@@ -0,0 +1,2 @@
+PLUGIN: alias
+OPT: -alias -alias-verbose 3
diff --git a/src/plugins/alias/tests/unsupported/asm.c b/src/plugins/alias/tests/unsupported/asm.c
new file mode 100644
index 0000000000000000000000000000000000000000..ba2e80cb752079eb603e6a82baf938ea40e72804
--- /dev/null
+++ b/src/plugins/alias/tests/unsupported/asm.c
@@ -0,0 +1,4 @@
+int main () {
+	asm("movq %0, %%rsi");
+	return 0;
+}
diff --git a/src/plugins/alias/tests/unsupported/explicit_pointer.c b/src/plugins/alias/tests/unsupported/explicit_pointer.c
new file mode 100644
index 0000000000000000000000000000000000000000..a0b5e8f2c516d9f042cb31a6870bf803430a770c
--- /dev/null
+++ b/src/plugins/alias/tests/unsupported/explicit_pointer.c
@@ -0,0 +1,3 @@
+int main () {
+  return *((int*)1);
+}
diff --git a/src/plugins/alias/tests/unsupported/pointer_call.c b/src/plugins/alias/tests/unsupported/pointer_call.c
new file mode 100644
index 0000000000000000000000000000000000000000..448ec0f752f68628673aafccdb70969d51f5a381
--- /dev/null
+++ b/src/plugins/alias/tests/unsupported/pointer_call.c
@@ -0,0 +1,8 @@
+int f () {
+  return 0;
+}
+
+int main () {
+  int (*p)() = &f;
+  return ((*p)());
+}