Commit 04afbf1c by Dodji Seketeli Committed by Dodji Seketeli

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
parent d6648997
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
......
......@@ -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;
......
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
......
// 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> ();
}
};
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment