'Propagate the sharing attributes of a variable. If the privatization is
determined by a parent scope, done propagate further.
If we are a prange, we propagate our sharing attributes outwards to
other pranges. If we are a prange in parallel block and the parallel
block does not determine the variable private, we propagate to the
parent of the parent. Recursion stops at parallel blocks, as they have
no concept of lastprivate or reduction.
So the following cases propagate:
sum is a reduction for all loops:
for i in prange(n):
for j in prange(n):
for k in prange(n):
sum += i * j * k
sum is a reduction for both loops, local_var is private to the
parallel with block:
for i in prange(n):
with parallel:
local_var = ... # private to the parallel
for j in prange(n):
sum += i * j
Nested with parallel blocks are disallowed, because they wouldn\'t
allow you to propagate lastprivates or reductions:
#pragma omp parallel for lastprivate(i)
for i in prange(n):
sum = 0
#pragma omp parallel private(j, sum)
with parallel:
#pragma omp parallel
with parallel:
#pragma omp for lastprivate(j) reduction(+:sum)
for j in prange(n):
sum += i
# sum and j are well-defined here
# sum and j are undefined here
# sum and j are undefined here'

def propagate_var_privatization(self, entry, pos, op, lastprivate):

    self.privates[entry] = (op, lastprivate)
    if entry.type.is_memoryviewslice:
        error(pos, 'Memoryview    slices    can    only    be    shared    in    parallel    sections')
        return
    if self.is_prange:
        if ((not self.is_parallel) and (entry not in self.parent.assignments)):
            parent = self.parent.parent
        else:
            parent = self.parent
        if (parent and (op or lastprivate)):
            parent.propagate_var_privatization(entry, pos, op, lastprivate)
