JustinStitt wrote: Hi @efriedma-quic, thanks for dumping all these cases! I will respond to each one individually.
I understand you think adding a type would be better so I am exploring that option (I am thinking something similar to [extended vectors](https://clang.llvm.org/docs/LanguageExtensions.html#vectors-and-extended-vectors)). But for now, I am trying to make this attribute as useful and compatible as possible. > If you have a select with both wrapping and non-wrapping operands, is the > result wrapping? I assume you're referring to a ternary statement? Currently, no. Although, I should add support for this similar to how BinaryOperators are considered wrapping if any of their operands are. ``` `-ConditionalOperator 0x559ddad37998 <col:4, col:15> 'int' |-ImplicitCastExpr 0x559ddad37950 <col:4> 'int' <IntegralCast> | `-ImplicitCastExpr 0x559ddad37938 <col:4> '_Bool' <LValueToRValue> | `-DeclRefExpr 0x559ddad378d8 <col:4> 'volatile _Bool' lvalue Var 0x559ddad7a350 'cond' 'volatile _Bool' |-ImplicitCastExpr 0x559ddad37968 <col:11> 'wrap_int':'int' <LValueToRValue> | `-DeclRefExpr 0x559ddad378f8 <col:11> 'const wrap_int':'const int' lvalue Var 0x559ddad37780 'a' 'const wrap_int':'const int' `-ImplicitCastExpr 0x559ddad37980 <col:15> 'int' <LValueToRValue> `-DeclRefExpr 0x559ddad37918 <col:15> 'const int' lvalue Var 0x559ddad37838 'b' 'const int' ``` --- > If you declare a variable as both wrapping and non-wrapping, is it wrapping? I am not sure how to do this. I am sure that with the magic of C anything is possible but I can't conceive a way to have a variable both have the attribute and not have the attribute (to be clear, there doesn't exist a `__attribute__((no-wraps))` currently) > If you declare a function parameter both wrapping and non-wrapping, is it > wrapping? Same here, not sure what you mean. > If you assign to a wrapping variable, is the result wrapping? It depends on the type of the assignee, which I discuss later with a `const` analogy. ```c wrap_int a; int b = a; // b is not wrapping wrap_int c = a; // c is wrapping ``` --- > If you mark a `short` wrapping, is the type after promotion wrapping? This concerns the `-fsanitize=implicit-signed-integer-truncation` sanitizer which the wraps attribute disables. So the type boundaries pre-promotion are not enforced by this sanitizer for wrapping types (e.g. for short, [-32768,32767]). > If the operands of an equality operation are wrapping, is the resulting > boolean wrapping? I don't think you can get a less-than-int from an equality operator as the result. With that being said, and for all BinaryOperators, the resulting type will be wrapping if any of the operands are wrapping. ``` `-IfStmt 0x56518e85e710 <line:9:3, line:11:3> |-BinaryOperator 0x56518e85e6e0 <line:9:7, col:12> 'int __attribute__((wraps))':'int' '==' | |-ImplicitCastExpr 0x56518e85e6b0 <col:7> 'wrap_int':'int' <LValueToRValue> | | `-DeclRefExpr 0x56518e85e670 <col:7> 'wrap_int':'int' lvalue Var 0x56518e85e560 'a' 'wrap_int':'int' | `-ImplicitCastExpr 0x56518e85e6c8 <col:12> 'wrap_int':'int' <LValueToRValue> | `-DeclRefExpr 0x56518e85e690 <col:12> 'wrap_int':'int' lvalue Var 0x56518e85e5d8 'b' 'wrap_int':'int' `-CompoundStmt 0x56518e85e700 <col:15, line:11:3> ``` --- > If you mark a bitfield wrapping, does it wrap? Ah, nice corner case. This concerns the `-fsanitize=implicit-bitfield-conversion` sanitizer and is something I did not consider. So, currently the wraps attribute won't do anything on bitfields. I could add support for disabling this sanitizer for wrapping bitfields. > The fact that with this patch, a wrapping int is "just" an int is both the > strength and weakness: you don't need to write out all these interactions... > but the result is just based on clang's internal preferences for preserving > type sugar, which are not documented. In the cases where the attribute is "lost" it is similar to how `const` qualifiers disappear during assignments/type changes. ```c const int a; int b = a; // b is not const // or extern void foo(int some); foo(a); // const-ness is stripped, @some is not const ``` In the cases where the attribute sticks around, it follows these rules: * Persists through Unary operators 👍 * If any operand within a BinaryOperator expression are wrapping then the entire expression result is considered wrapping. * When used in assignments or passed as arguments to a function, the wrapping attribute will be present if the left-hand side or the function argument is wrapping. (similar to `const`, I suppose). --- So, after reading all your cases my TODO list is: * add support for ternary operator results gaining the wrapping attribute if any of its operands have it * add support for disabling `-fsanitize=implicit-bitfield-conversion` when bitfields are marked as wrapping. https://github.com/llvm/llvm-project/pull/86618 _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits