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

📄 pt.c

📁 gcc库的原代码,对编程有很大帮助.
💻 C
📖 第 1 页 / 共 5 页
字号:
/* Handle parameterized types (templates) for GNU C++.   Copyright (C) 1992, 1993, 1994, 1995 Free Software Foundation, Inc.   Written by Ken Raeburn (raeburn@cygnus.com) while at Watchmaker Computing.This file is part of GNU CC.GNU CC is free software; you can redistribute it and/or modifyit under the terms of the GNU General Public License as published bythe Free Software Foundation; either version 2, or (at your option)any later version.GNU CC is distributed in the hope that it will be useful,but WITHOUT ANY WARRANTY; without even the implied warranty ofMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See theGNU General Public License for more details.You should have received a copy of the GNU General Public Licensealong with GNU CC; see the file COPYING.  If not, write tothe Free Software Foundation, 59 Temple Place - Suite 330,Boston, MA 02111-1307, USA.  *//* Known bugs or deficiencies include:   * templates for class static data don't work (methods only)   * duplicated method templates can crash the compiler   * interface/impl data is taken from file defining the template   * all methods must be provided in header files; can't use a source     file that contains only the method templates and "just win"   * method templates must be seen before the expansion of the     class template is done */#include "config.h"#include <stdio.h>#include "obstack.h"#include "tree.h"#include "flags.h"#include "cp-tree.h"#include "decl.h"#include "parse.h"#include "lex.h"#include "output.h"#include "defaults.h"extern struct obstack permanent_obstack;extern int lineno;extern char *input_filename;struct pending_inline *pending_template_expansions;int processing_template_decl;int processing_template_defn;/* This is a kludge to handle instantiation of template methods that are   used before their definition.  It should not be necessary after the   template rewrite.  */static tree template_classes;#define obstack_chunk_alloc xmalloc#define obstack_chunk_free freestatic int unify ();static void add_pending_template ();void overload_template_name (), pop_template_decls ();/* We've got a template header coming up; set obstacks up to save the   nodes created permanently.  (There might be cases with nested templates   where we don't have to do this, but they aren't implemented, and it   probably wouldn't be worth the effort.)  */voidbegin_template_parm_list (){  pushlevel (0);  push_obstacks (&permanent_obstack, &permanent_obstack);  pushlevel (0);}/* Process information from new template parameter NEXT and append it to the   LIST being built.  The rules for use of a template parameter type name   by later parameters are not well-defined for us just yet.  However, the   only way to avoid having to parse expressions of unknown complexity (and   with tokens of unknown types) is to disallow it completely.	So for now,   that is what is assumed.  */treeprocess_template_parm (list, next)     tree list, next;{  tree parm;  tree decl = 0;  tree defval;  int is_type;  parm = next;  my_friendly_assert (TREE_CODE (parm) == TREE_LIST, 259);  defval = TREE_PURPOSE (parm);  parm = TREE_VALUE (parm);  is_type = TREE_PURPOSE (parm) == class_type_node;  if (!is_type)    {      tree tinfo = 0;      my_friendly_assert (TREE_CODE (TREE_PURPOSE (parm)) == TREE_LIST, 260);      /* is a const-param */      parm = grokdeclarator (TREE_VALUE (parm), TREE_PURPOSE (parm),			     PARM, 0, NULL_TREE, NULL_TREE);      /* A template parameter is not modifiable.  */      TREE_READONLY (parm) = 1;      if (IS_AGGR_TYPE (TREE_TYPE (parm)))	{	  sorry ("aggregate template parameter types");	  TREE_TYPE (parm) = void_type_node;	}      tinfo = make_node (TEMPLATE_CONST_PARM);      my_friendly_assert (TREE_PERMANENT (tinfo), 260.5);      if (TREE_PERMANENT (parm) == 0)        {	  parm = copy_node (parm);	  TREE_PERMANENT (parm) = 1;        }      TREE_TYPE (tinfo) = TREE_TYPE (parm);      decl = build_decl (CONST_DECL, DECL_NAME (parm), TREE_TYPE (parm));      DECL_INITIAL (decl) = tinfo;      DECL_INITIAL (parm) = tinfo;    }  else    {      tree t = make_node (TEMPLATE_TYPE_PARM);      decl = build_decl (TYPE_DECL, TREE_VALUE (parm), t);      TYPE_MAIN_DECL (t) = decl;      parm = decl;      if (defval)	{	  if (IDENTIFIER_HAS_TYPE_VALUE (defval))	    defval = IDENTIFIER_TYPE_VALUE (defval);	  else	    defval = TREE_TYPE (IDENTIFIER_GLOBAL_VALUE (defval));	}    }  SET_DECL_ARTIFICIAL (decl);  pushdecl (decl);  parm = build_tree_list (defval, parm);  return chainon (list, parm);}/* The end of a template parameter list has been reached.  Process the   tree list into a parameter vector, converting each parameter into a more   useful form.	 Type parameters are saved as IDENTIFIER_NODEs, and others   as PARM_DECLs.  */treeend_template_parm_list (parms)     tree parms;{  int nparms = 0;  int saw_default = 0;  tree saved_parmlist;  tree parm;  for (parm = parms; parm; parm = TREE_CHAIN (parm))    nparms++;  saved_parmlist = make_tree_vec (nparms);  for (parm = parms, nparms = 0; parm; parm = TREE_CHAIN (parm), nparms++)    {      tree p = TREE_VALUE (parm);      if (TREE_PURPOSE (parm))	saw_default = 1;      else if (saw_default)	{	  error ("if a default argument is given for one template parameter");	  error ("default arguments must be given for all subsequent");	  error ("parameters as well");	}      if (TREE_CODE (p) == TYPE_DECL)	{	  tree t = TREE_TYPE (p);	  TEMPLATE_TYPE_SET_INFO (t, saved_parmlist, nparms);	}      else	{	  tree tinfo = DECL_INITIAL (p);	  DECL_INITIAL (p) = NULL_TREE;	  TEMPLATE_CONST_SET_INFO (tinfo, saved_parmlist, nparms);	}      TREE_VEC_ELT (saved_parmlist, nparms) = parm;    }  set_current_level_tags_transparency (1);  processing_template_decl++;  return saved_parmlist;}/* end_template_decl is called after a template declaration is seen.   D1 is template header; D2 is class_head_sans_basetype or a   TEMPLATE_DECL with its DECL_RESULT field set.  */voidend_template_decl (d1, d2, is_class, defn)     tree d1, d2, is_class;     int defn;{  tree decl;  struct template_info *tmpl;  tmpl = (struct template_info *) obstack_alloc (&permanent_obstack,					    sizeof (struct template_info));  tmpl->text = 0;  tmpl->length = 0;  tmpl->aggr = is_class;  /* cloned from reinit_parse_for_template */  tmpl->filename = input_filename;  tmpl->lineno = lineno;  tmpl->parm_vec = d1;          /* [eichin:19911015.2306EST] */  if (d2 == NULL_TREE || d2 == error_mark_node)    {      decl = 0;      goto lose;    }  if (is_class)    {      decl = build_lang_decl (TEMPLATE_DECL, d2, NULL_TREE);      GNU_xref_decl (current_function_decl, decl);    }  else    {      if (TREE_CODE (d2) == TEMPLATE_DECL)	decl = d2;      else	{	  /* Class destructor templates and operator templates are	     slipping past as non-template nodes.  Process them here, since	     I haven't figured out where to catch them earlier.  I could	     go do that, but it's a choice between getting that done and	     staying only N months behind schedule.  Sorry....  */	  enum tree_code code;	  my_friendly_assert (TREE_CODE (d2) == CALL_EXPR, 263);	  code = TREE_CODE (TREE_OPERAND (d2, 0));	  my_friendly_assert (code == BIT_NOT_EXPR		  || code == OP_IDENTIFIER		  || code == SCOPE_REF, 264);	  d2 = grokdeclarator (d2, NULL_TREE, MEMFUNCDEF, 0, NULL_TREE, NULL_TREE);	  decl = build_lang_decl (TEMPLATE_DECL, DECL_NAME (d2),				  TREE_TYPE (d2));	  DECL_TEMPLATE_RESULT (decl) = d2;	  DECL_CONTEXT (decl) = DECL_CONTEXT (d2);	  DECL_CLASS_CONTEXT (decl) = DECL_CLASS_CONTEXT (d2);	  DECL_NAME (decl) = DECL_NAME (d2);	  TREE_TYPE (decl) = TREE_TYPE (d2);	  if (interface_unknown && flag_external_templates	      && ! flag_alt_external_templates	      && ! DECL_IN_SYSTEM_HEADER (decl))	    warn_if_unknown_interface (decl);	  TREE_PUBLIC (decl) = TREE_PUBLIC (d2) = flag_external_templates && !interface_unknown;	  DECL_EXTERNAL (decl) = (DECL_EXTERNAL (d2)				  && !(DECL_CLASS_CONTEXT (d2)				       && !DECL_THIS_EXTERN (d2)));	}      /* All routines creating TEMPLATE_DECL nodes should now be using	 build_lang_decl, which will have set this up already.	*/      my_friendly_assert (DECL_LANG_SPECIFIC (decl) != 0, 265);      /* @@ Somewhere, permanent allocation isn't being used.  */      if (! DECL_TEMPLATE_IS_CLASS (decl)	  && TREE_CODE (DECL_TEMPLATE_RESULT (decl)) == FUNCTION_DECL)	{	  tree result = DECL_TEMPLATE_RESULT (decl);	  /* Will do nothing if allocation was already permanent.  */	  DECL_ARGUMENTS (result) = copy_to_permanent (DECL_ARGUMENTS (result));	}      /* If this is for a method, there's an extra binding level here.	*/      if (DECL_CONTEXT (DECL_TEMPLATE_RESULT (decl)) != NULL_TREE)	{	  /* @@ Find out where this should be getting set!  */	  tree r = DECL_TEMPLATE_RESULT (decl);	  if (DECL_LANG_SPECIFIC (r) && DECL_CLASS_CONTEXT (r) == NULL_TREE)	    DECL_CLASS_CONTEXT (r) = DECL_CONTEXT (r);	}    }  DECL_TEMPLATE_INFO (decl) = tmpl;  DECL_TEMPLATE_PARMS (decl) = d1;  /* So that duplicate_decls can do the right thing.  */  if (defn)    DECL_INITIAL (decl) = error_mark_node;    /* If context of decl is non-null (i.e., method template), add it     to the appropriate class template, and pop the binding levels.  */  if (! is_class && DECL_CONTEXT (DECL_TEMPLATE_RESULT (decl)) != NULL_TREE)    {      tree ctx = DECL_CONTEXT (DECL_TEMPLATE_RESULT (decl));      tree tmpl, t;      my_friendly_assert (TREE_CODE (ctx) == UNINSTANTIATED_P_TYPE, 266);      tmpl = UPT_TEMPLATE (ctx);      for (t = DECL_TEMPLATE_MEMBERS (tmpl); t; t = TREE_CHAIN (t))	if (TREE_PURPOSE (t) == DECL_NAME (decl)	    && duplicate_decls (decl, TREE_VALUE (t)))	  goto already_there;      DECL_TEMPLATE_MEMBERS (tmpl) =	perm_tree_cons (DECL_NAME (decl), decl, DECL_TEMPLATE_MEMBERS (tmpl));    already_there:      poplevel (0, 0, 0);      poplevel (0, 0, 0);    }  /* Otherwise, go back to top level first, and push the template decl     again there.  */  else    {      poplevel (0, 0, 0);      poplevel (0, 0, 0);      pushdecl (decl);    } lose:#if 0 /* It happens sometimes, with syntactic or semantic errors.	 One specific case:	 template <class A, int X, int Y> class Foo { ... };	 template <class A, int X, int y> Foo<X,Y>::method (Foo& x) { ... }	 Note the missing "A" in the class containing "method".  */  my_friendly_assert (global_bindings_p (), 267);#else  while (! global_bindings_p ())    poplevel (0, 0, 0);#endif  pop_obstacks ();  processing_template_decl--;  (void) get_pending_sizes ();}tree tsubst		PROTO ((tree, tree*, int, tree));/* Convert all template arguments to their appropriate types, and return   a vector containing the resulting values.  If any error occurs, return   error_mark_node.  */static treecoerce_template_parms (parms, arglist, in_decl)     tree parms, arglist;     tree in_decl;{  int nparms, nargs, i, lost = 0;  tree vec;  if (arglist == NULL_TREE)    nargs = 0;  else if (TREE_CODE (arglist) == TREE_VEC)    nargs = TREE_VEC_LENGTH (arglist);  else    nargs = list_length (arglist);  nparms = TREE_VEC_LENGTH (parms);  if (nargs > nparms      || (nargs < nparms	  && TREE_PURPOSE (TREE_VEC_ELT (parms, nargs)) == NULL_TREE))    {      error ("incorrect number of parameters (%d, should be %d)",	     nargs, nparms);      if (in_decl)	cp_error_at ("in template expansion for decl `%D'", in_decl);      return error_mark_node;    }  if (arglist && TREE_CODE (arglist) == TREE_VEC)    vec = copy_node (arglist);  else    {      vec = make_tree_vec (nparms);      for (i = 0; i < nparms; i++)	{	  tree arg;	  if (arglist)	    {	      arg = arglist;	      arglist = TREE_CHAIN (arglist);	      if (arg == error_mark_node)		lost++;	      else		arg = TREE_VALUE (arg);	    }	  else	    arg = TREE_PURPOSE (TREE_VEC_ELT (parms, i));	  TREE_VEC_ELT (vec, i) = arg;	}    }  for (i = 0; i < nparms; i++)    {      tree arg = TREE_VEC_ELT (vec, i);      tree parm = TREE_VALUE (TREE_VEC_ELT (parms, i));      tree val = 0;      int is_type, requires_type;      is_type = TREE_CODE_CLASS (TREE_CODE (arg)) == 't';      requires_type = TREE_CODE (parm) == TYPE_DECL;      if (is_type != requires_type)	{	  if (in_decl)	    cp_error ("type/value mismatch in template parameter list for `%D'",		      in_decl);	  lost++;	  TREE_VEC_ELT (vec, i) = error_mark_node;	  continue;	}      if (is_type)	val = groktypename (arg);      else	{	  tree t = tsubst (TREE_TYPE (parm), &TREE_VEC_ELT (vec, 0),			   TREE_VEC_LENGTH (vec), in_decl);	  val = digest_init (t, arg, (tree *) 0);	  if (val == error_mark_node)	    ;	  /* 14.2: Other template-arguments must be constant-expressions,	     addresses of objects or functions with external linkage, or of	     static class members.  */	  else if (!TREE_CONSTANT (val))	    {	      cp_error ("non-const `%E' cannot be used as template argument",			arg);	      val = error_mark_node;	    }	  else if (POINTER_TYPE_P (TREE_TYPE (val))		   && ! integer_zerop (val)		   && TREE_CODE (TREE_TYPE (TREE_TYPE (val))) != OFFSET_TYPE		   && TREE_CODE (TREE_TYPE (TREE_TYPE (val))) != METHOD_TYPE)	    {	      t = val;	      STRIP_NOPS (t);	      if (TREE_CODE (t) == ADDR_EXPR)		{		  tree a = TREE_OPERAND (t, 0);		  STRIP_NOPS (a);		  if (TREE_CODE (a) == STRING_CST)		    {		      cp_error ("string literal %E is not a valid template argument", a);		      error ("because it is the address of an object with static linkage");		      val = error_mark_node;		    }		  else if (TREE_CODE (a) != VAR_DECL			   && TREE_CODE (a) != FUNCTION_DECL)		    goto bad;		  else if (! DECL_PUBLIC (a))		    {		      cp_error ("address of non-extern `%E' cannot be used as template argument", a);		      val = error_mark_node;		    }		}	      else		{		bad:		  cp_error ("`%E' is not a valid template argument", t);		  error ("it must be %s%s with external linkage",			 TREE_CODE (TREE_TYPE (val)) == POINTER_TYPE			 ? "a pointer to " : "",

⌨️ 快捷键说明

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