62nd Cygnus<->FSF merge
authorMike Stump <mrs@gcc.gnu.org>
Mon, 3 Apr 1995 19:28:01 +0000 (19:28 +0000)
committerMike Stump <mrs@gcc.gnu.org>
Mon, 3 Apr 1995 19:28:01 +0000 (19:28 +0000)
From-SVN: r9298

16 files changed:
gcc/cp/ChangeLog
gcc/cp/Make-lang.in
gcc/cp/Makefile.in
gcc/cp/call.c
gcc/cp/cp-tree.h
gcc/cp/cvt.c
gcc/cp/decl.c
gcc/cp/decl2.c
gcc/cp/except.c
gcc/cp/lex.c
gcc/cp/method.c
gcc/cp/parse.y
gcc/cp/pt.c
gcc/cp/repo.c [new file with mode: 0644]
gcc/cp/search.c
gcc/cp/typeck.c

index 3f1f604c649bf96f9776719b189ae5dd5952deac..1f68bf6ca9939d55d2b7fea13a4c51df0a990dbf 100644 (file)
@@ -1,3 +1,116 @@
+Sun Apr  2 23:43:51 1995  Jason Merrill  <jason@phydeaux.cygnus.com>
+
+       * search.c (compute_access): Don't try to do access control on
+       nested types.
+
+Fri Mar 31 10:14:23 1995  Jason Merrill  <jason@phydeaux.cygnus.com>
+
+       * repo.c: New file to handle things repo.
+
+       * pt.c (instantiate_template): Call repo_template_used if the
+       definition is accessible.
+       (mark_function_instantiated): Split out from
+       do_function_instantiation.
+       (mark_class_instantiated): Split out from do_type_instantiation.
+
+       * parse.y (template_instantiate_once): Call repo_template_used.
+
+       * lex.c (lang_init): Call init_repo.
+
+       * decl2.c: Handle flag_use_repository.
+       (finish_file): Call finish_repo.
+
+       * decl.c (start_method): Call repo_template_used if this is a
+       template method.
+
+       * Makefile.in (CXX_OBJS): Add repo.o.
+       (repo.o): Add dependencies.
+
+       * Make-lang.in (CXX_SRCS): Add repo.c.
+
+       * decl.c (start_function): If DECL_INTERFACE_KNOWN and
+       DECL_NOT_REALLY_EXTERN are both set, unset DECL_EXTERNAL.
+
+       * typeck.c (build_binary_op_nodefault): Identify the invalid operand
+       types used.
+
+       * decl.c (duplicate_decls): Propagate DECL_NOT_REALLY_EXTERN.
+
+Thu Mar 30 17:54:42 1995  Jason Merrill  <jason@phydeaux.cygnus.com>
+
+       * typeck.c (build_binary_op_nodefault): Tidy up use of build_type
+       and result_type.  When checking for comparison between signed
+       and unsigned, use result_type rather than the (possibly shortened)
+       type of op0.  Also, don't warn about equality comparison of a
+       signed operand to an unsigned constant that fits in the signed
+       type.
+
+       * method.c (do_build_copy_constructor): Reverse
+       current_base_init_list after we've built it up.
+
+Thu Mar 30 14:35:18 1995  Mike Stump  <mrs@cygnus.com>
+
+       * except.c (build_throw): Never warn about the value of throw not
+       being used.
+
+Thu Mar 30 13:16:54 1995  Mike Stump  <mrs@cygnus.com>
+
+       * except.c (expand_start_catch_block): Check for bad catch parameter
+       declarations.
+
+Thu Mar 30 13:06:11 1995  Jason Merrill  <jason@phydeaux.cygnus.com>
+
+       * decl.c (finish_function): Only set DECL_NOT_REALLY_EXTERN if
+       DECL_EXTERNAL is not already set.
+
+Thu Mar 30 11:26:24 1995  Mike Stump  <mrs@cygnus.com>
+
+       * method.c (emit_thunk): Let poplevel know that the last level is
+       for a function so it can create a BLOCK_NODE and set DECL_INITIAL.
+
+Thu Mar 30 11:15:06 1995  Jason Merrill  <jason@phydeaux.cygnus.com>
+
+       * decl2.c (import_export_inline): Don't set DECL_NOT_REALLY_EXTERN
+       here.
+
+       * decl.c (grokdeclarator): OK, don't abort if we see a decl with
+       METHOD_TYPE.
+       (finish_function): Set DECL_EXTERNAL and DECL_NOT_REALLY_EXTERN on
+       all deferred inlines.
+
+Wed Mar 29 19:35:02 1995  Jason Merrill  <jason@phydeaux.cygnus.com>
+
+       * cp-tree.h (DECL_THIS_INLINE): New macro.
+       (DECL_NOT_REALLY_EXTERN): New macro.
+       (DECL_THIS_STATIC): New macro.
+
+       * decl.c: Lose all references to current_extern_inline.  Break
+       inline semantics into DECL_INLINE for actual inlining and
+       DECL_THIS_INLINE for the linkage wierdness.  Use DECL_THIS_STATIC.
+       * decl2.c: Use DECL_NOT_REALLY_EXTERN to indicate that we want to
+       emit an inline here.  Associated changes.
+       * lex.c: Ditto.
+       * pt.c: Ditto.
+       * typeck.c: Ditto.
+
+       * call.c (build_method_call): Don't bother trying to handle inlines
+       specially.
+       * cvt.c (convert_to_aggr): Ditto.
+
+       * pt.c (do_function_instantiation): Handle instantiation of
+       public inlines, too.
+
+Wed Mar 29 16:04:25 1995  Mike Stump  <mrs@cygnus.com>
+
+       * except.c (init_exception_processing): Change the interface for
+       __throw_type_match and add decl for new rtti matching routine
+       __throw_type_match_rtti.
+       (build_eh_type): New routine to build a run time descriptor for the
+       expression given. 
+       (expand_start_catch_block): Update to use new calling convention for
+       the matcher.
+       (expand_throw): Update to use build_eh_type.
+
 Mon Mar 27 07:14:33 1995  Warner Losh  <imp@village.org>
 
        * g++.c: Removed __NetBSD__ from conditional.
index 75bd8dacb994a8d5a6515db9f395d9ff74cca41e..3eadf90a2ab023b466a60061c9b89b9866d8f8a6 100644 (file)
@@ -76,7 +76,7 @@ CXX_SRCS = $(srcdir)/cp/call.c $(srcdir)/cp/decl2.c \
  $(srcdir)/cp/errfn.c $(srcdir)/cp/gc.c $(srcdir)/cp/method.c \
  $(srcdir)/cp/search.c $(srcdir)/cp/typeck.c $(srcdir)/cp/decl.c \
  $(srcdir)/cp/error.c $(srcdir)/cp/init.c $(srcdir)/cp/parse.y \
- $(srcdir)/cp/sig.c $(srcdir)/cp/typeck2.c
+ $(srcdir)/cp/sig.c $(srcdir)/cp/typeck2.c $(srcdir)/cp/repo.c
 
 cc1plus: $(P) $(CXX_SRCS) $(LIBDEPS) stamp-objlist c-common.o c-pragma.o
        cd cp; $(MAKE) $(FLAGS_TO_PASS) $(CXX_FLAGS_TO_PASS) ../cc1plus
index 6007f00d0426fd3f7405cba1ad9e8029b64284c0..98fea7eb2aeea919ecb9d4a0877c305c9f5bcf35 100644 (file)
@@ -159,7 +159,7 @@ INCLUDES = -I. -I.. -I$(srcdir) -I$(srcdir)/.. -I$(srcdir)/../config
 
 CXX_OBJS = call.o decl.o errfn.o expr.o pt.o sig.o typeck2.o \
  class.o decl2.o error.o gc.o lex.o parse.o ptree.o spew.o typeck.o cvt.o \
- edsel.o except.o init.o method.o search.o tree.o xref.o
+ edsel.o except.o init.o method.o search.o tree.o xref.o repo.o
 
 # Language-independent object files.
 OBJS = `cat ../stamp-objlist` ../c-common.o ../c-pragma.o
@@ -247,6 +247,7 @@ pt.o : pt.c $(CONFIG_H) $(CXX_TREE_H) decl.h $(PARSE_H)
 error.o : error.c $(CONFIG_H) $(CXX_TREE_H)
 errfn.o : errfn.c $(CONFIG_H) $(CXX_TREE_H)
 sig.o : sig.c $(CONFIG_H) $(CXX_TREE_H) $(srcdir)/../flags.h
+repo.o : repo.c $(CONFIG.H) $(CXX_TREE_H)
 \f
 # These exist for maintenance purposes.
 
