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

📄 cp-pt.c

📁 早期freebsd实现
💻 C
📖 第 1 页 / 共 4 页
字号:
	 significant?  */      && type != integer_type_node      && type != void_type_node      && type != char_type_node)    type = build_type_variant (tsubst (type, args, nargs),			       TYPE_READONLY (type),			       TYPE_VOLATILE (type));  switch (TREE_CODE (t))    {    case ERROR_MARK:    case IDENTIFIER_NODE:    case OP_IDENTIFIER:    case VOID_TYPE:    case REAL_TYPE:    case ENUMERAL_TYPE:    case INTEGER_CST:    case REAL_CST:    case STRING_CST:    case RECORD_TYPE:    case UNION_TYPE:      return t;    case INTEGER_TYPE:      if (t == integer_type_node)	return t;      if (TREE_CODE (TYPE_MIN_VALUE (t)) == INTEGER_CST	  && TREE_CODE (TYPE_MAX_VALUE (t)) == INTEGER_CST)	return t;      return build_index_2_type (tsubst (TYPE_MIN_VALUE (t), args, nargs),				 tsubst (TYPE_MAX_VALUE (t), args, nargs));    case TEMPLATE_TYPE_PARM:      return build_type_variant (args[TEMPLATE_TYPE_IDX (t)],				 TYPE_READONLY (t),				 TYPE_VOLATILE (t));    case TEMPLATE_CONST_PARM:      return args[TEMPLATE_CONST_IDX (t)];    case FUNCTION_DECL:      {	tree r;	tree fnargs, result;		if (type == TREE_TYPE (t)	    && (DECL_CONTEXT (t) == NULL_TREE		|| TREE_CODE_CLASS (TREE_CODE (DECL_CONTEXT (t))) != 't'))	  return t;	fnargs = tsubst (DECL_ARGUMENTS (t), args, nargs);	result = tsubst (DECL_RESULT (t), args, nargs);	if (DECL_CONTEXT (t) != NULL_TREE	    && TREE_CODE_CLASS (TREE_CODE (DECL_CONTEXT (t))) == 't')	  {	    /* Look it up in that class, and return the decl node there,	       instead of creating a new one.  */	    tree ctx, methods, name, method;	    int n_methods;	    int i, found = 0;	    name = DECL_NAME (t);	    ctx = tsubst (DECL_CONTEXT (t), args, nargs);	    methods = CLASSTYPE_METHOD_VEC (ctx);	    if (methods == NULL_TREE)	      /* No methods at all -- no way this one can match.  */	      goto no_match;	    n_methods = TREE_VEC_LENGTH (methods);	    r = NULL_TREE;	    if (!strncmp (OPERATOR_TYPENAME_FORMAT,			  IDENTIFIER_POINTER (name),			  sizeof (OPERATOR_TYPENAME_FORMAT) - 1))	      {		/* Type-conversion operator.  Reconstruct the name, in		   case it's the name of one of the template's parameters.  */		name = build_typename_overload (TREE_TYPE (type));	      }	    if (DECL_CONTEXT (t) != NULL_TREE		&& TREE_CODE_CLASS (TREE_CODE (DECL_CONTEXT (t))) == 't'		&& constructor_name (DECL_CONTEXT (t)) == DECL_NAME (t))	      name = constructor_name (ctx);#if 0	    fprintf (stderr, "\nfor function %s in class %s:\n",		     IDENTIFIER_POINTER (name),		     IDENTIFIER_POINTER (TYPE_IDENTIFIER (ctx)));#endif	    for (i = 0; i < n_methods; i++)	      {		method = TREE_VEC_ELT (methods, i);		if (method == NULL_TREE || DECL_NAME (method) != name)		  continue;		for (; method; method = TREE_CHAIN (method))		  {		    my_friendly_assert (TREE_CODE (method) == FUNCTION_DECL,					282);		    if (TREE_TYPE (method) != type)		      {			tree mtype = TREE_TYPE (method);			tree t1, t2;			t1 = TYPE_ARG_TYPES (mtype);			t2 = TYPE_ARG_TYPES (type);			if (TREE_CODE (mtype) == FUNCTION_TYPE)			  t2 = TREE_CHAIN (t2);			if (list_eq (t1, t2))			  {			    if (TREE_CODE (mtype) == FUNCTION_TYPE)			      {				tree newtype;				newtype = build_function_type (TREE_TYPE (type),							       TYPE_ARG_TYPES (type));				newtype = build_type_variant (newtype,							      TYPE_READONLY (type),							      TYPE_VOLATILE (type));				type = newtype;				if (TREE_TYPE (type) != TREE_TYPE (mtype))				  goto maybe_bad_return_type;			      }			    else if (TYPE_METHOD_BASETYPE (mtype)				     == TYPE_METHOD_BASETYPE (type))			      {				/* Types didn't match, but arg types and				   `this' do match, so the return type is				   all that should be messing it up.  */			      maybe_bad_return_type:				if (TREE_TYPE (type) != TREE_TYPE (mtype))				  error ("inconsistent return types for method `%s' in class `%s'",					 IDENTIFIER_POINTER (name),					 IDENTIFIER_POINTER (TYPE_IDENTIFIER (ctx)));			      }			    r = method;			    break;			  }			found = 1;			continue;		      }#if 0		    fprintf (stderr, "\tfound %s\n\n",			     IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (method)));#endif		    if (! TREE_PERMANENT (DECL_ARGUMENTS (method)))		      /* @@ Is this early enough?  Might we want to do			 this instead while processing the expansion?	 */		      DECL_ARGUMENTS (method)			= tsubst (DECL_ARGUMENTS (t), args, nargs);		    r = method;		    break;		  }	      }	    if (r == NULL_TREE)	      {	      no_match:		error (found		       ? "template for method `%s' doesn't match any in class `%s'"		       : "method `%s' not found in class `%s'",		       IDENTIFIER_POINTER (name),		       IDENTIFIER_POINTER (TYPE_IDENTIFIER (ctx)));		return error_mark_node;	      }	  }	else	  {	    r = DECL_NAME (t);	    {	      tree decls, val;	      int got_it = 0;	      decls = IDENTIFIER_GLOBAL_VALUE (r);	      if (decls == NULL_TREE)		/* no match */;	      else if (TREE_CODE (decls) == TREE_LIST)		while (decls)		  {		    val = TREE_VALUE (decls);		    decls = TREE_CHAIN (decls);		  try_one:		    if (TREE_CODE (val) == FUNCTION_DECL			&& TREE_TYPE (val) == type)		      {			got_it = 1;			r = val;			break;		      }		  }	      else		{		  val = decls;		  decls = NULL_TREE;		  goto try_one;		}	      if (!got_it)		r = build_lang_decl (FUNCTION_DECL, r, type);	    }	  }	TREE_PUBLIC (r) = TREE_PUBLIC (t);	DECL_EXTERNAL (r) = DECL_EXTERNAL (t);	TREE_STATIC (r) = TREE_STATIC (t);	DECL_INLINE (r) = DECL_INLINE (t);	DECL_SOURCE_FILE (r) = DECL_SOURCE_FILE (t);	DECL_SOURCE_LINE (r) = DECL_SOURCE_LINE (t);	DECL_CLASS_CONTEXT (r) = tsubst (DECL_CLASS_CONTEXT (t), args, nargs);	make_decl_rtl (r, 0, 1);	DECL_ARGUMENTS (r) = fnargs;	DECL_RESULT (r) = result;	if (DECL_CONTEXT (t) == NULL_TREE	    || TREE_CODE_CLASS (TREE_CODE (DECL_CONTEXT (t))) != 't')	  push_overloaded_decl_top_level (r, 0);	return r;      }    case PARM_DECL:      {	tree r;	r = build_decl (PARM_DECL, DECL_NAME (t), type);	DECL_INITIAL (r) = TREE_TYPE (r);	if (TREE_CHAIN (t))	  TREE_CHAIN (r) = tsubst (TREE_CHAIN (t), args, nargs);	return r;      }    case TREE_LIST:      {	tree purpose, value, chain, result;	int via_public, via_virtual, via_protected;	if (t == void_list_node)	  return t;	via_public = TREE_VIA_PUBLIC (t);	via_protected = TREE_VIA_PROTECTED (t);	via_virtual = TREE_VIA_VIRTUAL (t);	purpose = TREE_PURPOSE (t);	if (purpose)	  purpose = tsubst (purpose, args, nargs);	value = TREE_VALUE (t);	if (value)	  value = tsubst (value, args, nargs);	chain = TREE_CHAIN (t);	if (chain	    && chain != void_type_node)	  chain = tsubst (chain, args, nargs);	if (purpose == TREE_PURPOSE (t)	    && value == TREE_VALUE (t)	    && chain == TREE_CHAIN (t))	  return t;	result = hash_tree_cons (via_public, via_virtual, via_protected,				 purpose, value, chain);	TREE_PARMLIST (result) = TREE_PARMLIST (t);	return result;      }    case TREE_VEC:      {	int len = TREE_VEC_LENGTH (t), need_new = 0, i;	tree *elts = (tree *) alloca (len * sizeof (tree));	bzero (elts, len * sizeof (tree));	for (i = 0; i < len; i++)	  {	    elts[i] = tsubst (TREE_VEC_ELT (t, i), args, nargs);	    if (elts[i] != TREE_VEC_ELT (t, i))	      need_new = 1;	  }	if (!need_new)	  return t;	t = make_tree_vec (len);	for (i = 0; i < len; i++)	  TREE_VEC_ELT (t, i) = elts[i];	return t;      }    case POINTER_TYPE:    case REFERENCE_TYPE:      {	tree r;	enum tree_code code;	if (type == TREE_TYPE (t))	  return t;	code = TREE_CODE (t);	if (code == POINTER_TYPE)	  r = build_pointer_type (type);	else	  r = build_reference_type (type);	r = build_type_variant (r, TYPE_READONLY (t), TYPE_VOLATILE (t));	/* Will this ever be needed for TYPE_..._TO values?  */	layout_type (r);	return r;      }    case FUNCTION_TYPE:    case METHOD_TYPE:      {	tree values = TYPE_VALUES (t); /* same as TYPE_ARG_TYPES */	tree context = TYPE_CONTEXT (t);	tree new_value;	/* Don't bother recursing if we know it won't change anything.	*/	if (! (values == void_type_node	       || values == integer_type_node))	  values = tsubst (values, args, nargs);	if (context)	  context = tsubst (context, args, nargs);	/* Could also optimize cases where return value and	   values have common elements (e.g., T min(const &T, const T&).  */	/* If the above parameters haven't changed, just return the type.  */	if (type == TREE_TYPE (t)	    && values == TYPE_VALUES (t)	    && context == TYPE_CONTEXT (t))	  return t;	/* Construct a new type node and return it.  */	if (TREE_CODE (t) == FUNCTION_TYPE	    && context == NULL_TREE)	  {	    new_value = build_function_type (type, values);	  }	else if (context == NULL_TREE)	  {	    tree base = tsubst (TREE_TYPE (TREE_VALUE (TYPE_ARG_TYPES (t))),				args, nargs);	    new_value = build_cplus_method_type (base, type,						 TREE_CHAIN (values));	  }	else	  {	    new_value = make_node (TREE_CODE (t));	    TREE_TYPE (new_value) = type;	    TYPE_CONTEXT (new_value) = context;	    TYPE_VALUES (new_value) = values;	    TYPE_SIZE (new_value) = TYPE_SIZE (t);	    TYPE_ALIGN (new_value) = TYPE_ALIGN (t);	    TYPE_MODE (new_value) = TYPE_MODE (t);	    if (TYPE_METHOD_BASETYPE (t))	      TYPE_METHOD_BASETYPE (new_value) = tsubst (TYPE_METHOD_BASETYPE (t),							 args, nargs);	    /* Need to generate hash value.  */	    my_friendly_abort (84);	  }	new_value = build_type_variant (new_value,					TYPE_READONLY (t),					TYPE_VOLATILE (t));	return new_value;      }    case ARRAY_TYPE:      {	tree domain = tsubst (TYPE_DOMAIN (t), args, nargs);	tree r;	if (type == TREE_TYPE (t) && domain == TYPE_DOMAIN (t))	  return t;	r = build_cplus_array_type (type, domain);	return r;      }    case UNINSTANTIATED_P_TYPE:      {	int nparms = TREE_VEC_LENGTH (DECL_TEMPLATE_PARMS (UPT_TEMPLATE (t)));	tree argvec = make_tree_vec (nparms);	tree parmvec = UPT_PARMS (t);	int i;	tree id;	for (i = 0; i < nparms; i++)	  TREE_VEC_ELT (argvec, i) = tsubst (TREE_VEC_ELT (parmvec, i),					     args, nargs);	id = lookup_template_class (DECL_NAME (UPT_TEMPLATE (t)), argvec);	if (! IDENTIFIER_HAS_TYPE_VALUE (id)) {	  instantiate_class_template(id, 0);	  /* set up pending_classes */	  add_pending_template (id);	  TYPE_MAIN_VARIANT (IDENTIFIER_TYPE_VALUE (id)) =	    IDENTIFIER_TYPE_VALUE (id);	}	return build_type_variant (IDENTIFIER_TYPE_VALUE (id),				   TYPE_READONLY (t),				   TYPE_VOLATILE (t));      }    case MINUS_EXPR:    case PLUS_EXPR:      return fold (build (TREE_CODE (t), TREE_TYPE (t),			  tsubst (TREE_OPERAND (t, 0), args, nargs),			  tsubst (TREE_OPERAND (t, 1), args, nargs)));    case NEGATE_EXPR:    case NOP_EXPR:      return fold (build1 (TREE_CODE (t), TREE_TYPE (t),			   tsubst (TREE_OPERAND (t, 0), args, nargs)));    default:      sorry ("use of `%s' in function template",	     tree_code_name [(int) TREE_CODE (t)]);      return error_mark_node;    }}treeinstantiate_template (tmpl, targ_ptr)     tree tmpl, *targ_ptr;{  tree targs, fndecl;  int i, len;  struct pending_inline *p;  struct template_info *t;  struct obstack *old_fmp_obstack;  extern struct obstack *function_maybepermanent_obstack;  push_obstacks (&permanent_obstack, &permanent_obstack);  old_fmp_obstack = function_maybepermanent_obstack;  function_maybepermanent_obstack = &permanent_obstack;  my_friendly_assert (TREE_CODE (tmpl) == TEMPLATE_DECL, 283);  len = TREE_VEC_LENGTH (DECL_TEMPLATE_PARMS (tmpl));  for (fndecl = DECL_TEMPLATE_INSTANTIATIONS (tmpl);       fndecl; fndecl = TREE_CHAIN (fndecl))    {      tree *t1 = &TREE_VEC_ELT (TREE_PURPOSE (fndecl), 0);      for (i = len - 1; i >= 0; i--)	if (t1[i] != targ_ptr[i])	  goto no_match;      /* Here, we have a match.  */      fndecl = TREE_VALUE (fndecl);      function_maybepermanent_obstack = old_fmp_obstack;      pop_obstacks ();      return fndecl;    no_match:      ;    }  targs = make_tree_vec (len);  i = len;  while (i--)    TREE_VEC_ELT (targs, i) = targ_ptr[i];  /* substitute template parameters */  fndecl = tsubst (DECL_RESULT (tmpl), targ_ptr,		   TREE_VEC_LENGTH (targs));  t = DECL_TEMPLATE_INFO (tmpl);  if (t->text)    {      p = (struct pending_inline *) permalloc (sizeof (struct pending_inline));      p->parm_vec = t->parm_vec;      p->bindings = targs;      p->can_free = 0;      p->deja_vu = 0;      p->lineno = t->lineno;      p->filename = t->filename;      p->buf = t->text;      p->len = t->length;      p->fndecl = fndecl;      p->interface = 1;		/* unknown */    }  else    p = 0;  DECL_TEMPLATE_INSTANTIATIONS (tmpl) =    tree_cons (targs, fndecl, DECL_TEMPLATE_INSTANTIATIONS (tmpl));  function_maybepermanent_obstack = old_fmp_obstack;  pop_obstacks ();  if (fndecl == error_mark_node || p == 0)    {      /* do nothing */    }  else if (DECL_INLINE (fndecl))    {      DECL_PENDING_INLINE_INFO (fndecl) = p;      p->next = pending_inlines;      pending_inlines = p;    }  else    {      p->next = pending_template_expansions;      pending_template_expansions = p;    }  return fndecl;}voidundo_template_name_overload (id, classlevel)     tree id;     int classlevel;{  tree template;  template = IDENTIFIER_TEMPLATE (id);  if (!template)    return;#ifdef DEBUG_CP_BINDING_LEVELS  indent_to (stderr, debug_bindings_indentation);  fprintf (stderr, "undo_template_name_overload");  debug_bindings_indentation += 4;#endif#if 0 /* not yet, should get fixed properly later */  poplevel (0, 0, 0);#endif  if (!classlevel)    poplevel (0, 0, 0);#ifdef DEBUG_CP_BINDING_LEVELS  debug_bindings_indentation -= 4;#endif}void

⌨️ 快捷键说明

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