================ @@ -0,0 +1,182 @@ +// NOTE: Assertions have been autogenerated by utils/update_cc_test_checks.py UTC_ARGS: --version 5 +// RUN: %clang_cc1 -triple x86_64-unknown-unknown -O2 -emit-llvm -o - %s | FileCheck %s --check-prefix=X86_64 +// RUN: %clang_cc1 -triple i386-unknown-unknown -O2 -emit-llvm -o - %s | FileCheck %s --check-prefix=I386 + +struct a { + char x; + short count; + int array[] __attribute__((counted_by(count))); +}; + +// X86_64-LABEL: define dso_local noalias noundef ptr @test1( +// X86_64-SAME: i32 noundef [[SIZE:%.*]]) local_unnamed_addr #[[ATTR0:[0-9]+]] { +// X86_64-NEXT: [[ENTRY:.*:]] +// X86_64-NEXT: [[CONV:%.*]] = sext i32 [[SIZE]] to i64 +// X86_64-NEXT: [[MUL:%.*]] = shl nsw i64 [[CONV]], 2 +// X86_64-NEXT: [[ADD:%.*]] = add nsw i64 [[MUL]], 4 +// X86_64-NEXT: [[CALL:%.*]] = tail call ptr @malloc(i64 noundef [[ADD]]) #[[ATTR3:[0-9]+]] +// X86_64-NEXT: [[CONV1:%.*]] = trunc i32 [[SIZE]] to i16 +// X86_64-NEXT: [[DOT_COUNTED_BY_GEP:%.*]] = getelementptr inbounds i8, ptr [[CALL]], i64 2 +// X86_64-NEXT: store i16 [[CONV1]], ptr [[DOT_COUNTED_BY_GEP]], align 2, !tbaa [[TBAA2:![0-9]+]] +// X86_64-NEXT: ret ptr [[CALL]] +// +// I386-LABEL: define dso_local noalias noundef ptr @test1( +// I386-SAME: i32 noundef [[SIZE:%.*]]) local_unnamed_addr #[[ATTR0:[0-9]+]] { +// I386-NEXT: [[ENTRY:.*:]] +// I386-NEXT: [[MUL:%.*]] = shl i32 [[SIZE]], 2 +// I386-NEXT: [[ADD:%.*]] = add i32 [[MUL]], 4 +// I386-NEXT: [[CALL:%.*]] = tail call ptr @malloc(i32 noundef [[ADD]]) #[[ATTR3:[0-9]+]] +// I386-NEXT: [[CONV:%.*]] = trunc i32 [[SIZE]] to i16 +// I386-NEXT: [[DOT_COUNTED_BY_GEP:%.*]] = getelementptr inbounds i8, ptr [[CALL]], i32 2 +// I386-NEXT: store i16 [[CONV]], ptr [[DOT_COUNTED_BY_GEP]], align 2, !tbaa [[TBAA3:![0-9]+]] +// I386-NEXT: ret ptr [[CALL]] +// +struct a *test1(int size) { + struct a *p = __builtin_malloc(sizeof(struct a) + sizeof(int) * size); + + *__builtin_counted_by_ref(p->array) = size; + *__builtin_counted_by_ref(&p->array[0]) = size; + return p; +} + +struct b { + int _filler; + struct { + int __filler; + struct { + int ___filler; + struct { + char count; + }; + }; + }; + struct { + int filler_; + struct { + int filler__; + struct { + long array[] __attribute__((counted_by(count))); + }; + }; + }; +}; + +// X86_64-LABEL: define dso_local noalias noundef ptr @test2( +// X86_64-SAME: i32 noundef [[SIZE:%.*]]) local_unnamed_addr #[[ATTR0]] { +// X86_64-NEXT: [[ENTRY:.*:]] +// X86_64-NEXT: [[CONV:%.*]] = sext i32 [[SIZE]] to i64 +// X86_64-NEXT: [[MUL:%.*]] = shl nsw i64 [[CONV]], 2 +// X86_64-NEXT: [[ADD:%.*]] = add nsw i64 [[MUL]], 4 +// X86_64-NEXT: [[CALL:%.*]] = tail call ptr @malloc(i64 noundef [[ADD]]) #[[ATTR3]] +// X86_64-NEXT: [[CONV1:%.*]] = trunc i32 [[SIZE]] to i8 +// X86_64-NEXT: [[DOT_COUNTED_BY_GEP:%.*]] = getelementptr inbounds i8, ptr [[CALL]], i64 12 +// X86_64-NEXT: store i8 [[CONV1]], ptr [[DOT_COUNTED_BY_GEP]], align 1, !tbaa [[TBAA6:![0-9]+]] +// X86_64-NEXT: ret ptr [[CALL]] +// +// I386-LABEL: define dso_local noalias noundef ptr @test2( +// I386-SAME: i32 noundef [[SIZE:%.*]]) local_unnamed_addr #[[ATTR0]] { +// I386-NEXT: [[ENTRY:.*:]] +// I386-NEXT: [[MUL:%.*]] = shl i32 [[SIZE]], 2 +// I386-NEXT: [[ADD:%.*]] = add i32 [[MUL]], 4 +// I386-NEXT: [[CALL:%.*]] = tail call ptr @malloc(i32 noundef [[ADD]]) #[[ATTR3]] +// I386-NEXT: [[CONV:%.*]] = trunc i32 [[SIZE]] to i8 +// I386-NEXT: [[DOT_COUNTED_BY_GEP:%.*]] = getelementptr inbounds i8, ptr [[CALL]], i32 12 +// I386-NEXT: store i8 [[CONV]], ptr [[DOT_COUNTED_BY_GEP]], align 1, !tbaa [[TBAA7:![0-9]+]] +// I386-NEXT: ret ptr [[CALL]] +// +struct b *test2(int size) { + struct b *p = __builtin_malloc(sizeof(struct a) + sizeof(int) * size); + + *__builtin_counted_by_ref(p->array) = size; + *__builtin_counted_by_ref(&p->array[0]) = size; + return p; +} + +struct c { + char x; + short count; + int array[]; +}; + +// X86_64-LABEL: define dso_local noalias noundef ptr @test3( +// X86_64-SAME: i32 noundef [[SIZE:%.*]]) local_unnamed_addr #[[ATTR2:[0-9]+]] { +// X86_64-NEXT: [[ENTRY:.*:]] +// X86_64-NEXT: [[CONV:%.*]] = sext i32 [[SIZE]] to i64 +// X86_64-NEXT: [[MUL:%.*]] = shl nsw i64 [[CONV]], 2 +// X86_64-NEXT: [[ADD:%.*]] = add nsw i64 [[MUL]], 4 +// X86_64-NEXT: [[CALL:%.*]] = tail call ptr @malloc(i64 noundef [[ADD]]) #[[ATTR3]] +// X86_64-NEXT: ret ptr [[CALL]] +// +// I386-LABEL: define dso_local noalias noundef ptr @test3( +// I386-SAME: i32 noundef [[SIZE:%.*]]) local_unnamed_addr #[[ATTR2:[0-9]+]] { +// I386-NEXT: [[ENTRY:.*:]] +// I386-NEXT: [[MUL:%.*]] = shl i32 [[SIZE]], 2 +// I386-NEXT: [[ADD:%.*]] = add i32 [[MUL]], 4 +// I386-NEXT: [[CALL:%.*]] = tail call ptr @malloc(i32 noundef [[ADD]]) #[[ATTR3]] +// I386-NEXT: ret ptr [[CALL]] +// +struct c *test3(int size) { + struct c *p = __builtin_malloc(sizeof(struct c) + sizeof(int) * size); + unsigned long int __ignored; + + *_Generic( + __builtin_counted_by_ref(&p->array[0]), + void *: &__ignored, + default: __builtin_counted_by_ref(&p->array[0])) = size; + + return p; +} + +struct d { + char x; + short count; + int array[] __attribute__((counted_by(count))); +}; + +// X86_64-LABEL: define dso_local noalias noundef ptr @test4( +// X86_64-SAME: i32 noundef [[SIZE:%.*]], i32 noundef [[IDX:%.*]]) local_unnamed_addr #[[ATTR0]] { +// X86_64-NEXT: [[ENTRY:.*:]] +// X86_64-NEXT: [[CONV:%.*]] = sext i32 [[SIZE]] to i64 +// X86_64-NEXT: [[MUL:%.*]] = shl nsw i64 [[CONV]], 2 +// X86_64-NEXT: [[ADD:%.*]] = add nsw i64 [[MUL]], 4 +// X86_64-NEXT: [[CALL:%.*]] = tail call ptr @malloc(i64 noundef [[ADD]]) #[[ATTR3]] +// X86_64-NEXT: [[CONV1:%.*]] = trunc i32 [[SIZE]] to i16 +// X86_64-NEXT: [[DOT_COUNTED_BY_GEP:%.*]] = getelementptr inbounds i8, ptr [[CALL]], i64 2 +// X86_64-NEXT: store i16 [[CONV1]], ptr [[DOT_COUNTED_BY_GEP]], align 2, !tbaa [[TBAA2]] +// X86_64-NEXT: ret ptr [[CALL]] +// +// I386-LABEL: define dso_local noalias noundef ptr @test4( +// I386-SAME: i32 noundef [[SIZE:%.*]], i32 noundef [[IDX:%.*]]) local_unnamed_addr #[[ATTR0]] { +// I386-NEXT: [[ENTRY:.*:]] +// I386-NEXT: [[MUL:%.*]] = shl i32 [[SIZE]], 2 +// I386-NEXT: [[ADD:%.*]] = add i32 [[MUL]], 4 +// I386-NEXT: [[CALL:%.*]] = tail call ptr @malloc(i32 noundef [[ADD]]) #[[ATTR3]] +// I386-NEXT: [[CONV:%.*]] = trunc i32 [[SIZE]] to i16 +// I386-NEXT: [[DOT_COUNTED_BY_GEP:%.*]] = getelementptr inbounds i8, ptr [[CALL]], i32 2 +// I386-NEXT: store i16 [[CONV]], ptr [[DOT_COUNTED_BY_GEP]], align 2, !tbaa [[TBAA3]] +// I386-NEXT: ret ptr [[CALL]] +// +struct d *test4(int size, int idx) { + struct d *p = __builtin_malloc(sizeof(struct d) + sizeof(int) * size); + unsigned long int __ignored; + + *_Generic( + __builtin_counted_by_ref(&p->array[0]), + void *: &__ignored, + default: __builtin_counted_by_ref(&p->array[idx++])) = size; ---------------- rapidsna wrote:
Yes, upgrading to an error sounds good to me! Also, the message might need to be updated (since the side effect is not actually ignored). https://github.com/llvm/llvm-project/pull/114495 _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits