]> git.ipfire.org Git - thirdparty/gcc.git/commitdiff
40th Cygnus<->FSF merge
authorMike Stump <mrs@gcc.gnu.org>
Wed, 15 Jun 1994 18:30:58 +0000 (18:30 +0000)
committerMike Stump <mrs@gcc.gnu.org>
Wed, 15 Jun 1994 18:30:58 +0000 (18:30 +0000)
From-SVN: r7493

15 files changed:
gcc/cp/ChangeLog
gcc/cp/class.c
gcc/cp/cp-tree.h
gcc/cp/cvt.c
gcc/cp/decl.c
gcc/cp/decl2.c
gcc/cp/gxxint.texi
gcc/cp/lex.c
gcc/cp/parse.y
gcc/cp/pt.c
gcc/cp/search.c
gcc/cp/tree.c
gcc/cp/typeck.c
gcc/cp/typeck2.c
gcc/cp/xref.c

index 385d239cb7842e8b10103cceebf4135a827a928c..cddc168d576788622096449b7d035acc88e69e3a 100644 (file)
@@ -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)
 
index 638fedfb9c6149bec9696866cc4a008cd199bf57..1d276816f993b712d3f0bf8bca399222d14f2463 100644 (file)
@@ -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;
index 7ae511fc4ea7b7bedcb16006df6bb0ede246add3..9ba72b02ad57359890e1a84be85c1f2dd03a575f 100644 (file)
@@ -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 */
index fc8d261b0efc2e333654412cd7a9ad447093ba2a..3750221aeeff0e92682543e7223986aa8745b94c 100644 (file)
@@ -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));
index 10e9d0e63f2a889d895f9ceae8c5ae8a361ddb63..4bbfec9c9adfaf1000a78b8cfe612b4370c15ec1 100644 (file)
@@ -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.
index fa05063fcabbe9a6167f2bbda556c608e184385b..964615e71e7026387157075a5917863572835880 100644 (file)
@@ -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)
index d91a97e4a59ebd339c22c9257771a13f471880e0..426417acdad9be0ec27f42d4391b489fb3175b86 100644 (file)
@@ -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
index 68f801e1f9858f9f02cae3bb4c966fb46815e06a..5edf65927ad968d5954c0e095f14ebe754b4fe57 100644 (file)
@@ -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';
index cb2046d21001cc2254954bfc5b244eb87dc19d84..1f26e4cb640bd7a32b88e9b20f043d502239cf64 100644 (file)
@@ -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
index 36248be80edaea1904fa36f1797ebf85ef9a6b59..79d37f7dad3d0cbbfe67761dfadf5864041ce273 100644 (file)
@@ -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));
       }
   }
 
index ea7de8f9f6f37c352e36e1afe065fd472133b232..c4c6a4ea7c16be305ecf2d7534e86bbd978deffc 100644 (file)
@@ -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 ());
 }
 \f
 /*  Attach to the type of the virtual base class, the pointer to the
index 98cbd41d5a8fc13026b500d64769b1ba638da1f4..5805d36d5111a27e618e8abc2678622f243874f5 100644 (file)
@@ -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)
index ffc6fd74cd6143a039b52f2284318862eeea7f1a..746bcd855ada5f6a50a9a814c069cae69906ab48 100644 (file)
@@ -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);
       }
     }
 
index 237d02a0f843dffb6d29d281a57f66af62216114..2fe60403b6d78fb47d2df444bb0c7ce48791379d 100644 (file)
@@ -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
index 4a300c2d63583064134d49e1a37c0135a7a18dd8..283771b1cf7ae12b659727d9452f8a241e726a17 100644 (file)
@@ -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;