[C++ PATCH]Fix for bug 29,g++.oliva/partspec1.C (revised)
Kriang Lerdsuwanakij
lerdsuwa@scf.usc.edu
Wed Nov 29 22:25:00 GMT 2000
Hi
This is an updated version of the patch I submitted earlier
http://gcc.gnu.org/ml/gcc-patches/2000-11/msg01431.html
The tsubst call in verify_class_unification() called from
try_class_unification() is redundant in this case. So
only the template_args_equal() is retained and is moved to
unify().
Tested on i586-pc-linux-gnu. OK to installed the patch?
--Kriang
ChangeLog for cp:
2000-11-29 Kriang Lerdsuwanakij <lerdsuwa@users.sourceforge.net>
* pt.c (verify_class_unification): New function.
(get_class_bindings): Use it.
(unify): Handle when argument of a template-id is not
template parameter dependent.
ChangeLog for testsuite:
2000-11-29 Kriang Lerdsuwanakij <lerdsuwa@users.sourceforge.net>
* g++.old-deja/g++.oliva/partspec1.C: Remove XFAIL.
* g++.old-deja/g++.pt/partial4.C: New test.
diff -cprN gcc-old/gcc/cp/pt.c gcc-new/gcc/cp/pt.c
*** gcc-old/gcc/cp/pt.c Mon Nov 27 04:53:38 2000
--- gcc-new/gcc/cp/pt.c Wed Nov 29 17:22:00 2000
*************** static tree tsubst_call_declarator_parms
*** 157,162 ****
--- 157,163 ----
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));
*************** try_one_overload (tparms, orig_targs, ta
*** 8038,8043 ****
--- 8039,8090 ----
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
*************** try_class_unification (tparms, targs, pa
*** 8050,8056 ****
tree parm;
tree arg;
{
- int i;
tree copy_of_targs;
if (!CLASSTYPE_TEMPLATE_INFO (arg)
--- 8097,8102 ----
*************** try_class_unification (tparms, targs, pa
*** 8088,8101 ****
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)
return NULL_TREE;
! else
! return arg;
}
/* Subroutine of get_template_base. RVAL, if non-NULL, is a base we
--- 8134,8146 ----
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));
/* If unification failed, we're done. */
! if (unify (tparms, copy_of_targs, CLASSTYPE_TI_ARGS (parm),
! CLASSTYPE_TI_ARGS (arg), UNIFY_ALLOW_NONE))
return NULL_TREE;
!
! return arg;
}
/* Subroutine of get_template_base. RVAL, if non-NULL, is a base we
*************** unify (tparms, targs, parm, arg, strict)
*** 8697,8721 ****
default:
if (IS_EXPR_CODE_CLASS (TREE_CODE_CLASS (TREE_CODE (parm))))
! /* We're looking at an expression. This can happen with
! something like:
! template <int I>
! void foo(S<I>, S<I + 2>);
! This is a "nondeduced context":
! [deduct.type]
! 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.
! In these cases, we assume deduction succeeded, but don't
! actually infer any unifications. */
! return 0;
else
sorry ("use of `%s' in template type unification",
tree_code_name [(int) TREE_CODE (parm)]);
--- 8742,8778 ----
default:
if (IS_EXPR_CODE_CLASS (TREE_CODE_CLASS (TREE_CODE (parm))))
! {
!
! /* We're looking at an expression. This can happen with
! something like:
! template <int I>
! void foo(S<I>, S<I + 2>);
! This is a "nondeduced context":
! [deduct.type]
! 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.
! In these cases, we assume deduction succeeded, but don't
! actually infer any unifications. */
!
! if (!uses_template_parms (parm))
! {
! while (TREE_CODE (arg) == NOP_EXPR)
! arg = TREE_OPERAND (arg, 0);
!
! if (!template_args_equal (parm, arg))
! return 1;
! }
! return 0;
! }
else
sorry ("use of `%s' in template type unification",
tree_code_name [(int) TREE_CODE (parm)]);
*************** get_class_bindings (tparms, parms, args)
*** 8921,8934 ****
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))
return NULL_TREE;
for (i = 0; i < ntparms; ++i)
if (! TREE_VEC_ELT (vec, i))
return NULL_TREE;
return vec;
}
--- 8978,8993 ----
int i, ntparms = TREE_VEC_LENGTH (tparms);
tree vec = make_tree_vec (ntparms);
! 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;
}
diff -cprN gcc-old/gcc/testsuite/g++.old-deja/g++.oliva/partspec1.C gcc-new/gcc/testsuite/g++.old-deja/g++.oliva/partspec1.C
*** gcc-old/gcc/testsuite/g++.old-deja/g++.oliva/partspec1.C Sat Sep 4 08:09:04 1999
--- gcc-new/gcc/testsuite/g++.old-deja/g++.oliva/partspec1.C Wed Nov 29 13:34:35 2000
*************** template <typename A, int* P> struct X;
*** 10,20 ****
int a;
template <typename A>
! struct X<A,&a> {}; // gets bogus error - candidate - XFAIL *-*-*
int b;
template <typename A>
! struct X<A,&b> {}; // gets bogus error - candidate - XFAIL *-*-*
! X<int,&a> x; // gets bogus error - ambiguous - XFAIL *-*-*
--- 10,20 ----
int a;
template <typename A>
! struct X<A,&a> {};
int b;
template <typename A>
! struct X<A,&b> {};
! X<int,&a> x;
diff -cprN gcc-old/gcc/testsuite/g++.old-deja/g++.pt/partial4.C gcc-new/gcc/testsuite/g++.old-deja/g++.pt/partial4.C
*** gcc-old/gcc/testsuite/g++.old-deja/g++.pt/partial4.C Wed Dec 31 16:00:00 1969
--- gcc-new/gcc/testsuite/g++.old-deja/g++.pt/partial4.C Wed Nov 29 13:34:35 2000
***************
*** 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;
+ }
More information about the Gcc-patches
mailing list