re PR c++/54738 ([C++11][SFINAE] Hard errors for pointer-to-member function expressions)
[gcc.git] / gcc / cp / decl2.c
index d1b252d58a84c1e6d1883559f31457e6c23c00ef..4cff0516d776060e0fede79ea70f9104fbbbb9db 100644 (file)
@@ -1,7 +1,7 @@
 /* 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, 2010,
-   2011 Free Software Foundation, Inc.
+   2011, 2012 Free Software Foundation, Inc.
    Hacked by Michael Tiemann (tiemann@cygnus.com)
 
 This file is part of GCC.
@@ -36,18 +36,16 @@ along with GCC; see the file COPYING3.  If not see
 #include "flags.h"
 #include "cp-tree.h"
 #include "decl.h"
-#include "output.h"
 #include "toplev.h"
 #include "timevar.h"
 #include "cpplib.h"
 #include "target.h"
 #include "c-family/c-common.h"
 #include "c-family/c-objc.h"
-#include "tree-mudflap.h"
 #include "cgraph.h"
 #include "tree-inline.h"
 #include "c-family/c-pragma.h"
-#include "tree-dump.h"
+#include "dumpfile.h"
 #include "intl.h"
 #include "gimple.h"
 #include "pointer-set.h"
@@ -86,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 bool determine_hidden_inline (tree);
 static bool decl_defined_p (tree);
 
 /* A list of static class variables.  This is needed, because a
@@ -151,6 +150,9 @@ change_return_type (tree new_ret, tree 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;
 
@@ -161,8 +163,7 @@ change_return_type (tree new_ret, tree fntype)
     }
   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)
@@ -334,7 +335,7 @@ grokclassfn (tree ctype, tree function, enum overload_flags flags)
    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;
@@ -348,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))
-       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);
     }
@@ -360,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)))
-    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;
@@ -371,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]'.  */
-      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);
@@ -437,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.  */
-  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);
 
@@ -495,6 +494,7 @@ check_member_template (tree tmpl)
   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))))
     {
@@ -770,7 +770,9 @@ finish_static_data_member_decl (tree 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);
 
@@ -796,7 +798,7 @@ grokfield (const cp_declarator *declarator,
 {
   tree value;
   const char *asmspec = 0;
-  int flags = LOOKUP_ONLYCONVERTING;
+  int flags;
   tree name;
 
   if (init
@@ -848,9 +850,6 @@ grokfield (const cp_declarator *declarator,
       DECL_NONLOCAL (value) = 1;
       DECL_CONTEXT (value) = current_class_type;
 
-      if (processing_template_decl)
-       value = push_template_decl (value);
-
       if (attrlist)
        {
          int attrflags = 0;
@@ -864,11 +863,18 @@ grokfield (const cp_declarator *declarator,
          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)
        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;
     }
 
@@ -902,6 +908,8 @@ grokfield (const cp_declarator *declarator,
                  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))
@@ -919,13 +927,14 @@ grokfield (const cp_declarator *declarator,
                     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)
-           init = digest_init (TREE_TYPE (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))
@@ -955,6 +964,12 @@ grokfield (const cp_declarator *declarator,
   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:
@@ -969,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);
-      DECL_INITIAL (value) = init;
       DECL_IN_AGGR_P (value) = 1;
       return value;
 
@@ -1090,6 +1104,11 @@ is_late_template_attribute (tree attr, tree decl)
   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))
@@ -1187,9 +1206,9 @@ save_template_attributes (tree *attr_p, tree *decl_p)
 
   old_attrs = *q;
 
-  /* Place the late attributes at the beginning of the attribute
+  /* Merge the late attributes at the beginning with the attribute
      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))
@@ -1249,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
-           (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)
@@ -1329,7 +1347,10 @@ 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)
-    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;
@@ -1353,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)
-       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);
@@ -1439,12 +1460,7 @@ finish_anon_union (tree anon_union_decl)
     }
 
   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
@@ -1665,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);
+         TREE_USED (decl) = 1;
        }
     }
 }
@@ -1770,10 +1787,7 @@ var_finalized_p (tree var)
 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);
 }
 
@@ -1799,9 +1813,7 @@ 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.  */
-  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.  */
@@ -1822,7 +1834,7 @@ maybe_emit_vtables (tree ctype)
   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.  */
@@ -1866,10 +1878,12 @@ maybe_emit_vtables (tree ctype)
 
       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.  */
-         gcc_assert (!expr);
+         gcc_assert (!expr && !cleanups);
        }
 
       /* Write it out.  */
@@ -1880,20 +1894,15 @@ maybe_emit_vtables (tree ctype)
         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)
