cp-tree.h (build_scoped_method_call): Remove.

* cp-tree.h (build_scoped_method_call): Remove.
	(lookup_qualified_name): Remove parameter.
	(tsubst_copy_and_build): Declare.
	(finish_qualified_object_call_expr): Remove.
	(check_accessibility_of_qualified_id): New function.
	(finish_qualified_id_expr): Likewise.
	(non_reference): Likewise.
	(build_expr_from-tree): Remove.
	* call.c (non_reference): Remove.
	(build_scoped_method_call): Likewise.
	(build_method_call): Use error_operand_p.  Assert that we are not
	processing a template.
	(standard_conversion): Use non_reference.
	* class.c (build_vtbl_entry_ref): Likewise.
	(build_vtbl_ref_1): Likewise.
	* cvt.c (build_expr_type_conversion): Use non_reference.
	* decl.c (lookup_qualified_name): Remove flags parameter.
	(grok_op_properties): Use non_reference.
	* decl2.c (grok_array_decl): Likewise.
	(build_expr_from_tree): Remove.
	(build_offset_ref_call_from_tree): Update comment.
	* error.c (parm_to_string): Call reinit_global_formatting_buffer.
	* except.c (prepare_eh_types): Use non_reference.
	(can_convert_eh): Likewise.
	* init.c (build_dtor_call): Avoid using build_method_call.
	* mangle.c (write_template_param): Remove misleading comment.
	* method.c (locate_copy): Use non_reference.
	* parser.c (cp_parser_scope_through_which_access_occurs): Remove.
	(cp_parser_primary_expression): Do not create SCOPE_REFs is
	non-dependent contexts.
	(cp_parser_postfix_expression): Use finish_qualified_id_expr.
	(cp_parser_direct_declarator): Use tsubst_copy_and_build, not
	build_expr_from_tree.
	(cp_parser_lookup_name): Adjust call to lookup_qualified_name.
	Use check_accessibility_of_qualified_id.
	* pt.c (maybe_fold_nontype_arg): Use tsubst_copy_and_build, not
	build_expr_from_tree.
	(tsubst_baselink): New function.
	(tsubst_qualified_id): Likewise.
	(tsubst_copy): Use them.  Remove support for METHOD_CALL_EXPR.
	(tsubst_expr): Adjust call to lookup_qualified_name.
	(tsubst_copy_and_build): Handle SCOPE_REFs specially.  Adjust
	handling of CALL_EXPRs.
	(value_dependent_expression_p): Use INTEGRAL_OR_ENUMERATION_TYPE_P.
	* rtti.c (get_tinfo_decl_dynamic): Use non_reference.
	* search.c (check_final_overrider): Likewise.
	* semantics.c (check_accessibility_of_qualified_id): New function.
	(finish_qualified_object_call_expr): Remove.
	* typeck.c (target_type): Use non_reference.
	(cxx_sizeof_or_alignof_type): Likewise.
	(dubious_conversion_warnings): Likewise.
	(convert_for_initialization): Likewise.
	(non_reference): New function.

From-SVN: r69063
This commit is contained in:
Mark Mitchell 2003-07-08 01:38:44 +00:00 committed by Mark Mitchell
parent 923c4cf299
commit ee76b9314b
18 changed files with 526 additions and 931 deletions

View File

