diff options
author | Dodji Seketeli <dodji@redhat.com> | 2010-02-21 18:06:39 +0000 |
---|---|---|
committer | Dodji Seketeli <dodji@gcc.gnu.org> | 2010-02-21 19:06:39 +0100 |
commit | 04afbf1c7feeaecd4d0e85bd2566ef3e65e84b21 (patch) | |
tree | 5f7f5bd5b1fcd57934503d28f2e1124f13056837 | |
parent | d66489977ef89a02300f3441c1fb183236351a76 (diff) | |
download | gcc-04afbf1c7feeaecd4d0e85bd2566ef3e65e84b21.zip gcc-04afbf1c7feeaecd4d0e85bd2566ef3e65e84b21.tar.gz gcc-04afbf1c7feeaecd4d0e85bd2566ef3e65e84b21.tar.bz2 |
re PR c++/42824 (c++ compilation complains about error: call of overloaded)
Fix PR c++/42824
gcc/cp/ChangeLog:
PR c++/42824
* pt.c (lookup_template_class): Better support of specialization
of member of class template implicit instantiation.
gcc/testsuite/ChangeLog:
PR c++/42824
* g++.dg/template/memclass4.C: New test.
From-SVN: r156939
-rw-r--r-- | gcc/cp/ChangeLog | 6 | ||||
-rw-r--r-- | gcc/cp/pt.c | 90 | ||||
-rw-r--r-- | gcc/testsuite/ChangeLog | 5 | ||||
-rw-r--r-- | gcc/testsuite/g++.dg/template/memclass4.C | 70 |
4 files changed, 154 insertions, 17 deletions
diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog index d71e2b4..2ce5e02 100644 --- a/gcc/cp/ChangeLog +++ b/gcc/cp/ChangeLog @@ -1,3 +1,9 @@ +2010-02-21 Dodji Seketeli <dodji@redhat.com> + + PR c++/42824 + * pt.c (lookup_template_class): Better support of specialization + of member of class template implicit instantiation. + 2010-02-20 Manuel López-Ibáñez <manu@gcc.gnu.org> PR c++/35669 diff --git a/gcc/cp/pt.c b/gcc/cp/pt.c index 9e159a2..8b19e2c 100644 --- a/gcc/cp/pt.c +++ b/gcc/cp/pt.c @@ -6379,7 +6379,8 @@ lookup_template_class (tree d1, tree found = NULL_TREE; int arg_depth; int parm_depth; - int is_partial_instantiation; + int is_dependent_type; + int use_partial_inst_tmpl = false; gen_tmpl = most_general_template (templ); parmlist = DECL_TEMPLATE_PARMS (gen_tmpl); @@ -6495,21 +6496,17 @@ lookup_template_class (tree d1, if (entry) POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, entry->spec); - /* This type is a "partial instantiation" if any of the template - arguments still involve template parameters. Note that we set - IS_PARTIAL_INSTANTIATION for partial specializations as - well. */ - is_partial_instantiation = uses_template_parms (arglist); + is_dependent_type = uses_template_parms (arglist); /* If the deduced arguments are invalid, then the binding failed. */ - if (!is_partial_instantiation + if (!is_dependent_type && check_instantiated_args (gen_tmpl, INNERMOST_TEMPLATE_ARGS (arglist), complain)) POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, error_mark_node); - if (!is_partial_instantiation + if (!is_dependent_type && !PRIMARY_TEMPLATE_P (gen_tmpl) && !LAMBDA_TYPE_P (TREE_TYPE (gen_tmpl)) && TREE_CODE (CP_DECL_CONTEXT (gen_tmpl)) == NAMESPACE_DECL) @@ -6528,7 +6525,7 @@ lookup_template_class (tree d1, /* Create the type. */ if (TREE_CODE (template_type) == ENUMERAL_TYPE) { - if (!is_partial_instantiation) + if (!is_dependent_type) { set_current_access_from_decl (TYPE_NAME (template_type)); t = start_enum (TYPE_IDENTIFIER (template_type), @@ -6594,11 +6591,71 @@ lookup_template_class (tree d1, DECL_VISIBILITY (type_decl) = CLASSTYPE_VISIBILITY (template_type); } - /* Set up the template information. We have to figure out which - template is the immediate parent if this is a full - instantiation. */ - if (parm_depth == 1 || is_partial_instantiation - || !PRIMARY_TEMPLATE_P (gen_tmpl)) + /* Let's consider the explicit specialization of a member + of a class template specialization that is implicitely instantiated, + e.g.: + template<class T> + struct S + { + template<class U> struct M {}; //#0 + }; + + template<> + template<> + struct S<int>::M<char> //#1 + { + int i; + }; + [temp.expl.spec]/4 says this is valid. + + In this case, when we write: + S<int>::M<char> m; + + M is instantiated from the CLASSTYPE_TI_TEMPLATE of #1, not from + the one of #0. + + When we encounter #1, we want to store the partial instantiation + of M (template<class T> S<int>::M<T>) in it's CLASSTYPE_TI_TEMPLATE. + + For all cases other than this "explicit specialization of member of a + class template", we just want to store the most general template into + the CLASSTYPE_TI_TEMPLATE of M. + + This case of "explicit specialization of member of a class template" + only happens when: + 1/ the enclosing class is an instantiation of, and therefore not + the same as, the context of the most general template, and + 2/ we aren't looking at the partial instantiation itself, i.e. + the innermost arguments are not the same as the innermost parms of + the most general template. + + So it's only when 1/ and 2/ happens that we want to use the partial + instantiation of the member template in lieu of its most general + template. */ + + if (PRIMARY_TEMPLATE_P (gen_tmpl) + && TMPL_ARGS_HAVE_MULTIPLE_LEVELS (arglist) + /* the enclosing class must be an instantiation... */ + && CLASS_TYPE_P (context) + && !same_type_p (context, DECL_CONTEXT (gen_tmpl))) + { + tree partial_inst_args; + TREE_VEC_LENGTH (arglist)--; + ++processing_template_decl; + partial_inst_args = + tsubst (INNERMOST_TEMPLATE_ARGS + (CLASSTYPE_TI_ARGS (TREE_TYPE (gen_tmpl))), + arglist, complain, NULL_TREE); + --processing_template_decl; + TREE_VEC_LENGTH (arglist)++; + use_partial_inst_tmpl = + /*...and we must not be looking at the partial instantiation + itself. */ + !comp_template_args (INNERMOST_TEMPLATE_ARGS (arglist), + partial_inst_args); + } + + if (!use_partial_inst_tmpl) /* This case is easy; there are no member templates involved. */ found = gen_tmpl; else @@ -6628,8 +6685,7 @@ lookup_template_class (tree d1, = tree_cons (arglist, t, DECL_TEMPLATE_INSTANTIATIONS (templ)); - if (TREE_CODE (t) == ENUMERAL_TYPE - && !is_partial_instantiation) + if (TREE_CODE (t) == ENUMERAL_TYPE && !is_dependent_type) /* Now that the type has been registered on the instantiations list, we set up the enumerators. Because the enumeration constants may involve the enumeration type itself, we make @@ -6639,7 +6695,7 @@ lookup_template_class (tree d1, the instantiation and exit above. */ tsubst_enum (template_type, t, arglist); - if (is_partial_instantiation) + if (is_dependent_type) /* If the type makes use of template parameters, the code that generates debugging information will crash. */ DECL_IGNORED_P (TYPE_STUB_DECL (t)) = 1; diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index 682a7e8..cc94d47 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,8 @@ +2010-02-21 Dodji Seketeli <dodji@redhat.com> + + PR c++/42824 + * g++.dg/template/memclass4.C: New test. + 2010-02-21 Tobias Burnus <burnus@net-b.de> PR fortran/35259 diff --git a/gcc/testsuite/g++.dg/template/memclass4.C b/gcc/testsuite/g++.dg/template/memclass4.C new file mode 100644 index 0000000..65a42a4 --- /dev/null +++ b/gcc/testsuite/g++.dg/template/memclass4.C @@ -0,0 +1,70 @@ +// Origin: PR c++/42824 +// { dg-do compile } + +template<int T> +class int_ { +}; + +template<int T, int T2> +class Unit { +public: + Unit(const Unit<T, T2>& other) {} +}; + +template<int T> +class Quan { +public: + Quan(void) {} + + template<int T2> + Quan(double value, Unit<T, T2> unit) {} +}; +typedef Quan<0> Scalar; + +template<int T> +class hlp { +public: + typedef Quan<T> type; +}; + +class Mtrl { +public: + template<int T> + struct AssoType { + typedef typename hlp<T>::type type; + }; +}; + +template<class T> +class Eval { +public: + Eval(const T& object){} + + template<int V> + void eval() { + eval<V> (int_<0>()); + } +private: + template<typename U> struct Wrap {}; + + template<int V, int V2> + void value(Wrap<Quan<V2> >) {} + + template<int V> + void value(Wrap<Scalar>) {} + + template<int V> + void eval(int_<0>) { + typedef typename T::template AssoType<V>::type Type; + value<V>(Wrap<Type>()); + } +}; + +class Foo { +public: + static void eval(const Mtrl& mtrl) { + Eval<Mtrl> h(mtrl); + h.eval<0> (); + } +}; + |