Parameters declared restrict and compiler warnings
Asked Answered
F

3

16

Neither gcc 5 nor clang 3.6 give warnings where the constraints of the restrict qualifier are violated, even when called with -Wall. Consider the following code fragment:

extern void f(char *restrict p, char *restrict q);

void g(char *p)
{
    f(p, p);
}

Naively, I'd expect that the violation can be determined statically, and I was expecting that -Wall would give a warning. Have I missed a flag somewhere, or is there some problem with giving warnings that I'm not seeing?

Formicary answered 5/6, 2015 at 0:2 Comment(2)
Top-level qualifiers in a prototype are meaningless (except as documentation); the function body could still be implemented as void f(char *p, char *q);. Apparently no compiler optimizes the calling code based on the presence of restrict either. Related threadGildagildas
In lieu of a compiler developer actually commenting - my guess would just be that nobody has asked for the feature and/or no developer has decided to put time into implementing it.Gildagildas
F
14

Starting with version 8, gcc gives a helpful warning for the above code:

a.c: In function ‘g’:
a.c:5:5: warning: passing argument 1 to restrict-qualified parameter aliases with argument 2 [-Wrestrict]
     f(p, p);
     ^
Formicary answered 24/5, 2018 at 12:28 Comment(0)
C
3

Given the code:

void test(int *restrict a, int *restrict b, int c)
{
  a[0] += b[c];
}

the only scenario affected by the restrict qualifier would be a==b+c; in that case, the pointer in a would be used to modify an object which is also accessed through unrelated pointer in b. In all other cases that would be defined in the absence of restrict, no object that is accessed via a would also be accessed via b, nor vice versa.

A compiler that could see that a function that was passed restrict- qualified pointer arguments used them in violation of the rules associated therewith might helpfully warn of such violation, but a compiler that can't see into a function would have no way of knowing what combinations of arguments would be valid or invalid.

Cardiff answered 17/5, 2017 at 20:34 Comment(6)
union { struct { char d; int e; } f; int g } h and test(&h.f.e, &h.g, 0) is a convoluted scenario that can be affected, even when test parameters a==b+c is not true.Accomplishment
@chux: Section 6.5p7 of the N1570 draft Standard refrains (IMHO deliberately) from granting blanket permission to access an aggregate using arbitrary lvalues of member type, with or without restrict. This makes sense iff accesses via an lvalue derived from an aggregate are sometimes recognized (for purposes of 6.5p7) as being performed via the aggregate type rather than the member type. Since the Standard doesn't say when implementations should recognize such association, that is presumably a Quality of Implementation issue.Cardiff
@chux: The code as written would clearly invoke UB in the case you describe, since operations on a[0] and b[c] are only sequenced when b[c] and a[0] identify the same complete object, rather than two partially-overlapping objects. If test were changed to int temp[b]c[; a[0]+=temp;, such code may or may not be defined depending upon whether an operation on heap storage using an lvalue derived from an aggregate is viewed as setting the Effective Type based purely upon the derived type or the aggregate type.Cardiff
Current practice seems to be that operations on heap storage via lvalues derived from an aggregate are at least sometimes regarded for purposes of the Effective Type rules as though they were performed using the aggregate type; given the lack of blanket permission to access aggregates via member-type lvalues, I don't think the Standard would impose any requirements upon the behavior of the code in any "overlap" scenarios.Cardiff
restrict implications are difficult to summarize definitively. Thanks for the info.Accomplishment
@chux: The implications of 6.5p7 are much harder to characterize. The only interpretation that makes sense is that the authors viewed significant aspects of 6.5p7 as a "quality of implementation" issue, and didn't think it necessary to prohibit garbage-quality-but-conforming implementations from processing most practical programs in nonsensical fashion.Cardiff
F
2

The restrict keyword is an explicit assurance from the programmer that the pointers in question don't alias. In essence, it allows the compiler to omit alias analysis for those pointers, because the programmer has already provided the presumed answer. In addition to enabling better optimization, this can also save compilation time. In large programs, analysis can be quite expensive, so that's potentially a big deal in its own right.

So, the answer to your question is, I believe, "the compilers aren't looking, because the code tells them not to bother"

Forwarder answered 5/6, 2015 at 0:12 Comment(1)
This doesn't really answer my question. I'd expect the compiler to give me warnings when programming errors are easy to detect.Formicary

© 2022 - 2024 — McMap. All rights reserved.