Commit 72c4a4ca by Geoffrey Keating Committed by Geoffrey Keating

decl.c (poplevel): Check DECL_INITIAL invariant.

	* decl.c (poplevel): Check DECL_INITIAL invariant.
	(duplicate_decls): Preserve DECL_INITIAL when eliminating
	a new definition in favour of an old declaration.
	(start_preparsed_function): Define and document value of
	DECL_INITIAL before and after routine.
	(finish_function): Check DECL_INITIAL invariant.
	* parser.c 
	(cp_parser_function_definition_from_specifiers_and_declarator): 
	Skip duplicate function definitions.

From-SVN: r119427
parent 01975fc7
2006-12-01 Geoffrey Keating <geoffk@apple.com>
* decl.c (poplevel): Check DECL_INITIAL invariant.
(duplicate_decls): Preserve DECL_INITIAL when eliminating
a new definition in favour of an old declaration.
(start_preparsed_function): Define and document value of
DECL_INITIAL before and after routine.
(finish_function): Check DECL_INITIAL invariant.
* parser.c
(cp_parser_function_definition_from_specifiers_and_declarator):
Skip duplicate function definitions.
2006-12-01 Volker Reichelt <reichelt@igpm.rwth-aachen.de> 2006-12-01 Volker Reichelt <reichelt@igpm.rwth-aachen.de>
PR c++/30022 PR c++/30022
......
...@@ -756,7 +756,12 @@ poplevel (int keep, int reverse, int functionbody) ...@@ -756,7 +756,12 @@ poplevel (int keep, int reverse, int functionbody)
leave_scope (); leave_scope ();
if (functionbody) if (functionbody)
DECL_INITIAL (current_function_decl) = block; {
/* The current function is being defined, so its DECL_INITIAL
should be error_mark_node. */
gcc_assert (DECL_INITIAL (current_function_decl) == error_mark_node);
DECL_INITIAL (current_function_decl) = block;
}
else if (block) else if (block)
current_binding_level->blocks current_binding_level->blocks
= chainon (current_binding_level->blocks, block); = chainon (current_binding_level->blocks, block);
...@@ -1632,13 +1637,15 @@ duplicate_decls (tree newdecl, tree olddecl, bool newdecl_is_friend) ...@@ -1632,13 +1637,15 @@ duplicate_decls (tree newdecl, tree olddecl, bool newdecl_is_friend)
} }
/* If the new declaration is a definition, update the file and /* If the new declaration is a definition, update the file and
line information on the declaration. */ line information on the declaration, and also make
the old declaration the same definition. */
if (DECL_INITIAL (old_result) == NULL_TREE if (DECL_INITIAL (old_result) == NULL_TREE
&& DECL_INITIAL (new_result) != NULL_TREE) && DECL_INITIAL (new_result) != NULL_TREE)
{ {
DECL_SOURCE_LOCATION (olddecl) DECL_SOURCE_LOCATION (olddecl)
= DECL_SOURCE_LOCATION (old_result) = DECL_SOURCE_LOCATION (old_result)
= DECL_SOURCE_LOCATION (newdecl); = DECL_SOURCE_LOCATION (newdecl);
DECL_INITIAL (old_result) = DECL_INITIAL (new_result);
if (DECL_FUNCTION_TEMPLATE_P (newdecl)) if (DECL_FUNCTION_TEMPLATE_P (newdecl))
DECL_ARGUMENTS (old_result) DECL_ARGUMENTS (old_result)
= DECL_ARGUMENTS (new_result); = DECL_ARGUMENTS (new_result);
...@@ -10374,7 +10381,13 @@ check_function_type (tree decl, tree current_function_parms) ...@@ -10374,7 +10381,13 @@ check_function_type (tree decl, tree current_function_parms)
For C++, we must first check whether that datum makes any sense. For C++, we must first check whether that datum makes any sense.
For example, "class A local_a(1,2);" means that variable local_a For example, "class A local_a(1,2);" means that variable local_a
is an aggregate of type A, which should have a constructor is an aggregate of type A, which should have a constructor
applied to it with the argument list [1, 2]. */ applied to it with the argument list [1, 2].
On entry, DECL_INITIAL (decl1) should be NULL_TREE or error_mark_node,
or may be a BLOCK if the function has been defined previously
in this translation unit. On exit, DECL_INITIAL (decl1) will be
error_mark_node if the function has never been defined, or
a BLOCK if the function has been defined somewhere. */
void void
start_preparsed_function (tree decl1, tree attrs, int flags) start_preparsed_function (tree decl1, tree attrs, int flags)
...@@ -10503,24 +10516,6 @@ start_preparsed_function (tree decl1, tree attrs, int flags) ...@@ -10503,24 +10516,6 @@ start_preparsed_function (tree decl1, tree attrs, int flags)
cp_apply_type_quals_to_decl (cp_type_quals (restype), resdecl); cp_apply_type_quals_to_decl (cp_type_quals (restype), resdecl);
} }
/* Initialize RTL machinery. We cannot do this until
CURRENT_FUNCTION_DECL and DECL_RESULT are set up. We do this
even when processing a template; this is how we get
CFUN set up, and our per-function variables initialized.
FIXME factor out the non-RTL stuff. */
bl = current_binding_level;
allocate_struct_function (decl1);
current_binding_level = bl;
/* Even though we're inside a function body, we still don't want to
call expand_expr to calculate the size of a variable-sized array.
We haven't necessarily assigned RTL to all variables yet, so it's
not safe to try to expand expressions involving them. */
cfun->x_dont_save_pending_sizes_p = 1;
/* Start the statement-tree, start the tree now. */
DECL_SAVED_TREE (decl1) = push_stmt_list ();
/* Let the user know we're compiling this function. */ /* Let the user know we're compiling this function. */
announce_function (decl1); announce_function (decl1);
...@@ -10566,9 +10561,33 @@ start_preparsed_function (tree decl1, tree attrs, int flags) ...@@ -10566,9 +10561,33 @@ start_preparsed_function (tree decl1, tree attrs, int flags)
maybe_apply_pragma_weak (decl1); maybe_apply_pragma_weak (decl1);
} }
/* Reset these in case the call to pushdecl changed them. */ /* Reset this in case the call to pushdecl changed it. */
current_function_decl = decl1; current_function_decl = decl1;
cfun->decl = decl1;
gcc_assert (DECL_INITIAL (decl1));
/* This function may already have been parsed, in which case just
return; our caller will skip over the body without parsing. */
if (DECL_INITIAL (decl1) != error_mark_node)
return;
/* Initialize RTL machinery. We cannot do this until
CURRENT_FUNCTION_DECL and DECL_RESULT are set up. We do this
even when processing a template; this is how we get
CFUN set up, and our per-function variables initialized.
FIXME factor out the non-RTL stuff. */
bl = current_binding_level;
allocate_struct_function (decl1);
current_binding_level = bl;
/* Even though we're inside a function body, we still don't want to
call expand_expr to calculate the size of a variable-sized array.
We haven't necessarily assigned RTL to all variables yet, so it's
not safe to try to expand expressions involving them. */
cfun->x_dont_save_pending_sizes_p = 1;
/* Start the statement-tree, start the tree now. */
DECL_SAVED_TREE (decl1) = push_stmt_list ();
/* If we are (erroneously) defining a function that we have already /* If we are (erroneously) defining a function that we have already
defined before, wipe out what we knew before. */ defined before, wipe out what we knew before. */
...@@ -11077,6 +11096,10 @@ finish_function (int flags) ...@@ -11077,6 +11096,10 @@ finish_function (int flags)
which then got a warning when stored in a ptr-to-function variable. */ which then got a warning when stored in a ptr-to-function variable. */
gcc_assert (building_stmt_tree ()); gcc_assert (building_stmt_tree ());
/* The current function is being defined, so its DECL_INITIAL should
be set, and unless there's a multiple definition, it should be
error_mark_node. */
gcc_assert (DECL_INITIAL (fndecl) == error_mark_node);
/* For a cloned function, we've already got all the code we need; /* For a cloned function, we've already got all the code we need;
there's no need to add any extra bits. */ there's no need to add any extra bits. */
......
...@@ -407,10 +407,6 @@ use_thunk (tree thunk_fndecl, bool emit_p) ...@@ -407,10 +407,6 @@ use_thunk (tree thunk_fndecl, bool emit_p)
} }
} }
/* The back-end expects DECL_INITIAL to contain a BLOCK, so we
create one. */
DECL_INITIAL (thunk_fndecl) = make_node (BLOCK);
/* Set up cloned argument trees for the thunk. */ /* Set up cloned argument trees for the thunk. */
t = NULL_TREE; t = NULL_TREE;
for (a = DECL_ARGUMENTS (function); a; a = TREE_CHAIN (a)) for (a = DECL_ARGUMENTS (function); a; a = TREE_CHAIN (a))
...@@ -424,17 +420,23 @@ use_thunk (tree thunk_fndecl, bool emit_p) ...@@ -424,17 +420,23 @@ use_thunk (tree thunk_fndecl, bool emit_p)
} }
a = nreverse (t); a = nreverse (t);
DECL_ARGUMENTS (thunk_fndecl) = a; DECL_ARGUMENTS (thunk_fndecl) = a;
BLOCK_VARS (DECL_INITIAL (thunk_fndecl)) = a;
if (this_adjusting if (this_adjusting
&& targetm.asm_out.can_output_mi_thunk (thunk_fndecl, fixed_offset, && targetm.asm_out.can_output_mi_thunk (thunk_fndecl, fixed_offset,
virtual_value, alias)) virtual_value, alias))
{ {
const char *fnname; const char *fnname;
tree fn_block;
current_function_decl = thunk_fndecl; current_function_decl = thunk_fndecl;
DECL_RESULT (thunk_fndecl) DECL_RESULT (thunk_fndecl)
= build_decl (RESULT_DECL, 0, integer_type_node); = build_decl (RESULT_DECL, 0, integer_type_node);
fnname = XSTR (XEXP (DECL_RTL (thunk_fndecl), 0), 0); fnname = XSTR (XEXP (DECL_RTL (thunk_fndecl), 0), 0);
/* The back-end expects DECL_INITIAL to contain a BLOCK, so we
create one. */
fn_block = make_node (BLOCK);
BLOCK_VARS (fn_block) = a;
DECL_INITIAL (thunk_fndecl) = fn_block;
init_function_start (thunk_fndecl); init_function_start (thunk_fndecl);
current_function_is_thunk = 1; current_function_is_thunk = 1;
assemble_start_function (thunk_fndecl, fnname); assemble_start_function (thunk_fndecl, fnname);
......
...@@ -15583,6 +15583,16 @@ cp_parser_function_definition_from_specifiers_and_declarator ...@@ -15583,6 +15583,16 @@ cp_parser_function_definition_from_specifiers_and_declarator
cp_parser_skip_to_end_of_block_or_statement (parser); cp_parser_skip_to_end_of_block_or_statement (parser);
fn = error_mark_node; fn = error_mark_node;
} }
else if (DECL_INITIAL (current_function_decl) != error_mark_node)
{
/* Seen already, skip it. An error message has already been output. */
cp_parser_skip_to_end_of_block_or_statement (parser);
fn = current_function_decl;
current_function_decl = NULL_TREE;
/* If this is a function from a class, pop the nested class. */
if (current_class_name)
pop_nested_class ();
}
else else
fn = cp_parser_function_definition_after_declarator (parser, fn = cp_parser_function_definition_after_declarator (parser,
/*inline_p=*/false); /*inline_p=*/false);
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment