// RUN: %clang_cc1 %s -Winteger-overflow -Wno-unused-value -fexperimental-overflow-behavior-types -Wconstant-conversion -Woverflow-behavior-conversion -verify -fsyntax-only // RUN: %clang_cc1 %s -Winteger-overflow -Wno-unused-value -fexperimental-overflow-behavior-types -Wconstant-conversion -Woverflow-behavior-conversion -verify -fsyntax-only -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 struct struct_not_allowed { int i; } __attribute__((overflow_behavior(wrap))); // expected-warning {{'overflow_behavior' attribute only applies to variables, typedefs, and data members}} void foo() { (2147483647 + 100); // expected-warning {{overflow in expression; result is }} (ok_wrap)2147483647 + 100; // no warn } // C++ stuff expects no warns typedef int __attribute__((overflow_behavior(wrap))) wrap_int; template T bar(T a) { return 1UL; } void f() { wrap_int a = 4; bar(a); } class TestOverload { public: void operator<<(int other); // expected-note {{candidate function}} void operator<<(char other); // expected-note {{candidate function}} }; void test_overload1() { wrap_int a = 4; TestOverload TO; TO << a; // expected-error {{use of overloaded operator '<<' is ambiguous}} } // expected-note@+1 {{candidate function}} int add_one(long a) { // expected-note {{candidate function}} return (a + 1); } // expected-note@+1 {{candidate function}} int add_one(char a) { // expected-note {{candidate function}} return (a + 1); } // expected-note@+1 {{candidate function}} int add_one(int a) { // expected-note {{candidate function}} return (a + 1); } void test_overload2(wrap_int a) { // to be clear, this is the same ambiguity expected when using a non-OBT int type. add_one(a); // expected-error {{call to 'add_one' is ambiguous}} long __attribute__((overflow_behavior(trap))) b; // don't consider underlying type an exact match. add_one(b); // expected-error {{call to 'add_one' is ambiguous}} } void func(__ob_trap int i); void func(int i); // Overload, not invalid redeclaration template void func2(__ob_trap Ty i) {} // expected-error {{__ob_trap specifier cannot be applied to non-integer type 'Ty'}} template struct S {}; template <> struct S<__ob_trap int> {}; template <> struct S {}; void ptr(int a) { int __ob_trap *p = &a; // expected-error-re {{cannot initialize a variable of type '__ob_trap int *' {{.*}}with an rvalue of type 'int *'}} } void ptr2(__ob_trap int a) { int *p = &a; // expected-error-re {{cannot initialize a variable of type 'int *' {{.*}}with an rvalue of type '__ob_trap int *'}} } void overloadme(__ob_trap int a); // expected-note {{candidate function}} void overloadme(short a); // expected-note {{candidate function}} void test_overload_ambiguity() { int a; overloadme(a); // expected-error {{call to 'overloadme' is ambiguous}} } void f(void) __attribute__((overflow_behavior(wrap))); // expected-error {{'overflow_behavior' attribute cannot be applied to non-integer type 'void (void)'}} typedef float __attribute__((overflow_behavior(wrap))) wrap_float; // expected-error {{'overflow_behavior' attribute cannot be applied to non-integer type 'float'}} void pointer_compatibility(int* i_ptr) { __ob_trap int* nowrap_ptr; // static_cast should fail. nowrap_ptr = static_cast<__ob_trap int*>(i_ptr); // expected-error {{static_cast from 'int *' to '__ob_trap int *' is not allowed}} // reinterpret_cast should succeed. nowrap_ptr = reinterpret_cast<__ob_trap int*>(i_ptr); (void)nowrap_ptr; } void cpp_constexpr_bracket_initialization() { constexpr short cx1 = {(int __ob_wrap)100000}; // expected-error {{constant expression evaluates to 100000 which cannot be narrowed to type 'short'}} // expected-note@-1 {{insert an explicit cast to silence this issue}} constexpr short __ob_wrap cx2 = {100000}; // expected-error {{constant expression evaluates to 100000 which cannot be narrowed to type '__ob_wrap short'}} constexpr short __ob_trap cx3 = {(int)100000}; // expected-error {{constant expression evaluates to 100000 which cannot be narrowed to type '__ob_trap short'}} // expected-warning@-1 {{implicit conversion from 'int' to '__ob_trap short const' changes value from 100000 to -31072}} constexpr short cx4 = {(int __ob_trap)100000}; // expected-error {{constant expression evaluates to 100000 which cannot be narrowed to type 'short'}} // expected-warning@-1 {{implicit conversion from '__ob_trap int' to '__ob_trap const short' changes value from 100000 to -31072}} // expected-note@-2 {{insert an explicit cast to silence this issue}} } // ensure that all qualifier placements result in the same canonical type void test_qualifier_placements() { using ConstInt = const int; using WrapConstInt1 = ConstInt __attribute__((overflow_behavior(wrap))); using WrapConstInt2 = const int __attribute__((overflow_behavior(wrap))); typedef const int __ob_wrap const_int_wrap; typedef int __ob_wrap const int_wrap_const; typedef int __ob_trap const int_trap_const; static_assert(__is_same(WrapConstInt1, WrapConstInt2)); static_assert(__is_same(const_int_wrap, int_wrap_const)); static_assert(!__is_same(const_int_wrap, int_trap_const)); } 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_initialization() { int __ob_trap a = 10; int __ob_wrap b = 20; int __ob_wrap c = a; // expected-error {{cannot initialize a variable of type '__ob_wrap int' with an lvalue of type '__ob_trap int'}} int __ob_trap d = b; // expected-error {{cannot initialize a variable of type '__ob_trap int' with an lvalue of type '__ob_wrap int'}} } 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; // 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')}} } // OBT on data members (both static and non-static) struct DataMembers { __ob_wrap int nonstatic_specifier; int __attribute__((overflow_behavior(wrap))) nonstatic_attr; static __ob_trap int static_specifier; static int __ob_wrap static_specifier2; static int __attribute__((overflow_behavior(trap))) static_attr; }; __ob_trap int DataMembers::static_specifier = 0; int __ob_wrap DataMembers::static_specifier2 = 0; int __attribute__((overflow_behavior(trap))) DataMembers::static_attr = 0;