pt.c

来自「GCC编译器源代码」· C语言 代码 · 共 2,388 行 · 第 1/5 页

C
2,388
字号
/* Handle parameterized types (templates) for GNU C++.   Copyright (C) 1992, 93, 94, 95, 96, 1997 Free Software Foundation, Inc.   Written by Ken Raeburn (raeburn@cygnus.com) while at Watchmaker Computing.   Rewritten by Jason Merrill (jason@cygnus.com).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:     all methods must be provided in header files; can't use a source     file that contains only the method templates and "just win".  */#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"#include "except.h"#ifdef HAVE_STDLIB_H#include <stdlib.h>#endifextern struct obstack permanent_obstack;extern int lineno;extern char *input_filename;struct pending_inline *pending_template_expansions;tree current_template_parms;HOST_WIDE_INT processing_template_decl;tree pending_templates;static tree *template_tail = &pending_templates;tree maybe_templates;static tree *maybe_template_tail = &maybe_templates;int minimal_parse_mode;int processing_specialization;static int template_header_count;#define obstack_chunk_alloc xmalloc#define obstack_chunk_free freestatic int unify PROTO((tree, tree *, int, tree, tree, int *, int));static void add_pending_template PROTO((tree));static int push_tinst_level PROTO((tree));static tree classtype_mangled_name PROTO((tree));static char *mangle_class_name_for_template PROTO((char *, tree, tree));static tree tsubst_expr_values PROTO((tree, tree));static int comp_template_args PROTO((tree, tree));static int list_eq PROTO((tree, tree));static tree get_class_bindings PROTO((tree, tree, tree));static tree coerce_template_parms PROTO((tree, tree, tree));static tree tsubst_enum	PROTO((tree, tree, int, tree *));static tree add_to_template_args PROTO((tree, tree));static int  type_unification_real PROTO((tree, tree *, tree, tree, int*,					 int, int, int));static int processing_explicit_specialization PROTO((int));static void note_template_header PROTO((int));/* Restore the template parameter context. */void begin_member_template_processing (decl)     tree decl;{  tree parms;  int i;  parms = DECL_INNERMOST_TEMPLATE_PARMS (DECL_TI_TEMPLATE (decl));  ++processing_template_decl;  current_template_parms     = tree_cons (build_int_2 (0, processing_template_decl),		 parms, current_template_parms);  pushlevel (0);  for (i = 0; i < TREE_VEC_LENGTH (parms); ++i)     {      tree parm = TREE_VALUE (TREE_VEC_ELT (parms, i));      my_friendly_assert (TREE_CODE_CLASS (TREE_CODE (parm)) == 'd', 0);            switch (TREE_CODE (parm))	{	case TYPE_DECL:	  pushdecl (parm);	  break;	case PARM_DECL:	  {	    /* Make a CONST_DECL as is done in process_template_parm. */	    tree decl = build_decl (CONST_DECL, DECL_NAME (parm),				    TREE_TYPE (parm));	    DECL_INITIAL (decl) = DECL_INITIAL (parm);	    pushdecl (decl);	  }	break;	default:	  my_friendly_abort (0);	}    }}/* Undo the effects of begin_member_template_processing. */void end_member_template_processing (){  if (! processing_template_decl)    return;  --processing_template_decl;  current_template_parms = TREE_CHAIN (current_template_parms);  poplevel (0, 0, 0);}/* Returns non-zero iff T is a member template function.  Works if T   is either a FUNCTION_DECL or a TEMPLATE_DECL.  */intis_member_template (t)     tree t;{  int r = 0;  if (TREE_CODE (t) != FUNCTION_DECL      && !DECL_FUNCTION_TEMPLATE_P (t))    /* Anything that isn't a template or a template function is       certainly not a member template.  */    return 0;  if ((DECL_FUNCTION_MEMBER_P (t)        && !DECL_TEMPLATE_SPECIALIZATION (t))      || (TREE_CODE (t) == TEMPLATE_DECL && 	  DECL_FUNCTION_MEMBER_P (DECL_TEMPLATE_RESULT (t))))    {      tree tmpl = NULL_TREE;      if (DECL_FUNCTION_TEMPLATE_P (t))	tmpl = t;      else if (DECL_TEMPLATE_INFO (t) 	       && DECL_FUNCTION_TEMPLATE_P (DECL_TI_TEMPLATE (t)))	tmpl = DECL_TI_TEMPLATE (t);      if (tmpl) 	{	  tree parms = DECL_TEMPLATE_PARMS (tmpl);	  int parm_levels = list_length (parms);	  int template_class_levels = 0;	  tree ctx = DECL_CLASS_CONTEXT (t);	  if (CLASSTYPE_TEMPLATE_INFO (ctx))	    {	      tree args;	      /* Here, we should really count the number of levels		 deep ctx is, making sure not to count any levels that		 are just specializations.  Since there are no member		 template classes yet, we don't have to do all that.  */	      if (!CLASSTYPE_TEMPLATE_SPECIALIZATION (ctx))		template_class_levels = 1;	      else		{		  int i;		  args = CLASSTYPE_TI_ARGS (ctx);		  if (args == NULL_TREE)		    template_class_levels = 1;		  else 		    for (i = 0; i < TREE_VEC_LENGTH (args); ++i)		      if (uses_template_parms (TREE_VEC_ELT (args, i)))			{			  template_class_levels++;			  break;			}		}	    }	  if (parm_levels > template_class_levels)	    r = 1;	}    }  return r;}/* Return a new template argument vector which contains all of ARGS,   but has as its innermost set of arguments the EXTRA_ARGS.  */static treeadd_to_template_args (args, extra_args)     tree args;     tree extra_args;{  tree new_args;  if (TREE_CODE (TREE_VEC_ELT (args, 0)) != TREE_VEC)    {      new_args = make_tree_vec (2);      TREE_VEC_ELT (new_args, 0) = args;    }  else     {      int i;      new_args = make_tree_vec (TREE_VEC_LENGTH (args) - 1);      for (i = 0; i < TREE_VEC_LENGTH (args); ++i)	TREE_VEC_ELT (new_args, i) = TREE_VEC_ELT (args, i);    }	    TREE_VEC_ELT (new_args, 		TREE_VEC_LENGTH (new_args) - 1) = extra_args;  return new_args;}/* We've got a template header coming up; push to a new level for storing   the parms.  */voidbegin_template_parm_list (){  pushlevel (0);  declare_pseudo_global_level ();  ++processing_template_decl;  note_template_header (0);}/* We've just seen template <>. */voidbegin_specialization (){  note_template_header (1);}/* Called at then end of processing a declaration preceded by   template<>.  */void end_specialization (){  reset_specialization ();}/* Any template <>'s that we have seen thus far are not referring to a   function specialization. */voidreset_specialization (){  processing_specialization = 0;  template_header_count = 0;}/* We've just seen a template header.  If SPECIALIZATION is non-zero,   it was of the form template <>.  */static void note_template_header (specialization)     int specialization;{  processing_specialization = specialization;  template_header_count++;}/* Returns non-zero iff a declarator, in which the number of template   types that appeared was TEMPLATE_COUNT, is an explicit   specialization.  */static intprocessing_explicit_specialization (template_count)     int template_count;{  /* A function declaration is an explicit specialization of a member     template if all of the following conditions hold:          o There was a template <...> preceding the declaration.     o The last template <...> was in fact template <>.     o The number of template <...>'s preceding the declaration, less       the number of template classes with arguments specified used to       qualify the function name, is 1.     For example:     template <> void S<int>::foo();      template <class T> template <> void S<T>::foo();     template <> struct S<int> { ... template <> void foo(); }     The first of these is not a specialization of S<int>::foo() (it     is instead a specialization of S<T>::foo), while the next two are     specializations of member template functions.  */  return processing_specialization     && template_header_count > template_count; }/* Returns the template function specialized by TEMPLATE_ID, or   NULL_TREE if there is none.   The TEMPLATE_ID is a TEMPLATE_ID_EXPR.  The TYPE is   the type it has been declared to have.  Return the TEMPLATE_DECL   that is being specialized, and put the specialization arguments in   *TARGS.  If no appropriate specialization can be found, NULL_TREE is   returned, and *TARGS is assigned NULL_TREE.  If complain is   non-zero, error messages are printed where appropriate.  */   treedetermine_explicit_specialization (template_id, type, targs_out,				   need_member_template,				   complain)     tree template_id;     tree type;     tree* targs_out;     int need_member_template;     int complain;{  int i;  int overloaded;  tree fns;  tree matching_fns = NULL_TREE;  tree name = NULL_TREE;  tree result;  tree fn;  my_friendly_assert (TREE_CODE (template_id) == TEMPLATE_ID_EXPR,		      0); 		        fns = TREE_OPERAND (template_id, 0);  overloaded = fns != NULL_TREE && really_overloaded_fn (fns);  for (fn = (fns != NULL_TREE) ? get_first_fn (fns) : NULL_TREE;        fn != NULL_TREE;        fn = overloaded ? DECL_CHAIN (fn) : NULL_TREE)    {      int dummy = 0;      tree targs;      if (name == NULL_TREE)	name = DECL_NAME (fn);      if (TREE_CODE (fn) != TEMPLATE_DECL	  || (need_member_template && !is_member_template (fn)))	continue;      if (list_length (TREE_OPERAND (template_id, 1)) > DECL_NTPARMS (fn))	continue;      targs = make_scratch_vec (DECL_NTPARMS (fn));      /* We allow incomplete unification here, because we are going to	 check all the functions. */      i = type_unification (DECL_INNERMOST_TEMPLATE_PARMS (fn),			    &TREE_VEC_ELT (targs, 0),			    type 			    ? TYPE_ARG_TYPES (TREE_TYPE (fn)) : NULL_TREE, 			    type ? TYPE_ARG_TYPES (type) : NULL_TREE,			    TREE_OPERAND (template_id, 1),			    &dummy, 1, 1);            if (i == 0) 	{	  /* Unification was successful.  See if the return types	     match. */	  if (type != NULL_TREE)	    {	      tree tmpl_return_type = tsubst (TREE_TYPE (TREE_TYPE (fn)),					      targs,					      DECL_NTPARMS (fn),					      NULL_TREE);	      	      if (tmpl_return_type != TREE_TYPE (type))		{		  /* Always complain about this.  With ambiguity, some		     other context, might resolve things.  But, a		     non-matching return type will always be a		     problem.  */		  cp_error ("Return type of explicit specialization of");		  cp_error ("`%D' is `%T', but should be `%T'.", 			    fn, TREE_TYPE (type), tmpl_return_type);		  *targs_out = NULL_TREE;		  return NULL_TREE;		}	    }	  matching_fns = scratch_tree_cons (fn, targs, matching_fns);	}    }  if (matching_fns == NULL_TREE)    {      if (complain)	cp_error ("Specialization of `%s' does not match any template declaration.",		  IDENTIFIER_POINTER (name));      *targs_out = NULL_TREE;      return NULL_TREE;    }  if (TREE_CHAIN (matching_fns) != NULL_TREE)     {      if (complain)	{	  tree fn;	  	  cp_error ("Ambiguous explicit specialization.  Candidates are:");	  for (fn = matching_fns; fn != NULL_TREE; fn = TREE_CHAIN (fn))	    cp_error ("    %D", TREE_PURPOSE (fn));	}      *targs_out = NULL_TREE;      return NULL_TREE;    }  /* We have one, and exactly one, match. */  *targs_out = TREE_VALUE (matching_fns);  return TREE_PURPOSE (matching_fns);}	/* Check to see if the function just declared, as indicated in   DECLARATOR, and in DECL, is a specialization.  Check that the   specialization is OK.  If FLAGS == 1, we are being called by   finish_struct_methods.  If FLAGS == 2, we are being called by   grokfndecl, and the function has a definition, or is a friend.  If   FLAGS == 3, this is a friend declaration.   Returns 0 if the decl is not an explicit specialization or   instantiation, 1 if it is an explicit specialization, and 2 if it   is an explicit instantiation.  */intcheck_explicit_specialization (declarator, decl, template_count, flags)     tree declarator;     tree decl;     int template_count;     int flags;{  int finish_member = flags == 1;  int have_def = flags == 2;  int is_friend = flags == 3;  if (processing_explicit_specialization (template_count)      || finish_member      || TREE_CODE (declarator) == TEMPLATE_ID_EXPR)    {

⌨️ 快捷键说明

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