C++ PATCH: PR 12735
Mark Mitchell
mark@codesourcery.com
Wed Nov 12 18:19:00 GMT 2003
This patch fixes a PR where we emitted the same error message twice
for this code:
struct T { ~T(); };
int main()
{
foo:
T t;
bar:
T t;
}
Fixed by making duplicate_decls distinguish between a failed
redeclaration and a unrelated declaration.
Tested on i686-pc-linux-gnu, applied on the mainline.
I do not know how to write a test case that counts the number of times
an error message occurs, so I haven't added a test to DejaGNU for this
case.
--
Mark Mitchell
CodeSourcery, LLC
mark@codesourcery.com
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.
Index: cp-tree.h
===================================================================
RCS file: /cvs/gcc/gcc/gcc/cp/cp-tree.h,v
retrieving revision 1.931
diff -c -5 -p -r1.931 cp-tree.h
*** cp-tree.h 11 Nov 2003 22:27:31 -0000 1.931
--- cp-tree.h 12 Nov 2003 17:35:23 -0000
*************** extern void push_switch (tree);
*** 3621,3631 ****
extern void pop_switch (void);
extern void pushtag (tree, tree, int);
extern tree make_anon_name (void);
extern void clear_anon_tags (void);
extern int decls_match (tree, tree);
! extern int duplicate_decls (tree, tree);
extern tree pushdecl_top_level (tree);
extern tree pushdecl_top_level_and_finish (tree, tree);
extern tree push_using_decl (tree, tree);
extern tree implicitly_declare (tree);
extern tree declare_local_label (tree);
--- 3621,3631 ----
extern void pop_switch (void);
extern void pushtag (tree, tree, int);
extern tree make_anon_name (void);
extern void clear_anon_tags (void);
extern int decls_match (tree, tree);
! extern tree duplicate_decls (tree, tree);
extern tree pushdecl_top_level (tree);
extern tree pushdecl_top_level_and_finish (tree, tree);
extern tree push_using_decl (tree, tree);
extern tree implicitly_declare (tree);
extern tree declare_local_label (tree);
Index: decl.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/cp/decl.c,v
retrieving revision 1.1151
diff -c -5 -p -r1.1151 decl.c
*** decl.c 6 Nov 2003 22:08:23 -0000 1.1151
--- decl.c 12 Nov 2003 17:35:24 -0000
*************** warn_extern_redeclared_static (tree newd
*** 1135,1160 ****
? implicit_extern_static_warning
: explicit_extern_static_warning, newdecl);
cp_pedwarn_at ("previous declaration of `%D'", olddecl);
}
! /* Handle when a new declaration NEWDECL has the same name as an old
! one OLDDECL in the same binding contour. Prints an error message
! if appropriate.
! If safely possible, alter OLDDECL to look like NEWDECL, and return 1.
! Otherwise, return 0. */
! int
duplicate_decls (tree newdecl, tree olddecl)
{
unsigned olddecl_uid = DECL_UID (olddecl);
int olddecl_friend = 0, types_match = 0;
int new_defines_function = 0;
if (newdecl == olddecl)
! return 1;
types_match = decls_match (newdecl, olddecl);
/* If either the type of the new decl or the type of the old decl is an
error_mark_node, then that implies that we have already issued an
--- 1135,1160 ----
? implicit_extern_static_warning
: explicit_extern_static_warning, newdecl);
cp_pedwarn_at ("previous declaration of `%D'", olddecl);
}
! /* If NEWDECL is a redeclaration of OLDDECL, merge the declarations.
! If the redeclaration is invalid, a diagnostic is issued, and the
! error_mark_node is returned. Otherwise, OLDDECL is returned.
! If NEWDECL is not a redeclaration of OLDDECL, NULL_TREE is
! returned. */
! tree
duplicate_decls (tree newdecl, tree olddecl)
{
unsigned olddecl_uid = DECL_UID (olddecl);
int olddecl_friend = 0, types_match = 0;
int new_defines_function = 0;
if (newdecl == olddecl)
! return olddecl;
types_match = decls_match (newdecl, olddecl);
/* If either the type of the new decl or the type of the old decl is an
error_mark_node, then that implies that we have already issued an
*************** duplicate_decls (tree newdecl, tree oldd
*** 1203,1213 ****
{
if (TREE_CODE (newdecl) != FUNCTION_DECL)
{
/* Avoid warnings redeclaring anticipated built-ins. */
if (DECL_ANTICIPATED (olddecl))
! return 0;
/* If you declare a built-in or predefined function name as static,
the old definition is overridden, but optionally warn this was a
bad choice of name. */
if (! TREE_PUBLIC (newdecl))
--- 1203,1213 ----
{
if (TREE_CODE (newdecl) != FUNCTION_DECL)
{
/* Avoid warnings redeclaring anticipated built-ins. */
if (DECL_ANTICIPATED (olddecl))
! return NULL_TREE;
/* If you declare a built-in or predefined function name as static,
the old definition is overridden, but optionally warn this was a
bad choice of name. */
if (! TREE_PUBLIC (newdecl))
*************** duplicate_decls (tree newdecl, tree oldd
*** 1215,1225 ****
if (warn_shadow)
warning ("shadowing %s function `%#D'",
DECL_BUILT_IN (olddecl) ? "built-in" : "library",
olddecl);
/* Discard the old built-in function. */
! return 0;
}
/* If the built-in is not ansi, then programs can override
it even globally without an error. */
else if (! DECL_BUILT_IN (olddecl))
warning ("library function `%#D' redeclared as non-function `%#D'",
--- 1215,1225 ----
if (warn_shadow)
warning ("shadowing %s function `%#D'",
DECL_BUILT_IN (olddecl) ? "built-in" : "library",
olddecl);
/* Discard the old built-in function. */
! return NULL_TREE;
}
/* If the built-in is not ansi, then programs can override
it even globally without an error. */
else if (! DECL_BUILT_IN (olddecl))
warning ("library function `%#D' redeclared as non-function `%#D'",
*************** duplicate_decls (tree newdecl, tree oldd
*** 1228,1238 ****
{
error ("declaration of `%#D'", newdecl);
error ("conflicts with built-in declaration `%#D'",
olddecl);
}
! return 0;
}
else if (!types_match)
{
/* Avoid warnings redeclaring anticipated built-ins. */
if (DECL_ANTICIPATED (olddecl))
--- 1228,1238 ----
{
error ("declaration of `%#D'", newdecl);
error ("conflicts with built-in declaration `%#D'",
olddecl);
}
! return NULL_TREE;
}
else if (!types_match)
{
/* Avoid warnings redeclaring anticipated built-ins. */
if (DECL_ANTICIPATED (olddecl))
*************** duplicate_decls (tree newdecl, tree oldd
*** 1255,1265 ****
DECL_BUILT_IN (olddecl) ? "built-in" : "library",
olddecl);
}
else
/* Discard the old built-in function. */
! return 0;
/* Replace the old RTL to avoid problems with inlining. */
SET_DECL_RTL (olddecl, DECL_RTL (newdecl));
}
/* Even if the types match, prefer the new declarations type
--- 1255,1265 ----
DECL_BUILT_IN (olddecl) ? "built-in" : "library",
olddecl);
}
else
/* Discard the old built-in function. */
! return NULL_TREE;
/* Replace the old RTL to avoid problems with inlining. */
SET_DECL_RTL (olddecl, DECL_RTL (newdecl));
}
/* Even if the types match, prefer the new declarations type
*************** duplicate_decls (tree newdecl, tree oldd
*** 1300,1334 ****
/* We do nothing special here, because C++ does such nasty
things with TYPE_DECLs. Instead, just let the 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
slot of the identifier. */
! return 0;
}
if ((TREE_CODE (newdecl) == FUNCTION_DECL
&& DECL_FUNCTION_TEMPLATE_P (olddecl))
|| (TREE_CODE (olddecl) == FUNCTION_DECL
&& DECL_FUNCTION_TEMPLATE_P (newdecl)))
! return 0;
error ("`%#D' redeclared as different kind of symbol", newdecl);
if (TREE_CODE (olddecl) == TREE_LIST)
olddecl = TREE_VALUE (olddecl);
cp_error_at ("previous declaration of `%#D'", olddecl);
/* New decl is completely inconsistent with the old one =>
tell caller to replace the old one. */
! return 0;
}
else if (!types_match)
{
if (CP_DECL_CONTEXT (newdecl) != CP_DECL_CONTEXT (olddecl))
/* These are certainly not duplicate declarations; they're
from different scopes. */
! return 0;
if (TREE_CODE (newdecl) == TEMPLATE_DECL)
{
/* The name of a class template may not be declared to refer to
any other template, class, function, object, namespace, value,
--- 1300,1334 ----
/* We do nothing special here, because C++ does such nasty
things with TYPE_DECLs. Instead, just let the 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
slot of the identifier. */
! return NULL_TREE;
}
if ((TREE_CODE (newdecl) == FUNCTION_DECL
&& DECL_FUNCTION_TEMPLATE_P (olddecl))
|| (TREE_CODE (olddecl) == FUNCTION_DECL
&& DECL_FUNCTION_TEMPLATE_P (newdecl)))
! return NULL_TREE;
error ("`%#D' redeclared as different kind of symbol", newdecl);
if (TREE_CODE (olddecl) == TREE_LIST)
olddecl = TREE_VALUE (olddecl);
cp_error_at ("previous declaration of `%#D'", olddecl);
/* New decl is completely inconsistent with the old one =>
tell caller to replace the old one. */
! return NULL_TREE;
}
else if (!types_match)
{
if (CP_DECL_CONTEXT (newdecl) != CP_DECL_CONTEXT (olddecl))
/* These are certainly not duplicate declarations; they're
from different scopes. */
! return NULL_TREE;
if (TREE_CODE (newdecl) == TEMPLATE_DECL)
{
/* The name of a class template may not be declared to refer to
any other template, class, function, object, namespace, value,
*************** duplicate_decls (tree newdecl, tree oldd
*** 1352,1362 ****
TREE_TYPE (TREE_TYPE (olddecl))))
{
error ("new declaration `%#D'", newdecl);
cp_error_at ("ambiguates old declaration `%#D'", olddecl);
}
! return 0;
}
if (TREE_CODE (newdecl) == FUNCTION_DECL)
{
if (DECL_EXTERN_C_P (newdecl) && DECL_EXTERN_C_P (olddecl))
{
--- 1352,1362 ----
TREE_TYPE (TREE_TYPE (olddecl))))
{
error ("new declaration `%#D'", newdecl);
cp_error_at ("ambiguates old declaration `%#D'", olddecl);
}
! return NULL_TREE;
}
if (TREE_CODE (newdecl) == FUNCTION_DECL)
{
if (DECL_EXTERN_C_P (newdecl) && DECL_EXTERN_C_P (olddecl))
{
*************** duplicate_decls (tree newdecl, tree oldd
*** 1369,1389 ****
{
error ("new declaration `%#D'", newdecl);
cp_error_at ("ambiguates old declaration `%#D'", olddecl);
}
else
! return 0;
}
/* Already complained about this, so don't do so again. */
else if (current_class_type == NULL_TREE
|| IDENTIFIER_ERROR_LOCUS (DECL_ASSEMBLER_NAME (newdecl)) != current_class_type)
{
error ("conflicting declaration '%#D'", newdecl);
cp_error_at ("'%D' has a previous declaration as `%#D'",
olddecl, olddecl);
! return false;
}
}
else if (TREE_CODE (newdecl) == FUNCTION_DECL
&& ((DECL_TEMPLATE_SPECIALIZATION (olddecl)
&& (!DECL_TEMPLATE_INFO (newdecl)
--- 1369,1389 ----
{
error ("new declaration `%#D'", newdecl);
cp_error_at ("ambiguates old declaration `%#D'", olddecl);
}
else
! return NULL_TREE;
}
/* Already complained about this, so don't do so again. */
else if (current_class_type == NULL_TREE
|| IDENTIFIER_ERROR_LOCUS (DECL_ASSEMBLER_NAME (newdecl)) != current_class_type)
{
error ("conflicting declaration '%#D'", newdecl);
cp_error_at ("'%D' has a previous declaration as `%#D'",
olddecl, olddecl);
! return NULL_TREE;
}
}
else if (TREE_CODE (newdecl) == FUNCTION_DECL
&& ((DECL_TEMPLATE_SPECIALIZATION (olddecl)
&& (!DECL_TEMPLATE_INFO (newdecl)
*************** duplicate_decls (tree newdecl, tree oldd
*** 1399,1422 ****
specialization, and the other is an instantiation of the same
template, that we do not exit at this point. That situation
can occur if we instantiate a template class, and then
specialize one of its methods. This situation is valid, but
the declarations must be merged in the usual way. */
! return 0;
else if (TREE_CODE (newdecl) == FUNCTION_DECL
&& ((DECL_TEMPLATE_INSTANTIATION (olddecl)
&& !DECL_USE_TEMPLATE (newdecl))
|| (DECL_TEMPLATE_INSTANTIATION (newdecl)
&& !DECL_USE_TEMPLATE (olddecl))))
/* One of the declarations is a template instantiation, and the
other is not a template at all. That's OK. */
! return 0;
else if (TREE_CODE (newdecl) == NAMESPACE_DECL
&& DECL_NAMESPACE_ALIAS (newdecl)
&& DECL_NAMESPACE_ALIAS (newdecl) == DECL_NAMESPACE_ALIAS (olddecl))
! /* Redeclaration of namespace alias, ignore it. */
! return 1;
else
{
const char *errmsg = redeclaration_error_message (newdecl, olddecl);
if (errmsg)
{
--- 1399,1430 ----
specialization, and the other is an instantiation of the same
template, that we do not exit at this point. That situation
can occur if we instantiate a template class, and then
specialize one of its methods. This situation is valid, but
the declarations must be merged in the usual way. */
! return NULL_TREE;
else if (TREE_CODE (newdecl) == FUNCTION_DECL
&& ((DECL_TEMPLATE_INSTANTIATION (olddecl)
&& !DECL_USE_TEMPLATE (newdecl))
|| (DECL_TEMPLATE_INSTANTIATION (newdecl)
&& !DECL_USE_TEMPLATE (olddecl))))
/* One of the declarations is a template instantiation, and the
other is not a template at all. That's OK. */
! return NULL_TREE;
else if (TREE_CODE (newdecl) == NAMESPACE_DECL
&& DECL_NAMESPACE_ALIAS (newdecl)
&& DECL_NAMESPACE_ALIAS (newdecl) == DECL_NAMESPACE_ALIAS (olddecl))
! /* In [namespace.alias] we have:
!
! 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
{
const char *errmsg = redeclaration_error_message (newdecl, olddecl);
if (errmsg)
{
*************** duplicate_decls (tree newdecl, tree oldd
*** 1424,1434 ****
if (DECL_NAME (olddecl) != NULL_TREE)
cp_error_at ((DECL_INITIAL (olddecl)
&& namespace_bindings_p ())
? "`%#D' previously defined here"
: "`%#D' previously declared here", olddecl);
! return 0;
}
else if (TREE_CODE (olddecl) == FUNCTION_DECL
&& DECL_INITIAL (olddecl) != NULL_TREE
&& TYPE_ARG_TYPES (TREE_TYPE (olddecl)) == NULL_TREE
&& TYPE_ARG_TYPES (TREE_TYPE (newdecl)) != NULL_TREE)
--- 1432,1442 ----
if (DECL_NAME (olddecl) != NULL_TREE)
cp_error_at ((DECL_INITIAL (olddecl)
&& namespace_bindings_p ())
? "`%#D' previously defined here"
: "`%#D' previously declared here", olddecl);
! return error_mark_node;
}
else if (TREE_CODE (olddecl) == FUNCTION_DECL
&& DECL_INITIAL (olddecl) != NULL_TREE
&& TYPE_ARG_TYPES (TREE_TYPE (olddecl)) == NULL_TREE
&& TYPE_ARG_TYPES (TREE_TYPE (newdecl)) != NULL_TREE)
*************** duplicate_decls (tree newdecl, tree oldd
*** 1504,1514 ****
the attribute should apply only to the typedef. */
if (TREE_CODE (olddecl) == TYPE_DECL
&& (DECL_IMPLICIT_TYPEDEF_P (olddecl)
|| DECL_IMPLICIT_TYPEDEF_P (newdecl)))
! return 0;
/* If new decl is `static' and an `extern' was seen previously,
warn about it. */
warn_extern_redeclared_static (newdecl, olddecl);
--- 1512,1522 ----
the attribute should apply only to the typedef. */
if (TREE_CODE (olddecl) == TYPE_DECL
&& (DECL_IMPLICIT_TYPEDEF_P (olddecl)
|| DECL_IMPLICIT_TYPEDEF_P (newdecl)))
! return NULL_TREE;
/* If new decl is `static' and an `extern' was seen previously,
warn about it. */
warn_extern_redeclared_static (newdecl, olddecl);
*************** duplicate_decls (tree newdecl, tree oldd
*** 1583,1593 ****
DECL_SOURCE_LOCATION (olddecl)
= DECL_SOURCE_LOCATION (DECL_TEMPLATE_RESULT (olddecl))
= DECL_SOURCE_LOCATION (newdecl);
}
! return 1;
}
if (types_match)
{
/* Automatically handles default parameters. */
--- 1591,1601 ----
DECL_SOURCE_LOCATION (olddecl)
= DECL_SOURCE_LOCATION (DECL_TEMPLATE_RESULT (olddecl))
= DECL_SOURCE_LOCATION (newdecl);
}
! return olddecl;
}
if (types_match)
{
/* Automatically handles default parameters. */
*************** duplicate_decls (tree newdecl, tree oldd
*** 1912,1922 ****
&& (TREE_CODE (olddecl) == FUNCTION_DECL
|| (TREE_CODE (olddecl) == VAR_DECL
&& TREE_STATIC (olddecl))))
make_decl_rtl (olddecl, NULL);
! return 1;
}
/* Generate an implicit declaration for identifier FUNCTIONID
as a function of type int (). Print a warning if appropriate. */
--- 1920,1930 ----
&& (TREE_CODE (olddecl) == FUNCTION_DECL
|| (TREE_CODE (olddecl) == VAR_DECL
&& TREE_STATIC (olddecl))))
make_decl_rtl (olddecl, NULL);
! return olddecl;
}
/* Generate an implicit declaration for identifier FUNCTIONID
as a function of type int (). Print a warning if appropriate. */
*************** start_function (tree declspecs, tree dec
*** 10216,10226 ****
if (!processing_template_decl && !(flags & SF_PRE_PARSED))
{
/* A specialization is not used to guide overload resolution. */
if (!DECL_TEMPLATE_SPECIALIZATION (decl1)
&& ! DECL_FUNCTION_MEMBER_P (decl1))
! decl1 = pushdecl (decl1);
else
{
/* We need to set the DECL_CONTEXT. */
if (!DECL_CONTEXT (decl1) && DECL_TEMPLATE_INFO (decl1))
DECL_CONTEXT (decl1) = DECL_CONTEXT (DECL_TI_TEMPLATE (decl1));
--- 10224,10246 ----
if (!processing_template_decl && !(flags & SF_PRE_PARSED))
{
/* A specialization is not used to guide overload resolution. */
if (!DECL_TEMPLATE_SPECIALIZATION (decl1)
&& ! DECL_FUNCTION_MEMBER_P (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
{
/* We need to set the DECL_CONTEXT. */
if (!DECL_CONTEXT (decl1) && DECL_TEMPLATE_INFO (decl1))
DECL_CONTEXT (decl1) = DECL_CONTEXT (DECL_TI_TEMPLATE (decl1));
Index: friend.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/cp/friend.c,v
retrieving revision 1.90
diff -c -5 -p -r1.90 friend.c
*** friend.c 5 Nov 2003 13:56:01 -0000 1.90
--- friend.c 12 Nov 2003 17:35:24 -0000
*************** do_friend (tree ctype, tree declarator,
*** 453,462 ****
--- 453,465 ----
explained = 1;
}
}
}
+ if (decl == error_mark_node)
+ return error_mark_node;
+
add_friend (current_class_type,
is_friend_template ? DECL_TI_TEMPLATE (decl) : decl,
/*complain=*/true);
DECL_FRIEND_P (decl) = 1;
}
Index: name-lookup.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/cp/name-lookup.c,v
retrieving revision 1.19
diff -c -5 -p -r1.19 name-lookup.c
*** name-lookup.c 11 Nov 2003 22:27:31 -0000 1.19
--- name-lookup.c 12 Nov 2003 17:35:24 -0000
*************** pushdecl (tree x)
*** 678,714 ****
TREE_TYPE (x));
/* Throw away the redeclaration. */
POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, t);
}
! else if (TREE_CODE (t) != TREE_CODE (x))
! {
! 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
! 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);
}
}
check_template_shadow (x);
--- 678,719 ----
TREE_TYPE (x));
/* Throw away the redeclaration. */
POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, t);
}
! else
{
! tree olddecl = duplicate_decls (x, t);
!
! /* If the redeclaration failed, we can stop at this
! 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);
! POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, t);
! }
! else if (DECL_MAIN_P (x))
! {
! /* A redeclaration of main, but not a duplicate of the
! 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);
! }
}
}
check_template_shadow (x);
*************** push_overloaded_decl (tree decl, int fla
*** 1980,1990 ****
&& compparms (TYPE_ARG_TYPES (TREE_TYPE (fn)),
TYPE_ARG_TYPES (TREE_TYPE (decl))))
error ("`%#D' conflicts with previous using declaration `%#D'",
decl, fn);
! if (duplicate_decls (decl, fn))
POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, fn);
}
}
else if (old == error_mark_node)
/* Ignore the undefined symbol marker. */
--- 1985,1995 ----
&& compparms (TYPE_ARG_TYPES (TREE_TYPE (fn)),
TYPE_ARG_TYPES (TREE_TYPE (decl))))
error ("`%#D' conflicts with previous using declaration `%#D'",
decl, fn);
! if (duplicate_decls (decl, fn) == fn)
POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, fn);
}
}
else if (old == error_mark_node)
/* Ignore the undefined symbol marker. */
More information about the Gcc-patches
mailing list