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