summaryrefslogtreecommitdiff
path: root/gcc/cp/decl.c
diff options
context:
space:
mode:
Diffstat (limited to 'gcc/cp/decl.c')
-rw-r--r--gcc/cp/decl.c153
1 files changed, 89 insertions, 64 deletions
diff --git a/gcc/cp/decl.c b/gcc/cp/decl.c
index 73b570945d2..fe1b60fb2df 100644
--- a/gcc/cp/decl.c
+++ b/gcc/cp/decl.c
@@ -300,6 +300,16 @@ tree pfn_identifier, index_identifier, delta_identifier, delta2_identifier;
tree pfn_or_delta2_identifier, tag_identifier;
tree vt_off_identifier;
+struct named_label_list
+{
+ struct binding_level *binding_level;
+ tree names_in_scope;
+ tree label_decl;
+ char *filename_o_goto;
+ int lineno_o_goto;
+ struct named_label_list *next;
+};
+
/* A list (chain of TREE_LIST nodes) of named label uses.
The TREE_PURPOSE field is the list of variables defined
the the label's scope defined at the point of use.
@@ -307,11 +317,17 @@ tree vt_off_identifier;
The TREE_TYPE field holds `current_binding_level' at the
point of the label's use.
+ BWAHAHAAHAHahhahahahaah. No, no, no, said the little chicken.
+
+ Look at the pretty struct named_label_list. See the pretty struct
+ with the pretty named fields that describe what they do. See the
+ pretty lack of gratuitous casts. Notice the code got a lot cleaner.
+
Used only for jumps to as-yet undefined labels, since
jumps to defined labels can have their validity checked
by stmt.c. */
-static tree named_label_uses;
+static struct named_label_list *named_label_uses = NULL;
/* A list of objects which have constructors or destructors
which reside in the global scope. The decl is stored in
@@ -1199,12 +1215,12 @@ poplevel (keep, reverse, functionbody)
level_chain = current_binding_level->level_chain;
if (level_chain)
{
- tree labels;
- for (labels = named_label_uses; labels; labels = TREE_CHAIN (labels))
- if (TREE_TYPE (labels) == (tree)current_binding_level)
+ struct named_label_list *labels;
+ for (labels = named_label_uses; labels; labels = labels->next)
+ if (labels->binding_level == current_binding_level)
{
- TREE_TYPE (labels) = (tree)level_chain;
- TREE_PURPOSE (labels) = level_chain->names;
+ labels->binding_level = level_chain;
+ labels->names_in_scope = level_chain->names;
}
}
}
@@ -1739,11 +1755,9 @@ struct saved_scope {
tree old_bindings;
struct saved_scope *prev;
tree class_name, class_type, function_decl;
- tree base_init_list, member_init_list;
struct binding_level *class_bindings;
tree *lang_base, *lang_stack, lang_name;
int lang_stacksize;
- tree named_labels;
int minimal_parse_mode;
tree last_function_parms;
tree template_parms;
@@ -1803,6 +1817,9 @@ maybe_push_to_top_level (pseudo)
struct binding_level *b = inner_binding_level;
tree old_bindings = NULL_TREE;
+ if (current_function_decl)
+ push_cp_function_context (NULL_TREE);
+
if (previous_class_type)
old_bindings = store_bindings (previous_class_values, old_bindings);
@@ -1832,19 +1849,17 @@ maybe_push_to_top_level (pseudo)
s->class_name = current_class_name;
s->class_type = current_class_type;
s->function_decl = current_function_decl;
- s->base_init_list = current_base_init_list;
- s->member_init_list = current_member_init_list;
s->class_bindings = class_binding_level;
s->lang_stack = current_lang_stack;
s->lang_base = current_lang_base;
s->lang_stacksize = current_lang_stacksize;
s->lang_name = current_lang_name;
- s->named_labels = named_labels;
s->minimal_parse_mode = minimal_parse_mode;
s->last_function_parms = last_function_parms;
s->template_parms = current_template_parms;
s->previous_class_type = previous_class_type;
s->previous_class_values = previous_class_values;
+
current_class_name = current_class_type = NULL_TREE;
current_function_decl = NULL_TREE;
class_binding_level = (struct binding_level *)0;
@@ -1902,8 +1917,6 @@ pop_from_top_level ()
}
current_class_name = s->class_name;
current_class_type = s->class_type;
- current_base_init_list = s->base_init_list;
- current_member_init_list = s->member_init_list;
current_function_decl = s->function_decl;
class_binding_level = s->class_bindings;
free (current_lang_base);
@@ -1915,7 +1928,6 @@ pop_from_top_level ()
strict_prototype = strict_prototypes_lang_cplusplus;
else if (current_lang_name == lang_name_c)
strict_prototype = strict_prototypes_lang_c;
- named_labels = s->named_labels;
minimal_parse_mode = s->minimal_parse_mode;
last_function_parms = s->last_function_parms;
current_template_parms = s->template_parms;
@@ -1923,6 +1935,9 @@ pop_from_top_level ()
previous_class_values = s->previous_class_values;
free (s);
+
+ if (current_function_decl)
+ pop_cp_function_context (NULL_TREE);
}
/* Push a definition of struct, union or enum tag "name".
@@ -3717,13 +3732,20 @@ lookup_label (id)
if ((decl == NULL_TREE
|| DECL_SOURCE_LINE (decl) == 0)
- && (named_label_uses == NULL_TREE
- || TREE_PURPOSE (named_label_uses) != current_binding_level->names
- || TREE_VALUE (named_label_uses) != decl))
- {
- named_label_uses
- = tree_cons (current_binding_level->names, decl, named_label_uses);
- TREE_TYPE (named_label_uses) = (tree)current_binding_level;
+ && (named_label_uses == NULL
+ || named_label_uses->names_in_scope != current_binding_level->names
+ || named_label_uses->label_decl != decl))
+ {
+ struct named_label_list *new_ent;
+ new_ent
+ = (struct named_label_list*)oballoc (sizeof (struct named_label_list));
+ new_ent->label_decl = decl;
+ new_ent->names_in_scope = current_binding_level->names;
+ new_ent->binding_level = current_binding_level;
+ new_ent->lineno_o_goto = lineno;
+ new_ent->filename_o_goto = input_filename;
+ new_ent->next = named_label_uses;
+ named_label_uses = new_ent;
}
/* Use a label already defined or ref'd with this name. */
@@ -3754,7 +3776,7 @@ lookup_label (id)
SET_IDENTIFIER_LABEL_VALUE (id, decl);
named_labels = tree_cons (NULL_TREE, decl, named_labels);
- TREE_VALUE (named_label_uses) = decl;
+ named_label_uses->label_decl = decl;
return decl;
}
@@ -3830,7 +3852,7 @@ define_label (filename, line, name)
}
else
{
- tree uses, prev;
+ struct named_label_list *uses, *prev;
int identified = 0;
/* Mark label as having been defined. */
@@ -3839,17 +3861,17 @@ define_label (filename, line, name)
DECL_SOURCE_FILE (decl) = filename;
DECL_SOURCE_LINE (decl) = line;
- for (prev = NULL_TREE, uses = named_label_uses;
- uses;
- prev = uses, uses = TREE_CHAIN (uses))
- if (TREE_VALUE (uses) == decl)
+ prev = NULL;
+ uses = named_label_uses;
+ while (uses != NULL)
+ if (uses->label_decl == decl)
{
struct binding_level *b = current_binding_level;
while (b)
{
tree new_decls = b->names;
- tree old_decls = ((tree)b == TREE_TYPE (uses)
- ? TREE_PURPOSE (uses) : NULL_TREE);
+ tree old_decls = (b == uses->binding_level)
+ ? uses->names_in_scope : NULL_TREE;
while (new_decls != old_decls)
{
if (TREE_CODE (new_decls) == VAR_DECL
@@ -3862,23 +3884,35 @@ define_label (filename, line, name)
&& DECL_INITIAL (new_decls) != error_mark_node)
|| TYPE_NEEDS_CONSTRUCTING (TREE_TYPE (new_decls))))
{
- if (! identified)
- cp_error ("jump to label `%D'", decl);
- identified = 1;
+ if (! identified)
+ {
+ cp_error ("jump to label `%D'", decl);
+ error_with_file_and_line (uses->filename_o_goto,
+ uses->lineno_o_goto,
+ " from here");
+ identified = 1;
+ }
cp_error_at (" crosses initialization of `%#D'",
new_decls);
}
new_decls = TREE_CHAIN (new_decls);
}
- if ((tree)b == TREE_TYPE (uses))
+ if (b == uses->binding_level)
break;
b = b->level_chain;
}
- if (prev)
- TREE_CHAIN (prev) = TREE_CHAIN (uses);
+ if (prev != NULL)
+ prev->next = uses->next;
else
- named_label_uses = TREE_CHAIN (uses);
+ named_label_uses = uses->next;
+
+ uses = uses->next;
+ }
+ else
+ {
+ prev = uses;
+ uses = uses->next;
}
current_function_return_value = NULL_TREE;
return decl;
@@ -4665,7 +4699,7 @@ init_decl_processing ()
current_function_decl = NULL_TREE;
named_labels = NULL_TREE;
- named_label_uses = NULL_TREE;
+ named_label_uses = NULL;
current_binding_level = NULL_BINDING_LEVEL;
free_binding_level = NULL_BINDING_LEVEL;
@@ -5797,8 +5831,13 @@ start_decl (declarator, declspecs, initialized, raises)
tree field = lookup_field (context, DECL_NAME (decl), 0, 0);
if (field == NULL_TREE || TREE_CODE (field) != VAR_DECL)
cp_error ("`%#D' is not a static member of `%#T'", decl, context);
- else if (duplicate_decls (decl, field))
- decl = field;
+ else
+ {
+ if (DECL_CONTEXT (field) != context)
+ cp_pedwarn ("ANSI C++ does not permit `%T::%D' to be defined as `%T::%D'", DECL_CONTEXT (field), DECL_NAME (decl), context, DECL_NAME (decl));
+ if (duplicate_decls (decl, field))
+ decl = field;
+ }
}
else
{
@@ -6034,25 +6073,7 @@ grok_reference_init (decl, type, init, cleanupp)
goto fail;
else if (tmp != NULL_TREE)
{
- tree subtype = TREE_TYPE (type);
init = tmp;
-
- /* Associate the cleanup with the reference so that we
- don't get burned by "aggressive" cleanup policy. */
- if (TYPE_NEEDS_DESTRUCTOR (subtype))
- {
- if (TREE_CODE (tmp) == ADDR_EXPR)
- tmp = TREE_OPERAND (tmp, 0);
- if (TREE_CODE (tmp) == TARGET_EXPR)
- {
- *cleanupp = build_delete
- (build_pointer_type (subtype),
- build_unary_op (ADDR_EXPR, TREE_OPERAND (tmp, 0), 0),
- integer_two_node, LOOKUP_NORMAL|LOOKUP_DESTRUCTOR, 0);
- TREE_OPERAND (tmp, 2) = error_mark_node;
- }
- }
-
DECL_INITIAL (decl) = save_expr (init);
}
else
@@ -6620,7 +6641,7 @@ cp_finish_decl (decl, init, asmspec_tree, need_pop, flags)
{
/* XXX: Why don't we use decl here? */
/* Ans: Because it was already expanded? */
- if (! cp_expand_decl_cleanup (NULL_TREE, cleanup))
+ if (! expand_decl_cleanup (NULL_TREE, cleanup))
cp_error ("parser lost in parsing declaration of `%D'",
decl);
/* Cleanup used up here. */
@@ -6710,7 +6731,7 @@ cp_finish_decl (decl, init, asmspec_tree, need_pop, flags)
/* Store the cleanup, if there was one. */
if (cleanup)
{
- if (! cp_expand_decl_cleanup (decl, cleanup))
+ if (! expand_decl_cleanup (decl, cleanup))
cp_error ("parser lost in parsing declaration of `%D'",
decl);
}
@@ -7113,6 +7134,8 @@ grokfndecl (ctype, type, declarator, virtualp, flags, quals,
if (check)
{
tmp = check_classfn (ctype, decl);
+ if (tmp && DECL_ARTIFICIAL (tmp))
+ cp_error ("definition of implicitly-declared `%D'", tmp);
if (tmp && duplicate_decls (decl, tmp))
return tmp;
}
@@ -7159,6 +7182,8 @@ grokfndecl (ctype, type, declarator, virtualp, flags, quals,
revert_static_member_fn (&decl, NULL, NULL);
last_function_parms = TREE_CHAIN (last_function_parms);
}
+ if (tmp && DECL_ARTIFICIAL (tmp))
+ cp_error ("definition of implicitly-declared `%D'", tmp);
if (tmp && duplicate_decls (decl, tmp))
return tmp;
}
@@ -7224,7 +7249,7 @@ grokvardecl (type, declarator, specbits, initialized, constp)
DECL_ASSEMBLER_NAME (decl) = build_static_name (basetype, declarator);
}
else
- decl = build_decl (VAR_DECL, declarator, type);
+ decl = build_decl (VAR_DECL, declarator, complete_type (type));
DECL_ASSEMBLER_NAME (decl) = current_namespace_id (DECL_ASSEMBLER_NAME (decl));
@@ -9118,7 +9143,7 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, raises, attrli
return NULL_TREE;
}
- decl = build_decl (PARM_DECL, declarator, type);
+ decl = build_decl (PARM_DECL, declarator, complete_type (type));
bad_specifiers (decl, "parameter", virtualp, quals != NULL_TREE,
inlinep, friendp, raises != NULL_TREE);
@@ -11279,7 +11304,7 @@ store_parm_decls ()
&& (cleanup = maybe_build_cleanup (parm), cleanup))
{
expand_decl (parm);
- if (! cp_expand_decl_cleanup (parm, cleanup))
+ if (! expand_decl_cleanup (parm, cleanup))
cp_error ("parser lost in parsing declaration of `%D'",
parm);
parms_have_cleanups = 1;
@@ -11973,7 +11998,7 @@ finish_function (lineno, call_poplevel, nested)
current_function_decl = NULL_TREE;
}
- named_label_uses = NULL_TREE;
+ named_label_uses = NULL;
current_class_ptr = NULL_TREE;
current_class_ref = NULL_TREE;
}
@@ -12200,7 +12225,7 @@ hack_incomplete_structures (type)
expand_decl (decl);
cleanup = maybe_build_cleanup (decl);
expand_decl_init (decl);
- if (! cp_expand_decl_cleanup (decl, cleanup))
+ if (! expand_decl_cleanup (decl, cleanup))
cp_error ("parser lost in parsing declaration of `%D'",
decl);
}