diff options
Diffstat (limited to 'clang/test')
40 files changed, 2048 insertions, 71 deletions
diff --git a/clang/test/C/C2y/n3525.c b/clang/test/C/C2y/n3525.c new file mode 100644 index 0000000..428df23 --- /dev/null +++ b/clang/test/C/C2y/n3525.c @@ -0,0 +1,30 @@ +// RUN: %clang_cc1 -verify -std=c2y -Wall -pedantic %s +// RUN: %clang_cc1 -verify -std=c23 -Wall -pedantic %s + +/* WG14 N3525: Yes + * static_assert without UB + * + * Ensures that a static_assert declaration cannot defer to runtime; it must + * take an integer constant expression that is resolved at compile time. + * + * Note: implementations are free to extend what is a valid integer constant + * expression, and Clang (and GCC) does so. So this test is validating that + * we quietly accept a pasing assertion, loudly reject a failing assertion, and + * issue a pedantic diagnostic for the extension case. + */ + +static_assert(1); // Okay + +static_assert(0); // expected-error {{static assertion failed}} + +extern int a; +static_assert(1 || a); // expected-warning {{expression is not an integer constant expression; folding it to a constant is a GNU extension}} + +static_assert(a); // expected-error {{static assertion expression is not an integral constant expression}} +static_assert(0 || a); // expected-error {{static assertion expression is not an integral constant expression}} + +// Note, there is no CodeGen test for this; we have existing tests for the ICE +// extension, so the pedantic warning is sufficient to verify we're not +// emitting code which reads 'a' in '1 || a' because of the folding, and +// there's no way to generate code for reading 'a' in '0 || a' because of the +// error. diff --git a/clang/test/CIR/CodeGen/object-size-flex-array.c b/clang/test/CIR/CodeGen/object-size-flex-array.c new file mode 100644 index 0000000..74229fd --- /dev/null +++ b/clang/test/CIR/CodeGen/object-size-flex-array.c @@ -0,0 +1,317 @@ +// RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -O2 -fclangir -emit-cir %s -o %t.cir +// RUN: FileCheck --input-file=%t.cir %s --check-prefix=CIR --check-prefix=CIR-NO-STRICT +// RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -O2 -fclangir -emit-llvm -disable-llvm-passes %s -o %t-cir.ll +// RUN: FileCheck --input-file=%t-cir.ll %s --check-prefix=LLVM --check-prefix=LLVM-NO-STRICT +// RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -O2 -emit-llvm -disable-llvm-passes %s -o %t.ll +// RUN: FileCheck --input-file=%t.ll %s --check-prefix=OGCG --check-prefix=OGCG-NO-STRICT + +// RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -O2 -fclangir -fstrict-flex-arrays=0 -emit-cir %s -o %t-strict-0.cir +// RUN: FileCheck --input-file=%t-strict-0.cir %s --check-prefix=CIR --check-prefix=CIR-STRICT-0 +// RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -O2 -fclangir -fstrict-flex-arrays=0 -emit-llvm -disable-llvm-passes %s -o %t-cir-strict-0.ll +// RUN: FileCheck --input-file=%t-cir-strict-0.ll %s --check-prefix=LLVM --check-prefix=LLVM-STRICT-0 +// RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -O2 -fstrict-flex-arrays=0 -emit-llvm -disable-llvm-passes %s -o %t-strict-0.ll +// RUN: FileCheck --input-file=%t-strict-0.ll %s --check-prefix=OGCG --check-prefix=OGCG-STRICT-0 + +// RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -O2 -fclangir -fstrict-flex-arrays=1 -emit-cir %s -o %t-strict-1.cir +// RUN: FileCheck --input-file=%t-strict-1.cir %s --check-prefix=CIR --check-prefix=CIR-STRICT-1 +// RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -O2 -fclangir -fstrict-flex-arrays=1 -emit-llvm -disable-llvm-passes %s -o %t-cir-strict-1.ll +// RUN: FileCheck --input-file=%t-cir-strict-1.ll %s --check-prefix=LLVM --check-prefix=LLVM-STRICT-1 +// RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -O2 -fstrict-flex-arrays=1 -emit-llvm -disable-llvm-passes %s -o %t-strict-1.ll +// RUN: FileCheck --input-file=%t-strict-1.ll %s --check-prefix=OGCG --check-prefix=OGCG-STRICT-1 + +// RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -O2 -fclangir -fstrict-flex-arrays=2 -emit-cir %s -o %t-strict-2.cir +// RUN: FileCheck --input-file=%t-strict-2.cir %s --check-prefix=CIR --check-prefix=CIR-STRICT-2 +// RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -O2 -fclangir -fstrict-flex-arrays=2 -emit-llvm -disable-llvm-passes %s -o %t-cir-strict-2.ll +// RUN: FileCheck --input-file=%t-cir-strict-2.ll %s --check-prefix=LLVM --check-prefix=LLVM-STRICT-2 +// RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -O2 -fstrict-flex-arrays=2 -emit-llvm -disable-llvm-passes %s -o %t-strict-2.ll +// RUN: FileCheck --input-file=%t-strict-2.ll %s --check-prefix=OGCG --check-prefix=OGCG-STRICT-2 + +// RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -O2 -fclangir -fstrict-flex-arrays=3 -emit-cir %s -o %t-strict-3.cir +// RUN: FileCheck --input-file=%t-strict-3.cir %s --check-prefix=CIR --check-prefix=CIR-STRICT-3 +// RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -O2 -fclangir -fstrict-flex-arrays=3 -emit-llvm -disable-llvm-passes %s -o %t-cir-strict-3.ll +// RUN: FileCheck --input-file=%t-cir-strict-3.ll %s --check-prefix=LLVM --check-prefix=LLVM-STRICT-3 +// RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -O2 -fstrict-flex-arrays=3 -emit-llvm -disable-llvm-passes %s -o %t-strict-3.ll +// RUN: FileCheck --input-file=%t-strict-3.ll %s --check-prefix=OGCG --check-prefix=OGCG-STRICT-3 + +#define OBJECT_SIZE_BUILTIN __builtin_object_size + +typedef struct { + float f; + double c[]; +} foo_t; + +typedef struct { + float f; + double c[0]; +} foo0_t; + +typedef struct { + float f; + double c[1]; +} foo1_t; + +typedef struct { + float f; + double c[2]; +} foo2_t; + +// CIR-LABEL: @bar +// LLVM-LABEL: @bar( +// OGCG-LABEL: @bar( +unsigned bar(foo_t *f) { + // CIR-NO-STRICT: cir.objsize max nullunknown {{.*}} : !cir.ptr<!void> -> !u64i + // CIR-STRICT-0: cir.objsize max nullunknown {{.*}} : !cir.ptr<!void> -> !u64i + // CIR-STRICT-1: cir.objsize max nullunknown {{.*}} : !cir.ptr<!void> -> !u64i + // CIR-STRICT-2: cir.objsize max nullunknown {{.*}} : !cir.ptr<!void> -> !u64i + // CIR-STRICT-3: cir.objsize max nullunknown {{.*}} : !cir.ptr<!void> -> !u64i + // LLVM-NO-STRICT: llvm.objectsize.i64.p0(ptr {{.*}}, i1 false, i1 true, i1 false) + // LLVM-STRICT-0: llvm.objectsize.i64.p0(ptr {{.*}}, i1 false, i1 true, i1 false) + // LLVM-STRICT-1: llvm.objectsize.i64.p0(ptr {{.*}}, i1 false, i1 true, i1 false) + // LLVM-STRICT-2: llvm.objectsize.i64.p0(ptr {{.*}}, i1 false, i1 true, i1 false) + // LLVM-STRICT-3: llvm.objectsize.i64.p0(ptr {{.*}}, i1 false, i1 true, i1 false) + // OGCG-NO-STRICT: llvm.objectsize.i64.p0(ptr {{.*}}, i1 false, i1 true, i1 false) + // OGCG-STRICT-0: llvm.objectsize.i64.p0(ptr {{.*}}, i1 false, i1 true, i1 false) + // OGCG-STRICT-1: llvm.objectsize.i64.p0(ptr {{.*}}, i1 false, i1 true, i1 false) + // OGCG-STRICT-2: llvm.objectsize.i64.p0(ptr {{.*}}, i1 false, i1 true, i1 false) + // OGCG-STRICT-3: llvm.objectsize.i64.p0(ptr {{.*}}, i1 false, i1 true, i1 false) + return OBJECT_SIZE_BUILTIN(f->c, 1); +} + +// CIR-LABEL: @bar0 +// LLVM-LABEL: @bar0( +// OGCG-LABEL: @bar0( +unsigned bar0(foo0_t *f) { + // CIR-NO-STRICT: cir.objsize max nullunknown {{.*}} : !cir.ptr<!void> -> !u64i + // CIR-STRICT-0: cir.objsize max nullunknown {{.*}} : !cir.ptr<!void> -> !u64i + // CIR-STRICT-1: cir.objsize max nullunknown {{.*}} : !cir.ptr<!void> -> !u64i + // CIR-STRICT-2: cir.objsize max nullunknown {{.*}} : !cir.ptr<!void> -> !u64i + // CIR-STRICT-3: cir.const #cir.int<0> + // LLVM-NO-STRICT: llvm.objectsize.i64.p0(ptr {{.*}}, i1 false, i1 true, i1 false) + // LLVM-STRICT-0: llvm.objectsize.i64.p0(ptr {{.*}}, i1 false, i1 true, i1 false) + // LLVM-STRICT-1: llvm.objectsize.i64.p0(ptr {{.*}}, i1 false, i1 true, i1 false) + // LLVM-STRICT-2: llvm.objectsize.i64.p0(ptr {{.*}}, i1 false, i1 true, i1 false) + // LLVM-STRICT-3: store i32 0 + // OGCG-NO-STRICT: llvm.objectsize.i64.p0(ptr {{.*}}, i1 false, i1 true, i1 false) + // OGCG-STRICT-0: llvm.objectsize.i64.p0(ptr {{.*}}, i1 false, i1 true, i1 false) + // OGCG-STRICT-1: llvm.objectsize.i64.p0(ptr {{.*}}, i1 false, i1 true, i1 false) + // OGCG-STRICT-2: llvm.objectsize.i64.p0(ptr {{.*}}, i1 false, i1 true, i1 false) + // OGCG-STRICT-3: ret i32 0 + return OBJECT_SIZE_BUILTIN(f->c, 1); +} + +// CIR-LABEL: @bar1 +// LLVM-LABEL: @bar1( +// OGCG-LABEL: @bar1( +unsigned bar1(foo1_t *f) { + // CIR-NO-STRICT: cir.objsize max nullunknown {{.*}} : !cir.ptr<!void> -> !u64i + // CIR-STRICT-0: cir.objsize max nullunknown {{.*}} : !cir.ptr<!void> -> !u64i + // CIR-STRICT-1: cir.objsize max nullunknown {{.*}} : !cir.ptr<!void> -> !u64i + // CIR-STRICT-2: cir.const #cir.int<8> + // CIR-STRICT-3: cir.const #cir.int<8> + // LLVM-NO-STRICT: llvm.objectsize.i64.p0(ptr {{.*}}, i1 false, i1 true, i1 false) + // LLVM-STRICT-0: llvm.objectsize.i64.p0(ptr {{.*}}, i1 false, i1 true, i1 false) + // LLVM-STRICT-1: llvm.objectsize.i64.p0(ptr {{.*}}, i1 false, i1 true, i1 false) + // LLVM-STRICT-2: store i32 8 + // LLVM-STRICT-3: store i32 8 + // OGCG-NO-STRICT: llvm.objectsize.i64.p0(ptr {{.*}}, i1 false, i1 true, i1 false) + // OGCG-STRICT-0: llvm.objectsize.i64.p0(ptr {{.*}}, i1 false, i1 true, i1 false) + // OGCG-STRICT-1: llvm.objectsize.i64.p0(ptr {{.*}}, i1 false, i1 true, i1 false) + // OGCG-STRICT-2: ret i32 8 + // OGCG-STRICT-3: ret i32 8 + return OBJECT_SIZE_BUILTIN(f->c, 1); +} + +// CIR-LABEL: @bar2 +// LLVM-LABEL: @bar2( +// OGCG-LABEL: @bar2( +unsigned bar2(foo2_t *f) { + // CIR-NO-STRICT: cir.objsize max nullunknown {{.*}} : !cir.ptr<!void> -> !u64i + // CIR-STRICT-0: cir.objsize max nullunknown {{.*}} : !cir.ptr<!void> -> !u64i + // CIR-STRICT-1: cir.const #cir.int<16> + // CIR-STRICT-2: cir.const #cir.int<16> + // CIR-STRICT-3: cir.const #cir.int<16> + // LLVM-NO-STRICT: llvm.objectsize.i64.p0(ptr {{.*}}, i1 false, i1 true, i1 false) + // LLVM-STRICT-0: llvm.objectsize.i64.p0(ptr {{.*}}, i1 false, i1 true, i1 false) + // LLVM-STRICT-1: store i32 16 + // LLVM-STRICT-2: store i32 16 + // LLVM-STRICT-3: store i32 16 + // OGCG-NO-STRICT: llvm.objectsize.i64.p0(ptr {{.*}}, i1 false, i1 true, i1 false) + // OGCG-STRICT-0: llvm.objectsize.i64.p0(ptr {{.*}}, i1 false, i1 true, i1 false) + // OGCG-STRICT-1: ret i32 16 + // OGCG-STRICT-2: ret i32 16 + // OGCG-STRICT-3: ret i32 16 + return OBJECT_SIZE_BUILTIN(f->c, 1); +} + +#define DYNAMIC_OBJECT_SIZE_BUILTIN __builtin_dynamic_object_size + +// CIR-LABEL: @dyn_bar +// LLVM-LABEL: @dyn_bar( +// OGCG-LABEL: @dyn_bar( +unsigned dyn_bar(foo_t *f) { + // CIR-NO-STRICT: cir.objsize max nullunknown dynamic {{.*}} : !cir.ptr<!void> -> !u64i + // CIR-STRICT-0: cir.objsize max nullunknown dynamic {{.*}} : !cir.ptr<!void> -> !u64i + // CIR-STRICT-1: cir.objsize max nullunknown dynamic {{.*}} : !cir.ptr<!void> -> !u64i + // CIR-STRICT-2: cir.objsize max nullunknown dynamic {{.*}} : !cir.ptr<!void> -> !u64i + // CIR-STRICT-3: cir.objsize max nullunknown dynamic {{.*}} : !cir.ptr<!void> -> !u64i + // LLVM-NO-STRICT: llvm.objectsize.i64.p0(ptr {{.*}}, i1 false, i1 true, i1 true) + // LLVM-STRICT-0: llvm.objectsize.i64.p0(ptr {{.*}}, i1 false, i1 true, i1 true) + // LLVM-STRICT-1: llvm.objectsize.i64.p0(ptr {{.*}}, i1 false, i1 true, i1 true) + // LLVM-STRICT-2: llvm.objectsize.i64.p0(ptr {{.*}}, i1 false, i1 true, i1 true) + // LLVM-STRICT-3: llvm.objectsize.i64.p0(ptr {{.*}}, i1 false, i1 true, i1 true) + // OGCG-NO-STRICT: llvm.objectsize.i64.p0(ptr {{.*}}, i1 false, i1 true, i1 true) + // OGCG-STRICT-0: llvm.objectsize.i64.p0(ptr {{.*}}, i1 false, i1 true, i1 true) + // OGCG-STRICT-1: llvm.objectsize.i64.p0(ptr {{.*}}, i1 false, i1 true, i1 true) + // OGCG-STRICT-2: llvm.objectsize.i64.p0(ptr {{.*}}, i1 false, i1 true, i1 true) + // OGCG-STRICT-3: llvm.objectsize.i64.p0(ptr {{.*}}, i1 false, i1 true, i1 true) + return DYNAMIC_OBJECT_SIZE_BUILTIN(f->c, 1); +} + +// CIR-LABEL: @dyn_bar0 +// LLVM-LABEL: @dyn_bar0( +// OGCG-LABEL: @dyn_bar0( +unsigned dyn_bar0(foo0_t *f) { + // CIR-NO-STRICT: cir.objsize max nullunknown dynamic {{.*}} : !cir.ptr<!void> -> !u64i + // CIR-STRICT-0: cir.objsize max nullunknown dynamic {{.*}} : !cir.ptr<!void> -> !u64i + // CIR-STRICT-1: cir.objsize max nullunknown dynamic {{.*}} : !cir.ptr<!void> -> !u64i + // CIR-STRICT-2: cir.objsize max nullunknown dynamic {{.*}} : !cir.ptr<!void> -> !u64i + // CIR-STRICT-3: cir.const #cir.int<0> + // LLVM-NO-STRICT: llvm.objectsize.i64.p0(ptr {{.*}}, i1 false, i1 true, i1 true) + // LLVM-STRICT-0: llvm.objectsize.i64.p0(ptr {{.*}}, i1 false, i1 true, i1 true) + // LLVM-STRICT-1: llvm.objectsize.i64.p0(ptr {{.*}}, i1 false, i1 true, i1 true) + // LLVM-STRICT-2: llvm.objectsize.i64.p0(ptr {{.*}}, i1 false, i1 true, i1 true) + // LLVM-STRICT-3: store i32 0 + // OGCG-NO-STRICT: llvm.objectsize.i64.p0(ptr {{.*}}, i1 false, i1 true, i1 true) + // OGCG-STRICT-0: llvm.objectsize.i64.p0(ptr {{.*}}, i1 false, i1 true, i1 true) + // OGCG-STRICT-1: llvm.objectsize.i64.p0(ptr {{.*}}, i1 false, i1 true, i1 true) + // OGCG-STRICT-2: llvm.objectsize.i64.p0(ptr {{.*}}, i1 false, i1 true, i1 true) + // OGCG-STRICT-3: ret i32 0 + return DYNAMIC_OBJECT_SIZE_BUILTIN(f->c, 1); +} + +// CIR-LABEL: @dyn_bar1 +// LLVM-LABEL: @dyn_bar1( +// OGCG-LABEL: @dyn_bar1( +unsigned dyn_bar1(foo1_t *f) { + // CIR-NO-STRICT: cir.objsize max nullunknown dynamic {{.*}} : !cir.ptr<!void> -> !u64i + // CIR-STRICT-0: cir.objsize max nullunknown dynamic {{.*}} : !cir.ptr<!void> -> !u64i + // CIR-STRICT-1: cir.objsize max nullunknown dynamic {{.*}} : !cir.ptr<!void> -> !u64i + // CIR-STRICT-2: cir.const #cir.int<8> + // CIR-STRICT-3: cir.const #cir.int<8> + // LLVM-NO-STRICT: llvm.objectsize.i64.p0(ptr {{.*}}, i1 false, i1 true, i1 true) + // LLVM-STRICT-0: llvm.objectsize.i64.p0(ptr {{.*}}, i1 false, i1 true, i1 true) + // LLVM-STRICT-1: llvm.objectsize.i64.p0(ptr {{.*}}, i1 false, i1 true, i1 true) + // LLVM-STRICT-2: store i32 8 + // LLVM-STRICT-3: store i32 8 + // OGCG-NO-STRICT: llvm.objectsize.i64.p0(ptr {{.*}}, i1 false, i1 true, i1 true) + // OGCG-STRICT-0: llvm.objectsize.i64.p0(ptr {{.*}}, i1 false, i1 true, i1 true) + // OGCG-STRICT-1: llvm.objectsize.i64.p0(ptr {{.*}}, i1 false, i1 true, i1 true) + // OGCG-STRICT-2: ret i32 8 + // OGCG-STRICT-3: ret i32 8 + return DYNAMIC_OBJECT_SIZE_BUILTIN(f->c, 1); +} + +// CIR-LABEL: @dyn_bar2 +// LLVM-LABEL: @dyn_bar2( +// OGCG-LABEL: @dyn_bar2( +unsigned dyn_bar2(foo2_t *f) { + // CIR-NO-STRICT: cir.objsize max nullunknown dynamic {{.*}} : !cir.ptr<!void> -> !u64i + // CIR-STRICT-0: cir.objsize max nullunknown dynamic {{.*}} : !cir.ptr<!void> -> !u64i + // CIR-STRICT-1: cir.const #cir.int<16> + // CIR-STRICT-2: cir.const #cir.int<16> + // CIR-STRICT-3: cir.const #cir.int<16> + // LLVM-NO-STRICT: llvm.objectsize.i64.p0(ptr {{.*}}, i1 false, i1 true, i1 true) + // LLVM-STRICT-0: llvm.objectsize.i64.p0(ptr {{.*}}, i1 false, i1 true, i1 true) + // LLVM-STRICT-1: store i32 16 + // LLVM-STRICT-2: store i32 16 + // LLVM-STRICT-3: store i32 16 + // OGCG-NO-STRICT: llvm.objectsize.i64.p0(ptr {{.*}}, i1 false, i1 true, i1 true) + // OGCG-STRICT-0: llvm.objectsize.i64.p0(ptr {{.*}}, i1 false, i1 true, i1 true) + // OGCG-STRICT-1: ret i32 16 + // OGCG-STRICT-2: ret i32 16 + // OGCG-STRICT-3: ret i32 16 + return DYNAMIC_OBJECT_SIZE_BUILTIN(f->c, 1); +} + +// Also checks for non-trailing flex-array like members + +typedef struct { + double c[0]; + float f; +} foofoo0_t; + +typedef struct { + double c[1]; + float f; +} foofoo1_t; + +typedef struct { + double c[2]; + float f; +} foofoo2_t; + +// CIR-LABEL: @babar0 +// LLVM-LABEL: @babar0( +// OGCG-LABEL: @babar0( +unsigned babar0(foofoo0_t *f) { + // CIR-NO-STRICT: cir.const #cir.int<0> + // CIR-STRICT-0: cir.const #cir.int<0> + // CIR-STRICT-1: cir.const #cir.int<0> + // CIR-STRICT-2: cir.const #cir.int<0> + // CIR-STRICT-3: cir.const #cir.int<0> + // LLVM-NO-STRICT: store i32 0 + // LLVM-STRICT-0: store i32 0 + // LLVM-STRICT-1: store i32 0 + // LLVM-STRICT-2: store i32 0 + // LLVM-STRICT-3: store i32 0 + // OGCG-NO-STRICT: ret i32 0 + // OGCG-STRICT-0: ret i32 0 + // OGCG-STRICT-1: ret i32 0 + // OGCG-STRICT-2: ret i32 0 + // OGCG-STRICT-3: ret i32 0 + return OBJECT_SIZE_BUILTIN(f->c, 1); +} + +// CIR-LABEL: @babar1 +// LLVM-LABEL: @babar1( +// OGCG-LABEL: @babar1( +unsigned babar1(foofoo1_t *f) { + // CIR-NO-STRICT: cir.const #cir.int<8> + // CIR-STRICT-0: cir.const #cir.int<8> + // CIR-STRICT-1: cir.const #cir.int<8> + // CIR-STRICT-2: cir.const #cir.int<8> + // CIR-STRICT-3: cir.const #cir.int<8> + // LLVM-NO-STRICT: store i32 8 + // LLVM-STRICT-0: store i32 8 + // LLVM-STRICT-1: store i32 8 + // LLVM-STRICT-2: store i32 8 + // LLVM-STRICT-3: store i32 8 + // OGCG-NO-STRICT: ret i32 8 + // OGCG-STRICT-0: ret i32 8 + // OGCG-STRICT-1: ret i32 8 + // OGCG-STRICT-2: ret i32 8 + // OGCG-STRICT-3: ret i32 8 + return OBJECT_SIZE_BUILTIN(f->c, 1); +} + +// CIR-LABEL: @babar2 +// LLVM-LABEL: @babar2( +// OGCG-LABEL: @babar2( +unsigned babar2(foofoo2_t *f) { + // CIR-NO-STRICT: cir.const #cir.int<16> + // CIR-STRICT-0: cir.const #cir.int<16> + // CIR-STRICT-1: cir.const #cir.int<16> + // CIR-STRICT-2: cir.const #cir.int<16> + // CIR-STRICT-3: cir.const #cir.int<16> + // LLVM-NO-STRICT: store i32 16 + // LLVM-STRICT-0: store i32 16 + // LLVM-STRICT-1: store i32 16 + // LLVM-STRICT-2: store i32 16 + // LLVM-STRICT-3: store i32 16 + // OGCG-NO-STRICT: ret i32 16 + // OGCG-STRICT-0: ret i32 16 + // OGCG-STRICT-1: ret i32 16 + // OGCG-STRICT-2: ret i32 16 + // OGCG-STRICT-3: ret i32 16 + return OBJECT_SIZE_BUILTIN(f->c, 1); +} diff --git a/clang/test/CIR/CodeGen/object-size.c b/clang/test/CIR/CodeGen/object-size.c new file mode 100644 index 0000000..1b10fb8b --- /dev/null +++ b/clang/test/CIR/CodeGen/object-size.c @@ -0,0 +1,877 @@ +// RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -fclangir -emit-cir %s -o %t.cir +// RUN: FileCheck --input-file=%t.cir %s --check-prefix=CIR +// RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -fclangir -emit-llvm %s -o %t-cir.ll +// RUN: FileCheck --input-file=%t-cir.ll %s --check-prefix=LLVM +// RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -emit-llvm %s -o %t.ll +// RUN: FileCheck --input-file=%t.ll %s --check-prefix=OGCG + +char gbuf[63]; +char *gp; +int gi, gj; + +// CIR-LABEL: @test1 +// LLVM-LABEL: define {{.*}} void @test1 +// OGCG-LABEL: define {{.*}} void @test1 +void test1(void) { + // CIR: cir.const #cir.int<59> + // LLVM: store i32 59 + // OGCG: store i32 59 + gi = __builtin_object_size(&gbuf[4], 1); +} + +// CIR-LABEL: @test2 +// LLVM-LABEL: define {{.*}} void @test2 +// OGCG-LABEL: define {{.*}} void @test2 +void test2(void) { + // CIR: cir.const #cir.int<63> + // LLVM: store i32 63 + // OGCG: store i32 63 + gi = __builtin_object_size(gbuf, 1); +} + +// CIR-LABEL: @test3 +// LLVM-LABEL: define {{.*}} void @test3 +// OGCG-LABEL: define {{.*}} void @test3 +void test3(void) { + // CIR: cir.const #cir.int<0> + // LLVM: store i32 0 + // OGCG: store i32 0 + gi = __builtin_object_size(&gbuf[100], 1); +} + +// CIR-LABEL: @test4 +// LLVM-LABEL: define {{.*}} void @test4 +// OGCG-LABEL: define {{.*}} void @test4 +void test4(void) { + // CIR: cir.const #cir.int<0> + // LLVM: store i32 0 + // OGCG: store i32 0 + gi = __builtin_object_size((char*)(void*)&gbuf[-1], 1); +} + +// CIR-LABEL: @test5 +// LLVM-LABEL: define {{.*}} void @test5 +// OGCG-LABEL: define {{.*}} void @test5 +void test5(void) { + // CIR: cir.objsize max nullunknown {{.*}} : !cir.ptr<!void> -> !u64i + // LLVM: call i64 @llvm.objectsize.i64.p0(ptr %{{.*}}, i1 false, i1 true, i1 + // OGCG: call i64 @llvm.objectsize.i64.p0(ptr %{{.*}}, i1 false, i1 true, i1 + gi = __builtin_object_size(gp, 0); +} + +// CIR-LABEL: @test6 +// LLVM-LABEL: define {{.*}} void @test6 +// OGCG-LABEL: define {{.*}} void @test6 +void test6(void) { + char buf[57]; + + // CIR: cir.const #cir.int<53> + // LLVM: store i32 53 + // OGCG: store i32 53 + gi = __builtin_object_size(&buf[4], 1); +} + +// CIR-LABEL: @test18 +// LLVM-LABEL: define {{.*}} i32 @test18 +// OGCG-LABEL: define {{.*}} i32 @test18 +unsigned test18(int cond) { + int a[4], b[4]; + // CIR: cir.objsize max nullunknown {{.*}} : !cir.ptr<!void> -> !u64i + // LLVM: call i64 @llvm.objectsize.i64 + // OGCG: call i64 @llvm.objectsize.i64 + return __builtin_object_size(cond ? a : b, 0); +} + +// CIR-LABEL: @test19 +// LLVM-LABEL: define {{.*}} void @test19 +// OGCG-LABEL: define {{.*}} void @test19 +void test19(void) { + struct { + int a, b; + } foo; + + // CIR: cir.const #cir.int<8> + // LLVM: store i32 8 + // OGCG: store i32 8 + gi = __builtin_object_size(&foo.a, 0); + + // CIR: cir.const #cir.int<4> + // LLVM: store i32 4 + // OGCG: store i32 4 + gi = __builtin_object_size(&foo.a, 1); + + // CIR: cir.const #cir.int<8> + // LLVM: store i32 8 + // OGCG: store i32 8 + gi = __builtin_object_size(&foo.a, 2); + + // CIR: cir.const #cir.int<4> + // LLVM: store i32 4 + // OGCG: store i32 4 + gi = __builtin_object_size(&foo.a, 3); + + // CIR: cir.const #cir.int<4> + // LLVM: store i32 4 + // OGCG: store i32 4 + gi = __builtin_object_size(&foo.b, 0); + + // CIR: cir.const #cir.int<4> + // LLVM: store i32 4 + // OGCG: store i32 4 + gi = __builtin_object_size(&foo.b, 1); + + // CIR: cir.const #cir.int<4> + // LLVM: store i32 4 + // OGCG: store i32 4 + gi = __builtin_object_size(&foo.b, 2); + + // CIR: cir.const #cir.int<4> + // LLVM: store i32 4 + // OGCG: store i32 4 + gi = __builtin_object_size(&foo.b, 3); +} + +// CIR-LABEL: @test20 +// LLVM-LABEL: define {{.*}} void @test20 +// OGCG-LABEL: define {{.*}} void @test20 +void test20(void) { + struct { int t[10]; } t[10]; + + // CIR: cir.const #cir.int<380> + // LLVM: store i32 380 + // OGCG: store i32 380 + gi = __builtin_object_size(&t[0].t[5], 0); + + // CIR: cir.const #cir.int<20> + // LLVM: store i32 20 + // OGCG: store i32 20 + gi = __builtin_object_size(&t[0].t[5], 1); + + // CIR: cir.const #cir.int<380> + // LLVM: store i32 380 + // OGCG: store i32 380 + gi = __builtin_object_size(&t[0].t[5], 2); + + // CIR: cir.const #cir.int<20> + // LLVM: store i32 20 + // OGCG: store i32 20 + gi = __builtin_object_size(&t[0].t[5], 3); +} + +// CIR-LABEL: @test21 +// LLVM-LABEL: define {{.*}} void @test21 +// OGCG-LABEL: define {{.*}} void @test21 +void test21(void) { + struct { int t; } t; + + // CIR: cir.const #cir.int<0> + // LLVM: store i32 0 + // OGCG: store i32 0 + gi = __builtin_object_size(&t + 1, 0); + + // CIR: cir.const #cir.int<0> + // LLVM: store i32 0 + // OGCG: store i32 0 + gi = __builtin_object_size(&t + 1, 1); + + // CIR: cir.const #cir.int<0> + // LLVM: store i32 0 + // OGCG: store i32 0 + gi = __builtin_object_size(&t + 1, 2); + + // CIR: cir.const #cir.int<0> + // LLVM: store i32 0 + // OGCG: store i32 0 + gi = __builtin_object_size(&t + 1, 3); + + // CIR: cir.const #cir.int<0> + // LLVM: store i32 0 + // OGCG: store i32 0 + gi = __builtin_object_size(&t.t + 1, 0); + + // CIR: cir.const #cir.int<0> + // LLVM: store i32 0 + // OGCG: store i32 0 + gi = __builtin_object_size(&t.t + 1, 1); + + // CIR: cir.const #cir.int<0> + // LLVM: store i32 0 + // OGCG: store i32 0 + gi = __builtin_object_size(&t.t + 1, 2); + + // CIR: cir.const #cir.int<0> + // LLVM: store i32 0 + // OGCG: store i32 0 + gi = __builtin_object_size(&t.t + 1, 3); +} + +// CIR-LABEL: @test22 +// LLVM-LABEL: define {{.*}} void @test22 +// OGCG-LABEL: define {{.*}} void @test22 +void test22(void) { + struct { int t[10]; } t[10]; + + // CIR: cir.const #cir.int<0> + // LLVM: store i32 0 + // OGCG: store i32 0 + gi = __builtin_object_size(&t[10], 0); + + // CIR: cir.const #cir.int<0> + // LLVM: store i32 0 + // OGCG: store i32 0 + gi = __builtin_object_size(&t[10], 1); + + // CIR: cir.const #cir.int<0> + // LLVM: store i32 0 + // OGCG: store i32 0 + gi = __builtin_object_size(&t[10], 2); + + // CIR: cir.const #cir.int<0> + // LLVM: store i32 0 + // OGCG: store i32 0 + gi = __builtin_object_size(&t[10], 3); + + // CIR: cir.const #cir.int<0> + // LLVM: store i32 0 + // OGCG: store i32 0 + gi = __builtin_object_size(&t[9].t[10], 0); + + // CIR: cir.const #cir.int<0> + // LLVM: store i32 0 + // OGCG: store i32 0 + gi = __builtin_object_size(&t[9].t[10], 1); + + // CIR: cir.const #cir.int<0> + // LLVM: store i32 0 + // OGCG: store i32 0 + gi = __builtin_object_size(&t[9].t[10], 2); + + // CIR: cir.const #cir.int<0> + // LLVM: store i32 0 + // OGCG: store i32 0 + gi = __builtin_object_size(&t[9].t[10], 3); + + // CIR: cir.const #cir.int<0> + // LLVM: store i32 0 + // OGCG: store i32 0 + gi = __builtin_object_size((char*)&t[0] + sizeof(t), 0); + + // CIR: cir.const #cir.int<0> + // LLVM: store i32 0 + // OGCG: store i32 0 + gi = __builtin_object_size((char*)&t[0] + sizeof(t), 1); + + // CIR: cir.const #cir.int<0> + // LLVM: store i32 0 + // OGCG: store i32 0 + gi = __builtin_object_size((char*)&t[0] + sizeof(t), 2); + + // CIR: cir.const #cir.int<0> + // LLVM: store i32 0 + // OGCG: store i32 0 + gi = __builtin_object_size((char*)&t[0] + sizeof(t), 3); + + // CIR: cir.const #cir.int<0> + // LLVM: store i32 0 + // OGCG: store i32 0 + gi = __builtin_object_size((char*)&t[9].t[0] + 10*sizeof(t[0].t), 0); + + // CIR: cir.const #cir.int<0> + // LLVM: store i32 0 + // OGCG: store i32 0 + gi = __builtin_object_size((char*)&t[9].t[0] + 10*sizeof(t[0].t), 1); + + // CIR: cir.const #cir.int<0> + // LLVM: store i32 0 + // OGCG: store i32 0 + gi = __builtin_object_size((char*)&t[9].t[0] + 10*sizeof(t[0].t), 2); + + // CIR: cir.const #cir.int<0> + // LLVM: store i32 0 + // OGCG: store i32 0 + gi = __builtin_object_size((char*)&t[9].t[0] + 10*sizeof(t[0].t), 3); +} + +struct Test23Ty { int a; int t[10]; }; + +// CIR-LABEL: @test23 +// LLVM-LABEL: define {{.*}} void @test23 +// OGCG-LABEL: define {{.*}} void @test23 +void test23(struct Test23Ty *p) { + // CIR: cir.objsize max nullunknown {{.*}} : !cir.ptr<!void> -> !u64i + // LLVM: call i64 @llvm.objectsize.i64.p0(ptr %{{.*}}, i1 false, i1 true, i1 + // OGCG: call i64 @llvm.objectsize.i64.p0(ptr %{{.*}}, i1 false, i1 true, i1 + gi = __builtin_object_size(p, 0); + + // CIR: cir.objsize max nullunknown {{.*}} : !cir.ptr<!void> -> !u64i + // LLVM: call i64 @llvm.objectsize.i64.p0(ptr %{{.*}}, i1 false, i1 true, i1 + // OGCG: call i64 @llvm.objectsize.i64.p0(ptr %{{.*}}, i1 false, i1 true, i1 + gi = __builtin_object_size(p, 1); + + // CIR: cir.objsize min nullunknown {{.*}} : !cir.ptr<!void> -> !u64i + // LLVM: call i64 @llvm.objectsize.i64.p0(ptr %{{.*}}, i1 true, i1 true, i1 + // OGCG: call i64 @llvm.objectsize.i64.p0(ptr %{{.*}}, i1 true, i1 true, i1 + gi = __builtin_object_size(p, 2); + + // CIR: cir.const #cir.int<0> + // LLVM: store i32 0 + // OGCG: store i32 0 + gi = __builtin_object_size(p, 3); + + // CIR: cir.objsize max nullunknown {{.*}} : !cir.ptr<!void> -> !u64i + // LLVM: call i64 @llvm.objectsize.i64.p0(ptr %{{.*}}, i1 false, i1 true, i1 + // OGCG: call i64 @llvm.objectsize.i64.p0(ptr %{{.*}}, i1 false, i1 true, i1 + gi = __builtin_object_size(&p->a, 0); + + // CIR: cir.const #cir.int<4> + // LLVM: store i32 4 + // OGCG: store i32 4 + gi = __builtin_object_size(&p->a, 1); + + // CIR: cir.objsize min nullunknown {{.*}} : !cir.ptr<!void> -> !u64i + // LLVM: call i64 @llvm.objectsize.i64.p0(ptr %{{.*}}, i1 true, i1 true, i1 + // OGCG: call i64 @llvm.objectsize.i64.p0(ptr %{{.*}}, i1 true, i1 true, i1 + gi = __builtin_object_size(&p->a, 2); + + // CIR: cir.const #cir.int<4> + // LLVM: store i32 4 + // OGCG: store i32 4 + gi = __builtin_object_size(&p->a, 3); + + // CIR: cir.objsize max nullunknown {{.*}} : !cir.ptr<!void> -> !u64i + // LLVM: call i64 @llvm.objectsize.i64.p0(ptr %{{.*}}, i1 false, i1 true, i1 + // OGCG: call i64 @llvm.objectsize.i64.p0(ptr %{{.*}}, i1 false, i1 true, i1 + gi = __builtin_object_size(&p->t[5], 0); + + // CIR: cir.objsize max nullunknown {{.*}} : !cir.ptr<!void> -> !u64i + // LLVM: call i64 @llvm.objectsize.i64.p0(ptr %{{.*}}, i1 false, i1 true, i1 + // OGCG: call i64 @llvm.objectsize.i64.p0(ptr %{{.*}}, i1 false, i1 true, i1 + gi = __builtin_object_size(&p->t[5], 1); + + // CIR: cir.objsize min nullunknown {{.*}} : !cir.ptr<!void> -> !u64i + // LLVM: call i64 @llvm.objectsize.i64.p0(ptr %{{.*}}, i1 true, i1 true, i1 + // OGCG: call i64 @llvm.objectsize.i64.p0(ptr %{{.*}}, i1 true, i1 true, i1 + gi = __builtin_object_size(&p->t[5], 2); + + // CIR: cir.const #cir.int<20> + // LLVM: store i32 20 + // OGCG: store i32 20 + gi = __builtin_object_size(&p->t[5], 3); +} + +// CIR-LABEL: @test24 +// LLVM-LABEL: define {{.*}} void @test24 +// OGCG-LABEL: define {{.*}} void @test24 +void test24(void) { + // CIR: cir.objsize max nullunknown {{.*}} : !cir.ptr<!void> -> !u64i + // LLVM: call i64 @llvm.objectsize.i64.p0(ptr {{.*}}, i1 false, i1 true, i1 + // OGCG: call i64 @llvm.objectsize.i64.p0(ptr {{.*}}, i1 false, i1 true, i1 + gi = __builtin_object_size((void*)0, 0); + + // CIR: cir.objsize max nullunknown {{.*}} : !cir.ptr<!void> -> !u64i + // LLVM: call i64 @llvm.objectsize.i64.p0(ptr {{.*}}, i1 false, i1 true, i1 + // OGCG: call i64 @llvm.objectsize.i64.p0(ptr {{.*}}, i1 false, i1 true, i1 + gi = __builtin_object_size((void*)0, 1); + + // CIR: cir.objsize min nullunknown {{.*}} : !cir.ptr<!void> -> !u64i + // LLVM: call i64 @llvm.objectsize.i64.p0(ptr {{.*}}, i1 true, i1 true, i1 + // OGCG: call i64 @llvm.objectsize.i64.p0(ptr {{.*}}, i1 true, i1 true, i1 + gi = __builtin_object_size((void*)0, 2); + + // CIR: cir.const #cir.int<0> + // LLVM: store i32 0 + // OGCG: store i32 0 + gi = __builtin_object_size((void*)0, 3); +} + +// CIR-LABEL: @test25 +// LLVM-LABEL: define {{.*}} void @test25 +// OGCG-LABEL: define {{.*}} void @test25 +void test25(void) { + // CIR: cir.objsize max nullunknown {{.*}} : !cir.ptr<!void> -> !u64i + // LLVM: call i64 @llvm.objectsize.i64.p0(ptr {{.*}}, i1 false, i1 true, i1 + // OGCG: call i64 @llvm.objectsize.i64.p0(ptr {{.*}}, i1 false, i1 true, i1 + gi = __builtin_object_size((void*)0x1000, 0); + + // CIR: cir.objsize max nullunknown {{.*}} : !cir.ptr<!void> -> !u64i + // LLVM: call i64 @llvm.objectsize.i64.p0(ptr {{.*}}, i1 false, i1 true, i1 + // OGCG: call i64 @llvm.objectsize.i64.p0(ptr {{.*}}, i1 false, i1 true, i1 + gi = __builtin_object_size((void*)0x1000, 1); + + // CIR: cir.objsize min nullunknown {{.*}} : !cir.ptr<!void> -> !u64i + // LLVM: call i64 @llvm.objectsize.i64.p0(ptr {{.*}}, i1 true, i1 true, i1 + // OGCG: call i64 @llvm.objectsize.i64.p0(ptr {{.*}}, i1 true, i1 true, i1 + gi = __builtin_object_size((void*)0x1000, 2); + + // CIR: cir.const #cir.int<0> + // LLVM: store i32 0 + // OGCG: store i32 0 + gi = __builtin_object_size((void*)0x1000, 3); + + // Skipping (void*)0 + 0x1000 tests - void pointer arithmetic NYI in CIR +} + +// CIR-LABEL: @test26 +// LLVM-LABEL: define {{.*}} void @test26 +// OGCG-LABEL: define {{.*}} void @test26 +void test26(void) { + struct { int v[10]; } t[10]; + + // CIR: cir.const #cir.int<316> + // LLVM: store i32 316 + // OGCG: store i32 316 + gi = __builtin_object_size(&t[1].v[11], 0); + + // CIR: cir.const #cir.int<312> + // LLVM: store i32 312 + // OGCG: store i32 312 + gi = __builtin_object_size(&t[1].v[12], 1); + + // CIR: cir.const #cir.int<308> + // LLVM: store i32 308 + // OGCG: store i32 308 + gi = __builtin_object_size(&t[1].v[13], 2); + + // CIR: cir.const #cir.int<0> + // LLVM: store i32 0 + // OGCG: store i32 0 + gi = __builtin_object_size(&t[1].v[14], 3); +} + +struct Test27IncompleteTy; + +// CIR-LABEL: @test27 +// LLVM-LABEL: define {{.*}} void @test27 +// OGCG-LABEL: define {{.*}} void @test27 +void test27(struct Test27IncompleteTy *t) { + // CIR: cir.objsize max nullunknown {{.*}} : !cir.ptr<!void> -> !u64i + // LLVM: call i64 @llvm.objectsize.i64.p0(ptr %{{.*}}, i1 false, i1 true, i1 + // OGCG: call i64 @llvm.objectsize.i64.p0(ptr %{{.*}}, i1 false, i1 true, i1 + gi = __builtin_object_size(t, 0); + + // CIR: cir.objsize max nullunknown {{.*}} : !cir.ptr<!void> -> !u64i + // LLVM: call i64 @llvm.objectsize.i64.p0(ptr %{{.*}}, i1 false, i1 true, i1 + // OGCG: call i64 @llvm.objectsize.i64.p0(ptr %{{.*}}, i1 false, i1 true, i1 + gi = __builtin_object_size(t, 1); + + // CIR: cir.objsize min nullunknown {{.*}} : !cir.ptr<!void> -> !u64i + // LLVM: call i64 @llvm.objectsize.i64.p0(ptr %{{.*}}, i1 true, i1 true, i1 + // OGCG: call i64 @llvm.objectsize.i64.p0(ptr %{{.*}}, i1 true, i1 true, i1 + gi = __builtin_object_size(t, 2); + + // CIR: cir.const #cir.int<0> + // LLVM: store i32 0 + // OGCG: store i32 0 + gi = __builtin_object_size(t, 3); + + // CIR: cir.objsize max nullunknown {{.*}} : !cir.ptr<!void> -> !u64i + // LLVM: call i64 @llvm.objectsize.i64.p0(ptr {{.*}}, i1 false, i1 true, i1 + // OGCG: call i64 @llvm.objectsize.i64.p0(ptr {{.*}}, i1 false, i1 true, i1 + gi = __builtin_object_size(&test27, 0); + + // CIR: cir.objsize max nullunknown {{.*}} : !cir.ptr<!void> -> !u64i + // LLVM: call i64 @llvm.objectsize.i64.p0(ptr {{.*}}, i1 false, i1 true, i1 + // OGCG: call i64 @llvm.objectsize.i64.p0(ptr {{.*}}, i1 false, i1 true, i1 + gi = __builtin_object_size(&test27, 1); + + // CIR: cir.objsize min nullunknown {{.*}} : !cir.ptr<!void> -> !u64i + // LLVM: call i64 @llvm.objectsize.i64.p0(ptr {{.*}}, i1 true, i1 true, i1 + // OGCG: call i64 @llvm.objectsize.i64.p0(ptr {{.*}}, i1 true, i1 true, i1 + gi = __builtin_object_size(&test27, 2); + + // CIR: cir.const #cir.int<0> + // LLVM: store i32 0 + // OGCG: store i32 0 + gi = __builtin_object_size(&test27, 3); +} + +// CIR-LABEL: @test28 +// LLVM-LABEL: define {{.*}} void @test28 +// OGCG-LABEL: define {{.*}} void @test28 +void test28(void) { + struct { int v[10]; } t[10]; + + // CIR: cir.const #cir.int<360> + // LLVM: store i32 360 + // OGCG: store i32 360 + gi = __builtin_object_size((char*)((short*)(&t[1])), 0); + + // CIR: cir.const #cir.int<360> + // LLVM: store i32 360 + // OGCG: store i32 360 + gi = __builtin_object_size((char*)((short*)(&t[1])), 1); + + // CIR: cir.const #cir.int<360> + // LLVM: store i32 360 + // OGCG: store i32 360 + gi = __builtin_object_size((char*)((short*)(&t[1])), 2); + + // CIR: cir.const #cir.int<360> + // LLVM: store i32 360 + // OGCG: store i32 360 + gi = __builtin_object_size((char*)((short*)(&t[1])), 3); + + // CIR: cir.const #cir.int<356> + // LLVM: store i32 356 + // OGCG: store i32 356 + gi = __builtin_object_size((char*)((short*)(&t[1].v[1])), 0); + + // CIR: cir.const #cir.int<36> + // LLVM: store i32 36 + // OGCG: store i32 36 + gi = __builtin_object_size((char*)((short*)(&t[1].v[1])), 1); + + // CIR: cir.const #cir.int<356> + // LLVM: store i32 356 + // OGCG: store i32 356 + gi = __builtin_object_size((char*)((short*)(&t[1].v[1])), 2); + + // CIR: cir.const #cir.int<36> + // LLVM: store i32 36 + // OGCG: store i32 36 + gi = __builtin_object_size((char*)((short*)(&t[1].v[1])), 3); +} + +struct DynStructVar { + char fst[16]; + char snd[]; +}; + +struct DynStruct0 { + char fst[16]; + char snd[0]; +}; + +struct DynStruct1 { + char fst[16]; + char snd[1]; +}; + +struct StaticStruct { + char fst[16]; + char snd[2]; +}; + +// CIR-LABEL: @test29 +// LLVM-LABEL: define {{.*}} void @test29 +// OGCG-LABEL: define {{.*}} void @test29 +void test29(struct DynStructVar *dv, struct DynStruct0 *d0, + struct DynStruct1 *d1, struct StaticStruct *ss) { + // CIR: cir.objsize max nullunknown {{.*}} : !cir.ptr<!void> -> !u64i + // LLVM: call i64 @llvm.objectsize.i64.p0(ptr %{{.*}}, i1 false, i1 true, i1 + // OGCG: call i64 @llvm.objectsize.i64.p0(ptr %{{.*}}, i1 false, i1 true, i1 + gi = __builtin_object_size(dv->snd, 0); + + // CIR: cir.objsize max nullunknown {{.*}} : !cir.ptr<!void> -> !u64i + // LLVM: call i64 @llvm.objectsize.i64.p0(ptr %{{.*}}, i1 false, i1 true, i1 + // OGCG: call i64 @llvm.objectsize.i64.p0(ptr %{{.*}}, i1 false, i1 true, i1 + gi = __builtin_object_size(dv->snd, 1); + + // CIR: cir.objsize min nullunknown {{.*}} : !cir.ptr<!void> -> !u64i + // LLVM: call i64 @llvm.objectsize.i64.p0(ptr %{{.*}}, i1 true, i1 true, i1 + // OGCG: call i64 @llvm.objectsize.i64.p0(ptr %{{.*}}, i1 true, i1 true, i1 + gi = __builtin_object_size(dv->snd, 2); + + // CIR: cir.const #cir.int<0> + // LLVM: store i32 0 + // OGCG: store i32 0 + gi = __builtin_object_size(dv->snd, 3); + + // CIR: cir.objsize max nullunknown {{.*}} : !cir.ptr<!void> -> !u64i + // LLVM: call i64 @llvm.objectsize.i64.p0(ptr %{{.*}}, i1 false, i1 true, i1 + // OGCG: call i64 @llvm.objectsize.i64.p0(ptr %{{.*}}, i1 false, i1 true, i1 + gi = __builtin_object_size(d0->snd, 0); + + // CIR: cir.objsize max nullunknown {{.*}} : !cir.ptr<!void> -> !u64i + // LLVM: call i64 @llvm.objectsize.i64.p0(ptr %{{.*}}, i1 false, i1 true, i1 + // OGCG: call i64 @llvm.objectsize.i64.p0(ptr %{{.*}}, i1 false, i1 true, i1 + gi = __builtin_object_size(d0->snd, 1); + + // CIR: cir.objsize min nullunknown {{.*}} : !cir.ptr<!void> -> !u64i + // LLVM: call i64 @llvm.objectsize.i64.p0(ptr %{{.*}}, i1 true, i1 true, i1 + // OGCG: call i64 @llvm.objectsize.i64.p0(ptr %{{.*}}, i1 true, i1 true, i1 + gi = __builtin_object_size(d0->snd, 2); + + // CIR: cir.const #cir.int<0> + // LLVM: store i32 0 + // OGCG: store i32 0 + gi = __builtin_object_size(d0->snd, 3); + + // CIR: cir.objsize max nullunknown {{.*}} : !cir.ptr<!void> -> !u64i + // LLVM: call i64 @llvm.objectsize.i64.p0(ptr %{{.*}}, i1 false, i1 true, i1 + // OGCG: call i64 @llvm.objectsize.i64.p0(ptr %{{.*}}, i1 false, i1 true, i1 + gi = __builtin_object_size(d1->snd, 0); + + // CIR: cir.objsize max nullunknown {{.*}} : !cir.ptr<!void> -> !u64i + // LLVM: call i64 @llvm.objectsize.i64.p0(ptr %{{.*}}, i1 false, i1 true, i1 + // OGCG: call i64 @llvm.objectsize.i64.p0(ptr %{{.*}}, i1 false, i1 true, i1 + gi = __builtin_object_size(d1->snd, 1); + + // CIR: cir.objsize min nullunknown {{.*}} : !cir.ptr<!void> -> !u64i + // LLVM: call i64 @llvm.objectsize.i64.p0(ptr %{{.*}}, i1 true, i1 true, i1 + // OGCG: call i64 @llvm.objectsize.i64.p0(ptr %{{.*}}, i1 true, i1 true, i1 + gi = __builtin_object_size(d1->snd, 2); + + // CIR: cir.const #cir.int<1> + // LLVM: store i32 1 + // OGCG: store i32 1 + gi = __builtin_object_size(d1->snd, 3); + + // CIR: cir.objsize max nullunknown {{.*}} : !cir.ptr<!void> -> !u64i + // LLVM: call i64 @llvm.objectsize.i64.p0(ptr %{{.*}}, i1 false, i1 true, i1 + // OGCG: call i64 @llvm.objectsize.i64.p0(ptr %{{.*}}, i1 false, i1 true, i1 + gi = __builtin_object_size(ss->snd, 0); + + // CIR: cir.objsize max nullunknown {{.*}} : !cir.ptr<!void> -> !u64i + // LLVM: call i64 @llvm.objectsize.i64.p0(ptr %{{.*}}, i1 false, i1 true, i1 + // OGCG: call i64 @llvm.objectsize.i64.p0(ptr %{{.*}}, i1 false, i1 true, i1 + gi = __builtin_object_size(ss->snd, 1); + + // CIR: cir.objsize min nullunknown {{.*}} : !cir.ptr<!void> -> !u64i + // LLVM: call i64 @llvm.objectsize.i64.p0(ptr %{{.*}}, i1 true, i1 true, i1 + // OGCG: call i64 @llvm.objectsize.i64.p0(ptr %{{.*}}, i1 true, i1 true, i1 + gi = __builtin_object_size(ss->snd, 2); + + // CIR: cir.const #cir.int<2> + // LLVM: store i32 2 + // OGCG: store i32 2 + gi = __builtin_object_size(ss->snd, 3); +} + +// CIR-LABEL: @test30 +// LLVM-LABEL: define {{.*}} void @test30 +// OGCG-LABEL: define {{.*}} void @test30 +void test30(void) { + struct { struct DynStruct1 fst, snd; } *nested; + + // CIR: cir.objsize max nullunknown {{.*}} : !cir.ptr<!void> -> !u64i + // LLVM: call i64 @llvm.objectsize.i64.p0(ptr %{{.*}}, i1 false, i1 true, i1 + // OGCG: call i64 @llvm.objectsize.i64.p0(ptr %{{.*}}, i1 false, i1 true, i1 + gi = __builtin_object_size(nested->fst.snd, 0); + + // CIR: cir.const #cir.int<1> + // LLVM: store i32 1 + // OGCG: store i32 1 + gi = __builtin_object_size(nested->fst.snd, 1); + + // CIR: cir.objsize min nullunknown {{.*}} : !cir.ptr<!void> -> !u64i + // LLVM: call i64 @llvm.objectsize.i64.p0(ptr %{{.*}}, i1 true, i1 true, i1 + // OGCG: call i64 @llvm.objectsize.i64.p0(ptr %{{.*}}, i1 true, i1 true, i1 + gi = __builtin_object_size(nested->fst.snd, 2); + + // CIR: cir.const #cir.int<1> + // LLVM: store i32 1 + // OGCG: store i32 1 + gi = __builtin_object_size(nested->fst.snd, 3); + + // CIR: cir.objsize max nullunknown {{.*}} : !cir.ptr<!void> -> !u64i + // LLVM: call i64 @llvm.objectsize.i64.p0(ptr %{{.*}}, i1 false, i1 true, i1 + // OGCG: call i64 @llvm.objectsize.i64.p0(ptr %{{.*}}, i1 false, i1 true, i1 + gi = __builtin_object_size(nested->snd.snd, 0); + + // CIR: cir.objsize max nullunknown {{.*}} : !cir.ptr<!void> -> !u64i + // LLVM: call i64 @llvm.objectsize.i64.p0(ptr %{{.*}}, i1 false, i1 true, i1 + // OGCG: call i64 @llvm.objectsize.i64.p0(ptr %{{.*}}, i1 false, i1 true, i1 + gi = __builtin_object_size(nested->snd.snd, 1); + + // CIR: cir.objsize min nullunknown {{.*}} : !cir.ptr<!void> -> !u64i + // LLVM: call i64 @llvm.objectsize.i64.p0(ptr %{{.*}}, i1 true, i1 true, i1 + // OGCG: call i64 @llvm.objectsize.i64.p0(ptr %{{.*}}, i1 true, i1 true, i1 + gi = __builtin_object_size(nested->snd.snd, 2); + + // CIR: cir.const #cir.int<1> + // LLVM: store i32 1 + // OGCG: store i32 1 + gi = __builtin_object_size(nested->snd.snd, 3); + + union { struct DynStruct1 d1; char c[1]; } *u; + + // CIR: cir.objsize max nullunknown {{.*}} : !cir.ptr<!void> -> !u64i + // LLVM: call i64 @llvm.objectsize.i64.p0(ptr %{{.*}}, i1 false, i1 true, i1 + // OGCG: call i64 @llvm.objectsize.i64.p0(ptr %{{.*}}, i1 false, i1 true, i1 + gi = __builtin_object_size(u->c, 0); + + // CIR: cir.objsize max nullunknown {{.*}} : !cir.ptr<!void> -> !u64i + // LLVM: call i64 @llvm.objectsize.i64.p0(ptr %{{.*}}, i1 false, i1 true, i1 + // OGCG: call i64 @llvm.objectsize.i64.p0(ptr %{{.*}}, i1 false, i1 true, i1 + gi = __builtin_object_size(u->c, 1); + + // CIR: cir.objsize min nullunknown {{.*}} : !cir.ptr<!void> -> !u64i + // LLVM: call i64 @llvm.objectsize.i64.p0(ptr %{{.*}}, i1 true, i1 true, i1 + // OGCG: call i64 @llvm.objectsize.i64.p0(ptr %{{.*}}, i1 true, i1 true, i1 + gi = __builtin_object_size(u->c, 2); + + // CIR: cir.const #cir.int<1> + // LLVM: store i32 1 + // OGCG: store i32 1 + gi = __builtin_object_size(u->c, 3); + + // CIR: cir.objsize max nullunknown {{.*}} : !cir.ptr<!void> -> !u64i + // LLVM: call i64 @llvm.objectsize.i64.p0(ptr %{{.*}}, i1 false, i1 true, i1 + // OGCG: call i64 @llvm.objectsize.i64.p0(ptr %{{.*}}, i1 false, i1 true, i1 + gi = __builtin_object_size(u->d1.snd, 0); + + // CIR: cir.objsize max nullunknown {{.*}} : !cir.ptr<!void> -> !u64i + // LLVM: call i64 @llvm.objectsize.i64.p0(ptr %{{.*}}, i1 false, i1 true, i1 + // OGCG: call i64 @llvm.objectsize.i64.p0(ptr %{{.*}}, i1 false, i1 true, i1 + gi = __builtin_object_size(u->d1.snd, 1); + + // CIR: cir.objsize min nullunknown {{.*}} : !cir.ptr<!void> -> !u64i + // LLVM: call i64 @llvm.objectsize.i64.p0(ptr %{{.*}}, i1 true, i1 true, i1 + // OGCG: call i64 @llvm.objectsize.i64.p0(ptr %{{.*}}, i1 true, i1 true, i1 + gi = __builtin_object_size(u->d1.snd, 2); + + // CIR: cir.const #cir.int<1> + // LLVM: store i32 1 + // OGCG: store i32 1 + gi = __builtin_object_size(u->d1.snd, 3); +} + +// CIR-LABEL: @test32 +// LLVM-LABEL: define {{.*}} i64 @test32 +// OGCG-LABEL: define {{.*}} i64 @test32 +static struct DynStructVar D32 = { + .fst = {}, + .snd = { 0, 1, 2, }, +}; +unsigned long test32(void) { + // CIR: cir.const #cir.int<19> + // LLVM: store i64 19 + // OGCG: ret i64 19 + return __builtin_object_size(&D32, 1); +} + +// CIR-LABEL: @test33 +// LLVM-LABEL: define {{.*}} i64 @test33 +// OGCG-LABEL: define {{.*}} i64 @test33 +static struct DynStructVar D33 = { + .fst = {}, + .snd = {}, +}; +unsigned long test33(void) { + // CIR: cir.const #cir.int<16> + // LLVM: store i64 16 + // OGCG: ret i64 16 + return __builtin_object_size(&D33, 1); +} + +// CIR-LABEL: @test34 +// LLVM-LABEL: define {{.*}} i64 @test34 +// OGCG-LABEL: define {{.*}} i64 @test34 +static struct DynStructVar D34 = { + .fst = {}, +}; +unsigned long test34(void) { + // CIR: cir.const #cir.int<16> + // LLVM: store i64 16 + // OGCG: ret i64 16 + return __builtin_object_size(&D34, 1); +} + +// CIR-LABEL: @test35 +// LLVM-LABEL: define {{.*}} i64 @test35 +// OGCG-LABEL: define {{.*}} i64 @test35 +unsigned long test35(void) { + // CIR: cir.const #cir.int<16> + // LLVM: store i64 16 + // OGCG: ret i64 16 + return __builtin_object_size(&(struct DynStructVar){}, 1); +} + +// CIR-LABEL: @test37 +// LLVM-LABEL: define {{.*}} i64 @test37 +// OGCG-LABEL: define {{.*}} i64 @test37 +struct Z { struct A { int x, y[]; } z; int a; int b[]; }; +static struct Z my_z = { .b = {1,2,3} }; +unsigned long test37(void) { + // CIR: cir.const #cir.int<4> + // LLVM: store i64 4 + // OGCG: ret i64 4 + return __builtin_object_size(&my_z.z, 1); +} + +// CIR-LABEL: @PR30346 +// LLVM-LABEL: define {{.*}} void @PR30346 +// OGCG-LABEL: define {{.*}} void @PR30346 +void PR30346(void) { + struct sa_family_t {}; + struct sockaddr { + struct sa_family_t sa_family; + char sa_data[14]; + }; + + struct sockaddr *sa; + + // CIR: cir.objsize max nullunknown {{.*}} : !cir.ptr<!void> -> !u64i + // LLVM: call i64 @llvm.objectsize.i64.p0(ptr %{{.*}}, i1 false, i1 true, i1 + // OGCG: call i64 @llvm.objectsize.i64.p0(ptr %{{.*}}, i1 false, i1 true, i1 + gi = __builtin_object_size(sa->sa_data, 0); + + // CIR: cir.objsize max nullunknown {{.*}} : !cir.ptr<!void> -> !u64i + // LLVM: call i64 @llvm.objectsize.i64.p0(ptr %{{.*}}, i1 false, i1 true, i1 + // OGCG: call i64 @llvm.objectsize.i64.p0(ptr %{{.*}}, i1 false, i1 true, i1 + gi = __builtin_object_size(sa->sa_data, 1); + + // CIR: cir.objsize min nullunknown {{.*}} : !cir.ptr<!void> -> !u64i + // LLVM: call i64 @llvm.objectsize.i64.p0(ptr %{{.*}}, i1 true, i1 true, i1 + // OGCG: call i64 @llvm.objectsize.i64.p0(ptr %{{.*}}, i1 true, i1 true, i1 + gi = __builtin_object_size(sa->sa_data, 2); + + // CIR: cir.const #cir.int<14> + // LLVM: store i32 14 + // OGCG: store i32 14 + gi = __builtin_object_size(sa->sa_data, 3); +} + +extern char incomplete_char_array[]; + +// CIR-LABEL: @incomplete_and_function_types +// LLVM-LABEL: define {{.*}} void @incomplete_and_function_types +// OGCG-LABEL: define {{.*}} void @incomplete_and_function_types +void incomplete_and_function_types(void) { + // CIR: cir.objsize max nullunknown {{.*}} : !cir.ptr<!void> -> !u64i + // LLVM: call i64 @llvm.objectsize.i64.p0 + // OGCG: call i64 @llvm.objectsize.i64.p0 + gi = __builtin_object_size(incomplete_char_array, 0); + + // CIR: cir.objsize max nullunknown {{.*}} : !cir.ptr<!void> -> !u64i + // LLVM: call i64 @llvm.objectsize.i64.p0 + // OGCG: call i64 @llvm.objectsize.i64.p0 + gi = __builtin_object_size(incomplete_char_array, 1); + + // CIR: cir.objsize min nullunknown {{.*}} : !cir.ptr<!void> -> !u64i + // LLVM: call i64 @llvm.objectsize.i64.p0 + // OGCG: call i64 @llvm.objectsize.i64.p0 + gi = __builtin_object_size(incomplete_char_array, 2); + + // CIR: cir.const #cir.int<0> + // LLVM: store i32 0 + // OGCG: store i32 0 + gi = __builtin_object_size(incomplete_char_array, 3); +} + +// CIR-LABEL: @deeply_nested +// LLVM-LABEL: define {{.*}} void @deeply_nested +// OGCG-LABEL: define {{.*}} void @deeply_nested +void deeply_nested(void) { + struct { + struct { + struct { + struct { + int e[2]; + char f; + } d[2]; + } c[2]; + } b[2]; + } *a; + + // CIR: cir.const #cir.int<4> + // LLVM: store i32 4 + // OGCG: store i32 4 + gi = __builtin_object_size(&a->b[1].c[1].d[1].e[1], 1); + + // CIR: cir.const #cir.int<4> + // LLVM: store i32 4 + // OGCG: store i32 4 + gi = __builtin_object_size(&a->b[1].c[1].d[1].e[1], 3); +} diff --git a/clang/test/CIR/CodeGen/object-size.cpp b/clang/test/CIR/CodeGen/object-size.cpp new file mode 100644 index 0000000..b60e245 --- /dev/null +++ b/clang/test/CIR/CodeGen/object-size.cpp @@ -0,0 +1,108 @@ +// RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -fclangir -emit-cir %s -o %t.cir +// RUN: FileCheck --input-file=%t.cir %s --check-prefix=CIR +// RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -fclangir -emit-llvm %s -o %t-cir.ll +// RUN: FileCheck --input-file=%t-cir.ll %s --check-prefix=LLVM +// RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -emit-llvm %s -o %t.ll +// RUN: FileCheck --input-file=%t.ll %s --check-prefix=OGCG + +// C++-specific tests for __builtin_object_size + +int gi; + +// CIR-LABEL: @_Z5test1v +// LLVM-LABEL: define{{.*}} void @_Z5test1v() +// OGCG-LABEL: define{{.*}} void @_Z5test1v() +void test1() { + // Guaranteeing that our cast removal logic doesn't break more interesting + // cases. + struct A { int a; }; + struct B { int b; }; + struct C: public A, public B {}; + + C c; + + // CIR: cir.const #cir.int<8> + // LLVM: store i32 8 + // OGCG: store i32 8 + gi = __builtin_object_size(&c, 0); + // CIR: cir.const #cir.int<8> + // LLVM: store i32 8 + // OGCG: store i32 8 + gi = __builtin_object_size((A*)&c, 0); + // CIR: cir.const #cir.int<4> + // LLVM: store i32 4 + // OGCG: store i32 4 + gi = __builtin_object_size((B*)&c, 0); + + // CIR: cir.const #cir.int<8> + // LLVM: store i32 8 + // OGCG: store i32 8 + gi = __builtin_object_size((char*)&c, 0); + // CIR: cir.const #cir.int<8> + // LLVM: store i32 8 + // OGCG: store i32 8 + gi = __builtin_object_size((char*)(A*)&c, 0); + // CIR: cir.const #cir.int<4> + // LLVM: store i32 4 + // OGCG: store i32 4 + gi = __builtin_object_size((char*)(B*)&c, 0); +} + +// CIR-LABEL: @_Z5test2v() +// LLVM-LABEL: define{{.*}} void @_Z5test2v() +// OGCG-LABEL: define{{.*}} void @_Z5test2v() +void test2() { + struct A { char buf[16]; }; + struct B : A {}; + struct C { int i; B bs[1]; } *c; + + // CIR: cir.objsize max nullunknown %{{.+}} : !cir.ptr<!void> -> !u64i + // LLVM: call i64 @llvm.objectsize.i64.p0(ptr %{{.*}}, i1 false, i1 true, i1 false) + // OGCG: call i64 @llvm.objectsize.i64.p0(ptr %{{.*}}, i1 false, i1 true, i1 false) + gi = __builtin_object_size(&c->bs[0], 0); + // CIR: cir.objsize max nullunknown %{{.+}} : !cir.ptr<!void> -> !u64i + // LLVM: call i64 @llvm.objectsize.i64.p0(ptr %{{.*}}, i1 false, i1 true, i1 false) + // OGCG: call i64 @llvm.objectsize.i64.p0(ptr %{{.*}}, i1 false, i1 true, i1 false) + gi = __builtin_object_size(&c->bs[0], 1); + // CIR: cir.objsize min nullunknown %{{.+}} : !cir.ptr<!void> -> !u64i + // LLVM: call i64 @llvm.objectsize.i64.p0(ptr %{{.*}}, i1 true, i1 true, i1 false) + // OGCG: call i64 @llvm.objectsize.i64.p0(ptr %{{.*}}, i1 true, i1 true, i1 false) + gi = __builtin_object_size(&c->bs[0], 2); + // CIR: cir.const #cir.int<16> + // LLVM: store i32 16 + // OGCG: store i32 16 + gi = __builtin_object_size(&c->bs[0], 3); + + // NYI: DerivedToBase cast + // gi = __builtin_object_size((A*)&c->bs[0], 0); + + // CIR: cir.const #cir.int<16> + // LLVM: store i32 16 + // OGCG: store i32 16 + gi = __builtin_object_size((A*)&c->bs[0], 1); + + // NYI: DerivedToBase cast + // gi = __builtin_object_size((A*)&c->bs[0], 2); + + // CIR: cir.const #cir.int<16> + // LLVM: store i32 16 + // OGCG: store i32 16 + gi = __builtin_object_size((A*)&c->bs[0], 3); + + // CIR: cir.objsize max nullunknown %{{.+}} : !cir.ptr<!void> -> !u64i + // LLVM: call i64 @llvm.objectsize.i64.p0(ptr %{{.*}}, i1 false, i1 true, i1 false) + // OGCG: call i64 @llvm.objectsize.i64.p0(ptr %{{.*}}, i1 false, i1 true, i1 false) + gi = __builtin_object_size(&c->bs[0].buf[0], 0); + // CIR: cir.const #cir.int<16> + // LLVM: store i32 16 + // OGCG: store i32 16 + gi = __builtin_object_size(&c->bs[0].buf[0], 1); + // CIR: cir.objsize min nullunknown %{{.+}} : !cir.ptr<!void> -> !u64i + // LLVM: call i64 @llvm.objectsize.i64.p0(ptr %{{.*}}, i1 true, i1 true, i1 false) + // OGCG: call i64 @llvm.objectsize.i64.p0(ptr %{{.*}}, i1 true, i1 true, i1 false) + gi = __builtin_object_size(&c->bs[0].buf[0], 2); + // CIR: cir.const #cir.int<16> + // LLVM: store i32 16 + // OGCG: store i32 16 + gi = __builtin_object_size(&c->bs[0].buf[0], 3); +} diff --git a/clang/test/CIR/IR/objsize.cir b/clang/test/CIR/IR/objsize.cir new file mode 100644 index 0000000..bc24551 --- /dev/null +++ b/clang/test/CIR/IR/objsize.cir @@ -0,0 +1,89 @@ +// Test the cir.objsize operation can parse and print correctly (roundtrip) +// with all possible combinations of optional attributes + +// RUN: cir-opt %s --verify-roundtrip | FileCheck %s + +!u64i = !cir.int<u, 64> +!void = !cir.void + +module { + cir.func @test_max(%arg0: !cir.ptr<!void>) -> !u64i { + %0 = cir.objsize max %arg0 : !cir.ptr<!void> -> !u64i + cir.return %0 : !u64i + } + + cir.func @test_max_nullunknown(%arg0: !cir.ptr<!void>) -> !u64i { + %0 = cir.objsize max nullunknown %arg0 : !cir.ptr<!void> -> !u64i + cir.return %0 : !u64i + } + + cir.func @test_max_dynamic(%arg0: !cir.ptr<!void>) -> !u64i { + %0 = cir.objsize max dynamic %arg0 : !cir.ptr<!void> -> !u64i + cir.return %0 : !u64i + } + + cir.func @test_max_nullunknown_dynamic(%arg0: !cir.ptr<!void>) -> !u64i { + %0 = cir.objsize max nullunknown dynamic %arg0 : !cir.ptr<!void> -> !u64i + cir.return %0 : !u64i + } + + cir.func @test_min(%arg0: !cir.ptr<!void>) -> !u64i { + %0 = cir.objsize min %arg0 : !cir.ptr<!void> -> !u64i + cir.return %0 : !u64i + } + + cir.func @test_min_nullunknown(%arg0: !cir.ptr<!void>) -> !u64i { + %0 = cir.objsize min nullunknown %arg0 : !cir.ptr<!void> -> !u64i + cir.return %0 : !u64i + } + + cir.func @test_min_dynamic(%arg0: !cir.ptr<!void>) -> !u64i { + %0 = cir.objsize min dynamic %arg0 : !cir.ptr<!void> -> !u64i + cir.return %0 : !u64i + } + + cir.func @test_min_nullunknown_dynamic(%arg0: !cir.ptr<!void>) -> !u64i { + %0 = cir.objsize min nullunknown dynamic %arg0 : !cir.ptr<!void> -> !u64i + cir.return %0 : !u64i + } +} + +// CHECK: cir.func @test_max(%arg0: !cir.ptr<!void>) -> !u64i { +// CHECK: %0 = cir.objsize max %arg0 : !cir.ptr<!void> -> !u64i +// CHECK: cir.return %0 : !u64i +// CHECK: } + +// CHECK: cir.func @test_max_nullunknown(%arg0: !cir.ptr<!void>) -> !u64i { +// CHECK: %0 = cir.objsize max nullunknown %arg0 : !cir.ptr<!void> -> !u64i +// CHECK: cir.return %0 : !u64i +// CHECK: } + +// CHECK: cir.func @test_max_dynamic(%arg0: !cir.ptr<!void>) -> !u64i { +// CHECK: %0 = cir.objsize max dynamic %arg0 : !cir.ptr<!void> -> !u64i +// CHECK: cir.return %0 : !u64i +// CHECK: } + +// CHECK: cir.func @test_max_nullunknown_dynamic(%arg0: !cir.ptr<!void>) -> !u64i { +// CHECK: %0 = cir.objsize max nullunknown dynamic %arg0 : !cir.ptr<!void> -> !u64i +// CHECK: cir.return %0 : !u64i +// CHECK: } + +// CHECK: cir.func @test_min(%arg0: !cir.ptr<!void>) -> !u64i { +// CHECK: %0 = cir.objsize min %arg0 : !cir.ptr<!void> -> !u64i +// CHECK: cir.return %0 : !u64i +// CHECK: } + +// CHECK: cir.func @test_min_nullunknown(%arg0: !cir.ptr<!void>) -> !u64i { +// CHECK: %0 = cir.objsize min nullunknown %arg0 : !cir.ptr<!void> -> !u64i +// CHECK: cir.return %0 : !u64i +// CHECK: } + +// CHECK: cir.func @test_min_dynamic(%arg0: !cir.ptr<!void>) -> !u64i { +// CHECK: %0 = cir.objsize min dynamic %arg0 : !cir.ptr<!void> -> !u64i +// CHECK: cir.return %0 : !u64i +// CHECK: } + +// CHECK: cir.func @test_min_nullunknown_dynamic(%arg0: !cir.ptr<!void>) -> !u64i { +// CHECK: %0 = cir.objsize min nullunknown dynamic %arg0 : !cir.ptr<!void> -> !u64i +// CHECK: cir.return %0 : !u64i +// CHECK: } diff --git a/clang/test/ClangScanDeps/strip-codegen-args.m b/clang/test/ClangScanDeps/strip-codegen-args.m index 71171f4..f2cec62 100644 --- a/clang/test/ClangScanDeps/strip-codegen-args.m +++ b/clang/test/ClangScanDeps/strip-codegen-args.m @@ -16,6 +16,7 @@ // CHECK-NOT: "-flto" // CHECK-NOT: "-fno-autolink" // CHECK-NOT: "-mrelax-relocations=no" +// CHECK-NOT: "-mspeculative-load-hardening" // CHECK: ] // CHECK: "name": "A" // CHECK: } @@ -39,6 +40,11 @@ "command": "clang -Imodules/A -fmodules -fmodules-cache-path=DIR/module-cache -fimplicit-modules -O2 -flto=full -fsyntax-only DIR/t3.m", "file": "DIR/t2.m" } + { + "directory": "DIR", + "command": "clang -Imodules/A -fmodules -fmodules-cache-path=DIR/module-cache -fimplicit-modules -O2 -mspeculative-load-hardening -fsyntax-only DIR/t3.m", + "file": "DIR/t3.m" + } ] //--- modules/A/module.modulemap diff --git a/clang/test/CodeGenHLSL/builtins/firstbithigh.hlsl b/clang/test/CodeGenHLSL/builtins/firstbithigh.hlsl index 368d652..51b0f81 100644 --- a/clang/test/CodeGenHLSL/builtins/firstbithigh.hlsl +++ b/clang/test/CodeGenHLSL/builtins/firstbithigh.hlsl @@ -1,161 +1,260 @@ // RUN: %clang_cc1 -finclude-default-header -x hlsl -triple \ -// RUN: dxil-pc-shadermodel6.3-library %s -fnative-half-type -fnative-int16-type \ -// RUN: -emit-llvm -disable-llvm-passes -o - | FileCheck %s -DTARGET=dx +// RUN: dxil-pc-shadermodel6.3-library %s -fnative-half-type \ +// RUN: -fnative-int16-type -emit-llvm -O1 -o - | FileCheck %s -DTARGET=dx \ +// RUN: --check-prefixes=CHECK,DXCHECK // RUN: %clang_cc1 -finclude-default-header -x hlsl -triple \ -// RUN: spirv-unknown-vulkan-compute %s -fnative-half-type -fnative-int16-type \ -// RUN: -emit-llvm -disable-llvm-passes \ -// RUN: -o - | FileCheck %s -DTARGET=spv +// RUN: spirv-unknown-vulkan-compute %s -fnative-half-type \ +// RUN: -fnative-int16-type -emit-llvm -O1 -o - | FileCheck %s -DTARGET=spv #ifdef __HLSL_ENABLE_16_BIT // CHECK-LABEL: test_firstbithigh_ushort -// CHECK: call i32 @llvm.[[TARGET]].firstbituhigh.i16 +// CHECK: [[FBH:%.*]] = tail call {{.*}}i32 @llvm.[[TARGET]].firstbituhigh.i16 +// DXCHECK-NEXT: [[SUB:%.*]] = sub i32 15, [[FBH]] +// DXCHECK-NEXT: [[ICMP:%.*]] = icmp eq i32 [[FBH]], -1 +// DXCHECK-NEXT: select i1 %cmp.i, i32 -1, i32 [[SUB]] +// CHECK-NEXT: ret i32 uint test_firstbithigh_ushort(uint16_t p0) { return firstbithigh(p0); } // CHECK-LABEL: test_firstbithigh_ushort2 -// CHECK: call <2 x i32> @llvm.[[TARGET]].firstbituhigh.v2i16 +// CHECK: [[FBH:%.*]] = tail call {{.*}}<2 x i32> @llvm.[[TARGET]].firstbituhigh.v2i16 +// DXCHECK-NEXT: [[SUB:%.*]] = sub <2 x i32> splat (i32 15), [[FBH]] +// DXCHECK-NEXT: [[ICMP:%.*]] = icmp eq <2 x i32> [[FBH]], splat (i32 -1) +// DXCHECK-NEXT: select <2 x i1> %cmp.i, <2 x i32> splat (i32 -1), <2 x i32> [[SUB]] +// CHECK-NEXT: ret <2 x i32> uint2 test_firstbithigh_ushort2(uint16_t2 p0) { return firstbithigh(p0); } // CHECK-LABEL: test_firstbithigh_ushort3 -// CHECK: call <3 x i32> @llvm.[[TARGET]].firstbituhigh.v3i16 +// CHECK: [[FBH:%.*]] = tail call {{.*}}<3 x i32> @llvm.[[TARGET]].firstbituhigh.v3i16 +// DXCHECK-NEXT: [[SUB:%.*]] = sub <3 x i32> splat (i32 15), [[FBH]] +// DXCHECK-NEXT: [[ICMP:%.*]] = icmp eq <3 x i32> [[FBH]], splat (i32 -1) +// DXCHECK-NEXT: select <3 x i1> %cmp.i, <3 x i32> splat (i32 -1), <3 x i32> [[SUB]] +// CHECK-NEXT: ret <3 x i32> uint3 test_firstbithigh_ushort3(uint16_t3 p0) { return firstbithigh(p0); } // CHECK-LABEL: test_firstbithigh_ushort4 -// CHECK: call <4 x i32> @llvm.[[TARGET]].firstbituhigh.v4i16 +// CHECK: [[FBH:%.*]] = tail call {{.*}}<4 x i32> @llvm.[[TARGET]].firstbituhigh.v4i16 +// DXCHECK-NEXT: [[SUB:%.*]] = sub <4 x i32> splat (i32 15), [[FBH]] +// DXCHECK-NEXT: [[ICMP:%.*]] = icmp eq <4 x i32> [[FBH]], splat (i32 -1) +// DXCHECK-NEXT: select <4 x i1> %cmp.i, <4 x i32> splat (i32 -1), <4 x i32> [[SUB]] +// CHECK-NEXT: ret <4 x i32> uint4 test_firstbithigh_ushort4(uint16_t4 p0) { return firstbithigh(p0); } // CHECK-LABEL: test_firstbithigh_short -// CHECK: call i32 @llvm.[[TARGET]].firstbitshigh.i16 +// CHECK: [[FBH:%.*]] = tail call {{.*}}i32 @llvm.[[TARGET]].firstbitshigh.i16 +// DXCHECK-NEXT: [[SUB:%.*]] = sub i32 15, [[FBH]] +// DXCHECK-NEXT: [[ICMP:%.*]] = icmp eq i32 [[FBH]], -1 +// DXCHECK-NEXT: select i1 %cmp.i, i32 -1, i32 [[SUB]] +// CHECK-NEXT: ret i32 uint test_firstbithigh_short(int16_t p0) { return firstbithigh(p0); } // CHECK-LABEL: test_firstbithigh_short2 -// CHECK: call <2 x i32> @llvm.[[TARGET]].firstbitshigh.v2i16 +// CHECK: [[FBH:%.*]] = tail call {{.*}}<2 x i32> @llvm.[[TARGET]].firstbitshigh.v2i16 +// DXCHECK-NEXT: [[SUB:%.*]] = sub <2 x i32> splat (i32 15), [[FBH]] +// DXCHECK-NEXT: [[ICMP:%.*]] = icmp eq <2 x i32> [[FBH]], splat (i32 -1) +// DXCHECK-NEXT: select <2 x i1> %cmp.i, <2 x i32> splat (i32 -1), <2 x i32> [[SUB]] +// CHECK-NEXT: ret <2 x i32> uint2 test_firstbithigh_short2(int16_t2 p0) { return firstbithigh(p0); } // CHECK-LABEL: test_firstbithigh_short3 -// CHECK: call <3 x i32> @llvm.[[TARGET]].firstbitshigh.v3i16 +// CHECK: [[FBH:%.*]] = tail call {{.*}}<3 x i32> @llvm.[[TARGET]].firstbitshigh.v3i16 +// DXCHECK-NEXT: [[SUB:%.*]] = sub <3 x i32> splat (i32 15), [[FBH]] +// DXCHECK-NEXT: [[ICMP:%.*]] = icmp eq <3 x i32> [[FBH]], splat (i32 -1) +// DXCHECK-NEXT: select <3 x i1> %cmp.i, <3 x i32> splat (i32 -1), <3 x i32> [[SUB]] +// CHECK-NEXT: ret <3 x i32> uint3 test_firstbithigh_short3(int16_t3 p0) { return firstbithigh(p0); } // CHECK-LABEL: test_firstbithigh_short4 -// CHECK: call <4 x i32> @llvm.[[TARGET]].firstbitshigh.v4i16 +// CHECK: [[FBH:%.*]] = tail call {{.*}}<4 x i32> @llvm.[[TARGET]].firstbitshigh.v4i16 +// DXCHECK-NEXT: [[SUB:%.*]] = sub <4 x i32> splat (i32 15), [[FBH]] +// DXCHECK-NEXT: [[ICMP:%.*]] = icmp eq <4 x i32> [[FBH]], splat (i32 -1) +// DXCHECK-NEXT: select <4 x i1> %cmp.i, <4 x i32> splat (i32 -1), <4 x i32> [[SUB]] +// CHECK-NEXT: ret <4 x i32> uint4 test_firstbithigh_short4(int16_t4 p0) { return firstbithigh(p0); } #endif // __HLSL_ENABLE_16_BIT // CHECK-LABEL: test_firstbithigh_uint -// CHECK: call i32 @llvm.[[TARGET]].firstbituhigh.i32 +// CHECK: [[FBH:%.*]] = tail call {{.*}}i32 @llvm.[[TARGET]].firstbituhigh.i32 +// DXCHECK-NEXT: [[SUB:%.*]] = sub i32 31, [[FBH]] +// DXCHECK-NEXT: [[ICMP:%.*]] = icmp eq i32 [[FBH]], -1 +// DXCHECK-NEXT: select i1 %cmp.i, i32 -1, i32 [[SUB]] +// CHECK-NEXT: ret i32 uint test_firstbithigh_uint(uint p0) { return firstbithigh(p0); } // CHECK-LABEL: test_firstbithigh_uint2 -// CHECK: call <2 x i32> @llvm.[[TARGET]].firstbituhigh.v2i32 +// CHECK: [[FBH:%.*]] = tail call {{.*}}<2 x i32> @llvm.[[TARGET]].firstbituhigh.v2i32 +// DXCHECK-NEXT: [[SUB:%.*]] = sub <2 x i32> splat (i32 31), [[FBH]] +// DXCHECK-NEXT: [[ICMP:%.*]] = icmp eq <2 x i32> [[FBH]], splat (i32 -1) +// DXCHECK-NEXT: select <2 x i1> %cmp.i, <2 x i32> splat (i32 -1), <2 x i32> [[SUB]] +// CHECK-NEXT: ret <2 x i32> uint2 test_firstbithigh_uint2(uint2 p0) { return firstbithigh(p0); } // CHECK-LABEL: test_firstbithigh_uint3 -// CHECK: call <3 x i32> @llvm.[[TARGET]].firstbituhigh.v3i32 +// CHECK: [[FBH:%.*]] = tail call {{.*}}<3 x i32> @llvm.[[TARGET]].firstbituhigh.v3i32 +// DXCHECK-NEXT: [[SUB:%.*]] = sub <3 x i32> splat (i32 31), [[FBH]] +// DXCHECK-NEXT: [[ICMP:%.*]] = icmp eq <3 x i32> [[FBH]], splat (i32 -1) +// DXCHECK-NEXT: select <3 x i1> %cmp.i, <3 x i32> splat (i32 -1), <3 x i32> [[SUB]] +// CHECK-NEXT: ret <3 x i32> uint3 test_firstbithigh_uint3(uint3 p0) { return firstbithigh(p0); } // CHECK-LABEL: test_firstbithigh_uint4 -// CHECK: call <4 x i32> @llvm.[[TARGET]].firstbituhigh.v4i32 +// CHECK: [[FBH:%.*]] = tail call {{.*}}<4 x i32> @llvm.[[TARGET]].firstbituhigh.v4i32 +// DXCHECK-NEXT: [[SUB:%.*]] = sub <4 x i32> splat (i32 31), [[FBH]] +// DXCHECK-NEXT: [[ICMP:%.*]] = icmp eq <4 x i32> [[FBH]], splat (i32 -1) +// DXCHECK-NEXT: select <4 x i1> %cmp.i, <4 x i32> splat (i32 -1), <4 x i32> [[SUB]] +// CHECK-NEXT: ret <4 x i32> uint4 test_firstbithigh_uint4(uint4 p0) { return firstbithigh(p0); } // CHECK-LABEL: test_firstbithigh_ulong -// CHECK: call i32 @llvm.[[TARGET]].firstbituhigh.i64 +// CHECK: [[FBH:%.*]] = tail call {{.*}}i32 @llvm.[[TARGET]].firstbituhigh.i64 +// DXCHECK-NEXT: [[SUB:%.*]] = sub i32 63, [[FBH]] +// DXCHECK-NEXT: [[ICMP:%.*]] = icmp eq i32 [[FBH]], -1 +// DXCHECK-NEXT: select i1 %cmp.i, i32 -1, i32 [[SUB]] +// CHECK-NEXT: ret i32 uint test_firstbithigh_ulong(uint64_t p0) { return firstbithigh(p0); } // CHECK-LABEL: test_firstbithigh_ulong2 -// CHECK: call <2 x i32> @llvm.[[TARGET]].firstbituhigh.v2i64 +// CHECK: [[FBH:%.*]] = tail call {{.*}}<2 x i32> @llvm.[[TARGET]].firstbituhigh.v2i64 +// DXCHECK-NEXT: [[SUB:%.*]] = sub <2 x i32> splat (i32 63), [[FBH]] +// DXCHECK-NEXT: [[ICMP:%.*]] = icmp eq <2 x i32> [[FBH]], splat (i32 -1) +// DXCHECK-NEXT: select <2 x i1> %cmp.i, <2 x i32> splat (i32 -1), <2 x i32> [[SUB]] +// CHECK-NEXT: ret <2 x i32> uint2 test_firstbithigh_ulong2(uint64_t2 p0) { return firstbithigh(p0); } // CHECK-LABEL: test_firstbithigh_ulong3 -// CHECK: call <3 x i32> @llvm.[[TARGET]].firstbituhigh.v3i64 +// CHECK: [[FBH:%.*]] = tail call {{.*}}<3 x i32> @llvm.[[TARGET]].firstbituhigh.v3i64 +// DXCHECK-NEXT: [[SUB:%.*]] = sub <3 x i32> splat (i32 63), [[FBH]] +// DXCHECK-NEXT: [[ICMP:%.*]] = icmp eq <3 x i32> [[FBH]], splat (i32 -1) +// DXCHECK-NEXT: select <3 x i1> %cmp.i, <3 x i32> splat (i32 -1), <3 x i32> [[SUB]] +// CHECK-NEXT: ret <3 x i32> uint3 test_firstbithigh_ulong3(uint64_t3 p0) { return firstbithigh(p0); } // CHECK-LABEL: test_firstbithigh_ulong4 -// CHECK: call <4 x i32> @llvm.[[TARGET]].firstbituhigh.v4i64 +// CHECK: [[FBH:%.*]] = tail call {{.*}}<4 x i32> @llvm.[[TARGET]].firstbituhigh.v4i64 +// DXCHECK-NEXT: [[SUB:%.*]] = sub <4 x i32> splat (i32 63), [[FBH]] +// DXCHECK-NEXT: [[ICMP:%.*]] = icmp eq <4 x i32> [[FBH]], splat (i32 -1) +// DXCHECK-NEXT: select <4 x i1> %cmp.i, <4 x i32> splat (i32 -1), <4 x i32> [[SUB]] +// CHECK-NEXT: ret <4 x i32> uint4 test_firstbithigh_ulong4(uint64_t4 p0) { return firstbithigh(p0); } // CHECK-LABEL: test_firstbithigh_int -// CHECK: call i32 @llvm.[[TARGET]].firstbitshigh.i32 +// CHECK: [[FBH:%.*]] = tail call {{.*}}i32 @llvm.[[TARGET]].firstbitshigh.i32 +// DXCHECK-NEXT: [[SUB:%.*]] = sub i32 31, [[FBH]] +// DXCHECK-NEXT: [[ICMP:%.*]] = icmp eq i32 [[FBH]], -1 +// DXCHECK-NEXT: select i1 %cmp.i, i32 -1, i32 [[SUB]] +// CHECK-NEXT: ret i32 uint test_firstbithigh_int(int p0) { return firstbithigh(p0); } // CHECK-LABEL: test_firstbithigh_int2 -// CHECK: call <2 x i32> @llvm.[[TARGET]].firstbitshigh.v2i32 +// CHECK: [[FBH:%.*]] = tail call {{.*}}<2 x i32> @llvm.[[TARGET]].firstbitshigh.v2i32 +// DXCHECK-NEXT: [[SUB:%.*]] = sub <2 x i32> splat (i32 31), [[FBH]] +// DXCHECK-NEXT: [[ICMP:%.*]] = icmp eq <2 x i32> [[FBH]], splat (i32 -1) +// DXCHECK-NEXT: select <2 x i1> %cmp.i, <2 x i32> splat (i32 -1), <2 x i32> [[SUB]] +// CHECK-NEXT: ret <2 x i32> uint2 test_firstbithigh_int2(int2 p0) { return firstbithigh(p0); } // CHECK-LABEL: test_firstbithigh_int3 -// CHECK: call <3 x i32> @llvm.[[TARGET]].firstbitshigh.v3i32 +// CHECK: [[FBH:%.*]] = tail call {{.*}}<3 x i32> @llvm.[[TARGET]].firstbitshigh.v3i32 +// DXCHECK-NEXT: [[SUB:%.*]] = sub <3 x i32> splat (i32 31), [[FBH]] +// DXCHECK-NEXT: [[ICMP:%.*]] = icmp eq <3 x i32> [[FBH]], splat (i32 -1) +// DXCHECK-NEXT: select <3 x i1> %cmp.i, <3 x i32> splat (i32 -1), <3 x i32> [[SUB]] +// CHECK-NEXT: ret <3 x i32> uint3 test_firstbithigh_int3(int3 p0) { return firstbithigh(p0); } // CHECK-LABEL: test_firstbithigh_int4 -// CHECK: call <4 x i32> @llvm.[[TARGET]].firstbitshigh.v4i32 +// CHECK: [[FBH:%.*]] = tail call {{.*}}<4 x i32> @llvm.[[TARGET]].firstbitshigh.v4i32 +// DXCHECK-NEXT: [[SUB:%.*]] = sub <4 x i32> splat (i32 31), [[FBH]] +// DXCHECK-NEXT: [[ICMP:%.*]] = icmp eq <4 x i32> [[FBH]], splat (i32 -1) +// DXCHECK-NEXT: select <4 x i1> %cmp.i, <4 x i32> splat (i32 -1), <4 x i32> [[SUB]] +// CHECK-NEXT: ret <4 x i32> uint4 test_firstbithigh_int4(int4 p0) { return firstbithigh(p0); } // CHECK-LABEL: test_firstbithigh_long -// CHECK: call i32 @llvm.[[TARGET]].firstbitshigh.i64 +// CHECK: [[FBH:%.*]] = tail call {{.*}}i32 @llvm.[[TARGET]].firstbitshigh.i64 +// DXCHECK-NEXT: [[SUB:%.*]] = sub i32 63, [[FBH]] +// DXCHECK-NEXT: [[ICMP:%.*]] = icmp eq i32 [[FBH]], -1 +// DXCHECK-NEXT: select i1 %cmp.i, i32 -1, i32 [[SUB]] +// CHECK-NEXT: ret i32 uint test_firstbithigh_long(int64_t p0) { return firstbithigh(p0); } // CHECK-LABEL: test_firstbithigh_long2 -// CHECK: call <2 x i32> @llvm.[[TARGET]].firstbitshigh.v2i64 +// CHECK: [[FBH:%.*]] = tail call {{.*}}<2 x i32> @llvm.[[TARGET]].firstbitshigh.v2i64 +// DXCHECK-NEXT: [[SUB:%.*]] = sub <2 x i32> splat (i32 63), [[FBH]] +// DXCHECK-NEXT: [[ICMP:%.*]] = icmp eq <2 x i32> [[FBH]], splat (i32 -1) +// DXCHECK-NEXT: select <2 x i1> %cmp.i, <2 x i32> splat (i32 -1), <2 x i32> [[SUB]] +// CHECK-NEXT: ret <2 x i32> uint2 test_firstbithigh_long2(int64_t2 p0) { return firstbithigh(p0); } // CHECK-LABEL: test_firstbithigh_long3 -// CHECK: call <3 x i32> @llvm.[[TARGET]].firstbitshigh.v3i64 +// CHECK: [[FBH:%.*]] = tail call {{.*}}<3 x i32> @llvm.[[TARGET]].firstbitshigh.v3i64 +// DXCHECK-NEXT: [[SUB:%.*]] = sub <3 x i32> splat (i32 63), [[FBH]] +// DXCHECK-NEXT: [[ICMP:%.*]] = icmp eq <3 x i32> [[FBH]], splat (i32 -1) +// DXCHECK-NEXT: select <3 x i1> %cmp.i, <3 x i32> splat (i32 -1), <3 x i32> [[SUB]] +// CHECK-NEXT: ret <3 x i32> uint3 test_firstbithigh_long3(int64_t3 p0) { return firstbithigh(p0); } // CHECK-LABEL: test_firstbithigh_long4 -// CHECK: call <4 x i32> @llvm.[[TARGET]].firstbitshigh.v4i64 +// CHECK: [[FBH:%.*]] = tail call {{.*}}<4 x i32> @llvm.[[TARGET]].firstbitshigh.v4i64 +// DXCHECK-NEXT: [[SUB:%.*]] = sub <4 x i32> splat (i32 63), [[FBH]] +// DXCHECK-NEXT: [[ICMP:%.*]] = icmp eq <4 x i32> [[FBH]], splat (i32 -1) +// DXCHECK-NEXT: select <4 x i1> %cmp.i, <4 x i32> splat (i32 -1), <4 x i32> [[SUB]] +// CHECK-NEXT: ret <4 x i32> uint4 test_firstbithigh_long4(int64_t4 p0) { return firstbithigh(p0); } // CHECK-LABEL: test_firstbithigh_upcast -// CHECK: [[FBH:%.*]] = call <4 x i32> @llvm.[[TARGET]].firstbituhigh.v4i32(<4 x i32> %{{.*}}) -// CHECK: [[CONV:%.*]] = zext <4 x i32> [[FBH]] to <4 x i64> -// CHECK: ret <4 x i64> [[CONV]] +// CHECK: [[FBH:%.*]] = tail call {{.*}}<4 x i32> @llvm.[[TARGET]].firstbituhigh.v4i32(<4 x i32> %{{.*}}) +// DXCHECK-NEXT: [[SUB:%.*]] = sub <4 x i32> splat (i32 31), [[FBH]] +// DXCHECK-NEXT: [[ICMP:%.*]] = icmp eq <4 x i32> [[FBH]], splat (i32 -1) +// DXCHECK-NEXT: select <4 x i1> %cmp.i, <4 x i32> splat (i32 -1), <4 x i32> [[SUB]] +// CHECK-NEXT: [[ZEXT:%.*]] = zext <4 x i32> {{.*}} to <4 x i64> +// CHECK-NEXT: ret <4 x i64> [[ZEXT]] uint64_t4 test_firstbithigh_upcast(uint4 p0) { return firstbithigh(p0); } diff --git a/clang/test/CodeGenHLSL/semantics/DispatchThreadID.hlsl b/clang/test/CodeGenHLSL/semantics/DispatchThreadID.hlsl index 7aeb877..b0abaed 100644 --- a/clang/test/CodeGenHLSL/semantics/DispatchThreadID.hlsl +++ b/clang/test/CodeGenHLSL/semantics/DispatchThreadID.hlsl @@ -24,4 +24,3 @@ void foo(uint Idx : SV_DispatchThreadID) {} [shader("compute")] [numthreads(8,8,1)] void bar(uint2 Idx : SV_DispatchThreadID) {} - diff --git a/clang/test/CodeGenHLSL/semantics/semantic.arbitrary.hlsl b/clang/test/CodeGenHLSL/semantics/semantic.arbitrary.hlsl new file mode 100644 index 0000000..96d5b99 --- /dev/null +++ b/clang/test/CodeGenHLSL/semantics/semantic.arbitrary.hlsl @@ -0,0 +1,36 @@ +// RUN: %clang_cc1 -triple spirv-unknown-vulkan-vertex -x hlsl -emit-llvm -finclude-default-header -disable-llvm-passes -o - %s | FileCheck %s --check-prefixes=CHECK,CHECK-SPIRV -DTARGET=spv +// RUN: %clang_cc1 -triple dxil-pc-shadermodel6.3-vertex -x hlsl -emit-llvm -finclude-default-header -disable-llvm-passes -o - %s | FileCheck %s --check-prefixes=CHECK,CHECK-DXIL -DTARGET=dx + +// CHECK-SPIRV-DAG: @AAA0 = external hidden thread_local addrspace(7) externally_initialized constant float, !spirv.Decorations ![[#METADATA_0:]] +// CHECK-SPIRV-DAG: @B0 = external hidden thread_local addrspace(7) externally_initialized constant i32, !spirv.Decorations ![[#METADATA_2:]] +// CHECK-SPIRV-DAG: @CC0 = external hidden thread_local addrspace(7) externally_initialized constant <2 x float>, !spirv.Decorations ![[#METADATA_4:]] + + +// FIXME: replace `float2 c` with a matrix when available. +void main(float a : AAA, int b : B, float2 c : CC) { + float tmp = a + b + c.x + c.y; +} +// CHECK-SPIRV: define internal spir_func void @_Z4mainfiDv2_f(float noundef nofpclass(nan inf) %a, i32 noundef %b, <2 x float> noundef nofpclass(nan inf) %c) #0 { + +// CHECK: define void @main() + +// CHECK-DXIL: %AAA0 = call float @llvm.dx.load.input.f32(i32 4, i32 0, i32 0, i8 0, i32 poison) +// CHECK-DXIL: %B0 = call i32 @llvm.dx.load.input.i32(i32 4, i32 0, i32 0, i8 0, i32 poison) +// CHECK-DXIL %CC0 = call <2 x float> @llvm.dx.load.input.v2f32(i32 4, i32 0, i32 0, i8 0, i32 poison) +// CHECK-DXIL: call void @_Z4mainfiDv2_f(float %AAA0, i32 %B0, <2 x float> %CC0) + +// CHECK-SPIRV: %[[#AAA0:]] = load float, ptr addrspace(7) @AAA0, align 4 +// CHECK-SPIRV: %[[#B0:]] = load i32, ptr addrspace(7) @B0, align 4 +// CHECK-SPIRV: %[[#CC0:]] = load <2 x float>, ptr addrspace(7) @CC0, align 8 +// CHECK-SPIRV: call spir_func void @_Z4mainfiDv2_f(float %[[#AAA0]], i32 %[[#B0]], <2 x float> %[[#CC0]]) [ "convergencectrl"(token %0) ] + + +// CHECK-SPIRV-DAG: ![[#METADATA_0]] = !{![[#METADATA_1:]]} +// CHECK-SPIRV-DAG: ![[#METADATA_2]] = !{![[#METADATA_3:]]} +// CHECK-SPIRV-DAG: ![[#METADATA_4]] = !{![[#METADATA_5:]]} + +// CHECK-SPIRV-DAG: ![[#METADATA_1]] = !{i32 30, i32 0} +// CHECK-SPIRV-DAG: ![[#METADATA_3]] = !{i32 30, i32 1} +// CHECK-SPIRV-DAG: ![[#METADATA_5]] = !{i32 30, i32 2} +// | `- Location index +// `-> Decoration "Location" diff --git a/clang/test/CodeGenHLSL/semantics/semantic.array.hlsl b/clang/test/CodeGenHLSL/semantics/semantic.array.hlsl new file mode 100644 index 0000000..b2cb3da --- /dev/null +++ b/clang/test/CodeGenHLSL/semantics/semantic.array.hlsl @@ -0,0 +1,37 @@ +// RUN: %clang_cc1 -triple spirv-linux-vulkan-library -x hlsl -emit-llvm -finclude-default-header -disable-llvm-passes -o - %s | FileCheck %s --check-prefixes=CHECK,CHECK-SPIRV -DTARGET=spv +// RUN: %clang_cc1 -triple dxil-px-shadermodel6.3-library -x hlsl -emit-llvm -finclude-default-header -disable-llvm-passes -o - %s | FileCheck %s --check-prefixes=CHECK,CHECK-DXIL -DTARGET=dx + +struct S0 { + float4 position[2]; + float4 color; +}; + +// CHECK: %struct.S0 = type { [2 x <4 x float>], <4 x float> } + +// CHECK-SPIRV: @A0 = external hidden thread_local addrspace(7) externally_initialized constant [2 x <4 x float>], !spirv.Decorations ![[#MD_0:]] +// CHECK-SPIRV: @A2 = external hidden thread_local addrspace(7) externally_initialized constant <4 x float>, !spirv.Decorations ![[#MD_2:]] + +// CHECK: define void @main0() +// CHECK-DXIL: %A0 = call [2 x <4 x float>] @llvm.dx.load.input.a2v4f32(i32 4, i32 0, i32 0, i8 0, i32 poison) +// CHECK-DXIL: %[[#TMP0:]] = insertvalue %struct.S0 poison, [2 x <4 x float>] %A0, 0 +// CHECK-DXIL: %A2 = call <4 x float> @llvm.dx.load.input.v4f32(i32 4, i32 0, i32 0, i8 0, i32 poison) +// CHECK-DXIL: %[[#TMP1:]] = insertvalue %struct.S0 %[[#TMP0]], <4 x float> %A2, 1 + +// CHECK-SPIRV: %[[#A0:]] = load [2 x <4 x float>], ptr addrspace(7) @A0, align 16 +// CHECK-SPIRV: %[[#TMP0:]] = insertvalue %struct.S0 poison, [2 x <4 x float>] %[[#A0]], 0 +// CHECK-SPIRV: %[[#A2:]] = load <4 x float>, ptr addrspace(7) @A2, align 16 +// CHECK-SPIRV: %[[#TMP1:]] = insertvalue %struct.S0 %[[#TMP0]], <4 x float> %[[#A2]], 1 + +// CHECK: %[[#ARG:]] = alloca %struct.S0, align 16 +// CHECK: store %struct.S0 %[[#TMP1]], ptr %[[#ARG]], align 16 +// CHECK-DXIL: call void @{{.*}}main0{{.*}}(ptr %[[#ARG]]) +// CHECK-SPIRV: call spir_func void @{{.*}}main0{{.*}}(ptr %[[#ARG]]) +[shader("pixel")] +void main0(S0 p : A) { + float tmp = p.position[0] + p.position[1] + p.color; +} + +// CHECK-SPIRV: ![[#MD_0]] = !{![[#MD_1:]]} +// CHECK-SPIRV: ![[#MD_1]] = !{i32 30, i32 0} +// CHECK-SPIRV: ![[#MD_2]] = !{![[#MD_3:]]} +// CHECK-SPIRV: ![[#MD_3]] = !{i32 30, i32 2} diff --git a/clang/test/CodeGenHLSL/semantics/semantic.struct.hlsl b/clang/test/CodeGenHLSL/semantics/semantic.struct.hlsl new file mode 100644 index 0000000..733cf3a --- /dev/null +++ b/clang/test/CodeGenHLSL/semantics/semantic.struct.hlsl @@ -0,0 +1,77 @@ +// RUN: %clang_cc1 -triple dxil-pc-shadermodel6.3-library -x hlsl -emit-llvm -finclude-default-header -disable-llvm-passes -o - %s | FileCheck %s --check-prefixes=CHECK,CHECK-DXIL -DTARGET=dx +// RUN: %clang_cc1 -triple spirv-linux-vulkan-library -x hlsl -emit-llvm -finclude-default-header -disable-llvm-passes -o - %s | FileCheck %s --check-prefixes=CHECK,CHECK-SPIRV -DTARGET=spv + +struct S0 { + uint Idx : SV_DispatchThreadID; +}; + +// CHECK: define void @main0() +// CHECK-DXIL: %[[#ID:]] = call i32 @llvm.[[TARGET]].thread.id(i32 0) +// CHECK-SPIRV: %[[#ID:]] = call i32 @llvm.[[TARGET]].thread.id.i32(i32 0) +// CHECK: %[[#TMP:]] = insertvalue %struct.S0 poison, i32 %[[#ID:]], 0 +// CHECK: %[[#ARG:]] = alloca %struct.S0, align 8 +// CHECK: store %struct.S0 %[[#TMP]], ptr %[[#ARG]], align 4 +// CHECK-DXIL: call void @{{.*}}main0{{.*}}(ptr %[[#ARG]]) +// CHECK-SPIRV: call spir_func void @{{.*}}main0{{.*}}(ptr %[[#ARG]]) +[shader("compute")] +[numthreads(8,8,1)] +void main0(S0 p) {} + +struct S1 { + uint2 a : SV_DispatchThreadID; + uint2 b : SV_GroupThreadID; +}; + +// CHECK: define void @main1() +// CHECK-DXIL: %[[#ID:]] = call i32 @llvm.[[TARGET]].thread.id(i32 0) +// CHECK-SPIRV: %[[#ID:]] = call i32 @llvm.[[TARGET]].thread.id.i32(i32 0) +// CHECK: %[[#AX_:]] = insertelement <2 x i32> poison, i32 %[[#ID]], i64 0 +// CHECK-DXIL: %[[#ID:]] = call i32 @llvm.[[TARGET]].thread.id(i32 1) +// CHECK-SPIRV: %[[#ID:]] = call i32 @llvm.[[TARGET]].thread.id.i32(i32 1) +// CHECK: %[[#AXY:]] = insertelement <2 x i32> %[[#AX_]], i32 %[[#ID]], i64 1 +// CHECK: %[[#S1A_:]] = insertvalue %struct.S1 poison, <2 x i32> %[[#AXY]], 0 +// CHECK-DXIL: %[[#ID_X:]] = call i32 @llvm.[[TARGET]].thread.id.in.group(i32 0) +// CHECK-SPIRV: %[[#ID_X:]] = call i32 @llvm.[[TARGET]].thread.id.in.group.i32(i32 0) +// CHECK: %[[#ID_X_:]] = insertelement <2 x i32> poison, i32 %[[#ID_X]], i64 0 +// CHECK-DXIL: %[[#ID_Y:]] = call i32 @llvm.[[TARGET]].thread.id.in.group(i32 1) +// CHECK-SPIRV: %[[#ID_Y:]] = call i32 @llvm.[[TARGET]].thread.id.in.group.i32(i32 1) +// CHECK: %[[#ID_XY:]] = insertelement <2 x i32> %[[#ID_X_]], i32 %[[#ID_Y]], i64 1 +// CHECK: %[[#S1AB:]] = insertvalue %struct.S1 %[[#S1A_]], <2 x i32> %[[#ID_XYZ:]], 1 +// CHECK: %[[#ARG:]] = alloca %struct.S1, align 8 +// CHECK: store %struct.S1 %[[#S1AB]], ptr %[[#ARG]], align 8 +// CHECK-DXIL: call void @{{.*}}main1{{.*}}(ptr %[[#ARG]]) +// CHECK-SPIRV: call spir_func void @{{.*}}main1{{.*}}(ptr %[[#ARG]]) +[shader("compute")] +[numthreads(8,8,1)] +void main1(S1 p) {} + +struct S2C { + uint2 b : SV_GroupThreadID; +}; + +struct S2 { + uint a : SV_DispatchThreadID; + S2C child; +}; + +// CHECK: define void @main2() +// CHECK-DXIL: %[[#ID:]] = call i32 @llvm.[[TARGET]].thread.id(i32 0) +// CHECK-SPIRV: %[[#ID:]] = call i32 @llvm.[[TARGET]].thread.id.i32(i32 0) +// CHECK: %[[#S2A_:]] = insertvalue %struct.S2 poison, i32 %[[#ID:]], 0 + +// CHECK-DXIL: %[[#ID_X:]] = call i32 @llvm.[[TARGET]].thread.id.in.group(i32 0) +// CHECK-SPIRV: %[[#ID_X:]] = call i32 @llvm.[[TARGET]].thread.id.in.group.i32(i32 0) +// CHECK: %[[#ID_X_:]] = insertelement <2 x i32> poison, i32 %[[#ID_X]], i64 0 +// CHECK-DXIL: %[[#ID_Y:]] = call i32 @llvm.[[TARGET]].thread.id.in.group(i32 1) +// CHECK-SPIRV: %[[#ID_Y:]] = call i32 @llvm.[[TARGET]].thread.id.in.group.i32(i32 1) +// CHECK: %[[#ID_XY:]] = insertelement <2 x i32> %[[#ID_X_]], i32 %[[#ID_Y]], i64 1 +// CHECK: %[[#S2C:]] = insertvalue %struct.S2C poison, <2 x i32> %[[#ID_XY:]], 0 + +// CHECK: %[[#S2AB:]] = insertvalue %struct.S2 %[[#S2A_]], %struct.S2C %[[#S2V:]], 1 +// CHECK: %[[#ARG:]] = alloca %struct.S2, align 8 +// CHECK: store %struct.S2 %[[#S2AB]], ptr %[[#ARG]], align 1 +// CHECK-DXIL: call void @{{.*}}main2{{.*}}(ptr %[[#ARG]]) +// CHECK-SPIRV: call spir_func void @{{.*}}main2{{.*}}(ptr %[[#ARG]]) +[shader("compute")] +[numthreads(8,8,1)] +void main2(S2 p) {} diff --git a/clang/test/Driver/HLSL/wconversion.hlsl b/clang/test/Driver/HLSL/wconversion.hlsl new file mode 100644 index 0000000..1857a3d --- /dev/null +++ b/clang/test/Driver/HLSL/wconversion.hlsl @@ -0,0 +1,7 @@ +// RUN: %clang_dxc -T lib_6_7 %s -### %s 2>&1 | FileCheck %s --check-prefixes=CONV +// RUN: %clang_dxc -T lib_6_7 -Wno-conversion %s -### %s 2>&1 | FileCheck %s --check-prefixes=NOCONV + +// make sure we generate -Wconversion by default +// CONV: "-Wconversion" +// make sure -Wno-conversion still works +// NOCONV: "-Wno-conversion" diff --git a/clang/test/Driver/Inputs/rocm/amdgcn/bitcode/oclc_isa_version_1250.bc b/clang/test/Driver/Inputs/rocm/amdgcn/bitcode/oclc_isa_version_1250.bc new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/clang/test/Driver/Inputs/rocm/amdgcn/bitcode/oclc_isa_version_1250.bc diff --git a/clang/test/Driver/Inputs/rocm/amdgcn/bitcode/oclc_isa_version_1251.bc b/clang/test/Driver/Inputs/rocm/amdgcn/bitcode/oclc_isa_version_1251.bc new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/clang/test/Driver/Inputs/rocm/amdgcn/bitcode/oclc_isa_version_1251.bc diff --git a/clang/test/Driver/amdgpu-openmp-sanitize-options.c b/clang/test/Driver/amdgpu-openmp-sanitize-options.c index 914e018..10d6498 100644 --- a/clang/test/Driver/amdgpu-openmp-sanitize-options.c +++ b/clang/test/Driver/amdgpu-openmp-sanitize-options.c @@ -22,10 +22,14 @@ // RUN: %clang -no-canonical-prefixes -### --target=x86_64-unknown-linux-gnu -fopenmp=libomp --offload-arch=gfx908:xnack+ -fsanitize=address --rocm-path=%S/Inputs/rocm %s 2>&1 \ // RUN: | FileCheck -check-prefixes=HOSTSAN,GPUSAN,SAN %s -// ASan enabled for multiple amdgpu-arch [gfx908:xnack+,gfx900:xnack+] +// GPU ASan enabled for multiple amdgpu-arch [gfx908:xnack+,gfx900:xnack+] // RUN: %clang -no-canonical-prefixes -### --target=x86_64-unknown-linux-gnu -fopenmp=libomp --offload-arch=gfx908:xnack+ --offload-arch=gfx900:xnack+ -fsanitize=address -fgpu-sanitize --rocm-path=%S/Inputs/rocm %s 2>&1 \ // RUN: | FileCheck -check-prefixes=HOSTSAN,GPUSAN,SAN %s +// GPU ASan enabled for amdgpu-arch [gfx1250,gfx1251] +// RUN: %clang -no-canonical-prefixes -### --target=x86_64-unknown-linux-gnu -fopenmp=libomp --offload-arch=gfx1250,gfx1251 -fsanitize=address -fgpu-sanitize --rocm-path=%S/Inputs/rocm %s 2>&1 \ +// RUN: | FileCheck -check-prefixes=HOSTSAN,GPUSAN,SAN %s + // GPU ASan Disabled Test Cases // GPU ASan disabled through '-fsanitize=address' without '-fgpu-sanitize' flag for amdgpu-arch [gfx908] @@ -56,9 +60,9 @@ // HOSTSAN: {{"[^"]*clang[^"]*" "-cc1" "-triple" "x86_64-unknown-linux-gnu".* "-fopenmp".* "-fsanitize=address".* "--offload-targets=amdgcn-amd-amdhsa".* "-x" "c".*}} -// GPUSAN: {{"[^"]*clang[^"]*" "-cc1" "-triple" "amdgcn-amd-amdhsa" "-aux-triple" "x86_64-unknown-linux-gnu".* "-emit-llvm-bc".* "-mlink-bitcode-file" "[^"]*asanrtl.bc".* "-mlink-bitcode-file" "[^"]*ockl.bc".* "-target-cpu" "(gfx908|gfx900)".* "-fopenmp".* "-fsanitize=address".* "-x" "c".*}} +// GPUSAN: {{"[^"]*clang[^"]*" "-cc1" "-triple" "amdgcn-amd-amdhsa" "-aux-triple" "x86_64-unknown-linux-gnu".* "-emit-llvm-bc".* "-mlink-bitcode-file" "[^"]*asanrtl.bc".* "-mlink-bitcode-file" "[^"]*ockl.bc".* "-target-cpu" "(gfx908|gfx900|gfx1250|gfx1251)".* "-fopenmp".* "-fsanitize=address".* "-x" "c".*}} // NOGPUSAN: {{"[^"]*clang[^"]*" "-cc1" "-triple" "amdgcn-amd-amdhsa" "-aux-triple" "x86_64-unknown-linux-gnu".* "-emit-llvm-bc".* "-target-cpu" "(gfx908|gfx900)".* "-fopenmp".* "-x" "c".*}} -// SAN: {{"[^"]*llvm-offload-binary[^"]*" "-o".* "--image=file=.*.bc,triple=amdgcn-amd-amdhsa,arch=gfx908(:xnack\-|:xnack\+)?,kind=openmp(,feature=(\-xnack|\+xnack))?"}} +// SAN: {{"[^"]*llvm-offload-binary[^"]*" "-o".* "--image=file=.*.bc,triple=amdgcn-amd-amdhsa,arch=(gfx908|gfx1250|gfx1251)(:xnack\-|:xnack\+)?,kind=openmp(,feature=(\-xnack|\+xnack))?"}} // SAN: {{"[^"]*clang[^"]*" "-cc1" "-triple" "x86_64-unknown-linux-gnu".* "-fopenmp".* "-fsanitize=address".* "--offload-targets=amdgcn-amd-amdhsa".* "-x" "ir".*}} // SAN: {{"[^"]*clang-linker-wrapper[^"]*".* "--host-triple=x86_64-unknown-linux-gnu".* "--linker-path=[^"]*".* "--whole-archive" "[^"]*(libclang_rt.asan_static.a|libclang_rt.asan_static-x86_64.a)".* "--whole-archive" "[^"]*(libclang_rt.asan.a|libclang_rt.asan-x86_64.a)".*}} diff --git a/clang/test/Driver/hip-sanitize-options.hip b/clang/test/Driver/hip-sanitize-options.hip index 0c9c15b..4903851 100644 --- a/clang/test/Driver/hip-sanitize-options.hip +++ b/clang/test/Driver/hip-sanitize-options.hip @@ -3,6 +3,11 @@ // RUN: -nogpuinc --rocm-path=%S/Inputs/rocm \ // RUN: %s 2>&1 | FileCheck -check-prefixes=NORDC %s +// RUN: %clang -### --target=x86_64-unknown-linux-gnu --offload-arch=gfx1250,gfx1251 \ +// RUN: -fsanitize=address \ +// RUN: -nogpuinc --rocm-path=%S/Inputs/rocm \ +// RUN: %s 2>&1 | FileCheck -check-prefixes=NORDC %s + // RUN: %clang -### --target=x86_64-unknown-linux-gnu --offload-arch=gfx900:xnack+ \ // RUN: -fsanitize=address -fno-gpu-sanitize \ // RUN: -nogpuinc --rocm-path=%S/Inputs/rocm \ diff --git a/clang/test/Driver/rocm-device-libs.cl b/clang/test/Driver/rocm-device-libs.cl index f9766e6..649dc85 100644 --- a/clang/test/Driver/rocm-device-libs.cl +++ b/clang/test/Driver/rocm-device-libs.cl @@ -139,6 +139,18 @@ // RUN: 2>&1 | FileCheck --check-prefixes=ASAN,COMMON %s // RUN: %clang -### -target amdgcn-amd-amdhsa \ +// RUN: -x cl -mcpu=gfx1250 -fsanitize=address \ +// RUN: --rocm-path=%S/Inputs/rocm \ +// RUN: %s \ +// RUN: 2>&1 | FileCheck --check-prefixes=ASAN,COMMON %s + +// RUN: %clang -### -target amdgcn-amd-amdhsa \ +// RUN: -x cl -mcpu=gfx1251 -fsanitize=address \ +// RUN: --rocm-path=%S/Inputs/rocm \ +// RUN: %s \ +// RUN: 2>&1 | FileCheck --check-prefixes=ASAN,COMMON %s + +// RUN: %clang -### -target amdgcn-amd-amdhsa \ // RUN: -x cl -mcpu=gfx908:xnack+ \ // RUN: --rocm-path=%S/Inputs/rocm \ // RUN: %s \ diff --git a/clang/test/Parser/lambda-misplaced-capture-default.cpp b/clang/test/Parser/lambda-misplaced-capture-default.cpp index d65b875..4f5bd6d 100644 --- a/clang/test/Parser/lambda-misplaced-capture-default.cpp +++ b/clang/test/Parser/lambda-misplaced-capture-default.cpp @@ -36,3 +36,12 @@ template <typename... Args> void Test(Args... args) { [... xs = &args, &] {}; // expected-error {{capture default must be first}} } } // namespace misplaced_capture_default_pack + +namespace GH163498 { +struct S { + template <class T> S(T) {} +}; +void t() { + S s{[a(42), &] {}}; // expected-error {{capture default must be first}} +} +} diff --git a/clang/test/ParserHLSL/semantic_parsing.hlsl b/clang/test/ParserHLSL/semantic_parsing.hlsl index 726dead..bff7bd0 100644 --- a/clang/test/ParserHLSL/semantic_parsing.hlsl +++ b/clang/test/ParserHLSL/semantic_parsing.hlsl @@ -12,30 +12,33 @@ void Pony(int GI : SV_IWantAPony) { } // expected-note@+1 {{to match this '('}} void SuperPony(int GI : 0) { } -// expected-error@+1 {{unknown HLSL semantic '_'}} +// '_' is a valid CPP identifier. void MegaPony(int GI : _) { } -// expected-error@+1 {{unknown HLSL semantic 'A0A'}} +void GarguantuanPony(int GI : _1) { } + void CoolPony(int GI : A0A0) { } -// expected-error@+1 {{unknown HLSL semantic 'A_'}} void NicePony(int GI : A_0) { } -// expected-error@+1 {{unknown HLSL semantic 'A'}} void CutePony(int GI : A00) { } -// expected-error@+3 {{unknown HLSL semantic 'A'}} // expected-error@+2 {{expected ')'}} // expected-note@+1 {{to match this '('}} void DoublePony(int GI : A00 B) { } -// expected-error@+1 {{unknown HLSL semantic 'é'}} -void BigPony(int GI : é) { } +// Unicode can be used: +// https://timsong-cpp.github.io/cppwp/n3337/charname.allowed +void FrenchPony(int GI : garçon_de_café) { } +void UnicodePony(int GI : ℮) { } + +// Since P1949 seems Emojis are not allowed, even if in the range +// mentioned in N3337. +// https://www.open-std.org/jtc1/sc22/wg21/docs/papers/2021/p1949r7.html // expected-error@+2 {{unexpected character <U+1F60A>}} // expected-error@+1 {{expected HLSL Semantic identifier}} void UTFPony(int GI : 😊) { } -// expected-error@+2 {{character <U+1F60A> not allowed in an identifier}} -// expected-error@+1 {{unknown HLSL semantic 'PonyWithA😊'}} +// expected-error@+1 {{character <U+1F60A> not allowed in an identifier}} void SmilingPony(int GI : PonyWithA😊) { } diff --git a/clang/test/Profile/Inputs/c-counter-overflows.proftext b/clang/test/Profile/Inputs/c-counter-overflows.proftext index 4d0287c..8633060 100644 --- a/clang/test/Profile/Inputs/c-counter-overflows.proftext +++ b/clang/test/Profile/Inputs/c-counter-overflows.proftext @@ -1,5 +1,5 @@ main -7779561829442898616 +862032801801816760 8 1 68719476720 diff --git a/clang/test/Profile/Inputs/c-general.profdata.v12 b/clang/test/Profile/Inputs/c-general.profdata.v12 Binary files differnew file mode 100644 index 0000000..57a72fa --- /dev/null +++ b/clang/test/Profile/Inputs/c-general.profdata.v12 diff --git a/clang/test/Profile/Inputs/c-general.proftext b/clang/test/Profile/Inputs/c-general.proftext index 08280ef..72e1be6 100644 --- a/clang/test/Profile/Inputs/c-general.proftext +++ b/clang/test/Profile/Inputs/c-general.proftext @@ -7,7 +7,7 @@ simple_loops 75 conditionals -4904767535850050386 +293081517422662482 13 1 100 @@ -24,7 +24,7 @@ conditionals 1 early_exits -2880354649761471549 +574511640547777597 9 1 0 @@ -37,7 +37,7 @@ early_exits 0 jumps -15051420506203462683 +63440946314451995 22 1 1 @@ -86,7 +86,7 @@ switches 0 big_switch -13144136522122330070 +461999971447013334 17 1 32 @@ -125,7 +125,7 @@ boolean_operators 33 boolop_loops -12402604614320574815 +873389568252105055 13 1 50 @@ -149,7 +149,7 @@ conditional_operator 1 do_fallthrough -8714614136504380050 +644163604256451218 4 1 10 diff --git a/clang/test/Profile/Inputs/c-unprofiled-blocks.proftext b/clang/test/Profile/Inputs/c-unprofiled-blocks.proftext index d880663..7af5097 100644 --- a/clang/test/Profile/Inputs/c-unprofiled-blocks.proftext +++ b/clang/test/Profile/Inputs/c-unprofiled-blocks.proftext @@ -1,5 +1,5 @@ never_called -6820425066224770721 +1055817543190535841 9 0 0 @@ -17,7 +17,7 @@ main 1 dead_code -5254464978620792806 +642778960193404902 10 1 0 diff --git a/clang/test/Profile/Inputs/cxx-rangefor.proftext b/clang/test/Profile/Inputs/cxx-rangefor.proftext index d41205b..cfc88da 100644 --- a/clang/test/Profile/Inputs/cxx-rangefor.proftext +++ b/clang/test/Profile/Inputs/cxx-rangefor.proftext @@ -1,5 +1,5 @@ _Z9range_forv -8789831523895825398 +719380991647896566 5 1 4 diff --git a/clang/test/Profile/Inputs/cxx-throws.proftext b/clang/test/Profile/Inputs/cxx-throws.proftext index 043dea0..92b0eab 100644 --- a/clang/test/Profile/Inputs/cxx-throws.proftext +++ b/clang/test/Profile/Inputs/cxx-throws.proftext @@ -1,5 +1,5 @@ _Z6throwsv -18172607911962830854 +878785342860126214 9 1 100 diff --git a/clang/test/Profile/Inputs/misexpect-switch-default.proftext b/clang/test/Profile/Inputs/misexpect-switch-default.proftext index 533da91..112426e 100644 --- a/clang/test/Profile/Inputs/misexpect-switch-default.proftext +++ b/clang/test/Profile/Inputs/misexpect-switch-default.proftext @@ -1,6 +1,6 @@ main # Func Hash: -8734802134600123338 +664351602352194506 # Num Counters: 9 # Counter Values: diff --git a/clang/test/Profile/Inputs/misexpect-switch-nonconst.proftext b/clang/test/Profile/Inputs/misexpect-switch-nonconst.proftext index 0da9379..99d067c 100644 --- a/clang/test/Profile/Inputs/misexpect-switch-nonconst.proftext +++ b/clang/test/Profile/Inputs/misexpect-switch-nonconst.proftext @@ -1,6 +1,6 @@ main # Func Hash: -3721743393642630379 +262978879822089451 # Num Counters: 10 # Counter Values: diff --git a/clang/test/Profile/c-collision.c b/clang/test/Profile/c-collision.c index 6c779c6..f35ba1b 100644 --- a/clang/test/Profile/c-collision.c +++ b/clang/test/Profile/c-collision.c @@ -2,8 +2,8 @@ // RUN: %clang_cc1 -UEXTRA -triple x86_64-unknown-linux-gnu -main-file-name c-collision.c %s -o - -emit-llvm -fprofile-instrument=clang | FileCheck %s --check-prefix=CHECK-NOEXTRA // RUN: %clang_cc1 -DEXTRA -triple x86_64-unknown-linux-gnu -main-file-name c-collision.c %s -o - -emit-llvm -fprofile-instrument=clang | FileCheck %s --check-prefix=CHECK-EXTRA -// CHECK-NOEXTRA: @__profd_foo = private global { {{.*}} } { i64 6699318081062747564, i64 7156072912471487002, -// CHECK-EXTRA: @__profd_foo = private global { {{.*}} } { i64 6699318081062747564, i64 -4383447408116050035, +// CHECK-NOEXTRA: @__profd_foo = private global { {{.*}} } { i64 6699318081062747564, i64 238543884830405146, +// CHECK-EXTRA: @__profd_foo = private global { {{.*}} } { i64 6699318081062747564, i64 228238610311337869, extern int bar; void foo(void) { diff --git a/clang/test/Profile/c-general.c b/clang/test/Profile/c-general.c index ee36a43..6c865e6 100644 --- a/clang/test/Profile/c-general.c +++ b/clang/test/Profile/c-general.c @@ -4,6 +4,7 @@ // RUN: llvm-profdata merge %S/Inputs/c-general.proftext -o %t.profdata // RUN: %clang_cc1 -triple x86_64-apple-macosx10.9 -main-file-name c-general.c %s -o - -emit-llvm -fprofile-instrument-use=clang -fprofile-instrument-use-path=%t.profdata | FileCheck -allow-deprecated-dag-overlap -check-prefix=PGOUSE %s +// RUN: %clang_cc1 -triple x86_64-apple-macosx10.9 -main-file-name c-general.c %s -o - -emit-llvm -fprofile-instrument-use=clang -fprofile-instrument-use-path=%S/Inputs/c-general.profdata.v12 | FileCheck -allow-deprecated-dag-overlap -check-prefix=PGOUSE %s // RUN: %clang_cc1 -triple x86_64-apple-macosx10.9 -main-file-name c-general.c %s -o - -emit-llvm -fprofile-instrument-use=clang -fprofile-instrument-use-path=%S/Inputs/c-general.profdata.v5 | FileCheck -allow-deprecated-dag-overlap -check-prefix=PGOUSE %s // RUN: %clang_cc1 -triple x86_64-apple-macosx10.9 -main-file-name c-general.c %s -o - -emit-llvm -fprofile-instrument-use=clang -fprofile-instrument-use-path=%S/Inputs/c-general.profdata.v3 | FileCheck -allow-deprecated-dag-overlap -check-prefix=PGOUSE %s // Also check compatibility with older profiles. diff --git a/clang/test/SemaCXX/attr-mode-tmpl.cpp b/clang/test/SemaCXX/attr-mode-tmpl.cpp index f665b1b..3a1da3b 100644 --- a/clang/test/SemaCXX/attr-mode-tmpl.cpp +++ b/clang/test/SemaCXX/attr-mode-tmpl.cpp @@ -45,7 +45,7 @@ void CheckMachineMode() { // Check attributes on function parameters. template <class T1, class T2> -void CheckParameters(T1 __attribute__((mode(SI))) paramSI, // expected-note{{ignored: substitution failure}} expected-note-re{{not viable: no known conversion from '{{.*}}' (vector of 4 '{{.*}}' values) to 'EnumType' for 2nd argument}} +void CheckParameters(T1 __attribute__((mode(SI))) paramSI, // expected-note{{ignored: substitution failure}} expected-note{{ignored: substitution failure [with T1 = int, T2 = int]: type of machine mode does not match type of base type}} T1 __attribute__((mode(V4DI))) paramV4DI, // expected-warning{{deprecated}} T2 __attribute__((mode(SF))) paramSF, T2 __attribute__((mode(V4DF))) paramV4DF) { // expected-warning{{deprecated}} diff --git a/clang/test/SemaCXX/cxx23-assume.cpp b/clang/test/SemaCXX/cxx23-assume.cpp index ce86266..a594a1a 100644 --- a/clang/test/SemaCXX/cxx23-assume.cpp +++ b/clang/test/SemaCXX/cxx23-assume.cpp @@ -108,7 +108,8 @@ constexpr bool f4() { template <typename T> concept C = f4<T>(); // expected-note 3 {{in instantiation of}} // expected-note@-1 3 {{while substituting}} - // expected-error@-2 2 {{resulted in a non-constant expression}} + // expected-error@-2 {{resulted in a non-constant expression}} + // expected-note@-3 {{because substituted constraint expression is ill-formed: substitution into constraint expression resulted in a non-constant expression}} struct D { int x; @@ -130,13 +131,13 @@ constexpr int f5() requires C<T> { return 1; } // expected-note {{while checking // expected-note@-1 {{candidate template ignored}} template <typename T> -constexpr int f5() requires (!C<T>) { return 2; } // expected-note 4 {{while checking the satisfaction}} \ - // expected-note 4 {{while substituting template arguments}} \ +constexpr int f5() requires (!C<T>) { return 2; } // expected-note 3 {{while checking the satisfaction}} \ + // expected-note 3 {{while substituting template arguments}} \ // expected-note {{candidate template ignored}} static_assert(f5<int>() == 1); -static_assert(f5<D>() == 1); // expected-note 3 {{while checking constraint satisfaction}} - // expected-note@-1 3 {{while substituting deduced template arguments}} +static_assert(f5<D>() == 1); // expected-note 2 {{while checking constraint satisfaction}} + // expected-note@-1 2 {{while substituting deduced template arguments}} // expected-error@-2 {{no matching function for call}} static_assert(f5<double>() == 2); @@ -170,7 +171,7 @@ foo (int x, int y) // Do not crash when assumptions are unreachable. namespace gh106898 { -int foo () { +int foo () { while(1); int a = 0, b = 1; __attribute__((assume (a < b))); diff --git a/clang/test/SemaCXX/cxx2b-warn-shadow.cpp b/clang/test/SemaCXX/cxx2b-warn-shadow.cpp index 76866c4..9ce0c5a 100644 --- a/clang/test/SemaCXX/cxx2b-warn-shadow.cpp +++ b/clang/test/SemaCXX/cxx2b-warn-shadow.cpp @@ -11,3 +11,29 @@ struct Foo { } }; } // namespace GH95707 + +namespace GH163731 { +struct S1 { + int a; + void m(this S1 &self) { + auto lambda = [](int a) { return a; }; + } +}; + +struct S2 { + int a; + void m(this S2 &self) { + int a = 1; // expected-note {{previous declaration is here}} + auto lambda = [](int a) { // expected-warning {{declaration shadows a local variable}} + return a; + }; + } +}; + +struct S3 { + int a; + void m(this S3 &self) { + auto lambda = [self](int a) { return a + self.a; }; + } +}; +} diff --git a/clang/test/SemaCXX/dependent-switch-case.cpp b/clang/test/SemaCXX/dependent-switch-case.cpp new file mode 100644 index 0000000..bbeab3a --- /dev/null +++ b/clang/test/SemaCXX/dependent-switch-case.cpp @@ -0,0 +1,6 @@ +// RUN: %clang_cc1 -std=c++20 %s -verify +// RUN: %clang_cc1 -std=c++20 %s -verify -fexperimental-new-constant-interpreter + +constexpr bool e(int){switch(0)0=0:return t(;} // expected-error {{expression is not assignable}} \ + // expected-error {{expected 'case' keyword before expression}} \ + // expected-error {{expected expression}} diff --git a/clang/test/SemaHLSL/BuiltIns/firstbithigh-errors.hlsl b/clang/test/SemaHLSL/BuiltIns/firstbithigh-errors.hlsl index f99e606..1f70186 100644 --- a/clang/test/SemaHLSL/BuiltIns/firstbithigh-errors.hlsl +++ b/clang/test/SemaHLSL/BuiltIns/firstbithigh-errors.hlsl @@ -12,7 +12,7 @@ int test_too_many_arg(int p0) { double test_int_builtin(double p0) { return firstbithigh(p0); - // expected-error@-1 {{call to 'firstbithigh' is ambiguous}} + // expected-error@-1 {{no matching function for call to 'firstbithigh'}} } double2 test_int_builtin_2(double2 p0) { diff --git a/clang/test/SemaHLSL/Semantics/semantics-invalid.hlsl b/clang/test/SemaHLSL/Semantics/semantics-invalid.hlsl new file mode 100644 index 0000000..fdba6f6 --- /dev/null +++ b/clang/test/SemaHLSL/Semantics/semantics-invalid.hlsl @@ -0,0 +1,17 @@ +// RUN: %clang_cc1 -triple dxil-pc-shadermodel6.0-compute -x hlsl -fsyntax-only -hlsl-entry main -verify %s + +typedef float t_f : SEMANTIC; // expected-warning{{'SEMANTIC' attribute only applies to parameters, non-static data members, and functions}} + +struct semantic_on_struct : SEMANTIC { // expected-error{{expected class name}} + float a; +}; + +struct s_fields_multiple_semantics { + float a : semantic_a : semantic_c; // expected-error{{use of undeclared identifier 'semantic_c'}} + float b : semantic_b; +}; + +[numthreads(1, 1, 1)] +void main() { + float a : SEM_A; // expected-warning{{'SEM_A' attribute only applies to parameters, non-static data members, and functions}} +} diff --git a/clang/test/SemaHLSL/Semantics/semantics-valid.hlsl b/clang/test/SemaHLSL/Semantics/semantics-valid.hlsl new file mode 100644 index 0000000..1e6bae4 --- /dev/null +++ b/clang/test/SemaHLSL/Semantics/semantics-valid.hlsl @@ -0,0 +1,33 @@ +// RUN: %clang_cc1 -triple dxil-pc-shadermodel6.0-compute -hlsl-entry CSMain -x hlsl -finclude-default-header -ast-dump -o - %s | FileCheck %s + +struct s_fields { + float a : semantic_a; + float b : semantic_b; +// CHECK: |-CXXRecordDecl 0x{{[0-9a-fA-F]+}} <{{.*}}> line:[[@LINE-3]]:8 struct s_fields definition +// CHECK: | |-FieldDecl 0x{{[0-9a-fA-F]+}} <{{.*}}> col:9 a 'float' +// CHECK: | | `-HLSLUserSemanticAttr 0x{{[0-9a-fA-F]+}} <col:13> +// CHECK: | `-FieldDecl 0x{{[0-9a-fA-F]+}} <{{.*}}> col:9 b 'float' +// CHECK: | `-HLSLUserSemanticAttr 0x{{[0-9a-fA-F]+}} <col:13> +}; + +float fn_foo1(float a : a, float b : b) : sem_ret { return 1.0f; } +// CHECK: |-FunctionDecl {{.*}} <{{.*}}> col:7 fn_foo1 'float (float, float)' +// CHECK-NEXT: | |-ParmVarDecl {{.*}} <{{.*}}> col:21 a 'float' +// CHECK-NEXT: | | `-HLSLUserSemanticAttr {{.*}} <{{.*}}> +// CHECK-NEXT: | |-ParmVarDecl {{.*}} <{{.*}}> col:34 b 'float' +// CHECK-NEXT: | | `-HLSLUserSemanticAttr {{.*}} <{{.*}}> +// CHECK-NEXT: | |-CompoundStmt {{.*}} <{{.*}}> +// CHECK-NEXT: | | `-ReturnStmt {{.*}} <{{.*}}> +// CHECK-NEXT: | | `-FloatingLiteral {{.*}} <{{.*}}> 'float' 1.000000e+00 +// CHECK-NEXT: | `-HLSLUserSemanticAttr {{.*}} <{{.*}}> +float fn_foo2(float a : a, float b : b) : sem_ret : also_ret { return 1.0f; } +// CHECK: `-FunctionDecl {{.*}} <{{.*}}> col:7 fn_foo2 'float (float, float)' +// CHECK-NEXT: |-ParmVarDecl {{.*}} <{{.*}}> col:21 a 'float' +// CHECK-NEXT: | `-HLSLUserSemanticAttr {{.*}} <{{.*}}> +// CHECK-NEXT: |-ParmVarDecl {{.*}} <{{.*}}> col:34 b 'float' +// CHECK-NEXT: | `-HLSLUserSemanticAttr {{.*}} <{{.*}}> +// CHECK-NEXT: |-CompoundStmt {{.*}} <{{.*}}> +// CHECK-NEXT: | `-ReturnStmt {{.*}} <{{.*}}> +// CHECK-NEXT: | `-FloatingLiteral {{.*}} <{{.*}}> 'float' 1.000000e+00 +// CHECK-NEXT: |-HLSLUserSemanticAttr {{.*}} <{{.*}}> +// CHECK-NEXT: `-HLSLUserSemanticAttr {{.*}} <{{.*}}> diff --git a/clang/test/SemaHLSL/Types/AggregateSplatConstantExpr.hlsl b/clang/test/SemaHLSL/Types/AggregateSplatConstantExpr.hlsl new file mode 100644 index 0000000..630acd8 --- /dev/null +++ b/clang/test/SemaHLSL/Types/AggregateSplatConstantExpr.hlsl @@ -0,0 +1,89 @@ +// RUN: %clang_cc1 -triple dxil-pc-shadermodel6.6-library -finclude-default-header -fnative-half-type -fnative-int16-type -std=hlsl202x -verify %s + +// expected-no-diagnostics + +struct Base { + double D; + uint64_t2 U; + int16_t I : 5; + uint16_t I2: 5; +}; + +struct R : Base { + int G : 10; + int : 30; + float F; +}; + +struct B1 { + float A; + float B; +}; + +struct B2 : B1 { + int C; + int D; + bool BB; +}; + +// tests for HLSLAggregateSplatCast +export void fn() { + // result type vector + // splat from a vector of size 1 + + constexpr float1 Y = {1.0}; + constexpr float4 F4 = (float4)Y; + _Static_assert(F4[0] == 1.0, "Woo!"); + _Static_assert(F4[1] == 1.0, "Woo!"); + _Static_assert(F4[2] == 1.0, "Woo!"); + _Static_assert(F4[3] == 1.0, "Woo!"); + + // result type array + // splat from a scalar + constexpr float F = 3.33; + constexpr int B6[6] = (int[6])F; + _Static_assert(B6[0] == 3, "Woo!"); + _Static_assert(B6[1] == 3, "Woo!"); + _Static_assert(B6[2] == 3, "Woo!"); + _Static_assert(B6[3] == 3, "Woo!"); + _Static_assert(B6[4] == 3, "Woo!"); + _Static_assert(B6[5] == 3, "Woo!"); + + // splat from a vector of size 1 + constexpr int1 A1 = {1}; + constexpr uint64_t2 A7[2] = (uint64_t2[2])A1; + _Static_assert(A7[0][0] == 1, "Woo!"); + _Static_assert(A7[0][1] == 1, "Woo!"); + _Static_assert(A7[1][0] == 1, "Woo!"); + _Static_assert(A7[1][1] == 1, "Woo!"); + + // result type struct + // splat from a scalar + constexpr double D = 97.6789; + constexpr R SR = (R)(D + 3.0); + _Static_assert(SR.D == 100.6789, "Woo!"); + _Static_assert(SR.U[0] == 100, "Woo!"); + _Static_assert(SR.U[1] == 100, "Woo!"); + _Static_assert(SR.I == 4, "Woo!"); + _Static_assert(SR.I2 == 4, "Woo!"); + _Static_assert(SR.G == 100, "Woo!"); + _Static_assert(SR.F == 100.6789, "Woo!"); + + // splat from a vector of size 1 + constexpr float1 A100 = {1000.1111}; + constexpr B2 SB2 = (B2)A100; + _Static_assert(SB2.A == 1000.1111, "Woo!"); + _Static_assert(SB2.B == 1000.1111, "Woo!"); + _Static_assert(SB2.C == 1000, "Woo!"); + _Static_assert(SB2.D == 1000, "Woo!"); + _Static_assert(SB2.BB == true, "Woo!"); + + // splat from a bool to an int and float etc + constexpr bool B = true; + constexpr B2 SB3 = (B2)B; + _Static_assert(SB3.A == 1.0, "Woo!"); + _Static_assert(SB3.B == 1.0, "Woo!"); + _Static_assert(SB3.C == 1, "Woo!"); + _Static_assert(SB3.D == 1, "Woo!"); + _Static_assert(SB3.BB == true, "Woo!"); +} diff --git a/clang/test/SemaHLSL/Types/ElementwiseCastConstantExpr.hlsl b/clang/test/SemaHLSL/Types/ElementwiseCastConstantExpr.hlsl new file mode 100644 index 0000000..c9963c3 --- /dev/null +++ b/clang/test/SemaHLSL/Types/ElementwiseCastConstantExpr.hlsl @@ -0,0 +1,90 @@ +// RUN: %clang_cc1 -triple dxil-pc-shadermodel6.6-library -finclude-default-header -fnative-half-type -fnative-int16-type -std=hlsl202x -verify %s + +// expected-no-diagnostics + +struct Base { + double D; + uint64_t2 U; + int16_t I : 5; + uint16_t I2: 5; +}; + +struct R : Base { + int G : 10; + int : 30; + float F; +}; + +struct B1 { + float A; + float B; +}; + +struct B2 : B1 { + int C; + int D; + bool BB; +}; + +export void fn() { + _Static_assert(((float4)(int[6]){1,2,3,4,5,6}).x == 1.0, "Woo!"); + + // This compiling successfully verifies that the array constant expression + // gets truncated to a float at compile time for instantiation via the + // flat cast + _Static_assert(((int)(int[2]){1,2}) == 1, "Woo!"); + + // truncation tests + // result type int + // truncate from struct + constexpr B1 SB1 = {1.0, 3.0}; + constexpr int X = (int)SB1; + _Static_assert(X == 1, "Woo!"); + + // result type float + // truncate from array + constexpr B1 Arr[2] = {4.0, 3.0, 2.0, 1.0}; + constexpr float F = (float)Arr; + _Static_assert(F == 4.0, "Woo!"); + + // result type vector + // truncate from array of vector + constexpr int2 Arr2[2] = {5,6,7,8}; + constexpr int2 I2 = (int2)Arr2; + _Static_assert(I2[0] == 5, "Woo!"); + _Static_assert(I2[1] == 6, "Woo!"); + + // lhs and rhs are same "size" tests + + // result type vector from array + constexpr int4 I4 = (int4)Arr; + _Static_assert(I4[0] == 4, "Woo!"); + _Static_assert(I4[1] == 3, "Woo!"); + _Static_assert(I4[2] == 2, "Woo!"); + _Static_assert(I4[3] == 1, "Woo!"); + + // result type array from vector + constexpr double3 D3 = {100.11, 200.11, 300.11}; + constexpr float FArr[3] = (float[3])D3; + _Static_assert(FArr[0] == 100.11, "Woo!"); + _Static_assert(FArr[1] == 200.11, "Woo!"); + _Static_assert(FArr[2] == 300.11, "Woo!"); + + // result type struct from struct + constexpr B2 SB2 = {5.5, 6.5, 1000, 5000, false}; + constexpr Base SB = (Base)SB2; + _Static_assert(SB.D == 5.5, "Woo!"); + _Static_assert(SB.U[0] == 6, "Woo!"); + _Static_assert(SB.U[1] == 1000, "Woo!"); + _Static_assert(SB.I == 8, "Woo!"); + _Static_assert(SB.I2 == 0, "Woo!"); + + // Make sure we read bitfields correctly + constexpr Base BB = {222.22, {100, 200}, -2, 7}; + constexpr int Arr3[5] = (int[5])BB; + _Static_assert(Arr3[0] == 222, "Woo!"); + _Static_assert(Arr3[1] == 100, "Woo!"); + _Static_assert(Arr3[2] == 200, "Woo!"); + _Static_assert(Arr3[3] == -2, "Woo!"); + _Static_assert(Arr3[4] == 7, "Woo!"); +} diff --git a/clang/test/SemaTemplate/temp_arg_nontype.cpp b/clang/test/SemaTemplate/temp_arg_nontype.cpp index 7d2a010..bd0bf3c 100644 --- a/clang/test/SemaTemplate/temp_arg_nontype.cpp +++ b/clang/test/SemaTemplate/temp_arg_nontype.cpp @@ -173,8 +173,7 @@ namespace pr6249 { } namespace PR6723 { - template<unsigned char C> void f(int (&a)[C]); // expected-note 3{{candidate template ignored: substitution failure [with C = '\x00']}} - // expected-note@-1 {{not viable: no known conversion from 'int[512]' to 'int (&)[0]'}} + template<unsigned char C> void f(int (&a)[C]); // expected-note 4{{candidate template ignored: substitution failure [with C = '\x00']}} void g() { int arr512[512]; f(arr512); // expected-error{{no matching function for call}} diff --git a/clang/test/SemaTemplate/temp_arg_nontype_cxx11.cpp b/clang/test/SemaTemplate/temp_arg_nontype_cxx11.cpp index 5752cba..45bdb4c 100644 --- a/clang/test/SemaTemplate/temp_arg_nontype_cxx11.cpp +++ b/clang/test/SemaTemplate/temp_arg_nontype_cxx11.cpp @@ -43,7 +43,7 @@ void TempFunc() {} void Useage() { //expected-error@+2 {{no matching function}} - //expected-note@-4 {{candidate template ignored: invalid explicitly-specified argument for template parameter 'b'}} + //expected-note@-4 {{candidate template ignored: substitution failure [with a = 1, b = 4294967295, c = 1]: non-type template argument evaluates to -1, which cannot be narrowed to type 'unsigned int'}} TempFunc<1, -1, 1>(); } } |
