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 /gcc/cp/pt.c | |
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
Diffstat (limited to 'gcc/cp/pt.c')
-rw-r--r-- | gcc/cp/pt.c | 90 |
1 files changed, 73 insertions, 17 deletions
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; |