+Fri Aug 5 01:12:20 1994 Mike Stump (mrs@cygnus.com)
+
+ * class.c (get_class_offset_1, get_class_offset): New routine to
+ find the offset of the class where a virtual function is defined,
+ from the complete type.
+ * class.c (modify_one_vtable, fixup_vtable_deltas): Use
+ get_class_offset instead of virtual_offset as get_class_offset will
+ always provide the right answer.
+ * tree.c (virtual_offset): Remove. It only ever worked some of the
+ time.
+
+Tue Aug 2 12:44:21 1994 Jason Merrill (jason@deneb.cygnus.com)
+
+ * call.c (build_method_call): Put back unary_complex_lvalue call
+ that I thought was redundant.
+
+ * typeck.c (c_expand_return): Fix a case I missed before.
+
+Sun Jul 31 17:54:02 1994 Jason Merrill (jason@deneb.cygnus.com)
+
+ * pt.c (unify): Strip cv-quals from template type arguments (when
+ 'const T*' is matched to 'const char*', that does not mean that T is
+ 'const char').
+
+Fri Jul 29 01:03:06 1994 Jason Merrill (jason@deneb.cygnus.com)
+
+ * pt.c (do_type_instantiation): Instantiate nested TAGS, not
+ typedefs. Third time's the charm?
+
+ * parse.y (template_parm): Support default template parms.
+ * pt.c (process_template_parm): Ditto.
+ (end_template_parm_list): Ditto.
+ (coerce_template_parms): Ditto.
+ (mangle_class_name_for_template): Ditto.
+ (push_template_decls): Ditto.
+ (unify): Ditto.
+ * method.c (build_overload_identifier): Ditto.
+ * error.c (dump_decl): Ditto.
+
+Wed Jul 27 17:47:00 1994 Jason Merrill (jason@deneb.cygnus.com)
+
+ * pt.c (do_type_instantiation): Only instantiate nested *classes*.
+
+Tue Jul 26 13:22:40 1994 Jason Merrill (jason@deneb.cygnus.com)
+
+ * search.c (note_debug_info_needed): Also emit debugging information
+ for the types of fields.
+
+Mon Jul 25 00:34:44 1994 Jason Merrill (jason@deneb.cygnus.com)
+
+ * pt.c (lookup_template_class): Pass 'template' to
+ coerce_template_parms instead of 'in_decl', since it's a more
+ meaningful context.
+
+ * typeck.c (c_expand_return): Make sure any cleanups for the return
+ expression get run.
+ (build_c_cast): Use CONVERT_EXPR for conversion to void.
+
+ * pt.c (do_type_instantiation): Also instantiate nested types.
+
+ * typeck.c (convert_for_assignment): Don't die when comparing
+ pointers with different levels of indirection.
+
+ * decl.c (grokdeclarator): The sub-call to grokdeclarator for
+ class-local typedefs sets DECL_ARGUMENTS, so we need to clear it
+ out.
+
+ * decl2.c (finish_anon_union): Don't die if the union has no
+ members.
+
+ * decl.c (grokdeclarator): Undo changes to declspecs when we're done
+ so that 'typedef int foo, bar;' will work.
+
+ * decl2.c (finish_file): Don't call expand_aggr_init for
+ non-aggregates.
+
+Mon Jul 25 00:03:10 1994 Teemu Torma (tot@trema.fi)
+
+ * decl.c (finish_function): We can't inline constructors and
+ destructors under some conditions with -fpic, but don't unset
+ DECL_INLINE.
+
+Mon Jul 25 00:03:10 1994 Jason Merrill (jason@deneb.cygnus.com)
+
+ * typeck.c (build_object_ref): Make sure 'datum' is a valid object.
+
+Sun Jul 24 14:19:31 1994 Jason Merrill (jason@deneb.cygnus.com)
+
+ * class.c (finish_struct): Don't set DECL_FIELD_BITPOS on
+ non-fields.
+ (finish_struct_methods): Use copy_assignment_arg_p.
+
+ * cvt.c (cp_convert): If expr is an OFFSET_REF, resolve it instead
+ of giving an error.
+
+ * typeck.c (build_binary_op_nodefault): Don't set result_type if we
+ don't know how to compare the operands.
+
+ * decl.c (grokdeclarator): Avoid seg fault when someone uses '__op'
+ as a declarator-id in their program. Like the Linux headers do.
+ Arrgh.
+
+ * tree.c (lvalue_p): Treat calls to functions returning objects by
+ value as lvalues again.
+
+ * typeck.c (build_component_addr): Use convert_force to convert the
+ pointer in case the component type is also a private base class.
+
+ * search.c (get_matching_virtual): Fix bogus warning of overloaded
+ virtual.
+
+ * pt.c (overload_template_name): Set DECL_ARTIFICIAL on the created
+ TYPE_DECL to fix bogus shadowing warnings.
+
+Fri Jul 22 01:15:32 1994 Jason Merrill (jason@deneb.cygnus.com)
+
+ * init.c (expand_aggr_init_1): const and volatile mismatches do not
+ prevent a TARGET_EXPR from initializing an object directly.
+
+Tue Jul 19 17:55:37 1994 Jason Merrill (jason@deneb.cygnus.com)
+
+ * cvt.c (build_up_reference): Allow building up references to
+ `this', don't warn about making references to artificial variables
+ (like `this').
+
+ * tree.c (lvalue_p): `this' is not an lvalue.
+
+ * call.c (build_method_call): Accept using a typedef name (or
+ template type parameter) for explicit destructor calls.
+
Wed Jul 13 03:57:54 1994 Jason Merrill (jason@deneb.cygnus.com)
- * method.c (hack_identifier): Put back old code so lists of
- non-functions will be handled properly.
+ * method.c (hack_identifier): Put back old code so lists of
+ non-functions will be handled properly.
- * cp-tree.h (TYPE_NEEDS_CONSTRUCTING): #if 0 out; this macro is now
- defined in the language-independent tree.h.
+ * cp-tree.h (TYPE_NEEDS_CONSTRUCTING): #if 0 out; this macro is now
+ defined in the language-independent tree.h.
- * tree.c (count_functions): Avoid bogus warning when compiling this
- function.
+ * tree.c (count_functions): Avoid bogus warning when compiling this
+ function.
Mon Jul 11 18:37:20 1994 Jason Merrill (jason@deneb.cygnus.com)
- * decl.c (grok_reference_init): Always save the initializer of a
- reference.
+ * decl.c (grok_reference_init): Always save the initializer of a
+ reference.
Fri Jul 8 17:41:46 1994 Mike Stump (mrs@cygnus.com)
* decl.c (push_overloaded_decl): Don't create overloads of one when
shadowing a class type.
- * typeck.c (build_x_function_call): Complain about overloads of one
+ * typeck.c (build_x_function_call): Complain about overloads of one.
* decl.c (grokdeclarator): Don't try to treat a char* as a tree.
(grokdeclarator): Fix setting of TREE_STATIC.
`echo $(srcdir)/parse.c | sed 's,^\./,,'`
$(srcdir)/parse.c $(srcdir)/parse.h : $(srcdir)/parse.y
- @echo expect 1 shift/reduce confict and 33 reduce/reduce conflicts.
+ @echo expect 1 shift/reduce confict and 34 reduce/reduce conflicts.
cd $(srcdir); $(BISON) $(BISONFLAGS) -d -o parse.c parse.y
cd $(srcdir); grep '^#define[ ]*YYEMPTY' parse.c >>parse.h
if (parms)
error ("destructors take no parameters");
basetype = TREE_TYPE (instance);
- if (IS_AGGR_TYPE (basetype))
+ if (! ((IS_AGGR_TYPE (basetype)
+ && name == constructor_name (basetype))
+ || basetype == get_type_value (name)))
{
- if (name == constructor_name (basetype))
- goto huzzah;
+ cp_error ("destructor name `~%D' does not match type `%T' of expression",
+ name, basetype);
+ return void_zero_node;
}
- else
- {
- if (basetype == get_type_value (name))
- goto huzzah;
- }
- cp_error ("destructor name `~%D' does not match type `%T' of expression",
- name, basetype);
- return void_zero_node;
- huzzah:
if (! TYPE_HAS_DESTRUCTOR (basetype))
return void_zero_node;
instance = default_conversion (instance);
{
tree parmtype = TREE_VALUE (FUNCTION_ARG_CHAIN (fn_fields));
- if (TREE_CODE (parmtype) == REFERENCE_TYPE
- && TYPE_MAIN_VARIANT (TREE_TYPE (parmtype)) == t)
+ if (copy_assignment_arg_p (parmtype, DECL_VIRTUAL_P (fn_fields)))
{
if (TREE_PROTECTED (fn_fields))
TYPE_HAS_NONPUBLIC_ASSIGN_REF (t) = 1;
return 0;
}
+static tree
+get_class_offset_1 (parent, binfo, context, t, fndecl)
+ tree parent, binfo, context, t, fndecl;
+{
+ tree binfos = BINFO_BASETYPES (binfo);
+ int i, n_baselinks = binfos ? TREE_VEC_LENGTH (binfos) : 0;
+ tree rval = NULL_TREE;
+
+ if (binfo == parent)
+ return error_mark_node;
+
+ for (i = 0; i < n_baselinks; i++)
+ {
+ tree base_binfo = TREE_VEC_ELT (binfos, i);
+ tree nrval;
+
+ if (TREE_VIA_VIRTUAL (base_binfo))
+ base_binfo = binfo_member (BINFO_TYPE (base_binfo),
+ CLASSTYPE_VBASECLASSES (t));
+ nrval = get_class_offset_1 (parent, base_binfo, context, t, fndecl);
+ /* See if we have a new value */
+ if (nrval && (nrval != error_mark_node || rval==0))
+ {
+ /* Only compare if we have two offsets */
+ if (rval && rval != error_mark_node
+ && ! tree_int_cst_equal (nrval, rval))
+ {
+ /* Only give error if the two offsets are different */
+ error ("every virtual function must have a unique final overrider");
+ cp_error (" found two (or more) `%T' class subobjects in `%T'", context, t);
+ cp_error (" with virtual `%D' from virtual base class", fndecl);
+ return rval;
+ }
+ rval = nrval;
+ }
+
+ if (rval && BINFO_TYPE (binfo) == context)
+ {
+ my_friendly_assert (rval == error_mark_node
+ || tree_int_cst_equal (rval, BINFO_OFFSET (binfo)), 999);
+ rval = BINFO_OFFSET (binfo);
+ }
+ }
+ return rval;
+}
+
+/* Get the offset to the CONTEXT subobject that is related to the
+ given BINFO. */
+static tree
+get_class_offset (context, t, binfo, fndecl)
+ tree context, t, binfo, fndecl;
+{
+ tree first_binfo = binfo;
+ tree offset;
+ int i;
+
+ if (context == t)
+ return integer_zero_node;
+
+ if (BINFO_TYPE (binfo) == context)
+ return BINFO_OFFSET (binfo);
+
+ /* Check less derived binfos first. */
+ while (BINFO_BASETYPES (binfo)
+ && (i=CLASSTYPE_VFIELD_PARENT (BINFO_TYPE (binfo))) != -1)
+ {
+ tree binfos = BINFO_BASETYPES (binfo);
+ binfo = TREE_VEC_ELT (binfos, i);
+ if (BINFO_TYPE (binfo) == context)
+ return BINFO_OFFSET (binfo);
+ }
+
+ /* Ok, not found in the less derived binfos, now check the more
+ derived binfos. */
+ offset = get_class_offset_1 (first_binfo, TYPE_BINFO (t), context, t, fndecl);
+ if (offset==0 || TREE_CODE (offset) != INTEGER_CST)
+ my_friendly_abort (999); /* we have to find it. */
+ return offset;
+}
+
static void
modify_one_vtable (binfo, t, fndecl, pfn)
tree binfo, t, fndecl, pfn;
tree vfield = CLASSTYPE_VFIELD (t);
tree this_offset;
- offset = integer_zero_node;
- if (context != t && TYPE_USES_COMPLEX_INHERITANCE (t))
- {
- offset = virtual_offset (context, CLASSTYPE_VBASECLASSES (t), offset);
- if (offset == NULL_TREE)
- {
- tree binfo = get_binfo (context, t, 0);
- offset = BINFO_OFFSET (binfo);
- }
- }
+ offset = get_class_offset (context, t, binfo, fndecl);
/* Find the right offset for the this pointer based on the
base class we just found. We have to take into
tree vfield = CLASSTYPE_VFIELD (t);
tree this_offset;
- offset = integer_zero_node;
- if (context != t && TYPE_USES_COMPLEX_INHERITANCE (t))
- {
- offset = virtual_offset (context, CLASSTYPE_VBASECLASSES (t), offset);
- if (offset == NULL_TREE)
- {
- tree binfo = get_binfo (context, t, 0);
- offset = BINFO_OFFSET (binfo);
- }
- }
+ offset = get_class_offset (context, t, binfo, fndecl);
/* Find the right offset for the this pointer based on the
base class we just found. We have to take into
tree uelt = TYPE_FIELDS (TREE_TYPE (field));
for (; uelt; uelt = TREE_CHAIN (uelt))
{
+ if (TREE_CODE (uelt) != FIELD_DECL)
+ continue;
+
DECL_FIELD_CONTEXT (uelt) = DECL_FIELD_CONTEXT (field);
DECL_FIELD_BITPOS (uelt) = DECL_FIELD_BITPOS (field);
}
tree uelt = TYPE_FIELDS (TREE_TYPE (field));
for (; uelt; uelt = TREE_CHAIN (uelt))
{
+ if (TREE_CODE (uelt) != FIELD_DECL)
+ continue;
+
DECL_FIELD_CONTEXT (uelt) = DECL_FIELD_CONTEXT (field);
DECL_FIELD_BITPOS (uelt) = DECL_FIELD_BITPOS (field);
}
extern tree binfo_value PROTO((tree, tree));
extern tree reverse_path PROTO((tree));
extern tree virtual_member PROTO((tree, tree));
-extern tree virtual_offset PROTO((tree, tree, tree));
extern void debug_binfo PROTO((tree));
extern int decl_list_length PROTO((tree));
extern int count_functions PROTO((tree));
break;
case PARM_DECL:
+#if 0
if (targ == current_class_decl)
{
error ("address of `this' not available");
-#if 0
+/* #if 0 */
/* This code makes the following core dump the compiler on a sun4,
if the code below is used.
TREE_ADDRESSABLE (targ) = 1; /* so compiler doesn't die later */
put_var_into_stack (targ);
break;
-#else
+/* #else */
return error_mark_node;
-#endif
+/* #endif */
}
+#endif
/* Fall through. */
case VAR_DECL:
case CONST_DECL:
- if (DECL_REGISTER (targ) && !TREE_ADDRESSABLE (targ))
- warning ("address needed to build reference for `%s', which is declared `register'",
- IDENTIFIER_POINTER (DECL_NAME (targ)));
+ if (DECL_REGISTER (targ) && !TREE_ADDRESSABLE (targ)
+ && !DECL_ARTIFICIAL (targ))
+ cp_warning ("address needed to build reference for `%D', which is declared `register'",
+ targ);
else if (staticp (targ))
literal_flag = 1;
else if (TREE_CODE (TREE_TYPE (e)) == REFERENCE_TYPE)
e = convert_from_reference (e);
+ if (TREE_CODE (e) == OFFSET_REF)
+ e = resolve_offset_ref (e);
+
if (TREE_READONLY_DECL_P (e))
e = decl_constant_value (e);
if (flag_pedantic_errors)
return error_mark_node;
}
- if (form == OFFSET_TYPE)
- cp_error_at ("pointer-to-member expression object not composed with type `%D' object",
- TYPE_NAME (TYPE_OFFSET_BASETYPE (intype)));
- else if (IS_AGGR_TYPE (intype))
+ if (IS_AGGR_TYPE (intype))
{
tree rval;
rval = build_type_conversion (CONVERT_EXPR, type, e, 1);
dname = decl;
decl = NULL_TREE;
- if (IDENTIFIER_OPNAME_P (dname))
+ if (! IDENTIFIER_OPNAME_P (dname)
+ /* Linux headers use '__op'. Arrgh. */
+ || IDENTIFIER_TYPENAME_P (dname) && ! TREE_TYPE (dname))
+ name = IDENTIFIER_POINTER (dname);
+ else
{
if (IDENTIFIER_TYPENAME_P (dname))
{
}
name = operator_name_string (dname);
}
- else
- name = IDENTIFIER_POINTER (dname);
break;
case RECORD_TYPE:
break;
}
- if (scanner == IDENTIFIER_AS_LIST (ridpointers [(int) RID_TYPEDEF]))
- {
- if (previous_declspec)
- TREE_CHAIN (previous_declspec)
- = IDENTIFIER_AS_LIST (ridpointers [(int) RID_STATIC]);
- else
- declspecs
- = IDENTIFIER_AS_LIST (ridpointers [(int) RID_STATIC]);
- }
+ if (previous_declspec)
+ TREE_CHAIN (previous_declspec) = TREE_CHAIN (scanner);
else
- TREE_VALUE (scanner) = ridpointers[(int) RID_STATIC];
+ declspecs = TREE_CHAIN (scanner);
+
+ declspecs = tree_cons (NULL_TREE, ridpointers[(int) RID_STATIC],
+ declspecs);
/* In the recursive call to grokdeclarator we need to know
whether we are working on a signature-local typedef. */
loc_typedecl =
grokdeclarator (declarator, declspecs, FIELD, 0, NULL_TREE);
+
+ if (previous_declspec)
+ TREE_CHAIN (previous_declspec) = scanner;
if (loc_typedecl != error_mark_node)
{
register int *pi;
TREE_SET_CODE (loc_typedecl, TYPE_DECL);
+ /* This is the same field as DECL_ARGUMENTS, which is set for
+ function typedefs by the above grokdeclarator. */
+ DECL_NESTED_TYPENAME (loc_typedecl) = 0;
pi = (int *) permalloc (sizeof (struct lang_decl_flags));
while (i > 0)
/* So we can tell if jump_optimize sets it to 1. */
can_reach_end = 0;
- /* ??? Compensate for Sun brain damage in dealing with data segments
- of PIC code. */
- if (flag_pic
- && (DECL_CONSTRUCTOR_P (fndecl)
- || DESTRUCTOR_NAME_P (DECL_ASSEMBLER_NAME (fndecl)))
- && CLASSTYPE_NEEDS_VIRTUAL_REINIT (TYPE_METHOD_BASETYPE (fntype)))
- DECL_INLINE (fndecl) = 0;
-
if (DECL_EXTERNAL (fndecl)
/* This function is just along for the ride. If we can make
it inline, that's great. Otherwise, just punt it. */
&& (DECL_INLINE (fndecl) == 0
|| flag_no_inline
- || function_cannot_inline_p (fndecl)))
+ || function_cannot_inline_p (fndecl)
+ /* ??? Compensate for Sun brain damage in dealing with
+ data segments of PIC code. */
+ || (flag_pic
+ && (DECL_CONSTRUCTOR_P (fndecl)
+ || DESTRUCTOR_NAME_P (DECL_ASSEMBLER_NAME (fndecl)))
+ && CLASSTYPE_NEEDS_VIRTUAL_REINIT (TYPE_METHOD_BASETYPE (fntype)))))
+
{
extern int rtl_dump_and_exit;
int old_rtl_dump_and_exit = rtl_dump_and_exit;
}
if (static_p)
{
- make_decl_rtl (main_decl, 0, global_bindings_p ());
- DECL_RTL (anon_union_decl) = DECL_RTL (main_decl);
+ if (main_decl)
+ {
+ make_decl_rtl (main_decl, 0, global_bindings_p ());
+ DECL_RTL (anon_union_decl) = DECL_RTL (main_decl);
+ }
+ else
+ {
+ warning ("anonymous union with no members");
+ return;
+ }
}
/* The following call assumes that there are never any cleanups
}
}
if (IS_AGGR_TYPE (TREE_TYPE (decl))
- || init == 0
|| TREE_CODE (TREE_TYPE (decl)) == ARRAY_TYPE)
expand_aggr_init (decl, init, 0);
else if (TREE_CODE (init) == TREE_VEC)
for (i = 0; i < len; i++)
{
tree arg = TREE_VEC_ELT (args, i);
- if (TREE_CODE (arg) == IDENTIFIER_NODE)
+ tree defval = TREE_PURPOSE (arg);
+ arg = TREE_VALUE (arg);
+ if (TREE_CODE (arg) == TYPE_DECL)
{
OB_PUTS ("class ");
- OB_PUTID (arg);
+ OB_PUTID (DECL_NAME (arg));
}
else
dump_decl (arg, 1);
+
+ if (defval)
+ {
+ OB_PUTS (" = ");
+ dump_decl (defval, 1);
+ }
+
OB_PUTC2 (',', ' ');
}
OB_UNPUT (2);
separately from the object being initialized. */
if (TREE_CODE (init) == TARGET_EXPR)
{
- if (init_type == type)
+ if (TYPE_MAIN_VARIANT (init_type) == TYPE_MAIN_VARIANT (type))
{
if (TREE_CODE (exp) == VAR_DECL
|| TREE_CODE (exp) == RESULT_DECL)
if (c_header_level && --c_header_level == 0)
{
if (entering_c_header)
- warning ("Badly nested C headers from preprocessor");
+ warning ("badly nested C headers from preprocessor");
--pending_lang_change;
}
if (flag_cadillac)
icat (nparms);
for (i = 0; i < nparms; i++)
{
- tree parm = TREE_VEC_ELT (parmlist, i);
+ tree parm = TREE_VALUE (TREE_VEC_ELT (parmlist, i));
tree arg = TREE_VEC_ELT (arglist, i);
- if (TREE_CODE (parm) == IDENTIFIER_NODE)
+ if (TREE_CODE (parm) == TYPE_DECL)
{
/* This parameter is a type. */
OB_PUTC ('Z');
%type <ttype> type_id absdcl type_quals
%type <ttype> direct_abstract_declarator conversion_declarator
%type <ttype> new_type_id new_declarator direct_new_declarator
-%type <ttype> xexpr parmlist parms parm bad_parm
+%type <ttype> xexpr parmlist parms parm bad_parm full_parm
%type <ttype> identifiers_or_typenames
%type <ttype> fcast_or_absdcl regcast_or_absdcl sub_cast_expr
%type <ttype> expr_or_declarator complex_notype_declarator
%type <ttype> nonmomentary_expr
%type <itype> forhead.2 initdcl0 notype_initdcl0 member_init_list
%type <ttype> template_header template_parm_list template_parm
+%type <ttype> template_type_parm
%type <ttype> template_type template_arg_list template_arg
%type <ttype> template_instantiation template_type_name tmpl.2
%type <ttype> template_instantiate_once template_instantiate_some
{ $$ = process_template_parm ($1, $3); }
;
+template_type_parm:
+ aggr
+ {
+ $$ = build_tree_list ($1, NULL_TREE);
+ ttpa:
+ if (TREE_PURPOSE ($$) == signature_type_node)
+ sorry ("signature as template type parameter");
+ else if (TREE_PURPOSE ($$) != class_type_node)
+ pedwarn ("template type parameters must use the keyword `class'");
+ }
+ | aggr identifier
+ { $$ = build_tree_list ($1, $2); goto ttpa; }
+ ;
+
template_parm:
/* The following rules introduce a new reduce/reduce
conflict on the ',' and '>' input tokens: they are valid
By putting them before the `parm' rule, we get
their match before considering them nameless parameter
declarations. */
- aggr identifier
- {
- if ($1 == signature_type_node)
- sorry ("signature as template type parameter");
- else if ($1 != class_type_node)
- error ("template type parameter must use keyword `class'");
- $$ = build_tree_list ($2, NULL_TREE);
- }
- | aggr identifier_defn ':' base_class.1
- {
- if ($1 == signature_type_node)
- sorry ("signature as template type parameter");
- else if ($1 != class_type_node)
- error ("template type parameter must use keyword `class'");
- warning ("restricted template type parameters not yet implemented");
- $$ = build_tree_list ($2, $4);
- }
- | parm
+ template_type_parm
+ { $$ = build_tree_list (NULL_TREE, $$); }
+ | template_type_parm '=' typespec
+ { $$ = build_tree_list ($3, $$); }
+ | full_parm
;
overloaddef:
template_type_name:
PTYPENAME '<' template_arg_list '>'
{ $$ = lookup_template_class ($$, $3, NULL_TREE); }
+ | PTYPENAME '<' '>'
+ { $$ = lookup_template_class ($$, NULL_TREE, NULL_TREE); }
| TYPENAME '<' template_arg_list '>'
{ $$ = lookup_template_class ($$, $3, NULL_TREE); }
;
{ $$ = build_tree_list (NULL_TREE, $$); }
| parm '=' init
{ $$ = build_tree_list ($3, $$); }
- | parms_comma parm
- { $$ = chainon ($$, build_tree_list (NULL_TREE, $2)); }
- | parms_comma parm '=' init
- { $$ = chainon ($$, build_tree_list ($4, $2)); }
+ | parms_comma full_parm
+ { $$ = chainon ($$, $2); }
| parms_comma bad_parm
{ $$ = chainon ($$, build_tree_list (NULL_TREE, $2)); }
| parms_comma bad_parm '=' init
{ $$ = build_tree_list ($$, $2); }
;
+full_parm:
+ parm
+ { $$ = build_tree_list (NULL_TREE, $$); }
+ | parm '=' init
+ { $$ = build_tree_list ($3, $$); }
+ ;
+
parm:
named_parm
| type_id
{
tree parm;
tree decl = 0;
+ tree defval;
int is_type;
parm = next;
my_friendly_assert (TREE_CODE (parm) == TREE_LIST, 259);
- is_type = TREE_CODE (TREE_PURPOSE (parm)) == IDENTIFIER_NODE;
+ defval = TREE_PURPOSE (parm);
+ parm = TREE_VALUE (parm);
+ is_type = TREE_PURPOSE (parm) == class_type_node;
if (!is_type)
{
tree tinfo = 0;
- parm = TREE_PURPOSE (parm);
- my_friendly_assert (TREE_CODE (parm) == TREE_LIST, 260);
- parm = TREE_VALUE (parm);
+ my_friendly_assert (TREE_CODE (TREE_PURPOSE (parm)) == TREE_LIST, 260);
/* is a const-param */
- parm = grokdeclarator (TREE_VALUE (next), TREE_PURPOSE (next),
+ parm = grokdeclarator (TREE_VALUE (parm), TREE_PURPOSE (parm),
PARM, 0, NULL_TREE);
/* A template parameter is not modifiable. */
TREE_READONLY (parm) = 1;
else
{
tree t = make_node (TEMPLATE_TYPE_PARM);
- decl = build_decl (TYPE_DECL, TREE_PURPOSE (parm), t);
- TYPE_NAME (t) = decl;
- TREE_VALUE (parm) = t;
+ decl = build_decl (TYPE_DECL, TREE_VALUE (parm), t);
+ TYPE_MAIN_DECL (t) = decl;
+ parm = decl;
+ if (defval)
+ {
+ if (IDENTIFIER_HAS_TYPE_VALUE (defval))
+ defval = IDENTIFIER_TYPE_VALUE (defval);
+ else
+ defval = TREE_TYPE (IDENTIFIER_GLOBAL_VALUE (defval));
+ }
}
pushdecl (decl);
+ parm = build_tree_list (defval, parm);
return chainon (list, parm);
}
tree parms;
{
int nparms = 0;
+ int saw_default = 0;
tree saved_parmlist;
tree parm;
for (parm = parms; parm; parm = TREE_CHAIN (parm))
for (parm = parms, nparms = 0; parm; parm = TREE_CHAIN (parm), nparms++)
{
- tree p = parm;
- if (TREE_CODE (p) == TREE_LIST)
+ tree p = TREE_VALUE (parm);
+ if (TREE_PURPOSE (parm))
+ saw_default = 1;
+ else if (saw_default)
+ {
+ error ("if a default argument is given for one template parameter");
+ error ("default arguments must be given for all subsequent");
+ error ("parameters as well");
+ }
+
+ if (TREE_CODE (p) == TYPE_DECL)
{
- tree t = TREE_VALUE (p);
- TREE_VALUE (p) = NULL_TREE;
- p = TREE_PURPOSE (p);
- my_friendly_assert (TREE_CODE (p) == IDENTIFIER_NODE, 261);
+ tree t = TREE_TYPE (p);
TEMPLATE_TYPE_SET_INFO (t, saved_parmlist, nparms);
}
else
DECL_INITIAL (p) = NULL_TREE;
TEMPLATE_CONST_SET_INFO (tinfo, saved_parmlist, nparms);
}
- TREE_VEC_ELT (saved_parmlist, nparms) = p;
+ TREE_VEC_ELT (saved_parmlist, nparms) = parm;
}
set_current_level_tags_transparency (1);
processing_template_decl++;
tree parms, arglist;
tree in_decl;
{
- int nparms, i, lost = 0;
+ int nparms, nargs, i, lost = 0;
tree vec;
- if (TREE_CODE (arglist) == TREE_VEC)
- nparms = TREE_VEC_LENGTH (arglist);
+ if (arglist == NULL_TREE)
+ nargs = 0;
+ else if (TREE_CODE (arglist) == TREE_VEC)
+ nargs = TREE_VEC_LENGTH (arglist);
else
- nparms = list_length (arglist);
- if (nparms != TREE_VEC_LENGTH (parms))
+ nargs = list_length (arglist);
+
+ nparms = TREE_VEC_LENGTH (parms);
+
+ if (nargs > nparms
+ || (nargs < nparms
+ && TREE_PURPOSE (TREE_VEC_ELT (parms, nargs)) == NULL_TREE))
{
error ("incorrect number of parameters (%d, should be %d)",
- nparms, TREE_VEC_LENGTH (parms));
+ nargs, nparms);
if (in_decl)
cp_error_at ("in template expansion for decl `%D'", in_decl);
return error_mark_node;
}
- if (TREE_CODE (arglist) == TREE_VEC)
+ if (arglist && TREE_CODE (arglist) == TREE_VEC)
vec = copy_node (arglist);
else
{
vec = make_tree_vec (nparms);
for (i = 0; i < nparms; i++)
{
- tree arg = arglist;
- arglist = TREE_CHAIN (arglist);
- if (arg == error_mark_node)
- lost++;
+ tree arg;
+
+ if (arglist)
+ {
+ arg = arglist;
+ arglist = TREE_CHAIN (arglist);
+
+ if (arg == error_mark_node)
+ lost++;
+ else
+ arg = TREE_VALUE (arg);
+ }
else
- arg = TREE_VALUE (arg);
+ arg = TREE_PURPOSE (TREE_VEC_ELT (parms, i));
+
TREE_VEC_ELT (vec, i) = arg;
}
}
for (i = 0; i < nparms; i++)
{
tree arg = TREE_VEC_ELT (vec, i);
- tree parm = TREE_VEC_ELT (parms, i);
+ tree parm = TREE_VALUE (TREE_VEC_ELT (parms, i));
tree val = 0;
int is_type, requires_type;
is_type = TREE_CODE_CLASS (TREE_CODE (arg)) == 't';
- requires_type = TREE_CODE (parm) == IDENTIFIER_NODE;
+ requires_type = TREE_CODE (parm) == TYPE_DECL;
if (is_type != requires_type)
{
if (in_decl)
{
grok_template_type (vec, &TREE_TYPE (parm));
val = digest_init (TREE_TYPE (parm), arg, (tree *) 0);
-
+
if (val == error_mark_node)
;
my_friendly_assert (nparms == TREE_VEC_LENGTH (arglist), 268);
for (i = 0; i < nparms; i++)
{
- tree parm = TREE_VEC_ELT (parms, i), arg = TREE_VEC_ELT (arglist, i);
+ tree parm = TREE_VALUE (TREE_VEC_ELT (parms, i));
+ tree arg = TREE_VEC_ELT (arglist, i);
if (i)
ccat (',');
- if (TREE_CODE (parm) == IDENTIFIER_NODE)
+ if (TREE_CODE (parm) == TYPE_DECL)
{
cat (type_as_string (arg, 0));
continue;
}
parmlist = DECL_TEMPLATE_PARMS (template);
- arglist = coerce_template_parms (parmlist, arglist, in_decl);
+ arglist = coerce_template_parms (parmlist, arglist, template);
if (arglist == error_mark_node)
return error_mark_node;
if (uses_template_parms (arglist))
for (i = 0; i < nparms; i++)
{
int requires_type, is_type;
- tree parm = TREE_VEC_ELT (parmlist, i);
+ tree parm = TREE_VALUE (TREE_VEC_ELT (parmlist, i));
tree arg = TREE_VEC_ELT (arglist, i);
tree decl = 0;
- requires_type = TREE_CODE (parm) == IDENTIFIER_NODE;
+ requires_type = TREE_CODE (parm) == TYPE_DECL;
is_type = TREE_CODE_CLASS (TREE_CODE (arg)) == 't';
if (is_type)
{
}
decl = arg;
my_friendly_assert (TREE_CODE_CLASS (TREE_CODE (decl)) == 't', 273);
- decl = build_decl (TYPE_DECL, parm, decl);
+ decl = build_decl (TYPE_DECL, DECL_NAME (parm), decl);
}
else
{
case 1:
/* Failure. */
failure:
- cp_error ("type unification error instantiating %T::%D",
- classname, tdecl);
- cp_error_at ("for template declaration `%D'", tdecl);
+ cp_error_at ("type unification error instantiating `%D'", tdecl);
+ cp_error ("while instantiating members of `%T'", classname);
continue /* loop of members */;
default:
|| TREE_CODE (t) == UNINSTANTIATED_P_TYPE, 286);
decl = build_decl (TYPE_DECL, template, t);
+ SET_DECL_ARTIFICIAL (decl);
#if 0 /* fix this later */
/* We don't want to call here if the work has already been done. */
return 1;
}
idx = TEMPLATE_TYPE_IDX (parm);
+ /* Template type parameters cannot contain cv-quals; i.e.
+ template <class T> void f (T& a, T& b) will not generate
+ void f (const int& a, const int& b). */
+ if (TYPE_READONLY (arg) > TYPE_READONLY (parm)
+ || TYPE_VOLATILE (arg) > TYPE_VOLATILE (parm))
+ return 1;
+ arg = TYPE_MAIN_VARIANT (arg);
/* Simple cases: Value already set, does match or doesn't. */
if (targs[idx] == arg)
return 0;
else if (targs[idx])
- {
- if (TYPE_MAIN_VARIANT (targs[idx]) == TYPE_MAIN_VARIANT (arg))
- /* allow different parms to have different cv-qualifiers */;
- else
- return 1;
- }
- /* Check for mixed types and values. */
- if (TREE_CODE (TREE_VEC_ELT (tparms, idx)) != IDENTIFIER_NODE)
return 1;
- /* Allow trivial conversions. */
- if (TYPE_READONLY (parm) < TYPE_READONLY (arg)
- || TYPE_VOLATILE (parm) < TYPE_VOLATILE (arg))
+ /* Check for mixed types and values. */
+ if (TREE_CODE (TREE_VALUE (TREE_VEC_ELT (tparms, idx))) != TYPE_DECL)
return 1;
targs[idx] = arg;
return 0;
tree t = TREE_TYPE (name);
int extern_p;
+ /* With -fexternal-templates, explicit instantiations are treated the same
+ as implicit ones. */
if (flag_external_templates)
return;
- if (CLASSTYPE_EXPLICIT_INSTANTIATION (t) && ! CLASSTYPE_INTERFACE_ONLY (t))
- return;
-
if (TYPE_SIZE (t) == NULL_TREE)
{
cp_error ("explicit instantiation of `%#T' before definition of template",
extern_p = 0;
}
+ /* We've already instantiated this. */
+ if (CLASSTYPE_EXPLICIT_INSTANTIATION (t) && ! CLASSTYPE_INTERFACE_ONLY (t))
+ {
+ if (! extern_p)
+ cp_pedwarn ("multiple explicit instantiation of `%#T'", t);
+ return;
+ }
+
SET_CLASSTYPE_EXPLICIT_INSTANTIATION (t);
CLASSTYPE_VTABLE_NEEDS_WRITING (t) = ! extern_p;
SET_CLASSTYPE_INTERFACE_KNOWN (t);
/* this should really be done by instantiate_member_templates */
{
- tree method = TREE_VEC_ELT (CLASSTYPE_METHOD_VEC (t), 0);
- for (; method; method = TREE_CHAIN (method))
+ tree tmp = TREE_VEC_ELT (CLASSTYPE_METHOD_VEC (t), 0);
+ for (; tmp; tmp = TREE_CHAIN (tmp))
{
- SET_DECL_EXPLICIT_INSTANTIATION (method);
- TREE_PUBLIC (method) = 1;
- DECL_EXTERNAL (method)
- = (extern_p || (DECL_INLINE (method) && ! flag_implement_inlines));
+ SET_DECL_EXPLICIT_INSTANTIATION (tmp);
+ TREE_PUBLIC (tmp) = 1;
+ DECL_EXTERNAL (tmp)
+ = (extern_p || (DECL_INLINE (tmp) && ! flag_implement_inlines));
}
- }
- /* and data member templates, too */
+#if 0
+ for (tmp = TYPE_FIELDS (t); tmp; tmp = TREE_CHAIN (tmp))
+ {
+ if (TREE_CODE (tmp) == VAR_DECL)
+ /* eventually do something */;
+ }
+#endif
+
+ for (tmp = CLASSTYPE_TAGS (t); tmp; tmp = TREE_CHAIN (tmp))
+ do_type_instantiation (TREE_VALUE (tmp), storage);
+ }
}
tree
if (IDENTIFIER_VIRTUAL_P (declarator) == 0)
return NULL_TREE;
+ baselink = get_virtuals_named_this (binfo);
+ if (baselink == NULL_TREE)
+ return NULL_TREE;
+
drettype = TREE_TYPE (TREE_TYPE (fndecl));
dtypes = TYPE_ARG_TYPES (TREE_TYPE (fndecl));
if (DECL_STATIC_FUNCTION_P (fndecl))
else
instptr_type = TREE_TYPE (TREE_VALUE (dtypes));
- for (baselink = get_virtuals_named_this (binfo);
- baselink; baselink = next_baselink (baselink))
+ for (; baselink; baselink = next_baselink (baselink))
{
for (tmp = TREE_VALUE (baselink); tmp; tmp = DECL_CHAIN (tmp))
{
&& ! comptypes (TREE_TYPE (TREE_TYPE (tmp)), drettype, 1))
{
cp_error ("conflicting return type specified for virtual function `%#D'", fndecl);
- cp_error ("overriding definition as `%#D'", tmp);
+ cp_error_at ("overriding definition as `%#D'", tmp);
SET_IDENTIFIER_ERROR_LOCUS (name, basetype);
}
break;
/* If we want debug info for a type TYPE, make sure all its base types
are also marked as being potentially interesting. This avoids
the problem of not writing any debug info for intermediate basetypes
- that have abstract virtual functions. */
+ that have abstract virtual functions. Also mark member types. */
void
note_debug_info_needed (type)
tree type;
{
+ tree field;
dfs_walk (TYPE_BINFO (type), dfs_debug_mark, dfs_debug_unmarkedp);
+ for (field = TYPE_FIELDS (type); field; field = TREE_CHAIN (field))
+ {
+ tree ttype;
+ if (TREE_CODE (field) == FIELD_DECL
+ && IS_AGGR_TYPE (ttype = target_type (TREE_TYPE (field)))
+ && dfs_debug_unmarkedp (TYPE_BINFO (ttype)))
+ note_debug_info_needed (ttype);
+ }
}
\f
/* Subroutines of push_class_decls (). */
lvalue_p (ref)
tree ref;
{
- register enum tree_code code = TREE_CODE (ref);
+ if (! language_lvalue_valid (ref))
+ return 0;
+
+ if (TREE_CODE (TREE_TYPE (ref)) == REFERENCE_TYPE)
+ return 1;
- if (language_lvalue_valid (ref))
+ if (ref == current_class_decl && flag_this_is_variable <= 0)
+ return 0;
+
+ switch (TREE_CODE (ref))
{
- if (TREE_CODE (TREE_TYPE (ref)) == REFERENCE_TYPE)
+ /* preincrements and predecrements are valid lvals, provided
+ what they refer to are valid lvals. */
+ case PREINCREMENT_EXPR:
+ case PREDECREMENT_EXPR:
+ case COMPONENT_REF:
+ case SAVE_EXPR:
+ return lvalue_p (TREE_OPERAND (ref, 0));
+
+ case STRING_CST:
+ return 1;
+
+ case VAR_DECL:
+ if (TREE_READONLY (ref) && ! TREE_STATIC (ref)
+ && DECL_LANG_SPECIFIC (ref)
+ && DECL_IN_AGGR_P (ref))
+ return 0;
+ case INDIRECT_REF:
+ case ARRAY_REF:
+ case PARM_DECL:
+ case RESULT_DECL:
+ case ERROR_MARK:
+ if (TREE_CODE (TREE_TYPE (ref)) != FUNCTION_TYPE
+ && TREE_CODE (TREE_TYPE (ref)) != METHOD_TYPE)
return 1;
-
- switch (code)
- {
- /* preincrements and predecrements are valid lvals, provided
- what they refer to are valid lvals. */
- case PREINCREMENT_EXPR:
- case PREDECREMENT_EXPR:
- case COMPONENT_REF:
- case SAVE_EXPR:
- return lvalue_p (TREE_OPERAND (ref, 0));
-
- case STRING_CST:
- return 1;
-
- case VAR_DECL:
- if (TREE_READONLY (ref) && ! TREE_STATIC (ref)
- && DECL_LANG_SPECIFIC (ref)
- && DECL_IN_AGGR_P (ref))
- return 0;
- case INDIRECT_REF:
- case ARRAY_REF:
- case PARM_DECL:
- case RESULT_DECL:
- case ERROR_MARK:
- if (TREE_CODE (TREE_TYPE (ref)) != FUNCTION_TYPE
- && TREE_CODE (TREE_TYPE (ref)) != METHOD_TYPE)
- return 1;
- break;
+ break;
- case TARGET_EXPR:
- case WITH_CLEANUP_EXPR:
- return 1;
-
- /* A currently unresolved scope ref. */
- case SCOPE_REF:
- my_friendly_abort (103);
- case OFFSET_REF:
- if (TREE_CODE (TREE_OPERAND (ref, 1)) == FUNCTION_DECL)
- return 1;
- return lvalue_p (TREE_OPERAND (ref, 0))
- && lvalue_p (TREE_OPERAND (ref, 1));
- break;
+ case WITH_CLEANUP_EXPR:
+ return lvalue_p (TREE_OPERAND (ref, 0));
+
+ case TARGET_EXPR:
+ return 1;
- case COND_EXPR:
- return (lvalue_p (TREE_OPERAND (ref, 1))
- && lvalue_p (TREE_OPERAND (ref, 2)));
+ case CALL_EXPR:
+ if (TREE_ADDRESSABLE (TREE_TYPE (ref)))
+ return 1;
+ break;
- case MODIFY_EXPR:
- return 1;
+ /* A currently unresolved scope ref. */
+ case SCOPE_REF:
+ my_friendly_abort (103);
+ case OFFSET_REF:
+ if (TREE_CODE (TREE_OPERAND (ref, 1)) == FUNCTION_DECL)
+ return 1;
+ return lvalue_p (TREE_OPERAND (ref, 0))
+ && lvalue_p (TREE_OPERAND (ref, 1));
+ break;
- case COMPOUND_EXPR:
- return lvalue_p (TREE_OPERAND (ref, 1));
- }
+ case COND_EXPR:
+ return (lvalue_p (TREE_OPERAND (ref, 1))
+ && lvalue_p (TREE_OPERAND (ref, 2)));
+
+ case MODIFY_EXPR:
+ return 1;
+
+ case COMPOUND_EXPR:
+ return lvalue_p (TREE_OPERAND (ref, 1));
}
+
return 0;
}
return rval;
}
-/* Return the offset (as an INTEGER_CST) for ELEM in LIST.
- INITIAL_OFFSET is the value to add to the offset that ELEM's
- binfo entry in LIST provides.
-
- Returns NULL if ELEM does not have an binfo value in LIST. */
-
-tree
-virtual_offset (elem, list, initial_offset)
- tree elem;
- tree list;
- tree initial_offset;
-{
- tree vb, offset;
- tree rval, nval;
-
- for (vb = list; vb; vb = TREE_CHAIN (vb))
- if (elem == BINFO_TYPE (vb))
- return size_binop (PLUS_EXPR, initial_offset, BINFO_OFFSET (vb));
- rval = 0;
- for (vb = list; vb; vb = TREE_CHAIN (vb))
- {
- tree binfos = BINFO_BASETYPES (vb);
- int i;
-
- if (binfos == NULL_TREE)
- continue;
-
- for (i = TREE_VEC_LENGTH (binfos)-1; i >= 0; i--)
- {
- nval = binfo_value (elem, BINFO_TYPE (TREE_VEC_ELT (binfos, i)));
- if (nval)
- {
- if (rval && BINFO_OFFSET (nval) != BINFO_OFFSET (rval))
- my_friendly_abort (105);
- offset = BINFO_OFFSET (vb);
- rval = nval;
- }
- }
- }
- if (rval == NULL_TREE)
- return rval;
- return size_binop (PLUS_EXPR, offset, BINFO_OFFSET (rval));
-}
-
void
debug_binfo (elem)
tree elem;
build_object_ref (datum, basetype, field)
tree datum, basetype, field;
{
+ tree dtype;
if (datum == error_mark_node)
return error_mark_node;
+
+ dtype = TREE_TYPE (datum);
+ if (TREE_CODE (dtype) == REFERENCE_TYPE)
+ dtype = TREE_TYPE (dtype);
+ if (! IS_AGGR_TYPE_CODE (TREE_CODE (dtype)))
+ {
+ cp_error ("request for member `%T::%D' in expression of non-aggregate type `%T'",
+ basetype, field, dtype);
+ return error_mark_node;
+ }
else if (IS_SIGNATURE (IDENTIFIER_TYPE_VALUE (basetype)))
{
warning ("signature name in scope resolution ignored");
case GE_EXPR:
case LT_EXPR:
case GT_EXPR:
+ result_type = bool_type_node;
if ((code0 == INTEGER_TYPE || code0 == REAL_TYPE)
&& (code1 == INTEGER_TYPE || code1 == REAL_TYPE))
short_compare = 1;
warning ("comparison between pointer and integer");
op0 = convert (TREE_TYPE (op1), op0);
}
- result_type = bool_type_node;
+ else
+ result_type = 0;
converted = 1;
break;
}
}
else
/* This conversion is harmless. */
- rval = convert (argtype, rval);
+ rval = convert_force (argtype, rval);
if (! integer_zerop (DECL_FIELD_BITPOS (field)))
{
value = TREE_VALUE (value);
if (TREE_CODE (type) == VOID_TYPE)
- value = build1 (NOP_EXPR, type, value);
+ value = build1 (CONVERT_EXPR, type, value);
else if (TREE_TYPE (value) == NULL_TREE
|| type_unknown_p (value))
{
add_quals = 1;
left_const &= TYPE_READONLY (ttl);
- if (TREE_CODE (ttl) != POINTER_TYPE)
+ if (TREE_CODE (ttl) != POINTER_TYPE
+ || TREE_CODE (ttr) != POINTER_TYPE)
break;
}
unsigned_parity = TREE_UNSIGNED (ttl) - TREE_UNSIGNED (ttr);
&& TREE_CODE (TREE_OPERAND (retval, 0)) == TARGET_EXPR)
retval = TREE_OPERAND (retval, 0);
expand_aggr_init (result, retval, 0);
+ expand_cleanups_to (NULL_TREE);
DECL_INITIAL (result) = NULL_TREE;
retval = 0;
}
&& any_pending_cleanups (1))
{
retval = get_temp_regvar (valtype, retval);
+ expand_cleanups_to (NULL_TREE);
use_temp = obey_regdecls;
result = 0;
}
{
/* Everything's great--RETVAL is in RESULT. */
if (original_result_rtx)
- store_expr (result, original_result_rtx, 0);
+ {
+ store_expr (result, original_result_rtx, 0);
+ expand_cleanups_to (NULL_TREE);
+ }
else if (retval && retval != result)
{
/* Clear this out so the later call to decl_function_context
RESULT from cleanups. */
retval = build (INIT_EXPR, TREE_TYPE (result), result, retval);
TREE_SIDE_EFFECTS (retval) = 1;
+ retval = build1 (CLEANUP_POINT_EXPR, TREE_TYPE (result), retval);
expand_return (retval);
}
else
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: 360. Free: */
+/* First used: 0 (reserved), Last used: 360. Free: 261. */
static int abortcount = 0;