diff options
author | Kriang Lerdsuwanakij <lerdsuwa@users.sourceforge.net> | 2000-12-07 07:17:09 +0000 |
---|---|---|
committer | Kriang Lerdsuwanakij <lerdsuwa@gcc.gnu.org> | 2000-12-07 07:17:09 +0000 |
commit | 74601d7c09fba7d38715dc1adb1b24fdd98cf1f3 (patch) | |
tree | 42bc9043447773d2eac4ced16950fa0b3283cbb2 | |
parent | 9ba2e1ef8028112b47eb48041ae387c60acea6b1 (diff) | |
download | gcc-74601d7c09fba7d38715dc1adb1b24fdd98cf1f3.zip gcc-74601d7c09fba7d38715dc1adb1b24fdd98cf1f3.tar.gz gcc-74601d7c09fba7d38715dc1adb1b24fdd98cf1f3.tar.bz2 |
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
-rw-r--r-- | gcc/cp/ChangeLog | 9 | ||||
-rw-r--r-- | gcc/cp/pt.c | 110 | ||||
-rw-r--r-- | gcc/testsuite/ChangeLog | 5 | ||||
-rw-r--r-- | gcc/testsuite/g++.old-deja/g++.oliva/partspec1.C | 6 | ||||
-rw-r--r-- | gcc/testsuite/g++.old-deja/g++.pt/partial4.C | 24 |
5 files changed, 124 insertions, 30 deletions
diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog index 585e815..49c3d64 100644 --- a/gcc/cp/ChangeLog +++ b/gcc/cp/ChangeLog @@ -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 diff --git a/gcc/cp/pt.c b/gcc/cp/pt.c index d975a7d..900ef3c 100644 --- a/gcc/cp/pt.c +++ b/gcc/cp/pt.c @@ -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; } diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index 36b7ef4..340a765 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -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. diff --git a/gcc/testsuite/g++.old-deja/g++.oliva/partspec1.C b/gcc/testsuite/g++.old-deja/g++.oliva/partspec1.C index 00942c0..067a635 100644 --- a/gcc/testsuite/g++.old-deja/g++.oliva/partspec1.C +++ b/gcc/testsuite/g++.old-deja/g++.oliva/partspec1.C @@ -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; diff --git a/gcc/testsuite/g++.old-deja/g++.pt/partial4.C b/gcc/testsuite/g++.old-deja/g++.pt/partial4.C new file mode 100644 index 0000000..3956a0c --- /dev/null +++ b/gcc/testsuite/g++.old-deja/g++.pt/partial4.C @@ -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; +} |