This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

C++ PATCH: PR 22263


This patch fixes a problem with explicit instantiation caused by:

  2004-06-02  Matt Austern  <austern@apple.com>

	* cp-tree.h (instantiate_decl): new boolean parameter,
	undefined_ok. Current behavior is equivalent to its being 0.
	...

The intent was that when explicitly instantiating a class template,
any members whose definitions were not available would be treated as
implicit instantiations.  The standard doesn't say whether the
members are instantiated implicitly or explicitly, so we use explicit
instantiations except where the definition is not available.  However,
the code that was supposed to reset the instantiated member to
implicit instantiation status wasn't complete; it forgot to reset
DECL_INTERFACE_KNOWN.

Tested on x86_64-unknown-linux-gnu, applied on the mainline and on the
branch.  The branch version contains just the DECL_INTERFACE_KNOWN
change, not the renaming cleanups.

I tried to make the test case work on systems (like AIX) that do not
have implicit instantiation, and I tested that with
-fno-implicit-templates.  But, there might be some problem; if people
start seeing failures for explicit7.C on such systems, please let me
know.  

--
Mark Mitchell
CodeSourcery, LLC
mark@codesourcery.com
 
2005-07-18  Mark Mitchell  <mark@codesourcery.com>

	PR c++/22263
	* cp-tree.h (instantiate_decl): Change prototype.
	* decl2.c (mark_used): Adjust accordingly.
	* pt.c (do_decl_instantiation): Likewise.
	(instantiate_class_member): Likewise.
	(instantiate_decl): Rename undefined_ok as expl_inst_class_mem_p.
	Clear DECL_INTERFACE_KNOWN for an explicitly instantiated template
	that has no definition available.
	(instantiate_pending_templates): Adjust call to instantiate_decl.

2005-07-18  Mark Mitchell  <mark@codesourcery.com>

	PR c++/22263
	* g++.dg/template/explicit7.C: New test.

Index: gcc/testsuite/g++.dg/template/explicit7.C
===================================================================
RCS file: gcc/testsuite/g++.dg/template/explicit7.C
diff -N gcc/testsuite/g++.dg/template/explicit7.C
*** /dev/null	1 Jan 1970 00:00:00 -0000
--- gcc/testsuite/g++.dg/template/explicit7.C	18 Jul 2005 15:38:53 -0000
***************
*** 0 ****
--- 1,13 ----
+ // PR c++/22263
+ // { dg-do link }
+ 
+ template <class T> struct S { T foo (); T bar (); };
+ template <class T> T S<T>::foo () { return bar (); }
+ template struct S<int>;
+ template <class T> T S<T>::bar () { return T (); }
+ 
+ #if !__GXX_WEAK__
+ template int S<int>::bar ();
+ #endif
+ 
+ int main () { return S<int>().foo (); }
Index: gcc/cp/cp-tree.h
===================================================================
RCS file: /cvs/gcc/gcc/gcc/cp/cp-tree.h,v
retrieving revision 1.1155
diff -c -5 -p -r1.1155 cp-tree.h
*** gcc/cp/cp-tree.h	17 Jul 2005 22:02:09 -0000	1.1155
--- gcc/cp/cp-tree.h	18 Jul 2005 15:38:53 -0000
*************** extern int fn_type_unification			(tree, 
*** 3995,4005 ****
  extern void mark_decl_instantiated		(tree, int);
  extern int more_specialized_fn			(tree, tree, int);
  extern void mark_class_instantiated		(tree, int);
  extern void do_decl_instantiation		(tree, tree);
  extern void do_type_instantiation		(tree, tree, tsubst_flags_t);
! extern tree instantiate_decl			(tree, int, int);
  extern int push_tinst_level			(tree);
  extern void pop_tinst_level			(void);
  extern int more_specialized_class		(tree, tree, tree);
  extern int comp_template_parms			(tree, tree);
  extern int template_class_depth			(tree);
--- 3995,4005 ----
  extern void mark_decl_instantiated		(tree, int);
  extern int more_specialized_fn			(tree, tree, int);
  extern void mark_class_instantiated		(tree, int);
  extern void do_decl_instantiation		(tree, tree);
  extern void do_type_instantiation		(tree, tree, tsubst_flags_t);
! extern tree instantiate_decl			(tree, int, bool);
  extern int push_tinst_level			(tree);
  extern void pop_tinst_level			(void);
  extern int more_specialized_class		(tree, tree, tree);
  extern int comp_template_parms			(tree, tree);
  extern int template_class_depth			(tree);
Index: gcc/cp/decl2.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/cp/decl2.c,v
retrieving revision 1.791
diff -c -5 -p -r1.791 decl2.c
*** gcc/cp/decl2.c	8 Jul 2005 23:37:00 -0000	1.791
--- gcc/cp/decl2.c	18 Jul 2005 15:38:53 -0000
*************** mark_used (tree decl)
*** 3276,3284 ****
  			      (template_for_substitution (decl))))))
      /* We put off instantiating functions in order to improve compile
         times.  Maintaining a stack of active functions is expensive,
         and the inliner knows to instantiate any functions it might
         need.  */
