aboutsummaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
Diffstat (limited to 'gcc')
-rw-r--r--gcc/cp/ChangeLog126
-rw-r--r--gcc/cp/class.c1
-rw-r--r--gcc/cp/cp-tree.h7
-rw-r--r--gcc/cp/cvt.c45
-rw-r--r--gcc/cp/decl.c66
-rw-r--r--gcc/cp/decl2.c38
-rw-r--r--gcc/cp/gxxint.texi60
-rw-r--r--gcc/cp/lex.c10
-rw-r--r--gcc/cp/parse.y12
-rw-r--r--gcc/cp/pt.c86
-rw-r--r--gcc/cp/search.c8
-rw-r--r--gcc/cp/tree.c16
-rw-r--r--gcc/cp/typeck.c25
-rw-r--r--gcc/cp/typeck2.c4
-rw-r--r--gcc/cp/xref.c12
15 files changed, 397 insertions, 119 deletions
diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog
index 385d239..cddc168 100644
--- a/gcc/cp/ChangeLog
+++ b/gcc/cp/ChangeLog
@@ -1,7 +1,133 @@
+Tue Jun 14 12:23:38 1994 Jason Merrill (jason@deneb.cygnus.com)
+
+ * decl.c (grok_op_properties): Const objects can be passed by value.
+
+Mon Jun 13 03:10:59 1994 Jason Merrill (jason@deneb.cygnus.com)
+
+ * decl2.c (import_export_vtable): Force implicit instantiations to
+ be interface_only when -fno-implicit-templates.
+
+ * decl.c (duplicate_decls): Redeclaring a class template name is an
+ error.
+
+ * pt.c (end_template_decl): Call GNU_xref_decl for class templates.
+ * xref.c (GNU_xref_decl): Support templates.
+
+Sat Jun 11 17:09:05 1994 Jason Merrill (jason@deneb.cygnus.com)
+
+ * decl.c (grok_op_properties): Split out checking for whether this
+ function should suppress the default assignment operator.
+ * decl2.c (grok_function_init): Ditto.
+ (copy_assignment_arg_p): New function do do just that.
+ Now considers virtual assignment operators that take a base as an
+ argument to count as copy assignment operators.
+
+ * search.c (dfs_debug_mark): Lose checks for DWARF_DEBUG and
+ TREE_ASM_WRITTEN, as they are redundant.
+
+ * pt.c (end_template_decl): Don't try to set DECL_CLASS_CONTEXT on a
+ decl that has no LANG_SPECIFIC part.
+ (do_type_instantiation): Force the debugging information for this
+ type to be emitted.
+
+ * decl.c (start_decl): Clear up uses of various types of templates
+ (say sorry for static data members, rather than "invalid template").
+ (expand_static_init): Fix initialization of static data members of
+ template classes.
+
+Fri Jun 10 00:41:19 1994 Jason Merrill (jason@deneb.cygnus.com)
+
+ * decl.c (grokdeclarator): Set DECL_CONTEXT on static data members.
+
+ * g++.c (main): Use -xc++-cpp-output for .i files.
+
+ * pt.c (tsubst): Give meaningful error about declaring template for
+ a copy constructor which was not declared in the class template.
+ (do_type_instantiation): Explicit instantiation before the class
+ template is an error.
+ (instantiate_template): Don't die if tsubst returns error_mark_node.
+
+Thu Jun 9 19:04:59 1994 Jason Merrill (jason@deneb.cygnus.com)
+
+ Don't synthesize the copy assignment operator if the one in a base
+ class is pure virtual.
+ * cp-tree.h (TYPE_HAS_ABSTRACT_ASSIGN_REF): New macro to indicate
+ whether the type has a pure virtual copy assignment operator.
+ * class.c (finish_base_struct): Don't generate the copy assignment
+ operator if a base class has a pure virtual one.
+ * decl.c (grok_op_properties): Add disabled code to set
+ TYPE_HAS_ABSTRACT_ASSIGN_REF with comment pointing to where it is
+ actually set.
+ * decl2.c (grok_function_init): Set TYPE_HAS_ABSTRACT_ASSIGN_REF.
+
+ * decl2.c (import_export_vtable): Always treat template
+ instantiations as if write_virtuals >= 2, and treat implicit
+ instantiations as external if -fno-implicit-templates.
+ (finish_file): Output all pending inlines if
+ flag_keep_inline_functions.
+
+Wed Jun 8 20:48:02 1994 Mike Stump (mrs@cygnus.com)
+
+ * tree.c (layout_vbasetypes): Align virtual base classes inside
+ complete objects, so that we don't core dump on machines such as
+ SPARCs when we access members that require larger than normal
+ alignments, such as a double. Also, we bump up the total alignment
+ on the complete type, as necessary.
+
+Wed Jun 8 16:18:14 1994 Jason Merrill (jason@deneb.cygnus.com)
+
+ * gxxint.texi (Free Store): New section with code for examining
+ cookie.
+ (Limitations of g++): Remove operator delete entry, since it is no
+ longer accurate. Fix access control entry.
+
+ * typeck.c (build_unary_op): Pedwarn about taking the address of or
+ incrementing a cast to non-reference type.
+ (build_modify_expr): Use convert instead of convert_force again.
+
+ * search.c (get_base_distance): Use IS_AGGR_TYPE_CODE to check for
+ class type, not == RECORD_TYPE.
+
+ * decl.c (grokdeclarator): Cope with grokfndecl returning NULL_TREE.
+
+ * typeck2.c (report_case_error): #if 0 out.
+ * lex.c (real_yylex): Lose RANGE.
+ * parse.y: Ditto.
+
+Tue Jun 7 18:17:35 1994 Jason Merrill (jason@deneb.cygnus.com)
+
+ * parse.y (simple_stmt, case ranges): Use ELLIPSIS instead of RANGE.
+
+Mon Jun 6 19:39:57 1994 Jason Merrill (jason@deneb.cygnus.com)
+
+ * typeck.c (build_c_cast): Don't shortcut conversions to the same
+ type. Don't replace consts with their values here, since that's now
+ done in cp_convert.
+
+ * cvt.c (cp_convert): When converting to bool, take
+ integer_zero_node to false_node and all other INTEGER_CSTs to
+ true_node.
+ (build_type_conversion): Don't complain about multiple conversions
+ to float if we're not really converting.
+
Fri Jun 3 02:10:56 1994 Jason Merrill (jason@deneb.cygnus.com)
+ Implement 'extern template class A<int>;' syntax for suppressing
+ specific implicit instantiations.
+ * cp-tree.h: Update prototypes for do_*_instantiation.
+ * pt.c (do_pending_expansions): Don't compile 'extern' explicit
+ instantiations.
+ (do_function_instantiation): Set DECL_EXTERNAL on 'extern' explicit
+ instantiations.
+ (do_type_instantiation): Ditto.
+ * parse.y (explicit_instantiation): Support 'extern template class
+ A<int>;' syntax.
+ * decl.c (start_function): Don't modify the settings of TREE_PUBLIC
+ and DECL_EXTERNAL on explicit instantiations.
+
* cvt.c (cp_convert): Replace constants with their values before
converting.
+ (cp_convert): Consistently use 'e' instead of 'expr'.
Thu Jun 2 03:53:30 1994 Jason Merrill (jason@deneb.cygnus.com)
diff --git a/gcc/cp/class.c b/gcc/cp/class.c
index 638fedf..1d27681 100644
--- a/gcc/cp/class.c
+++ b/gcc/cp/class.c
@@ -1390,6 +1390,7 @@ finish_base_struct (t, b, t_binfo)
&& !TYPE_HAS_CONST_ASSIGN_REF (basetype))
b->no_const_asn_ref = 1;
if (! TYPE_HAS_ASSIGN_REF (basetype)
+ || TYPE_HAS_ABSTRACT_ASSIGN_REF (basetype)
|| (TYPE_HAS_NONPUBLIC_ASSIGN_REF (basetype) == 2
&& ! is_friend_type (t, basetype)))
b->cant_synth_asn_ref = 1;
diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h
index 7ae511f..9ba72b0 100644
--- a/gcc/cp/cp-tree.h
+++ b/gcc/cp/cp-tree.h
@@ -438,11 +438,12 @@ struct lang_type
unsigned has_complex_init_ref : 1;
unsigned has_complex_assign_ref : 1;
unsigned vec_delete_takes_size : 1;
+ unsigned has_abstract_assign_ref : 1;
/* The MIPS compiler gets it wrong if this struct also
does not fill out to a multiple of 4 bytes. Add a
member `dummy' with new bits if you go over the edge. */
- unsigned dummy : 20;
+ unsigned dummy : 19;
unsigned n_vancestors : 16;
} type_flags;
@@ -1182,6 +1183,7 @@ struct lang_decl
/* Nonzero if there is a user-defined X::op=(x&) for this class. */
#define TYPE_HAS_REAL_ASSIGN_REF(NODE) (TYPE_LANG_SPECIFIC(NODE)->type_flags.has_real_assign_ref)
#define TYPE_HAS_COMPLEX_ASSIGN_REF(NODE) (TYPE_LANG_SPECIFIC(NODE)->type_flags.has_complex_assign_ref)
+#define TYPE_HAS_ABSTRACT_ASSIGN_REF(NODE) (TYPE_LANG_SPECIFIC(NODE)->type_flags.has_abstract_assign_ref)
#define TYPE_HAS_COMPLEX_INIT_REF(NODE) (TYPE_LANG_SPECIFIC(NODE)->type_flags.has_complex_init_ref)
/* Nonzero for _TYPE node means that destroying an object of this type
@@ -2160,7 +2162,8 @@ extern int type_unification PROTO((tree, tree *, tree, tree, int *, int));
extern int do_pending_expansions PROTO((void));
extern void do_pending_templates PROTO((void));
struct tinst_level *tinst_for_decl PROTO((void));
-extern void do_function_instantiation PROTO((tree, tree));
+extern void do_function_instantiation PROTO((tree, tree, tree));
+extern void do_type_instantiation PROTO((tree, tree));
extern tree create_nested_upt PROTO((tree, tree));
/* in search.c */
diff --git a/gcc/cp/cvt.c b/gcc/cp/cvt.c
index fc8d261..3750221 100644
--- a/gcc/cp/cvt.c
+++ b/gcc/cp/cvt.c
@@ -1194,15 +1194,15 @@ cp_convert (type, expr, convtype, flags)
register tree e = expr;
register enum tree_code code = TREE_CODE (type);
- if (type == TREE_TYPE (expr)
- || TREE_CODE (expr) == ERROR_MARK)
- return expr;
- if (TREE_CODE (TREE_TYPE (expr)) == ERROR_MARK)
+ if (type == TREE_TYPE (e)
+ || TREE_CODE (e) == ERROR_MARK)
+ return e;
+ if (TREE_CODE (TREE_TYPE (e)) == ERROR_MARK)
return error_mark_node;
/* Trivial conversion: cv-qualifiers do not matter on rvalues. */
- if (TYPE_MAIN_VARIANT (type) == TYPE_MAIN_VARIANT (TREE_TYPE (expr)))
- return fold (build1 (NOP_EXPR, type, expr));
+ if (TYPE_MAIN_VARIANT (type) == TYPE_MAIN_VARIANT (TREE_TYPE (e)))
+ return fold (build1 (NOP_EXPR, type, e));
if (code == VOID_TYPE && (convtype & CONV_STATIC))
return build1 (CONVERT_EXPR, type, e);
@@ -1210,8 +1210,8 @@ cp_convert (type, expr, convtype, flags)
#if 0
/* This is incorrect. A truncation can't be stripped this way.
Extensions will be stripped by the use of get_unwidened. */
- if (TREE_CODE (expr) == NOP_EXPR)
- return convert (type, TREE_OPERAND (expr, 0));
+ if (TREE_CODE (e) == NOP_EXPR)
+ return convert (type, TREE_OPERAND (e, 0));
#endif
/* Just convert to the type of the member. */
@@ -1231,7 +1231,7 @@ cp_convert (type, expr, convtype, flags)
if (INTEGRAL_CODE_P (code))
{
- tree intype = TREE_TYPE (expr);
+ tree intype = TREE_TYPE (e);
enum tree_code form = TREE_CODE (intype);
/* enum = enum, enum = int, enum = float are all errors. */
if (flag_int_enum_equivalence == 0
@@ -1249,7 +1249,7 @@ cp_convert (type, expr, convtype, flags)
else if (IS_AGGR_TYPE (intype))
{
tree rval;
- rval = build_type_conversion (CONVERT_EXPR, type, expr, 1);
+ rval = build_type_conversion (CONVERT_EXPR, type, e, 1);
if (rval) return rval;
if (code == BOOLEAN_TYPE)
cp_error ("`%#T' used where a `bool' was expected", intype);
@@ -1265,6 +1265,13 @@ cp_convert (type, expr, convtype, flags)
e = newe;
if (TREE_TYPE (e) == bool_type_node)
return e;
+ else if (TREE_CODE (e) == INTEGER_CST)
+ {
+ if (e == integer_zero_node)
+ e = false_node;
+ else
+ e = true_node;
+ }
else
return build1 (NOP_EXPR, bool_type_node, e);
}
@@ -1413,13 +1420,13 @@ cp_convert (type, expr, convtype, flags)
}
}
- /* If TYPE or TREE_TYPE (EXPR) is not on the permanent_obstack,
+ /* If TYPE or TREE_TYPE (E) is not on the permanent_obstack,
then the it won't be hashed and hence compare as not equal,
even when it is. */
if (code == ARRAY_TYPE
- && TREE_TYPE (TREE_TYPE (expr)) == TREE_TYPE (type)
- && index_type_equal (TYPE_DOMAIN (TREE_TYPE (expr)), TYPE_DOMAIN (type)))
- return expr;
+ && TREE_TYPE (TREE_TYPE (e)) == TREE_TYPE (type)
+ && index_type_equal (TYPE_DOMAIN (TREE_TYPE (e)), TYPE_DOMAIN (type)))
+ return e;
cp_error ("conversion from `%T' to non-scalar type `%T' requested",
TREE_TYPE (expr), type);
@@ -1789,9 +1796,13 @@ build_type_conversion (code, xtype, expr, for_sure)
operator int(). */
if (TYPE_HAS_INT_CONVERSION (basetype))
{
- error ("two possible conversions for type `%s'",
- TYPE_NAME_STRING (type));
- return error_mark_node;
+ if (for_sure)
+ {
+ cp_error ("two possible conversions for type `%T'", type);
+ return error_mark_node;
+ }
+ else
+ return NULL_TREE;
}
typename = DECL_NAME (CLASSTYPE_CONVERSION (basetype, real_conv));
diff --git a/gcc/cp/decl.c b/gcc/cp/decl.c
index 10e9d0e..4bbfec9 100644
--- a/gcc/cp/decl.c
+++ b/gcc/cp/decl.c
@@ -2175,7 +2175,19 @@ duplicate_decls (newdecl, olddecl)
else if (!types_match)
{
if (TREE_CODE (newdecl) == TEMPLATE_DECL)
- return 0;
+ {
+ /* The name of a class template may not be declared to refer to
+ any other template, class, function, object, namespace, value,
+ or type in the same scope. */
+ if (DECL_TEMPLATE_IS_CLASS (olddecl)
+ || DECL_TEMPLATE_IS_CLASS (newdecl))
+ {
+ cp_error ("declaration of template `%#D'", newdecl);
+ cp_error_at ("conflicts with previous declaration `%#D'",
+ olddecl);
+ }
+ return 0;
+ }
if (TREE_CODE (newdecl) == FUNCTION_DECL)
{
if (DECL_LANGUAGE (newdecl) == lang_c
@@ -5408,8 +5420,10 @@ start_decl (declarator, declspecs, initialized, raises)
return NULL_TREE;
}
- if (/* TREE_CODE (result) == VAR_DECL */ 1)
- {
+ if (TREE_CODE (result) == FUNCTION_DECL)
+ return tem;
+ else if (TREE_CODE (result) == VAR_DECL)
+ {
#if 0
tree tmpl = UPT_TEMPLATE (type);
@@ -5420,15 +5434,24 @@ start_decl (declarator, declspecs, initialized, raises)
DECL_TEMPLATE_MEMBERS (tmpl)
= perm_tree_cons (DECL_NAME (tem), tem,
DECL_TEMPLATE_MEMBERS (tmpl));
-#endif
return tem;
+#else
+ sorry ("static data member templates");
+ return NULL_TREE;
+#endif
}
- my_friendly_abort (13);
+ else
+ my_friendly_abort (13);
}
else if (TREE_CODE (result) == FUNCTION_DECL)
/*tem = push_overloaded_decl (tem, 0)*/;
- else if (TREE_CODE (result) == VAR_DECL
- || TREE_CODE (result) == TYPE_DECL)
+ else if (TREE_CODE (result) == VAR_DECL)
+ {
+ cp_error ("data template `%#D' must be member of a class template",
+ result);
+ return NULL_TREE;
+ }
+ else if (TREE_CODE (result) == TYPE_DECL)
{
cp_error ("invalid template `%#D'", result);
return NULL_TREE;
@@ -6450,7 +6473,8 @@ expand_static_init (decl, init)
if (TREE_PURPOSE (oldstatic) && init != NULL_TREE)
cp_error ("multiple initializations given for `%D'", decl);
}
- else if (current_binding_level != global_binding_level)
+ else if (current_binding_level != global_binding_level
+ && current_binding_level->pseudo_global == 0)
{
/* Emit code to perform this initialization but once. */
tree temp;
@@ -8859,6 +8883,9 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, raises)
decl = grokfndecl (ctype, type, declarator,
virtualp, flags, quals,
raises, friendp ? -1 : 0, publicp);
+ if (decl == NULL_TREE)
+ return NULL_TREE;
+
DECL_INLINE (decl) = inlinep;
}
else if (TREE_CODE (type) == METHOD_TYPE)
@@ -8868,6 +8895,9 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, raises)
decl = grokfndecl (ctype, type, declarator,
virtualp, flags, quals,
raises, friendp ? -1 : 0, 1);
+ if (decl == NULL_TREE)
+ return NULL_TREE;
+
DECL_INLINE (decl) = inlinep;
}
else if (TREE_CODE (type) == RECORD_TYPE
@@ -9056,6 +9086,8 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, raises)
raises,
processing_template_decl ? 0 : friendp ? 2 : 1,
publicp);
+ if (decl == NULL_TREE)
+ return NULL_TREE;
if (ctype == NULL_TREE && DECL_LANGUAGE (decl) != lang_c)
DECL_ASSEMBLER_NAME (decl) = declarator;
@@ -9126,6 +9158,7 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, raises)
if (ctype)
{
+ DECL_CONTEXT (decl) = ctype;
if (staticp == 1)
{
cp_error ("static member `%D' re-declared as static",
@@ -9725,14 +9758,17 @@ grok_op_properties (decl, virtualp, friendp)
}
parmtype = TREE_VALUE (TREE_CHAIN (argtypes));
- if (TREE_CODE (parmtype) == REFERENCE_TYPE
- && (TYPE_MAIN_VARIANT (TREE_TYPE (parmtype))
- == current_class_type)
+ if (copy_assignment_arg_p (parmtype, virtualp)
&& ! friendp)
{
TYPE_HAS_ASSIGN_REF (current_class_type) = 1;
- if (TYPE_READONLY (TREE_TYPE (parmtype)))
+ if (TREE_CODE (parmtype) != REFERENCE_TYPE
+ || TYPE_READONLY (TREE_TYPE (parmtype)))
TYPE_HAS_CONST_ASSIGN_REF (current_class_type) = 1;
+#if 0 /* Too soon; done in grok_function_init */
+ if (DECL_ABSTRACT_VIRTUAL_P (decl))
+ TYPE_HAS_ABSTRACT_ASSIGN_REF (current_class_type) = 1;
+#endif
}
}
else if (name == ansi_opname[(int) COND_EXPR])
@@ -10748,11 +10784,7 @@ start_function (declspecs, declarator, raises, pre_parsed_p)
|| (DECL_INLINE (decl1) && ! flag_implement_inlines));
}
else if (DECL_EXPLICIT_INSTANTIATION (decl1))
- {
- TREE_PUBLIC (decl1) = 1;
- DECL_EXTERNAL (decl1) = (DECL_INLINE (decl1)
- && ! flag_implement_inlines);
- }
+ /* PUBLIC and EXTERNAL set by do_*_instantiation */;
else
{
/* This is a definition, not a reference.
diff --git a/gcc/cp/decl2.c b/gcc/cp/decl2.c
index fa05063..964615e 100644
--- a/gcc/cp/decl2.c
+++ b/gcc/cp/decl2.c
@@ -1667,6 +1667,21 @@ grokoptypename (declspecs, declarator)
*/
+int
+copy_assignment_arg_p (parmtype, virtualp)
+ tree parmtype;
+ int virtualp;
+{
+ if (TREE_CODE (parmtype) == REFERENCE_TYPE)
+ parmtype = TREE_TYPE (parmtype);
+
+ if ((TYPE_MAIN_VARIANT (parmtype) == current_class_type)
+ || (virtualp && DERIVED_FROM_P (parmtype, current_class_type)))
+ return 1;
+
+ return 0;
+}
+
static void
grok_function_init (decl, init)
tree decl;
@@ -1696,6 +1711,14 @@ grok_function_init (decl, init)
}
#endif
DECL_ABSTRACT_VIRTUAL_P (decl) = 1;
+ if (DECL_NAME (decl) == ansi_opname [(int) MODIFY_EXPR])
+ {
+ tree parmtype
+ = TREE_VALUE (TREE_CHAIN (TYPE_ARG_TYPES (TREE_TYPE (decl))));
+
+ if (copy_assignment_arg_p (parmtype, 1))
+ TYPE_HAS_ABSTRACT_ASSIGN_REF (current_class_type) = 1;
+ }
}
else if (TREE_CODE (init) == OFFSET_REF
&& TREE_OPERAND (init, 0) == NULL_TREE
@@ -2311,8 +2334,18 @@ static void
import_export_vtable (decl, type)
tree decl, type;
{
- if (write_virtuals >= 2)
+ if (write_virtuals >= 2
+ || CLASSTYPE_TEMPLATE_INSTANTIATION (type))
{
+ if (CLASSTYPE_IMPLICIT_INSTANTIATION (type)
+ && ! flag_implicit_templates
+ && CLASSTYPE_INTERFACE_UNKNOWN (type))
+ {
+ SET_CLASSTYPE_INTERFACE_KNOWN (type);
+ CLASSTYPE_INTERFACE_ONLY (type) = 1;
+ CLASSTYPE_VTABLE_NEEDS_WRITING (type) = 0;
+ }
+
if (CLASSTYPE_INTERFACE_KNOWN (type))
{
TREE_PUBLIC (decl) = 1;
@@ -2745,7 +2778,8 @@ finish_file ()
|| (DECL_INLINE (decl) && ! flag_implement_inlines));
}
}
- if (TREE_PUBLIC (decl) || TREE_ADDRESSABLE (decl))
+ if (TREE_PUBLIC (decl) || TREE_ADDRESSABLE (decl)
+ || flag_keep_inline_functions)
{
if (DECL_EXTERNAL (decl)
|| (DECL_IMPLICIT_INSTANTIATION (decl)
diff --git a/gcc/cp/gxxint.texi b/gcc/cp/gxxint.texi
index d91a97e..426417a 100644
--- a/gcc/cp/gxxint.texi
+++ b/gcc/cp/gxxint.texi
@@ -24,7 +24,8 @@ Questions and comments to mrs@@cygnus.com.
* Error Reporting::
* Parser::
* Copying Objects::
-* Exception Handling::
+* Exception Handling::
+* Free Store::
* Concept Index::
@end menu
@@ -44,22 +45,9 @@ I suspect there are other uses of pushdecl_class_level that do not call
set_identifier_type_value in tandem with the call to
pushdecl_class_level. It would seem to be an omission.
-@cindex delete, two argument
-@item
-For two argument delete, the second argument is always calculated by
-``virtual_size ='' in the source. It currently has a problem, in that
-object size is not calculated by the virtual destructor and passed back
-for the second parameter to delete. Destructors need to return a value
-just like constructors. ANSI C++ Jun 5 92 wp 12.5.6
-
-The second argument is magically deleted in build_method_call, if it is
-not used. It needs to be deleted for global operator delete also.
-
@cindex access checking
@item
-Access checking in general is unimplemented, there are a few cases
-where it is implemented. grok_enum_decls should be used in more places
-to do access checking, but this is only the tip of a bigger problem.
+Access checking is unimplemented for nested types.
@cindex @code{volatile}
@item
@@ -1142,7 +1130,7 @@ them.
This issue is currently under discussion in the core reflector
(2/28/94).
-@node Copying Objects, Concept Index, Copying Objects, Top
+@node Exception Handling, Free Store, Copying Objects, Top
@section Exception Handling
This section describes the mapping of C++ exceptions in the C++
@@ -1155,7 +1143,7 @@ independent representation for exceptions.
The C++ front-end exceptions are mapping into the unwind-protect
semantics by the C++ front-end. The mapping is describe below.
-Objects with RTTI support, should use the RTTI information to do mapping
+Objects with RTTI support should use the RTTI information to do mapping
and checking. Objects without RTTI, like int and const char *, have to
use another means of matching. Currently we use the normal mangling used in
building functions names. Int's are "i", const char * is PCc, etc...
@@ -1189,7 +1177,43 @@ hit before the section finishes normally, they examine the list for
actions to perform. I hope they add this logic into the back-end, as it
would be nice to get that alternative approach in C++.
-@node Concept Index, , Exception Handling, Top
+@node Free Store, Concept Index, Exception Handling, Top
+@section Free Store
+
+operator new [] adds a magic cookie to the beginning of arrays for which
+the number of elements will be needed by operator delete []. These are
+arrays of objects with destructors and arrays of objects that define
+operator delete [] with the optional size_t argument. This cookie can
+be examined from a program as follows:
+
+@example
+typedef unsigned long size_t;
+extern "C" int printf (const char *, ...);
+
+size_t nelts (void *p)
+@{
+ struct cookie @{
+ size_t nelts __attribute__ ((aligned (sizeof (double))));
+ @};
+
+ cookie *cp = (cookie *)p;
+ --cp;
+
+ return cp->nelts;
+@}
+
+struct A @{
+ ~A() @{ @}
+@};
+
+main()
+@{
+ A *ap = new A[3];
+ printf ("%ld\n", nelts (ap));
+@}
+@end example
+
+@node Concept Index, , Free Store, Top
@section Concept Index
@printindex cp
diff --git a/gcc/cp/lex.c b/gcc/cp/lex.c
index 68f801e..5edf659 100644
--- a/gcc/cp/lex.c
+++ b/gcc/cp/lex.c
@@ -3571,10 +3571,7 @@ real_yylex ()
value = ELLIPSIS;
goto done;
}
- nextchar = c1;
- token_buffer[2] = '\0';
- value = RANGE;
- goto done;
+ error ("parse error at `..'");
}
if (isdigit (c1))
{
@@ -3689,10 +3686,7 @@ real_yylex ()
value = ELLIPSIS;
goto done;
}
- nextchar = c;
- token_buffer[2] = '\0';
- value = RANGE;
- goto done;
+ error ("parse error at `..'");
}
nextchar = c;
token_buffer[1] = '\0';
diff --git a/gcc/cp/parse.y b/gcc/cp/parse.y
index cb2046d..1f26e4c 100644
--- a/gcc/cp/parse.y
+++ b/gcc/cp/parse.y
@@ -171,7 +171,7 @@ empty_parms ()
%left '{' ',' ';'
%right <code> ASSIGN '='
-%right <code> '?' ':' RANGE
+%right <code> '?' ':'
%left <code> OROR
%left <code> ANDAND
%left <code> '|'
@@ -765,9 +765,13 @@ identifier_defn:
explicit_instantiation:
TEMPLATE specialization template_instantiation
- { do_type_instantiation ($3 ? $3 : $2); }
+ { do_type_instantiation ($3 ? $3 : $2, NULL_TREE); }
| TEMPLATE typed_declspecs declarator
- { do_function_instantiation ($2, $3); }
+ { do_function_instantiation ($2, $3, NULL_TREE); }
+ | SCSPEC TEMPLATE specialization template_instantiation
+ { do_type_instantiation ($4 ? $4 : $3, $1); }
+ | SCSPEC TEMPLATE typed_declspecs declarator
+ { do_function_instantiation ($3, $4, $1); }
;
template_type:
@@ -3205,7 +3209,7 @@ simple_stmt:
define_case_label (label);
}
stmt
- | CASE expr_no_commas RANGE expr_no_commas ':'
+ | CASE expr_no_commas ELLIPSIS expr_no_commas ':'
{ register tree value1 = check_cp_case_value ($2);
register tree value2 = check_cp_case_value ($4);
register tree label
diff --git a/gcc/cp/pt.c b/gcc/cp/pt.c
index 36248be..79d37f7 100644
--- a/gcc/cp/pt.c
+++ b/gcc/cp/pt.c
@@ -37,6 +37,7 @@ the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
#include "cp-tree.h"
#include "decl.h"
#include "parse.h"
+#include "lex.h"
extern struct obstack permanent_obstack;
extern tree grokdeclarator ();
@@ -195,6 +196,7 @@ end_template_decl (d1, d2, is_class, defn)
if (is_class)
{
decl = build_lang_decl (TEMPLATE_DECL, d2, NULL_TREE);
+ GNU_xref_decl (current_function_decl, decl);
}
else
{
@@ -243,12 +245,11 @@ end_template_decl (d1, d2, is_class, defn)
}
/* If this is for a method, there's an extra binding level here. */
- if (! DECL_TEMPLATE_IS_CLASS (decl)
- && DECL_CONTEXT (DECL_TEMPLATE_RESULT (decl)) != NULL_TREE)
+ if (DECL_CONTEXT (DECL_TEMPLATE_RESULT (decl)) != NULL_TREE)
{
/* @@ Find out where this should be getting set! */
tree r = DECL_TEMPLATE_RESULT (decl);
- if (DECL_CLASS_CONTEXT (r) == NULL_TREE)
+ if (DECL_LANG_SPECIFIC (r) && DECL_CLASS_CONTEXT (r) == NULL_TREE)
DECL_CLASS_CONTEXT (r) = DECL_CONTEXT (r);
}
}
@@ -261,8 +262,7 @@ end_template_decl (d1, d2, is_class, defn)
/* If context of decl is non-null (i.e., method template), add it
to the appropriate class template, and pop the binding levels. */
- if (! DECL_TEMPLATE_IS_CLASS (decl)
- && DECL_CONTEXT (DECL_TEMPLATE_RESULT (decl)) != NULL_TREE)
+ if (! is_class && DECL_CONTEXT (DECL_TEMPLATE_RESULT (decl)) != NULL_TREE)
{
tree ctx = DECL_CONTEXT (DECL_TEMPLATE_RESULT (decl));
tree tmpl, t;
@@ -1284,6 +1284,13 @@ tsubst (t, args, nargs, in_decl)
fprintf (stderr, "\tfound %s\n\n",
IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (method)));
#endif
+ if (DECL_ARTIFICIAL (method))
+ {
+ cp_error ("template for method `%D' which has default implementation in class `%T'", name, ctx);
+ if (in_decl)
+ cp_error_at ("in attempt to instantiate `%D' declared at this point in file", in_decl);
+ return error_mark_node;
+ }
if (DECL_ARGUMENTS (method)
&& ! TREE_PERMANENT (DECL_ARGUMENTS (method)))
@@ -1614,9 +1621,7 @@ instantiate_template (tmpl, targ_ptr)
/* Here, we have a match. */
fndecl = TREE_VALUE (fndecl);
- function_maybepermanent_obstack = old_fmp_obstack;
- pop_obstacks ();
- return fndecl;
+ goto exit;
no_match:
;
@@ -1631,10 +1636,12 @@ instantiate_template (tmpl, targ_ptr)
fndecl = tsubst (DECL_RESULT (tmpl), targ_ptr,
TREE_VEC_LENGTH (targs), tmpl);
+ if (fndecl == error_mark_node)
+ goto exit;
+
/* If it's a static member fn in the template, we need to change it
into a FUNCTION_TYPE and chop off its this pointer. */
if (TREE_CODE (TREE_TYPE (DECL_RESULT (tmpl))) == METHOD_TYPE
- && fndecl != error_mark_node
&& DECL_STATIC_FUNCTION_P (fndecl))
{
tree olddecl = DECL_RESULT (tmpl);
@@ -1693,10 +1700,7 @@ instantiate_template (tmpl, targ_ptr)
DECL_TEMPLATE_INSTANTIATIONS (tmpl) =
tree_cons (targs, fndecl, DECL_TEMPLATE_INSTANTIATIONS (tmpl));
- function_maybepermanent_obstack = old_fmp_obstack;
- pop_obstacks ();
-
- if (fndecl == error_mark_node || p == (struct pending_inline *)0)
+ if (p == (struct pending_inline *)0)
{
/* do nothing */
}
@@ -1711,6 +1715,10 @@ instantiate_template (tmpl, targ_ptr)
p->next = pending_template_expansions;
pending_template_expansions = p;
}
+ exit:
+ function_maybepermanent_obstack = old_fmp_obstack;
+ pop_obstacks ();
+
return fndecl;
}
@@ -2235,7 +2243,7 @@ do_pending_expansions ()
DECIDE (0);
if (DECL_EXPLICIT_INSTANTIATION (t))
- DECIDE (1);
+ DECIDE (! DECL_EXTERNAL (t));
else if (! flag_implicit_templates)
DECIDE (0);
@@ -2335,8 +2343,8 @@ add_pending_template (pt)
/* called from the parser. */
void
-do_function_instantiation (declspecs, declarator)
- tree declspecs, declarator;
+do_function_instantiation (declspecs, declarator, storage)
+ tree declspecs, declarator, storage;
{
tree decl = grokdeclarator (declarator, declspecs, NORMAL, 0, 0);
tree name = DECL_NAME (decl);
@@ -2371,22 +2379,54 @@ do_function_instantiation (declspecs, declarator)
SET_DECL_EXPLICIT_INSTANTIATION (result);
TREE_PUBLIC (result) = 1;
- DECL_EXTERNAL (result) = DECL_INLINE (result) && ! flag_implement_inlines;
+
+ if (storage == NULL_TREE)
+ DECL_EXTERNAL (result) = DECL_INLINE (result) && ! flag_implement_inlines;
+ else if (storage == ridpointers[(int) RID_EXTERN])
+ DECL_EXTERNAL (result) = 1;
+ else
+ cp_error ("storage class `%D' applied to template instantiation",
+ storage);
}
void
-do_type_instantiation (name)
- tree name;
+do_type_instantiation (name, storage)
+ tree name, storage;
{
tree t = TREE_TYPE (name);
+ int extern_p;
if (flag_external_templates)
return;
+ if (TYPE_SIZE (t) == NULL_TREE)
+ {
+ cp_error ("explicit instantiation of `%#T' before definition of template",
+ t);
+ return;
+ }
+
+ if (storage == NULL_TREE)
+ extern_p = 0;
+ else if (storage == ridpointers[(int) RID_EXTERN])
+ extern_p = 1;
+ else
+ {
+ cp_error ("storage class `%D' applied to template instantiation",
+ storage);
+ extern_p = 0;
+ }
+
SET_CLASSTYPE_EXPLICIT_INSTANTIATION (t);
- CLASSTYPE_VTABLE_NEEDS_WRITING (t) = 1;
+ CLASSTYPE_VTABLE_NEEDS_WRITING (t) = ! extern_p;
SET_CLASSTYPE_INTERFACE_KNOWN (t);
- CLASSTYPE_INTERFACE_ONLY (t) = 0;
+ CLASSTYPE_INTERFACE_ONLY (t) = extern_p;
+ if (! extern_p)
+ {
+ CLASSTYPE_DEBUG_REQUESTED (t) = 1;
+ TYPE_DECL_SUPPRESS_DEBUG (TYPE_NAME (t)) = 0;
+ rest_of_type_compilation (t, 1);
+ }
/* this should really be done by instantiate_member_templates */
{
@@ -2395,8 +2435,8 @@ do_type_instantiation (name)
{
SET_DECL_EXPLICIT_INSTANTIATION (method);
TREE_PUBLIC (method) = 1;
- DECL_EXTERNAL (method) = (DECL_INLINE (method)
- && ! flag_implement_inlines);
+ DECL_EXTERNAL (method)
+ = (extern_p || (DECL_INLINE (method) && ! flag_implement_inlines));
}
}
diff --git a/gcc/cp/search.c b/gcc/cp/search.c
index ea7de8f..c4c6a4e 100644
--- a/gcc/cp/search.c
+++ b/gcc/cp/search.c
@@ -594,7 +594,7 @@ get_base_distance (parent, binfo, protect, path_ptr)
if (TREE_CODE (binfo) == TREE_VEC)
type = BINFO_TYPE (binfo);
- else if (TREE_CODE (binfo) == RECORD_TYPE)
+ else if (IS_AGGR_TYPE_CODE (TREE_CODE (binfo)))
{
type = binfo;
binfo = TYPE_BINFO (type);
@@ -2366,10 +2366,8 @@ dfs_debug_mark (binfo)
}
/* We cannot rely on some alien method to solve our problems,
so we must write out the debug info ourselves. */
- if (write_symbols != DWARF_DEBUG)
- TYPE_DECL_SUPPRESS_DEBUG (TYPE_NAME (t)) = 0;
- if (! TREE_ASM_WRITTEN (TYPE_NAME (t)))
- rest_of_type_compilation (t, global_bindings_p ());
+ TYPE_DECL_SUPPRESS_DEBUG (TYPE_NAME (t)) = 0;
+ rest_of_type_compilation (t, global_bindings_p ());
}
/* Attach to the type of the virtual base class, the pointer to the
diff --git a/gcc/cp/tree.c b/gcc/cp/tree.c
index 98cbd41..5805d36 100644
--- a/gcc/cp/tree.c
+++ b/gcc/cp/tree.c
@@ -486,6 +486,7 @@ layout_vbasetypes (rec, max)
#else
unsigned record_align = MAX (BITS_PER_UNIT, TYPE_ALIGN (rec));
#endif
+ int desired_align;
/* Record size so far is CONST_SIZE + VAR_SIZE bits,
where CONST_SIZE is an integer
@@ -512,17 +513,25 @@ layout_vbasetypes (rec, max)
tree basetype = BINFO_TYPE (vbase_types);
tree offset;
+ desired_align = TYPE_ALIGN (basetype);
+ record_align = MAX (record_align, desired_align);
+
if (const_size == 0)
offset = integer_zero_node;
else
- offset = size_int ((const_size + BITS_PER_UNIT - 1) / BITS_PER_UNIT);
+ {
+ /* Give each virtual base type the alignment it wants. */
+ const_size = CEIL (const_size, TYPE_ALIGN (basetype))
+ * TYPE_ALIGN (basetype);
+ offset = size_int (CEIL (const_size, BITS_PER_UNIT));
+ }
if (CLASSTYPE_VSIZE (basetype) > max)
max = CLASSTYPE_VSIZE (basetype);
BINFO_OFFSET (vbase_types) = offset;
if (TREE_CODE (TYPE_SIZE (basetype)) == INTEGER_CST)
- const_size += MAX (record_align,
+ const_size += MAX (BITS_PER_UNIT,
TREE_INT_CST_LOW (TYPE_SIZE (basetype))
- TREE_INT_CST_LOW (CLASSTYPE_VBASE_SIZE (basetype)));
else if (var_size == 0)
@@ -533,6 +542,9 @@ layout_vbasetypes (rec, max)
vbase_types = TREE_CHAIN (vbase_types);
}
+ /* Set the alignment in the complete type. We don't set CLASSTYPE_ALIGN
+ here, as that is for this class, without any virtual base classes. */
+ TYPE_ALIGN (rec) = record_align;
if (const_size != nonvirtual_const_size)
{
CLASSTYPE_VBASE_SIZE (rec)
diff --git a/gcc/cp/typeck.c b/gcc/cp/typeck.c
index ffc6fd7..746bcd8 100644
--- a/gcc/cp/typeck.c
+++ b/gcc/cp/typeck.c
@@ -3990,6 +3990,8 @@ build_unary_op (code, xarg, noconvert)
case FIX_CEIL_EXPR:
{
tree incremented, modify, value;
+ if (! lvalue_p (arg) && pedantic)
+ pedwarn ("cast to non-reference type used as lvalue");
arg = stabilize_reference (arg);
if (code == PREINCREMENT_EXPR || code == PREDECREMENT_EXPR)
value = arg;
@@ -4143,11 +4145,6 @@ build_unary_op (code, xarg, noconvert)
if (val != 0)
return val;
-#if 0 /* Turned off because inconsistent;
- float f; *&(int)f = 3.4 stores in int format
- whereas (int)f = 3.4 stores in float format. */
- /* Address of a cast is just a cast of the address
- of the operand of the cast. */
switch (TREE_CODE (arg))
{
case NOP_EXPR:
@@ -4157,12 +4154,9 @@ build_unary_op (code, xarg, noconvert)
case FIX_FLOOR_EXPR:
case FIX_ROUND_EXPR:
case FIX_CEIL_EXPR:
- if (pedantic)
- pedwarn ("ANSI C++ forbids taking the address of a cast expression");
- return convert (build_pointer_type (TREE_TYPE (arg)),
- build_unary_op (ADDR_EXPR, TREE_OPERAND (arg, 0), 0));
+ if (! lvalue_p (arg) && pedantic)
+ pedwarn ("taking the address of a cast to non-reference type");
}
-#endif
/* Allow the address of a constructor if all the elements
are constant. */
@@ -4950,21 +4944,12 @@ build_c_cast (type, expr)
return error_mark_node;
}
- if (TREE_TYPE (value)
- && TYPE_MAIN_VARIANT (type) == TYPE_MAIN_VARIANT (TREE_TYPE (value)))
- return build1 (NOP_EXPR, type, value);
-
/* If there's only one function in the overloaded space,
just take it. */
if (TREE_CODE (value) == TREE_LIST
&& TREE_CHAIN (value) == NULL_TREE)
value = TREE_VALUE (value);
- /* Make up for the fact that we do not always perform
- `default_conversion' anymore. */
- if (TREE_READONLY_DECL_P (value))
- value = decl_constant_value (value);
-
if (TREE_CODE (type) == VOID_TYPE)
value = build1 (NOP_EXPR, type, value);
else if (TREE_TYPE (value) == NULL_TREE
@@ -5579,7 +5564,7 @@ build_modify_expr (lhs, modifycode, rhs)
convert (lhstype, newrhs)));
if (TREE_CODE (result) == ERROR_MARK)
return result;
- return convert_force (TREE_TYPE (lhs), result);
+ return convert (TREE_TYPE (lhs), result);
}
}
diff --git a/gcc/cp/typeck2.c b/gcc/cp/typeck2.c
index 237d02a..2fe6040 100644
--- a/gcc/cp/typeck2.c
+++ b/gcc/cp/typeck2.c
@@ -329,7 +329,7 @@ ack (s, v, v2)
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: 357. Free: */
+/* First used: 0 (reserved), Last used: 358. Free: */
static int abortcount = 0;
@@ -1496,6 +1496,7 @@ enum_name_string (value, type)
return IDENTIFIER_POINTER (TREE_PURPOSE (values));
}
+#if 0
/* Print out a language-specific error message for
(Pascal) case or (C) switch statements.
CODE tells what sort of message to print.
@@ -1598,3 +1599,4 @@ report_case_error (code, type, new_value, old_value)
error ("range values reversed");
}
}
+#endif
diff --git a/gcc/cp/xref.c b/gcc/cp/xref.c
index 4a300c2..283771b 100644
--- a/gcc/cp/xref.c
+++ b/gcc/cp/xref.c
@@ -397,6 +397,18 @@ GNU_xref_decl (fndecl,decl)
decl = TYPE_NAME (decl);
uselin = TRUE;
}
+ else if (TREE_CODE (decl) == TEMPLATE_DECL)
+ {
+ if (DECL_TEMPLATE_IS_CLASS (decl))
+ cls = "CLASSTEMP";
+ else if (TREE_CODE (DECL_RESULT (decl)) == FUNCTION_DECL)
+ cls = "FUNCTEMP";
+ else if (TREE_CODE (DECL_RESULT (decl)) == VAR_DECL)
+ cls = "VARTEMP";
+ else
+ my_friendly_abort (358);
+ uselin = TRUE;
+ }
else cls = "UNKNOWN";
if (decl == NULL || DECL_NAME (decl) == NULL) return;