CodeQL / Analyze (actions) (push) Canceled after 0s
CodeQL / Analyze (python) (push) Canceled after 0s
pre-commit / pre-commit (push) Canceled after 0s
Multi-Arch CI / setup (push) Canceled after 0s
Publish build_manylinux_x86_64 images / publish_build_manylinux_x86_64 (push) Canceled after 0s
Setup (Multi-Arch) / setup (push) Canceled after 0s
Multi-Arch CI / Linux::${{ fromJSON(needs.setup.outputs.linux_build_config || '{}').build_variant_label || 'skip' }} (push) Canceled after 0s
Publish TheRock Docker image / build-and-push-image (push) Canceled after 0s
Publish no_rocm_image_ubi10 image / publish_no_rocm_image_ubi10 (push) Canceled after 0s
Multi-Arch CI / Windows::${{ fromJSON(needs.setup.outputs.windows_build_config || '{}').build_variant_label || 'skip' }} (push) Canceled after 0s
Publish TheRock Docker image / build-and-push-image (push) Canceled after 0s
Multi-Arch CI / Manifest Diff (push) Canceled after 0s
TheRock Manifest Diff Report / Generate Manifest Diff Report (push) Canceled after 0s
Multi-Arch CI / CI Summary (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04 images / publish_no_rocm_image_ubuntu24_04 (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04_ocl_rt images / publish_no_rocm_image_ubuntu24_04_ocl_rt (push) Canceled after 0s
Publish TheRock Docker image / build-and-push-image (push) Canceled after 0s
Publish TheRock Docker image / build-and-push-image (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04 images / publish_no_rocm_image_ubuntu24_04_rocgdb (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04_rocgdb images / publish_no_rocm_image_ubuntu24_04_rocgdb (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04 images / publish_no_rocm_image_ubuntu24_04_ocl_rt (push) Canceled after 0s
Publish TheRock Docker image / build-and-push-image (push) Canceled after 0s
Unit Tests / Unit Tests :: ubuntu-24.04 (push) Canceled after 0s
Unit Tests / Unit Tests :: windows-2022 (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04 images / publish_no_rocm_image_ubuntu24_04_media (push) Canceled after 0s
Unit Tests / Unit Tests Summary (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04 images / publish_no_rocm_image_ubuntu24_04_openmpi (push) Canceled after 0s
253 lines
12 KiB
C
253 lines
12 KiB
C
// RUN: %clang_cc1 %s -Winteger-overflow -Wno-unused-value -fexperimental-overflow-behavior-types -Woverflow-behavior-conversion -Wconstant-conversion -verify -fsyntax-only -std=c11 -Wno-pointer-sign
|
|
// RUN: %clang_cc1 %s -Winteger-overflow -Wno-unused-value -fexperimental-overflow-behavior-types -Woverflow-behavior-conversion -Wconstant-conversion -verify -fsyntax-only -std=c11 -Wno-pointer-sign -fexperimental-new-constant-interpreter
|
|
|
|
typedef int __attribute__((overflow_behavior)) bad_arg_count; // expected-error {{'overflow_behavior' attribute takes one argument}}
|
|
typedef int __attribute__((overflow_behavior(not_real))) bad_arg_spec; // expected-error {{'not_real' is not a valid argument to attribute 'overflow_behavior'}}
|
|
typedef int __attribute__((overflow_behavior("not_real"))) bad_arg_spec_str; // expected-error {{'not_real' is not a valid argument to attribute 'overflow_behavior'}}
|
|
typedef char* __attribute__((overflow_behavior("wrap"))) bad_type; // expected-error {{'overflow_behavior' attribute cannot be applied to non-integer type 'char *'}}
|
|
|
|
typedef int __attribute__((overflow_behavior(wrap))) ok_wrap; // OK
|
|
typedef long __attribute__((overflow_behavior(trap))) ok_nowrap; // OK
|
|
typedef unsigned long __attribute__((overflow_behavior("wrap"))) str_ok_wrap; // OK
|
|
typedef char __attribute__((overflow_behavior("trap"))) str_ok_nowrap; // OK
|
|
|
|
void foo() {
|
|
(2147483647 + 100); // expected-warning {{overflow in expression; result is }}
|
|
(ok_wrap)2147483647 + 100; // no warn
|
|
}
|
|
|
|
void ptr(int a) {
|
|
int __ob_trap *p = &a; // expected-warning {{initializing '__ob_trap int *' with an expression of type 'int *' discards overflow behavior}}
|
|
}
|
|
|
|
void ptr2(__ob_trap int a) {
|
|
int *p = &a; // expected-warning {{initializing 'int *' with an expression of type '__ob_trap int *' discards overflow behavior}}
|
|
}
|
|
|
|
|
|
// verify semantics of OBT at function boundaries
|
|
void imp_disc_pedantic(unsigned a) {}
|
|
void imp_disc(int a) {}
|
|
void imp_disc_test(unsigned __attribute__((overflow_behavior(wrap))) a) {
|
|
imp_disc_pedantic(a); // expected-warning {{passing argument of type '__ob_wrap unsigned int' to parameter of type 'unsigned int' discards overflow behavior at function boundary}}
|
|
// expected-warning@-1 {{implicit conversion from '__ob_wrap unsigned int' to 'unsigned int' discards overflow behavior}}
|
|
imp_disc(a); // expected-warning {{passing argument of type '__ob_wrap unsigned int' to parameter of type 'int' discards overflow behavior at function boundary}}
|
|
// expected-warning@-1 {{implicit conversion from '__ob_wrap unsigned int' to 'int' discards overflow behavior}}
|
|
}
|
|
|
|
void assignment_disc(unsigned __attribute__((overflow_behavior(wrap))) a) {
|
|
int b = a; // expected-warning {{implicit conversion from '__ob_wrap unsigned int' to 'int' during assignment discards overflow behavior}}
|
|
int c = (int)a; // OK
|
|
}
|
|
|
|
void constant_conversion() {
|
|
short x1 = (int __ob_wrap)100000;
|
|
short __ob_wrap x2 = (int)100000; // No warning expected
|
|
// expected-warning@+1 {{implicit conversion from 'int' to '__ob_trap short' changes value from 100000 to -31072}}
|
|
short __ob_trap x3 = (int)100000;
|
|
// OBT now propagates through implicit casts, so x4 gets __ob_trap from the explicit cast
|
|
// expected-warning@+1 {{implicit conversion from '__ob_trap int' to '__ob_trap short' changes value from 100000 to -31072}}
|
|
short x4 = (int __ob_trap)100000;
|
|
|
|
unsigned short __ob_wrap ux1 = (unsigned int)100000; // No warning - wrapping expected
|
|
unsigned short ux2 = (unsigned int __ob_wrap)100000;
|
|
unsigned short __ob_trap ux3 = (unsigned int)100000; // expected-warning {{implicit conversion from 'unsigned int' to '__ob_trap unsigned short' changes value from 100000 to 34464}}
|
|
unsigned short __ob_trap ux4 = (unsigned int __ob_trap)100000; // expected-warning {{implicit conversion from '__ob_trap unsigned int' to '__ob_trap unsigned short' changes value from 100000 to 34464}}
|
|
unsigned short __ob_trap ux5 = (unsigned int __ob_wrap)100000; // expected-error {{assigning to '__ob_trap unsigned short' from '__ob_wrap unsigned int' with incompatible overflow behavior types ('__ob_trap' and '__ob_wrap')}}
|
|
}
|
|
|
|
typedef long s64_typedef1;
|
|
typedef s64_typedef1 __attribute__((overflow_behavior(trap))) nw_s64_typedef2;
|
|
nw_s64_typedef2 global_var;
|
|
void test_nested_typedef_control_flow() {
|
|
// We had a crash during Sema with nested typedefs and control flow, make
|
|
// sure we don't crash and just warn.
|
|
if (global_var) {} // expected-warning {{implicit conversion from 'nw_s64_typedef2'}}
|
|
}
|
|
|
|
int test_discard_on_return(unsigned long __ob_trap a) {
|
|
return a; // expected-warning {{implicit conversion from '__ob_trap unsigned long' to 'int' discards overflow behavior}}
|
|
}
|
|
|
|
// Test OBT pointer compatibility
|
|
void test_obt_pointer_compatibility() {
|
|
unsigned long x = 42;
|
|
unsigned long __ob_trap y = 42;
|
|
unsigned long __ob_wrap z = 42;
|
|
|
|
unsigned long *px = &x;
|
|
unsigned long __ob_trap *py = &y;
|
|
unsigned long __ob_wrap *pz = &z;
|
|
|
|
// Same types - should not warn
|
|
px = &x; // OK
|
|
py = &y; // OK
|
|
pz = &z; // OK
|
|
|
|
// Different OBT annotations - should warn but allow
|
|
// expected-warning@+1 {{assigning to 'unsigned long *' from '__ob_trap unsigned long *' discards overflow behavior}}
|
|
px = py;
|
|
// expected-warning@+1 {{assigning to 'unsigned long *' from '__ob_wrap unsigned long *' discards overflow behavior}}
|
|
px = pz;
|
|
// expected-warning@+1 {{assigning to '__ob_trap unsigned long *' from 'unsigned long *' discards overflow behavior}}
|
|
py = px;
|
|
// expected-warning@+1 {{assigning to '__ob_wrap unsigned long *' from 'unsigned long *' discards overflow behavior}}
|
|
pz = px;
|
|
// expected-error@+1 {{assigning to '__ob_trap unsigned long *' from '__ob_wrap unsigned long *' with incompatible overflow behavior types ('__ob_trap' and '__ob_wrap')}}
|
|
py = pz;
|
|
// expected-error@+1 {{assigning to '__ob_wrap unsigned long *' from '__ob_trap unsigned long *' with incompatible overflow behavior types ('__ob_wrap' and '__ob_trap')}}
|
|
pz = py;
|
|
}
|
|
|
|
// Test function parameter passing
|
|
// expected-note@+2 {{passing argument to parameter 'p' here}}
|
|
// expected-note@+1 {{passing argument to parameter 'p' here}}
|
|
void func_takes_regular_ptr(unsigned long *p) {}
|
|
// expected-note@+1 {{passing argument to parameter 'p' here}}
|
|
void func_takes_trap_ptr(unsigned long __ob_trap *p) {}
|
|
// expected-note@+1 {{passing argument to parameter 'p' here}}
|
|
void func_takes_wrap_ptr(unsigned long __ob_wrap *p) {}
|
|
|
|
void test_function_parameters() {
|
|
unsigned long x = 42;
|
|
unsigned long __ob_trap y = 42;
|
|
unsigned long __ob_wrap z = 42;
|
|
|
|
unsigned long *px = &x;
|
|
unsigned long __ob_trap *py = &y;
|
|
unsigned long __ob_wrap *pz = &z;
|
|
|
|
// Same types - should not warn
|
|
func_takes_regular_ptr(px); // OK
|
|
func_takes_trap_ptr(py); // OK
|
|
func_takes_wrap_ptr(pz); // OK
|
|
|
|
// Different OBT annotations - should warn but allow
|
|
// expected-warning@+1 {{passing '__ob_trap unsigned long *' to parameter of type 'unsigned long *' discards overflow behavior}}
|
|
func_takes_regular_ptr(py);
|
|
// expected-warning@+1 {{passing '__ob_wrap unsigned long *' to parameter of type 'unsigned long *' discards overflow behavior}}
|
|
func_takes_regular_ptr(pz);
|
|
// expected-warning@+1 {{passing 'unsigned long *' to parameter of type '__ob_trap unsigned long *' discards overflow behavior}}
|
|
func_takes_trap_ptr(px);
|
|
// expected-warning@+1 {{passing 'unsigned long *' to parameter of type '__ob_wrap unsigned long *' discards overflow behavior}}
|
|
func_takes_wrap_ptr(px);
|
|
}
|
|
|
|
void test_different_underlying_types_for_pointers() {
|
|
int x = 42;
|
|
unsigned long __ob_trap y = 42;
|
|
|
|
int *px = &x;
|
|
unsigned long __ob_trap *py = &y;
|
|
|
|
px = py; // expected-error {{incompatible pointer types assigning to 'int *' from '__ob_trap unsigned long *'}}
|
|
}
|
|
|
|
typedef unsigned long __ob_trap nw_ul;
|
|
typedef signed long sl;
|
|
|
|
void qux(nw_ul *ptr) {}
|
|
|
|
void test_signed_unsigned_pointer_compatibility() {
|
|
sl a;
|
|
qux(&a);
|
|
}
|
|
|
|
// expected-error@+1 {{conflicting 'overflow_behavior' attributes on the same type}}
|
|
typedef int __attribute__((overflow_behavior(wrap))) __attribute__((overflow_behavior(trap))) conflicting_trap_wins;
|
|
// expected-error@+1 {{conflicting 'overflow_behavior' attributes on the same type}}
|
|
typedef int __attribute__((overflow_behavior(trap))) __attribute__((overflow_behavior(wrap))) conflicting_wrap_ignored;
|
|
|
|
void test_conflicting_behavior_kinds() {
|
|
conflicting_trap_wins x = 42;
|
|
conflicting_wrap_ignored y = 42;
|
|
|
|
int __ob_trap *px = &x;
|
|
int __ob_trap *py = &y;
|
|
}
|
|
|
|
typedef int __attribute__((overflow_behavior(wrap))) __attribute__((overflow_behavior(wrap))) duplicate_wrap; // no warn
|
|
typedef int __attribute__((overflow_behavior(trap))) __attribute__((overflow_behavior(trap))) duplicate_trap; // no warn
|
|
|
|
// Test type merging behavior for OBTs on top of typedefs
|
|
typedef int pid_t;
|
|
typedef int clockid_t;
|
|
|
|
void test_obt_type_merging() {
|
|
pid_t __ob_wrap a = 1;
|
|
clockid_t __ob_wrap b = 2;
|
|
pid_t __ob_wrap c = 4;
|
|
_Static_assert(_Generic((a + b), int __ob_wrap: 1, default: 0), "a + b should be __ob_wrap int");
|
|
_Static_assert(_Generic((a + c), pid_t __ob_wrap: 1, default: 0), "a + c should be __ob_wrap pid_t");
|
|
}
|
|
|
|
typedef unsigned long __ob_trap test_size_t;
|
|
typedef int __ob_wrap test_wrap_int;
|
|
|
|
void test_pointer_arithmetic_crash_fix() {
|
|
int a = 42;
|
|
test_size_t offset = 10;
|
|
test_wrap_int w_offset = 5;
|
|
|
|
int *ptr1 = &a + offset;
|
|
int *ptr2 = &a + w_offset;
|
|
int *ptr3 = offset + &a;
|
|
|
|
test_size_t bad1 = &a + offset; // expected-error {{incompatible pointer to integer conversion}}
|
|
test_wrap_int bad2 = &a + w_offset; // expected-error {{incompatible pointer to integer conversion}}
|
|
test_size_t b = &a + b; // expected-error {{incompatible pointer to integer conversion}}
|
|
int arr[10];
|
|
test_size_t diff = &arr[5] - &arr[0]; // OK: pointer difference assigned to OBT
|
|
}
|
|
|
|
void test_mixed_specifier_attribute() {
|
|
int __ob_wrap __attribute__((overflow_behavior(wrap))) a; // expected-warning {{redundant overflow behavior specification; both specifier and attribute specify 'wrap'}}
|
|
int __ob_trap __attribute__((overflow_behavior(trap))) b; // expected-warning {{redundant overflow behavior specification; both specifier and attribute specify 'trap'}}
|
|
|
|
int __ob_wrap __attribute__((overflow_behavior(trap))) c; // expected-error {{conflicting overflow behavior specification; specifier specifies 'wrap' but attribute specifies 'trap'}}
|
|
int __ob_trap __attribute__((overflow_behavior(wrap))) d; // expected-error {{conflicting overflow behavior specification; specifier specifies 'trap' but attribute specifies 'wrap'}}
|
|
|
|
int __ob_wrap e; // OK
|
|
int __attribute__((overflow_behavior(trap))) f; // OK
|
|
}
|
|
|
|
void test_incompatible_obt_assignment() {
|
|
int __ob_trap trap_var;
|
|
int __ob_wrap wrap_var;
|
|
|
|
trap_var = wrap_var; // expected-error {{assigning to '__ob_trap int' from '__ob_wrap int' with incompatible overflow behavior types ('__ob_trap' and '__ob_wrap')}}
|
|
wrap_var = trap_var; // expected-error {{assigning to '__ob_wrap int' from '__ob_trap int' with incompatible overflow behavior types ('__ob_wrap' and '__ob_trap')}}
|
|
}
|
|
|
|
void test_signedness_differences(long long __ob_trap a,
|
|
unsigned long __ob_trap b) {
|
|
(void)(a + b); // OK
|
|
}
|
|
|
|
typedef unsigned long __ob_trap size_t_trap;
|
|
void takes_three_ints(int, int, int);
|
|
void test_explicit_cast_to_function_arg(void) {
|
|
// expected-warning@+1 {{passing argument of type 'size_t_trap' (aka '__ob_trap unsigned long') to parameter of type 'int' discards overflow behavior at function boundary}}
|
|
takes_three_ints(0, 0, (size_t_trap)0);
|
|
}
|
|
|
|
_Bool test_obt_to_bool_conversion(size_t_trap a) {
|
|
return a; // expected-warning {{implicit conversion from 'size_t_trap' (aka '__ob_trap unsigned long') to '_Bool' discards overflow behavior}}
|
|
}
|
|
|
|
void takes_obt_param(size_t_trap);
|
|
void test_int_literal_to_obt_param(void) {
|
|
takes_obt_param(0);
|
|
takes_obt_param(42);
|
|
}
|
|
|
|
// OBT specifiers cannot qualify pointers
|
|
void (* __ob_wrap bad_fp)(int); // expected-error {{__ob_wrap specifier cannot be applied to non-integer type 'void (*)(int)'}}
|
|
int (* __ob_wrap bad_arr_ptr)[10]; // expected-error {{__ob_wrap specifier cannot be applied to non-integer type 'int (*)[10]'}}
|
|
int * __ob_wrap bad_ptr; // expected-error {{__ob_wrap specifier cannot be applied to non-integer type 'int *'}}
|
|
int * __ob_trap bad_ptr2; // expected-error {{__ob_trap specifier cannot be applied to non-integer type 'int *'}}
|
|
|
|
// OBT specifiers on the base integer type (before *) are fine
|
|
int __ob_wrap *good_ptr;
|
|
int __ob_trap *good_ptr2;
|