re PR c++/68464 (ICE in valid constexpr function: ../../src/gcc/tree.c:11497)
[gcc.git] / gcc / cp / decl.c
index 959422341b2ef70a7f90463a6d15e0138960f0ce..62636c9eefaed72def3ec29d6b5950b0711ed0af 100644 (file)
@@ -29,39 +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 "symtab.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"
 
@@ -73,7 +59,6 @@ enum bad_spec_place {
   BSP_FIELD   /* field */
 };
 
-static tree grokparms (tree parmlist, tree *);
 static const char *redeclaration_error_message (tree, tree);
 
 static int decl_jump_unsafe (tree);
@@ -115,7 +100,7 @@ static void end_cleanup_fn (void);
 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);
+       (special_function_kind, tree, tree, int, const location_t*);
 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);
@@ -232,6 +217,7 @@ struct GTY((for_user)) named_label_entry {
   bool in_try_scope;
   bool in_catch_scope;
   bool in_omp_scope;
+  bool in_transaction_scope;
 };
 
 #define named_labels cp_function_chain->x_named_labels
@@ -256,10 +242,10 @@ enum deprecated_states deprecated_state = DEPRECATED_NORMAL;
 /* A list of VAR_DECLs whose type was incomplete at the time the
    variable was declared.  */
 
-typedef struct GTY(()) incomplete_var_d {
+struct GTY(()) incomplete_var {
   tree decl;
   tree incomplete_type;
-} incomplete_var;
+};
 
 
 static GTY(()) vec<incomplete_var, va_gc> *incomplete_vars;
@@ -500,6 +486,9 @@ poplevel_named_label_1 (named_label_entry **slot, cp_binding_level *bl)
        case sk_omp:
          ent->in_omp_scope = true;
          break;
+       case sk_transaction:
+         ent->in_transaction_scope = true;
+         break;
        default:
          break;
        }
@@ -641,14 +630,16 @@ poplevel (int keep, int reverse, int functionbody)
                                     TYPE_ATTRIBUTES (TREE_TYPE (decl)))))
          {
            if (! TREE_USED (decl))
-             warning (OPT_Wunused_variable, "unused variable %q+D", decl);
+             warning_at (DECL_SOURCE_LOCATION (decl),
+                         OPT_Wunused_variable, "unused variable %qD", 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)
              {
-               warning (OPT_Wunused_but_set_variable,
-                        "variable %q+D set but not used", decl);
+               warning_at (DECL_SOURCE_LOCATION (decl),
+                           OPT_Wunused_but_set_variable,
+                           "variable %qD set but not used", decl);
                unused_but_set_errorcount = errorcount;
              }
          }
@@ -1078,8 +1069,10 @@ decls_match (tree newdecl, tree olddecl)
     }
   else if (TREE_CODE (newdecl) == TEMPLATE_DECL)
     {
-      if (TREE_CODE (DECL_TEMPLATE_RESULT (newdecl))
-         != TREE_CODE (DECL_TEMPLATE_RESULT (olddecl)))
+      tree oldres = DECL_TEMPLATE_RESULT (olddecl);
+      tree newres = DECL_TEMPLATE_RESULT (newdecl);
+
+      if (TREE_CODE (newres) != TREE_CODE (oldres))
        return 0;
 
       if (!comp_template_parms (DECL_TEMPLATE_PARMS (newdecl),
@@ -1087,11 +1080,12 @@ decls_match (tree newdecl, tree olddecl)
        return 0;
 
       if (TREE_CODE (DECL_TEMPLATE_RESULT (newdecl)) == TYPE_DECL)
-       types_match = same_type_p (TREE_TYPE (DECL_TEMPLATE_RESULT (olddecl)),
-                                  TREE_TYPE (DECL_TEMPLATE_RESULT (newdecl)));
+       types_match = (same_type_p (TREE_TYPE (oldres), TREE_TYPE (newres))
+                      && equivalently_constrained (olddecl, newdecl));
       else
-       types_match = decls_match (DECL_TEMPLATE_RESULT (olddecl),
-                                  DECL_TEMPLATE_RESULT (newdecl));
+       // We don't need to check equivalently_constrained for variable and
+       // function templates because we check it on the results.
+       types_match = decls_match (oldres, newres);
     }
   else
     {
@@ -1119,6 +1113,11 @@ decls_match (tree newdecl, tree olddecl)
                                 COMPARE_REDECLARATION);
     }
 
+  // Normal functions can be constrained, as can variable partial
+  // specializations.
+  if (types_match && VAR_OR_FUNCTION_DECL_P (newdecl))
+    types_match = equivalently_constrained (newdecl, olddecl);
+
   return types_match;
 }
 
@@ -1158,7 +1157,8 @@ warn_extern_redeclared_static (tree newdecl, tree olddecl)
 
   if (permerror (DECL_SOURCE_LOCATION (newdecl),
                 "%qD was declared %<extern%> and later %<static%>", newdecl))
-    inform (input_location, "previous declaration of %q+D", olddecl);
+    inform (DECL_SOURCE_LOCATION (olddecl),
+           "previous declaration of %qD", olddecl);
 }
 
 /* NEW_DECL is a redeclaration of OLD_DECL; both are functions or
@@ -1241,6 +1241,36 @@ validate_constexpr_redeclaration (tree old_decl, tree new_decl)
   return true;
 }
 
+// If OLDDECL and NEWDECL are concept declarations with the same type
+// (i.e., and template parameters), but different requirements,
+// emit diagnostics and return true. Otherwise, return false.
+static inline bool
+check_concept_refinement (tree olddecl, tree newdecl)
+{
+  if (!DECL_DECLARED_CONCEPT_P (olddecl) || !DECL_DECLARED_CONCEPT_P (newdecl))
+    return false;
+
+  tree d1 = DECL_TEMPLATE_RESULT (olddecl);
+  tree d2 = DECL_TEMPLATE_RESULT (newdecl);
+  if (TREE_CODE (d1) != TREE_CODE (d2))
+    return false;
+
+  tree t1 = TREE_TYPE (d1);
+  tree t2 = TREE_TYPE (d2);
+  if (TREE_CODE (d1) == FUNCTION_DECL)
+    {
+      if (compparms (TYPE_ARG_TYPES (t1), TYPE_ARG_TYPES (t2))
+          && comp_template_parms (DECL_TEMPLATE_PARMS (olddecl),
+                                  DECL_TEMPLATE_PARMS (newdecl))
+          && !equivalently_constrained (olddecl, newdecl))
+        {
+          error ("cannot specialize concept %q#D", olddecl);
+          return true;
+        }
+    }
+  return false;
+}
+
 /* DECL is a redeclaration of a function or function template.  If
    it does have default arguments issue a diagnostic.  Note: this
    function is used to enforce the requirements in C++11 8.3.6 about
@@ -1255,8 +1285,8 @@ check_redeclaration_no_default_args (tree decl)
        t && t != void_list_node; t = TREE_CHAIN (t))
     if (TREE_PURPOSE (t))
       {
-       permerror (input_location,
-                  "redeclaration of %q+#D may not have default "
+       permerror (DECL_SOURCE_LOCATION (decl),
+                  "redeclaration of %q#D may not have default "
                   "arguments", decl);
        return;
       }
@@ -1329,8 +1359,9 @@ duplicate_decls (tree newdecl, tree olddecl, bool newdecl_is_friend)
               && DECL_UNINLINABLE (olddecl)
               && lookup_attribute ("noinline", DECL_ATTRIBUTES (olddecl)))
        {
-         if (warning (OPT_Wattributes, "function %q+D redeclared as inline",
-                      newdecl))
+         if (warning_at (DECL_SOURCE_LOCATION (newdecl),
+                         OPT_Wattributes, "function %qD redeclared as inline",
+                         newdecl))
            inform (DECL_SOURCE_LOCATION (olddecl),
                    "previous declaration of %qD with attribute noinline",
                    olddecl);
@@ -1339,8 +1370,9 @@ duplicate_decls (tree newdecl, tree olddecl, bool newdecl_is_friend)
               && DECL_UNINLINABLE (newdecl)
               && lookup_attribute ("noinline", DECL_ATTRIBUTES (newdecl)))
        {
-         if (warning (OPT_Wattributes, "function %q+D redeclared with "
-                      "attribute noinline", newdecl))
+         if (warning_at (DECL_SOURCE_LOCATION (newdecl),
+                         OPT_Wattributes, "function %qD redeclared with "
+                         "attribute noinline", newdecl))
            inform (DECL_SOURCE_LOCATION (olddecl),
                    "previous declaration of %qD was inline",
                    olddecl);
@@ -1374,8 +1406,9 @@ duplicate_decls (tree newdecl, tree olddecl, bool newdecl_is_friend)
          /* If the built-in is not ansi, then programs can override
             it even globally without an error.  */
          else if (! DECL_BUILT_IN (olddecl))
