[C++ PATCH] Template template parameter conformace issue (PR9737)

Kriang Lerdsuwanakij lerdsuwa@users.sourceforge.net
Fri Apr 18 14:52:00 GMT 2003


Hi

The following patch fixes an issue in template template parameter
implementation that does not conform to the C++ standard.  It's
about how template template parameter and argument matching when
the argument (the class template) is declared with default
arguments.  Previously, we allow code like:

	#include <vector>
	template <template <class> class TT> class C {};
	C<std::vector> c;

despite the `vector' class template declared with two parameters,
one with default argument std::allocator<T>.  This is now
consider non-standard compliance by core issue 150.  This behavior
is fixed by the patch below.

However, this new behavior makes template template parameter
feature rather useless when used together with standard C++ library
classes.  So an option `-fweak-template-templates' is also
introduced to weaken the parameter/argument matching rule to
allow the old behavior.

Patch tested on i686-pc-linux-gnu with no regressions.  OK to
commit to the main trunk?

--Kriang


2003-04-18  Kriang Lerdsuwanakij  <lerdsuwa@users.sourceforge.net>

	* c-common.c (flag_weak_template_templates): New variable.
	* c-common.h (flag_weak_template_templates): Add declaration.
	* c-opts.c (COMMAND_LINE_OPTIONS): Add
	flag_weak_template_templates.
	(c_common_decode_option): Set flag_weak_template_templates.
	* doc/invoke.texi: Document -fweak-template-templates.
	* doc/extend.texi: Likewise.

2003-04-18  Kriang Lerdsuwanakij  <lerdsuwa@users.sourceforge.net>

	* pt.c (coerce_template_template_parms): Check
	flag_weak_template_templates.
	(unify) <BOUND_TEMPLATE_TEMPLATE_PARM>: Likewise.
	* NEWS: Document changed behavior and -fweak-template-templates.

2003-04-16  Kriang Lerdsuwanakij  <lerdsuwa@users.sourceforge.net>

	* g++.old-deja/g++.pt/ttp9.C: Add -fweak-template-templates.
	* g++.old-deja/g++.pt/ttp19.C: Likewise.
	* g++.old-deja/g++.pt/ttp26.C: Likewise.
	* g++.old-deja/g++.pt/ttp35.C: Likewise.
	* g++.old-deja/g++.pt/ttp36.C: Likewise.
	* g++.old-deja/g++.pt/ttp37.C: Likewise.
	* g++.old-deja/g++.pt/ttp38.C: Likewise.
	* g++.old-deja/g++.pt/ttp39.C: Likewise.
	* g++.old-deja/g++.pt/ttp40.C: Likewise.
	* g++.old-deja/g++.pt/ttp51.C: Likewise.


diff -cprN gcc-main-save/gcc/c-common.c gcc-main-new/gcc/c-common.c
*** gcc-main-save/gcc/c-common.c	Wed Apr  2 21:02:34 2003
--- gcc-main-new/gcc/c-common.c	Wed Apr 16 18:46:14 2003
*************** int flag_permissive;
*** 593,598 ****
--- 593,604 ----
  
  int flag_enforce_eh_specs = 1;
  
