Commit b1a19c7c by Mark Mitchell Committed by Mark Mitchell

re PR c++/12735 (duplicate error messages for redeclaration errors)

	PR c++/12735
	* cp-tree.h (duplicate_decls): Return a tree.
	* decl.c (duplicate_decls): Clarify documentation.  Return
	error_mark_node to indicate a failed redeclaration.
	* friend.c (do_friend): Handle that case.
	* name-lookup.c (pushdecl): Likewise.

From-SVN: r73503
parent 3197c4fd
2003-11-12 Mark Mitchell <mark@codesourcery.com>
PR c++/12735
* cp-tree.h (duplicate_decls): Return a tree.
* decl.c (duplicate_decls): Clarify documentation. Return
error_mark_node to indicate a failed redeclaration.
* friend.c (do_friend): Handle that case.
* name-lookup.c (pushdecl): Likewise.
2003-11-11 Jason Merrill <jason@redhat.com> 2003-11-11 Jason Merrill <jason@redhat.com>
* cp-tree.h (DECL_NAMESPACE_ASSOCIATIONS): New macro. * cp-tree.h (DECL_NAMESPACE_ASSOCIATIONS): New macro.
......
...@@ -3623,7 +3623,7 @@ extern void pushtag (tree, tree, int); ...@@ -3623,7 +3623,7 @@ extern void pushtag (tree, tree, int);
extern tree make_anon_name (void); extern tree make_anon_name (void);
extern void clear_anon_tags (void); extern void clear_anon_tags (void);
extern int decls_match (tree, tree); extern int decls_match (tree, tree);
extern int duplicate_decls (tree, tree); extern tree duplicate_decls (tree, tree);
extern tree pushdecl_top_level (tree); extern tree pushdecl_top_level (tree);
extern tree pushdecl_top_level_and_finish (tree, tree); extern tree pushdecl_top_level_and_finish (tree, tree);
extern tree push_using_decl (tree, tree); extern tree push_using_decl (tree, tree);
......
...@@ -1137,14 +1137,14 @@ warn_extern_redeclared_static (tree newdecl, tree olddecl) ...@@ -1137,14 +1137,14 @@ warn_extern_redeclared_static (tree newdecl, tree olddecl)
cp_pedwarn_at ("previous declaration of `%D'", olddecl); cp_pedwarn_at ("previous declaration of `%D'", olddecl);
} }
/* Handle when a new declaration NEWDECL has the same name as an old /* If NEWDECL is a redeclaration of OLDDECL, merge the declarations.
one OLDDECL in the same binding contour. Prints an error message If the redeclaration is invalid, a diagnostic is issued, and the
if appropriate. error_mark_node is returned. Otherwise, OLDDECL is returned.
If safely possible, alter OLDDECL to look like NEWDECL, and return 1. If NEWDECL is not a redeclaration of OLDDECL, NULL_TREE is
Otherwise, return 0. */ returned. */
int tree
duplicate_decls (tree newdecl, tree olddecl) duplicate_decls (tree newdecl, tree olddecl)
{ {
unsigned olddecl_uid = DECL_UID (olddecl); unsigned olddecl_uid = DECL_UID (olddecl);
...@@ -1152,7 +1152,7 @@ duplicate_decls (tree newdecl, tree olddecl) ...@@ -1152,7 +1152,7 @@ duplicate_decls (tree newdecl, tree olddecl)
int new_defines_function = 0; int new_defines_function = 0;
if (newdecl == olddecl) if (newdecl == olddecl)
return 1; return olddecl;
types_match = decls_match (newdecl, olddecl); types_match = decls_match (newdecl, olddecl);
...@@ -1205,7 +1205,7 @@ duplicate_decls (tree newdecl, tree olddecl) ...@@ -1205,7 +1205,7 @@ duplicate_decls (tree newdecl, tree olddecl)
{ {
/* Avoid warnings redeclaring anticipated built-ins. */ /* Avoid warnings redeclaring anticipated built-ins. */
if (DECL_ANTICIPATED (olddecl)) if (DECL_ANTICIPATED (olddecl))
return 0; return NULL_TREE;
/* If you declare a built-in or predefined function name as static, /* If you declare a built-in or predefined function name as static,
the old definition is overridden, but optionally warn this was a the old definition is overridden, but optionally warn this was a
...@@ -1217,7 +1217,7 @@ duplicate_decls (tree newdecl, tree olddecl) ...@@ -1217,7 +1217,7 @@ duplicate_decls (tree newdecl, tree olddecl)
DECL_BUILT_IN (olddecl) ? "built-in" : "library", DECL_BUILT_IN (olddecl) ? "built-in" : "library",
olddecl); olddecl);
/* Discard the old built-in function. */ /* Discard the old built-in function. */
return 0; return NULL_TREE;
} }
/* If the built-in is not ansi, then programs can override /* If the built-in is not ansi, then programs can override
it even globally without an error. */ it even globally without an error. */
...@@ -1230,7 +1230,7 @@ duplicate_decls (tree newdecl, tree olddecl) ...@@ -1230,7 +1230,7 @@ duplicate_decls (tree newdecl, tree olddecl)
error ("conflicts with built-in declaration `%#D'", error ("conflicts with built-in declaration `%#D'",
olddecl); olddecl);
} }
return 0; return NULL_TREE;
} }
else if (!types_match) else if (!types_match)
{ {
...@@ -1257,7 +1257,7 @@ duplicate_decls (tree newdecl, tree olddecl) ...@@ -1257,7 +1257,7 @@ duplicate_decls (tree newdecl, tree olddecl)
} }
else else
/* Discard the old built-in function. */ /* Discard the old built-in function. */
return 0; return NULL_TREE;
/* Replace the old RTL to avoid problems with inlining. */ /* Replace the old RTL to avoid problems with inlining. */
SET_DECL_RTL (olddecl, DECL_RTL (newdecl)); SET_DECL_RTL (olddecl, DECL_RTL (newdecl));
...@@ -1302,14 +1302,14 @@ duplicate_decls (tree newdecl, tree olddecl) ...@@ -1302,14 +1302,14 @@ duplicate_decls (tree newdecl, tree olddecl)
get shadowed, and know that if we need to find a TYPE_DECL get shadowed, and know that if we need to find a TYPE_DECL
for a given name, we can look in the IDENTIFIER_TYPE_VALUE for a given name, we can look in the IDENTIFIER_TYPE_VALUE
slot of the identifier. */ slot of the identifier. */
return 0; return NULL_TREE;
} }
if ((TREE_CODE (newdecl) == FUNCTION_DECL if ((TREE_CODE (newdecl) == FUNCTION_DECL
&& DECL_FUNCTION_TEMPLATE_P (olddecl)) && DECL_FUNCTION_TEMPLATE_P (olddecl))
|| (TREE_CODE (olddecl) == FUNCTION_DECL || (TREE_CODE (olddecl) == FUNCTION_DECL
&& DECL_FUNCTION_TEMPLATE_P (newdecl))) && DECL_FUNCTION_TEMPLATE_P (newdecl)))
return 0; return NULL_TREE;
error ("`%#D' redeclared as different kind of symbol", newdecl); error ("`%#D' redeclared as different kind of symbol", newdecl);
if (TREE_CODE (olddecl) == TREE_LIST) if (TREE_CODE (olddecl) == TREE_LIST)
...@@ -1319,14 +1319,14 @@ duplicate_decls (tree newdecl, tree olddecl) ...@@ -1319,14 +1319,14 @@ duplicate_decls (tree newdecl, tree olddecl)
/* New decl is completely inconsistent with the old one => /* New decl is completely inconsistent with the old one =>
tell caller to replace the old one. */ tell caller to replace the old one. */
return 0; return NULL_TREE;
} }
else if (!types_match) else if (!types_match)
{ {
if (CP_DECL_CONTEXT (newdecl) != CP_DECL_CONTEXT (olddecl)) if (CP_DECL_CONTEXT (newdecl) != CP_DECL_CONTEXT (olddecl))
/* These are certainly not duplicate declarations; they're /* These are certainly not duplicate declarations; they're
from different scopes. */ from different scopes. */
return 0; return NULL_TREE;
if (TREE_CODE (newdecl) == TEMPLATE_DECL) if (TREE_CODE (newdecl) == TEMPLATE_DECL)
{ {
...@@ -1354,7 +1354,7 @@ duplicate_decls (tree newdecl, tree olddecl) ...@@ -1354,7 +1354,7 @@ duplicate_decls (tree newdecl, tree olddecl)
error ("new declaration `%#D'", newdecl); error ("new declaration `%#D'", newdecl);
cp_error_at ("ambiguates old declaration `%#D'", olddecl); cp_error_at ("ambiguates old declaration `%#D'", olddecl);
} }
return 0; return NULL_TREE;
} }
if (TREE_CODE (newdecl) == FUNCTION_DECL) if (TREE_CODE (newdecl) == FUNCTION_DECL)
{ {
...@@ -1371,7 +1371,7 @@ duplicate_decls (tree newdecl, tree olddecl) ...@@ -1371,7 +1371,7 @@ duplicate_decls (tree newdecl, tree olddecl)
cp_error_at ("ambiguates old declaration `%#D'", olddecl); cp_error_at ("ambiguates old declaration `%#D'", olddecl);
} }
else else
return 0; return NULL_TREE;
} }
/* Already complained about this, so don't do so again. */ /* Already complained about this, so don't do so again. */
...@@ -1381,7 +1381,7 @@ duplicate_decls (tree newdecl, tree olddecl) ...@@ -1381,7 +1381,7 @@ duplicate_decls (tree newdecl, tree olddecl)
error ("conflicting declaration '%#D'", newdecl); error ("conflicting declaration '%#D'", newdecl);
cp_error_at ("'%D' has a previous declaration as `%#D'", cp_error_at ("'%D' has a previous declaration as `%#D'",
olddecl, olddecl); olddecl, olddecl);
return false; return NULL_TREE;
} }
} }
else if (TREE_CODE (newdecl) == FUNCTION_DECL else if (TREE_CODE (newdecl) == FUNCTION_DECL
...@@ -1401,7 +1401,7 @@ duplicate_decls (tree newdecl, tree olddecl) ...@@ -1401,7 +1401,7 @@ duplicate_decls (tree newdecl, tree olddecl)
can occur if we instantiate a template class, and then can occur if we instantiate a template class, and then
specialize one of its methods. This situation is valid, but specialize one of its methods. This situation is valid, but
the declarations must be merged in the usual way. */ the declarations must be merged in the usual way. */
return 0; return NULL_TREE;
else if (TREE_CODE (newdecl) == FUNCTION_DECL else if (TREE_CODE (newdecl) == FUNCTION_DECL
&& ((DECL_TEMPLATE_INSTANTIATION (olddecl) && ((DECL_TEMPLATE_INSTANTIATION (olddecl)
&& !DECL_USE_TEMPLATE (newdecl)) && !DECL_USE_TEMPLATE (newdecl))
...@@ -1409,12 +1409,20 @@ duplicate_decls (tree newdecl, tree olddecl) ...@@ -1409,12 +1409,20 @@ duplicate_decls (tree newdecl, tree olddecl)
&& !DECL_USE_TEMPLATE (olddecl)))) && !DECL_USE_TEMPLATE (olddecl))))
/* One of the declarations is a template instantiation, and the /* One of the declarations is a template instantiation, and the
other is not a template at all. That's OK. */ other is not a template at all. That's OK. */
return 0; return NULL_TREE;
else if (TREE_CODE (newdecl) == NAMESPACE_DECL else if (TREE_CODE (newdecl) == NAMESPACE_DECL
&& DECL_NAMESPACE_ALIAS (newdecl) && DECL_NAMESPACE_ALIAS (newdecl)
&& DECL_NAMESPACE_ALIAS (newdecl) == DECL_NAMESPACE_ALIAS (olddecl)) && DECL_NAMESPACE_ALIAS (newdecl) == DECL_NAMESPACE_ALIAS (olddecl))
/* Redeclaration of namespace alias, ignore it. */ /* In [namespace.alias] we have:
return 1;
In a declarative region, a namespace-alias-definition can be
used to redefine a namespace-alias declared in that declarative
region to refer only to the namespace to which it already
refers.
Therefore, if we encounter a second alias directive for the same
alias, we can just ignore the second directive. */
return olddecl;
else else
{ {
const char *errmsg = redeclaration_error_message (newdecl, olddecl); const char *errmsg = redeclaration_error_message (newdecl, olddecl);
...@@ -1426,7 +1434,7 @@ duplicate_decls (tree newdecl, tree olddecl) ...@@ -1426,7 +1434,7 @@ duplicate_decls (tree newdecl, tree olddecl)
&& namespace_bindings_p ()) && namespace_bindings_p ())
? "`%#D' previously defined here" ? "`%#D' previously defined here"
: "`%#D' previously declared here", olddecl); : "`%#D' previously declared here", olddecl);
return 0; return error_mark_node;
} }
else if (TREE_CODE (olddecl) == FUNCTION_DECL else if (TREE_CODE (olddecl) == FUNCTION_DECL
&& DECL_INITIAL (olddecl) != NULL_TREE && DECL_INITIAL (olddecl) != NULL_TREE
...@@ -1506,7 +1514,7 @@ duplicate_decls (tree newdecl, tree olddecl) ...@@ -1506,7 +1514,7 @@ duplicate_decls (tree newdecl, tree olddecl)
if (TREE_CODE (olddecl) == TYPE_DECL if (TREE_CODE (olddecl) == TYPE_DECL
&& (DECL_IMPLICIT_TYPEDEF_P (olddecl) && (DECL_IMPLICIT_TYPEDEF_P (olddecl)
|| DECL_IMPLICIT_TYPEDEF_P (newdecl))) || DECL_IMPLICIT_TYPEDEF_P (newdecl)))
return 0; return NULL_TREE;
/* If new decl is `static' and an `extern' was seen previously, /* If new decl is `static' and an `extern' was seen previously,
warn about it. */ warn about it. */
...@@ -1585,7 +1593,7 @@ duplicate_decls (tree newdecl, tree olddecl) ...@@ -1585,7 +1593,7 @@ duplicate_decls (tree newdecl, tree olddecl)
= DECL_SOURCE_LOCATION (newdecl); = DECL_SOURCE_LOCATION (newdecl);
} }
return 1; return olddecl;
} }
if (types_match) if (types_match)
...@@ -1914,7 +1922,7 @@ duplicate_decls (tree newdecl, tree olddecl) ...@@ -1914,7 +1922,7 @@ duplicate_decls (tree newdecl, tree olddecl)
&& TREE_STATIC (olddecl)))) && TREE_STATIC (olddecl))))
make_decl_rtl (olddecl, NULL); make_decl_rtl (olddecl, NULL);
return 1; return olddecl;
} }
/* Generate an implicit declaration for identifier FUNCTIONID /* Generate an implicit declaration for identifier FUNCTIONID
...@@ -10218,7 +10226,19 @@ start_function (tree declspecs, tree declarator, tree attrs, int flags) ...@@ -10218,7 +10226,19 @@ start_function (tree declspecs, tree declarator, tree attrs, int flags)
/* A specialization is not used to guide overload resolution. */ /* A specialization is not used to guide overload resolution. */
if (!DECL_TEMPLATE_SPECIALIZATION (decl1) if (!DECL_TEMPLATE_SPECIALIZATION (decl1)
&& ! DECL_FUNCTION_MEMBER_P (decl1)) && ! DECL_FUNCTION_MEMBER_P (decl1))
decl1 = pushdecl (decl1); {
tree olddecl = pushdecl (decl1);
if (olddecl == error_mark_node)
/* If something went wrong when registering the declaration,
use DECL1; we have to have a FUNCTION_DECL to use when
parsing the body of the function. */
;
else
/* Otherwise, OLDDECL is either a previous declaration of
the same function or DECL1 itself. */
decl1 = olddecl;
}
else else
{ {
/* We need to set the DECL_CONTEXT. */ /* We need to set the DECL_CONTEXT. */
......
...@@ -455,6 +455,9 @@ do_friend (tree ctype, tree declarator, tree decl, tree parmdecls, ...@@ -455,6 +455,9 @@ do_friend (tree ctype, tree declarator, tree decl, tree parmdecls,
} }
} }
if (decl == error_mark_node)
return error_mark_node;
add_friend (current_class_type, add_friend (current_class_type,
is_friend_template ? DECL_TI_TEMPLATE (decl) : decl, is_friend_template ? DECL_TI_TEMPLATE (decl) : decl,
/*complain=*/true); /*complain=*/true);
......
...@@ -680,33 +680,38 @@ pushdecl (tree x) ...@@ -680,33 +680,38 @@ pushdecl (tree x)
/* Throw away the redeclaration. */ /* Throw away the redeclaration. */
POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, t); POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, t);
} }
else if (TREE_CODE (t) != TREE_CODE (x)) else
{
if (duplicate_decls (x, t))
POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, t);
}
else if (duplicate_decls (x, t))
{
if (TREE_CODE (t) == TYPE_DECL)
SET_IDENTIFIER_TYPE_VALUE (name, TREE_TYPE (t));
else if (TREE_CODE (t) == FUNCTION_DECL)
check_default_args (t);
POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, t);
}
else if (DECL_MAIN_P (x))
{ {
/* A redeclaration of main, but not a duplicate of the tree olddecl = duplicate_decls (x, t);
previous one.
/* If the redeclaration failed, we can stop at this
[basic.start.main] point. */
if (olddecl == error_mark_node)
POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, error_mark_node);
if (olddecl)
{
if (TREE_CODE (t) == TYPE_DECL)
SET_IDENTIFIER_TYPE_VALUE (name, TREE_TYPE (t));
else if (TREE_CODE (t) == FUNCTION_DECL)
check_default_args (t);
This function shall not be overloaded. */ POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, t);
cp_error_at ("invalid redeclaration of `%D'", t); }
error ("as `%D'", x); else if (DECL_MAIN_P (x))
/* We don't try to push this declaration since that {
causes a crash. */ /* A redeclaration of main, but not a duplicate of the
POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, x); previous one.
[basic.start.main]
This function shall not be overloaded. */
cp_error_at ("invalid redeclaration of `%D'", t);
error ("as `%D'", x);
/* We don't try to push this declaration since that
causes a crash. */
POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, x);
}
} }
} }
...@@ -1982,7 +1987,7 @@ push_overloaded_decl (tree decl, int flags) ...@@ -1982,7 +1987,7 @@ push_overloaded_decl (tree decl, int flags)
error ("`%#D' conflicts with previous using declaration `%#D'", error ("`%#D' conflicts with previous using declaration `%#D'",
decl, fn); decl, fn);
if (duplicate_decls (decl, fn)) if (duplicate_decls (decl, fn) == fn)
POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, fn); POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, fn);
} }
} }
......
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