index 9ba6d1894e7453641f8216658f9dfc61973dbfdb..151d02f0d7ae043fa4ef28de8257520a63687c37 100644 (file)
@@ -2575,14 +2575,8 @@ build_method_call (instance, name, parms, basetype_path, flags)
     if (TREE_CODE (function) == FUNCTION_DECL)
       {
        is_constructor = DECL_CONSTRUCTOR_P (function);
-       if (DECL_INLINE (function))
-         function = build1 (ADDR_EXPR, build_pointer_type (fntype), function);
-       else
-         {
-           assemble_external (function);
-           TREE_USED (function) = 1;
-           function = default_conversion (function);
-         }
+       TREE_USED (function) = 1;
+       function = default_conversion (function);
       }
     else
       {
index 98ea89f09f1e91fa067299a72f9e0a9390979429..5dd853aff73ced86fb27845c180d561ddb98856f 100644 (file)
@@ -954,9 +954,11 @@ struct lang_decl_flags
   unsigned saved_inline : 1;
   unsigned use_template : 2;
 
-  unsigned declared_static : 1;
+  unsigned c_static : 1;
   unsigned nonconverting : 1;
-  unsigned dummy : 6;
+  unsigned declared_inline : 1;
+  unsigned not_really_extern : 1;
+  unsigned dummy : 4;
 
   tree access;
   tree context;
@@ -1234,10 +1236,14 @@ struct lang_decl
 #define DELTA2_FROM_PTRMEMFUNC(NODE) (build_component_ref (build_component_ref ((NODE), pfn_or_delta2_identifier, 0, 0), delta2_identifier, 0, 0))
 #define PFN_FROM_PTRMEMFUNC(NODE) (build_component_ref (build_component_ref ((NODE), pfn_or_delta2_identifier, 0, 0), pfn_identifier, 0, 0))
 
-/* Nonzero for VAR_DECL and FUNCTION_DECL node means that `external' was
+/* Nonzero for VAR_DECL and FUNCTION_DECL node means that `extern' was
    specified in its declaration.  */
 #define DECL_THIS_EXTERN(NODE) (DECL_LANG_FLAG_2(NODE))
 
+/* Nonzero for VAR_DECL and FUNCTION_DECL node means that `static' was
+   specified in its declaration.  */
+#define DECL_THIS_STATIC(NODE) (DECL_LANG_FLAG_6(NODE))
+
 /* Nonzero for SAVE_EXPR if used to initialize a PARM_DECL.  */
 #define PARM_DECL_EXPR(NODE) (TREE_LANG_FLAG_2(NODE))
 
@@ -1338,13 +1344,26 @@ struct lang_decl
 /* We know what we're doing with this decl now.  */
 #define DECL_INTERFACE_KNOWN(NODE) DECL_LANG_FLAG_5 (NODE)
 
-/* This decl was declared to have internal linkage.  */
-#define DECL_DECLARED_STATIC(NODE) \
-  (DECL_LANG_SPECIFIC (NODE)->decl_flags.declared_static)
+/* This decl was declared or deduced to have internal linkage.  This is
+   only meaningful if TREE_PUBLIC is set.  */
+#define DECL_C_STATIC(NODE) \
+  (DECL_LANG_SPECIFIC (NODE)->decl_flags.c_static)
+
+/* This function was declared inline.  This flag controls the linkage
+   semantics of 'inline'; whether or not the function is inlined is
+   controlled by DECL_INLINE.  */
+#define DECL_THIS_INLINE(NODE) \
+  (DECL_LANG_SPECIFIC (NODE)->decl_flags.declared_inline)
+
+/* DECL_EXTERNAL must be set on a decl until the decl is actually emitted,
+   so that assemble_external will work properly.  So we have this flag to
+   tell us whether the decl is really not external.  */
+#define DECL_NOT_REALLY_EXTERN(NODE) \
+  (DECL_LANG_SPECIFIC (NODE)->decl_flags.not_really_extern)
 
 #define DECL_PUBLIC(NODE) \
-  (TREE_CODE (NODE) == FUNCTION_DECL ? ! DECL_DECLARED_STATIC (NODE) \
-   : TREE_PUBLIC (NODE))
+  (TREE_CODE (NODE) == FUNCTION_DECL \
+   ? ! DECL_C_STATIC (NODE) : TREE_PUBLIC (NODE))
 
 #define THUNK_DELTA(DECL) ((DECL)->decl.frame_size.i)
 
index 0ceabf01533d29d0c120a896dcec8c9649a3ad29..8cee211285aebe699e3145c3a1d2c0d56320f9b4 100644 (file)
@@ -1090,10 +1090,7 @@ convert_to_aggr (type, expr, msgp, protect)
     return NULL_TREE;
 
   fntype = TREE_TYPE (function);
-  if (DECL_INLINE (function) && TREE_CODE (function) == FUNCTION_DECL)
-    function = build1 (ADDR_EXPR, build_pointer_type (fntype), function);
-  else
-    function = default_conversion (function);
+  function = default_conversion (function);
 
   result = build_nt (CALL_EXPR, function,
                     convert_arguments (NULL_TREE, TYPE_ARG_TYPES (fntype),
index c6c63791c4428c255df4fdfe10d421462d3a39b0..de9e5b72e4e7c76d6eb32a9a5581a29cb93506a1 100644 (file)
@@ -406,10 +406,6 @@ tree current_function_return_value;
 
 static int warn_about_return_type;
 
-/* Nonzero when starting a function declared `extern inline'.  */
-
-static int current_extern_inline;
-
 /* Nonzero means give `double' the same size as `float'.  */
 
 extern int flag_short_double;
@@ -2082,13 +2078,11 @@ warn_extern_redeclared_static (newdecl, olddecl)
     = "`%D' was declared implicitly `extern' and later `static'";
 
   if (flag_traditional
-      || TREE_CODE (newdecl) == TYPE_DECL
-      || (! warn_extern_inline
-         && DECL_INLINE (newdecl)))
+      || TREE_CODE (newdecl) == TYPE_DECL)
     return;
 
   name = DECL_ASSEMBLER_NAME (newdecl);
-  if (TREE_PUBLIC (name) && ! DECL_PUBLIC (newdecl))
+  if (TREE_PUBLIC (name) && DECL_THIS_STATIC (newdecl))
     {
       /* It's okay to redeclare an ANSI built-in function as static,
         or to declare a non-ANSI built-in function as anything.  */
@@ -2516,8 +2510,9 @@ duplicate_decls (newdecl, olddecl)
 
       if (TREE_CODE (newdecl) == FUNCTION_DECL)
        {
-         DECL_DECLARED_STATIC (newdecl) = DECL_DECLARED_STATIC (olddecl);
+         DECL_C_STATIC (newdecl) = DECL_C_STATIC (olddecl);
          DECL_INTERFACE_KNOWN (newdecl) = DECL_INTERFACE_KNOWN (olddecl);
+         DECL_NOT_REALLY_EXTERN (newdecl) = DECL_NOT_REALLY_EXTERN (olddecl);
        }
     }
   else
@@ -2537,14 +2532,16 @@ duplicate_decls (newdecl, olddecl)
        }
     }
 
-  /* If either decl says `inline', this fn is inline,
-     unless its definition was passed already.  */
-  if (DECL_INLINE (newdecl) && DECL_INITIAL (olddecl) == NULL_TREE)
-    DECL_INLINE (olddecl) = 1;
-  DECL_INLINE (newdecl) = DECL_INLINE (olddecl);
-
   if (TREE_CODE (newdecl) == FUNCTION_DECL)
     {
+      DECL_THIS_INLINE (newdecl) |= DECL_THIS_INLINE (olddecl);
+
+      /* If either decl says `inline', this fn is inline, unless its
+         definition was passed already.  */
+      if (DECL_INLINE (newdecl) && DECL_INITIAL (olddecl) == NULL_TREE)
+       DECL_INLINE (olddecl) = 1;
+      DECL_INLINE (newdecl) = DECL_INLINE (olddecl);
+
       if (! types_match)
        {
          DECL_LANGUAGE (olddecl) = DECL_LANGUAGE (newdecl);
@@ -2968,7 +2965,7 @@ pushdecl (x)
          /* If this is an extern function declaration, see if we
             have a global definition or declaration for the function.  */
          if (oldlocal == NULL_TREE
-             && DECL_EXTERNAL (x) && !DECL_INLINE (x)
+             && DECL_EXTERNAL (x)
              && oldglobal != NULL_TREE
              && TREE_CODE (x) == FUNCTION_DECL
              && TREE_CODE (oldglobal) == FUNCTION_DECL)
@@ -3454,11 +3451,7 @@ redeclaration_error_message (newdecl, olddecl)
 
       /* defining the same name twice is no good.  */
       if (DECL_INITIAL (olddecl) != NULL_TREE
-         && DECL_INITIAL (newdecl) != NULL_TREE
-         /* However, defining once as extern inline and a second
-            time in another way is ok.  */
-         && !(DECL_INLINE (olddecl) && DECL_EXTERNAL (olddecl)
-              && !(DECL_INLINE (newdecl) && DECL_EXTERNAL (newdecl))))
+         && DECL_INITIAL (newdecl) != NULL_TREE)
        {
          if (DECL_NAME (olddecl) == NULL_TREE)
            return "`%#D' not declared in class";
@@ -6393,55 +6386,7 @@ finish_decl (decl, init, asmspec_tree, need_pop, flags)
        signature_error (decl, TREE_TYPE (type));
 
       if (TREE_CODE (decl) == FUNCTION_DECL)
-       {
-#if 0
-         /* C++: Handle overloaded functions with default parameters.  */
-         if (DECL_OVERLOADED (decl))
-           {
-             tree parmtypes = TYPE_ARG_TYPES (type);
-             tree prev = NULL_TREE;
-             tree original_name = DECL_NAME (decl);
-             struct lang_decl *tmp_lang_decl = DECL_LANG_SPECIFIC (decl);
-             /* All variants will share an uncollectible lang_decl.  */
-             copy_decl_lang_specific (decl);
-
-             while (parmtypes && parmtypes != void_list_node)
-               {
-                 /* The default value for the parameter in parmtypes is
-                    stored in the TREE_PURPOSE of the TREE_LIST.  */ 
-                 if (TREE_PURPOSE (parmtypes))
-                   {
-                     tree fnname, fndecl;
-                     tree *argp;
-
-                     argp = prev ? & TREE_CHAIN (prev)
-                       : & TYPE_ARG_TYPES (type);
-
-                     *argp = NULL_TREE;
-                     fnname = build_decl_overload (original_name,
-                                                   TYPE_ARG_TYPES (type), 0);
-                     *argp = parmtypes;
-                     fndecl = build_decl (FUNCTION_DECL, fnname, type);
-                     DECL_EXTERNAL (fndecl) = DECL_EXTERNAL (decl);
-                     TREE_PUBLIC (fndecl) = TREE_PUBLIC (decl);
-                     DECL_INLINE (fndecl) = DECL_INLINE (decl);
-                     /* Keep G++ from thinking this function is unused.
-                        It is only used to speed up search in name space.  */
-                     TREE_USED (fndecl) = 1;
-                     TREE_ASM_WRITTEN (fndecl) = 1;
-                     DECL_INITIAL (fndecl) = NULL_TREE;
-                     DECL_LANG_SPECIFIC (fndecl) = DECL_LANG_SPECIFIC (decl);
-                     fndecl = pushdecl (fndecl);
-                     DECL_INITIAL (fndecl) = error_mark_node;
-                     DECL_RTL (fndecl) = DECL_RTL (decl);
-                   }
-                 prev = parmtypes;
-                 parmtypes = TREE_CHAIN (parmtypes);
-               }
-             DECL_LANG_SPECIFIC (decl) = tmp_lang_decl;
-           }
-#endif
-       }
+       ;
       else if (DECL_EXTERNAL (decl))
        ;
       else if (TREE_STATIC (decl) && type != error_mark_node)
@@ -6775,13 +6720,13 @@ bad_specifiers (object, type, virtualp, quals, inlinep, friendp, raises)
    not look, and -1 if we should not call `grokclassfn' at all.  */
 static tree
 grokfndecl (ctype, type, declarator, virtualp, flags, quals,
-           raises, check, publicp)
+           raises, check, publicp, inlinep)
      tree ctype, type;
      tree declarator;
      int virtualp;
      enum overload_flags flags;
      tree quals, raises;
-     int check, publicp;
+     int check, publicp, inlinep;
 {
   tree cname, decl;
   int staticp = ctype && TREE_CODE (type) == FUNCTION_TYPE;
@@ -6814,10 +6759,21 @@ grokfndecl (ctype, type, declarator, virtualp, flags, quals,
      definition or EOF) if appropriate.  */
   TREE_PUBLIC (decl) = 1;
 
-  if (publicp)
-    ;
-  else
-    DECL_DECLARED_STATIC (decl) = 1;
+  if (ctype == NULL_TREE && ! strcmp (IDENTIFIER_POINTER (declarator), "main"))
+    {
+      if (inlinep)
+       error ("cannot declare `main' to be inline");
+      else if (! publicp)
+       error ("cannot declare `main' to be static");
+      inlinep = 0;
+      publicp = 1;
+    }
+         
+  if (! publicp)
+    DECL_C_STATIC (decl) = 1;
+
+  if (inlinep)
+    DECL_THIS_INLINE (decl) = DECL_INLINE (decl) = 1;
 
   DECL_EXTERNAL (decl) = 1;
   if (quals != NULL_TREE && TREE_CODE (type) == FUNCTION_TYPE)
@@ -9060,37 +9016,30 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, raises)
              }
 
            /* Tell grokfndecl if it needs to set TREE_PUBLIC on the node.  */
