typedef struct dw_loc_descr_struct *dw_loc_descr_ref;
typedef struct dw_loc_list_struct *dw_loc_list_ref;
+typedef struct deferred_locations_struct GTY(())
+{
+ tree variable;
+ dw_die_ref die;
+} deferred_locations;
+
+DEF_VEC_O(deferred_locations);
+DEF_VEC_ALLOC_O(deferred_locations,gc);
+
+static GTY(()) VEC(deferred_locations, gc) *deferred_locations_list;
+
/* Each DIE may have a series of attribute/value pairs. Values
can take on several forms. The forms that are used in this
implementation are listed below. */
{
dw_loc_descr_ref dw_loc_next;
enum dwarf_location_atom dw_loc_opc;
+ int dw_loc_addr;
dw_val_node dw_loc_oprnd1;
dw_val_node dw_loc_oprnd2;
- int dw_loc_addr;
}
dw_loc_descr_node;
static void add_bit_offset_attribute (dw_die_ref, tree);
static void add_bit_size_attribute (dw_die_ref, tree);
static void add_prototyped_attribute (dw_die_ref, tree);
-static void add_abstract_origin_attribute (dw_die_ref, tree);
+static dw_die_ref add_abstract_origin_attribute (dw_die_ref, tree);
static void add_pure_or_virtual_attribute (dw_die_ref, tree);
static void add_src_coords_attributes (dw_die_ref, tree);
static void add_name_and_src_coords_attributes (dw_die_ref, tree);
#if 0
static void gen_entry_point_die (tree, dw_die_ref);
#endif
-static void gen_inlined_enumeration_type_die (tree, dw_die_ref);
-static void gen_inlined_structure_type_die (tree, dw_die_ref);
-static void gen_inlined_union_type_die (tree, dw_die_ref);
static dw_die_ref gen_enumeration_type_die (tree, dw_die_ref);
-static dw_die_ref gen_formal_parameter_die (tree, dw_die_ref);
+static dw_die_ref gen_formal_parameter_die (tree, tree, dw_die_ref);
static void gen_unspecified_parameters_die (tree, dw_die_ref);
static void gen_formal_types_die (tree, dw_die_ref);
static void gen_subprogram_die (tree, dw_die_ref);
-static void gen_variable_die (tree, dw_die_ref);
+static void gen_variable_die (tree, tree, dw_die_ref);
static void gen_const_die (tree, dw_die_ref);
static void gen_label_die (tree, dw_die_ref);
static void gen_lexical_block_die (tree, dw_die_ref, int);
static void gen_subroutine_type_die (tree, dw_die_ref);
static void gen_typedef_die (tree, dw_die_ref);
static void gen_type_die (tree, dw_die_ref);
-static void gen_tagged_type_instantiation_die (tree, dw_die_ref);
static void gen_block_die (tree, dw_die_ref, int);
static void decls_for_scope (tree, dw_die_ref, int);
static int is_redundant_typedef (const_tree);
-static void gen_namespace_die (tree);
-static void gen_decl_die (tree, dw_die_ref);
+static void gen_namespace_die (tree, dw_die_ref);
+static void gen_decl_die (tree, tree, dw_die_ref);
static dw_die_ref force_decl_die (tree);
static dw_die_ref force_type_die (tree);
static dw_die_ref setup_namespace_context (tree, dw_die_ref);
tree_add_const_value_attribute (die, decl);
}
+/* Add VARIABLE and DIE into deferred locations list. */
+
+static void
+defer_location (tree variable, dw_die_ref die)
+{
+ deferred_locations entry;
+ entry.variable = variable;
+ entry.die = die;
+ VEC_safe_push (deferred_locations, gc, deferred_locations_list, &entry);
+}
+
/* Helper function for tree_add_const_value_attribute. Natively encode
initializer INIT into an array. Return true if successful. */
by looking in either the type declaration or object declaration
equate table. */
-static inline void
+static inline dw_die_ref
add_abstract_origin_attribute (dw_die_ref die, tree origin)
{
dw_die_ref origin_die = NULL;
here. */
if (origin_die)
- add_AT_die_ref (die, DW_AT_abstract_origin, origin_die);
+ add_AT_die_ref (die, DW_AT_abstract_origin, origin_die);
+ return origin_die;
}
/* We do not currently support the pure_virtual attribute. */
gen_type_die (VEC_index (tree, incomplete_types, i), comp_unit_die);
}
-/* Generate a DIE to represent an inlined instance of an enumeration type. */
-
-static void
-gen_inlined_enumeration_type_die (tree type, dw_die_ref context_die)
-{
- dw_die_ref type_die = new_die (DW_TAG_enumeration_type, context_die, type);
-
- /* We do not check for TREE_ASM_WRITTEN (type) being set, as the type may
- be incomplete and such types are not marked. */
- add_abstract_origin_attribute (type_die, type);
-}
-
/* Determine what tag to use for a record type. */
static enum dwarf_tag
}
}
-/* Generate a DIE to represent an inlined instance of a structure type. */
-
-static void
-gen_inlined_structure_type_die (tree type, dw_die_ref context_die)
-{
- dw_die_ref type_die = new_die (record_type_tag (type), context_die, type);
-
- /* We do not check for TREE_ASM_WRITTEN (type) being set, as the type may
- be incomplete and such types are not marked. */
- add_abstract_origin_attribute (type_die, type);
-}
-
-/* Generate a DIE to represent an inlined instance of a union type. */
-
-static void
-gen_inlined_union_type_die (tree type, dw_die_ref context_die)
-{
- dw_die_ref type_die = new_die (DW_TAG_union_type, context_die, type);
-
- /* We do not check for TREE_ASM_WRITTEN (type) being set, as the type may
- be incomplete and such types are not marked. */
- add_abstract_origin_attribute (type_die, type);
-}
-
/* Generate a DIE to represent an enumeration type. Note that these DIEs
include all of the information about the enumeration values also. Each
enumerated type name/value is listed as a child of the enumerated type
add_name_attribute (enum_die,
IDENTIFIER_POINTER (TREE_PURPOSE (link)));
+ if (TREE_CODE (value) == CONST_DECL)
+ value = DECL_INITIAL (value);
+
if (host_integerp (value, TYPE_UNSIGNED (TREE_TYPE (value))))
/* DWARF2 does not provide a way of indicating whether or
not enumeration constants are signed or unsigned. GDB
argument type of some subprogram type. */
static dw_die_ref
-gen_formal_parameter_die (tree node, dw_die_ref context_die)
+gen_formal_parameter_die (tree node, tree origin, dw_die_ref context_die)
{
+ tree node_or_origin = node ? node : origin;
dw_die_ref parm_die
= new_die (DW_TAG_formal_parameter, context_die, node);
- tree origin;
- switch (TREE_CODE_CLASS (TREE_CODE (node)))
+ switch (TREE_CODE_CLASS (TREE_CODE (node_or_origin)))
{
case tcc_declaration:
- origin = decl_ultimate_origin (node);
+ if (!origin)
+ origin = decl_ultimate_origin (node);
if (origin != NULL)
add_abstract_origin_attribute (parm_die, origin);
else
add_AT_flag (parm_die, DW_AT_artificial, 1);
}
- equate_decl_number_to_die (node, parm_die);
- if (! DECL_ABSTRACT (node))
- add_location_or_const_value_attribute (parm_die, node, DW_AT_location);
+ if (node)
+ equate_decl_number_to_die (node, parm_die);
+ if (! DECL_ABSTRACT (node_or_origin))
+ add_location_or_const_value_attribute (parm_die, node_or_origin,
+ DW_AT_location);
break;
case tcc_type:
/* We were called with some kind of a ..._TYPE node. */
- add_type_attribute (parm_die, node, 0, 0, context_die);
+ add_type_attribute (parm_die, node_or_origin, 0, 0, context_die);
break;
default:
break;
/* Output a (nameless) DIE to represent the formal parameter itself. */
- parm_die = gen_formal_parameter_die (formal_type, context_die);
+ parm_die = gen_formal_parameter_die (formal_type, NULL, context_die);
if ((TREE_CODE (function_or_method_type) == METHOD_TYPE
&& link == first_parm_type)
|| (arg && DECL_ARTIFICIAL (arg)))
}
}
else
- gen_variable_die (member, type_die);
+ gen_variable_die (member, NULL_TREE, type_die);
pop_decl_scope ();
}
"__builtin_va_alist"))
gen_unspecified_parameters_die (parm, subr_die);
else
- gen_decl_die (parm, subr_die);
+ gen_decl_die (parm, NULL, subr_die);
}
/* Decide whether we need an unspecified_parameters DIE at the end.
{
/* Emit a DW_TAG_variable DIE for a named return value. */
if (DECL_NAME (DECL_RESULT (decl)))
- gen_decl_die (DECL_RESULT (decl), subr_die);
+ gen_decl_die (DECL_RESULT (decl), NULL, subr_die);
current_function_has_inlines = 0;
decls_for_scope (outer_scope, subr_die, 0);
return d->decl_id == e->decl_id && d->die_parent == e->die_parent;
}
-/* Generate a DIE to represent a declared data object. */
+/* Generate a DIE to represent a declared data object.
+ Either DECL or ORIGIN must be non-null. */
static void
-gen_variable_die (tree decl, dw_die_ref context_die)
+gen_variable_die (tree decl, tree origin, dw_die_ref context_die)
{
HOST_WIDE_INT off;
tree com_decl;
+ tree decl_or_origin = decl ? decl : origin;
dw_die_ref var_die;
- tree origin = decl_ultimate_origin (decl);
- dw_die_ref old_die = lookup_decl_die (decl);
- int declaration = (DECL_EXTERNAL (decl)
+ dw_die_ref old_die = decl ? lookup_decl_die (decl) : NULL;
+ dw_die_ref origin_die;
+ int declaration = (DECL_EXTERNAL (decl_or_origin)
/* If DECL is COMDAT and has not actually been
emitted, we cannot take its address; there
might end up being no definition anywhere in
Here, S<int>::i is not DECL_EXTERNAL, but no
definition is required, so the compiler will
not emit a definition. */
- || (TREE_CODE (decl) == VAR_DECL
- && DECL_COMDAT (decl) && !TREE_ASM_WRITTEN (decl))
+ || (TREE_CODE (decl_or_origin) == VAR_DECL
+ && DECL_COMDAT (decl_or_origin)
+ && !TREE_ASM_WRITTEN (decl_or_origin))
|| class_or_namespace_scope_p (context_die));
- com_decl = fortran_common (decl, &off);
+ if (!origin)
+ origin = decl_ultimate_origin (decl);
+
+ com_decl = fortran_common (decl_or_origin, &off);
/* Symbol in common gets emitted as a child of the common block, in the form
of a data member. */
dw_loc_descr_ref loc;
die_node com_die_arg;
- var_die = lookup_decl_die (decl);
+ var_die = lookup_decl_die (decl_or_origin);
if (var_die)
{
if (get_AT (var_die, DW_AT_location) == NULL)
return;
}
+ /* If the compiler emitted a definition for the DECL declaration
+ and if we already emitted a DIE for it, don't emit a second
+ DIE for it again. */
+ if (old_die
+ && declaration
+ && old_die->die_parent == context_die)
+ return;
+
var_die = new_die (DW_TAG_variable, context_die, decl);
+ origin_die = NULL;
if (origin != NULL)
- add_abstract_origin_attribute (var_die, origin);
+ origin_die = add_abstract_origin_attribute (var_die, origin);
/* Loop unrolling can create multiple blocks that refer to the same
static variable, so we must test for the DW_AT_declaration flag.
if (declaration)
add_AT_flag (var_die, DW_AT_declaration, 1);
- if (DECL_ABSTRACT (decl) || declaration)
+ if (decl && (DECL_ABSTRACT (decl) || declaration))
equate_decl_number_to_die (decl, var_die);
- if (! declaration && ! DECL_ABSTRACT (decl))
- {
- add_location_or_const_value_attribute (var_die, decl, DW_AT_location);
- add_pubname (decl, var_die);
+ if (! declaration
+ && (! DECL_ABSTRACT (decl_or_origin)
+ /* Local static vars are shared between all clones/inlines,
+ so emit DW_AT_location on the abstract DIE if DECL_RTL is
+ already set. */
+ || (TREE_CODE (decl_or_origin) == VAR_DECL
+ && TREE_STATIC (decl_or_origin)
+ && DECL_RTL_SET_P (decl_or_origin)))
+ /* When abstract origin already has DW_AT_location attribute, no need
+ to add it again. */
+ && (origin_die == NULL || get_AT (origin_die, DW_AT_location) == NULL))
+ {
+ if (TREE_CODE (decl_or_origin) == VAR_DECL && TREE_STATIC (decl_or_origin)
+ && !TREE_SYMBOL_REFERENCED (DECL_ASSEMBLER_NAME (decl_or_origin)))
+ defer_location (decl_or_origin, var_die);
+ else
+ add_location_or_const_value_attribute (var_die,
+ decl_or_origin,
+ DW_AT_location);
+ add_pubname (decl_or_origin, var_die);
}
else
- tree_add_const_value_attribute (var_die, decl);
+ tree_add_const_value_attribute (var_die, decl_or_origin);
}
/* Generate a DIE to represent a named constant. */
}
-/* If STMT's abstract origin is a function declaration and STMT's
- first subblock's abstract origin is the function's outermost block,
- then we're looking at the main entry point. */
-static bool
-is_inlined_entry_point (const_tree stmt)
-{
- tree decl, block;
-
- if (!stmt || TREE_CODE (stmt) != BLOCK)
- return false;
-
- decl = block_ultimate_origin (stmt);
-
- if (!decl || TREE_CODE (decl) != FUNCTION_DECL)
- return false;
-
- block = BLOCK_SUBBLOCKS (stmt);
-
- if (block)
- {
- if (TREE_CODE (block) != BLOCK)
- return false;
-
- block = block_ultimate_origin (block);
- }
-
- return block == DECL_INITIAL (decl);
-}
-
/* A helper function for gen_lexical_block_die and gen_inlined_subroutine_die.
Add low_pc and high_pc attributes to the DIE for a block STMT. */
{
tree chain;
- if (is_inlined_entry_point (stmt))
+ if (inlined_function_outer_scope_p (stmt))
{
ASM_GENERATE_INTERNAL_LABEL (label, BLOCK_BEGIN_LABEL,
BLOCK_NUMBER (stmt));
{
dw_die_ref stmt_die = new_die (DW_TAG_lexical_block, context_die, stmt);
- if (! BLOCK_ABSTRACT (stmt))
+ if (! BLOCK_ABSTRACT (stmt) && TREE_ASM_WRITTEN (stmt))
add_high_low_attributes (stmt, stmt_die);
decls_for_scope (stmt, stmt_die, depth);
= new_die (DW_TAG_inlined_subroutine, context_die, stmt);
add_abstract_origin_attribute (subr_die, decl);
- add_high_low_attributes (stmt, subr_die);
+ if (TREE_ASM_WRITTEN (stmt))
+ add_high_low_attributes (stmt, subr_die);
add_call_src_coords_attributes (stmt, subr_die);
decls_for_scope (stmt, subr_die, depth);
if (child)
splice_child_die (context_die, child);
else
- gen_decl_die (member, context_die);
+ gen_decl_die (member, NULL, context_die);
}
/* Now output info about the function members (if any). */
if (child)
splice_child_die (context_die, child);
else
- gen_decl_die (member, context_die);
+ gen_decl_die (member, NULL, context_die);
}
}
gcc_assert (DECL_ORIGINAL_TYPE (TYPE_NAME (type)) != type);
TREE_ASM_WRITTEN (type) = 1;
- gen_decl_die (TYPE_NAME (type), context_die);
+ gen_decl_die (TYPE_NAME (type), NULL, context_die);
return;
}
gen_type_die_with_usage (type, context_die, DINFO_USAGE_DIR_USE);
}
-/* Generate a DIE for a tagged type instantiation. */
-
-static void
-gen_tagged_type_instantiation_die (tree type, dw_die_ref context_die)
-{
- if (type == NULL_TREE || type == error_mark_node)
- return;
-
- /* We are going to output a DIE to represent the unqualified version of
- this type (i.e. without any const or volatile qualifiers) so make sure
- that we have the main variant (i.e. the unqualified version) of this
- type now. */
- gcc_assert (type == type_main_variant (type));
-
- /* Do not check TREE_ASM_WRITTEN (type) as it may not be set if this is
- an instance of an unresolved type. */
-
- switch (TREE_CODE (type))
- {
- case ERROR_MARK:
- break;
-
- case ENUMERAL_TYPE:
- gen_inlined_enumeration_type_die (type, context_die);
- break;
-
- case RECORD_TYPE:
- gen_inlined_structure_type_die (type, context_die);
- break;
-
- case UNION_TYPE:
- case QUAL_UNION_TYPE:
- gen_inlined_union_type_die (type, context_die);
- break;
-
- default:
- gcc_unreachable ();
- }
-}
-
/* Generate a DW_TAG_lexical_block DIE followed by DIEs to represent all of the
things which are local to the given block. */
gen_block_die (tree stmt, dw_die_ref context_die, int depth)
{
int must_output_die = 0;
- tree origin;
- tree decl;
- enum tree_code origin_code;
+ bool inlined_func;
/* Ignore blocks that are NULL. */
if (stmt == NULL_TREE)
return;
+ inlined_func = inlined_function_outer_scope_p (stmt);
+
/* If the block is one fragment of a non-contiguous block, do not
process the variables, since they will have been done by the
origin block. Do process subblocks. */
return;
}
- /* Determine the "ultimate origin" of this block. This block may be an
- inlined instance of an inlined instance of inline function, so we have
- to trace all of the way back through the origin chain to find out what
- sort of node actually served as the original seed for the creation of
- the current block. */
- origin = block_ultimate_origin (stmt);
- origin_code = (origin != NULL) ? TREE_CODE (origin) : ERROR_MARK;
-
/* Determine if we need to output any Dwarf DIEs at all to represent this
block. */
- if (origin_code == FUNCTION_DECL)
+ if (inlined_func)
/* The outer scopes for inlinings *must* always be represented. We
generate DW_TAG_inlined_subroutine DIEs for them. (See below.) */
must_output_die = 1;
else
{
- /* In the case where the current block represents an inlining of the
- "body block" of an inline function, we must *NOT* output any DIE for
- this block because we have already output a DIE to represent the whole
- inlined function scope and the "body block" of any function doesn't
- really represent a different scope according to ANSI C rules. So we
- check here to make sure that this block does not represent a "body
- block inlining" before trying to set the MUST_OUTPUT_DIE flag. */
- if (! is_body_block (origin ? origin : stmt))
- {
- /* Determine if this block directly contains any "significant"
- local declarations which we will need to output DIEs for. */
- if (debug_info_level > DINFO_LEVEL_TERSE)
- /* We are not in terse mode so *any* local declaration counts
- as being a "significant" one. */
- must_output_die = (BLOCK_VARS (stmt) != NULL
- && (TREE_USED (stmt)
- || TREE_ASM_WRITTEN (stmt)
- || BLOCK_ABSTRACT (stmt)));
- else
- /* We are in terse mode, so only local (nested) function
- definitions count as "significant" local declarations. */
- for (decl = BLOCK_VARS (stmt);
- decl != NULL; decl = TREE_CHAIN (decl))
- if (TREE_CODE (decl) == FUNCTION_DECL
- && DECL_INITIAL (decl))
- {
- must_output_die = 1;
- break;
- }
- }
+ /* Determine if this block directly contains any "significant"
+ local declarations which we will need to output DIEs for. */
+ if (debug_info_level > DINFO_LEVEL_TERSE)
+ /* We are not in terse mode so *any* local declaration counts
+ as being a "significant" one. */
+ must_output_die = ((BLOCK_VARS (stmt) != NULL
+ || BLOCK_NUM_NONLOCALIZED_VARS (stmt))
+ && (TREE_USED (stmt)
+ || TREE_ASM_WRITTEN (stmt)
+ || BLOCK_ABSTRACT (stmt)));
+ else if ((TREE_USED (stmt)
+ || TREE_ASM_WRITTEN (stmt)
+ || BLOCK_ABSTRACT (stmt))
+ && !dwarf2out_ignore_block (stmt))
+ must_output_die = 1;
}
/* It would be a waste of space to generate a Dwarf DW_TAG_lexical_block
instances and local (nested) function definitions. */
if (must_output_die)
{
- if (origin_code == FUNCTION_DECL)
+ if (inlined_func)
gen_inlined_subroutine_die (stmt, context_die, depth);
else
gen_lexical_block_die (stmt, context_die, depth);
decls_for_scope (stmt, context_die, depth);
}
+/* Process variable DECL (or variable with origin ORIGIN) within
+ block STMT and add it to CONTEXT_DIE. */
+static void
+process_scope_var (tree stmt, tree decl, tree origin, dw_die_ref context_die)
+{
+ dw_die_ref die;
+ tree decl_or_origin = decl ? decl : origin;
+ tree ultimate_origin = origin ? decl_ultimate_origin (origin) : NULL;
+
+ if (ultimate_origin)
+ origin = ultimate_origin;
+
+ if (TREE_CODE (decl_or_origin) == FUNCTION_DECL)
+ die = lookup_decl_die (decl_or_origin);
+ else if (TREE_CODE (decl_or_origin) == TYPE_DECL
+ && TYPE_DECL_IS_STUB (decl_or_origin))
+ die = lookup_type_die (TREE_TYPE (decl_or_origin));
+ else
+ die = NULL;
+
+ if (die != NULL && die->die_parent == NULL)
+ add_child_die (context_die, die);
+ else if (TREE_CODE (decl_or_origin) == IMPORTED_DECL)
+ dwarf2out_imported_module_or_decl_1 (decl_or_origin, DECL_NAME (decl_or_origin),
+ stmt, context_die);
+ else
+ gen_decl_die (decl, origin, context_die);
+}
+
/* Generate all of the decls declared within a given scope and (recursively)
all of its sub-blocks. */
decls_for_scope (tree stmt, dw_die_ref context_die, int depth)
{
tree decl;
+ unsigned int i;
tree subblocks;
/* Ignore NULL blocks. */
if (stmt == NULL_TREE)
return;
- if (TREE_USED (stmt))
- {
- /* Output the DIEs to represent all of the data objects and typedefs
- declared directly within this block but not within any nested
- sub-blocks. Also, nested function and tag DIEs have been
- generated with a parent of NULL; fix that up now. */
- for (decl = BLOCK_VARS (stmt); decl != NULL; decl = TREE_CHAIN (decl))
- {
- dw_die_ref die;
-
- if (TREE_CODE (decl) == FUNCTION_DECL)
- die = lookup_decl_die (decl);
- else if (TREE_CODE (decl) == TYPE_DECL && TYPE_DECL_IS_STUB (decl))
- die = lookup_type_die (TREE_TYPE (decl));
- else
- die = NULL;
-
- if (die != NULL && die->die_parent == NULL)
- add_child_die (context_die, die);
- /* Do not produce debug information for static variables since
- these might be optimized out. We are called for these later
- in varpool_analyze_pending_decls.
-
- But *do* produce it for Fortran COMMON variables because,
- even though they are static, their names can differ depending
- on the scope, which we need to preserve. */
- if (TREE_CODE (decl) == VAR_DECL && TREE_STATIC (decl)
- && !(is_fortran () && TREE_PUBLIC (decl)))
- ;
- else if (TREE_CODE (decl) == IMPORTED_DECL)
- dwarf2out_imported_module_or_decl_1 (decl, DECL_NAME (decl),
- stmt, context_die);
- else
- gen_decl_die (decl, context_die);
- }
- }
+ /* Output the DIEs to represent all of the data objects and typedefs
+ declared directly within this block but not within any nested
+ sub-blocks. Also, nested function and tag DIEs have been
+ generated with a parent of NULL; fix that up now. */
+ for (decl = BLOCK_VARS (stmt); decl != NULL; decl = TREE_CHAIN (decl))
+ process_scope_var (stmt, decl, NULL_TREE, context_die);
+ for (i = 0; i < BLOCK_NUM_NONLOCALIZED_VARS (stmt); i++)
+ process_scope_var (stmt, NULL, BLOCK_NONLOCALIZED_VAR (stmt, i),
+ context_die);
/* If we're at -g1, we're not interested in subblocks. */
if (debug_info_level <= DINFO_LEVEL_TERSE)
gen_decl_die() call. */
saved_external_flag = DECL_EXTERNAL (decl);
DECL_EXTERNAL (decl) = 1;
- gen_decl_die (decl, context_die);
+ gen_decl_die (decl, NULL, context_die);
DECL_EXTERNAL (decl) = saved_external_flag;
break;
if (is_fortran ())
return ns_context;
if (DECL_P (thing))
- gen_decl_die (thing, ns_context);
+ gen_decl_die (thing, NULL, ns_context);
else
gen_type_die (thing, ns_context);
}
/* Generate a DIE for a namespace or namespace alias. */
static void
-gen_namespace_die (tree decl)
+gen_namespace_die (tree decl, dw_die_ref context_die)
{
- dw_die_ref context_die = setup_namespace_context (decl, comp_unit_die);
+ dw_die_ref namespace_die;
/* Namespace aliases have a DECL_ABSTRACT_ORIGIN of the namespace
they are an alias of. */
if (DECL_ABSTRACT_ORIGIN (decl) == NULL)
{
/* Output a real namespace or module. */
- dw_die_ref namespace_die
- = new_die (is_fortran () ? DW_TAG_module : DW_TAG_namespace,
- context_die, decl);
+ context_die = setup_namespace_context (decl, comp_unit_die);
+ namespace_die = new_die (is_fortran ()
+ ? DW_TAG_module : DW_TAG_namespace,
+ context_die, decl);
/* For Fortran modules defined in different CU don't add src coords. */
if (namespace_die->die_tag == DW_TAG_module && DECL_EXTERNAL (decl))
add_name_attribute (namespace_die, dwarf2_name (decl, 0));
dw_die_ref origin_die
= force_decl_die (DECL_ABSTRACT_ORIGIN (decl));
+ if (DECL_CONTEXT (decl) == NULL_TREE
+ || TREE_CODE (DECL_CONTEXT (decl)) == NAMESPACE_DECL)
+ context_die = setup_namespace_context (decl, comp_unit_die);
/* Now create the namespace alias DIE. */
- dw_die_ref namespace_die
- = new_die (DW_TAG_imported_declaration, context_die, decl);
+ namespace_die = new_die (DW_TAG_imported_declaration, context_die, decl);
add_name_and_src_coords_attributes (namespace_die, decl);
add_AT_die_ref (namespace_die, DW_AT_import, origin_die);
equate_decl_number_to_die (decl, namespace_die);
/* Generate Dwarf debug information for a decl described by DECL. */
static void
-gen_decl_die (tree decl, dw_die_ref context_die)
+gen_decl_die (tree decl, tree origin, dw_die_ref context_die)
{
- tree origin;
+ tree decl_or_origin = decl ? decl : origin;
+ tree class_origin = NULL;
- if (DECL_P (decl) && DECL_IGNORED_P (decl))
+ if (DECL_P (decl_or_origin) && DECL_IGNORED_P (decl_or_origin))
return;
- switch (TREE_CODE (decl))
+ switch (TREE_CODE (decl_or_origin))
{
case ERROR_MARK:
break;
case FUNCTION_DECL:
/* Don't output any DIEs to represent mere function declarations,
unless they are class members or explicit block externs. */
- if (DECL_INITIAL (decl) == NULL_TREE && DECL_CONTEXT (decl) == NULL_TREE
- && (current_function_decl == NULL_TREE || DECL_ARTIFICIAL (decl)))
+ if (DECL_INITIAL (decl_or_origin) == NULL_TREE
+ && DECL_CONTEXT (decl_or_origin) == NULL_TREE
+ && (current_function_decl == NULL_TREE
+ || DECL_ARTIFICIAL (decl_or_origin)))
break;
#if 0
#endif
/* If we're emitting a clone, emit info for the abstract instance. */
- if (DECL_ORIGIN (decl) != decl)
- dwarf2out_abstract_function (DECL_ABSTRACT_ORIGIN (decl));
+ if (origin || DECL_ORIGIN (decl) != decl)
+ dwarf2out_abstract_function (origin ? origin : DECL_ABSTRACT_ORIGIN (decl));
/* If we're emitting an out-of-line copy of an inline function,
emit info for the abstract instance and set up to refer to it. */
gen_type_die (DECL_CONTEXT (decl), context_die);
/* And its containing type. */
- origin = decl_class_context (decl);
+ if (!origin)
+ origin = decl_class_context (decl);
if (origin != NULL_TREE)
gen_type_die_for_member (origin, decl, context_die);
}
/* Now output a DIE to represent the function itself. */
- gen_subprogram_die (decl, context_die);
+ if (decl)
+ gen_subprogram_die (decl, context_die);
break;
case TYPE_DECL:
of some type tag, if the given TYPE_DECL is marked as having been
instantiated from some other (original) TYPE_DECL node (e.g. one which
was generated within the original definition of an inline function) we
- have to generate a special (abbreviated) DW_TAG_structure_type,
- DW_TAG_union_type, or DW_TAG_enumeration_type DIE here. */
- if (TYPE_DECL_IS_STUB (decl) && decl_ultimate_origin (decl) != NULL_TREE
- && is_tagged_type (TREE_TYPE (decl)))
- {
- gen_tagged_type_instantiation_die (TREE_TYPE (decl), context_die);
- break;
- }
+ used to generate a special (abbreviated) DW_TAG_structure_type,
+ DW_TAG_union_type, or DW_TAG_enumeration_type DIE here. But nothing
+ should be actually referencing those DIEs, as variable DIEs with that
+ type would be emitted already in the abstract origin, so it was always
+ removed during unused type prunning. Don't add anything in this
+ case. */
+ if (TYPE_DECL_IS_STUB (decl) && decl_ultimate_origin (decl) != NULL_TREE)
+ break;
if (is_redundant_typedef (decl))
gen_type_die (TREE_TYPE (decl), context_die);
/* Output any DIEs that are needed to specify the type of this data
object. */
- if (TREE_CODE (decl) == RESULT_DECL && DECL_BY_REFERENCE (decl))
- gen_type_die (TREE_TYPE (TREE_TYPE (decl)), context_die);
+ if (TREE_CODE (decl_or_origin) == RESULT_DECL
+ && DECL_BY_REFERENCE (decl_or_origin))
+ gen_type_die (TREE_TYPE (TREE_TYPE (decl_or_origin)), context_die);
else
- gen_type_die (TREE_TYPE (decl), context_die);
+ gen_type_die (TREE_TYPE (decl_or_origin), context_die);
/* And its containing type. */
- origin = decl_class_context (decl);
- if (origin != NULL_TREE)
- gen_type_die_for_member (origin, decl, context_die);
+ class_origin = decl_class_context (decl_or_origin);
+ if (class_origin != NULL_TREE)
+ gen_type_die_for_member (class_origin, decl_or_origin, context_die);
/* And its containing namespace. */
- context_die = declare_in_namespace (decl, context_die);
+ context_die = declare_in_namespace (decl_or_origin, context_die);
/* Now output the DIE to represent the data object itself. This gets
complicated because of the possibility that the VAR_DECL really
represents an inlined instance of a formal parameter for an inline
function. */
- origin = decl_ultimate_origin (decl);
+ if (!origin)
+ origin = decl_ultimate_origin (decl);
if (origin != NULL_TREE && TREE_CODE (origin) == PARM_DECL)
- gen_formal_parameter_die (decl, context_die);
+ gen_formal_parameter_die (decl, origin, context_die);
else
- gen_variable_die (decl, context_die);
+ gen_variable_die (decl, origin, context_die);
break;
case FIELD_DECL:
break;
case PARM_DECL:
- if (DECL_BY_REFERENCE (decl))
- gen_type_die (TREE_TYPE (TREE_TYPE (decl)), context_die);
+ if (DECL_BY_REFERENCE (decl_or_origin))
+ gen_type_die (TREE_TYPE (TREE_TYPE (decl_or_origin)), context_die);
else
- gen_type_die (TREE_TYPE (decl), context_die);
- gen_formal_parameter_die (decl, context_die);
+ gen_type_die (TREE_TYPE (decl_or_origin), context_die);
+ gen_formal_parameter_die (decl, origin, context_die);
break;
case NAMESPACE_DECL:
case IMPORTED_DECL:
- gen_namespace_die (decl);
+ gen_namespace_die (decl, context_die);
break;
default:
dw_die_ref imported_die = NULL;
dw_die_ref at_import_die;
+ if (TREE_CODE (decl) == IMPORTED_DECL)
+ {
+ xloc = expand_location (DECL_SOURCE_LOCATION (decl));
+ decl = IMPORTED_DECL_ASSOCIATED_DECL (decl);
+ gcc_assert (decl);
+ }
+ else
+ xloc = expand_location (input_location);
+
if (TREE_CODE (decl) == TYPE_DECL || TREE_CODE (decl) == CONST_DECL)
{
if (is_base_type (TREE_TYPE (decl)))
gcc_assert (at_import_die);
}
}
- else if (TREE_CODE (decl) == IMPORTED_DECL)
- {
- tree imported_ns_decl;
- /* IMPORTED_DECL nodes that are not imported namespace are just not
- supported yet. */
- gcc_assert (DECL_INITIAL (decl)
- && TREE_CODE (DECL_INITIAL (decl)) == NAMESPACE_DECL);
- imported_ns_decl = DECL_INITIAL (decl);
- at_import_die = lookup_decl_die (imported_ns_decl);
- if (!at_import_die)
- at_import_die = force_decl_die (imported_ns_decl);
- gcc_assert (at_import_die);
- }
else
{
at_import_die = lookup_decl_die (decl);
lexical_block_die,
lexical_block);
- xloc = expand_location (input_location);
add_AT_file (imported_die, DW_AT_decl_file, lookup_filename (xloc.file));
add_AT_unsigned (imported_die, DW_AT_decl_line, xloc.line);
if (name)
return;
}
- gen_decl_die (decl, context_die);
+ gen_decl_die (decl, NULL, context_die);
}
/* Output a marker (i.e. a label) for the beginning of the generated code for
dwarf2out_ignore_block (const_tree block)
{
tree decl;
+ unsigned int i;
for (decl = BLOCK_VARS (block); decl; decl = TREE_CHAIN (decl))
if (TREE_CODE (decl) == FUNCTION_DECL
|| (TREE_CODE (decl) == TYPE_DECL && TYPE_DECL_IS_STUB (decl)))
return 0;
+ for (i = 0; i < BLOCK_NUM_NONLOCALIZED_VARS (block); i++)
+ {
+ decl = BLOCK_NONLOCALIZED_VAR (block, i);
+ if (TREE_CODE (decl) == FUNCTION_DECL
+ || (TREE_CODE (decl) == TYPE_DECL && TYPE_DECL_IS_STUB (decl)))
+ return 0;
+ }
return 1;
}
{
limbo_die_node *node, *next_node;
dw_die_ref die = 0;
+ unsigned int i;
/* Add the name for the main input file now. We delayed this from
dwarf2out_init to avoid complications with PCH. */
add_comp_dir_attribute (comp_unit_die);
}
+ for (i = 0; i < VEC_length (deferred_locations, deferred_locations_list); i++)
+ {
+ add_location_or_const_value_attribute (
+ VEC_index (deferred_locations, deferred_locations_list, i)->die,
+ VEC_index (deferred_locations, deferred_locations_list, i)->variable,
+ DW_AT_location);
+ }
+
/* Traverse the limbo die list, and add parent/child links. The only
dies without parents that should be here are concrete instances of
inline functions, and the comp_unit_die. We can ignore the comp_unit_die.