This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
C++ PATCH: Rework function call machinery in templates
- From: Mark Mitchell <mark at codesourcery dot com>
- To: gcc-patches at gcc dot gnu dot org
- Date: Mon, 7 Jul 2003 18:43:13 -0700
- Subject: C++ PATCH: Rework function call machinery in templates
- Reply-to: mark at codesourcery dot com
This patch is preparation for finishing the two-phase name lookup work
begun with the new parser. This patch eliminates a bunch of
unncessary code and makes template instantiation of calls work more
like ordinary parsing of calls.
Tested on i686-pc-linux-gnu, applied on the mainline.
--
Mark Mitchell
CodeSourcery, LLC
mark@codesourcery.com
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.
Index: call.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/cp/call.c,v
retrieving revision 1.402
diff -c -5 -p -r1.402 call.c
*** call.c 6 Jul 2003 23:23:42 -0000 1.402
--- call.c 8 Jul 2003 01:36:06 -0000
*************** static struct z_candidate *add_conv_cand
*** 85,95 ****
static struct z_candidate *add_function_candidate
(struct z_candidate **, tree, tree, tree, tree, tree, int);
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 *);
static void maybe_handle_implicit_object (tree *);
static struct z_candidate *add_candidate
--- 85,94 ----
*************** check_dtor_name (tree basetype, tree nam
*** 203,312 ****
if (name && TYPE_MAIN_VARIANT (basetype) == TYPE_MAIN_VARIANT (name))
return true;
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. */
tree
build_addr_func (tree function)
--- 202,211 ----
*************** build_method_call (tree instance, tree n
*** 458,475 ****
#ifdef GATHER_STATISTICS
n_build_method_call++;
#endif
! if (instance == error_mark_node
|| name == error_mark_node
! || parms == error_mark_node
! || (instance && TREE_TYPE (instance) == error_mark_node))
return error_mark_node;
! if (processing_template_decl)
! return build_min_nt (METHOD_CALL_EXPR, name, instance, parms, NULL_TREE);
if (TREE_CODE (TREE_TYPE (instance)) == REFERENCE_TYPE)
instance = convert_from_reference (instance);
object_type = TREE_TYPE (instance);
--- 357,372 ----
#ifdef GATHER_STATISTICS
n_build_method_call++;
#endif
! if (error_operand_p (instance)
|| name == error_mark_node
! || parms == error_mark_node)
return error_mark_node;
! my_friendly_assert (!processing_template_decl, 20030707);
if (TREE_CODE (TREE_TYPE (instance)) == REFERENCE_TYPE)
instance = convert_from_reference (instance);
object_type = TREE_TYPE (instance);
*************** build_method_call (tree instance, tree n
*** 516,526 ****
if (has_template_args)
fn = lookup_fnfields (object_type, name, /*protect=*/2);
else
fn = lookup_member (object_type, name, /*protect=*/2, /*want_type=*/false);
! if (fn && TREE_CODE (fn) == TREE_LIST && !BASELINK_P (fn))
{
error ("request for member `%D' is ambiguous", name);
print_candidates (fn);
return error_mark_node;
}
--- 413,423 ----
if (has_template_args)
fn = lookup_fnfields (object_type, name, /*protect=*/2);
else
fn = lookup_member (object_type, name, /*protect=*/2, /*want_type=*/false);
! if (fn && TREE_CODE (fn) == TREE_LIST)
{
error ("request for member `%D' is ambiguous", name);
print_candidates (fn);
return error_mark_node;
}
*************** build_conv (enum tree_code code, tree ty
*** 667,687 ****
ICS_USER_FLAG (t) = (code == USER_CONV || ICS_USER_FLAG (from));
ICS_BAD_FLAG (t) = ICS_BAD_FLAG (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)
{
if (TREE_CODE (t) == ARRAY_TYPE)
return t;
--- 564,573 ----
*************** standard_conversion (tree to, tree from,
*** 697,708 ****
{
enum tree_code fcode, tcode;
tree conv;
bool fromref = false;
! if (TREE_CODE (to) == REFERENCE_TYPE)
! to = TREE_TYPE (to);
if (TREE_CODE (from) == REFERENCE_TYPE)
{
fromref = true;
from = TREE_TYPE (from);
}
--- 583,593 ----
{
enum tree_code fcode, tcode;
tree conv;
bool fromref = false;
! to = non_reference (to);
if (TREE_CODE (from) == REFERENCE_TYPE)
{
fromref = true;
from = TREE_TYPE (from);
}
Index: class.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/cp/class.c,v
retrieving revision 1.549
diff -c -5 -p -r1.549 class.c
*** class.c 6 Jul 2003 23:23:42 -0000 1.549
--- class.c 8 Jul 2003 01:36:07 -0000
*************** convert_to_base (tree object, tree type,
*** 399,411 ****
static tree
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);
vtable = get_vtbl_decl_for_binfo (TYPE_BINFO (basetype));
first_fn = TYPE_BINFO_VTABLE (basetype);
i = fold (build_array_ref (first_fn, idx));
--- 399,409 ----
static tree
build_vtable_entry_ref (tree array_ref, tree instance, tree idx)
{
tree i, i2, vtable, first_fn, basetype;
! basetype = non_reference (TREE_TYPE (instance));
vtable = get_vtbl_decl_for_binfo (TYPE_BINFO (basetype));
first_fn = TYPE_BINFO_VTABLE (basetype);
i = fold (build_array_ref (first_fn, idx));
*************** build_vtbl_ref_1 (tree instance, tree id
*** 437,449 ****
access its virtual function table directly. */
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);
if (fixed_type && !cdtorp)
{
tree binfo = lookup_base (fixed_type, basetype,
ba_ignore|ba_quiet, NULL);
--- 435,445 ----
access its virtual function table directly. */
int cdtorp = 0;
tree fixed_type = fixed_type_or_null (instance, NULL, &cdtorp);
! tree basetype = non_reference (TREE_TYPE (instance));
if (fixed_type && !cdtorp)
{
tree binfo = lookup_base (fixed_type, basetype,
ba_ignore|ba_quiet, NULL);
Index: cp-tree.h
===================================================================
RCS file: /cvs/gcc/gcc/gcc/cp/cp-tree.h,v
retrieving revision 1.869
diff -c -5 -p -r1.869 cp-tree.h
*** cp-tree.h 6 Jul 2003 23:23:43 -0000 1.869
--- cp-tree.h 8 Jul 2003 01:36:07 -0000
*************** extern GTY(()) operator_name_info_t assi
*** 3491,3501 ****
/* in call.c */
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);
extern tree build_method_call (tree, tree, tree, tree, int);
extern bool null_ptr_cst_p (tree);
--- 3491,3500 ----
*************** extern void set_namespace_binding
*** 3658,3668 ****
extern tree lookup_namespace_name (tree, tree);
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_name (tree, int);
extern tree lookup_name_current_level (tree);
extern tree lookup_type_current_level (tree);
extern tree lookup_name_real (tree, int, int, int, int);
extern tree namespace_ancestor (tree, tree);
--- 3657,3667 ----
extern tree lookup_namespace_name (tree, tree);
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);
extern tree lookup_name (tree, int);
extern tree lookup_name_current_level (tree);
extern tree lookup_type_current_level (tree);
extern tree lookup_name_real (tree, int, int, int, int);
extern tree namespace_ancestor (tree, tree);
*************** extern void comdat_linkage (tree);
*** 3773,3783 ****
extern void import_export_vtable (tree, tree, int);
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);
extern tree current_decl_namespace (void);
extern void push_decl_namespace (tree);
--- 3772,3781 ----
*************** extern void maybe_process_partial_specia
*** 3965,3974 ****
--- 3963,3973 ----
extern void maybe_check_template_type (tree);
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);
extern void record_last_problematic_instantiation (void);
extern tree current_instantiation (void);
*************** extern tree begin_stmt_expr
*** 4112,4122 ****
extern tree finish_stmt_expr (tree);
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);
extern tree finish_fname (tree);
extern int begin_function_definition (tree, tree, tree);
--- 4111,4120 ----
*************** extern void setup_vtbl_ptr (tree, tree
*** 4147,4156 ****
--- 4145,4156 ----
extern void clear_out_block (void);
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,
const char *);
extern tree stabilize_expr (tree, tree *);
*************** extern tree check_return_expr
*** 4297,4306 ****
--- 4297,4307 ----
#define cxx_sizeof(T) cxx_sizeof_or_alignof_type (T, SIZEOF_EXPR, true)
#define cxx_alignof(T) cxx_sizeof_or_alignof_type (T, ALIGNOF_EXPR, true)
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);
extern void cxx_incomplete_type_diagnostic (tree, tree, int);
#undef cxx_incomplete_type_error
Index: cvt.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/cp/cvt.c,v
retrieving revision 1.141
diff -c -5 -p -r1.141 cvt.c
*** cvt.c 6 Jul 2003 03:30:55 -0000 1.141
--- cvt.c 8 Jul 2003 01:36:07 -0000
*************** build_expr_type_conversion (int desires,
*** 1075,1087 ****
tree cand = TREE_VALUE (conv);
if (winner && winner == cand)
continue;
! candidate = TREE_TYPE (TREE_TYPE (cand));
! if (TREE_CODE (candidate) == REFERENCE_TYPE)
! candidate = TREE_TYPE (candidate);
switch (TREE_CODE (candidate))
{
case BOOLEAN_TYPE:
case INTEGER_TYPE:
--- 1075,1085 ----
tree cand = TREE_VALUE (conv);
if (winner && winner == cand)
continue;
! candidate = non_reference (TREE_TYPE (TREE_TYPE (cand)));
switch (TREE_CODE (candidate))
{
case BOOLEAN_TYPE:
case INTEGER_TYPE:
*************** build_expr_type_conversion (int desires,
*** 1115,1127 ****
}
}
if (winner)
{
! tree type = TREE_TYPE (TREE_TYPE (winner));
! if (TREE_CODE (type) == REFERENCE_TYPE)
! type = TREE_TYPE (type);
return build_user_type_conversion (type, expr, LOOKUP_NORMAL);
}
return NULL_TREE;
}
--- 1113,1123 ----
}
}
if (winner)
{
! tree type = non_reference (TREE_TYPE (TREE_TYPE (winner)));
return build_user_type_conversion (type, expr, LOOKUP_NORMAL);
}
return NULL_TREE;
}
Index: decl.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/cp/decl.c,v
retrieving revision 1.1081
diff -c -5 -p -r1.1081 decl.c
*** decl.c 6 Jul 2003 23:23:43 -0000 1.1081
--- decl.c 8 Jul 2003 01:36:08 -0000
*************** qualify_lookup (tree val, int flags)
*** 5774,5799 ****
Returns a DECL (or OVERLOAD, or BASELINK) representing the
declaration found. */
tree
! lookup_qualified_name (tree scope, tree name, bool is_type_p, int flags)
{
if (TREE_CODE (scope) == NAMESPACE_DECL)
{
cxx_binding binding;
cxx_binding_clear (&binding);
flags |= LOOKUP_COMPLAIN;
if (is_type_p)
flags |= LOOKUP_PREFER_TYPES;
! if (!qualified_lookup_using_namespace (name, scope, &binding, flags))
return NULL_TREE;
return select_decl (&binding, flags);
}
! else
return lookup_member (scope, name, 0, is_type_p);
}
/* Check to see whether or not DECL is a variable that would have been
in scope under the ARM, but is not in scope under the ANSI/ISO
standard. If so, issue an error message. If name lookup would
--- 5774,5804 ----
Returns a DECL (or OVERLOAD, or BASELINK) representing the
declaration found. */
tree
! lookup_qualified_name (tree scope, tree name, bool is_type_p)
{
+ int flags = 0;
+
if (TREE_CODE (scope) == NAMESPACE_DECL)
{
cxx_binding binding;
cxx_binding_clear (&binding);
flags |= LOOKUP_COMPLAIN;
if (is_type_p)
flags |= LOOKUP_PREFER_TYPES;
! if (!qualified_lookup_using_namespace (name, scope, &binding,
! flags))
return NULL_TREE;
return select_decl (&binding, flags);
}
! 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
in scope under the ARM, but is not in scope under the ANSI/ISO
standard. If so, issue an error message. If name lookup would
*************** grok_op_properties (tree decl, int frien
*** 12324,12336 ****
error ("`%D' must be either a non-static member function or a non-member function", decl);
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);
/* This lets bad template code slip through. */
if (IS_AGGR_TYPE (arg)
|| TREE_CODE (arg) == ENUMERAL_TYPE
|| TREE_CODE (arg) == TEMPLATE_TYPE_PARM
--- 12329,12339 ----
error ("`%D' must be either a non-static member function or a non-member function", decl);
if (p)
for (; TREE_CODE (TREE_VALUE (p)) != VOID_TYPE ; p = TREE_CHAIN (p))
{
! tree arg = non_reference (TREE_VALUE (p));
/* This lets bad template code slip through. */
if (IS_AGGR_TYPE (arg)
|| TREE_CODE (arg) == ENUMERAL_TYPE
|| TREE_CODE (arg) == TEMPLATE_TYPE_PARM
Index: decl2.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/cp/decl2.c,v
retrieving revision 1.643
diff -c -5 -p -r1.643 decl2.c
*** decl2.c 7 Jul 2003 19:11:58 -0000 1.643
--- decl2.c 8 Jul 2003 01:36:08 -0000
*************** grok_array_decl (tree array_expr, tree i
*** 407,418 ****
return build_min (ARRAY_REF, type ? TREE_TYPE (type) : NULL_TREE,
array_expr, index_exp);
my_friendly_assert (type, 20030626);
! if (TREE_CODE (type) == REFERENCE_TYPE)
! type = TREE_TYPE (type);
/* If they have an `operator[]', use that. */
if (IS_AGGR_TYPE (type) || IS_AGGR_TYPE (TREE_TYPE (index_exp)))
return build_new_op (ARRAY_REF, LOOKUP_NORMAL,
array_expr, index_exp, NULL_TREE);
--- 407,417 ----
return build_min (ARRAY_REF, type ? TREE_TYPE (type) : NULL_TREE,
array_expr, index_exp);
my_friendly_assert (type, 20030626);
! type = non_reference (type);
/* If they have an `operator[]', use that. */
if (IS_AGGR_TYPE (type) || IS_AGGR_TYPE (TREE_TYPE (index_exp)))
return build_new_op (ARRAY_REF, LOOKUP_NORMAL,
array_expr, index_exp, NULL_TREE);
*************** finish_file ()
*** 2936,3354 ****
dump_time_statistics ();
}
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
analzyed. */
--- 2935,2944 ----
*************** build_offset_ref_call_from_tree (tree fn
*** 3357,3382 ****
{
tree object_addr;
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) (); }
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 ();
else
{
--- 2947,2962 ----
{
tree object_addr;
my_friendly_assert (TREE_CODE (fn) == OFFSET_REF, 20020725);
! /* 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)(); } */
if (TREE_CODE (TREE_OPERAND (fn, 1)) == FIELD_DECL)
/* This case should now be handled elsewhere. */
abort ();
else
{
Index: error.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/cp/error.c,v
retrieving revision 1.218
diff -c -5 -p -r1.218 error.c
*** error.c 6 Jul 2003 23:23:44 -0000 1.218
--- error.c 8 Jul 2003 01:36:08 -0000
*************** language_to_string (enum languages c)
*** 2228,2237 ****
--- 2228,2239 ----
/* Return the proper printed version of a parameter to a C++ function. */
static const char *
parm_to_string (int p)
{
+ reinit_global_formatting_buffer ();
+
if (p < 0)
output_add_string (scratch_buffer, "'this'");
else
output_decimal (scratch_buffer, p + 1);
Index: except.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/cp/except.c,v
retrieving revision 1.156
diff -c -5 -p -r1.156 except.c
*** except.c 17 Jun 2003 05:07:59 -0000 1.156
--- except.c 8 Jul 2003 01:36:08 -0000
*************** prepare_eh_type (tree type)
*** 105,116 ****
return type;
if (type == error_mark_node)
return error_mark_node;
/* peel back references, so they match. */
! if (TREE_CODE (type) == REFERENCE_TYPE)
! type = TREE_TYPE (type);
/* Peel off cv qualifiers. */
type = TYPE_MAIN_VARIANT (type);
return type;
--- 105,115 ----
return type;
if (type == error_mark_node)
return error_mark_node;
/* peel back references, so they match. */
! type = non_reference (type);
/* Peel off cv qualifiers. */
type = TYPE_MAIN_VARIANT (type);
return type;
*************** nothrow_libfn_p (tree fn)
*** 870,883 ****
handler for type TO, as per [except.handle]. */
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);
if (TREE_CODE (to) == POINTER_TYPE && TREE_CODE (from) == POINTER_TYPE)
{
to = TREE_TYPE (to);
from = TREE_TYPE (from);
--- 869,880 ----
handler for type TO, as per [except.handle]. */
static int
can_convert_eh (tree to, tree from)
{
! to = non_reference (to);
! from = non_reference (from);
if (TREE_CODE (to) == POINTER_TYPE && TREE_CODE (from) == POINTER_TYPE)
{
to = TREE_TYPE (to);
from = TREE_TYPE (from);
Index: init.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/cp/init.c,v
retrieving revision 1.328
diff -c -5 -p -r1.328 init.c
*** init.c 6 Jul 2003 03:30:55 -0000 1.328
--- init.c 8 Jul 2003 01:36:08 -0000
*************** build_x_delete (tree addr, int which_del
*** 2913,2923 ****
static tree
build_dtor_call (tree exp, special_function_kind dtor_kind, int flags)
{
tree name;
!
switch (dtor_kind)
{
case sfk_complete_destructor:
name = complete_dtor_identifier;
break;
--- 2913,2923 ----
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:
name = complete_dtor_identifier;
break;
*************** build_dtor_call (tree exp, special_funct
*** 2931,2942 ****
break;
default:
abort ();
}
! return build_method_call (exp, name, NULL_TREE,
! TYPE_BINFO (TREE_TYPE (exp)), flags);
}
/* Generate a call to a destructor. TYPE is the type to cast ADDR to.
ADDR is an expression which yields the store to be destroyed.
AUTO_DELETE is the name of the destructor to call, i.e., either
--- 2931,2947 ----
break;
default:
abort ();
}
!
! 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.
ADDR is an expression which yields the store to be destroyed.
AUTO_DELETE is the name of the destructor to call, i.e., either
Index: mangle.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/cp/mangle.c,v
retrieving revision 1.82
diff -c -5 -p -r1.82 mangle.c
*** mangle.c 7 Jul 2003 19:11:59 -0000 1.82
--- mangle.c 8 Jul 2003 01:36:08 -0000
*************** write_pointer_to_member_type (const tree
*** 2195,2212 ****
/* Non-terminal <template-param>. PARM is a TEMPLATE_TYPE_PARM,
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. */
static void
write_template_param (const tree parm)
{
int parm_index;
--- 2195,2205 ----
/* Non-terminal <template-param>. PARM is a TEMPLATE_TYPE_PARM,
TEMPLATE_TEMPLATE_PARM, BOUND_TEMPLATE_TEMPLATE_PARM or a
TEMPLATE_PARM_INDEX.
! <template-param> ::= T </parameter/ number> _ */
static void
write_template_param (const tree parm)
{
int parm_index;
Index: method.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/cp/method.c,v
retrieving revision 1.259
diff -c -5 -p -r1.259 method.c
*** method.c 6 Jul 2003 23:23:44 -0000 1.259
--- method.c 8 Jul 2003 01:36:08 -0000
*************** locate_copy (tree type, void *client_)
*** 998,1010 ****
int quals;
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);
if (!same_type_ignoring_top_level_qualifiers_p (src_type, type))
continue;
if (!sufficient_parms_p (TREE_CHAIN (parms)))
continue;
quals = cp_type_quals (src_type);
--- 998,1008 ----
int quals;
parms = TREE_CHAIN (parms);
if (!parms)
continue;
! 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)))
continue;
quals = cp_type_quals (src_type);
Index: parser.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/cp/parser.c,v
retrieving revision 1.75
diff -c -5 -p -r1.75 parser.c
*** parser.c 6 Jul 2003 23:23:44 -0000 1.75
--- parser.c 8 Jul 2003 01:36:09 -0000
*************** static bool cp_parser_allow_gnu_extensio
*** 1715,1726 ****
(cp_parser *);
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. */
static inline bool
cp_parser_parsing_tentatively (cp_parser* parser)
--- 1715,1724 ----
*************** static bool
*** 1742,1807 ****
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
cp_parser_error (cp_parser* parser, const char* message)
{
--- 1740,1749 ----
*************** cp_parser_primary_expression (cp_parser
*** 2598,2608 ****
return decl;
}
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. */
*idk = (parser->scope
? CP_PARSER_ID_KIND_QUALIFIED
--- 2540,2550 ----
return decl;
}
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. */
*idk = (parser->scope
? CP_PARSER_ID_KIND_QUALIFIED
*************** cp_parser_primary_expression (cp_parser
*** 2708,2730 ****
/* If the name was dependent on a template parameter,
we will resolve the name at instantiation time. */
if (dependent_p)
{
! /* Create a SCOPE_REF for qualified names. */
if (parser->scope)
{
if (TYPE_P (parser->scope))
*qualifying_class = parser->scope;
/* Since this name was dependent, the expression isn't
constant -- yet. No error is issued because it
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);
}
/* A TEMPLATE_ID already contains all the information
we need. */
if (TREE_CODE (id_expression) == TEMPLATE_ID_EXPR)
return id_expression;
--- 2650,2677 ----
/* If the name was dependent on a template parameter,
we will resolve the name at instantiation time. */
if (dependent_p)
{
! /* Create a SCOPE_REF for qualified names, if the
! scope is dependent. */
if (parser->scope)
{
if (TYPE_P (parser->scope))
*qualifying_class = parser->scope;
/* Since this name was dependent, the expression isn't
constant -- yet. No error is issued because it
might be constant when things are instantiated. */
if (parser->constant_expression_p)
parser->non_constant_expression_p = true;
! 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. */
if (TREE_CODE (id_expression) == TEMPLATE_ID_EXPR)
return id_expression;
*************** cp_parser_postfix_expression (cp_parser
*** 3521,3531 ****
tree postfix_expression = NULL_TREE;
/* Non-NULL only if the current postfix-expression can be used to
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);
/* Some of the productions are determined by keywords. */
keyword = token->keyword;
--- 3468,3477 ----
*************** cp_parser_postfix_expression (cp_parser
*** 3750,3821 ****
&qualifying_class);
}
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 (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;
! /* 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;
! }
! }
}
/* Remember that there was a reference to this entity. */
if (DECL_P (postfix_expression))
mark_used (postfix_expression);
--- 3696,3727 ----
&qualifying_class);
}
break;
}
! /* 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)
{
! bool done;
! /* 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. */
if (DECL_P (postfix_expression))
mark_used (postfix_expression);
*************** cp_parser_postfix_expression (cp_parser
*** 3913,3923 ****
if (type_dependent_expression_p (TREE_VALUE (arg)))
break;
if (!arg)
{
postfix_expression
! = lookup_arg_dependent(identifier, functions, args);
if (!postfix_expression)
{
/* The unqualified name could not be resolved. */
unqualified_name_lookup_error (identifier);
postfix_expression = error_mark_node;
--- 3819,3829 ----
if (type_dependent_expression_p (TREE_VALUE (arg)))
break;
if (!arg)
{
postfix_expression
! = lookup_arg_dependent (identifier, functions, args);
if (!postfix_expression)
{
/* The unqualified name could not be resolved. */
unqualified_name_lookup_error (identifier);
postfix_expression = error_mark_node;
*************** cp_parser_postfix_expression (cp_parser
*** 4012,4023 ****
currently match the standard in this respect in
that our internal representation of an expression
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);
/* If the SCOPE is an OFFSET_TYPE, then we grab the
type of the field. We get an OFFSET_TYPE for
something like:
S::T.a ...
--- 3918,3928 ----
currently match the standard in this respect in
that our internal representation of an expression
may have reference type even when the standard says
it does not. Therefore, we have to manually obtain
the underlying type here. */
! 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:
S::T.a ...
*************** cp_parser_direct_declarator (cp_parser*
*** 10029,10039 ****
{
HOST_WIDE_INT saved_processing_template_decl;
saved_processing_template_decl = processing_template_decl;
processing_template_decl = 0;
! bounds = build_expr_from_tree (bounds);
processing_template_decl = saved_processing_template_decl;
}
}
else
bounds = NULL_TREE;
--- 9934,9947 ----
{
HOST_WIDE_INT saved_processing_template_decl;
saved_processing_template_decl = processing_template_decl;
processing_template_decl = 0;
! bounds = tsubst_copy_and_build (bounds,
! /*args=*/NULL_TREE,
! tf_error,
! /*in_decl=*/NULL_TREE);
processing_template_decl = saved_processing_template_decl;
}
}
else
bounds = NULL_TREE;
*************** cp_parser_lookup_name (cp_parser *parser
*** 13207,13218 ****
push_scope (parser->scope);
/* If the PARSER->SCOPE is a a template specialization, it
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);
if (dependent_p)
pop_scope (parser->scope);
}
parser->qualifying_scope = parser->scope;
parser->object_scope = NULL_TREE;
--- 13115,13125 ----
push_scope (parser->scope);
/* If the PARSER->SCOPE is a a template specialization, it
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);
if (dependent_p)
pop_scope (parser->scope);
}
parser->qualifying_scope = parser->scope;
parser->object_scope = NULL_TREE;
*************** cp_parser_lookup_name (cp_parser *parser
*** 13280,13301 ****
overload resolution is done.
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);
! }
return decl;
}
/* Like cp_parser_lookup_name, but for use in the typical case where
--- 13187,13197 ----
overload resolution is done.
During an explicit instantiation, access is not checked at all,
as per [temp.explicit]. */
if (DECL_P (decl))
! check_accessibility_of_qualified_id (decl, object_type, parser->scope);
return decl;
}
/* Like cp_parser_lookup_name, but for use in the typical case where
Index: pt.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/cp/pt.c,v
retrieving revision 1.714
diff -c -5 -p -r1.714 pt.c
*** pt.c 6 Jul 2003 23:23:45 -0000 1.714
--- pt.c 8 Jul 2003 01:36:09 -0000
*************** static int eq_local_specializations (con
*** 169,179 ****
static bool dependent_type_p_r (tree);
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
template, TEMPLATE_DECL for uninstantiated one, or VAR_DECL for
static member variable (need by instantiate_decl). ARGS is the
--- 169,178 ----
*************** maybe_fold_nontype_arg (tree arg)
*** 5525,5546 ****
{
/* Sometimes, one of the args was an expression involving a
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. */
/* 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
the trees will break. */
if (!TREE_TYPE (arg))
{
int saved_processing_template_decl = processing_template_decl;
processing_template_decl = 0;
! arg = build_expr_from_tree (arg);
processing_template_decl = saved_processing_template_decl;
}
arg = fold (arg);
}
--- 5524,5547 ----
{
/* Sometimes, one of the args was an expression involving a
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
! 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
the trees will break. */
if (!TREE_TYPE (arg))
{
int saved_processing_template_decl = processing_template_decl;
processing_template_decl = 0;
! arg = tsubst_copy_and_build (arg,
! /*args=*/NULL_TREE,
! tf_error,
! /*in_decl=*/NULL_TREE);
processing_template_decl = saved_processing_template_decl;
}
arg = fold (arg);
}
*************** tsubst (tree t, tree args, tsubst_flags_
*** 7074,7083 ****
--- 7075,7196 ----
tree_code_name [(int) TREE_CODE (t)]);
return error_mark_node;
}
}
+ /* 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. */
static tree
*************** tsubst_copy (tree t, tree args, tsubst_f
*** 7155,7201 ****
t = tsubst (t, args, complain, in_decl);
mark_used (t);
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);
! }
case TEMPLATE_DECL:
if (DECL_TEMPLATE_TEMPLATE_PARM_P (t))
return tsubst (TREE_TYPE (DECL_TEMPLATE_RESULT (t)),
args, complain, in_decl);
--- 7268,7278 ----
t = tsubst (t, args, complain, in_decl);
mark_used (t);
return t;
case BASELINK:
! return tsubst_baselink (t, current_class_type, args, complain, in_decl);
case TEMPLATE_DECL:
if (DECL_TEMPLATE_TEMPLATE_PARM_P (t))
return tsubst (TREE_TYPE (DECL_TEMPLATE_RESULT (t)),
args, complain, in_decl);
*************** tsubst_copy (tree t, tree args, tsubst_f
*** 7294,7305 ****
name = tsubst_copy (TREE_OPERAND (name, 0), args,
complain, in_decl);
name = build1 (BIT_NOT_EXPR, NULL_TREE, name);
name = build_nt (SCOPE_REF, base, name);
}
else
! name = tsubst_copy (TREE_OPERAND (t, 1), args, complain, in_decl);
return build_nt (COMPONENT_REF, object, name);
}
case PLUS_EXPR:
case MINUS_EXPR:
--- 7371,7387 ----
name = tsubst_copy (TREE_OPERAND (name, 0), args,
complain, 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 (name, args, complain, in_decl);
return build_nt (COMPONENT_REF, object, name);
}
case PLUS_EXPR:
case MINUS_EXPR:
*************** tsubst_copy (tree t, tree args, tsubst_f
*** 7350,7367 ****
complain, in_decl),
tsubst_copy (TREE_OPERAND (t, 1), args, complain,
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
assumes that there aren't any statements inside them. So, we
need to expand the STMT_EXPR here. */
--- 7432,7441 ----
*************** tsubst_expr (tree t, tree args, tsubst_f
*** 7545,7556 ****
tree name = DECL_NAME (decl);
scope = tsubst_expr (scope, args, complain, in_decl);
do_local_using_decl (lookup_qualified_name (scope,
name,
! /*is_type_p=*/0,
! /*flags=*/0));
}
else
{
init = DECL_INITIAL (decl);
decl = tsubst (decl, args, complain, in_decl);
--- 7619,7629 ----
tree name = DECL_NAME (decl);
scope = tsubst_expr (scope, args, complain, in_decl);
do_local_using_decl (lookup_qualified_name (scope,
name,
! /*is_type_p=*/0));
}
else
{
init = DECL_INITIAL (decl);
decl = tsubst (decl, args, complain, in_decl);
*************** tsubst_expr (tree t, tree args, tsubst_f
*** 7812,7827 ****
}
/* Like tsubst but deals with expressions and performs semantic
analysis. */
! static tree
tsubst_copy_and_build (tree t,
tree args,
tsubst_flags_t complain,
tree in_decl)
{
if (t == NULL_TREE || t == error_mark_node)
return t;
switch (TREE_CODE (t))
{
--- 7885,7902 ----
}
/* Like tsubst but deals with expressions and performs semantic
analysis. */
! 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;
switch (TREE_CODE (t))
{
*************** tsubst_copy_and_build (tree t,
*** 7857,7878 ****
case TEMPLATE_ID_EXPR:
{
tree object;
tree template
! = tsubst_copy (TREE_OPERAND (t, 0), args, complain, in_decl);
tree targs
! = tsubst_copy (TREE_OPERAND (t, 1), args, complain, in_decl);
if (TREE_CODE (template) == COMPONENT_REF)
{
object = TREE_OPERAND (template, 0);
template = TREE_OPERAND (template, 1);
}
else
object = NULL_TREE;
- maybe_fold_nontype_args (targs);
template = lookup_template_function (template, targs);
if (object)
return build (COMPONENT_REF, TREE_TYPE (template),
object, template);
--- 7932,7954 ----
case TEMPLATE_ID_EXPR:
{
tree object;
tree template
! = tsubst_copy_and_build (TREE_OPERAND (t, 0), args, complain,
! in_decl);
tree targs
! = tsubst_copy_and_build (TREE_OPERAND (t, 1), args, complain,
! in_decl);
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, targs);
if (object)
return build (COMPONENT_REF, TREE_TYPE (template),
object, template);
*************** tsubst_copy_and_build (tree t,
*** 7908,7921 ****
case STATIC_CAST_EXPR:
return build_static_cast
(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:
if (TREE_TYPE (t))
return tsubst_copy (t, args, complain, in_decl);
else
return build_x_unary_op
(TREE_CODE (t),
--- 7984,8008 ----
case STATIC_CAST_EXPR:
return build_static_cast
(tsubst (TREE_TYPE (t), args, complain, in_decl),
tsubst_copy_and_build (TREE_OPERAND (t, 0), args, complain, in_decl));
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
return build_x_unary_op
(TREE_CODE (t),
*************** tsubst_copy_and_build (tree t,
*** 7937,7948 ****
return t;
return build_x_unary_op
(TREE_CODE (t),
tsubst_copy_and_build (TREE_OPERAND (t, 0), args, complain, in_decl));
- case TRUTH_NOT_EXPR:
case ADDR_EXPR:
case CONVERT_EXPR: /* Unary + */
case REALPART_EXPR:
case IMAGPART_EXPR:
if (TREE_TYPE (t))
return tsubst_copy (t, args, complain, in_decl);
--- 8024,8043 ----
return t;
return build_x_unary_op
(TREE_CODE (t),
tsubst_copy_and_build (TREE_OPERAND (t, 0), args, complain, in_decl));
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:
if (TREE_TYPE (t))
return tsubst_copy (t, args, complain, in_decl);
*************** tsubst_copy_and_build (tree t,
*** 7992,8021 ****
return build_m_component_ref
(tsubst_copy_and_build (TREE_OPERAND (t, 0), args, complain, in_decl),
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));
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),
tsubst_copy_and_build (TREE_OPERAND (t, 1), args, complain,
in_decl));
! }
case SIZEOF_EXPR:
case ALIGNOF_EXPR:
{
tree r =
--- 8087,8121 ----
return build_m_component_ref
(tsubst_copy_and_build (TREE_OPERAND (t, 0), args, complain, in_decl),
tsubst_copy_and_build (TREE_OPERAND (t, 1), args, complain, in_decl));
case SCOPE_REF:
! 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));
!
! 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:
{
tree r =
*************** tsubst_copy_and_build (tree t,
*** 8032,8043 ****
(tsubst_copy_and_build (TREE_OPERAND (t, 0), args, complain, in_decl),
TREE_CODE (TREE_OPERAND (t, 1)),
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));
case NEW_EXPR:
return build_new
(tsubst_copy_and_build (TREE_OPERAND (t, 0), args, complain, in_decl),
tsubst_copy_and_build (TREE_OPERAND (t, 1), args, complain, in_decl),
--- 8132,8151 ----
(tsubst_copy_and_build (TREE_OPERAND (t, 0), args, complain, in_decl),
TREE_CODE (TREE_OPERAND (t, 1)),
tsubst_copy_and_build (TREE_OPERAND (t, 2), args, complain, in_decl));
case ARROW_EXPR:
! 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
(tsubst_copy_and_build (TREE_OPERAND (t, 0), args, complain, in_decl),
tsubst_copy_and_build (TREE_OPERAND (t, 1), args, complain, in_decl),
*************** tsubst_copy_and_build (tree t,
*** 8060,8167 ****
in_decl));
else
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;
! 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)
! {
! 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);
! }
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);
!
! 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);
}
}
case COND_EXPR:
return build_x_conditional_expr
--- 8168,8233 ----
in_decl));
else
abort ();
}
! case CALL_EXPR:
{
! tree function;
! tree call_args;
! tree koenig_name;
! bool qualified_p;
!
! 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)
{
! qualified_p = true;
! function = tsubst_qualified_id (function, args, complain, in_decl,
! /*done=*/false,
! /*address_p=*/false);
}
! else
{
! 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);
}
! /* 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);
}
}
case COND_EXPR:
return build_x_conditional_expr
*************** tsubst_copy_and_build (tree t,
*** 8198,8211 ****
return tree_cons (purpose, value, chain);
}
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);
if (!CLASS_TYPE_P (TREE_TYPE (object)))
{
if (TREE_CODE (member) == BIT_NOT_EXPR)
return finish_pseudo_destructor_expr (object,
--- 8264,8294 ----
return tree_cons (purpose, value, chain);
}
case COMPONENT_REF:
{
! 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)))
{
if (TREE_CODE (member) == BIT_NOT_EXPR)
return finish_pseudo_destructor_expr (object,
*************** tsubst_copy_and_build (tree t,
*** 8227,8238 ****
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
--- 8310,8320 ----
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);
if (BASELINK_P (member))
BASELINK_FUNCTIONS (member)
= build_nt (TEMPLATE_ID_EXPR, BASELINK_FUNCTIONS (member),
args);
else
*************** tsubst_copy_and_build (tree t,
*** 8301,8311 ****
case PARM_DECL:
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));
case VA_ARG_EXPR:
return build_x_va_arg
(tsubst_copy_and_build
(TREE_OPERAND (t, 0), args, complain, in_decl),
--- 8383,8395 ----
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);
case VA_ARG_EXPR:
return build_x_va_arg
(tsubst_copy_and_build
(TREE_OPERAND (t, 0), args, complain, in_decl),
*************** value_dependent_expression_p (tree expre
*** 11403,11414 ****
return true;
/* A constant with integral or enumeration type and is initialized
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)
&& value_dependent_expression_p (DECL_INITIAL (expression)))
return true;
/* These expressions are value-dependent if the type to which the
cast occurs is dependent or the expression being casted is
value-dependent. */
--- 11487,11497 ----
return true;
/* A constant with integral or enumeration type and is initialized
with an expression that is value-dependent. */
if (TREE_CODE (expression) == VAR_DECL
&& DECL_INITIAL (expression)
! && 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
cast occurs is dependent or the expression being casted is
value-dependent. */
Index: rtti.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/cp/rtti.c,v
retrieving revision 1.167
diff -c -5 -p -r1.167 rtti.c
*** rtti.c 6 Jul 2003 23:23:45 -0000 1.167
--- rtti.c 8 Jul 2003 01:36:10 -0000
*************** get_tinfo_decl_dynamic (tree exp)
*** 211,225 ****
tree t;
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);
/* Peel off cv qualifiers. */
type = TYPE_MAIN_VARIANT (type);
if (!VOID_TYPE_P (type))
--- 211,222 ----
tree t;
if (exp == error_mark_node)
return error_mark_node;
/* peel back references, so they match. */
! type = non_reference (TREE_TYPE (exp));
/* Peel off cv qualifiers. */
type = TYPE_MAIN_VARIANT (type);
if (!VOID_TYPE_P (type))
*************** get_typeid (tree type)
*** 406,417 ****
return build_min (TYPEID_EXPR, type_info_ref_type, 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);
/* The top-level cv-qualifiers of the lvalue expression or the type-id
that is the operand of typeid are always ignored. */
type = TYPE_MAIN_VARIANT (type);
--- 403,413 ----
return build_min (TYPEID_EXPR, type_info_ref_type, 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. */
! 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. */
type = TYPE_MAIN_VARIANT (type);
Index: search.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/cp/search.c,v
retrieving revision 1.272
diff -c -5 -p -r1.272 search.c
*** search.c 7 Jul 2003 19:11:59 -0000 1.272
--- search.c 8 Jul 2003 01:36:10 -0000
*************** check_final_overrider (tree overrider, t
*** 1710,1722 ****
/* GNU extension, allow trivial pointer conversions such as
converting to void *, or qualification conversion. */
{
/* 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);
if (CLASS_TYPE_P (over_return))
fail = 2;
}
else
fail = 2;
--- 1710,1720 ----
/* GNU extension, allow trivial pointer conversions such as
converting to void *, or qualification conversion. */
{
/* can_convert will permit user defined conversion from a
(reference to) class type. We must reject them. */
! over_return = non_reference (TREE_TYPE (over_type));
if (CLASS_TYPE_P (over_return))
fail = 2;
}
else
fail = 2;
Index: semantics.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/cp/semantics.c,v
retrieving revision 1.323
diff -c -5 -p -r1.323 semantics.c
*** semantics.c 7 Jul 2003 19:11:59 -0000 1.323
--- semantics.c 8 Jul 2003 01:36:10 -0000
*************** finish_non_static_data_member (tree decl
*** 1274,1283 ****
--- 1274,1396 ----
/*access_path=*/NULL_TREE,
/*preserve_reference=*/false);
}
}
+ /* 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. */
tree
begin_stmt_expr (void)
*************** finish_object_call_expr (tree fn, tree o
*** 1544,1563 ****
if (name_p (fn))
return build_method_call (object, fn, args, NULL_TREE, LOOKUP_NORMAL);
else
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
--- 1657,1666 ----
Index: typeck.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/cp/typeck.c,v
retrieving revision 1.475
diff -c -5 -p -r1.475 typeck.c
*** typeck.c 7 Jul 2003 19:11:58 -0000 1.475
--- typeck.c 8 Jul 2003 01:36:10 -0000
*************** static tree lookup_destructor (tree, tre
*** 70,81 ****
T*, T&, T[], T (...), and otherwise, just T. */
tree
target_type (tree type)
{
! if (TREE_CODE (type) == REFERENCE_TYPE)
! type = TREE_TYPE (type);
while (TREE_CODE (type) == POINTER_TYPE
|| TREE_CODE (type) == ARRAY_TYPE
|| TREE_CODE (type) == FUNCTION_TYPE
|| TREE_CODE (type) == METHOD_TYPE
|| TREE_CODE (type) == OFFSET_TYPE)
--- 70,80 ----
T*, T&, T[], T (...), and otherwise, just T. */
tree
target_type (tree type)
{
! type = non_reference (type);
while (TREE_CODE (type) == POINTER_TYPE
|| TREE_CODE (type) == ARRAY_TYPE
|| TREE_CODE (type) == FUNCTION_TYPE
|| TREE_CODE (type) == METHOD_TYPE
|| TREE_CODE (type) == OFFSET_TYPE)
*************** cxx_sizeof_or_alignof_type (tree type, e
*** 1419,1431 ****
my_friendly_assert (op == SIZEOF_EXPR || op == ALIGNOF_EXPR, 20020720);
if (processing_template_decl)
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_code = TREE_CODE (type);
if (type_code == METHOD_TYPE)
{
if (complain && (pedantic || warn_pointer_arith))
--- 1418,1429 ----
my_friendly_assert (op == SIZEOF_EXPR || op == ALIGNOF_EXPR, 20020720);
if (processing_template_decl)
return build_min_nt (op, type);
op_name = operator_name_info[(int) op].name;
!
! type = non_reference (type);
type_code = TREE_CODE (type);
if (type_code == METHOD_TYPE)
{
if (complain && (pedantic || warn_pointer_arith))
*************** pfn_from_ptrmemfunc (tree t)
*** 5886,5897 ****
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);
/* Issue warnings about peculiar, but valid, uses of NULL. */
if (ARITHMETIC_TYPE_P (type) && expr == null_node)
{
if (fndecl)
--- 5884,5894 ----
tree
dubious_conversion_warnings (tree type, tree expr,
const char *errtype, tree fndecl, int parmnum)
{
! type = non_reference (type);
/* Issue warnings about peculiar, but valid, uses of NULL. */
if (ARITHMETIC_TYPE_P (type) && expr == null_node)
{
if (fndecl)
*************** convert_for_initialization (tree exp, tr
*** 6100,6111 ****
if (exp != 0)
exp = require_complete_type (exp);
if (exp == error_mark_node)
return error_mark_node;
! if (TREE_CODE (rhstype) == REFERENCE_TYPE)
! rhstype = TREE_TYPE (rhstype);
type = complete_type (type);
if (IS_AGGR_TYPE (type))
return ocp_convert (type, rhs, CONV_IMPLICIT|CONV_FORCE_TEMP, flags);
--- 6097,6107 ----
if (exp != 0)
exp = require_complete_type (exp);
if (exp == error_mark_node)
return error_mark_node;
! rhstype = non_reference (rhstype);
type = complete_type (type);
if (IS_AGGR_TYPE (type))
return ocp_convert (type, rhs, CONV_IMPLICIT|CONV_FORCE_TEMP, flags);
*************** strip_all_pointer_quals (tree type)
*** 6705,6710 ****
--- 6701,6717 ----
else if (TREE_CODE (type) == OFFSET_TYPE)
return build_offset_type (TYPE_OFFSET_BASETYPE (type),
strip_all_pointer_quals (TREE_TYPE (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;
}