GeezerVisonThe World Wide Web, restored to 800 pixels of glory. | ||||||||||||||||||||||||||
| Home|About|Gaming cabinet|Archives|How it works|Starter sites | ||||||||||||||||||||||||||
GeezerVison is showing clang.llvm.org — OverflowBehaviorTypes - Clang OverflowBehaviorTypes#Introduction#Clang provides overflow behavior types that allow developers to have fine-grained control over the overflow behavior of integer types. Overflow behavior can be specified using either attribute syntax or keyword syntax to control how arithmetic operations on a given integer type should behave upon overflow. This is particularly useful for projects that need to balance performance and safety, allowing developers to enable or disable overflow checks for specific types. Overflow behavior types can be enabled using the Note This feature is experimental. The flag spelling may change in future releases as the feature matures. There are two syntax options for specifying overflow behavior: Attribute syntax: __attribute__((overflow_behavior(behavior))) Where
Keyword syntax: __ob_wrap // equivalent to __attribute__((overflow_behavior(wrap))) __ob_trap // equivalent to __attribute__((overflow_behavior(trap))) Either of these spellings can be applied to Arithmetic operations containing one or more overflow behavior types follow standard C integer promotion and conversion rules while preserving overflow behavior information. Not a Type Qualifier#An overflow behavior type is a type specifier, like This distinction is observable:
Qualifiers may still be applied to an overflow behavior type, and they behave as they do on any other type: const __ob_trap int a = 0; a = 1; // error: cannot assign to variable 'a' with const-qualified type // '__ob_trap const int' Examples#Here are examples using both syntax options: Using attribute syntax with a typedef: typedef unsigned int __attribute__((overflow_behavior(trap))) non_wrapping_uint; non_wrapping_uint add_one(non_wrapping_uint a) { return a + 1; // Overflow is checked for this operation. } Using keyword syntax with a typedef: typedef unsigned int __ob_trap non_wrapping_uint; non_wrapping_uint add_one(non_wrapping_uint a) { return a + 1; // Overflow is checked for this operation. } Using attribute syntax with a type directly: int mul_alot(int n) { int __attribute__((overflow_behavior(wrap))) a = n; return a * 1337; // Potential overflow is not checked and is well-defined } Using keyword syntax with a type directly: int mul_alot(int n) { int __ob_wrap a = n; return a * 1337; // Potential overflow is not checked and is well-defined } “Well-defined” overflow is consistent with two’s complement wrap-around semantics and won’t be removed via eager compiler optimizations (like some undefined behavior might). Promotion Rules#Overflow behavior types (OBTs) follow the traditional C integer promotion and conversion rules while propagating overflow behavior through implicit casts. This ensures compatibility with existing C semantics while maintaining overflow behavior information throughout arithmetic expressions. The resulting type characteristics for overflow behavior types (OBTs) across a variety of scenarios is detailed below.
Overflow Behavior Dominance Rules:
This model preserves traditional C semantics while ensuring overflow behavior information is correctly propagated through arithmetic expressions. Pointer Semantics#Overflow behavior types can be used with pointers, where the overflow behavior annotation applies to the pointee type. Pointers to overflow behavior types have specific compatibility and conversion rules. Pointer Type Compatibility: Pointers to overflow behavior types are treated as distinct types from their underlying types and from each other when they have different overflow behaviors. This affects assignment, parameter passing, and other pointer operations. Discarding Overflow Behavior: When assigning from a overflow behavior annotated type to a regular integer
type, the compiler issues a warning about discarding overflow behavior. This is
controlled by the unsigned long *px; unsigned long __ob_trap *py; unsigned long __ob_wrap *pz; // Discarding overflow behavior - warns but allowed px = py; // warning: assigning to 'unsigned long *' from // '__ob_trap unsigned long *' discards overflow behavior py = px; // warning: assigning to '__ob_trap unsigned long *' from // 'unsigned long *' discards overflow behavior Conversion Semantics#Overflow behavior types are implicitly convertible to and from built-in integral types with specific semantics for warnings and constant evaluation. Incompatible Overflow Behaviors: Attempting to assign or convert between types with incompatible overflow
behaviors ( int __ob_trap a; int __ob_wrap b; a = b; // error: assigning to '__ob_trap int' from '__ob_wrap int' with // incompatible overflow behavior types ('__ob_trap' and '__ob_wrap') The Diagnostics section further below details the exact diagnostics Clang provides for overflow behavior types. Truncation Semantics#Truncation and overflow are related and are both often desirable in some contexts and undesirable in others. To provide control over these behaviors, overflow behavior types may also be used to control truncation instrumentation at the type level. Note that implicit integer truncation is not an undefined behavior in C. Due to this, overflow behavior types make no special guarantees about whether implicit integer truncation is defined or not – the behavior is simply always defined. Use of overflow behavior types in these contexts only control instrumentation related to truncation. When an overflow behavior type is involved as the source or destination type of truncation, instrumentation checks behave as follows:
void foo(char a, int __ob_trap b) { a = b; // truncation checks are inserted, may trap } void bar(char a, int __ob_wrap b) { a = b; // sanitizer truncation checks disallowed } Note that truncation itself is a form of overflow behavior - when a value is
too large to fit in the destination type, the high-order bits are discarded,
which is a wrapping behavior that Constant Conversion Semantics#When converting constant values to overflow behavior types, the behavior depends on the overflow behavior annotation and whether the conversion would change the value: With ‘wrap’ types: Constant conversions that would overflow are accepted without warning when
assigning to or explicitly casting to short x1 = (int __ob_wrap)100000; // OK: explicit wrap cast short __ob_wrap x2 = (int)100000; // OK: wrap destination unsigned short __ob_wrap ux = 100000; // OK: wrapping expected With ‘trap’ types: Constant conversions that would change the value generate a warning when the
destination is a Implicit Conversions Due to Assignment#Like with the basic integral types in C and C++, types on the right-hand side of an assignment may be implicitly converted to match the left-hand side. All built-in integral types can be implicitly converted to an overflow behavior version. char x = 1; int __ob_wrap a = x; // x converted to __ob_wrap int Assigning one overflow behavior type to another is legal only when the two
types have matching overflow behavior kinds (i.e., int __ob_trap trap_var; int __ob_wrap wrap_var; trap_var = wrap_var; // error: assigning to '__ob_trap int' from // '__ob_wrap int' with incompatible overflow // behavior types ('__ob_trap' and '__ob_wrap') However, conversions between compatible overflow behavior types (same kind, different underlying widths or signedness) are allowed: long __ob_wrap x = __LONG_MAX__; int __ob_wrap a = x; // OK: both have 'wrap' behavior C++ Overload Resolution#For the purposes of C++ overload set formation, promotions or conversions to and from overflow behavior types are of the same rank as normal integer promotions and conversions. These rules have implications during overload candidate selection which may lead to unexpected but correct ambiguity errors. The example below shows potential ambiguity as matching just the underlying type of an OBT parameter is not enough to precisely pick an overload candidate. void foo(int __ob_trap a); void foo(short a); void bar(int a) { foo(a); // call to 'foo' is ambiguous } Most integral types can be implicitly converted to match OBT parameter types and this can be done unambiguously in certain cases. Especially, when all other candidates are not implicitly convertible. void foo(int __ob_trap a); void foo(char *a); void bar(int a) { foo(a); // picks foo(__ob_trap int) } Overflow behavior types with differing kinds may also create ambiguity in certain contexts. void foo(int __ob_trap a); void foo(int __ob_wrap a); void bar(int a) { foo(a); // call to 'foo' is ambiguous } Overflow behavior types may also be used as template parameters and used within
C C _Generic Expressions#Overflow behavior types may be used within C Overflow behavior types do not match against their underlying types within C
int foo(int __ob_wrap x) { return _Generic(x, int: 1, char: 2, default: 3); // returns 3 } int bar(int __ob_wrap x) { return _Generic(x, int __ob_wrap: 1, int: 2, default: 3); // returns 1 } C++ Template Specializations#Like with template<typename T> struct TypeProcessor { static constexpr int value = 0; // default case }; template<> struct TypeProcessor<int> { static constexpr int value = 1; // int specialization }; template<> struct TypeProcessor<int __ob_wrap> { static constexpr int value = 2; // __ob_wrap int specialization }; template<> struct TypeProcessor<int __ob_trap> { static constexpr int value = 3; // __ob_trap int specialization }; When no exact template specialization exists for an OBT, it falls back to the default template rather than matching the underlying type specialization, maintaining type safety and avoiding unexpected behavior. Interaction with Command-Line Flags and Sanitizer Special Case Lists#The
It is important to note the distinction between signed and unsigned types. For
unsigned integers, which wrap on overflow by default, The Diagnostics#Clang provides diagnostics to help developers manage overflow behavior types. Specification Errors and Warnings#When using overflow behavior types, several diagnostics help catch mistakes in how the types are specified. Conflicting Specifications: An error is issued when both the keyword syntax and attribute syntax are used with incompatible overflow behaviors on the same type: int __ob_wrap __attribute__((overflow_behavior(trap))) x; // error: conflicting overflow behavior specification; specifier // specifies 'wrap' but attribute specifies 'trap' Redundant Specifications: A warning is issued when both syntax forms specify the same behavior, which is redundant but allowed: int __ob_wrap __attribute__((overflow_behavior(wrap))) x; // warning: redundant overflow behavior specification; both specifier // and attribute specify 'wrap' Feature Not Enabled: When overflow behavior types are used without enabling the feature via
// Without -fexperimental-overflow-behavior-types int __attribute__((overflow_behavior(wrap))) x; // warning: 'overflow_behavior' attribute is ignored because it is // not enabled; pass -fexperimental-overflow-behavior-types -Woverflow-behavior-conversion#This warning group is issued when an overflow behavior type is implicitly converted to a standard integer type, which may lead to the loss of the specified overflow behavior. typedef int __ob_wrap wrapping_int; void some_function(int); void another_function(wrapping_int w) { some_function(w); // warning: implicit conversion from 'wrapping_int' to // 'int' discards overflow behavior } To fix this, you can explicitly cast the overflow behavior type to a standard integer type. typedef int __ob_wrap wrapping_int; void some_function(int); void another_function(wrapping_int w) { some_function(static_cast<int>(w)); // OK } This warning group includes
Note
-Wincompatible-pointer-types-discards-overflow-behavior#This warning (enabled by default) is issued when converting between pointer types where overflow behavior information is discarded. This occurs when assigning between pointers that differ only in their overflow behavior annotation. void example() { unsigned long __ob_trap *trap_ptr; unsigned long *regular_ptr; regular_ptr = trap_ptr; // warning: assigning to 'unsigned long *' // from '__ob_trap unsigned long *' discards // overflow behavior trap_ptr = regular_ptr; // warning: assigning to '__ob_trap unsigned long *' // from 'unsigned long *' discards overflow behavior } This warning is part of the -Wimplicit-overflow-behavior-conversion#This warning is issued when an overflow behavior type is implicitly converted
to a standard integer type as part of most conversions, which may lead to the
loss of the specified overflow behavior. This is the main warning in the
typedef int __ob_wrap wrapping_int; void some_function() { wrapping_int w = 1; int i = w; // warning: implicit conversion from 'wrapping_int' to 'int' // during assignment discards overflow behavior // [-Wimplicit-overflow-behavior-conversion] } Here’s another example showing function parameter conversion with a typedef int __ob_trap safe_int; void bar(int x); // Function expects standard int void foo() { safe_int s = 42; bar(s); // warning: implicit conversion from 'safe_int' to 'int' // discards overflow behavior // [-Wimplicit-overflow-behavior-conversion] } To fix this, you can explicitly cast the overflow behavior type to a standard integer type. typedef int __ob_wrap wrapping_int; typedef int __ob_trap safe_int; void some_function() { wrapping_int w = 1; int i = static_cast<int>(w); // OK int j = (int)w; // C-style OK } void bar(int x); void foo() { safe_int s = 42; bar(static_cast<int>(s)); // OK } -Wimplicit-overflow-behavior-conversion-assignment#This warning is issued specifically when an overflow behavior type is
implicitly converted to a standard integer type during assignment operations or
variable initialization. This is a subset of the more general
typedef int __ob_wrap wrapping_int; void some_function() { wrapping_int w = 1; int i = w; // warning: implicit conversion from 'wrapping_int' to 'int' // during assignment discards overflow behavior // [-Wimplicit-overflow-behavior-conversion-assignment] } This also applies to variable initialization: void another_example() { int __ob_trap safe = 42; int regular = safe; // warning: implicit conversion from '__ob_trap int' // to 'int' during assignment discards overflow behavior // [-Wimplicit-overflow-behavior-conversion-assignment] } This diagnostic can be controlled independently, allowing projects to suppress assignment-related warnings while still receiving warnings for other types of implicit conversions (such as function parameter passing). Note that when assigning from a non-OBT type to an OBT type, no warning is issued as overflow behavior is being added, not discarded: void adding_obt_is_ok() { int plain = 42; int __ob_wrap wrapped = plain; // OK - adding overflow behavior, no warning } -Wimplicit-overflow-behavior-conversion-assignment-pedantic#A less severe version of
void example() { unsigned int __ob_wrap wrapped_uint = 42; unsigned int regular = wrapped_uint; // warning: implicit conversion from // '__ob_wrap unsigned int' to // 'unsigned int' during assignment // discards overflow behavior // [-Wimplicit-overflow-behavior-conversion-assignment-pedantic] } This warning is useful for projects that want to track all overflow behavior
annotations but consider unsigned wrapping conversions to be lower priority
than signed conversions or -Wimplicit-overflow-behavior-conversion-function-boundary#This warning (disabled by default) is issued when an overflow behavior type is passed as an argument to a function parameter that does not have the same overflow behavior annotation. This helps identify situations where overflow behavior contracts may be lost at function boundaries. void process_value(int x); // Function expects standard int void caller() { int __ob_trap safe_value = 42; process_value(safe_value); // warning: passing argument of type // '__ob_trap int' to parameter of type 'int' // discards overflow behavior at function boundary // [-Wimplicit-overflow-behavior-conversion-function-boundary] } This warning can be particularly useful for catching cases where overflow
checking behavior is lost when crossing API boundaries. Both the general
version
( To fix this warning, you can either:
void process_value(int __ob_trap x); // Accept trap-annotated int void caller() { int __ob_trap safe_value = 42; process_value(safe_value); // OK }
void process_value(int x); void caller() { int __ob_trap safe_value = 42; process_value((int)safe_value); // OK - explicit cast } -Wimplicit-overflow-behavior-conversion-function-boundary-pedantic#A less severe version of the warning above which is issued only in the case of
unsigned Format String Functions#When overflow behavior types are used with format string functions (printf-family
functions like #include <cstdio> typedef int __ob_wrap wrap_int; typedef unsigned int __ob_trap nowrap_uint; void example() { wrap_int wi = 42; nowrap_uint su = 100; scanf("%d\n", &wi); // OK: &wi treated as int* for %d printf("%d\n", wi); // OK: wi treated as int for %d printf("%u\n", su); // OK: su treated as unsigned int for %u printf("%s\n", wi); // Error: int incompatible with %s (same as regular int) } This behavior ensures that overflow behavior types work seamlessly with existing format string functions without requiring special format specifiers, while still maintaining their overflow behavior semantics in arithmetic operations. The format string checker uses the underlying type to determine compatibility,
so Incompatibility With Non-Integer Types#An error is issued when attempting to create an overflow behavior type from a non-integer type. typedef float __attribute__((overflow_behavior(wrap))) wrapping_float; // error: 'overflow_behavior' attribute cannot be applied to non-integer type 'float' typedef struct S { int i; } __attribute__((overflow_behavior(wrap))) S_t; // error: 'overflow_behavior' attribute cannot be applied to non-integer type 'struct S' Incompatibility With
| ||||||||||||||||||||||||||
| You are visitor 01402503 — GeezerVison does not store the pages you look up. Best viewed with Netscape Navigator 4.7 or Internet Explorer 6 at 800×600. No cookies required. |