OSDN Git Service

* include/c_std/std_cmath.h: To prevent problems overloading
[pf3gnuchains/gcc-fork.git] / gcc / cp / decl.c
index 6fd9890..1739771 100644 (file)
@@ -46,6 +46,7 @@ Boston, MA 02111-1307, USA.  */
 #include "tm_p.h"
 #include "target.h"
 #include "c-common.h"
+#include "c-pragma.h"
 #include "diagnostic.h"
 
 extern const struct attribute_spec *lang_attribute_table;
@@ -86,6 +87,8 @@ static tree lookup_tag PARAMS ((enum tree_code, tree,
 static void set_identifier_type_value_with_scope
        PARAMS ((tree, tree, struct binding_level *));
 static void record_unknown_type PARAMS ((tree, const char *));
+static tree builtin_function_1 PARAMS ((const char *, tree, tree, int,
+                                      enum built_in_class, const char *));
 static tree build_library_fn_1 PARAMS ((tree, enum tree_code, tree));
 static int member_function_or_else PARAMS ((tree, tree, enum overload_flags));
 static void bad_specifiers PARAMS ((tree, const char *, int, int, int, int,
@@ -2500,6 +2503,7 @@ maybe_push_to_top_level (pseudo)
   s->bindings = b;
   s->need_pop_function_context = need_pop;
   s->function_decl = current_function_decl;
+  s->last_parms = last_function_parms;
 
   scope_chain = s;
   current_function_decl = NULL_TREE;
@@ -2541,6 +2545,7 @@ pop_from_top_level ()
   if (s->need_pop_function_context)
     pop_function_context_from (NULL_TREE);
   current_function_decl = s->function_decl;
+  last_function_parms = s->last_parms;
 
   free (s);
 }
@@ -3142,6 +3147,10 @@ duplicate_decls (newdecl, olddecl)
     {
       if (TREE_CODE (newdecl) != FUNCTION_DECL)
        {
+          /* Avoid warnings redeclaring anticipated built-ins.  */
+          if (DECL_ANTICIPATED (olddecl))
+            return 0;
+
          /* If you declare a built-in or predefined function name as static,
             the old definition is overridden, but optionally warn this was a
             bad choice of name.  */
@@ -3169,7 +3178,10 @@ duplicate_decls (newdecl, olddecl)
        }
       else if (!types_match)
        {
-         if ((DECL_EXTERN_C_P (newdecl)
+          /* Avoid warnings redeclaring anticipated built-ins.  */
+          if (DECL_ANTICIPATED (olddecl))
+            ;  /* Do nothing yet.  */
+         else if ((DECL_EXTERN_C_P (newdecl)
               && DECL_EXTERN_C_P (olddecl))
              || compparms (TYPE_ARG_TYPES (TREE_TYPE (newdecl)),
                            TYPE_ARG_TYPES (TREE_TYPE (olddecl))))
@@ -3344,6 +3356,7 @@ duplicate_decls (newdecl, olddecl)
                          && namespace_bindings_p ())
                         ? "`%#D' previously defined here"
                         : "`%#D' previously declared here", olddecl);
+         return 0;
        }
       else if (TREE_CODE (olddecl) == FUNCTION_DECL
               && DECL_INITIAL (olddecl) != NULL_TREE
@@ -3389,13 +3402,10 @@ duplicate_decls (newdecl, olddecl)
                if (1 == simple_cst_equal (TREE_PURPOSE (t1),
                                           TREE_PURPOSE (t2)))
                  {
-                   if (pedantic)
-                     {
-                       pedwarn ("default argument given for parameter %d of `%#D'",
-                                   i, newdecl);
-                       cp_pedwarn_at ("after previous specification in `%#D'",
-                                      olddecl);
-                     }
+                   pedwarn ("default argument given for parameter %d of `%#D'",
+                            i, newdecl);
+                   cp_pedwarn_at ("after previous specification in `%#D'",
+                                  olddecl);
                  }
                else
                  {
@@ -3484,6 +3494,7 @@ duplicate_decls (newdecl, olddecl)
      except for any that we copy here from the old type.  */
   DECL_ATTRIBUTES (newdecl)
     = (*targetm.merge_decl_attributes) (olddecl, newdecl);
+  decl_attributes (&newdecl, DECL_ATTRIBUTES (newdecl), 0);
 
   if (TREE_CODE (newdecl) == TEMPLATE_DECL)
     {
@@ -3515,16 +3526,16 @@ duplicate_decls (newdecl, olddecl)
       tree newtype;
 
       /* Merge the data types specified in the two decls.  */
-      newtype = common_type (TREE_TYPE (newdecl), TREE_TYPE (olddecl));
+      newtype = merge_types (TREE_TYPE (newdecl), TREE_TYPE (olddecl));
 
-      /* If common_type produces a non-typedef type, just use the old type.  */
+      /* If merge_types produces a non-typedef type, just use the old type.  */
       if (TREE_CODE (newdecl) == TYPE_DECL
          && newtype == DECL_ORIGINAL_TYPE (newdecl))
        newtype = oldtype;
 
       if (TREE_CODE (newdecl) == VAR_DECL)
        DECL_THIS_EXTERN (newdecl) |= DECL_THIS_EXTERN (olddecl);
-      /* Do this after calling `common_type' so that default
+      /* Do this after calling `merge_types' so that default
         parameters don't confuse us.  */
       else if (TREE_CODE (newdecl) == FUNCTION_DECL
          && (TYPE_RAISES_EXCEPTIONS (TREE_TYPE (newdecl))
@@ -3612,6 +3623,7 @@ duplicate_decls (newdecl, olddecl)
       TREE_READONLY (olddecl) = TREE_READONLY (newdecl);
       TREE_THIS_VOLATILE (olddecl) = TREE_THIS_VOLATILE (newdecl);
       TREE_SIDE_EFFECTS (olddecl) = TREE_SIDE_EFFECTS (newdecl);
+      COPY_DECL_RTL (newdecl, olddecl);
     }
 
   /* Merge the storage class information.  */
@@ -3782,7 +3794,7 @@ duplicate_decls (newdecl, olddecl)
       memcpy ((char *) olddecl + sizeof (struct tree_common),
              (char *) newdecl + sizeof (struct tree_common),
              sizeof (struct tree_decl) - sizeof (struct tree_common)
-             + tree_code_length [(int)TREE_CODE (newdecl)] * sizeof (char *));
+             + TREE_CODE_LENGTH (TREE_CODE (newdecl)) * sizeof (char *));
     }
 
   DECL_UID (olddecl) = olddecl_uid;
@@ -5346,7 +5358,7 @@ lookup_tag (form, name, binding_level, thislevel_only)
            if (old && DECL_ORIGINAL_TYPE (TYPE_NAME (old)))
              old = NULL_TREE;
            if (old && TREE_CODE (old) != form
-               && !(form != ENUMERAL_TYPE && TREE_CODE (old) == TEMPLATE_DECL))
+               && (form == ENUMERAL_TYPE || TREE_CODE (old) == ENUMERAL_TYPE))
              {
                error ("`%#D' redeclared as %C", old, form);
                return NULL_TREE;
@@ -5362,14 +5374,12 @@ lookup_tag (form, name, binding_level, thislevel_only)
            if (TREE_PURPOSE (tail) == name)
              {
                enum tree_code code = TREE_CODE (TREE_VALUE (tail));
-               /* Should tighten this up; it'll probably permit
-                  UNION_TYPE and a struct template, for example.  */
+               
                if (code != form
-                   && !(form != ENUMERAL_TYPE && code == TEMPLATE_DECL))
+                   && (form == ENUMERAL_TYPE || code == ENUMERAL_TYPE))
                  {
                    /* Definition isn't the kind we were looking for.  */
-                   error ("`%#D' redeclared as %C", TREE_VALUE (tail),
-                             form);
+                   error ("`%#D' redeclared as %C", TREE_VALUE (tail), form);
                    return NULL_TREE;
                  }
                return TREE_VALUE (tail);
@@ -5491,7 +5501,7 @@ lookup_namespace_name (namespace, name)
                                         /*in_decl=*/NULL_TREE,
                                         /*context=*/NULL_TREE,
                                         /*entering_scope=*/0,
-                                        /*complain=*/1);
+                                        tf_error | tf_warning);
          else if (DECL_FUNCTION_TEMPLATE_P (val)
                   || TREE_CODE (val) == OVERLOAD)
            val = lookup_template_function (val,
@@ -5507,7 +5517,12 @@ lookup_namespace_name (namespace, name)
       /* If we have a single function from a using decl, pull it out.  */
       if (TREE_CODE (val) == OVERLOAD && ! really_overloaded_fn (val))
        val = OVL_FUNCTION (val);
-      return val;
+
+      /* Ignore built-in functions that haven't been prototyped yet.  */
+      if (!val || !DECL_P(val)
+          || !DECL_LANG_SPECIFIC(val)
+          || !DECL_ANTICIPATED (val))
+        return val;
     }
 
   error ("`%D' undeclared in namespace `%D'", name, namespace);
@@ -5610,12 +5625,15 @@ build_typename_type (context, name, fullname, base_type)
 
 /* Resolve `typename CONTEXT::NAME'.  Returns an appropriate type,
    unless an error occurs, in which case error_mark_node is returned.
-   If COMPLAIN zero, don't complain about any errors that occur.  */
+   If we locate a non-artificial TYPE_DECL and TF_KEEP_TYPE_DECL is
+   set, we return that, rather than the _TYPE it corresponds to, in
+   other cases we look through the type decl.  If TF_ERROR is set,
+   complain about errors, otherwise be quiet.  */
 
 tree
 make_typename_type (context, name, complain)
      tree context, name;
-     int complain;
+     tsubst_flags_t complain;
 {
   tree fullname;
 
@@ -5654,7 +5672,7 @@ make_typename_type (context, name, complain)
     {
       /* We can get here from typename_sub0 in the explicit_template_type
         expansion.  Just fail.  */
-      if (complain)
+      if (complain & tf_error)
        error ("no class template named `%#T' in `%#T'",
                  name, context);
       return error_mark_node;
@@ -5670,7 +5688,7 @@ make_typename_type (context, name, complain)
            tmpl = lookup_field (context, name, 0, 0);
          if (!tmpl || !DECL_CLASS_TEMPLATE_P (tmpl))
            {
-             if (complain)
+             if (complain & tf_error)
                error ("no class template named `%#T' in `%#T'",
                          name, context);
              return error_mark_node;
@@ -5680,7 +5698,7 @@ make_typename_type (context, name, complain)
                                        TREE_OPERAND (fullname, 1),
                                        NULL_TREE, context,
                                        /*entering_scope=*/0,
-                                       /*complain=*/1);
+                                       tf_error | tf_warning);
        }
       else
        {
@@ -5688,14 +5706,18 @@ make_typename_type (context, name, complain)
 
          if (!IS_AGGR_TYPE (context))
            {
-             if (complain)
+             if (complain & tf_error)
                error ("no type named `%#T' in `%#T'", name, context);
              return error_mark_node;
            }
 
          t = lookup_field (context, name, 0, 1);
          if (t)
-           return TREE_TYPE (t);
+           {
+             if (DECL_ARTIFICIAL (t) || !(complain & tf_keep_type_decl))
+               t = TREE_TYPE (t);
+             return t;
+           }
        }
     }
 
@@ -5703,7 +5725,7 @@ make_typename_type (context, name, complain)
      there now or its never going to be.  */
   if (!uses_template_parms (context))
     {
-      if (complain)
+      if (complain & tf_error)
        error ("no type named `%#T' in `%#T'", name, context);
       return error_mark_node;
     }
@@ -5714,7 +5736,9 @@ make_typename_type (context, name, complain)
 
 /* Resolve `CONTEXT::template NAME'.  Returns an appropriate type,
    unless an error occurs, in which case error_mark_node is returned.
-   If COMPLAIN zero, don't complain about any errors that occur.  */
+   If we locate a TYPE_DECL, we return that, rather than the _TYPE it
+   corresponds to.  If COMPLAIN zero, don't complain about any errors
+   that occur.  */
 
 tree
 make_unbound_class_template (context, name, complain)
@@ -5777,14 +5801,6 @@ select_decl (binding, flags)
   tree val;
   val = BINDING_VALUE (binding);
 
-  /* When we implicitly declare some builtin entity, we mark it
-     DECL_ANTICIPATED, so that we know to ignore it until it is
-     really declared.  */
-  if (val && DECL_P (val)
-      && DECL_LANG_SPECIFIC (val)
-      && DECL_ANTICIPATED (val))
-    return NULL_TREE;
-
   if (LOOKUP_NAMESPACES_ONLY (flags))
     {
       /* We are not interested in types. */
@@ -5834,9 +5850,21 @@ unqualified_namespace_lookup (name, flags, spacesp)
        *spacesp = tree_cons (scope, NULL_TREE, *spacesp);
       val = binding_for_name (name, scope);
 
-      /* Initialize binding for this context. */
-      BINDING_VALUE (b) = BINDING_VALUE (val);
-      BINDING_TYPE (b) = BINDING_TYPE (val);
+      /* Ignore anticipated built-in functions.  */
+      if (val && BINDING_VALUE (val)
+          && DECL_P (BINDING_VALUE (val))
+          && DECL_LANG_SPECIFIC (BINDING_VALUE (val))
+          && DECL_ANTICIPATED (BINDING_VALUE (val)))
+        {
+          BINDING_VALUE (b) = NULL_TREE;
+          BINDING_TYPE (b) = NULL_TREE;
+        }
+      else
+        {
+          /* Initialize binding for this context. */
+          BINDING_VALUE (b) = BINDING_VALUE (val);
+          BINDING_TYPE (b) = BINDING_TYPE (val);
+        }
 
       /* Add all _DECLs seen through local using-directives. */
       for (level = current_binding_level;
@@ -6426,12 +6454,6 @@ cxx_init_decl_processing ()
       flag_inline_functions = 0;
     }
 
-  /* In C++, we never create builtin functions whose name does not
-     begin with `__'.  Users should be using headers to get prototypes
-     in C++.  It would be nice if we could warn when `-fbuiltin' is
-     used explicitly, but we do not have that information.  */
-  flag_no_builtin = 1;
-
   /* Initially, C.  */
   current_lang_name = lang_name_c;
 
@@ -6580,7 +6602,6 @@ cxx_init_decl_processing ()
 
   /* Perform other language dependent initializations.  */
   init_class_processing ();
-  init_init_processing ();
   init_search_processing ();
   init_rtti_processing ();
 
@@ -6602,8 +6623,8 @@ cxx_init_decl_processing ()
     flag_const_strings = 0;
 
   /* Add GC roots for all of our global variables.  */
-  ggc_add_tree_root (c_global_trees, sizeof c_global_trees / sizeof(tree));
-  ggc_add_tree_root (cp_global_trees, sizeof cp_global_trees / sizeof(tree));
+  ggc_add_tree_root (c_global_trees, ARRAY_SIZE (c_global_trees));
+  ggc_add_tree_root (cp_global_trees, ARRAY_SIZE (cp_global_trees));
   ggc_add_tree_root (&integer_three_node, 1);
   ggc_add_tree_root (&integer_two_node, 1);
   ggc_add_tree_root (&signed_size_zero_node, 1);
@@ -6696,10 +6717,9 @@ cp_make_fname_decl (id, type_dep)
   return decl;
 }
 
-/* Entry point for the benefit of c_common_nodes_and_builtins.
-
-   Make a definition for a builtin function named NAME and whose data type
-   is TYPE.  TYPE should be a function type with argument types.
+/* Make a definition for a builtin function named NAME in the current
+   namespace, whose data type is TYPE and whose context is CONTEXT.
+   TYPE should be a function type with argument types.
 
    CLASS and CODE tell later passes how to compile calls to this function.
    See tree.h for possible values.
@@ -6707,10 +6727,11 @@ cp_make_fname_decl (id, type_dep)
    If LIBNAME is nonzero, use that for DECL_ASSEMBLER_NAME,
    the name to be called if we can't opencode the function.  */
 
-tree
-builtin_function (name, type, code, class, libname)
+static tree
+builtin_function_1 (name, type, context, code, class, libname)
      const char *name;
      tree type;
+     tree context;
      int code;
      enum built_in_class class;
      const char *libname;
@@ -6718,19 +6739,13 @@ builtin_function (name, type, code, class, libname)
   tree decl = build_library_fn_1 (get_identifier (name), ERROR_MARK, type);
   DECL_BUILT_IN_CLASS (decl) = class;
   DECL_FUNCTION_CODE (decl) = code;
+  DECL_CONTEXT (decl) = context;
 
-  my_friendly_assert (DECL_CONTEXT (decl) == NULL_TREE, 392);
+  /* The return builtins leave the current function.  */
+  if (code == BUILT_IN_RETURN || code == BUILT_IN_EH_RETURN)
+    TREE_THIS_VOLATILE (decl) = 1;
 
-  /* All builtins that don't begin with an `_' should go in the `std'
-     namespace.  */
-  if (name[0] != '_')
-    {
-      push_namespace (std_identifier);
-      DECL_CONTEXT (decl) = std_node;
-    }
   pushdecl (decl);
-  if (name[0] != '_')
-    pop_namespace ();
 
   /* Since `pushdecl' relies on DECL_ASSEMBLER_NAME instead of DECL_NAME,
      we cannot change DECL_ASSEMBLER_NAME until we have installed this
@@ -6750,6 +6765,39 @@ builtin_function (name, type, code, class, libname)
   return decl;
 }
 
+/* Entry point for the benefit of c_common_nodes_and_builtins.
+
+   Make a defintion for a builtin function named NAME and whose data type
+   is TYPE.  TYPE should be a function type with argument types.  This
+   function places the anticipated declaration in the global namespace
+   and additionally in the std namespace if appropriate.
+
+   CLASS and CODE tell later passes how to compile calls to this function.
+   See tree.h for possible values.
+
+   If LIBNAME is nonzero, use that for DECL_ASSEMBLER_NAME,
+   the name to be called if we can't opencode the function.  */
+
+tree
+builtin_function (name, type, code, class, libname)
+     const char *name;
+     tree type;
+     int code;
+     enum built_in_class class;
+     const char *libname;
+{
+  /* All builtins that don't begin with an '_' should additionally
+     go in the 'std' namespace.  */
+  if (name[0] != '_')
+    {
+      push_namespace (std_identifier);
+      builtin_function_1 (name, type, std_node, code, class, libname);
+      pop_namespace ();
+    }
+
+  return builtin_function_1 (name, type, NULL_TREE, code, class, libname);
+}
+
 /* Generate a FUNCTION_DECL with the typical flags for a runtime library
    function.  Not called directly.  */
 
@@ -6874,7 +6922,7 @@ push_throw_library_fn (name, type)
    attributes.  */
 
 void
-insert_default_attributes (decl)
+cxx_insert_default_attributes (decl)
      tree decl;
 {
   if (!DECL_EXTERN_C_FUNCTION_P (decl))
@@ -7247,6 +7295,10 @@ start_decl (declarator, declspecs, initialized, attributes, prefix_attributes)
   /* Set attributes here so if duplicate decl, will have proper attributes.  */
   cplus_decl_attributes (&decl, attributes, 0);
 
+  /* If #pragma weak was used, mark the decl weak now.  */
+  if (current_binding_level == global_binding_level)
+    maybe_apply_pragma_weak (decl);
+
   if (TREE_CODE (decl) == FUNCTION_DECL
       && DECL_DECLARED_INLINE_P (decl)
       && DECL_UNINLINABLE (decl)
@@ -7847,18 +7899,21 @@ make_rtl_for_nonlocal_decl (decl, init, asmspec)
      DECL_STMT is expanded.  */
   defer_p = DECL_FUNCTION_SCOPE_P (decl) || DECL_VIRTUAL_P (decl);
 
-  /* We try to defer namespace-scope static constants so that they are
-     not emitted into the object file unnecessarily.  */
-  if (!DECL_VIRTUAL_P (decl)
-      && TREE_READONLY (decl)
-      && DECL_INITIAL (decl) != NULL_TREE
-      && DECL_INITIAL (decl) != error_mark_node
-      && ! EMPTY_CONSTRUCTOR_P (DECL_INITIAL (decl))
-      && toplev
-      && !TREE_PUBLIC (decl))
-    {
-      /* Fool with the linkage according to #pragma interface.  */
-      if (!interface_unknown)
+  /* We try to defer namespace-scope static constants and template
+     instantiations so that they are not emitted into the object file
+     unnecessarily.  */
+  if ((!DECL_VIRTUAL_P (decl)
+       && TREE_READONLY (decl)
+       && DECL_INITIAL (decl) != NULL_TREE
+       && DECL_INITIAL (decl) != error_mark_node
+       && ! EMPTY_CONSTRUCTOR_P (DECL_INITIAL (decl))
+       && toplev
+       && !TREE_PUBLIC (decl))
+      || DECL_COMDAT (decl))
+    {
+      /* Fool with the linkage of static consts according to #pragma
+        interface.  */
+      if (!interface_unknown && !TREE_PUBLIC (decl))
        {
          TREE_PUBLIC (decl) = 1;
          DECL_EXTERNAL (decl) = interface_only;
@@ -8015,11 +8070,10 @@ destroy_local_var (decl)
     return;
 
   /* Compute the cleanup.  */
-  cleanup = maybe_build_cleanup (decl);
+  cleanup = cxx_maybe_build_cleanup (decl);
 
   /* Record the cleanup required for this declaration.  */
-  if (DECL_SIZE (decl) && TREE_TYPE (decl) != error_mark_node
-      && cleanup)
+  if (DECL_SIZE (decl) && cleanup)
     finish_decl_cleanup (decl, cleanup);
 }
 
@@ -8053,8 +8107,10 @@ cp_finish_decl (decl, init, asmspec_tree, flags)
     }
 
   /* If a name was specified, get the string.  */
+  if (current_binding_level == global_binding_level)
+    asmspec_tree = maybe_apply_renaming_pragma (decl, asmspec_tree);
   if (asmspec_tree)
-      asmspec = TREE_STRING_POINTER (asmspec_tree);
+    asmspec = TREE_STRING_POINTER (asmspec_tree);
 
   if (init && TREE_CODE (init) == NAMESPACE_DECL)
     {
@@ -9603,9 +9659,6 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, attrlist)
   tree spec;
   tree type = NULL_TREE;
   int longlong = 0;
-  int constp;
-  int restrictp;
-  int volatilep;
   int type_quals;
   int virtualp, explicitp, friendp, inlinep, staticp;
   int explicit_int = 0;
@@ -10069,7 +10122,6 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, attrlist)
                }
            }
        }
-      /* C++ aggregate types.  */
       else if (TREE_CODE (id) == TYPE_DECL)
        {
          if (type)
@@ -10079,6 +10131,7 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, attrlist)
            {
              type = TREE_TYPE (id);
              TREE_VALUE (spec) = type;
+             typedef_decl = id;
            }
          goto found;
        }
@@ -10093,10 +10146,6 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, attrlist)
          else
            {
              type = TREE_TYPE (t);
-#if 0
-             /* See the code below that used this.  */
-             decl_attr = DECL_ATTRIBUTES (id);
-#endif
              typedef_decl = t;
            }
        }
@@ -10107,6 +10156,11 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, attrlist)
     found: ;
     }
 
+#if 0
+  /* See the code below that used this.  */
+  if (typedef_decl)
+    decl_attr = DECL_ATTRIBUTES (typedef_decl);
+#endif
   typedef_type = type;
 
   /* No type at all: default to `int', and set DEFAULTED_INT
@@ -10153,7 +10207,7 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, attrlist)
       type = integer_type_node;
     }
   
-  if (type && TREE_CODE (type) == TYPENAME_TYPE && TREE_TYPE (type))
+  if (type && IMPLICIT_TYPENAME_P (type))
     {
       /* The implicit typename extension is deprecated and will be
         removed.  Warn about its use now.  */
@@ -10310,26 +10364,24 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, attrlist)
        type = build_complex_type (type);
     }
 
-  if (sfk == sfk_conversion
-      && (RIDBIT_SETP (RID_CONST, specbits)
-         || RIDBIT_SETP (RID_VOLATILE, specbits)
-         || RIDBIT_SETP (RID_RESTRICT, specbits)))
+  type_quals = TYPE_UNQUALIFIED;
+  if (RIDBIT_SETP (RID_CONST, specbits))
+    type_quals |= TYPE_QUAL_CONST;
+  if (RIDBIT_SETP (RID_VOLATILE, specbits))
+    type_quals |= TYPE_QUAL_VOLATILE;
+  if (RIDBIT_SETP (RID_RESTRICT, specbits))
+    type_quals |= TYPE_QUAL_RESTRICT;
+  if (sfk == sfk_conversion && type_quals != TYPE_UNQUALIFIED)
     error ("qualifiers are not allowed on declaration of `operator %T'",
              ctor_return_type);
 
-  /* Set CONSTP if this declaration is `const', whether by
-     explicit specification or via a typedef.
-     Likewise for VOLATILEP.  */
-
-  constp = !! RIDBIT_SETP (RID_CONST, specbits) + CP_TYPE_CONST_P (type);
-  restrictp =
-    !! RIDBIT_SETP (RID_RESTRICT, specbits) + CP_TYPE_RESTRICT_P (type);
-  volatilep =
-    !! RIDBIT_SETP (RID_VOLATILE, specbits) + CP_TYPE_VOLATILE_P (type);
-  type_quals = ((constp ? TYPE_QUAL_CONST : 0)
-               | (restrictp ? TYPE_QUAL_RESTRICT : 0)
-               | (volatilep ? TYPE_QUAL_VOLATILE : 0));
-  type = cp_build_qualified_type (type, type_quals);
+  type_quals |= cp_type_quals (type);
+  type = cp_build_qualified_type_real
+    (type, type_quals, ((typedef_decl && !DECL_ARTIFICIAL (typedef_decl)
+                        ? tf_ignore_bad_quals : 0) | tf_error | tf_warning));
+  /* We might have ignored or rejected some of the qualifiers.  */
+  type_quals = cp_type_quals (type);
+  
   staticp = 0;
   inlinep = !! RIDBIT_SETP (RID_INLINE, specbits);
   virtualp = RIDBIT_SETP (RID_VIRTUAL, specbits);
