]> git.ipfire.org Git - thirdparty/gcc.git/blobdiff - gcc/cp/decl.c
Merge from trunk.
[thirdparty/gcc.git] / gcc / cp / decl.c
index cebd36103b79580f90e7ebbe3f8557efb947d735..babfc8893b850e9fb32805225e97d75694bf765c 100644 (file)
@@ -31,6 +31,11 @@ along with GCC; see the file COPYING3.  If not see
 #include "coretypes.h"
 #include "tm.h"
 #include "tree.h"
+#include "stringpool.h"
+#include "stor-layout.h"
+#include "varasm.h"
+#include "attribs.h"
+#include "calls.h"
 #include "flags.h"
 #include "cp-tree.h"
 #include "tree-iterator.h"
@@ -44,6 +49,8 @@ along with GCC; see the file COPYING3.  If not see
 #include "c-family/c-common.h"
 #include "c-family/c-objc.h"
 #include "c-family/c-pragma.h"
+#include "c-family/c-target.h"
+#include "c-family/c-ubsan.h"
 #include "diagnostic.h"
 #include "intl.h"
 #include "debug.h"
@@ -52,6 +59,7 @@ along with GCC; see the file COPYING3.  If not see
 #include "splay-tree.h"
 #include "plugin.h"
 #include "cgraph.h"
