FreeBSD/contrib/gcc/cp/decl.c
/* Return zero if the declaration NEWDECL is valid
   when the declaration OLDDECL (assumed to be for the same name)
   has already been seen.
   Otherwise return an error message format string with a %s
   where the identifier should go.  */
Return zero if the declaration NEWDECL is valid
when the declaration OLDDECL (assumed to be for the same name)
has already been seen.
Otherwise return an error message format string with a %s
where the identifier should go.
Return zero if the declaration NEWDECL is valid when the declaration OLDDECL ( assumed to be for the same name ) has already been seen . Otherwise return an error message format string with a %s where the identifier should go .
static const char *
redeclaration_error_message (tree newdecl, tree olddecl)
{
  if (TREE_CODE (newdecl) == TYPE_DECL)
    {
      if (same_type_p (TREE_TYPE (newdecl), TREE_TYPE (olddecl)))
	return NULL;
      else
	return "redefinition of %q#D";
    }
  else if (TREE_CODE (newdecl) == FUNCTION_DECL)
    {
      if (DECL_LANG_SPECIFIC (olddecl) && DECL_PURE_VIRTUAL_P (olddecl)
	  && DECL_INITIAL (olddecl) == NULL_TREE)
	return NULL;
      if (DECL_NAMESPACE_SCOPE_P (olddecl)
	  && DECL_CONTEXT (olddecl) != DECL_CONTEXT (newdecl)
	  && ! decls_match (olddecl, newdecl))
	return "%qD conflicts with used function";
      if (DECL_INITIAL (olddecl) != NULL_TREE
	  && DECL_INITIAL (newdecl) != NULL_TREE)
	{
	  if (DECL_NAME (olddecl) == NULL_TREE)
	    return "%q#D not declared in class";
	  else
	    return "redefinition of %q#D";
	}
      return NULL;
    }
  else if (TREE_CODE (newdecl) == TEMPLATE_DECL)
    {
      tree nt, ot;
      if (TREE_CODE (DECL_TEMPLATE_RESULT (newdecl)) == TYPE_DECL)
	{
	  if (COMPLETE_TYPE_P (TREE_TYPE (newdecl))
	      && COMPLETE_TYPE_P (TREE_TYPE (olddecl)))
	    return "redefinition of %q#D";
	  return NULL;
	}
      if (TREE_CODE (DECL_TEMPLATE_RESULT (newdecl)) != FUNCTION_DECL
	  || (DECL_TEMPLATE_RESULT (newdecl)
	      == DECL_TEMPLATE_RESULT (olddecl)))
	return NULL;
      nt = DECL_TEMPLATE_RESULT (newdecl);
      if (DECL_TEMPLATE_INFO (nt))
	nt = DECL_TEMPLATE_RESULT (template_for_substitution (nt));
      ot = DECL_TEMPLATE_RESULT (olddecl);
      if (DECL_TEMPLATE_INFO (ot))
	ot = DECL_TEMPLATE_RESULT (template_for_substitution (ot));
      if (DECL_INITIAL (nt) && DECL_INITIAL (ot))
	return "redefinition of %q#D";
      return NULL;
    }
  else if (TREE_CODE (newdecl) == VAR_DECL
	   && DECL_THREAD_LOCAL_P (newdecl) != DECL_THREAD_LOCAL_P (olddecl)
	   && (! DECL_LANG_SPECIFIC (olddecl)
	       || ! CP_DECL_THREADPRIVATE_P (olddecl)
	       || DECL_THREAD_LOCAL_P (newdecl)))
    {
      if (DECL_THREAD_LOCAL_P (newdecl))
	return "thread-local declaration of %q#D follows "
	       "non-thread-local declaration";
      else
	return "non-thread-local declaration of %q#D follows "
	       "thread-local declaration";
    }
  else if (toplevel_bindings_p () || DECL_NAMESPACE_SCOPE_P (newdecl))
    {
      if (DECL_ANON_UNION_VAR_P (newdecl)
	  || DECL_ANON_UNION_VAR_P (olddecl))
	return "redeclaration of %q#D";
      if (DECL_EXTERNAL (newdecl) || DECL_EXTERNAL (olddecl))
	return NULL;
      return "redefinition of %q#D";
    }
  else
    {
      if (!(DECL_EXTERNAL (newdecl) && DECL_EXTERNAL (olddecl)))
	return "redeclaration of %q#D";
      return NULL;
    }
}
static const char * redeclaration_error_message ( tree newdecl , tree olddecl ) { if ( TREE_CODE ( newdecl ) == TYPE_DECL ) { if ( same_type_p ( TREE_TYPE ( newdecl ) , TREE_TYPE ( olddecl ) ) ) return NULL ; else return " " ; } else if ( TREE_CODE ( newdecl ) == FUNCTION_DECL ) { if ( DECL_LANG_SPECIFIC ( olddecl ) && DECL_PURE_VIRTUAL_P ( olddecl ) && DECL_INITIAL ( olddecl ) == NULL_TREE ) return NULL ; if ( DECL_NAMESPACE_SCOPE_P ( olddecl ) && DECL_CONTEXT ( olddecl ) != DECL_CONTEXT ( newdecl ) && ! decls_match ( olddecl , newdecl ) ) return " " ; if ( DECL_INITIAL ( olddecl ) != NULL_TREE && DECL_INITIAL ( newdecl ) != NULL_TREE ) { if ( DECL_NAME ( olddecl ) == NULL_TREE ) return " " ; else return " " ; } return NULL ; } else if ( TREE_CODE ( newdecl ) == TEMPLATE_DECL ) { tree nt , ot ; if ( TREE_CODE ( DECL_TEMPLATE_RESULT ( newdecl ) ) == TYPE_DECL ) { if ( COMPLETE_TYPE_P ( TREE_TYPE ( newdecl ) ) && COMPLETE_TYPE_P ( TREE_TYPE ( olddecl ) ) ) return " " ; return NULL ; } if ( TREE_CODE ( DECL_TEMPLATE_RESULT ( newdecl ) ) != FUNCTION_DECL || ( DECL_TEMPLATE_RESULT ( newdecl ) == DECL_TEMPLATE_RESULT ( olddecl ) ) ) return NULL ; nt = DECL_TEMPLATE_RESULT ( newdecl ) ; if ( DECL_TEMPLATE_INFO ( nt ) ) nt = DECL_TEMPLATE_RESULT ( template_for_substitution ( nt ) ) ; ot = DECL_TEMPLATE_RESULT ( olddecl ) ; if ( DECL_TEMPLATE_INFO ( ot ) ) ot = DECL_TEMPLATE_RESULT ( template_for_substitution ( ot ) ) ; if ( DECL_INITIAL ( nt ) && DECL_INITIAL ( ot ) ) return " " ; return NULL ; } else if ( TREE_CODE ( newdecl ) == VAR_DECL && DECL_THREAD_LOCAL_P ( newdecl ) != DECL_THREAD_LOCAL_P ( olddecl ) && ( ! DECL_LANG_SPECIFIC ( olddecl ) || ! CP_DECL_THREADPRIVATE_P ( olddecl ) || DECL_THREAD_LOCAL_P ( newdecl ) ) ) { if ( DECL_THREAD_LOCAL_P ( newdecl ) ) return " " " " ; else return " " " " ; } else if ( toplevel_bindings_p ( ) || DECL_NAMESPACE_SCOPE_P ( newdecl ) ) { if ( DECL_ANON_UNION_VAR_P ( newdecl ) || DECL_ANON_UNION_VAR_P ( olddecl ) ) return " " ; if ( DECL_EXTERNAL ( newdecl ) || DECL_EXTERNAL ( olddecl ) ) return NULL ; return " " ; } else { if ( ! ( DECL_EXTERNAL ( newdecl ) && DECL_EXTERNAL ( olddecl ) ) ) return " " ; return NULL ; } }
Return zero if the declaration NEWDECL is valid
when the declaration OLDDECL (assumed to be for the same name)
has already been seen.
Return zero if the declaration NEWDECL is valid when the declaration OLDDECL ( assumed to be for the same name ) has already been seen .
/* Because C++ can put things into name space for free,
	 constructs like "typedef struct foo { ... } foo"
	 would look like an erroneous redeclaration.  */ /* If this is a pure function, its olddecl will actually be
	 the original initialization to `0' (which we force to call
	 abort()).  Don't complain about redefinition in this case.  */ /* If both functions come from different namespaces, this is not
	 a redeclaration - this is a conflict with a used function.  */ /* We'll complain about linkage mismatches in
	 warn_extern_redeclared_static.  */ /* Defining the same name twice is no good.  */ /* Only variables can be thread-local, and all declarations must
	 agree on this property.  */ /* The objects have been declared at namespace scope.  If either
	 is a member of an anonymous union, then this is an invalid
	 redeclaration.  For example:

	   int i;
	   union { int i; };

	   is invalid.  */ /* If at least one declaration is a reference, there is no
	 conflict.  For example:

	   int i = 3;
	   extern int i;

	 is valid.  */ /* Reject two definitions.  */ /* Objects declared with block scope:  */ /* Reject two definitions, and reject a definition
	 together with an external reference.  */