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]

PATCH to improve checking of explicit instantiations



This patch improves error-checking for explicit instantiation
directives. 

-- 
Mark Mitchell 			mark@markmitchell.com
Mark Mitchell Consulting	http://www.markmitchell.com

1998-08-23  Mark Mitchell  <mark@markmitchell.com>

	* iomanip.h: Use __extension__ for `extern' explicit template
	instantiations.
	* sinst.cc: Don't explicitly instantiation string_char_traits<char>.
	* cinst.cc: Likewiwse, for complex<float>, complex<double>,
	complex<long double>.
	
Sun Aug 23 11:56:08 1998  Mark Mitchell  <mark@markmitchell.com>

	* extend.texi: Remove description of extension to explicit
	instantiation that is now endorsed by standard C++.

1998-08-23  Mark Mitchell  <mark@markmitchell.com>

	* decl2.c (grok_array_decl): Add comment.
	(mark_used): Don't instantiate an explicit instantiation.
	* friend.c (make_friend_class): Remove bogus comment.  Fix check
	for partial specializations.
	* pt.c (check_explicit_specialization): Don't
	SET_DECL_EXPLICIT_INSTANTIATION here.
	(mark_decl_instantiated): Or here.
	(do_decl_instantiation): Do it here, instead.  Add checks for
	duplicate explicit instantiations, etc.  Tidy.
	(do_type_instantiation): Likewise.
	(instantiate_decl): Improve comments.  Complain about explicit
	instantiations where no definition is available.

Index: gcc/testsuite/g++.old-deja/g++.pt/friend31.C
===================================================================
RCS file: friend31.C
diff -N friend31.C
*** /dev/null	Mon Dec 31 20:00:00 1979
--- friend31.C	Sun Aug 23 11:16:53 1998
***************
*** 0 ****
--- 1,12 ----
+ // Build don't link:
+ 
+ template <class T>
+ struct S1 {
+ };
+ 
+ template <>
+ struct S1<int> {};
+ 
+ struct S2 {
+   friend class S1<int>;
+ };
Index: gcc/testsuite/g++.old-deja/g++.pt/explicit70.C
===================================================================
RCS file: explicit70.C
diff -N explicit70.C
*** /dev/null	Mon Dec 31 20:00:00 1979
--- explicit70.C	Sun Aug 23 11:10:34 1998
***************
*** 0 ****
--- 1,43 ----
+ // Build don't link:
+ 
+ template <class T>
+ void f(T) {}
+ 
+ template <class T>
+ struct S {
+   static T t;
+ };
+ 
+ template <class T>
+ T S<T>::t;
+ 
+ template void f(int);
+ template void f(int); // ERROR - duplicate explicit instantiation 
+ template int S<int>::t;
+ template int S<int>::t; // ERROR - duplicate explicit instantiation 
+ template class S<double>;
+ template class S<double>; // ERROR - duplicate explicit instantiation 
+ 
+ extern template void f(double); // WARNING - extern not allowed
+ inline template class S<float>; // WARNING - inline not allowed
+ 
+ template <class T>
+ struct S<T*> {};
+ 
+ template class S<void*>; // OK - explicit instantiation of partial
+                          // specialization
+ 
+ template <>
+ struct S<long double> {};  // ERROR - explicit specialization
+ 
+ template class S<long double>; // ERROR - explicit instantiation after
+ 
+ template <>
+ void f(long double) {}        // ERROR - explicit specialization
+ 
+ template void f(long double); // ERROR - explicit instantiation after
+ 
+ template <class T>
+ void g(T);
+ 
+ template void g(int); // ERROR - no definition of g.
Index: gcc/testsuite/g++.old-deja/g++.pt/instantiate1.C
===================================================================
RCS file: /egcs/carton/cvsfiles/egcs/gcc/testsuite/g++.old-deja/g++.pt/instantiate1.C,v
retrieving revision 1.1
diff -c -p -r1.1 instantiate1.C
*** instantiate1.C	1998/01/20 00:57:38	1.1
--- instantiate1.C	1998/08/23 18:10:34
***************
*** 1,7 ****
  // Build don't link:
  
  template <class T>
! void f(T t);
  
  template void f<int>(int);
  template void f<>(long);
--- 1,7 ----
  // Build don't link:
  
  template <class T>
! void f(T t) {}
  
  template void f<int>(int);
  template void f<>(long);
Index: libio/iomanip.h
===================================================================
RCS file: /egcs/carton/cvsfiles/egcs/libio/iomanip.h,v
retrieving revision 1.3
diff -c -p -r1.3 iomanip.h
*** iomanip.h	1997/11/11 09:43:06	1.3
--- iomanip.h	1998/08/23 18:10:40
*************** public:
*** 68,75 ****
  };
  
  #ifdef __GNUG__
! extern template class smanip<int>;
! extern template class smanip<ios::fmtflags>;
  #endif
  
  template<class TP>
--- 68,75 ----
  };
  
  #ifdef __GNUG__
! __extension__ extern template class smanip<int>;
! __extension__ extern template class smanip<ios::fmtflags>;
  #endif
  
  template<class TP>
*************** inline ostream& operator<<(ostream& o, c
*** 81,90 ****
  { (*m._f)(o, m._a); return o;}
  
  #ifdef __GNUG__
! extern template istream& operator>>(istream&, const smanip<int>&);
! extern template istream& operator>>(istream&, const smanip<ios::fmtflags>&);
! extern template ostream& operator<<(ostream&, const smanip<int>&);
! extern template ostream& operator<<(ostream&, const smanip<ios::fmtflags>&);
  #endif
  
  //-----------------------------------------------------------------------------
--- 81,94 ----
  { (*m._f)(o, m._a); return o;}
  
  #ifdef __GNUG__
! __extension__ extern 
! template istream& operator>>(istream&, const smanip<int>&);
! __extension__ extern 
! template istream& operator>>(istream&, const smanip<ios::fmtflags>&);
! __extension__ extern 
! template ostream& operator<<(ostream&, const smanip<int>&);
! __extension__ extern 
! template ostream& operator<<(ostream&, const smanip<ios::fmtflags>&);
  #endif
  
  //-----------------------------------------------------------------------------
Index: libstdc++/sinst.cc
===================================================================
RCS file: /egcs/carton/cvsfiles/egcs/libstdc++/sinst.cc,v
retrieving revision 1.2
diff -c -p -r1.2 sinst.cc
*** sinst.cc	1998/01/25 16:45:00	1.2
--- sinst.cc	1998/08/23 18:48:09
*************** typedef char c;
*** 42,49 ****
  typedef wchar_t c;
  #endif
  
! #ifdef TRAITS
  template class string_char_traits <c>;
  #endif
  
  typedef basic_string <c> s;
--- 42,52 ----
  typedef wchar_t c;
  #endif
  
! #if defined(TRAITS) && !defined(C)
  template class string_char_traits <c>;
+ #else
+ /* string_char_traits<char> is already explicitly specialized in
+    std/straits.h.  */
  #endif
  
  typedef basic_string <c> s;
Index: libstdc++/cinst.cc
===================================================================
RCS file: /egcs/carton/cvsfiles/egcs/libstdc++/cinst.cc,v
retrieving revision 1.2
diff -c -p -r1.2 cinst.cc
*** cinst.cc	1998/03/04 12:40:30	1.2
--- cinst.cc	1998/08/23 18:51:31
*************** typedef complex<f> c;
*** 32,38 ****
  typedef const c& ccr;
  
  #ifdef MAIN
- template class complex<f>;
  template c& __doapl (c*, ccr);
  template c& __doaml (c*, ccr);
  template c& __doami (c*, ccr);
--- 32,37 ----
Index: gcc/extend.texi
===================================================================
RCS file: /egcs/carton/cvsfiles/egcs/gcc/extend.texi,v
retrieving revision 1.13
diff -c -p -r1.13 extend.texi
*** extend.texi	1998/07/30 10:38:11	1.13
--- extend.texi	1998/08/23 18:07:34
*************** instances required by your explicit inst
*** 3330,3343 ****
  other files) without having to specify them as well.
  
  g++ has extended the template instantiation syntax outlined in the
! Working Paper to allow forward declaration of explicit instantiations,
! explicit instantiation of members of template classes and instantiation
! of the compiler support data for a template class (i.e. the vtable)
! without instantiating any of its members:
  
  @example
  extern template int max (int, int);
- template void Foo<int>::f ();
  inline template class Foo<int>;
  @end example
  
--- 3330,3341 ----
  other files) without having to specify them as well.
  
  g++ has extended the template instantiation syntax outlined in the
! Working Paper to allow forward declaration of explicit instantiations
! and instantiation of the compiler support data for a template class
! (i.e. the vtable) without instantiating any of its members:
  
  @example
  extern template int max (int, int);
  inline template class Foo<int>;
  @end example
  
Index: gcc/cp/decl2.c
===================================================================
RCS file: /egcs/carton/cvsfiles/egcs/gcc/cp/decl2.c,v
retrieving revision 1.116
diff -c -p -r1.116 decl2.c
*** decl2.c	1998/08/20 16:44:01	1.116
--- decl2.c	1998/08/23 18:09:11
*************** grok_array_decl (array_expr, index_exp)
*** 1223,1229 ****
      return build_opfncall (ARRAY_REF, LOOKUP_NORMAL,
  			   array_expr, index_exp, NULL_TREE);
  
!   /* Otherwise, create an ARRAY_REF for a pointer or array type.  */
  
    if (TREE_CODE (type) == ARRAY_TYPE)
      p1 = array_expr;
--- 1223,1231 ----
      return build_opfncall (ARRAY_REF, LOOKUP_NORMAL,
  			   array_expr, index_exp, NULL_TREE);
  
!   /* Otherwise, create an ARRAY_REF for a pointer or array type.  It
!      is a little-known fact that, if `a' is an array and `i' is an
!      int, you can write `i[a]', which means the same thing as `a[i]'.  */
  
    if (TREE_CODE (type) == ARRAY_TYPE)
      p1 = array_expr;
