re PR c++/11596 (ICE with int templates)

cp:
	PR c++/11596
	* pt.c (maybe_fold_nontype_arg, maybe_fold_nontype_args): Remove.
	(tsubst_template_arg): New.
	(tsubst_template_arg_vector): Rename to ...
	(tsubst_template_args): ... this. Accept a TREE_LIST form. Use
	tsubst_template_arg.
	(coerce_template_parms): Use tsubst_template_arg for default
	value.
	(tsubst_template_parms): Likewise.
	(tsubst_aggr_type): Adjust.
	(tsubst_decl): Likewise.
	(tsubst): Use tsubst_template_arg for a DOMAIN. Adjust.
	(tsubst_copy) <TEMPLATE_ID_EXPR case>: Use tsubst_template_args.
testsuite:
	PR 11596
	* g++.dg/template/defarg3.C: New test.

	* g++.dg/ext/packed2.C: Pack member struct too. Explain why.

From-SVN: r69776
This commit is contained in:
Nathan Sidwell 2003-07-25 10:16:13 +00:00
parent b6fe0bb8c5
commit a91db71189
5 changed files with 165 additions and 126 deletions

View File

@ -1,11 +1,27 @@
2003-07-25 Nathan Sidwell <nathan@codesourcery.com>
PR c++/11596
* pt.c (maybe_fold_nontype_arg, maybe_fold_nontype_args): Remove.
(tsubst_template_arg): New.
(tsubst_template_arg_vector): Rename to ...
(tsubst_template_args): ... this. Accept a TREE_LIST form. Use
tsubst_template_arg.
(coerce_template_parms): Use tsubst_template_arg for default
value.
(tsubst_template_parms): Likewise.
(tsubst_aggr_type): Adjust.
(tsubst_decl): Likewise.
(tsubst): Use tsubst_template_arg for a DOMAIN. Adjust.
(tsubst_copy) <TEMPLATE_ID_EXPR case>: Use tsubst_template_args.
2003-07-25 Gabriel Dos Reis <gdr@integrable-solutions.net>
* Make-lang.in (cp/error.o): Depend on DIAGNOSTIC_H.
* error.c: Use the new pretty-printer fraamework.
* error.c: Use the new pretty-printer framework.
2003-07-24 Per Bothner <pbothner@apple.com>
* decl.c (pushdecl_class_level): Don't use push_srcloc/pop_srcloc
* decl.c (pushdecl_class_level): Don't use push_srcloc/pop_srcloc
which causes errors messages to incorrectly mention included files.
2003-07-24 Mark Mitchell <mark@codesourcery.com>

View File

