+1999-05-20 Mark Mitchell <mark@codesourcery.com>
+
+ * cp-tree.h (make_ptrmem_cst): New function.
+ * expr.c (cplus_expand_constant): Split out from ...
+ (cplus_expand_expr): Here. Use cplus_expand_constant.
+ (init_cplus_expand): Set lang_expand_constant.
+ * pt.c (convert_nontype_argument): Use make_ptrmem_cst.
+ * tree.c (make_ptrmem_cst): Define.
+ * typeck.c (unary_complex_lvalue): Use make_ptrmem_cst.
+ * typeck2.c (initializer_constant_valid_p): Use make_ptrmem_cst.
+
1999-05-19 Mark Mitchell <mark@codesourcery.com>
* pt.c (build_template_decl): Copy DECL_NONCONVERTING_P.
extern int is_dummy_object PROTO((tree));
extern tree search_tree PROTO((tree, tree (*)(tree)));
extern int cp_valid_lang_attribute PROTO((tree, tree, tree, tree));
+extern tree make_ptrmem_cst PROTO((tree, tree));
#define scratchalloc expralloc
#define scratch_tree_cons expr_tree_cons
static rtx cplus_expand_expr PROTO((tree, rtx, enum machine_mode,
enum expand_modifier));
+/* Hook used by output_constant to expand language-specific
+ constants. */
+
+static tree
+cplus_expand_constant (cst)
+ tree cst;
+{
+ switch (TREE_CODE (cst))
+ {
+ case PTRMEM_CST:
+ {
+ tree type = TREE_TYPE (cst);
+ tree member;
+ tree offset;
+
+ /* Find the member. */
+ member = PTRMEM_CST_MEMBER (cst);
+
+ if (TREE_CODE (member) == FIELD_DECL)
+ {
+ /* Find the offset for the field. */
+ offset = convert (sizetype,
+ size_binop (EASY_DIV_EXPR,
+ DECL_FIELD_BITPOS (member),
+ size_int (BITS_PER_UNIT)));
+
+ /* We offset all pointer to data members by 1 so that we
+ can distinguish between a null pointer to data member
+ and the first data member of a structure. */
+ offset = size_binop (PLUS_EXPR, offset, size_int (1));
+
+ cst = cp_convert (type, offset);
+ }
+ else
+ {
+ tree delta;
+ tree idx;
+ tree pfn;
+ tree delta2;
+
+ expand_ptrmemfunc_cst (cst, &delta, &idx, &pfn, &delta2);
+
+ cst = build_ptrmemfunc1 (type, delta, idx,
+ pfn, delta2);
+ }
+ }
+ break;
+
+ default:
+ /* There's nothing to do. */
+ break;
+ }
+
+ return cst;
+}
+
/* Hook used by expand_expr to expand language-specific tree codes. */
static rtx
}
case PTRMEM_CST:
- {
- tree member;
- tree offset;
-
- /* Find the member. */
- member = PTRMEM_CST_MEMBER (exp);
-
- if (TREE_CODE (member) == FIELD_DECL)
- {
- /* Find the offset for the field. */
- offset = convert (sizetype,
- size_binop (EASY_DIV_EXPR,
- DECL_FIELD_BITPOS (member),
- size_int (BITS_PER_UNIT)));
-
- /* We offset all pointer to data members by 1 so that we
- can distinguish between a null pointer to data member
- and the first data member of a structure. */
- offset = size_binop (PLUS_EXPR, offset, size_int (1));
-
- return expand_expr (cp_convert (type, offset), target, tmode,
- modifier);
- }
- else
- {
- tree delta;
- tree idx;
- tree pfn;
- tree delta2;
-
- expand_ptrmemfunc_cst (exp, &delta, &idx, &pfn, &delta2);
-
- return expand_expr (build_ptrmemfunc1 (type, delta, idx,
- pfn, delta2),
- target, tmode, modifier);
- }
- }
+ return expand_expr (cplus_expand_constant (exp),
+ target, tmode, modifier);
case OFFSET_REF:
{
init_cplus_expand ()
{
lang_expand_expr = cplus_expand_expr;
+ lang_expand_constant = cplus_expand_constant;
}
/* If DECL had its rtl moved from where callers expect it
applied. */
e = perform_qualification_conversions (type, expr);
if (TREE_CODE (e) == NOP_EXPR)
- {
- /* The call to perform_qualification_conversions will
- insert a NOP_EXPR over EXPR to do express
- conversion, if necessary. But, that will confuse
- us if we use this (converted) template parameter to
- instantiate another template; then the thing will
- not look like a valid template argument. So, just
- make a new constant, of the appropriate type. */
- e = make_node (PTRMEM_CST);
- TREE_TYPE (e) = type;
- PTRMEM_CST_MEMBER (e) = PTRMEM_CST_MEMBER (expr);
- }
+ /* The call to perform_qualification_conversions will
+ insert a NOP_EXPR over EXPR to do express conversion,
+ if necessary. But, that will confuse us if we use
+ this (converted) template parameter to instantiate
+ another template; then the thing will not look like a
+ valid template argument. So, just make a new
+ constant, of the appropriate type. */
+ e = make_ptrmem_cst (type, PTRMEM_CST_MEMBER (expr));
return e;
}
else if (TREE_CODE (type_pointed_to) == FUNCTION_TYPE)
return 0;
}
+
+/* Return a new PTRMEM_CST of the indicated TYPE. The MEMBER is the
+ thing pointed to by the constant. */
+
+tree
+make_ptrmem_cst (type, member)
+ tree type;
+ tree member;
+{
+ tree ptrmem_cst = make_node (PTRMEM_CST);
+ /* If would seem a great convenience if make_node would set
+ TREE_CONSTANT for things of class `c', but it does not. */
+ TREE_CONSTANT (ptrmem_cst) = 1;
+ TREE_TYPE (ptrmem_cst) = type;
+ PTRMEM_CST_MEMBER (ptrmem_cst) = member;
+ return ptrmem_cst;
+}
+
type = build_offset_type (DECL_FIELD_CONTEXT (t), TREE_TYPE (t));
type = build_pointer_type (type);
- t = make_node (PTRMEM_CST);
- TREE_TYPE (t) = type;
- PTRMEM_CST_MEMBER (t) = TREE_OPERAND (arg, 1);
+ t = make_ptrmem_cst (type, TREE_OPERAND (arg, 1));
return t;
}
}
fn = TREE_OPERAND (pfn, 0);
my_friendly_assert (TREE_CODE (fn) == FUNCTION_DECL, 0);
- npfn = make_node (PTRMEM_CST);
- TREE_TYPE (npfn) = build_ptrmemfunc_type (type);
- PTRMEM_CST_MEMBER (npfn) = fn;
- return npfn;
+ return make_ptrmem_cst (build_ptrmemfunc_type (type), fn);
}
/* Return the DELTA, IDX, PFN, and DELTA2 values for the PTRMEM_CST
case REAL_CST:
case STRING_CST:
case COMPLEX_CST:
+ case PTRMEM_CST:
return null_pointer_node;
case ADDR_EXPR: