re PR c++/68464 (ICE in valid constexpr function: ../../src/gcc/tree.c:11497)
[gcc.git] / gcc / cp / decl.c
index 8036fb78b432a30689a47cb67c513b32b6ae36e6..62636c9eefaed72def3ec29d6b5950b0711ed0af 100644 (file)
@@ -29,38 +29,25 @@ along with GCC; see the file COPYING3.  If not see
 #include "config.h"
 #include "system.h"
 #include "coretypes.h"
-#include "tm.h"
-#include "alias.h"
-#include "tree.h"
-#include "tree-hasher.h"
+#include "target.h"
+#include "c-family/c-target.h"
+#include "cp-tree.h"
+#include "timevar.h"
 #include "stringpool.h"
+#include "cgraph.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"
-#include "tree-inline.h"
 #include "decl.h"
 #include "intl.h"
 #include "toplev.h"
-#include "tm_p.h"
-#include "target.h"
-#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"
-#include "timevar.h"
-#include "splay-tree.h"
 #include "plugin.h"
-#include "hard-reg-set.h"
-#include "function.h"
-#include "cgraph.h"
 #include "cilk.h"
 #include "builtins.h"
 
@@ -2027,7 +2014,22 @@ duplicate_decls (tree newdecl, tree olddecl, bool newdecl_is_friend)
       /* For typedefs use the old type, as the new type's DECL_NAME points
         at newdecl, which will be ggc_freed.  */
       if (TREE_CODE (newdecl) == TYPE_DECL)
-       newtype = oldtype;
+       {
+         newtype = oldtype;
+
+         /* And remove the new type from the variants list.  */
+         if (TYPE_NAME (TREE_TYPE (newdecl)) == newdecl)
+           {
+             tree remove = TREE_TYPE (newdecl);
+             for (tree t = TYPE_MAIN_VARIANT (remove); ;
+                  t = TYPE_NEXT_VARIANT (t))
+               if (TYPE_NEXT_VARIANT (t) == remove)
+                 {
+                   TYPE_NEXT_VARIANT (t) = TYPE_NEXT_VARIANT (remove);
+                   break;
+                 }
+           }
+       }
       else
        /* Merge the data types specified in the two decls.  */
        newtype = merge_types (TREE_TYPE (newdecl), TREE_TYPE (olddecl));
@@ -2965,14 +2967,16 @@ decl_jump_unsafe (tree decl)
   return 0;
 }
 
-/* A subroutine of check_previous_goto_1 to identify a branch to the user.  */
+/* A subroutine of check_previous_goto_1 and check_goto to identify a branch
+   to the user.  */
 
 static bool