@@ -10822,21 +10874,30 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, attrlist)
            {
              register tree typemodlist;
              int erred = 0;
-
-             constp = 0;
-             volatilep = 0;
-             restrictp = 0;
+             int constp = 0;
+             int volatilep = 0;
+             int restrictp = 0;
+             
              for (typemodlist = TREE_TYPE (declarator); typemodlist;
                   typemodlist = TREE_CHAIN (typemodlist))
                {
                  tree qualifier = TREE_VALUE (typemodlist);
 
                  if (qualifier == ridpointers[(int) RID_CONST])
-                   constp++;
+                   {
+                     constp++;
+                     type_quals |= TYPE_QUAL_CONST;
+                   }
                  else if (qualifier == ridpointers[(int) RID_VOLATILE])
-                   volatilep++;
+                   {
+                     volatilep++;
+                     type_quals |= TYPE_QUAL_VOLATILE;
+                   }
                  else if (qualifier == ridpointers[(int) RID_RESTRICT])
-                   restrictp++;
+                   {
+                     restrictp++;
+                     type_quals |= TYPE_QUAL_RESTRICT;
+                   }
                  else if (!erred)
                    {
                      erred = 1;
@@ -10849,20 +10910,8 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, attrlist)
                pedwarn ("duplicate `volatile'");
              if (restrictp > 1)
                pedwarn ("duplicate `restrict'");
-
-             type_quals = ((constp ? TYPE_QUAL_CONST : 0)
-                           | (restrictp ? TYPE_QUAL_RESTRICT : 0)
-                           | (volatilep ? TYPE_QUAL_VOLATILE : 0));
-             if (TREE_CODE (declarator) == ADDR_EXPR
-                 && (constp || volatilep))
-               {
-                 if (constp)
-                   pedwarn ("discarding `const' applied to a reference");
-                 if (volatilep)
-                   pedwarn ("discarding `volatile' applied to a reference");
-                 type_quals &= ~(TYPE_QUAL_CONST | TYPE_QUAL_VOLATILE);
-               }
              type = cp_build_qualified_type (type, type_quals);
+             type_quals = cp_type_quals (type);
            }
          declarator = TREE_OPERAND (declarator, 0);
          ctype = NULL_TREE;
@@ -10906,7 +10955,8 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, attrlist)
                    && uses_template_parms (current_class_type))
                  {
                    tree args = current_template_args ();
-                   type = tsubst (type, args, /*complain=*/1, NULL_TREE);
+                   type = tsubst (type, args, tf_error | tf_warning,
+                                  NULL_TREE);
                  }
 
                /* This pop_nested_class corresponds to the
@@ -11105,7 +11155,7 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, attrlist)
       else if (type_quals & TYPE_QUAL_CONST)
        {
          error ("const `%s' cannot be declared `mutable'", name);
-         RIDBIT_RESET (RID_MUTABLE, specbits);
+         RIDBIT_RESET (RID_MUTABLE, specbits);
        }
     }
 
@@ -11216,16 +11266,13 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, attrlist)
 
   /* Detect the case of an array type of unspecified size
      which came, as such, direct from a typedef name.
-     We must copy the type, so that each identifier gets
-     a distinct type, so that each identifier's size can be
-     controlled separately by its own initializer.  */
+     We must copy the type, so that the array's domain can be
+     individually set by the object's initializer.  */
 