-           last->same_comdat_group = current;
+           symtab_add_to_same_comdat_group ((symtab_node) current, (symtab_node) last);
          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);
@@ -1941,10 +1950,12 @@ type_visibility (tree type)
 }
 
 /* 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)
     {
@@ -1962,12 +1973,12 @@ constrain_visibility (tree decl, int visibility)
        }
     }
   else if (visibility > DECL_VISIBILITY (decl)
-          && !DECL_VISIBILITY_SPECIFIED (decl))
+          && (tmpl || !DECL_VISIBILITY_SPECIFIED (decl)))
     {
       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
@@ -2003,7 +2014,7 @@ constrain_visibility_for_template (tree decl, tree targs)
            }
        }
       if (vis)
-       constrain_visibility (decl, vis);
+       constrain_visibility (decl, vis, true);
     }
 }
 
@@ -2078,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);
-         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
-           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.  */
@@ -2101,7 +2127,7 @@ determine_visibility (tree decl)
          if (underlying_vis == VISIBILITY_ANON
              || (CLASS_TYPE_P (underlying_type)
                  && CLASSTYPE_VISIBILITY_SPECIFIED (underlying_type)))
-           constrain_visibility (decl, underlying_vis);
+           constrain_visibility (decl, underlying_vis, false);
          else
            DECL_VISIBILITY (decl) = VISIBILITY_DEFAULT;
        }
@@ -2109,7 +2135,7 @@ determine_visibility (tree decl)
        {
          /* 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.  */
@@ -2124,10 +2150,15 @@ determine_visibility (tree 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;
+            }
        }
     }
 
@@ -2139,23 +2170,52 @@ determine_visibility (tree decl)
                    ? 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)
        {
-         int depth = TMPL_ARGS_DEPTH (args);
          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);
+           }
        }
     }
 
@@ -2165,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.  */
-    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))
-       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
@@ -2183,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.  */
-    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.  */
@@ -2204,15 +2264,7 @@ determine_visibility_from_class (tree decl, tree class_type)
   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
     {
@@ -2237,6 +2289,23 @@ determine_visibility_from_class (tree decl, tree class_type)
     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.  */
 
@@ -2973,8 +3042,8 @@ get_priority_info (int priority)
    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);
 
@@ -3362,44 +3431,6 @@ generate_ctor_and_dtor_functions_for_priority (splay_tree_node n, void * data)
   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_get_create_node (PTRMEM_CST_MEMBER (t)));
-      break;
-    case BASELINK:
-      if (TREE_CODE (BASELINK_FUNCTIONS (t)) == FUNCTION_DECL)
-       cgraph_mark_address_taken_node (
-                             cgraph_get_create_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
@@ -3415,9 +3446,9 @@ collect_candidates_for_java_method_aliases (void)
   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))
@@ -3449,9 +3480,9 @@ build_java_method_aliases (struct pointer_set_t *candidates)
   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))
