FreeBSD/contrib/gcc/cp/decl.c
/* Get the struct, enum or union (TAG_CODE says which) with tag NAME.
   Define the tag as a forward-reference if it is not defined.

   If a declaration is given, process it here, and report an error if
   multiple declarations are not identical.

   SCOPE is TS_CURRENT when this is also a definition.  Only look in
   the current frame for the name (since C++ allows new names in any
   scope.)  It is TS_WITHIN_ENCLOSING_NON_CLASS if this is a friend
   declaration.  Only look beginning from the current scope outward up
   till the nearest non-class scope.  Otherwise it is TS_GLOBAL.

   TEMPLATE_HEADER_P is true when this declaration is preceded by
   a set of template parameters.  */
Get the struct, enum or union (TAG_CODE says which) with tag NAME.
Define the tag as a forward-reference if it is not defined.

If a declaration is given, process it here, and report an error if
multiple declarations are not identical.

SCOPE is TS_CURRENT when this is also a definition.  Only look in
the current frame for the name (since C++ allows new names in any
scope.)  It is TS_WITHIN_ENCLOSING_NON_CLASS if this is a friend
declaration.  Only look beginning from the current scope outward up
till the nearest non-class scope.  Otherwise it is TS_GLOBAL.

TEMPLATE_HEADER_P is true when this declaration is preceded by
a set of template parameters.
Get the struct enum or union ( TAG_CODE says which ) with tag NAME . Define the tag as a forward - reference if it is not defined . If a declaration is given process it here and report an error if multiple declarations are not identical . SCOPE is TS_CURRENT when this is also a definition . Only look in the current frame for the name ( since C ++ allows new names in any scope . ) It is TS_WITHIN_ENCLOSING_NON_CLASS if this is a friend declaration . Only look beginning from the current scope outward up till the nearest non - class scope . Otherwise it is TS_GLOBAL . TEMPLATE_HEADER_P is true when this declaration is preceded by a set of template parameters .
tree
xref_tag (enum tag_types tag_code, tree name,
	  tag_scope scope, bool template_header_p)
{
  enum tree_code code;
  tree t;
  tree context = NULL_TREE;
  timevar_push (TV_NAME_LOOKUP);
  gcc_assert (TREE_CODE (name) == IDENTIFIER_NODE);
  switch (tag_code)
    {
    case record_type:
    case class_type:
      code = RECORD_TYPE;
      break;
    case union_type:
      code = UNION_TYPE;
      break;
    case enum_type:
      code = ENUMERAL_TYPE;
      break;
    default:
      gcc_unreachable ();
    }
  if (ANON_AGGRNAME_P (name))
    t = NULL_TREE;
  else
    t = lookup_and_check_tag  (tag_code, name,
			       scope, template_header_p);
  if (t == error_mark_node)
    POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, error_mark_node);
  if (scope != ts_current && t && current_class_type
      && template_class_depth (current_class_type)
      && template_header_p)
    {
      context = TYPE_CONTEXT (t);
      t = NULL_TREE;
    }
  if (! t)
    {
      if (code == ENUMERAL_TYPE)
	{
	  error ("use of enum %q#D without previous declaration", name);
	  POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, error_mark_node);
	}
      else
	{
	  t = make_aggr_type (code);
	  TYPE_CONTEXT (t) = context;
	  t = pushtag (name, t, scope);
	}
    }
  else
    {
      if (template_header_p && IS_AGGR_TYPE (t))
        {
	  if (!redeclare_class_template (t, current_template_parms))
            POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, error_mark_node);
        }
      else if (!processing_template_decl
	       && CLASS_TYPE_P (t)
	       && CLASSTYPE_IS_TEMPLATE (t))
	{
	  error ("redeclaration of %qT as a non-template", t);
	  error ("previous declaration %q+D", t);
	  POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, error_mark_node);
	}
      if (scope != ts_within_enclosing_non_class
	  && hidden_name_p (TYPE_NAME (t)))
	{
	  DECL_ANTICIPATED (TYPE_NAME (t)) = 0;
	  DECL_FRIEND_P (TYPE_NAME (t)) = 0;
	  if (TYPE_TEMPLATE_INFO (t))
	    {
	      DECL_ANTICIPATED (TYPE_TI_TEMPLATE (t)) = 0;
	      DECL_FRIEND_P (TYPE_TI_TEMPLATE (t)) = 0;
	    }
	}
    }
  POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, t);
}
tree xref_tag ( enum tag_types tag_code , tree name , tag_scope scope , bool template_header_p ) { enum tree_code code ; tree t ; tree context = NULL_TREE ; timevar_push ( TV_NAME_LOOKUP ) ; gcc_assert ( TREE_CODE ( name ) == IDENTIFIER_NODE ) ; switch ( tag_code ) { case record_type : case class_type : code = RECORD_TYPE ; break ; case union_type : code = UNION_TYPE ; break ; case enum_type : code = ENUMERAL_TYPE ; break ; default : gcc_unreachable ( ) ; } if ( ANON_AGGRNAME_P ( name ) ) t = NULL_TREE ; else t = lookup_and_check_tag ( tag_code , name , scope , template_header_p ) ; if ( t == error_mark_node ) POP_TIMEVAR_AND_RETURN ( TV_NAME_LOOKUP , error_mark_node ) ; if ( scope != ts_current && t && current_class_type && template_class_depth ( current_class_type ) && template_header_p ) { context = TYPE_CONTEXT ( t ) ; t = NULL_TREE ; } if ( ! t ) { if ( code == ENUMERAL_TYPE ) { error ( " " , name ) ; POP_TIMEVAR_AND_RETURN ( TV_NAME_LOOKUP , error_mark_node ) ; } else { t = make_aggr_type ( code ) ; TYPE_CONTEXT ( t ) = context ; t = pushtag ( name , t , scope ) ; } } else { if ( template_header_p && IS_AGGR_TYPE ( t ) ) { if ( ! redeclare_class_template ( t , current_template_parms ) ) POP_TIMEVAR_AND_RETURN ( TV_NAME_LOOKUP , error_mark_node ) ; } else if ( ! processing_template_decl && CLASS_TYPE_P ( t ) && CLASSTYPE_IS_TEMPLATE ( t ) ) { error ( " " , t ) ; error ( " " , t ) ; POP_TIMEVAR_AND_RETURN ( TV_NAME_LOOKUP , error_mark_node ) ; } if ( scope != ts_within_enclosing_non_class && hidden_name_p ( TYPE_NAME ( t ) ) ) { DECL_ANTICIPATED ( TYPE_NAME ( t ) ) = 0 ; DECL_FRIEND_P ( TYPE_NAME ( t ) ) = 0 ; if ( TYPE_TEMPLATE_INFO ( t ) ) { DECL_ANTICIPATED ( TYPE_TI_TEMPLATE ( t ) ) = 0 ; DECL_FRIEND_P ( TYPE_TI_TEMPLATE ( t ) ) = 0 ; } } } POP_TIMEVAR_AND_RETURN ( TV_NAME_LOOKUP , t ) ; }
Get the struct, enum or union (TAG_CODE says which) with tag NAME.
Get the struct enum or union ( TAG_CODE says which ) with tag NAME .
/* In case of anonymous name, xref_tag is only called to
     make type node and push name.  Name lookup is not required.  */ /* Since SCOPE is not TS_CURRENT, we are not looking at a
	 definition of this tag.  Since, in addition, we are currently
	 processing a (member) template declaration of a template
	 class, we must be very careful; consider:

	   template <class X>
	   struct S1

	   template <class U>
	   struct S2
	   { template <class V>
	   friend struct S1; };

	 Here, the S2::S1 declaration should not be confused with the
	 outer declaration.  In particular, the inner version should
	 have a template parameter of level 2, not level 1.  This
	 would be particularly important if the member declaration
	 were instead:

	   template <class V = U> friend struct S1;

	 say, when we should tsubst into `U' when instantiating
	 S2.  On the other hand, when presented with:

	   template <class T>
	   struct S1 {
	     template <class U>
	     struct S2 {};
	     template <class U>
	     friend struct S2;
	   };

	 we must find the inner binding eventually.  We
	 accomplish this by making sure that the new type we
	 create to represent this declaration has the right
	 TYPE_CONTEXT.  */ /* If no such tag is yet defined, create a forward-reference node
	 and record it as the "definition".
	 When a real declaration of this type is found,
	 the forward-reference will be altered into a real type.  */ /* Make injected friend class visible.  */