diff --git a/gcc/c-family/c.opt b/gcc/c-family/c.opt
index 06457ac739e..8a4cd634f77 100644
--- a/gcc/c-family/c.opt
+++ b/gcc/c-family/c.opt
@@ -1712,6 +1712,10 @@ fimplement-inlines
 C++ ObjC++ Var(flag_implement_inlines) Init(1)
 Export functions even if they can be inlined.
 
+fimplicit-constexpr
+C++ ObjC++ Var(flag_implicit_constexpr)
+Make inline functions constexpr by default.
+
 fimplicit-inline-templates
 C++ ObjC++ Var(flag_implicit_inline_templates) Init(1)
 Emit implicit instantiations of inline templates.
diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h
index f387b5036d2..acc98c9c452 100644
--- a/gcc/cp/cp-tree.h
+++ b/gcc/cp/cp-tree.h
@@ -2868,8 +2868,9 @@ struct GTY(()) lang_decl_fn {
   unsigned immediate_fn_p : 1;
   unsigned maybe_deleted : 1;
   unsigned coroutine_p : 1;
+  unsigned implicit_constexpr : 1;
 
-  unsigned spare : 10;
+  unsigned spare : 9;
 
   /* 32-bits padding on 64-bit host.  */
 
@@ -8315,6 +8316,7 @@ extern vec<tree> cx_error_context               (void);
 extern tree fold_sizeof_expr			(tree);
 extern void clear_cv_and_fold_caches		(void);
 extern tree unshare_constructor			(tree CXX_MEM_STAT_INFO);
+extern bool decl_implicit_constexpr_p		(tree);
 
 /* An RAII sentinel used to restrict constexpr evaluation so that it
    doesn't do anything that causes extra DECL_UID generation.  */
diff --git a/gcc/c-family/c-cppbuiltin.c b/gcc/c-family/c-cppbuiltin.c
index 60e9e052062..eb34d5af004 100644
--- a/gcc/c-family/c-cppbuiltin.c
+++ b/gcc/c-family/c-cppbuiltin.c
@@ -1111,6 +1111,8 @@ c_cpp_builtins (cpp_reader *pfile)
       if (cxx_dialect >= cxx11 && strcmp (thread_model, "single") != 0)
 	cpp_define (pfile, "__STDCPP_THREADS__=1");
 #endif
+      if (flag_implicit_constexpr)
+	cpp_define (pfile, "__cpp_implicit_constexpr=20211111L");
     }
   /* Note that we define this for C as well, so that we know if
      __attribute__((cleanup)) will interface with EH.  */
diff --git a/gcc/c-family/c-opts.c b/gcc/c-family/c-opts.c
index 0225cba7a4b..62f58295c11 100644
--- a/gcc/c-family/c-opts.c
+++ b/gcc/c-family/c-opts.c
@@ -1052,6 +1052,9 @@ c_common_post_options (const char **pfilename)
       && flag_strong_eval_order == -1)
     flag_strong_eval_order = (cxx_dialect >= cxx17 ? 2 : 1);
 
+  if (flag_implicit_constexpr && cxx_dialect < cxx14)
+    flag_implicit_constexpr = false;
+
   /* Global sized deallocation is new in C++14.  */
   if (flag_sized_deallocation == -1)
     flag_sized_deallocation = (cxx_dialect >= cxx14);
diff --git a/gcc/cp/class.c b/gcc/cp/class.c
index bf92300a178..c30a44f039b 100644
--- a/gcc/cp/class.c
+++ b/gcc/cp/class.c
@@ -5547,10 +5547,16 @@ type_has_constexpr_destructor (tree t)
 static bool
 type_maybe_constexpr_destructor (tree t)
 {
+  /* Until C++20, only trivial destruction is constexpr.  */
+  if (TYPE_HAS_TRIVIAL_DESTRUCTOR (t))
+    return true;
+  if (cxx_dialect < cxx20)
+    return false;
   if (CLASS_TYPE_P (t) && CLASSTYPE_LAZY_DESTRUCTOR (t))
     /* Assume it's constexpr.  */
     return true;
-  return type_has_constexpr_destructor (t);
+  tree fn = CLASSTYPE_DESTRUCTOR (t);
+  return (fn && maybe_constexpr_fn (fn));
 }
 
 /* Returns true iff class TYPE has a virtual destructor.  */
@@ -5823,8 +5829,7 @@ finalize_literal_type_property (tree t)
   if (cxx_dialect < cxx11)
     CLASSTYPE_LITERAL_P (t) = false;
   else if (CLASSTYPE_LITERAL_P (t)
-	   && TYPE_HAS_NONTRIVIAL_DESTRUCTOR (t)
-	   && (cxx_dialect < cxx20 || !type_maybe_constexpr_destructor (t)))
+	   && !type_maybe_constexpr_destructor (t))
     CLASSTYPE_LITERAL_P (t) = false;
   else if (CLASSTYPE_LITERAL_P (t) && LAMBDA_TYPE_P (t))
     CLASSTYPE_LITERAL_P (t) = (cxx_dialect >= cxx17);
diff --git a/gcc/cp/constexpr.c b/gcc/cp/constexpr.c
index c92db5d413c..69d9d3daeca 100644
--- a/gcc/cp/constexpr.c
+++ b/gcc/cp/constexpr.c
@@ -37,6 +37,8 @@ along with GCC; see the file COPYING3.  If not see
 #include "stor-layout.h"
 #include "cgraph.h"
 #include "opts.h"
+#include "stringpool.h"
+#include "attribs.h"
 
 static bool verify_constant (tree, bool, bool *, bool *);
 #define VERIFY_CONSTANT(X)						\
@@ -220,6 +222,17 @@ is_valid_constexpr_fn (tree fun, bool complain)
 	inform (DECL_SOURCE_LOCATION (fun),
 		"lambdas are implicitly %<constexpr%> only in C++17 and later");
     }