@@ -3573,26 +3604,16 @@ decl_defined_p (tree decl)
 bool
 decl_constant_var_p (tree decl)
 {
-  bool ret;
-  tree type = TREE_TYPE (decl);
-  if (TREE_CODE (decl) != VAR_DECL)
+  if (!decl_maybe_constant_var_p (decl))
     return false;
-  if (DECL_DECLARED_CONSTEXPR_P (decl)
-      || (CP_TYPE_CONST_NON_VOLATILE_P (type)
-         && INTEGRAL_OR_ENUMERATION_TYPE_P (type)))
-    {
-      /* 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);
-      ret = DECL_INITIALIZED_BY_CONSTANT_EXPRESSION_P (decl);
-    }
-  else
-    ret = false;
 
-  return ret;
+  /* 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
@@ -3637,6 +3658,15 @@ 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
@@ -3665,6 +3695,8 @@ cp_write_global_declarations (void)
   if (pch_file)
     c_common_write_pch ();
 
+  cgraph_process_same_body_aliases ();
+
   /* Handle -fdump-ada-spec[-slim] */
   if (dump_enabled_p (TDI_ada))
     {
@@ -3678,6 +3710,8 @@ cp_write_global_declarations (void)
 
   /* 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:
 
@@ -3694,8 +3728,6 @@ cp_write_global_declarations (void)
      generating the initializer for an object may cause templates to be
      instantiated, etc., etc.  */
 
-  timevar_push (TV_VARCONST);
-
   emit_support_tinfos ();
 
   do
@@ -3859,34 +3891,23 @@ cp_write_global_declarations (void)
              && 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 (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 = 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
@@ -3949,10 +3970,10 @@ cp_write_global_declarations (void)
             #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.  */
@@ -4002,7 +4023,13 @@ cp_write_global_declarations (void)
   /* 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.  */
@@ -4039,8 +4066,6 @@ cp_write_global_declarations (void)
       }
   }
 
-  timevar_pop (TV_VARCONST);
-
   if (flag_detailed_statistics)
     {
       dump_tree_statistics ();
@@ -4051,6 +4076,8 @@ cp_write_global_declarations (void)
 #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
@@ -4060,7 +4087,8 @@ cp_write_global_declarations (void)
    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;
@@ -4088,7 +4116,7 @@ build_offset_ref_call_from_tree (tree fn, VEC(tree,gc) **args)
       if (TREE_CODE (TREE_TYPE (fn)) == METHOD_TYPE)
        {
          if (TREE_CODE (fn) == DOTSTAR_EXPR)
-           object = cp_build_addr_expr (object, tf_warning_or_error);
+           object = cp_build_addr_expr (object, complain);
          VEC_safe_insert (tree, gc, *args, 0, object);
        }
       /* Now that the arguments are done, transform FN.  */
@@ -4103,16 +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)
     {
-      tree object_addr = cp_build_addr_expr (object, tf_warning_or_error);
+      tree object_addr = cp_build_addr_expr (object, complain);
       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);
     }
 
   if (CLASS_TYPE_P (TREE_TYPE (fn)))
-    expr = build_op_call (fn, args, tf_warning_or_error);
+    expr = build_op_call (fn, args, complain);
   else
-    expr = cp_build_function_call_vec (fn, args, tf_warning_or_error);
+    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);
 
@@ -4159,20 +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,
-   generate the actual definition.  */
+   generate the actual definition.  Return false if something goes
+   wrong, true otherwise.  */
 
-void
+bool
 mark_used (tree decl)
 {
   /* 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))
-       return;
+       return true;
       decl = OVL_CURRENT (decl);
     }
 
@@ -4181,6 +4211,10 @@ mark_used (tree decl)
   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))
     {
@@ -4193,13 +4227,13 @@ mark_used (tree decl)
                 generate it properly; see maybe_add_lambda_conv_op.  */
              sorry ("converting lambda which uses %<...%> to "
                     "function pointer");
-             return;
+             return false;
            }
        }
       error ("use of deleted function %qD", decl);
       if (!maybe_explain_implicit_delete (decl))
        error_at (DECL_SOURCE_LOCATION (decl), "declared here");
-      return;
+      return false;
     }
 
   /* We can only check DECL_ODR_USED on variables or functions with
@@ -4208,32 +4242,45 @@ mark_used (tree 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))
-    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);
-      return;
+      return true;
     }
 
+  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.  */
+     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)))
-      && !DECL_INITIAL (decl)
+          && (DECL_DECLARED_CONSTEXPR_P (decl)
+              || type_uses_auto (TREE_TYPE (TREE_TYPE (decl))))))
       && DECL_LANG_SPECIFIC (decl)
-      && DECL_TEMPLATE_INSTANTIATION (decl))
+      && DECL_TEMPLATE_INFO (decl)
+      && !uses_template_parms (DECL_TI_ARGS (decl)))
     {
       /* Instantiating a function will result in garbage collection.  We
         must treat this situation as if we were within the body of a
@@ -4245,17 +4292,23 @@ mark_used (tree decl)
       --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;
+    return true;
 
   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;
+    return true;
 
   DECL_ODR_USED (decl) = 1;
   if (DECL_CLONED_FUNCTION_P (decl))
@@ -4290,8 +4343,19 @@ mark_used (tree 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))
     {
+      /* 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.  */
@@ -4303,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
-         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);
@@ -4324,8 +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.  */
-    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;
+    }
+
+  return true;
 }
 
 #include "gt-cp-decl2.h"