+#include "wide-int.h"
 
 /* Possible cases of bad specifiers type used by bad_specifiers. */
 enum bad_spec_place {
@@ -75,7 +83,6 @@ static tree grokvardecl (tree, tree, const cp_decl_specifier_seq *,
 static int check_static_variable_definition (tree, tree);
 static void record_unknown_type (tree, const char *);
 static tree builtin_function_1 (tree, tree, bool);
-static tree build_library_fn_1 (tree, enum tree_code, tree);
 static int member_function_or_else (tree, tree, enum overload_flags);
 static void bad_specifiers (tree, enum bad_spec_place, int, int, int, int,
                            int);
@@ -107,8 +114,8 @@ static tree cp_make_fname_decl (location_t, tree, int);
 static void initialize_predefined_identifiers (void);
 static tree check_special_function_return_type
        (special_function_kind, tree, tree);
-static tree push_cp_library_fn (enum tree_code, tree);
-static tree build_cp_library_fn (tree, enum tree_code, tree);
+static tree push_cp_library_fn (enum tree_code, tree, int);
+static tree build_cp_library_fn (tree, enum tree_code, tree, int);
 static void store_parm_decls (tree);
 static void initialize_local_var (tree, tree);
 static void expand_static_init (tree, tree);
@@ -622,17 +629,22 @@ poplevel (int keep, int reverse, int functionbody)
           push_local_binding where the list of decls returned by
           getdecls is built.  */
        decl = TREE_CODE (d) == TREE_LIST ? TREE_VALUE (d) : d;
+       // See through references for improved -Wunused-variable (PR 38958).
+       tree type = non_reference (TREE_TYPE (decl));
        if (VAR_P (decl)
            && (! TREE_USED (decl) || !DECL_READ_P (decl))
            && ! DECL_IN_SYSTEM_HEADER (decl)
            && DECL_NAME (decl) && ! DECL_ARTIFICIAL (decl)
-           && TREE_TYPE (decl) != error_mark_node
-           && (!CLASS_TYPE_P (TREE_TYPE (decl))
-               || !TYPE_HAS_NONTRIVIAL_DESTRUCTOR (TREE_TYPE (decl))))
+           && type != error_mark_node
+           && (!CLASS_TYPE_P (type)
+               || !TYPE_HAS_NONTRIVIAL_DESTRUCTOR (type)
+               || lookup_attribute ("warn_unused",
+                                    TYPE_ATTRIBUTES (TREE_TYPE (decl)))))
          {
            if (! TREE_USED (decl))
              warning (OPT_Wunused_variable, "unused variable %q+D", decl);
            else if (DECL_CONTEXT (decl) == current_function_decl
+                    // For -Wunused-but-set-variable leave references alone.
                     && TREE_CODE (TREE_TYPE (decl)) != REFERENCE_TYPE
                     && errorcount == unused_but_set_errorcount)
              {
@@ -649,7 +661,7 @@ poplevel (int keep, int reverse, int functionbody)
       if (leaving_for_scope && VAR_P (link)
          /* It's hard to make this ARM compatibility hack play nicely with
             lambdas, and it really isn't necessary in C++11 mode.  */
-         && cxx_dialect < cxx0x
+         && cxx_dialect < cxx11
          && DECL_NAME (link))
        {
          tree name = DECL_NAME (link);
@@ -1024,6 +1036,7 @@ decls_match (tree newdecl, tree olddecl)
          else
            types_match =
              compparms (p1, p2)
+             && type_memfn_rqual (f1) == type_memfn_rqual (f2)
              && (TYPE_ATTRIBUTES (TREE_TYPE (newdecl)) == NULL_TREE
                  || comp_type_attributes (TREE_TYPE (newdecl),
                                           TREE_TYPE (olddecl)) != 0);
@@ -1140,8 +1153,9 @@ warn_extern_redeclared_static (tree newdecl, tree olddecl)
       && DECL_ARTIFICIAL (olddecl))
     return;
 
-  permerror (input_location, "%qD was declared %<extern%> and later %<static%>", newdecl);
-  permerror (input_location, "previous declaration of %q+D", olddecl);
+  if (permerror (input_location,
+                "%qD was declared %<extern%> and later %<static%>", newdecl))
+    inform (input_location, "previous declaration of %q+D", olddecl);
 }
 
 /* NEW_DECL is a redeclaration of OLD_DECL; both are functions or
@@ -1208,10 +1222,12 @@ validate_constexpr_redeclaration (tree old_decl, tree new_decl)
       if (! DECL_TEMPLATE_SPECIALIZATION (old_decl)
          && DECL_TEMPLATE_SPECIALIZATION (new_decl))
        return true;
+
+      error ("redeclaration %qD differs in %<constexpr%>", new_decl);
+      error ("from previous declaration %q+D", old_decl);
+      return false;
     }
-  error ("redeclaration %qD differs in %<constexpr%>", new_decl);
-  error ("from previous declaration %q+D", old_decl);
-  return false;
+  return true;
 }
 
 #define GNU_INLINE_P(fn) (DECL_DECLARED_INLINE_P (fn)                  \
@@ -1281,19 +1297,19 @@ duplicate_decls (tree newdecl, tree olddecl, bool newdecl_is_friend)
               && DECL_UNINLINABLE (olddecl)
               && lookup_attribute ("noinline", DECL_ATTRIBUTES (olddecl)))
        {
-         warning (OPT_Wattributes, "function %q+D redeclared as inline",
-                  newdecl);
-         warning (OPT_Wattributes, "previous declaration of %q+D "
-                  "with attribute noinline", olddecl);
+         if (warning (OPT_Wattributes, "function %q+D redeclared as inline",
+                      newdecl))
+           inform (input_location, "previous declaration of %q+D "
+                   "with attribute noinline", olddecl);
        }
       else if (DECL_DECLARED_INLINE_P (olddecl)
               && DECL_UNINLINABLE (newdecl)
               && lookup_attribute ("noinline", DECL_ATTRIBUTES (newdecl)))
        {
-         warning (OPT_Wattributes, "function %q+D redeclared with "
-                  "attribute noinline", newdecl);
-         warning (OPT_Wattributes, "previous declaration of %q+D was inline",
-                  olddecl);
+         if (warning (OPT_Wattributes, "function %q+D redeclared with "
+                      "attribute noinline", newdecl))
+           inform (input_location, "previous declaration of %q+D was inline",
+                   olddecl);
        }
     }
 
@@ -1334,6 +1350,15 @@ duplicate_decls (tree newdecl, tree olddecl, bool newdecl_is_friend)
            }
          return NULL_TREE;
        }
+      else if (DECL_OMP_DECLARE_REDUCTION_P (olddecl))
+       {
+         gcc_assert (DECL_OMP_DECLARE_REDUCTION_P (newdecl));
+         error_at (DECL_SOURCE_LOCATION (newdecl),
+                   "redeclaration of %<pragma omp declare reduction%>");
+         error_at (DECL_SOURCE_LOCATION (olddecl),
+                   "previous %<pragma omp declare reduction%> declaration");
+         return error_mark_node;
+       }
       else if (!types_match)
        {
          /* Avoid warnings redeclaring built-ins which have not been
@@ -1479,7 +1504,7 @@ duplicate_decls (tree newdecl, tree olddecl, bool newdecl_is_friend)
       error ("%q#D redeclared as different kind of symbol", newdecl);
       if (TREE_CODE (olddecl) == TREE_LIST)
        olddecl = TREE_VALUE (olddecl);
-      error ("previous declaration of %q+#D", olddecl);
+      inform (input_location, "previous declaration of %q+#D", olddecl);
 
       return error_mark_node;
     }
@@ -1544,7 +1569,8 @@ duplicate_decls (tree newdecl, tree olddecl, bool newdecl_is_friend)
       else
        {
          error ("conflicting declaration %q#D", newdecl);
-         error ("%q+D has a previous declaration as %q#D", olddecl, olddecl);
+         inform (input_location,
+                 "%q+D has a previous declaration as %q#D", olddecl, olddecl);
          return error_mark_node;
        }
     }
@@ -1607,9 +1633,10 @@ duplicate_decls (tree newdecl, tree olddecl, bool newdecl_is_friend)
        {
          error_at (DECL_SOURCE_LOCATION (newdecl), errmsg, newdecl);
          if (DECL_NAME (olddecl) != NULL_TREE)
-           error ((DECL_INITIAL (olddecl) && namespace_bindings_p ())
-                  ? G_("%q+#D previously defined here")
-                  : G_("%q+#D previously declared here"), olddecl);
+           inform (input_location,
+                   (DECL_INITIAL (olddecl) && namespace_bindings_p ())
+                   ? G_("%q+#D previously defined here")
+                   : G_("%q+#D previously declared here"), olddecl);
          return error_mark_node;
        }
       else if (TREE_CODE (olddecl) == FUNCTION_DECL
@@ -1753,8 +1780,10 @@ duplicate_decls (tree newdecl, tree olddecl, bool newdecl_is_friend)
          && (! DECL_TEMPLATE_SPECIALIZATION (newdecl)
              || DECL_TEMPLATE_SPECIALIZATION (olddecl)))
        {
-         warning (OPT_Wredundant_decls, "redundant redeclaration of %qD in same scope", newdecl);
-         warning (OPT_Wredundant_decls, "previous declaration of %q+D", olddecl);
+         if (warning (OPT_Wredundant_decls,
+                      "redundant redeclaration of %qD in same scope",
+                      newdecl))
+           inform (input_location, "previous declaration of %q+D", olddecl);
        }
 
       if (!(DECL_TEMPLATE_INSTANTIATION (olddecl)
@@ -3086,13 +3115,15 @@ case_conversion (tree type, tree value)
   if (value == NULL_TREE)
     return value;
 
-  if (cxx_dialect >= cxx0x
+  if (cxx_dialect >= cxx11
       && (SCOPED_ENUM_P (type)
          || !INTEGRAL_OR_UNSCOPED_ENUMERATION_TYPE_P (TREE_TYPE (value))))
     {
       if (INTEGRAL_OR_UNSCOPED_ENUMERATION_TYPE_P (type))
        type = type_promotes_to (type);
-      value = perform_implicit_conversion (type, value, tf_warning_or_error);
+      value = (perform_implicit_conversion_flags
+              (type, value, tf_warning_or_error,
+               LOOKUP_IMPLICIT | LOOKUP_NO_NON_INTEGRAL));
     }
   return cxx_constant_value (value);
 }
@@ -3787,10 +3818,10 @@ cxx_init_decl_processing (void)
     newtype = build_exception_variant (newtype, new_eh_spec);
     deltype = cp_build_type_attribute_variant (void_ftype_ptr, extvisattr);
     deltype = build_exception_variant (deltype, empty_except_spec);
-    push_cp_library_fn (NEW_EXPR, newtype);
-    push_cp_library_fn (VEC_NEW_EXPR, newtype);
-    global_delete_fndecl = push_cp_library_fn (DELETE_EXPR, deltype);
-    push_cp_library_fn (VEC_DELETE_EXPR, deltype);
+    DECL_IS_OPERATOR_NEW (push_cp_library_fn (NEW_EXPR, newtype, 0)) = 1;
+    DECL_IS_OPERATOR_NEW (push_cp_library_fn (VEC_NEW_EXPR, newtype, 0)) = 1;
+    global_delete_fndecl = push_cp_library_fn (DELETE_EXPR, deltype, ECF_NOTHROW);
+    push_cp_library_fn (VEC_DELETE_EXPR, deltype, ECF_NOTHROW);
 
     nullptr_type_node = make_node (NULLPTR_TYPE);
     TYPE_SIZE (nullptr_type_node) = bitsize_int (GET_MODE_BITSIZE (ptr_mode));
@@ -3803,7 +3834,8 @@ cxx_init_decl_processing (void)
   }
 
   abort_fndecl
-    = build_library_fn_ptr ("__cxa_pure_virtual", void_ftype);
+    = build_library_fn_ptr ("__cxa_pure_virtual", void_ftype,
+                           ECF_NORETURN | ECF_NOTHROW);
 
   /* Perform other language dependent initializations.  */
   init_class_processing ();
@@ -3994,7 +4026,8 @@ cxx_builtin_function_ext_scope (tree decl)
    function.  Not called directly.  */
 
 static tree
-build_library_fn_1 (tree name, enum tree_code operator_code, tree type)
+build_library_fn (tree name, enum tree_code operator_code, tree type,
+                 int ecf_flags)
 {
   tree fn = build_lang_decl (FUNCTION_DECL, name, type);
   DECL_EXTERNAL (fn) = 1;
@@ -4006,28 +4039,17 @@ build_library_fn_1 (tree name, enum tree_code operator_code, tree type)
      external shared object.  */
   DECL_VISIBILITY (fn) = VISIBILITY_DEFAULT;
   DECL_VISIBILITY_SPECIFIED (fn) = 1;
-  return fn;
-}
-
-/* Returns the _DECL for a library function with C linkage.
-   We assume that such functions never throw; if this is incorrect,
-   callers should unset TREE_NOTHROW.  */
-
-static tree
-build_library_fn (tree name, tree type)
-{
-  tree fn = build_library_fn_1 (name, ERROR_MARK, type);
-  TREE_NOTHROW (fn) = 1;
+  set_call_expr_flags (fn, ecf_flags);
   return fn;
 }
 
 /* Returns the _DECL for a library function with C++ linkage.  */
 
 static tree
-build_cp_library_fn (tree name, enum tree_code operator_code, tree type)
+build_cp_library_fn (tree name, enum tree_code operator_code, tree type,
+                    int ecf_flags)
 {
-  tree fn = build_library_fn_1 (name, operator_code, type);
-  TREE_NOTHROW (fn) = TYPE_NOTHROW_P (type);
+  tree fn = build_library_fn (name, operator_code, type, ecf_flags);
   DECL_CONTEXT (fn) = FROB_CONTEXT (current_namespace);
   SET_DECL_LANGUAGE (fn, lang_cplusplus);
   return fn;
@@ -4037,18 +4059,19 @@ build_cp_library_fn (tree name, enum tree_code operator_code, tree type)
    IDENTIFIER_NODE.  */
 
 tree
-build_library_fn_ptr (const char* name, tree type)
+build_library_fn_ptr (const char* name, tree type, int ecf_flags)
 {
-  return build_library_fn (get_identifier (name), type);
+  return build_library_fn (get_identifier (name), ERROR_MARK, type, ecf_flags);
 }
 
 /* Like build_cp_library_fn, but takes a C string instead of an
    IDENTIFIER_NODE.  */
 
 tree
-build_cp_library_fn_ptr (const char* name, tree type)
+build_cp_library_fn_ptr (const char* name, tree type, int ecf_flags)
 {
-  return build_cp_library_fn (get_identifier (name), ERROR_MARK, type);
+  return build_cp_library_fn (get_identifier (name), ERROR_MARK, type,
+                             ecf_flags);
 }
 
 /* Like build_library_fn, but also pushes the function so that we will
@@ -4056,14 +4079,14 @@ build_cp_library_fn_ptr (const char* name, tree type)
    may throw exceptions listed in RAISES.  */
 
 tree
-push_library_fn (tree name, tree type, tree raises)
+push_library_fn (tree name, tree type, tree raises, int ecf_flags)
 {
   tree fn;
 
   if (raises)
     type = build_exception_variant (type, raises);
 
-  fn = build_library_fn (name, type);
+  fn = build_library_fn (name, ERROR_MARK, type, ecf_flags);
   pushdecl_top_level (fn);
   return fn;
 }
@@ -4072,11 +4095,12 @@ push_library_fn (tree name, tree type, tree raises)
    will be found by normal lookup.  */
 
 static tree
-push_cp_library_fn (enum tree_code operator_code, tree type)
+push_cp_library_fn (enum tree_code operator_code, tree type,
+                   int ecf_flags)
 {
   tree fn = build_cp_library_fn (ansi_opname (operator_code),
                                 operator_code,
-                                type);
+                                type, ecf_flags);
   pushdecl (fn);
   if (flag_tm)
     apply_tm_attr (fn, get_identifier ("transaction_safe"));
@@ -4087,10 +4111,10 @@ push_cp_library_fn (enum tree_code operator_code, tree type)
    a FUNCTION_TYPE.  */
 
 tree
-push_void_library_fn (tree name, tree parmtypes)
+push_void_library_fn (tree name, tree parmtypes, int ecf_flags)
 {
   tree type = build_function_type (void_type_node, parmtypes);
-  return push_library_fn (name, type, NULL_TREE);
+  return push_library_fn (name, type, NULL_TREE, ecf_flags);
 }
 
 /* Like push_library_fn, but also note that this function throws
@@ -4099,9 +4123,7 @@ push_void_library_fn (tree name, tree parmtypes)
 tree
 push_throw_library_fn (tree name, tree type)
 {
-  tree fn = push_library_fn (name, type, NULL_TREE);
-  TREE_THIS_VOLATILE (fn) = 1;
-  TREE_NOTHROW (fn) = 0;
+  tree fn = push_library_fn (name, type, NULL_TREE, ECF_NORETURN);
   return fn;
 }
 \f
@@ -4790,7 +4812,7 @@ check_array_designated_initializer (constructor_elt *ce,
       if (TREE_CODE (ce->index) == INTEGER_CST)
        {
          /* A C99 designator is OK if it matches the current index.  */
-         if (TREE_INT_CST_LOW (ce->index) == index)
+         if (wi::eq_p (ce->index, index))
            return true;
          else
            sorry ("non-trivial designated initializers not supported");
@@ -4882,7 +4904,7 @@ layout_var_decl (tree decl)
   if (type == error_mark_node)
     return;
 
-  /* If we haven't already layed out this declaration, do so now.
+  /* If we haven't already laid out this declaration, do so now.
      Note that we must not call complete type for an external object
      because it's type might involve templates that we are not
      supposed to instantiate yet.  (And it's perfectly valid to say
@@ -5077,12 +5099,11 @@ reshape_init_array_1 (tree elt_type, tree max_index, reshape_iter *d,
       if (integer_all_onesp (max_index))
        return new_init;
 
-      if (host_integerp (max_index, 1))
-       max_index_cst = tree_low_cst (max_index, 1);
+      if (tree_fits_uhwi_p (max_index))
+       max_index_cst = tree_to_uhwi (max_index);
       /* sizetype is sign extended, not zero extended.  */
       else
-       max_index_cst = tree_low_cst (fold_convert (size_type_node, max_index),
-                                     1);
+       max_index_cst = tree_to_uhwi (fold_convert (size_type_node, max_index));
     }
 
   /* Loop until there are no more initializers.  */
@@ -5199,6 +5220,9 @@ reshape_init_class (tree type, reshape_iter *d, bool first_initializer_p,
       /* Handle designated initializers, as an extension.  */
       if (d->cur->index)
        {
+         if (d->cur->index == error_mark_node)
+           return error_mark_node;
+
          if (TREE_CODE (d->cur->index) == INTEGER_CST)
            {
              if (complain & tf_error)
@@ -5666,6 +5690,7 @@ check_initializer (tree decl, tree init, int flags, vec<tree, va_gc> **cleanups)
          && !(init && BRACE_ENCLOSED_INITIALIZER_P (init)
               && CP_AGGREGATE_TYPE_P (type)
               && (CLASS_TYPE_P (type)
+                  || !TYPE_NEEDS_CONSTRUCTING (type)
                   || type_has_extended_temps (type))))
        {
          init_code = build_aggr_init_full_exprs (decl, init, flags);
@@ -5750,7 +5775,7 @@ check_initializer (tree decl, tree init, int flags, vec<tree, va_gc> **cleanups)
     {
       static int explained = 0;
 
-      if (cxx_dialect < cxx0x)
+      if (cxx_dialect < cxx11)
        error ("initializer invalid for static member with constructor");
       else
        error ("non-constant in-class initialization invalid for static "
@@ -6339,25 +6364,6 @@ cp_finish_decl (tree decl, tree init, bool init_const_expr_p,
          cleanups = make_tree_vector ();
          init = check_initializer (decl, init, flags, &cleanups);
 
-         /* Check that the initializer for a static data member was a
-            constant.  Although we check in the parser that the
-            initializer is an integral constant expression, we do not
-            simplify division-by-zero at the point at which it
-            occurs.  Therefore, in:
-
-              struct S { static const int i = 7 / 0; };
-
-            we issue an error at this point.  It would
-            probably be better to forbid division by zero in
-            integral constant expressions.  */
-         if (DECL_EXTERNAL (decl) && init)
-           {
-             error ("%qD cannot be initialized by a non-constant expression"
-                    " when being declared", decl);
-             DECL_INITIALIZED_IN_CLASS_P (decl) = 0;
-             init = NULL_TREE;
-           }
-
          /* Handle:
 
             [dcl.init]
@@ -6402,21 +6408,6 @@ cp_finish_decl (tree decl, tree init, bool init_const_expr_p,
           && TYPE_FOR_JAVA (type) && MAYBE_CLASS_TYPE_P (type))
     error ("non-static data member %qD has Java class type", decl);
 
-  if (array_of_runtime_bound_p (type))
-    {
-      /* If the VLA bound is larger than half the address space, or less
-        than zero, throw std::bad_array_length.  */
-      tree max = convert (ssizetype, TYPE_MAX_VALUE (TYPE_DOMAIN (type)));
-      /* C++1y says we should throw for length <= 0, but we have
-        historically supported zero-length arrays.  Let's treat that as an
-        extension to be disabled by -std=c++NN.  */
-      int lower = flag_iso ? 0 : -1;
-      tree comp = build2 (LT_EXPR, boolean_type_node, max, ssize_int (lower));
-      comp = build3 (COND_EXPR, void_type_node, comp,
-                    throw_bad_array_length (), void_zero_node);
-      finish_expr_stmt (comp);
-    }
-
   /* Add this declaration to the statement-tree.  This needs to happen
      after the call to check_initializer so that the DECL_EXPR for a
      reference temp is added before the DECL_EXPR for the reference itself.  */
@@ -6647,7 +6638,7 @@ get_atexit_node (void)
 
   /* Now, build the function declaration.  */
   push_lang_context (lang_name_c);
-  atexit_fndecl = build_library_fn_ptr (name, fn_type);
+  atexit_fndecl = build_library_fn_ptr (name, fn_type, ECF_LEAF | ECF_NOTHROW);
   mark_used (atexit_fndecl);
   pop_lang_context ();
   atexit_node = decay_conversion (atexit_fndecl, tf_warning_or_error);
@@ -6669,7 +6660,8 @@ get_thread_atexit_node (void)
                                           NULL_TREE);
 
   /* Now, build the function declaration.  */
-  tree atexit_fndecl = build_library_fn_ptr ("__cxa_thread_atexit", fn_type);
+  tree atexit_fndecl = build_library_fn_ptr ("__cxa_thread_atexit", fn_type,
+                                            ECF_LEAF | ECF_NOTHROW);
   return decay_conversion (atexit_fndecl, tf_warning_or_error);
 }
 
@@ -6899,7 +6891,11 @@ expand_static_init (tree decl, tree init)
   /* Some variables require no dynamic initialization.  */
   if (!init
       && TYPE_HAS_TRIVIAL_DESTRUCTOR (TREE_TYPE (decl)))
-    return;
+    {
+      /* Make sure the destructor is callable.  */
+      cxx_maybe_build_cleanup (decl, tf_warning_or_error);
+      return;
+    }
 
   if (DECL_THREAD_LOCAL_P (decl) && DECL_GNU_TLS_P (decl)
       && !DECL_FUNCTION_SCOPE_P (decl))
@@ -6995,15 +6991,17 @@ expand_static_init (tree decl, tree init)
              (acquire_name, build_function_type_list (integer_type_node,
                                                       TREE_TYPE (guard_addr),
                                                       NULL_TREE),
-              NULL_TREE);
+              NULL_TREE, ECF_NOTHROW | ECF_LEAF);
          if (!release_fn || !abort_fn)
            vfntype = build_function_type_list (void_type_node,
                                                TREE_TYPE (guard_addr),
                                                NULL_TREE);
          if (!release_fn)
-           release_fn = push_library_fn (release_name, vfntype, NULL_TREE);
+           release_fn = push_library_fn (release_name, vfntype, NULL_TREE,
+                                          ECF_NOTHROW | ECF_LEAF);
          if (!abort_fn)
-           abort_fn = push_library_fn (abort_name, vfntype, NULL_TREE);
+           abort_fn = push_library_fn (abort_name, vfntype, NULL_TREE,
+                                       ECF_NOTHROW | ECF_LEAF);
 
          inner_if_stmt = begin_if_stmt ();
          finish_if_stmt_cond (build_call_n (acquire_fn, 1, guard_addr),
@@ -7311,6 +7309,22 @@ check_static_quals (tree decl, cp_cv_quals quals)
           decl);
 }
 
+/* Helper function.  Replace the temporary this parameter injected
+   during cp_finish_omp_declare_simd with the real this parameter.  */
+
+static tree
+declare_simd_adjust_this (tree *tp, int *walk_subtrees, void *data)
+{
+  tree this_parm = (tree) data;
+  if (TREE_CODE (*tp) == PARM_DECL
+      && DECL_NAME (*tp) == this_identifier
+      && *tp != this_parm)
+    *tp = this_parm;
+  else if (TYPE_P (*tp))
+    *walk_subtrees = 0;
+  return NULL_TREE;
+}
+
 /* CTYPE is class type, or null if non-class.
    TYPE is type this FUNCTION_DECL should have, either FUNCTION_TYPE
    or METHOD_TYPE.
@@ -7430,17 +7444,6 @@ grokfndecl (tree ctype,
             the information in the TEMPLATE_ID_EXPR.  */
          SET_DECL_IMPLICIT_INSTANTIATION (decl);
 
-         if (TREE_CODE (fns) == COMPONENT_REF)
-           {
-             /* Due to bison parser ickiness, we will have already looked
-                up an operator_name or PFUNCNAME within the current class
-                (see template_id in parse.y). If the current class contains
-                such a name, we'll get a COMPONENT_REF here. Undo that.  */
-
-             gcc_assert (TREE_TYPE (TREE_OPERAND (fns, 0))
-                         == current_class_type);
-             fns = TREE_OPERAND (fns, 1);
-           }
          gcc_assert (identifier_p (fns) || TREE_CODE (fns) == OVERLOAD);
          DECL_TEMPLATE_INFO (decl) = build_template_info (fns, args);
 
@@ -7478,7 +7481,9 @@ grokfndecl (tree ctype,
        || (IDENTIFIER_LENGTH (declarator) > 10
           && IDENTIFIER_POINTER (declarator)[0] == '_'
           && IDENTIFIER_POINTER (declarator)[1] == '_'
-          && strncmp (IDENTIFIER_POINTER (declarator)+2, "builtin_", 8) == 0))
+          && strncmp (IDENTIFIER_POINTER (declarator)+2, "builtin_", 8) == 0)
+       || (targetcm.cxx_implicit_extern_c
+          && targetcm.cxx_implicit_extern_c(IDENTIFIER_POINTER (declarator))))
       && current_lang_name == lang_name_cplusplus
       && ctype == NULL_TREE
       && DECL_FILE_SCOPE_P (decl))
