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

Reply via email to