* gimplify.c (nonlocal_vlas): Delete.
(nonlocal_vla_vars): Likewise.
(gimplify_var_or_parm_decl): Do not add debug VAR_DECLs for non-local
referenced VLAs.
(gimplify_body): Do not create and destroy nonlocal_vlas.
* tree-nested.c: Include diagnostic.h.
(use_pointer_in_frame): Tweak.
(lookup_field_for_decl): Add assertion and declare the transformation.
(convert_nonlocal_reference_op) <PARM_DECL>: Rework and issue an
internal error when the reference is in a wrong context. Do not
create a debug decl by default.
(note_nonlocal_block_vlas): Delete.
(convert_nonlocal_reference_stmt) <GIMPLE_BIND>: Do not call it.
(convert_local_reference_op) <PARM_DECL>: Skip the frame decl. Do not
create a debug decl by default.
(convert_gimple_call) <GIMPLE_CALL>: Issue an internal error when the
call is in a wrong context.
(fixup_vla_decls): New function.
(finalize_nesting_tree_1): Adjust comment. Call fixup_vla_decls if no
debug variables were created.
* tree.c (decl_value_expr_lookup): Add checking assertion.
(decl_value_expr_insert): Likewise.
fortran/
* fortran/trans-decl.c (nonlocal_dummy_decl_pset): Delete.
(nonlocal_dummy_decls): Likewise.
(gfc_nonlocal_dummy_array_decl): Likewise.
(gfc_get_symbol_decl): Do not call gfc_nonlocal_dummy_array_decl.
(gfc_get_fake_result_decl): Do not generate a new DECL if simply
reusing the result of a recursive call.
(gfc_generate_function_code): Do not create, insert and destroy
nonlocal_dummy_decls.
From-SVN: r261687
+2018-06-17 Eric Botcazou <ebotcazou@adacore.com>
+
+ * gimplify.c (nonlocal_vlas): Delete.
+ (nonlocal_vla_vars): Likewise.
+ (gimplify_var_or_parm_decl): Do not add debug VAR_DECLs for non-local
+ referenced VLAs.
+ (gimplify_body): Do not create and destroy nonlocal_vlas.
+ * tree-nested.c: Include diagnostic.h.
+ (use_pointer_in_frame): Tweak.
+ (lookup_field_for_decl): Add assertion and declare the transformation.
+ (convert_nonlocal_reference_op) <PARM_DECL>: Rework and issue an
+ internal error when the reference is in a wrong context. Do not
+ create a debug decl by default.
+ (note_nonlocal_block_vlas): Delete.
+ (convert_nonlocal_reference_stmt) <GIMPLE_BIND>: Do not call it.
+ (convert_local_reference_op) <PARM_DECL>: Skip the frame decl. Do not
+ create a debug decl by default.
+ (convert_gimple_call) <GIMPLE_CALL>: Issue an internal error when the
+ call is in a wrong context.
+ (fixup_vla_decls): New function.
+ (finalize_nesting_tree_1): Adjust comment. Call fixup_vla_decls if no
+ debug variables were created.
+ * tree.c (decl_value_expr_lookup): Add checking assertion.
+ (decl_value_expr_insert): Likewise.
+
2018-06-16 Kugan Vivekanandarajah <kuganv@linaro.org>
PR middle-end/82479
+2018-06-17 Eric Botcazou <ebotcazou@adacore.com>
+
+ * fortran/trans-decl.c (nonlocal_dummy_decl_pset): Delete.
+ (nonlocal_dummy_decls): Likewise.
+ (gfc_nonlocal_dummy_array_decl): Likewise.
+ (gfc_get_symbol_decl): Do not call gfc_nonlocal_dummy_array_decl.
+ (gfc_get_fake_result_decl): Do not generate a new DECL if simply
+ reusing the result of a recursive call.
+ (gfc_generate_function_code): Do not create, insert and destroy
+ nonlocal_dummy_decls.
+
2018-06-13 Steven G. Kargl <kargl@gcc.gnu.org>
PR fortran/86110
static GTY(()) tree saved_function_decls;
static GTY(()) tree saved_parent_function_decls;
-static hash_set<tree> *nonlocal_dummy_decl_pset;
-static GTY(()) tree nonlocal_dummy_decls;
-
/* Holds the variable DECLs that are locals. */
static GTY(()) tree saved_local_decls;
return decl;
}
-/* For symbol SYM with GFC_DECL_SAVED_DESCRIPTOR used in contained
- function add a VAR_DECL to the current function with DECL_VALUE_EXPR
- pointing to the artificial variable for debug info purposes. */
-
-static void
-gfc_nonlocal_dummy_array_decl (gfc_symbol *sym)
-{
- tree decl, dummy;
-
- if (! nonlocal_dummy_decl_pset)
- nonlocal_dummy_decl_pset = new hash_set<tree>;
-
- if (nonlocal_dummy_decl_pset->add (sym->backend_decl))
- return;
-
- dummy = GFC_DECL_SAVED_DESCRIPTOR (sym->backend_decl);
- decl = build_decl (input_location, VAR_DECL, DECL_NAME (dummy),
- TREE_TYPE (sym->backend_decl));
- DECL_ARTIFICIAL (decl) = 0;
- TREE_USED (decl) = 1;
- TREE_PUBLIC (decl) = 0;
- TREE_STATIC (decl) = 0;
- DECL_EXTERNAL (decl) = 0;
- if (DECL_BY_REFERENCE (dummy))
- DECL_BY_REFERENCE (decl) = 1;
- DECL_LANG_SPECIFIC (decl) = DECL_LANG_SPECIFIC (sym->backend_decl);
- SET_DECL_VALUE_EXPR (decl, sym->backend_decl);
- DECL_HAS_VALUE_EXPR_P (decl) = 1;
- DECL_CONTEXT (decl) = DECL_CONTEXT (sym->backend_decl);
- DECL_CHAIN (decl) = nonlocal_dummy_decls;
- nonlocal_dummy_decls = decl;
-}
-
/* Return a constant or a variable to use as a string length. Does not
add the decl to the current scope. */
gfc_add_assign_aux_vars (sym);
}
- if ((sym->attr.dimension || IS_CLASS_ARRAY (sym))
- && DECL_LANG_SPECIFIC (sym->backend_decl)
- && GFC_DECL_SAVED_DESCRIPTOR (sym->backend_decl)
- && DECL_CONTEXT (sym->backend_decl) != current_function_decl)
- gfc_nonlocal_dummy_array_decl (sym);
-
if (sym->ts.type == BT_CLASS && sym->backend_decl)
GFC_DECL_CLASS(sym->backend_decl) = 1;
&& sym->ns->proc_name->attr.entry_master
&& sym != sym->ns->proc_name)
{
- tree t = NULL, var;
+ tree t = NULL, var, field;
if (this_fake_result_decl != NULL)
for (t = TREE_CHAIN (this_fake_result_decl); t; t = TREE_CHAIN (t))
if (strcmp (IDENTIFIER_POINTER (TREE_PURPOSE (t)), sym->name) == 0)
break;
if (t)
return TREE_VALUE (t);
+
decl = gfc_get_fake_result_decl (sym->ns->proc_name, parent_flag);
if (parent_flag)
else
this_fake_result_decl = current_fake_result_decl;
- if (decl && sym->ns->proc_name->attr.mixed_entry_master)
- {
- tree field;
+ if (!sym->ns->proc_name->attr.mixed_entry_master)
+ return decl;
- for (field = TYPE_FIELDS (TREE_TYPE (decl));
- field; field = DECL_CHAIN (field))
- if (strcmp (IDENTIFIER_POINTER (DECL_NAME (field)),
- sym->name) == 0)
- break;
+ for (field = TYPE_FIELDS (TREE_TYPE (decl));
+ field; field = DECL_CHAIN (field))
+ if (strcmp (IDENTIFIER_POINTER (DECL_NAME (field)), sym->name) == 0)
+ break;
- gcc_assert (field != NULL_TREE);
- decl = fold_build3_loc (input_location, COMPONENT_REF,
- TREE_TYPE (field), decl, field, NULL_TREE);
- }
+ gcc_assert (field != NULL_TREE);
+ decl = fold_build3_loc (input_location, COMPONENT_REF,
+ TREE_TYPE (field), decl, field, NULL_TREE);
var = create_tmp_var_raw (TREE_TYPE (decl), sym->name);
if (parent_flag)
gfc_generate_contained_functions (ns);
- nonlocal_dummy_decls = NULL;
- nonlocal_dummy_decl_pset = NULL;
-
has_coarray_vars = false;
generate_local_vars (ns);
= build3_v (BIND_EXPR, decl, DECL_SAVED_TREE (fndecl),
DECL_INITIAL (fndecl));
- if (nonlocal_dummy_decls)
- {
- BLOCK_VARS (DECL_INITIAL (fndecl))
- = chainon (BLOCK_VARS (DECL_INITIAL (fndecl)), nonlocal_dummy_decls);
- delete nonlocal_dummy_decl_pset;
- nonlocal_dummy_decls = NULL;
- nonlocal_dummy_decl_pset = NULL;
- }
-
/* Output the GENERIC tree. */
dump_function (TDI_original, fndecl);
return GS_OK;
}
-/* Nonlocal VLAs seen in the current function. */
-static hash_set<tree> *nonlocal_vlas;
-
-/* The VAR_DECLs created for nonlocal VLAs for debug info purposes. */
-static tree nonlocal_vla_vars;
-
/* Gimplify a VAR_DECL or PARM_DECL. Return GS_OK if we expanded a
DECL_VALUE_EXPR, and it's worth re-examining things. */
/* If the decl is an alias for another expression, substitute it now. */
if (DECL_HAS_VALUE_EXPR_P (decl))
{
- tree value_expr = DECL_VALUE_EXPR (decl);
-
- /* For referenced nonlocal VLAs add a decl for debugging purposes
- to the current function. */
- if (VAR_P (decl)
- && TREE_CODE (DECL_SIZE_UNIT (decl)) != INTEGER_CST
- && nonlocal_vlas != NULL
- && TREE_CODE (value_expr) == INDIRECT_REF
- && TREE_CODE (TREE_OPERAND (value_expr, 0)) == VAR_DECL
- && decl_function_context (decl) != current_function_decl)
- {
- struct gimplify_omp_ctx *ctx = gimplify_omp_ctxp;
- while (ctx
- && (ctx->region_type == ORT_WORKSHARE
- || ctx->region_type == ORT_SIMD
- || ctx->region_type == ORT_ACC))
- ctx = ctx->outer_context;
- if (!ctx && !nonlocal_vlas->add (decl))
- {
- tree copy = copy_node (decl);
-
- lang_hooks.dup_lang_specific_decl (copy);
- SET_DECL_RTL (copy, 0);
- TREE_USED (copy) = 1;
- DECL_CHAIN (copy) = nonlocal_vla_vars;
- nonlocal_vla_vars = copy;
- SET_DECL_VALUE_EXPR (copy, unshare_expr (value_expr));
- DECL_HAS_VALUE_EXPR_P (copy) = 1;
- }
- }
-
- *expr_p = unshare_expr (value_expr);
+ *expr_p = unshare_expr (DECL_VALUE_EXPR (decl));
return GS_OK;
}
gimple_seq parm_stmts, parm_cleanup = NULL, seq;
gimple *outer_stmt;
gbind *outer_bind;
- struct cgraph_node *cgn;
timevar_push (TV_TREE_GIMPLIFY);
unshare_body (fndecl);
unvisit_body (fndecl);
- cgn = cgraph_node::get (fndecl);
- if (cgn && cgn->origin)
- nonlocal_vlas = new hash_set<tree>;
-
/* Make sure input_location isn't set to something weird. */
input_location = DECL_SOURCE_LOCATION (fndecl);
}
}
- if (nonlocal_vlas)
- {
- if (nonlocal_vla_vars)
- {
- /* tree-nested.c may later on call declare_vars (..., true);
- which relies on BLOCK_VARS chain to be the tail of the
- gimple_bind_vars chain. Ensure we don't violate that
- assumption. */
- if (gimple_bind_block (outer_bind)
- == DECL_INITIAL (current_function_decl))
- declare_vars (nonlocal_vla_vars, outer_bind, true);
- else
- BLOCK_VARS (DECL_INITIAL (current_function_decl))
- = chainon (BLOCK_VARS (DECL_INITIAL (current_function_decl)),
- nonlocal_vla_vars);
- nonlocal_vla_vars = NULL_TREE;
- }
- delete nonlocal_vlas;
- nonlocal_vlas = NULL;
- }
-
if ((flag_openacc || flag_openmp || flag_openmp_simd)
&& gimplify_omp_ctxp)
{
+2018-06-17 Eric Botcazou <ebotcazou@adacore.com>
+
+ * gcc.dg/debug/dwarf2/pr37726.c: Move to...
+ * gcc.dg/guality/pr37726.c: ...here and turn into GDB test.
+ * gnat.dg/stack_usage5.adb: New test.
+
2018-06-16 Kugan Vivekanandarajah <kuganv@linaro.org>
PR middle-end/82479
+++ /dev/null
-/* PR debug/37726 */
-/* { dg-do compile } */
-/* { dg-options "-gdwarf -O0 -dA -fno-merge-debug-strings" } */
-
-int foo (int parm)
-{
- int var = 0;
- int bar (void)
- {
- return parm + var;
- }
- parm++;
- var++;
- return bar ();
-}
-
-int
-main (void)
-{
- return foo (4) - 6;
-}
-
-/* Both parm and var variables should be in debug info for both foo and bar. */
-/* { dg-final { scan-assembler-times "\"parm\[^\n\]*\"\[^\n\]*DW_AT_name" 2 } } */
-/* { dg-final { scan-assembler-times "\"var\[^\n\]*\"\[^\n\]*DW_AT_name" 2 } } */
--- /dev/null
+/* PR debug/37726 */
+/* { dg-do run } */
+/* { dg-options "-g" } */
+/* { dg-skip-if "" { *-*-* } { "*" } { "-O0" } } */
+
+int foo (int parm)
+{
+ int var = 0;
+ int bar (void)
+ {
+ return parm + var; /* BREAK */
+ }
+ parm++; /* BREAK */
+ var++;
+ return bar ();
+}
+
+int
+main (void)
+{
+ return foo (4) - 6;
+}
+
+/* { dg-final { gdb-test 11 "parm" "5" } } */
+/* { dg-final { gdb-test 11 "var" "1" } } */
+/* { dg-final { gdb-test 13 "parm" "4" } } */
+/* { dg-final { gdb-test 13 "var" "0" } } */
--- /dev/null
+-- { dg-do compile }
+-- { dg-options "-Wstack-usage=512" }
+
+procedure Stack_Usage5 (C : Character) is
+
+ S : String (1 .. 300);
+
+ procedure Set is
+ begin
+ S (1) := C;
+ end;
+
+begin
+ Set;
+end;
#include "langhooks.h"
#include "gimple-low.h"
#include "gomp-constants.h"
+#include "diagnostic.h"
/* The object of this pass is to lower the representation of a set of nested
return type;
}
-/* Return true if DECL should be referenced by pointer in the non-local
- frame structure. */
+/* Return true if DECL should be referenced by pointer in the non-local frame
+ structure. */
static bool
use_pointer_in_frame (tree decl)
{
if (TREE_CODE (decl) == PARM_DECL)
{
- /* It's illegal to copy TREE_ADDRESSABLE, impossible to copy variable
- sized decls, and inefficient to copy large aggregates. Don't bother
- moving anything but scalar variables. */
+ /* It's illegal to copy TREE_ADDRESSABLE, impossible to copy variable-
+ sized DECLs, and inefficient to copy large aggregates. Don't bother
+ moving anything but scalar parameters. */
return AGGREGATE_TYPE_P (TREE_TYPE (decl));
}
else
{
- /* Variable sized types make things "interesting" in the frame. */
- return DECL_SIZE (decl) == NULL || !TREE_CONSTANT (DECL_SIZE (decl));
+ /* Variable-sized DECLs can only come from OMP clauses at this point
+ since the gimplifier has already turned the regular variables into
+ pointers. Do the same as the gimplifier. */
+ return !DECL_SIZE (decl) || TREE_CODE (DECL_SIZE (decl)) != INTEGER_CST;
}
}
lookup_field_for_decl (struct nesting_info *info, tree decl,
enum insert_option insert)
{
+ gcc_checking_assert (decl_function_context (decl) == info->context);
+
if (insert == NO_INSERT)
{
tree *slot = info->field_map->get (decl);
tree *slot = &info->field_map->get_or_insert (decl);
if (!*slot)
{
+ tree type = get_frame_type (info);
tree field = make_node (FIELD_DECL);
DECL_NAME (field) = DECL_NAME (decl);
TREE_ADDRESSABLE (field) = TREE_ADDRESSABLE (decl);
DECL_NONADDRESSABLE_P (field) = !TREE_ADDRESSABLE (decl);
TREE_THIS_VOLATILE (field) = TREE_THIS_VOLATILE (decl);
+
+ /* Declare the transformation and adjust the original DECL. For a
+ variable or for a parameter when not optimizing, we make it point
+ to the field in the frame directly. For a parameter, we don't do
+ it when optimizing because the variable tracking pass will already
+ do the job, */
+ if (VAR_P (decl) || !optimize)
+ {
+ tree x
+ = build3 (COMPONENT_REF, TREE_TYPE (field), info->frame_decl,
+ field, NULL_TREE);
+
+ /* If the next declaration is a PARM_DECL pointing to the DECL,
+ we need to adjust its VALUE_EXPR directly, since chains of
+ VALUE_EXPRs run afoul of garbage collection. This occurs
+ in Ada for Out parameters that aren't copied in. */
+ tree next = DECL_CHAIN (decl);
+ if (next
+ && TREE_CODE (next) == PARM_DECL
+ && DECL_HAS_VALUE_EXPR_P (next)
+ && DECL_VALUE_EXPR (next) == decl)
+ SET_DECL_VALUE_EXPR (next, x);
+
+ SET_DECL_VALUE_EXPR (decl, x);
+ DECL_HAS_VALUE_EXPR_P (decl) = 1;
+ }
}
- insert_field_into_struct (get_frame_type (info), field);
+ insert_field_into_struct (type, field);
*slot = field;
if (TREE_CODE (decl) == PARM_DECL)
/* FALLTHRU */
case PARM_DECL:
- if (decl_function_context (t) != info->context)
- {
- tree x;
- wi->changed = true;
+ {
+ tree x, target_context = decl_function_context (t);
- x = get_nonlocal_debug_decl (info, t);
- if (!bitmap_bit_p (info->suppress_expansion, DECL_UID (t)))
- {
- tree target_context = decl_function_context (t);
- struct nesting_info *i;
- for (i = info->outer; i->context != target_context; i = i->outer)
- continue;
- x = lookup_field_for_decl (i, t, INSERT);
- x = get_frame_field (info, target_context, x, &wi->gsi);
- if (use_pointer_in_frame (t))
- {
- x = init_tmp_var (info, x, &wi->gsi);
- x = build_simple_mem_ref (x);
- }
- }
+ if (info->context == target_context)
+ break;
- if (wi->val_only)
- {
- if (wi->is_lhs)
- x = save_tmp_var (info, x, &wi->gsi);
- else
+ wi->changed = true;
+
+ if (bitmap_bit_p (info->suppress_expansion, DECL_UID (t)))
+ x = get_nonlocal_debug_decl (info, t);
+ else
+ {
+ struct nesting_info *i = info;
+ while (i && i->context != target_context)
+ i = i->outer;
+ /* If none of the outer contexts is the target context, this means
+ that the VAR or PARM_DECL is referenced in a wrong context. */
+ if (!i)
+ internal_error ("%s from %s referenced in %s",
+ IDENTIFIER_POINTER (DECL_NAME (t)),
+ IDENTIFIER_POINTER (DECL_NAME (target_context)),
+ IDENTIFIER_POINTER (DECL_NAME (info->context)));
+
+ x = lookup_field_for_decl (i, t, INSERT);
+ x = get_frame_field (info, target_context, x, &wi->gsi);
+ if (use_pointer_in_frame (t))
+ {
x = init_tmp_var (info, x, &wi->gsi);
- }
+ x = build_simple_mem_ref (x);
+ }
+ }
- *tp = x;
- }
+ if (wi->val_only)
+ {
+ if (wi->is_lhs)
+ x = save_tmp_var (info, x, &wi->gsi);
+ else
+ x = init_tmp_var (info, x, &wi->gsi);
+ }
+
+ *tp = x;
+ }
break;
case LABEL_DECL:
}
}
-/* Create nonlocal debug decls for nonlocal VLA array bounds for VLAs
- in BLOCK. */
-
-static void
-note_nonlocal_block_vlas (struct nesting_info *info, tree block)
-{
- tree var;
-
- for (var = BLOCK_VARS (block); var; var = DECL_CHAIN (var))
- if (VAR_P (var)
- && variably_modified_type_p (TREE_TYPE (var), NULL)
- && DECL_HAS_VALUE_EXPR_P (var)
- && decl_function_context (var) != info->context)
- note_nonlocal_vla_type (info, TREE_TYPE (var));
-}
-
/* 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
case GIMPLE_BIND:
{
gbind *bind_stmt = as_a <gbind *> (stmt);
- if (!optimize && gimple_bind_block (bind_stmt))
- note_nonlocal_block_vlas (info, gimple_bind_block (bind_stmt));
for (tree var = gimple_bind_vars (bind_stmt); var; var = DECL_CHAIN (var))
if (TREE_CODE (var) == NAMELIST_DECL)
/* FALLTHRU */
case PARM_DECL:
- if (decl_function_context (t) == info->context)
+ if (t != info->frame_decl && decl_function_context (t) == info->context)
{
/* If we copied a pointer to the frame, then the original decl
is used unchanged in the parent function. */
break;
wi->changed = true;
- x = get_local_debug_decl (info, t, field);
- if (!bitmap_bit_p (info->suppress_expansion, DECL_UID (t)))
+ if (bitmap_bit_p (info->suppress_expansion, DECL_UID (t)))
+ x = get_local_debug_decl (info, t, field);
+ else
x = get_frame_field (info, info->context, field, &wi->gsi);
if (wi->val_only)
target_context = decl_function_context (decl);
if (target_context && DECL_STATIC_CHAIN (decl))
{
+ struct nesting_info *i = info;
+ while (i && i->context != target_context)
+ i = i->outer;
+ /* If none of the outer contexts is the target context, this means
+ that the function is called in a wrong context. */
+ if (!i)
+ internal_error ("%s from %s called in %s",
+ IDENTIFIER_POINTER (DECL_NAME (decl)),
+ IDENTIFIER_POINTER (DECL_NAME (target_context)),
+ IDENTIFIER_POINTER (DECL_NAME (info->context)));
+
gimple_call_set_chain (as_a <gcall *> (stmt),
get_static_chain (info, target_context,
&wi->gsi));
delete id.cb.decl_map;
}
+/* Fixup VLA decls in BLOCK and subblocks if remapped variables are
+ involved. */
+
+static void
+fixup_vla_decls (tree block)
+{
+ for (tree var = BLOCK_VARS (block); var; var = DECL_CHAIN (var))
+ if (VAR_P (var) && DECL_HAS_VALUE_EXPR_P (var))
+ {
+ tree val = DECL_VALUE_EXPR (var);
+
+ if (!(TREE_CODE (val) == INDIRECT_REF
+ && VAR_P (TREE_OPERAND (val, 0))
+ && DECL_HAS_VALUE_EXPR_P (TREE_OPERAND (val, 0))))
+ continue;
+
+ /* Fully expand value expressions. This avoids having debug variables
+ only referenced from them and that can be swept during GC. */
+ val = build1 (INDIRECT_REF, TREE_TYPE (val),
+ DECL_VALUE_EXPR (TREE_OPERAND (val, 0)));
+ SET_DECL_VALUE_EXPR (var, val);
+ }
+
+ for (tree sub = BLOCK_SUBBLOCKS (block); sub; sub = BLOCK_CHAIN (sub))
+ fixup_vla_decls (sub);
+}
+
/* Fold the MEM_REF *E. */
bool
fold_mem_refs (tree *const &e, void *data ATTRIBUTE_UNUSED)
gimple_seq_first_stmt (gimple_body (context)), true);
}
- /* If any parameters were referenced non-locally, then we need to
- insert a copy. Likewise, if any variables were referenced by
- pointer, we need to initialize the address. */
+ /* If any parameters were referenced non-locally, then we need to insert
+ a copy or a pointer. */
if (root->any_parm_remapped)
{
tree p;
= chainon (BLOCK_VARS (DECL_INITIAL (root->context)),
root->debug_var_chain);
}
+ else
+ fixup_vla_decls (DECL_INITIAL (root->context));
/* Fold the rewritten MEM_REF trees. */
root->mem_refs->traverse<void *, fold_mem_refs> (NULL);
h = value_expr_for_decl->find_with_hash (&in, DECL_UID (from));
if (h)
- return h->to;
+ {
+ /* Chains of value expressions may run afoul of garbage collection. */
+ gcc_checking_assert (!(h->to
+ && (TREE_CODE (h->to) == PARM_DECL
+ || TREE_CODE (h->to) == VAR_DECL)
+ && DECL_HAS_VALUE_EXPR_P (h->to)));
+ return h->to;
+ }
+
return NULL_TREE;
}
{
struct tree_decl_map *h;
+ /* Chains of value expressions may run afoul of garbage collection. */
+ gcc_checking_assert (!(to
+ && (TREE_CODE (to) == PARM_DECL
+ || TREE_CODE (to) == VAR_DECL)
+ && DECL_HAS_VALUE_EXPR_P (to)));
+
h = ggc_alloc<tree_decl_map> ();
h->base.from = from;
h->to = to;