!     instantiate_decl (decl, /*defer_ok=*/true, /*undefined_ok=*/0);
  }
  
  #include "gt-cp-decl2.h"
--- 3276,3285 ----
  			      (template_for_substitution (decl))))))
      /* We put off instantiating functions in order to improve compile
         times.  Maintaining a stack of active functions is expensive,
         and the inliner knows to instantiate any functions it might
         need.  */
!     instantiate_decl (decl, /*defer_ok=*/true, 
! 		      /*expl_inst_class_mem_p=*/false);
  }
  
  #include "gt-cp-decl2.h"
Index: gcc/cp/pt.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/cp/pt.c,v
retrieving revision 1.1015
diff -c -5 -p -r1.1015 pt.c
*** gcc/cp/pt.c	12 Jul 2005 16:07:34 -0000	1.1015
--- gcc/cp/pt.c	18 Jul 2005 15:38:53 -0000
*************** do_decl_instantiation (tree decl, tree s
*** 11008,11018 ****
    else
      error ("storage class %qD applied to template instantiation", storage);
  
    mark_decl_instantiated (result, extern_p);
    if (! extern_p)
!     instantiate_decl (result, /*defer_ok=*/1, /*undefined_ok=*/0);
  }
  
  void
  mark_class_instantiated (tree t, int extern_p)
  {
--- 11008,11019 ----
    else
      error ("storage class %qD applied to template instantiation", storage);
  
    mark_decl_instantiated (result, extern_p);
    if (! extern_p)
!     instantiate_decl (result, /*defer_ok=*/1, 
! 		      /*expl_inst_class_mem_p=*/false);
  }
  
  void
  mark_class_instantiated (tree t, int extern_p)
  {
*************** bt_instantiate_type_proc (binding_entry 
*** 11045,11055 ****
  static void
  instantiate_class_member (tree decl, int extern_p)
  {
    mark_decl_instantiated (decl, extern_p);
    if (! extern_p)
!     instantiate_decl (decl, /*defer_ok=*/1, /* undefined_ok=*/1);
  }
  
  /* Perform an explicit instantiation of template class T.  STORAGE, if
     non-null, is the RID for extern, inline or static.  COMPLAIN is
     nonzero if this is called from the parser, zero if called recursively,
--- 11046,11057 ----
  static void
  instantiate_class_member (tree decl, int extern_p)
  {
    mark_decl_instantiated (decl, extern_p);
    if (! extern_p)
!     instantiate_decl (decl, /*defer_ok=*/1, 
! 		      /*expl_inst_class_mem_p=*/true);
  }
  
  /* Perform an explicit instantiation of template class T.  STORAGE, if
     non-null, is the RID for extern, inline or static.  COMPLAIN is
     nonzero if this is called from the parser, zero if called recursively,
*************** template_for_substitution (tree decl)
*** 11341,11358 ****
  
  /* Produce the definition of D, a _DECL generated from a template.  If
     DEFER_OK is nonzero, then we don't have to actually do the
     instantiation now; we just have to do it sometime.  Normally it is
     an error if this is an explicit instantiation but D is undefined.
!    If UNDEFINED_OK is nonzero, then instead we treat it as an implicit
!    instantiation.  UNDEFINED_OK is nonzero only if we are being used
!    to instantiate the members of an explicitly instantiated class
!    template.  */
! 
  
  tree