-           publicp = (RIDBIT_SETP (RID_EXTERN, specbits)
-                      || (ctype != NULL_TREE
-                          && funcdef_flag >= 0
-                          && RIDBIT_NOTSETP (RID_INLINE, specbits))
-                      || (friendp
-                          && ! funcdef_flag
-                          && RIDBIT_NOTSETP (RID_STATIC, specbits)
-                          && RIDBIT_NOTSETP (RID_INLINE, specbits)));
+           publicp = (! friendp
+                      || RIDBIT_SETP (RID_EXTERN, specbits)
+                      || ! (funcdef_flag < 0 || inlinep));
            decl = grokfndecl (ctype, type, declarator,
                               virtualp, flags, quals,
-                              raises, friendp ? -1 : 0, publicp);
+                              raises, friendp ? -1 : 0, publicp, inlinep);
            if (decl == NULL_TREE)
              return NULL_TREE;
            decl = build_decl_attribute_variant (decl, decl_machine_attr);
 
            if (explicitp == 2)
              DECL_NONCONVERTING_P (decl) = 1;
-
-           DECL_INLINE (decl) = inlinep;
          }
        else if (TREE_CODE (type) == METHOD_TYPE)
          {
+           /* We only get here for friend declarations of
+              members of other classes.  */
            /* All method decls are public, so tell grokfndecl to set
               TREE_PUBLIC, also.  */
            decl = grokfndecl (ctype, type, declarator,
                               virtualp, flags, quals,
-                              raises, friendp ? -1 : 0, 1);
+                              raises, friendp ? -1 : 0, 1, 0);
            if (decl == NULL_TREE)
              return NULL_TREE;
-
-           DECL_INLINE (decl) = inlinep;
          }
        else if (TYPE_SIZE (type) == NULL_TREE && !staticp
                 && (TREE_CODE (type) != ARRAY_TYPE || initialized == 0))
@@ -9255,16 +9204,16 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, raises)
          type = build_cplus_method_type (build_type_variant (ctype, constp, volatilep),
                                          TREE_TYPE (type), TYPE_ARG_TYPES (type));
 
-       /* Record presence of `static'.  In C++, `inline' is like `static'.  */
-       publicp
-         = !(RIDBIT_SETP (RID_STATIC, specbits)
-             || RIDBIT_SETP (RID_INLINE, specbits));
+       /* Record presence of `static'.  In C++, `inline' implies `static'.  */
+       publicp = (ctype != NULL_TREE
+                  || (!RIDBIT_SETP (RID_STATIC, specbits)
+                      && !RIDBIT_SETP (RID_INLINE, specbits)));
 
        decl = grokfndecl (ctype, type, original_name,
                           virtualp, flags, quals,
                           raises,
                           processing_template_decl ? 0 : friendp ? 2 : 1,
-                          publicp);
+                          publicp, inlinep);
        if (decl == NULL_TREE)
          return NULL_TREE;
 
@@ -9282,14 +9231,6 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, raises)
                cp_pedwarn ("cannot declare member function `%D' to have static linkage", decl);
                illegal_static = 1;
              }
-           else if (! ctype
-                    && IDENTIFIER_LENGTH (original_name) == 4
-                    && IDENTIFIER_POINTER (original_name)[0] == 'm'
-                    && ! strcmp (IDENTIFIER_POINTER (original_name), "main"))
-             {
-               error ("cannot declare function `main' to have static linkage");
-               illegal_static = 1;
-             }
            else if (current_function_decl)
              {
                /* FIXME need arm citation */
@@ -9303,28 +9244,6 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, raises)
                RIDBIT_RESET (RID_STATIC, specbits);
              }
          }
-
-       /* Record presence of `inline', if it is reasonable.  */
-       if (inlinep)
-         {
-           tree last = tree_last (TYPE_ARG_TYPES (type));
-
-           if (! ctype
-               && ! strcmp (IDENTIFIER_POINTER (original_name), "main"))
-             error ("cannot inline function `main'");
-           else if (last && last != void_list_node)
-             cp_warning ("cannot inline function `%D' which takes `...'", original_name);
-           else
-             /* Assume that otherwise the function can be inlined.  */
-             DECL_INLINE (decl) = 1;
-
-           if (RIDBIT_SETP (RID_EXTERN, specbits))
-             {
-               current_extern_inline = 1;
-               if (pedantic)
-                 pedwarn ("ANSI C++ does not permit `extern inline'");
-             }
-         }
       }
     else
       {
@@ -9398,6 +9317,9 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, raises)
     if (RIDBIT_SETP (RID_EXTERN, specbits))
       DECL_THIS_EXTERN (decl) = 1;
 
+    if (RIDBIT_SETP (RID_STATIC, specbits))
+      DECL_THIS_STATIC (decl) = 1;
+
     /* Record constancy and volatility.  */
 
     if (constp)
@@ -10723,7 +10645,6 @@ start_function (declspecs, declarator, raises, pre_parsed_p)
   current_function_returns_value = 0;
   current_function_returns_null = 0;
   warn_about_return_type = 0;
-  current_extern_inline = 0;
   current_function_assigns_this = 0;
   current_function_just_assigned_this = 0;
   current_function_parms_stored = 0;
@@ -10781,11 +10702,6 @@ start_function (declspecs, declarator, raises, pre_parsed_p)
            doing_friend = 1;
        }
 
-      if ( !(DECL_VINDEX (decl1)
-            && write_virtuals >= 2
-            && CLASSTYPE_VTABLE_NEEDS_WRITING (ctype)))
-       current_extern_inline = DECL_THIS_EXTERN (decl1) && DECL_INLINE (decl1);
-
       raises = TYPE_RAISES_EXCEPTIONS (fntype);
 
       /* In a fcn definition, arg types must be complete.  */
@@ -10890,18 +10806,21 @@ start_function (declspecs, declarator, raises, pre_parsed_p)
   TREE_STATIC (decl1) = 1;
 
   if (DECL_INTERFACE_KNOWN (decl1))
