[C++ PATCH] Rewrite convert_nontype_argument

Jason Merrill jason@redhat.com
Tue Jul 20 22:44:00 GMT 2004


On Fri, 16 Jul 2004 13:36:31 +0200, "Giovanni Bajo" <giovannibajo@libero.it> wrote:

> I split two functions out of it: one is to convert template argument of
> function type (which is used for both member and non-member function), and
> another one is Mark's loop to extract the costant inizializer from a variable
> used in a constant context (which keeps calling decl_constant_value and
> fold_non_dependent_expr until it gets to the true costant). The latter is
> called only once for now, but I believe it could be made public and used
> somewhere else, it looks generically useful.

Agreed.

> The change in mangle.c is just moving a block of code a few lines before.
> write_expression was first lowering PTRMEM_CST into ADDR_EXPR<SCOPE_REF>, and
> then stripping NOPs. But now we generate the sequence NOP_EXPR<PTRMEM_CST> in
> convert_nontype_argument (to do a qualification conversion), so swapping the
> two blocks is enough to fix the problem. This looks correct to me, but I always
> fear any change to mangle.c...

Sounds correct.

The whitespace in your patch is pretty screwy; can you include it as an
attachment in future?

>   static tree
>   convert_nontype_argument (tree type, tree expr)
>   {
>     tree expr_type;
>
> +   /* Detect immediatly string literals as invalid non-type argument.

Typo: "immediately".

> !   /* HACK: Due to double coercion, we can get a
> !      NOP_EXPR<REFERENCE_TYPE>(ADDR_EXPR<POINTER_TYPE> (arg)) here,
> !      which is the tree that we built on the first call (see
> !      below when coercing to reference to object or to reference to
> !      function). We just strip everything and get to the arg.
> !      See g++.old-deja/g++.oliva/template4.C and g++.dg/template/nontype9.C
> !      for examples.  */
> !   if (TREE_CODE (expr) == NOP_EXPR)
> !     {
> !       if ((TYPE_REFOB_P (type) || TYPE_REFFN_P (type)))
> !  {
> !    /* ??? Maybe we could use convert_from_reference here, but we
> !       would need to relax its constraints because the NOP_EXPR
> !       could actually change the type to something more cv-qualified,
> !       and this is not folded by convert_from_reference.  */
> !    tree addr = TREE_OPERAND (expr, 0);
> !    my_friendly_assert (TREE_CODE (expr_type) == REFERENCE_TYPE, 0);
> !    my_friendly_assert (TREE_CODE (addr) == ADDR_EXPR, 0);
> !    my_friendly_assert
> !      (TREE_CODE (TREE_TYPE (addr)) == POINTER_TYPE, 0);
> !    my_friendly_assert (same_type_ignoring_top_level_qualifiers_p
> !          (TREE_TYPE (expr_type),
> !     TREE_TYPE (TREE_TYPE (addr))), 0);
> !
> !    expr = TREE_OPERAND (addr, 0);
> !    expr_type = TREE_TYPE (expr);
> !  }
> !
> !       /* We could also generate a NOP_EXPR(ADDR_EXPR()) when the
> !   parameter is a pointer to object, through decay and
> !   qualification conversion. Let's strip everything.  */

Will this properly reject casts written by the user?

> !   /* [temp.arg.nontype]/5, bullet 1
> !
> !      For a non-type template-parameter of integral or enumeration type,
> !      integral promotions (_conv.prom_) and integral conversions
> !      (_conv.integral_) are applied.  */
> !   if (INTEGRAL_TYPE_P (type))
> !     {
> !       if (!INTEGRAL_TYPE_P (expr_type))
> !  return error_mark_node;
> !
> !       expr = fold_decl_constant_value (expr);
> !       if (!TREE_CONSTANT (expr))
> !  {
> !    error ("`%E' is not a valid template argument for type `%T' "
> !    "because it is a non-constant expression", expr, type);
> !    return NULL_TREE;
> !  }
> !       /* At this point, an implicit conversion does what we want,
> !   because we already know that the expression is of integral
> !   type.  */
> !       expr = cp_convert (type, expr);

It looks like this will still allow conversions between enum types, and
from integers to enums.  Perhaps you mean perform_implicit_conversion?

> !       expr = build_nop (type, build_address (expr));

Replace all uses of build_nop with convert.  Mark, what's the point of
build_nop?

Jason



More information about the Gcc-patches mailing list