[clang] [Clang][C++23] Implement P2448R2: Relaxing some constexpr restrictions (PR #77753)

Mariya Podchishchaeva via cfe-commits cfe-commits at lists.llvm.org
Tue Mar 5 07:12:13 PST 2024


https://github.com/Fznamznon updated https://github.com/llvm/llvm-project/pull/77753

>From 699f47bba02012523e1862f9b15ce9de1d7511b5 Mon Sep 17 00:00:00 2001
From: "Podchishchaeva, Mariya" <mariya.podchishchaeva at intel.com>
Date: Wed, 18 Oct 2023 02:47:33 -0700
Subject: [PATCH 01/11] [Clang][C++23] Implement P2448R2: Relaxing some
 constexpr restrictions

Per https://www.open-std.org/jtc1/sc22/wg21/docs/papers/2022/p2448r2.html
function/constructor/destructor can be marked `constexpr` even though it never
produces a constant expression.
Non-literal types as return types and parameter types of functions
marked `constexpr` are also allowed.
Since this is not a DR, the diagnostic messages are still preserved for
C++ standards older than C++23.
---
 clang/docs/ReleaseNotes.rst                   |   2 +
 .../clang/Basic/DiagnosticSemaKinds.td        |  42 +++--
 clang/lib/Sema/SemaDeclCXX.cpp                |  54 +++++--
 clang/test/AST/Interp/cxx23.cpp               |  24 +--
 clang/test/AST/Interp/literals.cpp            |   2 +-
 clang/test/AST/Interp/shifts.cpp              |   8 +-
 clang/test/CXX/basic/basic.types/p10.cpp      |  26 +--
 .../dcl.dcl/dcl.spec/dcl.constexpr/dtor.cpp   |   8 +-
 .../dcl.dcl/dcl.spec/dcl.constexpr/p3-2b.cpp  |   4 +-
 .../CXX/dcl.dcl/dcl.spec/dcl.constexpr/p3.cpp |  27 ++--
 .../CXX/dcl.dcl/dcl.spec/dcl.constexpr/p4.cpp |  20 +--
 .../CXX/dcl.dcl/dcl.spec/dcl.constexpr/p5.cpp |   6 +-
 .../CXX/dcl.dcl/dcl.spec/dcl.constexpr/p6.cpp |   2 +-
 .../dcl.fct.def/dcl.fct.def.default/p2.cpp    |   6 +-
 clang/test/CXX/drs/dr13xx.cpp                 |  22 +--
 clang/test/CXX/drs/dr14xx.cpp                 |   6 +-
 clang/test/CXX/drs/dr16xx.cpp                 |  12 +-
 clang/test/CXX/drs/dr6xx.cpp                  |  24 +--
 clang/test/CXX/expr/expr.const/p2-0x.cpp      |   2 +-
 clang/test/CXX/expr/expr.const/p5-26.cpp      |   4 +-
 clang/test/CXX/special/class.copy/p13-0x.cpp  |   2 +-
 clang/test/PCH/cxx11-constexpr.cpp            |   2 +-
 clang/test/SemaCXX/builtin_vectorelements.cpp |   2 +-
 .../SemaCXX/constant-expression-cxx11.cpp     |  29 ++--
 .../SemaCXX/constant-expression-cxx14.cpp     |  33 ++--
 .../SemaCXX/constant-expression-cxx2b.cpp     |  18 ++-
 .../constexpr-function-recovery-crash.cpp     |   4 +-
 .../test/SemaCXX/cxx1z-constexpr-lambdas.cpp  |   4 +-
 .../test/SemaCXX/cxx23-invalid-constexpr.cpp  | 152 ++++++++++++++++++
 clang/test/SemaCXX/cxx2a-consteval.cpp        |   4 +-
 .../SemaCXX/deduced-return-type-cxx14.cpp     |   8 +-
 clang/test/SemaCXX/ms-constexpr-invalid.cpp   |   6 +-
 clang/test/SemaCXX/ms-constexpr.cpp           |   2 +-
 clang/test/SemaCXX/sizeless-1.cpp             |   2 +-
 .../addrspace-constructors.clcpp              |   2 +-
 clang/www/cxx_status.html                     |   9 +-
 36 files changed, 378 insertions(+), 202 deletions(-)
 create mode 100644 clang/test/SemaCXX/cxx23-invalid-constexpr.cpp

diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst
index a18d36a16b1a9c..23342a6a7256d8 100644
--- a/clang/docs/ReleaseNotes.rst
+++ b/clang/docs/ReleaseNotes.rst
@@ -165,6 +165,8 @@ C++23 Feature Support
 - Added a separate warning to warn the use of attributes on lambdas as a C++23 extension
   in previous language versions: ``-Wc++23-lambda-attributes``.
 
+- Implemented `P2448R2: Relaxing some constexpr restrictions <https://wg21.link/P2448R2>`_.
+
 C++2c Feature Support
 ^^^^^^^^^^^^^^^^^^^^^
 
diff --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td b/clang/include/clang/Basic/DiagnosticSemaKinds.td
index 1a79892e40030a..67409374f26dfa 100644
--- a/clang/include/clang/Basic/DiagnosticSemaKinds.td
+++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td
@@ -2765,10 +2765,14 @@ def err_constexpr_tag : Error<
   "cannot be marked %sub{select_constexpr_spec_kind}1">;
 def err_constexpr_dtor : Error<
   "destructor cannot be declared %sub{select_constexpr_spec_kind}0">;
-def err_constexpr_dtor_subobject : Error<
-  "destructor cannot be declared %sub{select_constexpr_spec_kind}0 because "
+def ext_constexpr_dtor_subobject : ExtWarn<
+  "destructor cannot be declared %sub{select_constexpr_spec_kind}0 before C++23 because "
   "%select{data member %2|base class %3}1 does not have a "
-  "constexpr destructor">;
+  "constexpr destructor">, InGroup<CXX23>, DefaultError;
+def warn_cxx23_compat_constexpr_dtor_subobject : ExtWarn<
+  "%sub{select_constexpr_spec_kind}0 destructor is incompatible with C++ standards before C++23 because "
+  "%select{data member %2|base class %3}1 does not have a "
+  "constexpr destructor">, InGroup<CXXPre23Compat>, DefaultIgnore;
 def note_constexpr_dtor_subobject : Note<
   "%select{data member %1|base class %2}0 declared here">;
 def err_constexpr_wrong_decl_kind : Error<
@@ -2800,11 +2804,14 @@ def note_non_literal_incomplete : Note<
 def note_non_literal_virtual_base : Note<"%select{struct|interface|class}0 "
   "with virtual base %plural{1:class|:classes}1 is not a literal type">;
 def note_constexpr_virtual_base_here : Note<"virtual base class declared here">;
-def err_constexpr_non_literal_return : Error<
-  "%select{constexpr|consteval}0 function's return type %1 is not a literal type">;
-def err_constexpr_non_literal_param : Error<
-  "%select{constexpr|consteval}2 %select{function|constructor}1's %ordinal0 parameter type %3 is "
-  "not a literal type">;
+def ext_constexpr_non_literal_return : ExtWarn<
+  "%select{constexpr|consteval}0 function with non-literal return type %1 is a C++23 extension">, InGroup<CXX23>, DefaultError;
+def warn_cxx23_compat_constexpr_non_literal_return : Warning<
+  "%select{constexpr|consteval}0 function with non-literal return type %1 is incompatible with C++ standards before C++23">, InGroup<CXXPre23Compat>, DefaultIgnore;
+def ext_constexpr_non_literal_param : ExtWarn<
+  "%select{constexpr|consteval}2 %select{function|constructor}1 with %ordinal0 non-literal parameter type %3 is a C++23 extension">, InGroup<CXX23>, DefaultError;
+def warn_cxx23_compat_constexpr_non_literal_param : Warning<
+  "%select{constexpr|consteval}2 %select{function|constructor}1 with %ordinal0 non-literal parameter type %3 is not compatible with C++ standards before C++23">, InGroup<CXXPre23Compat>, DefaultIgnore;
 def err_constexpr_body_invalid_stmt : Error<
   "statement not allowed in %select{constexpr|consteval}1 %select{function|constructor}0">;
 def ext_constexpr_body_invalid_stmt : ExtWarn<
@@ -2865,8 +2872,11 @@ def warn_cxx17_compat_constexpr_local_var_no_init : Warning<
   "is incompatible with C++ standards before C++20">,
   InGroup<CXXPre20Compat>, DefaultIgnore;
 def ext_constexpr_function_never_constant_expr : ExtWarn<
-  "%select{constexpr|consteval}1 %select{function|constructor}0 never produces a "
-  "constant expression">, InGroup<DiagGroup<"invalid-constexpr">>, DefaultError;
+  "%select{constexpr|consteval}1 %select{function|constructor}0 that never produces a "
+  "constant expression is a C++23 extension">, InGroup<DiagGroup<"invalid-constexpr">>, DefaultError;
+def warn_cxx23_compat_constexpr_function_never_constant_expr : Warning<
+  "%select{constexpr|consteval}1 %select{function|constructor}0 that never produces a "
+  "constant expression is incompatible with C++ standards before C++23">, InGroup<CXXPre23Compat>, DefaultIgnore;
 def err_attr_cond_never_constant_expr : Error<
   "%0 attribute expression never produces a constant expression">;
 def err_diagnose_if_invalid_diagnostic_type : Error<
@@ -9539,14 +9549,14 @@ def err_defaulted_special_member_copy_const_param : Error<
 def err_defaulted_copy_assign_not_ref : Error<
   "the parameter for an explicitly-defaulted copy assignment operator must be an "
   "lvalue reference type">;
-def err_incorrect_defaulted_constexpr : Error<
-  "defaulted definition of %sub{select_special_member_kind}0 "
-  "is not constexpr">;
+def ext_incorrect_defaulted_constexpr : ExtWarn<
+  "defaulted definition of %sub{select_special_member_kind}0 that marked %select{constexpr|consteval}1 "
+  "but never produces a constant expression is a C++23 extension">, InGroup<CXX23>, DefaultError;
+def warn_cxx23_compat_incorrect_defaulted_constexpr : Warning<
+  "defaulted definition of %sub{select_special_member_kind}0 that marked %select{constexpr|consteval}1 "
+  "but never produces a constant expression is incompatible with C++ standards before C++23">, InGroup<CXXPre23Compat>, DefaultIgnore;
 def err_incorrect_defaulted_constexpr_with_vb: Error<
   "%sub{select_special_member_kind}0 cannot be 'constexpr' in a class with virtual base class">;
-def err_incorrect_defaulted_consteval : Error<
-  "defaulted declaration of %sub{select_special_member_kind}0 "
-  "cannot be consteval because implicit definition is not constexpr">;
 def warn_defaulted_method_deleted : Warning<
   "explicitly defaulted %sub{select_special_member_kind}0 is implicitly "
   "deleted">, InGroup<DefaultedFunctionDeleted>;
diff --git a/clang/lib/Sema/SemaDeclCXX.cpp b/clang/lib/Sema/SemaDeclCXX.cpp
index 36e53c684ac4dc..aa49dc73e157bf 100644
--- a/clang/lib/Sema/SemaDeclCXX.cpp
+++ b/clang/lib/Sema/SemaDeclCXX.cpp
@@ -1722,12 +1722,19 @@ static bool CheckConstexprDestructorSubobjects(Sema &SemaRef,
       return true;
 
     if (Kind == Sema::CheckConstexprKind::Diagnose) {
-      SemaRef.Diag(DD->getLocation(), diag::err_constexpr_dtor_subobject)
+      SemaRef.Diag(DD->getLocation(),
+                   SemaRef.getLangOpts().CPlusPlus23
+                       ? diag::warn_cxx23_compat_constexpr_dtor_subobject
+                       : diag::ext_constexpr_dtor_subobject)
           << static_cast<int>(DD->getConstexprKind()) << !FD
           << (FD ? FD->getDeclName() : DeclarationName()) << T;
       SemaRef.Diag(Loc, diag::note_constexpr_dtor_subobject)
           << !FD << (FD ? FD->getDeclName() : DeclarationName()) << T;
     }
+
+    if (SemaRef.getLangOpts().CPlusPlus23)
+      return true;
+
     return false;
   };
 
@@ -1754,11 +1761,17 @@ static bool CheckConstexprParameterTypes(Sema &SemaRef,
     const ParmVarDecl *PD = FD->getParamDecl(ArgIndex);
     assert(PD && "null in a parameter list");
     SourceLocation ParamLoc = PD->getLocation();
-    if (CheckLiteralType(SemaRef, Kind, ParamLoc, *i,
-                         diag::err_constexpr_non_literal_param, ArgIndex + 1,
-                         PD->getSourceRange(), isa<CXXConstructorDecl>(FD),
-                         FD->isConsteval()))
+    if (CheckLiteralType(
+            SemaRef, Kind, ParamLoc, *i,
+            SemaRef.getLangOpts().CPlusPlus23
+                ? diag::warn_cxx23_compat_constexpr_non_literal_param
+                : diag::ext_constexpr_non_literal_param,
+            ArgIndex + 1, PD->getSourceRange(), isa<CXXConstructorDecl>(FD),
+            FD->isConsteval())) {
+      if (SemaRef.getLangOpts().CPlusPlus23)
+        return true;
       return false;
+    }
   }
   return true;
 }
