In Fortran one can specify the intent of variables thus if all arguments have INTENT(IN) then GCC should be able to detect that alist in the call to cshift is uninitialized. This depends on the middle end support of intents (PR31094) plus using these in gfortran. Example (using an intrinsic function): program testcshft integer :: alist(4) alist =cshift(alist,-1) write(*,*) alist end program testcshft
Confirmed.
Still no warning at revision 200371.
Several(?) C duplicates exist which implicitely suggest a similar attribute. void bar (int *); void foo () { int i; bar (&i); } if we can annotate the first arg of 'bar' as "intent in" (aka, should be fully(!) initialized) then we can warn on this use.
I have implemented three attributes: read_only, read_write, and write_only. They take two arguments: one refers to the pointer function parameter and the other to the size of the object the pointer points to. See bug 83859. Besides warning, they can also be used for optimization. I'm hoping to submit the feature for GCC 10.
The C family patch: https://gcc.gnu.org/ml/gcc-patches/2019-09/msg01690.html
In conjunction with attribute access (read_only) (which I presume is the moral equivalent of INTENT(IN)), the patch I submitted for pr10138 puts in place the infrastructure to implement this warning for FORTRAN as well. All that it should need is mapping INTENT(IN) to the attribute. https://gcc.gnu.org/pipermail/gcc-patches/2020-May/545856.html
GCC added the attributes mentioned in comment #4 under the name access -- see below. Getting the middle end to issue a warning for the cases described in comment #0 should be a matter of the Fortran front end making use of the attribute. $ cat x.c && gcc -S -Wall x.c __attribute__ ((access (read_only, 1))) void f (int*); void g (void) { int x; f (&x); } x.c: In function ‘g’: x.c:6:3: warning: ‘x’ is used uninitialized [-Wuninitialized] 6 | f (&x); | ^~~~~~ x.c:1:46: note: in a call to ‘f’ declared with attribute ‘access (read_only, 1)’ here 1 | __attribute__ ((access (read_only, 1))) void f (int*); | ^ x.c:5:7: note: ‘x’ declared here 5 | int x; | ^
The original testcase hides everything behind array descriptors, even with unrolling and vectorization disabled we end up with <bb 2> [local count: 214748368]: parm.0.data = &alist[0]; parm.0.offset = -1; parm.0.dtype.elem_len = 4; MEM <unsigned long> [(void *)&parm.0 + 24B] = 1103806595072; parm.0.span = 4; parm.0.dim[0].stride = 1; parm.0.dim[0].lbound = 1; parm.0.dim[0].ubound = 4; atmp.1.data = &A.2; atmp.1.offset = 0; atmp.1.dtype.elem_len = 4; MEM <unsigned long> [(void *)&atmp.1 + 24B] = 1103806595072; atmp.1.span = 4; atmp.1.dim[0].stride = 1; atmp.1.dim[0].lbound = 0; atmp.1.dim[0].ubound = 3; _gfortran_cshift0_4 (&atmp.1, &parm.0, &C.4234, 0B); the frontend might set the fnspec correctly to r (read-only, even transitively) which we might use here but then the actual use is the intrinsic and the fnspec does not say that the function acrually reads from the uninitialized storage.