| [d2ac7d5] | 1 | ## Options for safer void* handling # | 
|---|
|  | 2 | C allows implicit conversions between `void*` and other pointer types, as per | 
|---|
|  | 3 | section 6.3.2.3.1 of the standard. | 
|---|
|  | 4 | Making these implicit conversions explicit in Cforall would provide | 
|---|
|  | 5 | significant type-safety benefits, and is precedented in C++. | 
|---|
|  | 6 | A weaker version of this proposal would be to allow implicit conversions to | 
|---|
|  | 7 | `void*` (as a sort of "top type" for all pointer types), but to make the | 
|---|
|  | 8 | unsafe conversion from `void*` back to a concrete pointer type an explicit | 
|---|
|  | 9 | conversion. | 
|---|
|  | 10 | However, `int *p = malloc( sizeof(int) );` and friends are hugely common | 
|---|
|  | 11 | in C code, and rely on the unsafe implicit conversion from the `void*` return | 
|---|
|  | 12 | type of `malloc` to the `int*` type of the variable - obviously it would be | 
|---|
|  | 13 | too much of a source-compatibility break to disallow this for C code. | 
|---|
|  | 14 | We do already need to wrap C code in an `extern "C"` block, though, so it is | 
|---|
|  | 15 | technically feasible to make the `void*` conversions implicit in C but | 
|---|
|  | 16 | explicit in Cforall. | 
|---|
|  | 17 |  | 
|---|
|  | 18 | As a possible mitigation for calling C code with `void*`-based APIs, pointers-to-dtype are | 
|---|
|  | 19 | calling-convention compatible with `void*`; we could read `void*` in function | 
|---|
|  | 20 | signatures as essentially a fresh dtype type variable, e.g: | 
|---|
|  | 21 |  | 
|---|
|  | 22 | void* malloc( size_t ) | 
|---|
|  | 23 | => forall(dtype T0) T0* malloc( size_t ) | 
|---|
|  | 24 | void qsort( void*, size_t, size_t, int (*)( const void*, const void* ) ) | 
|---|
|  | 25 | => forall(dtype T0, dtype T1, dtype T2) | 
|---|
|  | 26 | void qsort( T0*, size_t, size_t, int (*)( const T1*, const T2* ) ) | 
|---|
|  | 27 |  | 
|---|
|  | 28 | In this case, there would be no conversion needed to call `malloc`, just the | 
|---|
|  | 29 | polymorphic type binding. | 
|---|
|  | 30 | This should handle many of the uses of `void*` in C. | 
|---|
|  | 31 |  | 
|---|
|  | 32 | This feature would even allow us to leverage some of Cforall's type safety to write | 
|---|
|  | 33 | better declarations for legacy C API functions, like the following wrapper for | 
|---|
|  | 34 | `qsort`: | 
|---|
|  | 35 |  | 
|---|
|  | 36 | extern "C" { // turns off name-mangling so that this calls the C library | 
|---|
|  | 37 | // call-compatible type-safe qsort signature | 
|---|
|  | 38 | forall(dtype T) | 
|---|
|  | 39 | void qsort( T*, size_t, size_t, int (*)( const T*, const T* ) ); | 
|---|
|  | 40 |  | 
|---|
|  | 41 | // forbid type-unsafe C signature from resolving | 
|---|
|  | 42 | void qsort( void*, size_t, size_t, int (*)( const void*, const void* ) ) | 
|---|
|  | 43 | = delete; | 
|---|
|  | 44 | } | 
|---|