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

📄 pt.c

📁 gcc-2.95.3 Linux下最常用的C编译器
💻 C
📖 第 1 页 / 共 5 页
字号:
		       turns out to be a specialization:		         template <class T> void foo(T);			 class S { friend void foo<>(int) };			 template <> void foo(int);  		       We transform the existing DECL in place so that		       any pointers to it become pointers to the		       updated declaration.  		       If there was a definition for the template, but		       not for the specialization, we want this to		       look as if there is no definition, and vice		       versa.  */		    DECL_INITIAL (fn) = NULL_TREE;		    duplicate_decls (spec, fn);		    return fn;		  }	      }	    else if (DECL_TEMPLATE_SPECIALIZATION (fn))	      {		duplicate_decls (spec, fn);		return fn;	      }	  }      }  DECL_TEMPLATE_SPECIALIZATIONS (tmpl)     = perm_tree_cons (args, spec, DECL_TEMPLATE_SPECIALIZATIONS (tmpl));  return spec;}/* Unregister the specialization SPEC as a specialization of TMPL.   Returns nonzero if the SPEC was listed as a specialization of   TMPL.  */static intunregister_specialization (spec, tmpl)     tree spec;     tree tmpl;{  tree* s;  for (s = &DECL_TEMPLATE_SPECIALIZATIONS (tmpl);       *s != NULL_TREE;       s = &TREE_CHAIN (*s))    if (TREE_VALUE (*s) == spec)      {	*s = TREE_CHAIN (*s);	return 1;      }  return 0;}/* Print the list of candidate FNS in an error message.  */voidprint_candidates (fns)     tree fns;{  tree fn;  const char *str = "candidates are:";  for (fn = fns; fn != NULL_TREE; fn = TREE_CHAIN (fn))    {      tree f;      for (f = TREE_VALUE (fn); f; f = OVL_NEXT (f))	cp_error_at ("%s %+#D", str, OVL_CURRENT (f));      str = "               ";    }}/* Returns the template (one of the functions given by TEMPLATE_ID)   which can be specialized to match the indicated DECL with the   explicit template args given in TEMPLATE_ID.  The DECL may be   NULL_TREE if none is available.  In that case, the functions in   TEMPLATE_ID are non-members.   If NEED_MEMBER_TEMPLATE is non-zero the function is known to be a   specialization of a member template.   The template args (those explicitly specified and those deduced)   are output in a newly created vector *TARGS_OUT.   If it is impossible to determine the result, an error message is   issued.  The error_mark_node is returned to indicate failure.  */static treedetermine_specialization (template_id, decl, targs_out, 			  need_member_template)     tree template_id;     tree decl;     tree* targs_out;     int need_member_template;{  tree fn;  tree fns;  tree targs;  tree explicit_targs;  tree candidates = NULL_TREE;  tree templates = NULL_TREE;  *targs_out = NULL_TREE;  if (template_id == error_mark_node)    return error_mark_node;  fns = TREE_OPERAND (template_id, 0);  explicit_targs = TREE_OPERAND (template_id, 1);  if (fns == error_mark_node)    return error_mark_node;  /* Check for baselinks. */  if (TREE_CODE (fns) == TREE_LIST)    fns = TREE_VALUE (fns);  for (; fns; fns = OVL_NEXT (fns))    {      tree tmpl;      fn = OVL_CURRENT (fns);      if (TREE_CODE (fn) == TEMPLATE_DECL)	/* DECL might be a specialization of FN.  */	tmpl = fn;      else if (need_member_template)	/* FN is an ordinary member function, and we need a	   specialization of a member template.  */	continue;      else if (TREE_CODE (fn) != FUNCTION_DECL)	/* We can get IDENTIFIER_NODEs here in certain erroneous	   cases.  */	continue;      else if (!DECL_FUNCTION_MEMBER_P (fn))	/* This is just an ordinary non-member function.  Nothing can	   be a specialization of that.  */	continue;      else	{	  tree decl_arg_types;	  /* This is an ordinary member function.  However, since	     we're here, we can assume it's enclosing class is a	     template class.  For example,	     	       template <typename T> struct S { void f(); };	       template <> void S<int>::f() {}	     Here, S<int>::f is a non-template, but S<int> is a	     template class.  If FN has the same type as DECL, we	     might be in business.  */	  if (!same_type_p (TREE_TYPE (TREE_TYPE (decl)),			    TREE_TYPE (TREE_TYPE (fn))))	    /* The return types differ.  */	    continue;	  /* Adjust the type of DECL in case FN is a static member.  */	  decl_arg_types = TYPE_ARG_TYPES (TREE_TYPE (decl));	  if (DECL_STATIC_FUNCTION_P (fn) 	      && DECL_NONSTATIC_MEMBER_FUNCTION_P (decl))	    decl_arg_types = TREE_CHAIN (decl_arg_types);	  if (compparms (TYPE_ARG_TYPES (TREE_TYPE (fn)), 			 decl_arg_types))	    /* They match!  */	    candidates = tree_cons (NULL_TREE, fn, candidates);	  continue;	}      /* See whether this function might be a specialization of this	 template.  */      targs = get_bindings (tmpl, decl, explicit_targs);      if (!targs)	/* We cannot deduce template arguments that when used to	   specialize TMPL will produce DECL.  */	continue;      /* Save this template, and the arguments deduced.  */      templates = scratch_tree_cons (targs, tmpl, templates);    }  if (templates && TREE_CHAIN (templates))    {      /* We have:	 	   [temp.expl.spec]	   It is possible for a specialization with a given function	   signature to be instantiated from more than one function	   template.  In such cases, explicit specification of the	   template arguments must be used to uniquely identify the	   function template specialization being specialized.	 Note that here, there's no suggestion that we're supposed to	 determine which of the candidate templates is most	 specialized.  However, we, also have:	   [temp.func.order]	   Partial ordering of overloaded function template	   declarations is used in the following contexts to select	   the function template to which a function template	   specialization refers:            -- when an explicit specialization refers to a function	      template. 	 So, we do use the partial ordering rules, at least for now.	 This extension can only serve to make illegal programs legal,	 so it's safe.  And, there is strong anecdotal evidence that	 the committee intended the partial ordering rules to apply;	 the EDG front-end has that behavior, and John Spicer claims	 that the committee simply forgot to delete the wording in	 [temp.expl.spec].  */     tree tmpl = most_specialized (templates, decl, explicit_targs);     if (tmpl && tmpl != error_mark_node)       {	 targs = get_bindings (tmpl, decl, explicit_targs);	 templates = scratch_tree_cons (targs, tmpl, NULL_TREE);       }    }  if (templates == NULL_TREE && candidates == NULL_TREE)    {      cp_error_at ("template-id `%D' for `%+D' does not match any template declaration",		   template_id, decl);      return error_mark_node;    }  else if ((templates && TREE_CHAIN (templates))	   || (candidates && TREE_CHAIN (candidates))	   || (templates && candidates))    {      cp_error_at ("ambiguous template specialization `%D' for `%+D'",		   template_id, decl);      chainon (candidates, templates);      print_candidates (candidates);      return error_mark_node;    }  /* We have one, and exactly one, match. */  if (candidates)    {      /* It was a specialization of an ordinary member function in a	 template class.  */      *targs_out = copy_node (DECL_TI_ARGS (TREE_VALUE (candidates)));      return DECL_TI_TEMPLATE (TREE_VALUE (candidates));    }  /* It was a specialization of a template.  */  targs = DECL_TI_ARGS (DECL_RESULT (TREE_VALUE (templates)));  if (TMPL_ARGS_HAVE_MULTIPLE_LEVELS (targs))    {      *targs_out = copy_node (targs);      SET_TMPL_ARGS_LEVEL (*targs_out, 			   TMPL_ARGS_DEPTH (*targs_out),			   TREE_PURPOSE (templates));    }  else    *targs_out = TREE_PURPOSE (templates);  return TREE_VALUE (templates);}      /* Check to see if the function just declared, as indicated in   DECLARATOR, and in DECL, is a specialization of a function   template.  We may also discover that the declaration is an explicit   instantiation at this point.   Returns DECL, or an equivalent declaration that should be used   instead if all goes well.  Issues an error message if something is   amiss.  Returns error_mark_node if the error is not easily   recoverable.      FLAGS is a bitmask consisting of the following flags:    2: The function has a definition.   4: The function is a friend.   The TEMPLATE_COUNT is the number of references to qualifying   template classes that appeared in the name of the function.  For   example, in     template <class T> struct S { void f(); };     void S<int>::f();        the TEMPLATE_COUNT would be 1.  However, explicitly specialized   classes are not counted in the TEMPLATE_COUNT, so that in     template <class T> struct S {};     template <> struct S<int> { void f(); }     template <> void S<int>::f();   the TEMPLATE_COUNT would be 0.  (Note that this declaration is   illegal; there should be no template <>.)   If the function is a specialization, it is marked as such via   DECL_TEMPLATE_SPECIALIZATION.  Furthermore, its DECL_TEMPLATE_INFO   is set up correctly, and it is added to the list of specializations    for that template.  */treecheck_explicit_specialization (declarator, decl, template_count, flags)     tree declarator;     tree decl;     int template_count;     int flags;{  int have_def = flags & 2;  int is_friend = flags & 4;  int specialization = 0;  int explicit_instantiation = 0;  int member_specialization = 0;  tree ctype = DECL_CLASS_CONTEXT (decl);  tree dname = DECL_NAME (decl);  if (processing_specialization)     {      /* The last template header was of the form template <>.  */	        if (template_header_count > template_count) 	{	  /* There were more template headers than qualifying template	     classes.  */	  if (template_header_count - template_count > 1)	    /* There shouldn't be that many template parameter lists.	       There can be at most one parameter list for every	       qualifying class, plus one for the function itself.  */	    cp_error ("too many template parameter lists in declaration of `%D'", decl);	  SET_DECL_TEMPLATE_SPECIALIZATION (decl);	  if (ctype)	    member_specialization = 1;	  else	    specialization = 1;	}      else if (template_header_count == template_count)	{	  /* The counts are equal.  So, this might be a	     specialization, but it is not a specialization of a	     member template.  It might be something like		 	     template <class T> struct S { 	     void f(int i); 	     };	     template <>	     void S<int>::f(int i) {}  */	  specialization = 1;	  SET_DECL_TEMPLATE_SPECIALIZATION (decl);	}      else 	{	  /* This cannot be an explicit specialization.  There are not	     enough headers for all of the qualifying classes.  For	     example, we might have:	     	     template <>	     void S<int>::T<char>::f();	     But, we're missing another template <>.  */	  cp_error("too few template parameter lists in declaration of `%D'", decl);	  return decl;	}     }  else if (processing_explicit_instantiation)    {      if (template_header_count)	cp_error ("template parameter list used in explicit instantiation");	        if (have_def)	cp_error ("definition provided for explicit instantiation");      explicit_instantiation = 1;    }  else if (ctype != NULL_TREE	   && !TYPE_BEING_DEFINED (ctype)	   && CLASSTYPE_TEMPLATE_INSTANTIATION (ctype)	   && !is_friend)    {      /* This case catches outdated code that looks like this:	 template <class T> struct S { void f(); };	 void S<int>::f() {} // Missing template <>	 We disable this check when the type is being defined to	 avoid complaining about default compiler-generated	 constructors, destructors, and assignment operators.	 Since the type is an instantiation, not a specialization,	 these are the only functions that can be defined before	 the class is complete.  */	  /* If they said	       template <class T> void S<int>::f() {}	     that's bogus.  */      if (template_header_count)	{	  cp_error ("template parameters specified in specialization");	  return decl;	}      if (pedantic)	cp_pedwarn	  ("explicit specialization not preceded by `template <>'");      specialization = 1;      SET_DECL_TEMPLATE_SPECIALIZATION (decl);    }  else if (TREE_CODE (declarator) == TEMPLATE_ID_EXPR)    {      if (is_friend)	/* This could be something like:	   template <class T> void f(T);	   class S { friend void f<>(int); }  */	specialization = 1;      else	{	  /* This case handles bogus declarations like template <>	     template <class T> void f<int>(); */	  cp_error ("template-id `%D' in declaration of primary template",		    declarator);	  return decl;

⌨️ 快捷键说明

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