+2004-12-08 Nathan Sidwell <nathan@codesourcery.com>
+
+ PR c++/18803
+ * cp-tree.h (REFERENCE_REF_P): New.
+ (CPTI_TYPE_INFO_TYPE): Rename to ...
+ (CPTI_CONST_TYPE_INFO_TYPE): ... here.
+ (CPTI_TYPE_INFO_REF_TYPE): Remove.
+ (type_info_type_node): Rename to ...
+ (const_type_info_type_node): ... here.
+ (type_info_ref_type): Remove.
+ * call.c (build_user_type_conversion): Reformat.
+ (resolve_args): Do not convert_from_reference.
+ (build_object_call): Call convert_from_reference.
+ (prep_operand): Do not convert_from_reference.
+ (build_new_method_call): Likewise.
+ * class.c (build_vfield_ref): Likewise.
+ * cvt.c (convert_to_reference): Likewise.
+ (convert_from_reference): Build INDIRECT_REF here, not with
+ build_indirect_ref.
+ (convert_force): Do not convert_from_reference.
+ (build_expr_type_conversion): Likewise.
+ * decl.c (grok_reference_init): Likewise.
+ * decl2.c (delete_sanity): Likewise.
+ * except.c (initialize_handler_parm): Use POINTER_TYPE_P.
+ * init.c (build_dtor_call): Do not convert_from_reference.
+ * parser.c (cp_parser_template_argument): Unwrap indirected
+ reference. Allow TEMPLATE_PARM_INDEX as an object parm.
+ * pt.c (tsubst_copy_and_build) <case INDIRECT_REF>: Use
+ convert_from_reference, if indicated.
+ <case CALL_EXPR>: Do not convert_from_reference.
+ <case PARM_DECL, VAR_DECL>: Convert_from_reference if needed.
+ (tsubst_initializer_list): Do not convert_from_reference.
+ * rtti.c (init_rtti_processing): Adjust node creation.
+ (throw_bad_typeid): Use const_type_info_type_node.
+ Do not convert_from_reference.
+ (typeid_ok_p): Use const_type_info_type_node.
+ (build_typeid, get_typeid): Always return type_info typed node.
+ (build_dynamic_cast_1): Dont convert_from_reference. Refactor.
+ * semantics.c (finish_stmt_expr_expr): Do not
+ convert_from_reference.
+ (finish_id_expression): Convert_from_reference as appropriate.
+ * typeck.c (decay_conversion): Do not convert_from_reference.
+ (finish_class_member_access_expr): Likewise.
+ (build_indirect_ref): Use POINTER_TYPE_P.
+ (convert_arguments): Do not convert_from_reference.
+ (build_modify_expr): Likewise.
+ (convert_for_initialization): Likewise.
+ * typeck2.c (build_x_arrow): Likewise.
+
2004-12-07 Ziemowit Laski <zlaski@apple.com>
* cp-tree.h (struct lang_type_class): Rename 'objc_protocols'
{
if (cand->second_conv->kind == ck_ambig)
return error_mark_node;
- return convert_from_reference (convert_like (cand->second_conv, expr));
+ expr = convert_like (cand->second_conv, expr);
+ return convert_from_reference (expr);
}
return NULL_TREE;
}
error ("invalid use of void expression");
return error_mark_node;
}
- arg = convert_from_reference (arg);
- TREE_VALUE (t) = arg;
}
return args;
}
else
{
obj = convert_like_with_context (cand->convs[0], obj, cand->fn, -1);
+ obj = convert_from_reference (obj);
result = build_function_call (obj, args);
}
}
{
if (operand)
{
- operand = convert_from_reference (operand);
if (CLASS_TYPE_P (TREE_TYPE (operand))
&& CLASSTYPE_TEMPLATE_INSTANTIATION (TREE_TYPE (operand)))
/* Make sure the template type is instantiated now. */
if (args == error_mark_node)
return error_mark_node;
- if (TREE_CODE (TREE_TYPE (instance)) == REFERENCE_TYPE)
- instance = convert_from_reference (instance);
basetype = TYPE_MAIN_VARIANT (TREE_TYPE (instance));
instance_ptr = build_this (instance);
if (datum == error_mark_node)
return error_mark_node;
- if (TREE_CODE (TREE_TYPE (datum)) == REFERENCE_TYPE)
- datum = convert_from_reference (datum);
-
/* First, convert to the requested type. */
if (!same_type_ignoring_top_level_qualifiers_p (TREE_TYPE (datum), type))
datum = convert_to_base (datum, type, /*check_access=*/false,
EXPR_STMT_STMT_EXPR_RESULT (in EXPR_STMT)
BIND_EXPR_TRY_BLOCK (in BIND_EXPR)
TYPENAME_IS_ENUM_P (in TYPENAME_TYPE)
+ REFERENCE_REF_P (in INDIRECT_EXPR)
1: IDENTIFIER_VIRTUAL_P (in IDENTIFIER_NODE)
TI_PENDING_TEMPLATE_FLAG.
TEMPLATE_PARMS_FOR_INLINE.
CPTI_VTBL_PTR_TYPE,
CPTI_STD,
CPTI_ABI,
- CPTI_TYPE_INFO_TYPE,
+ CPTI_CONST_TYPE_INFO_TYPE,
CPTI_TYPE_INFO_PTR_TYPE,
- CPTI_TYPE_INFO_REF_TYPE,
CPTI_ABORT_FNDECL,
CPTI_GLOBAL_DELETE_FNDECL,
CPTI_AGGR_TAG,
#define vtbl_ptr_type_node cp_global_trees[CPTI_VTBL_PTR_TYPE]
#define std_node cp_global_trees[CPTI_STD]
#define abi_node cp_global_trees[CPTI_ABI]
-#define type_info_type_node cp_global_trees[CPTI_TYPE_INFO_TYPE]
+#define const_type_info_type_node cp_global_trees[CPTI_CONST_TYPE_INFO_TYPE]
#define type_info_ptr_type cp_global_trees[CPTI_TYPE_INFO_PTR_TYPE]
-#define type_info_ref_type cp_global_trees[CPTI_TYPE_INFO_REF_TYPE]
#define abort_fndecl cp_global_trees[CPTI_ABORT_FNDECL]
#define global_delete_fndecl cp_global_trees[CPTI_GLOBAL_DELETE_FNDECL]
#define current_aggr cp_global_trees[CPTI_AGGR_TAG]
(DECL_LANG_SPECIFIC (FUNCTION_DECL_CHECK (NODE)) \
->u.f.u.saved_language_function)
+/* Indicates an indirect_expr is for converting a reference. */
+#define REFERENCE_REF_P(NODE) \
+ TREE_LANG_FLAG_0 (INDIRECT_REF_CHECK (NODE))
+
#define NEW_EXPR_USE_GLOBAL(NODE) \
TREE_LANG_FLAG_0 (NEW_EXPR_CHECK (NODE))
#define DELETE_EXPR_USE_GLOBAL(NODE) \
expr = instantiate_type (type, expr,
(flags & LOOKUP_COMPLAIN)
? tf_error | tf_warning : tf_none);
- else
- expr = convert_from_reference (expr);
if (expr == error_mark_node)
return error_mark_node;
convert_from_reference (tree val)
{
if (TREE_CODE (TREE_TYPE (val)) == REFERENCE_TYPE)
- return build_indirect_ref (val, NULL);
+ {
+ tree t = canonical_type_variant (TREE_TYPE (TREE_TYPE (val)));
+ tree ref = build1 (INDIRECT_REF, t, val);
+
+ /* We *must* set TREE_READONLY when dereferencing a pointer to const,
+ so that we get the proper error message if the result is used
+ to assign to. Also, &* is supposed to be a no-op. */
+ TREE_READONLY (ref) = CP_TYPE_CONST_P (t);
+ TREE_THIS_VOLATILE (ref) = CP_TYPE_VOLATILE_P (t);
+ TREE_SIDE_EFFECTS (ref)
+ = (TREE_THIS_VOLATILE (ref) || TREE_SIDE_EFFECTS (val));
+ REFERENCE_REF_P (ref) = 1;
+ val = ref;
+ }
+
return val;
}
return (fold_if_not_in_template
(convert_to_reference (type, e, CONV_C_CAST, LOOKUP_COMPLAIN,
NULL_TREE)));
- else if (TREE_CODE (TREE_TYPE (e)) == REFERENCE_TYPE)
- e = convert_from_reference (e);
if (code == POINTER_TYPE)
return fold_if_not_in_template (convert_to_pointer_force (type, e));
&& !(desires & WANT_NULL))
warning ("converting NULL to non-pointer type");
- expr = convert_from_reference (expr);
basetype = TREE_TYPE (expr);
if (basetype == error_mark_node)
if (TREE_CODE (init) == TREE_LIST)
init = build_x_compound_expr_from_list (init, "initializer");
- if (TREE_CODE (TREE_TYPE (init)) == REFERENCE_TYPE)
- init = convert_from_reference (init);
-
if (TREE_CODE (TREE_TYPE (type)) != ARRAY_TYPE
&& TREE_CODE (TREE_TYPE (init)) == ARRAY_TYPE)
/* Note: default conversion is only called in very special cases. */
return t;
}
- exp = convert_from_reference (exp);
-
/* An array can't have been allocated by new, so complain. */
if (TREE_CODE (exp) == VAR_DECL
&& TREE_CODE (TREE_TYPE (exp)) == ARRAY_TYPE)
adjusted by value from __cxa_begin_catch. Others are returned by
reference. */
init_type = TREE_TYPE (decl);
- if (! TYPE_PTR_P (init_type)
- && TREE_CODE (init_type) != REFERENCE_TYPE)
+ if (!POINTER_TYPE_P (init_type))
init_type = build_reference_type (init_type);
choose_personality_routine (decl_is_java_type (init_type, 0)
default:
gcc_unreachable ();
}
-
- exp = convert_from_reference (exp);
fn = lookup_fnfields (TREE_TYPE (exp), name, /*protect=*/2);
return build_new_method_call (exp, fn,
/*args=*/NULL_TREE,
if (cp_parser_parse_definitely (parser))
return argument;
}
+
/* If the next token is "&", the argument must be the address of an
object or function with external linkage. */
address_p = cp_lexer_next_token_is (parser->lexer, CPP_AND);
cp_parser_abort_tentative_parse (parser);
else
{
+ if (TREE_CODE (argument) == INDIRECT_REF)
+ {
+ gcc_assert (REFERENCE_REF_P (argument));
+ argument = TREE_OPERAND (argument, 0);
+ }
+
if (qualifying_class)
argument = finish_qualified_id_expr (qualifying_class,
argument,
|| TREE_CODE (argument) == SCOPE_REF))
/* A pointer-to-member. */
;
+ else if (TREE_CODE (argument) == TEMPLATE_PARM_INDEX)
+ ;
else
cp_parser_simulate_error (parser);
cp_parser_error (parser, "invalid non-type template argument");
return error_mark_node;
}
+
/* If the argument wasn't successfully parsed as a type-id followed
by '>>', the argument can only be a constant expression now.
Otherwise, we try parsing the constant-expression tentatively,
}
case INDIRECT_REF:
- return build_x_indirect_ref (RECUR (TREE_OPERAND (t, 0)), "unary *");
+ {
+ tree r = RECUR (TREE_OPERAND (t, 0));
+
+ if (REFERENCE_REF_P (t))
+ {
+ gcc_assert (TREE_CODE (TREE_TYPE (r)) == REFERENCE_TYPE);
+ r = convert_from_reference (r);
+ }
+ else
+ r = build_x_indirect_ref (r, "unary *");
+ return r;
+ }
case NOP_EXPR:
return build_nop
if (DECL_P (function))
mark_used (function);
- function = convert_from_reference (function);
-
if (TREE_CODE (function) == OFFSET_REF)
return build_offset_ref_call_from_tree (function, call_args);
if (TREE_CODE (function) == COMPONENT_REF)
return build_typeid (operand_0);
}
- case PARM_DECL:
- return convert_from_reference (tsubst_copy (t, args, complain, in_decl));
-
case VAR_DECL:
- if (args)
- t = tsubst_copy (t, args, complain, in_decl);
- return convert_from_reference (t);
+ if (!args)
+ return t;
+ /* Fall through */
+
+ case PARM_DECL:
+ {
+ tree r = tsubst_copy (t, args, complain, in_decl);
+
+ if (TREE_CODE (TREE_TYPE (t)) != REFERENCE_TYPE)
+ /* If the original type was a reference, we'll be wrapped in
+ the appropriate INDIRECT_REF. */
+ r = convert_from_reference (r);
+ return r;
+ }
case VA_ARG_EXPR:
return build_x_va_arg (RECUR (TREE_OPERAND (t, 0)),
{
tree decl;
tree init;
- tree val;
decl = tsubst_copy (TREE_PURPOSE (t), argvec, tf_error | tf_warning,
NULL_TREE);
init = tsubst_expr (TREE_VALUE (t), argvec, tf_error | tf_warning,
NULL_TREE);
- if (!init)
- ;
- else if (TREE_CODE (init) == TREE_LIST)
- for (val = init; val; val = TREE_CHAIN (val))
- TREE_VALUE (val) = convert_from_reference (TREE_VALUE (val));
- else if (init != void_type_node)
- init = convert_from_reference (init);
-
in_base_initializer = 0;
if (decl)
void
init_rtti_processing (void)
{
- tree const_type_info_type;
-
+ tree type_info_type;
+
push_namespace (std_identifier);
- type_info_type_node
- = xref_tag (class_type, get_identifier ("type_info"),
- /*tag_scope=*/ts_global, false);
+ type_info_type = xref_tag (class_type, get_identifier ("type_info"),
+ /*tag_scope=*/ts_global, false);
pop_namespace ();
- const_type_info_type = build_qualified_type (type_info_type_node,
- TYPE_QUAL_CONST);
- type_info_ptr_type = build_pointer_type (const_type_info_type);
- type_info_ref_type = build_reference_type (const_type_info_type);
+ const_type_info_type_node
+ = build_qualified_type (type_info_type, TYPE_QUAL_CONST);
+ type_info_ptr_type = build_pointer_type (const_type_info_type_node);
unemitted_tinfo_decls = VEC_alloc (tree, 124);
tree fn = get_identifier ("__cxa_bad_typeid");
if (!get_global_value_if_present (fn, &fn))
{
- tree t = build_qualified_type (type_info_type_node, TYPE_QUAL_CONST);
- t = build_function_type (build_reference_type (t), void_list_node);
+ tree t;
+
+ t = build_reference_type (const_type_info_type_node);
+ t = build_function_type (t, void_list_node);
fn = push_throw_library_fn (fn, t);
}
- return convert_from_reference (build_cxx_call (fn, NULL_TREE));
+ return build_cxx_call (fn, NULL_TREE);
}
\f
/* Return an lvalue expression whose type is "const std::type_info"
return false;
}
- if (!COMPLETE_TYPE_P (type_info_type_node))
+ if (!COMPLETE_TYPE_P (const_type_info_type_node))
{
error ("must #include <typeinfo> before using typeid");
return false;
return error_mark_node;
if (processing_template_decl)
- return build_min (TYPEID_EXPR, type_info_ref_type, exp);
+ return build_min (TYPEID_EXPR, const_type_info_type_node, exp);
if (TREE_CODE (exp) == INDIRECT_REF
&& TREE_CODE (TREE_TYPE (TREE_OPERAND (exp, 0))) == POINTER_TYPE
return error_mark_node;
if (processing_template_decl)
- return build_min (TYPEID_EXPR, type_info_ref_type, type);
+ return build_min (TYPEID_EXPR, const_type_info_type_node, type);
/* If the type of the type-id is a reference type, the result of the
typeid expression refers to a type_info object representing the
case POINTER_TYPE:
if (TREE_CODE (TREE_TYPE (type)) == VOID_TYPE)
break;
+ /* Fall through. */
case REFERENCE_TYPE:
if (! IS_AGGR_TYPE (TREE_TYPE (type)))
{
goto fail;
}
- if (tc == POINTER_TYPE)
- expr = convert_from_reference (expr);
- else if (TREE_CODE (exprtype) != REFERENCE_TYPE)
- {
- /* Apply trivial conversion T -> T& for dereferenced ptrs. */
- exprtype = build_reference_type (exprtype);
- expr = convert_to_reference (exprtype, expr, CONV_IMPLICIT,
- LOOKUP_NORMAL, NULL_TREE);
- }
-
- exprtype = TREE_TYPE (expr);
-
if (tc == POINTER_TYPE)
{
/* If T is a pointer type, v shall be an rvalue of a pointer to
}
else
{
+ /* Apply trivial conversion T -> T& for dereferenced ptrs. */
+ exprtype = build_reference_type (exprtype);
+ expr = convert_to_reference (exprtype, expr, CONV_IMPLICIT,
+ LOOKUP_NORMAL, NULL_TREE);
+
/* T is a reference type, v shall be an lvalue of a complete class
type, and the result is an lvalue of the type referred to by T. */
|| TREE_CODE (type) == FUNCTION_TYPE)
expr = decay_conversion (expr);
- expr = convert_from_reference (expr);
expr = require_complete_type (expr);
type = TREE_TYPE (expr);
if ((TREE_CODE (decl) == CONST_DECL && DECL_TEMPLATE_PARM_P (decl))
|| TREE_CODE (decl) == TEMPLATE_PARM_INDEX)
{
+ tree r;
+
*idk = CP_ID_KIND_NONE;
if (TREE_CODE (decl) == TEMPLATE_PARM_INDEX)
decl = TEMPLATE_PARM_DECL (decl);
+ r = convert_from_reference (DECL_INITIAL (decl));
+
if (integral_constant_expression_p
&& !dependent_type_p (TREE_TYPE (decl))
- && !INTEGRAL_OR_ENUMERATION_TYPE_P (TREE_TYPE (decl)))
+ && !(INTEGRAL_OR_ENUMERATION_TYPE_P (TREE_TYPE (r))))
{
if (!allow_non_integral_constant_expression_p)
error ("template parameter %qD of type %qT is not allowed in "
"integral or enumeration type", decl, TREE_TYPE (decl));
*non_integral_constant_expression_p = true;
}
- return DECL_INITIAL (decl);
+ return r;
}
/* Similarly, we resolve enumeration constants to their
underlying values. */
if (TYPE_P (scope) && dependent_type_p (scope))
return build_nt (SCOPE_REF, scope, id_expression);
else if (TYPE_P (scope) && DECL_P (decl))
- return build2 (SCOPE_REF, TREE_TYPE (decl), scope,
- id_expression);
+ return convert_from_reference
+ (build2 (SCOPE_REF, TREE_TYPE (decl), scope, id_expression));
else
- return decl;
+ return convert_from_reference (decl);
}
/* A TEMPLATE_ID already contains all the information we
need. */
(or an instantiation thereof). */
if (TREE_CODE (decl) == VAR_DECL
|| TREE_CODE (decl) == PARM_DECL)
- return decl;
+ return convert_from_reference (decl);
/* The same is true for FIELD_DECL, but we also need to
make sure that the syntax is correct. */
else if (TREE_CODE (decl) == FIELD_DECL)
}
/* Only certain kinds of names are allowed in constant
- expression. Enumerators and template parameters
- have already been handled above. */
+ expression. Enumerators and template parameters have already
+ been handled above. */
if (integral_constant_expression_p
&& !DECL_INTEGRAL_CONSTANT_VAR_P (decl))
{
if (TREE_CODE (decl) == FIELD_DECL || BASELINK_P (decl))
*qualifying_class = scope;
- else if (!processing_template_decl)
- decl = convert_from_reference (decl);
- else if (TYPE_P (scope))
- decl = build2 (SCOPE_REF, TREE_TYPE (decl), scope, decl);
+ else
+ {
+ tree r = convert_from_reference (decl);
+
+ if (processing_template_decl
+ && TYPE_P (scope))
+ r = build2 (SCOPE_REF, TREE_TYPE (r), scope, decl);
+ decl = r;
+ }
}
else if (TREE_CODE (decl) == FIELD_DECL)
decl = finish_non_static_data_member (decl, current_class_ref,
perform_or_defer_access_check (TYPE_BINFO (path), decl);
}
- if (! processing_template_decl)
- decl = convert_from_reference (decl);
+ decl = convert_from_reference (decl);
}
/* Resolve references to variables of anonymous unions
type = TREE_TYPE (exp);
code = TREE_CODE (type);
- if (code == REFERENCE_TYPE)
- {
- exp = convert_from_reference (exp);
- type = TREE_TYPE (exp);
- code = TREE_CODE (type);
- }
-
if (type == error_mark_node)
return error_mark_node;
object = build_non_dependent_expr (object);
}
- if (TREE_CODE (object_type) == REFERENCE_TYPE)
- {
- object = convert_from_reference (object);
- object_type = TREE_TYPE (object);
- }
-
/* [expr.ref]
The type of the first expression shall be "class object" (of a
? ptr : decay_conversion (ptr));
type = TREE_TYPE (pointer);
- if (TYPE_PTR_P (type) || TREE_CODE (type) == REFERENCE_TYPE)
+ if (POINTER_TYPE_P (type))
{
/* [expr.unary.op]
}
else
{
- if (TREE_CODE (TREE_TYPE (val)) == REFERENCE_TYPE)
- val = convert_from_reference (val);
-
if (fndecl && DECL_BUILT_IN (fndecl)
&& DECL_FUNCTION_CODE (fndecl) == BUILT_IN_CONSTANT_P)
/* Don't do ellipsis conversion for __built_in_constant_p
}
else
{
- if (TREE_CODE (lhstype) == REFERENCE_TYPE)
- {
- lhs = convert_from_reference (lhs);
- olhstype = lhstype = TREE_TYPE (lhs);
- }
lhs = require_complete_type (lhs);
if (lhs == error_mark_node)
return error_mark_node;
|| (TREE_CODE (rhs) == TREE_LIST && TREE_VALUE (rhs) == error_mark_node))
return error_mark_node;
- if (TREE_CODE (TREE_TYPE (rhs)) == REFERENCE_TYPE)
- rhs = convert_from_reference (rhs);
-
if ((TREE_CODE (TREE_TYPE (rhs)) == ARRAY_TYPE
&& TREE_CODE (type) != ARRAY_TYPE
&& (TREE_CODE (type) != REFERENCE_TYPE
expr = build_non_dependent_expr (expr);
}
- if (TREE_CODE (type) == REFERENCE_TYPE)
- {
- expr = convert_from_reference (expr);
- type = TREE_TYPE (expr);
- }
-
if (IS_AGGR_TYPE (type))
{
while ((expr = build_new_op (COMPONENT_REF, LOOKUP_NORMAL, expr,
+2004-12-08 Nathan Sidwell <nathan@codesourcery.com>
+
+ PR c++/18803
+ * g++.dg/template/operator5.C: New.
+
2004-12-08 Hans-Peter Nilsson <hp@bitrange.com>
PR c/18867
--- /dev/null
+// Copyright (C) 2004 Free Software Foundation, Inc.
+// Contributed by Nathan Sidwell 7 Dec 2004 <nathan@codesourcery.com>
+
+// PR 18803: reject legal
+// Origin: Wolfgang Bangerth <bangerth@dealii.org>
+
+struct A {
+ int operator() ();
+};
+
+template <int> void foo () {
+ A &a = *new A();
+ const int i = a();
+}