! instantiate_decl (tree d, int defer_ok, int undefined_ok)
  {
    tree tmpl = DECL_TI_TEMPLATE (d);
    tree gen_args;
    tree args;
    tree td;
--- 11343,11358 ----
  
  /* Produce the definition of D, a _DECL generated from a template.  If
     DEFER_OK is nonzero, then we don't have to actually do the
     instantiation now; we just have to do it sometime.  Normally it is
     an error if this is an explicit instantiation but D is undefined.
!    EXPL_INST_CLASS_MEM_P is true iff D is a member of an
!    explicitly instantiated class template.  */
  
  tree
! instantiate_decl (tree d, int defer_ok, 
! 		  bool expl_inst_class_mem_p)
  {
    tree tmpl = DECL_TI_TEMPLATE (d);
    tree gen_args;
    tree args;
    tree td;
*************** instantiate_decl (tree d, int defer_ok, 
*** 11437,11449 ****
        && !DECL_NOT_REALLY_EXTERN (d))
      mark_definable (d);
  
    input_location = DECL_SOURCE_LOCATION (d);
  
!   if (! pattern_defined && DECL_EXPLICIT_INSTANTIATION (d) && undefined_ok)
      {
        DECL_NOT_REALLY_EXTERN (d) = 0;
        SET_DECL_IMPLICIT_INSTANTIATION (d);
      }
  
    if (!defer_ok)
      {
--- 11437,11454 ----
        && !DECL_NOT_REALLY_EXTERN (d))
      mark_definable (d);
  
    input_location = DECL_SOURCE_LOCATION (d);
  
!   /* If D is a member of an explicitly instantiated class template,
!      and no definition is available, treat it like an implicit
!      instantiation.  */ 
!   if (!pattern_defined && expl_inst_class_mem_p 
!       && DECL_EXPLICIT_INSTANTIATION (d)) 
      {
        DECL_NOT_REALLY_EXTERN (d) = 0;
+       DECL_INTERFACE_KNOWN (d) = 0;
        SET_DECL_IMPLICIT_INSTANTIATION (d);
      }
  
    if (!defer_ok)
      {
*************** instantiate_pending_templates (int retri
*** 11676,11687 ****
  		  if (CLASSTYPE_TEMPLATE_INSTANTIATION (instantiation))
  		    for (fn = TYPE_METHODS (instantiation);
  			 fn;
  			 fn = TREE_CHAIN (fn))
  		      if (! DECL_ARTIFICIAL (fn))
! 			instantiate_decl (fn, /*defer_ok=*/0,
! 					  /*undefined_ok=*/0);
  		  if (COMPLETE_TYPE_P (instantiation))
  		    reconsider = 1;
  		}
  
  	      if (COMPLETE_TYPE_P (instantiation))
--- 11681,11693 ----
  		  if (CLASSTYPE_TEMPLATE_INSTANTIATION (instantiation))
  		    for (fn = TYPE_METHODS (instantiation);
  			 fn;
  			 fn = TREE_CHAIN (fn))
  		      if (! DECL_ARTIFICIAL (fn))
! 			instantiate_decl (fn, 
! 					  /*defer_ok=*/0,
! 					  /*expl_inst_class_mem_p=*/false);
  		  if (COMPLETE_TYPE_P (instantiation))
  		    reconsider = 1;
  		}
  
  	      if (COMPLETE_TYPE_P (instantiation))
*************** instantiate_pending_templates (int retri
*** 11697,11709 ****
  	  else
  	    {
  	      if (!DECL_TEMPLATE_SPECIALIZATION (instantiation)
  		  && !DECL_TEMPLATE_INSTANTIATED (instantiation))
  		{
! 		  instantiation = instantiate_decl (instantiation,
! 						    /*defer_ok=*/0,
! 						    /*undefined_ok=*/0);
  		  if (DECL_TEMPLATE_INSTANTIATED (instantiation))
  		    reconsider = 1;
  		}
  
  	      if (DECL_TEMPLATE_SPECIALIZATION (instantiation)
--- 11703,11716 ----
  	  else
  	    {
  	      if (!DECL_TEMPLATE_SPECIALIZATION (instantiation)
  		  && !DECL_TEMPLATE_INSTANTIATED (instantiation))
  		{
! 		  instantiation 
! 		    = instantiate_decl (instantiation,
! 					/*defer_ok=*/0,
! 					/*expl_inst_class_mem_p=*/false);
  		  if (DECL_TEMPLATE_INSTANTIATED (instantiation))
  		    reconsider = 1;
  		}
  
  	      if (DECL_TEMPLATE_SPECIALIZATION (instantiation)


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]