-  if (type != 0 && typedef_type != 0
-      && TREE_CODE (type) == ARRAY_TYPE && TYPE_DOMAIN (type) == 0
+  if (type && typedef_type
+      && TREE_CODE (type) == ARRAY_TYPE && !TYPE_DOMAIN (type)
       && TYPE_MAIN_VARIANT (type) == TYPE_MAIN_VARIANT (typedef_type))
-    {
-      type = build_cplus_array_type (TREE_TYPE (type), TYPE_DOMAIN (type));
-    }
+    type = build_cplus_array_type (TREE_TYPE (type), NULL_TREE);
 
   /* Detect where we're using a typedef of function type to declare a
      function. last_function_parms will not be set, so we must create
@@ -11292,9 +11339,7 @@ friend declaration requires class-key, i.e. `friend %#T'",
          /* Only try to do this stuff if we didn't already give up.  */
          if (type != integer_type_node)
            {
-             /* DR 209. The friendly class does not need to be accessible
-                 in the scope of the class granting friendship. */
-             skip_type_access_control ();
+             decl_type_access_control (TYPE_NAME (type));
 
              /* A friendly class?  */
              if (current_class_type)
@@ -11556,33 +11601,32 @@ friend declaration requires class-key, i.e. `friend %#T'",
        if (friendp)
          {
            /* Friends are treated specially.  */
-            tree t = NULL_TREE;
-           
-           /* DR 209. The friend does not need to be accessible at this
-               point. */
-           skip_type_access_control ();
-           
            if (ctype == current_class_type)
              warning ("member functions are implicitly friends of their class");
-
-            if (decl && DECL_NAME (decl))
-              {
-                if (template_class_depth (current_class_type) == 0)
-                  {
-                   decl = check_explicit_specialization
-                           (declarator, decl,
-                            template_count, 2 * (funcdef_flag != 0) + 4);
-                   if (decl == error_mark_node)
-                     return error_mark_node;
-                  }
-              
-                t = do_friend (ctype, declarator, decl,
-                              last_function_parms, *attrlist, flags, quals,
-                              funcdef_flag);
-              }
-            if (t && funcdef_flag)
-              return t;
-           return void_type_node;
+           else
+             {
+               tree t = NULL_TREE;
+               if (decl && DECL_NAME (decl))
+                 {
+                   if (template_class_depth (current_class_type) == 0)
+                     {
+                       decl
+                         = check_explicit_specialization
+                         (declarator, decl,
+                          template_count, 2 * (funcdef_flag != 0) + 4);
+                       if (decl == error_mark_node)
+                         return error_mark_node;
+                     }
+                   
+                   t = do_friend (ctype, declarator, decl,
+                                  last_function_parms, *attrlist,
+                                  flags, quals, funcdef_flag);
+                 }
+               if (t && funcdef_flag)
+                 return t;
+  
+               return void_type_node;
+             }
          }
 
        /* Structure field.  It may not be a function, except for C++ */
@@ -12860,19 +12904,6 @@ xref_tag (code_type_node, name, globalize)
        redeclare_class_template (ref, current_template_parms);
     }
 
-  /* Until the type is defined, tentatively accept whatever
-     structure tag the user hands us.  */
-  if (!COMPLETE_TYPE_P (ref)
-      && ref != current_class_type
-      /* Have to check this, in case we have contradictory tag info.  */
-      && IS_AGGR_TYPE_CODE (TREE_CODE (ref)))
-    {
-      if (tag_code == class_type)
-       CLASSTYPE_DECLARED_CLASS (ref) = 1;
-      else if (tag_code == record_type)
-       CLASSTYPE_DECLARED_CLASS (ref) = 0;
-    }
-
   TYPE_ATTRIBUTES (ref) = attributes;
 
   return ref;
@@ -13115,9 +13146,6 @@ start_enum (name)
       pushtag (name, enumtype, 0);
     }
 
-  if (current_class_type)
-    TREE_ADDRESSABLE (b->tags) = 1;
-
   return enumtype;
 }
 
@@ -13492,6 +13520,10 @@ start_function (declspecs, declarator, attrs, flags)
 
       cplus_decl_attributes (&decl1, attrs, 0);
 
+      /* If #pragma weak was used, mark the decl weak now.  */
+      if (current_binding_level == global_binding_level)
+       maybe_apply_pragma_weak (decl1);
+
       fntype = TREE_TYPE (decl1);
 
       restype = TREE_TYPE (fntype);
@@ -14221,15 +14253,16 @@ finish_function (flags)
     DECL_UNINLINABLE (fndecl) = 1;
 
   /* Complain if there's just no return statement.  */
-  if (!processing_template_decl
+  if (warn_return_type
+      && !processing_template_decl
       && TREE_CODE (TREE_TYPE (fntype)) != VOID_TYPE
-      && !current_function_returns_value
-      && !DECL_NAME (DECL_RESULT (fndecl))
+      && !current_function_returns_value && !current_function_returns_null
       /* Don't complain if we abort or throw.  */
       && !current_function_returns_abnormally
-      /* If we have -Wreturn-type, let flow complain.  Unless we're an
+      && !DECL_NAME (DECL_RESULT (fndecl))
+      /* Normally, with -Wreturn-type, flow will complain.  Unless we're an
         inline function, as we might never be compiled separately.  */
-      && (!warn_return_type || DECL_INLINE (fndecl)))
+      && DECL_INLINE (fndecl))
     warning ("no return statement in function returning non-void");
     
   /* Clear out memory we no longer need.  */
@@ -14454,7 +14487,7 @@ hack_incomplete_structures (type)
                {
                  tree cleanup;
                  expand_decl (decl);
-                 cleanup = maybe_build_cleanup (decl);
+                 cleanup = cxx_maybe_build_cleanup (decl);
                  expand_decl_init (decl);
                  if (! expand_decl_cleanup (decl, cleanup))
                    error ("parser lost in parsing declaration of `%D'",
@@ -14482,7 +14515,7 @@ hack_incomplete_structures (type)
    here.  */
 
 tree
-maybe_build_cleanup (decl)
+cxx_maybe_build_cleanup (decl)
      tree decl;
 {
   tree type = TREE_TYPE (decl);
@@ -14515,7 +14548,7 @@ maybe_build_cleanup (decl)
 
       return rval;
     }
-  return 0;
+  return NULL_TREE;
 }
 \f
 /* When a stmt has been parsed, this function is called.  */
@@ -14627,7 +14660,7 @@ mark_cp_function_context (f)
 }
 
 void
-lang_mark_tree (t)
+cxx_mark_tree (t)
      tree t;
 {
   enum tree_code code = TREE_CODE (t);