*************** mark_used (decl)
*** 4900,4908 ****
       template, we now know that we will need to actually do the
       instantiation.  A TEMPLATE_DECL may also have DECL_TEMPLATE_INFO,
       if it's a partial instantiation, but there's no need to
!      instantiate such a thing.  */
    if (TREE_CODE (decl) != TEMPLATE_DECL
!       && DECL_LANG_SPECIFIC (decl) && DECL_TEMPLATE_INFO (decl))
      instantiate_decl (decl);
  }
  
--- 4902,4912 ----
       template, we now know that we will need to actually do the
       instantiation.  A TEMPLATE_DECL may also have DECL_TEMPLATE_INFO,
       if it's a partial instantiation, but there's no need to
!      instantiate such a thing.  We check that DECL is not an explicit
!      instantiation because that is not checked in instantiate_decl.  */
    if (TREE_CODE (decl) != TEMPLATE_DECL
!       && DECL_LANG_SPECIFIC (decl) && DECL_TEMPLATE_INFO (decl)
!       && !DECL_EXPLICIT_INSTANTIATION (decl))
      instantiate_decl (decl);
  }
  
Index: gcc/cp/friend.c
===================================================================
RCS file: /egcs/carton/cvsfiles/egcs/gcc/cp/friend.c,v
retrieving revision 1.24
diff -c -p -r1.24 friend.c
*** friend.c	1998/07/31 15:01:16	1.24
--- friend.c	1998/08/23 18:09:17
*************** make_friend_class (type, friend_type)
*** 262,276 ****
        return;
      }
  
