⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 cp-pt.c

📁 早期freebsd实现
💻 C
📖 第 1 页 / 共 4 页
字号:
		 tree_code_name [(int) TREE_CODE (type)]);	  my_friendly_abort (81);	}    }  {    char *bufp = obstack_next_free (&scratch_obstack);    int offset = 0;    while (bufp[offset - 1] == ' ')      offset--;    obstack_blank_fast (&scratch_obstack, offset);  }  ccat ('>');  ccat ('\0');  return (char *) obstack_base (&scratch_obstack); too_long:  fatal ("out of (preallocated) string space creating template instantiation name");  /* NOTREACHED */  return NULL;}/* Given an IDENTIFIER_NODE (type TEMPLATE_DECL) and a chain of   parameters, find the desired type.   D1 is the PTYPENAME terminal, and ARGLIST is the list of arguments.   Since ARGLIST is build on the decl_obstack, we must copy it here   to keep it from being reclaimed when the decl storage is reclaimed.	*/treelookup_template_class (d1, arglist)     tree d1, arglist;{  tree template, parmlist;  char *mangled_name;  tree id;  my_friendly_assert (TREE_CODE (d1) == IDENTIFIER_NODE, 272);  template = IDENTIFIER_GLOBAL_VALUE (d1); /* XXX */  if (TREE_CODE (template) != TEMPLATE_DECL)    {      error ("Non-template type '%s' used as a template",	     IDENTIFIER_POINTER (d1));      return error_mark_node;    }  parmlist = DECL_TEMPLATE_PARMS (template);  arglist = coerce_template_parms (parmlist, arglist);  if (arglist == error_mark_node)    return error_mark_node;  if (uses_template_parms (arglist))    {      tree t = make_lang_type (UNINSTANTIATED_P_TYPE);      tree d;      id = make_anon_name ();      d = build_lang_decl (TYPE_DECL, id, t);      TYPE_NAME (t) = d;      TYPE_VALUES (t) = build_tree_list (template, arglist);      pushdecl_top_level (d);    }  else    {      mangled_name = mangle_class_name_for_template (IDENTIFIER_POINTER (d1),						     parmlist, arglist);      id = get_identifier (mangled_name);    }  if (!IDENTIFIER_TEMPLATE (id))    {      arglist = copy_to_permanent (arglist);      IDENTIFIER_TEMPLATE (id) = perm_tree_cons (template, arglist, NULL_TREE);    }  return id;}voidpush_template_decls (parmlist, arglist, class_level)     tree parmlist, arglist;     int class_level;{  int i, nparms;#ifdef DEBUG_CP_BINDING_LEVELS  indent_to (stderr, debug_bindings_indentation);  fprintf (stderr, "push_template_decls");  debug_bindings_indentation += 4;#endif  /* Don't want to push values into global context.  */  if (!class_level)    pushlevel (0);  nparms = TREE_VEC_LENGTH (parmlist);  for (i = 0; i < nparms; i++)    {      int requires_type, is_type;      tree parm = TREE_VEC_ELT (parmlist, i);      tree arg = TREE_VEC_ELT (arglist, i);      tree decl = 0;      requires_type = TREE_CODE (parm) == IDENTIFIER_NODE;      is_type = TREE_CODE_CLASS (TREE_CODE (arg)) == 't';      if (is_type)	{	  /* add typename to namespace */	  if (!requires_type)	    {	      error ("template use error: type provided where value needed");	      continue;	    }	  decl = arg;	  my_friendly_assert (TREE_CODE_CLASS (TREE_CODE (decl)) == 't', 273);	  decl = build_lang_decl (TYPE_DECL, parm, decl);	}      else	{	  /* add const decl to namespace */	  tree val;	  if (requires_type)	    {	      error ("template use error: value provided where type needed");	      continue;	    }	  val = digest_init (TREE_TYPE (parm), arg, (tree *) 0);	  if (val != error_mark_node)	    {	      decl = build_decl (VAR_DECL, DECL_NAME (parm), TREE_TYPE (parm));	      DECL_INITIAL (decl) = val;	      TREE_READONLY (decl) = 1;	    }	}      if (decl != 0)	{	  layout_decl (decl, 0);	  if (class_level)	    pushdecl_class_level (decl);	  else	    pushdecl (decl);	}    }  if (!class_level)    set_current_level_tags_transparency (1);#ifdef DEBUG_CP_BINDING_LEVELS  debug_bindings_indentation -= 4;#endif}voidpop_template_decls (parmlist, arglist, class_level)     tree parmlist, arglist;     int class_level;{#ifdef DEBUG_CP_BINDING_LEVELS  indent_to (stderr, debug_bindings_indentation);  fprintf (stderr, "pop_template_decls");  debug_bindings_indentation += 4;#endif  if (!class_level)    poplevel (0, 0, 0);#ifdef DEBUG_CP_BINDING_LEVELS  debug_bindings_indentation -= 4;#endif}/* Should be defined in cp-parse.h.  */extern int yychar;intuses_template_parms (t)     tree t;{  if (!t)    return 0;  switch (TREE_CODE (t))    {    case INDIRECT_REF:    case COMPONENT_REF:      /* We assume that the object must be instantiated in order to build	 the COMPONENT_REF, so we test only whether the type of the	 COMPONENT_REF uses template parms.  */      return uses_template_parms (TREE_TYPE (t));    case IDENTIFIER_NODE:      if (!IDENTIFIER_TEMPLATE (t))	return 0;      return uses_template_parms (TREE_VALUE (IDENTIFIER_TEMPLATE (t)));      /* aggregates of tree nodes */    case TREE_VEC:      {	int i = TREE_VEC_LENGTH (t);	while (i--)	  if (uses_template_parms (TREE_VEC_ELT (t, i)))	    return 1;	return 0;      }    case TREE_LIST:      if (uses_template_parms (TREE_PURPOSE (t))	  || uses_template_parms (TREE_VALUE (t)))	return 1;      return uses_template_parms (TREE_CHAIN (t));      /* constructed type nodes */    case POINTER_TYPE:    case REFERENCE_TYPE:      return uses_template_parms (TREE_TYPE (t));    case RECORD_TYPE:    case UNION_TYPE:      if (!TYPE_NAME (t))	return 0;      if (!TYPE_IDENTIFIER (t))	return 0;      return uses_template_parms (TYPE_IDENTIFIER (t));    case FUNCTION_TYPE:      if (uses_template_parms (TYPE_ARG_TYPES (t)))	return 1;      return uses_template_parms (TREE_TYPE (t));    case ARRAY_TYPE:      if (uses_template_parms (TYPE_DOMAIN (t)))	return 1;      return uses_template_parms (TREE_TYPE (t));    case OFFSET_TYPE:      if (uses_template_parms (TYPE_OFFSET_BASETYPE (t)))	return 1;      return uses_template_parms (TREE_TYPE (t));    case METHOD_TYPE:      if (uses_template_parms (TYPE_OFFSET_BASETYPE (t)))	return 1;      if (uses_template_parms (TYPE_ARG_TYPES (t)))	return 1;      return uses_template_parms (TREE_TYPE (t));      /* decl nodes */    case TYPE_DECL:      return uses_template_parms (DECL_NAME (t));    case FUNCTION_DECL:      if (uses_template_parms (TREE_TYPE (t)))	return 1;      /* fall through */    case VAR_DECL:    case PARM_DECL:      /* ??? What about FIELD_DECLs?  */      /* The type of a decl can't use template parms if the name of the	 variable doesn't, because it's impossible to resolve them.  So	 ignore the type field for now.	 */      if (DECL_CONTEXT (t) && uses_template_parms (DECL_CONTEXT (t)))	return 1;      if (uses_template_parms (TREE_TYPE (t)))	{	  error ("template parms used where they can't be resolved");	}      return 0;    case CALL_EXPR:      return uses_template_parms (TREE_TYPE (t));    case ADDR_EXPR:      return uses_template_parms (TREE_OPERAND (t, 0));      /* template parm nodes */    case TEMPLATE_TYPE_PARM:    case TEMPLATE_CONST_PARM:      return 1;      /* simple type nodes */    case INTEGER_TYPE:      if (uses_template_parms (TYPE_MIN_VALUE (t)))	return 1;      return uses_template_parms (TYPE_MAX_VALUE (t));    case REAL_TYPE:    case VOID_TYPE:    case ENUMERAL_TYPE:      return 0;      /* constants */    case INTEGER_CST:    case REAL_CST:    case STRING_CST:      return 0;    case ERROR_MARK:      /* Non-error_mark_node ERROR_MARKs are bad things.  */      my_friendly_assert (t == error_mark_node, 274);      /* NOTREACHED */      return 0;    case UNINSTANTIATED_P_TYPE:      return 1;    default:      switch (TREE_CODE_CLASS (TREE_CODE (t)))	{	case '1':	case '2':	case '3':	case '<':	  {	    int i;	    for (i = tree_code_length[(int) TREE_CODE (t)]; --i >= 0;)	      if (uses_template_parms (TREE_OPERAND (t, i)))		return 1;	    return 0;	  }	default:	  break;	}      sorry ("testing %s for template parms",	     tree_code_name [(int) TREE_CODE (t)]);      my_friendly_abort (82);      /* NOTREACHED */      return 0;    }}voidinstantiate_member_templates (arg)     tree arg;{  tree t;  tree classname = TREE_VALUE (arg);  tree id = classname;  tree members = DECL_TEMPLATE_MEMBERS (TREE_PURPOSE (IDENTIFIER_TEMPLATE (id)));  for (t = members; t; t = TREE_CHAIN (t))    {      tree parmvec, type, classparms, tdecl, t2;      int nparms, xxx, i;      my_friendly_assert (TREE_VALUE (t) != NULL_TREE, 275);      my_friendly_assert (TREE_CODE (TREE_VALUE (t)) == TEMPLATE_DECL, 276);      /* @@ Should verify that class parm list is a list of	 distinct template parameters, and covers all the template	 parameters.  */      tdecl = TREE_VALUE (t);      type = DECL_CONTEXT (DECL_TEMPLATE_RESULT (tdecl));      classparms = UPT_PARMS (type);      nparms = TREE_VEC_LENGTH (classparms);      parmvec = make_tree_vec (nparms);      for (i = 0; i < nparms; i++)	TREE_VEC_ELT (parmvec, i) = NULL_TREE;      switch (unify (DECL_TEMPLATE_PARMS (tdecl),		     &TREE_VEC_ELT (parmvec, 0), nparms,		     type, IDENTIFIER_TYPE_VALUE (classname),		     &xxx))	{	case 0:	  /* Success -- well, no inconsistency, at least.  */	  for (i = 0; i < nparms; i++)	    if (TREE_VEC_ELT (parmvec, i) == NULL_TREE)	      goto failure;	  t2 = instantiate_template (tdecl,				     &TREE_VEC_ELT (parmvec, 0));	  type = IDENTIFIER_TYPE_VALUE (id);	  my_friendly_assert (type != 0, 277);	  if (CLASSTYPE_INTERFACE_UNKNOWN (type))	    {	      DECL_EXTERNAL (t2) = 0;	      TREE_PUBLIC (t2) = 0;	    }	  else	    {	      DECL_EXTERNAL (t2) = CLASSTYPE_INTERFACE_ONLY (type);	      TREE_PUBLIC (t2) = 1;	    }	  break;	case 1:	  /* Failure.  */	failure:	  error ("type unification error instantiating %s::%s",		 IDENTIFIER_POINTER (classname),		 IDENTIFIER_POINTER (DECL_NAME (tdecl)));	  continue /* loop of members */;	default:	  /* Eek, a bug.  */	  my_friendly_abort (83);	}    }}treeinstantiate_class_template (classname, setup_parse)     tree classname;     int setup_parse;{  struct template_info *template_info;  tree template, t1;  if (classname == error_mark_node)    return error_mark_node;  my_friendly_assert (TREE_CODE (classname) == IDENTIFIER_NODE, 278);  template = IDENTIFIER_TEMPLATE (classname);  if (IDENTIFIER_HAS_TYPE_VALUE (classname))    {      tree type = IDENTIFIER_TYPE_VALUE (classname);      if (TREE_CODE (type) == UNINSTANTIATED_P_TYPE)	return type;      if (TYPE_BEING_DEFINED (type)	  || TYPE_SIZE (type)	  || CLASSTYPE_USE_TEMPLATE (type) != 0)	return type;    }  if (uses_template_parms (classname))    {      if (!TREE_TYPE (classname))	{	  tree t = make_lang_type (RECORD_TYPE);	  tree d = build_lang_decl (TYPE_DECL, classname, t);	  DECL_NAME (d) = classname;	  TYPE_NAME (t) = d;	  pushdecl (d);	}      return NULL_TREE;    }  t1 = TREE_PURPOSE (template);  my_friendly_assert (TREE_CODE (t1) == TEMPLATE_DECL, 279);  /* If a template is declared but not defined, accept it; don't crash.     Later uses requiring the definition will be flagged as errors by     other code.  Thanks to niklas@appli.se for this bug fix.  */  if (DECL_TEMPLATE_INFO (t1)->text == 0)    setup_parse = 0;#ifdef DEBUG_CP_BINDING_LEVELS  indent_to (stderr, debug_bindings_indentation);  fprintf (stderr, "instantiate_class_template");  debug_bindings_indentation += 4;#endif  push_to_top_level ();  push_template_decls (DECL_TEMPLATE_PARMS (TREE_PURPOSE (template)),		       TREE_VALUE (template), 0);  set_current_level_tags_transparency (1);  template_info = DECL_TEMPLATE_INFO (t1);  if (setup_parse)    {      feed_input (template_info->text, template_info->length, (struct obstack *)0);      lineno = template_info->lineno;      input_filename = template_info->filename;      /* Get interface/implementation back in sync.  */      extract_interface_info ();      overload_template_name (classname, 0);      yychar = PRE_PARSED_CLASS_DECL;      yylval.ttype = build_tree_list (class_type_node, classname);      processing_template_defn++;    }  else    {      tree t, decl, id, tmpl;      id = classname;      tmpl = TREE_PURPOSE (IDENTIFIER_TEMPLATE (id));      t = xref_tag (DECL_TEMPLATE_INFO (tmpl)->aggr, id, NULL_TREE);      my_friendly_assert (TREE_CODE (t) == RECORD_TYPE, 280);#if 1      lineno = template_info->lineno;      input_filename = template_info->filename;      /* Get interface/implementation back in sync.  */      extract_interface_info ();#endif      /* Now, put a copy of the decl in global scope, to avoid       * recursive expansion.  */      decl = IDENTIFIER_LOCAL_VALUE (id);      if (!decl)	decl = IDENTIFIER_CLASS_VALUE (id);      if (decl)	{	  my_friendly_assert (TREE_CODE (decl) == TYPE_DECL, 281);	  /* We'd better make sure we're on the permanent obstack or else	   * we'll get a "friendly" abort 124 in pushdecl.  Perhaps a	   * copy_to_permanent would be sufficient here, but then a	   * sharing problem might occur.  I don't know -- niklas@appli.se */	  push_obstacks (&permanent_obstack, &permanent_obstack);	  pushdecl_top_level (copy_node (decl));	  pop_obstacks ();	}      pop_from_top_level ();    }#ifdef DEBUG_CP_BINDING_LEVELS  debug_bindings_indentation -= 4;#endif  return NULL_TREE;}static intlist_eq (t1, t2)     tree t1, t2;{  if (t1 == NULL_TREE)    return t2 == NULL_TREE;  if (t2 == NULL_TREE)    return 0;  /* Don't care if one declares its arg const and the other doesn't -- the     main variant of the arg type is all that matters.  */  if (TYPE_MAIN_VARIANT (TREE_VALUE (t1))      != TYPE_MAIN_VARIANT (TREE_VALUE (t2)))    return 0;  return list_eq (TREE_CHAIN (t1), TREE_CHAIN (t2));}static treetsubst (t, args, nargs)     tree t, *args;{  tree type;  if (t == NULL_TREE || t == error_mark_node)    return t;  type = TREE_TYPE (t);  if (type      /* Minor optimization.	 ?? Are these really the most frequent cases?  Is the savings

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -