diff --git a/src/plugins/value/domains/cvalue/builtins_malloc.ml b/src/plugins/value/domains/cvalue/builtins_malloc.ml
index 6af07c51781883bdf7d51cc74660b05aa2199c87..6b1c91f9f98e28883186f750e01ac87c693c7089 100644
--- a/src/plugins/value/domains/cvalue/builtins_malloc.ml
+++ b/src/plugins/value/domains/cvalue/builtins_malloc.ml
@@ -55,6 +55,11 @@ let () = Ast.add_monotonic_state Dynamic_Alloc_Bases.self
 
 (* -------------------------- Auxiliary functions  -------------------------- *)
 
+let current_call_site () =
+  match Value_util.call_stack () with
+  | (_kf, Kstmt stmt) :: _ -> stmt
+  | _ -> Cil.dummyStmt
+
 (* Remove some parts of the callstack:
    - Remove the bottom of the call tree until we get to the call site
      of the call to the first malloc function. The idea is that each of
@@ -469,13 +474,22 @@ let alloc_by_stack region prefix sizev state =
   in
   aux 0 all_vars
 
-let register_malloc ?replace name ?returns_null allocate_base =
+let choose_base_allocation () =
+  let open Eva_annotations in
+  match get_allocation (current_call_site ()) with
+  | Fresh -> alloc_fresh Strong
+  | Fresh_weak -> alloc_fresh Weak
+  | By_stack -> alloc_by_stack
+  | Imprecise -> fun region _ _ _ -> alloc_weakest_base region
+
+let register_malloc ?replace name ?returns_null prefix region =
   let builtin state args =
     let size = match args with
       | [ _, size, _ ] -> size
       | _ -> raise (Builtins.Invalid_nb_of_args 1)
     in
-    let new_base, max_alloc = allocate_base size state in
+    let allocate_base = choose_base_allocation () in
+    let new_base, max_alloc = allocate_base region prefix size state in
     let new_state = add_uninitialized state new_base max_alloc in
     let ret = V.inject new_base Ival.zero in
     let c_values = wrap_fallible_alloc ?returns_null ret state new_state in
@@ -489,22 +503,11 @@ let register_malloc ?replace name ?returns_null allocate_base =
   Builtins.register_builtin ?replace name builtin ~typ
 
 let () =
-  register_malloc "malloc_fresh"
-    (alloc_fresh Strong Base.Malloc "malloc");
-  register_malloc "malloc_fresh_weak"
-    (alloc_fresh Weak Base.Malloc "malloc");
-  register_malloc ~replace:"malloc" "malloc_by_stack"
-    (alloc_by_stack Base.Malloc "malloc");
-  register_malloc ~replace:"__fc_vla_alloc" "vla_alloc_by_stack"
-    (alloc_by_stack Base.VLA "malloc") ~returns_null:false;
-  register_malloc ~replace:"alloca" "alloca"
-    (alloc_by_stack Base.Alloca "alloca") ~returns_null:false;
-  register_malloc "malloc_imprecise"
-    (fun _ _ -> alloc_weakest_base Base.Malloc);
-  register_malloc "vla_alloc_imprecise"
-    (fun _ _ -> alloc_weakest_base Base.VLA);
-  register_malloc "alloca_imprecise"
-    (fun _ _ -> alloc_weakest_base Base.Alloca)
+  register_malloc ~replace:"malloc" "malloc" "malloc" Base.Malloc;
+  register_malloc ~replace:"__fc_vla_alloc" "vla_alloc" "malloc" Base.VLA
+    ~returns_null:false;
+  register_malloc ~replace:"alloca" "alloca" "alloca" Base.Alloca
+    ~returns_null:false
 
 (* --------------------------------- Calloc --------------------------------- *)
 
@@ -520,51 +523,42 @@ let alloc_size_ok intended_size =
     else Alarmset.False
   with Cvalue.V.Not_based_on_null -> Alarmset.Unknown (* garbled mix in size *)
 
-(* Builds and registers a builtin [name] for calloc, from the function
-   [allocate_base] that returns a base for the allocation. *)
-let register_calloc ?replace name allocate_base =
-  let builtin state args =
-    let nmemb, sizev =
-      match args with
-      | [(_, nmemb, _); (_, size, _)] -> nmemb, size
-      | _ -> raise (Builtins.Invalid_nb_of_args 2)
-    in
-    let alloc_size = Cvalue.V.mul nmemb sizev in
-    let size_ok = alloc_size_ok alloc_size in
-    if size_ok <> Alarmset.True then
-      Value_util.warning_once_current
-        "calloc out of bounds: assert(nmemb * size <= SIZE_MAX)";
-    let c_values =
-      if size_ok = Alarmset.False (* size always overflows *)
-      then [Eval_op.wrap_ptr Cvalue.V.singleton_zero, state]
-      else
-        let base, max_valid = allocate_base "calloc" alloc_size state in
-        let new_state = add_zeroes state base max_valid in
-        let returns_null =
-          if size_ok = Alarmset.Unknown then Some true else None
-        in
-        let ret = V.inject base Ival.zero in
-        wrap_fallible_alloc ?returns_null ret state new_state
-    in
-    { Value_types.c_values;
-      c_clobbered = Base.SetLattice.bottom;
-      c_cacheable = Value_types.NoCacheCallers;
-      c_from = None; }
+let calloc_builtin state args =
+  let nmemb, sizev =
+    match args with
+    | [(_, nmemb, _); (_, size, _)] -> nmemb, size
+    | _ -> raise (Builtins.Invalid_nb_of_args 2)
   in
-  let name = "Frama_C_" ^ name in
+  let size = Cvalue.V.mul nmemb sizev in
+  let size_ok = alloc_size_ok size in
+  if size_ok <> Alarmset.True then
+    Value_util.warning_once_current
+      "calloc out of bounds: assert(nmemb * size <= SIZE_MAX)";
+  let c_values =
+    if size_ok = Alarmset.False (* size always overflows *)
+    then [Eval_op.wrap_ptr Cvalue.V.singleton_zero, state]
+    else
+      let allocate_base = choose_base_allocation () in
+      let base, max_valid = allocate_base Base.Malloc "calloc" size state in
+      let new_state = add_zeroes state base max_valid in
+      let returns_null =
+        if size_ok = Alarmset.Unknown then Some true else None
+      in
+      let ret = V.inject base Ival.zero in
+      wrap_fallible_alloc ?returns_null ret state new_state
+  in
+  { Value_types.c_values;
+    c_clobbered = Base.SetLattice.bottom;
+    c_cacheable = Value_types.NoCacheCallers;
+    c_from = None; }
+
+let () =
+  let name = "Frama_C_calloc" in
   let typ () =
     let sizeof_typ = Cil.theMachine.Cil.typeOfSizeOf in
     Cil.voidPtrType, [ sizeof_typ; sizeof_typ ]
   in
-  Builtins.register_builtin ?replace name builtin ~typ
-
-let () =
-  register_calloc "calloc_fresh" (alloc_fresh Strong Base.Malloc);
-  register_calloc "calloc_fresh_weak" (alloc_fresh Weak Base.Malloc);
-  register_calloc ~replace:"calloc" "calloc_by_stack"
-    (alloc_by_stack Base.Malloc);
-  register_calloc "calloc_imprecise"
-    (fun _ _ _ -> alloc_weakest_base Base.Malloc)
+  Builtins.register_builtin ~replace:"calloc" name calloc_builtin ~typ
 
 (* ---------------------------------- Free ---------------------------------- *)