+ /* Nonzero means template template argument containing default
+    argument is allowed to match template template parameter with
+    fewer parameters.  */
+ 
+ int flag_weak_template_templates = 0;
+ 
  /*  The version of the C++ ABI in use.  The following values are
      allowed:
  
diff -cprN gcc-main-save/gcc/c-common.h gcc-main-new/gcc/c-common.h
*** gcc-main-save/gcc/c-common.h	Sun Mar 30 00:55:42 2003
--- gcc-main-new/gcc/c-common.h	Wed Apr 16 18:46:08 2003
*************** extern int flag_permissive;
*** 763,768 ****
--- 763,774 ----
  
  extern int flag_enforce_eh_specs;
  
+ /* Nonzero means template template argument containing default
+    argument is allowed to match template template parameter with
+    fewer parameters.  */
+ 
+ extern int flag_weak_template_templates;
+ 
  /*  The version of the C++ ABI in use.  The following values are
      allowed:
  
diff -cprN gcc-main-save/gcc/c-opts.c gcc-main-new/gcc/c-opts.c
*** gcc-main-save/gcc/c-opts.c	Fri Mar 21 21:41:44 2003
--- gcc-main-new/gcc/c-opts.c	Wed Apr 16 19:28:36 2003
*************** static void finish_options PARAMS ((void
*** 302,307 ****
--- 302,308 ----
    OPT("fvtable-gc",		CL_CXX,   OPT_fvtable_gc)		     \
    OPT("fvtable-thunks",		CL_CXX,   OPT_fvtable_thunks)		     \
    OPT("fweak",			CL_CXX,   OPT_fweak)			     \
+   OPT("fweak-template-templates", CL_CXX,   OPT_fweak_template_templates)    \
    OPT("fxref",			CL_CXX,   OPT_fxref)			     \
    OPT("gen-decls",		CL_OBJC,  OPT_gen_decls)		     \
    OPT("idirafter",              CL_ALL | CL_ARG, OPT_idirafter)              \
*************** c_common_decode_option (argc, argv)
*** 1356,1361 ****
--- 1357,1366 ----
        flag_weak = on;
        break;
  
+     case OPT_fweak_template_templates:
+       flag_weak_template_templates = on;
+       break;
+ 
      case OPT_gen_decls:
        flag_gen_declaration = 1;
        break;
diff -cprN gcc-main-save/gcc/cp/NEWS gcc-main-new/gcc/cp/NEWS
*** gcc-main-save/gcc/cp/NEWS	Mon Jan 27 16:59:56 2003
--- gcc-main-new/gcc/cp/NEWS	Fri Apr 18 21:17:38 2003
***************
*** 70,75 ****
--- 70,92 ----
  
      X x __attribute__((...)) (1);
  
+ * Templates with default arguments are no longer allowed as arguments
+   to template template parameters with fewer declared parameters.
+   For example:
+ 
+     #include <vector>
+     template <template <class> class TT> class C {};
+     C<std::vector> c;
+ 
+   is now invalid.  The following standard conformance syntax for `C'
+   has to be used:
+ 
+     template <template <class T, class alloc = std::allocator<T> >
+ 	      class TT> class C {};
+ 
+   The option `-fweak-template-templates' is provided to retain the
+   old behavior.
+ 
  *** Changes in GCC 3.3:
  
  * The "new X = 3" extension has been removed; you must now use "new X(3)".
diff -cprN gcc-main-save/gcc/cp/pt.c gcc-main-new/gcc/cp/pt.c
*** gcc-main-save/gcc/cp/pt.c	Wed Apr 16 21:40:25 2003
--- gcc-main-new/gcc/cp/pt.c	Wed Apr 16 19:38:08 2003
*************** convert_nontype_argument (type, expr)
*** 3406,3422 ****
     vectors of TREE_LIST nodes containing TYPE_DECL, TEMPLATE_DECL 
     or PARM_DECL.
     
!    ARG_PARMS may contain more parameters than PARM_PARMS.  If this is 
!    the case, then extra parameters must have default arguments.
  
     Consider the example:
       template <class T, class Allocator = allocator> class vector;
       template<template <class U> class TT> class C;
  
!    C<vector> is a valid instantiation.  PARM_PARMS for the above code 
!    contains a TYPE_DECL (for U),  ARG_PARMS contains two TYPE_DECLs (for 
!    T and Allocator) and OUTER_ARGS contains the argument that is used to 
!    substitute the TT parameter.  */
  
  static int
  coerce_template_template_parms (parm_parms, arg_parms, complain, 
--- 3406,3424 ----
     vectors of TREE_LIST nodes containing TYPE_DECL, TEMPLATE_DECL 
     or PARM_DECL.
     
!    If FLAG_WEAK_TEMPLATE_TEMPLATES is nonzero, matching rule is
!    weaken so that ARG_PARMS may contain more parameters than
!    PARM_PARMS.  If this is the case, then extra parameters must have
!    default arguments.
  
     Consider the example:
       template <class T, class Allocator = allocator> class vector;
       template<template <class U> class TT> class C;
  
!    C<vector> is treated as a valid instantiation.  PARM_PARMS for the
!    above code contains a TYPE_DECL (for U),  ARG_PARMS contains two
!    TYPE_DECLs (for T and Allocator) and OUTER_ARGS contains the
!    argument that is used to substitute the TT parameter.  */
  
  static int
  coerce_template_template_parms (parm_parms, arg_parms, complain, 
*************** coerce_template_template_parms (parm_par
*** 3434,3443 ****
    nparms = TREE_VEC_LENGTH (parm_parms);
    nargs = TREE_VEC_LENGTH (arg_parms);
  
!   /* The rule here is opposite of coerce_template_parms.  */
!   if (nargs < nparms
!       || (nargs > nparms
! 	  && TREE_PURPOSE (TREE_VEC_ELT (arg_parms, nparms)) == NULL_TREE))
      return 0;
  
    for (i = 0; i < nparms; ++i)
--- 3436,3450 ----
    nparms = TREE_VEC_LENGTH (parm_parms);
    nargs = TREE_VEC_LENGTH (arg_parms);
  
!   if (flag_weak_template_templates)
!     {
!       /* The rule here is opposite of coerce_template_parms.  */
!       if (nargs < nparms
! 	  || (nargs > nparms
! 	      && TREE_PURPOSE (TREE_VEC_ELT (arg_parms, nparms)) == NULL_TREE))
! 	return 0;
!     }
!   else if (nargs != nparms)
      return 0;
  
    for (i = 0; i < nparms; ++i)
*************** unify (tparms, targs, parm, arg, strict)
*** 9512,9523 ****
  	      = DECL_INNERMOST_TEMPLATE_PARMS (TYPE_TI_TEMPLATE (arg));
  	    int i;
  
  	    /* The parameter and argument roles have to be switched here 
  	       in order to handle default arguments properly.  For example, 
! 	       template<template <class> class TT> void f(TT<int>) 
! 	       should be able to accept vector<int> which comes from 
! 	       template <class T, class Allocator = allocator> 
! 	       class vector.  */
  
  	    if (coerce_template_parms (argtmplvec, parmvec, parmtmpl, 0, 1)
  	        == error_mark_node)
--- 9519,9539 ----
  	      = DECL_INNERMOST_TEMPLATE_PARMS (TYPE_TI_TEMPLATE (arg));
  	    int i;
  
+ 	    /* If FLAG_WEAK_TEMPLATE_TEMPLATES is zero, the number of
+ 	       parameters for parameter and argument must agree.  */
+ 	    if (!flag_weak_template_templates
+ 		&& TREE_VEC_LENGTH (parmvec) != TREE_VEC_LENGTH (argtmplvec))
+ 	      return 1;
+ 	    
  	    /* The parameter and argument roles have to be switched here 
  	       in order to handle default arguments properly.  For example, 
! 
! 		 template<template <class> class TT> void f(TT<int>);
! 
! 	       may accept vector<int> which comes from
! 
! 		 template <class T, class Allocator = allocator>
! 	 	 class vector;  */
  
  	    if (coerce_template_parms (argtmplvec, parmvec, parmtmpl, 0, 1)
  	        == error_mark_node)
*************** unify (tparms, targs, parm, arg, strict)
*** 9525,9531 ****
  	  
  	    /* Deduce arguments T, i from TT<T> or TT<i>.  
  	       We check each element of PARMVEC and ARGVEC individually
! 	       rather than the whole TREE_VEC since they can have
  	       different number of elements.  */
  
  	    for (i = 0; i < TREE_VEC_LENGTH (parmvec); ++i)
--- 9541,9547 ----
  	  
  	    /* Deduce arguments T, i from TT<T> or TT<i>.  
  	       We check each element of PARMVEC and ARGVEC individually
! 	       rather than the whole TREE_VEC since they may have
  	       different number of elements.  */
  
  	    for (i = 0; i < TREE_VEC_LENGTH (parmvec); ++i)
diff -cprN gcc-main-save/gcc/doc/extend.texi gcc-main-new/gcc/doc/extend.texi
*** gcc-main-save/gcc/doc/extend.texi	Sun Mar 30 00:55:57 2003
--- gcc-main-new/gcc/doc/extend.texi	Fri Apr 18 21:16:55 2003
*************** Predefined Macros,cpp.info,The C Preproc
*** 6934,6939 ****
--- 6934,6941 ----
                          each needed template instantiation is emitted.
  * Bound member functions:: You can extract a function pointer to the
                          method denoted by a @samp{->*} or @samp{.*} expression.
+ * Template template parameters:: Alternative rule for template template
+                         parameter matching.
  * C++ Attributes::      Variable, function, and type attributes for C++ only.
  * Java Exceptions::     Tweaking exception handling to work with Java.
  * Deprecated Features:: Things might disappear from g++.
*************** fptr p1 = (fptr)(&A::foo);
*** 7496,7501 ****
--- 7498,7537 ----
  @opindex Wno-pmf-conversions
  You must specify @option{-Wno-pmf-conversions} to use this extension.
  
+ 
+ @node Template template parameters
+ @section Template Template Parameters
+ 
+ The standard C++ requires that every parameter of a template template
+ parameter must by specified in the template signature.  For example,
+ if you want to pass the template @code{std::vector}, declared
+ as @code{template<class T, class A = std::allocator<T> > class vector},
+ as a template argument to a class you created, this class has to be
+ declared as:
+ 
+ @example
+ #include <vector>
+ template <template <class T, class A = allocator<T> > class TT> class C {};
+ C<std::vector> c;
+ @end example
+ 
+ This was not sufficiently clear from the standard until the core language
+ issue 150 was resolved.  Therefore in previous versions of GCC, it also
+ accepts the following declaration as valid:
+ 
+ @example
+ #include <vector>
+ template <template <class> class TT> class C {};
+ C<std::vector> c;
+ @end example
+ 
+ because the second template parameter of @code{std::vector} has a
+ default argument.  This is now rejected by GCC by default.  However, 
+ some might still find the old behavior more useful.  And the option 
+ @option{-fweak-template-templates} is provided to restore this behavior
+ as a GNU extension.
+ 
+ 
  @node C++ Attributes
  @section C++-Specific Variable, Function, and Type Attributes
  
diff -cprN gcc-main-save/gcc/doc/invoke.texi gcc-main-new/gcc/doc/invoke.texi
*** gcc-main-save/gcc/doc/invoke.texi	Wed Apr  2 21:02:45 2003
--- gcc-main-new/gcc/doc/invoke.texi	Wed Apr 16 21:13:35 2003
*************** in the following sections.
*** 177,183 ****
  @gccoptlist{
  -fabi-version=@var{n} -fno-access-control  -fcheck-new @gol
  -fconserve-space -fno-const-strings  -fdollars-in-identifiers @gol
! -fno-elide-constructors @gol
  -fno-enforce-eh-specs  -fexternal-templates @gol
  -falt-external-templates @gol
  -ffor-scope  -fno-for-scope  -fno-gnu-keywords @gol
--- 177,183 ----
  @gccoptlist{
  -fabi-version=@var{n} -fno-access-control  -fcheck-new @gol
  -fconserve-space -fno-const-strings  -fdollars-in-identifiers @gol
! -fno-default-inline -fno-elide-constructors @gol
  -fno-enforce-eh-specs  -fexternal-templates @gol
  -falt-external-templates @gol
  -ffor-scope  -fno-for-scope  -fno-gnu-keywords @gol
*************** in the following sections.
*** 187,194 ****
  -fno-nonansi-builtins  -fno-operator-names @gol
  -fno-optional-diags  -fpermissive @gol
  -frepo  -fno-rtti  -fstats  -ftemplate-depth-@var{n} @gol
! -fuse-cxa-atexit  -fvtable-gc  -fno-weak  -nostdinc++ @gol
! -fno-default-inline -Wabi -Wctor-dtor-privacy @gol
  -Wnon-virtual-dtor  -Wreorder @gol
  -Weffc++  -Wno-deprecated @gol
  -Wno-non-template-friend  -Wold-style-cast @gol
--- 187,195 ----
  -fno-nonansi-builtins  -fno-operator-names @gol
  -fno-optional-diags  -fpermissive @gol
  -frepo  -fno-rtti  -fstats  -ftemplate-depth-@var{n} @gol
! -fuse-cxa-atexit  -fvtable-gc  -fno-weak @gol
! -fweak-template-templates -nostdinc++ @gol
! -Wabi -Wctor-dtor-privacy @gol
  -Wnon-virtual-dtor  -Wreorder @gol
  -Weffc++  -Wno-deprecated @gol
  -Wno-non-template-friend  -Wold-style-cast @gol
*************** option exists only for testing, and shou
*** 1516,1521 ****
--- 1517,1529 ----
  it will result in inferior code and has no benefits.  This option may
  be removed in a future release of G++.
  
+ @item -fweak-template-templates
+ @opindex fweak-template-templates
+ Weaken template template argument matching so that template with more
+ parameters than that required by template template parameter is allowed
+ provided that the extra parameters contain default arguments.
+ This is a GNU extension to the core language issue 150.
+ 
  @item -nostdinc++
  @opindex nostdinc++
  Do not search for header files in the standard directories specific to
diff -cprN gcc-main-save/gcc/testsuite/g++.old-deja/g++.pt/ttp19.C gcc-main-new/gcc/testsuite/g++.old-deja/g++.pt/ttp19.C
*** gcc-main-save/gcc/testsuite/g++.old-deja/g++.pt/ttp19.C	Thu Dec 17 05:01:31 1998
--- gcc-main-new/gcc/testsuite/g++.old-deja/g++.pt/ttp19.C	Wed Apr 16 20:41:57 2003
***************
*** 1,3 ****
--- 1,5 ----
+ // Special g++ Options: -fweak-template-templates
+ 
  #include <vector>
  
  template<template<class> class D,class E> class C
diff -cprN gcc-main-save/gcc/testsuite/g++.old-deja/g++.pt/ttp26.C gcc-main-new/gcc/testsuite/g++.old-deja/g++.pt/ttp26.C
*** gcc-main-save/gcc/testsuite/g++.old-deja/g++.pt/ttp26.C	Thu Dec 17 05:01:39 1998
--- gcc-main-new/gcc/testsuite/g++.old-deja/g++.pt/ttp26.C	Wed Apr 16 20:44:57 2003
***************
*** 1,3 ****
--- 1,5 ----
+ // Special g++ Options: -fweak-template-templates
+ 
  template<class T, class U = int> class D
  {
  	public:
diff -cprN gcc-main-save/gcc/testsuite/g++.old-deja/g++.pt/ttp35.C gcc-main-new/gcc/testsuite/g++.old-deja/g++.pt/ttp35.C
*** gcc-main-save/gcc/testsuite/g++.old-deja/g++.pt/ttp35.C	Thu Dec 17 05:01:50 1998
--- gcc-main-new/gcc/testsuite/g++.old-deja/g++.pt/ttp35.C	Wed Apr 16 20:44:59 2003
***************
*** 1,3 ****
--- 1,5 ----
+ // Special g++ Options: -fweak-template-templates
+ 
  template<int T, class U = int> class D
  {
  	public:
diff -cprN gcc-main-save/gcc/testsuite/g++.old-deja/g++.pt/ttp36.C gcc-main-new/gcc/testsuite/g++.old-deja/g++.pt/ttp36.C
*** gcc-main-save/gcc/testsuite/g++.old-deja/g++.pt/ttp36.C	Thu Dec 17 05:01:51 1998
--- gcc-main-new/gcc/testsuite/g++.old-deja/g++.pt/ttp36.C	Wed Apr 16 20:44:57 2003
***************
*** 1,3 ****
--- 1,5 ----
+ // Special g++ Options: -fweak-template-templates
+ 
  template<int T, class U = int> class D
  {
  	public:
diff -cprN gcc-main-save/gcc/testsuite/g++.old-deja/g++.pt/ttp37.C gcc-main-new/gcc/testsuite/g++.old-deja/g++.pt/ttp37.C
*** gcc-main-save/gcc/testsuite/g++.old-deja/g++.pt/ttp37.C	Thu Dec 17 05:01:52 1998
--- gcc-main-new/gcc/testsuite/g++.old-deja/g++.pt/ttp37.C	Wed Apr 16 20:44:58 2003
***************
*** 1,3 ****
--- 1,5 ----
+ // Special g++ Options: -fweak-template-templates
+ 
  template<int T, class U = int> class D
  {
  	public:
diff -cprN gcc-main-save/gcc/testsuite/g++.old-deja/g++.pt/ttp38.C gcc-main-new/gcc/testsuite/g++.old-deja/g++.pt/ttp38.C
*** gcc-main-save/gcc/testsuite/g++.old-deja/g++.pt/ttp38.C	Thu Dec 17 05:01:53 1998
--- gcc-main-new/gcc/testsuite/g++.old-deja/g++.pt/ttp38.C	Wed Apr 16 20:44:54 2003
***************
*** 1,3 ****
--- 1,5 ----
+ // Special g++ Options: -fweak-template-templates
+ 
  template<class T, class U = int> class D
  {
  	public:
diff -cprN gcc-main-save/gcc/testsuite/g++.old-deja/g++.pt/ttp39.C gcc-main-new/gcc/testsuite/g++.old-deja/g++.pt/ttp39.C
*** gcc-main-save/gcc/testsuite/g++.old-deja/g++.pt/ttp39.C	Thu Dec 17 05:01:54 1998
--- gcc-main-new/gcc/testsuite/g++.old-deja/g++.pt/ttp39.C	Wed Apr 16 20:44:58 2003
***************
*** 1,3 ****
--- 1,5 ----
+ // Special g++ Options: -fweak-template-templates
+ 
  template<class T, class U = T> class D
  {
  	public:
diff -cprN gcc-main-save/gcc/testsuite/g++.old-deja/g++.pt/ttp40.C gcc-main-new/gcc/testsuite/g++.old-deja/g++.pt/ttp40.C
*** gcc-main-save/gcc/testsuite/g++.old-deja/g++.pt/ttp40.C	Thu Dec 17 05:01:56 1998
--- gcc-main-new/gcc/testsuite/g++.old-deja/g++.pt/ttp40.C	Wed Apr 16 20:45:28 2003
***************
*** 1,3 ****
--- 1,5 ----
+ // Special g++ Options: -fweak-template-templates
+ 
  #include <vector>
  
  template<class E,template<class> class DD = std::vector> class C
diff -cprN gcc-main-save/gcc/testsuite/g++.old-deja/g++.pt/ttp51.C gcc-main-new/gcc/testsuite/g++.old-deja/g++.pt/ttp51.C
*** gcc-main-save/gcc/testsuite/g++.old-deja/g++.pt/ttp51.C	Thu Dec 17 05:02:09 1998
--- gcc-main-new/gcc/testsuite/g++.old-deja/g++.pt/ttp51.C	Wed Apr 16 20:45:29 2003
***************
*** 1,3 ****
--- 1,5 ----
+ // Special g++ Options: -fweak-template-templates
+ 
  template<class E, int i, class F, class G=int, int j=i, class H=E> class D
  {
  };
diff -cprN gcc-main-save/gcc/testsuite/g++.old-deja/g++.pt/ttp9.C gcc-main-new/gcc/testsuite/g++.old-deja/g++.pt/ttp9.C
*** gcc-main-save/gcc/testsuite/g++.old-deja/g++.pt/ttp9.C	Thu Dec 17 05:02:15 1998
--- gcc-main-new/gcc/testsuite/g++.old-deja/g++.pt/ttp9.C	Wed Apr 16 20:38:53 2003
*************** template<class E,class F=int> class D
*** 2,8 ****
  {
  };
  
! template<template<class> class D,class E> class C
  {
  	D<E>	d;
  };
--- 2,8 ----
  {
  };
  
! template<template<class,class=int> class D,class E> class C
  {
  	D<E>	d;
  };



More information about the Gcc-patches mailing list