+Wed Apr 24 00:36:21 1996 Jason Merrill <jason@yorick.cygnus.com>
+
+ * pt.c (tsubst_expr, DECL_STMT): If we don't have an initializer,
+ don't pass LOOKUP_ONLYCONVERTING.
+
+Tue Apr 23 17:18:47 1996 Bob Manson <manson@charmed.cygnus.com>
+
+ * typeck.c (common_type): Fix the ARRAY_TYPE case so it
+ properly keeps track of const and volatile type modifiers.
+
+Tue Apr 23 10:52:56 1996 Jason Merrill <jason@yorick.cygnus.com>
+
+ * tree.c (cp_tree_equal): C++ version of simple_cst_equal.
+ * pt.c (comp_template_args): Use it.
+
+ * rtti.c (get_tinfo_fn, build_dynamic_cast, expand_*_desc): Call
+ assemble_external for artificial function decls.
+
+ * decl.c (cp_finish_decl): Oops.
+
+Mon Apr 22 17:28:27 1996 Jason Merrill <jason@yorick.cygnus.com>
+
+ * decl2.c (import_export_decl): Put static data member templates
+ into common storage, or make them weak, depending on whether they
+ are dynamically or statically initialized.
+ (get_sentry): New function.
+ (finish_file): Do import_export_decl for static data members before
+ building the init/fini functions. Don't init/fini a variable that's
+ EXTERNAL. Use a sentry for variables in common. Fix mismatching
+ push/pop_temp_slots.
+ * decl.c (cp_finish_decl): If DECL_NOT_REALLY_EXTERN, do the
+ expand_static_init thang.
+ * method.c (get_id_2): New function.
+
+Mon Apr 22 15:32:45 1996 Bob Manson <manson@charmed.cygnus.com>
+
+ * parse.y (empty_parms): Make sure we use C++-style prototypes
+ when we're declaring member functions.
+
+Sun Apr 21 10:08:22 1996 Jason Merrill <jason@yorick.cygnus.com>
+
+ * Makefile.in (CONFLICTS): 16 s/r conflicts.
+ * parse.y (self_template_type): New nonterminal.
+
Thu Apr 18 08:56:54 1996 Jason Merrill <jason@yorick.cygnus.com>
* decl.c (make_typename_type): Handle getting a TYPE_DECL for a
$(CC) -c $(ALL_CFLAGS) $(ALL_CPPFLAGS) $(INCLUDES) $(BIG_SWITCHFLAG) \
`echo $(PARSE_C) | sed 's,^\./,,'`
-CONFLICTS = expect 12 shift/reduce conflicts and 39 reduce/reduce conflicts.
+CONFLICTS = expect 16 shift/reduce conflicts and 39 reduce/reduce conflicts.
$(PARSE_H) : $(PARSE_C)
$(PARSE_C) : $(srcdir)/parse.y
@echo $(CONFLICTS)
if (TREE_CODE (decl) == FUNCTION_DECL)
;
- else if (DECL_EXTERNAL (decl))
+ else if (DECL_EXTERNAL (decl)
+ && ! (DECL_LANG_SPECIFIC (decl)
+ && DECL_NOT_REALLY_EXTERN (decl)))
{
if (init)
DECL_INITIAL (decl) = init;
DECL_NOT_REALLY_EXTERN (decl) = 1;
if (DECL_IMPLICIT_INSTANTIATION (decl) && flag_implicit_templates)
{
- /* For now, leave vars public so multiple defs will break. */
if (TREE_CODE (decl) == FUNCTION_DECL)
{
if (flag_weak)
else
TREE_PUBLIC (decl) = 0;
}
+ /* Dynamically initialized vars go into common. */
+ else if (DECL_INITIAL (decl) == NULL_TREE
+ || DECL_INITIAL (decl) == error_mark_node)
+ DECL_COMMON (decl) = 1;
+ else if (EMPTY_CONSTRUCTOR_P (DECL_INITIAL (decl)))
+ {
+ DECL_COMMON (decl) = 1;
+ DECL_INITIAL (decl) = error_mark_node;
+ }
+ /* Statically initialized vars are weak or comdat, if supported. */
+ else if (flag_weak)
+ DECL_WEAK (decl) = 1;
+ /* else leave vars public so multiple defs will break. */
}
else
DECL_NOT_REALLY_EXTERN (decl) = 0;
#define TIMEVAR(VAR, BODY) \
do { int otime = get_run_time (); BODY; VAR += get_run_time () - otime; } while (0)
+extern struct obstack permanent_obstack;
+extern tree get_id_2 ();
+
+tree
+get_sentry (base)
+ tree base;
+{
+ tree sname = get_id_2 ("__sn", base);
+ tree sentry = IDENTIFIER_GLOBAL_VALUE (sname);
+ if (! sentry)
+ {
+ push_obstacks (&permanent_obstack, &permanent_obstack);
+ sentry = build_decl (VAR_DECL, sname, integer_type_node);
+ TREE_PUBLIC (sentry) = 1;
+ DECL_ARTIFICIAL (sentry) = 1;
+ TREE_STATIC (sentry) = 1;
+ TREE_USED (sentry) = 1;
+ DECL_COMMON (sentry) = 1;
+ pushdecl_top_level (sentry);
+ cp_finish_decl (sentry, NULL_TREE, NULL_TREE, 0, 0);
+ pop_obstacks ();
+ }
+ return sentry;
+}
+
/* This routine is called from the last rule in yyparse ().
Its job is to create all the code needed to initialize and
destroy the global aggregates. We do the destruction
that we can pick up any other tdecls that those routines need. */
walk_vtables ((void (*)())0, finish_prevtable_vardecl);
+ for (vars = pending_statics; vars; vars = TREE_CHAIN (vars))
+ {
+ tree decl = TREE_VALUE (vars);
+
+ if (DECL_TEMPLATE_INSTANTIATION (decl)
+ && ! DECL_IN_AGGR_P (decl))
+ {
+ import_export_decl (decl);
+ DECL_EXTERNAL (decl) = ! DECL_NOT_REALLY_EXTERN (decl);
+ }
+ }
+
vars = static_aggregates;
if (static_ctors || vars || might_have_exceptions_p ())
tree type = TREE_TYPE (decl);
tree temp = TREE_PURPOSE (vars);
- if (TYPE_NEEDS_DESTRUCTOR (type) && ! TREE_STATIC (vars))
+ if (TYPE_NEEDS_DESTRUCTOR (type) && ! TREE_STATIC (vars)
+ && ! DECL_EXTERNAL (decl))
{
temp = build_cleanup (decl);
+
+ if (DECL_COMMON (decl))
+ {
+ tree sentry = get_sentry (DECL_ASSEMBLER_NAME (decl));
+ sentry = build_unary_op (PREDECREMENT_EXPR, sentry, 0);
+ sentry = build_binary_op (EQ_EXPR, sentry, integer_zero_node, 1);
+ expand_start_cond (sentry, 0);
+ }
+
expand_expr_stmt (temp);
+
+ if (DECL_COMMON (decl))
+ expand_end_cond ();
}
}
then don't initialize it here. Also, don't bother
with initializers that contain errors. */
if (TREE_STATIC (vars)
+ || DECL_EXTERNAL (decl)
|| (init && TREE_CODE (init) == TREE_LIST
&& value_member (error_mark_node, init)))
{
vars = TREE_CHAIN (vars);
- continue;
+ goto next_mess;
}
if (TREE_CODE (decl) == VAR_DECL)
DECL_CLASS_CONTEXT (current_function_decl) = DECL_CONTEXT (decl);
DECL_STATIC_FUNCTION_P (current_function_decl) = 1;
+ if (DECL_COMMON (decl))
+ {
+ tree sentry = get_sentry (DECL_ASSEMBLER_NAME (decl));
+ sentry = build_unary_op (PREINCREMENT_EXPR, sentry, 0);
+ sentry = build_binary_op
+ (EQ_EXPR, sentry, integer_one_node, 1);
+ expand_start_cond (sentry, 0);
+ }
+
if (IS_AGGR_TYPE (TREE_TYPE (decl))
|| TREE_CODE (TREE_TYPE (decl)) == ARRAY_TYPE)
expand_aggr_init (decl, init, 0, 0);
else
expand_assignment (decl, init, 0, 0);
+ if (DECL_COMMON (decl))
+ expand_end_cond ();
+
DECL_CLASS_CONTEXT (current_function_decl) = NULL_TREE;
DECL_STATIC_FUNCTION_P (current_function_decl) = 0;
}
- else if (TREE_CODE (decl) == SAVE_EXPR)
- {
- if (! PARM_DECL_EXPR (decl))
- {
- /* a `new' expression at top level. */
- expand_expr (decl, const0_rtx, VOIDmode, 0);
- if (TREE_CODE (init) == TREE_VEC)
- {
- expand_expr (expand_vec_init (decl, TREE_VEC_ELT (init, 0),
- TREE_VEC_ELT (init, 1),
- TREE_VEC_ELT (init, 2), 0),
- const0_rtx, VOIDmode, 0);
- }
- else
- expand_aggr_init (build_indirect_ref (decl, NULL_PTR), init, 0, 0);
- }
- }
else if (decl == error_mark_node)
;
else my_friendly_abort (22);
/* Cleanup any temporaries needed for the initial value. */
expand_cleanups_to (old_cleanups);
+ next_mess:
pop_temp_slots ();
pop_temp_slots ();
target_temp_slot_level = old_temp_level;
{
tree decl = TREE_VALUE (pending_statics);
- if (DECL_TEMPLATE_INSTANTIATION (decl)
- && ! DECL_IN_AGGR_P (decl))
- {
- import_export_decl (decl);
- DECL_EXTERNAL (decl) = ! DECL_NOT_REALLY_EXTERN (decl);
- }
-
if (TREE_USED (decl) == 1
|| TREE_READONLY (decl) == 0
|| DECL_INITIAL (decl) == 0)
return get_identifier (obstack_base (&scratch_obstack));
}
+tree
+get_id_2 (name, name2)
+ char *name;
+ tree name2;
+{
+ OB_INIT ();
+ OB_PUTCP (name);
+ OB_PUTID (name2);
+ OB_FINISH ();
+ return get_identifier (obstack_base (&scratch_obstack));
+}
+
/* Top-level interface to explicit overload requests. Allow NAME
to be overloaded. Error if NAME is already declared for the current
scope. Warning if function is redundantly overloaded. */
{
tree parms;
- if (strict_prototype)
+ if (strict_prototype
+ || current_class_type != NULL)
parms = void_list_node;
else
parms = NULL_TREE;
%type <ttype> named_class_head_sans_basetype_defn
%type <ttype> identifier_defn IDENTIFIER_DEFN TYPENAME_DEFN PTYPENAME_DEFN
+%type <ttype> self_template_type
+
%token NSNAME
%type <ttype> NSNAME
}
$$ = build_parse_node (CALL_EXPR, $$, empty_parms (), $5);
}
+ | nested_name_specifier self_template_type '('
+ {
+ $$ = build_parse_node (SCOPE_REF, $1, $2);
+ if ($1 != current_class_type)
+ {
+ push_nested_class ($1, 3);
+ TREE_COMPLEXITY ($$) = current_class_depth;
+ }
+ }
+ parmlist ')' type_quals
+ { $$ = build_parse_node (CALL_EXPR, $<ttype>4, $5, $7); }
+ | nested_name_specifier self_template_type LEFT_RIGHT type_quals
+ {
+ $$ = build_parse_node (SCOPE_REF, $1, $2);
+ if ($1 != current_class_type)
+ {
+ push_nested_class ($1, 3);
+ TREE_COMPLEXITY ($$) = current_class_depth;
+ }
+ $$ = build_parse_node (CALL_EXPR, $$, empty_parms (), $4);
+ }
+ | global_scope nested_name_specifier self_template_type '('
+ {
+ $$ = build_parse_node (SCOPE_REF, $2, $3);
+ if ($2 != current_class_type)
+ {
+ push_nested_class ($2, 3);
+ TREE_COMPLEXITY ($$) = current_class_depth;
+ }
+ }
+ parmlist ')' type_quals
+ { $$ = build_parse_node (CALL_EXPR, $<ttype>5, $6, $8); }
+ | global_scope nested_name_specifier self_template_type LEFT_RIGHT type_quals
+ {
+ $$ = build_parse_node (SCOPE_REF, $2, $3);
+ if ($2 != current_class_type)
+ {
+ push_nested_class ($2, 3);
+ TREE_COMPLEXITY ($$) = current_class_depth;
+ }
+ $$ = build_parse_node (CALL_EXPR, $$, empty_parms (), $5);
+ }
;
fn.def1:
{ $$ = build_parse_node (CALL_EXPR, $1, $3, $5); }
| SELFNAME LEFT_RIGHT type_quals
{ $$ = build_parse_node (CALL_EXPR, $1, empty_parms (), $3); }
+ | self_template_type '(' parmlist ')' type_quals
+ { $$ = build_parse_node (CALL_EXPR, $1, $3, $5); }
+ | self_template_type LEFT_RIGHT type_quals
+ { $$ = build_parse_node (CALL_EXPR, $1, empty_parms (), $3); }
;
/* more C++ complexity. See component_decl for a comment on the
if ($$ != error_mark_node)
$$ = TYPE_STUB_DECL ($$);
}
- | SELFNAME '<' template_arg_list template_close_bracket
+ | self_template_type
+ ;
+
+self_template_type:
+ SELFNAME '<' template_arg_list template_close_bracket
{
$$ = lookup_template_class ($1, $3, NULL_TREE);
if ($$ != error_mark_node)
continue;
if (TREE_CODE (nt) != TREE_CODE (ot))
return 0;
- if (TREE_CODE_CLASS (TREE_CODE (ot)) == 't' && comptypes (ot, nt, 1))
- continue;
- if (TREE_CODE (ot) == TEMPLATE_CONST_PARM
- && TEMPLATE_CONST_IDX (nt) == TEMPLATE_CONST_IDX (ot))
+ if (TREE_CODE_CLASS (TREE_CODE (ot)) == 't')
+ {
+ if (comptypes (ot, nt, 1))
+ continue;
+ }
+ else if (cp_tree_equal (ot, nt) > 0)
continue;
return 0;
}
case DECL_STMT:
{
int i = suspend_momentary ();
- tree dcl;
+ tree dcl, init;
lineno = TREE_COMPLEXITY (t);
emit_line_note (input_filename, lineno);
tsubst (TREE_OPERAND (t, 1), args, nargs, in_decl),
TREE_OPERAND (t, 3) != 0,
tsubst (TREE_OPERAND (t, 2), args, nargs, in_decl));
+ init = tsubst_expr (TREE_OPERAND (t, 3), args, nargs, in_decl);
cp_finish_decl
- (dcl, tsubst_expr (TREE_OPERAND (t, 3), args, nargs, in_decl),
- NULL_TREE, 1, LOOKUP_ONLYCONVERTING);
+ (dcl, init, NULL_TREE, 1, init ? LOOKUP_ONLYCONVERTING : 0);
resume_momentary (i);
return dcl;
}
TREE_TYPE (name) = type;
pushdecl_top_level (d);
make_function_rtl (d);
+ assemble_external (d);
mark_inline_for_output (d);
if (at_eof)
import_export_decl (d);
DECL_ARTIFICIAL (d) = 1;
pushdecl_top_level (d);
make_function_rtl (d);
+ assemble_external (d);
pop_obstacks ();
DECL_ARTIFICIAL (dcast_fn) = 1;
pushdecl_top_level (dcast_fn);
make_function_rtl (dcast_fn);
+ assemble_external (dcast_fn);
pop_obstacks ();
}
DECL_ARTIFICIAL (fn) = 1;
pushdecl_top_level (fn);
make_function_rtl (fn);
+ assemble_external (fn);
pop_obstacks ();
}
DECL_ARTIFICIAL (fn) = 1;
pushdecl_top_level (fn);
make_function_rtl (fn);
+ assemble_external (fn);
pop_obstacks ();
}
DECL_ARTIFICIAL (fn) = 1;
pushdecl_top_level (fn);
make_function_rtl (fn);
+ assemble_external (fn);
pop_obstacks ();
}
DECL_ARTIFICIAL (fn) = 1;
pushdecl_top_level (fn);
make_function_rtl (fn);
+ assemble_external (fn);
pop_obstacks ();
}
DECL_ARTIFICIAL (fn) = 1;
pushdecl_top_level (fn);
make_function_rtl (fn);
+ assemble_external (fn);
pop_obstacks ();
}
return decl_function_context (TYPE_MAIN_DECL (DECL_CLASS_CONTEXT (decl)));
return decl_function_context (decl);
}
+
+/* Return truthvalue of whether T1 is the same tree structure as T2.
+ Return 1 if they are the same.
+ Return 0 if they are understandably different.
+ Return -1 if either contains tree structure not understood by
+ this function. */
+
+int
+cp_tree_equal (t1, t2)
+ tree t1, t2;
+{
+ register enum tree_code code1, code2;
+ int cmp;
+
+ if (t1 == t2)
+ return 1;
+ if (t1 == 0 || t2 == 0)
+ return 0;
+
+ code1 = TREE_CODE (t1);
+ code2 = TREE_CODE (t2);
+
+ if (code1 == NOP_EXPR || code1 == CONVERT_EXPR || code1 == NON_LVALUE_EXPR)
+ if (code2 == NOP_EXPR || code2 == CONVERT_EXPR || code2 == NON_LVALUE_EXPR)
+ return cp_tree_equal (TREE_OPERAND (t1, 0), TREE_OPERAND (t2, 0));
+ else
+ return cp_tree_equal (TREE_OPERAND (t1, 0), t2);
+ else if (code2 == NOP_EXPR || code2 == CONVERT_EXPR
+ || code2 == NON_LVALUE_EXPR)
+ return cp_tree_equal (t1, TREE_OPERAND (t2, 0));
+
+ if (code1 != code2)
+ return 0;
+
+ switch (code1)
+ {
+ case INTEGER_CST:
+ return TREE_INT_CST_LOW (t1) == TREE_INT_CST_LOW (t2)
+ && TREE_INT_CST_HIGH (t1) == TREE_INT_CST_HIGH (t2);
+
+ case REAL_CST:
+ return REAL_VALUES_EQUAL (TREE_REAL_CST (t1), TREE_REAL_CST (t2));
+
+ case STRING_CST:
+ return TREE_STRING_LENGTH (t1) == TREE_STRING_LENGTH (t2)
+ && !bcmp (TREE_STRING_POINTER (t1), TREE_STRING_POINTER (t2),
+ TREE_STRING_LENGTH (t1));
+
+ case CONSTRUCTOR:
+ abort ();
+
+ case SAVE_EXPR:
+ return cp_tree_equal (TREE_OPERAND (t1, 0), TREE_OPERAND (t2, 0));
+
+ case CALL_EXPR:
+ cmp = cp_tree_equal (TREE_OPERAND (t1, 0), TREE_OPERAND (t2, 0));
+ if (cmp <= 0)
+ return cmp;
+ return simple_cst_list_equal (TREE_OPERAND (t1, 1), TREE_OPERAND (t2, 1));
+
+ case TARGET_EXPR:
+ /* Special case: if either target is an unallocated VAR_DECL,
+ it means that it's going to be unified with whatever the
+ TARGET_EXPR is really supposed to initialize, so treat it
+ as being equivalent to anything. */
+ if ((TREE_CODE (TREE_OPERAND (t1, 0)) == VAR_DECL
+ && DECL_NAME (TREE_OPERAND (t1, 0)) == NULL_TREE
+ && DECL_RTL (TREE_OPERAND (t1, 0)) == 0)
+ || (TREE_CODE (TREE_OPERAND (t2, 0)) == VAR_DECL
+ && DECL_NAME (TREE_OPERAND (t2, 0)) == NULL_TREE
+ && DECL_RTL (TREE_OPERAND (t2, 0)) == 0))
+ cmp = 1;
+ else
+ cmp = cp_tree_equal (TREE_OPERAND (t1, 0), TREE_OPERAND (t2, 0));
+ if (cmp <= 0)
+ return cmp;
+ return cp_tree_equal (TREE_OPERAND (t1, 1), TREE_OPERAND (t2, 1));
+
+ case WITH_CLEANUP_EXPR:
+ cmp = cp_tree_equal (TREE_OPERAND (t1, 0), TREE_OPERAND (t2, 0));
+ if (cmp <= 0)
+ return cmp;
+ return cp_tree_equal (TREE_OPERAND (t1, 2), TREE_OPERAND (t1, 2));
+
+ case COMPONENT_REF:
+ if (TREE_OPERAND (t1, 1) == TREE_OPERAND (t2, 1))
+ return cp_tree_equal (TREE_OPERAND (t1, 0), TREE_OPERAND (t2, 0));
+ return 0;
+
+ case VAR_DECL:
+ case PARM_DECL:
+ case CONST_DECL:
+ case FUNCTION_DECL:
+ return 0;
+
+ case TEMPLATE_CONST_PARM:
+ return TEMPLATE_CONST_IDX (t1) == TEMPLATE_CONST_IDX (t2);
+
+ case SIZEOF_EXPR:
+ if (TREE_CODE (TREE_OPERAND (t1, 0)) != TREE_CODE (TREE_OPERAND (t2, 0)))
+ return 0;
+ if (TREE_CODE_CLASS (TREE_CODE (TREE_OPERAND (t1, 0))) == 't')
+ return comptypes (TREE_OPERAND (t1, 0), TREE_OPERAND (t2, 0), 1);
+ break;
+ }
+
+ switch (TREE_CODE_CLASS (code1))
+ {
+ int i;
+ case '1':
+ case '2':
+ case '<':
+ case 'e':
+ case 'r':
+ case 's':
+ cmp = 1;
+ for (i=0; i<tree_code_length[(int) code1]; ++i)
+ {
+ cmp = cp_tree_equal (TREE_OPERAND (t1, i), TREE_OPERAND (t2, i));
+ if (cmp <= 0)
+ return cmp;
+ }
+ return cmp;
+ }
+
+ return -1;
+}
case ARRAY_TYPE:
{
+ int constp
+ = TYPE_READONLY (t1) || TYPE_READONLY (t2);
+ int volatilep
+ = TYPE_VOLATILE (t1) || TYPE_VOLATILE (t2);
tree elt = common_type (TREE_TYPE (t1), TREE_TYPE (t2));
/* Save space: see if the result is identical to one of the args. */
if (elt == TREE_TYPE (t1) && TYPE_DOMAIN (t1))
if (elt == TREE_TYPE (t2) && TYPE_DOMAIN (t2))
return build_type_attribute_variant (t2, attributes);
/* Merge the element types, and have a size if either arg has one. */
- t1 = build_cplus_array_type (elt, TYPE_DOMAIN (TYPE_DOMAIN (t1) ? t1 : t2));
+ t1 = build_cplus_array_type (TYPE_MAIN_VARIANT (elt), TYPE_DOMAIN (TYPE_DOMAIN (t1) ? t1 : t2));
+ if (constp || volatilep)
+ t1 = cp_build_type_variant (t1, constp, volatilep);
return build_type_attribute_variant (t1, attributes);
}