Patch for g++-980308: bug in template template parameter implementation again
Kriang Lerdsuwanakij
lerdsuwa@scf-fs.usc.edu
Sun Mar 15 16:25:00 GMT 1998
Bernd Nottelmann <nottelm@PTP283.UNI-MUENSTER.DE> wrote:
> Unfortunately I have found a new internal compiler error -
> though I have installed the two patches from Kriang
> ( http://www.cygnus.com/ml/egcs-bugs/1998-Mar/0229.html and
> http://www.cygnus.com/ml/egcs-bugs/1998-Mar/0255.html ) ...
> here is some sample code:
>
> /*-------------------bug3.C-------------------*/
> template < class T, template < class > class E1, template < class > class E2 >
> struct Add {
> Add(const E1<T>& e1, const E2<T>& e2) {}
> };
>
> template < class T >
> struct Id {
> template < template < class > class E >
> Add < T, Id, E > operator+(const E<T>& e) const {
> return Add < T, Id, E >(*this, e);
> }
>
> template <> Add < T, Id, Id > operator+(const Id<T>& e) const {
> return Add < T, Id, Id >(*this, e);
> }
> };
>
The code look ok to me. The patch included below fixes a bug that
affect the code above (without an extra `<>' after `operator+' in the
specialization syntax). It also fixes the `Id<double>& + Id<double>&'
bug you mentioned.
I believe that the extra bracket is not required (according to C++
Programming Language, page 344). The parser in egcs still cannot handle
various template function or operator specialization construct. It might
lead to incorrect error messages or internal compiler error. I haven't
found a good fix for this. :(
--Kriang
* pt.c (complete_template_args): New function.
(get_bindings): Deal with specializations of function templates
with return type containing parameters from outer class
templates.
(tsubst, TEMPLATE_TEMPLATE_PARM): When reducing parameter level,
substitute arguments and compose a new type.
diff -cprN gcc-980311/cp/pt.c gcc-980315/cp/pt.c
*** gcc-980311/cp/pt.c Wed Mar 11 20:18:48 1998
--- gcc-980315/cp/pt.c Sun Mar 15 15:32:25 1998
*************** static tree get_class_bindings PROTO((tr
*** 81,86 ****
--- 81,87 ----
static tree coerce_template_parms PROTO((tree, tree, tree, int, int, int));
static tree tsubst_enum PROTO((tree, tree, tree *));
static tree add_to_template_args PROTO((tree, tree));
+ static tree complete_template_args PROTO((tree, tree));
static int type_unification_real PROTO((tree, tree *, tree, tree,
int, int, int));
static void note_template_header PROTO((int));
*************** is_member_template (t)
*** 296,301 ****
--- 297,370 ----
return is_member_or_friend_template (t, 0);
}
+ /* Return a new template argument vector which contains all of ARGS
+ for all outer templates TYPE is contained in, but has as its
+ innermost set of arguments the EXTRA_ARGS. */
+
+ static tree
+ complete_template_args (decl, extra_args)
+ tree decl;
+ tree extra_args;
+ {
+ int depth;
+ tree type;
+
+ my_friendly_assert (TREE_CODE (decl) == TEMPLATE_DECL, 0);
+ my_friendly_assert (TREE_CODE (extra_args) == TREE_VEC, 0);
+
+ decl = DECL_TEMPLATE_RESULT (decl);
+ type = DECL_REAL_CONTEXT (decl);
+
+ /* For constructor and destructor, it can be template simply
+ because the class it belongs to is. If this is the case,
+ it and its context share the same template arguments and
+ we don't want its context in template_class_depth
+ computation. */
+
+ if (DECL_LANG_SPECIFIC (decl) && DECL_CONSTRUCTOR_P (decl))
+ {
+ /* Check whether its context is a template class. */
+ if (CLASSTYPE_TEMPLATE_INFO (type)
+ && PRIMARY_TEMPLATE_P (CLASSTYPE_TI_TEMPLATE (type))
+ && uses_template_parms (CLASSTYPE_TI_ARGS (type)))
+ {
+ if (comp_template_args (CLASSTYPE_TI_ARGS (type),
+ DECL_TI_ARGS (decl)))
+ type = TYPE_CONTEXT (type);
+
+ }
+ }
+ else if (DESTRUCTOR_NAME_P (DECL_ASSEMBLER_NAME (decl)))
+ {
+ /* There is no template destructors. */
+ type = TYPE_CONTEXT (type);
+ }
+
+ depth = template_class_depth (type);
+ if (depth)
+ {
+ tree new_args = make_tree_vec (depth + 1);
+
+ for (; type && TREE_CODE (type) != FUNCTION_DECL;
+ type = TYPE_CONTEXT (type))
+ {
+ if (CLASSTYPE_TEMPLATE_INFO (type)
+ && PRIMARY_TEMPLATE_P (CLASSTYPE_TI_TEMPLATE (type))
+ && uses_template_parms (CLASSTYPE_TI_ARGS (type)))
+ {
+ --depth;
+ TREE_VEC_ELT (new_args, depth) = CLASSTYPE_TI_ARGS (type);
+ }
+ }
+
+ TREE_VEC_ELT (new_args,
+ TREE_VEC_LENGTH (new_args) - 1) = extra_args;
+ extra_args = new_args;
+ }
+
+ return extra_args;
+ }
+
/* Return a new template argument vector which contains all of ARGS,
but has as its innermost set of arguments the EXTRA_ARGS. */
*************** tsubst (t, args, in_decl)
*** 3525,3531 ****
{
case TEMPLATE_TYPE_PARM:
case TEMPLATE_TEMPLATE_PARM:
! r = copy_node (t);
TEMPLATE_TYPE_PARM_INDEX (r)
= reduce_template_parm_level (TEMPLATE_TYPE_PARM_INDEX (t),
r, levels);
--- 3594,3613 ----
{
case TEMPLATE_TYPE_PARM:
case TEMPLATE_TEMPLATE_PARM:
!
! if (TREE_CODE (t) == TEMPLATE_TEMPLATE_PARM
! && CLASSTYPE_TEMPLATE_INFO (t))
! {
! tree argvec = tsubst (CLASSTYPE_TI_ARGS (t),
! args, in_decl);
! r = lookup_template_class (TYPE_NAME (t), argvec, in_decl,
! DECL_CONTEXT (TYPE_NAME (t)));
! r = cp_build_type_variant (r, TYPE_READONLY (t),
! TYPE_VOLATILE (t));
! }
! else
! r = copy_node (t);
!
TEMPLATE_TYPE_PARM_INDEX (r)
= reduce_template_parm_level (TEMPLATE_TYPE_PARM_INDEX (t),
r, levels);
*************** get_bindings (fn, decl, explicit_args)
*** 5702,5708 ****
if (i == 0)
{
/* Check to see that the resulting return type is also OK. */
! tree t = tsubst (TREE_TYPE (TREE_TYPE (fn)), targs, NULL_TREE);
if (!comptypes (t, TREE_TYPE (TREE_TYPE (decl)), 1))
return NULL_TREE;
--- 5784,5792 ----
if (i == 0)
{
/* Check to see that the resulting return type is also OK. */
! tree t = tsubst (TREE_TYPE (TREE_TYPE (fn)),
! complete_template_args (fn, targs),
! NULL_TREE);
if (!comptypes (t, TREE_TYPE (TREE_TYPE (decl)), 1))
return NULL_TREE;
More information about the Gcc-bugs
mailing list