https://gcc.gnu.org/bugzilla/show_bug.cgi?id=89651
--- Comment #3 from Jakub Jelinek <jakub at gcc dot gnu.org> --- t is privatized and the emitted code looks just fine to me. The standard says for privatization clauses: For a list item or the subobject of a list item with the ALLOCATABLE attribute: - if the allocation status is “not currently allocated”, the new list item or the subobject of the new list item will have an initial allocation status of "not currently allocated". - if the allocation status is “currently allocated”, the new list item or the subobject of the new list item will have an initial allocation status of "currently allocated". - If the new list item or the subobject of the new list item is an array, its bounds will be the same as those of the original list item or the subobject of the original list item. and that is what GCC implements. If you e.g. look at omplower dump, there is: D.3953 = .omp_data_i->t; D.3954 = D.3953->data; if (D.3954 != 0B) goto <D.3955>; else goto <D.3956>; <D.3955>: D.3953 = .omp_data_i->t; t = *D.3953; D.3957 = t.dim[0].ubound; D.3958 = t.dim[0].lbound; D.3959 = D.3957 - D.3958; D.3960 = D.3959 + 1; D.3961 = D.3960 * 4; D.3951 = (unsigned long) D.3961; D.3962 = MAX_EXPR <D.3951, 1>; D.3952 = __builtin_malloc (D.3962); D.3963 = D.3952 == 0B; D.3964 = (integer(kind=8)) D.3963; D.3965 = .BUILTIN_EXPECT (D.3964, 0, 42); D.3966 = (logical(kind=1)) D.3965; if (D.3966 != 0) goto <D.3967>; else goto <D.3968>; <D.3967>: _gfortran_os_error (&"Allocation would exceed memory limit"[1]{lb: 1 sz: 1}); <D.3968>: t.data = D.3952; goto <D.3969>; <D.3956>: t.data = 0B; <D.3969>: where *.omp_data_i->t is the descriptor of the original t and t being assigned is the privatized t. If the original t is not allocated, then we only clear t.data and leave the rest uninitialized, exactly like if in the testcase you comment out the allocate and !$omp lines. If t is allocated, then everything is copied and new array allocated. To shut up the warning, we could e.g. do: D.3953 = .omp_data_i->t; t = *D.3953; unconditionally instead of conditionally, but it would be a wasteful at runtime for the case when the original var is not allocated, copying 64 bytes that won't be really needed. Another option (best) would be to propagate from the outer to inner outlined OpenMP regions information like that .omp_data_i->t.data is non-NULL etc.; while we should improve the IPA opts on the boundary of OpenMP regions and pass stuff like VRP info etc. down, I'm afraid because this is a pointer inside a large struct and we don't really do VRP or bitwise ccp, alignment info etc. for aggregate elts unless SRA optimized, this won't happen any time soon. So yet another option would be to set TREE_NO_WARNING here on the privatized variable.