+Mon Mar 13 21:00:28 1995 Brendan Kehoe (brendan@lisa.cygnus.com)
+
+ * decl.c (grokdeclarator, case ARRAY_REF): Wrap the exp with fold,
+ and convert the size and integer_one_node to the index type.
+
+Mon Mar 13 08:01:02 1995 Jason Merrill <jason@phydeaux.cygnus.com>
+
+ * typeck.c (get_member_function_from_ptrfunc): Save the instance
+ argument, and tack it onto the front of the COND_EXPR to make the
+ semantics come out right. Grab the instance argument from
+ '*instance_ptrptr', rather than having it passed in separately.
+
+ * various: Change various consed-up comparison operations to have
+ boolean type. Remove the instance argument in calls to
+ get_member_function_from_ptrfunc.
+
+ * error.c (dump_expr): Dump true and false as "true" and "false".
+
+ * decl2.c (finish_file): Also set DECL_STATIC_FUNCTION_P on the
+ global init function.
+
+ * decl.c (finish_function): Only set DECL_EXTERNAL here if the
+ inline function is public.
+
+Sat Mar 11 00:58:03 1995 Jason Merrill <jason@phydeaux.cygnus.com>
+
+ * init.c (is_friend): Be more careful about checking
+ DECL_CLASS_CONTEXT on non-member functions.
+
+ * decl2.c (finish_vtable_vardecl): Don't bother calling
+ assemble_external here.
+ (prune_vtable_vardecl): New function that just splices out the
+ vtable decl from the top-level decls.
+ (import_export_inline): Unset DECL_EXTERNAL at first.
+ (finish_file): Don't bother calling assemble_external here. Do
+ splice out all of the vtables.
+
+Fri Mar 10 14:42:29 1995 Jason Merrill <jason@phydeaux.cygnus.com>
+
+ * decl.c (finish_function): If we're not emitting the function yet,
+ call assemble_external for it.
+
+ * decl2.c (finish_prevtable_vardecl): Don't call mark_vtable_entries
+ here.
+ (finish_vtable_vardecl): Don't do the linkage deduction thing here.
+ Also don't splice out the current vtable if it is unused.
+ (finish_file): Move the second walk_vtables and the synthesis check
+ inside the 'reconsider' loop. Move thunk emission after the
+ 'reconsider' loop.
+
+Thu Mar 9 16:28:16 1995 Brendan Kehoe (brendan@lisa.cygnus.com)
+
+ * pt.c (tsubst): Don't bother calling cp_build_type_variant, since it
+ was passing bogus values for readonly and volatile from the original
+ template decl, not the resultant type of the tsubst call.
+
+ * class.c (duplicate_tag_error): Use cp_error_at to point out the
+ previous definition of the tag.
+
+Thu Mar 9 10:46:17 1995 Jason Merrill <jason@phydeaux.cygnus.com>
+
+ * decl.c (start_function): Clear base_init_insns and protect_list.
+ (struct cp_function): Add base_init_insns field.
+ (push_cp_function_context): Also save base_init_insns.
+ (pop_cp_function_context): Also restore base_init_insns.
+
+Wed Mar 8 13:31:44 1995 Jason Merrill <jason@phydeaux.cygnus.com>
+
+ * init.c (member_init_ok_or_else): Check for initializing a static
+ member here.
+ (emit_base_init): Instead of here.
+
+Tue Mar 7 16:03:26 1995 Jason Merrill <jason@phydeaux.cygnus.com>
+
+ * call.c (build_method_call): Disable synthesis as needed.
+ * lex.c (cons_up_default_function): Ditto.
+
Tue Mar 7 10:14:29 1995 Brendan Kehoe (brendan@lisa.cygnus.com)
* parse.y: New rules to allow attributes in a prefix position.
(grokdeclarator): Added code to support machine attributes.
* Makefile.in (stamp-parse): Expect 5 shift/reduce failures.
+Mon Mar 6 15:07:02 1995 Jason Merrill <jason@phydeaux.cygnus.com>
+
+ * call.c (build_method_call): Don't synthesize methods outside of a
+ function.
+
+ Make base initialization more re-entrant so that synthesis on the
+ fly will work (and, eventually, template instantation on the fly).
+ * init.c (sort_member_init): Don't bother with members that can't be
+ initialized. Reorganize a bit. Don't initialize base members here.
+ (sort_base_init): New function, like sort_member_init, but for base
+ classes. Steals some code from emit_base_init.
+ (emit_base_init): Simplify. Call sort_{member,base}_init before
+ doing any initialization, so we don't have to save
+ current_{member,base}_init_list in push_cp_function_context.
+ (expand_aggr_vbase_init_1): Adjust for sort_base_init.
+ (expand_aggr_vbase_init): Simplify.
+ * decl.c (struct cp_function): Add protect_list field.
+ (push_cp_function_context): Also save protect_list.
+ (pop_cp_function_context): Also restore protect_list.
+ * call.c (build_method_call): Enable synthesis at point of call.
+ * lex.c (cons_up_default_function): Ditto.
+
+ * parse.y: Turn -ansi checks back into -pedantic checks.
+
+ * init.c (build_new): Fix -fcheck-new for array new.
+
+Sat Mar 4 15:55:42 1995 Fergus Henderson <fjh@cs.mu.oz.au>
+
+ * typeck.c (build_compound_expr): warn if left-hand operand of
+ comma expression has no side-effects.
+
+Fri Mar 3 15:16:45 1995 Jason Merrill <jason@phydeaux.cygnus.com>
+
+ * parse.y (primary): Change 'object qualified_id *' rules to 'object
+ overqualified_id *'.
+
+Fri Mar 3 12:48:17 1995 Brendan Kehoe (brendan@lisa.cygnus.com)
+
+ * parse.y (unary_expr): Catch doing sizeof an overloaded function.
+ Make the error look the same as the one we issue in c_sizeof.
+
+ * typeck.c (build_binary_op_nodefault): Give an error for trying
+ to compare a pointer-to-member to `void *'.
+
+Fri Mar 3 11:28:50 1995 Jason Merrill <jason@phydeaux.cygnus.com>
+
+ * typeck.c (build_unary_op): Handle bool increment with smoke and
+ mirrors here, rather than in expand_increment where it belongs,
+ because Kenner doesn't agree with me.
+
+Fri Mar 3 00:08:10 1995 Brendan Kehoe (brendan@lisa.cygnus.com)
+
+ * decl.c (grokparms): Catch a PARM_DECL being used for a default
+ argument as well.
+
+Thu Mar 2 20:05:54 1995 Brendan Kehoe (brendan@lisa.cygnus.com)
+
+ * init.c (build_new): Don't allow new on a function type.
+
+ * parse.y (primary): Avoid a crash when seeing if the arg is of
+ the same type as that given for the typespec in an explicit dtor call.
+
+Thu Mar 2 00:49:38 1995 Jason Merrill <jason@phydeaux.cygnus.com>
+
+ * decl.c (finish_function): Change test for calling
+ mark_inline_for_output.
+
+Wed Mar 1 11:23:46 1995 Jason Merrill <jason@phydeaux.cygnus.com>
+
+ * typeck.c (build_modify_expr): Complain if
+ build_default_binary_type_conversion fails.
+
+ * init.c (expand_default_init): Handle arguments of unknown type
+ properly.
+
+ * cvt.c (build_expr_type_conversion): Only complain about ambiguity
+ if 'complain'.
+ * various: Pass 'complain'.
+
+ * typeck.c (comptypes): Be more picky about comparing UPTs.
+
+Wed Mar 1 11:03:41 1995 Brendan Kehoe (brendan@lisa.cygnus.com)
+
+ * decl.c (grokdeclarator): If declarator is null, say that the
+ type used has an incomplete type.
+
+Wed Mar 1 10:06:20 1995 Jason Merrill <jason@phydeaux.cygnus.com>
+
+ * pt.c (instantiate_template): Copy the template arguments to the
+ permanent_obstack. Also use simple_cst_equal to compare them when
+ looking for a previous instantiation.
+
+ * tree.c (make_deep_copy): Support copying INTEGER_TYPEs (assuming
+ they are array domain types).
+
+Tue Feb 28 23:24:55 1995 Jason Merrill <jason@phydeaux.cygnus.com>
+
+ * cp-tree.h: Define WANT_* constants for passing to
+ build_expr_type_conversion.
+ * cvt.c (build_expr_type_conversion): New function to build
+ conversion to one of a group of suitable types.
+ (build_default_binary_type_conversion): Use it.
+ * decl2.c (grok_array_decl): Ditto.
+ * typeck.c (build_unary_op): Ditto.
+ (build_array_ref): Tidy up a bit.
+ (build_binary_op): Ditto.
+
+Tue Feb 28 19:57:31 1995 Brendan Kehoe (brendan@lisa.cygnus.com)
+
+ * decl.c (grokdeclarator): Don't allow decl of an argument as `void'.
+
+Tue Feb 28 17:23:36 1995 Jason Merrill <jason@phydeaux.cygnus.com>
+
+ * parse.y (typed_declspecs1): Add 'typespec reserved_typespecquals
+ reserved_declspecs' rule.
+
+ * parse.y (expr_or_declarator): Remove notype_qualified_id rule.
+ (direct_notype_declarator): Ditto.
+ (complex_direct_notype_declarator): Add notype_qualified_id rule.
+
+ * lex.c (real_yylex): Handle :> digraph properly.
+
+Tue Feb 28 12:26:29 1995 Brendan Kehoe (brendan@lisa.cygnus.com)
+
+ * decl.c (grokdeclarator): Check if it's a friend, not if it's
+ non-virtual, that's being initialized. Move the check up to
+ before FRIENDP would get cleared. Catch an unnamed var/field
+ being declared void. Say just `field' instead of `structure field'
+ in the error message. Only go for the operator name if DECLARATOR
+ is non-null.
+
+Tue Feb 28 00:08:01 1995 Jason Merrill <jason@phydeaux.cygnus.com>
+
+ * decl.c (start_function): Complain about abstract return type.
+ (grokdeclarator): Complain about declaring constructors and
+ destructors to be const or volatile. Complain about declaring
+ destructors to be static.
+
+ * pt.c (uses_template_parms): Handle pmfs.
+
+ * decl.c (grokdeclarator): Don't call variable_size for array bounds
+ that only depend on template constant parameters.
+
+Mon Feb 27 15:38:16 1995 Brendan Kehoe (brendan@lisa.cygnus.com)
+
+ * error.c (dump_decl): Only look to see if it's a vtable if we
+ actually have a name to check out.
+
+Mon Feb 27 13:37:53 1995 Jason Merrill <jason@phydeaux.cygnus.com>
+
+ * cvt.c (convert_to_aggr): Lose misleading shortcut.
+
+Sun Feb 26 17:27:32 1995 Doug Evans <dje@canuck.cygnus.com>
+
+ * decl.c (set_nested_typename): Always set DECL_IGNORED_P,
+ not just for dwarf.
+
+Sun Feb 26 00:10:18 1995 Brendan Kehoe (brendan@lisa.cygnus.com)
+
+ * decl.c (grokdeclarator): Don't allow a static member to be
+ declared `register'.
+
+ * init.c (make_friend_class): Move up to a pedwarn for the warning
+ about a class declaring friends with itself.
+
+ * decl.c (grokdeclarator): You can't do `volatile friend class foo'
+ or `inline friend class foo'. Only try to make a friend out of
+ TYPE if we didn't already reset it to integer_type_node.
+
+Sat Feb 25 22:32:03 1995 Brendan Kehoe (brendan@lisa.cygnus.com)
+
+ * decl.c (grokdeclarator): Don't allow initialization of a
+ non-virtual function.
+
+ * decl.c (start_function): Do a pedwarn if we're changing `main'
+ to have an int return type.
+
+Sat Feb 25 00:02:05 1995 Jason Merrill <jason@phydeaux.cygnus.com>
+
+ * typeck.c (build_modify_expr): Handle simple assignment from
+ TARGET_EXPRs by building up an RTL_EXPR to force expansion. Whew.
+
+Fri Feb 24 18:27:14 1995 Brendan Kehoe (brendan@lisa.cygnus.com)
+
+ * decl.c (grokdeclarator): Also don't allow virtual outside of a
+ class decl for a scope method definition performed at global binding.
+
+ * init.c (build_offset_ref): Don't allow creation of an OFFSET_REF
+ of a bitfield.
+
+ * decl.c (grokdeclarator): Don't allow a const to be declared mutable.
+
+ * typeck.c (build_binary_op): Return an error_mark_node if either
+ one of the args turned into an error_mark_node when we tried to
+ use default_conversion.
+
+ * typeck.c (build_unary_op): Forbid using postfix -- on a bool.
+
+ * decl.c (grokdeclarator): Allow `signed' and `unsigned' to be
+ used on `__wchar_t'.
+
+Fri Feb 24 13:59:53 1995 Mike Stump <mrs@cygnus.com>
+
+ * except.c (end_protect_partials): Do it the right way.
+
+Wed Feb 22 15:42:56 1995 Jason Merrill <jason@phydeaux.cygnus.com>
+
+ * typeck.c (build_binary_op_nodefault): Upgrade warning about
+ comparing distinct pointer types to pedwarn.
+
+ * typeck2.c (digest_init): Cope with extra braces.
+
+ * typeck.c (build_binary_op_nodefault): Use tree_int_cst_sgn instead
+ of INT_CST_LT (..., interger_zero_node).
+
+Wed Feb 22 14:45:52 1995 Brendan Kehoe (brendan@lisa.cygnus.com)
+
+ * except.c [!TRY_NEW_EH] (end_protect_partials): Define dummy
+ function for systems that don't have EH.
+
+Tue Feb 21 19:18:31 1995 Jason Merrill <jason@phydeaux.cygnus.com>
+
+ * call.c (can_convert_arg): Like can_convert, but takes an arg as
+ well.
+
+ * pt.c (type_unification): Allow implicit conversions for parameters
+ that do not depend on template parameters.
+
Tue Feb 21 18:43:48 1995 Douglas Rupp (drupp@cs.washington.edu)
* Make-lang.in, config-lang.in: ($exeext): New macro.
* cp/g++.c: Added #ifdefs for sys/file.h and process.h for NT.
Modified spawnvp to have to correct number of arguments for OS/2, NT.
-Thu Feb 2 15:07:58 1995 Jason Merrill <jason@phydeaux.cygnus.com>
+Tue Feb 21 18:36:55 1995 Mike Stump <mrs@cygnus.com>
+
+ * decl.c (finish_function): Add calls to end_protect_partials to end
+ the exception region that protects constructors so that partially
+ constructed objects can be partially destructed when the constructor
+ throws an exception.
+ * init.c (perform_member_init, sort_member_init, emit_base_init):
+ Added support for partially constructed objects.
+ * init.c (build_partial_cleanup_for): New routine to do partial
+ cleanups of a base class.
+ * decl2.c (finish_file): Move the emitting of the exception table
+ down, after we emit all code that might have exception regions in
+ them.
+ * except.c (end_protect_partials, might_have_exceptions_p): New
+ routines.
+ (emit_exception_table): Always output table if called.
+ * cp-tree.h (protect_list, end_protect_partials,
+ might_have_exceptions_p, emit_exception_table): Added.
+
+Tue Feb 21 16:05:59 1995 Brendan Kehoe (brendan@lisa.cygnus.com)
+
+ * gc.c (build_typeid): Pass a NULL_TREE, not the bogus, unused
+ address of a local variable.
+ * class.c (build_vfn_ref): Only try to build the PLUS_EXPR if we
+ were given a non-null PTR_TO_INSTPTR.
+
+Tue Feb 21 01:53:18 1995 Jason Merrill <jason@phydeaux.cygnus.com>
+
+ * decl.c (duplicate_decls): Always lay out the merged decl.
+
+ * decl2.c (finish_vtable_vardecl): Don't do vtable hack on templates.
+ (finish_prevtable_vardecl): Ditto.
- * class.c (build_vbase_path): Bash types to make the backend happy.
- * cvt.c (build_up_reference): Bash the types bashed by
- build_vbase_path to be reference types instead of pointer types.
- (convert_to_reference): Ditto.
+ * method.c (synthesize_method): Set interface_{unknown,only}
+ according to the settings for our class, not the file where it comes
+ from.
-Wed Jan 25 15:02:09 1995 David S. Miller (davem@nadzieja.rutgers.edu)
+Sat Feb 18 12:26:48 1995 Mike Stump <mrs@cygnus.com>
- * class.c (instantiate_type): Change error message text.
- * typeck2.c (store_init_value): Likewise.
+ * except.c: Handle systems that define __i386__ but not __i386.
Fri Feb 17 15:31:31 1995 Jason Merrill <jason@phydeaux.cygnus.com>
* typeck2.c (build_functional_cast): Don't assume that a NOP_EXPR
will suffice to convert from integer_zero_node.
+Wed Jan 25 15:02:09 1995 David S. Miller (davem@nadzieja.rutgers.edu)
+
+ * class.c (instantiate_type): Change error message text.
+ * typeck2.c (store_init_value): Likewise.
+
Mon Jan 23 21:57:14 1995 Mike Stump <mrs@cygnus.com>
* pt.c (tsubst): When we copy a node, don't forget to copy
* Language directory reorganization.
See parent makefile.
-Fri Apr 22 03:27:26 1994 Doug Evans (dje@cygnus.com)
-
- * Language directory reorganization.
- See parent makefile.
-
Thu Apr 21 18:27:57 1994 Per Bothner (bothner@kalessin.cygnus.com)
* cp-tree.h (THUNK_DELTA): It is normally negative, so
$(CC) -c $(ALL_CFLAGS) $(ALL_CPPFLAGS) $(INCLUDES) $(BIG_SWITCHFLAG) \
`echo $(PARSE_C) | sed 's,^\./,,'`
+CONFLICTS = expect 5 shift/reduce confict and 38 reduce/reduce conflicts.
$(PARSE_H) : $(PARSE_C)
$(PARSE_C) : $(srcdir)/parse.y
- @echo expect 5 shift/reduce confict and 39 reduce/reduce conflicts.
+ @echo $(CONFLICTS)
cd $(srcdir); $(BISON) $(BISONFLAGS) -d -o parse.c parse.y
cd $(srcdir); grep '^#define[ ]*YYEMPTY' parse.c >>parse.h
#$(PARSE_C) $(PARSE_H) : stamp-parse ; @true
#stamp-parse: $(srcdir)/parse.y
-# @echo expect 1 shift/reduce confict and 39 reduce/reduce conflicts.
+# @echo $(CONFLICTS)
# $(BISON) $(BISONFLAGS) -d $(srcdir)/parse.y
# grep '^#define[ ]*YYEMPTY' y.tab.c >>y.tab.h
# $(srcdir)/../move-if-change y.tab.c $(PARSE_C)
return h.code < USER_CODE;
}
+int
+can_convert_arg (to, from, arg)
+ tree to, from, arg;
+{
+ struct harshness_code h;
+ h = convert_harshness (to, from, arg);
+ return h.code < USER_CODE;
+}
+
#ifdef DEBUG_MATCHING
static char *
print_harshness (h)
assemble_external (function);
#if 0
+ /* Is it a synthesized method that needs to be synthesized? */
if (DECL_ARTIFICIAL (function) && ! flag_no_inline
&& DECL_SAVED_INSNS (function) == 0
- && ! TREE_ASM_WRITTEN (function))
+ && ! TREE_ASM_WRITTEN (function)
+ /* Kludge: don't synthesize for default args. */
+ && current_function_decl)
synthesize_method (function);
#endif
{
null_expr = build1 (NOP_EXPR, TYPE_POINTER_TO (last_virtual), integer_zero_node);
expr = build (COND_EXPR, TYPE_POINTER_TO (last_virtual),
- build (EQ_EXPR, integer_type_node, expr,
+ build (EQ_EXPR, boolean_type_node, expr,
integer_zero_node),
null_expr, nonnull_expr);
}
expr = save_expr (expr);
return build (COND_EXPR, type,
- build (EQ_EXPR, integer_type_node, expr, integer_zero_node),
+ build (EQ_EXPR, boolean_type_node, expr, integer_zero_node),
null_expr,
build (code, type, expr, offset));
}
return aref;
else
{
- *ptr_to_instptr
- = build (PLUS_EXPR, TREE_TYPE (*ptr_to_instptr),
- *ptr_to_instptr,
- convert (ptrdiff_type_node,
- build_component_ref (aref, delta_identifier, 0, 0)));
+ if (ptr_to_instptr)
+ *ptr_to_instptr
+ = build (PLUS_EXPR, TREE_TYPE (*ptr_to_instptr),
+ *ptr_to_instptr,
+ convert (ptrdiff_type_node,
+ build_component_ref (aref, delta_identifier, 0, 0)));
return build_component_ref (aref, pfn_identifier, 0, 0);
}
}
tree t;
{
cp_error ("redefinition of `%#T'", t);
+ cp_error_at ("previous definition here", t);
/* Pretend we haven't defined this type. */
#define CONV_C_CAST (CONV_IMPLICIT | CONV_STATIC | CONV_CONST \
| CONV_REINTERPRET | CONV_PRIVATE | CONV_FORCE_TEMP)
+/* Used by build_expr_type_conversion to indicate which types are
+ acceptable as arguments to the expression under consideration. */
+
+#define WANT_INT 1 /* integer types, including bool */
+#define WANT_FLOAT 2 /* floating point types */
+#define WANT_ENUM 4 /* enumerated types */
+#define WANT_POINTER 8 /* pointer types */
+#define WANT_NULL 16 /* null pointer constant */
+
+#define WANT_ARITH (WANT_INT | WANT_FLOAT)
+
/* Anatomy of a DECL_FRIENDLIST (which is a TREE_LIST):
purpose = friend name (IDENTIFIER_NODE);
value = TREE_LIST of FUNCTION_DECLS;
extern tree cp_convert PROTO((tree, tree, int, int));
extern tree convert_force PROTO((tree, tree, int));
extern tree build_type_conversion PROTO((enum tree_code, tree, tree, int));
+extern tree build_expr_type_conversion PROTO((int, tree, int));
extern int build_default_binary_type_conversion PROTO((enum tree_code, tree *, tree *));
-extern int build_default_unary_type_conversion PROTO((enum tree_code, tree *));
extern tree type_promotes_to PROTO((tree));
/* decl.c */
/* in edsel.c */
/* in except.c */
-
+extern tree protect_list;
extern void start_protect PROTO((void));
extern void end_protect PROTO((tree));
+extern void end_protect_partials ();
extern void expand_exception_blocks PROTO((void));
extern void expand_start_try_stmts PROTO((void));
extern void expand_end_try_stmts PROTO((void));
extern void start_catch_block PROTO((tree, tree));
extern void end_catch_block PROTO((void));
extern void expand_throw PROTO((tree));
-extern int build_exception_table PROTO((void));
+extern int might_have_exceptions_p PROTO((void));
+extern void emit_exception_table PROTO((void));
extern tree build_throw PROTO((tree));
extern void init_exception_processing PROTO((void));
extern tree build_member_call PROTO((tree, tree, tree));
extern tree build_offset_ref PROTO((tree, tree));
extern tree get_member_function PROTO((tree *, tree, tree));
-extern tree get_member_function_from_ptrfunc PROTO((tree *, tree, tree));
+extern tree get_member_function_from_ptrfunc PROTO((tree *, tree));
extern tree resolve_offset_ref PROTO((tree));
extern tree decl_constant_value PROTO((tree));
extern int is_friend_type PROTO((tree, tree));
parmlist = tree_cons (NULL_TREE, integer_zero_node, parmlist);
parmtypes = tree_cons (NULL_TREE, TYPE_POINTER_TO (basetype), parmtypes);
+#if 0
method_name = build_decl_overload (name, parmtypes, 1);
/* constructors are up front. */
}
fndecl = DECL_CHAIN (fndecl);
}
+#endif
/* No exact conversion was found. See if an approximate
one will do. */
{
cp_error ("ambiguous conversion from `%T' to `%T'", basetype,
xtype);
- cp_error (" candidate conversion functions include `%T' and `%T'",
+ cp_error (" candidate conversions include `%T' and `%T'",
TREE_VALUE (winner), TREE_VALUE (conv));
return NULL_TREE;
}
return NULL_TREE;
}
-/* Must convert two aggregate types to non-aggregate type.
- Attempts to find a non-ambiguous, "best" type conversion.
-
- Return 1 on success, 0 on failure.
+/* Convert the given EXPR to one of a group of types suitable for use in an
+ expression. DESIRES is a combination of various WANT_* flags (q.v.)
+ which indicates which types are suitable. If COMPLAIN is 1, complain
+ about ambiguity; otherwise, the caller will deal with it. */
- @@ What are the real semantics of this supposed to be??? */
-int
-build_default_binary_type_conversion (code, arg1, arg2)
- enum tree_code code;
- tree *arg1, *arg2;
+tree
+build_expr_type_conversion (desires, expr, complain)
+ int desires;
+ tree expr;
+ int complain;
{
- tree type1 = TREE_TYPE (*arg1);
- tree type2 = TREE_TYPE (*arg2);
-
- if (TREE_CODE (type1) == REFERENCE_TYPE
- || TREE_CODE (type1) == POINTER_TYPE)
- type1 = TREE_TYPE (type1);
- if (TREE_CODE (type2) == REFERENCE_TYPE
- || TREE_CODE (type2) == POINTER_TYPE)
- type2 = TREE_TYPE (type2);
+ tree basetype = TREE_TYPE (expr);
+ tree conv;
+ tree winner = NULL_TREE;
- if (TREE_CODE (TYPE_NAME (type1)) != TYPE_DECL)
+ if (TREE_CODE (basetype) == OFFSET_TYPE)
{
- tree decl = typedecl_for_tag (type1);
- if (decl)
- error ("type conversion nonexistent for type `%s'",
- IDENTIFIER_POINTER (DECL_NAME (decl)));
- else
- error ("type conversion nonexistent for non-C++ type");
- return 0;
- }
- if (TREE_CODE (TYPE_NAME (type2)) != TYPE_DECL)
- {
- tree decl = typedecl_for_tag (type2);
- if (decl)
- error ("type conversion nonexistent for type `%s'",
- IDENTIFIER_POINTER (decl));
- else
- error ("type conversion nonexistent for non-C++ type");
- return 0;
+ expr = resolve_offset_ref (expr);
+ basetype = TREE_TYPE (expr);
}
- if (!IS_AGGR_TYPE (type1) || !TYPE_HAS_CONVERSION (type1))
- {
- if (!IS_AGGR_TYPE (type2) || !TYPE_HAS_CONVERSION (type2))
- cp_error ("no conversion from `%T' and `%T' to types with default `%O' ",
- type1, type2, code);
- else
- cp_error ("no conversion from `%T' to type with default `%O'",
- type1, code);
- return 0;
- }
- else if (!IS_AGGR_TYPE (type2) || !TYPE_HAS_CONVERSION (type2))
- {
- cp_error ("no conversion from `%T' to type with default `%O'",
- type2, code);
- return 0;
- }
+ if (! IS_AGGR_TYPE (basetype))
+ switch (TREE_CODE (basetype))
+ {
+ case INTEGER_TYPE:
+ if ((desires & WANT_NULL) && TREE_CODE (expr) == INTEGER_CST
+ && integer_zerop (expr))
+ return expr;
+ /* else fall through... */
+
+ case BOOLEAN_TYPE:
+ return (desires & WANT_INT) ? expr : NULL_TREE;
+ case ENUMERAL_TYPE:
+ return (desires & WANT_ENUM) ? expr : NULL_TREE;
+ case REAL_TYPE:
+ return (desires & WANT_FLOAT) ? expr : NULL_TREE;
+ case POINTER_TYPE:
+ return (desires & WANT_POINTER) ? expr : NULL_TREE;
+
+ case FUNCTION_TYPE:
+ case ARRAY_TYPE:
+ return (desires & WANT_POINTER) ? default_conversion (expr)
+ : NULL_TREE;
+ default:
+ return NULL_TREE;
+ }
- if (code == TRUTH_ANDIF_EXPR
- || code == TRUTH_ORIF_EXPR)
- {
- *arg1 = convert (boolean_type_node, *arg1);
- *arg2 = convert (boolean_type_node, *arg2);
- }
- else if (TYPE_HAS_INT_CONVERSION (type1))
- {
- if (TYPE_HAS_REAL_CONVERSION (type1))
- cp_pedwarn ("ambiguous type conversion for type `%T', defaulting to int",
- type1);
- *arg1 = build_type_conversion (code, integer_type_node, *arg1, 1);
- *arg2 = build_type_conversion (code, integer_type_node, *arg2, 1);
- }
- else if (TYPE_HAS_REAL_CONVERSION (type1))
- {
- *arg1 = build_type_conversion (code, double_type_node, *arg1, 1);
- *arg2 = build_type_conversion (code, double_type_node, *arg2, 1);
- }
- else
- {
- *arg1 = build_type_conversion (code, ptr_type_node, *arg1, 1);
- if (*arg1 == error_mark_node)
- error ("ambiguous pointer conversion");
- *arg2 = build_type_conversion (code, ptr_type_node, *arg2, 1);
- if (*arg1 != error_mark_node && *arg2 == error_mark_node)
- error ("ambiguous pointer conversion");
- }
- if (*arg1 == 0)
- {
- if (*arg2 == 0 && type1 != type2)
- cp_error ("default type conversion for types `%T' and `%T' failed",
- type1, type2);
- else
- cp_error ("default type conversion for type `%T' failed", type1);
- return 0;
- }
- else if (*arg2 == 0)
+ if (! TYPE_HAS_CONVERSION (basetype))
+ return NULL_TREE;
+
+ for (conv = lookup_conversions (basetype); conv; conv = TREE_CHAIN (conv))
{
- cp_error ("default type conversion for type `%T' failed", type2);
- return 0;
+ int win = 0;
+
+ if (winner && TREE_PURPOSE (winner) == TREE_PURPOSE (conv))
+ continue;
+
+ switch (TREE_CODE (TREE_VALUE (conv)))
+ {
+ case BOOLEAN_TYPE:
+ case INTEGER_TYPE:
+ win = (desires & WANT_INT); break;
+ case ENUMERAL_TYPE:
+ win = (desires & WANT_ENUM); break;
+ case REAL_TYPE:
+ win = (desires & WANT_FLOAT); break;
+ case POINTER_TYPE:
+ win = (desires & WANT_POINTER); break;
+ }
+
+ if (win)
+ {
+ if (winner)
+ {
+ if (complain)
+ {
+ cp_error ("ambiguous default type conversion from `%T'",
+ basetype);
+ cp_error (" candidate conversions include `%T' and `%T'",
+ TREE_VALUE (winner), TREE_VALUE (conv));
+ }
+ return error_mark_node;
+ }
+ else
+ winner = conv;
+ }
}
- return 1;
+
+ if (winner)
+ return build_type_conversion_1 (TREE_VALUE (winner), basetype, expr,
+ TREE_PURPOSE (winner), 1);
+
+ return NULL_TREE;
}
-/* Must convert an aggregate type to non-aggregate type.
+/* Must convert two aggregate types to non-aggregate type.
Attempts to find a non-ambiguous, "best" type conversion.
Return 1 on success, 0 on failure.
- The type of the argument is expected to be of aggregate type here.
-
@@ What are the real semantics of this supposed to be??? */
int
-build_default_unary_type_conversion (code, arg)
+build_default_binary_type_conversion (code, arg1, arg2)
enum tree_code code;
- tree *arg;
+ tree *arg1, *arg2;
{
- tree type = TREE_TYPE (*arg);
-
- if (! TYPE_HAS_CONVERSION (type))
+ switch (code)
{
- cp_error ("type conversion required for type `%T'", type);
- return 0;
- }
+ case MULT_EXPR:
+ case TRUNC_DIV_EXPR:
+ case CEIL_DIV_EXPR:
+ case FLOOR_DIV_EXPR:
+ case ROUND_DIV_EXPR:
+ case EXACT_DIV_EXPR:
+ *arg1 = build_expr_type_conversion (WANT_ARITH | WANT_ENUM, *arg1, 0);
+ *arg2 = build_expr_type_conversion (WANT_ARITH | WANT_ENUM, *arg2, 0);
+ break;
- if (code == TRUTH_NOT_EXPR)
- *arg = convert (boolean_type_node, *arg);
- else if (TYPE_HAS_INT_CONVERSION (type))
- {
- if (TYPE_HAS_REAL_CONVERSION (type))
- cp_pedwarn ("ambiguous type conversion for type `%T', defaulting to int",
- type);
- *arg = build_type_conversion (code, integer_type_node, *arg, 1);
- }
- else if (TYPE_HAS_REAL_CONVERSION (type))
- *arg = build_type_conversion (code, double_type_node, *arg, 1);
- else
- {
- *arg = build_type_conversion (code, ptr_type_node, *arg, 1);
- if (*arg == error_mark_node)
- error ("ambiguous pointer conversion");
- }
- if (*arg == NULL_TREE)
- {
- cp_error ("default type conversion for type `%T' failed", type);
- return 0;
+ case TRUNC_MOD_EXPR:
+ case FLOOR_MOD_EXPR:
+ case LSHIFT_EXPR:
+ case RSHIFT_EXPR:
+ case BIT_AND_EXPR:
+ case BIT_XOR_EXPR:
+ case BIT_IOR_EXPR:
+ *arg1 = build_expr_type_conversion (WANT_INT | WANT_ENUM, *arg1, 0);
+ *arg2 = build_expr_type_conversion (WANT_INT | WANT_ENUM, *arg2, 0);
+ break;
+
+ case PLUS_EXPR:
+ {
+ tree a1, a2, p1, p2;
+ int wins;
+
+ a1 = build_expr_type_conversion (WANT_ARITH | WANT_ENUM, *arg1, 0);
+ a2 = build_expr_type_conversion (WANT_ARITH | WANT_ENUM, *arg2, 0);
+ p1 = build_expr_type_conversion (WANT_POINTER, *arg1, 0);
+ p2 = build_expr_type_conversion (WANT_POINTER, *arg2, 0);
+
+ wins = (a1 && a2) + (a1 && p2) + (p1 && a2);
+
+ if (wins > 1)
+ error ("ambiguous default type conversion for `operator +'");
+
+ if (a1 && a2)
+ *arg1 = a1, *arg2 = a2;
+ else if (a1 && p2)
+ *arg1 = a1, *arg2 = p2;
+ else
+ *arg1 = p1, *arg2 = a2;
+ break;
+ }
+
+ case MINUS_EXPR:
+ {
+ tree a1, a2, p1, p2;
+ int wins;
+
+ a1 = build_expr_type_conversion (WANT_ARITH | WANT_ENUM, *arg1, 0);
+ a2 = build_expr_type_conversion (WANT_ARITH | WANT_ENUM, *arg2, 0);
+ p1 = build_expr_type_conversion (WANT_POINTER, *arg1, 0);
+ p2 = build_expr_type_conversion (WANT_POINTER, *arg2, 0);
+
+ wins = (a1 && a2) + (p1 && p2) + (p1 && a2);
+
+ if (wins > 1)
+ error ("ambiguous default type conversion for `operator -'");
+
+ if (a1 && a2)
+ *arg1 = a1, *arg2 = a2;
+ else if (p1 && p2)
+ *arg1 = p1, *arg2 = p2;
+ else
+ *arg1 = p1, *arg2 = a2;
+ break;
+ }
+
+ case GT_EXPR:
+ case LT_EXPR:
+ case GE_EXPR:
+ case LE_EXPR:
+ case EQ_EXPR:
+ case NE_EXPR:
+ {
+ tree a1, a2, p1, p2;
+ int wins;
+
+ a1 = build_expr_type_conversion (WANT_ARITH | WANT_ENUM, *arg1, 0);
+ a2 = build_expr_type_conversion (WANT_ARITH | WANT_ENUM, *arg2, 0);
+ p1 = build_expr_type_conversion (WANT_POINTER | WANT_NULL, *arg1, 0);
+ p2 = build_expr_type_conversion (WANT_POINTER | WANT_NULL, *arg2, 0);
+
+ wins = (a1 && a2) + (p1 && p2);
+
+ if (wins > 1)
+ cp_error ("ambiguous default type conversion for `%O'", code);
+
+ if (a1 && a2)
+ *arg1 = a1, *arg2 = a2;
+ else
+ *arg1 = p1, *arg2 = p2;
+ break;
+ }
+
+ case TRUTH_ANDIF_EXPR:
+ case TRUTH_ORIF_EXPR:
+ *arg1 = convert (boolean_type_node, *arg1);
+ *arg2 = convert (boolean_type_node, *arg2);
+ break;
+
+ default:
+ *arg1 = NULL_TREE;
+ *arg2 = NULL_TREE;
}
- return 1;
+
+ if (*arg1 == error_mark_node || *arg2 == error_mark_node)
+ cp_error ("ambiguous default type conversion for `%O'", code);
+
+ if (*arg1 && *arg2)
+ return 1;
+
+ return 0;
}
/* Implements integral promotion (4.1) and float->double promotion. */
type_decl = build_decl (TYPE_DECL, nested, type);
DECL_NESTED_TYPENAME (type_decl) = nested;
SET_DECL_ARTIFICIAL (type_decl);
-#ifdef DWARF_DEBUGGING_INFO
- /* Mark the TYPE_DECL node created just above as a
- gratuitous one so that dwarfout.c will know not to
- generate a TAG_typedef DIE for it. */
- if (write_symbols == DWARF_DEBUG)
- DECL_IGNORED_P (type_decl) = 1;
-#endif /* DWARF_DEBUGGING_INFO */
+ /* Mark the TYPE_DECL node created just above as a gratuitous one so that
+ dwarfout.c will know not to generate a TAG_typedef DIE for it, and
+ sdbout.c won't try to output a .def for "::foo". */
+ DECL_IGNORED_P (type_decl) = 1;
/* Remove this when local classes are fixed. */
SET_IDENTIFIER_TYPE_VALUE (nested, type);
TREE_TYPE (newdecl) = TREE_TYPE (olddecl) = newtype;
/* Lay the type out, unless already done. */
- if (oldtype != TREE_TYPE (newdecl))
- {
- if (TREE_TYPE (newdecl) != error_mark_node)
- layout_type (TREE_TYPE (newdecl));
- if (TREE_CODE (newdecl) != FUNCTION_DECL
- && TREE_CODE (newdecl) != TYPE_DECL
- && TREE_CODE (newdecl) != CONST_DECL
- && TREE_CODE (newdecl) != TEMPLATE_DECL)
- layout_decl (newdecl, 0);
- }
- else
- {
- /* Since the type is OLDDECL's, make OLDDECL's size go with. */
- DECL_SIZE (newdecl) = DECL_SIZE (olddecl);
- }
+ if (oldtype != TREE_TYPE (newdecl)
+ && TREE_TYPE (newdecl) != error_mark_node)
+ layout_type (TREE_TYPE (newdecl));
+
+ if (TREE_CODE (newdecl) == VAR_DECL
+ || TREE_CODE (newdecl) == PARM_DECL
+ || TREE_CODE (newdecl) == RESULT_DECL
+ || TREE_CODE (newdecl) == FIELD_DECL
+ || TREE_CODE (newdecl) == TYPE_DECL)
+ layout_decl (newdecl, 0);
/* Merge the type qualifiers. */
if (TREE_READONLY (newdecl))
if (TREE_CODE (type) == REAL_TYPE)
error ("short, signed or unsigned invalid for `%s'", name);
- else if (TREE_CODE (type) != INTEGER_TYPE || type == wchar_type_node)
+ else if (TREE_CODE (type) != INTEGER_TYPE)
error ("long, short, signed or unsigned invalid for `%s'", name);
else if (RIDBIT_SETP (RID_LONG, specbits)
&& RIDBIT_SETP (RID_SHORT, specbits))
error ("non-object member `%s' cannot be declared `mutable'", name);
RIDBIT_RESET (RID_MUTABLE, specbits);
}
+ else if (constp)
+ {
+ error ("const `%s' cannot be declared `mutable'", name);
+ RIDBIT_RESET (RID_MUTABLE, specbits);
+ }
else if (staticp)
{
error ("static `%s' cannot be declared `mutable'", name);
}
/* Give error if `virtual' is used outside of class declaration. */
- if (virtualp && current_class_name == NULL_TREE)
+ if (virtualp
+ && (current_class_name == NULL_TREE || decl_context != FIELD))
{
error ("virtual outside class declaration");
virtualp = 0;
{
if (decl_context == FIELD)
{
- tree tmp = TREE_OPERAND (declarator, 0);
- register int op = IDENTIFIER_OPNAME_P (tmp);
+ tree tmp = NULL_TREE;
+ register int op = 0;
+
+ if (declarator)
+ {
+ tmp = TREE_OPERAND (declarator, 0);
+ op = IDENTIFIER_OPNAME_P (tmp);
+ }
error ("storage class specified for %s `%s'",
IS_SIGNATURE (current_class_type)
? (op
? "signature member operator"
: "signature member function")
- : (op ? "member operator" : "structure field"),
+ : (op ? "member operator" : "field"),
op ? operator_name_string (tmp) : name);
}
else
{
register tree itype = NULL_TREE;
register tree size = TREE_OPERAND (declarator, 1);
+ /* The index is a signed object `sizetype' bits wide. */
+ tree index_type = signed_type (sizetype);
declarator = TREE_OPERAND (declarator, 0);
cp_error ("size of array `%D' is negative", dname);
size = integer_one_node;
}
- itype = build_index_type (size_binop (MINUS_EXPR, size,
- integer_one_node));
}
else
{
else
cp_pedwarn ("ANSI C++ forbids variable-size array");
}
- dont_grok_size:
- itype =
- build_binary_op (MINUS_EXPR, size, integer_one_node, 1);
/* Make sure the array size remains visibly nonconstant
- even if it is (eg) a const variable with known value. */
+ even if it is (eg) a const variable with known value. */
size_varies = 1;
- itype = variable_size (itype);
- itype = build_index_type (itype);
}
+
+ dont_grok_size:
+ itype =
+ fold (build_binary_op (MINUS_EXPR,
+ convert (index_type, size),
+ convert (index_type,
+ integer_one_node), 1));
+ if (! TREE_CONSTANT (itype))
+ itype = variable_size (itype);
+ itype = build_index_type (itype);
resume_momentary (yes);
}
if (inner_decl && TREE_CODE (inner_decl) == SCOPE_REF)
inner_decl = TREE_OPERAND (inner_decl, 1);
+ /* Pick up type qualifiers which should be applied to `this'. */
+ quals = TREE_OPERAND (declarator, 2);
+
/* Say it's a definition only for the CALL_EXPR
closest to the identifier. */
funcdecl_p =
- inner_decl && TREE_CODE (inner_decl) == IDENTIFIER_NODE;
+ inner_decl && (TREE_CODE (inner_decl) == IDENTIFIER_NODE
+ || TREE_CODE (inner_decl) == BIT_NOT_EXPR);
if (ctype == NULL_TREE
&& decl_context == FIELD
may not be static. */
if (staticp == 2)
error ("destructor cannot be static member function");
- if (TYPE_READONLY (type))
- {
- error ("destructors cannot be declared `const'");
- return void_type_node;
- }
- if (TYPE_VOLATILE (type))
+ if (quals)
{
- error ("destructors cannot be declared `volatile'");
+ error ("destructors cannot be declared `const' or `volatile'");
return void_type_node;
}
if (decl_context == FIELD)
pedwarn ("constructors cannot be declared virtual");
virtualp = 0;
}
- if (TYPE_READONLY (type))
+ if (quals)
{
- error ("constructors cannot be declared `const'");
+ error ("constructors cannot be declared `const' or `volatile'");
return void_type_node;
}
- if (TYPE_VOLATILE (type))
- {
- error ("constructors cannot be declared `volatile'");
- return void_type_node;
- }
{
RID_BIT_TYPE tmp_bits;
bcopy ((void*)&specbits, (void*)&tmp_bits, sizeof(RID_BIT_TYPE));
if (decl_context == FIELD)
staticp = 0;
}
- else if (friendp && virtualp)
+ else if (friendp)
{
- /* Cannot be both friend and virtual. */
- error ("virtual functions cannot be friends");
- RIDBIT_RESET (RID_FRIEND, specbits);
- friendp = 0;
+ if (initialized)
+ error ("can't initialize friend function `%s'", name);
+ if (virtualp)
+ {
+ /* Cannot be both friend and virtual. */
+ error ("virtual functions cannot be friends");
+ RIDBIT_RESET (RID_FRIEND, specbits);
+ friendp = 0;
+ }
}
if (decl_context == NORMAL && friendp)
error ("friend declaration not in class definition");
- /* Pick up type qualifiers which should be applied to `this'. */
- quals = TREE_OPERAND (declarator, 2);
-
/* Traditionally, declaring return type float means double. */
if (flag_traditional
/* Special case: "friend class foo" looks like a TYPENAME context. */
if (friendp)
{
- /* A friendly class? */
- if (current_class_type)
- make_friend_class (current_class_type, TYPE_MAIN_VARIANT (type));
- else
- error("trying to make class `%s' a friend of global scope",
- TYPE_NAME_STRING (type));
- type = void_type_node;
+ if (volatilep)
+ {
+ cp_error ("`volatile' specified for friend class declaration");
+ volatilep = 0;
+ }
+ if (inlinep)
+ {
+ cp_error ("`inline' specified for friend class declaration");
+ inlinep = 0;
+ }
+
+ /* Only try to do this stuff if we didn't already give up. */
+ if (type != integer_type_node)
+ {
+ /* A friendly class? */
+ if (current_class_type)
+ make_friend_class (current_class_type, TYPE_MAIN_VARIANT (type));
+ else
+ error ("trying to make class `%s' a friend of global scope",
+ TYPE_NAME_STRING (type));
+ type = void_type_node;
+ }
}
else if (quals)
{
if (TYPE_MAIN_VARIANT (type) == void_type_node && decl_context != PARM)
{
- if (TREE_CODE (declarator) == IDENTIFIER_NODE)
+ if (! declarator)
+ error ("unnamed variable or field declared void");
+ else if (TREE_CODE (declarator) == IDENTIFIER_NODE)
{
if (IDENTIFIER_OPNAME_P (declarator))
#if 0 /* How could this happen? */
type = build_pointer_type (type);
else if (TREE_CODE (type) == OFFSET_TYPE)
type = build_pointer_type (type);
+ else if (type == void_type_node && declarator)
+ {
+ error ("declaration of `%s' as void", name);
+ return NULL_TREE;
+ }
decl = build_decl (PARM_DECL, declarator, type);
else if (TYPE_SIZE (type) == NULL_TREE && !staticp
&& (TREE_CODE (type) != ARRAY_TYPE || initialized == 0))
{
- cp_error ("field `%D' has incomplete type", declarator);
+ if (declarator)
+ cp_error ("field `%D' has incomplete type", declarator);
+ else
+ cp_error ("name `%T' has incomplete type", type);
/* If we're instantiating a template, tell them which
instantiation made the field's type be incomplete. */
staticp = 0;
RIDBIT_RESET (RID_STATIC, specbits);
}
+ if (RIDBIT_SETP (RID_REGISTER, specbits) && TREE_STATIC (decl))
+ {
+ cp_error ("static member `%D' declared `register'", decl);
+ RIDBIT_RESET (RID_REGISTER, specbits);
+ }
if (RIDBIT_SETP (RID_EXTERN, specbits))
{
cp_error ("cannot explicitly declare member `%#D' to have extern linkage",
any_init++;
if (TREE_CODE (init) == SAVE_EXPR)
PARM_DECL_EXPR (init) = 1;
- else if (TREE_CODE (init) == VAR_DECL)
+ else if (TREE_CODE (init) == VAR_DECL
+ || TREE_CODE (init) == PARM_DECL)
{
if (IDENTIFIER_LOCAL_VALUE (DECL_NAME (init)))
{
original_result_rtx = NULL_RTX;
current_function_obstack_index = 0;
current_function_obstack_usage = 0;
+ base_init_insns = NULL_RTX;
+ protect_list = NULL_TREE;
clear_temp_name ();
if (TREE_TYPE (TREE_TYPE (decl1)) != integer_type_node)
{
if (pedantic || warn_return_type)
- warning ("return type for `main' changed to integer type");
+ pedwarn ("return type for `main' changed to integer type");
TREE_TYPE (decl1) = fntype = default_function_type;
}
warn_about_return_type = 0;
DECL_RESULT (decl1) = build_decl (RESULT_DECL, 0, TREE_TYPE (fntype));
}
+ if (TYPE_LANG_SPECIFIC (TREE_TYPE (fntype))
+ && CLASSTYPE_ABSTRACT_VIRTUALS (TREE_TYPE (fntype)))
+ abstract_virtuals_error (decl1, TREE_TYPE (fntype));
+
if (warn_about_return_type)
warning ("return-type defaults to `int'");
DECL_EXTERNAL (decl1) = current_extern_inline;
DECL_INTERFACE_KNOWN (decl1) = 1;
}
+ else if (current_extern_inline)
+ {
+ /* `extern inline' acts like a declaration except for
+ defining how to inline. So set DECL_EXTERNAL in that case. */
+ DECL_EXTERNAL (decl1) = 1;
+ DECL_INTERFACE_KNOWN (decl1) = 1;
+ }
else
{
/* This is a definition, not a reference.
- So normally clear DECL_EXTERNAL.
- However, `extern inline' acts like a declaration except for
- defining how to inline. So set DECL_EXTERNAL in that case. */
- DECL_EXTERNAL (decl1) = current_extern_inline;
-
+ So clear DECL_EXTERNAL. */
+ DECL_EXTERNAL (decl1) = 0;
+
if (DECL_INLINE (decl1) && (DECL_FUNCTION_MEMBER_P (decl1)
|| DECL_TEMPLATE_INSTANTIATION (decl1)))
/* We know nothing yet */;
if (DECL_CONSTRUCTOR_P (current_function_decl))
{
+ end_protect_partials ();
expand_label (ctor_label);
ctor_label = NULL_TREE;
if (mark != get_last_insn ())
reorder_insns (next_insn (mark), get_last_insn (), last_parm_insn);
+ end_protect_partials ();
+
/* This is where the body of the constructor ends. */
expand_label (ctor_label);
ctor_label = NULL_TREE;
/* Run the optimizers and output the assembler code for this function. */
rest_of_compilation (fndecl);
- if (DECL_DEFER_OUTPUT (fndecl))
- mark_inline_for_output (fndecl);
+ if (DECL_SAVED_INSNS (fndecl) && ! TREE_ASM_WRITTEN (fndecl))
+ {
+ /* Set DECL_EXTERNAL so that assemble_external will be called as
+ necessary. We'll clear it again in import_export_inline. */
+ if (TREE_PUBLIC (fndecl))
+ DECL_EXTERNAL (fndecl) = 1;
+ mark_inline_for_output (fndecl);
+ }
if (ctype && TREE_ASM_WRITTEN (fndecl))
note_debug_info_needed (ctype);
tree shadowed_labels;
tree ctor_label;
tree dtor_label;
+ tree protect_list;
rtx result_rtx;
+ rtx base_init_insns;
struct cp_function *next;
struct binding_level *binding_level;
};
p->just_assigned_this = current_function_just_assigned_this;
p->parms_stored = current_function_parms_stored;
p->result_rtx = original_result_rtx;
+ p->base_init_insns = base_init_insns;
+ p->protect_list = protect_list;
}
/* Restore the variables used during compilation of a C++ function. */
current_binding_level = p->binding_level;
ctor_label = p->ctor_label;
dtor_label = p->dtor_label;
+ protect_list = p->protect_list;
current_function_assigns_this = p->assigns_this;
current_function_just_assigned_this = p->just_assigned_this;
current_function_parms_stored = p->parms_stored;
original_result_rtx = p->result_rtx;
+ base_init_insns = p->base_init_insns;
free (p);
}
tree array_expr, index_exp;
{
tree type = TREE_TYPE (array_expr);
+ tree p1, p2, i1, i2;
if (type == error_mark_node || index_exp == error_mark_node)
return error_mark_node;
array_expr, index_exp, NULL_TREE);
/* Otherwise, create an ARRAY_REF for a pointer or array type. */
- if (TREE_CODE (type) == POINTER_TYPE
- || TREE_CODE (type) == ARRAY_TYPE)
- return build_array_ref (array_expr, index_exp);
- /* Woops, looks like they did something like `5[a]' instead of `a[5]'.
- We don't emit a warning or error for this, since it's allowed
- by ARM $8.2.4. */
+ if (TREE_CODE (type) == ARRAY_TYPE)
+ p1 = array_expr;
+ else
+ p1 = build_expr_type_conversion (WANT_POINTER, array_expr, 0);
- type = TREE_TYPE (index_exp);
+ if (TREE_CODE (TREE_TYPE (index_exp)) == ARRAY_TYPE)
+ p2 = index_exp;
+ else
+ p2 = build_expr_type_conversion (WANT_POINTER, index_exp, 0);
- if (TREE_CODE (type) == OFFSET_TYPE
- || TREE_CODE (type) == REFERENCE_TYPE)
- type = TREE_TYPE (type);
+ i1 = build_expr_type_conversion (WANT_INT | WANT_ENUM, array_expr, 0);
+ i2 = build_expr_type_conversion (WANT_INT | WANT_ENUM, index_exp, 0);
- if (TREE_CODE (type) == POINTER_TYPE
- || TREE_CODE (type) == ARRAY_TYPE)
- return build_array_ref (index_exp, array_expr);
+ if ((p1 && i2) && (i1 && p2))
+ error ("ambiguous conversion for array subscript");
- /* The expression E1[E2] is identical (by definition) to *((E1)+(E2)). */
- return build_indirect_ref (build_binary_op (PLUS_EXPR, array_expr,
- index_exp, 1),
- "array indexing");
+ if (p1 && i2)
+ array_expr = p1, index_exp = i2;
+ else if (i1 && p2)
+ array_expr = p2, index_exp = i1;
+ else
+ {
+ cp_error ("invalid types `%T[%T]' for array subscript",
+ type, TREE_TYPE (index_exp));
+ return error_mark_node;
+ }
+
+ if (array_expr == error_mark_node || index_exp == error_mark_node)
+ error ("ambiguous conversion for array subscript");
+
+ return build_array_ref (array_expr, index_exp);
}
/* Given the cast expression EXP, checking out its validity. Either return
}
else
{
- /* We can only do this optimization if we have real non-inline
- virtual functions in our class, or if we come from a template. */
+ /* We can only wait to decide if we have real non-inline virtual
+ functions in our class, or if we come from a template. */
int found = CLASSTYPE_TEMPLATE_INSTANTIATION (type);
tree ctype = DECL_CONTEXT (vars);
import_export_template (ctype);
- if (CLASSTYPE_INTERFACE_UNKNOWN (ctype) && TYPE_VIRTUAL_P (ctype))
+ if (CLASSTYPE_INTERFACE_UNKNOWN (ctype) && TYPE_VIRTUAL_P (ctype)
+ && ! CLASSTYPE_TEMPLATE_INSTANTIATION (ctype))
{
tree method;
for (method = CLASSTYPE_METHODS (ctype); method != NULL_TREE;
import_export_vtable (vars, ctype, 1);
- if (write_virtuals >= 0
+ if (flag_rtti && write_virtuals >= 0
&& ! DECL_EXTERNAL (vars) && (TREE_PUBLIC (vars) || TREE_USED (vars)))
{
- extern tree the_null_vtable_entry;
-
/* Kick out the type descriptor before writing out the vtable. */
- if (flag_rtti)
- {
- build_t_desc (ctype, 1);
- }
-
- /* Write it out. */
- mark_vtable_entries (vars);
+ build_t_desc (ctype, 1);
}
}
finish_vtable_vardecl (prev, vars)
tree prev, vars;
{
- tree ctype = DECL_CONTEXT (vars);
- import_export_template (ctype);
-
- if (CLASSTYPE_INTERFACE_UNKNOWN (ctype) && TYPE_VIRTUAL_P (ctype))
- {
- tree method;
- for (method = CLASSTYPE_METHODS (ctype); method != NULL_TREE;
- method = DECL_NEXT_METHOD (method))
- {
- if (DECL_VINDEX (method) != NULL_TREE && !DECL_SAVED_INSNS (method)
- && !DECL_ABSTRACT_VIRTUAL_P (method))
- {
- SET_CLASSTYPE_INTERFACE_KNOWN (ctype);
- CLASSTYPE_VTABLE_NEEDS_WRITING (ctype) = ! DECL_EXTERNAL (method);
- CLASSTYPE_INTERFACE_ONLY (ctype) = DECL_EXTERNAL (method);
- if (flag_rtti)
- cp_warning ("compiler error: rtti entry for `%T' decided too late", ctype);
- break;
- }
- }
- }
-
- import_export_vtable (vars, ctype, 1);
-
if (write_virtuals >= 0
&& ! DECL_EXTERNAL (vars) && (TREE_PUBLIC (vars) || TREE_USED (vars)))
{
- extern tree the_null_vtable_entry;
-
/* Write it out. */
mark_vtable_entries (vars);
if (TREE_TYPE (DECL_INITIAL (vars)) == 0)
- store_init_value (vars, DECL_INITIAL (vars));
+ store_init_value (vars, DECL_INITIAL (vars));
#ifdef DWARF_DEBUGGING_INFO
if (write_symbols == DWARF_DEBUG)
rest_of_decl_compilation (vars, NULL_PTR, 1, 1);
}
- else if (TREE_USED (vars))
- assemble_external (vars);
+ else if (! TREE_USED (vars))
+ /* We don't know what to do with this one yet. */
+ return;
+
+ /* We know that PREV must be non-zero here. */
+ TREE_CHAIN (prev) = TREE_CHAIN (vars);
+}
+
+static void
+prune_vtable_vardecl (prev, vars)
+ tree prev, vars;
+{
/* We know that PREV must be non-zero here. */
TREE_CHAIN (prev) = TREE_CHAIN (vars);
}
if (DECL_INTERFACE_KNOWN (decl))
return;
+ DECL_EXTERNAL (decl) = 0;
+
if (DECL_TEMPLATE_INSTANTIATION (decl))
{
if (DECL_IMPLICIT_INSTANTIATION (decl) && flag_implicit_templates)
tree fnname;
tree vars = static_aggregates;
int needs_cleaning = 0, needs_messing_up = 0;
- int have_exception_handlers = build_exception_table ();
if (flag_detailed_statistics)
dump_tree_statistics ();
we'll need here. */
push_lang_context (lang_name_c);
- if (static_ctors || vars || have_exception_handlers)
+ if (static_ctors || vars || might_have_exceptions_p ())
needs_messing_up = 1;
if (static_dtors)
needs_cleaning = 1;
push_momentary ();
expand_start_bindings (0);
- if (have_exception_handlers)
+ if (might_have_exceptions_p ())
register_exception_table ();
while (vars)
/* 9.5p5: The initializer of a static member of a class has
the same acess rights as a member function. */
DECL_CLASS_CONTEXT (current_function_decl) = DECL_CONTEXT (decl);
+ DECL_STATIC_FUNCTION_P (current_function_decl) = 1;
#if 0
if (init)
pushdecl (vars);
#endif
- walk_vtables ((void (*)())0, finish_vtable_vardecl);
if (flag_handle_signatures)
walk_sigtables ((void (*)())0, finish_sigtable_vardecl);
- for (vars = saved_inlines; vars; vars = TREE_CHAIN (vars))
- {
- tree decl = TREE_VALUE (vars);
-
- if (DECL_ARTIFICIAL (decl)
- && ! DECL_INITIAL (decl)
- && TREE_USED (decl))
- synthesize_method (decl);
- }
-
- for (vars = getdecls (); vars; vars = TREE_CHAIN (vars))
- {
- if (TREE_CODE (vars) == THUNK_DECL)
- emit_thunk (vars);
- else if (TREE_CODE (vars) == FUNCTION_DECL
- && ! DECL_INTERFACE_KNOWN (vars)
- && DECL_DECLARED_STATIC (vars))
- TREE_PUBLIC (vars) = 0;
- }
-
/* Now write out inline functions which had their addresses taken and
which were not declared virtual and which were not declared `extern
inline'. */
tree place = TREE_CHAIN (saved_inlines);
reconsider = 0;
+ walk_vtables ((void (*)())0, finish_vtable_vardecl);
+
for (; place; place = TREE_CHAIN (place))
{
tree decl = TREE_VALUE (place);
+ if (DECL_ARTIFICIAL (decl) && ! DECL_INITIAL (decl))
+ {
+ if (TREE_USED (decl))
+ synthesize_method (decl);
+ else
+ {
+ last = place;
+ continue;
+ }
+ }
+
if (TREE_ASM_WRITTEN (decl) || DECL_SAVED_INSNS (decl) == 0)
{
TREE_CHAIN (last) = TREE_CHAIN (place);
{
TREE_CHAIN (last) = TREE_CHAIN (place);
- if (DECL_EXTERNAL (decl))
- assemble_external (decl);
- else
+ if (! DECL_EXTERNAL (decl))
{
reconsider = 1;
temporary_allocation ();
}
}
+ walk_vtables ((void (*)())0, prune_vtable_vardecl);
+
+ for (vars = getdecls (); vars; vars = TREE_CHAIN (vars))
+ {
+ if (TREE_CODE (vars) == THUNK_DECL)
+ emit_thunk (vars);
+ else if (TREE_CODE (vars) == FUNCTION_DECL
+ && ! DECL_INTERFACE_KNOWN (vars)
+ && DECL_DECLARED_STATIC (vars))
+ TREE_PUBLIC (vars) = 0;
+ }
+
+ if (might_have_exceptions_p ())
+ emit_exception_table ();
+
if (write_virtuals == 2)
{
/* Now complain about an virtual function tables promised
break;
case VAR_DECL:
- if (VTABLE_NAME_P (DECL_NAME (t)))
+ if (DECL_NAME (t) && VTABLE_NAME_P (DECL_NAME (t)))
{
OB_PUTS ("vtable for ");
dump_type (DECL_CONTEXT (t), v);
char *p = enum_name_string (t, type);
OB_PUTCP (p);
}
- else if (type == char_type_node
- || type == signed_char_type_node
- || type == unsigned_char_type_node)
+ else if (type == boolean_type_node)
+ {
+ if (t == boolean_false_node)
+ OB_PUTS ("false");
+ else if (t == boolean_true_node)
+ OB_PUTS ("true");
+ else
+ my_friendly_abort (366);
+ }
+ else if (type == char_type_node)
{
OB_PUTC ('\'');
dump_char (TREE_INT_CST_LOW (t));
#include "obstack.h"
#include "expr.h"
+tree protect_list;
+
extern void (*interim_eh_hook) PROTO((tree));
/* holds the fndecl for __builtin_return_address () */
#define __mips
#endif
#endif
+#ifdef __i386__
+#ifndef __i386
+#define __i386
+#endif
+#endif
#if defined(__i386) || defined(__rs6000) || defined(__hppa) || defined(__mc68000) || defined (__mips) || defined (__arm) || defined (__alpha)
#define TRY_NEW_EH
#endif
end_protect (finalization)
tree finalization;
{
- struct ehEntry *entry = pop_eh_entry (&ehstack);
+ struct ehEntry *entry;
if (! doing_eh (0))
return;
+ entry = pop_eh_entry (&ehstack);
+
emit_label (entry->end_label);
entry->finalization = finalization;
/* end of: my-cp-except.c */
#endif
+void
+end_protect_partials () {
+ while (protect_list)
+ {
+ end_protect (TREE_VALUE (protect_list));
+ protect_list = TREE_CHAIN (protect_list);
+ }
+}
+
+int
+might_have_exceptions_p ()
+{
+#ifdef TRY_NEW_EH
+ if (eh_table_output_queue.head)
+ return 1;
+#endif
+ return 0;
+}
/* Output the exception table.
Return the number of handlers. */
-int
-build_exception_table ()
+void
+emit_exception_table ()
{
int count = 0;
#ifdef TRY_NEW_EH
tree eh_node_decl;
if (! doing_eh (0))
- return 0;
+ return;
+
+ exception_section ();
+
+ /* Beginning marker for table. */
+ ASM_OUTPUT_ALIGN (asm_out_file, 2);
+ ASM_OUTPUT_LABEL (asm_out_file, "__EXCEPTION_TABLE__");
+ output_exception_table_entry (asm_out_file,
+ const0_rtx, const0_rtx, const0_rtx);
while (entry = dequeue_eh_entry (&eh_table_output_queue))
{
if (context && ! TREE_ASM_WRITTEN (context))
continue;
- if (count == 0)
- {
- exception_section ();
-
- /* Beginning marker for table. */
- ASM_OUTPUT_ALIGN (asm_out_file, 2);
- ASM_OUTPUT_LABEL (asm_out_file, "__EXCEPTION_TABLE__");
- output_exception_table_entry (asm_out_file,
- const0_rtx, const0_rtx, const0_rtx);
- }
count++;
output_exception_table_entry (asm_out_file,
entry->start_label, entry->end_label,
entry->exception_handler_label);
}
- if (count)
- {
- /* Ending marker for table. */
- ASM_OUTPUT_LABEL (asm_out_file, "__EXCEPTION_END__");
- output_exception_table_entry (asm_out_file,
- constm1_rtx, constm1_rtx, constm1_rtx);
- }
+ /* Ending marker for table. */
+ ASM_OUTPUT_LABEL (asm_out_file, "__EXCEPTION_END__");
+ output_exception_table_entry (asm_out_file,
+ constm1_rtx, constm1_rtx, constm1_rtx);
#endif /* TRY_NEW_EH */
- return count;
}
void
/* 348 - 351 */
/* Subroutine of emit_base_init. */
static void
-perform_member_init (member, name, init, explicit)
- tree member, name, init;
+perform_member_init (member, name, init, explicit, protect_list)
+ tree member, name, init, *protect_list;
int explicit;
{
tree decl;
}
}
expand_cleanups_to (NULL_TREE);
- if (flag_handle_exceptions && TYPE_NEEDS_DESTRUCTOR (type))
- cp_warning ("caution, member `%D' may not be destroyed in the presense of an exception during construction", member);
+
+ if (TYPE_NEEDS_DESTRUCTOR (type))
+ {
+ tree expr = build_component_ref (C_C_D, name, 0, explicit);
+ expr = build_delete (type, expr, integer_zero_node,
+ LOOKUP_NONVIRTUAL|LOOKUP_DESTRUCTOR, 0);
+
+ if (expr != error_mark_node)
+ {
+ start_protect ();
+ *protect_list = tree_cons (NULL_TREE, expr, *protect_list);
+ }
+ }
}
+extern int warn_reorder;
+
/* Subroutine of emit_member_init. */
static tree
sort_member_init (t)
tree t;
{
- extern int warn_reorder;
tree x, member, name, field, init;
tree init_list = NULL_TREE;
tree fields_to_unmark = NULL_TREE;
- int found;
int last_pos = 0;
tree last_field;
for (member = TYPE_FIELDS (t); member ; member = TREE_CHAIN (member))
{
int pos;
- found = 0;
+
+ /* member could be, for example, a CONST_DECL for an enumerated
+ tag; we don't want to try to initialize that, since it already
+ has a value. */
+ if (TREE_CODE (member) != FIELD_DECL || !DECL_NAME (member))
+ continue;
+
for (x = current_member_init_list, pos = 0; x; x = TREE_CHAIN (x), ++pos)
{
/* If we cleared this out, then pay no attention to it. */
if (field == member)
{
- /* See if we already found an initializer for this field. */
- if (found)
- {
- if (DECL_NAME (field))
- cp_error ("multiple initializations given for member `%D'",
- field);
- continue;
- }
- else
+ if (warn_reorder)
{
- if (pos < last_pos && warn_reorder)
+ if (pos < last_pos)
{
cp_warning_at ("member initializers for `%#D'", last_field);
cp_warning_at (" and `%#D'", field);
last_field = field;
}
- init_list = chainon (init_list,
- build_tree_list (name, TREE_VALUE (x)));
/* Make sure we won't try to work on this init again. */
TREE_PURPOSE (x) = NULL_TREE;
- found = 1;
- break;
+ x = build_tree_list (name, TREE_VALUE (x));
+ goto got_it;
}
}
/* If we didn't find MEMBER in the list, create a dummy entry
so the two lists (INIT_LIST and the list of members) will be
symmetrical. */
- if (! found)
- init_list = chainon (init_list, build_tree_list (NULL_TREE, NULL_TREE));
+ x = build_tree_list (NULL_TREE, NULL_TREE);
+ got_it:
+ init_list = chainon (init_list, x);
}
+ /* Initializers for base members go at the end. */
for (x = current_member_init_list ; x ; x = TREE_CHAIN (x))
{
- if (TREE_PURPOSE (x))
+ name = TREE_PURPOSE (x);
+ if (name)
{
- name = TREE_PURPOSE (x);
- init = TREE_VALUE (x);
- /* XXX: this may need the COMPONENT_REF operand 0 check if
- it turns out we actually get them. */
- field = IDENTIFIER_CLASS_VALUE (name);
-
- /* If one member shadows another, get the outermost one. */
- if (TREE_CODE (field) == TREE_LIST)
+ if (purpose_member (name, init_list))
{
- field = TREE_VALUE (field);
- if (decl_type_context (field) != current_class_type)
- cp_error ("field `%D' not in immediate context", field);
+ cp_error ("multiple initializations given for member `%D'",
+ IDENTIFIER_CLASS_VALUE (name));
+ continue;
}
+
+ init_list = chainon (init_list,
+ build_tree_list (name, TREE_VALUE (x)));
+ TREE_PURPOSE (x) = NULL_TREE;
+ }
+ }
-#if 0
- /* It turns out if you have an anonymous union in the
- class, a member from it can end up not being on the
- list of fields (rather, the type is), and therefore
- won't be seen by the for loop above. */
+ return init_list;
+}
- /* The code in this for loop is derived from a general loop
- which had this check in it. Theoretically, we've hit
- every initialization for the list of members in T, so
- we shouldn't have anything but these left in this list. */
- my_friendly_assert (DECL_FIELD_CONTEXT (field) != t, 351);
-#endif
+static void
+sort_base_init (t, rbase_ptr, vbase_ptr)
+ tree t, *rbase_ptr, *vbase_ptr;
+{
+ tree binfos = BINFO_BASETYPES (TYPE_BINFO (t));
+ int n_baseclasses = binfos ? TREE_VEC_LENGTH (binfos) : 0;
+
+ int i;
+ tree x;
+ tree last;
+
+ /* For warn_reorder. */
+ int last_pos = 0;
+ tree last_base = NULL_TREE;
+
+ tree rbases = NULL_TREE;
+ tree vbases = NULL_TREE;
- if (TREE_HAS_CONSTRUCTOR (field))
+ /* First walk through and splice out vbase and invalid initializers.
+ Also replace names with binfos. */
+
+ last = tree_cons (NULL_TREE, NULL_TREE, current_base_init_list);
+ for (x = TREE_CHAIN (last); x; x = TREE_CHAIN (x))
+ {
+ tree basename = TREE_PURPOSE (x);
+ tree binfo;
+
+ if (basename == NULL_TREE)
+ {
+ /* Initializer for single base class. Must not
+ use multiple inheritance or this is ambiguous. */
+ switch (n_baseclasses)
{
- if (DECL_NAME (field))
- error ("multiple initializations given for member `%s'",
- IDENTIFIER_POINTER (DECL_NAME (field)));
- continue;
+ case 0:
+ cp_error ("`%T' does not have a base class to initialize",
+ current_class_type);
+ return;
+ case 1:
+ break;
+ default:
+ cp_error ("unnamed initializer ambiguous for `%T' which uses multiple inheritance",
+ current_class_type);
+ return;
}
+ binfo = TREE_VEC_ELT (binfos, 0);
+ }
+ else if (is_aggr_typedef (basename, 1))
+ {
+ binfo = binfo_or_else (IDENTIFIER_TYPE_VALUE (basename), t);
+ if (binfo == NULL_TREE)
+ continue;
- TREE_HAS_CONSTRUCTOR (field) = 1;
- fields_to_unmark = tree_cons (NULL_TREE, field, fields_to_unmark);
+ /* Virtual base classes are special cases. Their initializers
+ are recorded with this constructor, and they are used when
+ this constructor is the top-level constructor called. */
+ if (TREE_VIA_VIRTUAL (binfo))
+ {
+ tree v = CLASSTYPE_VBASECLASSES (t);
+ while (BINFO_TYPE (v) != BINFO_TYPE (binfo))
+ v = TREE_CHAIN (v);
- perform_member_init (field, name, init, 1);
- TREE_PURPOSE (x) = NULL_TREE;
+ vbases = tree_cons (v, TREE_VALUE (x), vbases);
+ continue;
+ }
+ else
+ {
+ /* Otherwise, if it is not an immediate base class, complain. */
+ for (i = n_baseclasses-1; i >= 0; i--)
+ if (BINFO_TYPE (binfo) == BINFO_TYPE (TREE_VEC_ELT (binfos, i)))
+ break;
+ if (i < 0)
+ {
+ cp_error ("`%T' is not an immediate base class of `%T'",
+ IDENTIFIER_TYPE_VALUE (basename),
+ current_class_type);
+ continue;
+ }
+ }
}
+ else
+ my_friendly_abort (365);
+
+ TREE_PURPOSE (x) = binfo;
+ TREE_CHAIN (last) = x;
+ last = x;
}
+ TREE_CHAIN (last) = NULL_TREE;
- /* Unmark fields which are initialized for the base class. */
- while (fields_to_unmark)
+ /* Now walk through our regular bases and make sure they're initialized. */
+
+ for (i = 0; i < n_baseclasses; ++i)
{
- TREE_HAS_CONSTRUCTOR (TREE_VALUE (fields_to_unmark)) = 0;
- /* XXX is this a memory leak? */
- fields_to_unmark = TREE_CHAIN (fields_to_unmark);
+ tree base_binfo = TREE_VEC_ELT (binfos, i);
+ int pos;
+
+ if (TREE_VIA_VIRTUAL (base_binfo))
+ continue;
+
+ for (x = current_base_init_list, pos = 0; x; x = TREE_CHAIN (x), ++pos)
+ {
+ tree binfo = TREE_PURPOSE (x);
+
+ if (binfo == NULL_TREE)
+ continue;
+
+ if (binfo == base_binfo)
+ {
+ if (warn_reorder)
+ {
+ if (pos < last_pos)
+ {
+ cp_warning_at ("base initializers for `%#T'", last_base);
+ cp_warning_at (" and `%#T'", BINFO_TYPE (binfo));
+ warning (" will be re-ordered to match inheritance order");
+ }
+ last_pos = pos;
+ last_base = BINFO_TYPE (binfo);
+ }
+
+ /* Make sure we won't try to work on this init again. */
+ TREE_PURPOSE (x) = NULL_TREE;
+ x = build_tree_list (binfo, TREE_VALUE (x));
+ goto got_it;
+ }
+ }
+
+ /* If we didn't find BASE_BINFO in the list, create a dummy entry
+ so the two lists (RBASES and the list of bases) will be
+ symmetrical. */
+ x = build_tree_list (NULL_TREE, NULL_TREE);
+ got_it:
+ rbases = chainon (rbases, x);
}
- return init_list;
+ *rbase_ptr = rbases;
+ *vbase_ptr = vbases;
+}
+
+/* Perform partial cleanups for a base for exception handling. */
+static tree
+build_partial_cleanup_for (binfo)
+ tree binfo;
+{
+ tree expr = convert_pointer_to_real (binfo,
+ build_unary_op (ADDR_EXPR, C_C_D, 0));
+
+ return build_delete (TREE_TYPE (expr),
+ expr,
+ integer_zero_node,
+ LOOKUP_NONVIRTUAL|LOOKUP_DESTRUCTOR, 0);
}
/* Perform whatever initializations have yet to be done on the base
{
extern tree in_charge_identifier;
- tree member, vbases;
- tree init_list;
- int pass, start;
+ tree member, x;
+ tree mem_init_list;
+ tree rbase_init_list, vbase_init_list;
tree t_binfo = TYPE_BINFO (t);
tree binfos = BINFO_BASETYPES (t_binfo);
int i, n_baseclasses = binfos ? TREE_VEC_LENGTH (binfos) : 0;
- int have_init_list = 0, from_init_list;
+
+ my_friendly_assert (protect_list == NULL_TREE, 999);
if (! immediately)
{
emit_line_note_force (DECL_SOURCE_FILE (current_function_decl),
DECL_SOURCE_LINE (current_function_decl));
- start = ! TYPE_USES_VIRTUAL_BASECLASSES (t);
- for (pass = start; pass < 2; pass++)
- {
- tree vbase_init_list = NULL_TREE;
-
- for (init_list = current_base_init_list; init_list;
- init_list = TREE_CHAIN (init_list))
- {
- tree basename = TREE_PURPOSE (init_list);
- tree binfo;
- tree init = TREE_VALUE (init_list);
-
- if (basename == NULL_TREE)
- {
- /* Initializer for single base class. Must not
- use multiple inheritance or this is ambiguous. */
- switch (n_baseclasses)
- {
- case 0:
- cp_error ("`%T' does not have a base class to initialize",
- current_class_type);
- return;
- case 1:
- break;
- default:
- cp_error ("unnamed initializer ambiguous for `%T' which uses multiple inheritance",
- current_class_type);
- return;
- }
- binfo = TREE_VEC_ELT (binfos, 0);
- }
- else if (is_aggr_typedef (basename, 1))
- {
- binfo = binfo_or_else (IDENTIFIER_TYPE_VALUE (basename), t);
- if (binfo == NULL_TREE)
- continue;
-
- /* Virtual base classes are special cases. Their initializers
- are recorded with this constructor, and they are used when
- this constructor is the top-level constructor called. */
- if (! TREE_VIA_VIRTUAL (binfo))
- {
- /* Otherwise, if it is not an immediate base class, complain. */
- for (i = n_baseclasses-1; i >= 0; i--)
- if (BINFO_TYPE (binfo) == BINFO_TYPE (TREE_VEC_ELT (binfos, i)))
- break;
- if (i < 0)
- {
- cp_error ("`%T' is not an immediate base class of `%T'",
- IDENTIFIER_TYPE_VALUE (basename),
- current_class_type);
- continue;
- }
- }
- }
- else
- continue;
-
- /* The base initialization list goes up to the first
- base class which can actually use it. */
-
- if (pass == start)
- {
- char *msgp = (! TYPE_HAS_CONSTRUCTOR (BINFO_TYPE (binfo)))
- ? "cannot pass initialization up to class `%s'" : 0;
-
- while (! TYPE_HAS_CONSTRUCTOR (BINFO_TYPE (binfo))
- && BINFO_BASETYPES (binfo) != NULL_TREE
- && TREE_VEC_LENGTH (BINFO_BASETYPES (binfo)) == 1)
- {
- /* ?? This should be fixed in RENO by forcing
- default constructors to exist. */
- SET_BINFO_BASEINIT_MARKED (binfo);
- binfo = BINFO_BASETYPE (binfo, 0);
- }
-
- /* We used to give an error if this wasn't true, saying that
- there's no constructor for the initialization of basename.
- This turned out to be incorrect---it should use the
- default constructor, since a user could try to initialize
- the class in a derived class's base initializer list. */
- if (TYPE_HAS_CONSTRUCTOR (BINFO_TYPE (binfo)))
- {
- if (msgp)
- {
- if (pedantic)
- error_with_aggr_type (binfo, msgp);
- else
- msgp = NULL;
- }
- }
-
- if (BINFO_BASEINIT_MARKED (binfo))
- {
- msgp = "class `%s' initializer already specified";
- error (msgp, IDENTIFIER_POINTER (basename));
- }
-
- if (msgp)
- continue;
-
- SET_BINFO_BASEINIT_MARKED (binfo);
- if (TREE_VIA_VIRTUAL (binfo))
- {
- vbase_init_list = tree_cons (init, BINFO_TYPE (binfo),
- vbase_init_list);
- continue;
- }
- if (pass == 0)
- continue;
- }
- else if (TREE_VIA_VIRTUAL (binfo))
- continue;
+ mem_init_list = sort_member_init (t);
+ current_member_init_list = NULL_TREE;
- member = convert_pointer_to (binfo, current_class_decl);
- expand_aggr_init_1 (binfo, 0,
- build_indirect_ref (member, NULL_PTR), init,
- BINFO_OFFSET_ZEROP (binfo), LOOKUP_NORMAL);
- expand_cleanups_to (NULL_TREE);
- }
+ sort_base_init (t, &rbase_init_list, &vbase_init_list);
+ current_base_init_list = NULL_TREE;
- if (pass == 0)
- {
- tree first_arg = TREE_CHAIN (DECL_ARGUMENTS (current_function_decl));
- tree vbases;
+ if (TYPE_USES_VIRTUAL_BASECLASSES (t))
+ {
+ tree first_arg = TREE_CHAIN (DECL_ARGUMENTS (current_function_decl));
- if (DECL_NAME (current_function_decl) == NULL_TREE
- && TREE_CHAIN (first_arg) != NULL_TREE)
- {
- /* If there are virtual baseclasses without initialization
- specified, and this is a default X(X&) constructor,
- build the initialization list so that each virtual baseclass
- of the new object is initialized from the virtual baseclass
- of the incoming arg. */
- tree init_arg = build_unary_op (ADDR_EXPR, TREE_CHAIN (first_arg), 0);
- for (vbases = CLASSTYPE_VBASECLASSES (t);
- vbases; vbases = TREE_CHAIN (vbases))
- {
- if (BINFO_BASEINIT_MARKED (vbases) == 0)
- {
- member = convert_pointer_to (vbases, init_arg);
- if (member == init_arg)
- member = TREE_CHAIN (first_arg);
- else
- TREE_TYPE (member) = build_reference_type (BINFO_TYPE (vbases));
- vbase_init_list = tree_cons (convert_from_reference (member),
- vbases, vbase_init_list);
- SET_BINFO_BASEINIT_MARKED (vbases);
- }
- }
- }
- expand_start_cond (first_arg, 0);
- expand_aggr_vbase_init (t_binfo, C_C_D, current_class_decl,
- vbase_init_list);
- expand_end_cond ();
- }
+ expand_start_cond (first_arg, 0);
+ expand_aggr_vbase_init (t_binfo, C_C_D, current_class_decl,
+ vbase_init_list);
+ expand_end_cond ();
}
- current_base_init_list = NULL_TREE;
- /* Now, perform default initialization of all base classes which
- have not yet been initialized, and unmark baseclasses which
- have been initialized. */
+ /* Now, perform initialization of non-virtual base classes. */
for (i = 0; i < n_baseclasses; i++)
{
tree base = current_class_decl;
tree base_binfo = TREE_VEC_ELT (binfos, i);
+ tree init = void_list_node;
+
+ if (TREE_VIA_VIRTUAL (base_binfo))
+ continue;
#if 0 /* Once unsharing happens soon enough. */
my_friendly_assert (BINFO_INHERITANCE_CHAIN (base_binfo) == t_binfo);
BINFO_INHERITANCE_CHAIN (base_binfo) = t_binfo;
#endif
- if (TYPE_NEEDS_CONSTRUCTING (BINFO_TYPE (base_binfo)))
- {
- if (! TREE_VIA_VIRTUAL (base_binfo)
- && ! BINFO_BASEINIT_MARKED (base_binfo))
- {
- tree ref;
+ if (TREE_PURPOSE (rbase_init_list))
+ init = TREE_VALUE (rbase_init_list);
+ else if (TYPE_NEEDS_CONSTRUCTING (BINFO_TYPE (base_binfo)))
+ init = NULL_TREE;
- if (BINFO_OFFSET_ZEROP (base_binfo))
- base = build1 (NOP_EXPR,
- TYPE_POINTER_TO (BINFO_TYPE (base_binfo)),
- current_class_decl);
- else
- base = build (PLUS_EXPR,
- TYPE_POINTER_TO (BINFO_TYPE (base_binfo)),
- current_class_decl, BINFO_OFFSET (base_binfo));
-
- ref = build_indirect_ref (base, NULL_PTR);
- expand_aggr_init_1 (base_binfo, 0, ref, NULL_TREE,
- BINFO_OFFSET_ZEROP (base_binfo),
- LOOKUP_NORMAL);
- expand_cleanups_to (NULL_TREE);
- }
+ if (init != void_list_node)
+ {
+ member = convert_pointer_to (base_binfo, current_class_decl);
+ expand_aggr_init_1 (base_binfo, 0,
+ build_indirect_ref (member, NULL_PTR), init,
+ BINFO_OFFSET_ZEROP (base_binfo), LOOKUP_NORMAL);
+ expand_cleanups_to (NULL_TREE);
}
- CLEAR_BINFO_BASEINIT_MARKED (base_binfo);
- if (! TYPE_USES_VIRTUAL_BASECLASSES (t))
+ if (TYPE_NEEDS_DESTRUCTOR (BINFO_TYPE (base_binfo)))
{
- while (! TYPE_HAS_CONSTRUCTOR (BINFO_TYPE (base_binfo))
- && BINFO_BASETYPES (base_binfo) != NULL_TREE
- && TREE_VEC_LENGTH (BINFO_BASETYPES (base_binfo)) == 1)
- {
- /* ?? This should be fixed in RENO by forcing
- default constructors to exist. It is needed for symmetry
- with code above. */
- base_binfo = BINFO_BASETYPE (base_binfo, 0);
- CLEAR_BINFO_BASEINIT_MARKED (base_binfo);
- }
+ start_protect ();
+ protect_list = tree_cons (NULL_TREE,
+ build_partial_cleanup_for (base_binfo),
+ protect_list);
}
+
+ rbase_init_list = TREE_CHAIN (rbase_init_list);
}
/* Initialize all the virtual function table fields that
do come from virtual base classes. */
if (TYPE_USES_VIRTUAL_BASECLASSES (t))
expand_indirect_vtbls_init (t_binfo, C_C_D, current_class_decl, 0);
- for (vbases = CLASSTYPE_VBASECLASSES (t); vbases; vbases = TREE_CHAIN (vbases))
- CLEAR_BINFO_BASEINIT_MARKED (vbases);
/* Initialize all the virtual function table fields that
do not come from virtual base classes. */
expand_direct_vtbls_init (t_binfo, t_binfo, 1, 1, current_class_decl);
- if (current_member_init_list)
- {
- init_list = sort_member_init (t);
- have_init_list = 1;
- }
-
for (member = TYPE_FIELDS (t); member; member = TREE_CHAIN (member))
{
tree init, name;
- from_init_list = 0;
+ int from_init_list;
+
+ /* member could be, for example, a CONST_DECL for an enumerated
+ tag; we don't want to try to initialize that, since it already
+ has a value. */
+ if (TREE_CODE (member) != FIELD_DECL || !DECL_NAME (member))
+ continue;
/* See if we had a user-specified member initialization. */
- if (have_init_list)
+ if (TREE_PURPOSE (mem_init_list))
{
- if (TREE_PURPOSE (init_list))
- {
- name = TREE_PURPOSE (init_list);
- init = TREE_VALUE (init_list);
- from_init_list = 1;
+ name = TREE_PURPOSE (mem_init_list);
+ init = TREE_VALUE (mem_init_list);
+ from_init_list = 1;
- if (TREE_STATIC (member))
- {
- cp_error ("field `%#D' is static; only point of initialization is its declaration",
- member);
- continue;
- }
-
- /* Also see if it's ever a COMPONENT_REF here. If it is, we
- need to do `expand_assignment (name, init, 0, 0);' and
- a continue. */
- my_friendly_assert (TREE_CODE (name) != COMPONENT_REF, 349);
- }
-
- init_list = TREE_CHAIN (init_list);
+ /* Also see if it's ever a COMPONENT_REF here. If it is, we
+ need to do `expand_assignment (name, init, 0, 0);' and
+ a continue. */
+ my_friendly_assert (TREE_CODE (name) != COMPONENT_REF, 349);
}
-
- if (! from_init_list)
+ else
{
- /* member could be, for example, a CONST_DECL for an enumerated
- tag; we don't want to try to initialize that, since it already
- has a value. */
- if (TREE_CODE (member) != FIELD_DECL || !DECL_NAME (member))
- continue;
-
name = DECL_NAME (member);
init = DECL_INITIAL (member);
+
+ from_init_list = 0;
}
- perform_member_init (member, name, init, from_init_list);
+ perform_member_init (member, name, init, from_init_list, &protect_list);
+ mem_init_list = TREE_CHAIN (mem_init_list);
}
- current_member_init_list = NULL_TREE;
+ /* Now initialize any members from our bases. */
+ while (mem_init_list)
+ {
+ tree name, init, field;
+
+ if (TREE_PURPOSE (mem_init_list))
+ {
+ name = TREE_PURPOSE (mem_init_list);
+ init = TREE_VALUE (mem_init_list);
+ /* XXX: this may need the COMPONENT_REF operand 0 check if
+ it turns out we actually get them. */
+ field = IDENTIFIER_CLASS_VALUE (name);
+
+ /* If one member shadows another, get the outermost one. */
+ if (TREE_CODE (field) == TREE_LIST)
+ {
+ field = TREE_VALUE (field);
+ if (decl_type_context (field) != current_class_type)
+ cp_error ("field `%D' not in immediate context", field);
+ }
+
+#if 0
+ /* It turns out if you have an anonymous union in the
+ class, a member from it can end up not being on the
+ list of fields (rather, the type is), and therefore
+ won't be seen by the for loop above. */
+
+ /* The code in this for loop is derived from a general loop
+ which had this check in it. Theoretically, we've hit
+ every initialization for the list of members in T, so
+ we shouldn't have anything but these left in this list. */
+ my_friendly_assert (DECL_FIELD_CONTEXT (field) != t, 351);
+#endif
+
+ perform_member_init (field, name, init, 1, &protect_list);
+ }
+ mem_init_list = TREE_CHAIN (mem_init_list);
+ }
if (! immediately)
{
expand_aggr_vbase_init_1 (binfo, exp, addr, init_list)
tree binfo, exp, addr, init_list;
{
- tree init = value_member (BINFO_TYPE (binfo), init_list);
+ tree init = purpose_member (binfo, init_list);
tree ref = build_indirect_ref (addr, NULL_PTR);
if (init)
- init = TREE_PURPOSE (init);
+ init = TREE_VALUE (init);
/* Call constructors, but don't set up vtables. */
expand_aggr_init_1 (binfo, exp, ref, init, 0, LOOKUP_COMPLAIN);
expand_cleanups_to (NULL_TREE);
- CLEAR_BINFO_VBASE_INIT_MARKED (binfo);
}
/* Initialize this object's virtual base class pointers. This must be
if (result)
expand_expr_stmt (build_compound_expr (result));
- /* Mark everything as having an initializer
- (either explicit or default). */
- for (vbases = CLASSTYPE_VBASECLASSES (type);
- vbases; vbases = TREE_CHAIN (vbases))
- SET_BINFO_VBASE_INIT_MARKED (vbases);
-
- /* First, initialize baseclasses which could be baseclasses
- for other virtual baseclasses. */
- for (vbases = CLASSTYPE_VBASECLASSES (type);
- vbases; vbases = TREE_CHAIN (vbases))
- /* Don't initialize twice. */
- if (BINFO_VBASE_INIT_MARKED (vbases))
- {
- tree tmp = result;
-
- while (BINFO_TYPE (vbases) != BINFO_TYPE (TREE_PURPOSE (tmp)))
- tmp = TREE_CHAIN (tmp);
- expand_aggr_vbase_init_1 (vbases, exp,
- TREE_OPERAND (TREE_VALUE (tmp), 0),
- init_list);
- }
-
- /* Now initialize the baseclasses which don't have virtual baseclasses. */
- for (; result; result = TREE_CHAIN (result))
- /* Don't initialize twice. */
- if (BINFO_VBASE_INIT_MARKED (TREE_PURPOSE (result)))
- {
- my_friendly_abort (47);
- expand_aggr_vbase_init_1 (TREE_PURPOSE (result), exp,
- TREE_OPERAND (TREE_VALUE (result), 0),
- init_list);
- }
+ for (vbases = CLASSTYPE_VBASECLASSES (type); vbases;
+ vbases = TREE_CHAIN (vbases))
+ {
+ tree tmp = purpose_member (vbases, result);
+ expand_aggr_vbase_init_1 (vbases, exp,
+ TREE_OPERAND (TREE_VALUE (tmp), 0),
+ init_list);
+ }
}
}
if (field == NULL_TREE)
{
cp_error ("class `%T' does not have any field named `%s'", type,
- member_name);
+ member_name);
return 0;
}
if (DECL_CONTEXT (field) != type
field);
return 0;
}
+ if (TREE_STATIC (field))
+ {
+ cp_error ("field `%#D' is static; only point of initialization is its declaration",
+ field);
+ return 0;
+ }
+
return 1;
}
tree rval;
tree parms;
- if (init == NULL_TREE || TREE_CODE (init) == TREE_LIST)
+ if (init == NULL_TREE
+ || (TREE_CODE (init) == TREE_LIST && ! TREE_TYPE (init)))
{
parms = init;
if (parms)
return t;
}
+ if (TREE_CODE (t) == FIELD_DECL && DECL_BIT_FIELD (t))
+ {
+ cp_error ("illegal pointer to bit field `%D'", t);
+ return error_mark_node;
+ }
+
/* static class functions too. */
if (TREE_CODE (t) == FUNCTION_DECL && TREE_CODE (TREE_TYPE (t)) == FUNCTION_TYPE)
my_friendly_abort (53);
if (UNITS_PER_WORD <= 1)
my_friendly_abort (54);
- e1 = build (GT_EXPR, integer_type_node, e0, integer_zero_node);
+ e1 = build (GT_EXPR, boolean_type_node, e0, integer_zero_node);
e1 = build_compound_expr (tree_cons (NULL_TREE, exp_addr,
build_tree_list (NULL_TREE, e1)));
e1 = save_expr (e1);
}
else if (TYPE_PTRMEMFUNC_P (TREE_TYPE (member)))
{
- return get_member_function_from_ptrfunc (&addr, base, member);
+ return get_member_function_from_ptrfunc (&addr, member);
}
my_friendly_abort (56);
/* NOTREACHED */
{
tree list = DECL_FRIENDLIST (TYPE_NAME (type));
tree name = DECL_NAME (supplicant);
- tree ctype = DECL_CLASS_CONTEXT (supplicant);
+ tree ctype;
+
+ if (DECL_FUNCTION_MEMBER_P (supplicant))
+ ctype = DECL_CLASS_CONTEXT (supplicant);
+ else
+ ctype = NULL_TREE;
+
for (; list ; list = TREE_CHAIN (list))
{
if (name == TREE_PURPOSE (list))
}
{
- tree context = declp ? DECL_CLASS_CONTEXT (supplicant)
- : DECL_CONTEXT (TYPE_NAME (supplicant));
+ tree context;
+
+ if (! declp)
+ context = DECL_CONTEXT (TYPE_NAME (supplicant));
+ else if (DECL_FUNCTION_MEMBER_P (supplicant))
+ context = DECL_CLASS_CONTEXT (supplicant);
+ else
+ context = NULL_TREE;
if (context)
return is_friend (type, context);
}
if (type == friend_type)
{
- warning ("class `%s' is implicitly friends with itself",
+ pedwarn ("class `%s' is implicitly friends with itself",
TYPE_NAME_STRING (type));
return;
}
{
tree type, true_type, size, rval;
tree nelts;
- tree alloc_expr;
+ tree alloc_expr, alloc_temp;
int has_array = 0;
enum tree_code code = NEW_EXPR;
type = true_type = TREE_TYPE (type);
}
+ if (TREE_CODE (type) == FUNCTION_TYPE)
+ {
+ error ("new cannot be applied to a function type");
+ return error_mark_node;
+ }
+
/* When the object being created is an array, the new-expression yields a
pointer to the initial element (if any) of the array. For example,
both new int and new int[10] return an int*. 5.3.4. */
if (true_type == void_type_node)
{
- error ("invalid type for new: `void'");
+ error ("invalid type `void' for new");
return error_mark_node;
}
TREE_CALLS_NEW (rval) = 1;
}
- if (flag_check_new)
+ if (flag_check_new && rval)
{
- if (rval)
- rval = save_expr (rval);
- alloc_expr = rval;
+ /* For array new, we need to make sure that the call to new is
+ not expanded as part of the RTL_EXPR for the initialization,
+ so we can't just use save_expr here. */
+
+ alloc_temp = get_temp_name (TREE_TYPE (rval), 0);
+ alloc_expr = build (MODIFY_EXPR, TREE_TYPE (rval), alloc_temp, rval);
+ TREE_SIDE_EFFECTS (alloc_expr) = 1;
+ rval = alloc_temp;
}
+ else
+ alloc_expr = NULL_TREE;
/* if rval is NULL_TREE I don't have to allocate it, but are we totally
sure we have some extra bytes in that case for the BI_header_size
done:
- if (flag_check_new && alloc_expr && rval != alloc_expr)
+ if (alloc_expr)
{
- tree ifexp = build_binary_op (NE_EXPR, alloc_expr, integer_zero_node, 1);
- rval = build_conditional_expr (ifexp, rval, alloc_expr);
+ /* Did we modify the storage? */
+ if (rval != alloc_temp)
+ {
+ tree ifexp = build_binary_op (NE_EXPR, alloc_expr,
+ integer_zero_node, 1);
+ rval = build_conditional_expr (ifexp, rval, alloc_temp);
+ }
+ else
+ rval = alloc_expr;
}
if (rval && TREE_TYPE (rval) != build_pointer_type (type))
}
}
- expand_start_cond (build (GE_EXPR, integer_type_node,
+ expand_start_cond (build (GE_EXPR, boolean_type_node,
iterator, integer_zero_node), 0);
expand_start_loop_continue_elsewhere (1);
expand_assignment (base2,
build (PLUS_EXPR, TYPE_POINTER_TO (type), base2, size), 0, 0);
expand_loop_continue_here ();
- expand_exit_loop_if_false (0, build (NE_EXPR, integer_type_node,
+ expand_exit_loop_if_false (0, build (NE_EXPR, boolean_type_node,
build (PREDECREMENT_EXPR, integer_type_node, iterator, integer_one_node), minus_one));
if (obey_regdecls)
body = tree_cons (NULL_TREE,
build (EXIT_EXPR, void_type_node,
- build (EQ_EXPR, integer_type_node, base, tbase)),
+ build (EQ_EXPR, boolean_type_node, base, tbase)),
body);
loop = build (LOOP_EXPR, void_type_node, build_compound_expr (body));
/* Outermost wrapper: If pointer is null, punt. */
body = build (COND_EXPR, void_type_node,
- build (NE_EXPR, integer_type_node, base, integer_zero_node),
+ build (NE_EXPR, boolean_type_node, base, integer_zero_node),
body, integer_zero_node);
body = build1 (NOP_EXPR, void_type_node, body);
{ value = '}'; goto done; }
else if (c == '%' && c1 == ':')
{ value = '#'; goto done; }
- else if (c == ':' && c1 == '>')
- { value = ']'; goto done; }
nextchar = c1;
token_buffer[1] = 0;
value = SCOPE;
yylval.itype = 1;
}
+ else if (c == '>')
+ {
+ value = ']';
+ goto done;
+ }
else
{
nextchar = c;
int nested = (current_function_decl != NULL_TREE);
int toplev = (decl_function_context (fndecl) == NULL_TREE);
char *f = input_filename;
+ tree base = DECL_CLASS_CONTEXT (fndecl);
if (nested)
push_cp_function_context (toplev);
input_filename = DECL_SOURCE_FILE (fndecl);
- extract_interface_info ();
+ interface_unknown = CLASSTYPE_INTERFACE_UNKNOWN (base);
+ interface_only = CLASSTYPE_INTERFACE_ONLY (base);
start_function (NULL_TREE, fndecl, NULL_TREE, 1);
store_parm_decls ();
{
tree t = TREE_VALUE ($2);
if (t != NULL_TREE
- && TREE_CODE (TREE_TYPE (t)) == FUNCTION_TYPE)
- pedwarn ("ANSI C++ forbids using sizeof() on a function");
+ && ((TREE_TYPE (t)
+ && TREE_CODE (TREE_TYPE (t)) == FUNCTION_TYPE)
+ || is_overloaded_fn (t)))
+ pedwarn ("ANSI C++ forbids taking the sizeof a function type");
}
$$ = c_sizeof (TREE_TYPE ($2)); }
| SIZEOF '(' type_id ')' %prec HYPERUNARY
syntactically valid but semantically invalid. */
| '=' init
{
- if (flag_ansi)
+ if (pedantic)
pedwarn ("ANSI C++ forbids initialization of new expression with `='");
$$ = $2;
}
{
tree init = build_nt (CONSTRUCTOR, NULL_TREE,
nreverse ($3));
- if (flag_ansi)
+ if (pedantic)
pedwarn ("ANSI C++ forbids constructor-expressions");
/* Indicate that this was a GNU C constructor expression. */
TREE_HAS_CONSTRUCTOR (init) = 1;
expr_or_declarator:
notype_unqualified_id
- | notype_qualified_id
| '*' expr_or_declarator %prec UNARY
{ $$ = build_parse_node (INDIRECT_REF, $2); }
| '&' expr_or_declarator %prec UNARY
direct_notype_declarator:
complex_direct_notype_declarator
| notype_unqualified_id
- | notype_qualified_id
- { push_nested_class (TREE_TYPE (OP0 ($$)), 3);
- TREE_COMPLEXITY ($$) = current_class_depth; }
| '(' expr_or_declarator ')'
{ $$ = finish_decl_parsing ($2); }
;
$<ttype>$ = expand_start_stmt_expr (); }
compstmt ')'
{ tree rtl_exp;
- if (flag_ansi)
+ if (pedantic)
pedwarn ("ANSI C++ forbids braced-groups within expressions");
rtl_exp = expand_end_stmt_expr ($<ttype>2);
/* The statements have side effects, so the group does. */
| object unqualified_id %prec UNARY
{ got_object = NULL_TREE;
$$ = build_component_ref ($$, $2, NULL_TREE, 1); }
- | object qualified_id %prec UNARY
+ | object overqualified_id %prec UNARY
{ got_object = NULL_TREE;
$$ = build_object_ref ($$, OP0 ($2), OP1 ($2)); }
| object unqualified_id '(' nonnull_exprlist ')'
(LOOKUP_NORMAL|LOOKUP_AGGR));
#endif
}
- | object qualified_id '(' nonnull_exprlist ')'
+ | object overqualified_id '(' nonnull_exprlist ')'
{
got_object = NULL_TREE;
if (IS_SIGNATURE (IDENTIFIER_TYPE_VALUE (OP0 ($2))))
else
$$ = build_scoped_method_call ($$, OP0 ($2), OP1 ($2), $4);
}
- | object qualified_id LEFT_RIGHT
+ | object overqualified_id LEFT_RIGHT
{
got_object = NULL_TREE;
if (IS_SIGNATURE (IDENTIFIER_TYPE_VALUE (OP0 ($2))))
| object '~' TYPESPEC LEFT_RIGHT
{
got_object = NULL_TREE;
- if (TREE_CODE (TREE_TYPE ($1))
- != TREE_CODE (TREE_TYPE (IDENTIFIER_GLOBAL_VALUE ($3))))
+ if (IDENTIFIER_GLOBAL_VALUE ($3)
+ && (TREE_CODE (TREE_TYPE ($1))
+ != TREE_CODE (TREE_TYPE (IDENTIFIER_GLOBAL_VALUE ($3)))))
cp_error ("`%E' is not of type `%T'", $1, $3);
$$ = convert (void_type_node, $1);
}
}
$<ttype>$ = expand_start_stmt_expr (); }
compstmt ')'
- { if (flag_ansi)
+ { if (pedantic)
pedwarn ("ANSI C++ forbids braced-groups within expressions");
$$ = expand_end_stmt_expr ($<ttype>2); }
| primary_no_id '(' nonnull_exprlist ')'
{ $$ = decl_tree_cons (NULL_TREE, $2, $$); }
| typespec reserved_declspecs %prec HYPERUNARY
{ $$ = decl_tree_cons (NULL_TREE, $$, $2); }
+ | typespec reserved_typespecquals reserved_declspecs
+ { $$ = decl_tree_cons (NULL_TREE, $$, chainon ($2, $3)); }
| declmods typespec reserved_declspecs
{ $$ = decl_tree_cons (NULL_TREE, $2, chainon ($3, $$)); }
| declmods typespec reserved_typespecquals
| complete_type_name
| TYPEOF '(' expr ')'
{ $$ = TREE_TYPE ($3);
- if (flag_ansi)
+ if (pedantic)
pedwarn ("ANSI C++ forbids `typeof'"); }
| TYPEOF '(' type_id ')'
{ $$ = groktypename ($3);
- if (flag_ansi)
+ if (pedantic)
pedwarn ("ANSI C++ forbids `typeof'"); }
| SIGOF '(' expr ')'
{ tree type = TREE_TYPE ($3);
non-constant dimension. */
| '(' type_id ')' '[' expr ']'
{
- if (flag_ansi)
+ if (pedantic)
pedwarn ("ANSI C++ forbids array dimensions with parenthesized type in new");
$$ = build_parse_node (ARRAY_REF, TREE_VALUE ($2), $5);
$$ = build_decl_list (TREE_PURPOSE ($2), $$);
{ $$ = build_parse_node (ARRAY_REF, $$, $3); }
| direct_notype_declarator '[' ']'
{ $$ = build_parse_node (ARRAY_REF, $$, NULL_TREE); }
+ | notype_qualified_id
+ { push_nested_class (TREE_TYPE (OP0 ($$)), 3);
+ TREE_COMPLEXITY ($$) = current_class_depth; }
;
qualified_id:
maybe_label_decls:
/* empty */
| label_decls
- { if (flag_ansi)
+ { if (pedantic)
pedwarn ("ANSI C++ forbids label declarations"); }
;
register tree label
= build_decl (LABEL_DECL, NULL_TREE, NULL_TREE);
- if (flag_ansi)
+ if (pedantic)
pedwarn ("ANSI C++ forbids range expressions in switch statement");
if (value1 != error_mark_node
&& value2 != error_mark_node)
case REFERENCE_TYPE:
return uses_template_parms (TREE_TYPE (t));
case RECORD_TYPE:
+ if (TYPE_PTRMEMFUNC_FLAG (t))
+ return uses_template_parms (TYPE_PTRMEMFUNC_FN_TYPE (t));
case UNION_TYPE:
if (!TYPE_NAME (t))
return 0;
&& type != integer_type_node
&& type != void_type_node
&& type != char_type_node)
- type = cp_build_type_variant (tsubst (type, args, nargs, in_decl),
- TYPE_READONLY (type),
- TYPE_VOLATILE (type));
+ type = tsubst (type, args, nargs, in_decl);
+
switch (TREE_CODE (t))
{
case RECORD_TYPE:
my_friendly_assert (TREE_CODE (tmpl) == TEMPLATE_DECL, 283);
len = TREE_VEC_LENGTH (DECL_TEMPLATE_PARMS (tmpl));
+ i = len;
+ while (i--)
+ targ_ptr[i] = copy_to_permanent (targ_ptr[i]);
+
for (fndecl = DECL_TEMPLATE_INSTANTIATIONS (tmpl);
fndecl; fndecl = TREE_CHAIN (fndecl))
{
tree *t1 = &TREE_VEC_ELT (TREE_PURPOSE (fndecl), 0);
for (i = len - 1; i >= 0; i--)
- if (t1[i] != targ_ptr[i])
+ if (simple_cst_equal (t1[i], targ_ptr[i]) <= 0)
goto no_match;
/* Here, we have a match. */
return 1;
if (arg == unknown_type_node)
return 1;
+
+ if (! uses_template_parms (parm)
+ && TREE_CODE_CLASS (TREE_CODE (arg)) != 't')
+ {
+ if (can_convert_arg (parm, TREE_TYPE (arg), arg))
+ continue;
+ return 1;
+ }
+
#if 0
if (TREE_CODE (arg) == VAR_DECL)
arg = TREE_TYPE (arg);
case ARRAY_TYPE:
return build_array_type (make_deep_copy (TREE_TYPE (t)),
make_deep_copy (TYPE_DOMAIN (t)));
+ case INTEGER_TYPE:
+ return build_index_type (make_deep_copy (TYPE_MAX_VALUE (t)));
+
case OFFSET_TYPE:
return build_offset_type (make_deep_copy (TYPE_OFFSET_BASETYPE (t)),
make_deep_copy (TREE_TYPE (t)));
build_function_type
(make_deep_copy (TREE_TYPE (t)),
make_deep_copy (TREE_CHAIN (TYPE_ARG_TYPES (t)))));
+
case RECORD_TYPE:
if (TYPE_PTRMEMFUNC_P (t))
return build_ptrmemfunc_type
return 1;
case UNINSTANTIATED_P_TYPE:
- return UPT_TEMPLATE (t1) == UPT_TEMPLATE (t2);
+ if (UPT_TEMPLATE (t1) != UPT_TEMPLATE (t2))
+ return 0;
+ {
+ int i = TREE_VEC_LENGTH (UPT_PARMS (t1));
+ tree *p1 = &TREE_VEC_ELT (UPT_PARMS (t1), 0);
+ tree *p2 = &TREE_VEC_ELT (UPT_PARMS (t2), 0);
+
+ while (i--)
+ {
+ if (TREE_CODE_CLASS (TREE_CODE (p1[i])) == 't')
+ {
+ if (! comptypes (p1[i], p2[i], 1))
+ return 0;
+ }
+ else
+ {
+ if (simple_cst_equal (p1[i], p2[i]) <= 0)
+ return 0;
+ }
+ }
+ }
+ return 1;
}
return attrval == 2 && val == 1 ? 2 : val;
}
return error_mark_node;
itype = TREE_TYPE (idx);
- /* We must check here for the reference, so we can do the possible
- conversions immediately afterwards. */
- if (TREE_CODE (itype) == REFERENCE_TYPE)
- {
- idx = convert_from_reference (idx);
- itype = TREE_TYPE (idx);
- }
-
- if (IS_AGGR_TYPE (itype))
- {
- if (TYPE_HAS_INT_CONVERSION (itype))
- idx = build_type_conversion (CONVERT_EXPR,
- integer_type_node, idx, 1);
- else
- {
- error_with_aggr_type (itype,
- "type `%s' requires integer conversion for array indexing");
- return error_mark_node;
- }
- }
if (TREE_CODE (TREE_TYPE (array)) == ARRAY_TYPE
&& TREE_CODE (array) != INDIRECT_REF)
return error_mark_node;
}
- /* Note in C++ we don't bother warning about subscripting a
- `register' array, since it's valid in C++ to take the address
- of something with that storage specification. */
if (pedantic && !lvalue_p (array))
pedwarn ("ANSI C++ forbids subscripting non-lvalue array");
- if (pedantic)
+ /* Note in C++ it is valid to subscript a `register' array, since
+ it is valid to take the address of something with that
+ storage specification. */
+ if (extra_warnings)
{
tree foo = array;
while (TREE_CODE (foo) == COMPONENT_REF)
foo = TREE_OPERAND (foo, 0);
if (TREE_CODE (foo) == VAR_DECL && DECL_REGISTER (foo))
- pedwarn ("ANSI C++ forbids subscripting non-lvalue array");
+ warning ("subscripting array declared `register'");
}
type = TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (array)));
decl = C_C_D;
decl_addr = build_unary_op (ADDR_EXPR, decl, 0);
- function = get_member_function_from_ptrfunc (&decl_addr, decl,
+ function = get_member_function_from_ptrfunc (&decl_addr,
TREE_OPERAND (function, 1));
params = tree_cons (NULL_TREE, decl_addr, params);
return build_function_call (function, params);
instance to use, if the member points to a virtual member. */
tree
-get_member_function_from_ptrfunc (instance_ptrptr, instance, function)
+get_member_function_from_ptrfunc (instance_ptrptr, function)
tree *instance_ptrptr;
- tree instance;
tree function;
{
if (TREE_CODE (function) == OFFSET_REF)
tree index = save_expr (build_component_ref (function,
index_identifier,
0, 0));
- tree e1 = build (GT_EXPR, delta_type_node, index,
+ tree e1 = build (GT_EXPR, boolean_type_node, index,
convert (delta_type_node, integer_zero_node));
tree delta = convert (ptrdiff_type_node,
build_component_ref (function, delta_identifier, 0, 0));
tree e3;
tree aref, vtbl;
+ tree instance;
+ tree instance_ptr = *instance_ptrptr;
+
+ if (TREE_SIDE_EFFECTS (instance_ptr))
+ instance_ptr = save_expr (instance_ptr);
+
/* convert down to the right base, before using the instance. */
- instance = convert_pointer_to_real (TYPE_METHOD_BASETYPE (TREE_TYPE (fntype)),
- build_unary_op (ADDR_EXPR, instance, 0));
+ instance
+ = convert_pointer_to_real (TYPE_METHOD_BASETYPE (TREE_TYPE (fntype)),
+ instance_ptr);
if (instance == error_mark_node)
return instance;
delta, 1);
}
- *instance_ptrptr = build (PLUS_EXPR, TREE_TYPE (*instance_ptrptr),
- *instance_ptrptr,
- delta);
+ *instance_ptrptr = build (PLUS_EXPR, TREE_TYPE (instance_ptr),
+ instance_ptr, delta);
if (flag_vtable_thunks)
e2 = aref;
else
e3 = PFN_FROM_PTRMEMFUNC (function);
TREE_TYPE (e2) = TREE_TYPE (e3);
function = build_conditional_expr (e1, e2, e3);
+
+ /* Make sure this doesn't get evaluated first inside one of the
+ branches of the COND_EXPR. */
+ if (TREE_CODE (instance_ptr) == SAVE_EXPR)
+ function = build (COMPOUND_EXPR, TREE_TYPE (function),
+ instance_ptr, function);
}
return function;
}
{
tree instance_ptr = build_unary_op (ADDR_EXPR, C_C_D, 0);
fntype = TYPE_PTRMEMFUNC_FN_TYPE (fntype);
- function = get_member_function_from_ptrfunc (&instance_ptr, C_C_D, function);
+ function = get_member_function_from_ptrfunc (&instance_ptr, function);
}
is_method = (TREE_CODE (fntype) == POINTER_TYPE
tree arg1, arg2;
int convert_p;
{
- tree type1, type2;
tree args[2];
args[0] = arg1;
if (convert_p)
{
tree args_save [2];
+ tree type0, type1;
args[0] = args_save [0] = default_conversion (args[0]);
args[1] = args_save [1] = default_conversion (args[1]);
+ if (args[0] == error_mark_node || args[1] == error_mark_node)
+ return error_mark_node;
+
+ type0 = TREE_TYPE (args[0]);
+ type1 = TREE_TYPE (args[1]);
+
if (type_unknown_p (args[0]))
{
- args[0] = instantiate_type (TREE_TYPE (args[1]), args[0], 1);
+ args[0] = instantiate_type (type1, args[0], 1);
args[0] = default_conversion (args[0]);
}
else if (type_unknown_p (args[1]))
{
- args[1] = require_instantiated_type (TREE_TYPE (args[0]),
- args[1],
+ args[1] = require_instantiated_type (type0, args[1],
error_mark_node);
args[1] = default_conversion (args[1]);
}
- type1 = TREE_TYPE (args[0]);
- type2 = TREE_TYPE (args[1]);
-
- if (IS_AGGR_TYPE_2 (type1, type2))
+ if (IS_AGGR_TYPE (type0) || IS_AGGR_TYPE (type1))
{
/* Try to convert this to something reasonable. */
if (! build_default_binary_type_conversion(code, &args[0], &args[1]))
- return error_mark_node;
- }
- else if (IS_AGGR_TYPE (type1) || IS_AGGR_TYPE (type2))
- {
- int convert_index = IS_AGGR_TYPE (type2);
- /* Avoid being tripped up by things like (ARG1 != 0). */
- tree types[2], try;
-
- types[0] = type1; types[1] = type2;
- if (code == TRUTH_ANDIF_EXPR || code == TRUTH_ORIF_EXPR)
- try = build_type_conversion (code, boolean_type_node,
- args[convert_index], 1);
- else
- {
- try = build_type_conversion (code, types[convert_index ^ 1],
- args[convert_index], 1);
-
- if (try == 0
- && args[1] == integer_zero_node
- && (code == NE_EXPR || code == EQ_EXPR))
- try = build_type_conversion (code, ptr_type_node,
- args[convert_index], 1);
- }
-
- if (try == 0)
{
cp_error ("no match for `%O(%#T, %#T)'", code,
TREE_TYPE (arg1), TREE_TYPE (arg2));
return error_mark_node;
}
- if (try == error_mark_node)
- error ("ambiguous pointer conversion");
- args[convert_index] = try;
}
-
+
if (args[0] == args_save[0])
args[0] = arg1;
if (args[1] == args_save[1])
{
tree base = common_base_type (tt0, tt1);
if (base == NULL_TREE)
- cp_warning ("comparison of distinct object pointer types `%T' and `%T'", type0, type1);
+ cp_pedwarn ("comparison of distinct object pointer types `%T' and `%T'", type0, type1);
else if (base == error_mark_node)
{
cp_error ("comparison of pointer types `%T' and `%T' requires conversion to ambiguous supertype", type0, type1);
if (pedantic && TREE_CODE (tt1) == FUNCTION_TYPE
&& tree_int_cst_lt (TYPE_SIZE (type0), TYPE_SIZE (type1)))
pedwarn ("ANSI C++ forbids comparison of `void *' with function pointer");
+ else if (TREE_CODE (tt1) == OFFSET_TYPE)
+ pedwarn ("ANSI C++ forbids conversion of a pointer to member to `void *'");
}
else if (tt1 == void_type_node)
{
}
else if (code0 == POINTER_TYPE && TREE_CODE (op1) == INTEGER_CST
&& integer_zerop (op1))
- {
- op1 = null_pointer_node;
- if (pedantic)
- pedwarn ("ordered comparison of pointer with integer zero");
- }
+ op1 = null_pointer_node;
else if (code1 == POINTER_TYPE && TREE_CODE (op0) == INTEGER_CST
&& integer_zerop (op0))
- {
- op0 = null_pointer_node;
- if (pedantic)
- pedwarn ("ANSI C++ forbids ordered comparison of pointer with integer zero");
- }
+ op0 = null_pointer_node;
else if (code0 == POINTER_TYPE && code1 == INTEGER_TYPE)
{
if (pedantic)
/* Do the checking based on the original operand trees, so that
casts will be considered, but default promotions won't be. */
if (TREE_UNSIGNED (comp_type)
- && ((op0_signed
- && (TREE_CODE (op0) != INTEGER_CST
- || (TREE_CODE (op0) == INTEGER_CST
- && INT_CST_LT (op0, integer_zero_node))))
- || (op1_signed
- && (TREE_CODE (op1) != INTEGER_CST
- || (TREE_CODE (op1) == INTEGER_CST
- && INT_CST_LT (op1, integer_zero_node))))))
+ && ((op0_signed && (TREE_CODE (orig_op0) != INTEGER_CST
+ || tree_int_cst_sgn (orig_op0) == -1))
+ || (op1_signed && (TREE_CODE (orig_op1) != INTEGER_CST
+ || tree_int_cst_sgn (orig_op1) == -1))))
warning ("comparison between signed and unsigned");
/* Warn if two unsigned values are being compared in a size
/* No default_conversion here. It causes trouble for ADDR_EXPR. */
register tree arg = xarg;
register tree argtype = 0;
- register enum tree_code typecode = TREE_CODE (TREE_TYPE (arg));
char *errstring = NULL;
tree val;
- int isaggrtype;
- if (typecode == ERROR_MARK)
+ if (arg == error_mark_node)
return error_mark_node;
- if (typecode == REFERENCE_TYPE && code != ADDR_EXPR && ! noconvert)
- {
- arg = convert_from_reference (arg);
- typecode = TREE_CODE (TREE_TYPE (arg));
- }
-
- if (typecode == ENUMERAL_TYPE)
- typecode = INTEGER_TYPE;
-
- if (typecode == BOOLEAN_TYPE && ! noconvert)
- typecode = INTEGER_TYPE;
-
- isaggrtype = IS_AGGR_TYPE_CODE (typecode);
-
switch (code)
{
case CONVERT_EXPR:
/* This is used for unary plus, because a CONVERT_EXPR
is enough to prevent anybody from looking inside for
associativity, but won't generate any code. */
- if (!(typecode == INTEGER_TYPE || typecode == REAL_TYPE))
- errstring = "wrong type argument to unary plus";
- else if (!noconvert)
- arg = default_conversion (arg);
- arg = build1 (NON_LVALUE_EXPR, TREE_TYPE (arg), arg);
- break;
-
- case NEGATE_EXPR:
- if (typecode == OFFSET_TYPE)
- {
- arg = resolve_offset_ref (arg);
- typecode = TREE_CODE (TREE_TYPE (arg));
- isaggrtype = IS_AGGR_TYPE_CODE (typecode);
- }
-
- if (isaggrtype)
+ if (!(arg = build_expr_type_conversion
+ (WANT_ARITH | WANT_ENUM | WANT_POINTER, arg, 1)))
+ errstring = "wrong type argument to unary plus";
+ else
{
if (!noconvert)
- arg = default_conversion (arg);
- else
- {
- cp_error ("type conversion for type `%T' not allowed",
- TREE_TYPE (arg));
- return error_mark_node;
- }
- typecode = TREE_CODE (TREE_TYPE (arg));
- noconvert = 1;
+ arg = default_conversion (arg);
+ arg = build1 (NON_LVALUE_EXPR, TREE_TYPE (arg), arg);
}
+ break;
- if (!(typecode == INTEGER_TYPE || typecode == REAL_TYPE))
- errstring = "wrong type argument to unary minus";
+ case NEGATE_EXPR:
+ if (!(arg = build_expr_type_conversion (WANT_ARITH | WANT_ENUM, arg, 1)))
+ errstring = "wrong type argument to unary minus";
else if (!noconvert)
arg = default_conversion (arg);
break;
case BIT_NOT_EXPR:
- if (typecode == OFFSET_TYPE)
- {
- arg = resolve_offset_ref (arg);
- typecode = TREE_CODE (TREE_TYPE (arg));
- isaggrtype = IS_AGGR_TYPE_CODE (typecode);
- }
-
- if (isaggrtype)
- {
- if (!noconvert)
- arg = default_conversion (arg);
- else
- {
- cp_error ("type conversion for type `%T' not allowed",
- TREE_TYPE (arg));
- return error_mark_node;
- }
- typecode = TREE_CODE (TREE_TYPE (arg));
- noconvert = 1;
- }
-
- if (typecode != INTEGER_TYPE)
- errstring = "wrong type argument to bit-complement";
+ if (!(arg = build_expr_type_conversion (WANT_INT | WANT_ENUM, arg, 1)))
+ errstring = "wrong type argument to bit-complement";
else if (!noconvert)
arg = default_conversion (arg);
break;
case ABS_EXPR:
- if (typecode == OFFSET_TYPE)
- {
- arg = resolve_offset_ref (arg);
- typecode = TREE_CODE (TREE_TYPE (arg));
- isaggrtype = IS_AGGR_TYPE_CODE (typecode);
- }
-
- if (isaggrtype)
- {
- if (!noconvert)
- arg = default_conversion (arg);
- else
- {
- cp_error ("type conversion for type `%T' not allowed",
- TREE_TYPE (arg));
- return error_mark_node;
- }
- typecode = TREE_CODE (TREE_TYPE (arg));
- noconvert = 1;
- }
-
- if (!(typecode == INTEGER_TYPE || typecode == REAL_TYPE))
- errstring = "wrong type argument to abs";
+ if (!(arg = build_expr_type_conversion (WANT_ARITH | WANT_ENUM, arg, 1)))
+ errstring = "wrong type argument to abs";
else if (!noconvert)
arg = default_conversion (arg);
break;
/* Report invalid types. */
- if (typecode == OFFSET_TYPE)
- {
- arg = resolve_offset_ref (arg);
- typecode = TREE_CODE (TREE_TYPE (arg));
- isaggrtype = IS_AGGR_TYPE_CODE (typecode);
- }
-
- if (isaggrtype)
- {
- arg = default_conversion (arg);
- typecode = TREE_CODE (TREE_TYPE (arg));
- }
-
- if (typecode != POINTER_TYPE
- && typecode != INTEGER_TYPE && typecode != REAL_TYPE)
+ if (!(arg = build_expr_type_conversion (WANT_ARITH | WANT_POINTER,
+ arg, 1)))
{
if (code == PREINCREMENT_EXPR)
errstring ="no pre-increment operator for type";
/* Compute the increment. */
- if (typecode == POINTER_TYPE)
+ if (TREE_CODE (argtype) == POINTER_TYPE)
{
enum tree_code tmp = TREE_CODE (TREE_TYPE (argtype));
if (TYPE_SIZE (TREE_TYPE (argtype)) == 0)
? "increment" : "decrement")))
return error_mark_node;
- val = build (code, TREE_TYPE (arg), arg, inc);
+ /* Forbid using -- on `bool'. */
+ if (TREE_TYPE (arg) == boolean_type_node)
+ {
+ if (code == POSTDECREMENT_EXPR || code == PREDECREMENT_EXPR)
+ {
+ cp_error ("invalid use of `--' on bool variable `%D'", arg);
+ return error_mark_node;
+ }
+#if 0
+ /* This will only work if someone can convince Kenner to accept
+ my patch to expand_increment. (jason) */
+ val = build (code, TREE_TYPE (arg), arg, inc);
+#else
+ if (code == POSTINCREMENT_EXPR)
+ {
+ arg = stabilize_reference (arg);
+ val = build (MODIFY_EXPR, TREE_TYPE (arg), arg,
+ boolean_true_node);
+ TREE_SIDE_EFFECTS (val) = 1;
+ arg = save_expr (arg);
+ val = build (COMPOUND_EXPR, TREE_TYPE (arg), val, arg);
+ val = build (COMPOUND_EXPR, TREE_TYPE (arg), arg, val);
+ }
+ else
+ val = build (MODIFY_EXPR, TREE_TYPE (arg), arg,
+ boolean_true_node);
+#endif
+ }
+ else
+ val = build (code, TREE_TYPE (arg), arg, inc);
+
TREE_SIDE_EFFECTS (val) = 1;
return convert (result_type, val);
}
/* Note that this operation never does default_conversion
regardless of NOCONVERT. */
- if (typecode == REFERENCE_TYPE)
+ argtype = TREE_TYPE (arg);
+ if (TREE_CODE (argtype) == REFERENCE_TYPE)
{
arg = build1 (CONVERT_EXPR, build_pointer_type (TREE_TYPE (TREE_TYPE (arg))), arg);
TREE_REFERENCE_EXPR (arg) = 1;
;
/* Anything not already handled and not a true memory reference
is an error. */
- else if (typecode != FUNCTION_TYPE
- && typecode != METHOD_TYPE
+ else if (TREE_CODE (argtype) != FUNCTION_TYPE
+ && TREE_CODE (argtype) != METHOD_TYPE
&& !lvalue_or_else (arg, "unary `&'"))
return error_mark_node;
/* Ordinary case; arg is a COMPONENT_REF or a decl. */
- argtype = TREE_TYPE (arg);
/* If the lvalue is const or volatile,
merge that into the type that the address will point to. */
if (TREE_CODE_CLASS (TREE_CODE (arg)) == 'd'
rest = build_compound_expr (TREE_CHAIN (list));
- /* When pedantic, a compound expression can be neither an lvalue
- nor an integer constant expression. */
- if (! TREE_SIDE_EFFECTS (TREE_VALUE (list)) && ! pedantic)
- return rest;
+ if (! TREE_SIDE_EFFECTS (TREE_VALUE (list)))
+ {
+ /* the left-hand operand of a comma expression is like an expression
+ statement: we should warn if it doesn't have any side-effects,
+ unless it was explicitly cast to (void). */
+ if ((extra_warnings || warn_unused)
+ && !(TREE_CODE (TREE_VALUE(list)) == CONVERT_EXPR
+ && TREE_TYPE (TREE_VALUE(list)) == void_type_node))
+ warning("left-hand operand of comma expression has no effect");
+
+ /* When pedantic, a compound expression can be neither an lvalue
+ nor an integer constant expression. */
+ if (! pedantic)
+ return rest;
+ }
+#if 0 /* this requires a gcc backend patch to export warn_if_unused_value */
+ else if (warn_unused)
+ warn_if_unused_value (TREE_VALUE(list));
+#endif
return build (COMPOUND_EXPR, TREE_TYPE (rest),
break_out_cleanups (TREE_VALUE (list)), rest);
cp_error ("`%T' does not define operator=", lhstype);
else if (! TYPE_HAS_REAL_ASSIGNMENT (lhstype)
&& ! TYPE_HAS_COMPLEX_ASSIGN_REF (lhstype)
- /* FIXME find some way to deal with TARGET_EXPRs here. */
- && TREE_CODE (newrhs) != TARGET_EXPR
&& TYPE_MAIN_VARIANT (lhstype) == TYPE_MAIN_VARIANT (TREE_TYPE (newrhs)))
/* Do the default thing */;
else
newrhs = build_binary_op (modifycode, lhs, rhs_tmp, 1);
}
else
- return error_mark_node;
+ {
+ cp_error ("no match for `%O(%#T, %#T)'", modifycode,
+ TREE_TYPE (lhs), TREE_TYPE (rhs));
+ return error_mark_node;
+ }
}
else
{
}
else
newrhs = convert_for_assignment (lhstype, newrhs, "assignment",
- NULL_TREE, 0);
- if (flag_elide_constructors == 0
- && TREE_CODE (newrhs) == CALL_EXPR
- && TREE_ADDRESSABLE (lhstype))
+ NULL_TREE, 0);
+ if (TREE_CODE (newrhs) == CALL_EXPR
+ && TYPE_NEEDS_CONSTRUCTING (lhstype))
+ newrhs = build_cplus_new (lhstype, newrhs, 0);
+
+ if (TREE_CODE (newrhs) == TARGET_EXPR)
{
- /* Can't initialized directly from a CALL_EXPR, since
- we don't know about what doesn't alias what. */
+ /* Can't initialize directly from a TARGET_EXPR, since that would
+ cause the lhs to be constructed twice. So we force the
+ TARGET_EXPR to be expanded. expand_expr should really do this
+ by itself. */
+
+ tree xval = make_node (RTL_EXPR);
+ rtx rtxval;
- tree temp = get_temp_name (lhstype, 0);
- newrhs = build (COMPOUND_EXPR, lhstype,
- build_modify_expr (temp, INIT_EXPR, newrhs),
- temp);
+ do_pending_stack_adjust ();
+ start_sequence_for_rtl_expr (xval);
+ emit_note (0, -1);
+ rtxval = expand_expr (newrhs, NULL, VOIDmode, 0);
+ do_pending_stack_adjust ();
+ TREE_SIDE_EFFECTS (xval) = 1;
+ RTL_EXPR_SEQUENCE (xval) = get_insns ();
+ end_sequence ();
+ RTL_EXPR_RTL (xval) = rtxval;
+ TREE_TYPE (xval) = lhstype;
+ newrhs = xval;
}
}
}
if (TREE_VIA_VIRTUAL (binfo))
{
- warning ("pointer to member conversion to virtual base class will only work if your very careful");
+ warning ("pointer to member conversion to virtual base class will only work if you are very careful");
}
return build_binary_op (MINUS_EXPR,
integer_zero_node,
}
if (TREE_VIA_VIRTUAL (binfo))
{
- warning ("pointer to member conversion from virtual base class will only work if your very careful");
+ warning ("pointer to member conversion from virtual base class will only work if you are very careful");
}
return BINFO_OFFSET (binfo);
}
force);
delta = build_binary_op (PLUS_EXPR, delta, ndelta, 1);
delta2 = build_binary_op (PLUS_EXPR, ndelta2, delta2, 1);
- e1 = fold (build (GT_EXPR, integer_type_node, index, integer_zero_node));
+ e1 = fold (build (GT_EXPR, boolean_type_node, index, integer_zero_node));
u = build_nt (CONSTRUCTOR, 0, tree_cons (delta2_identifier, delta2, NULL_TREE));
u = build_nt (CONSTRUCTOR, 0, tree_cons (NULL_TREE, delta,
silly. So instead, we just do the equivalent of a call to fatal in the
same situation (call exit). */
-/* First used: 0 (reserved), Last used: 364. Free: */
+/* First used: 0 (reserved), Last used: 366. Free: */
static int abortcount = 0;
}
init = element;
}
+ while (TREE_CODE (init) == CONSTRUCTOR)
+ {
+ cp_pedwarn ("braces around scalar initializer for `%T'", type);
+ init = CONSTRUCTOR_ELTS (init);
+ if (TREE_CHAIN (init))
+ cp_pedwarn ("ignoring extra initializers for `%T'", type);
+ init = TREE_VALUE (init);
+ }
return convert_for_initialization (0, type, init, LOOKUP_NORMAL,
"initialization", NULL_TREE, 0);