re PR c++/54738 ([C++11][SFINAE] Hard errors for pointer-to-member function expressions)
[gcc.git] / gcc / cp / decl2.c
index 2fd63056016768217655a091672eb21794bf167a..4cff0516d776060e0fede79ea70f9104fbbbb9db 100644 (file)
@@ -1,7 +1,7 @@
 /* Process declarations and variables for C++ compiler.
    Copyright (C) 1988, 1992, 1993, 1994, 1995, 1996, 1997, 1998,
 /* Process declarations and variables for C++ compiler.
    Copyright (C) 1988, 1992, 1993, 1994, 1995, 1996, 1997, 1998,
-   1999, 2000, 2001, 2002, 2003, 2004, 2005, 2007, 2008, 2009
-   Free Software Foundation, Inc.
+   1999, 2000, 2001, 2002, 2003, 2004, 2005, 2007, 2008, 2009, 2010,
+   2011, 2012 Free Software Foundation, Inc.
    Hacked by Michael Tiemann (tiemann@cygnus.com)
 
 This file is part of GCC.
    Hacked by Michael Tiemann (tiemann@cygnus.com)
 
 This file is part of GCC.
@@ -33,26 +33,25 @@ along with GCC; see the file COPYING3.  If not see
 #include "coretypes.h"
 #include "tm.h"
 #include "tree.h"
 #include "coretypes.h"
 #include "tm.h"
 #include "tree.h"
-#include "rtl.h"
-#include "expr.h"
 #include "flags.h"
 #include "cp-tree.h"
 #include "decl.h"
 #include "flags.h"
 #include "cp-tree.h"
 #include "decl.h"
-#include "output.h"
-#include "except.h"
 #include "toplev.h"
 #include "timevar.h"
 #include "cpplib.h"
 #include "target.h"
 #include "toplev.h"
 #include "timevar.h"
 #include "cpplib.h"
 #include "target.h"
-#include "c-common.h"
-#include "tree-mudflap.h"
+#include "c-family/c-common.h"
+#include "c-family/c-objc.h"
 #include "cgraph.h"
 #include "tree-inline.h"
 #include "cgraph.h"
 #include "tree-inline.h"
-#include "c-pragma.h"
-#include "tree-dump.h"
+#include "c-family/c-pragma.h"
+#include "dumpfile.h"
 #include "intl.h"
 #include "gimple.h"
 #include "pointer-set.h"
 #include "intl.h"
 #include "gimple.h"
 #include "pointer-set.h"
+#include "splay-tree.h"
+#include "langhooks.h"
+#include "c-family/c-ada-spec.h"
 
 extern cpp_reader *parse_in;
 
 
 extern cpp_reader *parse_in;
 
@@ -85,6 +84,7 @@ static void write_out_vars (tree);
 static void import_export_class (tree);
 static tree get_guard_bits (tree);
 static void determine_visibility_from_class (tree, tree);
 static void import_export_class (tree);
 static tree get_guard_bits (tree);
 static void determine_visibility_from_class (tree, tree);
+static bool determine_hidden_inline (tree);
 static bool decl_defined_p (tree);
 
 /* A list of static class variables.  This is needed, because a
 static bool decl_defined_p (tree);
 
 /* A list of static class variables.  This is needed, because a
@@ -150,6 +150,9 @@ change_return_type (tree new_ret, tree fntype)
   tree raises = TYPE_RAISES_EXCEPTIONS (fntype);
   tree attrs = TYPE_ATTRIBUTES (fntype);
 
   tree raises = TYPE_RAISES_EXCEPTIONS (fntype);
   tree attrs = TYPE_ATTRIBUTES (fntype);
 
+  if (new_ret == error_mark_node)
+    return fntype;
+
   if (same_type_p (new_ret, TREE_TYPE (fntype)))
     return fntype;
 
   if (same_type_p (new_ret, TREE_TYPE (fntype)))
     return fntype;
 
@@ -160,8 +163,7 @@ change_return_type (tree new_ret, tree fntype)
     }
   else
     newtype = build_method_type_directly
     }
   else
     newtype = build_method_type_directly
-      (TREE_TYPE (TREE_VALUE (TYPE_ARG_TYPES (fntype))),
-       new_ret, TREE_CHAIN (args));
+      (class_of_this_parm (fntype), new_ret, TREE_CHAIN (args));
   if (raises)
     newtype = build_exception_variant (newtype, raises);
   if (attrs)
   if (raises)
     newtype = build_exception_variant (newtype, raises);
   if (attrs)
@@ -242,7 +244,7 @@ maybe_retrofit_in_chrg (tree fn)
   basetype = TREE_TYPE (TREE_VALUE (arg_types));
   arg_types = TREE_CHAIN (arg_types);
 
   basetype = TREE_TYPE (TREE_VALUE (arg_types));
   arg_types = TREE_CHAIN (arg_types);
 
-  parms = TREE_CHAIN (DECL_ARGUMENTS (fn));
+  parms = DECL_CHAIN (DECL_ARGUMENTS (fn));
 
   /* If this is a subobject constructor or destructor, our caller will
      pass us a pointer to our VTT.  */
 
   /* If this is a subobject constructor or destructor, our caller will
      pass us a pointer to our VTT.  */
@@ -251,7 +253,7 @@ maybe_retrofit_in_chrg (tree fn)
       parm = build_artificial_parm (vtt_parm_identifier, vtt_parm_type);
 
       /* First add it to DECL_ARGUMENTS between 'this' and the real args...  */
       parm = build_artificial_parm (vtt_parm_identifier, vtt_parm_type);
 
       /* First add it to DECL_ARGUMENTS between 'this' and the real args...  */
-      TREE_CHAIN (parm) = parms;
+      DECL_CHAIN (parm) = parms;
       parms = parm;
 
       /* ...and then to TYPE_ARG_TYPES.  */
       parms = parm;
 
       /* ...and then to TYPE_ARG_TYPES.  */
@@ -262,12 +264,12 @@ maybe_retrofit_in_chrg (tree fn)
 
   /* Then add the in-charge parm (before the VTT parm).  */
   parm = build_artificial_parm (in_charge_identifier, integer_type_node);
 
   /* Then add the in-charge parm (before the VTT parm).  */
   parm = build_artificial_parm (in_charge_identifier, integer_type_node);
-  TREE_CHAIN (parm) = parms;
+  DECL_CHAIN (parm) = parms;
   parms = parm;
   arg_types = hash_tree_chain (integer_type_node, arg_types);
 
   /* Insert our new parameter(s) into the list.  */
   parms = parm;
   arg_types = hash_tree_chain (integer_type_node, arg_types);
 
   /* Insert our new parameter(s) into the list.  */
