[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