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

📄 pt.c

📁 gcc库的原代码,对编程有很大帮助.
💻 C
📖 第 1 页 / 共 5 页
字号:
static struct tinst_level *free_tinst_level = 0;static int tinst_depth = 0;int max_tinst_depth = 17;intpush_tinst_level (name)     tree name;{  struct tinst_level *new;  tree global = IDENTIFIER_GLOBAL_VALUE (name);  if (tinst_depth >= max_tinst_depth)    {      error ("template instantiation depth exceeds maximum of %d",	     max_tinst_depth);      cp_error ("  instantiating `%D'", name);      return 0;    }  if (free_tinst_level)    {      new = free_tinst_level;      free_tinst_level = new->next;    }  else    new = (struct tinst_level *) xmalloc (sizeof (struct tinst_level));  new->classname = name;  if (global)    {      new->line = DECL_SOURCE_LINE (global);      new->file = DECL_SOURCE_FILE (global);    }  else    {      new->line = lineno;      new->file = input_filename;    }  new->next = current_tinst_level;  current_tinst_level = new;  ++tinst_depth;  return 1;}voidpop_tinst_level (){  struct tinst_level *old = current_tinst_level;  current_tinst_level = old->next;  old->next = free_tinst_level;  free_tinst_level = old;  --tinst_depth;}struct tinst_level *tinst_for_decl (){  struct tinst_level *p = current_tinst_level;  if (p)    for (; p->next ; p = p->next )      ;  return p;}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 IDENTIFIER_LOCAL_VALUE is already set on this template classname     (it's something like `foo<int>'), that means we're already working on     the instantiation for it.  Normally, a classname comes in with nothing     but its IDENTIFIER_TEMPLATE slot set.  If we were to try to instantiate     this again, we'd get a redeclaration error.  Since we're already working     on it, we'll pass back this classname's TYPE_DECL (it's the value of     the classname's IDENTIFIER_LOCAL_VALUE).  Only do this if we're setting     things up for the parser, though---if we're just trying to instantiate     it (e.g., via tsubst) we can trip up cuz it may not have an     IDENTIFIER_TYPE_VALUE when it will need one.  */  if (setup_parse && IDENTIFIER_LOCAL_VALUE (classname))    return IDENTIFIER_LOCAL_VALUE (classname);  if (uses_template_parms (classname))    {      if (!TREE_TYPE (classname))	{	  tree t = make_lang_type (RECORD_TYPE);	  tree d = build_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;  push_to_top_level ();  template_info = DECL_TEMPLATE_INFO (t1);  if (setup_parse && push_tinst_level (classname))    {      push_template_decls (DECL_TEMPLATE_PARMS (TREE_PURPOSE (template)),			   TREE_VALUE (template), 0);      set_current_level_tags_transparency (1);      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);      /* Kludge so that we don't get screwed by our own base classes.  */      TYPE_BEING_DEFINED (TREE_TYPE (classname)) = 1;      yychar = PRE_PARSED_CLASS_DECL;      yylval.ttype = classname;      processing_template_defn++;      if (!flag_external_templates)	interface_unknown++;      template_classes	= perm_tree_cons (classname, NULL_TREE, template_classes);    }  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, 0);      my_friendly_assert (TREE_CODE (t) == RECORD_TYPE			  || TREE_CODE (t) == UNION_TYPE, 280);      /* 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 ();    }  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 tree lookup_nested_type_by_name (ctype, name)        tree ctype, name;{  tree t;  for (t = CLASSTYPE_TAGS (ctype); t; t = TREE_CHAIN (t))    {      if (name == TREE_PURPOSE (t))	return TREE_VALUE (t);    }  return NULL_TREE;}static treesearch_nested_type_in_tmpl (tmpl, type)        tree tmpl, type;{  tree t;  if (tmpl == NULL || TYPE_CONTEXT(type) == NULL)    return tmpl;  t = search_nested_type_in_tmpl (tmpl, TYPE_CONTEXT(type));  if (t == NULL) return t;  t = lookup_nested_type_by_name(t, DECL_NAME(TYPE_NAME(type)));  return t;}treetsubst (t, args, nargs, in_decl)     tree t, *args;     int nargs;     tree in_decl;{  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	 significant?  */      && type != integer_type_node      && type != void_type_node      && type != char_type_node)    type = tsubst (type, args, nargs, in_decl);  switch (TREE_CODE (t))    {    case RECORD_TYPE:      if (TYPE_PTRMEMFUNC_P (t))	return build_ptrmemfunc_type	  (tsubst (TYPE_PTRMEMFUNC_FN_TYPE (t), args, nargs, in_decl));	        /* else fall through */    case ERROR_MARK:    case IDENTIFIER_NODE:    case OP_IDENTIFIER:    case VOID_TYPE:    case REAL_TYPE:    case ENUMERAL_TYPE:    case BOOLEAN_TYPE:    case INTEGER_CST:    case REAL_CST:    case STRING_CST:    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, in_decl),	 tsubst (TYPE_MAX_VALUE (t), args, nargs, in_decl));    case TEMPLATE_TYPE_PARM:      {	tree arg = args[TEMPLATE_TYPE_IDX (t)];	return cp_build_type_variant	  (arg, TYPE_READONLY (arg) || TYPE_READONLY (t),	   TYPE_VOLATILE (arg) || 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, t);	result = tsubst (DECL_RESULT (t), args, nargs, t);	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, t);	    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 (DECL_CONSTRUCTOR_P (t) && TYPE_USES_VIRTUAL_BASECLASSES (ctx))	      {		/* Since we didn't know that this class had virtual bases until after		   we instantiated it, we have to recreate the arguments to this		   constructor, as otherwise it would miss the __in_chrg parameter.  */		tree newtype, parm;		tree parms = TREE_CHAIN (TYPE_ARG_TYPES (type));		parms = hash_tree_chain (integer_type_node, parms);		newtype = build_cplus_method_type (ctx,						   TREE_TYPE (type),						   parms);		newtype = build_type_variant (newtype,					      TYPE_READONLY (type),					      TYPE_VOLATILE (type));		type = newtype;		fnargs = copy_node (DECL_ARGUMENTS (t));		TREE_CHAIN (fnargs) = TREE_CHAIN (DECL_ARGUMENTS (t));		/* In this case we need "in-charge" flag saying whether		   this constructor is responsible for initialization		   of virtual baseclasses or not.  */		parm = build_decl (PARM_DECL, in_charge_identifier, integer_type_node);		/* Mark the artificial `__in_chrg' parameter as "artificial".  */		SET_DECL_ARTIFICIAL (parm);		DECL_ARG_TYPE (parm) = integer_type_node;		DECL_REGISTER (parm) = 1;		TREE_CHAIN (parm) = TREE_CHAIN (fnargs);		TREE_CHAIN (fnargs) = parm;		fnargs = tsubst (fnargs, args, nargs, t);	      }#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++)	      {		int pass;		method = TREE_VEC_ELT (methods, i);		if (method == NULL_TREE || DECL_NAME (method) != name)		  continue;		pass = 0;	      maybe_error:		for (; method; method = DECL_CHAIN (method))		  {		    my_friendly_assert (TREE_CODE (method) == FUNCTION_DECL,					282);		    if (! comptypes (type, TREE_TYPE (method), 1))		      {			tree mtype = TREE_TYPE (method);			tree t1, t2;			/* Keep looking for a method that matches			   perfectly.  This takes care of the problem			   where destructors (which have implicit int args)			   look like constructors which have an int arg.  */			if (pass == 0)			  continue;			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 (DECL_ARTIFICIAL (method))		      {			cp_error ("template for method `%D' which has default implementation in class `%T'", name, ctx);			if (in_decl)			  cp_error_at ("in attempt to instantiate `%D' declared at this point in file", in_decl);			return error_mark_node;		      }		    if (DECL_ARGUMENTS (method)			&& ! 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, t);		    r = method;		    break;		  }		if (r == NULL_TREE && pass == 0)		  {		    pass = 1;		    method = TREE_VEC_ELT (methods, i);

⌨️ 快捷键说明

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