lebedev.ri added inline comments.

================
Comment at: lib/CodeGen/CGExprScalar.cpp:1036
+    return;
+  // That's it. We can't rule out any more cases with the data we have.
+
----------------
rsmith wrote:
> lebedev.ri wrote:
> > rsmith wrote:
> > > rsmith wrote:
> > > > lebedev.ri wrote:
> > > > > rsmith wrote:
> > > > > > I don't like the overlap between the implicit truncation check and 
> > > > > > this check. I think you should aim for exactly one of those checks 
> > > > > > to fire for any given integer conversion. There are the following 
> > > > > > cases:
> > > > > > 
> > > > > >  * Dst is smaller than Src: if the value changes at all (with sign 
> > > > > > change or without), then the truncation check already catches it, 
> > > > > > and catching it here does not seem useful
> > > > > >  * Dst is the same size as Src or larger: sign change is the only 
> > > > > > problem, and is only possible if exactly one of Src and Dst is 
> > > > > > signed
> > > > > > 
> > > > > > So I think you should bail out of this function if either Src and 
> > > > > > Dst are both unsigned or both are signed, and also if Src is larger 
> > > > > > than Dst (because we treat that case as a lossy truncation rather 
> > > > > > than as a sign change).
> > > > > > 
> > > > > > And when you do emit a check here, the only thing you need to check 
> > > > > > is if the signed value is negative (if so, you definitely changed 
> > > > > > the sign, and if not, you definitely didn't -- except in the 
> > > > > > truncation cases that the truncation sanitizer catches).
> > > > > To be clear: we want to skip emitting in those cases if the other 
> > > > > check (truncation) is enabled, right?
> > > > > It does seem to make sense, (and i did thought about that a bit), but 
> > > > > i need to think about it more..
> > > > I think we want to skip emitting those checks always (regardless of 
> > > > whether the other sanitizer is enabled). One way to think of it: this 
> > > > sanitizer checks for non-truncating implicit integer conversions that 
> > > > change the value of the result. The other sanitizer checks for 
> > > > truncating implicit integer conversions that change the value of the 
> > > > result.
> > > > 
> > > > I don't see any point in allowing the user to ask to sanitize 
> > > > sign-changing truncation but not other value-changing truncations. That 
> > > > would lead to this:
> > > > ```
> > > > int a = 0x17fffffff; // no sanitizer warning
> > > > int b = 0x180000000; // sanitizer warning
> > > > int c = 0x1ffffffff; // sanitizer warning
> > > > int d = 0x200000000; // no sanitizer warning
> > > > ```
> > > > ... which I think makes no sense.
> > > Hmm, wait, the "truncation" sanitizer doesn't catch this:
> > > 
> > > `int a = 0x80000000u;`
> > > 
> > > ... does it? (Because it looks for cases where the value doesn't 
> > > round-trip, not for cases where the value was changed by the truncation.)
> > > 
> > > 
> > > I've thought a bit more about the user model and use cases for these 
> > > sanitizers, and I think what we want is:
> > > 
> > >  * a sanitizer that checks for implicit conversions with data loss (the 
> > > existing truncation sanitizer)
> > >  * a sanitizer that checks for implicit conversions that change the 
> > > value, where either the source or destination was signed (approximately 
> > > what this sanitizer is doing)
> > > 
> > > The difference between that and what you have here is that I think the 
> > > new sanitizer should catch all of these cases:
> > > 
> > > ```
> > > int a = 0x17fffffff;
> > > int b = 0x180000000;
> > > int c = 0x1ffffffff;
> > > int d = 0x200000000;
> > > ```
> > > 
> > > ... because while the initializations of `a` and `d` don't change the 
> > > sign of the result, that's only because they wrap around *past* a sign 
> > > change.
> > > 
> > > So, I think what you have here is fine for the SrcBits <= DstBits case, 
> > > but for the SrcBits > DstBits case, you should also check whether the 
> > > value is the same as the original (that is, perform the truncation check).
> > > 
> > > In order to avoid duplicating work when both sanitizers are enabled, it'd 
> > > make sense to combine the two sanitizer functions into a single function 
> > > and reuse the checks.
> > Yep, makes sense. I don't think i have followed the recommendations to the 
> > letter,
> > but i think the end result is not worse than suggested. Added tests shows 
> > how it works now.
> OK, so to be clear I'm following:
> 
>  * Any implicit conversion that truncates and changes the value triggers the 
> truncation sanitizer (unsigned if both source and destination are unsigned, 
> signed otherwise)
>  * Any implicit conversion that results in a sign change triggers the sign 
> change sanitizer
>  * Any implicit conversion that triggers both sanitizers produces a single 
> warning classified as ICCK_SignedIntegerTruncationOrSignChange (eg, the 
> truncation changed the value, and the sign changed -- possibly multiple times 
> -- when dropping bits)
> 
> That seems fine to me.
> OK, so to be clear I'm following:

I do think that is what is going on.
It does warn on all of the cases you highlighted:
```
int a = 0x80000000u;

int a = 0x17fffffff;
int b = 0x180000000;
int c = 0x1ffffffff;
int d = 0x200000000;
```


================
Comment at: lib/CodeGen/CGExprScalar.cpp:1071
+    // So which 'lt' predicate for the comparison do we have to use?
+    // NOTE: if it is unsigned, then the comparison is naturally always 
'false'.
+    llvm::ICmpInst::Predicate Pred =
----------------
rsmith wrote:
> Just emit `i1 false` directly in this case. `IRBuilder` generally only 
> constant-folds values for you if all the operands are constant, and 
> sanitizers are often used at -O0, so there's no guarantee that anyone else 
> will clean this up.
Ok, fair enough.


Repository:
  rC Clang

https://reviews.llvm.org/D50250



_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to