@ -1,3 +1,59 @@
2003-07-07 Mark Mitchell <mark@codesourcery.com>
* cp-tree.h (build_scoped_method_call): Remove.
(lookup_qualified_name): Remove parameter.
(tsubst_copy_and_build): Declare.
(finish_qualified_object_call_expr): Remove.
(check_accessibility_of_qualified_id): New function.
(finish_qualified_id_expr): Likewise.
(non_reference): Likewise.
(build_expr_from-tree): Remove.
* call.c (non_reference): Remove.
(build_scoped_method_call): Likewise.
(build_method_call): Use error_operand_p. Assert that we are not
processing a template.
(standard_conversion): Use non_reference.
* class.c (build_vtbl_entry_ref): Likewise.
(build_vtbl_ref_1): Likewise.
* cvt.c (build_expr_type_conversion): Use non_reference.
* decl.c (lookup_qualified_name): Remove flags parameter.
(grok_op_properties): Use non_reference.
* decl2.c (grok_array_decl): Likewise.
(build_expr_from_tree): Remove.
(build_offset_ref_call_from_tree): Update comment.
* error.c (parm_to_string): Call reinit_global_formatting_buffer.
* except.c (prepare_eh_types): Use non_reference.
(can_convert_eh): Likewise.
* init.c (build_dtor_call): Avoid using build_method_call.
* mangle.c (write_template_param): Remove misleading comment.
* method.c (locate_copy): Use non_reference.
* parser.c (cp_parser_scope_through_which_access_occurs): Remove.
(cp_parser_primary_expression): Do not create SCOPE_REFs is
non-dependent contexts.
(cp_parser_postfix_expression): Use finish_qualified_id_expr.
(cp_parser_direct_declarator): Use tsubst_copy_and_build, not
build_expr_from_tree.
(cp_parser_lookup_name): Adjust call to lookup_qualified_name.
Use check_accessibility_of_qualified_id.
* pt.c (maybe_fold_nontype_arg): Use tsubst_copy_and_build, not
build_expr_from_tree.
(tsubst_baselink): New function.
(tsubst_qualified_id): Likewise.
(tsubst_copy): Use them. Remove support for METHOD_CALL_EXPR.
(tsubst_expr): Adjust call to lookup_qualified_name.
(tsubst_copy_and_build): Handle SCOPE_REFs specially. Adjust
handling of CALL_EXPRs.
(value_dependent_expression_p): Use INTEGRAL_OR_ENUMERATION_TYPE_P.
* rtti.c (get_tinfo_decl_dynamic): Use non_reference.
* search.c (check_final_overrider): Likewise.
* semantics.c (check_accessibility_of_qualified_id): New function.
(finish_qualified_object_call_expr): Remove.
* typeck.c (target_type): Use non_reference.
(cxx_sizeof_or_alignof_type): Likewise.
(dubious_conversion_warnings): Likewise.
(convert_for_initialization): Likewise.
(non_reference): New function.
2003-07-07 Kaveh R. Ghazi <ghazi@caip.rutgers.edu>
* decl.c (print_binding_level, print_other_binding_stack,

View File

@ -87,7 +87,6 @@ static struct z_candidate *add_function_candidate
static tree implicit_conversion (tree, tree, tree, int);
static tree standard_conversion (tree, tree, tree);
static tree reference_binding (tree, tree, tree, int);
static tree non_reference (tree);
static tree build_conv (enum tree_code, tree, tree);
static bool is_subseq (tree, tree);
static tree maybe_handle_ref_bind (tree *);
@ -205,106 +204,6 @@ check_dtor_name (tree basetype, tree name)
return false;
}
/* Build a method call of the form `EXP->SCOPES::NAME (PARMS)'.
This is how virtual function calls are avoided. */
tree
build_scoped_method_call (tree exp, tree basetype, tree name, tree parms)
{
/* Because this syntactic form does not allow
a pointer to a base class to be `stolen',
we need not protect the derived->base conversion
that happens here.
@@ But we do have to check access privileges later. */
tree binfo, decl;
tree type = TREE_TYPE (exp);
if (type == error_mark_node
|| basetype == error_mark_node)
return error_mark_node;
if (processing_template_decl)
{
name = build_min_nt (SCOPE_REF, basetype, name);
return build_min_nt (METHOD_CALL_EXPR, name, exp, parms, NULL_TREE);
}
if (TREE_CODE (type) == REFERENCE_TYPE)
type = TREE_TYPE (type);
if (TREE_CODE (basetype) == TREE_VEC)
{
binfo = basetype;
basetype = BINFO_TYPE (binfo);
}
else
binfo = NULL_TREE;
/* Check the destructor call syntax. */
if (TREE_CODE (name) == BIT_NOT_EXPR)
{
/* We can get here if someone writes their destructor call like
`obj.NS::~T()'; this isn't really a scoped method call, so hand
it off. */
if (TREE_CODE (basetype) == NAMESPACE_DECL)
return build_method_call (exp, name, parms, NULL_TREE, LOOKUP_NORMAL);
if (! check_dtor_name (basetype, name))
error ("qualified type `%T' does not match destructor name `~%T'",
basetype, TREE_OPERAND (name, 0));
/* Destructors can be "called" for simple types; see 5.2.4 and 12.4 Note
that explicit ~int is caught in the parser; this deals with typedefs
and template parms. */
if (! IS_AGGR_TYPE (basetype))
{
if (TYPE_MAIN_VARIANT (type) != TYPE_MAIN_VARIANT (basetype))
error ("type of `%E' does not match destructor type `%T' (type was `%T')",
exp, basetype, type);
return convert_to_void (exp, /*implicit=*/NULL);
}
}
if (TREE_CODE (basetype) == NAMESPACE_DECL)
{
error ("`%D' is a namespace", basetype);
return error_mark_node;
}
if (! is_aggr_type (basetype, 1))
return error_mark_node;
if (! IS_AGGR_TYPE (type))
{
error ("base object `%E' of scoped method call is of non-aggregate type `%T'",
exp, type);
return error_mark_node;
}
decl = build_scoped_ref (exp, basetype, &binfo);
if (binfo)
{
/* Call to a destructor. */
if (TREE_CODE (name) == BIT_NOT_EXPR)
{
if (! TYPE_HAS_DESTRUCTOR (TREE_TYPE (decl)))
return convert_to_void (exp, /*implicit=*/NULL);
return build_delete (TREE_TYPE (decl), decl,
sfk_complete_destructor,
LOOKUP_NORMAL|LOOKUP_NONVIRTUAL|LOOKUP_DESTRUCTOR,
0);
}
/* Call to a method. */
return build_method_call (decl, name, parms, binfo,
LOOKUP_NORMAL|LOOKUP_NONVIRTUAL);
}
return error_mark_node;
}
/* We want the address of a function or method. We avoid creating a
pointer-to-member function. */
@ -460,14 +359,12 @@ build_method_call (tree instance, tree name, tree parms,
n_build_method_call++;
#endif
if (instance == error_mark_node
if (error_operand_p (instance)
|| name == error_mark_node
|| parms == error_mark_node
|| (instance && TREE_TYPE (instance) == error_mark_node))
|| parms == error_mark_node)
return error_mark_node;
if (processing_template_decl)
return build_min_nt (METHOD_CALL_EXPR, name, instance, parms, NULL_TREE);
my_friendly_assert (!processing_template_decl, 20030707);
if (TREE_CODE (TREE_TYPE (instance)) == REFERENCE_TYPE)
instance = convert_from_reference (instance);
@ -518,7 +415,7 @@ build_method_call (tree instance, tree name, tree parms,
else
fn = lookup_member (object_type, name, /*protect=*/2, /*want_type=*/false);
if (fn && TREE_CODE (fn) == TREE_LIST && !BASELINK_P (fn))
if (fn && TREE_CODE (fn) == TREE_LIST)
{
error ("request for member `%D' is ambiguous", name);
print_candidates (fn);
@ -669,17 +566,6 @@ build_conv (enum tree_code code, tree type, tree from)
return t;
}
/* If T is a REFERENCE_TYPE return the type to which T refers.
Otherwise, return T itself. */
static tree
non_reference (tree t)
{
if (TREE_CODE (t) == REFERENCE_TYPE)
t = TREE_TYPE (t);
return t;
}
tree
strip_top_quals (tree t)
{
@ -699,8 +585,7 @@ standard_conversion (tree to, tree from, tree expr)
tree conv;
bool fromref = false;
if (TREE_CODE (to) == REFERENCE_TYPE)
to = TREE_TYPE (to);
to = non_reference (to);
if (TREE_CODE (from) == REFERENCE_TYPE)
{
fromref = true;

View File

@ -401,9 +401,7 @@ build_vtable_entry_ref (tree array_ref, tree instance, tree idx)
{
tree i, i2, vtable, first_fn, basetype;
basetype = TREE_TYPE (instance);
if (TREE_CODE (basetype) == REFERENCE_TYPE)
basetype = TREE_TYPE (basetype);
basetype = non_reference (TREE_TYPE (instance));
vtable = get_vtbl_decl_for_binfo (TYPE_BINFO (basetype));
first_fn = TYPE_BINFO_VTABLE (basetype);
@ -439,9 +437,7 @@ build_vtbl_ref_1 (tree instance, tree idx)
int cdtorp = 0;
tree fixed_type = fixed_type_or_null (instance, NULL, &cdtorp);
tree basetype = TREE_TYPE (instance);
if (TREE_CODE (basetype) == REFERENCE_TYPE)
basetype = TREE_TYPE (basetype);
tree basetype = non_reference (TREE_TYPE (instance));
if (fixed_type && !cdtorp)
{

View File

@ -3493,7 +3493,6 @@ extern GTY(()) operator_name_info_t assignment_operator_name_info
extern bool check_dtor_name (tree, tree);
extern tree build_vfield_ref (tree, tree);
extern tree build_scoped_method_call (tree, tree, tree, tree);
extern tree build_conditional_expr (tree, tree, tree);
extern tree build_addr_func (tree);
extern tree build_call (tree, tree);
@ -3660,7 +3659,7 @@ extern tree make_typename_type (tree, tree, tsubst_flags_t);
extern tree make_unbound_class_template (tree, tree, tsubst_flags_t);
extern tree lookup_name_nonclass (tree);
extern tree lookup_function_nonclass (tree, tree);
extern tree lookup_qualified_name (tree, tree, bool, int);
extern tree lookup_qualified_name (tree, tree, bool);
extern tree lookup_name (tree, int);
extern tree lookup_name_current_level (tree);
extern tree lookup_type_current_level (tree);
@ -3775,7 +3774,6 @@ extern void import_export_decl (tree);
extern void import_export_tinfo (tree, tree, bool);
extern void finish_file (void);
extern tree build_cleanup (tree);
extern tree build_expr_from_tree (tree);
extern tree build_offset_ref_call_from_tree (tree, tree);
extern tree build_call_from_tree (tree, tree, bool);
extern void set_decl_namespace (tree, tree, bool);
@ -3967,6 +3965,7 @@ extern tree most_specialized_instantiation (tree);
extern void print_candidates (tree);
extern int instantiate_pending_templates (void);
extern tree tsubst_default_argument (tree, tree, tree);
extern tree tsubst_copy_and_build (tree, tree, tsubst_flags_t, tree);
extern tree most_general_template (tree);
extern tree get_mostly_instantiated_function_type (tree);
extern int problematic_instantiation_changed (void);
@ -4114,7 +4113,6 @@ extern tree finish_call_expr (tree, tree, bool);
extern tree finish_increment_expr (tree, enum tree_code);
extern tree finish_this_expr (void);
extern tree finish_object_call_expr (tree, tree, tree);
extern tree finish_qualified_object_call_expr (tree, tree, tree);
extern tree finish_pseudo_destructor_expr (tree, tree, tree);
extern tree finish_unary_op_expr (enum tree_code, tree);
extern tree finish_compound_literal (tree, tree);
@ -4149,6 +4147,8 @@ extern tree begin_global_stmt_expr (void);
extern tree finish_global_stmt_expr (tree);
extern tree check_template_template_default_arg (tree);
extern void expand_or_defer_fn (tree);
extern void check_accessibility_of_qualified_id (tree, tree, tree);
extern tree finish_qualified_id_expr (tree, tree, bool, bool);
/* in tree.c */
extern void lang_check_failed (const char *, int,
@ -4299,6 +4299,7 @@ extern tree check_return_expr (tree);
extern tree build_ptrmemfunc_access_expr (tree, tree);
extern tree build_address (tree);
extern tree build_nop (tree, tree);
extern tree non_reference (tree);
/* in typeck2.c */
extern void require_complete_eh_spec_types (tree, tree);

View File

@ -1077,9 +1077,7 @@ build_expr_type_conversion (int desires, tree expr, bool complain)
if (winner && winner == cand)
continue;
candidate = TREE_TYPE (TREE_TYPE (cand));
if (TREE_CODE (candidate) == REFERENCE_TYPE)
candidate = TREE_TYPE (candidate);
candidate = non_reference (TREE_TYPE (TREE_TYPE (cand)));
switch (TREE_CODE (candidate))
{
@ -1117,9 +1115,7 @@ build_expr_type_conversion (int desires, tree expr, bool complain)
if (winner)
{
tree type = TREE_TYPE (TREE_TYPE (winner));
if (TREE_CODE (type) == REFERENCE_TYPE)
type = TREE_TYPE (type);
tree type = non_reference (TREE_TYPE (TREE_TYPE (winner)));
return build_user_type_conversion (type, expr, LOOKUP_NORMAL);
}

View File

@ -5770,8 +5770,10 @@ qualify_lookup (tree val, int flags)
declaration found. */
tree
lookup_qualified_name (tree scope, tree name, bool is_type_p, int flags)
lookup_qualified_name (tree scope, tree name, bool is_type_p)
{
int flags = 0;
if (TREE_CODE (scope) == NAMESPACE_DECL)
{
cxx_binding binding;
@ -5780,12 +5782,15 @@ lookup_qualified_name (tree scope, tree name, bool is_type_p, int flags)
flags |= LOOKUP_COMPLAIN;
if (is_type_p)
flags |= LOOKUP_PREFER_TYPES;
if (!qualified_lookup_using_namespace (name, scope, &binding, flags))
if (!qualified_lookup_using_namespace (name, scope, &binding,
flags))
return NULL_TREE;
return select_decl (&binding, flags);
}
else
else if (is_aggr_type (scope, /*or_else=*/1))
return lookup_member (scope, name, 0, is_type_p);
else
return error_mark_node;
}
/* Check to see whether or not DECL is a variable that would have been
@ -12320,9 +12325,7 @@ grok_op_properties (tree decl, int friendp)
if (p)
for (; TREE_CODE (TREE_VALUE (p)) != VOID_TYPE ; p = TREE_CHAIN (p))
{
tree arg = TREE_VALUE (p);
if (TREE_CODE (arg) == REFERENCE_TYPE)
arg = TREE_TYPE (arg);
tree arg = non_reference (TREE_VALUE (p));
/* This lets bad template code slip through. */
if (IS_AGGR_TYPE (arg)

View File

@ -409,8 +409,7 @@ grok_array_decl (tree array_expr, tree index_exp)
my_friendly_assert (type, 20030626);
if (TREE_CODE (type) == REFERENCE_TYPE)
type = TREE_TYPE (type);
type = non_reference (type);
/* If they have an `operator[]', use that. */
if (IS_AGGR_TYPE (type) || IS_AGGR_TYPE (TREE_TYPE (index_exp)))
@ -2938,415 +2937,6 @@ finish_file ()
input_location = locus;
}
/* T is the parse tree for an expression. Return the expression after
performing semantic analysis. */
tree
build_expr_from_tree (tree t)
{
if (t == NULL_TREE || t == error_mark_node)
return t;
switch (TREE_CODE (t))
{
case IDENTIFIER_NODE:
return do_identifier (t, NULL_TREE);
case LOOKUP_EXPR:
if (LOOKUP_EXPR_GLOBAL (t))
{
tree token = TREE_OPERAND (t, 0);
return do_scoped_id (token, IDENTIFIER_GLOBAL_VALUE (token));
}
else
{
t = do_identifier (TREE_OPERAND (t, 0), NULL_TREE);
if (TREE_CODE (t) == ALIAS_DECL)
t = DECL_INITIAL (t);
return t;
}
case TEMPLATE_ID_EXPR:
{
tree template;
tree args;
tree object;
template = build_expr_from_tree (TREE_OPERAND (t, 0));
args = build_expr_from_tree (TREE_OPERAND (t, 1));
if (TREE_CODE (template) == COMPONENT_REF)
{
object = TREE_OPERAND (template, 0);
template = TREE_OPERAND (template, 1);
}
else
object = NULL_TREE;
template = lookup_template_function (template, args);
if (object)
return build (COMPONENT_REF, TREE_TYPE (template),
object, template);
else
return template;
}
case INDIRECT_REF:
return build_x_indirect_ref
(build_expr_from_tree (TREE_OPERAND (t, 0)), "unary *");
case CAST_EXPR:
return build_functional_cast
(TREE_TYPE (t), build_expr_from_tree (TREE_OPERAND (t, 0)));
case REINTERPRET_CAST_EXPR:
return build_reinterpret_cast
(TREE_TYPE (t), build_expr_from_tree (TREE_OPERAND (t, 0)));
case CONST_CAST_EXPR:
return build_const_cast
(TREE_TYPE (t), build_expr_from_tree (TREE_OPERAND (t, 0)));
case DYNAMIC_CAST_EXPR:
return build_dynamic_cast
(TREE_TYPE (t), build_expr_from_tree (TREE_OPERAND (t, 0)));
case STATIC_CAST_EXPR:
return build_static_cast
(TREE_TYPE (t), build_expr_from_tree (TREE_OPERAND (t, 0)));
case PREDECREMENT_EXPR:
case PREINCREMENT_EXPR:
case POSTDECREMENT_EXPR:
case POSTINCREMENT_EXPR:
case NEGATE_EXPR:
case BIT_NOT_EXPR:
case ABS_EXPR:
case TRUTH_NOT_EXPR:
case ADDR_EXPR:
case CONVERT_EXPR: /* Unary + */
case REALPART_EXPR:
case IMAGPART_EXPR:
if (TREE_TYPE (t))
return t;
return build_x_unary_op (TREE_CODE (t),
build_expr_from_tree (TREE_OPERAND (t, 0)));
case PLUS_EXPR:
case MINUS_EXPR:
case MULT_EXPR:
case TRUNC_DIV_EXPR:
case CEIL_DIV_EXPR:
case FLOOR_DIV_EXPR:
case ROUND_DIV_EXPR:
case EXACT_DIV_EXPR:
case BIT_AND_EXPR:
case BIT_ANDTC_EXPR:
case BIT_IOR_EXPR:
case BIT_XOR_EXPR:
case TRUNC_MOD_EXPR:
case FLOOR_MOD_EXPR:
case TRUTH_ANDIF_EXPR:
case TRUTH_ORIF_EXPR:
case TRUTH_AND_EXPR:
case TRUTH_OR_EXPR:
case RSHIFT_EXPR:
case LSHIFT_EXPR:
case RROTATE_EXPR:
case LROTATE_EXPR:
case EQ_EXPR:
case NE_EXPR:
case MAX_EXPR:
case MIN_EXPR:
case LE_EXPR:
case GE_EXPR:
case LT_EXPR:
case GT_EXPR:
case MEMBER_REF:
return build_x_binary_op
(TREE_CODE (t),
build_expr_from_tree (TREE_OPERAND (t, 0)),
build_expr_from_tree (TREE_OPERAND (t, 1)));
case DOTSTAR_EXPR:
return build_m_component_ref
(build_expr_from_tree (TREE_OPERAND (t, 0)),
build_expr_from_tree (TREE_OPERAND (t, 1)));
case SCOPE_REF:
return build_offset_ref (TREE_OPERAND (t, 0), TREE_OPERAND (t, 1));
case ARRAY_REF:
if (TREE_OPERAND (t, 0) == NULL_TREE)
/* new-type-id */
return build_nt (ARRAY_REF, NULL_TREE,
build_expr_from_tree (TREE_OPERAND (t, 1)));
return grok_array_decl (build_expr_from_tree (TREE_OPERAND (t, 0)),
build_expr_from_tree (TREE_OPERAND (t, 1)));
case SIZEOF_EXPR:
case ALIGNOF_EXPR:
{
tree r = build_expr_from_tree (TREE_OPERAND (t, 0));
if (!TYPE_P (r))
return TREE_CODE (t) == SIZEOF_EXPR ? expr_sizeof (r) : c_alignof_expr (r);
else
return cxx_sizeof_or_alignof_type (r, TREE_CODE (t), true);
}
case MODOP_EXPR:
return build_x_modify_expr
(build_expr_from_tree (TREE_OPERAND (t, 0)),
TREE_CODE (TREE_OPERAND (t, 1)),
build_expr_from_tree (TREE_OPERAND (t, 2)));
case ARROW_EXPR:
return build_x_arrow
(build_expr_from_tree (TREE_OPERAND (t, 0)));
case NEW_EXPR:
return build_new
(build_expr_from_tree (TREE_OPERAND (t, 0)),
build_expr_from_tree (TREE_OPERAND (t, 1)),
build_expr_from_tree (TREE_OPERAND (t, 2)),
NEW_EXPR_USE_GLOBAL (t));
case DELETE_EXPR:
return delete_sanity
(build_expr_from_tree (TREE_OPERAND (t, 0)),
build_expr_from_tree (TREE_OPERAND (t, 1)),
DELETE_EXPR_USE_VEC (t), DELETE_EXPR_USE_GLOBAL (t));
case COMPOUND_EXPR:
if (TREE_OPERAND (t, 1) == NULL_TREE)
return build_x_compound_expr
(build_expr_from_tree (TREE_OPERAND (t, 0)));
else
abort ();
case METHOD_CALL_EXPR:
if (TREE_CODE (TREE_OPERAND (t, 0)) == SCOPE_REF)
{
tree ref = TREE_OPERAND (t, 0);
tree name = TREE_OPERAND (ref, 1);
if (TREE_CODE (name) == TEMPLATE_ID_EXPR)
name = build_nt (TEMPLATE_ID_EXPR,
TREE_OPERAND (name, 0),
build_expr_from_tree (TREE_OPERAND (name, 1)));
return build_scoped_method_call
(build_expr_from_tree (TREE_OPERAND (t, 1)),
build_expr_from_tree (TREE_OPERAND (ref, 0)),
name,
build_expr_from_tree (TREE_OPERAND (t, 2)));
}
else
{
tree fn = TREE_OPERAND (t, 0);
/* We can get a TEMPLATE_ID_EXPR here on code like:
x->f<2>();
so we must resolve that. However, we can also get things
like a BIT_NOT_EXPR here, when referring to a destructor,
and things like that are not correctly resolved by
build_expr_from_tree. So, just use build_expr_from_tree
when we really need it. */
if (TREE_CODE (fn) == TEMPLATE_ID_EXPR)
fn = lookup_template_function
(TREE_OPERAND (fn, 0),
build_expr_from_tree (TREE_OPERAND (fn, 1)));
return build_method_call
(build_expr_from_tree (TREE_OPERAND (t, 1)),
fn,
build_expr_from_tree (TREE_OPERAND (t, 2)),
NULL_TREE, LOOKUP_NORMAL);
}
case CALL_EXPR:
if (TREE_CODE (TREE_OPERAND (t, 0)) == SCOPE_REF)
{
tree ref = TREE_OPERAND (t, 0);
tree name = TREE_OPERAND (ref, 1);
tree fn, scope, args;
if (TREE_CODE (name) == TEMPLATE_ID_EXPR)
name = build_nt (TEMPLATE_ID_EXPR,
TREE_OPERAND (name, 0),
build_expr_from_tree (TREE_OPERAND (name, 1)));
scope = build_expr_from_tree (TREE_OPERAND (ref, 0));
args = build_expr_from_tree (TREE_OPERAND (t, 1));
fn = resolve_scoped_fn_name (scope, name);
return build_call_from_tree (fn, args, 1);
}
else
{
tree name = TREE_OPERAND (t, 0);
tree id;
tree args = build_expr_from_tree (TREE_OPERAND (t, 1));
if (args != NULL_TREE && TREE_CODE (name) == LOOKUP_EXPR
&& !LOOKUP_EXPR_GLOBAL (name)
&& TREE_CODE ((id = TREE_OPERAND (name, 0))) == IDENTIFIER_NODE
&& (!current_class_type
|| !lookup_member (current_class_type, id, 0, false)))
{
/* Do Koenig lookup if there are no class members. */
name = do_identifier (id, args);
}
else if (TREE_CODE (name) == TEMPLATE_ID_EXPR
|| ! really_overloaded_fn (name))
name = build_expr_from_tree (name);
if (TREE_CODE (name) == OFFSET_REF)
return build_offset_ref_call_from_tree (name, args);
if (TREE_CODE (name) == COMPONENT_REF)
return finish_object_call_expr (TREE_OPERAND (name, 1),
TREE_OPERAND (name, 0),
args);
name = convert_from_reference (name);
return build_call_from_tree (name, args,
/*disallow_virtual=*/false);
}
case COND_EXPR:
return build_x_conditional_expr
(build_expr_from_tree (TREE_OPERAND (t, 0)),
build_expr_from_tree (TREE_OPERAND (t, 1)),
build_expr_from_tree (TREE_OPERAND (t, 2)));
case PSEUDO_DTOR_EXPR:
return (finish_pseudo_destructor_expr
(build_expr_from_tree (TREE_OPERAND (t, 0)),
build_expr_from_tree (TREE_OPERAND (t, 1)),
build_expr_from_tree (TREE_OPERAND (t, 2))));
case TREE_LIST:
{
tree purpose, value, chain;
if (t == void_list_node)
return t;
purpose = TREE_PURPOSE (t);
if (purpose)
purpose = build_expr_from_tree (purpose);
value = TREE_VALUE (t);
if (value)
value = build_expr_from_tree (value);
chain = TREE_CHAIN (t);
if (chain && chain != void_type_node)
chain = build_expr_from_tree (chain);
return tree_cons (purpose, value, chain);
}
case COMPONENT_REF:
{
tree object = build_expr_from_tree (TREE_OPERAND (t, 0));
tree member = TREE_OPERAND (t, 1);
if (!CLASS_TYPE_P (TREE_TYPE (object)))
{
if (TREE_CODE (member) == BIT_NOT_EXPR)
return finish_pseudo_destructor_expr (object,
NULL_TREE,
TREE_TYPE (object));
else if (TREE_CODE (member) == SCOPE_REF
&& (TREE_CODE (TREE_OPERAND (member, 1)) == BIT_NOT_EXPR))
return finish_pseudo_destructor_expr (object,
TREE_OPERAND (t, 0),
TREE_TYPE (object));
}
else if (TREE_CODE (member) == SCOPE_REF
&& TREE_CODE (TREE_OPERAND (member, 1)) == TEMPLATE_ID_EXPR)
{
tree tmpl;
tree args;
/* Lookup the template functions now that we know what the
scope is. */
tmpl = TREE_OPERAND (TREE_OPERAND (member, 1), 0);
args = TREE_OPERAND (TREE_OPERAND (member, 1), 1);
member = lookup_qualified_name (TREE_OPERAND (member, 0),
tmpl,
/*is_type=*/0,
/*flags=*/0);
if (BASELINK_P (member))
BASELINK_FUNCTIONS (member)
= build_nt (TEMPLATE_ID_EXPR, BASELINK_FUNCTIONS (member),
args);
else
{
error ("`%D' is not a member of `%T'",
tmpl, TREE_TYPE (object));
return error_mark_node;
}
}
return finish_class_member_access_expr (object, member);
}
case THROW_EXPR:
return build_throw (build_expr_from_tree (TREE_OPERAND (t, 0)));
case CONSTRUCTOR:
{
tree r;
tree elts;
tree type = TREE_TYPE (t);
bool purpose_p;
/* digest_init will do the wrong thing if we let it. */
if (type && TYPE_PTRMEMFUNC_P (type))
return t;
r = NULL_TREE;
/* We do not want to process the purpose of aggregate
initializers as they are identifier nodes which will be
looked up by digest_init. */
purpose_p = !(type && IS_AGGR_TYPE (type));
for (elts = CONSTRUCTOR_ELTS (t); elts; elts = TREE_CHAIN (elts))
{
tree purpose = TREE_PURPOSE (elts);
tree value = TREE_VALUE (elts);
if (purpose && purpose_p)
purpose = build_expr_from_tree (purpose);
value = build_expr_from_tree (value);
r = tree_cons (purpose, value, r);
}
r = build_constructor (NULL_TREE, nreverse (r));
TREE_HAS_CONSTRUCTOR (r) = TREE_HAS_CONSTRUCTOR (t);
if (type)
return digest_init (type, r, 0);
return r;
}
case TYPEID_EXPR:
if (TYPE_P (TREE_OPERAND (t, 0)))
return get_typeid (TREE_OPERAND (t, 0));
return build_typeid (build_expr_from_tree (TREE_OPERAND (t, 0)));
case PARM_DECL:
case VAR_DECL:
return convert_from_reference (t);
case VA_ARG_EXPR:
return build_va_arg (build_expr_from_tree (TREE_OPERAND (t, 0)),
TREE_TYPE (t));
default:
return t;
}
}
/* FN is an OFFSET_REF indicating the function to call in parse-tree
form; it has not yet been semantically analyzed. ARGS are the
arguments to the function. They have already been semantically
@ -3359,22 +2949,12 @@ build_offset_ref_call_from_tree (tree fn, tree args)
my_friendly_assert (TREE_CODE (fn) == OFFSET_REF, 20020725);
/* A qualified name corresponding to a non-static member
function or a pointer-to-member is represented as an
OFFSET_REF.
For both of these function calls, FN will be an OFFSET_REF.
struct A { void f(); };
void A::f() { (A::f) (); }
/* A qualified name corresponding to a bound pointer-to-member is
represented as an OFFSET_REF:
struct B { void g(); };
void (B::*p)();
void B::g() { (this->*p)(); } */
/* This code is not really correct (for example, it does not
handle the case that `A::f' is overloaded), but it is
historically how we have handled this situation. */
if (TREE_CODE (TREE_OPERAND (fn, 1)) == FIELD_DECL)
/* This case should now be handled elsewhere. */
abort ();

View File

@ -2230,6 +2230,8 @@ language_to_string (enum languages c)
static const char *
parm_to_string (int p)
{
reinit_global_formatting_buffer ();
if (p < 0)
output_add_string (scratch_buffer, "'this'");
else

View File

@ -107,8 +107,7 @@ prepare_eh_type (tree type)
return error_mark_node;
/* peel back references, so they match. */
if (TREE_CODE (type) == REFERENCE_TYPE)
type = TREE_TYPE (type);
type = non_reference (type);
/* Peel off cv qualifiers. */
type = TYPE_MAIN_VARIANT (type);
@ -872,10 +871,8 @@ nothrow_libfn_p (tree fn)
static int
can_convert_eh (tree to, tree from)
{
if (TREE_CODE (to) == REFERENCE_TYPE)
to = TREE_TYPE (to);
if (TREE_CODE (from) == REFERENCE_TYPE)
from = TREE_TYPE (from);
to = non_reference (to);
from = non_reference (from);
if (TREE_CODE (to) == POINTER_TYPE && TREE_CODE (from) == POINTER_TYPE)
{

View File

@ -2915,7 +2915,7 @@ static tree
build_dtor_call (tree exp, special_function_kind dtor_kind, int flags)
{
tree name;
tree fn;
switch (dtor_kind)
{
case sfk_complete_destructor:
@ -2933,8 +2933,13 @@ build_dtor_call (tree exp, special_function_kind dtor_kind, int flags)
default:
abort ();
}
return build_method_call (exp, name, NULL_TREE,
TYPE_BINFO (TREE_TYPE (exp)), flags);
exp = convert_from_reference (exp);
fn = lookup_fnfields (TREE_TYPE (exp), name, /*protect=*/2);
return build_new_method_call (exp, fn,
/*args=*/NULL_TREE,
/*conversion_path=*/NULL_TREE,
flags);
}
/* Generate a call to a destructor. TYPE is the type to cast ADDR to.

View File

@ -2197,14 +2197,7 @@ write_pointer_to_member_type (const tree type)
TEMPLATE_TEMPLATE_PARM, BOUND_TEMPLATE_TEMPLATE_PARM or a
TEMPLATE_PARM_INDEX.
<template-param> ::= T </parameter/ number> _
If we are internally mangling then we distinguish level and, for
non-type parms, type too. The mangling appends
</level/ number> _ </non-type type/ type> _
This is used by mangle_conv_op_name_for_type. */
<template-param> ::= T </parameter/ number> _ */
static void
write_template_param (const tree parm)

View File

@ -1000,9 +1000,7 @@ locate_copy (tree type, void *client_)
parms = TREE_CHAIN (parms);
if (!parms)
continue;
src_type = TREE_VALUE (parms);
if (TREE_CODE (src_type) == REFERENCE_TYPE)
src_type = TREE_TYPE (src_type);
src_type = non_reference (TREE_VALUE (parms));
if (!same_type_ignoring_top_level_qualifiers_p (src_type, type))
continue;
if (!sufficient_parms_p (TREE_CHAIN (parms)))

View File

@ -1717,8 +1717,6 @@ static bool cp_parser_is_string_literal
(cp_token *);
static bool cp_parser_is_keyword
(cp_token *, enum rid);
static tree cp_parser_scope_through_which_access_occurs
(tree, tree, tree);
/* Returns nonzero if we are parsing tentatively. */
@ -1744,62 +1742,6 @@ cp_parser_is_keyword (cp_token* token, enum rid keyword)
return token->keyword == keyword;
}
/* Returns the scope through which DECL is being accessed, or
NULL_TREE if DECL is not a member. If OBJECT_TYPE is non-NULL, we
have just seen `x->' or `x.' and OBJECT_TYPE is the type of `*x',
or `x', respectively. If the DECL was named as `A::B' then
NESTED_NAME_SPECIFIER is `A'. */
static tree
cp_parser_scope_through_which_access_occurs (tree decl,
tree object_type,
tree nested_name_specifier)
{
tree scope;
tree qualifying_type = NULL_TREE;
/* Determine the SCOPE of DECL. */
scope = context_for_name_lookup (decl);
/* If the SCOPE is not a type, then DECL is not a member. */
if (!TYPE_P (scope))
return NULL_TREE;
/* Figure out the type through which DECL is being accessed. */
if (object_type
/* OBJECT_TYPE might not be a class type; consider:
class A { typedef int I; };
I *p;
p->A::I::~I();
In this case, we will have "A::I" as the DECL, but "I" as the
OBJECT_TYPE. */
&& CLASS_TYPE_P (object_type)
&& DERIVED_FROM_P (scope, object_type))
/* If we are processing a `->' or `.' expression, use the type of the
left-hand side. */
qualifying_type = object_type;
else if (nested_name_specifier)
{
/* If the reference is to a non-static member of the
current class, treat it as if it were referenced through
`this'. */
if (DECL_NONSTATIC_MEMBER_P (decl)
&& current_class_ptr
&& DERIVED_FROM_P (scope, current_class_type))
qualifying_type = current_class_type;
/* Otherwise, use the type indicated by the
nested-name-specifier. */
else
qualifying_type = nested_name_specifier;
}
else
/* Otherwise, the name must be from the current class or one of
its bases. */
qualifying_type = currently_open_derived_class (scope);
return qualifying_type;
}
/* Issue the indicated error MESSAGE. */
static void
@ -2600,7 +2542,7 @@ cp_parser_primary_expression (cp_parser *parser,
else
{
bool dependent_p;
/* If the declaration was explicitly qualified indicate
that. The semantics of `A::f(3)' are different than
`f(3)' if `f' is virtual. */
@ -2710,7 +2652,8 @@ cp_parser_primary_expression (cp_parser *parser,
we will resolve the name at instantiation time. */
if (dependent_p)
{
/* Create a SCOPE_REF for qualified names. */
/* Create a SCOPE_REF for qualified names, if the
scope is dependent. */
if (parser->scope)
{
if (TYPE_P (parser->scope))
@ -2720,9 +2663,13 @@ cp_parser_primary_expression (cp_parser *parser,
might be constant when things are instantiated. */
if (parser->constant_expression_p)
parser->non_constant_expression_p = true;
return build_nt (SCOPE_REF,
parser->scope,
id_expression);
if (TYPE_P (parser->scope)
&& dependent_type_p (parser->scope))
return build_nt (SCOPE_REF,
parser->scope,
id_expression);
else
return decl;
}
/* A TEMPLATE_ID already contains all the information
we need. */
@ -3523,7 +3470,6 @@ cp_parser_postfix_expression (cp_parser *parser, bool address_p)
form a pointer-to-member. In that case, QUALIFYING_CLASS is the
class used to qualify the member. */
tree qualifying_class = NULL_TREE;
bool done;
/* Peek at the next token. */
token = cp_lexer_peek_token (parser->lexer);
@ -3752,68 +3698,28 @@ cp_parser_postfix_expression (cp_parser *parser, bool address_p)
break;
}
/* Peek at the next token. */
token = cp_lexer_peek_token (parser->lexer);
done = (token->type != CPP_OPEN_SQUARE
&& token->type != CPP_OPEN_PAREN
&& token->type != CPP_DOT
&& token->type != CPP_DEREF
&& token->type != CPP_PLUS_PLUS
&& token->type != CPP_MINUS_MINUS);
/* If the postfix expression is complete, finish up. */
if (address_p && qualifying_class && done)
{
if (TREE_CODE (postfix_expression) == SCOPE_REF)
postfix_expression = TREE_OPERAND (postfix_expression, 1);
postfix_expression
= build_offset_ref (qualifying_class, postfix_expression);
return postfix_expression;
}
/* Otherwise, if we were avoiding committing until we knew
whether or not we had a pointer-to-member, we now know that
the expression is an ordinary reference to a qualified name. */
/* If we were avoiding committing to the processing of a
qualified-id until we knew whether or not we had a
pointer-to-member, we now know. */
if (qualifying_class)
{
if (TREE_CODE (postfix_expression) == FIELD_DECL)
postfix_expression
= finish_non_static_data_member (postfix_expression,
qualifying_class);
else if (BASELINK_P (postfix_expression)
&& !processing_template_decl)
{
tree fn;
tree fns;
bool done;
/* See if any of the functions are non-static members. */
fns = BASELINK_FUNCTIONS (postfix_expression);
if (TREE_CODE (fns) == TEMPLATE_ID_EXPR)
fns = TREE_OPERAND (fns, 0);
for (fn = fns; fn; fn = OVL_NEXT (fn))
if (DECL_NONSTATIC_MEMBER_FUNCTION_P (fn))
break;
/* If so, the expression may be relative to the current
class. */
if (fn && current_class_type
&& DERIVED_FROM_P (qualifying_class, current_class_type))
postfix_expression
= (build_class_member_access_expr
(maybe_dummy_object (qualifying_class, NULL),
postfix_expression,
BASELINK_ACCESS_BINFO (postfix_expression),
/*preserve_reference=*/false));
else if (done)
{
/* The expression is a qualified name whose address is not
being taken. */
postfix_expression = build_offset_ref (qualifying_class,
postfix_expression);
if (TREE_CODE (postfix_expression) == OFFSET_REF)
postfix_expression = resolve_offset_ref (postfix_expression);
return postfix_expression;
}
}
/* Peek at the next token. */
token = cp_lexer_peek_token (parser->lexer);
done = (token->type != CPP_OPEN_SQUARE
&& token->type != CPP_OPEN_PAREN
&& token->type != CPP_DOT
&& token->type != CPP_DEREF
&& token->type != CPP_PLUS_PLUS
&& token->type != CPP_MINUS_MINUS);
postfix_expression = finish_qualified_id_expr (qualifying_class,
postfix_expression,
done,
address_p);
if (done)
return postfix_expression;
}
/* Remember that there was a reference to this entity. */
@ -3915,7 +3821,7 @@ cp_parser_postfix_expression (cp_parser *parser, bool address_p)
if (!arg)
{
postfix_expression
= lookup_arg_dependent(identifier, functions, args);
= lookup_arg_dependent (identifier, functions, args);
if (!postfix_expression)
{
/* The unqualified name could not be resolved. */
@ -4014,8 +3920,7 @@ cp_parser_postfix_expression (cp_parser *parser, bool address_p)
may have reference type even when the standard says
it does not. Therefore, we have to manually obtain
the underlying type here. */
if (TREE_CODE (scope) == REFERENCE_TYPE)
scope = TREE_TYPE (scope);
scope = non_reference (scope);
/* If the SCOPE is an OFFSET_TYPE, then we grab the
type of the field. We get an OFFSET_TYPE for
something like:
@ -10031,7 +9936,10 @@ cp_parser_direct_declarator (cp_parser* parser,
saved_processing_template_decl = processing_template_decl;
processing_template_decl = 0;
bounds = build_expr_from_tree (bounds);
bounds = tsubst_copy_and_build (bounds,
/*args=*/NULL_TREE,
tf_error,
/*in_decl=*/NULL_TREE);
processing_template_decl = saved_processing_template_decl;
}
}
@ -13209,8 +13117,7 @@ cp_parser_lookup_name (cp_parser *parser, tree name,
may be instantiated during name lookup. In that case,
errors may be issued. Even if we rollback the current
tentative parse, those errors are valid. */
decl = lookup_qualified_name (parser->scope, name, is_type,
/*flags=*/0);
decl = lookup_qualified_name (parser->scope, name, is_type);
if (dependent_p)
pop_scope (parser->scope);
}
@ -13282,18 +13189,7 @@ cp_parser_lookup_name (cp_parser *parser, tree name,
During an explicit instantiation, access is not checked at all,
as per [temp.explicit]. */
if (DECL_P (decl))
{
tree qualifying_type;
/* Figure out the type through which DECL is being
accessed. */
qualifying_type
= cp_parser_scope_through_which_access_occurs (decl,
object_type,
parser->scope);
if (qualifying_type)
perform_or_defer_access_check (TYPE_BINFO (qualifying_type), decl);
}
check_accessibility_of_qualified_id (decl, object_type, parser->scope);
return decl;
}

View File

@ -171,7 +171,6 @@ static bool dependent_template_id_p (tree, tree);
static tree tsubst (tree, tree, tsubst_flags_t, tree);
static tree tsubst_expr (tree, tree, tsubst_flags_t, tree);
static tree tsubst_copy (tree, tree, tsubst_flags_t, tree);
static tree tsubst_copy_and_build (tree, tree, tsubst_flags_t, tree);
/* Make the current scope suitable for access checking when we are
processing T. T can be FUNCTION_DECL for instantiated function
@ -5527,9 +5526,8 @@ maybe_fold_nontype_arg (tree arg)
template constant parameter, like N - 1. Now that we've
tsubst'd, we might have something like 2 - 1. This will
confuse lookup_template_class, so we do constant folding
here. We have to unset processing_template_decl, to
fool build_expr_from_tree() into building an actual
tree. */
here. We have to unset processing_template_decl, to fool
tsubst_copy_and_build() into building an actual tree. */
/* If the TREE_TYPE of ARG is not NULL_TREE, ARG is already
as simple as it's going to get, and trying to reprocess
@ -5538,7 +5536,10 @@ maybe_fold_nontype_arg (tree arg)
{
int saved_processing_template_decl = processing_template_decl;
processing_template_decl = 0;
arg = build_expr_from_tree (arg);
arg = tsubst_copy_and_build (arg,
/*args=*/NULL_TREE,
tf_error,
/*in_decl=*/NULL_TREE);
processing_template_decl = saved_processing_template_decl;
}
@ -7076,6 +7077,118 @@ tsubst (tree t, tree args, tsubst_flags_t complain, tree in_decl)
}
}
/* Like tsubst_expr for a BASELINK. OBJECT_TYPE, if non-NULL, is the
type of the expression on the left-hand side of the "." or "->"
operator. */
static tree
tsubst_baselink (tree baselink, tree object_type,
tree args, tsubst_flags_t complain, tree in_decl)
{
tree name;
tree qualifying_scope;
tree fns;
tree template_args = 0;
bool template_id_p = false;
/* A baselink indicates a function from a base class. The
BASELINK_ACCESS_BINFO and BASELINK_BINFO are going to have
non-dependent types; otherwise, the lookup could not have
succeeded. However, they may indicate bases of the template
class, rather than the instantiated class.
In addition, lookups that were not ambiguous before may be
ambiguous now. Therefore, we perform the lookup again. */
qualifying_scope = BINFO_TYPE (BASELINK_ACCESS_BINFO (baselink));
fns = BASELINK_FUNCTIONS (baselink);
if (TREE_CODE (fns) == TEMPLATE_ID_EXPR)
{
template_id_p = true;
template_args = TREE_OPERAND (fns, 1);
fns = TREE_OPERAND (fns, 0);
template_args = tsubst_copy (template_args, args,
complain, in_decl);
maybe_fold_nontype_args (template_args);
}
name = DECL_NAME (get_first_fn (fns));
baselink = lookup_fnfields (qualifying_scope, name, /*protect=*/1);
if (BASELINK_P (baselink) && template_id_p)
BASELINK_FUNCTIONS (baselink)
= build_nt (TEMPLATE_ID_EXPR,
BASELINK_FUNCTIONS (baselink),
template_args);
if (!object_type)
object_type = current_class_type;
return adjust_result_of_qualified_name_lookup (baselink,
qualifying_scope,
object_type);
}
/* Like tsubst_expr for a SCOPE_REF, given by QUALIFIED_ID. DONE is
true if the qualified-id will be a postfix-expression in-and-of
itself; false if more of the postfix-expression follows the
QUALIFIED_ID. ADDRESS_P is true if the qualified-id is the operand
of "&". */
static tree
tsubst_qualified_id (tree qualified_id, tree args,
tsubst_flags_t complain, tree in_decl,
bool done, bool address_p)
{
tree expr;
tree scope;
tree name;
bool is_template;
tree template_args;
my_friendly_assert (TREE_CODE (qualified_id) == SCOPE_REF, 20030706);
/* Look up the qualified name. */
scope = TREE_OPERAND (qualified_id, 0);
scope = tsubst (scope, args, complain, in_decl);
/* Figure out what name to look up. */
name = TREE_OPERAND (qualified_id, 1);
if (TREE_CODE (name) == TEMPLATE_ID_EXPR)
{
is_template = true;
template_args = tsubst_copy_and_build (TREE_OPERAND (name, 1),
args, complain, in_decl);
name = TREE_OPERAND (name, 0);
}
else
{
is_template = false;
template_args = NULL_TREE;
}
expr = tsubst_copy (name, args, complain, in_decl);
if (!BASELINK_P (name))
{
expr = lookup_qualified_name (scope, expr, /*is_type_p=*/0);
if (DECL_P (expr))
check_accessibility_of_qualified_id (expr,
/*object_type=*/NULL_TREE,
scope);
}
/* Remember that there was a reference to this entity. */
if (DECL_P (expr))
mark_used (expr);
if (is_template)
lookup_template_function (expr, template_args);
if (TYPE_P (scope))
{
expr = (adjust_result_of_qualified_name_lookup
(expr, scope, current_class_type));
expr = finish_qualified_id_expr (scope, expr, done, address_p);
}
return expr;
}
/* Like tsubst, but deals with expressions. This function just replaces
template parms; to finish processing the resultant expression, use
tsubst_expr. */
@ -7157,43 +7270,7 @@ tsubst_copy (tree t, tree args, tsubst_flags_t complain, tree in_decl)
return t;
case BASELINK:
{
tree name;
tree qualifying_scope;
tree fns;
tree template_args = 0;
bool template_id_p = false;
/* A baselink indicates a function from a base class. The
BASELINK_ACCESS_BINFO and BASELINK_BINFO are going to have
non-dependent types; otherwise, the lookup could not have
succeeded. However, they may indicate bases of the template
class, rather than the instantiated class.
In addition, lookups that were not ambiguous before may be
ambiguous now. Therefore, we perform the lookup again. */
qualifying_scope = BINFO_TYPE (BASELINK_ACCESS_BINFO (t));
fns = BASELINK_FUNCTIONS (t);
if (TREE_CODE (fns) == TEMPLATE_ID_EXPR)
{
template_id_p = true;
template_args = TREE_OPERAND (fns, 1);
fns = TREE_OPERAND (fns, 0);
template_args = tsubst_copy (template_args, args,
complain, in_decl);
maybe_fold_nontype_args (template_args);
}
name = DECL_NAME (get_first_fn (fns));
t = lookup_fnfields (qualifying_scope, name, /*protect=*/1);
if (BASELINK_P (t) && template_id_p)
BASELINK_FUNCTIONS (t)
= build_nt (TEMPLATE_ID_EXPR,
BASELINK_FUNCTIONS (t),
template_args);
return adjust_result_of_qualified_name_lookup (t,
qualifying_scope,
current_class_type);
}
return tsubst_baselink (t, current_class_type, args, complain, in_decl);
case TEMPLATE_DECL:
if (DECL_TEMPLATE_TEMPLATE_PARM_P (t))
@ -7296,8 +7373,13 @@ tsubst_copy (tree t, tree args, tsubst_flags_t complain, tree in_decl)
name = build1 (BIT_NOT_EXPR, NULL_TREE, name);
name = build_nt (SCOPE_REF, base, name);
}
else if (TREE_CODE (name) == BASELINK)
name = tsubst_baselink (name,
non_reference (TREE_TYPE (object)),
args, complain,
in_decl);
else
name = tsubst_copy (TREE_OPERAND (t, 1), args, complain, in_decl);
name = tsubst_copy (name, args, complain, in_decl);
return build_nt (COMPONENT_REF, object, name);
}
@ -7352,14 +7434,6 @@ tsubst_copy (tree t, tree args, tsubst_flags_t complain, tree in_decl)
in_decl),
NULL_TREE);
case METHOD_CALL_EXPR:
return build_nt
(code,
tsubst_copy (TREE_OPERAND (t, 0), args, complain, in_decl),
tsubst_copy (TREE_OPERAND (t, 1), args, complain, in_decl),
tsubst_copy (TREE_OPERAND (t, 2), args, complain, in_decl),
NULL_TREE);
case STMT_EXPR:
/* This processing should really occur in tsubst_expr. However,
tsubst_expr does not recurse into expressions, since it
@ -7547,8 +7621,7 @@ tsubst_expr (tree t, tree args, tsubst_flags_t complain, tree in_decl)
scope = tsubst_expr (scope, args, complain, in_decl);
do_local_using_decl (lookup_qualified_name (scope,
name,
/*is_type_p=*/0,
/*flags=*/0));
/*is_type_p=*/0));
}
else
{
@ -7814,12 +7887,14 @@ tsubst_expr (tree t, tree args, tsubst_flags_t complain, tree in_decl)
/* Like tsubst but deals with expressions and performs semantic
analysis. */
static tree
tree
tsubst_copy_and_build (tree t,
tree args,
tsubst_flags_t complain,
tree in_decl)
{
tree op1;
if (t == NULL_TREE || t == error_mark_node)
return t;
@ -7859,9 +7934,11 @@ tsubst_copy_and_build (tree t,
{
tree object;
tree template
= tsubst_copy (TREE_OPERAND (t, 0), args, complain, in_decl);
= tsubst_copy_and_build (TREE_OPERAND (t, 0), args, complain,
in_decl);
tree targs
= tsubst_copy (TREE_OPERAND (t, 1), args, complain, in_decl);
= tsubst_copy_and_build (TREE_OPERAND (t, 1), args, complain,
in_decl);
if (TREE_CODE (template) == COMPONENT_REF)
{
@ -7870,7 +7947,6 @@ tsubst_copy_and_build (tree t,
}
else
object = NULL_TREE;
maybe_fold_nontype_args (targs);
template = lookup_template_function (template, targs);
if (object)
@ -7910,10 +7986,21 @@ tsubst_copy_and_build (tree t,
(tsubst (TREE_TYPE (t), args, complain, in_decl),
tsubst_copy_and_build (TREE_OPERAND (t, 0), args, complain, in_decl));
case PREDECREMENT_EXPR:
case PREINCREMENT_EXPR:
case POSTDECREMENT_EXPR:
case POSTINCREMENT_EXPR:
op1 = TREE_OPERAND (t, 0);
if (TREE_CODE (op1) == SCOPE_REF)
op1 = tsubst_qualified_id (TREE_OPERAND (t, 0),
args, complain,
in_decl,
/*done=*/false,
/*address_p=*/false);
else
op1 = tsubst_copy_and_build (op1, args, complain, in_decl);
return build_x_unary_op (TREE_CODE (t), op1);
case PREDECREMENT_EXPR:
case PREINCREMENT_EXPR:
if (TREE_TYPE (t))
return tsubst_copy (t, args, complain, in_decl);
else
@ -7939,8 +8026,16 @@ tsubst_copy_and_build (tree t,
(TREE_CODE (t),
tsubst_copy_and_build (TREE_OPERAND (t, 0), args, complain, in_decl));
case TRUTH_NOT_EXPR:
case ADDR_EXPR:
op1 = TREE_OPERAND (t, 0);
if (TREE_CODE (op1) == SCOPE_REF)
op1 = tsubst_qualified_id (op1, args, complain, in_decl,
/*done=*/true, /*address_p=*/true);
else
op1 = tsubst_copy_and_build (op1, args, complain, in_decl);
return build_x_unary_op (ADDR_EXPR, op1);
case TRUTH_NOT_EXPR:
case CONVERT_EXPR: /* Unary + */
case REALPART_EXPR:
case IMAGPART_EXPR:
@ -7994,26 +8089,31 @@ tsubst_copy_and_build (tree t,
tsubst_copy_and_build (TREE_OPERAND (t, 1), args, complain, in_decl));
case SCOPE_REF:
return build_offset_ref
(tsubst_copy (TREE_OPERAND (t, 0), args, complain, in_decl),
tsubst_copy (TREE_OPERAND (t, 1), args, complain, in_decl));
return tsubst_qualified_id (t, args, complain, in_decl, /*done=*/true,
/*address_p=*/false);
case ARRAY_REF:
{
if (tsubst_copy (TREE_OPERAND (t, 0), args, complain, in_decl)
== NULL_TREE)
/* new-type-id */
return build_nt
(ARRAY_REF, NULL_TREE,
tsubst_copy_and_build (TREE_OPERAND (t, 1), args, complain,
in_decl));
return grok_array_decl
(tsubst_copy_and_build (TREE_OPERAND (t, 0), args, complain,
in_decl),
if (tsubst_copy (TREE_OPERAND (t, 0), args, complain, in_decl)
== NULL_TREE)
/* new-type-id */
return build_nt
(ARRAY_REF, NULL_TREE,
tsubst_copy_and_build (TREE_OPERAND (t, 1), args, complain,
in_decl));
}
op1 = TREE_OPERAND (t, 0);
if (TREE_CODE (op1) == SCOPE_REF)
op1 = tsubst_qualified_id (op1, args, complain, in_decl,
/*done=*/false, /*address_p=*/false);
else
op1 = tsubst_copy_and_build (op1, args, complain, in_decl);
/* Remember that there was a reference to this entity. */
if (DECL_P (op1))
mark_used (op1);
return grok_array_decl (op1,
tsubst_copy_and_build (TREE_OPERAND (t, 1),
args, complain,
in_decl));
case SIZEOF_EXPR:
case ALIGNOF_EXPR:
@ -8034,8 +8134,16 @@ tsubst_copy_and_build (tree t,
tsubst_copy_and_build (TREE_OPERAND (t, 2), args, complain, in_decl));
case ARROW_EXPR:
return build_x_arrow
(tsubst_copy_and_build (TREE_OPERAND (t, 0), args, complain, in_decl));
op1 = TREE_OPERAND (t, 0);
if (TREE_CODE (op1) == SCOPE_REF)
op1 = tsubst_qualified_id (op1, args, complain, in_decl,
/*done=*/false, /*address_p=*/false);
else
op1 = tsubst_copy_and_build (op1, args, complain, in_decl);
/* Remember that there was a reference to this entity. */
if (DECL_P (op1))
mark_used (op1);
return build_x_arrow (op1);
case NEW_EXPR:
return build_new
@ -8062,104 +8170,62 @@ tsubst_copy_and_build (tree t,
abort ();
}
case METHOD_CALL_EXPR:
{
tree method
= tsubst_copy (TREE_OPERAND (t, 0), args, complain, in_decl);
if (TREE_CODE (method) == SCOPE_REF)
{
tree name = TREE_OPERAND (method, 1);
if (TREE_CODE (name) == TEMPLATE_ID_EXPR)
name = build_nt (TEMPLATE_ID_EXPR,
TREE_OPERAND (name, 0),
TREE_OPERAND (name, 1));
return build_scoped_method_call
(tsubst_copy_and_build
(TREE_OPERAND (t, 1), args, complain, in_decl),
TREE_OPERAND (method, 0),
name,
tsubst_copy_and_build
(TREE_OPERAND (t, 2), args, complain, in_decl));
}
else
{
/* We can get a TEMPLATE_ID_EXPR here on code like:
x->f<2>();
so we must resolve that. However, we can also get things
like a BIT_NOT_EXPR here, when referring to a destructor,
and things like that are not correctly resolved by this
function so just use it when we really need it. */
if (TREE_CODE (method) == TEMPLATE_ID_EXPR)
method = lookup_template_function
(TREE_OPERAND (method, 0),
TREE_OPERAND (method, 1));
return build_method_call
(tsubst_copy_and_build
(TREE_OPERAND (t, 1), args, complain, in_decl),
method,
tsubst_copy_and_build
(TREE_OPERAND (t, 2), args, complain, in_decl),
NULL_TREE, LOOKUP_NORMAL);
}
}
case CALL_EXPR:
{
tree function, copy_args;
tree function;
tree call_args;
tree koenig_name;
bool qualified_p;
function = tsubst_copy (TREE_OPERAND (t, 0), args, complain, in_decl);
copy_args = tsubst_copy_and_build (TREE_OPERAND (t, 1), args,
complain, in_decl);
if (BASELINK_P (function))
return build_call_from_tree (function, copy_args, 1);
else if (TREE_CODE (function) == SCOPE_REF)
function = TREE_OPERAND (t, 0);
if (TREE_CODE (function) == LOOKUP_EXPR
&& !LOOKUP_EXPR_GLOBAL (function))
koenig_name = TREE_OPERAND (function, 0);
else
koenig_name = NULL_TREE;
if (TREE_CODE (function) == SCOPE_REF)
{
tree name = TREE_OPERAND (function, 1);
if (TREE_CODE (name) == TEMPLATE_ID_EXPR)
name = build_nt (TEMPLATE_ID_EXPR,
TREE_OPERAND (name, 0),
build_expr_from_tree (TREE_OPERAND (name, 1)));
function = resolve_scoped_fn_name (TREE_OPERAND (function, 0),
name);
return build_call_from_tree (function, copy_args, 1);
qualified_p = true;
function = tsubst_qualified_id (function, args, complain, in_decl,
/*done=*/false,
/*address_p=*/false);
}
else
{
tree name = function;
tree id;
if (copy_args != NULL_TREE && TREE_CODE (name) == LOOKUP_EXPR
&& !LOOKUP_EXPR_GLOBAL (name)
&& (TREE_CODE ((id = TREE_OPERAND (name, 0)))
== IDENTIFIER_NODE)
&& (!current_class_type
|| !lookup_member (current_class_type, id, 0, false)))
{
/* Do Koenig lookup if there are no class members. */
name = do_identifier (id, copy_args);
}
else if (TREE_CODE (name) == TEMPLATE_ID_EXPR
|| ! really_overloaded_fn (name))
name = build_expr_from_tree (name);
qualified_p = (TREE_CODE (function) == COMPONENT_REF
&& (TREE_CODE (TREE_OPERAND (function, 1))
== SCOPE_REF));
function = tsubst_copy_and_build (function, args, complain,
in_decl);
function = convert_from_reference (function);
}
if (TREE_CODE (name) == OFFSET_REF)
return build_offset_ref_call_from_tree (name, copy_args);
if (TREE_CODE (name) == COMPONENT_REF)
return finish_object_call_expr (TREE_OPERAND (name, 1),
TREE_OPERAND (name, 0),
copy_args);
name = convert_from_reference (name);
return build_call_from_tree (name, copy_args,
/*disallow_virtual=*/false);
/* Remember that there was a reference to this entity. */
if (DECL_P (function))
mark_used (function);
call_args = tsubst_copy_and_build (TREE_OPERAND (t, 1), args,
complain, in_decl);
if (BASELINK_P (function))
return build_call_from_tree (function, call_args, 1);
else
{
if (call_args != NULL_TREE && koenig_name)
function = lookup_arg_dependent (koenig_name,
function,
call_args);
if (TREE_CODE (function) == OFFSET_REF)
return build_offset_ref_call_from_tree (function, call_args);
if (TREE_CODE (function) == COMPONENT_REF)
return (build_new_method_call
(TREE_OPERAND (function, 0),
TREE_OPERAND (function, 1),
call_args, NULL_TREE,
qualified_p ? LOOKUP_NONVIRTUAL : LOOKUP_NORMAL));
return finish_call_expr (function, call_args,
/*disallow_virtual=*/qualified_p);
}
}
@ -8200,10 +8266,27 @@ tsubst_copy_and_build (tree t,
case COMPONENT_REF:
{
tree object =
tsubst_copy_and_build (TREE_OPERAND (t, 0), args, complain, in_decl);
tree member =
tsubst_copy (TREE_OPERAND (t, 1), args, complain, in_decl);
tree object;
tree member;
object = TREE_OPERAND (t, 0);
if (TREE_CODE (object) == SCOPE_REF)
object = tsubst_qualified_id (object, args, complain, in_decl,
/*done=*/false, /*address_p=*/false);
else
object = tsubst_copy_and_build (object, args, complain, in_decl);
/* Remember that there was a reference to this entity. */
if (DECL_P (object))
mark_used (object);
member = TREE_OPERAND (t, 1);
if (BASELINK_P (member))
member = tsubst_baselink (member,
non_reference (TREE_TYPE (object)),
args, complain, in_decl);
else
member = tsubst_copy (member, args, complain, in_decl);
if (!CLASS_TYPE_P (TREE_TYPE (object)))
{
@ -8229,8 +8312,7 @@ tsubst_copy_and_build (tree t,
args = TREE_OPERAND (TREE_OPERAND (member, 1), 1);
member = lookup_qualified_name (TREE_OPERAND (member, 0),
tmpl,
/*is_type=*/0,
/*flags=*/0);
/*is_type=*/0);
if (BASELINK_P (member))
BASELINK_FUNCTIONS (member)
= build_nt (TEMPLATE_ID_EXPR, BASELINK_FUNCTIONS (member),
@ -8303,7 +8385,9 @@ tsubst_copy_and_build (tree t,
return convert_from_reference (tsubst_copy (t, args, complain, in_decl));
case VAR_DECL:
return convert_from_reference (tsubst_copy (t, args, complain, in_decl));
if (args)
t = tsubst_copy (t, args, complain, in_decl);
return convert_from_reference (t);
case VA_ARG_EXPR:
return build_x_va_arg
@ -11405,8 +11489,7 @@ value_dependent_expression_p (tree expression)
with an expression that is value-dependent. */
if (TREE_CODE (expression) == VAR_DECL
&& DECL_INITIAL (expression)
&& (CP_INTEGRAL_TYPE_P (TREE_TYPE (expression))
|| TREE_CODE (TREE_TYPE (expression)) == ENUMERAL_TYPE)
&& INTEGRAL_OR_ENUMERATION_TYPE_P (expression)
&& value_dependent_expression_p (DECL_INITIAL (expression)))
return true;
/* These expressions are value-dependent if the type to which the

View File

@ -213,11 +213,8 @@ get_tinfo_decl_dynamic (tree exp)
if (exp == error_mark_node)
return error_mark_node;
type = TREE_TYPE (exp);
/* peel back references, so they match. */
if (TREE_CODE (type) == REFERENCE_TYPE)
type = TREE_TYPE (type);
type = non_reference (TREE_TYPE (exp));
/* Peel off cv qualifiers. */
type = TYPE_MAIN_VARIANT (type);
@ -408,8 +405,7 @@ get_typeid (tree 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
referenced type. */
if (TREE_CODE (type) == REFERENCE_TYPE)
type = TREE_TYPE (type);
type = non_reference (type);
/* The top-level cv-qualifiers of the lvalue expression or the type-id
that is the operand of typeid are always ignored. */

View File

@ -1712,9 +1712,7 @@ check_final_overrider (tree overrider, tree basefn)
{
/* can_convert will permit user defined conversion from a
(reference to) class type. We must reject them. */
over_return = TREE_TYPE (over_type);
if (TREE_CODE (over_return) == REFERENCE_TYPE)
over_return = TREE_TYPE (over_return);
over_return = non_reference (TREE_TYPE (over_type));
if (CLASS_TYPE_P (over_return))
fail = 2;
}

View File

@ -1276,6 +1276,119 @@ finish_non_static_data_member (tree decl, tree qualifying_scope)
}
}
/* DECL was the declaration to which a qualified-id resolved. Issue
an error message if it is not accessible. If OBJECT_TYPE is
non-NULL, we have just seen `x->' or `x.' and OBJECT_TYPE is the
type of `*x', or `x', respectively. If the DECL was named as
`A::B' then NESTED_NAME_SPECIFIER is `A'. */
void
check_accessibility_of_qualified_id (tree decl,
tree object_type,
tree nested_name_specifier)
{
tree scope;
tree qualifying_type = NULL_TREE;
/* Determine the SCOPE of DECL. */
scope = context_for_name_lookup (decl);
/* If the SCOPE is not a type, then DECL is not a member. */
if (!TYPE_P (scope))
return;
/* Compute the scope through which DECL is being accessed. */
if (object_type
/* OBJECT_TYPE might not be a class type; consider:
class A { typedef int I; };
I *p;
p->A::I::~I();
In this case, we will have "A::I" as the DECL, but "I" as the
OBJECT_TYPE. */
&& CLASS_TYPE_P (object_type)
&& DERIVED_FROM_P (scope, object_type))
/* If we are processing a `->' or `.' expression, use the type of the
left-hand side. */
qualifying_type = object_type;
else if (nested_name_specifier)
{
/* If the reference is to a non-static member of the
current class, treat it as if it were referenced through
`this'. */
if (DECL_NONSTATIC_MEMBER_P (decl)
&& current_class_ptr
&& DERIVED_FROM_P (scope, current_class_type))
qualifying_type = current_class_type;
/* Otherwise, use the type indicated by the
nested-name-specifier. */
else
qualifying_type = nested_name_specifier;
}
else
/* Otherwise, the name must be from the current class or one of
its bases. */
qualifying_type = currently_open_derived_class (scope);
if (qualifying_type)
perform_or_defer_access_check (TYPE_BINFO (qualifying_type), decl);
}
/* EXPR is the result of a qualified-id. The QUALIFYING_CLASS was the
class named to the left of the "::" operator. DONE is true if this
expression is a complete postfix-expression; it is false if this
expression is followed by '->', '[', '(', etc. ADDRESS_P is true
iff this expression is the operand of '&'. */
tree
finish_qualified_id_expr (tree qualifying_class, tree expr, bool done,
bool address_p)
{
/* If EXPR occurs as the operand of '&', use special handling that
permits a pointer-to-member. */
if (address_p && done)
{
if (TREE_CODE (expr) == SCOPE_REF)
expr = TREE_OPERAND (expr, 1);
expr = build_offset_ref (qualifying_class, expr);
return expr;
}
if (TREE_CODE (expr) == FIELD_DECL)
expr = finish_non_static_data_member (expr, qualifying_class);
else if (BASELINK_P (expr) && !processing_template_decl)
{
tree fn;
tree fns;
/* See if any of the functions are non-static members. */
fns = BASELINK_FUNCTIONS (expr);
if (TREE_CODE (fns) == TEMPLATE_ID_EXPR)
fns = TREE_OPERAND (fns, 0);
for (fn = fns; fn; fn = OVL_NEXT (fn))
if (DECL_NONSTATIC_MEMBER_FUNCTION_P (fn))
break;
/* If so, the expression may be relative to the current
class. */
if (fn && current_class_type
&& DERIVED_FROM_P (qualifying_class, current_class_type))
expr = (build_class_member_access_expr
(maybe_dummy_object (qualifying_class, NULL),
expr,
BASELINK_ACCESS_BINFO (expr),
/*preserve_reference=*/false));
else if (done)
{
/* The expression is a qualified name whose address is not
being taken. */
expr = build_offset_ref (qualifying_class, expr);
if (TREE_CODE (expr) == OFFSET_REF)
expr = resolve_offset_ref (expr);
}
}
return expr;
}
/* Begin a statement-expression. The value returned must be passed to
finish_stmt_expr. */
@ -1548,16 +1661,6 @@ finish_object_call_expr (tree fn, tree object, tree args)
return build_new_method_call (object, fn, args, NULL_TREE, LOOKUP_NORMAL);
}
/* Finish a qualified member function call using OBJECT and ARGS as
arguments to FN. Returns an expression for the call. */
tree
finish_qualified_object_call_expr (tree fn, tree object, tree args)
{
return build_scoped_method_call (object, TREE_OPERAND (fn, 0),
TREE_OPERAND (fn, 1), args);
}
/* Finish a pseudo-destructor expression. If SCOPE is NULL, the
expression was of the form `OBJECT.~DESTRUCTOR' where DESTRUCTOR is
the TYPE for the type given. If SCOPE is non-NULL, the expression

View File

@ -72,8 +72,7 @@ static tree lookup_destructor (tree, tree, tree);
tree
target_type (tree type)
{
if (TREE_CODE (type) == REFERENCE_TYPE)
type = TREE_TYPE (type);
type = non_reference (type);
while (TREE_CODE (type) == POINTER_TYPE
|| TREE_CODE (type) == ARRAY_TYPE
|| TREE_CODE (type) == FUNCTION_TYPE
@ -1421,9 +1420,8 @@ cxx_sizeof_or_alignof_type (tree type, enum tree_code op, int complain)
return build_min_nt (op, type);
op_name = operator_name_info[(int) op].name;
if (TREE_CODE (type) == REFERENCE_TYPE)
type = TREE_TYPE (type);
type = non_reference (type);
type_code = TREE_CODE (type);
if (type_code == METHOD_TYPE)
@ -5888,8 +5886,7 @@ tree
dubious_conversion_warnings (tree type, tree expr,
const char *errtype, tree fndecl, int parmnum)
{
if (TREE_CODE (type) == REFERENCE_TYPE)
type = TREE_TYPE (type);
type = non_reference (type);
/* Issue warnings about peculiar, but valid, uses of NULL. */
if (ARITHMETIC_TYPE_P (type) && expr == null_node)
@ -6102,8 +6099,7 @@ convert_for_initialization (tree exp, tree type, tree rhs, int flags,
if (exp == error_mark_node)
return error_mark_node;
if (TREE_CODE (rhstype) == REFERENCE_TYPE)
rhstype = TREE_TYPE (rhstype);
rhstype = non_reference (rhstype);
type = complete_type (type);
@ -6708,3 +6704,14 @@ strip_all_pointer_quals (tree type)
else
return TYPE_MAIN_VARIANT (type);
}
/* If T is a REFERENCE_TYPE return the type to which T refers.
Otherwise, return T itself. */
tree
non_reference (tree t)
{
if (TREE_CODE (t) == REFERENCE_TYPE)
t = TREE_TYPE (t);
return t;
}