-    /* We know.  */;
+    {
+      if (DECL_NOT_REALLY_EXTERN (decl1))
+       DECL_EXTERNAL (decl1) = 0;
+    }
   /* If this function belongs to an interface, it is public.
      If it belongs to someone else's interface, it is also external.
      It doesn't matter whether it's inline or not.  */
   else if (interface_unknown == 0)
     {
-      if (DECL_DECLARED_STATIC (decl1) || DECL_TEMPLATE_INSTANTIATION (decl1))
+      if (DECL_THIS_INLINE (decl1) || DECL_TEMPLATE_INSTANTIATION (decl1))
        DECL_EXTERNAL (decl1)
          = (interface_only
-            || (DECL_INLINE (decl1) && ! flag_implement_inlines));
+            || (DECL_THIS_INLINE (decl1) && ! flag_implement_inlines));
       else
-       DECL_EXTERNAL (decl1) = current_extern_inline;
+       DECL_EXTERNAL (decl1) = 0;
       DECL_INTERFACE_KNOWN (decl1) = 1;
     }
   else
@@ -10909,19 +10828,15 @@ start_function (declspecs, declarator, raises, pre_parsed_p)
       /* This is a definition, not a reference.
         So clear DECL_EXTERNAL.  */
       DECL_EXTERNAL (decl1) = 0;
-      
-      if (DECL_INLINE (decl1) && (DECL_FUNCTION_MEMBER_P (decl1)
-                                 || DECL_TEMPLATE_INSTANTIATION (decl1)
-                                 || current_extern_inline))
-       /* We know nothing yet */;
+
+      if (DECL_THIS_INLINE (decl1) && ! DECL_C_STATIC (decl1))
+       DECL_DEFER_OUTPUT (decl1) = 1;
       else
        {
          DECL_INTERFACE_KNOWN (decl1) = 1;
-         if (DECL_DECLARED_STATIC (decl1))
+         if (DECL_C_STATIC (decl1))
            TREE_PUBLIC (decl1) = 0;
        }
-
-      DECL_DEFER_OUTPUT (decl1) = ! DECL_INTERFACE_KNOWN (decl1);
     }
 
   /* Record the decl so that the function name is defined.
@@ -11728,9 +11643,10 @@ finish_function (lineno, call_poplevel, nested)
   if (DECL_SAVED_INSNS (fndecl) && ! TREE_ASM_WRITTEN (fndecl))
     {
       /* Set DECL_EXTERNAL so that assemble_external will be called as
-         necessary.  We'll clear it again in import_export_inline.  */
-      if (TREE_PUBLIC (fndecl))
-       DECL_EXTERNAL (fndecl) = 1;
+         necessary.  We'll clear it again in finish_file.  */
+      if (! DECL_EXTERNAL (fndecl))
+       DECL_NOT_REALLY_EXTERN (fndecl) = 1;
+      DECL_EXTERNAL (fndecl) = 1;
       mark_inline_for_output (fndecl);
     }
 
@@ -11857,11 +11773,16 @@ start_method (declspecs, declarator, raises)
       return void_type_node;
     }
 
+  DECL_THIS_INLINE (fndecl) = 1;
+
   if (flag_default_inline)
     DECL_INLINE (fndecl) = 1;
 
   if (processing_template_defn)
-    SET_DECL_IMPLICIT_INSTANTIATION (fndecl);
+    {
+      SET_DECL_IMPLICIT_INSTANTIATION (fndecl);
+      repo_template_used (fndecl);
+    }
 
   /* We read in the parameters on the maybepermanent_obstack,
      but we won't be getting back to them until after we
@@ -12207,7 +12128,6 @@ struct cp_function
   int returns_value;
   int returns_null;
   int warn_about_return_type;
-  int extern_inline;
   int assigns_this;
   int just_assigned_this;
   int parms_stored;
@@ -12247,7 +12167,6 @@ push_cp_function_context (context)
   p->returns_value = current_function_returns_value;
   p->returns_null = current_function_returns_null;
   p->warn_about_return_type = warn_about_return_type;
-  p->extern_inline = current_extern_inline;
   p->binding_level = current_binding_level;
   p->ctor_label = ctor_label;
   p->dtor_label = dtor_label;
@@ -12295,7 +12214,6 @@ pop_cp_function_context (context)
   current_function_returns_value = p->returns_value;
   current_function_returns_null = p->returns_null;
   warn_about_return_type = p->warn_about_return_type;
-  current_extern_inline = p->extern_inline;
   current_binding_level = p->binding_level;
   ctor_label = p->ctor_label;
   dtor_label = p->dtor_label;
index 55ad97e0269dc44e179682a7244db371f36355d8..edce580237534a2ee5ca46462120b799588f37e4 100644 (file)
@@ -148,6 +148,10 @@ int warn_ctor_dtor_privacy = 1;
 
 int flag_vtable_thunks;
 
+/* True if we want to deal with repository information.  */
+
+int flag_use_repository;
+
 /* Nonzero means give string constants the type `const char *'
    to get extra warnings from them.  These warnings will be too numerous
    to be useful, except in thoroughly ANSIfied programs.  */
@@ -399,7 +403,8 @@ static struct { char *string; int *variable; int on_value;} lang_f_options[] =
   {"nonansi-builtins", &flag_no_nonansi_builtin, 0},
   {"gnu-keywords", &flag_no_gnu_keywords, 0},
   {"operator-names", &flag_operator_names, 1},
-  {"check-new", &flag_check_new, 1}
+  {"check-new", &flag_check_new, 1},
+  {"repo", &flag_use_repository, 1}
 };
 
 /* Decode the string P as a language-specific option.
@@ -2466,13 +2471,7 @@ mark_vtable_entries (decl)
            fnaddr = TREE_VALUE (entries);
          TREE_OPERAND (fnaddr, 0) = fn = abort_fndecl;
        }
-      if (TREE_PUBLIC (fn) && ! TREE_ASM_WRITTEN (fn))
-       {
-         int save_extern = DECL_EXTERNAL (fn);
-         DECL_EXTERNAL (fn) = 1;
-         assemble_external (fn);
-         DECL_EXTERNAL (fn) = save_extern;
-       }
+      assemble_external (fn);
     }
 }
 
@@ -2513,12 +2512,11 @@ import_export_vtable (decl, type, final)
 
       if (! found && ! final)
        {
-         /* This check only works before the method definitions are seen,
-            since DECL_INLINE may get bashed.  */
          tree method;
          for (method = CLASSTYPE_METHODS (type); method != NULL_TREE;
               method = DECL_NEXT_METHOD (method))
-           if (DECL_VINDEX (method) != NULL_TREE && ! DECL_INLINE (method)
+           if (DECL_VINDEX (method) != NULL_TREE
+               && ! DECL_THIS_INLINE (method)
                && ! DECL_ABSTRACT_VIRTUAL_P (method))
              {
                found = 1;
@@ -2528,15 +2526,17 @@ import_export_vtable (decl, type, final)
 
       if (final || ! found)
        {
+#ifdef ASSEMBLE_EXTERNAL
+         if (TREE_PUBLIC (decl))
+           cp_error ("all virtual functions redeclared inline");
+#endif
          TREE_PUBLIC (decl) = 0;
          DECL_EXTERNAL (decl) = 0;
-         DECL_INTERFACE_KNOWN (decl) = 1;
        }
       else
        {
          TREE_PUBLIC (decl) = 1;
          DECL_EXTERNAL (decl) = 1;
-         DECL_INTERFACE_KNOWN (decl) = 0;
        }
     }
 }
@@ -2570,7 +2570,7 @@ finish_prevtable_vardecl (prev, vars)
           method = DECL_NEXT_METHOD (method))
        {
          if (DECL_VINDEX (method) != NULL_TREE
-             && !DECL_DECLARED_STATIC (method)
+             && !DECL_THIS_INLINE (method)
              && !DECL_ABSTRACT_VIRTUAL_P (method))
            {
              SET_CLASSTYPE_INTERFACE_KNOWN (ctype);
@@ -2747,23 +2747,21 @@ import_export_inline (decl)
   if (DECL_INTERFACE_KNOWN (decl))
     return;
 
-  DECL_EXTERNAL (decl) = 0;
-
   if (DECL_TEMPLATE_INSTANTIATION (decl))
     {
       if (DECL_IMPLICIT_INSTANTIATION (decl) && flag_implicit_templates)
        TREE_PUBLIC (decl) = 0;
       else
-       DECL_EXTERNAL (decl) = 1;
+       DECL_NOT_REALLY_EXTERN (decl) = 0;
     }
   else if (DECL_FUNCTION_MEMBER_P (decl))
     {
       tree ctype = DECL_CLASS_CONTEXT (decl);
       if (CLASSTYPE_INTERFACE_KNOWN (ctype))
        {
-         DECL_EXTERNAL (decl)
-           = (CLASSTYPE_INTERFACE_ONLY (ctype)
-              || (DECL_INLINE (decl) && ! flag_implement_inlines));
+         DECL_NOT_REALLY_EXTERN (decl)
+           = (CLASSTYPE_INTERFACE_ONLY (ctype)
+                || (DECL_THIS_INLINE (decl) && ! flag_implement_inlines));
        }
       else
        TREE_PUBLIC (decl) = 0;
@@ -3045,6 +3043,8 @@ finish_file ()
       assemble_constructor (IDENTIFIER_POINTER (fnname));
     }
 
+  permanent_allocation (1);
+
   /* Done with C language context needs.  */
   pop_lang_context ();
 
@@ -3115,8 +3115,9 @@ finish_file ()
              {
                TREE_CHAIN (last) = TREE_CHAIN (place);
 
-               if (! DECL_EXTERNAL (decl))
+               if (DECL_NOT_REALLY_EXTERN (decl))
                  {
+                   DECL_EXTERNAL (decl) = 0;
                    reconsider = 1;
                    temporary_allocation ();
                    output_inline_function (decl);
@@ -3142,7 +3143,7 @@ finish_file ()
        emit_thunk (vars);
       else if (TREE_CODE (vars) == FUNCTION_DECL
               && ! DECL_INTERFACE_KNOWN (vars)
-              && DECL_DECLARED_STATIC (vars))
+              && DECL_C_STATIC (vars))
        TREE_PUBLIC (vars) = 0;
     }
 
@@ -3162,7 +3163,8 @@ finish_file ()
        }
     }
 
