diff options
author | Mark Mitchell <mark@codesourcery.com> | 2006-02-07 11:11:30 +0000 |
---|---|---|
committer | Mark Mitchell <mmitchel@gcc.gnu.org> | 2006-02-07 11:11:30 +0000 |
commit | e7e9396544525de5ad6e09527b4b3d29ab1e6429 (patch) | |
tree | b84246452027309b78b972cb94e51976cb9d0314 /gcc | |
parent | 369681318051ea25a6933cf21f32e98919b1c680 (diff) | |
download | gcc-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/ChangeLog | 14 | ||||
-rw-r--r-- | gcc/cp/pt.c | 111 | ||||
-rw-r--r-- | gcc/testsuite/ChangeLog | 17 | ||||
-rw-r--r-- | gcc/testsuite/g++.dg/template/ttp15.C | 21 | ||||
-rw-r--r-- | gcc/testsuite/g++.dg/template/ttp16.C | 7 | ||||
-rw-r--r-- | gcc/testsuite/g++.dg/template/ttp17.C | 7 | ||||
-rw-r--r-- | gcc/testsuite/g++.old-deja/g++.pt/ttp19.C | 25 | ||||
-rw-r--r-- | gcc/testsuite/g++.old-deja/g++.pt/ttp26.C | 34 | ||||
-rw-r--r-- | gcc/testsuite/g++.old-deja/g++.pt/ttp35.C | 36 | ||||
-rw-r--r-- | gcc/testsuite/g++.old-deja/g++.pt/ttp36.C | 30 | ||||
-rw-r--r-- | gcc/testsuite/g++.old-deja/g++.pt/ttp37.C | 30 | ||||
-rw-r--r-- | gcc/testsuite/g++.old-deja/g++.pt/ttp38.C | 30 | ||||
-rw-r--r-- | gcc/testsuite/g++.old-deja/g++.pt/ttp39.C | 30 | ||||
-rw-r--r-- | gcc/testsuite/g++.old-deja/g++.pt/ttp40.C | 21 | ||||
-rw-r--r-- | gcc/testsuite/g++.old-deja/g++.pt/ttp51.C | 14 | ||||
-rw-r--r-- | gcc/testsuite/g++.old-deja/g++.pt/ttp9.C | 14 |
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; -} |