-  TREE_CHAIN (DECL_ARGUMENTS (fn)) = parms;
+  DECL_CHAIN (DECL_ARGUMENTS (fn)) = parms;
 
   /* And rebuild the function type.  */
   fntype = build_method_type_directly (basetype, TREE_TYPE (TREE_TYPE (fn)),
 
   /* And rebuild the function type.  */
   fntype = build_method_type_directly (basetype, TREE_TYPE (TREE_TYPE (fn)),
@@ -333,7 +335,7 @@ grokclassfn (tree ctype, tree function, enum overload_flags flags)
    along the way.  */
 
 tree
    along the way.  */
 
 tree
-grok_array_decl (tree array_expr, tree index_exp)
+grok_array_decl (location_t loc, tree array_expr, tree index_exp)
 {
   tree type;
   tree expr;
 {
   tree type;
   tree expr;
@@ -347,8 +349,8 @@ grok_array_decl (tree array_expr, tree index_exp)
     {
       if (type_dependent_expression_p (array_expr)
          || type_dependent_expression_p (index_exp))
     {
       if (type_dependent_expression_p (array_expr)
          || type_dependent_expression_p (index_exp))
-       return build_min_nt (ARRAY_REF, array_expr, index_exp,
-                            NULL_TREE, NULL_TREE);
+       return build_min_nt_loc (loc, ARRAY_REF, array_expr, index_exp,
+                                NULL_TREE, NULL_TREE);
       array_expr = build_non_dependent_expr (array_expr);
       index_exp = build_non_dependent_expr (index_exp);
     }
       array_expr = build_non_dependent_expr (array_expr);
       index_exp = build_non_dependent_expr (index_exp);
     }
@@ -359,9 +361,8 @@ grok_array_decl (tree array_expr, tree index_exp)
 
   /* If they have an `operator[]', use that.  */
   if (MAYBE_CLASS_TYPE_P (type) || MAYBE_CLASS_TYPE_P (TREE_TYPE (index_exp)))
 
   /* If they have an `operator[]', use that.  */
   if (MAYBE_CLASS_TYPE_P (type) || MAYBE_CLASS_TYPE_P (TREE_TYPE (index_exp)))
-    expr = build_new_op (ARRAY_REF, LOOKUP_NORMAL,
-                        array_expr, index_exp, NULL_TREE,
-                        /*overloaded_p=*/NULL, tf_warning_or_error);
+    expr = build_new_op (loc, ARRAY_REF, LOOKUP_NORMAL, array_expr, index_exp,
+                        NULL_TREE, /*overload=*/NULL, tf_warning_or_error);
   else
     {
       tree p1, p2, i1, i2;
   else
     {
       tree p1, p2, i1, i2;
@@ -370,7 +371,7 @@ grok_array_decl (tree array_expr, tree index_exp)
         It is a little-known fact that, if `a' is an array and `i' is
         an int, you can write `i[a]', which means the same thing as
         `a[i]'.  */
         It is a little-known fact that, if `a' is an array and `i' is
         an int, you can write `i[a]', which means the same thing as
         `a[i]'.  */
-      if (TREE_CODE (type) == ARRAY_TYPE)
+      if (TREE_CODE (type) == ARRAY_TYPE || TREE_CODE (type) == VECTOR_TYPE)
        p1 = array_expr;
       else
        p1 = build_expr_type_conversion (WANT_POINTER, array_expr, false);
        p1 = array_expr;
       else
        p1 = build_expr_type_conversion (WANT_POINTER, array_expr, false);
@@ -418,7 +419,8 @@ grok_array_decl (tree array_expr, tree index_exp)
    Implements ARM $5.3.4.  This is called from the parser.  */
 
 tree
    Implements ARM $5.3.4.  This is called from the parser.  */
 
 tree
-delete_sanity (tree exp, tree size, bool doing_vec, int use_global_delete)
+delete_sanity (tree exp, tree size, bool doing_vec, int use_global_delete,
+              tsubst_flags_t complain)
 {
   tree t, type;
 
 {
   tree t, type;
 
@@ -435,9 +437,8 @@ delete_sanity (tree exp, tree size, bool doing_vec, int use_global_delete)
     }
 
   /* An array can't have been allocated by new, so complain.  */
     }
 
   /* An array can't have been allocated by new, so complain.  */
-  if (TREE_CODE (exp) == VAR_DECL
-      && TREE_CODE (TREE_TYPE (exp)) == ARRAY_TYPE)
-    warning (0, "deleting array %q#D", exp);
+  if (TREE_CODE (TREE_TYPE (exp)) == ARRAY_TYPE)
+    warning (0, "deleting array %q#E", exp);
 
   t = build_expr_type_conversion (WANT_POINTER, exp, true);
 
 
   t = build_expr_type_conversion (WANT_POINTER, exp, true);
 
@@ -474,10 +475,11 @@ delete_sanity (tree exp, tree size, bool doing_vec, int use_global_delete)
   if (doing_vec)
     return build_vec_delete (t, /*maxindex=*/NULL_TREE,
                             sfk_deleting_destructor,
   if (doing_vec)
     return build_vec_delete (t, /*maxindex=*/NULL_TREE,
                             sfk_deleting_destructor,
-                            use_global_delete);
+                            use_global_delete, complain);
   else
     return build_delete (type, t, sfk_deleting_destructor,
   else
     return build_delete (type, t, sfk_deleting_destructor,
-                        LOOKUP_NORMAL, use_global_delete);
+                        LOOKUP_NORMAL, use_global_delete,
+                        complain);
 }
 
 /* Report an error if the indicated template declaration is not the
 }
 
 /* Report an error if the indicated template declaration is not the
@@ -492,6 +494,7 @@ check_member_template (tree tmpl)
   decl = DECL_TEMPLATE_RESULT (tmpl);
 
   if (TREE_CODE (decl) == FUNCTION_DECL
   decl = DECL_TEMPLATE_RESULT (tmpl);
 
   if (TREE_CODE (decl) == FUNCTION_DECL
+      || DECL_ALIAS_TEMPLATE_P (tmpl)
       || (TREE_CODE (decl) == TYPE_DECL
          && MAYBE_CLASS_TYPE_P (TREE_TYPE (decl))))
     {
       || (TREE_CODE (decl) == TYPE_DECL
          && MAYBE_CLASS_TYPE_P (TREE_TYPE (decl))))
     {
@@ -624,7 +627,7 @@ check_classfn (tree ctype, tree function, tree template_parms)
          && !comp_template_parms (template_parms,
                                   DECL_TEMPLATE_PARMS (function)))
        {
          && !comp_template_parms (template_parms,
                                   DECL_TEMPLATE_PARMS (function)))
        {
-         error ("template parameter lists provided don't match the "
+         error ("template parameter lists provided don%'t match the "
                 "template parameters of %qD", function);
          return error_mark_node;
        }
                 "template parameters of %qD", function);
          return error_mark_node;
        }
@@ -767,25 +770,12 @@ finish_static_data_member_decl (tree decl,
   if (! processing_template_decl)
     VEC_safe_push (tree, gc, pending_statics, decl);
 
   if (! processing_template_decl)
     VEC_safe_push (tree, gc, pending_statics, decl);
 
-  if (LOCAL_CLASS_P (current_class_type))
+  if (LOCAL_CLASS_P (current_class_type)
+      /* We already complained about the template definition.  */
+      && !DECL_TEMPLATE_INSTANTIATION (decl))
     permerror (input_location, "local class %q#T shall not have static data member %q#D",
               current_class_type, decl);
 
     permerror (input_location, "local class %q#T shall not have static data member %q#D",
               current_class_type, decl);
 
-  /* Static consts need not be initialized in the class definition.  */
-  if (init != NULL_TREE && TYPE_NEEDS_CONSTRUCTING (TREE_TYPE (decl)))
-    {
-      static int explained = 0;
-
-      error ("initializer invalid for static member with constructor");
-      if (!explained)
-       {
-         error ("(an out of class initialization is required)");
-         explained = 1;
-       }
-      init = NULL_TREE;
-    }
-
-  DECL_INITIAL (decl) = init;
   DECL_IN_AGGR_P (decl) = 1;
 
   if (TREE_CODE (TREE_TYPE (decl)) == ARRAY_TYPE
   DECL_IN_AGGR_P (decl) = 1;
 
   if (TREE_CODE (TREE_TYPE (decl)) == ARRAY_TYPE
@@ -808,7 +798,7 @@ grokfield (const cp_declarator *declarator,
 {
   tree value;
   const char *asmspec = 0;
 {
   tree value;
   const char *asmspec = 0;
-  int flags = LOOKUP_ONLYCONVERTING;
+  int flags;
   tree name;
 
   if (init
   tree name;
 
   if (init
@@ -860,9 +850,6 @@ grokfield (const cp_declarator *declarator,
       DECL_NONLOCAL (value) = 1;
       DECL_CONTEXT (value) = current_class_type;
 
       DECL_NONLOCAL (value) = 1;
       DECL_CONTEXT (value) = current_class_type;
 
-      if (processing_template_decl)
-       value = push_template_decl (value);
-
       if (attrlist)
        {
          int attrflags = 0;
       if (attrlist)
        {
          int attrflags = 0;
@@ -876,11 +863,18 @@ grokfield (const cp_declarator *declarator,
          cplus_decl_attributes (&value, attrlist, attrflags);
        }
 
          cplus_decl_attributes (&value, attrlist, attrflags);
        }
 
-      if (declspecs->specs[(int)ds_typedef]
+      if (decl_spec_seq_has_spec_p (declspecs, ds_typedef)
           && TREE_TYPE (value) != error_mark_node
           && TYPE_NAME (TYPE_MAIN_VARIANT (TREE_TYPE (value))) != value)
           && TREE_TYPE (value) != error_mark_node
           && TYPE_NAME (TYPE_MAIN_VARIANT (TREE_TYPE (value))) != value)
-       cp_set_underlying_type (value);
+       set_underlying_type (value);
 
 
+      /* It's important that push_template_decl below follows
+        set_underlying_type above so that the created template
+        carries the properly set type of VALUE.  */
+      if (processing_template_decl)
+       value = push_template_decl (value);
+
+      record_locally_defined_typedef (value);
       return value;
     }
 
       return value;
     }
 
@@ -914,6 +908,8 @@ grokfield (const cp_declarator *declarator,
                  DECL_DECLARED_INLINE_P (value) = 1;
                }
            }
                  DECL_DECLARED_INLINE_P (value) = 1;
                }
            }
+         else if (TREE_CODE (init) == DEFAULT_ARG)
+           error ("invalid initializer for member function %qD", value);
          else if (TREE_CODE (TREE_TYPE (value)) == METHOD_TYPE)
            {
              if (integer_zerop (init))
          else if (TREE_CODE (TREE_TYPE (value)) == METHOD_TYPE)
            {
              if (integer_zerop (init))
@@ -931,15 +927,15 @@ grokfield (const cp_declarator *declarator,
                     value);
            }
        }
                     value);
            }
        }
-      else if (pedantic && TREE_CODE (value) != VAR_DECL)
-       /* Already complained in grokdeclarator.  */
-       init = NULL_TREE;
+      else if (TREE_CODE (value) == FIELD_DECL)
+       /* C++11 NSDMI, keep going.  */;
+      else if (TREE_CODE (value) != VAR_DECL)
+       gcc_unreachable ();
       else if (!processing_template_decl)
        {
          if (TREE_CODE (init) == CONSTRUCTOR)
       else if (!processing_template_decl)
        {
          if (TREE_CODE (init) == CONSTRUCTOR)
-           init = digest_init (TREE_TYPE (value), init);
-         else
-           init = integral_constant_value (init);
+           init = digest_init (TREE_TYPE (value), init, tf_warning_or_error);
+         init = maybe_constant_init (init);
 
          if (init != error_mark_node && !TREE_CONSTANT (init))
            {
 
          if (init != error_mark_node && !TREE_CONSTANT (init))
            {
@@ -968,6 +964,12 @@ grokfield (const cp_declarator *declarator,
   if (attrlist)
     cplus_decl_attributes (&value, attrlist, 0);
 
   if (attrlist)
     cplus_decl_attributes (&value, attrlist, 0);
 
+  if (init && BRACE_ENCLOSED_INITIALIZER_P (init)
+      && CONSTRUCTOR_IS_DIRECT_INIT (init))
+    flags = LOOKUP_NORMAL;
+  else
+    flags = LOOKUP_IMPLICIT;
+
   switch (TREE_CODE (value))
     {
     case VAR_DECL:
   switch (TREE_CODE (value))
     {
     case VAR_DECL:
@@ -982,7 +984,6 @@ grokfield (const cp_declarator *declarator,
        init = error_mark_node;
       cp_finish_decl (value, init, /*init_const_expr_p=*/false,
                      NULL_TREE, flags);
        init = error_mark_node;
       cp_finish_decl (value, init, /*init_const_expr_p=*/false,
                      NULL_TREE, flags);
-      DECL_INITIAL (value) = init;
       DECL_IN_AGGR_P (value) = 1;
       return value;
 
       DECL_IN_AGGR_P (value) = 1;
       return value;
 
@@ -1066,7 +1067,11 @@ grokbitfield (const cp_declarator *declarator,
 
   if (width != error_mark_node)
     {
 
   if (width != error_mark_node)
     {
-      constant_expression_warning (width);
+      /* The width must be an integer type.  */
+      if (!type_dependent_expression_p (width)
+         && !INTEGRAL_OR_UNSCOPED_ENUMERATION_TYPE_P (TREE_TYPE (width)))
+       error ("width of bit-field %qD has non-integral type %qT", value,
+              TREE_TYPE (width));
       DECL_INITIAL (value) = width;
       SET_DECL_C_BIT_FIELD (value);
     }
       DECL_INITIAL (value) = width;
       SET_DECL_C_BIT_FIELD (value);
     }
@@ -1099,6 +1104,11 @@ is_late_template_attribute (tree attr, tree decl)
   if (is_attribute_p ("weak", name))
     return true;
 
   if (is_attribute_p ("weak", name))
     return true;
 
+  /* Attribute unused is applied directly, as it appertains to
+     decls. */
+  if (is_attribute_p ("unused", name))
+    return false;
+
   /* If any of the arguments are dependent expressions, we can't evaluate
      the attribute until instantiation time.  */
   for (arg = args; arg; arg = TREE_CHAIN (arg))
   /* If any of the arguments are dependent expressions, we can't evaluate
      the attribute until instantiation time.  */
   for (arg = args; arg; arg = TREE_CHAIN (arg))
@@ -1196,9 +1206,9 @@ save_template_attributes (tree *attr_p, tree *decl_p)
 
   old_attrs = *q;
 
 
   old_attrs = *q;
 
-  /* Place the late attributes at the beginning of the attribute
+  /* Merge the late attributes at the beginning with the attribute
      list.  */
      list.  */
-  TREE_CHAIN (tree_last (late_attrs)) = *q;
+  late_attrs = merge_attributes (late_attrs, *q);
   *q = late_attrs;
 
   if (!DECL_P (*decl_p) && *decl_p == TYPE_MAIN_VARIANT (*decl_p))
   *q = late_attrs;
 
   if (!DECL_P (*decl_p) && *decl_p == TYPE_MAIN_VARIANT (*decl_p))
@@ -1258,8 +1268,7 @@ cp_reconstruct_complex_type (tree type, tree bottom)
         so we must compensate by getting rid of it.  */
       outer
        = build_method_type_directly
         so we must compensate by getting rid of it.  */
       outer
        = build_method_type_directly
-           (TREE_TYPE (TREE_VALUE (TYPE_ARG_TYPES (type))),
-            inner,
+           (class_of_this_parm (type), inner,
             TREE_CHAIN (TYPE_ARG_TYPES (type)));
     }
   else if (TREE_CODE (type) == OFFSET_TYPE)
             TREE_CHAIN (TYPE_ARG_TYPES (type)));
     }
   else if (TREE_CODE (type) == OFFSET_TYPE)
@@ -1275,6 +1284,25 @@ cp_reconstruct_complex_type (tree type, tree bottom)
   return cp_build_qualified_type (outer, cp_type_quals (type));
 }
 
   return cp_build_qualified_type (outer, cp_type_quals (type));
 }
 
+/* Replaces any constexpr expression that may be into the attributes
+   arguments with their reduced value.  */
+
+static void
+cp_check_const_attributes (tree attributes)
+{
+  tree attr;
+  for (attr = attributes; attr; attr = TREE_CHAIN (attr))
+    {
+      tree arg;
+      for (arg = TREE_VALUE (attr); arg; arg = TREE_CHAIN (arg))
+       {
+         tree expr = TREE_VALUE (arg);
+         if (EXPR_P (expr))
+           TREE_VALUE (arg) = maybe_constant_value (expr);
+       }
+    }
+}
+
 /* Like decl_attributes, but handle C++ complexity.  */
 
 void
 /* Like decl_attributes, but handle C++ complexity.  */
 
 void
@@ -1295,6 +1323,8 @@ cplus_decl_attributes (tree *decl, tree attributes, int flags)
        return;
     }
 
        return;
     }
 
+  cp_check_const_attributes (attributes);
+
   if (TREE_CODE (*decl) == TEMPLATE_DECL)
     decl = &DECL_TEMPLATE_RESULT (*decl);
 
   if (TREE_CODE (*decl) == TEMPLATE_DECL)
     decl = &DECL_TEMPLATE_RESULT (*decl);
 
@@ -1317,11 +1347,14 @@ build_anon_union_vars (tree type, tree object)
   /* Rather than write the code to handle the non-union case,
      just give an error.  */
   if (TREE_CODE (type) != UNION_TYPE)
   /* Rather than write the code to handle the non-union case,
      just give an error.  */
   if (TREE_CODE (type) != UNION_TYPE)
-    error ("anonymous struct not inside named type");
+    {
+      error ("anonymous struct not inside named type");
+      return error_mark_node;
+    }
 
   for (field = TYPE_FIELDS (type);
        field != NULL_TREE;
 
   for (field = TYPE_FIELDS (type);
        field != NULL_TREE;
-       field = TREE_CHAIN (field))
+       field = DECL_CHAIN (field))
     {
       tree decl;
       tree ref;
     {
       tree decl;
       tree ref;
@@ -1341,8 +1374,8 @@ build_anon_union_vars (tree type, tree object)
        permerror (input_location, "protected member %q+#D in anonymous union", field);
 
       if (processing_template_decl)
        permerror (input_location, "protected member %q+#D in anonymous union", field);
 
       if (processing_template_decl)
-       ref = build_min_nt (COMPONENT_REF, object,
-                           DECL_NAME (field), NULL_TREE);
+       ref = build_min_nt_loc (UNKNOWN_LOCATION, COMPONENT_REF, object,
+                               DECL_NAME (field), NULL_TREE);
       else
        ref = build_class_member_access_expr (object, field, NULL_TREE,
                                              false, tf_warning_or_error);
       else
        ref = build_class_member_access_expr (object, field, NULL_TREE,
                                              false, tf_warning_or_error);
@@ -1421,17 +1454,13 @@ finish_anon_union (tree anon_union_decl)
       /* Use main_decl to set the mangled name.  */
       DECL_NAME (anon_union_decl) = DECL_NAME (main_decl);
       maybe_commonize_var (anon_union_decl);
       /* Use main_decl to set the mangled name.  */
       DECL_NAME (anon_union_decl) = DECL_NAME (main_decl);
       maybe_commonize_var (anon_union_decl);
-      mangle_decl (anon_union_decl);
+      if (TREE_STATIC (anon_union_decl) || DECL_EXTERNAL (anon_union_decl))
+       mangle_decl (anon_union_decl);
       DECL_NAME (anon_union_decl) = NULL_TREE;
     }
 
   pushdecl (anon_union_decl);
       DECL_NAME (anon_union_decl) = NULL_TREE;
     }
 
   pushdecl (anon_union_decl);
-  if (building_stmt_tree ()
-      && at_function_scope_p ())
-    add_decl_expr (anon_union_decl);
-  else if (!processing_template_decl)
-    rest_of_decl_compilation (anon_union_decl,
-                             toplevel_bindings_p (), at_eof);
+  cp_finish_decl (anon_union_decl, NULL_TREE, false, NULL_TREE, 0);
 }
 \f
 /* Auxiliary functions to make type signatures for
 }
 \f
 /* Auxiliary functions to make type signatures for
@@ -1652,6 +1681,7 @@ maybe_make_one_only (tree decl)
          DECL_COMDAT (decl) = 1;
          /* Mark it needed so we don't forget to emit it.  */
          mark_decl_referenced (decl);
          DECL_COMDAT (decl) = 1;
          /* Mark it needed so we don't forget to emit it.  */
          mark_decl_referenced (decl);
+         TREE_USED (decl) = 1;
        }
     }
 }
        }
     }
 }
@@ -1757,10 +1787,7 @@ var_finalized_p (tree var)
 void
 mark_needed (tree decl)
 {
 void
 mark_needed (tree decl)
 {
-  /* It's possible that we no longer need to set
-     TREE_SYMBOL_REFERENCED here directly, but doing so is
-     harmless.  */
-  TREE_SYMBOL_REFERENCED (DECL_ASSEMBLER_NAME (decl)) = 1;
+  TREE_USED (decl) = 1;
   mark_decl_referenced (decl);
 }
 
   mark_decl_referenced (decl);
 }
 
@@ -1786,13 +1813,12 @@ decl_needed_p (tree decl)
     return true;
   /* If this entity was used, let the back end see it; it will decide
      whether or not to emit it into the object file.  */
     return true;
   /* If this entity was used, let the back end see it; it will decide
      whether or not to emit it into the object file.  */
-  if (TREE_USED (decl)
-      || (DECL_ASSEMBLER_NAME_SET_P (decl)
-         && TREE_SYMBOL_REFERENCED (DECL_ASSEMBLER_NAME (decl))))
+  if (TREE_USED (decl))
       return true;
   /* Functions marked "dllexport" must be emitted so that they are
      visible to other DLLs.  */
       return true;
   /* Functions marked "dllexport" must be emitted so that they are
      visible to other DLLs.  */
-  if (lookup_attribute ("dllexport", DECL_ATTRIBUTES (decl)))
+  if (flag_keep_inline_dllexport
+      && lookup_attribute ("dllexport", DECL_ATTRIBUTES (decl)))
     return true;
   /* Otherwise, DECL does not need to be emitted -- yet.  A subsequent
      reference to DECL might cause it to be emitted later.  */
     return true;
   /* Otherwise, DECL does not need to be emitted -- yet.  A subsequent
      reference to DECL might cause it to be emitted later.  */
@@ -1808,7 +1834,7 @@ maybe_emit_vtables (tree ctype)
   tree vtbl;
   tree primary_vtbl;
   int needed = 0;
   tree vtbl;
   tree primary_vtbl;
   int needed = 0;
-  struct varpool_node *current = NULL, *last = NULL, *first = NULL;
+  struct varpool_node *current = NULL, *last = NULL;
 
   /* If the vtables for this class have already been emitted there is
      nothing more to do.  */
 
   /* If the vtables for this class have already been emitted there is
      nothing more to do.  */
@@ -1826,7 +1852,7 @@ maybe_emit_vtables (tree ctype)
     determine_key_method (ctype);
 
   /* See if any of the vtables are needed.  */
     determine_key_method (ctype);
 
   /* See if any of the vtables are needed.  */
-  for (vtbl = CLASSTYPE_VTABLES (ctype); vtbl; vtbl = TREE_CHAIN (vtbl))
+  for (vtbl = CLASSTYPE_VTABLES (ctype); vtbl; vtbl = DECL_CHAIN (vtbl))
     {
       import_export_decl (vtbl);
       if (DECL_NOT_REALLY_EXTERN (vtbl) && decl_needed_p (vtbl))
     {
       import_export_decl (vtbl);
       if (DECL_NOT_REALLY_EXTERN (vtbl) && decl_needed_p (vtbl))
@@ -1845,17 +1871,19 @@ maybe_emit_vtables (tree ctype)
 
   /* The ABI requires that we emit all of the vtables if we emit any
      of them.  */
 
   /* The ABI requires that we emit all of the vtables if we emit any
      of them.  */
-  for (vtbl = CLASSTYPE_VTABLES (ctype); vtbl; vtbl = TREE_CHAIN (vtbl))
+  for (vtbl = CLASSTYPE_VTABLES (ctype); vtbl; vtbl = DECL_CHAIN (vtbl))
     {
       /* Mark entities references from the virtual table as used.  */
       mark_vtable_entries (vtbl);
 
       if (TREE_TYPE (DECL_INITIAL (vtbl)) == 0)
        {
     {
       /* Mark entities references from the virtual table as used.  */
       mark_vtable_entries (vtbl);
 
       if (TREE_TYPE (DECL_INITIAL (vtbl)) == 0)
        {
-         tree expr = store_init_value (vtbl, DECL_INITIAL (vtbl), LOOKUP_NORMAL);
+         VEC(tree,gc)* cleanups = NULL;
+         tree expr = store_init_value (vtbl, DECL_INITIAL (vtbl), &cleanups,
+                                       LOOKUP_NORMAL);
 
          /* It had better be all done at compile-time.  */
 
          /* It had better be all done at compile-time.  */
-         gcc_assert (!expr);
+         gcc_assert (!expr && !cleanups);
        }
 
       /* Write it out.  */
        }
 
       /* Write it out.  */
@@ -1866,20 +1894,15 @@ maybe_emit_vtables (tree ctype)
         actually marking the variable as written.  */
       if (flag_syntax_only)
        TREE_ASM_WRITTEN (vtbl) = 1;
         actually marking the variable as written.  */
       if (flag_syntax_only)
        TREE_ASM_WRITTEN (vtbl) = 1;
-      else if (DECL_COMDAT (vtbl))
+      else if (DECL_ONE_ONLY (vtbl))
        {
          current = varpool_node (vtbl);
          if (last)
        {
          current = varpool_node (vtbl);
          if (last)
-           last->same_comdat_group = current;
+           symtab_add_to_same_comdat_group ((symtab_node) current, (symtab_node) last);
          last = current;
          last = current;
-         if (!first)
-           first = current;
        }
     }
 
        }
     }
 
-  if (first != last)
-    last->same_comdat_group = first;
-
   /* Since we're writing out the vtable here, also write the debug
      info.  */
   note_debug_info_needed (ctype);
   /* Since we're writing out the vtable here, also write the debug
      info.  */
   note_debug_info_needed (ctype);
@@ -1927,10 +1950,12 @@ type_visibility (tree type)
 }
 
 /* Limit the visibility of DECL to VISIBILITY, if not explicitly
 }
 
 /* Limit the visibility of DECL to VISIBILITY, if not explicitly
-   specified (or if VISIBILITY is static).  */
+   specified (or if VISIBILITY is static).  If TMPL is true, this
+   constraint is for a template argument, and takes precedence
+   over explicitly-specified visibility on the template.  */
 
 
-static bool
-constrain_visibility (tree decl, int visibility)
+static void
+constrain_visibility (tree decl, int visibility, bool tmpl)
 {
   if (visibility == VISIBILITY_ANON)
     {
 {
   if (visibility == VISIBILITY_ANON)
     {
@@ -1948,12 +1973,12 @@ constrain_visibility (tree decl, int visibility)
        }
     }
   else if (visibility > DECL_VISIBILITY (decl)
        }
     }
   else if (visibility > DECL_VISIBILITY (decl)
-          && !DECL_VISIBILITY_SPECIFIED (decl))
+          && (tmpl || !DECL_VISIBILITY_SPECIFIED (decl)))
     {
       DECL_VISIBILITY (decl) = (enum symbol_visibility) visibility;
     {
       DECL_VISIBILITY (decl) = (enum symbol_visibility) visibility;
-      return true;
+      /* This visibility was not specified.  */
+      DECL_VISIBILITY_SPECIFIED (decl) = false;
     }
     }
-  return false;
 }
 
 /* Constrain the visibility of DECL based on the visibility of its template
 }
 
 /* Constrain the visibility of DECL based on the visibility of its template
@@ -1989,7 +2014,7 @@ constrain_visibility_for_template (tree decl, tree targs)
            }
        }
       if (vis)
            }
        }
       if (vis)
-       constrain_visibility (decl, vis);
+       constrain_visibility (decl, vis, true);
     }
 }
 
     }
 }
 
@@ -2064,14 +2089,29 @@ determine_visibility (tree decl)
             containing function by default, except that
             -fvisibility-inlines-hidden doesn't affect them.  */
          tree fn = DECL_CONTEXT (decl);
             containing function by default, except that
             -fvisibility-inlines-hidden doesn't affect them.  */
          tree fn = DECL_CONTEXT (decl);
-         if (DECL_VISIBILITY_SPECIFIED (fn) || ! DECL_CLASS_SCOPE_P (fn))
+         if (DECL_VISIBILITY_SPECIFIED (fn))
            {
              DECL_VISIBILITY (decl) = DECL_VISIBILITY (fn);
              DECL_VISIBILITY_SPECIFIED (decl) = 
                DECL_VISIBILITY_SPECIFIED (fn);
            }
          else
            {
              DECL_VISIBILITY (decl) = DECL_VISIBILITY (fn);
              DECL_VISIBILITY_SPECIFIED (decl) = 
                DECL_VISIBILITY_SPECIFIED (fn);
            }
          else
-           determine_visibility_from_class (decl, DECL_CONTEXT (fn));
+           {
+             if (DECL_CLASS_SCOPE_P (fn))
+               determine_visibility_from_class (decl, DECL_CONTEXT (fn));
+             else if (determine_hidden_inline (fn))
+               {
+                 DECL_VISIBILITY (decl) = default_visibility;
+                 DECL_VISIBILITY_SPECIFIED (decl) =
+                   visibility_options.inpragma;
+               }
+             else
+               {
+                 DECL_VISIBILITY (decl) = DECL_VISIBILITY (fn);
+                 DECL_VISIBILITY_SPECIFIED (decl) =
+                   DECL_VISIBILITY_SPECIFIED (fn);
+               }
+           }
 
          /* Local classes in templates have CLASSTYPE_USE_TEMPLATE set,
             but have no TEMPLATE_INFO, so don't try to check it.  */
 
          /* Local classes in templates have CLASSTYPE_USE_TEMPLATE set,
             but have no TEMPLATE_INFO, so don't try to check it.  */
@@ -2085,8 +2125,9 @@ determine_visibility (tree decl)
          tree underlying_type = TREE_TYPE (DECL_NAME (decl));
          int underlying_vis = type_visibility (underlying_type);
          if (underlying_vis == VISIBILITY_ANON
          tree underlying_type = TREE_TYPE (DECL_NAME (decl));
          int underlying_vis = type_visibility (underlying_type);
          if (underlying_vis == VISIBILITY_ANON
-             || CLASSTYPE_VISIBILITY_SPECIFIED (underlying_type))
-           constrain_visibility (decl, underlying_vis);
+             || (CLASS_TYPE_P (underlying_type)
+                 && CLASSTYPE_VISIBILITY_SPECIFIED (underlying_type)))
+           constrain_visibility (decl, underlying_vis, false);
          else
            DECL_VISIBILITY (decl) = VISIBILITY_DEFAULT;
        }
          else
            DECL_VISIBILITY (decl) = VISIBILITY_DEFAULT;
        }
