[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