-
Notifications
You must be signed in to change notification settings - Fork 3
Conversion operations
C allow implicit conversion operations at assignments,
function call arguments, and function returns. For pointer types,
conversions between void *
pointers and other pointer types are
allowed. When an expected type differs from the actual type,
and one type is void *
and other type is a pointer type,
an impicit conversion is done.
The Checked C extension allows implicit conversions between different kinds of pointer types as these same program locations. The conversions must meet target bounds requirements at compile time and cannot be points of runtime failure.
A T *
can be converted to a _Ptr<T>
or _Array_ptr<T>
.
There are only a few kinds of T *
expressions that have
known bounds, though:
int x;
_Ptr<int> p = &x; // OK, &x meets bounds requirements.
_Array_ptr<int> p = &x; // OK, no bounds required.
_Array_ptr<int> p : count(1) = &x; // OK, &x meets bounds requirements.
_Array_ptr<int> p : count(2) = &x; // Error, &x does not meet bounds requirements.
int arr[10];
_Ptr<int> r = arr; // OK, arr meets bounds requirements.
_Array_ptr<int> r = arr; // OK, no bounds required.
_Array_ptr<int> r : count(10) = r; // OK, arr meets bounds requirements.
_Array_ptr<int> r : count(11) = r; // Error, x does not meet bounds requirements.
f(int *x) {
_Ptr<int> p = x; // Error, x does not bounds requirements for Ptr.
_Array_ptr<int> r : count(1) = x; // Error, x does not bounds requirement.
}
Some conversions between checked pointers to the same type are allowed:
-
_Ptr<T>
can be converted to_Array_ptr<T>
-
_Array_ptr<T>
can be converted to_Ptr<T>
-
_Nt_array_ptr<T>
can be converted to_Ptr<T>
or_Array_ptr<T>
.
// Implicit conversion from _Ptr<int> to _Array_ptr<int>
void f(_Array_ptr<int> a count(len), int len);
void g(_Ptr<int> b) {
f(b, 1);
}
_Array_ptr<int> c : count(5);
_Ptr<int> d = c + 2;
Implicit conversions from checked pointer types to unchecked pointer types are allowed only at bounds-safe interfaces, where the expected checked bounds or types have been declared. Otherwise they are not allowed.
There are 3 conversion operators between pointer types in the Checked C extension.
In the descriptions below, the type D
is the result type and must be a pointer type.
The expression e must have pointer or integer type. The value of each conversion operation
is the value of e reinterpreted bitwise as a value of type D
.
- C-style casts, given by
(D)
e. IfD
is_Ptr<T>
orT *
, e must have space for a value of typeT
. This must be provable at compile-time. Runtime failures cannot occur at these casts. - Dynamically-checked bounds casts, given by
_Dynamic_bounds_cast<T>(
e,
bounds-expr)
. The bounds of e are checked at runtime against bounds-expr. If the bounds are not satisfied, a runtime fault is signalled. IfD
is a_Ptr<T>
orT *
type, bounds-expr is omitted and the bounds are for a single element of typeT
. Note that for count bounds expressions, bounds-expr are the bounds for the value at the new typeT
, not the original type of e. - Trusted bounds casts, given by
_Assume_bounds_cast(
e,
bounds-expr)
. The bounds of the resulting expression are assumed to be bounds-expr. If T is a_Ptr<S>
orS *
type, bounds-expr is omitted.
Here are examples:
// Reinterpret a pointer to an array of characters as a pointer to an integer.
_Array_ptr<char> a : count(12) = ...
_Ptr<int> b = (_Ptr<int>) a;
// Reinterpret pointers to characters as pointers to integers.
// lb and ub have bound(unknown), so they cannot be used to access memory.
_Array_ptr<int> lb = (_Array_ptr<int>) a;
_Array_ptr<int> ub = (_Array_ptr<int>) (b + 12);
// Reinterpret a pointer to an array of characters as a pointer to an
// array of integers. This will fail at runtime if sizeof(int) > 3.
_Array_ptr<int> c : count(3) =
_Dynamic_bounds_cast<_Array_ptr<int>>(a, count(3));
// Create a checked_pointer to a hardware buffer.
unsigned int hardware_buf = 0xf0000;
_Array_ptr<char> d : count(4096) =
_Assume_bounds_cast<_Array_ptr<char>>(hardware_buf, 4096);
Checked C Wiki