@@ -2094,7 +2135,7 @@ determine_visibility (tree decl)
        {
          /* tinfo visibility is based on the type it's for.  */
          constrain_visibility
        {
          /* tinfo visibility is based on the type it's for.  */
          constrain_visibility
-           (decl, type_visibility (TREE_TYPE (DECL_NAME (decl))));
+           (decl, type_visibility (TREE_TYPE (DECL_NAME (decl))), false);
 
          /* Give the target a chance to override the visibility associated
             with DECL.  */
 
          /* Give the target a chance to override the visibility associated
             with DECL.  */
@@ -2109,10 +2150,15 @@ determine_visibility (tree decl)
           on their template unless they override it with an attribute.  */;
       else if (! DECL_VISIBILITY_SPECIFIED (decl))
        {
           on their template unless they override it with an attribute.  */;
       else if (! DECL_VISIBILITY_SPECIFIED (decl))
        {
-         /* Set default visibility to whatever the user supplied with
-            #pragma GCC visibility or a namespace visibility attribute.  */
-         DECL_VISIBILITY (decl) = default_visibility;
-         DECL_VISIBILITY_SPECIFIED (decl) = visibility_options.inpragma;
+          if (determine_hidden_inline (decl))
+           DECL_VISIBILITY (decl) = VISIBILITY_HIDDEN;
+         else
+            {
+             /* Set default visibility to whatever the user supplied with
+                #pragma GCC visibility or a namespace visibility attribute.  */
+             DECL_VISIBILITY (decl) = default_visibility;
+             DECL_VISIBILITY_SPECIFIED (decl) = visibility_options.inpragma;
+            }
        }
     }
 
        }
     }
 