+  else if (DECL_DESTRUCTOR_P (fun))
+    {
+      if (cxx_dialect < cxx20)
+	{
+	  ret = false;
+	  if (complain)
+	    error_at (DECL_SOURCE_LOCATION (fun),
+		      "%<constexpr%> destructors only available"
+		      " with %<-std=c++20%> or %<-std=gnu++20%>");
+	}
+    }
   else if (!DECL_CONSTRUCTOR_P (fun))
     {
       tree rettype = TREE_TYPE (TREE_TYPE (fun));
@@ -865,12 +878,31 @@ void
 maybe_save_constexpr_fundef (tree fun)
 {
   if (processing_template_decl
-      || !DECL_DECLARED_CONSTEXPR_P (fun)
       || cp_function_chain->invalid_constexpr
       || (DECL_CLONED_FUNCTION_P (fun) && !DECL_DELETING_DESTRUCTOR_P (fun)))
     return;
 
-  bool complain = !DECL_GENERATED_P (fun);
+  /* With -fimplicit-constexpr, try to make inlines constexpr.  We'll
+     actually set DECL_DECLARED_CONSTEXPR_P below if the checks pass.  */
+  bool implicit = false;
+  if (flag_implicit_constexpr)
+    {
+      if (DECL_DELETING_DESTRUCTOR_P (fun)
+	  && decl_implicit_constexpr_p (DECL_CLONED_FUNCTION (fun)))
+	/* Don't inherit implicit constexpr from the non-deleting
+	   destructor.  */
+	DECL_DECLARED_CONSTEXPR_P (fun) = false;
+
+      if (!DECL_DECLARED_CONSTEXPR_P (fun)
+	  && DECL_DECLARED_INLINE_P (fun)
+	  && !lookup_attribute ("noinline", DECL_ATTRIBUTES (fun)))
+	implicit = true;
+    }
+
+  if (!DECL_DECLARED_CONSTEXPR_P (fun) && !implicit)
+    return;
+
+  bool complain = !DECL_GENERATED_P (fun) && !implicit;
 
   if (!is_valid_constexpr_fn (fun, complain))
     return;
@@ -878,7 +910,7 @@ maybe_save_constexpr_fundef (tree fun)
   tree massaged = massage_constexpr_body (fun, DECL_SAVED_TREE (fun));
   if (massaged == NULL_TREE || massaged == error_mark_node)
     {
-      if (!DECL_CONSTRUCTOR_P (fun))
+      if (!DECL_CONSTRUCTOR_P (fun) && complain)
 	error ("body of %<constexpr%> function %qD not a return-statement",
 	       fun);
       return;
@@ -907,6 +939,21 @@ maybe_save_constexpr_fundef (tree fun)
   if (!potential && complain)
     return;
 
+  if (implicit)
+    {
+      if (potential)
+	{
+	  DECL_DECLARED_CONSTEXPR_P (fun) = true;
+	  DECL_LANG_SPECIFIC (fun)->u.fn.implicit_constexpr = true;
+	  if (DECL_CONSTRUCTOR_P (fun))
+	    TYPE_HAS_CONSTEXPR_CTOR (DECL_CONTEXT (fun)) = true;
+	}
+      else
+	/* Don't bother keeping the pre-generic body of unsuitable functions
+	   not explicitly declared constexpr.  */
+	return;
+    }
+
   constexpr_fundef entry = {fun, NULL_TREE, NULL_TREE, NULL_TREE};
   bool clear_ctx = false;
   if (DECL_RESULT (fun) && DECL_CONTEXT (DECL_RESULT (fun)) == NULL_TREE)
@@ -2404,7 +2451,7 @@ cxx_eval_call_expression (const constexpr_ctx *ctx, tree t,
 					   lval, non_constant_p, overflow_p);
   if (DECL_THUNK_P (fun))
     return cxx_eval_thunk_call (ctx, t, fun, lval, non_constant_p, overflow_p);
-  if (!DECL_DECLARED_CONSTEXPR_P (fun))
+  if (!maybe_constexpr_fn (fun))
     {
       if (TREE_CODE (t) == CALL_EXPR
 	  && cxx_replaceable_global_alloc_fn (fun)
@@ -5229,7 +5276,9 @@ bool
 maybe_constexpr_fn (tree t)
 {
   return (DECL_DECLARED_CONSTEXPR_P (t)
-	  || (cxx_dialect >= cxx17 && LAMBDA_FUNCTION_P (t)));
+	  || (cxx_dialect >= cxx17 && LAMBDA_FUNCTION_P (t))
+	  || (flag_implicit_constexpr
+	      && DECL_DECLARED_INLINE_P (STRIP_TEMPLATE (t))));
 }
 
 /* True if T was declared in a function that might be constexpr: either a
@@ -5238,11 +5287,8 @@ maybe_constexpr_fn (tree t)
 bool
 var_in_maybe_constexpr_fn (tree t)
 {
-  if (cxx_dialect >= cxx17
-      && DECL_FUNCTION_SCOPE_P (t)
-      && LAMBDA_FUNCTION_P (DECL_CONTEXT (t)))
-    return true;
-  return var_in_constexpr_fn (t);
+  return (DECL_FUNCTION_SCOPE_P (t)
+	  && maybe_constexpr_fn (DECL_CONTEXT (t)));
 }
 
 /* We're assigning INIT to TARGET.  In do_build_copy_constructor and
@@ -8219,7 +8265,7 @@ potential_constant_expression_1 (tree t, bool want_rval, bool strict, bool now,
 	      {
 		if (builtin_valid_in_constant_expr_p (fun))
 		  return true;
-		if (!DECL_DECLARED_CONSTEXPR_P (fun)
+		if (!maybe_constexpr_fn (fun)
 		    /* Allow any built-in function; if the expansion
 		       isn't constant, we'll deal with that then.  */
 		    && !fndecl_built_in_p (fun)
@@ -9257,6 +9303,23 @@ is_nondependent_static_init_expression (tree t)
 	  && !instantiation_dependent_expression_p (t));
 }
 
+/* True iff FN is an implicitly constexpr function.  */
+
+bool
+decl_implicit_constexpr_p (tree fn)
+{
+  if (!(flag_implicit_constexpr
+	&& TREE_CODE (fn) == FUNCTION_DECL
+	&& DECL_DECLARED_CONSTEXPR_P (fn)))
+    return false;
+
+  if (DECL_CLONED_FUNCTION_P (fn))
+    fn = DECL_CLONED_FUNCTION (fn);
+
+  return (DECL_LANG_SPECIFIC (fn)
+	  && DECL_LANG_SPECIFIC (fn)->u.fn.implicit_constexpr);
+}
+
 /* Finalize constexpr processing after parsing.  */
 
 void
diff --git a/gcc/cp/decl.c b/gcc/cp/decl.c
index eed478199ea..2ddf0e4a524 100644
--- a/gcc/cp/decl.c
+++ b/gcc/cp/decl.c
@@ -1290,6 +1290,12 @@ validate_constexpr_redeclaration (tree old_decl, tree new_decl)
     }
   if (TREE_CODE (old_decl) == FUNCTION_DECL)
     {
+      /* With -fimplicit-constexpr, ignore changes in the constexpr
+	 keyword.  */
+      if (flag_implicit_constexpr
+	  && (DECL_IMMEDIATE_FUNCTION_P (new_decl)
+	      == DECL_IMMEDIATE_FUNCTION_P (old_decl)))
+	return true;
       if (fndecl_built_in_p (old_decl))
 	{
 	  /* Hide a built-in declaration.  */
@@ -14863,7 +14869,7 @@ grok_special_member_properties (tree decl)
       if (is_list_ctor (decl))
 	TYPE_HAS_LIST_CTOR (class_type) = 1;
 
-      if (DECL_DECLARED_CONSTEXPR_P (decl)
+      if (maybe_constexpr_fn (decl)
 	  && !ctor && !move_fn_p (decl))
 	TYPE_HAS_CONSTEXPR_CTOR (class_type) = 1;
     }
diff --git a/gcc/cp/error.c b/gcc/cp/error.c
index 012a4ecddf4..872479369ab 100644
--- a/gcc/cp/error.c
+++ b/gcc/cp/error.c
@@ -1686,7 +1686,8 @@ dump_function_decl (cxx_pretty_printer *pp, tree t, int flags)
   exceptions = TYPE_RAISES_EXCEPTIONS (TREE_TYPE (t));
 
   /* Likewise for the constexpr specifier, in case t is a specialization.  */
-  constexpr_p = DECL_DECLARED_CONSTEXPR_P (t);
+  constexpr_p = (DECL_DECLARED_CONSTEXPR_P (t)
+		 && !decl_implicit_constexpr_p (t));
 
   /* Pretty print template instantiations only.  */
   if (DECL_USE_TEMPLATE (t) && DECL_TEMPLATE_INFO (t)
diff --git a/gcc/testsuite/g++.dg/abi/abi-tag16.C b/gcc/testsuite/g++.dg/abi/abi-tag16.C
index d4fa142762a..3027d7906f5 100644
--- a/gcc/testsuite/g++.dg/abi/abi-tag16.C
+++ b/gcc/testsuite/g++.dg/abi/abi-tag16.C
@@ -1,4 +1,4 @@
-// { dg-options -Wabi=9 }
+// { dg-options "-Wabi=9 -fno-implicit-constexpr" }
 // { dg-final { scan-assembler "_ZGVZN1N1FEvE4NameB5cxx11" } }
 namespace std {
   __extension__ inline namespace __cxx11 __attribute__((abi_tag("cxx11"))) {
diff --git a/gcc/testsuite/g++.dg/abi/abi-tag18a.C b/gcc/testsuite/g++.dg/abi/abi-tag18a.C
index 95e192ae6f4..c6fb1607a41 100644
--- a/gcc/testsuite/g++.dg/abi/abi-tag18a.C
+++ b/gcc/testsuite/g++.dg/abi/abi-tag18a.C
@@ -1,5 +1,5 @@
 // { dg-skip-if "PR 70349" { hppa*-*-hpux* && { ! lp64 } } }
-// { dg-options -fabi-version=9 }
+// { dg-options "-fabi-version=9 -fno-implicit-constexpr" }
 // { dg-final { scan-assembler "_Z1fB7__test1v" } }
 // { dg-final { scan-assembler "_ZZ1fB7__test1vEN1T1gB7__test2Ev" } }
 // { dg-final { scan-assembler "_ZZZ1fB7__test1vEN1T1gEvE1x" } }
diff --git a/gcc/testsuite/g++.dg/abi/guard4.C b/gcc/testsuite/g++.dg/abi/guard4.C
index 537c90524f3..71e6744e381 100644
--- a/gcc/testsuite/g++.dg/abi/guard4.C
+++ b/gcc/testsuite/g++.dg/abi/guard4.C
@@ -3,9 +3,10 @@
 
 namespace x {
   struct s {
-    s() {}
+    s();
     static int a;
   };
+  s::s() {}
   // { dg-final { scan-assembler {.weak[^\n]*_ZGVN1x1bE} } }
   struct s __attribute__((weak)) b = s();
 }
diff --git a/gcc/testsuite/g++.dg/abi/lambda-defarg1.C b/gcc/testsuite/g++.dg/abi/lambda-defarg1.C
index 8c538581240..79e4fa64ac5 100644
--- a/gcc/testsuite/g++.dg/abi/lambda-defarg1.C
+++ b/gcc/testsuite/g++.dg/abi/lambda-defarg1.C
@@ -1,5 +1,6 @@
 // PR c++/91241
 // { dg-do compile { target c++11 } }
+// { dg-additional-options -fkeep-inline-functions }
 
 struct A {
   int *b(const int & = []() -> int { return 0; }(),
diff --git a/gcc/testsuite/g++.dg/cpp0x/constexpr-diag3.C b/gcc/testsuite/g++.dg/cpp0x/constexpr-diag3.C
index 1c43569615c..c167bb1d8bc 100644
--- a/gcc/testsuite/g++.dg/cpp0x/constexpr-diag3.C
+++ b/gcc/testsuite/g++.dg/cpp0x/constexpr-diag3.C
@@ -13,7 +13,7 @@ int main()
 
 // --------------------
 
-struct complex 			// { dg-message "no .constexpr. constructor" }
+struct complex 			// { dg-message "no .constexpr. constructor" "" { target { ! implicit_constexpr } } }
 {
   complex(double r, double i) : re(r), im(i) { }
   constexpr double real() const { return re; } // { dg-error "not a literal type" "" { target c++11_only } }
@@ -24,23 +24,23 @@ private:
   double im;
 };
 
-constexpr complex co1(0, 1);	   // { dg-error "19:the type .const complex. of .constexpr. variable .co1. is not literal" }
-constexpr double dd2 = co1.real(); // { dg-error "|in .constexpr. expansion of " }
+constexpr complex co1(0, 1);	   // { dg-error "19:the type .const complex. of .constexpr. variable .co1. is not literal" "" { target { ! implicit_constexpr } } }
+constexpr double dd2 = co1.real(); // { dg-error "|in .constexpr. expansion of " "" { target { ! implicit_constexpr } } }
 
 // --------------------
 
-struct base		       // { dg-message "no .constexpr. constructor" }
+struct base		       // { dg-message "no .constexpr. constructor" "" { target { ! implicit_constexpr } } }
 {
   int _M_i;
   base() : _M_i(5) { }
 };
 
-struct derived : public base	// { dg-message "base class" }
+struct derived : public base	// { dg-message "base class" "" { target { ! implicit_constexpr } } }
 {
-  constexpr derived(): base() { } // { dg-error "non-.constexpr. function" }
+  constexpr derived(): base() { } // { dg-error "non-.constexpr. function" "" { target { ! implicit_constexpr } } }
 };
 
-constexpr derived obj;		// { dg-error "not literal" }
+constexpr derived obj;		// { dg-error "not literal" "" { target { ! implicit_constexpr } } }
 
 // --------------------
 
diff --git a/gcc/testsuite/g++.dg/cpp0x/constexpr-ex1.C b/gcc/testsuite/g++.dg/cpp0x/constexpr-ex1.C
index e5e58bddab0..1d5c58b4090 100644
--- a/gcc/testsuite/g++.dg/cpp0x/constexpr-ex1.C
+++ b/gcc/testsuite/g++.dg/cpp0x/constexpr-ex1.C
@@ -87,7 +87,7 @@ struct resource {
   }
 };
 constexpr resource f(resource d)
-{ return d; }                  // { dg-error "non-.constexpr." }
-constexpr resource d = f(9);   // { dg-message ".constexpr." }
+{ return d; }                  // { dg-error "non-.constexpr." "" { target { ! implicit_constexpr } } }
+constexpr resource d = f(9);   // { dg-message ".constexpr." "" { target { ! implicit_constexpr } } }
 
 // 4.4 floating-point constant expressions
diff --git a/gcc/testsuite/g++.dg/cpp0x/constexpr-ice5.C b/gcc/testsuite/g++.dg/cpp0x/constexpr-ice5.C
index 51b328e2598..e934421c2f4 100644
--- a/gcc/testsuite/g++.dg/cpp0x/constexpr-ice5.C
+++ b/gcc/testsuite/g++.dg/cpp0x/constexpr-ice5.C
@@ -9,5 +9,5 @@ struct A
 struct B
 {
   A a[1];
-  constexpr B() : a() {} // { dg-error "non-constant|non-.constexpr." }
+  constexpr B() : a() {} // { dg-error "non-constant|non-.constexpr." "" { target { ! implicit_constexpr } } }
 };
diff --git a/gcc/testsuite/g++.dg/cpp0x/constexpr-incomplete2.C b/gcc/testsuite/g++.dg/cpp0x/constexpr-incomplete2.C
index a04f1d51d22..c018eded1de 100644
--- a/gcc/testsuite/g++.dg/cpp0x/constexpr-incomplete2.C
+++ b/gcc/testsuite/g++.dg/cpp0x/constexpr-incomplete2.C
@@ -28,4 +28,4 @@ struct D
   C<D> c;
 };
 
-constexpr D d {};		// { dg-error "non-.constexpr. function" }
+constexpr D d {};		// { dg-error "non-.constexpr. function" "" { target { ! implicit_constexpr } } }
diff --git a/gcc/testsuite/g++.dg/cpp0x/constexpr-memfn1.C b/gcc/testsuite/g++.dg/cpp0x/constexpr-memfn1.C
index d58e2ec6b15..37255282ded 100644
--- a/gcc/testsuite/g++.dg/cpp0x/constexpr-memfn1.C
+++ b/gcc/testsuite/g++.dg/cpp0x/constexpr-memfn1.C
@@ -13,6 +13,6 @@ constexpr X X::g(X x) { return x; }
 struct Y
 {
   Y() { }
-  constexpr Y f(Y y) { return y; }  // { dg-error "constexpr" }
-  static constexpr Y g(Y y) { return y; } // { dg-error "constexpr" }
+  constexpr Y f(Y y) { return y; }  // { dg-error "constexpr" "" { target { ! implicit_constexpr } } }
+  static constexpr Y g(Y y) { return y; } // { dg-error "constexpr" "" { target { ! implicit_constexpr } } }
 };
diff --git a/gcc/testsuite/g++.dg/cpp0x/constexpr-neg3.C b/gcc/testsuite/g++.dg/cpp0x/constexpr-neg3.C
index 55bb838a2bf..89559d76058 100644
--- a/gcc/testsuite/g++.dg/cpp0x/constexpr-neg3.C
+++ b/gcc/testsuite/g++.dg/cpp0x/constexpr-neg3.C
@@ -9,7 +9,7 @@ struct A
 template<typename> struct B
 {
   A a;
-  constexpr int bar() { return a.foo(); } // { dg-error "foo" }
+  constexpr int bar() { return a.foo(); } // { dg-error "foo" "" { target { ! implicit_constexpr } } }
 };
 
-constexpr int i = B<void>().bar(); // { dg-error "bar" }
+constexpr int i = B<void>().bar(); // { dg-error "bar" "" { target { ! implicit_constexpr } } }
diff --git a/gcc/testsuite/g++.dg/cpp0x/constexpr-specialization.C b/gcc/testsuite/g++.dg/cpp0x/constexpr-specialization.C
index 64d8f4ec266..acda6e0bcbf 100644
--- a/gcc/testsuite/g++.dg/cpp0x/constexpr-specialization.C
+++ b/gcc/testsuite/g++.dg/cpp0x/constexpr-specialization.C
@@ -3,10 +3,10 @@
 
 template<typename T> constexpr int foo(T);
 template<> int foo(int);
-template<> int foo(int);            // { dg-message "previous declaration 'int foo" }
-template<> constexpr int foo(int);  // { dg-error "redeclaration 'constexpr int foo" }
+template<> int foo(int);            // { dg-message "previous declaration 'int foo" "" { target { ! implicit_constexpr } } }
+template<> constexpr int foo(int);  // { dg-error "redeclaration 'constexpr int foo" "" { target { ! implicit_constexpr } } }
 
 template<typename T> int bar(T);
 template<> constexpr int bar(int);
-template<> constexpr int bar(int);  // { dg-message "previous declaration 'constexpr int bar" }
-template<> int bar(int);            // { dg-error "redeclaration 'int bar" }
+template<> constexpr int bar(int);  // { dg-message "previous declaration 'constexpr int bar" "" { target { ! implicit_constexpr } } }
+template<> int bar(int);            // { dg-error "redeclaration 'int bar" "" { target { ! implicit_constexpr } } }
diff --git a/gcc/testsuite/g++.dg/cpp0x/inh-ctor19.C b/gcc/testsuite/g++.dg/cpp0x/inh-ctor19.C
index 7e2d58b422e..3476f9607ac 100644
--- a/gcc/testsuite/g++.dg/cpp0x/inh-ctor19.C
+++ b/gcc/testsuite/g++.dg/cpp0x/inh-ctor19.C
@@ -11,4 +11,4 @@ struct B : A
   using A::A;
 };
 
-constexpr B b;  // { dg-error "literal" }
+constexpr B b;  // { dg-error "literal" "" { target { ! implicit_constexpr } } }
diff --git a/gcc/testsuite/g++.dg/cpp0x/inh-ctor30.C b/gcc/testsuite/g++.dg/cpp0x/inh-ctor30.C
index 04c58636d8d..c8161d3d3e3 100644
--- a/gcc/testsuite/g++.dg/cpp0x/inh-ctor30.C
+++ b/gcc/testsuite/g++.dg/cpp0x/inh-ctor30.C
@@ -1,6 +1,7 @@
 // PR c++/81860
 // { dg-do compile { target c++11 } }
 // { dg-final { scan-assembler "_ZN1AIjEC\[12\]Ev" } }
+// { dg-additional-options -fno-inline }
 
 template <typename T>
 struct A
diff --git a/gcc/testsuite/g++.dg/cpp0x/lambda/lambda-mangle3.C b/gcc/testsuite/g++.dg/cpp0x/lambda/lambda-mangle3.C
index 5f17a21cac4..286a4cf23df 100644
--- a/gcc/testsuite/g++.dg/cpp0x/lambda/lambda-mangle3.C
+++ b/gcc/testsuite/g++.dg/cpp0x/lambda/lambda-mangle3.C
@@ -1,6 +1,7 @@
 // PR c++/51818
 // { dg-do compile { target c++11 } }
 // { dg-final { scan-assembler "_ZN1AC1IN3foo3barMUlvE_EEET_" } }
+// { dg-additional-options -fno-inline }
 
 struct A
 {
diff --git a/gcc/testsuite/g++.dg/cpp0x/lambda/lambda-mangle5.C b/gcc/testsuite/g++.dg/cpp0x/lambda/lambda-mangle5.C
index dd95894755c..23df3a2b416 100644
--- a/gcc/testsuite/g++.dg/cpp0x/lambda/lambda-mangle5.C
+++ b/gcc/testsuite/g++.dg/cpp0x/lambda/lambda-mangle5.C
@@ -1,4 +1,5 @@
 // { dg-do compile { target c++11 } }
+// { dg-additional-options -fkeep-inline-functions }
 // { dg-final { scan-assembler "_ZZN1AIiEC4IiEET_S2_Ed_NKUlvE_clEv" } }
 
 template <class T> struct A
diff --git a/gcc/testsuite/g++.dg/cpp1y/auto-fn12.C b/gcc/testsuite/g++.dg/cpp1y/auto-fn12.C
index 224f2789bcd..98885799de9 100644
--- a/gcc/testsuite/g++.dg/cpp1y/auto-fn12.C
+++ b/gcc/testsuite/g++.dg/cpp1y/auto-fn12.C
@@ -1,5 +1,6 @@
 // { dg-do compile { target c++14 } }
 // { dg-final { scan-assembler "_ZN1AIiEcvDaEv" } }
+// { dg-additional-options -fno-implicit-constexpr }
 
 template <class T>
 struct A {
diff --git a/gcc/testsuite/g++.dg/cpp1y/constexpr-loop5.C b/gcc/testsuite/g++.dg/cpp1y/constexpr-loop5.C
index 02f372d9888..150aadfe609 100644
--- a/gcc/testsuite/g++.dg/cpp1y/constexpr-loop5.C
+++ b/gcc/testsuite/g++.dg/cpp1y/constexpr-loop5.C
@@ -9,11 +9,11 @@ template<typename>
 constexpr int count()
 {
     auto item = thing {};
-    for(; (item.foo(), false);); // { dg-error "foo" }
+    for(; (item.foo(), false);); // { dg-error "foo" "" { target { ! implicit_constexpr } } }
     return 0;
 }
 
 int main()
 {
-    static_assert( count<int>() == 0, "" ); // { dg-error "" }
+    static_assert( count<int>() == 0, "" ); // { dg-error "" "" { target { ! implicit_constexpr } } }
 }
diff --git a/gcc/testsuite/g++.dg/cpp1z/constexpr-lambda7.C b/gcc/testsuite/g++.dg/cpp1z/constexpr-lambda7.C
index 474ce88f81f..faac00ca997 100644
--- a/gcc/testsuite/g++.dg/cpp1z/constexpr-lambda7.C
+++ b/gcc/testsuite/g++.dg/cpp1z/constexpr-lambda7.C
@@ -8,5 +8,5 @@ struct NonLiteral {
   int n;
 };
 
-static_assert( ID (NonLiteral{3}).n == 3); // { dg-error "non-literal" }
+static_assert( ID (NonLiteral{3}).n == 3); // { dg-error "non-literal" "" { target { ! implicit_constexpr } } }
 // { dg-prune-output "static assertion" }
diff --git a/gcc/testsuite/g++.dg/cpp2a/constexpr-dtor3.C b/gcc/testsuite/g++.dg/cpp2a/constexpr-dtor3.C
index 69fe9e26654..a68a6b4af8b 100644
--- a/gcc/testsuite/g++.dg/cpp2a/constexpr-dtor3.C
+++ b/gcc/testsuite/g++.dg/cpp2a/constexpr-dtor3.C
@@ -7,16 +7,16 @@ struct S
   constexpr ~S () {}
   int s;
 };
-struct T	// { dg-message "'T' is not literal because" }
-{		// { dg-message "'T' does not have 'constexpr' destructor" "" { target *-*-* } .-1 }
+struct T	// { dg-message "'T' is not literal because" "" { target { ! implicit_constexpr } } }
+{		// { dg-message "'T' does not have 'constexpr' destructor" "" { target { ! implicit_constexpr } } .-1 }
   constexpr T () : t (0) {}
-  ~T () {}	// { dg-message "defaulted destructor calls non-'constexpr' 'T::~T\\(\\)'" }
+  ~T () {}	// { dg-message "defaulted destructor calls non-'constexpr' 'T::~T\\(\\)'" "" { target { ! implicit_constexpr } } }
   int t;
 };
 struct U : public S
 {
   constexpr U () : u (0) {}
-  constexpr ~U () = default;	// { dg-error "explicitly defaulted function 'constexpr U::~U\\(\\)' cannot be declared 'constexpr' because the implicit declaration is not 'constexpr'" }
+  constexpr ~U () = default;	// { dg-error "explicitly defaulted function 'constexpr U::~U\\(\\)' cannot be declared 'constexpr' because the implicit declaration is not 'constexpr'" "" { target { ! implicit_constexpr } } }
   int u;
   T t;
 };
@@ -100,11 +100,11 @@ struct W8
 struct X : public T
 {
   constexpr X () : x (0) {}
-  constexpr ~X () = default;	// { dg-error "explicitly defaulted function 'constexpr X::~X\\(\\)' cannot be declared 'constexpr' because the implicit declaration is not 'constexpr'" }
+  constexpr ~X () = default;	// { dg-error "explicitly defaulted function 'constexpr X::~X\\(\\)' cannot be declared 'constexpr' because the implicit declaration is not 'constexpr'" "" { target { ! implicit_constexpr } } }
   int x;
 };
 constexpr S s;
-constexpr T t;	// { dg-error "the type 'const T' of 'constexpr' variable 't' is not literal" }
+constexpr T t;	// { dg-error "the type 'const T' of 'constexpr' variable 't' is not literal" "" { target { ! implicit_constexpr } } }
 constexpr W0 w1;
 constexpr W0 w2 = 12;
 constexpr W1 w3 = 5;	// { dg-message "in 'constexpr' expansion of" }
@@ -167,19 +167,19 @@ constexpr int x5 = f5 ();	// { dg-message "in 'constexpr' expansion of" }
 void
 f6 ()
 {
-  constexpr T t2;	// { dg-error "the type 'const T' of 'constexpr' variable 't2' is not literal" }
+  constexpr T t2;	// { dg-error "the type 'const T' of 'constexpr' variable 't2' is not literal" "" { target { ! implicit_constexpr } } }
 }
 
 constexpr int
 f7 ()
 {
-  constexpr T t3;	// { dg-error "the type 'const T' of 'constexpr' variable 't3' is not literal" }
+  constexpr T t3;	// { dg-error "the type 'const T' of 'constexpr' variable 't3' is not literal" "" { target { ! implicit_constexpr } } }
   return 0;
 }
 
 constexpr int
 f8 ()
 {
-  T t4;			// { dg-error "variable 't4' of non-literal type 'T' in 'constexpr' function only available with" "" { target c++20_down } }
+  T t4;			// { dg-error "variable 't4' of non-literal type 'T' in 'constexpr' function only available with" "" { target { c++20_down && { ! implicit_constexpr } } } }
   return 0;
 }
diff --git a/gcc/testsuite/g++.dg/cpp2a/constexpr-new13.C b/gcc/testsuite/g++.dg/cpp2a/constexpr-new13.C
index 6762c24a342..7eed50c7f4c 100644
--- a/gcc/testsuite/g++.dg/cpp2a/constexpr-new13.C
+++ b/gcc/testsuite/g++.dg/cpp2a/constexpr-new13.C
@@ -9,7 +9,7 @@ struct A {
 
 struct B : A {
   constexpr B () : b (0) {}
-  virtual int foo () { return 0 + b * 4; }	// { dg-message "declared here" }
+  virtual int foo () { return 0 + b * 4; }	// { dg-message "declared here" "" { target { ! implicit_constexpr } } }
   int b;
 };
 
@@ -18,7 +18,7 @@ foo ()
 {
   A *a = new B ();
   a->a = 4;
-  int r = a->foo ();	// { dg-error "call to non-.constexpr. function" }
+  int r = a->foo ();	// { dg-error "call to non-.constexpr. function" "" { target { ! implicit_constexpr } } }
   delete a;
   return r;
 }
diff --git a/gcc/testsuite/g++.dg/cpp2a/constinit11.C b/gcc/testsuite/g++.dg/cpp2a/constinit11.C
index e8b3bcb570b..b0902771814 100644
--- a/gcc/testsuite/g++.dg/cpp2a/constinit11.C
+++ b/gcc/testsuite/g++.dg/cpp2a/constinit11.C
@@ -39,9 +39,9 @@ constinit thread_local const int &r2 = gl;
 constinit const int &r3 // { dg-error "variable .r3. does not have a constant initializer" }
   = foo (); // { dg-error "call to non-.constexpr. function" }
 constinit const literal &r4 = 42;
-constinit const nonliteral &r5 // { dg-error "variable .r5. does not have a constant initializer" }
-  = 42; // { dg-error "call to non-.constexpr. function" }
-constinit const int &r6 = nonliteral(2).m; // { dg-error "variable .r6. does not have a constant initializer|call to non-.constexpr. function" }
+constinit const nonliteral &r5 // { dg-error "variable .r5. does not have a constant initializer" "" { target { ! implicit_constexpr } } }
+  = 42; // { dg-error "call to non-.constexpr. function" "" { target { ! implicit_constexpr } } }
+constinit const int &r6 = nonliteral(2).m; // { dg-error "variable .r6. does not have a constant initializer|call to non-.constexpr. function" "" { target { ! implicit_constexpr } } }
 
 constinit pod p1;
 constinit pod p2 = { 42 };
@@ -64,8 +64,8 @@ constinit thread_local literal l11{};
 pod S::p;
 constinit pod S::pc(S::p); // { dg-error "variable .S::pc. does not have a constant initializer|not usable" }
 
-constinit const nonliteral S::n(42); // { dg-error "variable .S::n. does not have a constant initializer|call to non-.constexpr. function" }
-constinit int n1 = nonliteral{42}.m; // { dg-error "variable .n1. does not have a constant initializer|temporary of non-literal type" }
+constinit const nonliteral S::n(42); // { dg-error "variable .S::n. does not have a constant initializer|call to non-.constexpr. function" "" { target { ! implicit_constexpr } } }
+constinit int n1 = nonliteral{42}.m; // { dg-error "variable .n1. does not have a constant initializer|temporary of non-literal type" "" { target { ! implicit_constexpr } } }
 constinit int n2 = literal{42}.m;
 
 void
diff --git a/gcc/testsuite/g++.dg/cpp2a/constinit12.C b/gcc/testsuite/g++.dg/cpp2a/constinit12.C
index cc6569b2277..faa1b430cee 100644
--- a/gcc/testsuite/g++.dg/cpp2a/constinit12.C
+++ b/gcc/testsuite/g++.dg/cpp2a/constinit12.C
@@ -8,7 +8,7 @@ struct S {
 template <class T>
 struct U {
   T m;
-  constexpr U(int i) : m(i) { } // { dg-error "call to non-.constexpr. function" }
+  constexpr U(int i) : m(i) { } // { dg-error "call to non-.constexpr. function" "" { target { ! implicit_constexpr } } }
 };
 
-constinit U<S> u(42); // { dg-error "does not have a constant initializer|called in a constant expression" }
+constinit U<S> u(42); // { dg-error "does not have a constant initializer|called in a constant expression" "" { target { ! implicit_constexpr } } }
diff --git a/gcc/testsuite/g++.dg/cpp2a/constinit14.C b/gcc/testsuite/g++.dg/cpp2a/constinit14.C
index 86a058b632c..06c4cb46722 100644
--- a/gcc/testsuite/g++.dg/cpp2a/constinit14.C
+++ b/gcc/testsuite/g++.dg/cpp2a/constinit14.C
@@ -2,7 +2,7 @@
 // { dg-do compile { target c++20 } }
 
 struct Value {
-  Value() : v{new int{42}} {}
+  Value() : v{new int{42}} {}	// { dg-error "result of 'operator new'" "" { target implicit_constexpr } }
   int* v;
 };
 
diff --git a/gcc/testsuite/g++.dg/cpp2a/constinit15.C b/gcc/testsuite/g++.dg/cpp2a/constinit15.C
index 29e8b51326d..b6215587bad 100644
--- a/gcc/testsuite/g++.dg/cpp2a/constinit15.C
+++ b/gcc/testsuite/g++.dg/cpp2a/constinit15.C
@@ -6,7 +6,7 @@ struct B {
 };
 
 struct A {
-    constinit static inline B b1{}; // { dg-error "does not have a constant initializer|call to non-.constexpr. function" }
+    constinit static inline B b1{}; // { dg-error "does not have a constant initializer|call to non-.constexpr. function" "" { target { ! implicit_constexpr } } }
 };
 
 int main() {
diff --git a/gcc/testsuite/g++.dg/cpp2a/spaceship-constexpr1.C b/gcc/testsuite/g++.dg/cpp2a/spaceship-constexpr1.C
index 6ccc7e8507b..dff59271a1e 100644
--- a/gcc/testsuite/g++.dg/cpp2a/spaceship-constexpr1.C
+++ b/gcc/testsuite/g++.dg/cpp2a/spaceship-constexpr1.C
@@ -9,7 +9,7 @@ struct A
 struct B
 {
   A a;
-  bool operator==(const B&) const = default; // { dg-error "A::operator==" }
+  bool operator==(const B&) const = default; // { dg-error "A::operator==" "" { target { ! implicit_constexpr } } }
 };
 
-constexpr bool x = B() == B();	// { dg-error "non-.constexpr" }
+constexpr bool x = B() == B();	// { dg-error "non-.constexpr" "" { target { ! implicit_constexpr } } }
diff --git a/gcc/testsuite/g++.dg/cpp2a/spaceship-eq3.C b/gcc/testsuite/g++.dg/cpp2a/spaceship-eq3.C
index d31faef095d..7a517a8016c 100644
--- a/gcc/testsuite/g++.dg/cpp2a/spaceship-eq3.C
+++ b/gcc/testsuite/g++.dg/cpp2a/spaceship-eq3.C
@@ -12,5 +12,5 @@ struct D
 };
 
 constexpr D d{A()};
-static_assert (d == d);		// { dg-error "non-constant|constexpr" }
-static_assert (!(d != d));	// { dg-error "non-constant|constexpr" }
+static_assert (d == d);		// { dg-error "constant|constexpr" }
+static_assert (!(d != d));	// { dg-error "constant|constexpr" }
diff --git a/gcc/testsuite/g++.dg/cpp2a/udlit-class-nttp-neg2.C b/gcc/testsuite/g++.dg/cpp2a/udlit-class-nttp-neg2.C
index 62cb86ae695..ab7c012f5f4 100644
--- a/gcc/testsuite/g++.dg/cpp2a/udlit-class-nttp-neg2.C
+++ b/gcc/testsuite/g++.dg/cpp2a/udlit-class-nttp-neg2.C
@@ -9,5 +9,5 @@ struct non_literal_class {
   // auto operator<=> (const non_literal_fixed_string&) = default;
 };
 
-template <non_literal_class> // { dg-error "11:is not a valid type for a template non-type parameter because it is not structural" }
-int operator"" _udl();       // { dg-error "5:literal operator template .int operator\"\"_udl\\(\\). has invalid parameter list" }
+template <non_literal_class> // { dg-error "11:is not a valid type for a template non-type parameter because it is not structural" "" { target { ! implicit_constexpr } } }
+int operator"" _udl();       // { dg-error "5:literal operator template .int operator\"\"_udl\\(\\). has invalid parameter list" "" { target { ! implicit_constexpr } } }
diff --git a/gcc/testsuite/g++.dg/debug/dwarf2/auto1.C b/gcc/testsuite/g++.dg/debug/dwarf2/auto1.C
index 5daf3cd5c87..3e5867d258c 100644
--- a/gcc/testsuite/g++.dg/debug/dwarf2/auto1.C
+++ b/gcc/testsuite/g++.dg/debug/dwarf2/auto1.C
@@ -1,6 +1,6 @@
 // PR c++/53756
 // { dg-do compile { target c++14 } }
-// { dg-options "-gdwarf-2 -dA -fno-debug-types-section" }
+// { dg-options "-gdwarf-2 -dA -fno-debug-types-section -fno-inline" }
 // We're looking for something like
 
 // .uleb128 0x3    # (DIE (0x33) DW_TAG_subprogram)
diff --git a/gcc/testsuite/g++.dg/debug/dwarf2/cdtor-1.C b/gcc/testsuite/g++.dg/debug/dwarf2/cdtor-1.C
index c0d3d225187..4605b927001 100644
--- a/gcc/testsuite/g++.dg/debug/dwarf2/cdtor-1.C
+++ b/gcc/testsuite/g++.dg/debug/dwarf2/cdtor-1.C
@@ -1,5 +1,5 @@
 // origin PR debug/49047
-// { dg-options "-gdwarf-2 -dA -fno-merge-debug-strings" }
+// { dg-options "-gdwarf-2 -dA -fno-merge-debug-strings -fno-inline" }
 // { dg-do compile }
 
 struct K
diff --git a/gcc/testsuite/g++.dg/debug/dwarf2/lambda1.C b/gcc/testsuite/g++.dg/debug/dwarf2/lambda1.C
index bd3ce5dc807..b2566c7aa7a 100644
--- a/gcc/testsuite/g++.dg/debug/dwarf2/lambda1.C
+++ b/gcc/testsuite/g++.dg/debug/dwarf2/lambda1.C
@@ -1,6 +1,6 @@
 // PR c++/43912
 // { dg-do compile { target c++11 } }
-// { dg-options "-gdwarf-2 -dA -fno-merge-debug-strings -gno-strict-dwarf" }
+// { dg-options "-gdwarf-2 -dA -fno-merge-debug-strings -gno-strict-dwarf -fno-inline" }
 
 // Check for the local alias variables that point to the members of the closure.
 // { dg-final { scan-assembler-times "DW_TAG_variable\[^.\]*\.ascii \"j.0\"" 4 { xfail { powerpc-ibm-aix* } } } }
diff --git a/gcc/testsuite/g++.dg/debug/dwarf2/pr54508.C b/gcc/testsuite/g++.dg/debug/dwarf2/pr54508.C
index e7a6aa41c0d..0a3721ee6b1 100644
--- a/gcc/testsuite/g++.dg/debug/dwarf2/pr54508.C
+++ b/gcc/testsuite/g++.dg/debug/dwarf2/pr54508.C
@@ -1,6 +1,6 @@
 // PR debug/54508
 // { dg-do compile }
-// { dg-options "-gdwarf-2 -g2 -dA -fno-merge-debug-strings" }
+// { dg-options "-gdwarf-2 -g2 -dA -fno-merge-debug-strings -fno-inline" }
 
 // { dg-final { scan-assembler "\"cbase\\\\0\"\[ \t\]+\[#;/!|@\]+ +DW_AT_name" } }
 // { dg-final { scan-assembler "\"OPCODE\\\\0\"\[ \t\]+\[#;/!|@\]+ +DW_AT_name" } }
diff --git a/gcc/testsuite/g++.dg/debug/dwarf2/pubnames-2.C b/gcc/testsuite/g++.dg/debug/dwarf2/pubnames-2.C
index af0f6f1b95c..1fb5004df40 100644
--- a/gcc/testsuite/g++.dg/debug/dwarf2/pubnames-2.C
+++ b/gcc/testsuite/g++.dg/debug/dwarf2/pubnames-2.C
@@ -1,6 +1,6 @@
 // { dg-do compile { target c++11 } }
 // { dg-skip-if "" { powerpc-ibm-aix* } }
-// { dg-options "-gpubnames -gdwarf-4 -fno-debug-types-section -dA" }
+// { dg-options "-gpubnames -gdwarf-4 -fno-debug-types-section -dA -fno-inline" }
 // { dg-final { scan-assembler-times "\.section\[\t \]\[^\n\]*debug_pubnames" 1 } }
 // { dg-final { scan-assembler "\"\\(anonymous namespace\\)\\\\0\"+\[ \t\]+\[#;/|@!]+\[ \t\]+external name" } }
 // { dg-final { scan-assembler "\"one\\\\0\"+\[ \t\]+\[#;/|@!]+\[ \t\]+external name" } }
diff --git a/gcc/testsuite/g++.dg/debug/dwarf2/pubnames-3.C b/gcc/testsuite/g++.dg/debug/dwarf2/pubnames-3.C
index 63b870bc8e7..37e04fb6c97 100644
--- a/gcc/testsuite/g++.dg/debug/dwarf2/pubnames-3.C
+++ b/gcc/testsuite/g++.dg/debug/dwarf2/pubnames-3.C
@@ -1,6 +1,6 @@
 // { dg-do compile { target c++11 } }
 // { dg-skip-if "" { powerpc-ibm-aix* } }
-// { dg-options "-gpubnames -gdwarf-4 -fdebug-types-section -dA" }
+// { dg-options "-gpubnames -gdwarf-4 -fdebug-types-section -dA -fno-inline" }
 // { dg-final { scan-assembler-times "\.section\[\t \]\[^\n\]*debug_pubnames" 1 } }
 // { dg-final { scan-assembler "\"\\(anonymous namespace\\)\\\\0\"+\[ \t\]+\[#;/|@!]+\[ \t\]+external name" } }
 // { dg-final { scan-assembler "\"one\\\\0\"+\[ \t\]+\[#;/|@!]+\[ \t\]+external name" } }
diff --git a/gcc/testsuite/g++.dg/ext/is_literal_type3.C b/gcc/testsuite/g++.dg/ext/is_literal_type3.C
index 22d8494a2b4..4fede879a42 100644
--- a/gcc/testsuite/g++.dg/ext/is_literal_type3.C
+++ b/gcc/testsuite/g++.dg/ext/is_literal_type3.C
@@ -6,7 +6,11 @@ struct S {
   int n;
 };
 
+#if __cpp_implicit_constexpr
+static_assert(__is_literal_type(S), "");
+#else
 static_assert(!__is_literal_type(S), "");
+#endif
 
 #ifdef __cpp_constexpr_dynamic_alloc
 struct T {
diff --git a/gcc/testsuite/g++.dg/ext/visibility/template7.C b/gcc/testsuite/g++.dg/ext/visibility/template7.C
index 5197fb1c960..f1490fa3d32 100644
--- a/gcc/testsuite/g++.dg/ext/visibility/template7.C
+++ b/gcc/testsuite/g++.dg/ext/visibility/template7.C
@@ -1,6 +1,6 @@
 // PR c++/35688
 // { dg-require-visibility "" }
-// { dg-options "-fvisibility=hidden" }
+// { dg-options "-fvisibility=hidden -fno-inline" }
 
 // { dg-final { scan-hidden "_ZN1s6vectorI1AEC1Ev" } }
 // { dg-final { scan-hidden "_ZN1s3fooI1AEEvT_" } }
diff --git a/gcc/testsuite/g++.dg/gcov/gcov-12.C b/gcc/testsuite/g++.dg/gcov/gcov-12.C
index c4708e40726..9f2b29b4da5 100644
--- a/gcc/testsuite/g++.dg/gcov/gcov-12.C
+++ b/gcc/testsuite/g++.dg/gcov/gcov-12.C
@@ -1,5 +1,5 @@
 /* PR 51113 */
-/* { dg-options "-fprofile-arcs -ftest-coverage -fpic" } */
+/* { dg-options "-fprofile-arcs -ftest-coverage -fpic -fno-implicit-constexpr" } */
 /* { dg-do run { target native } } */
 /* { dg-additional-sources "gcovpart-12b.C" } */
 
diff --git a/gcc/testsuite/g++.dg/gcov/gcov-2.C b/gcc/testsuite/g++.dg/gcov/gcov-2.C
index 2b4cdd844e9..05db15de7cc 100644
--- a/gcc/testsuite/g++.dg/gcov/gcov-2.C
+++ b/gcc/testsuite/g++.dg/gcov/gcov-2.C
@@ -1,6 +1,6 @@
 /* Verify line coverage counts for simple member functions. */
 
-/* { dg-options "-fprofile-arcs -ftest-coverage" } */
+/* { dg-options "-fprofile-arcs -ftest-coverage -fno-implicit-constexpr" } */
 /* { dg-do run { target native } } */
 
 class C {
diff --git a/gcc/testsuite/g++.dg/ipa/devirt-35.C b/gcc/testsuite/g++.dg/ipa/devirt-35.C
index 87f72b89984..ca9ccb7a133 100644
--- a/gcc/testsuite/g++.dg/ipa/devirt-35.C
+++ b/gcc/testsuite/g++.dg/ipa/devirt-35.C
@@ -15,7 +15,6 @@ m(struct B *b)
                   //  test2 may change the type of A by placement new.
                   // C++ standard is bit imprecise about this.
 }
-/* { dg-final { scan-tree-dump "converting indirect call to function virtual int B::t"  "fre1"  } } */
-/* { dg-final { scan-ipa-dump "to virtual int B::t"  "devirt"  } } */
+/* { dg-final { scan-tree-dump "converting indirect call to function virtual int B::t"  "fre1" { target { ! implicit_constexpr } } } } */
+/* { dg-final { scan-ipa-dump "to virtual int B::t"  "devirt" { target { ! implicit_constexpr } } } } */
 /* { dg-final { scan-ipa-dump "1 speculatively devirtualized"  "devirt"  } } */
-
diff --git a/gcc/testsuite/g++.dg/ipa/devirt-36.C b/gcc/testsuite/g++.dg/ipa/devirt-36.C
index 067a2bb8ca1..60b830186bb 100644
--- a/gcc/testsuite/g++.dg/ipa/devirt-36.C
+++ b/gcc/testsuite/g++.dg/ipa/devirt-36.C
@@ -18,7 +18,7 @@ m(struct B *b)
                   //  test2 may change the type of A by placement new.
                   // C++ standard is bit imprecise about this.
 }
-/* { dg-final { scan-tree-dump "converting indirect call to function virtual int B::t"  "fre1"  } } */
-/* { dg-final { scan-ipa-dump "to virtual int B::t"  "devirt"  } } */
+/* { dg-final { scan-tree-dump "converting indirect call to function virtual int B::t"  "fre1" { target { ! implicit_constexpr } } } } */
+/* { dg-final { scan-ipa-dump "to virtual int B::t"  "devirt" { target { ! implicit_constexpr } } } } */
 /* { dg-final { scan-ipa-dump "1 speculatively devirtualized"  "devirt"  } } */
 
diff --git a/gcc/testsuite/g++.dg/ipa/devirt-37.C b/gcc/testsuite/g++.dg/ipa/devirt-37.C
index b7f52a0a5e9..df5ab901f82 100644
--- a/gcc/testsuite/g++.dg/ipa/devirt-37.C
+++ b/gcc/testsuite/g++.dg/ipa/devirt-37.C
@@ -33,4 +33,4 @@ t()
 /* { dg-final { scan-tree-dump "No dynamic type change found."  "fre3"  } } */
 /* { dg-final { scan-tree-dump "Checking vtbl store:"  "fre3"  } } */
 /* { dg-final { scan-tree-dump "Function call may change dynamic type:extcall"  "fre3"  } } */
-/* { dg-final { scan-tree-dump "converting indirect call to function virtual void"  "fre3"  } } */
+/* { dg-final { scan-tree-dump "converting indirect call to function virtual void"  "fre3" { target { ! implicit_constexpr } } } } */
diff --git a/gcc/testsuite/g++.dg/ipa/devirt-44.C b/gcc/testsuite/g++.dg/ipa/devirt-44.C
index 5de761412d0..ed211e11739 100644
--- a/gcc/testsuite/g++.dg/ipa/devirt-44.C
+++ b/gcc/testsuite/g++.dg/ipa/devirt-44.C
@@ -1,5 +1,5 @@
 /* { dg-do compile } */
-/* { dg-options "-O3 -fno-ipa-cp -fdump-ipa-inline-details -fno-early-inlining" } */
+/* { dg-options "-O3 -fno-ipa-cp -fdump-ipa-inline-details -fno-early-inlining -fno-implicit-constexpr" } */
 struct A {
   virtual int foo () {return 1;}
   void wrapfoo () {foo();}
diff --git a/gcc/testsuite/g++.dg/ipa/imm-devirt-1.C b/gcc/testsuite/g++.dg/ipa/imm-devirt-1.C
index 00ac61e7f38..fa31cfbae54 100644
--- a/gcc/testsuite/g++.dg/ipa/imm-devirt-1.C
+++ b/gcc/testsuite/g++.dg/ipa/imm-devirt-1.C
@@ -60,7 +60,7 @@ int main (int argc, char *argv[])
 
 /* middleman_2 gets early inlined and the virtual call should get turned to
    a direct call.  */
-/* { dg-final { scan-tree-dump "Inlining int middleman_1" "einline"  } } */
-/* { dg-final { scan-tree-dump "Inlining int middleman_2" "einline"  } } */
+/* { dg-final { scan-tree-dump "Inlining int middleman_1" "einline" { target { ! implicit_constexpr } } } } */
+/* { dg-final { scan-tree-dump "Inlining int middleman_2" "einline" { target { ! implicit_constexpr } } } } */
 /* { dg-final { scan-tree-dump "B::foo \\(" "einline"  } } */
 /* { dg-final { scan-tree-dump-times "OBJ_TYPE_REF" 2 "einline"  } } */
diff --git a/gcc/testsuite/g++.dg/lookup/builtin5.C b/gcc/testsuite/g++.dg/lookup/builtin5.C
index 1bd67dce5ac..652e3f58b67 100644
--- a/gcc/testsuite/g++.dg/lookup/builtin5.C
+++ b/gcc/testsuite/g++.dg/lookup/builtin5.C
@@ -1,5 +1,5 @@
 // PR c++/37276
-
+// { dg-additional-options -fno-inline }
 // { dg-final { scan-assembler "_ZSt5atanhd" } }
 
 namespace std
diff --git a/gcc/testsuite/g++.dg/lto/inline-crossmodule-1_0.C b/gcc/testsuite/g++.dg/lto/inline-crossmodule-1_0.C
index adbc43ea253..0294dcc4bfb 100644
--- a/gcc/testsuite/g++.dg/lto/inline-crossmodule-1_0.C
+++ b/gcc/testsuite/g++.dg/lto/inline-crossmodule-1_0.C
@@ -1,5 +1,5 @@
 // { dg-lto-do link }
-/* { dg-lto-options { "-O2 -fno-early-inlining -flto -fdump-ipa-inline-details" } } */
+/* { dg-lto-options { "-O2 -fno-early-inlining -fno-implicit-constexpr -flto -fdump-ipa-inline-details" } } */
 #include "inline-crossmodule-1.h"
 int a::key ()
 {
diff --git a/gcc/testsuite/g++.dg/modules/enum-1_a.C b/gcc/testsuite/g++.dg/modules/enum-1_a.C
index 53e2ac88f20..24cad286464 100644
--- a/gcc/testsuite/g++.dg/modules/enum-1_a.C
+++ b/gcc/testsuite/g++.dg/modules/enum-1_a.C
@@ -1,5 +1,5 @@
 // { dg-module-do run }
-// { dg-additional-options "-fmodules-ts -fdump-lang-module-uid" }
+// { dg-additional-options "-fmodules-ts -fdump-lang-module-uid -fno-implicit-constexpr" }
 export module enUm;
 // { dg-module-cmi "enUm" }
 
diff --git a/gcc/testsuite/g++.dg/modules/fn-inline-1_c.C b/gcc/testsuite/g++.dg/modules/fn-inline-1_c.C
index 55a7aaa26b4..2b8bbdcd1af 100644
--- a/gcc/testsuite/g++.dg/modules/fn-inline-1_c.C
+++ b/gcc/testsuite/g++.dg/modules/fn-inline-1_c.C
@@ -1,4 +1,4 @@
-// { dg-additional-options "-fmodules-ts" }
+// { dg-additional-options "-fmodules-ts -fno-inline" }
 import bob;
 
 int main ()
diff --git a/gcc/testsuite/g++.dg/modules/pmf-1_b.C b/gcc/testsuite/g++.dg/modules/pmf-1_b.C
index 0b086107045..cb2a35bbc3b 100644
--- a/gcc/testsuite/g++.dg/modules/pmf-1_b.C
+++ b/gcc/testsuite/g++.dg/modules/pmf-1_b.C
@@ -1,4 +1,4 @@
-// { dg-additional-options "-fmodules-ts -fno-module-lazy -fdump-lang-module-alias" }
+// { dg-additional-options "-fmodules-ts -fno-module-lazy -fdump-lang-module-alias -fno-implicit-constexpr" }
 
 #include "pmf-1.h"
 import "pmf-1_a.H";
diff --git a/gcc/testsuite/g++.dg/modules/used-1_c.C b/gcc/testsuite/g++.dg/modules/used-1_c.C
index 0d1514e031c..b51a19fb8d7 100644
--- a/gcc/testsuite/g++.dg/modules/used-1_c.C
+++ b/gcc/testsuite/g++.dg/modules/used-1_c.C
@@ -1,4 +1,4 @@
-// { dg-additional-options -fmodules-ts }
+// { dg-additional-options "-fmodules-ts -fno-inline" }
 
 import "used-1_b.H";
 
diff --git a/gcc/testsuite/g++.dg/tls/thread_local11.C b/gcc/testsuite/g++.dg/tls/thread_local11.C
index 273ee03d702..608c9580b2e 100644
--- a/gcc/testsuite/g++.dg/tls/thread_local11.C
+++ b/gcc/testsuite/g++.dg/tls/thread_local11.C
@@ -2,7 +2,7 @@
 // { dg-do compile { target c++11 } }
 // { dg-add-options tls }
 // { dg-require-effective-target tls_runtime }
-// { dg-additional-options "-fdump-tree-gimple" }
+// { dg-additional-options "-fdump-tree-gimple -fno-inline" }
 // { dg-final { scan-tree-dump-times "_ZTW2s1" 2 "gimple" } }
 // { dg-final { scan-tree-dump-times "_ZTW2s2" 2 "gimple" } }
 // { dg-final { scan-tree-dump-times "_ZTW2s3" 2 "gimple" } }
diff --git a/gcc/testsuite/g++.dg/tls/thread_local11a.C b/gcc/testsuite/g++.dg/tls/thread_local11a.C
index d8c4a6dc0ab..836f4c8f966 100644
--- a/gcc/testsuite/g++.dg/tls/thread_local11a.C
+++ b/gcc/testsuite/g++.dg/tls/thread_local11a.C
@@ -3,7 +3,7 @@
 // { dg-add-options tls }
 // { dg-require-alias "" }
 // { dg-require-effective-target tls_runtime }
-// { dg-additional-options "-fdump-tree-gimple" }
+// { dg-additional-options "-fdump-tree-gimple -fno-inline" }
 // { dg-final { scan-tree-dump-times "_ZTH2s1" 1 "gimple" } }
 // { dg-final { scan-tree-dump-times "_ZTH2s2" 1 "gimple" } }
 // { dg-final { scan-tree-dump-times "_ZTH2s3" 1 "gimple" } }
diff --git a/gcc/testsuite/g++.dg/tm/pr46653.C b/gcc/testsuite/g++.dg/tm/pr46653.C
index f8f3a1d3117..a4649eb5ffc 100644
--- a/gcc/testsuite/g++.dg/tm/pr46653.C
+++ b/gcc/testsuite/g++.dg/tm/pr46653.C
@@ -1,5 +1,5 @@
 // { dg-do compile }
-// { dg-options "-fgnu-tm -O" }
+// { dg-options "-fgnu-tm -O -fno-implicit-constexpr" }
 
 class shared_count
 {
diff --git a/gcc/testsuite/g++.old-deja/g++.other/delete6.C b/gcc/testsuite/g++.old-deja/g++.other/delete6.C
index 733a6e22cb9..56cfa000e8d 100644
--- a/gcc/testsuite/g++.old-deja/g++.other/delete6.C
+++ b/gcc/testsuite/g++.old-deja/g++.other/delete6.C
@@ -25,4 +25,4 @@ inline void A::operator delete(void*p)
 
 int main()
 {A *ap=new A;
-delete ap;}
+delete ap;}			// { dg-prune-output "unallocated object 'i'" }
diff --git a/libstdc++-v3/testsuite/20_util/to_address/1_neg.cc b/libstdc++-v3/testsuite/20_util/to_address/1_neg.cc
index ff3a1fbcb5d..5030f89b345 100644
--- a/libstdc++-v3/testsuite/20_util/to_address/1_neg.cc
+++ b/libstdc++-v3/testsuite/20_util/to_address/1_neg.cc
@@ -32,5 +32,5 @@ struct P
 void test01()
 {
   P p;
-  std::to_address(p); // { dg-error "required from here" }
+  std::to_address(p); // { dg-error "" }
 }
diff --git a/libstdc++-v3/testsuite/26_numerics/random/concept.cc b/libstdc++-v3/testsuite/26_numerics/random/concept.cc
index 1adc0c11baa..0a0cbbf7c4e 100644
--- a/libstdc++-v3/testsuite/26_numerics/random/concept.cc
+++ b/libstdc++-v3/testsuite/26_numerics/random/concept.cc
@@ -227,7 +227,11 @@ struct N12
   static constexpr unsigned max() { return 1; }
 };
 
+#if __cpp_implicit_constexpr
+static_assert( std::uniform_random_bit_generator<N12> ); // LWG 3150
+#else
 static_assert( ! std::uniform_random_bit_generator<N12> ); // LWG 3150
+#endif
 
 struct N13
 {
@@ -236,7 +240,11 @@ struct N13
   static unsigned max() { return 1; } // not constexpr
 };
 
+#if __cpp_implicit_constexpr
+static_assert( std::uniform_random_bit_generator<N13> ); // LWG 3150
+#else
 static_assert( ! std::uniform_random_bit_generator<N13> ); // LWG 3150
+#endif
 
 struct N14
 {
diff --git a/gcc/cp/Make-lang.in b/gcc/cp/Make-lang.in
index 84694249b87..de1fc0249e6 100644
--- a/gcc/cp/Make-lang.in
+++ b/gcc/cp/Make-lang.in
@@ -221,7 +221,7 @@ check-c++17:
 
 # Run the testsuite in all standard conformance levels.
 check-c++-all:
-	$(MAKE) RUNTESTFLAGS="$(RUNTESTFLAGS) --stds=98,11,14,17,2a,concepts" check-g++
+	$(MAKE) RUNTESTFLAGS="$(RUNTESTFLAGS) --stds=98,11,14,17,20,23,impcx" check-g++
 
 # Run the testsuite with garbage collection at every opportunity.
 check-g++-strict-gc:
diff --git a/gcc/testsuite/g++.dg/modules/pmf-1_a.H b/gcc/testsuite/g++.dg/modules/pmf-1_a.H
index c597db1fe8a..a7b3fc370ec 100644
--- a/gcc/testsuite/g++.dg/modules/pmf-1_a.H
+++ b/gcc/testsuite/g++.dg/modules/pmf-1_a.H
@@ -1,4 +1,4 @@
-// { dg-additional-options -fmodule-header }
+// { dg-additional-options "-fmodule-header -fno-implicit-constexpr" }
 // { dg-module-cmi {} }
 
 #include "pmf-1.h"
diff --git a/gcc/testsuite/lib/g++-dg.exp b/gcc/testsuite/lib/g++-dg.exp
index c360770a7a2..fd06d278faa 100644
--- a/gcc/testsuite/lib/g++-dg.exp
+++ b/gcc/testsuite/lib/g++-dg.exp
@@ -57,7 +57,8 @@ proc g++-dg-runtest { testcases flags default-extra-flags } {
 	    set option_list { }
 	    foreach x $std_list {
 		# Handle "concepts" as C++17 plus Concepts TS.
-		if { $x eq "concepts" } then { set x "17 -fconcepts" }
+		if { $x eq "concepts" } then { set x "17 -fconcepts"
+		} elseif { $x eq "impcx" } then { set x "23 -fimplicit-constexpr" }
 		lappend option_list "${std_prefix}$x"
 	    }
 	} else {
diff --git a/gcc/testsuite/lib/target-supports.exp b/gcc/testsuite/lib/target-supports.exp
index 8cbda192fe0..c928d99a14b 100644
--- a/gcc/testsuite/lib/target-supports.exp
+++ b/gcc/testsuite/lib/target-supports.exp
@@ -10232,6 +10232,10 @@ proc check_effective_target_concepts { } {
     return [check-flags { "" { } { -fconcepts } }]
 }
 
+proc check_effective_target_implicit_constexpr { } {
+    return [check-flags { "" { } { -fimplicit-constexpr } }]
+}
+
 # Return 1 if expensive testcases should be run.
 
 proc check_effective_target_run_expensive_tests { } {