!   if (CLASSTYPE_TEMPLATE_SPECIALIZATION (friend_type)) 
      {
        /* [temp.friend]
  	 
  	 Friend declarations shall not declare partial
! 	 specializations.  
! 
!          Note that CLASSTYPE_TEMPLATE_SPECIALIZATION is not set for
! 	 full specializations.  */ 
        cp_error ("partial specialization `%T' declared `friend'",
  		friend_type);
        return;
--- 262,274 ----
        return;
      }
  
!   if (CLASSTYPE_TEMPLATE_SPECIALIZATION (friend_type)
!       && uses_template_parms (friend_type))
      {
        /* [temp.friend]
  	 
  	 Friend declarations shall not declare partial
! 	 specializations.  */
        cp_error ("partial specialization `%T' declared `friend'",
  		friend_type);
        return;
Index: gcc/cp/pt.c
===================================================================
RCS file: /egcs/carton/cvsfiles/egcs/gcc/cp/pt.c,v
retrieving revision 1.181
diff -c -p -r1.181 pt.c
*** pt.c	1998/08/20 17:41:42	1.181
--- pt.c	1998/08/23 19:20:32
*************** check_explicit_specialization (declarato
*** 1299,1312 ****
  
  	  if (explicit_instantiation)
  	    {
  	      decl = instantiate_template (tmpl, innermost_args (targs));
- 	      if (!DECL_TEMPLATE_SPECIALIZATION (decl))
- 		/* There doesn't seem to be anything in the draft to
- 		   prevent a specialization from being explicitly
- 		   instantiated.  We're careful not to destroy the
- 		   information indicating that this is a
- 		   specialization here.  */
- 		SET_DECL_EXPLICIT_INSTANTIATION (decl);
  	      return decl;
  	    }
  	  
--- 1299,1307 ----
  
  	  if (explicit_instantiation)
  	    {
+ 	      /* We don't set DECL_EXPLICIT_INSTANTIATION here; that
+ 		 is done by do_decl_instantiation later.  */
  	      decl = instantiate_template (tmpl, innermost_args (targs));
  	      return decl;
  	    }
  	  
*************** type_unification_real (tparms, targs, pa
*** 6595,6606 ****
  	  arg = TREE_TYPE (arg);
  	}
  #endif
-       if (! flag_ansi && arg == TREE_TYPE (null_node))
- 	{
- 	  warning ("using type void* for NULL");
- 	  arg = ptr_type_node;
- 	}
- 
        if (!subr)
  	maybe_adjust_types_for_deduction (strict, &parm, &arg);
  
--- 6590,6595 ----
*************** unify (tparms, targs, parm, arg, strict,
*** 7109,7122 ****
      }
  }
  
  void
  mark_decl_instantiated (result, extern_p)
       tree result;
       int extern_p;
  {
-   if (DECL_TEMPLATE_INSTANTIATION (result))
-     SET_DECL_EXPLICIT_INSTANTIATION (result);
- 
    if (TREE_CODE (result) != FUNCTION_DECL)
      /* The TREE_PUBLIC flag for function declarations will have been
         set correctly by tsubst.  */
--- 7098,7112 ----
      }
  }
  