-           warning (0, "library function %q#D redeclared as non-function %q+#D",
-                    olddecl, newdecl);
+           warning_at (DECL_SOURCE_LOCATION (newdecl), 0,
+                       "library function %q#D redeclared as non-function %q#D",
+                       olddecl, newdecl);
          else
            error ("declaration of %q+#D conflicts with built-in "
                   "declaration %q#D", newdecl, olddecl);
@@ -1437,8 +1470,9 @@ duplicate_decls (tree newdecl, tree olddecl, bool newdecl_is_friend)
              /* A near match; override the builtin.  */
 
              if (TREE_PUBLIC (newdecl))
-               warning (0, "new declaration %q+#D ambiguates built-in "
-                        "declaration %q#D", newdecl, olddecl);
+               warning_at (DECL_SOURCE_LOCATION (newdecl), 0,
+                           "new declaration %q#D ambiguates built-in "
+                           "declaration %q#D", newdecl, olddecl);
              else
                warning (OPT_Wshadow, 
                          DECL_BUILT_IN (olddecl)
@@ -1565,12 +1599,17 @@ duplicate_decls (tree newdecl, tree olddecl, bool newdecl_is_friend)
                   /* Template functions can be disambiguated by
                      return type.  */
                   && same_type_p (TREE_TYPE (TREE_TYPE (newdecl)),
-                                  TREE_TYPE (TREE_TYPE (olddecl))))
+                                  TREE_TYPE (TREE_TYPE (olddecl)))
+                   // Template functions can also be disambiguated by
+                   // constraints.
+                   && equivalently_constrained (olddecl, newdecl))
            {
              error ("ambiguating new declaration %q+#D", newdecl);
              inform (DECL_SOURCE_LOCATION (olddecl),
                      "old declaration %q#D", olddecl);
            }
+          else if (check_concept_refinement (olddecl, newdecl))
+           return error_mark_node;
          return NULL_TREE;
        }
       if (TREE_CODE (newdecl) == FUNCTION_DECL)
@@ -1587,8 +1626,11 @@ duplicate_decls (tree newdecl, tree olddecl, bool newdecl_is_friend)
             are not ambiguous.  */
          else if ((!DECL_FUNCTION_VERSIONED (newdecl)
                    && !DECL_FUNCTION_VERSIONED (olddecl))
+                   // The functions have the same parameter types.
                   && compparms (TYPE_ARG_TYPES (TREE_TYPE (newdecl)),
-                             TYPE_ARG_TYPES (TREE_TYPE (olddecl))))
+                                TYPE_ARG_TYPES (TREE_TYPE (olddecl)))
+                   // And the same constraints.
+                   && equivalently_constrained (newdecl, olddecl))
            {
              error ("ambiguating new declaration of %q+#D", newdecl);
              inform (DECL_SOURCE_LOCATION (olddecl),
@@ -1666,10 +1708,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)
-           inform (input_location,
+           inform (DECL_SOURCE_LOCATION (olddecl),
                    (DECL_INITIAL (olddecl) && namespace_bindings_p ())
-                   ? G_("%q+#D previously defined here")
-                   : G_("%q+#D previously declared here"), olddecl);
+                   ? G_("%q#D previously defined here")
+                   : G_("%q#D previously declared here"), olddecl);
          return error_mark_node;
        }
       else if (TREE_CODE (olddecl) == FUNCTION_DECL
@@ -1679,7 +1721,7 @@ duplicate_decls (tree newdecl, tree olddecl, bool newdecl_is_friend)
        {
          /* Prototype decl follows defn w/o prototype.  */
          if (warning_at (DECL_SOURCE_LOCATION (newdecl), 0,
-                         "prototype specified for %q+#D", newdecl))
+                         "prototype specified for %q#D", newdecl))
            inform (DECL_SOURCE_LOCATION (olddecl),
                    "previous non-prototype definition here");
        }
@@ -1832,9 +1874,10 @@ duplicate_decls (tree newdecl, tree olddecl, bool newdecl_is_friend)
          && (! DECL_TEMPLATE_SPECIALIZATION (newdecl)
              || DECL_TEMPLATE_SPECIALIZATION (olddecl)))
        {
-         if (warning (OPT_Wredundant_decls,
-                      "redundant redeclaration of %q+D in same scope",
-                      newdecl))
+         if (warning_at (DECL_SOURCE_LOCATION (newdecl),
+                         OPT_Wredundant_decls,
+                         "redundant redeclaration of %qD in same scope",
+                         newdecl))
            inform (DECL_SOURCE_LOCATION (olddecl),
                    "previous declaration of %qD", olddecl);
        }
@@ -1971,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));
@@ -1997,6 +2055,17 @@ duplicate_decls (tree newdecl, tree olddecl, bool newdecl_is_friend)
            }
        }
 
+      /* An explicit specialization of a function template or of a member
+        function of a class template can be declared transaction_safe
+        independently of whether the corresponding template entity is declared
+        transaction_safe. */
+      if (flag_tm && TREE_CODE (newdecl) == FUNCTION_DECL
+         && DECL_TEMPLATE_INSTANTIATION (olddecl)
+         && DECL_TEMPLATE_SPECIALIZATION (newdecl)
+         && tx_safe_fn_type_p (newtype)
+         && !tx_safe_fn_type_p (TREE_TYPE (newdecl)))
+       newtype = tx_unsafe_fn_variant (newtype);
+
       TREE_TYPE (newdecl) = TREE_TYPE (olddecl) = newtype;
 
       if (TREE_CODE (newdecl) == FUNCTION_DECL)
@@ -2523,8 +2592,12 @@ duplicate_decls (tree newdecl, tree olddecl, bool newdecl_is_friend)
        }
 
       if (VAR_P (newdecl)
-         && DECL_THREAD_LOCAL_P (newdecl))
-       set_decl_tls_model (olddecl, DECL_TLS_MODEL (newdecl));
+         && CP_DECL_THREAD_LOCAL_P (newdecl))
+       {
+         CP_DECL_THREAD_LOCAL_P (olddecl) = true;
+         if (!processing_template_decl)
+           set_decl_tls_model (olddecl, DECL_TLS_MODEL (newdecl));
+       }
     }
 
   DECL_UID (olddecl) = olddecl_uid;
@@ -2565,6 +2638,12 @@ duplicate_decls (tree newdecl, tree olddecl, bool newdecl_is_friend)
       if (snode)
        snode->remove ();
     }
+
+  /* Remove the associated constraints for newdecl, if any, before
+     reclaiming memory. */
+  if (flag_concepts)
+    remove_constraints (newdecl);
+
   ggc_free (newdecl);
 
   return olddecl;
@@ -2702,14 +2781,14 @@ redeclaration_error_message (tree newdecl, tree olddecl)
       return NULL;
     }
   else if (VAR_P (newdecl)
-          && DECL_THREAD_LOCAL_P (newdecl) != DECL_THREAD_LOCAL_P (olddecl)
+          && CP_DECL_THREAD_LOCAL_P (newdecl) != CP_DECL_THREAD_LOCAL_P (olddecl)
           && (! DECL_LANG_SPECIFIC (olddecl)
               || ! CP_DECL_THREADPRIVATE_P (olddecl)
-              || DECL_THREAD_LOCAL_P (newdecl)))
+              || CP_DECL_THREAD_LOCAL_P (newdecl)))
     {
       /* Only variables can be thread-local, and all declarations must
         agree on this property.  */
-      if (DECL_THREAD_LOCAL_P (newdecl))
+      if (CP_DECL_THREAD_LOCAL_P (newdecl))
        return G_("thread-local declaration of %q#D follows "
                  "non-thread-local declaration");
       else
@@ -2888,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;
@@ -2912,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 saw_eh = false, saw_omp = 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)
@@ -2937,16 +3020,18 @@ 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)
            {
              if (problem > 1)
-               inform (input_location,
-                       "  crosses initialization of %q+#D", new_decls);
+               inform (DECL_SOURCE_LOCATION (new_decls),
+                       "  crosses initialization of %q#D", new_decls);
              else
-               inform (input_location, "  enters scope of %q+#D which has "
+               inform (DECL_SOURCE_LOCATION (new_decls),
+                       "  enters scope of %q#D which has "
                        "non-trivial destructor", new_decls);
            }
        }
@@ -2955,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)
            {
@@ -2971,15 +3057,29 @@ 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");
          saw_omp = true;
        }
+      if (b->kind == sk_transaction && !saw_tm)
+       {
+         if (identified < 2)
+           {
+             complained = identify_goto (decl, input_location, locus,
+                                         DK_ERROR);
+             identified = 2;
+           }
+         if (complained)
+           inform (input_location,
+                   "  enters synchronized or atomic statement");
+         saw_tm = true;
+       }
     }
 
   return !identified;
@@ -3006,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;
 
@@ -3046,13 +3147,16 @@ check_goto (tree decl)
       return;
     }
 
-  if (ent->in_try_scope || ent->in_catch_scope
+  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 (input_location, "jump to label %q+D", 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)
@@ -3062,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;
@@ -3069,9 +3179,11 @@ check_goto (tree decl)
       else if (complained)
        {
          if (u > 1)
-           inform (input_location, "  skips initialization of %q+#D", bad);
+           inform (DECL_SOURCE_LOCATION (bad),
+                   "  skips initialization of %q#D", bad);
          else
-           inform (input_location, "  enters scope of %q+#D which has "
+           inform (DECL_SOURCE_LOCATION (bad),
+                   "  enters scope of %q#D which has "
                    "non-trivial destructor", bad);
        }
     }
@@ -3082,6 +3194,8 @@ check_goto (tree decl)
        inform (input_location, "  enters try block");
       else if (ent->in_catch_scope && !saw_catch)
        inform (input_location, "  enters catch block");
+      else if (ent->in_transaction_scope)
+       inform (input_location, "  enters synchronized or atomic statement");
     }
 
   if (ent->in_omp_scope)
@@ -3098,13 +3212,12 @@ check_goto (tree decl)
            break;
          if (b->kind == sk_omp)
            {
-             if (!identified)
+             if (identified < 2)
                {
-                 complained = permerror (input_location,
-                                         "jump to label %q+D", 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");
@@ -3208,6 +3321,9 @@ struct cp_switch
      label.  We need a tree, rather than simply a hash table, because
      of the GNU case range extension.  */
   splay_tree cases;
+  /* Remember whether there was a case value that is outside the
+     range of the original type of the controlling expression.  */
+  bool outside_range_p;
 };
 
 /* A stack of the currently active switch statements.  The innermost
@@ -3229,6 +3345,7 @@ push_switch (tree switch_stmt)
   p->next = switch_stack;
   p->switch_stmt = switch_stmt;
   p->cases = splay_tree_new (case_compare, NULL, NULL);
+  p->outside_range_p = false;
   switch_stack = p;
 }
 
@@ -3240,10 +3357,14 @@ pop_switch (void)
 
   /* Emit warnings as needed.  */
   switch_location = EXPR_LOC_OR_LOC (cs->switch_stmt, input_location);
+  const bool bool_cond_p
+    = (SWITCH_STMT_TYPE (cs->switch_stmt)
+       && TREE_CODE (SWITCH_STMT_TYPE (cs->switch_stmt)) == BOOLEAN_TYPE);
   if (!processing_template_decl)
     c_do_switch_warnings (cs->cases, switch_location,
                          SWITCH_STMT_TYPE (cs->switch_stmt),
-                         SWITCH_STMT_COND (cs->switch_stmt));
+                         SWITCH_STMT_COND (cs->switch_stmt),
+                         bool_cond_p, cs->outside_range_p);
 
   splay_tree_delete (cs->cases);
   switch_stack = switch_stack->next;
@@ -3308,7 +3429,8 @@ finish_case_label (location_t loc, tree low_value, tree high_value)
   high_value = case_conversion (type, high_value);
 
   r = c_add_case_label (loc, switch_stack->cases, cond, type,
-                       low_value, high_value);
+                       low_value, high_value,
+                       &switch_stack->outside_range_p);
 
   /* After labels, make any new cleanups in the function go into their
      own new (temporary) binding contour.  */
@@ -3752,7 +3874,7 @@ record_unknown_type (tree type, const char* name)
 /* A string for which we should create an IDENTIFIER_NODE at
    startup.  */
 
-typedef struct predefined_identifier
+struct predefined_identifier
 {
   /* The name of the identifier.  */
   const char *const name;
@@ -3760,7 +3882,7 @@ typedef struct predefined_identifier
   tree *const node;
   /* Nonzero if this is the name of a constructor or destructor.  */
   const int ctor_or_dtor_p;
-} predefined_identifier;
+};
 
 /* Create all the predefined identifiers.  */
 
@@ -3957,6 +4079,10 @@ cxx_init_decl_processing (void)
 
     /* Ensure attribs.c is initialized.  */
     init_attributes ();
+
+    /* Ensure constraint.cc is initialized. */
+    init_constraint_processing ();
+
     extvisattr = build_tree_list (get_identifier ("externally_visible"),
                                  NULL_TREE);
     newattrs = tree_cons (get_identifier ("alloc_size"),
@@ -3994,6 +4120,8 @@ cxx_init_decl_processing (void)
     TYPE_SIZE_UNIT (nullptr_type_node) = size_int (GET_MODE_SIZE (ptr_mode));
     TYPE_UNSIGNED (nullptr_type_node) = 1;
     TYPE_PRECISION (nullptr_type_node) = GET_MODE_BITSIZE (ptr_mode);
+    if (abi_version_at_least (9))
+      TYPE_ALIGN (nullptr_type_node) = GET_MODE_ALIGNMENT (ptr_mode);
     SET_TYPE_MODE (nullptr_type_node, ptr_mode);
     record_builtin_type (RID_MAX, "decltype(nullptr)", nullptr_type_node);
     nullptr_node = build_int_cst (nullptr_type_node, 0);
@@ -4427,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.  */
@@ -4724,7 +4853,8 @@ start_decl (const cp_declarator *declarator,
       && DECL_DECLARED_INLINE_P (decl)
       && DECL_UNINLINABLE (decl)
       && lookup_attribute ("noinline", DECL_ATTRIBUTES (decl)))
-    warning (0, "inline function %q+D given attribute noinline", decl);
+    warning_at (DECL_SOURCE_LOCATION (decl), 0,
+               "inline function %qD given attribute noinline", decl);
 
   if (TYPE_P (context) && COMPLETE_TYPE_P (complete_type (context)))
     {
@@ -4850,7 +4980,7 @@ start_decl (const cp_declarator *declarator,
       && DECL_DECLARED_CONSTEXPR_P (current_function_decl))
     {
       bool ok = false;
-      if (DECL_THREAD_LOCAL_P (decl))
+      if (CP_DECL_THREAD_LOCAL_P (decl))
        error ("%qD declared %<thread_local%> in %<constexpr%> function",
               decl);
       else if (TREE_STATIC (decl))
@@ -5277,8 +5407,9 @@ check_for_uninitialized_const_var (tree decl)
            inform (DECL_SOURCE_LOCATION (defaulted_ctor),
                    "constructor is not user-provided because it is "
                    "explicitly defaulted in the class body");
-         inform (0, "and the implicitly-defined constructor does not "
-                 "initialize %q+#D", field);
+         inform (DECL_SOURCE_LOCATION (field),
+                 "and the implicitly-defined constructor does not "
+                 "initialize %q#D", field);
        }
     }
 }
@@ -5286,11 +5417,11 @@ check_for_uninitialized_const_var (tree decl)
 /* Structure holding the current initializer being processed by reshape_init.
    CUR is a pointer to the current element being processed, END is a pointer
    after the last element present in the initializer.  */
-typedef struct reshape_iterator_t
+struct reshape_iter
 {
   constructor_elt *cur;
   constructor_elt *end;
-} reshape_iter;
+};
 
 static tree reshape_init_r (tree, reshape_iter *, bool, tsubst_flags_t);
 
@@ -5392,7 +5523,7 @@ reshape_init_vector (tree type, reshape_iter *d, tsubst_flags_t complain)
 {
   tree max_index = NULL_TREE;
 
-  gcc_assert (TREE_CODE (type) == VECTOR_TYPE);
+  gcc_assert (VECTOR_TYPE_P (type));
 
   if (COMPOUND_LITERAL_P (d->cur->value))
     {
@@ -5409,7 +5540,7 @@ reshape_init_vector (tree type, reshape_iter *d, tsubst_flags_t complain)
     }
 
   /* For a vector, we initialize it as an array of the appropriate size.  */
-  if (TREE_CODE (type) == VECTOR_TYPE)
+  if (VECTOR_TYPE_P (type))
     max_index = size_int (TYPE_VECTOR_SUBPARTS (type) - 1);
 
   return reshape_init_array_1 (TREE_TYPE (type), max_index, d, complain);
@@ -5717,7 +5848,7 @@ reshape_init_r (tree type, reshape_iter *d, bool first_initializer_p,
     return reshape_init_class (type, d, first_initializer_p, complain);
   else if (TREE_CODE (type) == ARRAY_TYPE)
     return reshape_init_array (type, d, complain);
-  else if (TREE_CODE (type) == VECTOR_TYPE)
+  else if (VECTOR_TYPE_P (type))
     return reshape_init_vector (type, d, complain);
   else
     gcc_unreachable();
@@ -5919,7 +6050,7 @@ check_initializer (tree decl, tree init, int flags, vec<tree, va_gc> **cleanups)
                       "not by %<{...}%>",
                       decl);
            }
-         else if (TREE_CODE (type) == VECTOR_TYPE && TYPE_VECTOR_OPAQUE (type))
+         else if (VECTOR_TYPE_P (type) && TYPE_VECTOR_OPAQUE (type))
            {
              error ("opaque vector types cannot be initialized");
              init = error_mark_node;
@@ -6340,6 +6471,16 @@ value_dependent_init_p (tree init)
   return false;
 }
 
+// Returns true if a DECL is VAR_DECL with the concept specifier.
+static inline bool
+is_concept_var (tree decl)
+{
+  return (VAR_P (decl)
+         // Not all variables have DECL_LANG_SPECIFIC.
+          && DECL_LANG_SPECIFIC (decl)
+          && DECL_DECLARED_CONCEPT_P (decl));
+}
+
 /* Finish processing of a declaration;
    install its line number and initial value.
    If the length of an array type is not known before,
@@ -6418,7 +6559,9 @@ cp_finish_decl (tree decl, tree init, bool init_const_expr_p,
                                                  tf_warning_or_error);
       d_init = resolve_nondeduced_context (d_init);
       type = TREE_TYPE (decl) = do_auto_deduction (type, d_init,
-                                                  auto_node);
+                                                  auto_node,
+                                                   tf_warning_or_error,
+                                                   adc_variable_type);
       if (type == error_mark_node)
        return;
       cp_apply_type_quals_to_decl (cp_type_quals (type), decl);
@@ -6497,11 +6640,10 @@ cp_finish_decl (tree decl, tree init, bool init_const_expr_p,
         then it can be used in future constant expressions, so its value
         must be available. */
 
