'The following shenanigans are instated when we break, return or
propagate errors from a prange. In this case we cannot rely on
lastprivate() to do its job, as no iterations may have executed yet
in the last thread, leaving the values undefined. It is most likely
that the breaking thread has well-defined values of the lastprivate
variables, so we keep those values.'

def save_parallel_vars(self, code):

    section_name = ('__pyx_parallel_lastprivates%d' % self.critical_section_counter)
    code.putln_openmp(('#pragma    omp    critical(%s)' % section_name))
    ParallelStatNode.critical_section_counter += 1
    code.begin_block()
    c = self.begin_of_parallel_control_block_point
    temp_count = 0
    for (entry, (op, lastprivate)) in sorted(self.privates.items()):
        if ((not lastprivate) or entry.type.is_pyobject):
            continue
        type_decl = entry.type.empty_declaration_code()
        temp_cname = ('__pyx_parallel_temp%d' % temp_count)
        private_cname = entry.cname
        temp_count += 1
        invalid_value = entry.type.invalid_value()
        if invalid_value:
            init = ('    =    ' + entry.type.cast_code(invalid_value))
        else:
            init = ''
        c.putln(('%s    %s%s;' % (type_decl, temp_cname, init)))
        code.putln(('%s    =    %s;' % (temp_cname, private_cname)))
        self.parallel_private_temps.append((temp_cname, private_cname))
    code.end_block()