@@ -1767,10 +1780,16 @@ static bool CheckConstexprParameterTypes(Sema &SemaRef,
 /// true. If not, produce a suitable diagnostic and return false.
 static bool CheckConstexprReturnType(Sema &SemaRef, const FunctionDecl *FD,
                                      Sema::CheckConstexprKind Kind) {
-  if (CheckLiteralType(SemaRef, Kind, FD->getLocation(), FD->getReturnType(),
-                       diag::err_constexpr_non_literal_return,
-                       FD->isConsteval()))
+  if (CheckLiteralType(
+          SemaRef, Kind, FD->getLocation(), FD->getReturnType(),
+          SemaRef.getLangOpts().CPlusPlus23
+              ? diag::warn_cxx23_compat_constexpr_non_literal_return
+              : diag::ext_constexpr_non_literal_return,
+          FD->isConsteval())) {
+    if (SemaRef.getLangOpts().CPlusPlus23)
+      return true;
     return false;
+  }
   return true;
 }
 
@@ -2458,8 +2477,11 @@ static bool CheckConstexprFunctionBody(Sema &SemaRef, const FunctionDecl *Dcl,
   SmallVector<PartialDiagnosticAt, 8> Diags;
   if (Kind == Sema::CheckConstexprKind::Diagnose &&
       !Expr::isPotentialConstantExpr(Dcl, Diags)) {
-    SemaRef.Diag(Dcl->getLocation(),
-                 diag::ext_constexpr_function_never_constant_expr)
+    SemaRef.Diag(
+        Dcl->getLocation(),
+        SemaRef.getLangOpts().CPlusPlus23
+            ? diag::warn_cxx23_compat_constexpr_function_never_constant_expr
+            : diag::ext_constexpr_function_never_constant_expr)
         << isa<CXXConstructorDecl>(Dcl) << Dcl->isConsteval()
         << Dcl->getNameInfo().getSourceRange();
     for (size_t I = 0, N = Diags.size(); I != N; ++I)
@@ -7852,13 +7874,15 @@ bool Sema::CheckExplicitlyDefaultedSpecialMember(CXXMethodDecl *MD,
           for (const auto &I : RD->vbases())
             Diag(I.getBeginLoc(), diag::note_constexpr_virtual_base_here);
         } else {
-          Diag(MD->getBeginLoc(), MD->isConsteval()
-                                      ? diag::err_incorrect_defaulted_consteval
-                                      : diag::err_incorrect_defaulted_constexpr)
-              << CSM;
+          Diag(MD->getBeginLoc(),
+               getLangOpts().CPlusPlus23
+                   ? diag::warn_cxx23_compat_incorrect_defaulted_constexpr
+                   : diag::ext_incorrect_defaulted_constexpr)
+              << CSM << MD->isConsteval();
         }
     // FIXME: Explain why the special member can't be constexpr.
-    HadError = true;
+    if (!getLangOpts().CPlusPlus23)
+      HadError = true;
   }
 
   if (First) {
diff --git a/clang/test/AST/Interp/cxx23.cpp b/clang/test/AST/Interp/cxx23.cpp
index bd1cf186d519c5..6ef7df9662e6a4 100644
--- a/clang/test/AST/Interp/cxx23.cpp
+++ b/clang/test/AST/Interp/cxx23.cpp
@@ -6,57 +6,45 @@
 
 /// FIXME: The new interpreter is missing all the 'control flows through...' diagnostics.
 
-constexpr int f(int n) {  // ref20-error {{constexpr function never produces a constant expression}} \
-                          // ref23-error {{constexpr function never produces a constant expression}}
+constexpr int f(int n) {  // ref20-error {{constexpr function that never produces a constant expression}}
   static const int m = n; // ref20-note {{control flows through the definition of a static variable}} \
                           // ref20-warning {{is a C++23 extension}} \
-                          // ref23-note {{control flows through the definition of a static variable}} \
                           // expected20-warning {{is a C++23 extension}}
 
   return m;
 }
-constexpr int g(int n) {        // ref20-error {{constexpr function never produces a constant expression}} \
-                                // ref23-error {{constexpr function never produces a constant expression}}
+constexpr int g(int n) {        // ref20-error {{constexpr function that never produces a constant expression}}
   thread_local const int m = n; // ref20-note {{control flows through the definition of a thread_local variable}} \
                                 // ref20-warning {{is a C++23 extension}} \
-                                // ref23-note {{control flows through the definition of a thread_local variable}} \
                                 // expected20-warning {{is a C++23 extension}}
   return m;
 }
 
-constexpr int c_thread_local(int n) { // ref20-error {{constexpr function never produces a constant expression}} \
-                                      // ref23-error {{constexpr function never produces a constant expression}}
+constexpr int c_thread_local(int n) { // ref20-error {{constexpr function that never produces a constant expression}}
   static _Thread_local int m = 0;     // ref20-note {{control flows through the definition of a thread_local variable}} \
                                       // ref20-warning {{is a C++23 extension}} \
-                                      // ref23-note {{control flows through the definition of a thread_local variable}} \
                                       // expected20-warning {{is a C++23 extension}}
   return m;
 }
 
 
-constexpr int gnu_thread_local(int n) { // ref20-error {{constexpr function never produces a constant expression}} \
-                                        // ref23-error {{constexpr function never produces a constant expression}}
+constexpr int gnu_thread_local(int n) { // ref20-error {{constexpr function that never produces a constant expression}}
   static __thread int m = 0;            // ref20-note {{control flows through the definition of a thread_local variable}} \
                                         // ref20-warning {{is a C++23 extension}} \
-                                        // ref23-note {{control flows through the definition of a thread_local variable}} \
                                         // expected20-warning {{is a C++23 extension}}
   return m;
 }
 
-constexpr int h(int n) {  // ref20-error {{constexpr function never produces a constant expression}} \
-                          // ref23-error {{constexpr function never produces a constant expression}}
+constexpr int h(int n) {  // ref20-error {{constexpr function that never produces a constant expression}}
   static const int m = n; // ref20-note {{control flows through the definition of a static variable}} \
                           // ref20-warning {{is a C++23 extension}} \
-                          // ref23-note {{control flows through the definition of a static variable}} \
                           // expected20-warning {{is a C++23 extension}}
   return &m - &m;
 }
 
-constexpr int i(int n) {        // ref20-error {{constexpr function never produces a constant expression}} \
-                                // ref23-error {{constexpr function never produces a constant expression}}
+constexpr int i(int n) {        // ref20-error {{constexpr function that never produces a constant expression}}
   thread_local const int m = n; // ref20-note {{control flows through the definition of a thread_local variable}} \
                                 // ref20-warning {{is a C++23 extension}} \
-                                // ref23-note {{control flows through the definition of a thread_local variable}} \
                                 // expected20-warning {{is a C++23 extension}}
   return &m - &m;
 }
diff --git a/clang/test/AST/Interp/literals.cpp b/clang/test/AST/Interp/literals.cpp
index 61825bc11438f6..ab09280e883fba 100644
--- a/clang/test/AST/Interp/literals.cpp
+++ b/clang/test/AST/Interp/literals.cpp
@@ -275,7 +275,7 @@ namespace SizeOf {
 
 #if __cplusplus >= 202002L
   /// FIXME: The following code should be accepted.
-  consteval int foo(int n) { // ref-error {{consteval function never produces a constant expression}}
+  consteval int foo(int n) { // ref-error {{consteval function that never produces a constant expression}}
     return sizeof(int[n]); // ref-note 3{{not valid in a constant expression}}
   }
   constinit int var = foo(5); // ref-error {{not a constant expression}} \
diff --git a/clang/test/AST/Interp/shifts.cpp b/clang/test/AST/Interp/shifts.cpp
index cf71e7145c2742..f8fa1b5d095da0 100644
--- a/clang/test/AST/Interp/shifts.cpp
+++ b/clang/test/AST/Interp/shifts.cpp
@@ -7,10 +7,10 @@
 
 
 namespace shifts {
-  constexpr void test() { // ref-error {{constexpr function never produces a constant expression}} \
-                          // ref-cxx17-error {{constexpr function never produces a constant expression}} \
-                          // expected-error {{constexpr function never produces a constant expression}} \
-                          // cxx17-error {{constexpr function never produces a constant expression}} \
+  constexpr void test() { // ref-error {{constexpr function that never produces a constant expression}} \
+                          // ref-cxx17-error {{constexpr function that never produces a constant expression}} \
+                          // expected-error {{constexpr function that never produces a constant expression}} \
+                          // cxx17-error {{constexpr function that never produces a constant expression}} \
 
     char c; // cxx17-warning {{uninitialized variable}} \
             // ref-cxx17-warning {{uninitialized variable}}
diff --git a/clang/test/CXX/basic/basic.types/p10.cpp b/clang/test/CXX/basic/basic.types/p10.cpp
index a543f248e53711..19e099d5077de7 100644
--- a/clang/test/CXX/basic/basic.types/p10.cpp
+++ b/clang/test/CXX/basic/basic.types/p10.cpp
@@ -8,7 +8,7 @@ struct NonLiteral { NonLiteral(); };
 // [C++1y] - void
 constexpr void f() {}
 #ifndef CXX1Y
-// expected-error at -2 {{'void' is not a literal type}}
+// expected-error at -2 {{constexpr function with non-literal return type 'void' is a C++23 extension}}
 #endif
 
 // - a scalar type
@@ -40,12 +40,12 @@ constexpr ClassTemp<int> classtemplate2[] = {};
 struct UserProvDtor {
   ~UserProvDtor(); // expected-note {{has a user-provided destructor}}
 };
-constexpr int f(UserProvDtor) { return 0; } // expected-error {{'UserProvDtor' is not a literal type}}
+constexpr int f(UserProvDtor) { return 0; } // expected-error {{non-literal parameter type 'UserProvDtor'}}
 struct NonTrivDtor {
   constexpr NonTrivDtor();
   virtual ~NonTrivDtor() = default; // expected-note {{has a non-trivial destructor}} expected-note {{because it is virtual}}
 };
-constexpr int f(NonTrivDtor) { return 0; } // expected-error {{'NonTrivDtor' is not a literal type}}
+constexpr int f(NonTrivDtor) { return 0; } // expected-error {{non-literal parameter type 'NonTrivDtor'}}
 struct NonTrivDtorBase {
   ~NonTrivDtorBase();
 };
@@ -53,7 +53,7 @@ template<typename T>
 struct DerivedFromNonTrivDtor : T { // expected-note {{'DerivedFromNonTrivDtor<NonTrivDtorBase>' is not literal because it has base class 'NonTrivDtorBase' of non-literal type}}
   constexpr DerivedFromNonTrivDtor();
 };
-constexpr int f(DerivedFromNonTrivDtor<NonTrivDtorBase>) { return 0; } // expected-error {{constexpr function's 1st parameter type 'DerivedFromNonTrivDtor<NonTrivDtorBase>' is not a literal type}}
+constexpr int f(DerivedFromNonTrivDtor<NonTrivDtorBase>) { return 0; } // expected-error {{constexpr function with 1st non-literal parameter type 'DerivedFromNonTrivDtor<NonTrivDtorBase>' is a C++23 extension}}
 struct TrivDtor {
   constexpr TrivDtor();
 };
@@ -77,11 +77,11 @@ struct CtorTemplate {
 struct CopyCtorOnly { // expected-note {{'CopyCtorOnly' is not literal because it is not an aggregate and has no constexpr constructors other than copy or move constructors}}
   constexpr CopyCtorOnly(CopyCtorOnly&);
 };
-constexpr int f(CopyCtorOnly) { return 0; } // expected-error {{'CopyCtorOnly' is not a literal type}}
+constexpr int f(CopyCtorOnly) { return 0; } // expected-error {{non-literal parameter type 'CopyCtorOnly'}}
 struct MoveCtorOnly { // expected-note {{no constexpr constructors other than copy or move constructors}}
   constexpr MoveCtorOnly(MoveCtorOnly&&);
 };
-constexpr int f(MoveCtorOnly) { return 0; } // expected-error {{'MoveCtorOnly' is not a literal type}}
+constexpr int f(MoveCtorOnly) { return 0; } // expected-error {{non-literal parameter type 'MoveCtorOnly'}}
 template<typename T>
 struct CtorArg {
   constexpr CtorArg(T);
@@ -97,7 +97,7 @@ struct Derived : HasVBase {
 template<typename T> struct DerivedFromVBase : T { // expected-note {{struct with virtual base class is not a literal type}}
   constexpr DerivedFromVBase();
 };
-constexpr int f(DerivedFromVBase<HasVBase>) {} // expected-error {{constexpr function's 1st parameter type 'DerivedFromVBase<HasVBase>' is not a literal type}}
+constexpr int f(DerivedFromVBase<HasVBase>) {} // expected-error {{constexpr function with 1st non-literal parameter type 'DerivedFromVBase<HasVBase>' is a C++23 extension}}
 template<typename T> constexpr DerivedFromVBase<T>::DerivedFromVBase() : T() {}
 constexpr int nVBase = (DerivedFromVBase<HasVBase>(), 0); // expected-error {{constant expression}} expected-note {{cannot construct object of type 'DerivedFromVBase<HasVBase>' with virtual base class in a constant expression}}
 
@@ -105,12 +105,12 @@ constexpr int nVBase = (DerivedFromVBase<HasVBase>(), 0); // expected-error {{co
 struct NonLitMember {
   S s; // expected-note {{has data member 's' of non-literal type 'S'}}
 };
-constexpr int f(NonLitMember) {} // expected-error {{1st parameter type 'NonLitMember' is not a literal type}}
+constexpr int f(NonLitMember) {} // expected-error {{1st non-literal parameter type 'NonLitMember' is a C++23 extension}}
 struct NonLitBase :
   S { // expected-note {{base class 'S' of non-literal type}}
   constexpr NonLitBase();
 };
-constexpr int f(NonLitBase) { return 0; } // expected-error {{'NonLitBase' is not a literal type}}
+constexpr int f(NonLitBase) { return 0; } // expected-error {{non-literal parameter type 'NonLitBase'}}
 struct LitMemBase : Agg {
   Agg agg;
 };
@@ -120,7 +120,7 @@ struct MemberType {
   constexpr MemberType();
 };
 constexpr int f(MemberType<int>) { return 0; }
-constexpr int f(MemberType<NonLiteral>) { return 0; } // expected-error {{not a literal type}}
+constexpr int f(MemberType<NonLiteral>) { return 0; } // expected-error {{non-literal parameter type}}
 
 // - an array of literal type [C++1y] other than an array of runtime bound
 struct ArrGood {
@@ -134,7 +134,7 @@ constexpr int f(ArrGood) { return 0; }
 struct ArrBad {
   S s[3]; // expected-note {{data member 's' of non-literal type 'S[3]'}}
 };
-constexpr int f(ArrBad) { return 0; } // expected-error {{1st parameter type 'ArrBad' is not a literal type}}
+constexpr int f(ArrBad) { return 0; } // expected-error {{1st non-literal parameter type 'ArrBad'}}
 
 constexpr int arb(int n) { // expected-note {{declared here}}
   int a[n]; // expected-error {{variable of non-literal type 'int[n]' cannot be defined in a constexpr function}} \
@@ -159,7 +159,7 @@ namespace inherited_ctor {
     D(int);
     using C::C;
   };
-  constexpr int f(D) { return 0; } // expected-error {{not a literal type}}
+  constexpr int f(D) { return 0; } // expected-error {{non-literal parameter type}}
 
   // This one is a bit odd: F inherits E's default constructor, which is
   // constexpr. Because F has a constructor of its own, it doesn't declare a
@@ -178,7 +178,7 @@ namespace inherited_ctor {
   struct H : G { // expected-note {{because}}
     using G::G;
   };
-  constexpr int f(H) { return 0; } // expected-error {{not a literal type}}
+  constexpr int f(H) { return 0; } // expected-error {{non-literal parameter type}}
 
   struct J;
   struct I { constexpr I(const J&); };
diff --git a/clang/test/CXX/dcl.dcl/dcl.spec/dcl.constexpr/dtor.cpp b/clang/test/CXX/dcl.dcl/dcl.spec/dcl.constexpr/dtor.cpp
index 7ad2e582a81268..1a3da8bdc252ac 100644
--- a/clang/test/CXX/dcl.dcl/dcl.spec/dcl.constexpr/dtor.cpp
+++ b/clang/test/CXX/dcl.dcl/dcl.spec/dcl.constexpr/dtor.cpp
@@ -58,12 +58,12 @@ namespace subobject {
   struct A {
     ~A();
   };
-  struct B : A { // expected-note {{here}}
-    constexpr ~B() {} // expected-error {{destructor cannot be declared constexpr because base class 'A' does not have a constexpr destructor}}
+  struct B : A { // cxx2a-note {{here}}
+    constexpr ~B() {} // cxx2a-error {{destructor cannot be declared constexpr before C++23 because base class 'A' does not have a constexpr destructor}}
   };
   struct C {
-    A a; // expected-note {{here}}
-    constexpr ~C() {} // expected-error {{destructor cannot be declared constexpr because data member 'a' does not have a constexpr destructor}}
+    A a; // cxx2a-note {{here}}
+    constexpr ~C() {} // cxx2a-error {{destructor cannot be declared constexpr before C++23 because data member 'a' does not have a constexpr destructor}}
   };
   struct D : A {
     A a;
diff --git a/clang/test/CXX/dcl.dcl/dcl.spec/dcl.constexpr/p3-2b.cpp b/clang/test/CXX/dcl.dcl/dcl.spec/dcl.constexpr/p3-2b.cpp
index c07502c0555b50..e8c71b44edd620 100644
--- a/clang/test/CXX/dcl.dcl/dcl.spec/dcl.constexpr/p3-2b.cpp
+++ b/clang/test/CXX/dcl.dcl/dcl.spec/dcl.constexpr/p3-2b.cpp
@@ -14,7 +14,7 @@ constexpr int i(int n) {
   return m;
 }
 
-constexpr int g() { // expected-error {{constexpr function never produces a constant expression}}
+constexpr int g() { // expected-warning {{constexpr function that never produces a constant expression is incompatible with C++ standards before C++23}}
   goto test;        // expected-note {{subexpression not valid in a constant expression}} \
            // expected-warning {{use of this statement in a constexpr function is incompatible with C++ standards before C++23}}
 test:
@@ -29,7 +29,7 @@ struct NonLiteral { // expected-note 2 {{'NonLiteral' is not literal}}
   NonLiteral() {}
 };
 
-constexpr void non_literal() { // expected-error {{constexpr function never produces a constant expression}}
+constexpr void non_literal() { // expected-warning {{constexpr function that never produces a constant expression is incompatible with C++ standards before C++23}}
   NonLiteral n;                // expected-note {{non-literal type 'NonLiteral' cannot be used in a constant expression}} \
                                // expected-warning {{definition of a variable of non-literal type in a constexpr function is incompatible with C++ standards before C++23}}
 }
diff --git a/clang/test/CXX/dcl.dcl/dcl.spec/dcl.constexpr/p3.cpp b/clang/test/CXX/dcl.dcl/dcl.spec/dcl.constexpr/p3.cpp
index 6214ff8006d67f..d57c098faff6dd 100644
--- a/clang/test/CXX/dcl.dcl/dcl.spec/dcl.constexpr/p3.cpp
+++ b/clang/test/CXX/dcl.dcl/dcl.spec/dcl.constexpr/p3.cpp
@@ -1,6 +1,6 @@
 // RUN: %clang_cc1 -fcxx-exceptions -verify=expected,beforecxx14,beforecxx20,beforecxx23 -std=c++11 %s
-// RUN: %clang_cc1 -fcxx-exceptions -verify=expected,aftercxx14,beforecxx20,beforecxx23 -std=c++14 %s
-// RUN: %clang_cc1 -fcxx-exceptions -verify=expected,aftercxx14,aftercxx20,beforecxx23 -std=c++20  %s
+// RUN: %clang_cc1 -fcxx-exceptions -verify=expected,aftercxx14,beforecxx20,beforecxx23,cxx14_20 -std=c++14 %s
+// RUN: %clang_cc1 -fcxx-exceptions -verify=expected,aftercxx14,aftercxx20,beforecxx23,cxx14_20 -std=c++20  %s
 // RUN: %clang_cc1 -fcxx-exceptions -verify=expected,aftercxx14,aftercxx20 -std=c++23 %s
 
 namespace N {
@@ -11,7 +11,7 @@ namespace M {
   typedef double D;
 }
 
-struct NonLiteral { // expected-note 2{{no constexpr constructors}}
+struct NonLiteral { // beforecxx23-note 2{{no constexpr constructors}}
   NonLiteral() {}
   NonLiteral(int) {}
 };
@@ -41,18 +41,17 @@ struct T : SS, NonLiteral {
   virtual constexpr int OutOfLineVirtual() const; // beforecxx20-error {{virtual function cannot be constexpr}}
 
   //  - its return type shall be a literal type;
-  // Once we support P2448R2 constexpr functions will be allowd to return non-literal types
-  // The destructor will also be allowed
-  constexpr NonLiteral NonLiteralReturn() const { return {}; } // expected-error {{constexpr function's return type 'NonLiteral' is not a literal type}}
-  constexpr void VoidReturn() const { return; }                // beforecxx14-error {{constexpr function's return type 'void' is not a literal type}}
+  // With support for P2448R2 constexpr functions are allowed to return non-literal types in C++23.
+  constexpr NonLiteral NonLiteralReturn() const { return {}; } // beforecxx23-error {{constexpr function with non-literal return type 'NonLiteral' is a C++23 extension}}
+  constexpr void VoidReturn() const { return; }                // beforecxx14-error {{constexpr function with non-literal return type 'void' is a C++23 extension}}
   constexpr ~T();                                              // beforecxx20-error {{destructor cannot be declared constexpr}}
 
   typedef NonLiteral F() const;
   constexpr F NonLiteralReturn2; // ok until definition
 
   //  - each of its parameter types shall be a literal type;
-  // Once we support P2448R2 constexpr functions will be allowd to have parameters of non-literal types
-  constexpr int NonLiteralParam(NonLiteral) const { return 0; } // expected-error {{constexpr function's 1st parameter type 'NonLiteral' is not a literal type}}
+  // With support for P2448R2 constexpr functions are allowed to have parameters of non-literal types in C++23.
+  constexpr int NonLiteralParam(NonLiteral) const { return 0; } // beforecxx23-error {{constexpr function with 1st non-literal parameter type 'NonLiteral' is a C++23 extension}}
   typedef int G(NonLiteral) const;
   constexpr G NonLiteralParam2; // ok until definition
 
@@ -66,7 +65,7 @@ struct T : SS, NonLiteral {
   // constexpr since they can't be const.
   constexpr T &operator=(const T &) = default; // beforecxx14-error {{an explicitly-defaulted copy assignment operator may not have 'const', 'constexpr' or 'volatile' qualifiers}} \
                                                // beforecxx14-warning {{C++14}} \
-                                               // aftercxx14-error{{defaulted definition of copy assignment operator is not constexpr}}
+                                               // cxx14_20-error{{defaulted definition of copy assignment operator that marked constexpr but never produces a constant expression}}
 };
 
 constexpr int T::OutOfLineVirtual() const { return 0; }
@@ -229,9 +228,9 @@ namespace DR1364 {
     return k; // ok, even though lvalue-to-rvalue conversion of a function
               // parameter is not allowed in a constant expression.
   }
-  int kGlobal; // expected-note {{here}}
-  constexpr int f() { // expected-error {{constexpr function never produces a constant expression}}
-    return kGlobal;   // expected-note {{read of non-const}}
+  int kGlobal; // beforecxx23-note {{here}}
+  constexpr int f() { // beforecxx23-error {{constexpr function that never produces a constant expression is a C++23 extension}}
+    return kGlobal;   // beforecxx23-note {{read of non-const}}
   }
 }
 
@@ -272,7 +271,7 @@ namespace std_example {
     int a; // beforecxx20-warning {{uninitialized}}
     return a;
   }
-  constexpr int prev(int x) { // beforecxx14-error {{never produces a constant expression}}
+  constexpr int prev(int x) { // beforecxx14-error {{constexpr function that never produces a constant expression is a C++23 extension}}
     return --x;               // beforecxx14-note {{subexpression}}
   }
 
diff --git a/clang/test/CXX/dcl.dcl/dcl.spec/dcl.constexpr/p4.cpp b/clang/test/CXX/dcl.dcl/dcl.spec/dcl.constexpr/p4.cpp
index f1f677ebfcd341..71c8d09d3041d4 100644
--- a/clang/test/CXX/dcl.dcl/dcl.spec/dcl.constexpr/p4.cpp
+++ b/clang/test/CXX/dcl.dcl/dcl.spec/dcl.constexpr/p4.cpp
@@ -24,8 +24,8 @@ struct Literal {
 // shall be a literal type.
 struct S {
   constexpr S(int, N::C) {}
-  constexpr S(int, NonLiteral, N::C) {} // expected-error {{constexpr constructor's 2nd parameter type 'NonLiteral' is not a literal type}}
-  constexpr S(int, NonLiteral = 42) {} // expected-error {{constexpr constructor's 2nd parameter type 'NonLiteral' is not a literal type}}
+  constexpr S(int, NonLiteral, N::C) {} // expected-error {{constexpr constructor with 2nd non-literal parameter type 'NonLiteral' is a C++23 extension}}
+  constexpr S(int, NonLiteral = 42) {} // expected-error {{constexpr constructor with 2nd non-literal parameter type 'NonLiteral' is a C++23 extension}}
 
   // In addition, either its function-body shall be = delete or = default
   constexpr S() = default;
@@ -242,15 +242,15 @@ constexpr int f(enable_shared_from_this<int>);
 
 // - every constructor involved in initializing non-static data members and base
 //   class sub-objects shall be a constexpr constructor.
-// This will no longer be the case once we support P2448R2
+// This is the case before C++23.
 struct ConstexprBaseMemberCtors : Literal {
   Literal l;
 
   constexpr ConstexprBaseMemberCtors() : Literal(), l() {} // ok
-  constexpr ConstexprBaseMemberCtors(char) : // expected-error {{constexpr constructor never produces a constant expression}}
+  constexpr ConstexprBaseMemberCtors(char) : // expected-error {{constexpr constructor that never produces a constant expression is a C++23 extension}}
     Literal(0), // expected-note {{non-constexpr constructor}}
     l() {}
-  constexpr ConstexprBaseMemberCtors(double) : Literal(), // expected-error {{constexpr constructor never produces a constant expression}}
+  constexpr ConstexprBaseMemberCtors(double) : Literal(), // expected-error {{constexpr constructor that never produces a constant expression is a C++23 extension}}
     l(0) // expected-note {{non-constexpr constructor}}
   {}
 };
@@ -272,7 +272,7 @@ struct X {
 
 union XU1 { int a; constexpr XU1() = default; };
 #ifndef CXX2A
-// expected-error at -2{{not constexpr}}
+// expected-error at -2{{marked constexpr but never produces a constant expression}}
 #endif
 union XU2 { int a = 1; constexpr XU2() = default; };
 
@@ -282,7 +282,7 @@ struct XU3 {
   };
   constexpr XU3() = default;
 #ifndef CXX2A
-  // expected-error at -2{{not constexpr}}
+  // expected-error at -2{{marked constexpr but never produces a constant expression}}
 #endif
 };
 struct XU4 {
@@ -306,7 +306,7 @@ static_assert(XU4().a == 1, "");
 int kGlobal; // expected-note {{here}}
 struct Z {
   constexpr Z(int a) : n(a) {}
-  constexpr Z() : n(kGlobal) {} // expected-error {{constexpr constructor never produces a constant expression}} expected-note {{read of non-const}}
+  constexpr Z() : n(kGlobal) {} // expected-error {{constexpr constructor that never produces a constant expression is a C++23 extension}} expected-note {{read of non-const}}
   int n;
 };
 
@@ -333,7 +333,7 @@ namespace CtorLookup {
     constexpr B(B&);
   };
   constexpr B::B(const B&) = default;
-  constexpr B::B(B&) = default; // expected-error {{not constexpr}}
+  constexpr B::B(B&) = default; // expected-error {{marked constexpr but never produces a constant expression}}
 
   struct C {
     A a;
@@ -342,7 +342,7 @@ namespace CtorLookup {
     constexpr C(C&);
   };
   constexpr C::C(const C&) = default;
-  constexpr C::C(C&) = default; // expected-error {{not constexpr}}
+  constexpr C::C(C&) = default; // expected-error {{marked constexpr but never produces a constant expression}}
 }
 
 namespace PR14503 {
diff --git a/clang/test/CXX/dcl.dcl/dcl.spec/dcl.constexpr/p5.cpp b/clang/test/CXX/dcl.dcl/dcl.spec/dcl.constexpr/p5.cpp
index 18b2c6b1d6d15b..7c06e5a9f928ad 100644
--- a/clang/test/CXX/dcl.dcl/dcl.spec/dcl.constexpr/p5.cpp
+++ b/clang/test/CXX/dcl.dcl/dcl.spec/dcl.constexpr/p5.cpp
@@ -30,7 +30,7 @@ static_assert(g4() == 5, "");
 
 constexpr int f(bool b)
   { return b ? throw 0 : 0; } // ok
-constexpr int f() { return throw 0, 0; } // expected-error {{constexpr function never produces a constant expression}} expected-note {{subexpression}}
+constexpr int f() { return throw 0, 0; } // expected-error {{constexpr function that never produces a constant expression is a C++23 extension}} expected-note {{subexpression}}
 
 struct B {
   constexpr B(int x) : i(0) { }
@@ -40,14 +40,14 @@ struct B {
 int global; // expected-note {{declared here}}
 
 struct D : B {
-  constexpr D() : B(global) { } // expected-error {{constexpr constructor never produces a constant expression}} expected-note {{read of non-const}}
+  constexpr D() : B(global) { } // expected-error {{constexpr constructor that never produces a constant expression}} expected-note {{read of non-const}}
 };
 
 }
 
 namespace PotentialConstant {
 
-constexpr int Comma(int n) { return // expected-error {{constexpr function never produces a constant expression}}
+constexpr int Comma(int n) { return // expected-error {{constexpr function that never produces a constant expression}}
   (void)(n * 2),
   throw 0, // expected-note {{subexpression}}
   0;
diff --git a/clang/test/CXX/dcl.dcl/dcl.spec/dcl.constexpr/p6.cpp b/clang/test/CXX/dcl.dcl/dcl.spec/dcl.constexpr/p6.cpp
index 00ef78426289fa..850420ca8ae1c0 100644
--- a/clang/test/CXX/dcl.dcl/dcl.spec/dcl.constexpr/p6.cpp
+++ b/clang/test/CXX/dcl.dcl/dcl.spec/dcl.constexpr/p6.cpp
@@ -64,5 +64,5 @@ namespace TemplateVBase {
     constexpr T3() {}
   };
   constexpr T3<Literal> g3() { return {}; } // ok
-  constexpr T3<VirtBase> g4() { return {}; } // expected-error {{not a literal type}}
+  constexpr T3<VirtBase> g4() { return {}; } // expected-error {{non-literal return type}}
 }
diff --git a/clang/test/CXX/dcl.decl/dcl.fct.def/dcl.fct.def.default/p2.cpp b/clang/test/CXX/dcl.decl/dcl.fct.def/dcl.fct.def.default/p2.cpp
index 5b525fc91aba1c..9c9034c7f908ba 100644
--- a/clang/test/CXX/dcl.decl/dcl.fct.def/dcl.fct.def.default/p2.cpp
+++ b/clang/test/CXX/dcl.decl/dcl.fct.def/dcl.fct.def.default/p2.cpp
@@ -3,7 +3,7 @@
 // An explicitly-defaulted function may be declared constexpr only if it would
 // have been implicitly declared as constexpr.
 struct S1 {
-  constexpr S1() = default; // expected-error {{defaulted definition of default constructor is not constexpr}}
+  constexpr S1() = default; // expected-error {{marked constexpr but never produces a constant expression}}
   constexpr S1(const S1&) = default;
   constexpr S1(S1&&) = default;
   constexpr S1 &operator=(const S1&) const = default; // expected-error {{explicitly-defaulted copy assignment operator may not have}}
@@ -18,8 +18,8 @@ struct NoCopyMove {
 };
 struct S2 {
   constexpr S2() = default;
-  constexpr S2(const S2&) = default; // expected-error {{defaulted definition of copy constructor is not constexpr}}
-  constexpr S2(S2&&) = default; // expected-error {{defaulted definition of move constructor is not constexpr}}
+  constexpr S2(const S2&) = default; // expected-error {{defaulted definition of copy constructor that marked constexpr but never produces a constant expression is a C++23 extension}}
+  constexpr S2(S2&&) = default; // expected-error {{defaulted definition of move constructor that marked constexpr but never produces a constant expression}}
   NoCopyMove ncm;
 };
 
diff --git a/clang/test/CXX/drs/dr13xx.cpp b/clang/test/CXX/drs/dr13xx.cpp
index 359c04b3e0f3d4..be656c4468eaeb 100644
--- a/clang/test/CXX/drs/dr13xx.cpp
+++ b/clang/test/CXX/drs/dr13xx.cpp
@@ -1,8 +1,8 @@
 // RUN: %clang_cc1 -std=c++98 %s -verify=expected,cxx98-14,cxx98 -fexceptions -fcxx-exceptions -pedantic-errors
-// RUN: %clang_cc1 -std=c++11 %s -verify=expected,cxx11-17,cxx11-14,cxx98-14,since-cxx11,cxx11 -fexceptions -fcxx-exceptions -pedantic-errors
-// RUN: %clang_cc1 -std=c++14 %s -verify=expected,cxx11-17,cxx11-14,since-cxx14,cxx98-14,since-cxx11 -fexceptions -fcxx-exceptions -pedantic-errors
-// RUN: %clang_cc1 -std=c++17 %s -verify=expected,cxx11-17,since-cxx14,since-cxx17,since-cxx11 -fexceptions -fcxx-exceptions -pedantic-errors
-// RUN: %clang_cc1 -std=c++20 %s -verify=expected,since-cxx14,since-cxx20,since-cxx17,since-cxx11 -fexceptions -fcxx-exceptions -pedantic-errors
+// RUN: %clang_cc1 -std=c++11 %s -verify=expected,cxx11-20,cxx11-17,cxx11-14,cxx98-14,since-cxx11,cxx11 -fexceptions -fcxx-exceptions -pedantic-errors
+// RUN: %clang_cc1 -std=c++14 %s -verify=expected,cxx11-20,cxx11-17,cxx11-14,since-cxx14,cxx98-14,since-cxx11 -fexceptions -fcxx-exceptions -pedantic-errors
+// RUN: %clang_cc1 -std=c++17 %s -verify=expected,cxx11-20,cxx11-17,since-cxx14,since-cxx17,since-cxx11 -fexceptions -fcxx-exceptions -pedantic-errors
+// RUN: %clang_cc1 -std=c++20 %s -verify=expected,cxx11-20,since-cxx14,since-cxx20,since-cxx17,since-cxx11 -fexceptions -fcxx-exceptions -pedantic-errors
 // RUN: %clang_cc1 -std=c++23 %s -verify=expected,since-cxx14,since-cxx20,since-cxx17,since-cxx11 -fexceptions -fcxx-exceptions -pedantic-errors
 // RUN: %clang_cc1 -std=c++2c %s -verify=expected,since-cxx14,since-cxx20,since-cxx17,since-cxx11 -fexceptions -fcxx-exceptions -pedantic-errors
 
@@ -410,11 +410,11 @@ namespace dr1358 { // dr1358: 3.1
   struct B : Virt {
     int member;
     constexpr B(NonLit u) : member(u) {}
-    // since-cxx11-error at -1 {{constexpr constructor's 1st parameter type 'NonLit' is not a literal type}}
-    //   since-cxx11-note@#dr1358-NonLit {{'NonLit' is not literal because it is not an aggregate and has no constexpr constructors other than copy or move constructors}}
+    // cxx11-20-error at -1 {{constexpr constructor with 1st non-literal parameter type 'NonLit' is a C++23 extension}}
+    // cxx11-20-note@#dr1358-NonLit {{'NonLit' is not literal because it is not an aggregate and has no constexpr constructors other than copy or move constructors}}
     constexpr NonLit f(NonLit u) const { return NonLit(); }
-    // since-cxx11-error at -1 {{constexpr function's return type 'NonLit' is not a literal type}}
-    //   since-cxx11-note@#dr1358-NonLit {{'NonLit' is not literal because it is not an aggregate and has no constexpr constructors other than copy or move constructors}}
+    // cxx11-20-error at -1 {{constexpr function with non-literal return type 'NonLit' is a C++23 extension}}
+    // cxx11-20-note@#dr1358-NonLit {{'NonLit' is not literal because it is not an aggregate and has no constexpr constructors other than copy or move constructors}}
   };
 #endif
 }
@@ -423,13 +423,13 @@ namespace dr1359 { // dr1359: 3.5
 #if __cplusplus >= 201103L
   union A { constexpr A() = default; };
   union B { constexpr B() = default; int a; }; // #dr1359-B
-  // cxx11-17-error at -1 {{defaulted definition of default constructor is not constexpr}}
+  // cxx11-17-error at -1 {{defaulted definition of default constructor that marked constexpr but never produces a constant expression is a C++23 extension}}
   union C { constexpr C() = default; int a, b; }; // #dr1359-C
-  // cxx11-17-error at -1 {{defaulted definition of default constructor is not constexpr}} 
+  // cxx11-17-error at -1 {{defaulted definition of default constructor that marked constexpr}} 
   struct X { constexpr X() = default; union {}; };
   // since-cxx11-error at -1 {{declaration does not declare anything}}
   struct Y { constexpr Y() = default; union { int a; }; }; // #dr1359-Y
-  // cxx11-17-error at -1 {{defaulted definition of default constructor is not constexpr}}
+  // cxx11-17-error at -1 {{defaulted definition of default constructor that marked constexpr}}
 
   constexpr A a = A();
   constexpr B b = B();
diff --git a/clang/test/CXX/drs/dr14xx.cpp b/clang/test/CXX/drs/dr14xx.cpp
index d262f6f9dcab79..4bce1de0ab5149 100644
--- a/clang/test/CXX/drs/dr14xx.cpp
+++ b/clang/test/CXX/drs/dr14xx.cpp
@@ -153,16 +153,16 @@ namespace dr1460 { // dr1460: 3.5
   namespace Defaulted {
     union A { constexpr A() = default; };
     union B { int n; constexpr B() = default; };
-    // cxx11-17-error at -1 {{defaulted definition of default constructor is not constexpr}}
+    // cxx11-17-error at -1 {{defaulted definition of default constructor that marked constexpr but never produces a constant expression is a C++23 extension}}
     union C { int n = 0; constexpr C() = default; };
     struct D { union {}; constexpr D() = default; };
     // expected-error at -1 {{declaration does not declare anything}}
     struct E { union { int n; }; constexpr E() = default; };
-    // cxx11-17-error at -1 {{defaulted definition of default constructor is not constexpr}}
+    // cxx11-17-error at -1 {{defaulted definition of default constructor that marked constexpr but never produces a constant expression is a C++23 extension}}
     struct F { union { int n = 0; }; constexpr F() = default; };
 
     struct G { union { int n = 0; }; union { int m; }; constexpr G() = default; };
-    // cxx11-17-error at -1 {{defaulted definition of default constructor is not constexpr}}
+    // cxx11-17-error at -1 {{defaulted definition of default constructor that marked constexpr but never produces a constant expression is a C++23 extension}}
     struct H {
       union {
         int n = 0;
diff --git a/clang/test/CXX/drs/dr16xx.cpp b/clang/test/CXX/drs/dr16xx.cpp
index 3f074c4d57354a..1cf7bb840507ff 100644
--- a/clang/test/CXX/drs/dr16xx.cpp
+++ b/clang/test/CXX/drs/dr16xx.cpp
@@ -1,8 +1,8 @@
 // RUN: %clang_cc1 -std=c++98 -triple x86_64-unknown-unknown %s -verify=expected,cxx98-14,cxx98 -fexceptions -fcxx-exceptions -pedantic-errors
-// RUN: %clang_cc1 -std=c++11 -triple x86_64-unknown-unknown %s -verify=expected,cxx98-14,since-cxx11,cxx11 -fexceptions -fcxx-exceptions -pedantic-errors
-// RUN: %clang_cc1 -std=c++14 -triple x86_64-unknown-unknown %s -verify=expected,since-cxx14,cxx98-14,since-cxx11 -fexceptions -fcxx-exceptions -pedantic-errors
-// RUN: %clang_cc1 -std=c++17 -triple x86_64-unknown-unknown %s -verify=expected,since-cxx14,since-cxx17,since-cxx11 -fexceptions -fcxx-exceptions -pedantic-errors
-// RUN: %clang_cc1 -std=c++20 -triple x86_64-unknown-unknown %s -verify=expected,since-cxx14,since-cxx20,since-cxx17,since-cxx11 -fexceptions -fcxx-exceptions -pedantic-errors
+// RUN: %clang_cc1 -std=c++11 -triple x86_64-unknown-unknown %s -verify=expected,cxx11-20,cxx98-14,since-cxx11,cxx11 -fexceptions -fcxx-exceptions -pedantic-errors
+// RUN: %clang_cc1 -std=c++14 -triple x86_64-unknown-unknown %s -verify=expected,cxx11-20,since-cxx14,cxx98-14,since-cxx11 -fexceptions -fcxx-exceptions -pedantic-errors
+// RUN: %clang_cc1 -std=c++17 -triple x86_64-unknown-unknown %s -verify=expected,cxx11-20,since-cxx14,since-cxx17,since-cxx11 -fexceptions -fcxx-exceptions -pedantic-errors
+// RUN: %clang_cc1 -std=c++20 -triple x86_64-unknown-unknown %s -verify=expected,cxx11-20,since-cxx14,since-cxx20,since-cxx17,since-cxx11 -fexceptions -fcxx-exceptions -pedantic-errors
 // RUN: %clang_cc1 -std=c++23 -triple x86_64-unknown-unknown %s -verify=expected,since-cxx14,since-cxx20,since-cxx17,since-cxx11 -fexceptions -fcxx-exceptions -pedantic-errors
 // RUN: %clang_cc1 -std=c++2c -triple x86_64-unknown-unknown %s -verify=expected,since-cxx14,since-cxx20,since-cxx17,since-cxx11 -fexceptions -fcxx-exceptions -pedantic-errors
 
@@ -349,8 +349,8 @@ namespace dr1684 { // dr1684: 3.6
   };
   constexpr int f(NonLiteral &) { return 0; }
   constexpr int f(NonLiteral) { return 0; }
-  // since-cxx11-error at -1 {{constexpr function's 1st parameter type 'NonLiteral' is not a literal type}}
-  //   since-cxx11-note@#dr1684-struct {{'NonLiteral' is not literal because it is not an aggregate and has no constexpr constructors other than copy or move constructors}}
+  // cxx11-20-error at -1 {{constexpr function with 1st non-literal parameter type 'NonLiteral' is a C++23 extension}}
+  // cxx11-20-note@#dr1684-struct {{'NonLiteral' is not literal because it is not an aggregate and has no constexpr constructors other than copy or move constructors}}
 #endif
 }
 
diff --git a/clang/test/CXX/drs/dr6xx.cpp b/clang/test/CXX/drs/dr6xx.cpp
index 78604d480aa1ca..17e32dcc51ac98 100644
--- a/clang/test/CXX/drs/dr6xx.cpp
+++ b/clang/test/CXX/drs/dr6xx.cpp
@@ -1,8 +1,8 @@
 // RUN: %clang_cc1 -std=c++98 %s -verify=expected,cxx98-17,cxx98-14,cxx98 -fexceptions -fcxx-exceptions -pedantic-errors -fno-spell-checking
-// RUN: %clang_cc1 -std=c++11 %s -verify=expected,cxx98-17,cxx11-17,cxx98-14,since-cxx11,cxx11 -fexceptions -fcxx-exceptions -pedantic-errors -fno-spell-checking
-// RUN: %clang_cc1 -std=c++14 %s -verify=expected,cxx98-17,cxx11-17,cxx98-14,since-cxx11 -fexceptions -fcxx-exceptions -pedantic-errors -fno-spell-checking
-// RUN: %clang_cc1 -std=c++17 %s -verify=expected,cxx98-17,cxx11-17,since-cxx11 -fexceptions -fcxx-exceptions -pedantic-errors -fno-spell-checking
-// RUN: %clang_cc1 -std=c++20 %s -verify=expected,since-cxx11 -fexceptions -fcxx-exceptions -pedantic-errors -fno-spell-checking
+// RUN: %clang_cc1 -std=c++11 %s -verify=expected,cxx11-20,cxx98-17,cxx11-17,cxx98-14,since-cxx11,cxx11 -fexceptions -fcxx-exceptions -pedantic-errors -fno-spell-checking
+// RUN: %clang_cc1 -std=c++14 %s -verify=expected,cxx11-20,cxx98-17,cxx11-17,cxx98-14,since-cxx11 -fexceptions -fcxx-exceptions -pedantic-errors -fno-spell-checking
+// RUN: %clang_cc1 -std=c++17 %s -verify=expected,cxx11-20,cxx98-17,cxx11-17,since-cxx11 -fexceptions -fcxx-exceptions -pedantic-errors -fno-spell-checking
+// RUN: %clang_cc1 -std=c++20 %s -verify=expected,cxx11-20,since-cxx11 -fexceptions -fcxx-exceptions -pedantic-errors -fno-spell-checking
 // RUN: %clang_cc1 -std=c++23 %s -verify=expected,since-cxx11 -fexceptions -fcxx-exceptions -pedantic-errors -fno-spell-checking
 
 namespace dr600 { // dr600: 2.8
@@ -584,8 +584,8 @@ namespace dr647 { // dr647: 3.1
   struct C {
     constexpr C(NonLiteral);
     constexpr C(NonLiteral, int) {}
-    // since-cxx11-error at -1 {{constexpr constructor's 1st parameter type 'NonLiteral' is not a literal type}}
-    //   since-cxx11-note@#dr647-NonLiteral {{'NonLiteral' is not literal because it is not an aggregate and has no constexpr constructors other than copy or move constructors}}
+    // cxx11-20-error at -1 {{constexpr constructor with 1st non-literal parameter type 'NonLiteral' is a C++23 extension}}
+    // cxx11-20-note@#dr647-NonLiteral {{'NonLiteral' is not literal because it is not an aggregate and has no constexpr constructors other than copy or move constructors}}
     constexpr C() try {} catch (...) {}
     // cxx11-17-error at -1 {{function try block in constexpr constructor is a C++20 extension}}
     // cxx11-error at -2 {{use of this statement in a constexpr constructor is a C++14 extension}}
@@ -609,15 +609,15 @@ namespace dr647 { // dr647: 3.1
           d(0) {}
 
     constexpr E(int)
-    // since-cxx11-error at -1 {{constexpr constructor never produces a constant expression}}
-    //   since-cxx11-note@#dr647-int-d {{non-constexpr constructor 'D' cannot be used in a constant expression}}
-    //   since-cxx11-note@#dr647-D-float-ctor {{declared here}}
+    // cxx11-20-error at -1 {{constexpr constructor that never produces a constant expression}}
+    //   cxx11-20-note@#dr647-int-d {{non-constexpr constructor 'D' cannot be used in a constant expression}}
+    //   cxx11-20-note@#dr647-D-float-ctor {{declared here}}
         : n(0),
           d(0.0f) {} // #dr647-int-d
     constexpr E(float f)
-    // since-cxx11-error at -1 {{never produces a constant expression}}
-    //   since-cxx11-note@#dr647-float-d {{non-constexpr constructor}}
-    //   since-cxx11-note@#dr647-D-float-ctor {{declared here}}
+    // cxx11-20-error at -1 {{never produces a constant expression}}
+    //   cxx11-20-note@#dr647-float-d {{non-constexpr constructor}}
+    //   cxx11-20-note@#dr647-D-float-ctor {{declared here}}
         : n(get()),
           d(D(0) + f) {} // #dr647-float-d
   };
diff --git a/clang/test/CXX/expr/expr.const/p2-0x.cpp b/clang/test/CXX/expr/expr.const/p2-0x.cpp
index e3cd057baba75f..868dacd4415a39 100644
--- a/clang/test/CXX/expr/expr.const/p2-0x.cpp
+++ b/clang/test/CXX/expr/expr.const/p2-0x.cpp
@@ -302,7 +302,7 @@ constexpr float negpi = -pi; // expect no error on unary operator
 
 #if __cplusplus >= 201703L
 namespace CompoundAssignment {
-constexpr int rem() { // expected-error {{constexpr function never produces a constant expression}}
+constexpr int rem() { // expected-error {{constexpr function that never produces a constant expression}}
     int x = ~__INT_MAX__;
     return x%=-1; // cxx20-note {{value 2147483648 is outside the range of representable values of type 'int'}}
 }
diff --git a/clang/test/CXX/expr/expr.const/p5-26.cpp b/clang/test/CXX/expr/expr.const/p5-26.cpp
index de2afa71b42669..3624b1e5a3e3df 100644
--- a/clang/test/CXX/expr/expr.const/p5-26.cpp
+++ b/clang/test/CXX/expr/expr.const/p5-26.cpp
@@ -5,11 +5,11 @@
 struct S {};
 struct T : S {} t;
 
-consteval void test() { // cxx23-error{{consteval function never produces a constant expression}}
+consteval void test() {
     void* a = &t;
     const void* b = &t;
     volatile void* c = &t;
-    (void)static_cast<T*>(a); //cxx23-note {{cast from 'void *' is not allowed in a constant expression in C++ standards before C++2c}}
+    (void)static_cast<T*>(a);
     (void)static_cast<const T*>(a);
     (void)static_cast<volatile T*>(a);
 
diff --git a/clang/test/CXX/special/class.copy/p13-0x.cpp b/clang/test/CXX/special/class.copy/p13-0x.cpp
index 16c8a4029cbac6..2f6173be74a2ae 100644
--- a/clang/test/CXX/special/class.copy/p13-0x.cpp
+++ b/clang/test/CXX/special/class.copy/p13-0x.cpp
@@ -125,7 +125,7 @@ namespace Mutable {
     mutable A a;
   };
   struct C {
-    constexpr C(const C &) = default; // expected-error {{not constexpr}}
+    constexpr C(const C &) = default; // expected-error {{marked constexpr but never produces a constant expression}}
     A a;
   };
 }
diff --git a/clang/test/PCH/cxx11-constexpr.cpp b/clang/test/PCH/cxx11-constexpr.cpp
index b315b477dbf1c6..22cc53e9152cd6 100644
--- a/clang/test/PCH/cxx11-constexpr.cpp
+++ b/clang/test/PCH/cxx11-constexpr.cpp
@@ -33,7 +33,7 @@ constexpr T plus_seven(T other) {
 #else
 
 static_assert(D(4).k == 9, "");
-constexpr int f(C c) { return 0; } // expected-error {{not a literal type}}
+constexpr int f(C c) { return 0; } // expected-error {{non-literal parameter type}}
 // expected-note at 16 {{not an aggregate and has no constexpr constructors}}
 constexpr B b; // expected-error {{constant expression}} expected-note {{non-constexpr}}
                // expected-note at 12 {{here}}
diff --git a/clang/test/SemaCXX/builtin_vectorelements.cpp b/clang/test/SemaCXX/builtin_vectorelements.cpp
index 59ff09ac72e42d..e83d931ee4026f 100644
--- a/clang/test/SemaCXX/builtin_vectorelements.cpp
+++ b/clang/test/SemaCXX/builtin_vectorelements.cpp
@@ -41,7 +41,7 @@ void test_builtin_vectorelements() {
 #if defined(__ARM_FEATURE_SVE)
 #include <arm_sve.h>
 
-consteval int consteval_elements() { // expected-error {{consteval function never produces a constant expression}}
+consteval int consteval_elements() { // expected-error {{consteval function that never produces a constant expression}}
   return __builtin_vectorelements(svuint64_t); // expected-note {{cannot determine number of elements for sizeless vectors in a constant expression}}  // expected-note {{cannot determine number of elements for sizeless vectors in a constant expression}} // expected-note {{cannot determine number of elements for sizeless vectors in a constant expression}}
 }
 
diff --git a/clang/test/SemaCXX/constant-expression-cxx11.cpp b/clang/test/SemaCXX/constant-expression-cxx11.cpp
index 9e2ae07cbe4c9c..a29659301dfd66 100644
--- a/clang/test/SemaCXX/constant-expression-cxx11.cpp
+++ b/clang/test/SemaCXX/constant-expression-cxx11.cpp
@@ -1273,8 +1273,8 @@ namespace PR11595 {
   struct B { B(); A& x; };
   static_assert(B().x == 3, "");  // expected-error {{constant expression}} expected-note {{non-literal type 'B' cannot be used in a constant expression}}
 
-  constexpr bool f(int k) { // expected-error {{constexpr function never produces a constant expression}}
-    return B().x == k; // expected-note {{non-literal type 'B' cannot be used in a constant expression}}
+  constexpr bool f(int k) { // cxx11_20-error {{constexpr function that never produces a constant expression}}
+    return B().x == k; // cxx11_20-note {{non-literal type 'B' cannot be used in a constant expression}}
   }
 }
 
@@ -1326,8 +1326,8 @@ namespace ExternConstexpr {
   constexpr int g() { return q; } // expected-note {{outside its lifetime}}
   constexpr int q = g(); // expected-error {{constant expression}} expected-note {{in call}}
 
-  extern int r; // expected-note {{here}}
-  constexpr int h() { return r; } // expected-error {{never produces a constant}} expected-note {{read of non-const}}
+  extern int r; // cxx11_20-note {{here}}
+  constexpr int h() { return r; } // cxx11_20-error {{never produces a constant}} cxx11_20-note {{read of non-const}}
 
   struct S { int n; };
   extern const S s;
@@ -1767,7 +1767,7 @@ namespace TLS {
 }
 
 namespace Void {
-  constexpr void f() { return; } // cxx11-error{{constexpr function's return type 'void' is not a literal type}}
+  constexpr void f() { return; } // cxx11-error{{constexpr function with non-literal return type 'void' is a C++23 extension}}
 
   void assert_failed(const char *msg, const char *file, int line); // expected-note {{declared here}}
 #define ASSERT(expr) ((expr) ? static_cast<void>(0) : assert_failed(#expr, __FILE__, __LINE__))
@@ -1906,9 +1906,9 @@ namespace StmtExpr {
     });
   }
   static_assert(g(123) == 15129, "");
-  constexpr int h() { // expected-error {{never produces a constant}}
+  constexpr int h() { // cxx11_20-error {{never produces a constant}}
     return ({ // expected-warning {{extension}}
-      return 0; // expected-note {{not supported}}
+      return 0; // cxx11_20-note {{not supported}}
       1;
     });
   }
@@ -2093,8 +2093,8 @@ namespace ZeroSizeTypes {
   // expected-note at -2 {{subtraction of pointers to type 'int[0]' of zero size}}
 
   int arr[5][0];
-  constexpr int f() { // expected-error {{never produces a constant expression}}
-    return &arr[3] - &arr[0]; // expected-note {{subtraction of pointers to type 'int[0]' of zero size}}
+  constexpr int f() { // cxx11_20-error {{never produces a constant expression}}
+    return &arr[3] - &arr[0]; // cxx11_20-note {{subtraction of pointers to type 'int[0]' of zero size}}
   }
 }
 
@@ -2118,8 +2118,8 @@ namespace NeverConstantTwoWays {
   // If we see something non-constant but foldable followed by something
   // non-constant and not foldable, we want the first diagnostic, not the
   // second.
-  constexpr int f(int n) { // expected-error {{never produces a constant expression}}
-    return (int *)(long)&n == &n ? // expected-note {{reinterpret_cast}}
+  constexpr int f(int n) { // cxx11_20-error {{never produces a constant expression}}
+    return (int *)(long)&n == &n ? // cxx11_20-note {{reinterpret_cast}}
         1 / 0 : // expected-warning {{division by zero}}
         0;
   }
@@ -2316,10 +2316,11 @@ namespace InheritedCtor {
 namespace PR28366 {
 namespace ns1 {
 
-void f(char c) { //expected-note2{{declared here}}
+void f(char c) { //expected-note{{declared here}}
+  //cxx11_20-note at -1{{declared here}}
   struct X {
-    static constexpr char f() { //expected-error{{never produces a constant expression}}
-      return c; //expected-error{{reference to local}} expected-note{{function parameter}}
+    static constexpr char f() { // cxx11_20-error {{never produces a constant expression}}
+      return c; //expected-error{{reference to local}} cxx11_20-note{{function parameter}}
     }
   };
   int I = X::f();
diff --git a/clang/test/SemaCXX/constant-expression-cxx14.cpp b/clang/test/SemaCXX/constant-expression-cxx14.cpp
index 273d7ff3a208e2..c829bcc1fc94d4 100644
--- a/clang/test/SemaCXX/constant-expression-cxx14.cpp
+++ b/clang/test/SemaCXX/constant-expression-cxx14.cpp
@@ -44,13 +44,13 @@ constexpr int g(int k) {
   return 3 * k3 + 5 * k2 + n * k - 20;
 }
 static_assert(g(2) == 42, "");
-constexpr int h(int n) {  // expected-error {{constexpr function never produces a constant expression}}
-  static const int m = n; // expected-note {{control flows through the definition of a static variable}} \
+constexpr int h(int n) {  // cxx14_20-error {{constexpr function that never produces a constant expression}}
+  static const int m = n; // cxx14_20-note {{control flows through the definition of a static variable}} \
                           // cxx14_20-warning {{definition of a static variable in a constexpr function is a C++23 extension}}
   return m;
 }
-constexpr int i(int n) {        // expected-error {{constexpr function never produces a constant expression}}
-  thread_local const int m = n; // expected-note {{control flows through the definition of a thread_local variable}} \
+constexpr int i(int n) {        // cxx14_20-error {{constexpr function that never produces a constant expression}}
+  thread_local const int m = n; // cxx14_20-note {{control flows through the definition of a thread_local variable}} \
                                 // cxx14_20-warning {{definition of a thread_local variable in a constexpr function is a C++23 extension}}
   return m;
 }
@@ -68,6 +68,7 @@ constexpr int j(int k) {
     }
   }
 } // expected-note 2{{control reached end of constexpr function}}
+  // cxx23-warning at -1 {{does not return a value in all control paths}}
 static_assert(j(0) == -3, "");
 static_assert(j(1) == 5, "");
 static_assert(j(2), ""); // expected-error {{constant expression}} expected-note {{in call to 'j(2)'}}
@@ -104,10 +105,10 @@ static_assert(l(false) == 5, "");
 static_assert(l(true), ""); // expected-error {{constant expression}} expected-note {{in call to 'l(true)'}}
 
 // Potential constant expression checking is still applied where possible.
-constexpr int htonl(int x) { // expected-error {{never produces a constant expression}}
+constexpr int htonl(int x) { // cxx14_20-error {{never produces a constant expression}}
   typedef unsigned char uchar;
   uchar arr[4] = { uchar(x >> 24), uchar(x >> 16), uchar(x >> 8), uchar(x) };
-  return *reinterpret_cast<int*>(arr); // expected-note {{reinterpret_cast is not allowed in a constant expression}}
+  return *reinterpret_cast<int*>(arr); // cxx14_20-note {{reinterpret_cast is not allowed in a constant expression}}
 }
 
 constexpr int maybe_htonl(bool isBigEndian, int x) {
@@ -183,7 +184,7 @@ namespace string_assign {
   static_assert(!test1(100), "");
   static_assert(!test1(101), ""); // expected-error {{constant expression}} expected-note {{in call to 'test1(101)'}}
 
-  constexpr void f() { // expected-error{{constexpr function never produces a constant expression}} expected-note at +2{{assignment to dereferenced one-past-the-end pointer is not allowed in a constant expression}}
+  constexpr void f() { // cxx14_20-error{{constexpr function that never produces a constant expression}} cxx14_20-note at +2{{assignment to dereferenced one-past-the-end pointer is not allowed in a constant expression}}
     char foo[10] = { "z" }; // expected-note {{here}}
     foo[10] = 'x'; // expected-warning {{past the end}}
   }
@@ -207,14 +208,14 @@ namespace array_resize {
 namespace potential_const_expr {
   constexpr void set(int &n) { n = 1; }
   constexpr int div_zero_1() { int z = 0; set(z); return 100 / z; } // no error
-  constexpr int div_zero_2() { // expected-error {{never produces a constant expression}}
+  constexpr int div_zero_2() { // cxx14_20-error {{never produces a constant expression}}
     int z = 0;
-    return 100 / (set(z), 0); // expected-note {{division by zero}}
+    return 100 / (set(z), 0); // cxx14_20-note {{division by zero}}
   }
-  int n; // expected-note {{declared here}}
-  constexpr int ref() { // expected-error {{never produces a constant expression}}
+  int n; // cxx14_20-note {{declared here}}
+  constexpr int ref() { // cxx14_20-error {{never produces a constant expression}}
     int &r = n;
-    return r; // expected-note {{read of non-const variable 'n'}}
+    return r; // cxx14_20-note {{read of non-const variable 'n'}}
   }
 }
 
@@ -846,8 +847,8 @@ namespace StmtExpr {
   static_assert(g() == 0, ""); // expected-error {{constant expression}} expected-note {{in call}}
 
   // FIXME: We should handle the void statement expression case.
-  constexpr int h() { // expected-error {{never produces a constant}}
-    ({ if (true) {} }); // expected-note {{not supported}}
+  constexpr int h() { // cxx14_20-error {{never produces a constant}}
+    ({ if (true) {} }); // cxx14_20-note {{not supported}}
     return 0;
   }
 }
@@ -1043,9 +1044,9 @@ static_assert(sum(Cs) == 'a' + 'b', ""); // expected-error{{not an integral cons
 constexpr int S = sum(Cs); // expected-error{{must be initialized by a constant expression}} expected-note{{in call}}
 }
 
-constexpr void PR28739(int n) { // expected-error {{never produces a constant}}
+constexpr void PR28739(int n) { // cxx14_20-error {{never produces a constant}}
   int *p = &n;                  // expected-note {{array 'p' declared here}}
-  p += (__int128)(unsigned long)-1; // expected-note {{cannot refer to element 18446744073709551615 of non-array object in a constant expression}}
+  p += (__int128)(unsigned long)-1; // cxx14_20-note {{cannot refer to element 18446744073709551615 of non-array object in a constant expression}}
   // expected-warning at -1 {{the pointer incremented by 18446744073709551615 refers past the last possible element for an array in 64-bit address space containing 32-bit (4-byte) elements (max possible 4611686018427387904 elements)}}
 }
 
diff --git a/clang/test/SemaCXX/constant-expression-cxx2b.cpp b/clang/test/SemaCXX/constant-expression-cxx2b.cpp
index 2ee1d48d1cd697..e92a64d830881f 100644
--- a/clang/test/SemaCXX/constant-expression-cxx2b.cpp
+++ b/clang/test/SemaCXX/constant-expression-cxx2b.cpp
@@ -10,35 +10,41 @@ struct Constexpr{};
 
 #if __cplusplus > 202002L
 
-constexpr int f(int n) {  // expected-error {{constexpr function never produces a constant expression}}
+constexpr int f(int n) {  // cxx2a-error {{constexpr function that never produces a constant expression}} \
+                          // cxx23-warning {{constexpr function that never produces a constant expression is incompatible with C++ standards before C++23}}
   static const int m = n; // expected-note {{control flows through the definition of a static variable}} \
                           // cxx23-warning {{definition of a static variable in a constexpr function is incompatible with C++ standards before C++23}}
   return m;
 }
-constexpr int g(int n) {        // expected-error {{constexpr function never produces a constant expression}}
+constexpr int g(int n) {        // cxx2a-error {{constexpr function that never produces a constant expression}} \
+                                // cxx23-warning {{constexpr function that never produces a constant expression is incompatible with C++ standards before C++23}}
   thread_local const int m = n; // expected-note {{control flows through the definition of a thread_local variable}} \
                                 // cxx23-warning {{definition of a thread_local variable in a constexpr function is incompatible with C++ standards before C++23}}
   return m;
 }
 
-constexpr int c_thread_local(int n) { // expected-error {{constexpr function never produces a constant expression}}
+constexpr int c_thread_local(int n) { // cxx2a-error {{constexpr function that never produces a constant expression}} \
+                                      // cxx23-warning {{constexpr function that never produces a constant expression is incompatible with C++ standards before C++23}}
   static _Thread_local int m = 0;     // expected-note {{control flows through the definition of a thread_local variable}} \
                                       // cxx23-warning {{definition of a static variable in a constexpr function is incompatible with C++ standards before C++23}}
   return m;
 }
 
-constexpr int gnu_thread_local(int n) { // expected-error {{constexpr function never produces a constant expression}}
+constexpr int gnu_thread_local(int n) { // cxx2a-error {{constexpr function that never produces a constant expression}} \
+                                        // cxx23-warning {{constexpr function that never produces a constant expression is incompatible with C++ standards before C++23}}
   static __thread int m = 0;            // expected-note {{control flows through the definition of a thread_local variable}} \
                                         // cxx23-warning {{definition of a static variable in a constexpr function is incompatible with C++ standards before C++23}}
   return m;
 }
 
-constexpr int h(int n) {  // expected-error {{constexpr function never produces a constant expression}}
+constexpr int h(int n) {  // cxx2a-error {{constexpr function that never produces a constant expression}} \
+                          // cxx23-warning {{constexpr function that never produces a constant expression is incompatible with C++ standards before C++23}}
   static const int m = n; // expected-note {{control flows through the definition of a static variable}} \
                           // cxx23-warning {{definition of a static variable in a constexpr function is incompatible with C++ standards before C++23}}
   return &m - &m;
 }
-constexpr int i(int n) {        // expected-error {{constexpr function never produces a constant expression}}
+constexpr int i(int n) {        // cxx2a-error {{constexpr function that never produces a constant expression}} \
+                                // cxx23-warning {{constexpr function that never produces a constant expression is incompatible with C++ standards before C++23}}
   thread_local const int m = n; // expected-note {{control flows through the definition of a thread_local variable}} \
                                  // cxx23-warning {{definition of a thread_local variable in a constexpr function is incompatible with C++ standards before C++23}}
   return &m - &m;
diff --git a/clang/test/SemaCXX/constexpr-function-recovery-crash.cpp b/clang/test/SemaCXX/constexpr-function-recovery-crash.cpp
index 90ee7892b2fc2e..dd0b911fc516b2 100644
--- a/clang/test/SemaCXX/constexpr-function-recovery-crash.cpp
+++ b/clang/test/SemaCXX/constexpr-function-recovery-crash.cpp
@@ -34,13 +34,13 @@ constexpr int test4() {
     return 0;
 }
 
-constexpr int test5() { // expected-error {{constexpr function never produce}}
+constexpr int test5() { // expected-error {{constexpr function that never produce}}
   for (;; a++); // expected-error {{use of undeclared identifier}}  \
                    expected-note {{constexpr evaluation hit maximum step limit; possible infinite loop?}}
   return 1;
 }
 
-constexpr int test6() { // expected-error {{constexpr function never produce}}
+constexpr int test6() { // expected-error {{constexpr function that never produce}}
   int n = 0;
   switch (n) {
     for (;; a++) { // expected-error {{use of undeclared identifier}}
diff --git a/clang/test/SemaCXX/cxx1z-constexpr-lambdas.cpp b/clang/test/SemaCXX/cxx1z-constexpr-lambdas.cpp
index 6a1f48bf7958fd..46c24cc3e5d0b7 100644
--- a/clang/test/SemaCXX/cxx1z-constexpr-lambdas.cpp
+++ b/clang/test/SemaCXX/cxx1z-constexpr-lambdas.cpp
@@ -6,7 +6,7 @@
 
 namespace test_lambda_is_literal {
 #ifdef CPP14_AND_EARLIER
-//expected-error at +4{{not a literal type}}
+//expected-error at +4{{non-literal parameter type}}
 //expected-note at +2{{lambda closure types are non-literal types before C++17}}
 #endif
 auto L = [] { };
@@ -19,7 +19,7 @@ namespace test_constexpr_checking {
 
 namespace ns1 {
   struct NonLit { ~NonLit(); };  //expected-note{{not literal}}
-  auto L = [](NonLit NL) constexpr { }; //expected-error{{not a literal type}}
+  auto L = [](NonLit NL) constexpr { }; //expected-error{{non-literal parameter type}}
 } // end ns1
 
 namespace ns2 {
diff --git a/clang/test/SemaCXX/cxx23-invalid-constexpr.cpp b/clang/test/SemaCXX/cxx23-invalid-constexpr.cpp
new file mode 100644
index 00000000000000..69562ebfeaf736
--- /dev/null
+++ b/clang/test/SemaCXX/cxx23-invalid-constexpr.cpp
@@ -0,0 +1,152 @@
+// RUN: %clang_cc1 -fsyntax-only -verify -std=c++23 -Wpre-c++23-compat %s
+
+// This test covers modifications made by P2448R2 in C++23 mode.
+
+// Check that there is no error when a constexpr function that never produces a
+// constant expression, but still an error if such function is called from
+// constexpr context.
+constexpr int F(int N) {  
+  // expected-warning at -1 {{constexpr function that never produces a constant expression is incompatible with C++ standards before C++23}}
+  double D = 2.0 / 0.0; // expected-note 2{{division by zero}}
+  return 1;
+}
+
+// No warning here since the function can produce a constant expression.
+constexpr int F0(int N) {
+  if (N == 0)
+    double d2 = 2.0 / 0.0; // expected-note {{division by zero}}
+  return 1;
+}
+
+template <typename T>
+constexpr int FT(T N) {
+  double D = 2.0 / 0.0; // expected-note {{division by zero}}
+  return 1;
+}
+
+class NonLiteral {
+// expected-note at -1 3{{'NonLiteral' is not literal because it is not an aggregate and has no constexpr constructors other than copy or move constructors}}
+public:
+  NonLiteral() {} // expected-note 2{{declared here}}
+  ~NonLiteral() {}
+};
+
+constexpr NonLiteral F1() {
+// expected-warning at -1 {{constexpr function with non-literal return type 'NonLiteral' is incompatible with C++ standards before C++23}}
+// expected-warning at -2 {{constexpr function that never produces a constant expression is incompatible with C++ standards before C++23}}
+  return NonLiteral{};
+// expected-note at -1 {{non-constexpr constructor 'NonLiteral' cannot be used in a constant expression}}
+}
+
+constexpr int F2(NonLiteral N) {
+  // expected-warning at -1 {{constexpr function with 1st non-literal parameter type 'NonLiteral' is not compatible with C++ standards before C++23}}
+  return 8;
+}
+
+class Derived : public NonLiteral { // expected-note {{declared here}}
+  constexpr ~Derived() {};
+  // expected-warning at -1{{constexpr destructor is incompatible with C++ standards before C++23 because base class 'NonLiteral' does not have a constexpr destructor}}
+
+};
+
+class Derived1 : public NonLiteral {
+  constexpr Derived1() : NonLiteral () {}
+  // expected-warning at -1{{constexpr constructor that never produces a constant expression is incompatible with C++ standards before C++23}}
+  // expected-note at -2 {{non-constexpr constructor 'NonLiteral' cannot be used in a constant expression}}
+};
+
+
+struct X { // expected-note 2{{'X' is not literal because it is not an aggregate and has no constexpr constructors other than copy or move constructors}}
+  X(); // expected-note 3{{declared here}}
+  X(const X&); // expected-note 2{{declared here}}
+  X(X&&);
+  X& operator=(X&);
+  X& operator=(X&& other);
+  bool operator==(X const&) const; // expected-note 2{{non-constexpr comparison function declared here}}
+};
+
+template <typename T>
+struct Wrapper {
+  constexpr Wrapper() = default;
+  constexpr Wrapper(Wrapper const&) = default;
+  constexpr Wrapper(T const& t) : t(t) { }
+  constexpr Wrapper(Wrapper &&) = default;
+  constexpr X get() const { return t; } // expected-warning {{constexpr function with non-literal return type 'X' is incompatible with C++ standards before C++23}}
+  constexpr bool operator==(Wrapper const&) const = default; // expected-warning {{defaulted definition of equality comparison operator that is declared constexpr but invokes a non-constexpr comparison function is incompatible with C++ standards before C++23}}
+private:
+  T t; // expected-note {{non-constexpr comparison function would be used to compare member 't'}}
+};
+
+struct WrapperNonT {
+  constexpr WrapperNonT() = default; // expected-warning {{defaulted definition of default constructor that marked constexpr but never produces a constant expression is incompatible with C++ standards before C++23}}
+  // expected-note at -1 {{declared here}}
+  constexpr WrapperNonT(WrapperNonT const&) = default; // expected-warning {{defaulted definition of copy constructor that marked constexpr but never produces a constant expression is incompatible with C++ standards before C++23}}
+  constexpr WrapperNonT(X const& t) : t(t) { } // expected-warning {{constexpr constructor that never produces a constant expression is incompatible with C++ standards before C++23}}
+  // expected-note at -1 {{non-constexpr constructor 'X' cannot be used in a constant expression}}
+  constexpr WrapperNonT(WrapperNonT &&) = default; // expected-warning {{defaulted definition of move constructor that marked constexpr but never produces a constant expression is incompatible with C++ standards before C++23}}
+  constexpr WrapperNonT& operator=(WrapperNonT &) = default; // expected-warning {{defaulted definition of copy assignment operator that marked constexpr but never produces a constant expression is incompatible with C++ standards before C++23}}
+  constexpr WrapperNonT& operator=(WrapperNonT&& other) = default; // expected-warning {{defaulted definition of move assignment operator that marked constexpr but never produces a constant expression is incompatible with C++ standards before C++23}}
+  constexpr X get() const { return t; } // expected-warning {{constexpr function with non-literal return type 'X' is incompatible with C++ standards before C++23}}
+  // expected-warning at -1{{constexpr function that never produces a constant expression is incompatible with C++ standards before C++23}}
+  // expected-note at -2 {{non-constexpr constructor 'X' cannot be used in a constant expression}}
+  constexpr bool operator==(WrapperNonT const&) const = default; // expected-warning {{defaulted definition of equality comparison operator that is declared constexpr but invokes a non-constexpr comparison function is incompatible with C++ standards before C++23}}
+private:
+  X t; // expected-note {{non-constexpr comparison function would be used to compare member 't'}}
+};
+
+struct NonDefaultMembers {
+  constexpr NonDefaultMembers() {}; // expected-warning {{constexpr constructor that never produces a constant expression is incompatible with C++ standards before C++23}}
+  // expected-note at -1 {{non-constexpr constructor 'X' cannot be used in a constant expression}}
+  // expected-note at -2 {{non-literal type 'X' cannot be used in a constant expression}}
+  constexpr NonDefaultMembers(NonDefaultMembers const&) {}; // expected-warning {{constexpr constructor that never produces a constant expression is incompatible with C++ standards before C++23}}
+  // expected-note at -1 {{non-constexpr constructor 'X' cannot be used in a constant expression}}
+  constexpr NonDefaultMembers(NonDefaultMembers &&) {}; // expected-warning {{constexpr constructor that never produces a constant expression is incompatible with C++ standards before C++23}}
+  // expected-note at -1 {{non-constexpr constructor 'X' cannot be used in a constant expression}}
+  constexpr NonDefaultMembers& operator=(NonDefaultMembers &other) {this->t = other.t; return *this;}
+  constexpr NonDefaultMembers& operator=(NonDefaultMembers&& other) {this->t = other.t; return *this;}
+  constexpr bool operator==(NonDefaultMembers const& other) const {return this->t == other.t;}
+  X t;
+};
+
+static int Glob = 0; // expected-note {{declared here}}
+class C1 {
+public:
+  constexpr C1() : D(Glob) {}; // expected-warning {{constexpr constructor that never produces a constant expression is incompatible with C++ standards before C++23}}
+  // expected-note at -1 {{read of non-const variable 'Glob' is not allowed in a constant expression}}
+private:
+  int D;
+};
+
+void test() {
+
+  constexpr int A = F(3); // expected-error {{constexpr variable 'A' must be initialized by a constant expression}}
+                          // expected-note at -1 {{in call}}
+  F(3);
+  constexpr int B = F0(0); // expected-error {{constexpr variable 'B' must be initialized by a constant expression}}
+                           // expected-note at -1 {{in call}}
+  F0(0);
+  constexpr auto C = F1(); // expected-error {{constexpr variable cannot have non-literal type 'const NonLiteral'}}
+  F1();
+  NonLiteral L;
+  constexpr auto D = F2(L); // expected-error {{constexpr variable 'D' must be initialized by a constant expression}}
+                            // expected-note at -1 {{non-literal type 'NonLiteral' cannot be used in a constant expression}}
+
+  constexpr auto E = FT(1); // expected-error {{constexpr variable 'E' must be initialized by a constant expression}}
+                            // expected-note at -1 {{in call}}
+  F2(L);
+
+  Wrapper<X> x; // expected-note {{requested here}}
+  WrapperNonT x1;
+  NonDefaultMembers x2;
+
+  // TODO produces note with an invalid source location
+  // static_assert((Wrapper<X>(), true));
+  
+  static_assert((WrapperNonT(), true)); // expected-error{{expression is not an integral constant expression}}\
+                                        // expected-note {{non-constexpr constructor 'WrapperNonT' cannot be used in a constant expression}}
+  static_assert((NonDefaultMembers(), true)); // expected-error{{expression is not an integral constant expression}} \
+                                              // expected-note {{in call to}}
+  constexpr bool FFF = (NonDefaultMembers() == NonDefaultMembers()); // expected-error{{must be initialized by a constant expression}} \
+                                                                     // expected-note{{non-literal}}
+
+}
diff --git a/clang/test/SemaCXX/cxx2a-consteval.cpp b/clang/test/SemaCXX/cxx2a-consteval.cpp
index d8482ec53f0ed4..0a3eb29675844b 100644
--- a/clang/test/SemaCXX/cxx2a-consteval.cpp
+++ b/clang/test/SemaCXX/cxx2a-consteval.cpp
@@ -54,7 +54,7 @@ struct C {
 
 struct D {
   C c;
-  consteval D() = default; // expected-error {{cannot be consteval}}
+  consteval D() = default; // expected-error {{marked consteval but never produces a constant expression}}
   consteval ~D() = default; // expected-error {{destructor cannot be declared consteval}}
 };
 
@@ -884,7 +884,7 @@ void func() {
   S<Baz, 3> s7;
 }
 
-consteval int aConstevalFunction() { // expected-error {{consteval function never produces a constant expression}}
+consteval int aConstevalFunction() { // expected-error {{consteval function that never produces a constant expression}}
   // Defaulted default constructors are implicitly consteval.
   S<Bar, 1> s1;
 
diff --git a/clang/test/SemaCXX/deduced-return-type-cxx14.cpp b/clang/test/SemaCXX/deduced-return-type-cxx14.cpp
index eac9c587869f55..90856b59e999cd 100644
--- a/clang/test/SemaCXX/deduced-return-type-cxx14.cpp
+++ b/clang/test/SemaCXX/deduced-return-type-cxx14.cpp
@@ -1,8 +1,8 @@
 // RUN: %clang_cc1 -std=c++23 -fsyntax-only -verify=expected,cxx20_23,cxx23    %s
 // RUN: %clang_cc1 -std=c++23 -fsyntax-only -verify=expected,cxx20_23,cxx23    %s -fdelayed-template-parsing -DDELAYED_TEMPLATE_PARSING
 
-// RUN: %clang_cc1 -std=c++20 -fsyntax-only -verify=expected,cxx14_20,cxx20_23 %s
-// RUN: %clang_cc1 -std=c++20 -fsyntax-only -verify=expected,cxx14_20,cxx20_23 %s -fdelayed-template-parsing -DDELAYED_TEMPLATE_PARSING
+// RUN: %clang_cc1 -std=c++20 -fsyntax-only -verify=expected,cxx14_20,cxx20_23,cxx20 %s
+// RUN: %clang_cc1 -std=c++20 -fsyntax-only -verify=expected,cxx14_20,cxx20_23,cxx20 %s -fdelayed-template-parsing -DDELAYED_TEMPLATE_PARSING
 
 // RUN: %clang_cc1 -std=c++14 -fsyntax-only -verify=expected,cxx14_20,cxx14    %s
 // RUN: %clang_cc1 -std=c++14 -fsyntax-only -verify=expected,cxx14_20,cxx14    %s -fdelayed-template-parsing -DDELAYED_TEMPLATE_PARSING
@@ -299,8 +299,8 @@ namespace Constexpr {
     constexpr int q = Y<int>().f(); // expected-error {{must be initialized by a constant expression}} expected-note {{in call to 'Y<int>().f()'}}
   }
   struct NonLiteral { ~NonLiteral(); } nl; // cxx14-note {{user-provided destructor}}
-  // cxx20_23-note at -1 {{'NonLiteral' is not literal because its destructor is not constexpr}}
-  constexpr auto f2(int n) { return nl; } // expected-error {{return type 'struct NonLiteral' is not a literal type}}
+  // cxx20-note at -1 {{'NonLiteral' is not literal because its destructor is not constexpr}}
+  constexpr auto f2(int n) { return nl; } // cxx14_20-error {{with non-literal return type 'struct NonLiteral' is a C++23 extension}}
 }
 
 // It's not really clear whether these are valid, but this matches g++.
diff --git a/clang/test/SemaCXX/ms-constexpr-invalid.cpp b/clang/test/SemaCXX/ms-constexpr-invalid.cpp
index e5bec0c7119b02..94a4d62515ee87 100644
--- a/clang/test/SemaCXX/ms-constexpr-invalid.cpp
+++ b/clang/test/SemaCXX/ms-constexpr-invalid.cpp
@@ -5,7 +5,7 @@
 
 void runtime() {} // expected-note {{declared here}}
 
-[[msvc::constexpr]] void f0() { runtime(); } // expected-error {{constexpr function never produces a constant expression}} \
+[[msvc::constexpr]] void f0() { runtime(); } // expected-error {{constexpr function that never produces a constant expression}} \
                                              // expected-note {{non-constexpr function 'runtime' cannot be used in a constant expression}}
 [[msvc::constexpr]] constexpr void f1() {} // expected-error {{attribute 'msvc::constexpr' cannot be applied to the constexpr function 'f1'}}
 #if __cplusplus >= 202202L
@@ -31,13 +31,13 @@ static_assert(f5()); // expected-error {{static assertion expression is not an i
 
 int f6(int x) { [[msvc::constexpr]] return x > 1 ? 1 + f6(x / 2) : 0; } // expected-note {{declared here}} \
                                                                         // expected-note {{declared here}}
-constexpr bool f7() { [[msvc::constexpr]] return f6(32) == 5; } // expected-error {{constexpr function never produces a constant expression}} \
+constexpr bool f7() { [[msvc::constexpr]] return f6(32) == 5; } // expected-error {{constexpr function that never produces a constant expression}} \
                                                                 // expected-note {{non-constexpr function 'f6' cannot be used in a constant expression}} \
                                                                 // expected-note {{non-constexpr function 'f6' cannot be used in a constant expression}}
 static_assert(f7()); // expected-error {{static assertion expression is not an integral constant expression}} \
                      // expected-note {{in call to 'f7()'}}
 
-constexpr bool f8() { // expected-error {{constexpr function never produces a constant expression}}
+constexpr bool f8() { // expected-error {{constexpr function that never produces a constant expression}}
     [[msvc::constexpr]] f4(32); // expected-error {{'constexpr' attribute only applies to functions and return statements}} \
                                 // expected-note {{non-constexpr function 'f4' cannot be used in a constant expression}} \
                                 // expected-note {{non-constexpr function 'f4' cannot be used in a constant expression}}
diff --git a/clang/test/SemaCXX/ms-constexpr.cpp b/clang/test/SemaCXX/ms-constexpr.cpp
index 79f71a34cb7d84..6bf2dec91250c9 100644
--- a/clang/test/SemaCXX/ms-constexpr.cpp
+++ b/clang/test/SemaCXX/ms-constexpr.cpp
@@ -29,7 +29,7 @@ static_assert(test_get_msconstexpr_true());
 struct S2 {
     [[msvc::constexpr]] S2() {}
     [[msvc::constexpr]] bool value() { return true; }
-    static constexpr bool check() { [[msvc::constexpr]] return S2{}.value(); } // expected-error {{constexpr function never produces a constant expression}} \
+    static constexpr bool check() { [[msvc::constexpr]] return S2{}.value(); } // expected-error {{constexpr function that never produces a constant expression}} \
                                                                                // expected-note {{non-literal type 'S2' cannot be used in a constant expression}} \
                                                                                // expected-note {{non-literal type 'S2' cannot be used in a constant expression}}
 };
diff --git a/clang/test/SemaCXX/sizeless-1.cpp b/clang/test/SemaCXX/sizeless-1.cpp
index 368a3eeb6955bd..1300f9960ca751 100644
--- a/clang/test/SemaCXX/sizeless-1.cpp
+++ b/clang/test/SemaCXX/sizeless-1.cpp
@@ -303,7 +303,7 @@ struct constructible_from_sizeless {
 void with_default(svint8_t = svint8_t());
 
 #if __cplusplus >= 201103L
-constexpr int ce_taking_int8(svint8_t) { return 1; } // expected-error {{constexpr function's 1st parameter type 'svint8_t' (aka '__SVInt8_t') is not a literal type}}
+constexpr int ce_taking_int8(svint8_t) { return 1; } // expected-error {{constexpr function with 1st non-literal parameter type 'svint8_t' (aka '__SVInt8_t') is a C++23 extension}}
 #endif
 
 #if __cplusplus < 201703L
diff --git a/clang/test/SemaOpenCLCXX/addrspace-constructors.clcpp b/clang/test/SemaOpenCLCXX/addrspace-constructors.clcpp
index 1b97484767b1a5..23102b8ab88725 100644
--- a/clang/test/SemaOpenCLCXX/addrspace-constructors.clcpp
+++ b/clang/test/SemaOpenCLCXX/addrspace-constructors.clcpp
@@ -54,5 +54,5 @@ struct Z {
 
 struct W {
   int w;
-  constexpr W() __constant = default; // expected-error {{defaulted definition of default constructor is not constexpr}}
+  constexpr W() __constant = default; // expected-error {{defaulted definition of default constructor that marked constexpr but never produces a constant expression is a C++23 extension}}
 };
diff --git a/clang/www/cxx_status.html b/clang/www/cxx_status.html
index 197726f3aa3eee..0bec14c62765b7 100755
--- a/clang/www/cxx_status.html
+++ b/clang/www/cxx_status.html
@@ -356,14 +356,7 @@ <h2 id="cxx23">C++23 implementation status</h2>
     <tr>
       <td>Relaxing some constexpr restrictions</td>
       <td><a href="https://wg21.link/P2448R2">P2448R2</a></td>
-      <td class="partial" align="center">
-        <details><summary>Clang 17 (Partial)</summary>
-	  We do not support outside of defaulted special memeber functions the change that constexpr functions no
-          longer have to be constexpr compatible but rather support a less restricted requirements for constexpr
-          functions. Which include allowing non-literal types as return values and parameters, allow calling of
-          non-constexpr functions and constructors.
-        </details></td>
-      </td>
+      <td class="full" align="center">Clang 18</td>
     </tr>
     <tr>
       <td>Using unknown pointers and references in constant expressions</td>

>From 8527b69506cc08bf45d20ad86e891b4b5b3663ea Mon Sep 17 00:00:00 2001
From: "Podchishchaeva, Mariya" <mariya.podchishchaeva at intel.com>
Date: Wed, 17 Jan 2024 03:59:28 -0800
Subject: [PATCH 02/11] Make sure feature is actually backported

---
 clang/docs/LanguageExtensions.rst             |   1 +
 clang/docs/ReleaseNotes.rst                   |   3 +-
 clang/lib/Sema/SemaDeclCXX.cpp                |   3 +-
 clang/test/CXX/drs/dr13xx.cpp                 |   9 --
 .../test/SemaCXX/cxx23-invalid-constexpr.cpp  | 116 ++++++++++--------
 5 files changed, 69 insertions(+), 63 deletions(-)

diff --git a/clang/docs/LanguageExtensions.rst b/clang/docs/LanguageExtensions.rst
index c1420079f75118..eb83faebfebba1 100644
--- a/clang/docs/LanguageExtensions.rst
+++ b/clang/docs/LanguageExtensions.rst
@@ -1486,6 +1486,7 @@ Conditional ``explicit``               __cpp_conditional_explicit       C++20
 ``if consteval``                       __cpp_if_consteval               C++23         C++20
 ``static operator()``                  __cpp_static_call_operator       C++23         C++03
 Attributes on Lambda-Expressions                                        C++23         C++11
+Relaxing some constexpr restrictions   __cpp_constexpr                  C++23         C++11
 -------------------------------------- -------------------------------- ------------- -------------
 Designated initializers (N494)                                          C99           C89
 Array & element qualification (N2607)                                   C23           C89
diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst
index 23342a6a7256d8..ba005ccbc471e8 100644
--- a/clang/docs/ReleaseNotes.rst
+++ b/clang/docs/ReleaseNotes.rst
@@ -165,7 +165,8 @@ C++23 Feature Support
 - Added a separate warning to warn the use of attributes on lambdas as a C++23 extension
   in previous language versions: ``-Wc++23-lambda-attributes``.
 
-- Implemented `P2448R2: Relaxing some constexpr restrictions <https://wg21.link/P2448R2>`_.
+- Implemented `P2448R2: Relaxing some constexpr restrictions <https://wg21.link/P2448R2>`_
+  as a conforming extension.
 
 C++2c Feature Support
 ^^^^^^^^^^^^^^^^^^^^^
diff --git a/clang/lib/Sema/SemaDeclCXX.cpp b/clang/lib/Sema/SemaDeclCXX.cpp
index aa49dc73e157bf..f4affcd262b23a 100644
--- a/clang/lib/Sema/SemaDeclCXX.cpp
+++ b/clang/lib/Sema/SemaDeclCXX.cpp
@@ -7873,6 +7873,7 @@ bool Sema::CheckExplicitlyDefaultedSpecialMember(CXXMethodDecl *MD,
               << CSM;
           for (const auto &I : RD->vbases())
             Diag(I.getBeginLoc(), diag::note_constexpr_virtual_base_here);
+          HadError = true;
         } else {
           Diag(MD->getBeginLoc(),
                getLangOpts().CPlusPlus23
@@ -7881,8 +7882,6 @@ bool Sema::CheckExplicitlyDefaultedSpecialMember(CXXMethodDecl *MD,
               << CSM << MD->isConsteval();
         }
     // FIXME: Explain why the special member can't be constexpr.
-    if (!getLangOpts().CPlusPlus23)
-      HadError = true;
   }
 
   if (First) {
diff --git a/clang/test/CXX/drs/dr13xx.cpp b/clang/test/CXX/drs/dr13xx.cpp
index be656c4468eaeb..f025eff3a48c2d 100644
--- a/clang/test/CXX/drs/dr13xx.cpp
+++ b/clang/test/CXX/drs/dr13xx.cpp
@@ -433,18 +433,9 @@ namespace dr1359 { // dr1359: 3.5
 
   constexpr A a = A();
   constexpr B b = B();
-  // cxx11-17-error at -1 {{no matching constructor for initialization of 'B'}}
-  //   cxx11-17-note@#dr1359-B {{candidate constructor (the implicit copy constructor) not viable: requires 1 argument, but 0 were provided}}
-  //   cxx11-17-note@#dr1359-B {{candidate constructor (the implicit move constructor) not viable: requires 1 argument, but 0 were provided}}
   constexpr C c = C();
-  // cxx11-17-error at -1 {{no matching constructor for initialization of 'C'}}
-  //   cxx11-17-note@#dr1359-C {{candidate constructor (the implicit copy constructor) not viable: requires 1 argument, but 0 were provided}}
-  //   cxx11-17-note@#dr1359-C {{candidate constructor (the implicit move constructor) not viable: requires 1 argument, but 0 were provided}}
   constexpr X x = X();
   constexpr Y y = Y();
-  // cxx11-17-error at -1 {{no matching constructor for initialization of 'Y'}}
-  //   cxx11-17-note@#dr1359-Y {{candidate constructor (the implicit copy constructor) not viable: requires 1 argument, but 0 were provided}}
-  //   cxx11-17-note@#dr1359-Y {{candidate constructor (the implicit move constructor) not viable: requires 1 argument, but 0 were provided}}
 #endif
 }
 
diff --git a/clang/test/SemaCXX/cxx23-invalid-constexpr.cpp b/clang/test/SemaCXX/cxx23-invalid-constexpr.cpp
index 69562ebfeaf736..355495689ccd83 100644
--- a/clang/test/SemaCXX/cxx23-invalid-constexpr.cpp
+++ b/clang/test/SemaCXX/cxx23-invalid-constexpr.cpp
@@ -1,13 +1,18 @@
-// RUN: %clang_cc1 -fsyntax-only -verify -std=c++23 -Wpre-c++23-compat %s
+// RUN: %clang_cc1 -fsyntax-only -verify=expected,cxx23 -std=c++23 -Wpre-c++23-compat %s
+// RUN: %clang_cc1 -fsyntax-only -verify=expected -std=c++20 -Wno-c++23-extensions -Wno-invalid-constexpr %s
+// RUN: %clang_cc1 -fsyntax-only -verify=expected,precxx20 -std=c++17 -Wno-c++23-extensions -Wno-invalid-constexpr %s
+// RUN: %clang_cc1 -fsyntax-only -verify=expected,precxx20 -std=c++14 -Wno-c++23-extensions -Wno-invalid-constexpr %s
+// RUN: %clang_cc1 -fsyntax-only -verify=expected,precxx20,cxx11 -std=c++11 -Wno-c++14-extensions -Wno-c++23-extensions -Wno-invalid-constexpr -Wno-constexpr-not-const %s
 
-// This test covers modifications made by P2448R2 in C++23 mode.
+// This test covers modifications made by P2448R2.
 
 // Check that there is no error when a constexpr function that never produces a
 // constant expression, but still an error if such function is called from
 // constexpr context.
 constexpr int F(int N) {  
-  // expected-warning at -1 {{constexpr function that never produces a constant expression is incompatible with C++ standards before C++23}}
-  double D = 2.0 / 0.0; // expected-note 2{{division by zero}}
+  // cxx23-warning at -1 {{constexpr function that never produces a constant expression is incompatible with C++ standards before C++23}}
+  double D = 2.0 / 0.0; // cxx23-note {{division by zero}} \
+                        // expected-note {{division by zero}}
   return 1;
 }
 
@@ -25,44 +30,44 @@ constexpr int FT(T N) {
 }
 
 class NonLiteral {
-// expected-note at -1 3{{'NonLiteral' is not literal because it is not an aggregate and has no constexpr constructors other than copy or move constructors}}
+// cxx23-note at -1 3{{'NonLiteral' is not literal because it is not an aggregate and has no constexpr constructors other than copy or move constructors}}
 public:
-  NonLiteral() {} // expected-note 2{{declared here}}
+  NonLiteral() {} // cxx23-note 2{{declared here}}
   ~NonLiteral() {}
 };
 
 constexpr NonLiteral F1() {
-// expected-warning at -1 {{constexpr function with non-literal return type 'NonLiteral' is incompatible with C++ standards before C++23}}
-// expected-warning at -2 {{constexpr function that never produces a constant expression is incompatible with C++ standards before C++23}}
+// cxx23-warning at -1 {{constexpr function with non-literal return type 'NonLiteral' is incompatible with C++ standards before C++23}}
+// cxx23-warning at -2 {{constexpr function that never produces a constant expression is incompatible with C++ standards before C++23}}
   return NonLiteral{};
-// expected-note at -1 {{non-constexpr constructor 'NonLiteral' cannot be used in a constant expression}}
+// cxx23-note at -1 {{non-constexpr constructor 'NonLiteral' cannot be used in a constant expression}}
 }
 
 constexpr int F2(NonLiteral N) {
-  // expected-warning at -1 {{constexpr function with 1st non-literal parameter type 'NonLiteral' is not compatible with C++ standards before C++23}}
+  // cxx23-warning at -1 {{constexpr function with 1st non-literal parameter type 'NonLiteral' is not compatible with C++ standards before C++23}}
   return 8;
 }
 
-class Derived : public NonLiteral { // expected-note {{declared here}}
-  constexpr ~Derived() {};
-  // expected-warning at -1{{constexpr destructor is incompatible with C++ standards before C++23 because base class 'NonLiteral' does not have a constexpr destructor}}
+class Derived : public NonLiteral { // cxx23-note {{declared here}}
+  constexpr ~Derived() {}; // precxx20-error {{destructor cannot be declared constexpr}}
+  // cxx23-warning at -1{{constexpr destructor is incompatible with C++ standards before C++23 because base class 'NonLiteral' does not have a constexpr destructor}}
 
 };
 
 class Derived1 : public NonLiteral {
   constexpr Derived1() : NonLiteral () {}
-  // expected-warning at -1{{constexpr constructor that never produces a constant expression is incompatible with C++ standards before C++23}}
-  // expected-note at -2 {{non-constexpr constructor 'NonLiteral' cannot be used in a constant expression}}
+  // cxx23-warning at -1{{constexpr constructor that never produces a constant expression is incompatible with C++ standards before C++23}}
+  // cxx23-note at -2 {{non-constexpr constructor 'NonLiteral' cannot be used in a constant expression}}
 };
 
 
-struct X { // expected-note 2{{'X' is not literal because it is not an aggregate and has no constexpr constructors other than copy or move constructors}}
-  X(); // expected-note 3{{declared here}}
-  X(const X&); // expected-note 2{{declared here}}
+struct X { // cxx23-note 2{{'X' is not literal because it is not an aggregate and has no constexpr constructors other than copy or move constructors}}
+  X(); // cxx23-note 3{{declared here}}
+  X(const X&); // cxx23-note 2{{declared here}}
   X(X&&);
-  X& operator=(X&);
-  X& operator=(X&& other);
-  bool operator==(X const&) const; // expected-note 2{{non-constexpr comparison function declared here}}
+  X& operator=(X&); // cxx11-note 2{{not viable: 'this' argument has type 'const X', but method is not marked const}}
+  X& operator=(X&& other); // cxx11-note 2{{not viable: 'this' argument has type 'const X', but method is not marked const}}
+  bool operator==(X const&) const; // cxx23-note 2{{non-constexpr comparison function declared here}}
 };
 
 template <typename T>
@@ -71,48 +76,56 @@ struct Wrapper {
   constexpr Wrapper(Wrapper const&) = default;
   constexpr Wrapper(T const& t) : t(t) { }
   constexpr Wrapper(Wrapper &&) = default;
-  constexpr X get() const { return t; } // expected-warning {{constexpr function with non-literal return type 'X' is incompatible with C++ standards before C++23}}
-  constexpr bool operator==(Wrapper const&) const = default; // expected-warning {{defaulted definition of equality comparison operator that is declared constexpr but invokes a non-constexpr comparison function is incompatible with C++ standards before C++23}}
+  constexpr X get() const { return t; } // cxx23-warning {{constexpr function with non-literal return type 'X' is incompatible with C++ standards before C++23}}
+  constexpr bool operator==(Wrapper const&) const = default; // cxx23-warning {{defaulted definition of equality comparison operator that is declared constexpr but invokes a non-constexpr comparison function is incompatible with C++ standards before C++23}}
+  // precxx20-warning at -1 2{{defaulted comparison operators are a C++20 extension}}
 private:
-  T t; // expected-note {{non-constexpr comparison function would be used to compare member 't'}}
+  T t; // cxx23-note {{non-constexpr comparison function would be used to compare member 't'}}
 };
 
 struct WrapperNonT {
-  constexpr WrapperNonT() = default; // expected-warning {{defaulted definition of default constructor that marked constexpr but never produces a constant expression is incompatible with C++ standards before C++23}}
+  constexpr WrapperNonT() = default; // cxx23-warning {{defaulted definition of default constructor that marked constexpr but never produces a constant expression is incompatible with C++ standards before C++23}}
   // expected-note at -1 {{declared here}}
-  constexpr WrapperNonT(WrapperNonT const&) = default; // expected-warning {{defaulted definition of copy constructor that marked constexpr but never produces a constant expression is incompatible with C++ standards before C++23}}
-  constexpr WrapperNonT(X const& t) : t(t) { } // expected-warning {{constexpr constructor that never produces a constant expression is incompatible with C++ standards before C++23}}
-  // expected-note at -1 {{non-constexpr constructor 'X' cannot be used in a constant expression}}
-  constexpr WrapperNonT(WrapperNonT &&) = default; // expected-warning {{defaulted definition of move constructor that marked constexpr but never produces a constant expression is incompatible with C++ standards before C++23}}
-  constexpr WrapperNonT& operator=(WrapperNonT &) = default; // expected-warning {{defaulted definition of copy assignment operator that marked constexpr but never produces a constant expression is incompatible with C++ standards before C++23}}
-  constexpr WrapperNonT& operator=(WrapperNonT&& other) = default; // expected-warning {{defaulted definition of move assignment operator that marked constexpr but never produces a constant expression is incompatible with C++ standards before C++23}}
-  constexpr X get() const { return t; } // expected-warning {{constexpr function with non-literal return type 'X' is incompatible with C++ standards before C++23}}
-  // expected-warning at -1{{constexpr function that never produces a constant expression is incompatible with C++ standards before C++23}}
-  // expected-note at -2 {{non-constexpr constructor 'X' cannot be used in a constant expression}}
-  constexpr bool operator==(WrapperNonT const&) const = default; // expected-warning {{defaulted definition of equality comparison operator that is declared constexpr but invokes a non-constexpr comparison function is incompatible with C++ standards before C++23}}
+  constexpr WrapperNonT(WrapperNonT const&) = default; // cxx23-warning {{defaulted definition of copy constructor that marked constexpr but never produces a constant expression is incompatible with C++ standards before C++23}}
+  constexpr WrapperNonT(X const& t) : t(t) { } // cxx23-warning {{constexpr constructor that never produces a constant expression is incompatible with C++ standards before C++23}}
+  // cxx23-note at -1 {{non-constexpr constructor 'X' cannot be used in a constant expression}}
+  constexpr WrapperNonT(WrapperNonT &&) = default; // cxx23-warning {{defaulted definition of move constructor that marked constexpr but never produces a constant expression is incompatible with C++ standards before C++23}}
+  constexpr WrapperNonT& operator=(WrapperNonT &) = default; // cxx23-warning {{defaulted definition of copy assignment operator that marked constexpr but never produces a constant expression is incompatible with C++ standards before C++23}}
+  // cxx11-error at -1 {{an explicitly-defaulted copy assignment operator may not have 'const', 'constexpr' or 'volatile' qualifiers}}
+  constexpr WrapperNonT& operator=(WrapperNonT&& other) = default; // cxx23-warning {{defaulted definition of move assignment operator that marked constexpr but never produces a constant expression is incompatible with C++ standards before C++23}}
+  // cxx11-error at -1 {{an explicitly-defaulted move assignment operator may not have 'const', 'constexpr' or 'volatile' qualifiers}}
+  constexpr X get() const { return t; } // cxx23-warning {{constexpr function with non-literal return type 'X' is incompatible with C++ standards before C++23}}
+  // cxx23-warning at -1{{constexpr function that never produces a constant expression is incompatible with C++ standards before C++23}}
+  // cxx23-note at -2 {{non-constexpr constructor 'X' cannot be used in a constant expression}}
+  constexpr bool operator==(WrapperNonT const&) const = default; // cxx23-warning {{defaulted definition of equality comparison operator that is declared constexpr but invokes a non-constexpr comparison function is incompatible with C++ standards before C++23}}
+  // precxx20-warning at -1 {{defaulted comparison operators are a C++20 extension}}
 private:
-  X t; // expected-note {{non-constexpr comparison function would be used to compare member 't'}}
+  X t; // cxx23-note {{non-constexpr comparison function would be used to compare member 't'}}
 };
 
 struct NonDefaultMembers {
-  constexpr NonDefaultMembers() {}; // expected-warning {{constexpr constructor that never produces a constant expression is incompatible with C++ standards before C++23}}
-  // expected-note at -1 {{non-constexpr constructor 'X' cannot be used in a constant expression}}
+  constexpr NonDefaultMembers() {}; // cxx23-warning {{constexpr constructor that never produces a constant expression is incompatible with C++ standards before C++23}}
+  // cxx23-note at -1 {{non-constexpr constructor 'X' cannot be used in a constant expression}}
   // expected-note at -2 {{non-literal type 'X' cannot be used in a constant expression}}
-  constexpr NonDefaultMembers(NonDefaultMembers const&) {}; // expected-warning {{constexpr constructor that never produces a constant expression is incompatible with C++ standards before C++23}}
-  // expected-note at -1 {{non-constexpr constructor 'X' cannot be used in a constant expression}}
-  constexpr NonDefaultMembers(NonDefaultMembers &&) {}; // expected-warning {{constexpr constructor that never produces a constant expression is incompatible with C++ standards before C++23}}
-  // expected-note at -1 {{non-constexpr constructor 'X' cannot be used in a constant expression}}
+  constexpr NonDefaultMembers(NonDefaultMembers const&) {}; // cxx23-warning {{constexpr constructor that never produces a constant expression is incompatible with C++ standards before C++23}}
+  // cxx23-note at -1 {{non-constexpr constructor 'X' cannot be used in a constant expression}}
+  constexpr NonDefaultMembers(NonDefaultMembers &&) {}; // cxx23-warning {{constexpr constructor that never produces a constant expression is incompatible with C++ standards before C++23}}
+  // cxx23-note at -1 {{non-constexpr constructor 'X' cannot be used in a constant expression}}
   constexpr NonDefaultMembers& operator=(NonDefaultMembers &other) {this->t = other.t; return *this;}
+  // cxx11-error at -1 {{no viable overloaded '='}}
+  // cxx11-error at -2 {{binding reference of type 'NonDefaultMembers' to value of type 'const NonDefaultMembers' drops 'const' qualifier}}
   constexpr NonDefaultMembers& operator=(NonDefaultMembers&& other) {this->t = other.t; return *this;}
+  // cxx11-error at -1 {{no viable overloaded '='}}
+  // cxx11-error at -2 {{binding reference of type 'NonDefaultMembers' to value of type 'const NonDefaultMembers' drops 'const' qualifier}}
   constexpr bool operator==(NonDefaultMembers const& other) const {return this->t == other.t;}
   X t;
 };
 
-static int Glob = 0; // expected-note {{declared here}}
+static int Glob = 0; // cxx23-note {{declared here}}
 class C1 {
 public:
-  constexpr C1() : D(Glob) {}; // expected-warning {{constexpr constructor that never produces a constant expression is incompatible with C++ standards before C++23}}
-  // expected-note at -1 {{read of non-const variable 'Glob' is not allowed in a constant expression}}
+  constexpr C1() : D(Glob) {}; // cxx23-warning {{constexpr constructor that never produces a constant expression is incompatible with C++ standards before C++23}}
+  // cxx23-note at -1 {{read of non-const variable 'Glob' is not allowed in a constant expression}}
 private:
   int D;
 };
@@ -125,26 +138,27 @@ void test() {
   constexpr int B = F0(0); // expected-error {{constexpr variable 'B' must be initialized by a constant expression}}
                            // expected-note at -1 {{in call}}
   F0(0);
-  constexpr auto C = F1(); // expected-error {{constexpr variable cannot have non-literal type 'const NonLiteral'}}
+  constexpr auto C = F1(); // cxx23-error {{constexpr variable cannot have non-literal type 'const NonLiteral'}}
   F1();
   NonLiteral L;
-  constexpr auto D = F2(L); // expected-error {{constexpr variable 'D' must be initialized by a constant expression}}
-                            // expected-note at -1 {{non-literal type 'NonLiteral' cannot be used in a constant expression}}
+  constexpr auto D = F2(L); // cxx23-error {{constexpr variable 'D' must be initialized by a constant expression}}
+                            // cxx23-note at -1 {{non-literal type 'NonLiteral' cannot be used in a constant expression}}
 
   constexpr auto E = FT(1); // expected-error {{constexpr variable 'E' must be initialized by a constant expression}}
                             // expected-note at -1 {{in call}}
   F2(L);
 
-  Wrapper<X> x; // expected-note {{requested here}}
+  Wrapper<X> x; // cxx23-note {{requested here}}
+                // precxx20-note at -1 {{requested here}}
   WrapperNonT x1;
   NonDefaultMembers x2;
 
   // TODO produces note with an invalid source location
   // static_assert((Wrapper<X>(), true));
   
-  static_assert((WrapperNonT(), true)); // expected-error{{expression is not an integral constant expression}}\
+  static_assert((WrapperNonT(), true),""); // expected-error{{expression is not an integral constant expression}}\
                                         // expected-note {{non-constexpr constructor 'WrapperNonT' cannot be used in a constant expression}}
-  static_assert((NonDefaultMembers(), true)); // expected-error{{expression is not an integral constant expression}} \
+  static_assert((NonDefaultMembers(), true),""); // expected-error{{expression is not an integral constant expression}} \
                                               // expected-note {{in call to}}
   constexpr bool FFF = (NonDefaultMembers() == NonDefaultMembers()); // expected-error{{must be initialized by a constant expression}} \
                                                                      // expected-note{{non-literal}}

>From 8ca1f210d51c584783948c2d0ea708ba7bf8796e Mon Sep 17 00:00:00 2001
From: "Podchishchaeva, Mariya" <mariya.podchishchaeva at intel.com>
Date: Wed, 17 Jan 2024 04:14:27 -0800
Subject: [PATCH 03/11] Minor changes applied

---
 clang/lib/Sema/SemaDeclCXX.cpp | 20 +++++---------------
 clang/test/CXX/drs/dr13xx.cpp  |  4 ++--
 clang/test/CXX/drs/dr16xx.cpp  |  2 +-
 clang/test/CXX/drs/dr6xx.cpp   |  2 +-
 4 files changed, 9 insertions(+), 19 deletions(-)

diff --git a/clang/lib/Sema/SemaDeclCXX.cpp b/clang/lib/Sema/SemaDeclCXX.cpp
index f4affcd262b23a..a9c1bcf5db7267 100644
--- a/clang/lib/Sema/SemaDeclCXX.cpp
+++ b/clang/lib/Sema/SemaDeclCXX.cpp
@@ -1731,11 +1731,7 @@ static bool CheckConstexprDestructorSubobjects(Sema &SemaRef,
       SemaRef.Diag(Loc, diag::note_constexpr_dtor_subobject)
           << !FD << (FD ? FD->getDeclName() : DeclarationName()) << T;
     }
-
-    if (SemaRef.getLangOpts().CPlusPlus23)
-      return true;
-
-    return false;
+    return !!SemaRef.getLangOpts().CPlusPlus23;
   };
 
   const CXXRecordDecl *RD = DD->getParent();
@@ -1767,11 +1763,8 @@ static bool CheckConstexprParameterTypes(Sema &SemaRef,
                 ? diag::warn_cxx23_compat_constexpr_non_literal_param
                 : diag::ext_constexpr_non_literal_param,
             ArgIndex + 1, PD->getSourceRange(), isa<CXXConstructorDecl>(FD),
-            FD->isConsteval())) {
-      if (SemaRef.getLangOpts().CPlusPlus23)
-        return true;
-      return false;
-    }
+            FD->isConsteval()))
+      return SemaRef.getLangOpts().CPlusPlus23;
   }
   return true;
 }
@@ -1785,11 +1778,8 @@ static bool CheckConstexprReturnType(Sema &SemaRef, const FunctionDecl *FD,
           SemaRef.getLangOpts().CPlusPlus23
               ? diag::warn_cxx23_compat_constexpr_non_literal_return
               : diag::ext_constexpr_non_literal_return,
-          FD->isConsteval())) {
-    if (SemaRef.getLangOpts().CPlusPlus23)
-      return true;
-    return false;
-  }
+          FD->isConsteval()))
+    return SemaRef.getLangOpts().CPlusPlus23;
   return true;
 }
 
diff --git a/clang/test/CXX/drs/dr13xx.cpp b/clang/test/CXX/drs/dr13xx.cpp
index f025eff3a48c2d..f2457194e8d443 100644
--- a/clang/test/CXX/drs/dr13xx.cpp
+++ b/clang/test/CXX/drs/dr13xx.cpp
@@ -411,10 +411,10 @@ namespace dr1358 { // dr1358: 3.1
     int member;
     constexpr B(NonLit u) : member(u) {}
     // cxx11-20-error at -1 {{constexpr constructor with 1st non-literal parameter type 'NonLit' is a C++23 extension}}
-    // cxx11-20-note@#dr1358-NonLit {{'NonLit' is not literal because it is not an aggregate and has no constexpr constructors other than copy or move constructors}}
+    //   cxx11-20-note@#dr1358-NonLit {{'NonLit' is not literal because it is not an aggregate and has no constexpr constructors other than copy or move constructors}}
     constexpr NonLit f(NonLit u) const { return NonLit(); }
     // cxx11-20-error at -1 {{constexpr function with non-literal return type 'NonLit' is a C++23 extension}}
-    // cxx11-20-note@#dr1358-NonLit {{'NonLit' is not literal because it is not an aggregate and has no constexpr constructors other than copy or move constructors}}
+    //   cxx11-20-note@#dr1358-NonLit {{'NonLit' is not literal because it is not an aggregate and has no constexpr constructors other than copy or move constructors}}
   };
 #endif
 }
diff --git a/clang/test/CXX/drs/dr16xx.cpp b/clang/test/CXX/drs/dr16xx.cpp
index 1cf7bb840507ff..c00e1f483c123a 100644
--- a/clang/test/CXX/drs/dr16xx.cpp
+++ b/clang/test/CXX/drs/dr16xx.cpp
@@ -350,7 +350,7 @@ namespace dr1684 { // dr1684: 3.6
   constexpr int f(NonLiteral &) { return 0; }
   constexpr int f(NonLiteral) { return 0; }
   // cxx11-20-error at -1 {{constexpr function with 1st non-literal parameter type 'NonLiteral' is a C++23 extension}}
-  // cxx11-20-note@#dr1684-struct {{'NonLiteral' is not literal because it is not an aggregate and has no constexpr constructors other than copy or move constructors}}
+  //   cxx11-20-note@#dr1684-struct {{'NonLiteral' is not literal because it is not an aggregate and has no constexpr constructors other than copy or move constructors}}
 #endif
 }
 
diff --git a/clang/test/CXX/drs/dr6xx.cpp b/clang/test/CXX/drs/dr6xx.cpp
index 17e32dcc51ac98..7d4ab70a32adb7 100644
--- a/clang/test/CXX/drs/dr6xx.cpp
+++ b/clang/test/CXX/drs/dr6xx.cpp
@@ -585,7 +585,7 @@ namespace dr647 { // dr647: 3.1
     constexpr C(NonLiteral);
     constexpr C(NonLiteral, int) {}
     // cxx11-20-error at -1 {{constexpr constructor with 1st non-literal parameter type 'NonLiteral' is a C++23 extension}}
-    // cxx11-20-note@#dr647-NonLiteral {{'NonLiteral' is not literal because it is not an aggregate and has no constexpr constructors other than copy or move constructors}}
+    //   cxx11-20-note@#dr647-NonLiteral {{'NonLiteral' is not literal because it is not an aggregate and has no constexpr constructors other than copy or move constructors}}
     constexpr C() try {} catch (...) {}
     // cxx11-17-error at -1 {{function try block in constexpr constructor is a C++20 extension}}
     // cxx11-error at -2 {{use of this statement in a constexpr constructor is a C++14 extension}}

>From b365e48a36550d68dda83515b790e3beaf6d7893 Mon Sep 17 00:00:00 2001
From: "Podchishchaeva, Mariya" <mariya.podchishchaeva at intel.com>
Date: Wed, 17 Jan 2024 04:21:12 -0800
Subject: [PATCH 04/11] Clang 18 is unreleased

---
 clang/www/cxx_status.html | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/clang/www/cxx_status.html b/clang/www/cxx_status.html
index 0bec14c62765b7..b60d0329854765 100755
--- a/clang/www/cxx_status.html
+++ b/clang/www/cxx_status.html
@@ -356,7 +356,7 @@ <h2 id="cxx23">C++23 implementation status</h2>
     <tr>
       <td>Relaxing some constexpr restrictions</td>
       <td><a href="https://wg21.link/P2448R2">P2448R2</a></td>
-      <td class="full" align="center">Clang 18</td>
+      <td class="unreleased" align="center">Clang 18</td>
     </tr>
     <tr>
       <td>Using unknown pointers and references in constant expressions</td>

>From 1a35417ff41c818bc721fa0aaa944d2eca708849 Mon Sep 17 00:00:00 2001
From: "Podchishchaeva, Mariya" <mariya.podchishchaeva at intel.com>
Date: Wed, 17 Jan 2024 04:55:43 -0800
Subject: [PATCH 05/11] Make format happy

---
 clang/lib/Sema/SemaDeclCXX.cpp | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/clang/lib/Sema/SemaDeclCXX.cpp b/clang/lib/Sema/SemaDeclCXX.cpp
index 6fadca805b35ac..5adc825c03f06e 100644
--- a/clang/lib/Sema/SemaDeclCXX.cpp
+++ b/clang/lib/Sema/SemaDeclCXX.cpp
@@ -7871,7 +7871,7 @@ bool Sema::CheckExplicitlyDefaultedSpecialMember(CXXMethodDecl *MD,
                    : diag::ext_incorrect_defaulted_constexpr)
               << CSM << MD->isConsteval();
         }
-    // FIXME: Explain why the special member can't be constexpr.
+        // FIXME: Explain why the special member can't be constexpr.
   }
 
   if (First) {

>From 0a0253fb66a74503b5f91962accdc0c7cdbe7a9a Mon Sep 17 00:00:00 2001
From: "Podchishchaeva, Mariya" <mariya.podchishchaeva at intel.com>
Date: Thu, 18 Jan 2024 06:35:08 -0800
Subject: [PATCH 06/11] Fix diagnostic concern

---
 clang/include/clang/Basic/DiagnosticSemaKinds.td | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td b/clang/include/clang/Basic/DiagnosticSemaKinds.td
index af92472bf9e6ae..0be20d46369648 100644
--- a/clang/include/clang/Basic/DiagnosticSemaKinds.td
+++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td
@@ -2769,7 +2769,7 @@ def ext_constexpr_dtor_subobject : ExtWarn<
   "destructor cannot be declared %sub{select_constexpr_spec_kind}0 before C++23 because "
   "%select{data member %2|base class %3}1 does not have a "
   "constexpr destructor">, InGroup<CXX23>, DefaultError;
-def warn_cxx23_compat_constexpr_dtor_subobject : ExtWarn<
+def warn_cxx23_compat_constexpr_dtor_subobject : Warning<
   "%sub{select_constexpr_spec_kind}0 destructor is incompatible with C++ standards before C++23 because "
   "%select{data member %2|base class %3}1 does not have a "
   "constexpr destructor">, InGroup<CXXPre23Compat>, DefaultIgnore;

>From 28a3fcd825a1c761c7c62774431997c6b9a57293 Mon Sep 17 00:00:00 2001
From: "Podchishchaeva, Mariya" <mariya.podchishchaeva at intel.com>
Date: Tue, 23 Jan 2024 08:51:13 -0800
Subject: [PATCH 07/11] Make defaulted special members actually constexpr

---
 .../clang/Basic/DiagnosticSemaKinds.td        |  3 -
 clang/lib/AST/DeclCXX.cpp                     | 11 ++--
 clang/lib/Sema/SemaDeclCXX.cpp                | 61 ++++++++++---------
 clang/test/CXX/drs/dr15xx.cpp                 | 21 ++++---
 clang/test/CXX/drs/dr16xx.cpp                 |  8 +--
 .../SemaCXX/constant-expression-cxx11.cpp     | 11 ++--
 .../test/SemaCXX/cxx23-invalid-constexpr.cpp  | 22 +++----
 7 files changed, 70 insertions(+), 67 deletions(-)

diff --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td b/clang/include/clang/Basic/DiagnosticSemaKinds.td
index 0be20d46369648..a0e203a9bccd64 100644
--- a/clang/include/clang/Basic/DiagnosticSemaKinds.td
+++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td
@@ -9565,9 +9565,6 @@ def err_defaulted_copy_assign_not_ref : Error<
 def ext_incorrect_defaulted_constexpr : ExtWarn<
   "defaulted definition of %sub{select_special_member_kind}0 that marked %select{constexpr|consteval}1 "
   "but never produces a constant expression is a C++23 extension">, InGroup<CXX23>, DefaultError;
-def warn_cxx23_compat_incorrect_defaulted_constexpr : Warning<
-  "defaulted definition of %sub{select_special_member_kind}0 that marked %select{constexpr|consteval}1 "
-  "but never produces a constant expression is incompatible with C++ standards before C++23">, InGroup<CXXPre23Compat>, DefaultIgnore;
 def err_incorrect_defaulted_constexpr_with_vb: Error<
   "%sub{select_special_member_kind}0 cannot be 'constexpr' in a class with virtual base class">;
 def warn_defaulted_method_deleted : Warning<
diff --git a/clang/lib/AST/DeclCXX.cpp b/clang/lib/AST/DeclCXX.cpp
index 117e802dae2d9d..1da9fa4bbb4eb1 100644
--- a/clang/lib/AST/DeclCXX.cpp
+++ b/clang/lib/AST/DeclCXX.cpp
@@ -400,10 +400,11 @@ CXXRecordDecl::setBases(CXXBaseSpecifier const * const *Bases,
 
       // C++11 [class.ctor]p6:
       //   If that user-written default constructor would satisfy the
-      //   requirements of a constexpr constructor, the implicitly-defined
+      //   requirements of a constexpr constructor/function(C++23), the implicitly-defined
       //   default constructor is constexpr.
       if (!BaseClassDecl->hasConstexprDefaultConstructor())
-        data().DefaultedDefaultConstructorIsConstexpr = false;
+        data().DefaultedDefaultConstructorIsConstexpr =
+            C.getLangOpts().CPlusPlus23;
 
       // C++1z [class.copy]p8:
       //   The implicitly-declared copy constructor for a class X will have
@@ -548,7 +549,8 @@ void CXXRecordDecl::addedClassSubobject(CXXRecordDecl *Subobj) {
   //   -- for every subobject of class type or (possibly multi-dimensional)
   //      array thereof, that class type shall have a constexpr destructor
   if (!Subobj->hasConstexprDestructor())
-    data().DefaultedDestructorIsConstexpr = false;
+    data().DefaultedDestructorIsConstexpr =
+        getASTContext().getLangOpts().CPlusPlus23;
 
   // C++20 [temp.param]p7:
   //   A structural type is [...] a literal class type [for which] the types
@@ -1297,7 +1299,8 @@ void CXXRecordDecl::addedMember(Decl *D) {
             !FieldRec->hasConstexprDefaultConstructor() && !isUnion())
           // The standard requires any in-class initializer to be a constant
           // expression. We consider this to be a defect.
-          data().DefaultedDefaultConstructorIsConstexpr = false;
+          data().DefaultedDefaultConstructorIsConstexpr =
+              Context.getLangOpts().CPlusPlus23;
 
         // C++11 [class.copy]p8:
         //   The implicitly-declared copy constructor for a class X will have
diff --git a/clang/lib/Sema/SemaDeclCXX.cpp b/clang/lib/Sema/SemaDeclCXX.cpp
index 14712ae34cae42..85cf291519c0ea 100644
--- a/clang/lib/Sema/SemaDeclCXX.cpp
+++ b/clang/lib/Sema/SemaDeclCXX.cpp
@@ -1873,8 +1873,9 @@ bool Sema::CheckConstexprFunctionDefinition(const FunctionDecl *NewFD,
   if (auto *Dtor = dyn_cast<CXXDestructorDecl>(NewFD)) {
     // A destructor can be constexpr only if the defaulted destructor could be;
     // we don't need to check the members and bases if we already know they all
-    // have constexpr destructors.
-    if (!Dtor->getParent()->defaultedDestructorIsConstexpr()) {
+    // have constexpr destructors. (removed in C++23)
+    if (!getLangOpts().CPlusPlus23 &&
+        !Dtor->getParent()->defaultedDestructorIsConstexpr()) {
       if (Kind == CheckConstexprKind::CheckValid)
         return false;
       if (!CheckConstexprDestructorSubobjects(*this, Dtor, Kind))
@@ -7535,21 +7536,23 @@ static bool defaultedSpecialMemberIsConstexpr(
 
   // C++1y [class.copy]p26:
   //   -- [the class] is a literal type, and
-  if (!Ctor && !ClassDecl->isLiteral())
+  if (!Ctor && !ClassDecl->isLiteral() && !S.getLangOpts().CPlusPlus23)
     return false;
 
   //   -- every constructor involved in initializing [...] base class
   //      sub-objects shall be a constexpr constructor;
   //   -- the assignment operator selected to copy/move each direct base
   //      class is a constexpr function, and
-  for (const auto &B : ClassDecl->bases()) {
-    const RecordType *BaseType = B.getType()->getAs<RecordType>();
-    if (!BaseType)
-      continue;
-    CXXRecordDecl *BaseClassDecl = cast<CXXRecordDecl>(BaseType->getDecl());
-    if (!specialMemberIsConstexpr(S, BaseClassDecl, CSM, 0, ConstArg,
-                                  InheritedCtor, Inherited))
-      return false;
+  if (!S.getLangOpts().CPlusPlus23) {
+    for (const auto &B : ClassDecl->bases()) {
+      const RecordType *BaseType = B.getType()->getAs<RecordType>();
+      if (!BaseType)
+        continue;
+      CXXRecordDecl *BaseClassDecl = cast<CXXRecordDecl>(BaseType->getDecl());
+      if (!specialMemberIsConstexpr(S, BaseClassDecl, CSM, 0, ConstArg,
+                                    InheritedCtor, Inherited))
+        return false;
+    }
   }
 
   //   -- every constructor involved in initializing non-static data members
@@ -7559,20 +7562,22 @@ static bool defaultedSpecialMemberIsConstexpr(
   //   -- for each non-static data member of X that is of class type (or array
   //      thereof), the assignment operator selected to copy/move that member is
   //      a constexpr function
-  for (const auto *F : ClassDecl->fields()) {
-    if (F->isInvalidDecl())
-      continue;
-    if (CSM == Sema::CXXDefaultConstructor && F->hasInClassInitializer())
-      continue;
-    QualType BaseType = S.Context.getBaseElementType(F->getType());
-    if (const RecordType *RecordTy = BaseType->getAs<RecordType>()) {
-      CXXRecordDecl *FieldRecDecl = cast<CXXRecordDecl>(RecordTy->getDecl());
-      if (!specialMemberIsConstexpr(S, FieldRecDecl, CSM,
-                                    BaseType.getCVRQualifiers(),
-                                    ConstArg && !F->isMutable()))
+  if (!S.getLangOpts().CPlusPlus23) {
+    for (const auto *F : ClassDecl->fields()) {
+      if (F->isInvalidDecl())
+        continue;
+      if (CSM == Sema::CXXDefaultConstructor && F->hasInClassInitializer())
+        continue;
+      QualType BaseType = S.Context.getBaseElementType(F->getType());
+      if (const RecordType *RecordTy = BaseType->getAs<RecordType>()) {
+        CXXRecordDecl *FieldRecDecl = cast<CXXRecordDecl>(RecordTy->getDecl());
+        if (!specialMemberIsConstexpr(S, FieldRecDecl, CSM,
+                                      BaseType.getCVRQualifiers(),
+                                      ConstArg && !F->isMutable()))
+          return false;
+      } else if (CSM == Sema::CXXDefaultConstructor) {
         return false;
-    } else if (CSM == Sema::CXXDefaultConstructor) {
-      return false;
+      }
     }
   }
 
@@ -7864,10 +7869,7 @@ bool Sema::CheckExplicitlyDefaultedSpecialMember(CXXMethodDecl *MD,
             Diag(I.getBeginLoc(), diag::note_constexpr_virtual_base_here);
           HadError = true;
         } else {
-          Diag(MD->getBeginLoc(),
-               getLangOpts().CPlusPlus23
-                   ? diag::warn_cxx23_compat_incorrect_defaulted_constexpr
-                   : diag::ext_incorrect_defaulted_constexpr)
+          Diag(MD->getBeginLoc(), diag::ext_incorrect_defaulted_constexpr)
               << CSM << MD->isConsteval();
         }
         // FIXME: Explain why the special member can't be constexpr.
@@ -9121,7 +9123,8 @@ bool Sema::CheckExplicitlyDefaultedComparison(Scope *S, FunctionDecl *FD,
   //   declaration, it is implicitly considered to be constexpr.
   // FIXME: Only applying this to the first declaration seems problematic, as
   // simple reorderings can affect the meaning of the program.
-  if (First && !FD->isConstexpr() && Info.Constexpr)
+  if ((First && !FD->isConstexpr() && Info.Constexpr) ||
+      getLangOpts().CPlusPlus23)
     FD->setConstexprKind(ConstexprSpecKind::Constexpr);
 
   // C++2a [except.spec]p3:
diff --git a/clang/test/CXX/drs/dr15xx.cpp b/clang/test/CXX/drs/dr15xx.cpp
index 3d4050a5713f92..c79e1b9fdafe01 100644
--- a/clang/test/CXX/drs/dr15xx.cpp
+++ b/clang/test/CXX/drs/dr15xx.cpp
@@ -1,10 +1,10 @@
 // RUN: %clang_cc1 -std=c++98 -triple x86_64-unknown-unknown %s -verify=expected -fexceptions -fcxx-exceptions -pedantic-errors
-// RUN: %clang_cc1 -std=c++11 -triple x86_64-unknown-unknown %s -verify=expected,since-cxx11,cxx11-14 -fexceptions -fcxx-exceptions -pedantic-errors
-// RUN: %clang_cc1 -std=c++14 -triple x86_64-unknown-unknown %s -verify=expected,since-cxx11,cxx11-14,cxx14-17 -fexceptions -fcxx-exceptions -pedantic-errors
-// RUN: %clang_cc1 -std=c++17 -triple x86_64-unknown-unknown %s -verify=expected,since-cxx11,since-cxx17 -fexceptions -fcxx-exceptions -pedantic-errors
-// RUN: %clang_cc1 -std=c++20 -triple x86_64-unknown-unknown %s -verify=expected,since-cxx20,since-cxx11,since-cxx17 -fexceptions -fcxx-exceptions -pedantic-errors
-// RUN: %clang_cc1 -std=c++23 -triple x86_64-unknown-unknown %s -verify=expected,since-cxx20,since-cxx11,since-cxx17 -fexceptions -fcxx-exceptions -pedantic-errors
-// RUN: %clang_cc1 -std=c++2c -triple x86_64-unknown-unknown %s -verify=expected,since-cxx20,since-cxx11,since-cxx17 -fexceptions -fcxx-exceptions -pedantic-errors
+// RUN: %clang_cc1 -std=c++11 -triple x86_64-unknown-unknown %s -verify=expected,cxx11-20,since-cxx11,cxx11-14 -fexceptions -fcxx-exceptions -pedantic-errors
+// RUN: %clang_cc1 -std=c++14 -triple x86_64-unknown-unknown %s -verify=expected,cxx11-20,since-cxx11,cxx11-14,cxx14-17 -fexceptions -fcxx-exceptions -pedantic-errors
+// RUN: %clang_cc1 -std=c++17 -triple x86_64-unknown-unknown %s -verify=expected,cxx11-20,since-cxx11,since-cxx17 -fexceptions -fcxx-exceptions -pedantic-errors
+// RUN: %clang_cc1 -std=c++20 -triple x86_64-unknown-unknown %s -verify=expected,cxx11-20,since-cxx20,since-cxx11,since-cxx17 -fexceptions -fcxx-exceptions -pedantic-errors
+// RUN: %clang_cc1 -std=c++23 -triple x86_64-unknown-unknown %s -verify=expected,since-cxx23,since-cxx20,since-cxx11,since-cxx17 -fexceptions -fcxx-exceptions -pedantic-errors
+// RUN: %clang_cc1 -std=c++2c -triple x86_64-unknown-unknown %s -verify=expected,since-cxx23,since-cxx20,since-cxx11,since-cxx17 -fexceptions -fcxx-exceptions -pedantic-errors
 
 namespace dr1512 { // dr1512: 4
   void f(char *p) {
@@ -368,7 +368,7 @@ namespace dr1573 { // dr1573: 3.9
   B b(1, 'x', 4.0, "hello"); // ok
 
   // inherited constructor is effectively constexpr if the user-written constructor would be
-  struct C { C(); constexpr C(int) {} };
+  struct C { C(); constexpr C(int) {} }; // #dr1573-C
   struct D : C { using C::C; };
   constexpr D d = D(0); // ok
   struct E : C { using C::C; A a; }; // #dr1573-E
@@ -381,8 +381,11 @@ namespace dr1573 { // dr1573: 3.9
   struct F : C { using C::C; C c; }; // #dr1573-F
   constexpr F f = F(0);
   // since-cxx11-error at -1 {{constexpr variable 'f' must be initialized by a constant expression}}
-  //   since-cxx11-note at -2 {{constructor inherited from base class 'C' cannot be used in a constant expression; derived class cannot be implicitly initialized}}
-  //   since-cxx11-note@#dr1573-F {{declared here}}
+  //   cxx11-20-note at -2 {{constructor inherited from base class 'C' cannot be used in a constant expression; derived class cannot be implicitly initialized}}
+  //   since-cxx23-note at -3 {{in implicit initialization for inherited constructor of 'F'}}
+  //   since-cxx23-note@#dr1573-F {{non-constexpr constructor 'C' cannot be used in a constant expression}}
+  //   cxx11-20-note@#dr1573-F {{declared here}}
+  //   since-cxx23-note@#dr1573-C {{declared here}}
 
   // inherited constructor is effectively deleted if the user-written constructor would be
   struct G { G(int); };
diff --git a/clang/test/CXX/drs/dr16xx.cpp b/clang/test/CXX/drs/dr16xx.cpp
index 3f4f75df5b25dd..1dfe092d7b288e 100644
--- a/clang/test/CXX/drs/dr16xx.cpp
+++ b/clang/test/CXX/drs/dr16xx.cpp
@@ -3,8 +3,8 @@
 // RUN: %clang_cc1 -std=c++14 -triple x86_64-unknown-unknown %s -verify=expected,cxx11-20,since-cxx14,cxx98-14,since-cxx11 -fexceptions -fcxx-exceptions -pedantic-errors
 // RUN: %clang_cc1 -std=c++17 -triple x86_64-unknown-unknown %s -verify=expected,cxx11-20,since-cxx14,since-cxx17,since-cxx11 -fexceptions -fcxx-exceptions -pedantic-errors
 // RUN: %clang_cc1 -std=c++20 -triple x86_64-unknown-unknown %s -verify=expected,cxx11-20,since-cxx14,since-cxx20,since-cxx17,since-cxx11 -fexceptions -fcxx-exceptions -pedantic-errors
-// RUN: %clang_cc1 -std=c++23 -triple x86_64-unknown-unknown %s -verify=expected,since-cxx14,since-cxx20,since-cxx17,since-cxx11 -fexceptions -fcxx-exceptions -pedantic-errors
-// RUN: %clang_cc1 -std=c++2c -triple x86_64-unknown-unknown %s -verify=expected,since-cxx14,since-cxx20,since-cxx17,since-cxx11 -fexceptions -fcxx-exceptions -pedantic-errors
+// RUN: %clang_cc1 -std=c++23 -triple x86_64-unknown-unknown %s -verify=expected,since-cxx23,since-cxx14,since-cxx20,since-cxx17,since-cxx11 -fexceptions -fcxx-exceptions -pedantic-errors
+// RUN: %clang_cc1 -std=c++2c -triple x86_64-unknown-unknown %s -verify=expected,since-cxx23,since-cxx14,since-cxx20,since-cxx17,since-cxx11 -fexceptions -fcxx-exceptions -pedantic-errors
 
 #if __cplusplus == 199711L
 #define static_assert(...) __extension__ _Static_assert(__VA_ARGS__)
@@ -255,12 +255,12 @@ namespace dr1658 { // dr1658: 5
     struct A { A(A&); };
     struct B : virtual A { virtual void f() = 0; };
     struct C : virtual A { virtual void f(); };
-    struct D : A { virtual void f() = 0; };
+    struct D : A { virtual void f() = 0; }; // since-cxx23-note {{previous declaration is here}}
 
     struct X {
       friend B::B(const B&) throw();
       friend C::C(C&);
-      friend D::D(D&);
+      friend D::D(D&); // since-cxx23-error {{non-constexpr declaration of 'D' follows constexpr declaration}}
     };
   }
 
diff --git a/clang/test/SemaCXX/constant-expression-cxx11.cpp b/clang/test/SemaCXX/constant-expression-cxx11.cpp
index a29659301dfd66..43e9434dee4557 100644
--- a/clang/test/SemaCXX/constant-expression-cxx11.cpp
+++ b/clang/test/SemaCXX/constant-expression-cxx11.cpp
@@ -1678,7 +1678,7 @@ namespace ImplicitConstexpr {
   struct R { constexpr R() noexcept; constexpr R(const R&) noexcept; constexpr R(R&&) noexcept; ~R() noexcept; };
   struct S { R r; }; // expected-note 3{{here}}
   struct T { T(const T&) noexcept; T(T &&) noexcept; ~T() noexcept; };
-  struct U { T t; }; // expected-note 3{{here}}
+  struct U { T t; }; // cxx11_20-note 3{{here}}
   static_assert(!__is_literal_type(Q), "");
   static_assert(!__is_literal_type(R), "");
   static_assert(!__is_literal_type(S), "");
@@ -1691,9 +1691,9 @@ namespace ImplicitConstexpr {
     friend S::S() noexcept; // expected-error {{follows constexpr}}
     friend S::S(S&&) noexcept; // expected-error {{follows constexpr}}
     friend S::S(const S&) noexcept; // expected-error {{follows constexpr}}
-    friend constexpr U::U() noexcept; // expected-error {{follows non-constexpr}}
-    friend constexpr U::U(U&&) noexcept; // expected-error {{follows non-constexpr}}
-    friend constexpr U::U(const U&) noexcept; // expected-error {{follows non-constexpr}}
+    friend constexpr U::U() noexcept; // cxx11_20-error {{follows non-constexpr}}
+    friend constexpr U::U(U&&) noexcept; // cxx11_20-error {{follows non-constexpr}}
+    friend constexpr U::U(const U&) noexcept; // cxx11_20-error {{follows non-constexpr}}
   };
 }
 
@@ -2277,7 +2277,8 @@ namespace InheritedCtor {
   struct A { constexpr A(int) {} };
 
   struct B : A { int n; using A::A; }; // expected-note {{here}}
-  constexpr B b(0); // expected-error {{constant expression}} expected-note {{derived class}}
+  constexpr B b(0); // expected-error {{constant expression}} cxx11_20-note {{derived class}}\
+                    // cxx23-note {{not initialized}}
 
   struct C : A { using A::A; struct { union { int n, m = 0; }; union { int a = 0; }; int k = 0; }; struct {}; union {}; }; // expected-warning 6{{}}
   constexpr C c(0);
diff --git a/clang/test/SemaCXX/cxx23-invalid-constexpr.cpp b/clang/test/SemaCXX/cxx23-invalid-constexpr.cpp
index 355495689ccd83..da22d11a5dcbf4 100644
--- a/clang/test/SemaCXX/cxx23-invalid-constexpr.cpp
+++ b/clang/test/SemaCXX/cxx23-invalid-constexpr.cpp
@@ -48,10 +48,8 @@ constexpr int F2(NonLiteral N) {
   return 8;
 }
 
-class Derived : public NonLiteral { // cxx23-note {{declared here}}
+class Derived : public NonLiteral {
   constexpr ~Derived() {}; // precxx20-error {{destructor cannot be declared constexpr}}
-  // cxx23-warning at -1{{constexpr destructor is incompatible with C++ standards before C++23 because base class 'NonLiteral' does not have a constexpr destructor}}
-
 };
 
 class Derived1 : public NonLiteral {
@@ -84,15 +82,14 @@ struct Wrapper {
 };
 
 struct WrapperNonT {
-  constexpr WrapperNonT() = default; // cxx23-warning {{defaulted definition of default constructor that marked constexpr but never produces a constant expression is incompatible with C++ standards before C++23}}
-  // expected-note at -1 {{declared here}}
-  constexpr WrapperNonT(WrapperNonT const&) = default; // cxx23-warning {{defaulted definition of copy constructor that marked constexpr but never produces a constant expression is incompatible with C++ standards before C++23}}
+  constexpr WrapperNonT() = default;
+  constexpr WrapperNonT(WrapperNonT const&) = default;
   constexpr WrapperNonT(X const& t) : t(t) { } // cxx23-warning {{constexpr constructor that never produces a constant expression is incompatible with C++ standards before C++23}}
   // cxx23-note at -1 {{non-constexpr constructor 'X' cannot be used in a constant expression}}
-  constexpr WrapperNonT(WrapperNonT &&) = default; // cxx23-warning {{defaulted definition of move constructor that marked constexpr but never produces a constant expression is incompatible with C++ standards before C++23}}
-  constexpr WrapperNonT& operator=(WrapperNonT &) = default; // cxx23-warning {{defaulted definition of copy assignment operator that marked constexpr but never produces a constant expression is incompatible with C++ standards before C++23}}
+  constexpr WrapperNonT(WrapperNonT &&) = default;
+  constexpr WrapperNonT& operator=(WrapperNonT &) = default;
   // cxx11-error at -1 {{an explicitly-defaulted copy assignment operator may not have 'const', 'constexpr' or 'volatile' qualifiers}}
-  constexpr WrapperNonT& operator=(WrapperNonT&& other) = default; // cxx23-warning {{defaulted definition of move assignment operator that marked constexpr but never produces a constant expression is incompatible with C++ standards before C++23}}
+  constexpr WrapperNonT& operator=(WrapperNonT&& other) = default;
   // cxx11-error at -1 {{an explicitly-defaulted move assignment operator may not have 'const', 'constexpr' or 'volatile' qualifiers}}
   constexpr X get() const { return t; } // cxx23-warning {{constexpr function with non-literal return type 'X' is incompatible with C++ standards before C++23}}
   // cxx23-warning at -1{{constexpr function that never produces a constant expression is incompatible with C++ standards before C++23}}
@@ -153,11 +150,10 @@ void test() {
   WrapperNonT x1;
   NonDefaultMembers x2;
 
-  // TODO produces note with an invalid source location
+  // TODO these produce notes with an invalid source location.
   // static_assert((Wrapper<X>(), true));
-  
-  static_assert((WrapperNonT(), true),""); // expected-error{{expression is not an integral constant expression}}\
-                                        // expected-note {{non-constexpr constructor 'WrapperNonT' cannot be used in a constant expression}}
+  // static_assert((WrapperNonT(), true),""); 
+
   static_assert((NonDefaultMembers(), true),""); // expected-error{{expression is not an integral constant expression}} \
                                               // expected-note {{in call to}}
   constexpr bool FFF = (NonDefaultMembers() == NonDefaultMembers()); // expected-error{{must be initialized by a constant expression}} \

>From 26fdf352330e173543a973a38882dbd59332c9d9 Mon Sep 17 00:00:00 2001
From: "Podchishchaeva, Mariya" <mariya.podchishchaeva at intel.com>
Date: Wed, 24 Jan 2024 01:02:22 -0800
Subject: [PATCH 08/11] Fix test after merge

---
 clang/test/SemaCXX/deduced-return-type-cxx14.cpp | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/clang/test/SemaCXX/deduced-return-type-cxx14.cpp b/clang/test/SemaCXX/deduced-return-type-cxx14.cpp
index 8aa6f6bb05f3aa..367dfc85e229d9 100644
--- a/clang/test/SemaCXX/deduced-return-type-cxx14.cpp
+++ b/clang/test/SemaCXX/deduced-return-type-cxx14.cpp
@@ -1,8 +1,8 @@
 // RUN: %clang_cc1 -std=c++23 -fsyntax-only -verify=expected,since-cxx20,since-cxx14,cxx20_23,cxx23    %s
 // RUN: %clang_cc1 -std=c++23 -fsyntax-only -verify=expected,since-cxx20,since-cxx14,cxx20_23,cxx23    %s -fdelayed-template-parsing -DDELAYED_TEMPLATE_PARSING
 
-// RUN: %clang_cc1 -std=c++20 -fsyntax-only -verify=expected,since-cxx20,since-cxx14,cxx14_20,cxx20_23 %s
-// RUN: %clang_cc1 -std=c++20 -fsyntax-only -verify=expected,since-cxx20,since-cxx14,cxx14_20,cxx20_23 %s -fdelayed-template-parsing -DDELAYED_TEMPLATE_PARSING
+// RUN: %clang_cc1 -std=c++20 -fsyntax-only -verify=expected,cxx20,since-cxx20,since-cxx14,cxx14_20,cxx20_23 %s
+// RUN: %clang_cc1 -std=c++20 -fsyntax-only -verify=expected,cxx20,since-cxx20,since-cxx14,cxx14_20,cxx20_23 %s -fdelayed-template-parsing -DDELAYED_TEMPLATE_PARSING
 
 // RUN: %clang_cc1 -std=c++14 -fsyntax-only -verify=expected,since-cxx14,cxx14_20,cxx14    %s
 // RUN: %clang_cc1 -std=c++14 -fsyntax-only -verify=expected,since-cxx14,cxx14_20,cxx14    %s -fdelayed-template-parsing -DDELAYED_TEMPLATE_PARSING

>From 96a8f7f2f37b22cd63102b1134cceccc2cc9a734 Mon Sep 17 00:00:00 2001
From: "Podchishchaeva, Mariya" <mariya.podchishchaeva at intel.com>
Date: Wed, 24 Jan 2024 08:39:02 -0800
Subject: [PATCH 09/11] Format

---
 clang/lib/AST/DeclCXX.cpp | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/clang/lib/AST/DeclCXX.cpp b/clang/lib/AST/DeclCXX.cpp
index 1da9fa4bbb4eb1..63acd10d34b9ee 100644
--- a/clang/lib/AST/DeclCXX.cpp
+++ b/clang/lib/AST/DeclCXX.cpp
@@ -400,8 +400,8 @@ CXXRecordDecl::setBases(CXXBaseSpecifier const * const *Bases,
 
       // C++11 [class.ctor]p6:
       //   If that user-written default constructor would satisfy the
-      //   requirements of a constexpr constructor/function(C++23), the implicitly-defined
-      //   default constructor is constexpr.
+      //   requirements of a constexpr constructor/function(C++23), the
+      //   implicitly-defined default constructor is constexpr.
       if (!BaseClassDecl->hasConstexprDefaultConstructor())
         data().DefaultedDefaultConstructorIsConstexpr =
             C.getLangOpts().CPlusPlus23;

>From 1ed37bf0d0c060d390b81f77bf31eba5cc6dc685 Mon Sep 17 00:00:00 2001
From: "Podchishchaeva, Mariya" <mariya.podchishchaeva at intel.com>
Date: Tue, 5 Mar 2024 05:45:05 -0800
Subject: [PATCH 10/11] Fix test

---
 clang/test/AST/Interp/cxx17.cpp | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/clang/test/AST/Interp/cxx17.cpp b/clang/test/AST/Interp/cxx17.cpp
index 5e38d1a5887007..b063a9e71828ce 100644
--- a/clang/test/AST/Interp/cxx17.cpp
+++ b/clang/test/AST/Interp/cxx17.cpp
@@ -83,7 +83,7 @@ static_assert(b() == 11);
 
 /// The diagnostics between the two interpreters used to be different here.
 struct S { int a; };
-constexpr S getS() { // both-error {{constexpr function never produces a constant expression}}
+constexpr S getS() { // both-error {{constexpr function that never produces a constant expression}}
   (void)(1/0); // both-note 2{{division by zero}} \
                // both-warning {{division by zero}}
   return S{12};

>From 5b8e47672c8ddbbcbfcfacb245c4db16aab273ba Mon Sep 17 00:00:00 2001
From: "Podchishchaeva, Mariya" <mariya.podchishchaeva at intel.com>
Date: Tue, 5 Mar 2024 07:11:30 -0800
Subject: [PATCH 11/11] Roll back to C++23 only implementation

---
 clang/docs/LanguageExtensions.rst             |  1 -
 clang/docs/ReleaseNotes.rst                   |  3 +-
 .../clang/Basic/DiagnosticSemaKinds.td        | 26 +++++++--------
 clang/lib/Sema/SemaDeclCXX.cpp                | 21 ++++++------
 .../test/SemaCXX/cxx23-invalid-constexpr.cpp  | 32 ++++++++++++++++---
 5 files changed, 52 insertions(+), 31 deletions(-)

diff --git a/clang/docs/LanguageExtensions.rst b/clang/docs/LanguageExtensions.rst
index 898c2cb4bb721e..bcd69198eafdbe 100644
--- a/clang/docs/LanguageExtensions.rst
+++ b/clang/docs/LanguageExtensions.rst
@@ -1487,7 +1487,6 @@ Conditional ``explicit``               __cpp_conditional_explicit       C++20
 ``if consteval``                       __cpp_if_consteval               C++23         C++20
 ``static operator()``                  __cpp_static_call_operator       C++23         C++03
 Attributes on Lambda-Expressions                                        C++23         C++11
-Relaxing some constexpr restrictions   __cpp_constexpr                  C++23         C++11
 -------------------------------------- -------------------------------- ------------- -------------
 Designated initializers (N494)                                          C99           C89
 Array & element qualification (N2607)                                   C23           C89
diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst
index 28b9159c91127b..58348eaa8a4cb1 100644
--- a/clang/docs/ReleaseNotes.rst
+++ b/clang/docs/ReleaseNotes.rst
@@ -92,8 +92,7 @@ C++23 Feature Support
 - Implemented `P2718R0: Lifetime extension in range-based for loops <https://wg21.link/P2718R0>`_. Also
   materialize temporary object which is a prvalue in discarded-value expression.
 
-- Implemented `P2448R2: Relaxing some constexpr restrictions <https://wg21.link/P2448R2>`_
-  as a conforming extension.
+- Implemented `P2448R2: Relaxing some constexpr restrictions <https://wg21.link/P2448R2>`_.
 
 C++2c Feature Support
 ^^^^^^^^^^^^^^^^^^^^^
diff --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td b/clang/include/clang/Basic/DiagnosticSemaKinds.td
index c50d0d7aae9613..8cd89df2b4f7df 100644
--- a/clang/include/clang/Basic/DiagnosticSemaKinds.td
+++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td
@@ -2773,11 +2773,11 @@ def err_constexpr_tag : Error<
   "cannot be marked %sub{select_constexpr_spec_kind}1">;
 def err_constexpr_dtor : Error<
   "destructor cannot be declared %sub{select_constexpr_spec_kind}0">;
-def ext_constexpr_dtor_subobject : ExtWarn<
+def err_constexpr_dtor_subobject : Error<
   "destructor cannot be declared %sub{select_constexpr_spec_kind}0 before C++23 because "
   "%select{data member %2|base class %3}1 does not have a "
-  "constexpr destructor">, InGroup<CXX23>, DefaultError;
-def warn_cxx23_compat_constexpr_dtor_subobject : Warning<
+  "constexpr destructor">;
+def warn_cxx20_compat_constexpr_dtor_subobject : Warning<
   "%sub{select_constexpr_spec_kind}0 destructor is incompatible with C++ standards before C++23 because "
   "%select{data member %2|base class %3}1 does not have a "
   "constexpr destructor">, InGroup<CXXPre23Compat>, DefaultIgnore;
@@ -2812,13 +2812,13 @@ def note_non_literal_incomplete : Note<
 def note_non_literal_virtual_base : Note<"%select{struct|interface|class}0 "
   "with virtual base %plural{1:class|:classes}1 is not a literal type">;
 def note_constexpr_virtual_base_here : Note<"virtual base class declared here">;
-def ext_constexpr_non_literal_return : ExtWarn<
-  "%select{constexpr|consteval}0 function with non-literal return type %1 is a C++23 extension">, InGroup<CXX23>, DefaultError;
-def warn_cxx23_compat_constexpr_non_literal_return : Warning<
+def err_constexpr_non_literal_return : Error<
+  "%select{constexpr|consteval}0 function with non-literal return type %1 is a C++23 extension">;
+def warn_cxx20_compat_constexpr_non_literal_return : Warning<
   "%select{constexpr|consteval}0 function with non-literal return type %1 is incompatible with C++ standards before C++23">, InGroup<CXXPre23Compat>, DefaultIgnore;
-def ext_constexpr_non_literal_param : ExtWarn<
-  "%select{constexpr|consteval}2 %select{function|constructor}1 with %ordinal0 non-literal parameter type %3 is a C++23 extension">, InGroup<CXX23>, DefaultError;
-def warn_cxx23_compat_constexpr_non_literal_param : Warning<
+def err_constexpr_non_literal_param : Error<
+  "%select{constexpr|consteval}2 %select{function|constructor}1 with %ordinal0 non-literal parameter type %3 is a C++23 extension">;
+def warn_cxx20_compat_constexpr_non_literal_param : Warning<
   "%select{constexpr|consteval}2 %select{function|constructor}1 with %ordinal0 non-literal parameter type %3 is not compatible with C++ standards before C++23">, InGroup<CXXPre23Compat>, DefaultIgnore;
 def err_constexpr_body_invalid_stmt : Error<
   "statement not allowed in %select{constexpr|consteval}1 %select{function|constructor}0">;
@@ -2882,7 +2882,7 @@ def warn_cxx17_compat_constexpr_local_var_no_init : Warning<
 def ext_constexpr_function_never_constant_expr : ExtWarn<
   "%select{constexpr|consteval}1 %select{function|constructor}0 that never produces a "
   "constant expression is a C++23 extension">, InGroup<DiagGroup<"invalid-constexpr">>, DefaultError;
-def warn_cxx23_compat_constexpr_function_never_constant_expr : Warning<
+def warn_cxx20_compat_constexpr_function_never_constant_expr : Warning<
   "%select{constexpr|consteval}1 %select{function|constructor}0 that never produces a "
   "constant expression is incompatible with C++ standards before C++23">, InGroup<CXXPre23Compat>, DefaultIgnore;
 def err_attr_cond_never_constant_expr : Error<
@@ -9600,9 +9600,9 @@ def err_defaulted_special_member_copy_const_param : Error<
 def err_defaulted_copy_assign_not_ref : Error<
   "the parameter for an explicitly-defaulted copy assignment operator must be an "
   "lvalue reference type">;
-def ext_incorrect_defaulted_constexpr : ExtWarn<
+def err_incorrect_defaulted_constexpr : Error<
   "defaulted definition of %sub{select_special_member_kind}0 that marked %select{constexpr|consteval}1 "
-  "but never produces a constant expression is a C++23 extension">, InGroup<CXX23>, DefaultError;
+  "but never produces a constant expression is a C++23 extension">;
 def err_incorrect_defaulted_constexpr_with_vb: Error<
   "%sub{select_special_member_kind}0 cannot be 'constexpr' in a class with virtual base class">;
 def warn_defaulted_method_deleted : Warning<
@@ -9722,7 +9722,7 @@ def ext_defaulted_comparison_constexpr_mismatch : Extension<
   "%select{|for which the corresponding implicit 'operator==' }0 "
   "invokes a non-constexpr comparison function is a C++23 extension">,
   InGroup<DiagGroup<"c++23-default-comp-relaxed-constexpr">>;
-def warn_cxx23_compat_defaulted_comparison_constexpr_mismatch : Warning<
+def warn_cxx20_compat_defaulted_comparison_constexpr_mismatch : Warning<
   "defaulted definition of %select{%sub{select_defaulted_comparison_kind}1|"
   "three-way comparison operator}0 that is "
   "declared %select{constexpr|consteval}2 but"
diff --git a/clang/lib/Sema/SemaDeclCXX.cpp b/clang/lib/Sema/SemaDeclCXX.cpp
index ae953085a21b4a..78c94bce1f3d6e 100644
--- a/clang/lib/Sema/SemaDeclCXX.cpp
+++ b/clang/lib/Sema/SemaDeclCXX.cpp
@@ -1724,8 +1724,8 @@ static bool CheckConstexprDestructorSubobjects(Sema &SemaRef,
     if (Kind == Sema::CheckConstexprKind::Diagnose) {
       SemaRef.Diag(DD->getLocation(),
                    SemaRef.getLangOpts().CPlusPlus23
-                       ? diag::warn_cxx23_compat_constexpr_dtor_subobject
-                       : diag::ext_constexpr_dtor_subobject)
+                       ? diag::warn_cxx20_compat_constexpr_dtor_subobject
+                       : diag::err_constexpr_dtor_subobject)
           << static_cast<int>(DD->getConstexprKind()) << !FD
           << (FD ? FD->getDeclName() : DeclarationName()) << T;
       SemaRef.Diag(Loc, diag::note_constexpr_dtor_subobject)
@@ -1760,8 +1760,8 @@ static bool CheckConstexprParameterTypes(Sema &SemaRef,
     if (CheckLiteralType(
             SemaRef, Kind, ParamLoc, *i,
             SemaRef.getLangOpts().CPlusPlus23
-                ? diag::warn_cxx23_compat_constexpr_non_literal_param
-                : diag::ext_constexpr_non_literal_param,
+                ? diag::warn_cxx20_compat_constexpr_non_literal_param
+                : diag::err_constexpr_non_literal_param,
             ArgIndex + 1, PD->getSourceRange(), isa<CXXConstructorDecl>(FD),
             FD->isConsteval()))
       return SemaRef.getLangOpts().CPlusPlus23;
@@ -1776,8 +1776,8 @@ static bool CheckConstexprReturnType(Sema &SemaRef, const FunctionDecl *FD,
   if (CheckLiteralType(
           SemaRef, Kind, FD->getLocation(), FD->getReturnType(),
           SemaRef.getLangOpts().CPlusPlus23
-              ? diag::warn_cxx23_compat_constexpr_non_literal_return
-              : diag::ext_constexpr_non_literal_return,
+              ? diag::warn_cxx20_compat_constexpr_non_literal_return
+              : diag::err_constexpr_non_literal_return,
           FD->isConsteval()))
     return SemaRef.getLangOpts().CPlusPlus23;
   return true;
@@ -2471,7 +2471,7 @@ static bool CheckConstexprFunctionBody(Sema &SemaRef, const FunctionDecl *Dcl,
     SemaRef.Diag(
         Dcl->getLocation(),
         SemaRef.getLangOpts().CPlusPlus23
-            ? diag::warn_cxx23_compat_constexpr_function_never_constant_expr
+            ? diag::warn_cxx20_compat_constexpr_function_never_constant_expr
             : diag::ext_constexpr_function_never_constant_expr)
         << isa<CXXConstructorDecl>(Dcl) << Dcl->isConsteval()
         << Dcl->getNameInfo().getSourceRange();
@@ -7881,7 +7881,7 @@ bool Sema::CheckExplicitlyDefaultedSpecialMember(CXXMethodDecl *MD,
             Diag(I.getBeginLoc(), diag::note_constexpr_virtual_base_here);
           HadError = true;
         } else {
-          Diag(MD->getBeginLoc(), diag::ext_incorrect_defaulted_constexpr)
+          Diag(MD->getBeginLoc(), diag::err_incorrect_defaulted_constexpr)
               << CSM << MD->isConsteval();
         }
         // FIXME: Explain why the special member can't be constexpr.
@@ -9121,7 +9121,7 @@ bool Sema::CheckExplicitlyDefaultedComparison(Scope *S, FunctionDecl *FD,
         !Info.Constexpr) {
       Diag(FD->getBeginLoc(),
            getLangOpts().CPlusPlus23
-               ? diag::warn_cxx23_compat_defaulted_comparison_constexpr_mismatch
+               ? diag::warn_cxx20_compat_defaulted_comparison_constexpr_mismatch
                : diag::ext_defaulted_comparison_constexpr_mismatch)
           << FD->isImplicit() << (int)DCK << FD->isConsteval();
       DefaultedComparisonAnalyzer(*this, RD, FD, DCK,
@@ -9135,8 +9135,7 @@ bool Sema::CheckExplicitlyDefaultedComparison(Scope *S, FunctionDecl *FD,
   //   declaration, it is implicitly considered to be constexpr.
   // FIXME: Only applying this to the first declaration seems problematic, as
   // simple reorderings can affect the meaning of the program.
-  if ((First && !FD->isConstexpr() && Info.Constexpr) ||
-      getLangOpts().CPlusPlus23)
+  if (First && !FD->isConstexpr() && Info.Constexpr)
     FD->setConstexprKind(ConstexprSpecKind::Constexpr);
 
   // C++2a [except.spec]p3:
diff --git a/clang/test/SemaCXX/cxx23-invalid-constexpr.cpp b/clang/test/SemaCXX/cxx23-invalid-constexpr.cpp
index da22d11a5dcbf4..61d87def3718b1 100644
--- a/clang/test/SemaCXX/cxx23-invalid-constexpr.cpp
+++ b/clang/test/SemaCXX/cxx23-invalid-constexpr.cpp
@@ -1,8 +1,4 @@
 // RUN: %clang_cc1 -fsyntax-only -verify=expected,cxx23 -std=c++23 -Wpre-c++23-compat %s
-// RUN: %clang_cc1 -fsyntax-only -verify=expected -std=c++20 -Wno-c++23-extensions -Wno-invalid-constexpr %s
-// RUN: %clang_cc1 -fsyntax-only -verify=expected,precxx20 -std=c++17 -Wno-c++23-extensions -Wno-invalid-constexpr %s
-// RUN: %clang_cc1 -fsyntax-only -verify=expected,precxx20 -std=c++14 -Wno-c++23-extensions -Wno-invalid-constexpr %s
-// RUN: %clang_cc1 -fsyntax-only -verify=expected,precxx20,cxx11 -std=c++11 -Wno-c++14-extensions -Wno-c++23-extensions -Wno-invalid-constexpr -Wno-constexpr-not-const %s
 
 // This test covers modifications made by P2448R2.
 
@@ -158,5 +154,33 @@ void test() {
                                               // expected-note {{in call to}}
   constexpr bool FFF = (NonDefaultMembers() == NonDefaultMembers()); // expected-error{{must be initialized by a constant expression}} \
                                                                      // expected-note{{non-literal}}
+}
+
+struct A {
+  A ();
+  ~A();
+};
+
+template <class T>
+struct opt
+{
+  union {
+    char c;
+    T data;
+  };
+
+  constexpr opt() {}
 
+  constexpr ~opt()  {
+   if (engaged)
+     data.~T();
+ }
+
+  bool engaged = false;
+};
+
+consteval void foo() {
+  opt<A> a;
 }
+
+void bar() { foo(); }



More information about the cfe-commits mailing list