diff options
author | Mike Stump <mrs@gcc.gnu.org> | 1994-06-15 18:30:58 +0000 |
---|---|---|
committer | Mike Stump <mrs@gcc.gnu.org> | 1994-06-15 18:30:58 +0000 |
commit | f0e01782d7d294907fe8f8325bfae9c6fae7a877 (patch) | |
tree | 2990254a5379920de31c9e0548663ccf4769e623 /gcc/cp | |
parent | 7dbe2fdcf52add2c55b4e7ba95216942fb274a4a (diff) | |
download | gcc-f0e01782d7d294907fe8f8325bfae9c6fae7a877.zip gcc-f0e01782d7d294907fe8f8325bfae9c6fae7a877.tar.gz gcc-f0e01782d7d294907fe8f8325bfae9c6fae7a877.tar.bz2 |
40th Cygnus<->FSF merge
From-SVN: r7493
Diffstat (limited to 'gcc/cp')
-rw-r--r-- | gcc/cp/ChangeLog | 126 | ||||
-rw-r--r-- | gcc/cp/class.c | 1 | ||||
-rw-r--r-- | gcc/cp/cp-tree.h | 7 | ||||
-rw-r--r-- | gcc/cp/cvt.c | 45 | ||||
-rw-r--r-- | gcc/cp/decl.c | 66 | ||||
-rw-r--r-- | gcc/cp/decl2.c | 38 | ||||
-rw-r--r-- | gcc/cp/gxxint.texi | 60 | ||||
-rw-r--r-- | gcc/cp/lex.c | 10 | ||||
-rw-r--r-- | gcc/cp/parse.y | 12 | ||||
-rw-r--r-- | gcc/cp/pt.c | 86 | ||||
-rw-r--r-- | gcc/cp/search.c | 8 | ||||
-rw-r--r-- | gcc/cp/tree.c | 16 | ||||
-rw-r--r-- | gcc/cp/typeck.c | 25 | ||||
-rw-r--r-- | gcc/cp/typeck2.c | 4 | ||||
-rw-r--r-- | gcc/cp/xref.c | 12 |
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; |