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

📄 cp-pt.c

📁 早期freebsd实现
💻 C
📖 第 1 页 / 共 4 页
字号:
overload_template_name (id, classlevel)     tree id;     int classlevel;{  tree template, t, decl;  struct template_info *tinfo;  my_friendly_assert (TREE_CODE (id) == IDENTIFIER_NODE, 284);  template = IDENTIFIER_TEMPLATE (id);  if (!template)    return;#ifdef DEBUG_CP_BINDING_LEVELS  indent_to (stderr, debug_bindings_indentation);  fprintf (stderr, "overload_template_name(%d)", classlevel);  debug_bindings_indentation += 4;#endif  template = TREE_PURPOSE (template);  tinfo = DECL_TEMPLATE_INFO (template);  template = DECL_NAME (template);  my_friendly_assert (template != NULL_TREE, 285);  if (!classlevel)    {      pushlevel (1);      declare_pseudo_global_level ();    }  t = xref_tag (tinfo->aggr, id, NULL_TREE);  my_friendly_assert (TREE_CODE (t) == RECORD_TYPE	  || TREE_CODE (t) == UNINSTANTIATED_P_TYPE, 286);  decl = build_decl (TYPE_DECL, template, t);#if 0 /* fix this later */  /* We don't want to call here if the work has already been done.  */  t = (classlevel       ? IDENTIFIER_CLASS_VALUE (template)       : IDENTIFIER_LOCAL_VALUE (template));  if (t      && TREE_CODE (t) == TYPE_DECL      && TREE_TYPE (t) == t)    my_friendly_abort (85);#endif  if (classlevel)    pushdecl_class_level (decl);  else#if 0 /* not yet, should get fixed properly later */    pushdecl (decl);  pushlevel (1);#else    {      pushdecl (decl);      /* @@ Is this necessary now?  */      IDENTIFIER_LOCAL_VALUE (template) = decl;    }#endif#ifdef DEBUG_CP_BINDING_LEVELS  debug_bindings_indentation -= 4;#endif}/* T1 is PRE_PARSED_CLASS_DECL; T3 is result of XREF_TAG lookup.  */voidend_template_instantiation (t1, t3)     tree t1, t3;{  extern struct pending_input *to_be_restored;  tree t, decl;#ifdef DEBUG_CP_BINDING_LEVELS  indent_to (stderr, debug_bindings_indentation);  fprintf (stderr, "end_template_instantiation");  debug_bindings_indentation += 4;#endif  processing_template_defn--;  /* Restore the old parser input state.  */  if (yychar == YYEMPTY)    yychar = yylex ();  if (yychar != END_OF_SAVED_INPUT)    error ("parse error at end of class template");  else    {      restore_pending_input (to_be_restored);      to_be_restored = 0;    }  /* Our declarations didn't get stored in the global slot, since     there was a (supposedly tags-transparent) scope in between.  */  t = IDENTIFIER_TYPE_VALUE (TREE_VALUE (t1));  my_friendly_assert (t != NULL_TREE		      && TREE_CODE_CLASS (TREE_CODE (t)) == 't',		      287);  CLASSTYPE_USE_TEMPLATE (t) = 2;  /* Always make methods of template classes static, until we've     got a decent scheme for handling them.  The pragmas as they     are now are inadequate.  */  CLASSTYPE_INTERFACE_UNKNOWN (t) = 1;  decl = IDENTIFIER_GLOBAL_VALUE (TREE_VALUE (t1));  my_friendly_assert (TREE_CODE (decl) == TYPE_DECL, 288);  undo_template_name_overload (TREE_VALUE (t1), 0);  t = IDENTIFIER_TEMPLATE (TREE_VALUE (t1));  pop_template_decls (DECL_TEMPLATE_PARMS (TREE_PURPOSE (t)), TREE_VALUE (t),		      0);  pop_from_top_level ();  /* This will fix up the type-value field.  */  pushdecl_top_level (decl);  /* Restore interface/implementation settings.	 */  extract_interface_info ();#ifdef DEBUG_CP_BINDING_LEVELS  debug_bindings_indentation -= 4;#endif}/* Store away the text of an inline template function.	No rtl is   generated for this function until it is actually needed.  */voidreinit_parse_for_template (yychar, d1, d2)     int yychar;     tree d1, d2;{  struct template_info *template_info;  if (d2 == NULL_TREE || d2 == error_mark_node)    {    lose:      /* @@ Should use temp obstack, and discard results.  */      reinit_parse_for_block (yychar, &permanent_obstack, 1);      return;    }  if (TREE_CODE (d2) == IDENTIFIER_NODE)    d2 = IDENTIFIER_GLOBAL_VALUE (d2);  if (!d2)    goto lose;  template_info = DECL_TEMPLATE_INFO (d2);  if (!template_info)    {      template_info = (struct template_info *) permalloc (sizeof (struct template_info));      bzero (template_info, sizeof (struct template_info));      DECL_TEMPLATE_INFO (d2) = template_info;    }  template_info->filename = input_filename;  template_info->lineno = lineno;  reinit_parse_for_block (yychar, &permanent_obstack, 1);  template_info->text = obstack_base (&permanent_obstack);  template_info->length = obstack_object_size (&permanent_obstack);  obstack_finish (&permanent_obstack);  template_info->parm_vec = d1;}/* Type unification.   We have a function template signature with one or more references to   template parameters, and a parameter list we wish to fit to this   template.  If possible, produce a list of parameters for the template   which will cause it to fit the supplied parameter list.   Return zero for success, 2 for an incomplete match that doesn't resolve   all the types, and 1 for complete failure.  An error message will be   printed only for an incomplete match.   TPARMS[NTPARMS] is an array of template parameter types;   TARGS[NTPARMS] is the array of template parameter values.  PARMS is   the function template's signature (using TEMPLATE_PARM_IDX nodes),   and ARGS is the argument list we're trying to match against it.  */inttype_unification (tparms, targs, parms, args, nsubsts)     tree tparms, *targs, parms, args;     int *nsubsts;{  tree parm, arg;  int i;  int ntparms = TREE_VEC_LENGTH (tparms);  my_friendly_assert (TREE_CODE (tparms) == TREE_VEC, 289);  my_friendly_assert (TREE_CODE (parms) == TREE_LIST, 290);  my_friendly_assert (TREE_CODE (args) == TREE_LIST, 291);  my_friendly_assert (ntparms > 0, 292);  bzero (targs, sizeof (tree) * ntparms);  while (parms	 && parms != void_list_node	 && args)    {      parm = TREE_VALUE (parms);      parms = TREE_CHAIN (parms);      arg = TREE_VALUE (args);      args = TREE_CHAIN (args);      if (arg == error_mark_node)	return 1;      if (arg == unknown_type_node)	return 1;#if 0      if (TREE_CODE (arg) == VAR_DECL)	arg = TREE_TYPE (arg);      else if (TREE_CODE_CLASS (TREE_CODE (arg)) == 'e')	arg = TREE_TYPE (arg);#else      my_friendly_assert (TREE_TYPE (arg) != NULL_TREE, 293);      arg = TREE_TYPE (arg);#endif      switch (unify (tparms, targs, ntparms, parm, arg, nsubsts))	{	case 0:	  break;	case 1:	  return 1;	}    }  /* Fail if we've reached the end of the parm list, and more args     are present, and the parm list isn't variadic.  */  if (args && parms == void_list_node)    return 1;  /* Fail if parms are left and they don't have default values.	 */  if (parms      && parms != void_list_node      && TREE_PURPOSE (parms) == NULL_TREE)    return 1;  for (i = 0; i < ntparms; i++)    if (!targs[i])      {	error ("incomplete type unification");	return 2;      }  return 0;}/* Tail recursion is your friend.  */static intunify (tparms, targs, ntparms, parm, arg, nsubsts)     tree tparms, *targs, parm, arg;     int *nsubsts;{  int idx;  /* I don't think this will do the right thing with respect to types.     But the only case I've seen it in so far has been array bounds, where     signedness is the only information lost, and I think that will be     okay.  */  while (TREE_CODE (parm) == NOP_EXPR)    parm = TREE_OPERAND (parm, 0);  if (arg == error_mark_node)    return 1;  if (arg == unknown_type_node)    return 1;  if (arg == parm)    return 0;  switch (TREE_CODE (parm))    {    case TEMPLATE_TYPE_PARM:      (*nsubsts)++;      if (TEMPLATE_TYPE_TPARMLIST (parm) != tparms)	{	  error ("mixed template headers?!");	  my_friendly_abort (86);	  return 1;	}      idx = TEMPLATE_TYPE_IDX (parm);      /* Simple cases: Value already set, does match or doesn't.  */      if (targs[idx] == arg)	return 0;      else if (targs[idx])	return 1;      /* Check for mixed types and values.  */      if (TREE_CODE (TREE_VEC_ELT (tparms, idx)) != IDENTIFIER_NODE)	return 1;      targs[idx] = arg;      return 0;    case TEMPLATE_CONST_PARM:      (*nsubsts)++;      idx = TEMPLATE_CONST_IDX (parm);      if (targs[idx] == arg)	return 0;      else if (targs[idx])	{	  my_friendly_abort (87);	  return 1;	}/*	else if (typeof arg != tparms[idx])	return 1;*/      targs[idx] = copy_to_permanent (arg);      return 0;    case POINTER_TYPE:      if (TREE_CODE (arg) != POINTER_TYPE)	return 1;      return unify (tparms, targs, ntparms, TREE_TYPE (parm), TREE_TYPE (arg),		    nsubsts);    case REFERENCE_TYPE:      return unify (tparms, targs, ntparms, TREE_TYPE (parm), arg, nsubsts);    case ARRAY_TYPE:      if (TREE_CODE (arg) != ARRAY_TYPE)	return 1;      if (unify (tparms, targs, ntparms, TYPE_DOMAIN (parm), TYPE_DOMAIN (arg),		 nsubsts) != 0)	return 1;      return unify (tparms, targs, ntparms, TREE_TYPE (parm), TREE_TYPE (arg),		    nsubsts);    case REAL_TYPE:    case INTEGER_TYPE:      if (TREE_CODE (parm) == INTEGER_TYPE && TREE_CODE (arg) == INTEGER_TYPE)	{	  if (TYPE_MIN_VALUE (parm) && TYPE_MIN_VALUE (arg)	      && unify (tparms, targs, ntparms,			TYPE_MIN_VALUE (parm), TYPE_MIN_VALUE (arg), nsubsts))	    return 1;	  if (TYPE_MAX_VALUE (parm) && TYPE_MAX_VALUE (arg)	      && unify (tparms, targs, ntparms,			TYPE_MAX_VALUE (parm), TYPE_MAX_VALUE (arg), nsubsts))	    return 1;	}      /* As far as unification is concerned, this wins.	 Later checks	 will invalidate it if necessary.  */      return 0;      /* Types INTEGER_CST and MINUS_EXPR can come from array bounds.  */    case INTEGER_CST:      if (TREE_CODE (arg) != INTEGER_CST)	return 1;      return !tree_int_cst_equal (parm, arg);    case MINUS_EXPR:      {	tree t1, t2;	t1 = TREE_OPERAND (parm, 0);	t2 = TREE_OPERAND (parm, 1);	if (TREE_CODE (t1) != TEMPLATE_CONST_PARM)	  return 1;	return unify (tparms, targs, ntparms, t1,		      fold (build (PLUS_EXPR, integer_type_node, arg, t2)),		      nsubsts);      }    case TREE_VEC:      {	int i;	if (TREE_CODE (arg) != TREE_VEC)	  return 1;	if (TREE_VEC_LENGTH (parm) != TREE_VEC_LENGTH (arg))	  return 1;	for (i = TREE_VEC_LENGTH (parm) - 1; i >= 0; i--)	  if (unify (tparms, targs, ntparms,		     TREE_VEC_ELT (parm, i), TREE_VEC_ELT (arg, i),		     nsubsts))	    return 1;	return 0;      }    case UNINSTANTIATED_P_TYPE:      {	tree a;	/* Unification of something that is not a template fails. (mrs) */	if (TYPE_NAME (arg) == 0)	  return 1;	a = IDENTIFIER_TEMPLATE (TYPE_IDENTIFIER (arg));	/* Unification of something that is not a template fails. (mrs) */	if (a == 0)	  return 1;	if (UPT_TEMPLATE (parm) != TREE_PURPOSE (a))	  /* different templates */	  return 1;	return unify (tparms, targs, ntparms, UPT_PARMS (parm), TREE_VALUE (a),		      nsubsts);      }    case RECORD_TYPE:      /* Unification of something that is not a template fails. (mrs) */      return 1;    default:      sorry ("use of `%s' in template type unification",	     tree_code_name [(int) TREE_CODE (parm)]);      return 1;    }}#undef DEBUGintdo_pending_expansions (){  struct pending_inline *i, *new_list = 0;  if (!pending_template_expansions)    return 0;#ifdef DEBUG  fprintf (stderr, "\n\n\t\t IN DO_PENDING_EXPANSIONS\n\n");#endif  i = pending_template_expansions;  while (i)    {      tree context;      struct pending_inline *next = i->next;      tree t = i->fndecl;      int decision = 0;#define DECIDE(N) if(1){decision=(N); goto decided;}else      my_friendly_assert (TREE_CODE (t) == FUNCTION_DECL			  || TREE_CODE (t) == VAR_DECL, 294);      if (TREE_ASM_WRITTEN (t))	DECIDE (0);      /* If it's a method, let the class type decide it.	 @@ What if the method template is in a separate file?	 Maybe both file contexts should be taken into account?  */      context = DECL_CONTEXT (t);      if (context != NULL_TREE	  && TREE_CODE_CLASS (TREE_CODE (context)) == 't')	{	  /* If `unknown', we might want a static copy.	     If `implementation', we want a global one.	     If `interface', ext ref.  */	  if (!CLASSTYPE_INTERFACE_UNKNOWN (context))	    DECIDE (!CLASSTYPE_INTERFACE_ONLY (context));#if 0 /* This doesn't get us stuff needed only by the file initializer.  */	  DECIDE (TREE_USED (t));#else /* This compiles too much stuff, but that's probably better in	 most cases than never compiling the stuff we need.  */	  DECIDE (1);#endif	}      /* else maybe call extract_interface_info? */      if (TREE_USED (t)) /* is this right? */	DECIDE (1);    decided:#ifdef DEBUG      print_node_brief (stderr, decision ? "yes: " : "no: ", t, 0);      fprintf (stderr, "\t%s\n",	       (DECL_ASSEMBLER_NAME (t)		? IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (t))		: ""));#endif      if (decision == 1)	{	  i->next = pending_inlines;	  pending_inlines = i;	}      else	{	  i->next = new_list;	  new_list = i;	}      i = next;    }  pending_template_expansions = new_list;  if (!pending_inlines)    return 0;  do_pending_inlines ();  return 1;}struct pending_template {  struct pending_template *next;  tree id;};static struct pending_template* pending_templates;voiddo_pending_templates (){  struct pending_template* t;    for ( t = pending_templates; t; t = t->next)    {      instantiate_class_template (t->id, 1);    }  for ( t = pending_templates; t; t = pending_templates)    {      pending_templates = t->next;      free(t);    }}static voidadd_pending_template (pt)     tree pt;{  struct pending_template *p;    p = (struct pending_template *) malloc (sizeof (struct pending_template));  p->next = pending_templates;  pending_templates = p;  p->id = pt;}

⌨️ 快捷键说明

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