aboutsummaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
authorMark Mitchell <mark@codesourcery.com>2006-02-07 11:11:30 +0000
committerMark Mitchell <mmitchel@gcc.gnu.org>2006-02-07 11:11:30 +0000
commite7e9396544525de5ad6e09527b4b3d29ab1e6429 (patch)
treeb84246452027309b78b972cb94e51976cb9d0314 /gcc
parent369681318051ea25a6933cf21f32e98919b1c680 (diff)
downloadgcc-e7e9396544525de5ad6e09527b4b3d29ab1e6429.zip
gcc-e7e9396544525de5ad6e09527b4b3d29ab1e6429.tar.gz
gcc-e7e9396544525de5ad6e09527b4b3d29ab1e6429.tar.bz2
re PR c++/9737 ([DR150] Partial template specialisation selection failure involving template parameter defaults)
PR c++/9737 * pt.c (coerce_template_template_parms): Do not templates with excess default arguments to match template template parameters with fewer parameters. (coerce_template_parms): Add use_default_args parameter; use default arguments only when true. (lookup_template_class): Adjust call to coerce_template_parms. (fn_type_unification): Likewise. (unify): Likewise. (get_bindings): Likewise. (dependent_type_p): Add assertions. PR c++/9737 * g++.dg/template/ttp15.C: New test. * g++.dg/template/ttp16.C: Likewise. * g++.dg/template/ttp17.C: Likewise. * g++.old-deja/g++.pt/ttp36.C: Remove. * g++.old-deja/g++.pt/ttp19.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/ttp9.C: Likewise. * g++.old-deja/g++.pt/ttp40.C: Likewise. * g++.old-deja/g++.pt/ttp51.C: Likewise. * g++.old-deja/g++.pt/ttp26.C: Likewise. * g++.old-deja/g++.pt/ttp36.C: Likewise. * testsuite/testsuite_tr1.h (test_property): New function. * testsuite/tr1/4_metaprogramming/type_properties/extent/extent.cc (test01) From-SVN: r110693
Diffstat (limited to 'gcc')
-rw-r--r--gcc/cp/ChangeLog14
-rw-r--r--gcc/cp/pt.c111
-rw-r--r--gcc/testsuite/ChangeLog17
-rw-r--r--gcc/testsuite/g++.dg/template/ttp15.C21
-rw-r--r--gcc/testsuite/g++.dg/template/ttp16.C7
-rw-r--r--gcc/testsuite/g++.dg/template/ttp17.C7
-rw-r--r--gcc/testsuite/g++.old-deja/g++.pt/ttp19.C25
-rw-r--r--gcc/testsuite/g++.old-deja/g++.pt/ttp26.C34
-rw-r--r--gcc/testsuite/g++.old-deja/g++.pt/ttp35.C36
-rw-r--r--gcc/testsuite/g++.old-deja/g++.pt/ttp36.C30
-rw-r--r--gcc/testsuite/g++.old-deja/g++.pt/ttp37.C30
-rw-r--r--gcc/testsuite/g++.old-deja/g++.pt/ttp38.C30
-rw-r--r--gcc/testsuite/g++.old-deja/g++.pt/ttp39.C30
-rw-r--r--gcc/testsuite/g++.old-deja/g++.pt/ttp40.C21
-rw-r--r--gcc/testsuite/g++.old-deja/g++.pt/ttp51.C14
-rw-r--r--gcc/testsuite/g++.old-deja/g++.pt/ttp9.C14
16 files changed, 139 insertions, 302 deletions
diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog
index 18da128..cdfeaf3 100644
--- a/gcc/cp/ChangeLog
+++ b/gcc/cp/ChangeLog
@@ -1,3 +1,17 @@
+2006-02-07 Mark Mitchell <mark@codesourcery.com>
+
+ PR c++/9737
+ * pt.c (coerce_template_template_parms): Do not templates with
+ excess default arguments to match template template parameters
+ with fewer parameters.
+ (coerce_template_parms): Add use_default_args parameter; use
+ default arguments only when true.
+ (lookup_template_class): Adjust call to coerce_template_parms.
+ (fn_type_unification): Likewise.
+ (unify): Likewise.
+ (get_bindings): Likewise.
+ (dependent_type_p): Add assertions.
+
2006-02-06 Roger Sayle <roger@eyesopen.com>
* decl.c (grokdeclarator): Don't bother checking for CHAR_TYPE.
diff --git a/gcc/cp/pt.c b/gcc/cp/pt.c
index aac7f3c..b1da4af 100644
--- a/gcc/cp/pt.c
+++ b/gcc/cp/pt.c
@@ -102,7 +102,8 @@ static tree classtype_mangled_name (tree);
static char* mangle_class_name_for_template (const char *, tree, tree);
static tree tsubst_initializer_list (tree, tree);
static tree get_class_bindings (tree, tree, tree);
-static tree coerce_template_parms (tree, tree, tree, tsubst_flags_t, int);
+static tree coerce_template_parms (tree, tree, tree, tsubst_flags_t,
+ bool, bool);
static void tsubst_enum (tree, tree, tree);
static tree add_to_template_args (tree, tree);
static tree add_outermost_template_args (tree, tree);
@@ -3718,17 +3719,12 @@ convert_nontype_argument (tree type, tree expr)
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;
+ template <class T> class A;
+ template<template <class U> class TT> class B;
- 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. */
+ For B<A>, PARM_PARMS are the parameters to TT, while ARG_PARMS are
+ the parameters to A, and OUTER_ARGS contains A. */
static int
coerce_template_template_parms (tree parm_parms,
@@ -3746,10 +3742,7 @@ coerce_template_template_parms (tree parm_parms,
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))
+ if (nargs != nparms)
return 0;
for (i = 0; i < nparms; ++i)
@@ -3988,17 +3981,20 @@ convert_template_argument (tree parm,
arguments. If any error occurs, return error_mark_node. Error and
warning messages are issued under control of COMPLAIN.
- If REQUIRE_ALL_ARGUMENTS is nonzero, all arguments must be
- provided in ARGLIST, or else trailing parameters must have default
- values. If REQUIRE_ALL_ARGUMENTS is zero, we will attempt argument
- deduction for any unspecified trailing arguments. */
+ If REQUIRE_ALL_ARGS is false, argument deduction will be performed
+ for arugments not specified in ARGS. Otherwise, if
+ USE_DEFAULT_ARGS is true, default arguments will be used to fill in
+ unspecified arguments. If REQUIRE_ALL_ARGS is true, but
+ USE_DEFAULT_ARGS is false, then all arguments must be specified in
+ ARGS. */
static tree
coerce_template_parms (tree parms,
tree args,
tree in_decl,
tsubst_flags_t complain,
- int require_all_arguments)
+ bool require_all_args,
+ bool use_default_args)
{
int nparms, nargs, i, lost = 0;
tree inner_args;
@@ -4011,8 +4007,9 @@ coerce_template_parms (tree parms,
if (nargs > nparms
|| (nargs < nparms
- && require_all_arguments
- && TREE_PURPOSE (TREE_VEC_ELT (parms, nargs)) == NULL_TREE))
+ && require_all_args
+ && (!use_default_args
+ || !TREE_PURPOSE (TREE_VEC_ELT (parms, nargs)))))
{
if (complain & tf_error)
{
@@ -4039,7 +4036,7 @@ coerce_template_parms (tree parms,
/* Calculate the Ith argument. */
if (i < nargs)
arg = TREE_VEC_ELT (inner_args, i);
- else if (require_all_arguments)
+ else if (require_all_args)
/* There must be a default arg in this case. */
arg = tsubst_template_arg (TREE_PURPOSE (parm), new_args,
complain, in_decl);
@@ -4444,7 +4441,9 @@ lookup_template_class (tree d1,
arglist = add_to_template_args (current_template_args (), arglist);
arglist2 = coerce_template_parms (parmlist, arglist, template,
- complain, /*require_all_args=*/1);
+ complain,
+ /*require_all_args=*/true,
+ /*use_default_args=*/true);
if (arglist2 == error_mark_node
|| (!uses_template_parms (arglist2)
&& check_instantiated_args (template, arglist2, complain)))
@@ -4513,7 +4512,9 @@ lookup_template_class (tree d1,
{
tree a = coerce_template_parms (TREE_VALUE (t),
arglist, template,
- complain, /*require_all_args=*/1);
+ complain,
+ /*require_all_args=*/true,
+ /*use_default_args=*/true);
/* Don't process further if one of the levels fails. */
if (a == error_mark_node)
@@ -4542,7 +4543,9 @@ lookup_template_class (tree d1,
= coerce_template_parms (INNERMOST_TEMPLATE_PARMS (parmlist),
INNERMOST_TEMPLATE_ARGS (arglist),
template,
- complain, /*require_all_args=*/1);
+ complain,
+ /*require_all_args=*/true,
+ /*use_default_args=*/true);
if (arglist == error_mark_node)
/* We were unable to bind the arguments. */
@@ -9237,7 +9240,8 @@ fn_type_unification (tree fn,
converted_args
= (coerce_template_parms (DECL_INNERMOST_TEMPLATE_PARMS (fn),
explicit_targs, NULL_TREE, tf_none,
- /*require_all_arguments=*/0));
+ /*require_all_args=*/false,
+ /*use_default_args=*/false));
if (converted_args == error_mark_node)
return 1;
@@ -10003,21 +10007,44 @@ unify (tree tparms, tree targs, tree parm, tree arg, int strict)
return 1;
{
- tree parmtmpl = TYPE_TI_TEMPLATE (parm);
tree parmvec = TYPE_TI_ARGS (parm);
tree argvec = INNERMOST_TEMPLATE_ARGS (TYPE_TI_ARGS (arg));
tree argtmplvec
= 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. */
+ /* The resolution to DR150 makes clear that default
+ arguments for an N-argument may not be used to bind T
+ to a template template parameter with fewer than N
+ parameters. It is not safe to permit the binding of
+ default arguments as an extension, as that may change
+ the meaning of a conforming program. Consider:
+
+ struct Dense { static const unsigned int dim = 1; };
+
+ template <template <typename> class View,
+ typename Block>
+ void operator+(float, View<Block> const&);
+
+ template <typename Block,
+ unsigned int Dim = Block::dim>
+ struct Lvalue_proxy { operator float() const; };
+
+ void
+ test_1d (void) {
+ Lvalue_proxy<Dense> p;
+ float b;
+ b + p;
+ }
- if (coerce_template_parms (argtmplvec, parmvec, parmtmpl, 0, 1)
+ Here, if Lvalue_proxy is permitted to bind to View, then
+ the global operator+ will be used; if they are not, the
+ Lvalue_proxy will be converted to float. */
+ if (coerce_template_parms (argtmplvec, parmvec,
+ TYPE_TI_TEMPLATE (parm),
+ tf_none,
+ /*require_all_args=*/true,
+ /*use_default_args=*/false)
== error_mark_node)
return 1;
@@ -10733,9 +10760,11 @@ get_bindings (tree fn, tree decl, tree explicit_args, bool check_rettype)
return NULL_TREE;
converted_args
- = (coerce_template_parms (DECL_INNERMOST_TEMPLATE_PARMS (tmpl),
- explicit_args, NULL_TREE,
- tf_none, /*require_all_arguments=*/0));
+ = coerce_template_parms (DECL_INNERMOST_TEMPLATE_PARMS (tmpl),
+ explicit_args, NULL_TREE,
+ tf_none,
+ /*require_all_args=*/false,
+ /*use_default_args=*/false);
if (converted_args == error_mark_node)
return NULL_TREE;
@@ -12215,7 +12244,13 @@ dependent_type_p (tree type)
/* If there are no template parameters in scope, then there can't be
any dependent types. */
if (!processing_template_decl)
- return false;
+ {
+ /* If we are not processing a template, then nobody should be
+ providing us with a dependent type. */
+ gcc_assert (type);
+ gcc_assert (TREE_CODE (type) != TEMPLATE_TYPE_PARM);
+ return false;
+ }
/* If the type is NULL, we have not computed a type for the entity
in question; in that case, the type is dependent. */
diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog
index 3262a6a..dd2fdab 100644
--- a/gcc/testsuite/ChangeLog
+++ b/gcc/testsuite/ChangeLog
@@ -1,3 +1,20 @@
+2006-02-07 Mark Mitchell <mark@codesourcery.com>
+
+ PR c++/9737
+ * g++.dg/template/ttp15.C: New test.
+ * g++.dg/template/ttp16.C: Likewise.
+ * g++.dg/template/ttp17.C: Likewise.
+ * g++.old-deja/g++.pt/ttp36.C: Remove.
+ * g++.old-deja/g++.pt/ttp19.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/ttp9.C: Likewise.
+ * g++.old-deja/g++.pt/ttp40.C: Likewise.
+ * g++.old-deja/g++.pt/ttp51.C: Likewise.
+ * g++.old-deja/g++.pt/ttp26.C: Likewise.
+ * g++.old-deja/g++.pt/ttp36.C: Likewise.
+
2005-02-06 Thomas Koenig <Thomas.Koenig@online.de>
PR libfortran/23815
diff --git a/gcc/testsuite/g++.dg/template/ttp15.C b/gcc/testsuite/g++.dg/template/ttp15.C
new file mode 100644
index 0000000..5bb285e
--- /dev/null
+++ b/gcc/testsuite/g++.dg/template/ttp15.C
@@ -0,0 +1,21 @@
+struct Dense {
+ static const unsigned int dim = 1;
+};
+
+template <template <typename> class View,
+ typename Block>
+void operator+(float, View<Block> const&);
+
+template <typename Block,
+ unsigned int Dim = Block::dim>
+struct Lvalue_proxy {
+ operator float() const;
+};
+
+void
+test_1d (void)
+{
+ Lvalue_proxy<Dense> p;
+ float b;
+ b + p;
+}
diff --git a/gcc/testsuite/g++.dg/template/ttp16.C b/gcc/testsuite/g++.dg/template/ttp16.C
new file mode 100644
index 0000000..c556c7d
--- /dev/null
+++ b/gcc/testsuite/g++.dg/template/ttp16.C
@@ -0,0 +1,7 @@
+template <template <typename> class C>
+void f() {}
+
+template <typename T, typename U = int>
+struct S {};
+
+template void f<S>(); // { dg-error "match" }
diff --git a/gcc/testsuite/g++.dg/template/ttp17.C b/gcc/testsuite/g++.dg/template/ttp17.C
new file mode 100644
index 0000000..f1ddeb1
--- /dev/null
+++ b/gcc/testsuite/g++.dg/template/ttp17.C
@@ -0,0 +1,7 @@
+template <template <typename> class C>
+void f(C<double>) {}
+
+template <typename T, typename U = int>
+struct S {};
+
+template void f(S<double>); // { dg-error "match" }
diff --git a/gcc/testsuite/g++.old-deja/g++.pt/ttp19.C b/gcc/testsuite/g++.old-deja/g++.pt/ttp19.C
deleted file mode 100644
index 76ff601..0000000
--- a/gcc/testsuite/g++.old-deja/g++.pt/ttp19.C
+++ /dev/null
@@ -1,25 +0,0 @@
-// { dg-do run }
-#include <vector>
-
-template<template<class> class D,class E> class C
-{
- D<E> d;
- public:
- int size() { return d.size(); }
-};
-
-template<template<class> class D,class E> int size(D<E> &d1)
-{
- d1.size();
- C<D,E> d2;
- d2.size();
- return 0;
-}
-
-int main()
-{
- std::vector<int> c1;
- std::vector<char> c2;
- size(c1);
- size(c2);
-}
diff --git a/gcc/testsuite/g++.old-deja/g++.pt/ttp26.C b/gcc/testsuite/g++.old-deja/g++.pt/ttp26.C
deleted file mode 100644
index 0be2c44..0000000
--- a/gcc/testsuite/g++.old-deja/g++.pt/ttp26.C
+++ /dev/null
@@ -1,34 +0,0 @@
-// { dg-do run }
-template<class T, class U = int> class D
-{
- public:
- int f();
-};
-
-template<class T, class U> int D<T,U>::f()
-{
- return sizeof(T)+sizeof(U);
-}
-
-template<template<class> class D,class E> class C
-{
- D<E> d;
- public:
- int f() { return d.f(); }
-};
-
-template<template<class> class D,class E> int f(D<E> &d1)
-{
- d1.f();
- C<D,E> d2;
- d2.f();
- return 0;
-}
-
-int main()
-{
- D<int> c1;
- D<char> c2;
- f(c1);
- f(c2);
-}
diff --git a/gcc/testsuite/g++.old-deja/g++.pt/ttp35.C b/gcc/testsuite/g++.old-deja/g++.pt/ttp35.C
deleted file mode 100644
index 4e02a95..0000000
--- a/gcc/testsuite/g++.old-deja/g++.pt/ttp35.C
+++ /dev/null
@@ -1,36 +0,0 @@
-// { dg-do run }
-template<int T, class U = int> class D
-{
- public:
- int f();
-};
-
-template<int T, class U> int D<T,U>::f()
-{
- return T+sizeof(U);
-}
-
-template<template<int> class D,class E> class C
-{
- D<1> d;
- public:
- int f() { return d.f(); }
-};
-
-template<template<int> class D> int f(D<2> &d1)
-{
- d1.f();
- return 0;
-}
-
-template<template<int> class D> int f(D<1> &d1)
-{
- d1.f();
- return 0;
-}
-
-int main()
-{
- D<1> c1;
- f(c1);
-}
diff --git a/gcc/testsuite/g++.old-deja/g++.pt/ttp36.C b/gcc/testsuite/g++.old-deja/g++.pt/ttp36.C
deleted file mode 100644
index 2836e8a..0000000
--- a/gcc/testsuite/g++.old-deja/g++.pt/ttp36.C
+++ /dev/null
@@ -1,30 +0,0 @@
-// { dg-do run }
-template<int T, class U = int> class D
-{
- public:
- int f();
-};
-
-template<int T, class U> int D<T,U>::f()
-{
- return T+sizeof(U);
-}
-
-template<template<int> class D,class E> class C
-{
- D<1> d;
- public:
- int f() { return d.f(); }
-};
-
-template<template<int> class D> int f(D<1> &d1)
-{
- d1.f();
- return 0;
-}
-
-int main()
-{
- D<1> c1;
- f(c1);
-}
diff --git a/gcc/testsuite/g++.old-deja/g++.pt/ttp37.C b/gcc/testsuite/g++.old-deja/g++.pt/ttp37.C
deleted file mode 100644
index 4ef30dd..0000000
--- a/gcc/testsuite/g++.old-deja/g++.pt/ttp37.C
+++ /dev/null
@@ -1,30 +0,0 @@
-// { dg-do run }
-template<int T, class U = int> class D
-{
- public:
- int f();
-};
-
-template<int T, class U> int D<T,U>::f()
-{
- return T+sizeof(U);
-}
-
-template<template<int> class D,class E> class C
-{
- D<1> d;
- public:
- int f() { return d.f(); }
-};
-
-template<template<int> class D, int T> int f(D<T> &d1)
-{
- d1.f();
- return T;
-}
-
-int main()
-{
- D<1> c1;
- f(c1);
-}
diff --git a/gcc/testsuite/g++.old-deja/g++.pt/ttp38.C b/gcc/testsuite/g++.old-deja/g++.pt/ttp38.C
deleted file mode 100644
index be4bca9..0000000
--- a/gcc/testsuite/g++.old-deja/g++.pt/ttp38.C
+++ /dev/null
@@ -1,30 +0,0 @@
-// { dg-do run }
-template<class T, class U = int> class D
-{
- public:
- int f();
-};
-
-template<class T, class U> int D<T,U>::f()
-{
- return sizeof(T)+sizeof(U);
-}
-
-template<template<class> class D,class E> class C
-{
- D<E> d;
- public:
- int f() { return d.f(); }
-};
-
-template<template<class> class D> int f(D<int> &d1)
-{
- d1.f();
- return 0;
-}
-
-int main()
-{
- D<int> c1;
- f(c1);
-}
diff --git a/gcc/testsuite/g++.old-deja/g++.pt/ttp39.C b/gcc/testsuite/g++.old-deja/g++.pt/ttp39.C
deleted file mode 100644
index a962004..0000000
--- a/gcc/testsuite/g++.old-deja/g++.pt/ttp39.C
+++ /dev/null
@@ -1,30 +0,0 @@
-// { dg-do run }
-template<class T, class U = T> class D
-{
- public:
- int f();
-};
-
-template<class T, class U> int D<T,U>::f()
-{
- return sizeof(T)+sizeof(U);
-}
-
-template<template<class> class D,class E> class C
-{
- D<E> d;
- public:
- int f() { return d.f(); }
-};
-
-template<template<class> class D> int f(D<int> &d1)
-{
- d1.f();
- return 0;
-}
-
-int main()
-{
- D<int> c1;
- f(c1);
-}
diff --git a/gcc/testsuite/g++.old-deja/g++.pt/ttp40.C b/gcc/testsuite/g++.old-deja/g++.pt/ttp40.C
deleted file mode 100644
index 49d39e1..0000000
--- a/gcc/testsuite/g++.old-deja/g++.pt/ttp40.C
+++ /dev/null
@@ -1,21 +0,0 @@
-// { dg-do run }
-#include <vector>
-
-template<class E,template<class> class DD = std::vector> class C
-{
- DD<E> d;
- public:
- int f();
-};
-
-template<class E,template<class> class DD> int C<E,DD>::f()
-{
- DD<E> d2;
- return d2.size();
-}
-
-int main()
-{
- C<int> c;
- c.f();
-}
diff --git a/gcc/testsuite/g++.old-deja/g++.pt/ttp51.C b/gcc/testsuite/g++.old-deja/g++.pt/ttp51.C
deleted file mode 100644
index db83349..0000000
--- a/gcc/testsuite/g++.old-deja/g++.pt/ttp51.C
+++ /dev/null
@@ -1,14 +0,0 @@
-// { dg-do run }
-template<class E, int i, class F, class G=int, int j=i, class H=E> class D
-{
-};
-
-template<template<class,int,class,class> class D,class E> class C
-{
- D<E,2,char,bool> d;
-};
-
-int main()
-{
- C<D,int> c;
-}
diff --git a/gcc/testsuite/g++.old-deja/g++.pt/ttp9.C b/gcc/testsuite/g++.old-deja/g++.pt/ttp9.C
deleted file mode 100644
index 7ca9a9a..0000000
--- a/gcc/testsuite/g++.old-deja/g++.pt/ttp9.C
+++ /dev/null
@@ -1,14 +0,0 @@
-// { dg-do run }
-template<class E,class F=int> class D
-{
-};
-
-template<template<class> class D,class E> class C
-{
- D<E> d;
-};
-
-int main()
-{
- C<D,int> c;
-}