This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
Re: [C++ RFC / Patch] PR 31260
- From: Paolo Carlini <pcarlini at suse dot de>
- To: Mark Mitchell <mark at codesourcery dot com>
- Cc: gcc-patches at gcc dot gnu dot org
- Date: Sun, 30 Sep 2007 02:03:03 +0200
- Subject: Re: [C++ RFC / Patch] PR 31260
- References: <46F27355.7080705@suse.de> <46F6C4F0.6050305@codesourcery.com>
Hi again Mark, hi all,
It's true that tsubst_expr, etc., are (unfortunately) not idemopotent;
you can't safely do tsubst_expr (tsubst_expr (t)). However, I don't
understand the logic of the comment that you've (re)-added. In
particular, something like:
dynamic_cast <S*> (some expression)
will have type "S*" if "S*" is not a dependent type. But, that doesn't
mean that the expression is "at simple as it can get"; there may still
be substitutions to do in the expression.
I assume the crash is occurring because of the S3<S2> default argument
in your test case? But, how does that relate to the crash that you're
seeing?
as promised some additional analysis. We are dealing with this testcase
template<class T1>
struct S1
{
template<bool T2> struct S2;
template<template<bool> class T3>
struct S3
{
template<typename T4 = S3<S2> >
struct S4;
struct S5
: S4<> { };
};
};
and, as you pointed out above, we are calling fold_non_dependent_expr
from tsubst_template_arg exactly because of the default S3<S2> for T4.
From now on, due to the tsubst_copy_and_build call inside it with
/*args=*/NULL_TREE, we have args always NULL_TREE in all the next
tsubst_* calls. Then, at some point we enter tsubst with this t argument:
<template_type_parm 0x2b6fe534f820 T1 type_0 type_6 VOID
align 8 symtab 0 alias set -1 canonical type 0x2b6fe534f820
index 0 level 1 orig_level 1
chain <type_decl 0x2b6fe534f8f0 T1>>
and therefore we have a crash in the gcc_assert:
...
case TEMPLATE_TYPE_PARM:
case TEMPLATE_TEMPLATE_PARM:
case BOUND_TEMPLATE_TEMPLATE_PARM:
case TEMPLATE_PARM_INDEX:
{
int idx;
int level;
int levels;
tree arg = NULL_TREE;
r = NULL_TREE;
gcc_assert (TREE_VEC_LENGTH (args) > 0);
if (TREE_CODE (t) == TEMPLATE_TYPE_PARM
|| TREE_CODE (t) == TEMPLATE_TEMPLATE_PARM
|| TREE_CODE (t) == BOUND_TEMPLATE_TEMPLATE_PARM)
{
idx = TEMPLATE_TYPE_IDX (t);
level = TEMPLATE_TYPE_LEVEL (t);
}
else
{
idx = TEMPLATE_PARM_IDX (t);
level = TEMPLATE_PARM_LEVEL (t);
}
levels = TMPL_ARGS_DEPTH (args);
...
I tried changing the testcase in various ways avoiding the crash - e.g.,
S4<S3<S2> > as in the audit trail, moving S2 outside of S1 - and I'm
coming to the conclusion that there is nothing seriously wrong in the
way we are dealing with this type of situations except, args can be
NULL_TREE at that assertion exactly because fold_non_dependent_expr
(correctly, as far as I can see) calls tsubst_copy_and_build with a
NULL_TREE for it. In fact, adding an 'if (args == NULL_TREE) return t;'
before the assertion avoids the crash and passes the testsuite. What do
you think? Do you have any additional hints for me?
Thanks in advance,
Paolo.