Skip to content

Revert "[Clang][C++23] Implement P2448R2 ..." #85136

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Mar 13, 2024

Conversation

amykhuang
Copy link
Collaborator

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

This reverts commit 99500e8 because it causes a behavior change for std=c++20. See
#77753.

…trictions (llvm#77753)"

This reverts commit 99500e8 because it
causes a behavior change for std=c++20. See
llvm#77753.
@amykhuang amykhuang added the skip-precommit-approval PR for CI feedback, not intended for review label Mar 13, 2024
@amykhuang amykhuang requested a review from Endilll as a code owner March 13, 2024 21:45
@llvmbot llvmbot added clang Clang issues not falling into any other category clang:frontend Language frontend issues, e.g. anything involving "Sema" labels Mar 13, 2024
@llvmbot
Copy link
Member

llvmbot commented Mar 13, 2024

@llvm/pr-subscribers-clang

Author: Amy Huang (amykhuang)

Changes

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

This reverts commit 99500e8 because it causes a behavior change for std=c++20. See
#77753.


Patch is 83.76 KiB, truncated to 20.00 KiB below, full version: https://github.com/llvm/llvm-project/pull/85136.diff

27 Files Affected:

  • (modified) clang/docs/ReleaseNotes.rst (-2)
  • (modified) clang/include/clang/Basic/DiagnosticSemaKinds.td (+19-7)
  • (modified) clang/lib/AST/DeclCXX.cpp (+5-8)
  • (modified) clang/lib/Sema/SemaDeclCXX.cpp (+41-52)
  • (modified) clang/test/AST/Interp/cxx23.cpp (+41-18)
  • (modified) clang/test/CXX/class/class.compare/class.compare.default/p3.cpp (+19-21)
  • (modified) clang/test/CXX/class/class.compare/class.compare.default/p4.cpp (+10-10)
  • (modified) clang/test/CXX/dcl.dcl/dcl.spec/dcl.constexpr/dtor.cpp (+4-4)
  • (modified) clang/test/CXX/dcl.dcl/dcl.spec/dcl.constexpr/p3-2b.cpp (+6-4)
  • (modified) clang/test/CXX/dcl.dcl/dcl.spec/dcl.constexpr/p3.cpp (+9-9)
  • (modified) clang/test/CXX/dcl.dcl/dcl.spec/dcl.constexpr/p4.cpp (+4-4)
  • (modified) clang/test/CXX/dcl.decl/dcl.fct.def/dcl.fct.def.default/p2.cpp (+3-3)
  • (modified) clang/test/CXX/drs/dr13xx.cpp (+11-11)
  • (modified) clang/test/CXX/drs/dr14xx.cpp (+3-3)
  • (modified) clang/test/CXX/drs/dr15xx.cpp (+9-12)
  • (modified) clang/test/CXX/drs/dr16xx.cpp (+10-10)
  • (modified) clang/test/CXX/drs/dr6xx.cpp (+12-12)
  • (modified) clang/test/CXX/expr/expr.const/p5-26.cpp (+2-2)
  • (modified) clang/test/CXX/special/class.copy/p13-0x.cpp (+1-1)
  • (modified) clang/test/SemaCXX/constant-expression-cxx11.cpp (+18-20)
  • (modified) clang/test/SemaCXX/constant-expression-cxx14.cpp (+16-17)
  • (modified) clang/test/SemaCXX/constant-expression-cxx2b.cpp (+12-12)
  • (removed) clang/test/SemaCXX/cxx23-invalid-constexpr.cpp (-159)
  • (modified) clang/test/SemaCXX/cxx2a-consteval.cpp (+1-1)
  • (modified) clang/test/SemaCXX/deduced-return-type-cxx14.cpp (+4-4)
  • (modified) clang/test/SemaOpenCLCXX/addrspace-constructors.clcpp (+1-1)
  • (modified) clang/www/cxx_status.html (+8-1)
diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst
index 5fe3fd066df235..e018d38355945f 100644
--- a/clang/docs/ReleaseNotes.rst
+++ b/clang/docs/ReleaseNotes.rst
@@ -102,8 +102,6 @@ C++23 Feature Support
   materialize temporary object which is a prvalue in discarded-value expression.
 - Implemented `P1774R8: Portable assumptions <https://wg21.link/P1774R8>`_.
 
-- 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 d7ab1635cf12bc..605fbc52701df0 100644
--- a/clang/include/clang/Basic/DiagnosticSemaKinds.td
+++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td
@@ -9617,10 +9617,13 @@ 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 cannot be marked %select{constexpr|consteval}1 "
-  "before C++23">;
+  "defaulted definition of %sub{select_special_member_kind}0 "
+  "is not constexpr">;
 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>;
@@ -9731,12 +9734,21 @@ def note_defaulted_comparison_cannot_deduce_undeduced_auto : Note<
   "%select{|member|base class}0 %1 declared here">;
 def note_defaulted_comparison_cannot_deduce_callee : Note<
   "selected 'operator<=>' for %select{|member|base class}0 %1 declared here">;
-def err_defaulted_comparison_constexpr_mismatch : Error<
+def ext_defaulted_comparison_constexpr_mismatch : Extension<
   "defaulted definition of %select{%sub{select_defaulted_comparison_kind}1|"
-  "three-way comparison operator}0 cannot be "
-  "declared %select{constexpr|consteval}2 because "
-  "%select{it|for which the corresponding implicit 'operator==' }0 "
-  "invokes a non-constexpr comparison function ">;
+  "three-way comparison operator}0 that is "
+  "declared %select{constexpr|consteval}2 but"
+  "%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<
+  "defaulted definition of %select{%sub{select_defaulted_comparison_kind}1|"
+  "three-way comparison operator}0 that is "
+  "declared %select{constexpr|consteval}2 but"
+  "%select{|for which the corresponding implicit 'operator==' }0 "
+  "invokes a non-constexpr comparison function is incompatible with C++ "
+  "standards before C++23">,
+  InGroup<CXXPre23Compat>, DefaultIgnore;
 def note_defaulted_comparison_not_constexpr : Note<
   "non-constexpr comparison function would be used to compare "
   "%select{|member %1|base class %1}0">;
diff --git a/clang/lib/AST/DeclCXX.cpp b/clang/lib/AST/DeclCXX.cpp
index 1c3dcf63465c68..b4f2327d9c560a 100644
--- a/clang/lib/AST/DeclCXX.cpp
+++ b/clang/lib/AST/DeclCXX.cpp
@@ -400,11 +400,10 @@ 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, the implicitly-defined
+      //   default constructor is constexpr.
       if (!BaseClassDecl->hasConstexprDefaultConstructor())
-        data().DefaultedDefaultConstructorIsConstexpr =
-            C.getLangOpts().CPlusPlus23;
+        data().DefaultedDefaultConstructorIsConstexpr = false;
 
       // C++1z [class.copy]p8:
       //   The implicitly-declared copy constructor for a class X will have
@@ -549,8 +548,7 @@ 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 =
-        getASTContext().getLangOpts().CPlusPlus23;
+    data().DefaultedDestructorIsConstexpr = false;
 
   // C++20 [temp.param]p7:
   //   A structural type is [...] a literal class type [for which] the types
@@ -1299,8 +1297,7 @@ 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 =
-              Context.getLangOpts().CPlusPlus23;
+          data().DefaultedDefaultConstructorIsConstexpr = false;
 
         // 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 e258a4f7c89415..199f2523cfb5d2 100644
--- a/clang/lib/Sema/SemaDeclCXX.cpp
+++ b/clang/lib/Sema/SemaDeclCXX.cpp
@@ -1715,8 +1715,6 @@ static bool CheckLiteralType(Sema &SemaRef, Sema::CheckConstexprKind Kind,
 static bool CheckConstexprDestructorSubobjects(Sema &SemaRef,
                                                const CXXDestructorDecl *DD,
                                                Sema::CheckConstexprKind Kind) {
-  assert(!SemaRef.getLangOpts().CPlusPlus23 &&
-         "this check is obsolete for C++23");
   auto Check = [&](SourceLocation Loc, QualType T, const FieldDecl *FD) {
     const CXXRecordDecl *RD =
         T->getBaseElementTypeUnsafe()->getAsCXXRecordDecl();
@@ -1748,8 +1746,6 @@ static bool CheckConstexprDestructorSubobjects(Sema &SemaRef,
 static bool CheckConstexprParameterTypes(Sema &SemaRef,
                                          const FunctionDecl *FD,
                                          Sema::CheckConstexprKind Kind) {
-  assert(!SemaRef.getLangOpts().CPlusPlus23 &&
-         "this check is obsolete for C++23");
   unsigned ArgIndex = 0;
   const auto *FT = FD->getType()->castAs<FunctionProtoType>();
   for (FunctionProtoType::param_type_iterator i = FT->param_type_begin(),
@@ -1771,8 +1767,6 @@ 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) {
-  assert(!SemaRef.getLangOpts().CPlusPlus23 &&
-         "this check is obsolete for C++23");
   if (CheckLiteralType(SemaRef, Kind, FD->getLocation(), FD->getReturnType(),
                        diag::err_constexpr_non_literal_return,
                        FD->isConsteval()))
@@ -1862,18 +1856,16 @@ bool Sema::CheckConstexprFunctionDefinition(const FunctionDecl *NewFD,
       }
     }
 
-    // - its return type shall be a literal type; (removed in C++23)
-    if (!getLangOpts().CPlusPlus23 &&
-        !CheckConstexprReturnType(*this, NewFD, Kind))
+    // - its return type shall be a literal type;
+    if (!CheckConstexprReturnType(*this, NewFD, Kind))
       return false;
   }
 
   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. (removed in C++23)
-    if (!getLangOpts().CPlusPlus23 &&
-        !Dtor->getParent()->defaultedDestructorIsConstexpr()) {
+    // have constexpr destructors.
+    if (!Dtor->getParent()->defaultedDestructorIsConstexpr()) {
       if (Kind == CheckConstexprKind::CheckValid)
         return false;
       if (!CheckConstexprDestructorSubobjects(*this, Dtor, Kind))
@@ -1881,9 +1873,8 @@ bool Sema::CheckConstexprFunctionDefinition(const FunctionDecl *NewFD,
     }
   }
 
-  // - each of its parameter types shall be a literal type; (removed in C++23)
-  if (!getLangOpts().CPlusPlus23 &&
-      !CheckConstexprParameterTypes(*this, NewFD, Kind))
+  // - each of its parameter types shall be a literal type;
+  if (!CheckConstexprParameterTypes(*this, NewFD, Kind))
     return false;
 
   Stmt *Body = NewFD->getBody();
@@ -2466,8 +2457,7 @@ static bool CheckConstexprFunctionBody(Sema &SemaRef, const FunctionDecl *Dcl,
   // function", so is not checked in CheckValid mode.
   SmallVector<PartialDiagnosticAt, 8> Diags;
   if (Kind == Sema::CheckConstexprKind::Diagnose &&
-      !Expr::isPotentialConstantExpr(Dcl, Diags) &&
-      !SemaRef.getLangOpts().CPlusPlus23) {
+      !Expr::isPotentialConstantExpr(Dcl, Diags)) {
     SemaRef.Diag(Dcl->getLocation(),
                  diag::ext_constexpr_function_never_constant_expr)
         << isa<CXXConstructorDecl>(Dcl) << Dcl->isConsteval()
@@ -7545,23 +7535,21 @@ static bool defaultedSpecialMemberIsConstexpr(
 
   // C++1y [class.copy]p26:
   //   -- [the class] is a literal type, and
-  if (!Ctor && !ClassDecl->isLiteral() && !S.getLangOpts().CPlusPlus23)
+  if (!Ctor && !ClassDecl->isLiteral())
     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
-  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;
-    }
+  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
@@ -7571,22 +7559,20 @@ 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
-  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) {
+  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;
     }
   }
 
@@ -7872,17 +7858,18 @@ bool Sema::CheckExplicitlyDefaultedSpecialMember(CXXMethodDecl *MD,
       MD->isConstexpr() && !Constexpr &&
       MD->getTemplatedKind() == FunctionDecl::TK_NonTemplate) {
         if (!MD->isConsteval() && RD->getNumVBases()) {
-          Diag(MD->getBeginLoc(),
-               diag::err_incorrect_defaulted_constexpr_with_vb)
+          Diag(MD->getBeginLoc(), diag::err_incorrect_defaulted_constexpr_with_vb)
               << CSM;
           for (const auto &I : RD->vbases())
             Diag(I.getBeginLoc(), diag::note_constexpr_virtual_base_here);
         } else {
-          Diag(MD->getBeginLoc(), diag::err_incorrect_defaulted_constexpr)
-              << CSM << MD->isConsteval();
+          Diag(MD->getBeginLoc(), MD->isConsteval()
+                                      ? diag::err_incorrect_defaulted_consteval
+                                      : diag::err_incorrect_defaulted_constexpr)
+              << CSM;
         }
-        HadError = true;
-        // FIXME: Explain why the special member can't be constexpr.
+    // FIXME: Explain why the special member can't be constexpr.
+    HadError = true;
   }
 
   if (First) {
@@ -9114,11 +9101,13 @@ bool Sema::CheckExplicitlyDefaultedComparison(Scope *S, FunctionDecl *FD,
   //    - if the function is a constructor or destructor, its class does not
   //      have any virtual base classes.
   if (FD->isConstexpr()) {
-    if (!getLangOpts().CPlusPlus23 &&
-        CheckConstexprReturnType(*this, FD, CheckConstexprKind::Diagnose) &&
+    if (CheckConstexprReturnType(*this, FD, CheckConstexprKind::Diagnose) &&
         CheckConstexprParameterTypes(*this, FD, CheckConstexprKind::Diagnose) &&
         !Info.Constexpr) {
-      Diag(FD->getBeginLoc(), diag::err_defaulted_comparison_constexpr_mismatch)
+      Diag(FD->getBeginLoc(),
+           getLangOpts().CPlusPlus23
+               ? diag::warn_cxx23_compat_defaulted_comparison_constexpr_mismatch
+               : diag::ext_defaulted_comparison_constexpr_mismatch)
           << FD->isImplicit() << (int)DCK << FD->isConsteval();
       DefaultedComparisonAnalyzer(*this, RD, FD, DCK,
                                   DefaultedComparisonAnalyzer::ExplainConstexpr)
diff --git a/clang/test/AST/Interp/cxx23.cpp b/clang/test/AST/Interp/cxx23.cpp
index 127b58915127cf..f1df936a5abe74 100644
--- a/clang/test/AST/Interp/cxx23.cpp
+++ b/clang/test/AST/Interp/cxx23.cpp
@@ -1,58 +1,82 @@
-// RUN: %clang_cc1 -std=c++20 -fsyntax-only -fcxx-exceptions -verify=ref20,all,all-20 %s
+// RUN: %clang_cc1 -std=c++20 -fsyntax-only -fcxx-exceptions -verify=ref20,all %s
 // RUN: %clang_cc1 -std=c++23 -fsyntax-only -fcxx-exceptions -verify=ref23,all %s
-// RUN: %clang_cc1 -std=c++20 -fsyntax-only -fcxx-exceptions -verify=expected20,all,all-20 %s -fexperimental-new-constant-interpreter
+// RUN: %clang_cc1 -std=c++20 -fsyntax-only -fcxx-exceptions -verify=expected20,all %s -fexperimental-new-constant-interpreter
 // RUN: %clang_cc1 -std=c++23 -fsyntax-only -fcxx-exceptions -verify=expected23,all %s -fexperimental-new-constant-interpreter
 
 /// 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}} \
-                          // expected20-error {{constexpr function never produces a constant expression}}
+                          // ref23-error {{constexpr function never produces a constant expression}} \
+                          // expected20-error {{constexpr function never produces a constant expression}} \
+                          // expected23-error {{constexpr function 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}} \
                           // expected20-note {{declared here}} \
+                          // expected23-note {{declared here}}
 
-  return m; // expected20-note {{initializer of 'm' is not a constant expression}}
+  return m; // expected20-note {{initializer of 'm' is not a constant expression}} \
+            // expected23-note {{initializer of 'm' is not a constant expression}}
 }
 constexpr int g(int n) {        // ref20-error {{constexpr function never produces a constant expression}} \
-                                // expected20-error {{constexpr function never produces a constant expression}}
+                                // ref23-error {{constexpr function never produces a constant expression}} \
+                                // expected20-error {{constexpr function never produces a constant expression}} \
+                                // expected23-error {{constexpr function 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}} \
-                                // expected20-note {{declared here}}
-  return m; // expected20-note {{initializer of 'm' is not a constant expression}}
+                                // expected20-note {{declared here}} \
+                                // expected23-note {{declared here}}
+  return m; // expected20-note {{initializer of 'm' is not a constant expression}} \
+            // expected23-note {{initializer of 'm' is not a constant expression}}
 
 }
 
 constexpr int c_thread_local(int n) { // ref20-error {{constexpr function never produces a constant expression}} \
-                                      // expected20-error {{constexpr function never produces a constant expression}}
+                                      // ref23-error {{constexpr function never produces a constant expression}} \
+                                      // expected20-error {{constexpr function never produces a constant expression}} \
+                                      // expected23-error {{constexpr function 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}} \
-                                      // expected20-note {{declared here}}
-  return m; // expected20-note {{read of non-const variable}}
+                                      // expected20-note {{declared here}} \
+                                      // expected23-note {{declared here}}
+  return m; // expected20-note {{read of non-const variable}} \
+            // expected23-note {{read of non-const variable}}
 }
 
 
 constexpr int gnu_thread_local(int n) { // ref20-error {{constexpr function never produces a constant expression}} \
-                                        // expected20-error {{constexpr function never produces a constant expression}}
+                                        // ref23-error {{constexpr function never produces a constant expression}} \
+                                        // expected20-error {{constexpr function never produces a constant expression}} \
+                                        // expected23-error {{constexpr function never produces a cons...
[truncated]

Copy link

⚠️ C/C++ code formatter, clang-format found issues in your code. ⚠️

You can test this locally with the following command:
git-clang-format --diff ccfb9e6eb7429885e6d09e99cf89bce41f1ca3cc 2f67dfb012038678dd0b873394a55bd5c937f843 -- clang/lib/AST/DeclCXX.cpp clang/lib/Sema/SemaDeclCXX.cpp clang/test/AST/Interp/cxx23.cpp clang/test/CXX/class/class.compare/class.compare.default/p3.cpp clang/test/CXX/class/class.compare/class.compare.default/p4.cpp clang/test/CXX/dcl.dcl/dcl.spec/dcl.constexpr/dtor.cpp clang/test/CXX/dcl.dcl/dcl.spec/dcl.constexpr/p3-2b.cpp clang/test/CXX/dcl.dcl/dcl.spec/dcl.constexpr/p3.cpp clang/test/CXX/dcl.dcl/dcl.spec/dcl.constexpr/p4.cpp clang/test/CXX/dcl.decl/dcl.fct.def/dcl.fct.def.default/p2.cpp clang/test/CXX/drs/dr13xx.cpp clang/test/CXX/drs/dr14xx.cpp clang/test/CXX/drs/dr15xx.cpp clang/test/CXX/drs/dr16xx.cpp clang/test/CXX/drs/dr6xx.cpp clang/test/CXX/expr/expr.const/p5-26.cpp clang/test/CXX/special/class.copy/p13-0x.cpp clang/test/SemaCXX/constant-expression-cxx11.cpp clang/test/SemaCXX/constant-expression-cxx14.cpp clang/test/SemaCXX/constant-expression-cxx2b.cpp clang/test/SemaCXX/cxx2a-consteval.cpp clang/test/SemaCXX/deduced-return-type-cxx14.cpp
View the diff from clang-format here.
diff --git a/clang/lib/Sema/SemaDeclCXX.cpp b/clang/lib/Sema/SemaDeclCXX.cpp
index 199f2523cf..b14699894b 100644
--- a/clang/lib/Sema/SemaDeclCXX.cpp
+++ b/clang/lib/Sema/SemaDeclCXX.cpp
@@ -1743,8 +1743,7 @@ static bool CheckConstexprDestructorSubobjects(Sema &SemaRef,
 
 /// Check whether a function's parameter types are all literal types. If so,
 /// return true. If not, produce a suitable diagnostic and return false.
-static bool CheckConstexprParameterTypes(Sema &SemaRef,
-                                         const FunctionDecl *FD,
+static bool CheckConstexprParameterTypes(Sema &SemaRef, const FunctionDecl *FD,
                                          Sema::CheckConstexprKind Kind) {
   unsigned ArgIndex = 0;
   const auto *FT = FD->getType()->castAs<FunctionProtoType>();
@@ -7858,7 +7857,8 @@ bool Sema::CheckExplicitlyDefaultedSpecialMember(CXXMethodDecl *MD,
       MD->isConstexpr() && !Constexpr &&
       MD->getTemplatedKind() == FunctionDecl::TK_NonTemplate) {
         if (!MD->isConsteval() && RD->getNumVBases()) {
-          Diag(MD->getBeginLoc(), diag::err_incorrect_defaulted_constexpr_with_vb)
+          Diag(MD->getBeginLoc(),
+               diag::err_incorrect_defaulted_constexpr_with_vb)
               << CSM;
           for (const auto &I : RD->vbases())
             Diag(I.getBeginLoc(), diag::note_constexpr_virtual_base_here);
@@ -7868,8 +7868,8 @@ bool Sema::CheckExplicitlyDefaultedSpecialMember(CXXMethodDecl *MD,
                                       : diag::err_incorrect_defaulted_constexpr)
               << CSM;
         }
-    // FIXME: Explain why the special member can't be constexpr.
-    HadError = true;
+        // FIXME: Explain why the special member can't be constexpr.
+        HadError = true;
   }
 
   if (First) {

@amykhuang amykhuang merged commit 003e292 into llvm:main Mar 13, 2024
amykhuang added a commit to amykhuang/llvm-project that referenced this pull request Mar 13, 2024
amykhuang added a commit that referenced this pull request Mar 13, 2024
This reverts commit 003e292 because
there were dependent changes in the codebase that now fail.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
clang:frontend Language frontend issues, e.g. anything involving "Sema" clang Clang issues not falling into any other category skip-precommit-approval PR for CI feedback, not intended for review
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants