JustinStitt wrote:

> > > 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)
> 
> Say you declare a global variable like the following:
> 
> ```
> typedef int wrapint __attribute((wraps));
> extern wrapint x;
> int x = 0;
> ```
> 
> Is "x" wrapping?

No. But I am confused, isn't this just shadowing a global variable with a 
lesser-scoped one. Are they the same? What behavior do we want here?

> 
> > > 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- and 
> > post-promotion are not enforced by this sanitizer for wrapping types.
> 
> There are cases that don't involve truncation:
> 
> ```
> typedef short wrapshort __attribute((wraps));
> wrapshort x = 0x7FFF;
> int y = x*x*x*x;
> ```

Arithmetic cannot be performed on less-than-ints so the implicit promotions are 
put in place which lose the attribute. I just worked on an update to carry the 
wraps attribute through implicit integer promotion. 

However, after making the patch and testing it I am not sure what we want. Do 
we want to cancel implicit promotions for less-than-ints that possess the wraps 
attribute (doesn't sound spec compliant)? Or, should wrapping things still 
undergo promotion but now wrap at different bounds than what their original 
type specified?

If I make a wrapping char [-128, 127] and do some arithmetic on it it will be 
promoted to int (and still have the wraps attribute, with my patch) then 
proceed.

In the example below, `x*x*x*x*x` is `33,038,369,407` which is greater than 
INT_MAX `2,147,483,647` and will thus overflow (a few times). However, this 
overflow is happening at the integer boundaries not at the char boundaries.

```c
wrapchar x = 127;
int y = x*x*x*x*x; // result: -1321368961
```

The options are:
1) don't carry the wraps attribute through implicit promotions
2) carry the wraps attribute but use promoted-to-type's boundaries for wrapping
3) carry attribute and use the pre-promotion type's boundaries

More on this, I don't see how changing implementation from attribute-based to 
type-based resolves any of these design decisions. Neither approach is 
necessarily easier to implement or to understand for developers, if the right 
decisions are made in terms of behavior then the attribute approach can be just 
as useful and predictable.

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