[C++ RFC / Patch] PR 31260

Paolo Carlini pcarlini@suse.de
Sun Sep 30 13:21:00 GMT 2007


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.



More information about the Gcc-patches mailing list