-  permanent_allocation (1);
+  finish_repo ();
+
   this_time = get_run_time ();
   parse_time -= this_time - start_time;
   varconst_time += this_time - start_time;
index 607d5034f2a55f3255912c7bd720c46b6f61345a..6c849fcdd5f10e9a42c78e9dfb5d330f9bc7cbf4 100644 (file)
@@ -780,9 +780,14 @@ init_exception_processing ()
   push_lang_context (lang_name_c);
 
   catch_match_fndecl =
-    define_function ("__throw_type_match",
-                    build_function_type (integer_type_node,
-                                         tree_cons (NULL_TREE, string_type_node, tree_cons (NULL_TREE, ptr_type_node, void_list_node))),
+    define_function (flag_rtti
+                    ? "__throw_type_match_rtti"
+                    : "__throw_type_match",
+                    build_function_type (ptr_type_node,
+                                         tree_cons (NULL_TREE, ptr_type_node,
+                                                    tree_cons (NULL_TREE, ptr_type_node,
+                                                               tree_cons (NULL_TREE, ptr_type_node,
+                                                                          void_list_node)))),
                     NOT_BUILT_IN,
                     pushdecl,
                     0);
@@ -1131,6 +1136,31 @@ expand_leftover_cleanups ()
     }
 }
 
+/* Build a type value for use at runtime for a exp that is thrown or
+   matched against by the exception handling system.  */
+static tree
+build_eh_type (exp)
+     tree exp;
+{
+  char *typestring;
+  tree type;
+
+  if (flag_rtti)
+    {
+      exp = build_typeid (exp);
+      return build1 (ADDR_EXPR, ptr_type_node, exp);
+    }
+  type = TREE_TYPE (exp);
+
+  /* peel back references, so they match. */
+  if (TREE_CODE (type) == REFERENCE_TYPE)
+    type = TREE_TYPE (type);
+
+  typestring = build_overload_name (type, 1, 1);
+  exp = combine_strings (build_string (strlen (typestring)+1, typestring));
+  return build1 (ADDR_EXPR, ptr_type_node, exp);
+}
+
 /* call this to start a catch block. Typename is the typename, and identifier
    is the variable to place the object in or NULL if the variable doesn't
    matter.  If typename is NULL, that means its a "catch (...)" or catch
@@ -1142,8 +1172,7 @@ expand_start_catch_block (declspecs, declarator)
 {
   rtx false_label_rtx;
   rtx protect_label_rtx;
-  tree type;
-  tree decl;
+  tree decl = NULL_TREE;
   tree init;
 
   if (! doing_eh (1))
@@ -1152,33 +1181,6 @@ expand_start_catch_block (declspecs, declarator)
   /* Create a binding level for the parm.  */
   expand_start_bindings (0);
 
-  if (declspecs)
-    {
-      tree init_type;
-      decl = grokdeclarator (declarator, declspecs, CATCHPARM, 1, NULL_TREE);
-
-      /* Figure out the type that the initializer is. */
-      init_type = TREE_TYPE (decl);
-      if (TREE_CODE (init_type) != REFERENCE_TYPE)
-       init_type = build_reference_type (init_type);
-
-      init = convert_from_reference (save_expr (make_tree (init_type, saved_throw_value)));
-      
-      /* Do we need the below two lines? */
-      /* Let `finish_decl' know that this initializer is ok.  */
-      DECL_INITIAL (decl) = init;
-      /* This needs to be preallocated under the try block,
-        in a union of all catch variables. */
-      pushdecl (decl);
-      type = TREE_TYPE (decl);
-
-      /* peel back references, so they match. */
-      if (TREE_CODE (type) == REFERENCE_TYPE)
-       type = TREE_TYPE (type);
-    }
-  else
-    type = NULL_TREE;
-
   /* These are saved for the exception table.  */
   push_rtl_perm ();
   false_label_rtx = gen_label_rtx ();
@@ -1187,34 +1189,50 @@ expand_start_catch_block (declspecs, declarator)
   push_label_entry (&false_label_stack, false_label_rtx);
   push_label_entry (&false_label_stack, protect_label_rtx);
 
