<div dir="ltr"><div class="gmail_extra"><div class="gmail_quote">On Wed, Oct 22, 2014 at 1:27 AM, Hal Finkel <span dir="ltr"><<a href="mailto:hfinkel@anl.gov" target="_blank">hfinkel@anl.gov</a>></span> wrote:<br><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><span class="">----- Original Message -----<br>
> From: "Richard Smith" <<a href="mailto:richard@metafoo.co.uk">richard@metafoo.co.uk</a>><br>
</span><span class="">> To: "Hal Finkel" <<a href="mailto:hfinkel@anl.gov">hfinkel@anl.gov</a>><br>
> Cc: <a href="mailto:reviews%2BD5872%2Bpublic%2B0417df57406a159b@reviews.llvm.org">reviews+D5872+public+0417df57406a159b@reviews.llvm.org</a>, "cfe commits" <<a href="mailto:cfe-commits@cs.uiuc.edu">cfe-commits@cs.uiuc.edu</a>>, "Daniel Berlin"<br>
> <<a href="mailto:dberlin@dberlin.org">dberlin@dberlin.org</a>>, "aaron ballman" <<a href="mailto:aaron.ballman@gmail.com">aaron.ballman@gmail.com</a>><br>
</span><span class="">> Sent: Tuesday, October 21, 2014 3:47:03 PM<br>
> Subject: Re: [PATCH] Enhanced ignored-qualifiers checks for restrict<br>
><br>
><br>
><br>
><br>
</span><span class="">> On Tue, Oct 21, 2014 at 8:11 AM, Hal Finkel < <a href="mailto:hfinkel@anl.gov">hfinkel@anl.gov</a> ><br>
> wrote:<br>
><br>
><br>
> ----- Original Message -----<br>
> > From: "Richard Smith" < <a href="mailto:richard@metafoo.co.uk">richard@metafoo.co.uk</a> ><br>
</span><div><div class="h5">> > To: <a href="mailto:hfinkel@anl.gov">hfinkel@anl.gov</a> , <a href="mailto:dberlin@dberlin.org">dberlin@dberlin.org</a> , "aaron ballman" <<br>
> > <a href="mailto:aaron.ballman@gmail.com">aaron.ballman@gmail.com</a> >, <a href="mailto:richard@metafoo.co.uk">richard@metafoo.co.uk</a><br>
> > Cc: <a href="mailto:cfe-commits@cs.uiuc.edu">cfe-commits@cs.uiuc.edu</a><br>
> > Sent: Monday, October 20, 2014 4:17:00 PM<br>
> > Subject: Re: [PATCH] Enhanced ignored-qualifiers checks for<br>
> > restrict<br>
> ><br>
> > First off, more warnings for dubious uses of `restrict` seem<br>
> > valuable<br>
> > to me. The two warnings you suggest seem like good ideas.<br>
><br>
> Thanks! There's more coming too...<br>
><br>
> For the record, I'd like to work on enhancing our support for<br>
> restrict (as well as the hopefully-better C++ version being<br>
> developed, WG21 N4150 has the current wording in progress). I think<br>
> that enhancing our warnings on restrict is a good first step.<br>
><br>
> > Some<br>
> > thoughts:<br>
> ><br>
> > I don't think cast expressions are the right thing to target here.<br>
> > The same issue applies to compound literals, new-expressions, and<br>
> > so<br>
> > on.<br>
><br>
> Good point.<br>
><br>
> > `restrict` only has meaning when used in "a declaration of an<br>
> > ordinary identifier that provides a means of designating an object<br>
> > P", so perhaps we should warn on it (at least at the top level) in<br>
> > all cases where it's not part of such a declaration (and can't be<br>
> > indirectly part of a declaration, such as if it's in a typedef or<br>
> > template argument).<br>
><br>
> As a note, and personally I find the wording here a bit unclear, but<br>
> if you look at the rational document (WG14 N334), it is explicit<br>
> that the wording also is intended to allow restrict to be useful on<br>
> fields of structures. The identifier can be the thing that provides<br>
> access to the structure.<br>
><br>
> But, generally speaking, I agree that the list of useful places is<br>
> much smaller than the list of useless places, and an exclusionary<br>
> design for the warning might make more sense. Do you have a<br>
> suggestion on how the warning should be implemented?<br>
><br>
><br>
> In SemaType's GetFullTypeForDeclarator, you have access to the<br>
> Context from the DeclSpec, which you can use to determine whether to<br>
> warn. (You'd probably want to add a check for whether the type from<br>
> the decl-specifiers is 'restrict', and also check each time you add<br>
> a pointer type whether that type introduces a 'restrict').<br>
<br>
</div></div>This is useful, thanks! However, for casts, I'd likely still want access to the FromTy, but more than that:<br>
<br>
char foo(float * __restrict__ x) {<br>
  char * __restrict__ y = (char * __restrict__) x;<br>
  return *y;<br>
}<br>
<br>
Should we warn here about the __restrict__ in the cast? I think this is questionable (because it is technically unnecessary), but:<br>
<br>
typedef float * __restrict__ floatp;<br>
typedef char * __restrict__ charp;<br>
<br>
char goo(floatp x) {<br>
  charp y = (charp) x;<br>
  return *y;<br>
}<br>
<br>
I definitely think that we should not warn here about the fact that charp is restrict-qualified in the cast (because I don't want to force anyone to manually expand a typedef to get around a warning). However, I certainly do want to warn on restrict-qualified typedefs generally: *((charp) p) += 1 should get a warning.<br>
<br>
so I may need even more context than the TheContext in DeclSpec currently provides?<br></blockquote><div><br></div><div>This is possible, and may not be too hard: you could add a list of the CastExprs you're considering warning about to the ExprEvaluationContext, remove them from the list if you see they're used as the initializer for a restrict-qualified pointer, and warn on them when you pop the context.</div><div><br></div><div>I suppose you should only do this for some flavors of initialization, though, and in particular not for function parameter initialization. Consider:</div><div><br></div><div>char *blah(charp x); // maybe warn here: restrict has no effect on a parameter in a function declaration?</div><div>void boo(char *p) {</div><div>  { // 1:<br></div><div>    char *q = blah(p); // ok, restrict on parameter only affects body of blah</div><div>  }</div><div>  { // 2:</div><div>    char *q = blah((charp)p); // warn, or not?</div><div>  }</div><div>  { // 3:</div><div>    charp r = (charp)p;</div><div>    char *q = blah(r);</div><div>  }</div><div>}</div><div><br></div><div>Now, suppose blah returns its argument. In blocks 1 and 2, it's permissible to use both p and q after the call. In block 3, it would be UB.</div><div><br></div><div>So I think we should warn on the non-defining declaration of 'blah'. And we should warn on block 2 because we used a restrict-qualified cast but the restrict was meaningless. But we should not warn about the cast in 3. Make sense?</div><div><br></div><div>Having said that, I wonder if we should warn about 3 regardless (probably under a different warning flag) for having an indirect use of 'restrict' through a typedef. It's not obvious to a reader of the code in 3 that the variable is in fact declared 'restrict', and it has a potentially-surprising effect on the semantics of the block. There's a simple syntactic transformation we could suggest to make this obvious to readers of the code (and to suppress such a warning):</div><div><br></div><div>  charp restrict r = (charp)p;</div><div><br></div><div>Perhaps people would always put the word 'restrict' in the name of the typedef, making this unnecessary. Do you have much experience with how these kinds of typedefs might be used?</div><div><br></div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">
Thanks again,<br>
Hal<br>
<div class="HOEnZb"><div class="h5"><br>
><br>
><br>
><br>
> > Taking the address of a `restrict`-qualified pointer has weird<br>
> > semantics, and perhaps deserves a warning. For instance:<br>
> ><br>
> > int *restrict a = &...;<br>
> > int **p = &a;<br>
> > *a = 1;<br>
> > int k = **p;<br>
> ><br>
> > ... is fine, even though `a` is accessed through a<br>
> > non-`restrict`-qualified pointer, because `*q` is based on `a`.<br>
><br>
> This seems like a reasonable idea, I'll think about it. We probably<br>
> want a warning like:<br>
><br>
> pointer access '**p' is based on restrict-qualified pointer 'a' in a<br>
> non-obvious way<br>
><br>
> ><br>
> > Similarly, declaring an object of a type that has a non-top-level<br>
> > `restrict` qualifier also has weird semantics, and we should<br>
> > perhaps<br>
> > warn on that.<br>
><br>
> Do you mean if someone tries to declare something like?<br>
> int * * restrict * restrict * x;<br>
><br>
><br>
> Sure. I was thinking of simpler things like<br>
><br>
><br>
> int *a = ...;<br>
> int **p = &a;<br>
> int *restrict *q = p;<br>
><br>
><br>
> // Now *p is based on 'a', which is 'restrict'ed because it can be<br>
> designated as the restrict-qualified pointer *p. But accessing 'a'<br>
> directly or through *p is fine, because those expressions are *also*<br>
> based on 'a'. So the 'restrict' here perhaps doesn't mean what its<br>
> author intended. Or maybe it does. *shrug*<br>
><br>
><br>
><br>
> > Perhaps we should also warn on copying a `restrict`-qualified<br>
> > pointer<br>
> > to a non-`restrict`-qualified pointer, since that also seems like a<br>
> > very common error.<br>
><br>
> I'm not sure about this one. It will be noisy, because as you noted<br>
> above, this is perfectly legal behavior (the non-restrict-qualified<br>
> variable's value simply becomes "based on" the restrict-qualified<br>
> pointer), and carries well-defined (if sometimes hard to deduce)<br>
> semantics.<br>
><br>
><br>
><br>
> Consider this trivial example:<br>
><br>
><br>
> int *restrict a = malloc(sizeof(int) * 4);<br>
> for (int *p = a; p != a + 4; ++p)<br>
> *p = 0;<br>
> int result = a[n];<br>
><br>
><br>
> This has undefined behavior because p is not based on a, and p is<br>
> used to modify an object accessed through a.<br>
><br>
><br>
> Thanks again,<br>
> Hal<br>
><br>
> ><br>
> > <a href="http://reviews.llvm.org/D5872" target="_blank">http://reviews.llvm.org/D5872</a><br>
> ><br>
> ><br>
> ><br>
><br>
> --<br>
> Hal Finkel<br>
> Assistant Computational Scientist<br>
> Leadership Computing Facility<br>
> Argonne National Laboratory<br>
><br>
><br>
<br>
--<br>
Hal Finkel<br>
Assistant Computational Scientist<br>
Leadership Computing Facility<br>
Argonne National Laboratory<br>
</div></div></blockquote></div><br></div></div>