FreeBSD/contrib/gcc/cp/decl.c
/* Name lookup in an elaborated-type-specifier (after the keyword
   indicated by TAG_CODE) has found the TYPE_DECL DECL.  If the
   elaborated-type-specifier is invalid, issue a diagnostic and return
   error_mark_node; otherwise, return the *_TYPE to which it referred.
   If ALLOW_TEMPLATE_P is true, TYPE may be a class template.  */
Name lookup in an elaborated-type-specifier (after the keyword
indicated by TAG_CODE) has found the TYPE_DECL DECL.  If the
elaborated-type-specifier is invalid, issue a diagnostic and return
error_mark_node; otherwise, return the *_TYPE to which it referred.
If ALLOW_TEMPLATE_P is true, TYPE may be a class template.
Name lookup in an elaborated - type - specifier ( after the keyword indicated by TAG_CODE ) has found the TYPE_DECL DECL . If the elaborated - type - specifier is invalid issue a diagnostic and return error_mark_node ; otherwise return the * _TYPE to which it referred . If ALLOW_TEMPLATE_P is true TYPE may be a class template .
tree
check_elaborated_type_specifier (enum tag_types tag_code,
				 tree decl,
				 bool allow_template_p)
{
  tree type;
  if (DECL_SELF_REFERENCE_P (decl))
    decl = TYPE_NAME (TREE_TYPE (decl));
  type = TREE_TYPE (decl);
  if (TREE_CODE (type) == TEMPLATE_TYPE_PARM)
    {
      error ("using template type parameter %qT after %qs",
	     type, tag_name (tag_code));
      return error_mark_node;
    }
  else if (!DECL_IMPLICIT_TYPEDEF_P (decl)
	   && tag_code != typename_type)
    {
      error ("using typedef-name %qD after %qs", decl, tag_name (tag_code));
      error ("%q+D has a previous declaration here", decl);
      return error_mark_node;
    }
  else if (TREE_CODE (type) != RECORD_TYPE
	   && TREE_CODE (type) != UNION_TYPE
	   && tag_code != enum_type
	   && tag_code != typename_type)
    {
      error ("%qT referred to as %qs", type, tag_name (tag_code));
      error ("%q+T has a previous declaration here", type);
      return error_mark_node;
    }
  else if (TREE_CODE (type) != ENUMERAL_TYPE
	   && tag_code == enum_type)
    {
      error ("%qT referred to as enum", type);
      error ("%q+T has a previous declaration here", type);
      return error_mark_node;
    }
  else if (!allow_template_p
	   && TREE_CODE (type) == RECORD_TYPE
	   && CLASSTYPE_IS_TEMPLATE (type))
    {
      error ("template argument required for %<%s %T%>",
	     tag_name (tag_code),
	     DECL_NAME (CLASSTYPE_TI_TEMPLATE (type)));
      return error_mark_node;
    }
  return type;
}
tree check_elaborated_type_specifier ( enum tag_types tag_code , tree decl , bool allow_template_p ) { tree type ; if ( DECL_SELF_REFERENCE_P ( decl ) ) decl = TYPE_NAME ( TREE_TYPE ( decl ) ) ; type = TREE_TYPE ( decl ) ; if ( TREE_CODE ( type ) == TEMPLATE_TYPE_PARM ) { error ( " " , type , tag_name ( tag_code ) ) ; return error_mark_node ; } else if ( ! DECL_IMPLICIT_TYPEDEF_P ( decl ) && tag_code != typename_type ) { error ( " " , decl , tag_name ( tag_code ) ) ; error ( " " , decl ) ; return error_mark_node ; } else if ( TREE_CODE ( type ) != RECORD_TYPE && TREE_CODE ( type ) != UNION_TYPE && tag_code != enum_type && tag_code != typename_type ) { error ( " " , type , tag_name ( tag_code ) ) ; error ( " " , type ) ; return error_mark_node ; } else if ( TREE_CODE ( type ) != ENUMERAL_TYPE && tag_code == enum_type ) { error ( " " , type ) ; error ( " " , type ) ; return error_mark_node ; } else if ( ! allow_template_p && TREE_CODE ( type ) == RECORD_TYPE && CLASSTYPE_IS_TEMPLATE ( type ) ) { error ( " " , tag_name ( tag_code ) , DECL_NAME ( CLASSTYPE_TI_TEMPLATE ( type ) ) ) ; return error_mark_node ; } return type ; }
Name lookup in an elaborated-type-specifier (after the keyword
indicated by TAG_CODE) has found the TYPE_DECL DECL.
Name lookup in an elaborated - type - specifier ( after the keyword indicated by TAG_CODE ) has found the TYPE_DECL DECL .
/* In the case of:

       struct S { struct S *p; };

     name lookup will find the TYPE_DECL for the implicit "S::S"
     typedef.  Adjust for that here.  */ /* Check TEMPLATE_TYPE_PARM first because DECL_IMPLICIT_TYPEDEF_P
     is false for this case as well.  */ /*   [dcl.type.elab]

       If the identifier resolves to a typedef-name or a template
       type-parameter, the elaborated-type-specifier is ill-formed.

     In other words, the only legitimate declaration to use in the
     elaborated type specifier is the implicit typedef created when
     the type is declared.  */ /* If a class template appears as elaborated type specifier
	 without a template header such as:

	   template <class T> class C {};
	   void f(class C);		// No template header here

	 then the required template argument is missing.  */