As we only briefly touched on this here, the expression can be a simple reference to a declaration, a constant (including calls to constant functions), or an arithmetic expression that does not have side effects. Therefore, the following examples will work:
// Single arithmetic expression without side effect
void foo(int tens, int ones, int *__counted_by(10 * tens + ones) ptr);
// Call to a const function
void const_foo(void) __attribute__((const));
int *__counted_by(const_foo()) var;
However, the current implementation doesn’t allow ternary operators, and we were planning to extend our specification to support ternary operators.
I’ve slightly adjusted the examples for C since the current proposal doesn’t support C++. An expression passed to a bounds annotation can refer to other members of the same struct, so the following example is allowed.
struct S {
int n;
// Allowed: Counted by a member variable
int *__counted_by(n) ptr;
};
However, referring to a member of another struct, including nested structs (or the base struct) is not allowed. This is because of complications to maintain the soundness of the count value in a different struct. In the following example, bp
, which is a pointer to Base
, is used to update n
. This could potentially break the correctness of the bounds information if the dynamic type of bp
is Derived
(or aliased with a pointer to Derived
) but Sema won’t be able to identify this.
struct Base {
int n;
};
struct Derived {
struct Base header;
// Not allowed: Counted by a member of other struct member
int * __counted_by(header.n) ptr;
};
void foo(struct Base *bp, struct Derived *dp) {
// Potentially unsafe and compiler doesn't know if `bp` and `dp` alias
bp->n++;
}
Currently, the extension does not support the patten of “counted by an array element” to support the example below, but we are open to hearing about use cases and suggestions to extend the model.
// Not allowed: Counted by an array element
void func(int n, int array[static 2], int * __counted_by(array[n]) ptr);
-fbounds-safety
rejects any mismatched annotations for function redeclarations. As a result, the compiler reports errors for most of the examples provided below.
void foo(int n, int *ptr);
void foo(int n, int * __counted_by(n)) {} // error due to a bounds annotation mismatch
void bar(int n, int * __counted_by(n) ptr);
void bar(int n, int *ptr) {} // error due to a bounds annotation mismatch
// In File1.c
void baz(int n, int *ptr) {}
// In File2.c
void baz(int n, int * __counted_by(n) ptr); // missing an error as the compiler cannot see the other decl in File1.c
void quux(int n, int m, int * __counted_by(n) ptr);
void quux(int n, int m, int * __counted_by(m) ptr); // error due to a bounds annotation mismatch
void barf(int n, int m, int * __counted_by(n) ptr1, int *ptr2);
void barf(int n, int m, int *ptr1, int * __counted_by(m) ptr2); // error due to bounds annotation mismatches