+ wi->is_lhs = false;
+ }
+ break;
+ }
+
+ return NULL_TREE;
+}
+
+static tree convert_nonlocal_reference_stmt (gimple_stmt_iterator *, bool *,
+ struct walk_stmt_info *);
+
+/* Helper for convert_nonlocal_references, rewrite all references to VAR
+ and PARM_DECLs that belong to outer functions. */
+
+static bool
+convert_nonlocal_omp_clauses (tree *pclauses, struct walk_stmt_info *wi)
+{
+ struct nesting_info *const info = (struct nesting_info *) wi->info;
+ bool need_chain = false, need_stmts = false;
+ tree clause, decl;
+ int dummy;
+ bitmap new_suppress;
+
+ new_suppress = BITMAP_GGC_ALLOC ();
+ bitmap_copy (new_suppress, info->suppress_expansion);
+
+ for (clause = *pclauses; clause ; clause = OMP_CLAUSE_CHAIN (clause))
+ {
+ switch (OMP_CLAUSE_CODE (clause))
+ {
+ case OMP_CLAUSE_REDUCTION:
+ if (OMP_CLAUSE_REDUCTION_PLACEHOLDER (clause))
+ need_stmts = true;
+ goto do_decl_clause;
+
+ case OMP_CLAUSE_LASTPRIVATE:
+ if (OMP_CLAUSE_LASTPRIVATE_GIMPLE_SEQ (clause))
+ need_stmts = true;
+ goto do_decl_clause;
+
+ case OMP_CLAUSE_PRIVATE:
+ case OMP_CLAUSE_FIRSTPRIVATE:
+ case OMP_CLAUSE_COPYPRIVATE:
+ case OMP_CLAUSE_SHARED:
+ do_decl_clause:
+ decl = OMP_CLAUSE_DECL (clause);
+ if (TREE_CODE (decl) == VAR_DECL
+ && (TREE_STATIC (decl) || DECL_EXTERNAL (decl)))
+ break;
+ if (decl_function_context (decl) != info->context)
+ {
+ bitmap_set_bit (new_suppress, DECL_UID (decl));
+ OMP_CLAUSE_DECL (clause) = get_nonlocal_debug_decl (info, decl);
+ need_chain = true;
+ }
+ break;
+
+ case OMP_CLAUSE_SCHEDULE:
+ if (OMP_CLAUSE_SCHEDULE_CHUNK_EXPR (clause) == NULL)
+ break;
+ /* FALLTHRU */
+ case OMP_CLAUSE_IF:
+ case OMP_CLAUSE_NUM_THREADS:
+ wi->val_only = true;
+ wi->is_lhs = false;
+ convert_nonlocal_reference_op (&OMP_CLAUSE_OPERAND (clause, 0),
+ &dummy, wi);
+ break;
+
+ case OMP_CLAUSE_NOWAIT:
+ case OMP_CLAUSE_ORDERED:
+ case OMP_CLAUSE_DEFAULT:
+ case OMP_CLAUSE_COPYIN:
+ case OMP_CLAUSE_COLLAPSE:
+ case OMP_CLAUSE_UNTIED:
+ break;
+
+ default:
+ gcc_unreachable ();
+ }
+ }
+
+ info->suppress_expansion = new_suppress;
+
+ if (need_stmts)
+ for (clause = *pclauses; clause ; clause = OMP_CLAUSE_CHAIN (clause))
+ switch (OMP_CLAUSE_CODE (clause))
+ {
+ case OMP_CLAUSE_REDUCTION:
+ if (OMP_CLAUSE_REDUCTION_PLACEHOLDER (clause))
+ {
+ tree old_context
+ = DECL_CONTEXT (OMP_CLAUSE_REDUCTION_PLACEHOLDER (clause));
+ DECL_CONTEXT (OMP_CLAUSE_REDUCTION_PLACEHOLDER (clause))
+ = info->context;
+ walk_body (convert_nonlocal_reference_stmt,
+ convert_nonlocal_reference_op, info,
+ OMP_CLAUSE_REDUCTION_GIMPLE_INIT (clause));
+ walk_body (convert_nonlocal_reference_stmt,
+ convert_nonlocal_reference_op, info,
+ OMP_CLAUSE_REDUCTION_GIMPLE_MERGE (clause));
+ DECL_CONTEXT (OMP_CLAUSE_REDUCTION_PLACEHOLDER (clause))
+ = old_context;
+ }
+ break;
+
+ case OMP_CLAUSE_LASTPRIVATE:
+ walk_body (convert_nonlocal_reference_stmt,
+ convert_nonlocal_reference_op, info,
+ OMP_CLAUSE_LASTPRIVATE_GIMPLE_SEQ (clause));
+ break;
+
+ default:
+ break;
+ }
+
+ return need_chain;
+}
+
+
+/* Callback for walk_gimple_stmt. Rewrite all references to VAR and
+ PARM_DECLs that belong to outer functions. This handles statements
+ that are not handled via the standard recursion done in
+ walk_gimple_stmt. STMT is the statement to examine, DATA is as in
+ convert_nonlocal_reference_op. Set *HANDLED_OPS_P to true if all the
+ operands of STMT have been handled by this function. */
+
+static tree
+convert_nonlocal_reference_stmt (gimple_stmt_iterator *gsi, bool *handled_ops_p,
+ struct walk_stmt_info *wi)
+{
+ struct nesting_info *info = (struct nesting_info *) wi->info;
+ tree save_local_var_chain;
+ bitmap save_suppress;
+ gimple stmt = gsi_stmt (*gsi);
+
+ switch (gimple_code (stmt))
+ {
+ case GIMPLE_GOTO:
+ /* Don't walk non-local gotos for now. */
+ if (TREE_CODE (gimple_goto_dest (stmt)) != LABEL_DECL)
+ {
+ wi->val_only = true;
+ wi->is_lhs = false;
+ *handled_ops_p = true;
+ return NULL_TREE;
+ }
+ break;
+
+ case GIMPLE_OMP_PARALLEL:
+ case GIMPLE_OMP_TASK:
+ save_suppress = info->suppress_expansion;
+ if (convert_nonlocal_omp_clauses (gimple_omp_taskreg_clauses_ptr (stmt),
+ wi))
+ {
+ tree c, decl;
+ decl = get_chain_decl (info);
+ c = build_omp_clause (OMP_CLAUSE_FIRSTPRIVATE);
+ OMP_CLAUSE_DECL (c) = decl;
+ OMP_CLAUSE_CHAIN (c) = gimple_omp_taskreg_clauses (stmt);
+ gimple_omp_taskreg_set_clauses (stmt, c);