+ /* Called if RESULT is explicitly instantiated, or is a member of an
+    explicitly instantiated class, or if using -frepo and the
+    instantiation of RESULT has been assigned to this file.  */
+ 
  void
  mark_decl_instantiated (result, extern_p)
       tree result;
       int extern_p;
  {
    if (TREE_CODE (result) != FUNCTION_DECL)
      /* The TREE_PUBLIC flag for function declarations will have been
         set correctly by tsubst.  */
*************** do_decl_instantiation (declspecs, declar
*** 7458,7496 ****
        cp_error ("explicit instantiation of non-template `%#D'", decl);
        return;
      }
! 
!   /* If we've already seen this template instance, use it.  */
!   if (TREE_CODE (decl) == VAR_DECL)
      {
        result = lookup_field (DECL_CONTEXT (decl), DECL_NAME (decl), 0, 0);
        if (result && TREE_CODE (result) != VAR_DECL)
! 	result = NULL_TREE;
      }
    else if (TREE_CODE (decl) != FUNCTION_DECL)
      {
        cp_error ("explicit instantiation of `%#D'", decl);
        return;
      }
!   else if (DECL_TEMPLATE_SPECIALIZATION (decl))
!     /* [temp.spec]
  
!        No program shall both explicitly instantiate and explicitly
!        specialize a template.  */
!     {
!       cp_error ("explicit instantiation of `%#D' after", decl);
!       cp_error_at ("explicit specialization here", decl);
        return;
      }
!   else if (DECL_TEMPLATE_INSTANTIATION (decl))
!     result = decl;
  
!   if (! result)
      {
!       cp_error ("no matching template for `%D' found", decl);
        return;
      }
! 
!   if (! DECL_TEMPLATE_INFO (result))
      {
        cp_pedwarn ("explicit instantiation of non-template `%#D'", result);
        return;
--- 7448,7516 ----
        cp_error ("explicit instantiation of non-template `%#D'", decl);
        return;
      }
!   else if (TREE_CODE (decl) == VAR_DECL)
      {
+       /* There is an asymmetry here in the way VAR_DECLs and
+ 	 FUNCTION_DECLs are handled by grokdeclarator.  In the case of
+ 	 the latter, the DECL we get back will be marked as a
+ 	 template instantiation, and the appropriate
+ 	 DECL_TEMPLATE_INFO will be set up.  This does not happen for
+ 	 VAR_DECLs so we do the lookup here.  Probably, grokdeclarator
+ 	 should handle VAR_DECLs as it currently handles
+ 	 FUNCTION_DECLs.  */
        result = lookup_field (DECL_CONTEXT (decl), DECL_NAME (decl), 0, 0);
        if (result && TREE_CODE (result) != VAR_DECL)
! 	{
! 	  cp_error ("no matching template for `%D' found", result);
! 	  return;
! 	}
      }
    else if (TREE_CODE (decl) != FUNCTION_DECL)
      {
        cp_error ("explicit instantiation of `%#D'", decl);
        return;
      }
!   else
!     result = decl;
  
!   /* Check for various error cases.  Note that if the explicit
!      instantiation is legal the RESULT will currently be marked as an
!      *implicit* instantiation; DECL_EXPLICIT_INSTANTIATION is not set
!      until we get here.  */
! 
!   if (DECL_TEMPLATE_SPECIALIZATION (result))
!     {
!       /* [temp.spec]
! 
! 	 No program shall both explicitly instantiate and explicitly
! 	 specialize a template.  */
!       cp_error ("explicit instantiation of `%#D' after", result);
!       cp_error_at ("explicit specialization here", result);
        return;
      }
!   else if (DECL_EXPLICIT_INSTANTIATION (result))
!     {
!       /* [temp.spec]
! 
! 	 No program shall explicitly instantiate any template more
! 	 than once.  
  
! 	 We check DECL_INTERFACE_KNOWN so as not to complain when the
! 	 first instantiation was `extern' and the second is not, and
! 	 EXTERN_P for the opposite case.  */
!       if (DECL_INTERFACE_KNOWN (result) && !extern_p)
! 	cp_error ("duplicate explicit instantiation of `%#D'", result);
! 
!       /* If we've already instantiated the template, just return now.  */
!       if (DECL_INTERFACE_KNOWN (result))
! 	return;
!     }
!   else if (!DECL_IMPLICIT_INSTANTIATION (result))
      {
!       cp_error ("no matching template for `%D' found", result);
        return;
      }
!   else if (!DECL_TEMPLATE_INFO (result))
      {
        cp_pedwarn ("explicit instantiation of non-template `%#D'", result);
        return;
*************** do_decl_instantiation (declspecs, declar
*** 7502,7512 ****
    if (storage == NULL_TREE)
      ;
    else if (storage == ridpointers[(int) RID_EXTERN])
!     extern_p = 1;
    else
      cp_error ("storage class `%D' applied to template instantiation",
  	      storage);
  
    mark_decl_instantiated (result, extern_p);
    repo_template_instantiated (result, extern_p);
    if (! extern_p)
--- 7522,7537 ----
    if (storage == NULL_TREE)
      ;
    else if (storage == ridpointers[(int) RID_EXTERN])
!     {
!       if (pedantic)
! 	cp_pedwarn ("ANSI C++ forbids the use of `extern' on explicit instantiations");
!       extern_p = 1;
!     }
    else
      cp_error ("storage class `%D' applied to template instantiation",
  	      storage);
  
+   SET_DECL_EXPLICIT_INSTANTIATION (result);
    mark_decl_instantiated (result, extern_p);
    repo_template_instantiated (result, extern_p);
    if (! extern_p)
*************** do_type_instantiation (t, storage)
*** 7561,7598 ****
        return;
      }
  
!   if (storage == NULL_TREE)
!     /* OK */;
!   else if (storage == ridpointers[(int) RID_INLINE])
!     nomem_p = 1;
!   else if (storage == ridpointers[(int) RID_EXTERN])
!     extern_p = 1;
!   else if (storage == ridpointers[(int) RID_STATIC])
!     static_p = 1;
!   else
      {
!       cp_error ("storage class `%D' applied to template instantiation",
! 		storage);
!       extern_p = 0;
      }
  
!   /* We've already instantiated this.  */
!   if (CLASSTYPE_EXPLICIT_INSTANTIATION (t) && ! CLASSTYPE_INTERFACE_ONLY (t)
!       && extern_p)
!     return;
  
!   if (! CLASSTYPE_TEMPLATE_SPECIALIZATION (t))
      {
!       mark_class_instantiated (t, extern_p);
!       repo_template_instantiated (t, extern_p);
      }
  
    if (nomem_p)
      return;
  
    {
      tree tmp;
  
      if (! static_p)
        for (tmp = TYPE_METHODS (t); tmp; tmp = TREE_CHAIN (tmp))
  	if (TREE_CODE (tmp) == FUNCTION_DECL
--- 7586,7667 ----
        return;
      }
  
!   if (storage != NULL_TREE)
      {
!       if (pedantic)
! 	cp_pedwarn("ANSI C++ forbids the use of `%s' on explicit instantiations", 
! 		   IDENTIFIER_POINTER (storage));
! 
!       if (storage == ridpointers[(int) RID_INLINE])
! 	nomem_p = 1;
!       else if (storage == ridpointers[(int) RID_EXTERN])
! 	extern_p = 1;
!       else if (storage == ridpointers[(int) RID_STATIC])
! 	static_p = 1;
!       else
! 	{
! 	  cp_error ("storage class `%D' applied to template instantiation",
! 		    storage);
! 	  extern_p = 0;
! 	}
      }
  
!   if (CLASSTYPE_TEMPLATE_SPECIALIZATION (t))
!     {
!       /* [temp.spec]
  
! 	 No program shall both explicitly instantiate and explicitly
! 	 specialize a template.  */
!       cp_error ("explicit instantiation of `%#T' after", t);
!       cp_error_at ("explicit specialization here", t);
!       return;
!     }
!   else if (CLASSTYPE_EXPLICIT_INSTANTIATION (t))
      {
!       /* [temp.spec]
! 
! 	 No program shall explicitly instantiate any template more
! 	 than once.  
! 
!          If CLASSTYPE_INTERFACE_ONLY, then the first explicit
! 	 instantiation was `extern', and if EXTERN_P then the second
! 	 is.  Both cases are OK.  */
!       if (!CLASSTYPE_INTERFACE_ONLY (t) && !extern_p)
! 	cp_error ("duplicate explicit instantiation of `%#T'", t);
!       
!       /* If we've already instantiated the template, just return now.  */
!       if (!CLASSTYPE_INTERFACE_ONLY (t))
! 	return;
      }
  
+   mark_class_instantiated (t, extern_p);
+   repo_template_instantiated (t, extern_p);
+ 
    if (nomem_p)
      return;
  
    {
      tree tmp;
  
+     /* In contrast to implicit instantiation, where only the
+        declarations, and not the definitions, of members are
+        instantiated, we have here:
+ 
+          [temp.explicit]
+ 
+ 	 The explicit instantiation of a class template specialization
+ 	 implies the instantiation of all of its members not
+ 	 previously explicitly specialized in the translation unit
+ 	 containing the explicit instantiation.  
+ 
+        Of course, we can't instantiate member template classes, since
+        we don't have any arguments for them.  Note that the standard
+        is unclear on whether the instatiation of the members are
+        *explicit* instantiations or not.  We choose to be generous,
+        and not set DECL_EXPLICIT_INSTANTIATION.  Therefore, we allow
+        the explicit instantiation of a class where some of the members
+        have no definition in the current translation unit.  */
+ 
      if (! static_p)
        for (tmp = TYPE_METHODS (t); tmp; tmp = TREE_CHAIN (tmp))
  	if (TREE_CODE (tmp) == FUNCTION_DECL
*************** do_type_instantiation (t, storage)
*** 7613,7631 ****
  	    instantiate_decl (tmp);
  	}
  
-     /* In contrast to implicit instantiation, where only the
-        declarations, and not the definitions, of members are
-        instantiated, we have here:
- 
-          [temp.explicit]
- 
- 	 The explicit instantiation of a class template specialization
- 	 implies the instantiation of all of its members not
- 	 previously explicitly specialized in the translation unit
- 	 containing the explicit instantiation.  
- 
-        Of course, we can't instantiate member template classes, since
-        we don't have any arguments for them.  */
      for (tmp = CLASSTYPE_TAGS (t); tmp; tmp = TREE_CHAIN (tmp))
        if (IS_AGGR_TYPE (TREE_VALUE (tmp))
  	  && !uses_template_parms (CLASSTYPE_TI_ARGS (TREE_VALUE (tmp))))
--- 7682,7687 ----
*************** instantiate_decl (d)
*** 7783,7789 ****
  
    if ((TREE_CODE (d) == FUNCTION_DECL && DECL_INITIAL (d))
        || (TREE_CODE (d) == VAR_DECL && !DECL_IN_AGGR_P (d)))
!     /* D has already been instantiated.  */
      return d;
  
    /* If we already have a specialization of this declaration, then
--- 7839,7849 ----
  
    if ((TREE_CODE (d) == FUNCTION_DECL && DECL_INITIAL (d))
        || (TREE_CODE (d) == VAR_DECL && !DECL_IN_AGGR_P (d)))
!     /* D has already been instantiated.  It might seem reasonable to
!        check whether or not D is an explict instantiation, and, if so,
!        stop here.  But when an explicit instantiation is deferred
!        until the end of the compilation, DECL_EXPLICIT_INSTANTIATION
!        is set, even though we still need to do the instantiation.  */
      return d;
  
    /* If we already have a specialization of this declaration, then
*************** instantiate_decl (d)
*** 7910,7915 ****
--- 7970,7987 ----
           function.  */
        lineno = line;
        input_filename = file;
+ 
+       if (at_eof && !pattern_defined 
+ 	  && DECL_EXPLICIT_INSTANTIATION (d))
+ 	/* [temp.explicit]
+ 
+ 	   The definition of a non-exported function template, a
+ 	   non-exported member function template, or a non-exported
+ 	   member function or static data member of a class template
+ 	   shall be present in every translation unit in which it is
+ 	   explicitly instantiated.  */
+ 	cp_error ("explicit instantiation of `%D' but no definition available",
+ 		  d);
  
        add_pending_template (d);
        goto out;


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