mirror of
https://github.com/llvm/llvm-project.git
synced 2025-04-26 04:16:10 +00:00

The __builtin_counted_by_ref builtin is used on a flexible array pointer and returns a pointer to the "counted_by" attribute's COUNT argument, which is a field in the same non-anonymous struct as the flexible array member. This is useful for automatically setting the count field without needing the programmer's intervention. Otherwise it's possible to get this anti-pattern: ptr = alloc(<ty>, ..., COUNT); ptr->FAM[9] = 42; /* <<< Sanitizer will complain */ ptr->count = COUNT; To prevent this anti-pattern, the user can create an allocator that automatically performs the assignment: #define alloc(TY, FAM, COUNT) ({ \ TY __p = alloc(get_size(TY, COUNT)); \ if (__builtin_counted_by_ref(__p->FAM)) \ *__builtin_counted_by_ref(__p->FAM) = COUNT; \ __p; \ }) The builtin's behavior is heavily dependent upon the "counted_by" attribute existing. It's main utility is during allocation to avoid the above anti-pattern. If the flexible array member doesn't have that attribute, the builtin becomes a no-op. Therefore, if the flexible array member has a "count" field not referenced by "counted_by", it must be set explicitly after the allocation as this builtin will return a "nullptr" and the assignment will most likely be elided. --------- Co-authored-by: Bill Wendling <isanbard@gmail.com> Co-authored-by: Aaron Ballman <aaron@aaronballman.com>
24 lines
761 B
C
24 lines
761 B
C
// RUN: %clang_cc1 -triple x86_64-unknown-linux -ast-print %s -o - | FileCheck %s
|
|
|
|
typedef unsigned long int size_t;
|
|
|
|
int global_array[42];
|
|
int global_int;
|
|
|
|
struct fam_struct {
|
|
int x;
|
|
char count;
|
|
int array[] __attribute__((counted_by(count)));
|
|
};
|
|
|
|
// CHECK-LABEL: void test1(struct fam_struct *ptr, int size) {
|
|
// CHECK-NEXT: size_t __ignored_assignment;
|
|
// CHECK-NEXT: *_Generic(__builtin_counted_by_ref(ptr->array), void *: &__ignored_assignment, default: __builtin_counted_by_ref(ptr->array)) = 42;
|
|
void test1(struct fam_struct *ptr, int size) {
|
|
size_t __ignored_assignment;
|
|
|
|
*_Generic(__builtin_counted_by_ref(ptr->array),
|
|
void *: &__ignored_assignment,
|
|
default: __builtin_counted_by_ref(ptr->array)) = 42; // ok
|
|
}
|