-  if (type)
+  if (declspecs)
     {
-      tree params;
-      char *typestring;
+      tree exp;
       rtx call_rtx, return_value_rtx;
-      tree catch_match_fcall;
-      tree catchmatch_arg, argval;
-
-      typestring = build_overload_name (type, 1, 1);
-
-      params = tree_cons (NULL_TREE,
-                        combine_strings (build_string (strlen (typestring)+1, typestring)),
-                        tree_cons (NULL_TREE,
-                                   make_tree (ptr_type_node, saved_throw_type),
-                                   NULL_TREE));
-      catch_match_fcall = build_function_call (CatchMatch, params);
-      call_rtx = expand_call (catch_match_fcall, NULL_RTX, 0);
+      tree init_type;
+
+      decl = grokdeclarator (declarator, declspecs, CATCHPARM, 1, NULL_TREE);
+
+      if (decl == NULL_TREE)
+       {
+         error ("invalid catch parameter");
+         return;
+       }
+
+      /* Figure out the type that the initializer is. */
+      init_type = TREE_TYPE (decl);
+      if (TREE_CODE (init_type) != REFERENCE_TYPE)
+       init_type = build_reference_type (init_type);
+
+      exp = make_tree (ptr_type_node, saved_throw_value);
+      exp = tree_cons (NULL_TREE,
+                      build_eh_type (decl),
+                      tree_cons (NULL_TREE,
+                                 make_tree (ptr_type_node, saved_throw_type),
+                                 tree_cons (NULL_TREE, exp, NULL_TREE)));
+      exp = build_function_call (CatchMatch, exp);
+      call_rtx = expand_call (exp, NULL_RTX, 0);
       assemble_external (TREE_OPERAND (CatchMatch, 0));
 
-      return_value_rtx =
-       hard_function_value (integer_type_node, catch_match_fcall);
+      return_value_rtx = hard_function_value (ptr_type_node, exp);
 
       /* did the throw type match function return TRUE? */
-      emit_cmp_insn (return_value_rtx, const0_rtx, NE, NULL_RTX,
+      emit_cmp_insn (return_value_rtx, const0_rtx, EQ, NULL_RTX,
                    GET_MODE (return_value_rtx), 0, 0);
 
       /* if it returned FALSE, jump over the catch block, else fall into it */
-      emit_jump_insn (gen_bne (false_label_rtx));
+      emit_jump_insn (gen_beq (false_label_rtx));
+
+      init = convert_from_reference (save_expr (make_tree (init_type, call_rtx)));
+
+      /* Do we need the below two lines? */
+      /* Let `finish_decl' know that this initializer is ok.  */
+      DECL_INITIAL (decl) = init;
+      decl = pushdecl (decl);
       finish_decl (decl, init, NULL_TREE, 0, LOOKUP_ONLYCONVERTING);
     }
   else
@@ -1535,7 +1553,6 @@ expand_throw (exp)
      tree exp;
 {
   rtx label;
-  tree type;
 
   if (! doing_eh (1))
     return;
@@ -1548,26 +1565,28 @@ expand_throw (exp)
 
   if (exp)
     {
+      tree throw_type;
+      rtx throw_type_rtx;
+      rtx throw_value_rtx;
+
       /* throw expression */
       /* First, decay it. */
       exp = default_conversion (exp);
-      type = TREE_TYPE (exp);
 
-      {
-       char *typestring = build_overload_name (type, 1, 1);
-       tree throw_type = build1 (ADDR_EXPR, ptr_type_node, combine_strings (build_string (strlen (typestring)+1, typestring)));
-       rtx throw_type_rtx = expand_expr (throw_type, NULL_RTX, VOIDmode, 0);
-       rtx throw_value_rtx;
-
-       /* Make a copy of the thrown object.  WP 15.1.5  */
-       exp = build_new (NULL_TREE, type, build_tree_list (NULL_TREE, exp), 0);
-
-       if (exp == error_mark_node)
-         error ("  in thrown expression");
-       throw_value_rtx = expand_expr (exp, NULL_RTX, VOIDmode, 0);
-       emit_move_insn (saved_throw_value, throw_value_rtx);
-       emit_move_insn (saved_throw_type, throw_type_rtx);
-      }
+      /* Make a copy of the thrown object.  WP 15.1.5  */
+      exp = build_new (NULL_TREE, TREE_TYPE (exp),
+                      build_tree_list (NULL_TREE, exp),
+                      0);
+
+      if (exp == error_mark_node)
+       error ("  in thrown expression");
+
+      throw_type = build_eh_type (build_indirect_ref (exp, NULL_PTR));
+      throw_type_rtx = expand_expr (throw_type, NULL_RTX, VOIDmode, 0);
+
+      throw_value_rtx = expand_expr (exp, NULL_RTX, VOIDmode, 0);
+      emit_move_insn (saved_throw_value, throw_value_rtx);
+      emit_move_insn (saved_throw_type, throw_type_rtx);
     }
   else
     {
@@ -1665,6 +1684,7 @@ build_throw (e)
     {
       e = build1 (THROW_EXPR, void_type_node, e);
       TREE_SIDE_EFFECTS (e) = 1;
+      TREE_USED (e) = 1;
     }
   return e;
 }
index 895f2694e8776d3e1756740e5a46b46d612ad5ac..6d46976769a65c9e7cfd162fe4550ff7d526da54 100644 (file)
@@ -362,6 +362,7 @@ lang_init ()
   if (flag_cadillac)
     cadillac_start ();
   if (flag_gnu_xref) GNU_xref_begin (input_filename);
+  init_repo (input_filename);
 }
 
 void
@@ -1448,7 +1449,7 @@ store_pending_inline (decl, t)
             punt them now, or output them now if we're doing implementations
             and we know no overrides will exist.  Otherwise, we delay until
             end-of-file, to see if the definition is really required.  */
-         if (DECL_INLINE (decl))
+         if (DECL_THIS_INLINE (decl))
            /* delay_to_eof == 0 */;
          else if (current_class_type && !interface_unknown)
            {
index adbb97e0e503d22c47edc882a3aa80d20659d2b7..1bf168438ed9d01349be4ea2fe7118369e27a633 100644 (file)
@@ -1936,7 +1936,7 @@ emit_thunk (thunk_fndecl)
     emit_insn (gen_rtx (USE, VOIDmode, need_use[--need_use_count]));
 
   expand_end_bindings (NULL, 1, 0);
-  poplevel (0, 0, 0);
+  poplevel (0, 0, 1);
 
   /* From now on, allocate rtl in current_obstack, not in saveable_obstack.
      Note that that may have been done above, in save_for_inline_copying.
@@ -2122,6 +2122,7 @@ do_build_copy_constructor (fndecl)
            = tree_cons (DECL_NAME (fields), init, current_member_init_list);
        }
       current_member_init_list = nreverse (current_member_init_list);
+      current_base_init_list = nreverse (current_base_init_list);
       setup_vtbl_ptr ();
     }
 
index d8d7eb8ef2ed2b94423ab11dee00b94dac025878..a4bbd55bdfb40f0ab97e9ed45ca74f63e259d9f8 100644 (file)
@@ -897,6 +897,8 @@ template_instantiate_once:
                  pop_obstacks ();
                  end_template_instantiation ($1);
 
+                 repo_template_used (t);
+
                   /* Now go after the methods & class data.  */
                   instantiate_member_templates ($1);
 
index ce5e4f8515dfbe63575e82877725a3831030bdbc..5b5dceb796290818e106bceafdaf7ea2767ebb7e 100644 (file)
@@ -1450,6 +1450,7 @@ tsubst (t, args, nargs, in_decl)
        TREE_STATIC (r) = 0;
        DECL_INTERFACE_KNOWN (r) = 0;
        DECL_INLINE (r) = DECL_INLINE (t);
+       DECL_THIS_INLINE (r) = DECL_THIS_INLINE (t);
        {
 #if 0                          /* Maybe later.  -jason  */
          struct tinst_level *til = tinst_for_decl();
@@ -1751,6 +1752,7 @@ instantiate_template (tmpl, targ_ptr)
   else if (t->text)
     {
       SET_DECL_IMPLICIT_INSTANTIATION (fndecl);
+      repo_template_used (fndecl);
       p = (struct pending_inline *) permalloc (sizeof (struct pending_inline));
       p->parm_vec = t->parm_vec;
       p->bindings = targs;
@@ -2384,7 +2386,7 @@ do_pending_expansions ()
        DECIDE (0);
 
       if (DECL_EXPLICIT_INSTANTIATION (t))
-       DECIDE (! DECL_EXTERNAL (t));
+       DECIDE (DECL_NOT_REALLY_EXTERN (t));
       else if (! flag_implicit_templates)
        DECIDE (0);
 
@@ -2486,6 +2488,22 @@ add_pending_template (pt)
   p->id = pt;
 }
 
+void
+mark_function_instantiated (result, extern_p)
+     tree result;
+     int extern_p;
+{
+  if (DECL_TEMPLATE_INSTANTIATION (result))
+    SET_DECL_EXPLICIT_INSTANTIATION (result);
+  TREE_PUBLIC (result) = 1;
+
+  if (! extern_p)
+    {
+      DECL_INTERFACE_KNOWN (result) = 1;
+      DECL_NOT_REALLY_EXTERN (result) = 1;
+    }
+}
+
 /* called from the parser.  */
 void
 do_function_instantiation (declspecs, declarator, storage)
@@ -2495,10 +2513,17 @@ do_function_instantiation (declspecs, declarator, storage)
   tree name = DECL_NAME (decl);
   tree fn = IDENTIFIER_GLOBAL_VALUE (name);
   tree result = NULL_TREE;
+  int extern_p = 0;
   if (fn)
     {
       for (fn = get_first_fn (fn); fn; fn = DECL_CHAIN (fn))
-       if (TREE_CODE (fn) == TEMPLATE_DECL)
+       if (decls_match (fn, decl)
+           && DECL_DEFER_OUTPUT (fn))
+         {
+           result = fn;
+           break;
+         }
+       else if (TREE_CODE (fn) == TEMPLATE_DECL)
          {
            int ntparms = TREE_VEC_LENGTH (DECL_TEMPLATE_PARMS (fn));
            tree *targs = (tree *) malloc (sizeof (tree) * ntparms);
@@ -2518,27 +2543,40 @@ do_function_instantiation (declspecs, declarator, storage)
          }
     }
   if (! result)
-    cp_error ("no matching template for `%D' found", decl);
+    {
+      cp_error ("no matching template for `%D' found", decl);
+      return;
+    }
 
   if (flag_external_templates)
     return;
 
-  SET_DECL_EXPLICIT_INSTANTIATION (result);
-  TREE_PUBLIC (result) = 1;
-
   if (storage == NULL_TREE)
-    {
-      DECL_INTERFACE_KNOWN (result) = 1;
-      DECL_EXTERNAL (result) = 0;
-      TREE_STATIC (result) = 1;
-    }
-  else if (storage == ridpointers[(int) RID_EXTERN])
     ;
+  else if (storage == ridpointers[(int) RID_EXTERN])
+    extern_p = 1;
   else
     cp_error ("storage class `%D' applied to template instantiation",
              storage);
+  mark_function_instantiated (result, extern_p);
 }
 
+void
+mark_class_instantiated (t, extern_p)
+     tree t;
+     int extern_p;
+{
+  SET_CLASSTYPE_EXPLICIT_INSTANTIATION (t);
+  SET_CLASSTYPE_INTERFACE_KNOWN (t);
+  CLASSTYPE_INTERFACE_ONLY (t) = extern_p;
+  CLASSTYPE_VTABLE_NEEDS_WRITING (t) = ! extern_p;
+  TYPE_DECL_SUPPRESS_DEBUG (TYPE_NAME (t)) = extern_p;
+  if (! extern_p)
+    {
+      CLASSTYPE_DEBUG_REQUESTED (t) = 1;
+      rest_of_type_compilation (t, 1);
+    }
+}     
 void
 do_type_instantiation (name, storage)
      tree name, storage;
@@ -2578,18 +2616,7 @@ do_type_instantiation (name, storage)
     }
 
   if (! CLASSTYPE_TEMPLATE_SPECIALIZATION (t))
-    {
-      SET_CLASSTYPE_EXPLICIT_INSTANTIATION (t);
-      SET_CLASSTYPE_INTERFACE_KNOWN (t);
-      CLASSTYPE_INTERFACE_ONLY (t) = extern_p;
-      CLASSTYPE_VTABLE_NEEDS_WRITING (t) = ! extern_p;
-      TYPE_DECL_SUPPRESS_DEBUG (TYPE_NAME (t)) = extern_p;
-      if (! extern_p)
-       {
-         CLASSTYPE_DEBUG_REQUESTED (t) = 1;
-         rest_of_type_compilation (t, 1);
-       }
-    }
+    mark_class_instantiated (t, extern_p);
   
   {
     tree tmp;
@@ -2615,8 +2642,7 @@ do_type_instantiation (name, storage)
        if (! extern_p)
          {
            DECL_INTERFACE_KNOWN (tmp) = 1;
-           DECL_EXTERNAL (tmp) = 0;
-           TREE_STATIC (tmp) = 1;
+           DECL_NOT_REALLY_EXTERN (tmp) = 1;
          }
       }
 
diff --git a/gcc/cp/repo.c b/gcc/cp/repo.c
new file mode 100644 (file)
index 0000000..78c8ddd
--- /dev/null
@@ -0,0 +1,278 @@
+/* Code to maintain a C++ template repository.
+   Copyright (C) 1995 Free Software Foundation, Inc.
+   Contributed by Jason Merrill (jason@cygnus.com)
+
+This file is part of GNU CC.
+
+GNU CC is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU CC is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU CC; see the file COPYING.  If not, write to
+the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.  */
+
+/* My strategy here is as follows:
+
+   Everything should be emitted in a translation unit where it is used.
+   The results of the automatic process should be easily reproducible with
+   explicit code.
+
+   I'm thinking of compiling with -frepo, running a Perl script to update
+   files, and then being able to rebuild everything with -fno-implicit.
+   Full automation can come later.  */
+
+#include <stdio.h>
+#include "tree.h"
+#include "cp-tree.h"
+#include "input.h"
+
+extern char * rindex ();
+
+static tree pending_repo;
+static char repo_name[1024];
+static FILE *repo_file;
+
+extern int flag_use_repository;
+extern int errorcount, sorrycount;
+
+static int repo_changed;
+
+#define IDENTIFIER_REPO_USED(NODE)   (TREE_LANG_FLAG_3 (NODE))
+#define IDENTIFIER_REPO_CHOSEN(NODE) (TREE_LANG_FLAG_4 (NODE))
+
+/* Record the flags used to compile this translation unit.  */
+
+void
+repo_compile_flags (argc, argv)
+     int argc;
+     char **argv;
+{
+}
+
+/* If this template has not been seen before, add a note to the repository
+   saying where the declaration was.  This may be used to find the
+   definition at link time.  */
+
+void
+repo_template_declared (t)
+     tree t;
+{}
+
+/* Note where the definition of a template lives so that instantiations can
+   be generated later.  */
+
+void
+repo_template_defined (t)
+     tree t;
+{}
+
+/* Note where the definition of a class lives to that template
+   instantiations can use it.  */
+
+void
+repo_class_defined (t)
+     tree t;
+{}
+
+/* Note that a template has been used.  If we can see the definition, offer
+   to emit it. */
+
+void
+repo_template_used (t)
+     tree t;
+{
+  tree id;
+
+  if (! flag_use_repository)
+    return;
+
+  if (TREE_CODE_CLASS (TREE_CODE (t)) == 't')
+    {
+      id = DECL_ASSEMBLER_NAME (TYPE_MAIN_DECL (t));
+      if (IDENTIFIER_REPO_CHOSEN (id))
+       mark_class_instantiated (t, 0);
+    }
+  else if (TREE_CODE_CLASS (TREE_CODE (t)) == 'd')
+    {
+      id = DECL_ASSEMBLER_NAME (t);
+      if (IDENTIFIER_REPO_CHOSEN (id))
+       mark_function_instantiated (t, 0);
+    }
+  else
+    my_friendly_abort (1);
+
+  if (! IDENTIFIER_REPO_USED (id))
+    {
+      repo_changed = 1;
+      IDENTIFIER_REPO_USED (id) = 1;
+    }
+  pending_repo = perm_tree_cons (NULL_TREE, t, pending_repo);
+}
+
+/* Note that the vtable for a class has been used, and offer to emit it.  */
+
+void
+repo_vtable_used (t)
+     tree t;
+{
+  if (! flag_use_repository)
+    return;
+
+  pending_repo = perm_tree_cons (NULL_TREE, t, pending_repo);
+}
+
+/* Note that an inline with external linkage has been used, and offer to
+   emit it.  */
+
+void
+repo_inline_used (fn)
+     tree fn;
+{
+  if (! flag_use_repository)
+    return;
+
+  /* Member functions of polymorphic classes go with their vtables.  */
+  if (DECL_FUNCTION_MEMBER_P (fn) && TYPE_VIRTUAL_P (DECL_CLASS_CONTEXT (fn)))
+    {
+      repo_vtable_used (DECL_CLASS_CONTEXT (fn));
+      return;
+    }
+
+  pending_repo = perm_tree_cons (NULL_TREE, fn, pending_repo);
+}
+
+/* Note that a particular typeinfo node has been used, and offer to
+   emit it.  */
+
+void
+repo_tinfo_used (ti)
+     tree ti;
+{
+}
+
+static void
+open_repo_file (filename)
+     char *filename;
+{
+  register char *p, *q;
+  char *file = filename;
+  char *s = rindex (file, '/');
+  if (s == NULL)
+    s = file;
+  else
+    ++s;
+
+  for (p = repo_name, q = file; q < s; )
+    *p++ = *q++;
+  *p++ = '.';
+  strcpy (p, q);
+  strcat (p, ".repo");
+
+  repo_file = fopen (repo_name, "r");
+}
+
+void
+init_repo (filename)
+     char *filename;
+{
+  char buf[1024];
+
+  if (! flag_use_repository)
+    return;
+
+  open_repo_file (filename);
+
+  if (repo_file == 0)
+    return;
+
+  while (fgets (buf, 1024, repo_file))
+    {
+      int len = strlen (buf) - 1;
+      if (buf[len] != '\n')
+       error ("repository info line too long in %s", repo_name);
+      buf[len] = '\0';
+
+      switch (buf[0])
+       {
+       case 'A':
+       case 'M':
+         break;
+       case 'C':
+       case 'O':
+         {
+           tree id = get_identifier (&buf[2]);
+           IDENTIFIER_REPO_USED (id) = 1;
+           if (buf[0] == 'C')
+             IDENTIFIER_REPO_CHOSEN (id) = 1;
+         }
+         break;
+       default:
+         error ("mysterious repository information in %s", repo_name);
+       }
+    }
+}
+
+static void
+reopen_repo_file_for_write ()
+{
+  if (repo_file)
+    fclose (repo_file);
+  repo_file = fopen (repo_name, "w");
+
+  if (repo_file == 0)
+    {
+      error ("man't create repository information file `%s'", repo_name);
+      flag_use_repository = 0;
+    }
+}
+
+/* Emit any pending repos.  */
+
+void
+finish_repo ()
+{
+  tree t;
+  int changed = 0;
+
+  if (! flag_use_repository)
+    return;
+
+  /* Do we have to write out a new info file?  */
+
+  if (! repo_changed || errorcount || sorrycount)
+    goto out;
+
+  reopen_repo_file_for_write ();
+
+  if (repo_file == 0)
+    goto out;
+
+  for (t = pending_repo; t; t = TREE_CHAIN (t))
+    {
+      tree val = TREE_VALUE (t);
+      char type;
+
+      if (TREE_CODE_CLASS (TREE_CODE (val)) == 't')
+       val = TYPE_MAIN_DECL (val);
+      val = DECL_ASSEMBLER_NAME (val);
+
+      if (! IDENTIFIER_REPO_USED (val))
+       continue;
+      IDENTIFIER_REPO_USED (val) = 0;
+
+      type = IDENTIFIER_REPO_CHOSEN (val) ? 'C' : 'O';
+
+      fprintf (repo_file, "%c %s\n", type, IDENTIFIER_POINTER (val));
+    }
+
+ out:
+  if (repo_file)
+    fclose (repo_file);
+}
index 3e44bd2a3cf38e38360357cd5256dc7f9649f2c1..c0f2f2f87717ba2793a71f0d8ffe4da4cfde547b 100644 (file)
@@ -793,6 +793,10 @@ compute_access (basetype_path, field)
     }
 #endif
 
