aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--gcc/cp/ChangeLog64
-rw-r--r--gcc/cp/Makefile.in16
-rw-r--r--gcc/cp/NEWS5
-rw-r--r--gcc/cp/class.c5
-rw-r--r--gcc/cp/cp-tree.h33
-rw-r--r--gcc/cp/decl.c410
-rw-r--r--gcc/cp/decl2.c15
-rw-r--r--gcc/cp/init.c44
-rw-r--r--gcc/cp/ir.texi55
-rw-r--r--gcc/cp/lang-options.h2
-rw-r--r--gcc/cp/pt.c5
-rw-r--r--gcc/cp/search.c6
-rw-r--r--gcc/cp/semantics.c99
-rw-r--r--gcc/cp/typeck.c16
-rw-r--r--gcc/testsuite/g++.old-deja/g++.other/static8.C7
15 files changed, 340 insertions, 442 deletions
diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog
index f26a659..5f0bce0 100644
--- a/gcc/cp/ChangeLog
+++ b/gcc/cp/ChangeLog
@@ -1,3 +1,67 @@
+1999-09-20 Mark Mitchell <mark@codesourcery.com>
+
+ Remove support for assigning to `this'.
+ * NEWS: Note that fact.
+ * class.c (build_vbase_path): Don't check flag_this_is_variable.
+ * cp-tree.h (EXPR_STMT_ASSIGNS_THIS): Remove.
+ (language_function): Remove assigns_this, just_assigned_this, and
+ x_base_init_expr. Add x_vcalls_possible_p. Add vtbls_set_up_p.
+ (base_init_expr): Remove.
+ (current_vcalls_possible_p): New macro.
+ (vtbls_set_up_p): Likewise.
+ (emit_base_init): Change prototype.
+ * decl.c (finish_destructor_body): New function, split out from
+ finish_function.
+ (current_function_assigns_this): Remove.
+ (current_function_just_assigned_this): Likewise.
+ (start_function): Don't set them.
+ (finish_function): Don't check them. Don't emit
+ base-initialization code here. Generate code for destructors when
+ doing semantic analysis.
+ (finish_stmt): Don't check current_function_just_assigned_this.
+ * decl2.c (lang_f_options): Remove this-is-variable.
+ (lang_decode_option): Likewise.
+ (grokclassfn): Don't check flag_this_is_variable.
+ * init.c (emit_base_init): Return the expression generated.
+ (construct_virtual_bases): Don't push/pop obstacks. Fix
+ typo.
+ (build_new_1): Don't check flag_this_is_variable.
+ (get_temp_regvar): Don't set DECL_REGISTER.
+ (build_vec_init): Don't call use_variable.
+ * lang-options.h: Remove "-fthis-is-variable" and
+ "-fno-this-is-variable".
+ * pt.c (tsubst_expr): Don't check EXPR_STMT_ASSIGNS_THIS.
+ * search.c (expand_upcast_fixups): Use finish_expr_stmt, not
+ expand_expr_stmt.
+ * semantics.c (finish_expr_stmt_real): Rename to ...
+ (finish_expr_stmt): This. Remove assigned_this parameter.
+ (begin_if_stmt): Call do_pushlevel before starting the statement.
+ (begin_compound_stmt): Don't declare __FUNCTION__ in scope-less
+ blocks.
+ (setup_vtbl_ptr): Emit initialization code for bases and members
+ at semantic-analysis time. Emit code to initialize vtables in
+ destructors here.
+ (expand_stmt): Use finish_expr_stmt, not finish_expr_stmt_real.
+ Don't handle CTOR_INITIALIZER any more.
+ * typeck.c (build_modify_expr): Don't check for assignments to
+ this.
+ (c_expand_return): Don't suggest assigning to `this'.
+
+ * Makefile.in (decl.o): Depend on RTL_H.
+ (decl2.o): Likewise.
+ (class.o): Likewise.
+ (call.o): Likewise.
+ (method.o): Likewise.
+ (search.o): Likewise.
+ (tree.o): Likewise.
+ (pt.o): Likewise.
+
+ * decl.c (duplicate_decls): When a builtin function is redeclared
+ as static, make sure it is mangled correctly.
+
+ * ir.texi (CTOR_INITIALIZER): Remove mention. Fix typo. Add
+ detail about the statement-tree.
+
1999-09-20 Nathan Sidwell <nathan@acm.org>
* parse.y (primary): Use build_functional_cast for CV_QUALIFIER.
diff --git a/gcc/cp/Makefile.in b/gcc/cp/Makefile.in
index 9ca789b..db32e7f 100644
--- a/gcc/cp/Makefile.in
+++ b/gcc/cp/Makefile.in
@@ -248,33 +248,33 @@ lex.o : lex.c $(CONFIG_H) $(CXX_TREE_H) \
decl.o : decl.c $(CONFIG_H) $(CXX_TREE_H) $(srcdir)/../flags.h \
lex.h decl.h $(srcdir)/../stack.h $(srcdir)/../output.h \
$(srcdir)/../except.h $(srcdir)/../system.h $(srcdir)/../toplev.h \
- $(srcdir)/../hash.h $(srcdir)/../ggc.h
+ $(srcdir)/../hash.h $(srcdir)/../ggc.h $(RTL_H)
decl2.o : decl2.c $(CONFIG_H) $(CXX_TREE_H) $(srcdir)/../flags.h \
lex.h decl.h $(EXPR_H) $(srcdir)/../except.h \
$(srcdir)/../output.h $(srcdir)/../except.h $(srcdir)/../system.h \
$(srcdir)/../toplev.h $(srcdir)/../dwarf2out.h $(srcdir)/../dwarfout.h \
- $(srcdir)/../../include/splay-tree.h $(srcdir)/../ggc.h
+ $(srcdir)/../../include/splay-tree.h $(srcdir)/../ggc.h $(RTL_H)
typeck2.o : typeck2.c $(CONFIG_H) $(CXX_TREE_H) $(srcdir)/../flags.h \
$(srcdir)/../system.h $(srcdir)/../toplev.h
typeck.o : typeck.c $(CONFIG_H) $(CXX_TREE_H) $(srcdir)/../flags.h $(RTL_H) \
$(EXPR_H) $(srcdir)/../system.h $(srcdir)/../toplev.h
class.o : class.c $(CONFIG_H) $(CXX_TREE_H) $(srcdir)/../flags.h \
$(srcdir)/../system.h $(srcdir)/../toplev.h \
- $(srcdir)/../../include/splay-tree.h
+ $(srcdir)/../../include/splay-tree.h $(RTL_H)
call.o : call.c $(CONFIG_H) $(CXX_TREE_H) $(srcdir)/../flags.h \
- $(srcdir)/../system.h $(srcdir)/../toplev.h
+ $(srcdir)/../system.h $(srcdir)/../toplev.h $(RTL_H)
friend.o : friend.c $(CONFIG_H) $(CXX_TREE_H) $(srcdir)/../flags.h $(RTL_H) \
$(srcdir)/../system.h $(srcdir)/../toplev.h
init.o : init.c $(CONFIG_H) $(CXX_TREE_H) $(srcdir)/../flags.h $(RTL_H) \
$(EXPR_H) $(srcdir)/../system.h $(srcdir)/../toplev.h $(srcdir)/../ggc.h
method.o : method.c $(CONFIG_H) $(CXX_TREE_H) $(srcdir)/../system.h \
- $(srcdir)/../toplev.h $(srcdir)/../ggc.h
+ $(srcdir)/../toplev.h $(srcdir)/../ggc.h $(RTL_H)
cvt.o : cvt.c $(CONFIG_H) $(CXX_TREE_H) $(srcdir)/../system.h decl.h \
$(srcdir)/../flags.h $(srcdir)/../toplev.h $(srcdir)/../convert.h
search.o : search.c $(CONFIG_H) $(CXX_TREE_H) $(srcdir)/../stack.h \
- $(srcdir)/../flags.h $(srcdir)/../system.h $(srcdir)/../toplev.h
+ $(srcdir)/../flags.h $(srcdir)/../system.h $(srcdir)/../toplev.h $(RTL_H)
tree.o : tree.c $(CONFIG_H) $(CXX_TREE_H) $(srcdir)/../flags.h \
- $(srcdir)/../system.h $(srcdir)/../toplev.h $(srcdir)/../ggc.h
+ $(srcdir)/../system.h $(srcdir)/../toplev.h $(srcdir)/../ggc.h $(RTL_H)
ptree.o : ptree.c $(CONFIG_H) $(CXX_TREE_H) $(srcdir)/../system.h
rtti.o : rtti.c $(CONFIG_H) $(CXX_TREE_H) $(srcdir)/../flags.h \
$(srcdir)/../system.h $(srcdir)/../toplev.h
@@ -285,7 +285,7 @@ expr.o : expr.c $(CONFIG_H) $(CXX_TREE_H) $(RTL_H) $(srcdir)/../flags.h \
xref.o : xref.c $(CONFIG_H) $(CXX_TREE_H) $(srcdir)/../input.h \
$(srcdir)/../system.h $(srcdir)/../toplev.h
pt.o : pt.c $(CONFIG_H) $(CXX_TREE_H) decl.h $(PARSE_H) lex.h \
- $(srcdir)/../system.h $(srcdir)/../toplev.h $(srcdir)/../ggc.h
+ $(srcdir)/../system.h $(srcdir)/../toplev.h $(srcdir)/../ggc.h $(RTL_H)
error.o : error.c $(CONFIG_H) $(CXX_TREE_H) $(srcdir)/../system.h \
$(srcdir)/../toplev.h
errfn.o : errfn.c $(CONFIG_H) $(CXX_TREE_H) $(srcdir)/../system.h \
diff --git a/gcc/cp/NEWS b/gcc/cp/NEWS
index 9c99d3e..a172f6d 100644
--- a/gcc/cp/NEWS
+++ b/gcc/cp/NEWS
@@ -1,5 +1,10 @@
*** Changes in GCC 3.0:
+* Support for assignment to `this' has been removed. This idiom
+ was used in the very early days of C++, before users were allowed
+ to overload `operator new'; it is no longer allowed by the C++
+ standard.
+
* Support for signatures, a G++ extension, have been removed.
* Certain invalid conversions that were previously accepted will now
diff --git a/gcc/cp/class.c b/gcc/cp/class.c
index a1437cb..ff0cd88 100644
--- a/gcc/cp/class.c
+++ b/gcc/cp/class.c
@@ -224,11 +224,6 @@ build_vbase_path (code, type, expr, path, nonnull)
if (BINFO_INHERITANCE_CHAIN (path) == NULL_TREE)
return build1 (NOP_EXPR, type, expr);
- /* If -fthis-is-variable, we might have set nonnull incorrectly. We
- don't care enough to get this right, so just clear it. */
- if (flag_this_is_variable > 0)
- nonnull = 0;
-
/* We could do better if we had additional logic to convert back to the
unconverted type (the static type of the complete object), and then
convert back to the type we want. Until that is done, we only optimize
diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h
index a572582..9a55744 100644
--- a/gcc/cp/cp-tree.h
+++ b/gcc/cp/cp-tree.h
@@ -29,7 +29,6 @@ Boston, MA 02111-1307, USA. */
/* Usage of TREE_LANG_FLAG_?:
0: BINFO_MARKED (BINFO nodes).
COMPOUND_STMT_NO_SCOPE (in COMPOUND_STMT).
- EXPR_STMT_ASSIGNS_THIS (in EXPR_STMT).
NEW_EXPR_USE_GLOBAL (in NEW_EXPR).
DELETE_EXPR_USE_GLOBAL (in DELETE_EXPR).
LOOKUP_EXPR_GLOBAL (in LOOKUP_EXPR).
@@ -618,7 +617,6 @@ struct language_function
tree x_dtor_label;
tree x_base_init_list;
tree x_member_init_list;
- tree x_base_init_expr;
tree x_current_class_ptr;
tree x_current_class_ref;
tree x_last_tree;
@@ -627,14 +625,14 @@ struct language_function
tree x_scope_stmt_stack;
tree x_in_charge_parm;
+ tree *x_vcalls_possible_p;
+
struct rtx_def *x_last_dtor_insn;
struct rtx_def *x_last_parm_cleanup_insn;
struct rtx_def *x_result_rtx;
int returns_value;
int returns_null;
- int assigns_this;
- int just_assigned_this;
int parms_stored;
int temp_name_counter;
int static_labelno;
@@ -642,6 +640,7 @@ struct language_function
int x_expanding_p;
int stmts_are_full_exprs_p;
int name_declared;
+ int vtbls_set_up_p;
struct named_label_list *x_named_label_uses;
struct binding_level *bindings;
@@ -674,10 +673,6 @@ struct language_function
#define current_base_init_list cp_function_chain->x_base_init_list
#define current_member_init_list cp_function_chain->x_member_init_list
-/* Sequence of insns which represents base initialization. */
-
-#define base_init_expr cp_function_chain->x_base_init_expr
-
/* When we're processing a member function, current_class_ptr is the
PARM_DECL for the `this' pointer. The current_class_ref is an
expression for `*this'. */
@@ -712,6 +707,12 @@ struct language_function
#define current_in_charge_parm cp_function_chain->x_in_charge_parm
+/* In destructors, this is a pointer to a condition in an
+ if-statement. If the pointed-to value is boolean_true_node, then
+ there may be virtual function calls in this destructor. */
+
+#define current_vcalls_possible_p cp_function_chain->x_vcalls_possible_p
+
/* Set to 0 at beginning of a function definition, set to 1 if
a return statement that specifies a return value is seen. */
@@ -734,6 +735,11 @@ struct language_function
#define current_function_name_declared \
cp_function_chain->name_declared
+/* Nonzero if we have already generated code to initialize virtual
+ function tables in this function. */
+
+#define vtbls_set_up_p cp_function_chain->vtbls_set_up_p
+
/* Used to help generate temporary names which are unique within
a function. Reset to 0 by start_function. */
@@ -1868,12 +1874,6 @@ struct lang_decl
constructor call, rather than an ordinary function call. */
#define AGGR_INIT_VIA_CTOR_P(NODE) TREE_LANG_FLAG_0 (NODE)
-/* Nonzero if this statement contained the first assigned to `this' in
- the current function. (Of course, one cannot assign to `this' in
- ANSI/ISO C++, but we still support assignments to this with
- -fthis-is-variable.) */
-#define EXPR_STMT_ASSIGNS_THIS(NODE) TREE_LANG_FLAG_0 ((NODE))
-
/* Nonzero if this statement should be considered a full-expression. */
#define STMT_IS_FULL_EXPR_P(NODE) TREE_LANG_FLAG_1 ((NODE))
@@ -2857,8 +2857,7 @@ struct pending_inline
/* in method.c */
extern struct pending_inline *pending_inlines;
-/* Positive values means that we cannot make optimizing assumptions about
- `this'. Negative values means we know `this' to be of static type. */
+/* Negative values means we know `this' to be of static type. */
extern int flag_this_is_variable;
@@ -3420,7 +3419,7 @@ extern tree do_friend PROTO((tree, tree, tree, tree, tree, enum overload_flag
/* in init.c */
extern void init_init_processing PROTO((void));
extern void expand_direct_vtbls_init PROTO((tree, tree, int, int, tree));
-extern void emit_base_init PROTO((tree));
+extern tree emit_base_init PROTO((tree));
extern void check_base_init PROTO((tree));
extern void expand_member_init PROTO((tree, tree, tree));
extern tree build_aggr_init PROTO((tree, tree, int));
diff --git a/gcc/cp/decl.c b/gcc/cp/decl.c
index c1a07c1..4371372 100644
--- a/gcc/cp/decl.c
+++ b/gcc/cp/decl.c
@@ -180,6 +180,7 @@ static void save_function_data PROTO((tree));
static void check_function_type PROTO((tree));
static void destroy_local_static PROTO((tree));
static void destroy_local_var PROTO((tree));
+static void finish_destructor_body PROTO((void));
#if defined (DEBUG_CP_BINDING_LEVELS)
static void indent PROTO((void));
@@ -371,13 +372,6 @@ extern int flag_conserve_space;
/* C and C++ flags are in decl2.c. */
-/* Set to 0 at beginning of a constructor, set to 1
- if that function does an allocation before referencing its
- instance variable. */
-#define current_function_assigns_this cp_function_chain->assigns_this
-#define current_function_just_assigned_this \
- cp_function_chain->just_assigned_this
-
/* Flag used when debugging spew.c */
extern int spew_debug;
@@ -3060,6 +3054,15 @@ duplicate_decls (newdecl, olddecl)
the declarations, but make the original one static. */
DECL_THIS_STATIC (olddecl) = 1;
TREE_PUBLIC (olddecl) = 0;
+
+ /* Make the olddeclaration consistent with the new one so that
+ all remnants of the builtin-ness of this function will be
+ banished. */
+ DECL_LANGUAGE (olddecl) = DECL_LANGUAGE (newdecl);
+ DECL_RTL (olddecl) = DECL_RTL (newdecl);
+ DECL_ASSEMBLER_NAME (olddecl) = DECL_ASSEMBLER_NAME (newdecl);
+ SET_IDENTIFIER_GLOBAL_VALUE (DECL_ASSEMBLER_NAME (newdecl),
+ newdecl);
}
}
else if (TREE_CODE (olddecl) != TREE_CODE (newdecl))
@@ -12927,10 +12930,6 @@ start_function (declspecs, declarator, attrs, flags)
*cp_function_chain = *DECL_SAVED_FUNCTION_DATA (decl1);
current_binding_level = bl;
- /* This function has not assigned to `this' yet. */
- current_function_assigns_this = 0;
- current_function_just_assigned_this = 0;
-
/* This function is being processed in whole-function mode; we
already did semantic analysis. */
current_function->x_whole_function_mode_p = 1;
@@ -13298,6 +13297,121 @@ save_function_data (decl)
f->x_expanding_p = 1;
}
+/* At the end of every destructor we generate code to restore virtual
+ function tables to the values desired by base classes and to call
+ to base class destructors. Do that now, for DECL. */
+
+static void
+finish_destructor_body ()
+{
+ tree compound_stmt;
+ tree in_charge;
+ tree virtual_size;
+ tree exprstmt;
+
+ /* Create a block to contain all the extra code. */
+ compound_stmt = begin_compound_stmt (/*has_no_scope=*/0);
+
+ /* Generate the code to call destructor on base class. If this
+ destructor belongs to a class with virtual functions, then set
+ the virtual function table pointer to represent the type of our
+ base class. */
+
+ /* This side-effect makes call to `build_delete' generate the code
+ we have to have at the end of this destructor. `build_delete'
+ will set the flag again. */
+ TYPE_HAS_DESTRUCTOR (current_class_type) = 0;
+
+ /* These are two cases where we cannot delegate deletion. */
+ if (TYPE_USES_VIRTUAL_BASECLASSES (current_class_type)
+ || TYPE_GETS_REG_DELETE (current_class_type))
+ in_charge = integer_zero_node;
+ else
+ in_charge = current_in_charge_parm;
+
+ exprstmt = build_delete (current_class_type,
+ current_class_ref,
+ in_charge,
+ LOOKUP_NONVIRTUAL|LOOKUP_DESTRUCTOR|LOOKUP_NORMAL,
+ 0);
+
+ if (exprstmt != error_mark_node
+ && (TREE_CODE (exprstmt) != NOP_EXPR
+ || TREE_OPERAND (exprstmt, 0) != integer_zero_node
+ || TYPE_USES_VIRTUAL_BASECLASSES (current_class_type)))
+ {
+ add_tree (build_min_nt (LABEL_STMT, dtor_label));
+ if (exprstmt != void_zero_node)
+ /* Don't call `expand_expr_stmt' if we're not going to do
+ anything, since -Wall will give a diagnostic. */
+ finish_expr_stmt (exprstmt);
+
+ /* Run destructor on all virtual baseclasses. */
+ if (TYPE_USES_VIRTUAL_BASECLASSES (current_class_type))
+ {
+ tree vbases = nreverse (copy_list (CLASSTYPE_VBASECLASSES (current_class_type)));
+ tree if_stmt = begin_if_stmt ();
+ finish_if_stmt_cond (build (BIT_AND_EXPR, integer_type_node,
+ current_in_charge_parm,
+ integer_two_node),
+ if_stmt);
+
+ while (vbases)
+ {
+ if (TYPE_NEEDS_DESTRUCTOR (BINFO_TYPE (vbases)))
+ {
+ tree vb = get_vbase
+ (BINFO_TYPE (vbases),
+ TYPE_BINFO (current_class_type));
+ finish_expr_stmt
+ (build_scoped_method_call
+ (current_class_ref, vb, dtor_identifier,
+ build_expr_list (NULL_TREE, integer_zero_node)));
+ }
+ vbases = TREE_CHAIN (vbases);
+ }
+
+ finish_then_clause (if_stmt);
+ finish_if_stmt ();
+ }
+ }
+
+ virtual_size = c_sizeof (current_class_type);
+
+ /* At the end, call delete if that's what's requested. */
+
+ /* FDIS sez: At the point of definition of a virtual destructor
+ (including an implicit definition), non-placement operator delete
+ shall be looked up in the scope of the destructor's class and if
+ found shall be accessible and unambiguous.
+
+ This is somewhat unclear, but I take it to mean that if the class
+ only defines placement deletes we don't do anything here. So we
+ pass LOOKUP_SPECULATIVELY; delete_sanity will complain for us if
+ they ever try to delete one of these. */
+ if (TYPE_GETS_REG_DELETE (current_class_type)
+ || TYPE_USES_VIRTUAL_BASECLASSES (current_class_type))
+ {
+ tree if_stmt;
+
+ exprstmt = build_op_delete_call
+ (DELETE_EXPR, current_class_ptr, virtual_size,
+ LOOKUP_NORMAL | LOOKUP_SPECULATIVELY, NULL_TREE);
+
+ if_stmt = begin_if_stmt ();
+ finish_if_stmt_cond (build (BIT_AND_EXPR, integer_type_node,
+ current_in_charge_parm,
+ integer_one_node),
+ if_stmt);
+ finish_expr_stmt (exprstmt);
+ finish_then_clause (if_stmt);
+ finish_if_stmt ();
+ }
+
+ /* Close the block we started above. */
+ finish_compound_stmt (/*has_no_scope=*/0, compound_stmt);
+}
+
/* Finish up a function declaration and compile that function
all the way to assembler language output. The free the storage
for the function definition.
@@ -13322,7 +13436,6 @@ finish_function (lineno, flags)
{
register tree fndecl = current_function_decl;
tree fntype, ctype = NULL_TREE;
- rtx fn_last_parm_insn, insns;
/* Label to use if this function is supposed to return a value. */
tree no_return_label = NULL_TREE;
int call_poplevel = (flags & 1) != 0;
@@ -13338,9 +13451,9 @@ finish_function (lineno, flags)
nested = function_depth > 1;
fntype = TREE_TYPE (fndecl);
-/* TREE_READONLY (fndecl) = 1;
- This caused &foo to be of type ptr-to-const-function
- which then got a warning when stored in a ptr-to-function variable. */
+ /* TREE_READONLY (fndecl) = 1;
+ This caused &foo to be of type ptr-to-const-function
+ which then got a warning when stored in a ptr-to-function variable. */
/* This happens on strange parse errors. */
if (! current_function_parms_stored)
@@ -13353,6 +13466,8 @@ finish_function (lineno, flags)
{
if (DECL_CONSTRUCTOR_P (fndecl) && call_poplevel)
do_poplevel ();
+ else if (DECL_DESTRUCTOR_P (fndecl) && !processing_template_decl)
+ finish_destructor_body ();
/* Finish dealing with exception specifiers. */
if (flag_exceptions && !processing_template_decl
@@ -13385,242 +13500,9 @@ finish_function (lineno, flags)
do_pending_stack_adjust ();
if (dtor_label)
- {
- tree binfo = TYPE_BINFO (current_class_type);
- tree cond = integer_one_node;
- tree exprstmt;
- tree virtual_size;
- int ok_to_optimize_dtor = 0;
- int empty_dtor = get_last_insn () == last_dtor_insn;
-
- if (current_function_assigns_this)
- cond = build (NE_EXPR, boolean_type_node,
- current_class_ptr, integer_zero_node);
- else
- {
- int n_baseclasses = CLASSTYPE_N_BASECLASSES (current_class_type);
-
- /* If this destructor is empty, then we don't need to check
- whether `this' is NULL in some cases. */
- if ((flag_this_is_variable & 1) == 0)
- ok_to_optimize_dtor = 1;
- else if (empty_dtor)
- ok_to_optimize_dtor
- = (n_baseclasses == 0
- || (n_baseclasses == 1
- && TYPE_HAS_DESTRUCTOR (TYPE_BINFO_BASETYPE (current_class_type, 0))));
- }
-
- /* These initializations might go inline. Protect
- the binding level of the parms. */
- do_pushlevel ();
-
- if (current_function_assigns_this)
- {
- current_function_assigns_this = 0;
- current_function_just_assigned_this = 0;
- }
-
- /* Generate the code to call destructor on base class.
- If this destructor belongs to a class with virtual
- functions, then set the virtual function table
- pointer to represent the type of our base class. */
-
- /* This side-effect makes call to `build_delete' generate the
- code we have to have at the end of this destructor.
- `build_delete' will set the flag again. */
- TYPE_HAS_DESTRUCTOR (current_class_type) = 0;
-
- /* These are two cases where we cannot delegate deletion. */
- if (TYPE_USES_VIRTUAL_BASECLASSES (current_class_type)
- || TYPE_GETS_REG_DELETE (current_class_type))
- exprstmt = build_delete (current_class_type, current_class_ref, integer_zero_node,
- LOOKUP_NONVIRTUAL|LOOKUP_DESTRUCTOR|LOOKUP_NORMAL, 0);
- else
- exprstmt = build_delete (current_class_type,
- current_class_ref,
- current_in_charge_parm,
- LOOKUP_NONVIRTUAL|LOOKUP_DESTRUCTOR|LOOKUP_NORMAL, 0);
-
- /* If we did not assign to this, then `this' is non-zero at
- the end of a destructor. As a special optimization, don't
- emit test if this is an empty destructor. If it does nothing,
- it does nothing. If it calls a base destructor, the base
- destructor will perform the test. */
-
- if (exprstmt != error_mark_node
- && (TREE_CODE (exprstmt) != NOP_EXPR
- || TREE_OPERAND (exprstmt, 0) != integer_zero_node
- || TYPE_USES_VIRTUAL_BASECLASSES (current_class_type)))
- {
- expand_label (dtor_label);
- if (cond != integer_one_node)
- expand_start_cond (cond, 0);
- if (exprstmt != void_zero_node)
- /* Don't call `expand_expr_stmt' if we're not going to do
- anything, since -Wall will give a diagnostic. */
- expand_expr_stmt (exprstmt);
-
- /* Run destructor on all virtual baseclasses. */
- if (TYPE_USES_VIRTUAL_BASECLASSES (current_class_type))
- {
- tree vbases = nreverse (copy_list (CLASSTYPE_VBASECLASSES (current_class_type)));
- expand_start_cond (build (BIT_AND_EXPR, integer_type_node,
- current_in_charge_parm,
- integer_two_node), 0);
- while (vbases)
- {
- if (TYPE_NEEDS_DESTRUCTOR (BINFO_TYPE (vbases)))
- {
- tree vb = get_vbase
- (BINFO_TYPE (vbases),
- TYPE_BINFO (current_class_type));
- expand_expr_stmt
- (build_scoped_method_call
- (current_class_ref, vb, dtor_identifier,
- build_expr_list (NULL_TREE, integer_zero_node)));
- }
- vbases = TREE_CHAIN (vbases);
- }
- expand_end_cond ();
- }
-
- do_pending_stack_adjust ();
- if (cond != integer_one_node)
- expand_end_cond ();
- }
-
- virtual_size = c_sizeof (current_class_type);
-
- /* At the end, call delete if that's what's requested. */
-
- /* FDIS sez: At the point of definition of a virtual destructor
- (including an implicit definition), non-placement operator
- delete shall be looked up in the scope of the destructor's
- class and if found shall be accessible and unambiguous.
-
- This is somewhat unclear, but I take it to mean that if the
- class only defines placement deletes we don't do anything here.
- So we pass LOOKUP_SPECULATIVELY; delete_sanity will complain
- for us if they ever try to delete one of these. */
-
- if (TYPE_GETS_REG_DELETE (current_class_type)
- || TYPE_USES_VIRTUAL_BASECLASSES (current_class_type))
- exprstmt = build_op_delete_call
- (DELETE_EXPR, current_class_ptr, virtual_size,
- LOOKUP_NORMAL | LOOKUP_SPECULATIVELY, NULL_TREE);
- else
- exprstmt = NULL_TREE;
-
- if (exprstmt)
- {
- cond = build (BIT_AND_EXPR, integer_type_node,
- current_in_charge_parm, integer_one_node);
- expand_start_cond (cond, 0);
- expand_expr_stmt (exprstmt);
- expand_end_cond ();
- }
-
- /* End of destructor. */
- do_poplevel ();
-
- /* Back to the top of destructor. */
- /* Don't execute destructor code if `this' is NULL. */
-
- start_sequence ();
-
- /* If the dtor is empty, and we know there is not possible way we
- could use any vtable entries, before they are possibly set by
- a base class dtor, we don't have to setup the vtables, as we
- know that any base class dtoring will set up any vtables it
- needs. We avoid MI, because one base class dtor can do a
- virtual dispatch to an overridden function that would need to
- have a non-related vtable set up, we cannot avoid setting up
- vtables in that case. We could change this to see if there is
- just one vtable. */
- if (! empty_dtor || TYPE_USES_COMPLEX_INHERITANCE (current_class_type))
- {
- /* Make all virtual function table pointers in non-virtual base
- classes point to CURRENT_CLASS_TYPE's virtual function
- tables. */
- expand_direct_vtbls_init (binfo, binfo, 1, 0, current_class_ptr);
-
- if (TYPE_USES_VIRTUAL_BASECLASSES (current_class_type))
- expand_indirect_vtbls_init (binfo, current_class_ref, current_class_ptr);
- }
-
- if (! ok_to_optimize_dtor)
- {
- cond = build_binary_op (NE_EXPR,
- current_class_ptr, integer_zero_node);
- expand_start_cond (cond, 0);
- }
-
- insns = get_insns ();
- end_sequence ();
-
- fn_last_parm_insn = get_first_nonparm_insn ();
- if (fn_last_parm_insn == NULL_RTX)
- fn_last_parm_insn = get_last_insn ();
- else
- fn_last_parm_insn = previous_insn (fn_last_parm_insn);
-
- emit_insns_after (insns, fn_last_parm_insn);
-
- if (! ok_to_optimize_dtor)
- expand_end_cond ();
- }
+ ;
else if (DECL_CONSTRUCTOR_P (fndecl))
{
- /* If the current function assigns to `this', then code to
- initialize members and base-classes will be generated
- directly after the assignment. */
- if (!current_function_assigns_this)
- {
- start_sequence ();
-
- if (flag_this_is_variable > 0)
- {
- /* Allow constructor for a type to get a new instance of
- the object using `build_new'. */
- tree cond = NULL_TREE, thenclause = NULL_TREE;
- tree abstract_virtuals
- = CLASSTYPE_ABSTRACT_VIRTUALS (current_class_type);
- CLASSTYPE_ABSTRACT_VIRTUALS (current_class_type) = NULL_TREE;
-
- cond = build_binary_op (EQ_EXPR,
- current_class_ptr, integer_zero_node);
-
- expand_start_cond (cond, 0);
-
- thenclause
- = build_modify_expr (current_class_ptr, NOP_EXPR,
- build_new (NULL_TREE,
- current_class_type,
-
- void_type_node, 0));
- CLASSTYPE_ABSTRACT_VIRTUALS (current_class_type)
- = abstract_virtuals;
- expand_expr_stmt (thenclause);
- expand_end_cond ();
- }
-
- /* Emit insns from `emit_base_init' which sets up
- virtual function table pointer(s). Don't do this for
- a function which assigns to `this' as we will emit
- the appropriate code right after the assignment. */
- if (!current_function_assigns_this && base_init_expr)
- {
- expand_expr_stmt (base_init_expr);
- base_init_expr = NULL_TREE;
- }
-
- insns = get_insns ();
- end_sequence ();
-
- emit_insns_after (insns, last_parm_cleanup_insn);
- }
-
/* This is where the body of the constructor begins. All
subobjects have been fully constructed at this point. */
end_protect_partials ();
@@ -13634,9 +13516,6 @@ finish_function (lineno, flags)
/* c_expand_return knows to return 'this' from a constructor. */
c_expand_return (NULL_TREE);
-
- current_function_assigns_this = 0;
- current_function_just_assigned_this = 0;
}
else if (DECL_MAIN_P (fndecl))
{
@@ -13648,13 +13527,9 @@ finish_function (lineno, flags)
#endif
}
else if (return_label != NULL_RTX
- && ((flag_this_is_variable <= 0
- && current_function_return_value == NULL_TREE
- && ! DECL_NAME (DECL_RESULT (current_function_decl)))
- || (flag_this_is_variable > 0
- && (TREE_CODE (TREE_TYPE (DECL_RESULT
- (current_function_decl)))
- == VOID_TYPE))))
+ && flag_this_is_variable <= 0
+ && current_function_return_value == NULL_TREE
+ && ! DECL_NAME (DECL_RESULT (current_function_decl)))
no_return_label = build_decl (LABEL_DECL, NULL_TREE, NULL_TREE);
if (flag_exceptions)
@@ -14241,22 +14116,6 @@ cplus_expand_expr_stmt (exp)
void
finish_stmt ()
{
- if (!current_function_assigns_this
- && current_function_just_assigned_this)
- {
- if (DECL_CONSTRUCTOR_P (current_function_decl)
- && !building_stmt_tree ())
- {
- /* Constructors must wait until we are out of control
- zones before calling base constructors. */
- if (in_control_zone_p ())
- return;
- expand_expr_stmt (base_init_expr);
- check_base_init (current_class_type);
- }
- current_function_assigns_this = 1;
- }
-
/* Always assume this statement was not an expression statement. If
it actually was an expression statement, its our callers
responsibility to fix this up. */
@@ -14344,7 +14203,6 @@ mark_lang_function (p)
ggc_mark_tree (p->x_dtor_label);
ggc_mark_tree (p->x_base_init_list);
ggc_mark_tree (p->x_member_init_list);
- ggc_mark_tree (p->x_base_init_expr);
ggc_mark_tree (p->x_current_class_ptr);
ggc_mark_tree (p->x_current_class_ref);
ggc_mark_tree (p->x_last_tree);
diff --git a/gcc/cp/decl2.c b/gcc/cp/decl2.c
index bb5f5e5..868a62e 100644
--- a/gcc/cp/decl2.c
+++ b/gcc/cp/decl2.c
@@ -523,7 +523,6 @@ lang_f_options[] =
{"squangle", &flag_do_squangling, 1},
{"stats", &flag_detailed_statistics, 1},
{"strict-prototype", &flag_strict_prototype, 1},
- {"this-is-variable", &flag_this_is_variable, 1},
{"vtable-gc", &flag_vtable_gc, 1},
{"vtable-thunks", &flag_vtable_thunks, 1},
{"weak", &flag_weak, 1},
@@ -619,12 +618,6 @@ lang_decode_option (argc, argv)
flag_guiding_decls = 0;
found = 1;
}
- else if (!strcmp (p, "this-is-variable"))
- {
- flag_this_is_variable = 1;
- found = 1;
- cp_deprecated ("-fthis-is-variable");
- }
else if (!strcmp (p, "external-templates"))
{
flag_external_templates = 1;
@@ -1007,11 +1000,6 @@ grokclassfn (ctype, function, flags, quals)
/* Right now we just make this a pointer. But later
we may wish to make it special. */
tree type = TREE_VALUE (arg_types);
- int constp = 1;
-
- if ((flag_this_is_variable > 0)
- && (flags == DTOR_FLAG || DECL_CONSTRUCTOR_P (function)))
- constp = 0;
parm = build_decl (PARM_DECL, this_identifier, type);
/* Mark the artificial `this' parameter as "artificial". */
@@ -1020,8 +1008,7 @@ grokclassfn (ctype, function, flags, quals)
/* We can make this a register, so long as we don't
accidentally complain if someone tries to take its address. */
DECL_REGISTER (parm) = 1;
- if (constp)
- TREE_READONLY (parm) = 1;
+ TREE_READONLY (parm) = 1;
TREE_CHAIN (parm) = last_function_parms;
last_function_parms = parm;
}
diff --git a/gcc/cp/init.c b/gcc/cp/init.c
index e0a1d13..11b96c4 100644
--- a/gcc/cp/init.c
+++ b/gcc/cp/init.c
@@ -483,7 +483,7 @@ sort_base_init (t, rbase_ptr, vbase_ptr)
Note that emit_base_init does *not* initialize virtual base
classes. That is done specially, elsewhere. */
-void
+tree
emit_base_init (t)
tree t;
{
@@ -623,10 +623,9 @@ emit_base_init (t)
mem_init_list = TREE_CHAIN (mem_init_list);
}
- base_init_expr = finish_init_stmts (stmt_expr, compound_stmt);
-
/* All the implicit try blocks we built up will be zapped
when we come to a real binding contour boundary. */
+ return finish_init_stmts (stmt_expr, compound_stmt);
}
/* Check that all fields are properly initialized after
@@ -747,10 +746,6 @@ construct_virtual_bases (type, this_ref, this_ptr, init_list, flag)
if_stmt = begin_if_stmt ();
finish_if_stmt_cond (flag, if_stmt);
result = init_vbase_pointers (type, this_ptr);
- /* The RESULT will contain entries on the momentary obstack. They
- must live until the end of this function; we use them in the loop
- below. */
- push_momentary ();
if (result)
finish_expr_stmt (build_compound_expr (result));
finish_then_clause (if_stmt);
@@ -785,14 +780,11 @@ construct_virtual_bases (type, this_ref, this_ptr, init_list, flag)
TREE_OPERAND (TREE_VALUE (tmp), 0),
init_list);
finish_compound_stmt (/*has_no_scope=*/1, compound_stmt);
- finish_then_clause (if_stmt);
+ finish_then_clause (inner_if_stmt);
finish_if_stmt ();
expand_cleanup_for_base (vbases, flag);
}
-
- /* Undo the call to push_momentary above. */
- pop_momentary ();
}
/* Find the context in which this FIELD can be initialized. */
@@ -2214,18 +2206,7 @@ build_new_1 (exp)
/* Allocate the object. */
- if (! has_array && ! placement && flag_this_is_variable > 0
- && TYPE_NEEDS_CONSTRUCTING (true_type) && init != void_type_node)
- {
- if (init == NULL_TREE || TREE_CODE (init) == TREE_LIST)
- rval = NULL_TREE;
- else
- {
- error ("constructors take parameter lists");
- return error_mark_node;
- }
- }
- else if (! placement && TYPE_FOR_JAVA (true_type))
+ if (! placement && TYPE_FOR_JAVA (true_type))
{
tree class_addr, alloc_decl;
tree class_decl = build_java_class_ref (true_type);
@@ -2677,7 +2658,6 @@ get_temp_regvar (type, init)
decl = create_temporary_var (type);
if (building_stmt_tree ())
add_decl_stmt (decl);
- DECL_REGISTER (decl) = 1;
if (!building_stmt_tree ())
DECL_RTL (decl) = assign_temp (type, 2, 0, 1);
finish_expr_stmt (build_modify_expr (decl, INIT_EXPR, init));
@@ -2827,9 +2807,6 @@ build_vec_init (decl, base, maxindex, init, from_array)
/* Clear out INIT so that we don't get confused below. */
init = NULL_TREE;
-
- if (obey_regdecls && !building_stmt_tree ())
- use_variable (DECL_RTL (base));
}
else if (from_array)
{
@@ -2958,13 +2935,6 @@ build_vec_init (decl, base, maxindex, init, from_array)
build (PLUS_EXPR, build_pointer_type (type),
base2, size)));
- if (obey_regdecls && !building_stmt_tree ())
- {
- use_variable (DECL_RTL (base));
- if (base2)
- use_variable (DECL_RTL (base2));
- }
-
finish_compound_stmt (/*has_no_scope=*/1, do_body);
finish_do_body (do_stmt);
finish_do_stmt (build (NE_EXPR, boolean_type_node,
@@ -2996,12 +2966,6 @@ build_vec_init (decl, base, maxindex, init, from_array)
finish_cleanup (e, try_block);
}
- if (obey_regdecls && !building_stmt_tree ())
- {
- use_variable (DECL_RTL (iterator));
- use_variable (DECL_RTL (rval));
- }
-
/* The value of the array initialization is the address of the
first element in the array. */
finish_expr_stmt (rval);
diff --git a/gcc/cp/ir.texi b/gcc/cp/ir.texi
index f924f4f..e1ff4ca 100644
--- a/gcc/cp/ir.texi
+++ b/gcc/cp/ir.texi
@@ -660,7 +660,7 @@ list. In particular, no @code{FIELD_DECL}, @code{LABEL_DECL}, or
A class type is represented by either a @code{RECORD_TYPE} or a
@code{UNION_TYPE}. A class declared with the @code{union} tag is
represented by a @code{UNION_TYPE}, while classes declared with either
-the @code{struct} or the @code{union} tag are represented by
+the @code{struct} or the @code{class} tag are represented by
@code{RECORD_TYPE}s. You can use the @code{CLASSTYPE_DECLARED_CLASS}
macro to discern whether or not a particular type is a @code{class} as
opposed to a @code{struct}. This macro will be true only for classes
@@ -1010,7 +1010,6 @@ FIXME: Explain about constructor try-catch blocks.
@tindex COMPOUND_STMT
@findex COMPOUND_BODY
@tindex CONTINUE_STMT
-@tindex CTOR_INITIALIZER
@tindex DECL_STMT
@findex DECL_STMT_DECL
@tindex DO_STMT
@@ -1050,26 +1049,17 @@ FIXME: Explain about constructor try-catch blocks.
@findex WHILE_COND
A function that has a definition in the current translation unit will
-have a non-NULL @code{DECL_INITIAL}. However, the @code{DECL_INITIAL}
-will simply be the @code{error_mark_node}. (When tree structure is
-translated to RTL, @code{DECL_INITIAL} will contain a different value.)
+have a non-NULL @code{DECL_INITIAL}. However, back-ends should not make
+use of the particular value given by @code{DECL_INITIAL}.
The @code{DECL_SAVED_TREE} macro will give the complete body of the
function. This node will usually be a @code{COMPOUND_STMT} representing
the outermost block of the function, but it may also be a
-@code{TRY_BLOCK}, @code{RETURN_INIT}, or @code{CTOR_INITIALIZER}, as
-described below.
+@code{TRY_BLOCK} or a @code{RETURN_INIT}.
If the function has a function try-block, the @code{DECL_SAVED_TREE}
will be a @code{TRY_BLOCK}. The @code{TRY_STMTS} will then be either a
-@code{RETURN_INIT}, @code{CTOR_INITIALIZER}, or @code{COMPOUND_STMT}.
-
-If the function is a constructor, the @code{DECL_SAVED_TREE} may be a
-@code{CTOR_INITIALIZER} node, indicating how base classes and members
-should be initialized. The @code{TREE_CHAIN} of the
-@code{CTOR_INITIALIZER} will be the @code{COMPOUND_STMT} representing
-the body of the constructor. FIXME: Document how the base initializers
-and member initializers can be used.
+@code{RETURN_INIT}, or a @code{COMPOUND_STMT}.
If the function uses the G++ ``named return value'' extension, meaning
that the function has been defined like:
@@ -1079,10 +1069,8 @@ S f(int) return s @{...@}
the @code{DECL_SAVED_TREE} will be a @code{RETURN_INIT}. The
@code{TREE_CHAIN} of the @code{RETURN_INIT} will be the
@code{COMPOUND_STMT} representing the body of the function. There is
-never a named returned value for a constructor, so there is never a
-situation in which a @code{RETURN_INIT} and a @code{CTOR_INITIALIZER}
-appear simultaneously. FIXME: Document how the @code{RETURN_INIT} can
-be used.
+never a named returned value for a constructor. FIXME: Document how the
+@code{RETURN_INIT} can be used.
@subsection Statements
@@ -1115,7 +1103,34 @@ Many of the statements have substatements. For example, a @code{while}
loop will have a body, which is itself a statement. If the substatement
is @code{NULL_TREE}, it is considered equivalent to a statement
consisting of a single @code{;}, i.e., an expression statement in which
-the expression has been omitted.
+the expression has been omitted. A substatement may in fact be a list
+of statements, connected via their @code{TREE_CHAIN}s. So, you should
+always process the statement tree by looping over substatements, like
+this:
+@example
+void process_stmt (stmt)
+ tree stmt;
+{
+ while (stmt)
+ {
+ switch (TREE_CODE (stmt))
+ {
+ case IF_STMT:
+ process_stmt (THEN_CLAUSE (stmt));
+ /* More processing here. */
+ break;
+
+ ...
+ }
+
+ stmt = TREE_CHAIN (stmt);
+ }
+}
+@end example
+In other words, while the @code{then} clause of an @code{if} statement
+in C++ can be only one statement (although that one statement may be a
+compound statement), the intermediate representation will sometimes use
+several statements chained together.
@table @code
@item ASM_STMT
diff --git a/gcc/cp/lang-options.h b/gcc/cp/lang-options.h
index ca7e436..f5bf2bb 100644
--- a/gcc/cp/lang-options.h
+++ b/gcc/cp/lang-options.h
@@ -96,8 +96,6 @@ DEFINE_LANG_NAME ("C++")
{ "-fstrict-prototype", "" },
{ "-fno-strict-prototype", "Do not assume that empty prototype means no args" },
{ "-ftemplate-depth-", "Specify maximum template instantiation depth"},
- { "-fthis-is-variable", "Make 'this' not be type '* const'" },
- { "-fno-this-is-variable", "" },
{ "-fvtable-gc", "Discard unused virtual functions" },
{ "-fno-vtable-gc", "" },
{ "-fvtable-thunks", "Implement vtables using thunks" },
diff --git a/gcc/cp/pt.c b/gcc/cp/pt.c
index 22efc7e..e7f35fa 100644
--- a/gcc/cp/pt.c
+++ b/gcc/cp/pt.c
@@ -7261,11 +7261,6 @@ tsubst_expr (t, args, complain, in_decl)
case EXPR_STMT:
prep_stmt (t);
- /* If we're doing tsubst'ing, then we should not yet have done
- semantic analysisy, so we should not know that this statement
- assigns to the `this' pointer. */
- my_friendly_assert (EXPR_STMT_ASSIGNS_THIS (t) == 0,
- 19990831);
finish_expr_stmt (tsubst_expr (EXPR_STMT_EXPR (t),
args, complain, in_decl));
break;
diff --git a/gcc/cp/search.c b/gcc/cp/search.c
index 6e81465..1f599c4 100644
--- a/gcc/cp/search.c
+++ b/gcc/cp/search.c
@@ -2609,12 +2609,12 @@ expand_upcast_fixups (binfo, addr, orig_addr, vbase, vbase_addr, t,
init = build (MODIFY_EXPR, TREE_TYPE (nvtbl),
nvtbl, vtbl);
TREE_SIDE_EFFECTS (init) = 1;
- expand_expr_stmt (init);
+ finish_expr_stmt (init);
/* Update the vtable pointers as necessary. */
ref = build_vfield_ref
(build_indirect_ref (addr, NULL_PTR),
DECL_CONTEXT (CLASSTYPE_VFIELD (BINFO_TYPE (binfo))));
- expand_expr_stmt
+ finish_expr_stmt
(build_modify_expr (ref, NOP_EXPR, nvtbl));
}
assemble_external (vtbl);
@@ -2657,7 +2657,7 @@ expand_upcast_fixups (binfo, addr, orig_addr, vbase, vbase_addr, t,
cp_build_qualified_type (TREE_TYPE (new_delta),
CP_TYPE_QUALS (TREE_TYPE (new_delta))
& ~TYPE_QUAL_CONST);
- expand_expr_stmt (build_modify_expr (new_delta, NOP_EXPR,
+ finish_expr_stmt (build_modify_expr (new_delta, NOP_EXPR,
old_delta));
}
++n;
diff --git a/gcc/cp/semantics.c b/gcc/cp/semantics.c
index 374dc02..d5ef09a 100644
--- a/gcc/cp/semantics.c
+++ b/gcc/cp/semantics.c
@@ -41,7 +41,6 @@
parsing into this file; that will make implementing the new parser
much easier since it will be able to make use of these routines. */
-static void finish_expr_stmt_real PROTO((tree, int));
static tree expand_cond PROTO((tree));
static tree maybe_convert_cond PROTO((tree));
@@ -110,14 +109,11 @@ maybe_convert_cond (cond)
return condition_conversion (cond);
}
-/* Finish an expression-statement, whose EXPRESSION is as indicated.
- If ASSIGNED_THIS is non-zero, then this statement just assigned to
- the `this' pointer. */
+/* Finish an expression-statement, whose EXPRESSION is as indicated. */
-static void
-finish_expr_stmt_real (expr, assigned_this)
+void
+finish_expr_stmt (expr)
tree expr;
- int assigned_this;
{
if (expr != NULL_TREE)
{
@@ -147,11 +143,6 @@ finish_expr_stmt_real (expr, assigned_this)
}
}
- /* If this statement assigned to the `this' pointer, record that
- fact for finish_stmt. */
- if (assigned_this)
- current_function_just_assigned_this = 1;
-
finish_stmt ();
/* This was an expression-statement, so we save the type of the
@@ -159,15 +150,6 @@ finish_expr_stmt_real (expr, assigned_this)
last_expr_type = expr ? TREE_TYPE (expr) : NULL_TREE;
}
-/* Like finish_expr_stmt_real, but ASSIGNS_THIS is always zero. */
-
-void
-finish_expr_stmt (expr)
- tree expr;
-{
- finish_expr_stmt_real (expr, /*assigns_this=*/0);
-}
-
/* Begin an if-statement. Returns a newly created IF_STMT if
appropriate. */
@@ -176,6 +158,8 @@ begin_if_stmt ()
{
tree r;
+ do_pushlevel ();
+
if (building_stmt_tree ())
{
r = build_min_nt (IF_STMT, NULL_TREE, NULL_TREE, NULL_TREE);
@@ -184,8 +168,6 @@ begin_if_stmt ()
else
r = NULL_TREE;
- do_pushlevel ();
-
return r;
}
@@ -924,7 +906,9 @@ begin_compound_stmt (has_no_scope)
/* If this is the outermost block of the function, declare the
variables __FUNCTION__, __PRETTY_FUNCTION__, and so forth. */
- if (!current_function_name_declared && !processing_template_decl)
+ if (!current_function_name_declared
+ && !processing_template_decl
+ && !has_no_scope)
{
declare_function_name ();
current_function_name_declared = 1;
@@ -1163,21 +1147,69 @@ finish_named_return_value (return_id, init)
void
setup_vtbl_ptr ()
{
- if (base_init_expr == 0
- && DECL_CONSTRUCTOR_P (current_function_decl))
+ my_friendly_assert (doing_semantic_analysis_p (), 19990919);
+
+ /* If we've already done this, there's no need to do it again. */
+ if (vtbls_set_up_p)
+ return;
+
+ if (DECL_CONSTRUCTOR_P (current_function_decl))
{
- if (building_stmt_tree ())
+ if (processing_template_decl)
add_tree (build_min_nt
(CTOR_INITIALIZER,
current_member_init_list, current_base_init_list));
else
- emit_base_init (current_class_type);
+ finish_expr_stmt (emit_base_init (current_class_type));
+ }
+ else if (DECL_DESTRUCTOR_P (current_function_decl)
+ && !processing_template_decl)
+ {
+ tree binfo = TYPE_BINFO (current_class_type);
+ tree if_stmt;
+ tree compound_stmt;
+
+ /* If the dtor is empty, and we know there is not possible way we
+ could use any vtable entries, before they are possibly set by
+ a base class dtor, we don't have to setup the vtables, as we
+ know that any base class dtoring will set up any vtables it
+ needs. We avoid MI, because one base class dtor can do a
+ virtual dispatch to an overridden function that would need to
+ have a non-related vtable set up, we cannot avoid setting up
+ vtables in that case. We could change this to see if there is
+ just one vtable. */
+ if_stmt = begin_if_stmt ();
+
+ /* If it is not safe to avoid setting up the vtables, then
+ someone will change the condition to be boolean_true_node.
+ (Actually, for now, we do not have code to set the condition
+ appropriate, so we just assume that we always need to
+ initialize the vtables.) */
+ finish_if_stmt_cond (boolean_true_node, if_stmt);
+ current_vcalls_possible_p = &IF_COND (if_stmt);
+ compound_stmt = begin_compound_stmt (/*has_no_scope=*/0);
+
+ /* Make all virtual function table pointers in non-virtual base
+ classes point to CURRENT_CLASS_TYPE's virtual function
+ tables. */
+ expand_direct_vtbls_init (binfo, binfo, 1, 0, current_class_ptr);
+
+ if (TYPE_USES_VIRTUAL_BASECLASSES (current_class_type))
+ expand_indirect_vtbls_init (binfo, current_class_ref,
+ current_class_ptr);
+
+ finish_compound_stmt (/*has_no_scope=*/0, compound_stmt);
+ finish_then_clause (if_stmt);
+ finish_if_stmt ();
}
/* Always keep the BLOCK node associated with the outermost pair of
- curley braces of a function. These are needed for correct
+ curly braces of a function. These are needed for correct
operation of dwarfout.c. */
keep_next_level (1);
+
+ /* The virtual function tables are set up now. */
+ vtbls_set_up_p = 1;
}
/* Begin a new scope. */
@@ -2214,8 +2246,7 @@ expand_stmt (t)
break;
case EXPR_STMT:
- finish_expr_stmt_real (EXPR_STMT_EXPR (t),
- EXPR_STMT_ASSIGNS_THIS (t));
+ finish_expr_stmt (EXPR_STMT_EXPR (t));
break;
case DECL_STMT:
@@ -2394,12 +2425,6 @@ expand_stmt (t)
expand_end_bindings (NULL_TREE, !SCOPE_NULLIFIED_P (t), 0);
break;
- case CTOR_INITIALIZER:
- current_member_init_list = TREE_OPERAND (t, 0);
- current_base_init_list = TREE_OPERAND (t, 1);
- setup_vtbl_ptr ();
- break;
-
case RETURN_INIT:
/* Clear this out so that finish_named_return_value can set it
again. */
diff --git a/gcc/cp/typeck.c b/gcc/cp/typeck.c
index 0fc589b..f4cdc92 100644
--- a/gcc/cp/typeck.c
+++ b/gcc/cp/typeck.c
@@ -5802,17 +5802,6 @@ build_modify_expr (lhs, modifycode, rhs)
}
}
- /* check to see if there is an assignment to `this' */
- if (lhs == current_class_ptr)
- {
- if (flag_this_is_variable > 0
- && DECL_NAME (current_function_decl) != NULL_TREE
- && (DECL_NAME (current_function_decl)
- != constructor_name (current_class_type)))
- warning ("assignment to `this' not in constructor or destructor");
- current_function_just_assigned_this = 1;
- }
-
if (modifycode != INIT_EXPR)
{
/* Make modifycode now either a NOP_EXPR or an INIT_EXPR. */
@@ -6716,10 +6705,7 @@ c_expand_return (retval)
}
else if (DECL_CONSTRUCTOR_P (current_function_decl))
{
- if (flag_this_is_variable)
- error ("return from a constructor: use `this = ...' instead");
- else
- error ("returning a value from a constructor");
+ error ("returning a value from a constructor");
retval = current_class_ptr;
}
diff --git a/gcc/testsuite/g++.old-deja/g++.other/static8.C b/gcc/testsuite/g++.old-deja/g++.other/static8.C
new file mode 100644
index 0000000..39575d2
--- /dev/null
+++ b/gcc/testsuite/g++.old-deja/g++.other/static8.C
@@ -0,0 +1,7 @@
+// Build don't link:
+// Special g++ Options: -fno-squangle
+// Origin: Mark Mitchell <mark@codesourcery.com>
+
+static unsigned int strlen (const char*) {} // ERROR - previous declaration
+
+int strlen__FPCc = 0; // ERROR - duplicate declaration