@@ -2124,23 +2170,52 @@ determine_visibility (tree decl)
                    ? TYPE_TEMPLATE_INFO (TREE_TYPE (decl))
                    : DECL_TEMPLATE_INFO (decl));
       tree args = TI_ARGS (tinfo);
                    ? TYPE_TEMPLATE_INFO (TREE_TYPE (decl))
                    : DECL_TEMPLATE_INFO (decl));
       tree args = TI_ARGS (tinfo);
+      tree attribs = (TREE_CODE (decl) == TYPE_DECL
+                     ? TYPE_ATTRIBUTES (TREE_TYPE (decl))
+                     : DECL_ATTRIBUTES (decl));
       
       if (args != error_mark_node)
        {
       
       if (args != error_mark_node)
        {
-         int depth = TMPL_ARGS_DEPTH (args);
          tree pattern = DECL_TEMPLATE_RESULT (TI_TEMPLATE (tinfo));
 
          if (!DECL_VISIBILITY_SPECIFIED (decl))
            {
          tree pattern = DECL_TEMPLATE_RESULT (TI_TEMPLATE (tinfo));
 
          if (!DECL_VISIBILITY_SPECIFIED (decl))
            {
-             DECL_VISIBILITY (decl) = DECL_VISIBILITY (pattern);
-             DECL_VISIBILITY_SPECIFIED (decl)
-               = DECL_VISIBILITY_SPECIFIED (pattern);
+             if (!DECL_VISIBILITY_SPECIFIED (pattern)
+                 && determine_hidden_inline (decl))
+               DECL_VISIBILITY (decl) = VISIBILITY_HIDDEN;
+             else
+               {
+                 DECL_VISIBILITY (decl) = DECL_VISIBILITY (pattern);
+                 DECL_VISIBILITY_SPECIFIED (decl)
+                   = DECL_VISIBILITY_SPECIFIED (pattern);
+               }
            }
 
            }
 
-         /* FIXME should TMPL_ARGS_DEPTH really return 1 for null input? */
-         if (args && depth > template_class_depth (class_type))
-           /* Limit visibility based on its template arguments.  */
-           constrain_visibility_for_template (decl, args);
+         if (args
+             /* Template argument visibility outweighs #pragma or namespace
+                visibility, but not an explicit attribute.  */
+             && !lookup_attribute ("visibility", attribs))
+           {
+             int depth = TMPL_ARGS_DEPTH (args);
+             int class_depth = 0;
+             if (class_type && CLASSTYPE_TEMPLATE_INFO (class_type))
+               class_depth = TMPL_ARGS_DEPTH (CLASSTYPE_TI_ARGS (class_type));
+             if (DECL_VISIBILITY_SPECIFIED (decl))
+               {
+                 /* A class template member with explicit visibility
+                    overrides the class visibility, so we need to apply
+                    all the levels of template args directly.  */
+                 int i;
+                 for (i = 1; i <= depth; ++i)
+                   {
+                     tree lev = TMPL_ARGS_LEVEL (args, i);
+                     constrain_visibility_for_template (decl, lev);
+                   }
+               }
+             else if (depth > class_depth)
+               /* Limit visibility based on its template arguments.  */
+               constrain_visibility_for_template (decl, args);
+           }
        }
     }
 
        }
     }
 
@@ -2150,14 +2225,14 @@ determine_visibility (tree decl)
   if (decl_anon_ns_mem_p (decl))
     /* Names in an anonymous namespace get internal linkage.
        This might change once we implement export.  */
   if (decl_anon_ns_mem_p (decl))
     /* Names in an anonymous namespace get internal linkage.
        This might change once we implement export.  */
-    constrain_visibility (decl, VISIBILITY_ANON);
+    constrain_visibility (decl, VISIBILITY_ANON, false);
   else if (TREE_CODE (decl) != TYPE_DECL)
     {
       /* Propagate anonymity from type to decl.  */
       int tvis = type_visibility (TREE_TYPE (decl));
       if (tvis == VISIBILITY_ANON
          || ! DECL_VISIBILITY_SPECIFIED (decl))
   else if (TREE_CODE (decl) != TYPE_DECL)
     {
       /* Propagate anonymity from type to decl.  */
       int tvis = type_visibility (TREE_TYPE (decl));
       if (tvis == VISIBILITY_ANON
          || ! DECL_VISIBILITY_SPECIFIED (decl))
-       constrain_visibility (decl, tvis);
+       constrain_visibility (decl, tvis, false);
     }
   else if (no_linkage_check (TREE_TYPE (decl), /*relaxed_p=*/true))
     /* DR 757: A type without linkage shall not be used as the type of a
     }
   else if (no_linkage_check (TREE_TYPE (decl), /*relaxed_p=*/true))
     /* DR 757: A type without linkage shall not be used as the type of a
@@ -2168,7 +2243,7 @@ determine_visibility (tree decl)
 
        Since non-extern "C" decls need to be defined in the same
        translation unit, we can make the type internal.  */
 
        Since non-extern "C" decls need to be defined in the same
        translation unit, we can make the type internal.  */