+  /* We don't currently support access control on nested types.  */
+  if (TREE_CODE (field) == TYPE_DECL)
+    return access_public;
+
   previous_scope = current_scope ();
   
   context = DECL_CLASS_CONTEXT (field);
index ff9bba1c3d218c07117c3d1e31045c63431a3a17..d83c3cba52e49b071bba4a51708e7e98fe8940de 100644 (file)
@@ -2880,7 +2880,7 @@ build_binary_op_nodefault (code, orig_op0, orig_op1, error_code)
   tree build_type = 0;
 
   /* Nonzero means after finally constructing the expression
-     give it this type.  Otherwise, give it type RESULT_TYPE.  */
+     convert it to this type.  */
   tree final_type = 0;
 
   /* Nonzero if this is an operation like MIN or MAX which can
@@ -3155,34 +3155,39 @@ build_binary_op_nodefault (code, orig_op0, orig_op1, error_code)
          else
            cp_pedwarn ("comparison of distinct pointer types `%T' and `%T' lacks a cast",
                        type0, type1);
+
+         if (result_type == NULL_TREE)
+           result_type = ptr_type_node;
        }
       else if (code0 == POINTER_TYPE && TREE_CODE (op1) == INTEGER_CST
               && integer_zerop (op1))
-       op1 = null_pointer_node;
+       result_type = type0;
       else if (code1 == POINTER_TYPE && TREE_CODE (op0) == INTEGER_CST
               && integer_zerop (op0))
-       op0 = null_pointer_node;
+       result_type = type1;
       else if (code0 == POINTER_TYPE && code1 == INTEGER_TYPE)
        {
+         result_type = type0;
          error ("ANSI C++ forbids comparison between pointer and integer");
-         op1 = convert (TREE_TYPE (op0), op1);
        }
       else if (code0 == INTEGER_TYPE && code1 == POINTER_TYPE)
        {
+         result_type = type1;
          error ("ANSI C++ forbids comparison between pointer and integer");
-         op0 = convert (TREE_TYPE (op1), op0);
        }
       else if (TYPE_PTRMEMFUNC_P (type0) && TREE_CODE (op1) == INTEGER_CST
               && integer_zerop (op1))
        {
          op0 = build_component_ref (op0, index_identifier, 0, 0);
          op1 = integer_zero_node;
+         result_type = TREE_TYPE (op0);
        }
       else if (TYPE_PTRMEMFUNC_P (type1) && TREE_CODE (op0) == INTEGER_CST
               && integer_zerop (op0))
        {
          op0 = build_component_ref (op1, index_identifier, 0, 0);
          op1 = integer_zero_node;
+         result_type = TREE_TYPE (op0);
        }
       else if (TYPE_PTRMEMFUNC_P (type0) && TYPE_PTRMEMFUNC_P (type1)
               && (TYPE_PTRMEMFUNC_FN_TYPE (type0)
@@ -3258,11 +3263,6 @@ build_binary_op_nodefault (code, orig_op0, orig_op1, error_code)
        {
          return build_binary_op (code, op1, op0, 1);
        }
-
-      type0 = TREE_TYPE (op0);
-      type1 = TREE_TYPE (op1);
-      if (result_type == NULL_TREE)
-       result_type = type0;
       break;
 
     case MAX_EXPR:
@@ -3272,29 +3272,15 @@ build_binary_op_nodefault (code, orig_op0, orig_op1, error_code)
        shorten = 1;
       else if (code0 == POINTER_TYPE && code1 == POINTER_TYPE)
        {
-         if (! comp_target_types (type0, type1, 1))
+         if (comp_target_types (type0, type1, 1))
+           result_type = common_type (type0, type1);
+         else
            {
              cp_pedwarn ("comparison of distinct pointer types `%T' and `%T' lacks a cast",
                          type0, type1);
              result_type = ptr_type_node;
            }
-#if 0
-         else if ((TYPE_SIZE (TREE_TYPE (type0)) != 0)
-                  != (TYPE_SIZE (TREE_TYPE (type1)) != 0))
-           cp_pedwarn ("comparison of %scomplete and %scomplete pointers",
-                       TYPE_SIZE (TREE_TYPE (type0)) == 0 ? "in" : "",
-                       TYPE_SIZE (TREE_TYPE (type1)) == 0 ? "in" : "",
-                       type0, type1);
-         else if (pedantic
-                  && TREE_CODE (TREE_TYPE (type0)) == FUNCTION_TYPE)
-           pedwarn ("ANSI C++ forbids ordered comparisons of pointers to functions");
-#endif
-         else
-           result_type = common_type (type0, type1);
        }
-
-      if (result_type == NULL_TREE)
-       result_type = type0;
       break;
 
     case LE_EXPR:
@@ -3307,50 +3293,37 @@ build_binary_op_nodefault (code, orig_op0, orig_op1, error_code)
        short_compare = 1;
       else if (code0 == POINTER_TYPE && code1 == POINTER_TYPE)
        {
-         if (! comp_target_types (type0, type1, 1))
-           cp_pedwarn ("comparison of distinct pointer types `%T' and `%T' lacks a cast",
-                       type0, type1);
-#if 0
-         else if ((TYPE_SIZE (TREE_TYPE (type0)) != 0)
-                  != (TYPE_SIZE (TREE_TYPE (type1)) != 0))
-           cp_pedwarn ("comparison of %scomplete and %scomplete pointers",
-                       TYPE_SIZE (TREE_TYPE (type0)) == 0 ? "in" : "",
-                       TYPE_SIZE (TREE_TYPE (type1)) == 0 ? "in" : "",
-                       type0, type1);
-         else if (pedantic 
-                  && TREE_CODE (TREE_TYPE (type0)) == FUNCTION_TYPE)
-           pedwarn ("ANSI C++ forbids ordered comparisons of pointers to functions");
-#endif
-         else
+         if (comp_target_types (type0, type1, 1))
            result_type = common_type (type0, type1);
+         else
+           {
+             cp_pedwarn ("comparison of distinct pointer types `%T' and `%T' lacks a cast",
+                         type0, type1);
+             result_type = ptr_type_node;
+           }
        }
       else if (code0 == POINTER_TYPE && TREE_CODE (op1) == INTEGER_CST
               && integer_zerop (op1))
-       op1 = null_pointer_node;
+       result_type = type0;
       else if (code1 == POINTER_TYPE && TREE_CODE (op0) == INTEGER_CST
               && integer_zerop (op0))
-       op0 = null_pointer_node;
+       result_type = type1;
       else if (code0 == POINTER_TYPE && code1 == INTEGER_TYPE)
        {
+         result_type = type0;
          if (pedantic)
            pedwarn ("ANSI C++ forbids comparison between pointer and integer");
          else if (! flag_traditional)
            warning ("comparison between pointer and integer");
-         op1 = convert (TREE_TYPE (op0), op1);
        }
       else if (code0 == INTEGER_TYPE && code1 == POINTER_TYPE)
        {
+         result_type = type1;
          if (pedantic)
            pedwarn ("ANSI C++ forbids comparison between pointer and integer");
          else if (! flag_traditional)
            warning ("comparison between pointer and integer");
-         op0 = convert (TREE_TYPE (op1), op0);
        }
-
-      type0 = TREE_TYPE (op0);
-      type1 = TREE_TYPE (op1);
-      if (result_type == NULL_TREE)
-       result_type = type0;
       break;
     }
 
@@ -3496,26 +3469,38 @@ build_binary_op_nodefault (code, orig_op0, orig_op1, error_code)
          int op0_signed = ! TREE_UNSIGNED (TREE_TYPE (orig_op0));
          int op1_signed = ! TREE_UNSIGNED (TREE_TYPE (orig_op1));
 
-         tree comp_type = TREE_TYPE (op0);
-
          int unsignedp0, unsignedp1;
          tree primop0 = get_narrower (op0, &unsignedp0);
          tree primop1 = get_narrower (op1, &unsignedp1);
 
          /* Give warnings for comparisons between signed and unsigned
-            quantities that may fail.  Do not warn if the signed quantity
-            is an unsuffixed integer literal (or some static constant
-            expression involving such literals) and it is positive.
-            Do not warn if the comparison is being done in a signed type,
-            since the signed type will only be chosen if it can represent
-            all the values of the unsigned type.  */
+            quantities that may fail.  */
          /* Do the checking based on the original operand trees, so that
             casts will be considered, but default promotions won't be.  */
