enum omp_clause_default_kind cxx_omp_predetermined_sharing (tree decl) { tree type; /* Static data members are predetermined as shared. */ if (TREE_STATIC (decl)) { tree ctx = CP_DECL_CONTEXT (decl); if (TYPE_P (ctx) && MAYBE_CLASS_TYPE_P (ctx)) return OMP_CLAUSE_DEFAULT_SHARED; } type = TREE_TYPE (decl); if (TREE_CODE (type) == REFERENCE_TYPE) { if (!is_invisiref_parm (decl)) return OMP_CLAUSE_DEFAULT_UNSPECIFIED; type = TREE_TYPE (type); if (TREE_CODE (decl) == RESULT_DECL && DECL_NAME (decl)) { /* NVR doesn't preserve const qualification of the variable's type. */ tree outer = outer_curly_brace_block (current_function_decl); tree var; if (outer) for (var = BLOCK_VARS (outer); var; var = TREE_CHAIN (var)) if (DECL_NAME (decl) == DECL_NAME (var) && (TYPE_MAIN_VARIANT (type) == TYPE_MAIN_VARIANT (TREE_TYPE (var)))) { if (TYPE_READONLY (TREE_TYPE (var))) type = TREE_TYPE (var); break; } } } if (type == error_mark_node) return OMP_CLAUSE_DEFAULT_UNSPECIFIED; /* Variables with const-qualified type having no mutable member are predetermined shared. */ if (TYPE_READONLY (type) && !cp_has_mutable_p (type)) return OMP_CLAUSE_DEFAULT_SHARED; return OMP_CLAUSE_DEFAULT_UNSPECIFIED; }
/* Return true if DECL is const qualified var having no mutable member. */ bool cxx_omp_const_qual_no_mutable (tree decl) { tree type = TREE_TYPE (decl); if (TREE_CODE (type) == REFERENCE_TYPE) { if (!is_invisiref_parm (decl)) return false; type = TREE_TYPE (type); if (TREE_CODE (decl) == RESULT_DECL && DECL_NAME (decl)) { /* NVR doesn't preserve const qualification of the variable's type. */ tree outer = outer_curly_brace_block (current_function_decl); tree var; if (outer) for (var = BLOCK_VARS (outer); var; var = DECL_CHAIN (var)) if (DECL_NAME (decl) == DECL_NAME (var) && (TYPE_MAIN_VARIANT (type) == TYPE_MAIN_VARIANT (TREE_TYPE (var)))) { if (TYPE_READONLY (TREE_TYPE (var))) type = TREE_TYPE (var); break; } } } if (type == error_mark_node) return false; /* Variables with const-qualified type having no mutable member are predetermined shared. */ if (TYPE_READONLY (type) && !cp_has_mutable_p (type)) return true; return false; }
void gcc_cp_genericize (tree fndecl) { register_src_file(fndecl); tree t; struct cp_genericize_data wtd; /* Fix up the types of parms passed by invisible reference. */ for (t = DECL_ARGUMENTS (fndecl); t; t = DECL_CHAIN (t)) if (TREE_ADDRESSABLE (TREE_TYPE (t))) { /* If a function's arguments are copied to create a thunk, then DECL_BY_REFERENCE will be set -- but the type of the argument will be a pointer type, so we will never get here. */ gcc_assert (!DECL_BY_REFERENCE (t)); gcc_assert (DECL_ARG_TYPE (t) != TREE_TYPE (t)); TREE_TYPE (t) = DECL_ARG_TYPE (t); DECL_BY_REFERENCE (t) = 1; TREE_ADDRESSABLE (t) = 0; relayout_decl (t); } /* Do the same for the return value. */ if (TREE_ADDRESSABLE (TREE_TYPE (DECL_RESULT (fndecl)))) { t = DECL_RESULT (fndecl); TREE_TYPE (t) = build_reference_type (TREE_TYPE (t)); DECL_BY_REFERENCE (t) = 1; TREE_ADDRESSABLE (t) = 0; relayout_decl (t); if (DECL_NAME (t)) { /* Adjust DECL_VALUE_EXPR of the original var. */ tree outer = outer_curly_brace_block (current_function_decl); tree var; if (outer) for (var = BLOCK_VARS (outer); var; var = DECL_CHAIN (var)) if (DECL_NAME (t) == DECL_NAME (var) && DECL_HAS_VALUE_EXPR_P (var) && DECL_VALUE_EXPR (var) == t) { tree val = convert_from_reference (t); SET_DECL_VALUE_EXPR (var, val); break; } } } /* If we're a clone, the body is already GIMPLE. */ if (DECL_CLONED_FUNCTION_P (fndecl)) return; /* We do want to see every occurrence of the parms, so we can't just use walk_tree's hash functionality. */ wtd.p_set = pointer_set_create (); wtd.bind_expr_stack = NULL; cp_walk_tree (&DECL_SAVED_TREE (fndecl), cp_genericize_r, &wtd, NULL); pointer_set_destroy (wtd.p_set); VEC_free (tree, heap, wtd.bind_expr_stack); /* Do everything else. */ gcc_genericize (fndecl); gcc_assert (bc_label[bc_break] == NULL); gcc_assert (bc_label[bc_continue] == NULL); }
void cp_genericize (tree fndecl) { tree t; /* Fix up the types of parms passed by invisible reference. */ for (t = DECL_ARGUMENTS (fndecl); t; t = DECL_CHAIN (t)) if (TREE_ADDRESSABLE (TREE_TYPE (t))) { /* If a function's arguments are copied to create a thunk, then DECL_BY_REFERENCE will be set -- but the type of the argument will be a pointer type, so we will never get here. */ gcc_assert (!DECL_BY_REFERENCE (t)); gcc_assert (DECL_ARG_TYPE (t) != TREE_TYPE (t)); TREE_TYPE (t) = DECL_ARG_TYPE (t); DECL_BY_REFERENCE (t) = 1; TREE_ADDRESSABLE (t) = 0; relayout_decl (t); } /* Do the same for the return value. */ if (TREE_ADDRESSABLE (TREE_TYPE (DECL_RESULT (fndecl)))) { t = DECL_RESULT (fndecl); TREE_TYPE (t) = build_reference_type (TREE_TYPE (t)); DECL_BY_REFERENCE (t) = 1; TREE_ADDRESSABLE (t) = 0; relayout_decl (t); if (DECL_NAME (t)) { /* Adjust DECL_VALUE_EXPR of the original var. */ tree outer = outer_curly_brace_block (current_function_decl); tree var; if (outer) for (var = BLOCK_VARS (outer); var; var = DECL_CHAIN (var)) if (DECL_NAME (t) == DECL_NAME (var) && DECL_HAS_VALUE_EXPR_P (var) && DECL_VALUE_EXPR (var) == t) { tree val = convert_from_reference (t); SET_DECL_VALUE_EXPR (var, val); break; } } } /* If we're a clone, the body is already GIMPLE. */ if (DECL_CLONED_FUNCTION_P (fndecl)) return; /* Expand all the array notations here. */ if (flag_enable_cilkplus && contains_array_notation_expr (DECL_SAVED_TREE (fndecl))) DECL_SAVED_TREE (fndecl) = expand_array_notation_exprs (DECL_SAVED_TREE (fndecl)); /* We do want to see every occurrence of the parms, so we can't just use walk_tree's hash functionality. */ cp_genericize_tree (&DECL_SAVED_TREE (fndecl)); if (flag_sanitize & SANITIZE_RETURN) cp_ubsan_maybe_instrument_return (fndecl); /* Do everything else. */ c_genericize (fndecl); gcc_assert (bc_label[bc_break] == NULL); gcc_assert (bc_label[bc_continue] == NULL); }