-    constrain_visibility (decl, VISIBILITY_ANON);
+    constrain_visibility (decl, VISIBILITY_ANON, false);
 
   /* If visibility changed and DECL already has DECL_RTL, ensure
      symbol flags are updated.  */
 
   /* If visibility changed and DECL already has DECL_RTL, ensure
      symbol flags are updated.  */
@@ -2189,15 +2264,7 @@ determine_visibility_from_class (tree decl, tree class_type)
   if (DECL_VISIBILITY_SPECIFIED (decl))
     return;
 
   if (DECL_VISIBILITY_SPECIFIED (decl))
     return;
 
-  if (visibility_options.inlines_hidden
-      /* Don't do this for inline templates; specializations might not be
-        inline, and we don't want them to inherit the hidden
-        visibility.  We'll set it here for all inline instantiations.  */
-      && !processing_template_decl
-      && TREE_CODE (decl) == FUNCTION_DECL
-      && DECL_DECLARED_INLINE_P (decl)
-      && (! DECL_LANG_SPECIFIC (decl)
-         || ! DECL_EXPLICIT_INSTANTIATION (decl)))
+  if (determine_hidden_inline (decl))
     DECL_VISIBILITY (decl) = VISIBILITY_HIDDEN;
   else
     {
     DECL_VISIBILITY (decl) = VISIBILITY_HIDDEN;
   else
     {
@@ -2222,6 +2289,23 @@ determine_visibility_from_class (tree decl, tree class_type)
     targetm.cxx.determine_class_data_visibility (decl);
 }
 
     targetm.cxx.determine_class_data_visibility (decl);
 }
 
+/* Returns true iff DECL is an inline that should get hidden visibility
+   because of -fvisibility-inlines-hidden.  */
+
+static bool
+determine_hidden_inline (tree decl)
+{
+  return (visibility_options.inlines_hidden
+         /* Don't do this for inline templates; specializations might not be
+            inline, and we don't want them to inherit the hidden
+            visibility.  We'll set it here for all inline instantiations.  */
+         && !processing_template_decl
+         && TREE_CODE (decl) == FUNCTION_DECL
+         && DECL_DECLARED_INLINE_P (decl)
+         && (! DECL_LANG_SPECIFIC (decl)
+             || ! DECL_EXPLICIT_INSTANTIATION (decl)));
+}
+
 /* Constrain the visibility of a class TYPE based on the visibility of its
    field types.  Warn if any fields require lesser visibility.  */
 
 /* Constrain the visibility of a class TYPE based on the visibility of its
    field types.  Warn if any fields require lesser visibility.  */
 
@@ -2242,7 +2326,7 @@ constrain_class_visibility (tree type)
   if (CLASSTYPE_VISIBILITY_SPECIFIED (type))
     vis = VISIBILITY_INTERNAL;
 
   if (CLASSTYPE_VISIBILITY_SPECIFIED (type))
     vis = VISIBILITY_INTERNAL;
 
-  for (t = TYPE_FIELDS (type); t; t = TREE_CHAIN (t))
+  for (t = TYPE_FIELDS (type); t; t = DECL_CHAIN (t))
     if (TREE_CODE (t) == FIELD_DECL && TREE_TYPE (t) != error_mark_node)
       {
        tree ftype = strip_pointer_or_array_types (TREE_TYPE (t));
     if (TREE_CODE (t) == FIELD_DECL && TREE_TYPE (t) != error_mark_node)
       {
        tree ftype = strip_pointer_or_array_types (TREE_TYPE (t));
@@ -2581,7 +2665,8 @@ build_cleanup (tree decl)
     temp = build_address (decl);
   temp = build_delete (TREE_TYPE (temp), temp,
                       sfk_complete_destructor,
     temp = build_address (decl);
   temp = build_delete (TREE_TYPE (temp), temp,
                       sfk_complete_destructor,
-                      LOOKUP_NORMAL|LOOKUP_NONVIRTUAL|LOOKUP_DESTRUCTOR, 0);
+                      LOOKUP_NORMAL|LOOKUP_NONVIRTUAL|LOOKUP_DESTRUCTOR, 0,
+                      tf_warning_or_error);
   return temp;
 }
 
   return temp;
 }
 
@@ -2703,7 +2788,7 @@ start_objects (int method_type, int initp)
 {
   tree body;
   tree fndecl;
 {
   tree body;
   tree fndecl;
-  char type[10];
+  char type[14];
 
   /* Make ctor or dtor function.  METHOD_TYPE may be 'I' or 'D'.  */
 
 
   /* Make ctor or dtor function.  METHOD_TYPE may be 'I' or 'D'.  */
 
@@ -2717,15 +2802,15 @@ start_objects (int method_type, int initp)
       joiner = '_';
 #endif
 
       joiner = '_';
 #endif
 
-      sprintf (type, "%c%c%.5u", method_type, joiner, initp);
+      sprintf (type, "sub_%c%c%.5u", method_type, joiner, initp);
     }
   else
     }
   else
-    sprintf (type, "%c", method_type);
+    sprintf (type, "sub_%c", method_type);
 
   fndecl = build_lang_decl (FUNCTION_DECL,
                            get_file_function_name (type),
 
   fndecl = build_lang_decl (FUNCTION_DECL,
                            get_file_function_name (type),
-                           build_function_type (void_type_node,
-                                                void_list_node));
+                           build_function_type_list (void_type_node,
+                                                     NULL_TREE));
   start_preparsed_function (fndecl, /*attrs=*/NULL_TREE, SF_PRE_PARSED);
 
   TREE_PUBLIC (current_function_decl) = 0;
   start_preparsed_function (fndecl, /*attrs=*/NULL_TREE, SF_PRE_PARSED);
 
   TREE_PUBLIC (current_function_decl) = 0;
