pt.c (verify_class_unification): New function.

* pt.c (verify_class_unification): New function.
	(get_class_bindings): Use it.
	(try_class_unification): Tidy.
	(unify): Handle when argument of a template-id is not
	template parameter dependent.
	(template_args_equal): Handle when TREE_CODE's do not match.

	* g++.old-deja/g++.oliva/partspec1.C: Remove XFAIL.
	* g++.old-deja/g++.pt/partial4.C: New test.

From-SVN: r38102
This commit is contained in:
Kriang Lerdsuwanakij 2000-12-07 07:17:09 +00:00 committed by Kriang Lerdsuwanakij
parent 9ba2e1ef80
commit 74601d7c09
5 changed files with 124 additions and 30 deletions

View File

@ -1,3 +1,12 @@
2000-12-06 Kriang Lerdsuwanakij <lerdsuwa@users.sourceforge.net>
* pt.c (verify_class_unification): New function.
(get_class_bindings): Use it.
(try_class_unification): Tidy.
(unify): Handle when argument of a template-id is not
template parameter dependent.
(template_args_equal): Handle when TREE_CODE's do not match.
2000-12-06 Alexandre Oliva <aoliva@redhat.com>
* lang-specs.h (c++): When invoking the stand-alone preprocessor

View File

@ -157,6 +157,7 @@ static tree tsubst_call_declarator_parms PARAMS ((tree, tree, int, tree));
static tree get_template_base_recursive PARAMS ((tree, tree,
tree, tree, tree, int));
static tree get_template_base PARAMS ((tree, tree, tree, tree));
static int verify_class_unification PARAMS ((tree, tree, tree));
static tree try_class_unification PARAMS ((tree, tree, tree, tree));
static int coerce_template_template_parms PARAMS ((tree, tree, int,
tree, tree));
@ -3464,13 +3465,14 @@ template_args_equal (ot, nt)
{
if (nt == ot)
return 1;
if (TREE_CODE (nt) != TREE_CODE (ot))
return 0;
if (TREE_CODE (nt) == TREE_VEC)
/* For member templates */
return comp_template_args (ot, nt);
else if (TYPE_P (ot))
return same_type_p (ot, nt);
return TREE_CODE (ot) == TREE_VEC && comp_template_args (ot, nt);
else if (TYPE_P (nt))
return TYPE_P (ot) && same_type_p (ot, nt);
else if (TREE_CODE (ot) == TREE_VEC || TYPE_P (ot))
return 0;
else
return (cp_tree_equal (ot, nt) > 0);
}
@ -8039,6 +8041,52 @@ try_one_overload (tparms, orig_targs, targs, parm, arg, strict,
return 1;
}
/* Verify that nondeduce template argument agrees with the type
obtained from argument deduction. Return nonzero if the
verification fails.
For example:
struct A { typedef int X; };
template <class T, class U> struct C {};
template <class T> struct C<T, typename T::X> {};
Then with the instantiation `C<A, int>', we can deduce that
`T' is `A' but unify () does not check whether `typename T::X'
is `int'. This function ensure that they agree.
TARGS, PARMS are the same as the arguments of unify.
ARGS contains template arguments from all levels. */
static int
verify_class_unification (targs, parms, args)
tree targs, parms, args;
{
int i;
int nparms = TREE_VEC_LENGTH (parms);
tree new_parms = tsubst (parms, add_outermost_template_args (args, targs),
/*complain=*/0, NULL_TREE);
if (new_parms == error_mark_node)
return 1;
args = INNERMOST_TEMPLATE_ARGS (args);
for (i = 0; i < nparms; i++)
{
tree parm = TREE_VEC_ELT (new_parms, i);
tree arg = TREE_VEC_ELT (args, i);
/* In case we are deducing from a function argument of a function
templates, some parameters may not be deduced yet. So we
make sure that only fully substituted elements of PARM are
compared below. */
if (!uses_template_parms (parm) && !template_args_equal (parm, arg))
return 1;
}
return 0;
}
/* PARM is a template class (perhaps with unbound template
parameters). ARG is a fully instantiated type. If ARG can be
bound to PARM, return ARG, otherwise return NULL_TREE. TPARMS and
@ -8051,7 +8099,6 @@ try_class_unification (tparms, targs, parm, arg)
tree parm;
tree arg;
{
int i;
tree copy_of_targs;
if (!CLASSTYPE_TEMPLATE_INFO (arg)
@ -8089,14 +8136,13 @@ try_class_unification (tparms, targs, parm, arg)
with S<I, I, I>. If we kept the already deduced knowledge, we
would reject the possibility I=1. */
copy_of_targs = make_tree_vec (TREE_VEC_LENGTH (targs));
i = unify (tparms, copy_of_targs, CLASSTYPE_TI_ARGS (parm),
CLASSTYPE_TI_ARGS (arg), UNIFY_ALLOW_NONE);
/* If unification failed, we're done. */
if (i != 0)
if (unify (tparms, copy_of_targs, CLASSTYPE_TI_ARGS (parm),
CLASSTYPE_TI_ARGS (arg), UNIFY_ALLOW_NONE))
return NULL_TREE;
else
return arg;
return arg;
}
/* Subroutine of get_template_base. RVAL, if non-NULL, is a base we
@ -8699,25 +8745,33 @@ unify (tparms, targs, parm, arg, strict)
default:
if (IS_EXPR_CODE_CLASS (TREE_CODE_CLASS (TREE_CODE (parm))))
/* We're looking at an expression. This can happen with
something like:
{
/* We're looking at an expression. This can happen with
something like:
template <int I>
void foo(S<I>, S<I + 2>);
template <int I>
void foo(S<I>, S<I + 2>);
This is a "nondeduced context":
This is a "nondeduced context":
[deduct.type]
[deduct.type]
The nondeduced contexts are:
The nondeduced contexts are:
--A type that is a template-id in which one or more of
the template-arguments is an expression that references
a template-parameter.
--A type that is a template-id in which one or more of
the template-arguments is an expression that references
a template-parameter.
In these cases, we assume deduction succeeded, but don't
actually infer any unifications. */
return 0;
In these cases, we assume deduction succeeded, but don't
actually infer any unifications. */
if (!uses_template_parms (parm)
&& !template_args_equal (parm, arg))
return 1;
else
return 0;
}
else
sorry ("use of `%s' in template type unification",
tree_code_name [(int) TREE_CODE (parm)]);
@ -8923,15 +8977,17 @@ get_class_bindings (tparms, parms, args)
int i, ntparms = TREE_VEC_LENGTH (tparms);
tree vec = make_tree_vec (ntparms);
args = INNERMOST_TEMPLATE_ARGS (args);
if (unify (tparms, vec, parms, args, UNIFY_ALLOW_NONE))
if (unify (tparms, vec, parms, INNERMOST_TEMPLATE_ARGS (args),
UNIFY_ALLOW_NONE))
return NULL_TREE;
for (i = 0; i < ntparms; ++i)
if (! TREE_VEC_ELT (vec, i))
return NULL_TREE;
if (verify_class_unification (vec, parms, args))
return NULL_TREE;
return vec;
}