-identify_goto (tree decl, const location_t *locus)
+identify_goto (tree decl, location_t loc, const location_t *locus,
+              diagnostic_t diag_kind)
 {
-  bool complained = (decl
-                    ? permerror (input_location, "jump to label %qD", decl)
-                    : permerror (input_location, "jump to case label"));
+  bool complained
+    = (decl ? emit_diagnostic (diag_kind, loc, 0, "jump to label %qD", decl)
+           : emit_diagnostic (diag_kind, loc, 0, "jump to case label"));
   if (complained && locus)
     inform (*locus, "  from here");
   return complained;
@@ -2989,15 +2993,17 @@ check_previous_goto_1 (tree decl, cp_binding_level* level, tree names,
                       bool exited_omp, const location_t *locus)
 {
   cp_binding_level *b;
-  bool identified = false, complained = false;
+  bool complained = false;
+  int identified = 0;
   bool saw_eh = false, saw_omp = false, saw_tm = false;
 
   if (exited_omp)
     {
-      complained = identify_goto (decl, locus);
+      complained = identify_goto (decl, input_location, locus, DK_ERROR);
       if (complained)
        inform (input_location, "  exits OpenMP structured block");
-      identified = saw_omp = true;
+      saw_omp = true;
+      identified = 2;
     }
 
   for (b = current_binding_level; b ; b = b->level_chain)
@@ -3014,8 +3020,9 @@ check_previous_goto_1 (tree decl, cp_binding_level* level, tree names,
 
          if (!identified)
            {
-             complained = identify_goto (decl, locus);
-             identified = true;
+             complained = identify_goto (decl, input_location, locus,
+                                         DK_PERMERROR);
+             identified = 1;
            }
          if (complained)
            {
@@ -3033,10 +3040,11 @@ check_previous_goto_1 (tree decl, cp_binding_level* level, tree names,
        break;
       if ((b->kind == sk_try || b->kind == sk_catch) && !saw_eh)
        {
-         if (!identified)
+         if (identified < 2)
            {
-             complained = identify_goto (decl, locus);
-             identified = true;
+             complained = identify_goto (decl, input_location, locus,
+                                         DK_ERROR);
+             identified = 2;
            }
          if (complained)
            {
@@ -3049,10 +3057,11 @@ check_previous_goto_1 (tree decl, cp_binding_level* level, tree names,
        }
       if (b->kind == sk_omp && !saw_omp)
        {
-         if (!identified)
+         if (identified < 2)
            {
-             complained = identify_goto (decl, locus);
-             identified = true;
+             complained = identify_goto (decl, input_location, locus,
+                                         DK_ERROR);
+             identified = 2;
            }
          if (complained)
            inform (input_location, "  enters OpenMP structured block");
@@ -3060,10 +3069,11 @@ check_previous_goto_1 (tree decl, cp_binding_level* level, tree names,
        }
       if (b->kind == sk_transaction && !saw_tm)
        {
-         if (!identified)
+         if (identified < 2)
            {
-             complained = identify_goto (decl, locus);
-             identified = true;
+             complained = identify_goto (decl, input_location, locus,
+                                         DK_ERROR);
+             identified = 2;
            }
          if (complained)
            inform (input_location,
@@ -3096,7 +3106,8 @@ void
 check_goto (tree decl)
 {
   struct named_label_entry *ent, dummy;
-  bool saw_catch = false, identified = false, complained = false;
+  bool saw_catch = false, complained = false;
+  int identified = 0;
   tree bad;
   unsigned ix;
 
@@ -3139,11 +3150,13 @@ check_goto (tree decl)
   if (ent->in_try_scope || ent->in_catch_scope || ent->in_transaction_scope
       || ent->in_omp_scope || !vec_safe_is_empty (ent->bad_decls))
     {
-      complained = permerror (DECL_SOURCE_LOCATION (decl),
-                             "jump to label %qD", decl);
-      if (complained)
-       inform (input_location, "  from here");
-      identified = true;
+      diagnostic_t diag_kind = DK_PERMERROR;
+      if (ent->in_try_scope || ent->in_catch_scope
+         || ent->in_transaction_scope || ent->in_omp_scope)
+       diag_kind = DK_ERROR;
+      complained = identify_goto (decl, DECL_SOURCE_LOCATION (decl),
+                                 &input_location, diag_kind);
+      identified = 1 + (diag_kind == DK_ERROR);
     }
 
   FOR_EACH_VEC_SAFE_ELT (ent->bad_decls, ix, bad)
@@ -3153,6 +3166,12 @@ check_goto (tree decl)
       if (u > 1 && DECL_ARTIFICIAL (bad))
        {
          /* Can't skip init of __exception_info.  */
+         if (identified == 1)
+           {
+             complained = identify_goto (decl, DECL_SOURCE_LOCATION (decl),
+                                         &input_location, DK_ERROR);
+             identified = 2;
+           }
          if (complained)
            inform (DECL_SOURCE_LOCATION (bad), "  enters catch block");
          saw_catch = true;
@@ -3193,13 +3212,12 @@ check_goto (tree decl)
            break;
          if (b->kind == sk_omp)
            {
-             if (!identified)
+             if (identified < 2)
                {
-                 complained = permerror (DECL_SOURCE_LOCATION (decl),
-                                         "jump to label %qD", decl);
-                 if (complained)
-                   inform (input_location, "  from here");
-                 identified = true;
+                 complained = identify_goto (decl,
+                                             DECL_SOURCE_LOCATION (decl),
+                                             &input_location, DK_ERROR);
+                 identified = 2;
                }
              if (complained)
                inform (input_location, "  exits OpenMP structured block");
@@ -4537,8 +4555,9 @@ check_tag_decl (cp_decl_specifier_seq *declspecs,
     permerror (input_location, "declaration does not declare anything");
   else if (declared_type != NULL_TREE && type_uses_auto (declared_type))
     {
-      error ("%<auto%> can only be specified for variables "
-            "or function declarations");
+      error_at (declspecs->locations[ds_type_spec],
+               "%<auto%> can only be specified for variables "
+               "or function declarations");
       return error_mark_node;
     }
   /* Check for an anonymous union.  */
@@ -6714,6 +6733,9 @@ cp_finish_decl (tree decl, tree init, bool init_const_expr_p,
               to put statics on the list so we can deal with the label
               address extension.  FIXME.  */
            add_local_decl (cfun, decl);
+         /* And make sure it's in the symbol table for
+            c_parse_final_cleanups to find.  */
+         varpool_node::get_create (decl);
        }
 
       /* Convert the initializer to the type of DECL, if we have not
@@ -7826,6 +7848,9 @@ grokfndecl (tree ctype,
       parm = build_this_parm (type, quals);
       DECL_CHAIN (parm) = parms;
       parms = parm;
+
+      /* Allocate space to hold the vptr bit if needed.  */
+      DECL_ALIGN (decl) = MINIMUM_METHOD_BOUNDARY;
     }
   DECL_ARGUMENTS (decl) = parms;
   for (t = parms; t; t = DECL_CHAIN (t))
@@ -7849,14 +7874,6 @@ grokfndecl (tree ctype,
       break;
     }
 
-  /* If pointers to member functions use the least significant bit to
-     indicate whether a function is virtual, ensure a pointer
-     to this function will have that bit clear.  */
-  if (TARGET_PTRMEMFUNC_VBIT_LOCATION == ptrmemfunc_vbit_in_pfn
-      && TREE_CODE (type) == METHOD_TYPE
-      && DECL_ALIGN (decl) < 2 * BITS_PER_UNIT)
-    DECL_ALIGN (decl) = 2 * BITS_PER_UNIT;
-
   if (friendp
       && TREE_CODE (orig_declarator) == TEMPLATE_ID_EXPR)
     {
@@ -8000,6 +8017,11 @@ grokfndecl (tree ctype,
   DECL_EXTERNAL (decl) = 1;
   if (TREE_CODE (type) == FUNCTION_TYPE)
     {
+      if (quals || rqual)
+       TREE_TYPE (decl) = apply_memfn_quals (TREE_TYPE (decl),
+                                             TYPE_UNQUALIFIED,
+                                             REF_QUAL_NONE);
+
       if (quals)
        {
          error (ctype
@@ -8584,33 +8606,24 @@ stabilize_vla_size (tree size)
   cp_walk_tree (&size, stabilize_save_expr_r, &pset, &pset);
 }
 
-/* Helper function for compute_array_index_type.  Look for SIZEOF_EXPR
-   not inside of SAVE_EXPR and fold them.  */
+/* Reduce a SIZEOF_EXPR to its value.  */
 
-static tree
-fold_sizeof_expr_r (tree *expr_p, int *walk_subtrees, void *data)
-{
-  tree expr = *expr_p;
-  if (TREE_CODE (expr) == SAVE_EXPR || TYPE_P (expr))
-    *walk_subtrees = 0;
-  else if (TREE_CODE (expr) == SIZEOF_EXPR)
-    {
-      *(bool *)data = true;
-      if (SIZEOF_EXPR_TYPE_P (expr))
-       expr = cxx_sizeof_or_alignof_type (TREE_TYPE (TREE_OPERAND (expr, 0)),
-                                          SIZEOF_EXPR, false);
-      else if (TYPE_P (TREE_OPERAND (expr, 0)))
-       expr = cxx_sizeof_or_alignof_type (TREE_OPERAND (expr, 0), SIZEOF_EXPR,
-                                          false);
-      else
-        expr = cxx_sizeof_or_alignof_expr (TREE_OPERAND (expr, 0), SIZEOF_EXPR,
-                                          false);
-      if (expr == error_mark_node)
-        expr = size_one_node;
-      *expr_p = expr;
-      *walk_subtrees = 0;
-    }
-  return NULL;
+tree
+fold_sizeof_expr (tree t)
+{
+  tree r;
+  if (SIZEOF_EXPR_TYPE_P (t))
+    r = cxx_sizeof_or_alignof_type (TREE_TYPE (TREE_OPERAND (t, 0)),
+                                   SIZEOF_EXPR, false);
+  else if (TYPE_P (TREE_OPERAND (t, 0)))
+    r = cxx_sizeof_or_alignof_type (TREE_OPERAND (t, 0), SIZEOF_EXPR,
+                                   false);
+  else
+    r = cxx_sizeof_or_alignof_expr (TREE_OPERAND (t, 0), SIZEOF_EXPR,
+                                   false);
+  if (r == error_mark_node)
+    r = size_one_node;
+  return r;
 }
 
 /* Given the SIZE (i.e., number of elements) in an array, compute an
@@ -8703,7 +8716,18 @@ compute_array_index_type (tree name, tree size, tsubst_flags_t complain)
       SET_TYPE_STRUCTURAL_EQUALITY (itype);
       return itype;
     }
-  
+
+  if (TREE_CODE (size) != INTEGER_CST)
+    {
+      tree folded = cp_fully_fold (size);
+      if (TREE_CODE (folded) == INTEGER_CST)
+       pedwarn (location_of (size), OPT_Wpedantic,
+                "size of array is not an integral constant-expression");
+      /* Use the folded result for VLAs, too; it will have resolved
+        SIZEOF_EXPR.  */
+      size = folded;
+    }
+
   /* Normally, the array-bound will be a constant.  */
   if (TREE_CODE (size) == INTEGER_CST)
     {
@@ -8790,7 +8814,7 @@ compute_array_index_type (tree name, tree size, tsubst_flags_t complain)
                                  cp_convert (ssizetype, integer_one_node,
                                              complain),
                                  complain);
-      itype = fold (itype);
+      itype = maybe_constant_value (itype);
       processing_template_decl = saved_processing_template_decl;
 
       if (!TREE_CONSTANT (itype))
@@ -8798,18 +8822,6 @@ 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
-                they might survive till gimplification.  */
-             tree newitype = itype;
-             bool found = false;
-             cp_walk_tree_without_duplicates (&newitype,
-                                              fold_sizeof_expr_r, &found);
-             if (found)
-               itype = variable_size (fold (newitype));
-           }
-
          stabilize_vla_size (itype);
 
          if (flag_sanitize & SANITIZE_VLA
@@ -9949,6 +9961,9 @@ grokdeclarator (const cp_declarator *declarator,
        case cdk_array:
          type = create_array_type_for_decl (dname, type,
                                             declarator->u.array.bounds);
+         if (!valid_array_size_p (input_location, type, dname))
+           type = error_mark_node;
+
          if (declarator->std_attributes)
            /* [dcl.array]/1:
 
@@ -10512,19 +10527,6 @@ grokdeclarator (const cp_declarator *declarator,
         error ("non-parameter %qs cannot be a parameter pack", name);
     }
 
-  /* Did array size calculations overflow or does the array cover more
-     than half of the address-space?  */
-  if (TREE_CODE (type) == ARRAY_TYPE
-      && COMPLETE_TYPE_P (type)
-      && TREE_CODE (TYPE_SIZE_UNIT (type)) == INTEGER_CST
-      && ! valid_constant_size_p (TYPE_SIZE_UNIT (type)))
-    {
-      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_to_[su]hwi().  */
-      type = error_mark_node;
-    }
-
   if ((decl_context == FIELD || decl_context == PARM)
       && !processing_template_decl
       && variably_modified_type_p (type, NULL_TREE))
@@ -13519,7 +13521,7 @@ incremented enumerator value is too large for %<long%>");
                   "type %<%T%>", value, ENUM_UNDERLYING_TYPE (enumtype));
 
           /* Convert the value to the appropriate type.  */
-          value = convert (ENUM_UNDERLYING_TYPE (enumtype), value);
+          value = fold_convert (ENUM_UNDERLYING_TYPE (enumtype), value);
         }
     }
 
@@ -14049,7 +14051,7 @@ start_preparsed_function (tree decl1, tree attrs, int flags)
       && flag_lifetime_dse && DECL_CONSTRUCTOR_P (decl1)
       /* We can't clobber safely for an implicitly-defined default constructor
         because part of the initialization might happen before we enter the
-        consructor, via AGGR_INIT_ZERO_FIRST (c++/68006).  */
+        constructor, via AGGR_INIT_ZERO_FIRST (c++/68006).  */
       && !implicit_default_ctor_p (decl1))
     {
       /* Insert a clobber to let the back end know that the object storage
@@ -14578,6 +14580,14 @@ finish_function (int flags)
      the NRV transformation.   */
   maybe_save_function_definition (fndecl);
 
+  /* Invoke the pre-genericize plugin before we start munging things.  */
+  if (!processing_template_decl)
+    invoke_plugin_callbacks (PLUGIN_PRE_GENERICIZE, fndecl);
+
+  /* Perform delayed folding before NRV transformation.  */
+  if (!processing_template_decl)
+    cp_fold_function (fndecl);
+
   /* Set up the named return value optimization, if we can.  Candidate
      variables are selected in check_return_expr.  */
   if (current_function_return_value)
@@ -14684,7 +14694,6 @@ finish_function (int flags)
   if (!processing_template_decl)
     {
       struct language_function *f = DECL_SAVED_FUNCTION_DATA (fndecl);
-      invoke_plugin_callbacks (PLUGIN_PRE_GENERICIZE, fndecl);
       cp_genericize (fndecl);
       /* Clear out the bits we don't need.  */
       f->x_current_class_ptr = NULL;
@@ -14887,10 +14896,6 @@ complete_vars (tree type)
              cp_apply_type_quals_to_decl (cp_type_quals (type), var);
            }
 
-         if (DECL_INITIAL (var)
-             && decl_constant_var_p (var))
-           DECL_INITIAL (var) = cplus_expand_constant (DECL_INITIAL (var));
-
          /* Remove this entry from the list.  */
          incomplete_vars->unordered_remove (ix);
        }