-         if (TREE_UNSIGNED (comp_type)
-             && ((op0_signed && (TREE_CODE (orig_op0) != INTEGER_CST
-                                 || tree_int_cst_sgn (orig_op0) == -1))
-                 || (op1_signed && (TREE_CODE (orig_op1) != INTEGER_CST
-                                    || tree_int_cst_sgn (orig_op1) == -1))))
+
+         /* Do not warn if the comparison is being done in a signed type,
+            since the signed type will only be chosen if it can represent
+            all the values of the unsigned type.  */
+         if (! TREE_UNSIGNED (result_type))
+           /* OK */;
+         /* Do not warn if the signed quantity is an unsuffixed
+            integer literal (or some static constant expression
+            involving such literals) and it is non-negative.  */
+         else if ((op0_signed && TREE_CODE (orig_op0) == INTEGER_CST
+                   && tree_int_cst_sgn (orig_op0) >= 0)
+                  || (op1_signed && TREE_CODE (orig_op1) == INTEGER_CST
+                      && tree_int_cst_sgn (orig_op1) >= 0))
+           /* OK */;
+         /* Do not warn if the comparison is an equality operation,
+            the unsigned quantity is an integral constant and it does
+            not use the most significant bit of result_type.  */
+         else if ((resultcode == EQ_EXPR || resultcode == NE_EXPR)
+                  && ((op0_signed && TREE_CODE (orig_op1) == INTEGER_CST
+                       && int_fits_type_p (orig_op1, signed_type (result_type))
+                       || (op1_signed && TREE_CODE (orig_op0) == INTEGER_CST
+                           && int_fits_type_p (orig_op0, signed_type (result_type))))))
+           /* OK */;
+         else
            warning ("comparison between signed and unsigned");
 
          /* Warn if two unsigned values are being compared in a size
@@ -3526,8 +3511,8 @@ build_binary_op_nodefault (code, orig_op0, orig_op1, error_code)
             have all bits set that are set in the ~ operand when it is
             extended.  */
 
-         else if (TREE_CODE (primop0) == BIT_NOT_EXPR
-                  ^ TREE_CODE (primop1) == BIT_NOT_EXPR)
+         if (TREE_CODE (primop0) == BIT_NOT_EXPR
+             ^ TREE_CODE (primop1) == BIT_NOT_EXPR)
            {
              if (TREE_CODE (primop0) == BIT_NOT_EXPR)
                primop0 = get_narrower (TREE_OPERAND (op0, 0), &unsignedp0);
@@ -3556,7 +3541,7 @@ build_binary_op_nodefault (code, orig_op0, orig_op1, error_code)
                    }
 
                  bits = TYPE_PRECISION (TREE_TYPE (primop));
-                 if (bits < TYPE_PRECISION (comp_type)
+                 if (bits < TYPE_PRECISION (result_type)
                      && bits < HOST_BITS_PER_LONG && unsignedp)
                    {
                      mask = (~ (HOST_WIDE_INT) 0) << bits;
@@ -3566,9 +3551,9 @@ build_binary_op_nodefault (code, orig_op0, orig_op1, error_code)
                }
              else if (unsignedp0 && unsignedp1
                       && (TYPE_PRECISION (TREE_TYPE (primop0))
-                          < TYPE_PRECISION (comp_type))
+                          < TYPE_PRECISION (result_type))
                       && (TYPE_PRECISION (TREE_TYPE (primop1))
-                          < TYPE_PRECISION (comp_type)))
+                          < TYPE_PRECISION (result_type)))
                warning ("comparison of promoted ~unsigned with unsigned");
            }
        }
@@ -3582,7 +3567,8 @@ build_binary_op_nodefault (code, orig_op0, orig_op1, error_code)
 
   if (!result_type)
     {
-      binary_op_error (error_code);
+      cp_error ("invalid operands `%T' and `%T' to binary `%O'",
+               TREE_TYPE (orig_op0), TREE_TYPE (orig_op1), error_code);
       return error_mark_node;
     }
 
@@ -4467,7 +4453,7 @@ mark_addressable (exp)
           be non-zero in the case of processing a default function.
           The second may be non-zero in the case of a template function.  */
        x = DECL_MAIN_VARIANT (x);
-       if ((DECL_INLINE (x) || DECL_PENDING_INLINE_INFO (x))
+       if ((DECL_THIS_INLINE (x) || DECL_PENDING_INLINE_INFO (x))
            && (DECL_CONTEXT (x) == NULL_TREE
                || TREE_CODE_CLASS (TREE_CODE (DECL_CONTEXT (x))) != 't'
                || ! CLASSTYPE_INTERFACE_ONLY (DECL_CONTEXT (x))))