E3059

E3059 — An extern declaration of malloc, calloc, realloc, aligned_alloc or free whose type is not C's. The compiler calls these functions too, and it can share only a declaration of C's type. A size is a 64-bit integer: usize, i64 or u64. A pointer is a raw pointer to host memory. free returns nothing.

What the compiler reports

Error[E3059] at 23:3: extern fn `malloc` does not have the type of C's `malloc`. Declare it as `fn malloc(size : usize) -> *mut i8`.
Error[E3059] at 24:3: extern fn `calloc` does not have the type of C's `calloc`. Declare it as `fn calloc(count : usize, size : usize) -> *mut i8`.
Error[E3059] at 25:3: extern fn `realloc` does not have the type of C's `realloc`. Declare it as `fn realloc(ptr : *mut i8, size : usize) -> *mut i8`.
Error[E3059] at 26:3: extern fn `aligned_alloc` does not have the type of C's `aligned_alloc`. Declare it as `fn aligned_alloc(alignment : usize, size : usize) -> *mut i8`.
Error[E3059] at 27:3: extern fn `free` does not have the type of C's `free`. Declare it as `fn free(ptr : *mut i8) -> void`.

The fragments the test suite holds the compiler to. An ellipsis marks text the test does not constrain; the emitted message also carries a source location.

A program that triggers it

//
// Part of the Vx Project, under the Apache License v2.0 with LLVM Exceptions.
// See LICENSE for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
// A program that declares one of C's allocation functions must give it C's type, because the
// compiler calls these functions too. A size is a 64-bit integer, and `free` returns nothing.
// Each declaration below is wrong in one place, and gets the error at its own position. With a
// task in the program, the error used to come from MLIR, with no position.
//

// A 32-bit size, a 32-bit second size, a 32-bit unsigned size, a result that is not a pointer,
// and a result where C's `free` has none.
extern "C" {
  fn malloc(size : i32) -> *mut i32;
  fn calloc(count : usize, size : i32) -> *mut i8;
  fn realloc(ptr : *mut i8, size : u32) -> *mut i8;
  fn aligned_alloc(alignment : usize, size : usize) -> i64;
  fn free(ptr : *mut i8) -> i32;
}

fn main() -> i32 {
  let p : *mut i32 = unsafe { malloc(4) };
  unsafe { p[0] = 5; }
  let mut total : i32 = 0;
  tasks {
    let a = spawn {
      2
    };
    total = a.join();
  }
  print(total + unsafe { p[0] });
  return 0;
}

From tests/frontend/fail/c_allocator_declared_with_another_type.vx, which asserts this diagnostic on every commit.

Related