@@ -2817,7 +2902,6 @@ static splay_tree priority_info_map;
 static tree
 start_static_storage_duration_function (unsigned count)
 {
 static tree
 start_static_storage_duration_function (unsigned count)
 {
-  tree parm_types;
   tree type;
   tree body;
   char id[sizeof (SSDF_IDENTIFIER) + 1 /* '\0' */ + 32];
   tree type;
   tree body;
   char id[sizeof (SSDF_IDENTIFIER) + 1 /* '\0' */ + 32];
@@ -2826,11 +2910,9 @@ start_static_storage_duration_function (unsigned count)
      SSDF_IDENTIFIER_<number>.  */
   sprintf (id, "%s_%u", SSDF_IDENTIFIER, count);
 
      SSDF_IDENTIFIER_<number>.  */
   sprintf (id, "%s_%u", SSDF_IDENTIFIER, count);
 
-  /* Create the parameters.  */
-  parm_types = void_list_node;
-  parm_types = tree_cons (NULL_TREE, integer_type_node, parm_types);
-  parm_types = tree_cons (NULL_TREE, integer_type_node, parm_types);
-  type = build_function_type (void_type_node, parm_types);
+  type = build_function_type_list (void_type_node,
+                                  integer_type_node, integer_type_node,
+                                  NULL_TREE);
 
   /* Create the FUNCTION_DECL itself.  */
   ssdf_decl = build_lang_decl (FUNCTION_DECL,
 
   /* Create the FUNCTION_DECL itself.  */
   ssdf_decl = build_lang_decl (FUNCTION_DECL,
@@ -2871,7 +2953,7 @@ start_static_storage_duration_function (unsigned count)
   DECL_CONTEXT (priority_decl) = ssdf_decl;
   TREE_USED (priority_decl) = 1;
 
   DECL_CONTEXT (priority_decl) = ssdf_decl;
   TREE_USED (priority_decl) = 1;
 
-  TREE_CHAIN (initialize_p_decl) = priority_decl;
+  DECL_CHAIN (initialize_p_decl) = priority_decl;
   DECL_ARGUMENTS (ssdf_decl) = initialize_p_decl;
 
   /* Put the function in the global scope.  */
   DECL_ARGUMENTS (ssdf_decl) = initialize_p_decl;
 
   /* Put the function in the global scope.  */
@@ -2960,8 +3042,8 @@ get_priority_info (int priority)
    it's DECL_CONTECT() properly set.  */
 static tree 
 fix_temporary_vars_context_r (tree *node,
    it's DECL_CONTECT() properly set.  */
 static tree 
 fix_temporary_vars_context_r (tree *node,
-                             int  *unused ATTRIBUTE_UNUSED,
-                             void *unused1 ATTRIBUTE_UNUSED)
+                             int  * /*unused*/,
+                             void * /*unused1*/)
 {
   gcc_assert (current_function_decl);
 
 {
   gcc_assert (current_function_decl);
 
@@ -2969,7 +3051,7 @@ fix_temporary_vars_context_r (tree *node,
     {
       tree var;
 
     {
       tree var;
 
-      for (var = BIND_EXPR_VARS (*node); var; var = TREE_CHAIN (var))
+      for (var = BIND_EXPR_VARS (*node); var; var = DECL_CHAIN (var))
        if (TREE_CODE (var) == VAR_DECL
          && !DECL_NAME (var)
          && DECL_ARTIFICIAL (var)
        if (TREE_CODE (var) == VAR_DECL
          && !DECL_NAME (var)
          && DECL_ARTIFICIAL (var)
@@ -3276,7 +3358,6 @@ generate_ctor_or_dtor_function (bool constructor_p, int priority,
                                location_t *locus)
 {
   char function_key;
                                location_t *locus)
 {
   char function_key;
-  tree arguments;
   tree fndecl;
   tree body;
   size_t i;
   tree fndecl;
   tree body;
   size_t i;
@@ -3304,22 +3385,23 @@ generate_ctor_or_dtor_function (bool constructor_p, int priority,
 
   /* Call the static storage duration function with appropriate
      arguments.  */
 
   /* Call the static storage duration function with appropriate
      arguments.  */
-  for (i = 0; VEC_iterate (tree, ssdf_decls, i, fndecl); ++i)
+  FOR_EACH_VEC_ELT (tree, ssdf_decls, i, fndecl)
     {
       /* Calls to pure or const functions will expand to nothing.  */
       if (! (flags_from_decl_or_type (fndecl) & (ECF_CONST | ECF_PURE)))
        {
     {
       /* Calls to pure or const functions will expand to nothing.  */
       if (! (flags_from_decl_or_type (fndecl) & (ECF_CONST | ECF_PURE)))
        {
+         tree call;
+
          if (! body)
            body = start_objects (function_key, priority);
 
          if (! body)
            body = start_objects (function_key, priority);
 
-         arguments = tree_cons (NULL_TREE,
-                                build_int_cst (NULL_TREE, priority),
-                                NULL_TREE);
-         arguments = tree_cons (NULL_TREE,
-                                build_int_cst (NULL_TREE, constructor_p),
-                                arguments);
-         finish_expr_stmt (cp_build_function_call (fndecl, arguments,
-                                                   tf_warning_or_error));
+         call = cp_build_function_call_nary (fndecl, tf_warning_or_error,
+                                             build_int_cst (NULL_TREE,
+                                                            constructor_p),
+                                             build_int_cst (NULL_TREE,
+                                                            priority),
+                                             NULL_TREE);
+         finish_expr_stmt (call);
        }
     }
 
        }
     }
 
@@ -3349,42 +3431,6 @@ generate_ctor_and_dtor_functions_for_priority (splay_tree_node n, void * data)
   return 0;
 }
 
   return 0;
 }
 
-/* Called via LANGHOOK_CALLGRAPH_ANALYZE_EXPR.  It is supposed to mark
-   decls referenced from front-end specific constructs; it will be called
-   only for language-specific tree nodes.
-
-   Here we must deal with member pointers.  */
-
-tree
-cxx_callgraph_analyze_expr (tree *tp, int *walk_subtrees ATTRIBUTE_UNUSED)
-{
-  tree t = *tp;
-
-  switch (TREE_CODE (t))
-    {
-    case PTRMEM_CST:
-      if (TYPE_PTRMEMFUNC_P (TREE_TYPE (t)))
-       cgraph_mark_address_taken_node (cgraph_node (PTRMEM_CST_MEMBER (t)));
-      break;
-    case BASELINK:
-      if (TREE_CODE (BASELINK_FUNCTIONS (t)) == FUNCTION_DECL)
-       cgraph_mark_address_taken_node (cgraph_node (BASELINK_FUNCTIONS (t)));
-      break;
-    case VAR_DECL:
-      if (DECL_CONTEXT (t)
-         && flag_use_repository
-         && TREE_CODE (DECL_CONTEXT (t)) == FUNCTION_DECL)
-       /* If we need a static variable in a function, then we
-          need the containing function.  */
-       mark_decl_referenced (DECL_CONTEXT (t));
-      break;
-    default:
-      break;
-    }
-
-  return NULL;
-}
-
 /* Java requires that we be able to reference a local address for a
    method, and not be confused by PLT entries.  If hidden aliases are
    supported, collect and return all the functions for which we should
 /* Java requires that we be able to reference a local address for a
    method, and not be confused by PLT entries.  If hidden aliases are
    supported, collect and return all the functions for which we should
@@ -3400,9 +3446,9 @@ collect_candidates_for_java_method_aliases (void)
   return candidates;
 #endif
 
   return candidates;
 #endif
 
-  for (node = cgraph_nodes; node ; node = node->next)
+  FOR_EACH_FUNCTION (node)
     {
     {
-      tree fndecl = node->decl;
+      tree fndecl = node->symbol.decl;
 
       if (DECL_CONTEXT (fndecl)
          && TYPE_P (DECL_CONTEXT (fndecl))
 
       if (DECL_CONTEXT (fndecl)
          && TYPE_P (DECL_CONTEXT (fndecl))
@@ -3434,9 +3480,9 @@ build_java_method_aliases (struct pointer_set_t *candidates)
   return;
 #endif
 
   return;
 #endif
 
-  for (node = cgraph_nodes; node ; node = node->next)
+  FOR_EACH_FUNCTION (node)
     {
     {
-      tree fndecl = node->decl;
+      tree fndecl = node->symbol.decl;
 
       if (TREE_ASM_WRITTEN (fndecl)
          && pointer_set_contains (candidates, fndecl))
 
       if (TREE_ASM_WRITTEN (fndecl)
          && pointer_set_contains (candidates, fndecl))
@@ -3462,6 +3508,69 @@ build_java_method_aliases (struct pointer_set_t *candidates)
     }
 }
 
     }
 }
 
+/* Return C++ property of T, based on given operation OP.  */
+
+static int
+cpp_check (tree t, cpp_operation op)
+{
+  switch (op)
+    {
+      case IS_ABSTRACT:
+       return DECL_PURE_VIRTUAL_P (t);
+      case IS_CONSTRUCTOR:
+       return DECL_CONSTRUCTOR_P (t);
+      case IS_DESTRUCTOR:
+       return DECL_DESTRUCTOR_P (t);
+      case IS_COPY_CONSTRUCTOR:
+       return DECL_COPY_CONSTRUCTOR_P (t);
+      case IS_TEMPLATE:
+       return TREE_CODE (t) == TEMPLATE_DECL;
+      default:
+        return 0;
+    }
+}
+
+/* Collect source file references recursively, starting from NAMESPC.  */
+
+static void 
+collect_source_refs (tree namespc) 
+{
+  tree t;
+
+  if (!namespc) 
+    return;
+
+  /* Iterate over names in this name space.  */
+  for (t = NAMESPACE_LEVEL (namespc)->names; t; t = TREE_CHAIN (t))
+    if (!DECL_IS_BUILTIN (t) )
+      collect_source_ref (DECL_SOURCE_FILE (t));
+  
+  /* Dump siblings, if any */
+  collect_source_refs (TREE_CHAIN (namespc));
+
+  /* Dump children, if any */
+  collect_source_refs (NAMESPACE_LEVEL (namespc)->namespaces);
+}
+
+/* Collect decls relevant to SOURCE_FILE from all namespaces recursively,
+   starting from NAMESPC.  */
+
+static void
+collect_ada_namespace (tree namespc, const char *source_file)
+{
+  if (!namespc)
+    return;
+
+  /* Collect decls from this namespace */
+  collect_ada_nodes (NAMESPACE_LEVEL (namespc)->names, source_file);
+
+  /* Collect siblings, if any */
+  collect_ada_namespace (TREE_CHAIN (namespc), source_file);
+
+  /* Collect children, if any */
+  collect_ada_namespace (NAMESPACE_LEVEL (namespc)->namespaces, source_file);
+}
+
 /* Returns true iff there is a definition available for variable or
    function DECL.  */
 
 /* Returns true iff there is a definition available for variable or
    function DECL.  */
 
@@ -3477,6 +3586,51 @@ decl_defined_p (tree decl)
     }
 }
 
     }
 }
 
+/* Nonzero for a VAR_DECL whose value can be used in a constant expression.
+
+      [expr.const]
+
+      An integral constant-expression can only involve ... const
+      variables of integral or enumeration types initialized with
+      constant expressions ...
+
+      C++0x also allows constexpr variables and temporaries initialized
+      with constant expressions.  We handle the former here, but the latter
+      are just folded away in cxx_eval_constant_expression.
+
+   The standard does not require that the expression be non-volatile.
+   G++ implements the proposed correction in DR 457.  */
+
+bool
+decl_constant_var_p (tree decl)
+{
+  if (!decl_maybe_constant_var_p (decl))
+    return false;
+
+  /* We don't know if a template static data member is initialized with
+     a constant expression until we instantiate its initializer.  Even
+     in the case of a constexpr variable, we can't treat it as a
+     constant until its initializer is complete in case it's used in
+     its own initializer.  */
+  mark_used (decl);
+  return DECL_INITIALIZED_BY_CONSTANT_EXPRESSION_P (decl);
+}
+
+/* Returns true if DECL could be a symbolic constant variable, depending on
+   its initializer.  */
+
+bool
+decl_maybe_constant_var_p (tree decl)
+{
+  tree type = TREE_TYPE (decl);
+  if (TREE_CODE (decl) != VAR_DECL)
+    return false;
+  if (DECL_DECLARED_CONSTEXPR_P (decl))
+    return true;
+  return (CP_TYPE_CONST_NON_VOLATILE_P (type)
+         && INTEGRAL_OR_ENUMERATION_TYPE_P (type));
+}
+
 /* Complain that DECL uses a type with no linkage but is never defined.  */
 
 static void
 /* Complain that DECL uses a type with no linkage but is never defined.  */
 
 static void
@@ -3496,6 +3650,23 @@ no_linkage_error (tree decl)
               "is used but never defined", decl, t);
 }
 
               "is used but never defined", decl, t);
 }
 
+/* Collect declarations from all namespaces relevant to SOURCE_FILE.  */
+
+static void
+collect_all_refs (const char *source_file)
+{
+  collect_ada_namespace (global_namespace, source_file);
+}
+
+/* Clear DECL_EXTERNAL for NODE.  */
+
+static bool
+clear_decl_external (struct cgraph_node *node, void * /*data*/)
+{
+  DECL_EXTERNAL (node->symbol.decl) = 0;
+  return false;
+}
+
 /* This routine is called at the end of compilation.
    Its job is to create all the code needed to initialize and
    destroy the global aggregates.  We do the destruction
 /* This routine is called at the end of compilation.
    Its job is to create all the code needed to initialize and
    destroy the global aggregates.  We do the destruction
@@ -3517,14 +3688,30 @@ cp_write_global_declarations (void)
   at_eof = 1;
 
   /* Bad parse errors.  Just forget about it.  */
   at_eof = 1;
 
   /* Bad parse errors.  Just forget about it.  */
-  if (! global_bindings_p () || current_class_type || decl_namespace_list)
+  if (! global_bindings_p () || current_class_type
+      || !VEC_empty (tree,decl_namespace_list))
     return;
 
   if (pch_file)
     c_common_write_pch ();
 
     return;
 
   if (pch_file)
     c_common_write_pch ();
 
+  cgraph_process_same_body_aliases ();
+
+  /* Handle -fdump-ada-spec[-slim] */
+  if (dump_enabled_p (TDI_ada))
+    {
+      if (get_dump_file_info (TDI_ada)->flags & TDF_SLIM)
+       collect_source_ref (main_input_filename);
+      else
+       collect_source_refs (global_namespace);
+
+      dump_ada_specs (collect_all_refs, cpp_check);
+    }
+
   /* FIXME - huh?  was  input_line -= 1;*/
 
   /* FIXME - huh?  was  input_line -= 1;*/
 
+  timevar_start (TV_PHASE_DEFERRED);
+
   /* We now have to write out all the stuff we put off writing out.
      These include:
 
   /* We now have to write out all the stuff we put off writing out.
      These include:
 
@@ -3541,8 +3728,6 @@ cp_write_global_declarations (void)
      generating the initializer for an object may cause templates to be
      instantiated, etc., etc.  */
 
      generating the initializer for an object may cause templates to be
      instantiated, etc., etc.  */
 
-  timevar_push (TV_VARCONST);
-
   emit_support_tinfos ();
 
   do
   emit_support_tinfos ();
 
   do
@@ -3662,7 +3847,7 @@ cp_write_global_declarations (void)
       /* Go through the set of inline functions whose bodies have not
         been emitted yet.  If out-of-line copies of these functions
         are required, emit them.  */
       /* Go through the set of inline functions whose bodies have not
         been emitted yet.  If out-of-line copies of these functions
         are required, emit them.  */
-      for (i = 0; VEC_iterate (tree, deferred_fns, i, decl); ++i)
+      FOR_EACH_VEC_ELT (tree, deferred_fns, i, decl)
        {
          /* Does it need synthesizing?  */
          if (DECL_DEFAULTED_FN (decl) && ! DECL_INITIAL (decl)
        {
          /* Does it need synthesizing?  */
          if (DECL_DEFAULTED_FN (decl) && ! DECL_INITIAL (decl)
@@ -3706,34 +3891,23 @@ cp_write_global_declarations (void)
              && DECL_INITIAL (decl)
              && decl_needed_p (decl))
            {
              && DECL_INITIAL (decl)
              && decl_needed_p (decl))
            {
-             struct cgraph_node *node = cgraph_get_node (decl), *alias, *next;
+             struct cgraph_node *node, *next;
 
 
-             DECL_EXTERNAL (decl) = 0;
-             /* If we mark !DECL_EXTERNAL one of the same body aliases,
-                we need to mark all of them that way.  */
-             if (node && node->same_body)
-               {
-                 DECL_EXTERNAL (node->decl) = 0;
-                 for (alias = node->same_body; alias; alias = alias->next)
-                   DECL_EXTERNAL (alias->decl) = 0;
-               }
+             node = cgraph_get_node (decl);
+             if (node->same_body_alias)
+               node = cgraph_alias_aliased_node (node);
+
+             cgraph_for_node_and_aliases (node, clear_decl_external,
+                                          NULL, true);
              /* If we mark !DECL_EXTERNAL one of the symbols in some comdat
                 group, we need to mark all symbols in the same comdat group
                 that way.  */
              /* If we mark !DECL_EXTERNAL one of the symbols in some comdat
                 group, we need to mark all symbols in the same comdat group
                 that way.  */
-             if (node->same_comdat_group)
-               for (next = node->same_comdat_group;
+             if (node->symbol.same_comdat_group)
+               for (next = cgraph (node->symbol.same_comdat_group);
                     next != node;
                     next != node;
-                    next = next->same_comdat_group)
-                 {
-                   DECL_EXTERNAL (next->decl) = 0;
-                   if (next->same_body)
-                     {
-                       for (alias = next->same_body;
-                            alias;
-                            alias = alias->next)
-                         DECL_EXTERNAL (alias->decl) = 0;
-                     }
-                 }
+                    next = cgraph (next->symbol.same_comdat_group))
+                 cgraph_for_node_and_aliases (next, clear_decl_external,
+                                              NULL, true);
            }
 
          /* If we're going to need to write this function out, and
            }
 
          /* If we're going to need to write this function out, and
@@ -3743,7 +3917,7 @@ cp_write_global_declarations (void)
          if (!DECL_EXTERNAL (decl)
              && decl_needed_p (decl)
              && !TREE_ASM_WRITTEN (decl)
          if (!DECL_EXTERNAL (decl)
              && decl_needed_p (decl)
              && !TREE_ASM_WRITTEN (decl)
-             && !cgraph_node (decl)->local.finalized)
+             && !cgraph_get_node (decl)->local.finalized)
            {
              /* We will output the function; no longer consider it in this
                 loop.  */
            {
              /* We will output the function; no longer consider it in this
                 loop.  */
@@ -3764,7 +3938,7 @@ cp_write_global_declarations (void)
        reconsider = true;
 
       /* Static data members are just like namespace-scope globals.  */
        reconsider = true;
 
       /* Static data members are just like namespace-scope globals.  */
-      for (i = 0; VEC_iterate (tree, pending_statics, i, decl); ++i)
+      FOR_EACH_VEC_ELT (tree, pending_statics, i, decl)
        {
          if (var_finalized_p (decl) || DECL_REALLY_EXTERN (decl)
              /* Don't write it out if we haven't seen a definition.  */
        {
          if (var_finalized_p (decl) || DECL_REALLY_EXTERN (decl)
              /* Don't write it out if we haven't seen a definition.  */
@@ -3786,7 +3960,7 @@ cp_write_global_declarations (void)
   while (reconsider);
 
   /* All used inline functions must have a definition at this point.  */
   while (reconsider);
 
   /* All used inline functions must have a definition at this point.  */
-  for (i = 0; VEC_iterate (tree, deferred_fns, i, decl); ++i)
+  FOR_EACH_VEC_ELT (tree, deferred_fns, i, decl)
     {
       if (/* Check online inline functions that were actually used.  */
          DECL_ODR_USED (decl) && DECL_DECLARED_INLINE_P (decl)
     {
       if (/* Check online inline functions that were actually used.  */
          DECL_ODR_USED (decl) && DECL_DECLARED_INLINE_P (decl)
@@ -3796,10 +3970,10 @@ cp_write_global_declarations (void)
             #pragma interface, etc.) we decided not to emit the
             definition here.  */
          && !DECL_INITIAL (decl)
             #pragma interface, etc.) we decided not to emit the
             definition here.  */
          && !DECL_INITIAL (decl)
-         /* An explicit instantiation can be used to specify
-            that the body is in another unit. It will have
-            already verified there was a definition.  */
-         && !DECL_EXPLICIT_INSTANTIATION (decl))
+         /* Don't complain if the template was defined.  */
+         && !(DECL_TEMPLATE_INSTANTIATION (decl)
+              && DECL_INITIAL (DECL_TEMPLATE_RESULT
+                               (template_for_substitution (decl)))))
        {
          warning (0, "inline function %q+D used but never defined", decl);
          /* Avoid a duplicate warning from check_global_declaration_1.  */
        {
          warning (0, "inline function %q+D used but never defined", decl);
          /* Avoid a duplicate warning from check_global_declaration_1.  */
@@ -3808,10 +3982,18 @@ cp_write_global_declarations (void)
     }
 
   /* So must decls that use a type with no linkage.  */
     }
 
   /* So must decls that use a type with no linkage.  */
-  for (i = 0; VEC_iterate (tree, no_linkage_decls, i, decl); ++i)
+  FOR_EACH_VEC_ELT (tree, no_linkage_decls, i, decl)
     if (!decl_defined_p (decl))
       no_linkage_error (decl);
 
     if (!decl_defined_p (decl))
       no_linkage_error (decl);
 
+  /* Then, do the Objective-C stuff.  This is where all the
+     Objective-C module stuff gets generated (symtab,
+     class/protocol/selector lists etc).  This must be done after C++
+     templates, destructors etc. so that selectors used in C++
+     templates are properly allocated.  */
+  if (c_dialect_objc ())
+    objc_write_global_declarations ();
+
   /* We give C linkage to static constructors and destructors.  */
   push_lang_context (lang_name_c);
 
   /* We give C linkage to static constructors and destructors.  */
   push_lang_context (lang_name_c);
 
@@ -3841,7 +4023,13 @@ cp_write_global_declarations (void)
   /* Collect candidates for Java hidden aliases.  */
   candidates = collect_candidates_for_java_method_aliases ();
 
   /* Collect candidates for Java hidden aliases.  */
   candidates = collect_candidates_for_java_method_aliases ();
 
-  cgraph_finalize_compilation_unit ();
+  timevar_stop (TV_PHASE_DEFERRED);
+  timevar_start (TV_PHASE_OPT_GEN);
+
+  finalize_compilation_unit ();
+
+  timevar_stop (TV_PHASE_OPT_GEN);
+  timevar_start (TV_PHASE_CHECK_DBGINFO);
 
   /* Now, issue warnings about static, but not defined, functions,
      etc., and emit debugging information.  */
 
   /* Now, issue warnings about static, but not defined, functions,
      etc., and emit debugging information.  */
@@ -3854,6 +4042,8 @@ cp_write_global_declarations (void)
                                      VEC_length (tree, pending_statics));
     }
 
                                      VEC_length (tree, pending_statics));
     }
 
+  perform_deferred_noexcept_checks ();
+
   /* Generate hidden aliases for Java.  */
   if (candidates)
     {
   /* Generate hidden aliases for Java.  */
   if (candidates)
     {
@@ -3876,8 +4066,6 @@ cp_write_global_declarations (void)
       }
   }
 
       }
   }
 
-  timevar_pop (TV_VARCONST);
-
   if (flag_detailed_statistics)
     {
       dump_tree_statistics ();
   if (flag_detailed_statistics)
     {
       dump_tree_statistics ();
@@ -3888,6 +4076,8 @@ cp_write_global_declarations (void)
 #ifdef ENABLE_CHECKING
   validate_conversion_obstack ();
 #endif /* ENABLE_CHECKING */
 #ifdef ENABLE_CHECKING
   validate_conversion_obstack ();
 #endif /* ENABLE_CHECKING */
+
+  timevar_stop (TV_PHASE_CHECK_DBGINFO);
 }
 
 /* FN is an OFFSET_REF, DOTSTAR_EXPR or MEMBER_REF indicating the
 }
 
 /* FN is an OFFSET_REF, DOTSTAR_EXPR or MEMBER_REF indicating the
@@ -3897,7 +4087,8 @@ cp_write_global_declarations (void)
    ARGS.  */
 
 tree
    ARGS.  */
 
 tree
-build_offset_ref_call_from_tree (tree fn, VEC(tree,gc) **args)
+build_offset_ref_call_from_tree (tree fn, VEC(tree,gc) **args,
+                                tsubst_flags_t complain)
 {
   tree orig_fn;
   VEC(tree,gc) *orig_args = NULL;
 {
   tree orig_fn;
   VEC(tree,gc) *orig_args = NULL;
@@ -3922,9 +4113,12 @@ build_offset_ref_call_from_tree (tree fn, VEC(tree,gc) **args)
         because we depend on the form of FN.  */
       make_args_non_dependent (*args);
       object = build_non_dependent_expr (object);
         because we depend on the form of FN.  */
       make_args_non_dependent (*args);
       object = build_non_dependent_expr (object);
-      if (TREE_CODE (fn) == DOTSTAR_EXPR)
-       object = cp_build_unary_op (ADDR_EXPR, object, 0, tf_warning_or_error);
-      VEC_safe_insert (tree, gc, *args, 0, object);
+      if (TREE_CODE (TREE_TYPE (fn)) == METHOD_TYPE)
+       {
+         if (TREE_CODE (fn) == DOTSTAR_EXPR)
+           object = cp_build_addr_expr (object, complain);
+         VEC_safe_insert (tree, gc, *args, 0, object);
+       }
       /* Now that the arguments are done, transform FN.  */
       fn = build_non_dependent_expr (fn);
     }
       /* Now that the arguments are done, transform FN.  */
       fn = build_non_dependent_expr (fn);
     }
@@ -3937,14 +4131,17 @@ build_offset_ref_call_from_tree (tree fn, VEC(tree,gc) **args)
        void B::g() { (this->*p)(); }  */
   if (TREE_CODE (fn) == OFFSET_REF)
     {
        void B::g() { (this->*p)(); }  */
   if (TREE_CODE (fn) == OFFSET_REF)
     {
-      tree object_addr = cp_build_unary_op (ADDR_EXPR, object, 0,
-                                         tf_warning_or_error);
+      tree object_addr = cp_build_addr_expr (object, complain);
       fn = TREE_OPERAND (fn, 1);
       fn = TREE_OPERAND (fn, 1);
-      fn = get_member_function_from_ptrfunc (&object_addr, fn);
+      fn = get_member_function_from_ptrfunc (&object_addr, fn,
+                                            complain);
       VEC_safe_insert (tree, gc, *args, 0, object_addr);
     }
 
       VEC_safe_insert (tree, gc, *args, 0, object_addr);
     }
 
-  expr = cp_build_function_call_vec (fn, args, tf_warning_or_error);
+  if (CLASS_TYPE_P (TREE_TYPE (fn)))
+    expr = build_op_call (fn, args, complain);
+  else
+    expr = cp_build_function_call_vec (fn, args, complain);
   if (processing_template_decl && expr != error_mark_node)
     expr = build_min_non_dep_call_vec (expr, orig_fn, orig_args);
 
   if (processing_template_decl && expr != error_mark_node)
     expr = build_min_non_dep_call_vec (expr, orig_fn, orig_args);
 
@@ -3991,22 +4188,21 @@ possibly_inlined_p (tree decl)
 
 /* Mark DECL (either a _DECL or a BASELINK) as "used" in the program.
    If DECL is a specialization or implicitly declared class member,
 
 /* Mark DECL (either a _DECL or a BASELINK) as "used" in the program.
    If DECL is a specialization or implicitly declared class member,
-   generate the actual definition.  */
+   generate the actual definition.  Return false if something goes
+   wrong, true otherwise.  */
 
 
-void
+bool
 mark_used (tree decl)
 {
 mark_used (tree decl)
 {
-  HOST_WIDE_INT saved_processing_template_decl = 0;
-
   /* If DECL is a BASELINK for a single function, then treat it just
      like the DECL for the function.  Otherwise, if the BASELINK is
      for an overloaded function, we don't know which function was
      actually used until after overload resolution.  */
   /* If DECL is a BASELINK for a single function, then treat it just
      like the DECL for the function.  Otherwise, if the BASELINK is
      for an overloaded function, we don't know which function was
      actually used until after overload resolution.  */
-  if (TREE_CODE (decl) == BASELINK)
+  if (BASELINK_P (decl))
     {
       decl = BASELINK_FUNCTIONS (decl);
       if (really_overloaded_fn (decl))
     {
       decl = BASELINK_FUNCTIONS (decl);
       if (really_overloaded_fn (decl))
-       return;
+       return true;
       decl = OVL_CURRENT (decl);
     }
 
       decl = OVL_CURRENT (decl);
     }
 
@@ -4015,6 +4211,10 @@ mark_used (tree decl)
   if (DECL_CLONED_FUNCTION_P (decl))
     TREE_USED (DECL_CLONED_FUNCTION (decl)) = 1;
 
   if (DECL_CLONED_FUNCTION_P (decl))
     TREE_USED (DECL_CLONED_FUNCTION (decl)) = 1;
 
+  /* Mark enumeration types as used.  */
+  if (TREE_CODE (decl) == CONST_DECL)
+    used_types_insert (DECL_CONTEXT (decl));
+
   if (TREE_CODE (decl) == FUNCTION_DECL
       && DECL_DELETED_FN (decl))
     {
   if (TREE_CODE (decl) == FUNCTION_DECL
       && DECL_DELETED_FN (decl))
     {
@@ -4027,16 +4227,14 @@ mark_used (tree decl)
                 generate it properly; see maybe_add_lambda_conv_op.  */
              sorry ("converting lambda which uses %<...%> to "
                     "function pointer");
                 generate it properly; see maybe_add_lambda_conv_op.  */
              sorry ("converting lambda which uses %<...%> to "
                     "function pointer");
-             return;
+             return false;
            }
        }
            }
        }
-      error ("deleted function %q+D", decl);
-      error ("used here");
-      return;
+      error ("use of deleted function %qD", decl);
+      if (!maybe_explain_implicit_delete (decl))
+       error_at (DECL_SOURCE_LOCATION (decl), "declared here");
+      return false;
     }
     }
-  /* If we don't need a value, then we don't need to synthesize DECL.  */
-  if (cp_unevaluated_operand != 0)
-    return;
 
   /* We can only check DECL_ODR_USED on variables or functions with
      DECL_LANG_SPECIFIC set, and these are also the only decls that we
 
   /* We can only check DECL_ODR_USED on variables or functions with
      DECL_LANG_SPECIFIC set, and these are also the only decls that we
@@ -4044,46 +4242,73 @@ mark_used (tree decl)
   if ((TREE_CODE (decl) != VAR_DECL && TREE_CODE (decl) != FUNCTION_DECL)
       || DECL_LANG_SPECIFIC (decl) == NULL
       || DECL_THUNK_P (decl))
   if ((TREE_CODE (decl) != VAR_DECL && TREE_CODE (decl) != FUNCTION_DECL)
       || DECL_LANG_SPECIFIC (decl) == NULL
       || DECL_THUNK_P (decl))
-    return;
+    {
+      if (!processing_template_decl && type_uses_auto (TREE_TYPE (decl)))
+       {
+         error ("use of %qD before deduction of %<auto%>", decl);
+         return false;
+       }
+      return true;
+    }
 
   /* We only want to do this processing once.  We don't need to keep trying
      to instantiate inline templates, because unit-at-a-time will make sure
      we get them compiled before functions that want to inline them.  */
   if (DECL_ODR_USED (decl))
 
   /* We only want to do this processing once.  We don't need to keep trying
      to instantiate inline templates, because unit-at-a-time will make sure
      we get them compiled before functions that want to inline them.  */
   if (DECL_ODR_USED (decl))
-    return;
+    return true;
 
   /* If within finish_function, defer the rest until that function
      finishes, otherwise it might recurse.  */
   if (defer_mark_used_calls)
     {
       VEC_safe_push (tree, gc, deferred_mark_used_calls, decl);
 
   /* If within finish_function, defer the rest until that function
      finishes, otherwise it might recurse.  */
   if (defer_mark_used_calls)
     {
       VEC_safe_push (tree, gc, deferred_mark_used_calls, decl);
-      return;
+      return true;
     }
 
     }
 
-  /* Normally, we can wait until instantiation-time to synthesize
-     DECL.  However, if DECL is a static data member initialized with
-     a constant, we need the value right now because a reference to
-     such a data member is not value-dependent.  */
-  if (TREE_CODE (decl) == VAR_DECL
-      && DECL_INITIALIZED_BY_CONSTANT_EXPRESSION_P (decl)
-      && DECL_CLASS_SCOPE_P (decl))
+  if (TREE_CODE (decl) == FUNCTION_DECL)
+    maybe_instantiate_noexcept (decl);
+
+  /* Normally, we can wait until instantiation-time to synthesize DECL.
+     However, if DECL is a static data member initialized with a constant
+     or a constexpr function, we need it right now because a reference to
+     such a data member or a call to such function is not value-dependent.
+     For a function that uses auto in the return type, we need to instantiate
+     it to find out its type.  */
+  if ((decl_maybe_constant_var_p (decl)
+       || (TREE_CODE (decl) == FUNCTION_DECL
+          && (DECL_DECLARED_CONSTEXPR_P (decl)
+              || type_uses_auto (TREE_TYPE (TREE_TYPE (decl))))))
+      && DECL_LANG_SPECIFIC (decl)
+      && DECL_TEMPLATE_INFO (decl)
+      && !uses_template_parms (DECL_TI_ARGS (decl)))
     {
     {
-      /* Don't try to instantiate members of dependent types.  We
-        cannot just use dependent_type_p here because this function
-        may be called from fold_non_dependent_expr, and then we may
-        see dependent types, even though processing_template_decl
-        will not be set.  */
-      if (CLASSTYPE_TEMPLATE_INFO ((DECL_CONTEXT (decl)))
-         && uses_template_parms (CLASSTYPE_TI_ARGS (DECL_CONTEXT (decl))))
-       return;
-      /* Pretend that we are not in a template, even if we are, so
-        that the static data member initializer will be processed.  */
-      saved_processing_template_decl = processing_template_decl;
-      processing_template_decl = 0;
+      /* Instantiating a function will result in garbage collection.  We
+        must treat this situation as if we were within the body of a
+        function so as to avoid collecting live data only referenced from
+        the stack (such as overload resolution candidates).  */
+      ++function_depth;
+      instantiate_decl (decl, /*defer_ok=*/false,
+                       /*expl_inst_class_mem_p=*/false);
+      --function_depth;
+    }
+
+  if (type_uses_auto (TREE_TYPE (decl)))
+    {
+      error ("use of %qD before deduction of %<auto%>", decl);
+      return false;
     }
 
     }
 
+  /* If we don't need a value, then we don't need to synthesize DECL.  */
+  if (cp_unevaluated_operand != 0)
+    return true;
+
   if (processing_template_decl)
   if (processing_template_decl)
-    return;
+    return true;
+
+  /* Check this too in case we're within fold_non_dependent_expr.  */
+  if (DECL_TEMPLATE_INFO (decl)
+      && uses_template_parms (DECL_TI_ARGS (decl)))
+    return true;
 
   DECL_ODR_USED (decl) = 1;
   if (DECL_CLONED_FUNCTION_P (decl))
 
   DECL_ODR_USED (decl) = 1;
   if (DECL_CLONED_FUNCTION_P (decl))
@@ -4118,8 +4343,19 @@ mark_used (tree decl)
   if (TREE_CODE (decl) == FUNCTION_DECL
       && DECL_NONSTATIC_MEMBER_FUNCTION_P (decl)
       && DECL_DEFAULTED_FN (decl)
   if (TREE_CODE (decl) == FUNCTION_DECL
       && DECL_NONSTATIC_MEMBER_FUNCTION_P (decl)
       && DECL_DEFAULTED_FN (decl)
+      /* A function defaulted outside the class is synthesized either by
+        cp_finish_decl or instantiate_decl.  */
+      && !DECL_DEFAULTED_OUTSIDE_CLASS_P (decl)
       && ! DECL_INITIAL (decl))
     {
       && ! DECL_INITIAL (decl))
     {
+      /* Defer virtual destructors so that thunks get the right
+        linkage.  */
+      if (DECL_VIRTUAL_P (decl) && !at_eof)
+       {
+         note_vague_linkage_fn (decl);
+         return true;
+       }
+
       /* Remember the current location for a function we will end up
         synthesizing.  Then we can inform the user where it was
         required in the case of error.  */
       /* Remember the current location for a function we will end up
         synthesizing.  Then we can inform the user where it was
         required in the case of error.  */
@@ -4131,7 +4367,7 @@ mark_used (tree decl)
         on the stack (such as overload resolution candidates).
 
          We could just let cp_write_global_declarations handle synthesizing
         on the stack (such as overload resolution candidates).
 
          We could just let cp_write_global_declarations handle synthesizing
-         this function, since we just added it to deferred_fns, but doing
+         this function by adding it to deferred_fns, but doing
          it at the use site produces better error messages.  */
       ++function_depth;
       synthesize_method (decl);
          it at the use site produces better error messages.  */
       ++function_depth;
       synthesize_method (decl);
@@ -4152,10 +4388,14 @@ mark_used (tree decl)
        times.  Maintaining a stack of active functions is expensive,
        and the inliner knows to instantiate any functions it might
        need.  Therefore, we always try to defer instantiation.  */
        times.  Maintaining a stack of active functions is expensive,
        and the inliner knows to instantiate any functions it might
        need.  Therefore, we always try to defer instantiation.  */
-    instantiate_decl (decl, /*defer_ok=*/true,
-                     /*expl_inst_class_mem_p=*/false);
+    {
+      ++function_depth;
+      instantiate_decl (decl, /*defer_ok=*/true,
+                       /*expl_inst_class_mem_p=*/false);
+      --function_depth;
+    }
 
 
-  processing_template_decl = saved_processing_template_decl;
+  return true;
 }
 
 #include "gt-cp-decl2.h"
 }
 
 #include "gt-cp-decl2.h"