@ -111,8 +111,6 @@ static int maybe_adjust_types_for_deduction (unification_kind_t, tree*, tree*);
static int type_unification_real (tree, tree, tree, tree,
int, unification_kind_t, int, int);
static void note_template_header (int);
static tree maybe_fold_nontype_arg (tree);
static void maybe_fold_nontype_args (tree);
static tree convert_nontype_argument (tree, tree);
static tree convert_template_argument (tree, tree, tree,
tsubst_flags_t, int, tree);
@ -136,7 +134,8 @@ static tree get_bindings (tree, tree, tree);
static tree get_bindings_real (tree, tree, tree, int, int, int);
static int template_decl_level (tree);
static int check_cv_quals_for_unify (int, tree, tree);
static tree tsubst_template_arg_vector (tree, tree, tsubst_flags_t);
static tree tsubst_template_arg (tree, tree, tsubst_flags_t, tree);
static tree tsubst_template_args (tree, tree, tsubst_flags_t, tree);
static tree tsubst_template_parms (tree, tree, tsubst_flags_t);
static void regenerate_decl_from_template (tree, tree);
static tree most_specialized (tree, tree, tree);
@ -3641,19 +3640,11 @@ coerce_template_parms (tree parms,
}
else if (i < nargs)
arg = TREE_VEC_ELT (inner_args, i);
/* If no template argument was supplied, look for a default
value. */
else if (TREE_PURPOSE (parm) == NULL_TREE)
{
/* There was no default value. */
my_friendly_assert (!require_all_arguments, 0);
break;
}
else if (TREE_CODE (TREE_VALUE (parm)) == TYPE_DECL)
arg = tsubst (TREE_PURPOSE (parm), new_args, complain, in_decl);
else
arg = tsubst_expr (TREE_PURPOSE (parm), new_args, complain,
in_decl);
/* If no template argument was supplied, look for a default
value. */
arg = tsubst_template_arg (TREE_PURPOSE (parm), new_args,
complain, in_decl);
/* Now, convert the Ith argument, as necessary. */
if (arg == NULL_TREE)
@ -5473,97 +5464,103 @@ list_eq (tree t1, tree t2)
return list_eq (TREE_CHAIN (t1), TREE_CHAIN (t2));
}
/* If arg is a non-type template parameter that does not depend on template
arguments, fold it like we weren't in the body of a template. */
static tree
maybe_fold_nontype_arg (tree arg)
tsubst_template_arg (tree t, tree args, tsubst_flags_t complain, tree in_decl)
{
if (arg && !TYPE_P (arg) && !uses_template_parms (arg))
{
/* Sometimes, one of the args was an expression involving a
template constant parameter, like N - 1. Now that we've
tsubst'd, we might have something like 2 - 1. This will
confuse lookup_template_class, so we do constant folding
here. We have to unset processing_template_decl, to fool
tsubst_copy_and_build() into building an actual tree. */
/* If the TREE_TYPE of ARG is not NULL_TREE, ARG is already
as simple as it's going to get, and trying to reprocess
the trees will break. */
if (!TREE_TYPE (arg))
{
int saved_processing_template_decl = processing_template_decl;
processing_template_decl = 0;
arg = tsubst_copy_and_build (arg,
/*args=*/NULL_TREE,
tf_error,
/*in_decl=*/NULL_TREE,
/*function_p=*/false);
processing_template_decl = saved_processing_template_decl;
}
arg = fold (arg);
}
return arg;
}
/* Apply maybe_fold_nontype_arg on a list or vector of args. */
static void
maybe_fold_nontype_args (tree targs)
{
if (!targs)
/*OK*/;
else if (TREE_CODE (targs) == TREE_LIST)
{
tree chain;
for (chain = targs; chain; chain = TREE_CHAIN (chain))
TREE_VALUE (chain) = maybe_fold_nontype_arg (TREE_VALUE (chain));
}
tree r;
if (!t)
r = t;
else if (TYPE_P (t))
r = tsubst (t, args, complain, in_decl);
else
{
int i;
for (i = 0; i < TREE_VEC_LENGTH (targs); ++i)
TREE_VEC_ELT (targs, i)
= maybe_fold_nontype_arg (TREE_VEC_ELT (targs, i));
r = tsubst_expr (t, args, complain, in_decl);
if (!uses_template_parms (r))
{
/* Sometimes, one of the args was an expression involving a
template constant parameter, like N - 1. Now that we've
tsubst'd, we might have something like 2 - 1. This will
confuse lookup_template_class, so we do constant folding
here. We have to unset processing_template_decl, to fool
tsubst_copy_and_build() into building an actual tree. */
/* If the TREE_TYPE of ARG is not NULL_TREE, ARG is already
as simple as it's going to get, and trying to reprocess
the trees will break. Once tsubst_expr et al DTRT for
non-dependent exprs, this code can go away, as the type
will always be set. */
if (!TREE_TYPE (r))
{
int saved_processing_template_decl = processing_template_decl;
processing_template_decl = 0;
r = tsubst_copy_and_build (r, /*args=*/NULL_TREE,
tf_error, /*in_decl=*/NULL_TREE,
/*function_p=*/false);
processing_template_decl = saved_processing_template_decl;
}
r = fold (r);
}
}
return r;
}
/* Substitute ARGS into the vector of template arguments T. */
/* Substitute ARGS into the vector or list of template arguments T. */
static tree
tsubst_template_arg_vector (tree t, tree args, tsubst_flags_t complain)
tsubst_template_args (tree t, tree args, tsubst_flags_t complain, tree in_decl)
{
int len = TREE_VEC_LENGTH (t), need_new = 0, i;
int is_list = !(t && TREE_CODE (t) == TREE_VEC);
int len = is_list ? list_length (t) : TREE_VEC_LENGTH (t);
int need_new = 0, i;
tree position = t;
tree *elts = alloca (len * sizeof (tree));
memset (elts, 0, len * sizeof (tree));
for (i = 0; i < len; i++)
{
if (TREE_VEC_ELT (t, i) != NULL_TREE
&& TREE_CODE (TREE_VEC_ELT (t, i)) == TREE_VEC)
elts[i] = tsubst_template_arg_vector (TREE_VEC_ELT (t, i),
args, complain);
tree orig_arg;
tree new_arg = NULL_TREE;
if (is_list)
{
orig_arg = TREE_VALUE (position);
position = TREE_CHAIN (position);
}
else
elts[i] = maybe_fold_nontype_arg
(tsubst_expr (TREE_VEC_ELT (t, i), args, complain,
NULL_TREE));
{
orig_arg = TREE_VEC_ELT (t, i);
if (TREE_CODE (orig_arg) == TREE_VEC)
new_arg = tsubst_template_args (orig_arg, args, complain, in_decl);
}
if (!new_arg)
new_arg = tsubst_template_arg (orig_arg, args, complain, in_decl);
if (elts[i] == error_mark_node)
if (new_arg == error_mark_node)
return error_mark_node;
if (elts[i] != TREE_VEC_ELT (t, i))
elts[i] = new_arg;
if (new_arg != orig_arg)
need_new = 1;
}
if (!need_new)
return t;
t = make_tree_vec (len);
for (i = 0; i < len; i++)
TREE_VEC_ELT (t, i) = elts[i];
if (is_list)
{
t = NULL_TREE;
for (i = len; i--;)
t = tree_cons (NULL_TREE, elts[i], t);
}
else
{
t = make_tree_vec (len);
for (i = 0; i < len; i++)
TREE_VEC_ELT (t, i) = elts[i];
}
return t;
}
@ -5597,10 +5594,10 @@ tsubst_template_parms (tree parms, tree args, tsubst_flags_t complain)
tree parm_decl = TREE_VALUE (tuple);
parm_decl = tsubst (parm_decl, args, complain, NULL_TREE);
default_value = tsubst_expr (default_value, args,
complain, NULL_TREE);
tuple = build_tree_list (maybe_fold_nontype_arg (default_value),
parm_decl);
default_value = tsubst_template_arg (default_value, args,
complain, NULL_TREE);
tuple = build_tree_list (default_value, parm_decl);
TREE_VEC_ELT (new_vec, i) = tuple;
}
@ -5662,8 +5659,8 @@ tsubst_aggr_type (tree t,
and supposing that we are instantiating f<int, double>,
then our ARGS will be {int, double}, but, when looking up
S we only want {double}. */
argvec = tsubst_template_arg_vector (TYPE_TI_ARGS (t), args,
complain);
argvec = tsubst_template_args (TYPE_TI_ARGS (t), args,
complain, in_decl);
if (argvec == error_mark_node)
return error_mark_node;
@ -5779,10 +5776,10 @@ tsubst_decl (tree t, tree args, tree type, tsubst_flags_t complain)
: DECL_TI_ARGS (DECL_TEMPLATE_RESULT (t));
tree full_args;
full_args = tsubst_template_arg_vector (tmpl_args, args,
complain);
full_args = tsubst_template_args (tmpl_args, args,
complain, in_decl);
/* tsubst_template_arg_vector doesn't copy the vector if
/* tsubst_template_args doesn't copy the vector if
nothing changed. But, *something* should have
changed. */
my_friendly_assert (full_args != tmpl_args, 0);
@ -5895,10 +5892,9 @@ tsubst_decl (tree t, tree args, tree type, tsubst_flags_t complain)
specialization, and the complete set of arguments used to
specialize R. */
gen_tmpl = most_general_template (DECL_TI_TEMPLATE (t));
argvec
= tsubst_template_arg_vector (DECL_TI_ARGS
(DECL_TEMPLATE_RESULT (gen_tmpl)),
args, complain);
argvec = tsubst_template_args (DECL_TI_ARGS
(DECL_TEMPLATE_RESULT (gen_tmpl)),
args, complain, in_decl);
/* Check to see if we already have this specialization. */
spec = retrieve_specialization (gen_tmpl, argvec);
@ -6477,12 +6473,9 @@ tsubst (tree t, tree args, tsubst_flags_t complain, tree in_decl)
{
tree max, omax = TREE_OPERAND (TYPE_MAX_VALUE (t), 0);
max = tsubst_expr (omax, args, complain, in_decl);
if (max == error_mark_node)
return error_mark_node;
/* See if we can reduce this expression to something simpler. */
max = maybe_fold_nontype_arg (max);
/* The array dimension behaves like a non-type template arg,
in that we want to fold it as much as possible. */
max = tsubst_template_arg (omax, args, complain, in_decl);
if (!processing_template_decl)
max = decl_constant_value (max);
@ -6726,7 +6719,7 @@ tsubst (tree t, tree args, tsubst_flags_t complain, tree in_decl)
}
/* Otherwise, a vector of template arguments. */
return tsubst_template_arg_vector (t, args, complain);
return tsubst_template_args (t, args, complain, in_decl);
case POINTER_TYPE:
case REFERENCE_TYPE:
@ -7157,8 +7150,7 @@ tsubst_qualified_id (tree qualified_id, tree args,
}
if (!BASELINK_P (name) && !DECL_P (expr))
expr = lookup_qualified_name (scope, expr, /*is_type_p=*/0,
(complain & tf_error) != 0);
expr = lookup_qualified_name (scope, expr, /*is_type_p=*/0, false);
if (DECL_P (expr))
check_accessibility_of_qualified_id (expr,
/*object_type=*/NULL_TREE,
@ -7175,7 +7167,9 @@ tsubst_qualified_id (tree qualified_id, tree args,
if (is_template)
expr = lookup_template_function (expr, template_args);
if (TYPE_P (scope))
if (expr == error_mark_node && complain & tf_error)
nested_name_lookup_error (scope, TREE_OPERAND (qualified_id, 1));
else if (TYPE_P (scope))
{
expr = (adjust_result_of_qualified_name_lookup
(expr, scope, current_class_type));
@ -7459,12 +7453,13 @@ tsubst_copy (tree t, tree args, tsubst_flags_t complain, tree in_decl)
case TEMPLATE_ID_EXPR:
{
/* Substituted template arguments */
tree targs = tsubst_copy (TREE_OPERAND (t, 1), args, complain,
in_decl);
tree fn = TREE_OPERAND (t, 0);
tree targs = TREE_OPERAND (t, 1);
maybe_fold_nontype_args (targs);
return lookup_template_function
(tsubst_copy (TREE_OPERAND (t, 0), args, complain, in_decl), targs);
fn = tsubst_copy (fn, args, complain, in_decl);
targs = tsubst_template_args (targs, args, complain, in_decl);
return lookup_template_function (fn, targs);
}
case TREE_LIST:
@ -7595,12 +7590,15 @@ tsubst_expr (tree t, tree args, tsubst_flags_t complain, tree in_decl)
{
tree scope = DECL_INITIAL (decl);
tree name = DECL_NAME (decl);
tree decl;
scope = tsubst_expr (scope, args, complain, in_decl);
do_local_using_decl (lookup_qualified_name (scope,
name,
/*is_type_p=*/0,
/*complain=*/true));
decl = lookup_qualified_name (scope, name,
/*is_type_p=*/0, /*complain=*/false);
if (decl == error_mark_node)
nested_name_lookup_error (scope, name);
else
do_local_using_decl (decl);
}
else
{
@ -8258,18 +8256,15 @@ tsubst_copy_and_build (tree t,
scope is. */
tmpl = TREE_OPERAND (TREE_OPERAND (member, 1), 0);
args = TREE_OPERAND (TREE_OPERAND (member, 1), 1);
member = lookup_qualified_name (TREE_OPERAND (member, 0),
tmpl,
/*is_type=*/0,
/*complain=*/true);
member = lookup_qualified_name (TREE_OPERAND (member, 0), tmpl,
/*is_type=*/0, /*complain=*/false);
if (BASELINK_P (member))
BASELINK_FUNCTIONS (member)
= build_nt (TEMPLATE_ID_EXPR, BASELINK_FUNCTIONS (member),
args);
else
{
error ("`%D' is not a member of `%T'",
tmpl, TREE_TYPE (object));
nested_name_lookup_error (TREE_TYPE (object), tmpl);
return error_mark_node;
}
}

View File

@ -1,3 +1,10 @@
2003-07-25 Nathan Sidwell <nathan@codesourcery.com>
PR 11596
* g++.dg/template/defarg3.C: New test.
* g++.dg/ext/packed2.C: Pack member struct too. Explain why.
2003-07-24 Mark Mitchell <mark@codesourcery.com>
* g++.dg/inherit/access5.C: New test.

View File

@ -1,18 +1,23 @@
// PR c++/10091
// Original synopsis
// Bug: We were dying because in general, B::a doesn't have enough
// alignment for us to take its address. But if the B is C::b, it does
// have enough alignment, and we should be able to determine that.
// This only failed on STRICT_ALIGNMENT targets (i.e. not i686)
// July 2003
// packing of non-pods is now only allowed if the non-pod is itself
// packed. Also only such pods can be reference bound to non-consts
struct A {
int i;
A();
A(const A&);
A& operator=(const A&);
};
} __attribute__ ((packed));
struct B {
A a;
@ -23,8 +28,8 @@ struct C {
int j;
};
void f (const A&);
void g (const C& c)
void f (A&);
void g (C& c)
{
f (c.b.a);
}

View File

@ -0,0 +1,16 @@
// { dg-do compile }
// Copyright (C) 2003 Free Software Foundation, Inc.
// Contributed by Nathan Sidwell 22 Jul 2003 <nathan@codesourcery.com>
// PR c++ 11596
template <int V, bool F = V < 1> struct A { enum { value }; };
template <int V> struct B { enum { value = A<1>::value }; };
int ary[!B<1>::value ? 1 : -1];
template <int V, bool F = V < 1> struct A1 { enum { value = 1}; };
template <int V> struct A1<V,false> { enum { value}; };
template <int V> struct B1 { enum { value = A1<1>::value }; };
int ary1[!B1<1>::value ? 1 : -1];