-      if (!VAR_P (decl) || dependent_type_p (type))
+      if (!VAR_P (decl) || type_dependent_p)
        /* We can't do anything if the decl has dependent type.  */;
       else if (init
               && init_const_expr_p
-              && !type_dependent_p
               && TREE_CODE (type) != REFERENCE_TYPE
               && decl_maybe_constant_var_p (decl)
               && !type_dependent_init_p (init)
@@ -6517,6 +6659,8 @@ cp_finish_decl (tree decl, tree init, bool init_const_expr_p,
            init = NULL_TREE;
          release_tree_vector (cleanups);
        }
+      else if (!init && is_concept_var (decl))
+        error ("variable concept has no initializer");
       else if (!DECL_PRETTY_FUNCTION_P (decl))
        {
          /* Deduce array size even if the initializer is dependent.  */
@@ -6589,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
@@ -7047,7 +7194,7 @@ register_dtor_fn (tree decl)
      function to do the cleanup.  */
   dso_parm = (flag_use_cxa_atexit
              && !targetm.cxx.use_atexit_for_cxa_atexit ());
-  ob_parm = (DECL_THREAD_LOCAL_P (decl) || dso_parm);
+  ob_parm = (CP_DECL_THREAD_LOCAL_P (decl) || dso_parm);
   use_dtor = ob_parm && CLASS_TYPE_P (type);
   if (use_dtor)
     {
@@ -7090,7 +7237,7 @@ register_dtor_fn (tree decl)
   mark_used (cleanup);
   cleanup = build_address (cleanup);
 
-  if (DECL_THREAD_LOCAL_P (decl))
+  if (CP_DECL_THREAD_LOCAL_P (decl))
     atex_node = get_thread_atexit_node ();
   else
     atex_node = get_atexit_node ();
@@ -7130,7 +7277,7 @@ register_dtor_fn (tree decl)
 
   if (ob_parm)
     {
-      if (!DECL_THREAD_LOCAL_P (decl)
+      if (!CP_DECL_THREAD_LOCAL_P (decl)
          && targetm.cxx.use_aeabi_atexit ())
        {
          arg1 = cleanup;
@@ -7170,7 +7317,7 @@ expand_static_init (tree decl, tree init)
        return;
     }
 
-  if (DECL_THREAD_LOCAL_P (decl) && DECL_GNU_TLS_P (decl)
+  if (CP_DECL_THREAD_LOCAL_P (decl) && DECL_GNU_TLS_P (decl)
       && !DECL_FUNCTION_SCOPE_P (decl))
     {
       if (init)
@@ -7199,7 +7346,7 @@ expand_static_init (tree decl, tree init)
       tree flag, begin;
       /* We don't need thread-safety code for thread-local vars.  */
       bool thread_guard = (flag_threadsafe_statics
-                          && !DECL_THREAD_LOCAL_P (decl));
+                          && !CP_DECL_THREAD_LOCAL_P (decl));
 
       /* Emit code to perform this initialization but once.  This code
         looks like:
@@ -7312,7 +7459,7 @@ expand_static_init (tree decl, tree init)
       finish_then_clause (if_stmt);
       finish_if_stmt (if_stmt);
     }
-  else if (DECL_THREAD_LOCAL_P (decl))
+  else if (CP_DECL_THREAD_LOCAL_P (decl))
     tls_aggregates = tree_cons (init, decl, tls_aggregates);
   else
     static_aggregates = tree_cons (init, decl, static_aggregates);
@@ -7579,6 +7726,23 @@ check_static_quals (tree decl, cp_cv_quals quals)
           decl);
 }
 
+// Check that FN takes no arguments and returns bool.
+static void
+check_concept_fn (tree fn)
+{
+  // A constraint is nullary.
+  if (DECL_ARGUMENTS (fn))
+    error ("concept %q#D declared with function parameters", fn);
+
+  // The declared return type of the concept shall be bool, and
+  // it shall not be deduced from it definition.
+  tree type = TREE_TYPE (TREE_TYPE (fn));
+  if (is_auto (type))
+    error ("concept %q#D declared with a deduced return type", fn);
+  else if (type != boolean_type_node)
+    error ("concept %q#D with non-%<bool%> return type %qT", fn, type);
+}
+
 /* Helper function.  Replace the temporary this parameter injected
    during cp_finish_omp_declare_simd with the real this parameter.  */
 
@@ -7619,6 +7783,7 @@ grokfndecl (tree ctype,
            tree declarator,
            tree parms,
            tree orig_declarator,
+           tree decl_reqs,
            int virtualp,
            enum overload_flags flags,
            cp_cv_quals quals,
@@ -7640,6 +7805,16 @@ grokfndecl (tree ctype,
   int staticp = ctype && TREE_CODE (type) == FUNCTION_TYPE;
   tree t;
 
+  // Was the concept specifier present?
+  bool concept_p = inlinep & 4;
+
+  // Concept declarations must have a corresponding definition.
+  if (concept_p && !funcdef_flag)
+    {
+      error ("concept %qD has no definition", declarator);
+      return NULL_TREE;
+    }
+
   if (rqual)
     type = build_ref_qualified_type (type, rqual);
   if (raises)
@@ -7647,6 +7822,21 @@ grokfndecl (tree ctype,
 
   decl = build_lang_decl (FUNCTION_DECL, declarator, type);
 
+  /* Set the constraints on the declaration. */
+  if (flag_concepts)
+    {
+      tree tmpl_reqs = NULL_TREE;
+      if (processing_template_decl > template_class_depth (ctype))
+        tmpl_reqs = TEMPLATE_PARMS_CONSTRAINTS (current_template_parms);
+
+      /* Adjust the required expression into a constraint. */
+      if (decl_reqs)
+        decl_reqs = make_predicate_constraint (decl_reqs);
+
+      tree ci = build_constraints (tmpl_reqs, decl_reqs);
+      set_constraints (decl, ci);
+    }
+
   /* If we have an explicit location, use it, otherwise use whatever
      build_lang_decl used (probably input_location).  */
   if (location != UNKNOWN_LOCATION)
@@ -7658,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))
@@ -7681,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)
     {
@@ -7729,15 +7914,12 @@ grokfndecl (tree ctype,
            }
 
          if (inlinep & 1)
-           error ("%<inline%> is not allowed in declaration of friend "
-                  "template specialization %qD",
-                  decl);
-         if (inlinep & 2)
-           error ("%<constexpr%> is not allowed in declaration of friend "
-                  "template specialization %qD",
-                  decl);
-         if (inlinep)
-           return NULL_TREE;
+           {
+             error ("%<inline%> is not allowed in declaration of friend "
+                    "template specialization %qD",
+                    decl);
+             return NULL_TREE;
+           }
        }
     }
 
@@ -7824,9 +8006,22 @@ grokfndecl (tree ctype,
   if (inlinep & 2)
     DECL_DECLARED_CONSTEXPR_P (decl) = true;
 
+  // If the concept declaration specifier was found, check
+  // that the declaration satisfies the necessary requirements.
+  if (concept_p)
+    {
+      DECL_DECLARED_CONCEPT_P (decl) = true;
+      check_concept_fn (decl);
+    }
+
   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
@@ -7899,7 +8094,7 @@ grokfndecl (tree ctype,
   if (TYPE_NOTHROW_P (type) || nothrow_libfn_p (decl))
     TREE_NOTHROW (decl) = 1;
 
-  if (flag_openmp || flag_cilkplus)
+  if (flag_openmp || flag_openmp_simd || flag_cilkplus)
     {
       /* Adjust "omp declare simd" attributes.  */
       tree ods = lookup_attribute ("omp declare simd", *attrlist);
@@ -7943,7 +8138,8 @@ grokfndecl (tree ctype,
   decl = check_explicit_specialization (orig_declarator, decl,
                                        template_count,
                                        2 * funcdef_flag +
-                                       4 * (friendp != 0));
+                                       4 * (friendp != 0) +
+                                        8 * concept_p);
   if (decl == error_mark_node)
     return NULL_TREE;
 
@@ -8101,7 +8297,7 @@ grokvardecl (tree type,
             tree orig_declarator,
             const cp_decl_specifier_seq *declspecs,
             int initialized,
-            int constp,
+            int flags,
             int template_count,
             tree scope)
 {
@@ -8110,6 +8306,9 @@ grokvardecl (tree type,
 
   gcc_assert (!name || identifier_p (name));
 
+  bool constp = flags&1;
+  bool conceptp = flags&2;
+
   /* Compute the scope in which to place the variable, but remember
      whether or not that scope was explicitly specified by the user.   */
   explicit_scope = scope;
@@ -8176,9 +8375,13 @@ grokvardecl (tree type,
   if (decl_spec_seq_has_spec_p (declspecs, ds_thread))
     {
       if (DECL_EXTERNAL (decl) || TREE_STATIC (decl))
-        set_decl_tls_model (decl, decl_default_tls_model (decl));
+       {
+         CP_DECL_THREAD_LOCAL_P (decl) = true;
+         if (!processing_template_decl)
+           set_decl_tls_model (decl, decl_default_tls_model (decl));
+       }
       if (declspecs->gnu_thread_keyword_p)
-       DECL_GNU_TLS_P (decl) = true;
+       SET_DECL_GNU_TLS_P (decl);
     }
 
   /* If the type of the decl has no linkage, make sure that we'll
@@ -8203,10 +8406,38 @@ grokvardecl (tree type,
   else
     DECL_INTERFACE_KNOWN (decl) = 1;
 
+  if (DECL_NAME (decl)
+      && MAIN_NAME_P (DECL_NAME (decl))
+      && scope == global_namespace)
+    error ("cannot declare %<::main%> to be a global variable");
+
+  /* Check that the variable can be safely declared as a concept.
+     Note that this also forbids explicit specializations.  */
+  if (conceptp)
+    {
+      if (!processing_template_decl)
+        {
+          error ("a non-template variable cannot be %<concept%>");
+          return NULL_TREE;
+        }
+      else
+        DECL_DECLARED_CONCEPT_P (decl) = true;
+      if (!same_type_ignoring_top_level_qualifiers_p (type, boolean_type_node))
+       error_at (declspecs->locations[ds_type_spec],
+                 "concept must have type %<bool%>");
+    }
+  else if (flag_concepts
+          && processing_template_decl > template_class_depth (scope))
+    {
+      tree reqs = TEMPLATE_PARMS_CONSTRAINTS (current_template_parms);
+      tree ci = build_constraints (reqs, NULL_TREE);
+      set_constraints (decl, ci);
+    }
+
   // Handle explicit specializations and instantiations of variable templates.
   if (orig_declarator)
     decl = check_explicit_specialization (orig_declarator, decl,
-                                         template_count, 0);
+                                         template_count, conceptp * 8);
 
   return decl != error_mark_node ? decl : NULL_TREE;
 }
@@ -8375,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
@@ -8494,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)
     {
@@ -8581,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))
@@ -8589,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
@@ -8744,24 +8965,51 @@ create_array_type_for_decl (tree name, tree type, tree size)
   return build_cplus_array_type (type, itype);
 }
 
-/* Check that it's OK to declare a function with the indicated TYPE.
-   SFK indicates the kind of special function (if any) that this
-   function is.  OPTYPE is the type given in a conversion operator
-   declaration, or the class type for a constructor/destructor.
-   Returns the actual return type of the function; that
-   may be different than TYPE if an error occurs, or for certain
-   special functions.  */
+/* Returns the smallest location != UNKNOWN_LOCATION among the
+   three stored in LOCATIONS[ds_const], LOCATIONS[ds_volatile],
+   and LOCATIONS[ds_restrict].  */
+
+static location_t
+smallest_type_quals_location (int type_quals, const location_t* locations)
+{
+  location_t loc = UNKNOWN_LOCATION;
+
+  if (type_quals & TYPE_QUAL_CONST)
+    loc = locations[ds_const];
+
+  if ((type_quals & TYPE_QUAL_VOLATILE)
+      && (loc == UNKNOWN_LOCATION || locations[ds_volatile] < loc))
+    loc = locations[ds_volatile];
+
+  if ((type_quals & TYPE_QUAL_RESTRICT)
+      && (loc == UNKNOWN_LOCATION || locations[ds_restrict] < loc))
+    loc = locations[ds_restrict];
+
+  return loc;
+}
+
+/* Check that it's OK to declare a function with the indicated TYPE
+   and TYPE_QUALS.  SFK indicates the kind of special function (if any)
+   that this function is.  OPTYPE is the type given in a conversion
+   operator declaration, or the class type for a constructor/destructor.
+   Returns the actual return type of the function; that may be different
+   than TYPE if an error occurs, or for certain special functions.  */
 
 static tree
 check_special_function_return_type (special_function_kind sfk,
                                    tree type,
-                                   tree optype)
+                                   tree optype,
+                                   int type_quals,
+                                   const location_t* locations)
 {
   switch (sfk)
     {
     case sfk_constructor:
       if (type)
        error ("return type specification for constructor invalid");
+      else if (type_quals != TYPE_UNQUALIFIED)
+       error_at (smallest_type_quals_location (type_quals, locations),
+                 "qualifiers are not allowed on constructor declaration");
 
       if (targetm.cxx.cdtor_returns_this () && !TYPE_FOR_JAVA (optype))
        type = build_pointer_type (optype);
@@ -8772,6 +9020,10 @@ check_special_function_return_type (special_function_kind sfk,
     case sfk_destructor:
       if (type)
        error ("return type specification for destructor invalid");
+      else if (type_quals != TYPE_UNQUALIFIED)
+       error_at (smallest_type_quals_location (type_quals, locations),
+                 "qualifiers are not allowed on destructor declaration");
+
       /* We can't use the proper return type here because we run into
         problems with ambiguous bases and covariant returns.
         Java classes are left unchanged because (void *) isn't a valid
@@ -8784,7 +9036,12 @@ check_special_function_return_type (special_function_kind sfk,
 
     case sfk_conversion:
       if (type)
-       error ("return type specified for %<operator %T%>",  optype);
+       error ("return type specified for %<operator %T%>", optype);
+      else if (type_quals != TYPE_UNQUALIFIED)
+       error_at (smallest_type_quals_location (type_quals, locations),
+                 "qualifiers are not allowed on declaration of "
+                 "%<operator %T%>", optype);
+
       type = optype;
       break;
 
@@ -8910,7 +9167,7 @@ grokdeclarator (const cp_declarator *declarator,
      a member function.  */
   cp_ref_qualifier rqual = REF_QUAL_NONE;
   /* cv-qualifiers that apply to the type specified by the DECLSPECS.  */
-  int type_quals;
+  int type_quals = TYPE_UNQUALIFIED;
   tree raises = NULL_TREE;
   int template_count = 0;
   tree returned_attrs = NULL_TREE;
@@ -8941,6 +9198,7 @@ grokdeclarator (const cp_declarator *declarator,
   bool array_parameter_p = false;
   source_location saved_loc = input_location;
   const char *errmsg;
+  tree reqs = NULL_TREE;
 
   signed_p = decl_spec_seq_has_spec_p (declspecs, ds_signed);
   unsigned_p = decl_spec_seq_has_spec_p (declspecs, ds_unsigned);
@@ -8950,6 +9208,19 @@ grokdeclarator (const cp_declarator *declarator,
   explicit_intN = declspecs->explicit_intN_p;
   thread_p = decl_spec_seq_has_spec_p (declspecs, ds_thread);
 
+  // Was concept_p specified? Note that ds_concept
+  // implies ds_constexpr!
+  bool concept_p = decl_spec_seq_has_spec_p (declspecs, ds_concept);
+  if (concept_p)
+    constexpr_p = true;
+
+  if (decl_spec_seq_has_spec_p (declspecs, ds_const))
+    type_quals |= TYPE_QUAL_CONST;
+  if (decl_spec_seq_has_spec_p (declspecs, ds_volatile))
+    type_quals |= TYPE_QUAL_VOLATILE;
+  if (decl_spec_seq_has_spec_p (declspecs, ds_restrict))
+    type_quals |= TYPE_QUAL_RESTRICT;
+
   if (decl_context == FUNCDEF)
     funcdef_flag = true, decl_context = NORMAL;
   else if (decl_context == MEMFUNCDEF)
@@ -9192,6 +9463,12 @@ grokdeclarator (const cp_declarator *declarator,
   if (name == NULL)
     name = decl_context == PARM ? "parameter" : "type name";
 
+  if (concept_p && typedef_p)
+    {
+      error ("%<concept%> cannot appear in a typedef declaration");
+      return error_mark_node;
+    }
+
   if (constexpr_p && typedef_p)
     {
       error ("%<constexpr%> cannot appear in a typedef declaration");
@@ -9269,8 +9546,13 @@ grokdeclarator (const cp_declarator *declarator,
     ctor_return_type = ctype;
 
   if (sfk != sfk_none)
-    type = check_special_function_return_type (sfk, type,
-                                              ctor_return_type);
+    {
+      type = check_special_function_return_type (sfk, type,
+                                                ctor_return_type,
+                                                type_quals,
+                                                declspecs->locations);
+      type_quals = TYPE_UNQUALIFIED;
+    }
   else if (type == NULL_TREE)
     {
       int is_main;
@@ -9300,7 +9582,12 @@ grokdeclarator (const cp_declarator *declarator,
        warning (OPT_Wreturn_type,
                  "ISO C++ forbids declaration of %qs with no type", name);
 
-      type = integer_type_node;
+      if (type_was_error_mark_node && template_parm_flag)
+       /* FIXME we should be able to propagate the error_mark_node as is
+          for other contexts too.  */
+       type = error_mark_node;
+      else
+       type = integer_type_node;
     }
 
   ctype = NULL_TREE;
@@ -9450,17 +9737,6 @@ grokdeclarator (const cp_declarator *declarator,
        type = build_complex_type (type);
     }
 
-  type_quals = TYPE_UNQUALIFIED;
-  if (decl_spec_seq_has_spec_p (declspecs, ds_const))
-    type_quals |= TYPE_QUAL_CONST;
-  if (decl_spec_seq_has_spec_p (declspecs, ds_volatile))
-    type_quals |= TYPE_QUAL_VOLATILE;
-  if (decl_spec_seq_has_spec_p (declspecs, ds_restrict))
-    type_quals |= TYPE_QUAL_RESTRICT;
-  if (sfk == sfk_conversion && type_quals != TYPE_UNQUALIFIED)
-    error ("qualifiers are not allowed on declaration of %<operator %T%>",
-          ctor_return_type);
-
   /* If we're using the injected-class-name to form a compound type or a
      declaration, replace it with the underlying class so we don't get
      redundant typedefs in the debug output.  But if we are returning the
@@ -9515,9 +9791,12 @@ grokdeclarator (const cp_declarator *declarator,
               || thread_p)
        error ("storage class specifiers invalid in parameter declarations");
 
+      /* Function parameters cannot be concept. */
+      if (concept_p)
+          error ("a parameter cannot be declared %<concept%>");
       /* Function parameters cannot be constexpr.  If we saw one, moan
          and pretend it wasn't there.  */
-      if (constexpr_p)
+      else if (constexpr_p)
         {
           error ("a parameter cannot be declared %<constexpr%>");
           constexpr_p = 0;
@@ -9682,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:
 
@@ -9738,6 +10020,8 @@ grokdeclarator (const cp_declarator *declarator,
             virt_specifiers = declarator->u.function.virt_specifiers;
            /* And ref-qualifier, too */
            rqual = declarator->u.function.ref_qualifier;
+           /* And tx-qualifier.  */
+           tree tx_qual = declarator->u.function.tx_qualifier;
            /* Pick up the exception specifications.  */
            raises = declarator->u.function.exception_specification;
            /* If the exception-specification is ill-formed, let's pretend
@@ -9745,6 +10029,10 @@ grokdeclarator (const cp_declarator *declarator,
            if (raises == error_mark_node)
              raises = NULL_TREE;
 
+           if (reqs)
+             error_at (location_of (reqs), "requires-clause on return type");
+           reqs = declarator->u.function.requires_clause;
+
            /* Say it's a definition only for the CALL_EXPR
               closest to the identifier.  */
            funcdecl_p = inner_declarator && inner_declarator->kind == cdk_id;
@@ -9911,13 +10199,24 @@ grokdeclarator (const cp_declarator *declarator,
              }
 
            type = build_function_type (type, arg_types);
-           if (declarator->std_attributes)
+
+           tree attrs = declarator->std_attributes;
+           if (tx_qual)
+             {
+               tree att = build_tree_list (tx_qual, NULL_TREE);
+               /* transaction_safe applies to the type, but
+                  transaction_safe_dynamic applies to the function.  */
+               if (is_attribute_p ("transaction_safe", tx_qual))
+                 attrs = chainon (attrs, att);
+               else
+                 returned_attrs = chainon (returned_attrs, att);
+             }
+           if (attrs)
              /* [dcl.fct]/2:
 
                 The optional attribute-specifier-seq appertains to
                 the function type.  */
-             decl_attributes (&type, declarator->std_attributes,
-                              0);
+             decl_attributes (&type, attrs, 0);
          }
          break;
 
@@ -10228,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))
@@ -10340,6 +10626,9 @@ grokdeclarator (const cp_declarator *declarator,
          type = error_mark_node;
        }
 
+      if (reqs)
+       error_at (location_of (reqs), "requires-clause on typedef");
+
       if (decl_context == FIELD)
        decl = build_lang_decl (TYPE_DECL, unqualified_id, type);
       else
@@ -10533,6 +10822,9 @@ grokdeclarator (const cp_declarator *declarator,
            error ("invalid qualifiers on non-member function type");
        }
 
+      if (reqs)
+       error_at (location_of (reqs), "requires-clause on type-id");
+
       return type;
     }
   else if (unqualified_id == NULL_TREE && decl_context != PARM
@@ -10554,6 +10846,13 @@ grokdeclarator (const cp_declarator *declarator,
       return error_mark_node;
     }
 
+  if (reqs
+      && TREE_CODE (type) != FUNCTION_TYPE
+      && TREE_CODE (type) != METHOD_TYPE)
+    error_at (location_of (reqs),
+             "requires-clause on declaration of non-function type %qT",
+             type);
+
   /* We don't check parameter types here because we can emit a better
      error message later.  */
   if (decl_context != PARM)
@@ -10711,6 +11010,11 @@ grokdeclarator (const cp_declarator *declarator,
                           uqname, ctype);
                    return error_mark_node;
                  }
+                if (concept_p)
+                  {
+                    error ("a destructor cannot be %<concept%>");
+                    return error_mark_node;
+                  }
                 if (constexpr_p)
                   {
                     error ("a destructor cannot be %<constexpr%>");
@@ -10724,6 +11028,17 @@ grokdeclarator (const cp_declarator *declarator,
                       id_declarator->u.id.unqualified_name);
                return error_mark_node;
              }
+           if (sfk == sfk_constructor)
+             if (concept_p)
+               {
+                 error ("a constructor cannot be %<concept%>");
+                 return error_mark_node;
+               }
+           if (concept_p)
+             {
+               error ("a concept cannot be a member function");
+               concept_p = false;
+             }
 
            if (TREE_CODE (unqualified_id) == TEMPLATE_ID_EXPR)
              {
@@ -10752,9 +11067,10 @@ grokdeclarator (const cp_declarator *declarator,
                               ? unqualified_id : dname,
                               parms,
                               unqualified_id,
+                              reqs,
                               virtualp, flags, memfn_quals, rqual, raises,
                               friendp ? -1 : 0, friendp, publicp,
-                               inlinep | (2 * constexpr_p),
+                               inlinep | (2 * constexpr_p) | (4 * concept_p),
                               initialized == SD_DELETED, sfk,
                               funcdef_flag, template_count, in_namespace,
                               attrlist, declarator->id_loc);
@@ -10851,12 +11167,16 @@ grokdeclarator (const cp_declarator *declarator,
 
                if (thread_p)
                  {
-                   set_decl_tls_model (decl, decl_default_tls_model (decl));
+                   CP_DECL_THREAD_LOCAL_P (decl) = true;
+                   if (!processing_template_decl)
+                     set_decl_tls_model (decl, decl_default_tls_model (decl));
                    if (declspecs->gnu_thread_keyword_p)
-                     DECL_GNU_TLS_P (decl) = true;
+                     SET_DECL_GNU_TLS_P (decl);
                  }
-
-               if (constexpr_p && !initialized)
+               if (concept_p)
+                   error ("static data member %qE declared %<concept%>",
+                          unqualified_id);
+               else if (constexpr_p && !initialized)
                  {
                    error ("constexpr static data member %qD must have an "
                           "initializer", decl);
@@ -10865,7 +11185,10 @@ grokdeclarator (const cp_declarator *declarator,
              }
            else
              {
-                if (constexpr_p)
+               if (concept_p)
+                 error ("non-static data member %qE declared %<concept%>",
+                        unqualified_id);
+                else if (constexpr_p)
                  {
                    error ("non-static data member %qE declared %<constexpr%>",
                           unqualified_id);
@@ -10975,10 +11298,12 @@ grokdeclarator (const cp_declarator *declarator,
          TYPE_HAS_LATE_RETURN_TYPE (type) = 1;
 
        decl = grokfndecl (ctype, type, original_name, parms, unqualified_id,
-                          virtualp, flags, memfn_quals, rqual, raises,
+                           reqs, virtualp, flags, memfn_quals, rqual, raises,
                           1, friendp,
-                          publicp, inlinep | (2 * constexpr_p),
-                          initialized == SD_DELETED, sfk,
+                          publicp,
+                           inlinep | (2 * constexpr_p) | (4 * concept_p),
+                          initialized == SD_DELETED,
+                           sfk,
                            funcdef_flag,
                           template_count, in_namespace, attrlist,
                           declarator->id_loc);
@@ -11019,7 +11344,7 @@ grokdeclarator (const cp_declarator *declarator,
        decl = grokvardecl (type, dname, unqualified_id,
                            declspecs,
                            initialized,
-                           (type_quals & TYPE_QUAL_CONST) != 0,
+                           ((type_quals & TYPE_QUAL_CONST) != 0) | (2 * concept_p),
                            template_count,
                            ctype ? ctype : in_namespace);
        if (decl == NULL_TREE)
@@ -11269,7 +11594,7 @@ type_is_deprecated (tree type)
 
    *PARMS is set to the chain of PARM_DECLs created.  */
 
-static tree
+tree
 grokparms (tree parmlist, tree *parms)
 {
   tree result = NULL_TREE;
@@ -12364,8 +12689,16 @@ xref_tag_1 (enum tag_types tag_code, tree name,
     {
       if (template_header_p && MAYBE_CLASS_TYPE_P (t))
         {
-         if (!redeclare_class_template (t, current_template_parms))
-            return error_mark_node;
+          /* Check that we aren't trying to overload a class with different
+             constraints.  */
+          tree constr = NULL_TREE;
+          if (current_template_parms)
+            {
+              tree reqs = TEMPLATE_PARMS_CONSTRAINTS (current_template_parms);
+              constr = build_constraints (reqs, NULL_TREE);
+            }
+         if (!redeclare_class_template (t, current_template_parms, constr))
+           return error_mark_node;
         }
       else if (!processing_template_decl
               && CLASS_TYPE_P (t)
@@ -12440,6 +12773,7 @@ xref_basetypes (tree ref, tree base_list)
   tree binfo, base_binfo;
   unsigned max_vbases = 0; /* Maximum direct & indirect virtual bases.  */
   unsigned max_bases = 0;  /* Maximum direct bases.  */
+  unsigned max_dvbases = 0; /* Maximum direct virtual bases.  */
   int i;
   tree default_access;
   tree igo_prev; /* Track Inheritance Graph Order.  */
@@ -12477,12 +12811,13 @@ xref_basetypes (tree ref, tree base_list)
        {
          max_bases++;
          if (TREE_TYPE (*basep))
-           max_vbases++;
+           max_dvbases++;
          if (CLASS_TYPE_P (basetype))
            max_vbases += vec_safe_length (CLASSTYPE_VBASECLASSES (basetype));
          basep = &TREE_CHAIN (*basep);
        }
     }
+  max_vbases += max_dvbases;
 
   TYPE_MARKED_P (ref) = 1;
 
@@ -12525,6 +12860,9 @@ xref_basetypes (tree ref, tree base_list)
          error ("Java class %qT cannot have multiple bases", ref);
           return false;
         }
+      else
+       warning (OPT_Wmultiple_inheritance,
+                "%qT defined with multiple direct bases", ref);
     }
 
   if (max_vbases)
@@ -12536,6 +12874,9 @@ xref_basetypes (tree ref, tree base_list)
          error ("Java class %qT cannot have virtual bases", ref);
           return false;
         }
+      else if (max_dvbases)
+       warning (OPT_Wvirtual_inheritance,
+                "%qT defined with direct virtual base", ref);
     }
 
   for (igo_prev = binfo; base_list; base_list = TREE_CHAIN (base_list))
@@ -13180,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);
         }
     }
 
@@ -13291,6 +13632,16 @@ check_function_type (tree decl, tree current_function_parms)
     abstract_virtuals_error (decl, TREE_TYPE (fntype));
 }
 
+/* True iff FN is an implicitly-defined default constructor.  */
+
+static bool
+implicit_default_ctor_p (tree fn)
+{
+  return (DECL_CONSTRUCTOR_P (fn)
+         && !user_provided_p (fn)
+         && sufficient_parms_p (FUNCTION_FIRST_USER_PARMTYPE (fn)));
+}
+
 /* Create the FUNCTION_DECL for a function definition.
    DECLSPECS and DECLARATOR are the parts of the declaration;
    they describe the function's name and the type it returns,
@@ -13353,7 +13704,8 @@ start_preparsed_function (tree decl1, tree attrs, int flags)
 
   if (DECL_DECLARED_INLINE_P (decl1)
       && lookup_attribute ("noinline", attrs))
-    warning (0, "inline function %q+D given attribute noinline", decl1);
+    warning_at (DECL_SOURCE_LOCATION (decl1), 0,
+               "inline function %qD given attribute noinline", decl1);
 
   /* Handle gnu_inline attribute.  */
   if (GNU_INLINE_P (decl1))
@@ -13494,8 +13846,9 @@ start_preparsed_function (tree decl1, tree attrs, int flags)
                    }
 
                  if (context == NULL)
-                   warning (OPT_Wmissing_declarations,
-                            "no previous declaration for %q+D", decl1);
+                   warning_at (DECL_SOURCE_LOCATION (decl1),
+                               OPT_Wmissing_declarations,
+                               "no previous declaration for %qD", decl1);
                }
 
              decl1 = olddecl;
@@ -13695,7 +14048,11 @@ start_preparsed_function (tree decl1, tree attrs, int flags)
   store_parm_decls (current_function_parms);
 
   if (!processing_template_decl
-      && flag_lifetime_dse && DECL_CONSTRUCTOR_P (decl1))
+      && 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
+        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
         is dead when we enter the constructor.  */
@@ -14215,10 +14572,22 @@ finish_function (int flags)
       fntype = TREE_TYPE (fndecl);
     }
 
+  // If this is a concept, check that the definition is reasonable.
+  if (DECL_DECLARED_CONCEPT_P (fndecl))
+    check_function_concept (fndecl);
+
   /* Save constexpr function body before it gets munged by
      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)
@@ -14305,8 +14674,9 @@ finish_function (int flags)
            && TREE_CODE (TREE_TYPE (decl)) != REFERENCE_TYPE
            && (!CLASS_TYPE_P (TREE_TYPE (decl))
                || !TYPE_HAS_NONTRIVIAL_DESTRUCTOR (TREE_TYPE (decl))))
-         warning (OPT_Wunused_but_set_parameter,
-                  "parameter %q+D set but not used", decl);
+         warning_at (DECL_SOURCE_LOCATION (decl),
+                     OPT_Wunused_but_set_parameter,
+                     "parameter %qD set but not used", decl);
       unused_but_set_errorcount = errorcount;
     }
 
@@ -14314,11 +14684,16 @@ finish_function (int flags)
      function.  */
   maybe_warn_unused_local_typedefs ();
 
+  /* Possibly warn about unused parameters.  */
+  if (warn_unused_parameter
+      && !processing_template_decl 
+      && !DECL_CLONED_FUNCTION_P (fndecl))
+    do_warn_unused_parameter (fndecl);
+
   /* Genericize before inlining.  */
   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;
@@ -14521,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);
        }
@@ -14612,8 +14983,7 @@ cxx_maybe_build_cleanup (tree decl, tsubst_flags_t complain)
      a "jumpy" behaviour for users of debuggers when they step around
      the end of the block.  So let's unset the location of the
      destructor call instead.  */
-  if (cleanup != NULL && EXPR_P (cleanup))
-    SET_EXPR_LOCATION (cleanup, UNKNOWN_LOCATION);
+  protected_set_expr_location (cleanup, UNKNOWN_LOCATION);
 
   if (cleanup
       && !lookup_attribute ("warn_unused", TYPE_ATTRIBUTES (TREE_TYPE (decl)))
@@ -14698,6 +15068,7 @@ cp_tree_node_structure (union lang_tree_node * t)
     case TRAIT_EXPR:           return TS_CP_TRAIT_EXPR;
     case LAMBDA_EXPR:          return TS_CP_LAMBDA_EXPR;
     case TEMPLATE_INFO:                return TS_CP_TEMPLATE_INFO;
+    case CONSTRAINT_INFO:       return TS_CP_CONSTRAINT_INFO;
     case USERDEF_LITERAL:      return TS_CP_USERDEF_LITERAL;
     default:                   return TS_CP_GENERIC;
     }