FreeBSD/contrib/gcc/cp/decl.c
/* Resolve `typename CONTEXT::NAME'.  TAG_TYPE indicates the tag
   provided to name the type.  Returns an appropriate type, unless an
   error occurs, in which case error_mark_node is returned.  If we
   locate a non-artificial TYPE_DECL and TF_KEEP_TYPE_DECL is set, we
   return that, rather than the _TYPE it corresponds to, in other
   cases we look through the type decl.  If TF_ERROR is set, complain
   about errors, otherwise be quiet.  */
Resolve `typename CONTEXT::NAME'.  TAG_TYPE indicates the tag
provided to name the type.  Returns an appropriate type, unless an
error occurs, in which case error_mark_node is returned.  If we
locate a non-artificial TYPE_DECL and TF_KEEP_TYPE_DECL is set, we
return that, rather than the _TYPE it corresponds to, in other
cases we look through the type decl.  If TF_ERROR is set, complain
about errors, otherwise be quiet.
Resolve ` typename CONTEXT :: NAME ' . TAG_TYPE indicates the tag provided to name the type . Returns an appropriate type unless an error occurs in which case error_mark_node is returned . If we locate a non - artificial TYPE_DECL and TF_KEEP_TYPE_DECL is set we return that rather than the _TYPE it corresponds to in other cases we look through the type decl . If TF_ERROR is set complain about errors otherwise be quiet .
tree
make_typename_type (tree context, tree name, enum tag_types tag_type,
		    tsubst_flags_t complain)
{
  tree fullname;
  tree t;
  bool want_template;
  if (name == error_mark_node
      || context == NULL_TREE
      || context == error_mark_node)
    return error_mark_node;
  if (TYPE_P (name))
    {
      if (!(TYPE_LANG_SPECIFIC (name)
	    && (CLASSTYPE_IS_TEMPLATE (name)
		|| CLASSTYPE_USE_TEMPLATE (name))))
	name = TYPE_IDENTIFIER (name);
      else
	name = build_nt (TEMPLATE_ID_EXPR,
			 CLASSTYPE_TI_TEMPLATE (name),
			 CLASSTYPE_TI_ARGS (name));
    }
  else if (TREE_CODE (name) == TYPE_DECL)
    name = DECL_NAME (name);
  fullname = name;
  if (TREE_CODE (name) == TEMPLATE_ID_EXPR)
    {
      name = TREE_OPERAND (name, 0);
      if (TREE_CODE (name) == TEMPLATE_DECL)
	name = TREE_OPERAND (fullname, 0) = DECL_NAME (name);
      else if (TREE_CODE (name) == OVERLOAD)
	{
	  error ("%qD is not a type", name);
	  return error_mark_node;
	}
    }
  if (TREE_CODE (name) == TEMPLATE_DECL)
    {
      error ("%qD used without template parameters", name);
      return error_mark_node;
    }
  gcc_assert (TREE_CODE (name) == IDENTIFIER_NODE);
  gcc_assert (TYPE_P (context));
  if (dependent_type_p (context))
    return build_typename_type (context, name, fullname, tag_type);
  if (!IS_AGGR_TYPE (context))
    {
      if (complain & tf_error)
	error ("%q#T is not a class", context);
      return error_mark_node;
    }
  want_template = TREE_CODE (fullname) == TEMPLATE_ID_EXPR;
  t = lookup_field (context, name, 0, true);
  if (!t)
    {
      if (complain & tf_error)
	error (want_template ? "no class template named %q#T in %q#T"
	       : "no type named %q#T in %q#T", name, context);
      return error_mark_node;
    }
  if (want_template && !DECL_CLASS_TEMPLATE_P (t))
    {
      if (complain & tf_error)
	error ("%<typename %T::%D%> names %q#T, which is not a class template",
	       context, name, t);
      return error_mark_node;
    }
  if (!want_template && TREE_CODE (t) != TYPE_DECL)
    {
      if (complain & tf_error)
	error ("%<typename %T::%D%> names %q#T, which is not a type",
	       context, name, t);
      return error_mark_node;
    }
  if (complain & tf_error)
    perform_or_defer_access_check (TYPE_BINFO (context), t, t);
  if (want_template)
    return lookup_template_class (t, TREE_OPERAND (fullname, 1),
				  NULL_TREE, context,
				  0,
				  tf_warning_or_error | tf_user);
  if (DECL_ARTIFICIAL (t) || !(complain & tf_keep_type_decl))
    t = TREE_TYPE (t);
  return t;
}
tree make_typename_type ( tree context , tree name , enum tag_types tag_type , tsubst_flags_t complain ) { tree fullname ; tree t ; bool want_template ; if ( name == error_mark_node || context == NULL_TREE || context == error_mark_node ) return error_mark_node ; if ( TYPE_P ( name ) ) { if ( ! ( TYPE_LANG_SPECIFIC ( name ) && ( CLASSTYPE_IS_TEMPLATE ( name ) || CLASSTYPE_USE_TEMPLATE ( name ) ) ) ) name = TYPE_IDENTIFIER ( name ) ; else name = build_nt ( TEMPLATE_ID_EXPR , CLASSTYPE_TI_TEMPLATE ( name ) , CLASSTYPE_TI_ARGS ( name ) ) ; } else if ( TREE_CODE ( name ) == TYPE_DECL ) name = DECL_NAME ( name ) ; fullname = name ; if ( TREE_CODE ( name ) == TEMPLATE_ID_EXPR ) { name = TREE_OPERAND ( name , 0 ) ; if ( TREE_CODE ( name ) == TEMPLATE_DECL ) name = TREE_OPERAND ( fullname , 0 ) = DECL_NAME ( name ) ; else if ( TREE_CODE ( name ) == OVERLOAD ) { error ( " " , name ) ; return error_mark_node ; } } if ( TREE_CODE ( name ) == TEMPLATE_DECL ) { error ( " " , name ) ; return error_mark_node ; } gcc_assert ( TREE_CODE ( name ) == IDENTIFIER_NODE ) ; gcc_assert ( TYPE_P ( context ) ) ; if ( dependent_type_p ( context ) ) return build_typename_type ( context , name , fullname , tag_type ) ; if ( ! IS_AGGR_TYPE ( context ) ) { if ( complain & tf_error ) error ( " " , context ) ; return error_mark_node ; } want_template = TREE_CODE ( fullname ) == TEMPLATE_ID_EXPR ; t = lookup_field ( context , name , 0 , true ) ; if ( ! t ) { if ( complain & tf_error ) error ( want_template ? " " : " " , name , context ) ; return error_mark_node ; } if ( want_template && ! DECL_CLASS_TEMPLATE_P ( t ) ) { if ( complain & tf_error ) error ( " " , context , name , t ) ; return error_mark_node ; } if ( ! want_template && TREE_CODE ( t ) != TYPE_DECL ) { if ( complain & tf_error ) error ( " " , context , name , t ) ; return error_mark_node ; } if ( complain & tf_error ) perform_or_defer_access_check ( TYPE_BINFO ( context ) , t , t ) ; if ( want_template ) return lookup_template_class ( t , TREE_OPERAND ( fullname , 1 ) , NULL_TREE , context , 0 , tf_warning_or_error | tf_user ) ; if ( DECL_ARTIFICIAL ( t ) || ! ( complain & tf_keep_type_decl ) ) t = TREE_TYPE ( t ) ; return t ; }
Resolve `typename CONTEXT::NAME'.
Resolve ` typename CONTEXT :: NAME ' .
/* Create a TEMPLATE_ID_EXPR for the type.  */ /* When the CONTEXT is a dependent type,  NAME could refer to a
     dependent base class of CONTEXT.  So we cannot peek inside it,
     even if CONTEXT is a currently open scope.  */ /* We should only set WANT_TYPE when we're a nested typename type.
     Then we can give better diagnostics if we find a non-type.  */ /*want_type=*/ /*entering_scope=*/