]> git.ipfire.org Git - thirdparty/gcc.git/blobdiff - gcc/cp/decl.c
Merge from trunk.
[thirdparty/gcc.git] / gcc / cp / decl.c
index 4076a24cf6af34f35da914d81c5bd7f0b430e17e..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);
@@ -1215,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)                  \
@@ -1341,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
@@ -3800,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));
@@ -3816,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 ();
@@ -4007,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;
@@ -4019,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;
@@ -4050,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
@@ -4069,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;
 }
@@ -4085,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"));
@@ -4100,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
@@ -4112,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
@@ -4803,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");
@@ -5090,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.  */
@@ -5682,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);
@@ -6399,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 (cxx_dialect >= cxx1y && 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.  */
@@ -6644,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);
@@ -6666,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);
 }
 
@@ -6896,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))
@@ -6992,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),
@@ -7308,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.
@@ -7464,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))
@@ -7624,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;
@@ -8331,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
@@ -8342,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
@@ -8778,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;
                      }
                  }
@@ -9742,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)
            {
@@ -9838,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)
@@ -9977,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;
     }
 
@@ -10327,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;
        }
 
@@ -12598,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;
@@ -12632,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)
@@ -12679,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);
@@ -12808,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++)
@@ -12823,7 +12886,7 @@ 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 < cxx11
@@ -12835,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)
@@ -14223,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;
 
@@ -14236,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