@@ -7638,6 +7643,33 @@ grokfndecl (tree ctype,
   if (TYPE_NOTHROW_P (type) || nothrow_libfn_p (decl))
     TREE_NOTHROW (decl) = 1;
 
+  if (flag_openmp)
+    {
+      /* Adjust "omp declare simd" attributes.  */
+      tree ods = lookup_attribute ("omp declare simd", *attrlist);
+      if (ods)
+       {
+         tree attr;
+         for (attr = ods; attr;
+              attr = lookup_attribute ("omp declare simd", TREE_CHAIN (attr)))
+           {
+             if (TREE_CODE (type) == METHOD_TYPE)
+               walk_tree (&TREE_VALUE (attr), declare_simd_adjust_this,
+                          DECL_ARGUMENTS (decl), NULL);
+             if (TREE_VALUE (attr) != NULL_TREE)
+               {
+                 tree cl = TREE_VALUE (TREE_VALUE (attr));
+                 cl = c_omp_declare_simd_clauses_to_numbers
+                                               (DECL_ARGUMENTS (decl), cl);
+                 if (cl)
+                   TREE_VALUE (TREE_VALUE (attr)) = cl;
+                 else
+                   TREE_VALUE (attr) = NULL_TREE;
+               }
+           }
+       }
+    }
+
   /* Caller will do the rest of this.  */
   if (check < 0)
     return decl;
@@ -7646,7 +7678,7 @@ grokfndecl (tree ctype,
     grokclassfn (ctype, decl, flags);
 
   /* 12.4/3  */
-  if (cxx_dialect >= cxx0x
+  if (cxx_dialect >= cxx11
       && DECL_DESTRUCTOR_P (decl)
       && !TYPE_BEING_DEFINED (DECL_CONTEXT (decl))
       && !processing_template_decl)
@@ -8046,7 +8078,7 @@ check_static_variable_definition (tree decl, tree type)
      in check_initializer.  */
   if (DECL_P (decl) && DECL_DECLARED_CONSTEXPR_P (decl))
     return 0;
-  else if (cxx_dialect >= cxx0x && !INTEGRAL_OR_ENUMERATION_TYPE_P (type))
+  else if (cxx_dialect >= cxx11 && !INTEGRAL_OR_ENUMERATION_TYPE_P (type))
     {
       if (!COMPLETE_TYPE_P (type))
        error ("in-class initialization of static data member %q#D of "
@@ -8168,7 +8200,7 @@ compute_array_index_type (tree name, tree size, tsubst_flags_t complain)
 
       mark_rvalue_use (size);
 
-      if (cxx_dialect < cxx0x && TREE_CODE (size) == NOP_EXPR
+      if (cxx_dialect < cxx11 && TREE_CODE (size) == NOP_EXPR
          && TREE_SIDE_EFFECTS (size))
        /* In C++98, we mark a non-constant array bound with a magic
           NOP_EXPR with TREE_SIDE_EFFECTS; don't fold in that case.  */;
@@ -8234,7 +8266,7 @@ compute_array_index_type (tree name, tree size, tsubst_flags_t complain)
         constant. Just build the index type and mark that it requires
         structural equality checks.  */
       itype = build_index_type (build_min (MINUS_EXPR, sizetype,
-                                          size, integer_one_node));
+                                          size, size_one_node));
       TYPE_DEPENDENT_P (itype) = 1;
       TYPE_DEPENDENT_P_VALID (itype) = 1;
       SET_TYPE_STRUCTURAL_EQUALITY (itype);
@@ -8289,7 +8321,8 @@ compute_array_index_type (tree name, tree size, tsubst_flags_t complain)
   else if (TREE_CONSTANT (size)
           /* We don't allow VLAs at non-function scopes, or during
              tentative template substitution.  */
-          || !at_function_scope_p () || !(complain & tf_error))
+          || !at_function_scope_p ()
+          || (cxx_dialect < cxx1y && !(complain & tf_error)))
     {
       if (!(complain & tf_error))
        return error_mark_node;
@@ -8344,6 +8377,7 @@ compute_array_index_type (tree name, tree size, tsubst_flags_t complain)
        {
          /* A variable sized array.  */
          itype = variable_size (itype);
+
          if (TREE_CODE (itype) != SAVE_EXPR)
            {
              /* Look for SIZEOF_EXPRs in itype and fold them, otherwise
@@ -8355,6 +8389,32 @@ compute_array_index_type (tree name, tree size, tsubst_flags_t complain)
              if (found)
                itype = variable_size (fold (newitype));
            }
+
+         stabilize_vla_size (itype);
+
+         if (cxx_dialect >= cxx1y)
+           {
+             /* If the VLA bound is larger than half the address space,
+                or less than zero, throw std::bad_array_length.  */
+             tree comp = build2 (LT_EXPR, boolean_type_node, itype,
+                                 ssize_int (-1));
+             comp = build3 (COND_EXPR, void_type_node, comp,
+                            throw_bad_array_length (), void_zero_node);
+             finish_expr_stmt (comp);
+           }
+         else if (flag_sanitize & SANITIZE_VLA)
+           {
+             /* From C++1y onwards, we throw an exception on a negative
+                length size of an array; see above.  */
+
+             /* We have to add 1 -- in the ubsan routine we generate
+                LE_EXPR rather than LT_EXPR.  */
+             tree t = fold_build2 (PLUS_EXPR, TREE_TYPE (itype), itype,
+                                   build_one_cst (TREE_TYPE (itype)));
+             t = fold_build2 (COMPOUND_EXPR, TREE_TYPE (t),
+                              ubsan_instrument_vla (input_location, t), t);
+             finish_expr_stmt (t);
+           }
        }
       /* Make sure that there was no overflow when creating to a signed
         index type.  (For example, on a 32-bit machine, an array with
@@ -8479,6 +8539,9 @@ create_array_type_for_decl (tree name, tree type, tree size)
       return error_mark_node;
     }
 
+  if (cxx_dialect >= cxx1y && array_of_runtime_bound_p (type))
+    pedwarn (input_location, OPT_Wvla, "array of array of runtime bound");
+
   /* Figure out the index type for the array.  */
   if (size)
     itype = compute_array_index_type (name, size, tf_warning_or_error);
@@ -8788,8 +8851,8 @@ grokdeclarator (const cp_declarator *declarator,
                             && !uniquely_derived_from_p (ctype,
                                                          current_class_type))
                      {
-                       error ("type %qT is not derived from type %qT",
-                              ctype, current_class_type);
+                       error ("invalid use of qualified-name %<%T::%D%>",
+                              qualifying_scope, decl);
                        return error_mark_node;
                      }
                  }
@@ -9523,7 +9586,7 @@ grokdeclarator (const cp_declarator *declarator,
                  }
                else if (declarator->u.function.late_return_type)
                  {
-                   if (cxx_dialect < cxx0x)
+                   if (cxx_dialect < cxx11)
                      /* Not using maybe_warn_cpp0x because this should
                         always be an error.  */
                      error ("trailing return type only available with "
@@ -9720,6 +9783,12 @@ grokdeclarator (const cp_declarator *declarator,
                    : G_("cannot declare pointer to qualified function type %qT"),
                   type);
 
+         if (cxx_dialect >= cxx1y && array_of_runtime_bound_p (type))
+           pedwarn (input_location, OPT_Wvla,
+                    declarator->kind == cdk_reference
+                    ? G_("reference to array of runtime bound")
+                    : G_("pointer to array of runtime bound"));
+
          /* When the pointed-to type involves components of variable size,
             care must be taken to ensure that the size evaluation code is
             emitted early enough to dominate all the possible later uses
@@ -9746,12 +9815,8 @@ grokdeclarator (const cp_declarator *declarator,
              && (decl_context == NORMAL || decl_context == FIELD)
              && at_function_scope_p ()
              && variably_modified_type_p (type, NULL_TREE))
-           {
-             /* First break out any side-effects.  */
-             stabilize_vla_size (TYPE_SIZE (type));
-             /* And then force evaluation of the SAVE_EXPR.  */
-             finish_expr_stmt (TYPE_SIZE (type));
-           }
+           /* Force evaluation of the SAVE_EXPR.  */
+           finish_expr_stmt (TYPE_SIZE (type));
 
          if (declarator->kind == cdk_reference)
            {
@@ -9842,14 +9907,6 @@ grokdeclarator (const cp_declarator *declarator,
        }
     }
 
-  /* We need to stabilize side-effects in VLA sizes for regular array
-     declarations too, not just pointers to arrays.  */
-  if (type != error_mark_node && !TYPE_NAME (type)
-      && (decl_context == NORMAL || decl_context == FIELD)
-      && at_function_scope_p ()
-      && variably_modified_type_p (type, NULL_TREE))
-    stabilize_vla_size (TYPE_SIZE (type));
-
   /* A `constexpr' specifier used in an object declaration declares
      the object as `const'.  */
   if (constexpr_p && innermost_code != cdk_function)
@@ -9981,7 +10038,7 @@ grokdeclarator (const cp_declarator *declarator,
     {
       error ("size of array %qs is too large", name);
       /* If we proceed with the array type as it is, we'll eventually
-        crash in tree_low_cst().  */
+        crash in tree_to_[su]hwi().  */
       type = error_mark_node;
     }
 
@@ -10074,6 +10131,10 @@ grokdeclarator (const cp_declarator *declarator,
          type = error_mark_node;
        }
 
+      if (cxx_dialect >= cxx1y && array_of_runtime_bound_p (type))
+       pedwarn (input_location, OPT_Wvla,
+                "typedef naming array of runtime bound");
+
       if (decl_context == FIELD)
        decl = build_lang_decl (TYPE_DECL, unqualified_id, type);
       else
@@ -10270,7 +10331,7 @@ grokdeclarator (const cp_declarator *declarator,
              type = void_type_node;
            }
        }
-      else if (memfn_quals)
+      else if (memfn_quals || rqual)
        {
          if (ctype == NULL_TREE
              && TREE_CODE (type) == METHOD_TYPE)
@@ -10278,8 +10339,10 @@ grokdeclarator (const cp_declarator *declarator,
 
          if (ctype)
            type = build_memfn_type (type, ctype, memfn_quals, rqual);
-         /* Core issue #547: need to allow this in template type args.  */
-         else if (template_type_arg && TREE_CODE (type) == FUNCTION_TYPE)
+         /* Core issue #547: need to allow this in template type args.
+            Allow it in general in C++11 for alias-declarations.  */
+         else if ((template_type_arg || cxx_dialect >= cxx11)
+                  && TREE_CODE (type) == FUNCTION_TYPE)
            type = apply_memfn_quals (type, memfn_quals, rqual);
          else
            error ("invalid qualifiers on non-member function type");
@@ -10325,7 +10388,10 @@ grokdeclarator (const cp_declarator *declarator,
 
       if (type_uses_auto (type))
        {
-         error ("parameter declared %<auto%>");
+         if (cxx_dialect >= cxx1y)
+           error ("%<auto%> parameter not permitted in this context");
+         else
+           error ("parameter declared %<auto%>");
          type = error_mark_node;
        }
 
@@ -10511,21 +10577,13 @@ grokdeclarator (const cp_declarator *declarator,
                 && (TREE_CODE (type) != ARRAY_TYPE || initialized == 0))
          {
            if (unqualified_id)
-             error ("field %qD has incomplete type", unqualified_id);
+             error ("field %qD has incomplete type %qT",
+                    unqualified_id, type);
            else
              error ("name %qT has incomplete type", type);
 
-           /* If we're instantiating a template, tell them which
-              instantiation made the field's type be incomplete.  */
-           if (current_class_type
-               && TYPE_NAME (current_class_type)
-               && IDENTIFIER_TEMPLATE (current_class_name)
-               && declspecs->type
-               && declspecs->type == type)
-             error ("  in instantiation of template %qT",
-                    current_class_type);
-
-           return error_mark_node;
+           type = error_mark_node;
+           decl = NULL_TREE;
          }
        else
          {
@@ -10885,7 +10943,7 @@ local_variable_p_walkfn (tree *tp, int *walk_subtrees,
    DECL, if there is no DECL available.  */
 
 tree
-check_default_argument (tree decl, tree arg)
+check_default_argument (tree decl, tree arg, tsubst_flags_t complain)
 {
   tree var;
   tree decl_type;
@@ -10917,13 +10975,14 @@ check_default_argument (tree decl, tree arg)
      A default argument expression is implicitly converted to the
      parameter type.  */
   ++cp_unevaluated_operand;
-  perform_implicit_conversion_flags (decl_type, arg, tf_warning_or_error,
+  perform_implicit_conversion_flags (decl_type, arg, complain,
                                     LOOKUP_IMPLICIT);
   --cp_unevaluated_operand;
 
   if (warn_zero_as_null_pointer_constant
       && TYPE_PTR_OR_PTRMEM_P (decl_type)
       && null_ptr_cst_p (arg)
+      && (complain & tf_warning)
       && maybe_warn_zero_as_null_pointer_constant (arg, input_location))
     return nullptr_node;
 
@@ -10937,10 +10996,14 @@ check_default_argument (tree decl, tree arg)
   var = cp_walk_tree_without_duplicates (&arg, local_variable_p_walkfn, NULL);
   if (var)
     {
-      if (DECL_NAME (var) == this_identifier)
-       permerror (input_location, "default argument %qE uses %qD", arg, var);
-      else
-       error ("default argument %qE uses local variable %qD", arg, var);
+      if (complain & tf_warning_or_error)
+       {
+         if (DECL_NAME (var) == this_identifier)
+           permerror (input_location, "default argument %qE uses %qD",
+                      arg, var);
+         else
+           error ("default argument %qE uses local variable %qD", arg, var);
+       }
       return error_mark_node;
     }
 
@@ -11091,7 +11154,7 @@ grokparms (tree parmlist, tree *parms)
          if (any_error)
            init = NULL_TREE;
          else if (init && !processing_template_decl)
-           init = check_default_argument (decl, init);
+           init = check_default_argument (decl, init, tf_warning_or_error);
        }
 
       DECL_CHAIN (decl) = decls;
@@ -11833,14 +11896,14 @@ check_elaborated_type_specifier (enum tag_types tag_code,
           && tag_code != typename_type)
     {
       error ("%qT referred to as %qs", type, tag_name (tag_code));
-      error ("%q+T has a previous declaration here", type);
+      inform (input_location, "%q+T has a previous declaration here", type);
       return error_mark_node;
     }
   else if (TREE_CODE (type) != ENUMERAL_TYPE
           && tag_code == enum_type)
     {
       error ("%qT referred to as enum", type);
-      error ("%q+T has a previous declaration here", type);
+      inform (input_location, "%q+T has a previous declaration here", type);
       return error_mark_node;
     }
   else if (!allow_template_p
@@ -12599,9 +12662,9 @@ finish_enum_value_list (tree enumtype)
         enumeration.  We must do this before the type of MINNODE and
         MAXNODE are transformed, since tree_int_cst_min_precision relies
         on the TREE_TYPE of the value it is passed.  */
-      bool unsignedp = tree_int_cst_sgn (minnode) >= 0;
-      int lowprec = tree_int_cst_min_precision (minnode, unsignedp);
-      int highprec = tree_int_cst_min_precision (maxnode, unsignedp);
+      signop sgn = tree_int_cst_sgn (minnode) >= 0 ? UNSIGNED : SIGNED;
+      int lowprec = tree_int_cst_min_precision (minnode, sgn);
+      int highprec = tree_int_cst_min_precision (maxnode, sgn);
       int precision = MAX (lowprec, highprec);
       unsigned int itk;
       bool use_short_enum;
@@ -12633,7 +12696,7 @@ finish_enum_value_list (tree enumtype)
           underlying_type = integer_types[itk];
           if (underlying_type != NULL_TREE
              && TYPE_PRECISION (underlying_type) >= precision
-              && TYPE_UNSIGNED (underlying_type) == unsignedp)
+              && TYPE_SIGN (underlying_type) == sgn)
             break;
         }
       if (itk == itk_none)
@@ -12680,12 +12743,11 @@ finish_enum_value_list (tree enumtype)
        = build_distinct_type_copy (underlying_type);
       TYPE_PRECISION (ENUM_UNDERLYING_TYPE (enumtype)) = precision;
       set_min_and_max_values_for_integral_type
-        (ENUM_UNDERLYING_TYPE (enumtype), precision, unsignedp);
+        (ENUM_UNDERLYING_TYPE (enumtype), precision, sgn);
 
       /* If -fstrict-enums, still constrain TYPE_MIN/MAX_VALUE.  */
       if (flag_strict_enums)
-       set_min_and_max_values_for_integral_type (enumtype, precision,
-                                                 unsignedp);
+       set_min_and_max_values_for_integral_type (enumtype, precision, sgn);
     }
   else
     underlying_type = ENUM_UNDERLYING_TYPE (enumtype);
@@ -12809,14 +12871,14 @@ build_enumerator (tree name, tree value, tree enumtype, location_t loc)
                value = error_mark_node;
              else
                {
-                 double_int di = TREE_INT_CST (prev_value)
-                                 .add_with_sign (double_int_one,
-                                                 false, &overflowed);
+                 tree type = TREE_TYPE (prev_value);
+                 signop sgn = TYPE_SIGN (type);
+                 widest_int wi = wi::add (wi::to_widest (prev_value), 1, sgn,
+                                          &overflowed);
                  if (!overflowed)
                    {
-                     tree type = TREE_TYPE (prev_value);
-                     bool pos = TYPE_UNSIGNED (type) || !di.is_negative ();
-                     if (!double_int_fits_to_tree_p (type, di))
+                     bool pos = !wi::neg_p (wi, sgn);
+                     if (!wi::fits_to_tree_p (wi, type))
                        {
                          unsigned int itk;
                          for (itk = itk_int; itk != itk_none; itk++)
@@ -12824,10 +12886,10 @@ build_enumerator (tree name, tree value, tree enumtype, location_t loc)
                              type = integer_types[itk];
                              if (type != NULL_TREE
                                  && (pos || !TYPE_UNSIGNED (type))
-                                 && double_int_fits_to_tree_p (type, di))
+                                 && wi::fits_to_tree_p (wi, type))
                                break;
                            }
-                         if (type && cxx_dialect < cxx0x
+                         if (type && cxx_dialect < cxx11
                              && itk > itk_unsigned_long)
                            pedwarn (input_location, OPT_Wlong_long, pos ? "\
 incremented enumerator value is too large for %<unsigned long%>" :  "\
@@ -12836,7 +12898,7 @@ incremented enumerator value is too large for %<long%>");
                      if (type == NULL_TREE)
                        overflowed = true;
                      else
-                       value = double_int_to_tree (type, di);
+                       value = wide_int_to_tree (type, wi);
                    }
 
                  if (overflowed)
@@ -12997,7 +13059,7 @@ check_function_type (tree decl, tree current_function_parms)
    error_mark_node if the function has never been defined, or
    a BLOCK if the function has been defined somewhere.  */
 
-void
+bool
 start_preparsed_function (tree decl1, tree attrs, int flags)
 {
   tree ctype = NULL_TREE;
@@ -13094,10 +13156,14 @@ start_preparsed_function (tree decl1, tree attrs, int flags)
      by push_nested_class.)  */
   if (processing_template_decl)
     {
-      /* FIXME: Handle error_mark_node more gracefully.  */
       tree newdecl1 = push_template_decl (decl1);
-      if (newdecl1 != error_mark_node)
-       decl1 = newdecl1;
+      if (newdecl1 == error_mark_node)
+       {
+         if (ctype || DECL_STATIC_FUNCTION_P (decl1))
+           pop_nested_class ();
+         return false;
+       }
+      decl1 = newdecl1;
     }
 
   /* We are now in the scope of the function being defined.  */
@@ -13208,7 +13274,7 @@ start_preparsed_function (tree decl1, tree attrs, int flags)
   /* This function may already have been parsed, in which case just
      return; our caller will skip over the body without parsing.  */
   if (DECL_INITIAL (decl1) != error_mark_node)
-    return;
+    return true;
 
   /* Initialize RTL machinery.  We cannot do this until
      CURRENT_FUNCTION_DECL and DECL_RESULT are set up.  We do this
@@ -13370,17 +13436,19 @@ start_preparsed_function (tree decl1, tree attrs, int flags)
   start_fname_decls ();
 
   store_parm_decls (current_function_parms);
+
+  return true;
 }
 
 
 /* Like start_preparsed_function, except that instead of a
    FUNCTION_DECL, this function takes DECLSPECS and DECLARATOR.
 
-   Returns 1 on success.  If the DECLARATOR is not suitable for a function
-   (it defines a datum instead), we return 0, which tells
-   yyparse to report a parse error.  */
+   Returns true on success.  If the DECLARATOR is not suitable
+   for a function, we return false, which tells the parser to
+   skip the entire function.  */
 
-int
+bool
 start_function (cp_decl_specifier_seq *declspecs,
                const cp_declarator *declarator,
                tree attrs)
@@ -13389,13 +13457,13 @@ start_function (cp_decl_specifier_seq *declspecs,
 
   decl1 = grokdeclarator (declarator, declspecs, FUNCDEF, 1, &attrs);
   if (decl1 == error_mark_node)
-    return 0;
+    return false;
   /* If the declarator is not suitable for a function definition,
      cause a syntax error.  */
   if (decl1 == NULL_TREE || TREE_CODE (decl1) != FUNCTION_DECL)
     {
       error ("invalid function declaration");
-      return 0;
+      return false;
     }
 
   if (DECL_MAIN_P (decl1))
@@ -13404,9 +13472,7 @@ start_function (cp_decl_specifier_seq *declspecs,
     gcc_assert (same_type_p (TREE_TYPE (TREE_TYPE (decl1)),
                             integer_type_node));
 
-  start_preparsed_function (decl1, attrs, /*flags=*/SF_DEFAULT);
-
-  return 1;
+  return start_preparsed_function (decl1, attrs, /*flags=*/SF_DEFAULT);
 }
 \f
 /* Returns true iff an EH_SPEC_BLOCK should be created in the body of
@@ -14220,11 +14286,9 @@ cxx_maybe_build_cleanup (tree decl, tsubst_flags_t complain)
     }
   /* Handle ordinary C++ destructors.  */
   type = TREE_TYPE (decl);
-  if (TYPE_HAS_NONTRIVIAL_DESTRUCTOR (type))
+  if (type_build_dtor_call (type))
     {
-      int flags = LOOKUP_NORMAL|LOOKUP_DESTRUCTOR;
-      bool has_vbases = (TREE_CODE (type) == RECORD_TYPE
-                        && CLASSTYPE_VBASECLASSES (type));
+      int flags = LOOKUP_NORMAL|LOOKUP_NONVIRTUAL|LOOKUP_DESTRUCTOR;
       tree addr;
       tree call;
 
@@ -14233,14 +14297,12 @@ cxx_maybe_build_cleanup (tree decl, tsubst_flags_t complain)
       else
        addr = build_address (decl);
 
-      /* Optimize for space over speed here.  */
-      if (!has_vbases || flag_expensive_optimizations)
-       flags |= LOOKUP_NONVIRTUAL;
-
       call = build_delete (TREE_TYPE (addr), addr,
                           sfk_complete_destructor, flags, 0, complain);
       if (call == error_mark_node)
        cleanup = error_mark_node;
+      else if (TYPE_HAS_TRIVIAL_DESTRUCTOR (type))
+       /* Discard the call.  */;
       else if (cleanup)
        cleanup = cp_build_compound_expr (cleanup, call, complain);
       else
@@ -14259,13 +14321,6 @@ cxx_maybe_build_cleanup (tree decl, tsubst_flags_t complain)
 }
 
 \f
-/* When a stmt has been parsed, this function is called.  */
-
-void
-finish_stmt (void)
-{
-}
-
 /* Return the FUNCTION_TYPE that corresponds to MEMFNTYPE, which can be a
    FUNCTION_DECL, METHOD_TYPE, FUNCTION_TYPE, pointer or reference to
    METHOD_TYPE or FUNCTION_TYPE, or pointer to member function.  */
@@ -14398,10 +14453,15 @@ fndecl_declared_return_type (tree fn)
 {
   fn = STRIP_TEMPLATE (fn);
   if (FNDECL_USED_AUTO (fn))
-    return (DECL_STRUCT_FUNCTION (fn)->language
-           ->x_auto_return_pattern);
-  else
-    return TREE_TYPE (TREE_TYPE (fn));
+    {
+      struct language_function *f = NULL;
+      if (DECL_STRUCT_FUNCTION (fn))
+       f = DECL_STRUCT_FUNCTION (fn)->language;
+      if (f == NULL)
+       f = DECL_SAVED_FUNCTION_DATA (fn);
+      return f->x_auto_return_pattern;
+    }
+  return TREE_TYPE (TREE_TYPE (fn));
 }
 
 /* Returns true iff DECL was declared with an auto return type and it has