View File

@ -1,3 +1,8 @@
2000-12-06 Kriang Lerdsuwanakij <lerdsuwa@users.sourceforge.net>
* g++.old-deja/g++.oliva/partspec1.C: Remove XFAIL.
* g++.old-deja/g++.pt/partial4.C: New test.
2000-12-06 J. David Anglin <dave@hiauly1.hia.nrc.ca>
* gcc.c-torture/execute/ieee/hugeval.x: New.

View File

@ -10,11 +10,11 @@ template <typename A, int* P> struct X;
int a;
template <typename A>
struct X<A,&a> {}; // gets bogus error - candidate - XFAIL *-*-*
struct X<A,&a> {};
int b;
template <typename A>
struct X<A,&b> {}; // gets bogus error - candidate - XFAIL *-*-*
struct X<A,&b> {};
X<int,&a> x; // gets bogus error - ambiguous - XFAIL *-*-*
X<int,&a> x;

View File

@ -0,0 +1,24 @@
// Build don't link:
// Origin: Gabriel Dos Reis <Gabriel.Dos-Reis@cmla.ens-cachan.fr>
// Bug 29. We failed to verify that template argument deduction
// produces a valid result in nondeduce context.
template<class T> struct Y { typedef T X; };
template<class T, class U> struct Base {};
template<class T> struct Base<T, typename T::X> {};
template<class T> struct Base<typename T::X, T> {};
template<class T, class U> struct Derived : Base <T, U> {};
struct A {};
template<class T> struct Derived<A, T> : Base< Y<T>, Y<T> > {};
int main()
{
Derived<A, int> d;
}