[llvm-branch-commits] [clang] [Clang] Implement CWG 2282 (PR #203832)

Igor Kudrin via llvm-branch-commits llvm-branch-commits at lists.llvm.org
Fri Jun 19 23:40:12 PDT 2026


https://github.com/igorkudrin updated https://github.com/llvm/llvm-project/pull/203832

>From 1b6cb0d8274f096b8388aa4ad9f5ffb256bd48bc Mon Sep 17 00:00:00 2001
From: Igor Kudrin <ikudrin at accesssoftek.com>
Date: Sat, 13 Jun 2026 23:14:25 -0700
Subject: [PATCH 1/3] [Clang] Implement CWG 2282

Link: https://wg21.link/cwg2282

For non-overaligned types, overload resolution now falls back to aligned
allocation functions in C++20 and later.
---
 clang/docs/ReleaseNotes.rst                   |  3 +
 clang/lib/Sema/SemaExprCXX.cpp                | 57 +++++++++++++------
 clang/test/CXX/drs/cwg22xx.cpp                | 38 +++++++++++--
 clang/test/CXX/drs/cwg5xx.cpp                 |  5 +-
 .../test/CXX/expr/expr.unary/expr.new/p14.cpp | 13 +++--
 clang/test/SemaCXX/new-delete.cpp             | 13 +++--
 .../std-align-val-t-in-operator-new.cpp       |  6 ++
 clang/www/cxx_dr_status.html                  |  2 +-
 8 files changed, 103 insertions(+), 34 deletions(-)

diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst
index c5e54b09b5ed4..97e35f50f0c66 100644
--- a/clang/docs/ReleaseNotes.rst
+++ b/clang/docs/ReleaseNotes.rst
@@ -216,6 +216,9 @@ Resolutions to C++ Defect Reports
 - Implemented `CWG1780 Explicit instantiation/specialization of generic lambda
   operator() <https://cplusplus.github.io/CWG/issues/1780.html>`_
 
+- Clang now falls back to alignment-aware allocation functions for non-overaligned
+  types in C++20 and later, implementing `CWG2282 <https://wg21.link/cwg2282>`_.
+
 - Clang now allows omitting ``typename`` before a template name in a
   conversion operator, implementing `CWG2413 <https://wg21.link/cwg2413>`_.
 
diff --git a/clang/lib/Sema/SemaExprCXX.cpp b/clang/lib/Sema/SemaExprCXX.cpp
index b4fd186d90354..1201868b246a3 100644
--- a/clang/lib/Sema/SemaExprCXX.cpp
+++ b/clang/lib/Sema/SemaExprCXX.cpp
@@ -2767,7 +2767,8 @@ static bool resolveAllocationOverload(
 
   case OR_No_Viable_Function:
     if (!PrefCandidates && !FallbackArgs.empty()) {
-      PassAlignment = AlignedAllocationMode::No;
+      PassAlignment =
+          alignedAllocationModeFromBool(!isAlignedAllocation(PassAlignment));
       return resolveAllocationOverload(S, R, Range, Mode, PrefArgs,
                                        FallbackArgs, PassAlignment, Operator,
                                        &Candidates, Diagnose);
@@ -2799,17 +2800,19 @@ static bool resolveAllocationOverload(
       // If this is an allocation of the form 'new (p) X' for some object
       // pointer p (or an expression that will decay to such a pointer),
       // diagnose the reason for the error.
-      if (!R.isClassLookup() && Args.size() == 2 &&
-          (Args[1]->getType()->isObjectPointerType() ||
-           Args[1]->getType()->isArrayType())) {
-        const QualType Arg1Type = Args[1]->getType();
+      if (!R.isClassLookup() &&
+          (Args.size() == 2 ||
+           (Args.size() == 3 && isAlignedAllocation(PassAlignment))) &&
+          (Args.back()->getType()->isObjectPointerType() ||
+           Args.back()->getType()->isArrayType())) {
+        const QualType Arg1Type = Args.back()->getType();
         QualType UnderlyingType = S.Context.getBaseElementType(Arg1Type);
         if (UnderlyingType->isPointerType())
           UnderlyingType = UnderlyingType->getPointeeType();
         if (UnderlyingType.isConstQualified()) {
-          S.Diag(Args[1]->getExprLoc(),
+          S.Diag(Args.back()->getExprLoc(),
                  diag::err_placement_new_into_const_qualified_storage)
-              << Arg1Type << Args[1]->getSourceRange();
+              << Arg1Type << Args.back()->getSourceRange();
           return true;
         }
         S.Diag(R.getNameLoc(), diag::err_need_header_before_placement_new)
@@ -2829,6 +2832,10 @@ static bool resolveAllocationOverload(
       if (PrefCandidates) {
         assert(Mode == ResolveMode::Untyped &&
                "Typed mode does not issue diagnostics");
+        bool PrefHasAlignArg = PrefArgs.size() > FallbackArgs.size();
+        assert(
+            PrefHasAlignArg == !isAlignedAllocation(PassAlignment) &&
+            "PassAlignment must match preferable and fallback argument lists");
         auto IsAligned = [](OverloadCandidate &C) {
           const unsigned AlignArgOffset = 1;
           return C.Function->getNumParams() > AlignArgOffset &&
@@ -2836,13 +2843,18 @@ static bool resolveAllocationOverload(
                      ->getType()
                      ->isAlignValT();
         };
-        auto IsUnaligned = [&](OverloadCandidate &C) { return !IsAligned(C); };
+        auto IsPref = [&](OverloadCandidate &C) {
+          return PrefHasAlignArg ? IsAligned(C) : !IsAligned(C);
+        };
+        auto IsFallback = [&](OverloadCandidate &C) {
+          return PrefHasAlignArg ? !IsAligned(C) : IsAligned(C);
+        };
 
         PrefCands = PrefCandidates->CompleteCandidates(
-            S, OCD_AllCandidates, PrefArgs, R.getNameLoc(), IsAligned);
+            S, OCD_AllCandidates, PrefArgs, R.getNameLoc(), IsPref);
 
         Cands = Candidates.CompleteCandidates(S, OCD_AllCandidates, Args,
-                                              R.getNameLoc(), IsUnaligned);
+                                              R.getNameLoc(), IsFallback);
       } else {
         Cands = Candidates.CompleteCandidates(S, OCD_AllCandidates, Args,
                                               R.getNameLoc());
@@ -2957,9 +2969,10 @@ bool Sema::FindAllocationFunctions(
 
   QualType AlignValT = Context.VoidTy;
   if (isTypeAwareAllocation(OriginalTypeAwareState) ||
-      isAlignedAllocation(OriginalAlignedAllocationMode)) {
+      getLangOpts().AlignedAllocation) {
     DeclareGlobalNewDelete();
-    AlignValT = Context.getCanonicalTagType(getStdAlignValT());
+    if (EnumDecl *StdAlignValT = getStdAlignValT())
+      AlignValT = Context.getCanonicalTagType(StdAlignValT);
   }
   CXXScalarValueInitExpr Align(AlignValT, nullptr, SourceLocation());
 
@@ -3043,11 +3056,23 @@ bool Sema::FindAllocationFunctions(
       //   If no matching function is found and the allocated object type has
       //   new-extended alignment, the alignment argument is removed from the
       //   argument list, and overload resolution is performed again.
+      //
+      // C++20 [expr.new]p18:
+      //   If no matching function is found then
+      //     — if the allocated object type has new-extended alignment, the
+      //       alignment argument is removed from the argument list;
+      //     — otherwise, an argument that is the type’s alignment and has type
+      //       std::align_val_t is added into the argument list immediately
+      //       after the first argument;
+      //   and then overload resolution is performed again.
+      bool UseFallback = isAlignedAllocation(OriginalAlignedAllocationMode) ||
+                         (getLangOpts().CPlusPlus20 && getStdAlignValT());
+      auto FallbackAlignedAllocationMode = alignedAllocationModeFromBool(
+          !isAlignedAllocation(OriginalAlignedAllocationMode));
       auto FallbackAllocArgs =
-          isAlignedAllocation(OriginalAlignedAllocationMode)
-              ? FillAllocArgs(TypeAwareAllocationMode::No,
-                              AlignedAllocationMode::No)
-              : ArgsVector();
+          UseFallback ? FillAllocArgs(TypeAwareAllocationMode::No,
+                                      FallbackAlignedAllocationMode)
+                      : ArgsVector();
       if (resolveAllocationOverload(*this, R, Range, ResolveMode::Untyped,
                                     AllocArgs, FallbackAllocArgs,
                                     IAP.PassAlignment, OperatorNew,
diff --git a/clang/test/CXX/drs/cwg22xx.cpp b/clang/test/CXX/drs/cwg22xx.cpp
index 6d51afcdda743..67500c482decd 100644
--- a/clang/test/CXX/drs/cwg22xx.cpp
+++ b/clang/test/CXX/drs/cwg22xx.cpp
@@ -1,11 +1,17 @@
 // RUN: %clang_cc1 -std=c++98 -triple x86_64-unknown-unknown %s -fexceptions -fcxx-exceptions -pedantic-errors -verify-directives -verify=expected
 // RUN: %clang_cc1 -std=c++11 -triple x86_64-unknown-unknown %s -fexceptions -fcxx-exceptions -pedantic-errors -verify-directives -verify=expected,since-cxx11
 // RUN: %clang_cc1 -std=c++14 -triple x86_64-unknown-unknown %s -fexceptions -fcxx-exceptions -pedantic-errors -verify-directives -verify=expected,since-cxx11
-// RUN: %clang_cc1 -std=c++17 -triple x86_64-unknown-unknown %s -fexceptions -fcxx-exceptions -pedantic-errors -verify-directives -verify=expected,since-cxx11,since-cxx17
-// RUN: %clang_cc1 -std=c++20 -triple x86_64-unknown-unknown %s -fexceptions -fcxx-exceptions -pedantic-errors -verify-directives -verify=expected,since-cxx11,since-cxx17
-// RUN: %clang_cc1 -std=c++23 -triple x86_64-unknown-unknown %s -fexceptions -fcxx-exceptions -pedantic-errors -verify-directives -verify=expected,since-cxx11,since-cxx17
-// RUN: %clang_cc1 -std=c++2c -triple x86_64-unknown-unknown %s -fexceptions -fcxx-exceptions -pedantic-errors -verify-directives -verify=expected,since-cxx11,since-cxx17
+// RUN: %clang_cc1 -std=c++17 -triple x86_64-unknown-unknown %s -fexceptions -fcxx-exceptions -pedantic-errors -verify-directives -verify=expected,since-cxx11,since-cxx17,cxx17
+// RUN: %clang_cc1 -std=c++20 -triple x86_64-unknown-unknown %s -fexceptions -fcxx-exceptions -pedantic-errors -verify-directives -verify=expected,since-cxx11,since-cxx17,since-cxx20
+// RUN: %clang_cc1 -std=c++23 -triple x86_64-unknown-unknown %s -fexceptions -fcxx-exceptions -pedantic-errors -verify-directives -verify=expected,since-cxx11,since-cxx17,since-cxx20
+// RUN: %clang_cc1 -std=c++2c -triple x86_64-unknown-unknown %s -fexceptions -fcxx-exceptions -pedantic-errors -verify-directives -verify=expected,since-cxx11,since-cxx17,since-cxx20
 
+__extension__ typedef __SIZE_TYPE__ size_t;
+#if __cplusplus >= 201703L
+namespace std {
+  enum class align_val_t : size_t {};
+} // namespace std
+#endif
 
 namespace cwg2211 { // cwg2211: 8
 #if __cplusplus >= 201103L
@@ -196,6 +202,30 @@ void g() {
 #endif
 } // namespace cwg2277
 
+namespace cwg2282 { // cwg2282: 23
+#if __cplusplus >= 201703L
+struct A {
+  void *operator new(size_t, std::align_val_t) = delete; // #cwg2282-A-operator-new-aligned
+  void *operator new(size_t, std::align_val_t, double) = delete; // #cwg2282-A-operator-new-aligned-placement
+};
+
+void f() {
+  (void)new A; // cxx17-error {{no matching function for call to 'operator new'}}
+  // cxx17-note@#cwg2282-A-operator-new-aligned {{candidate function not viable: requires 2 arguments, but 1 was provided}}
+  // cxx17-note@#cwg2282-A-operator-new-aligned-placement {{candidate function not viable: requires 3 arguments, but 1 was provided}}
+  // since-cxx20-error at -3 {{call to deleted function 'operator new'}}
+  // since-cxx20-note@#cwg2282-A-operator-new-aligned {{candidate function has been explicitly deleted}}
+  // since-cxx20-note@#cwg2282-A-operator-new-aligned-placement {{candidate function not viable: requires 3 arguments, but 2 were provided}}
+  (void)new (1.5) A; // cxx17-error {{no matching function for call to 'operator new'}}
+  // cxx17-note@#cwg2282-A-operator-new-aligned {{candidate function not viable: no known conversion from 'double' to 'std::align_val_t' for 2nd argument}}
+  // cxx17-note@#cwg2282-A-operator-new-aligned-placement {{candidate function not viable: requires 3 arguments, but 2 were provided}}
+  // since-cxx20-error at -3 {{call to deleted function 'operator new'}}
+  // since-cxx20-note@#cwg2282-A-operator-new-aligned-placement {{candidate function has been explicitly deleted}}
+  // since-cxx20-note@#cwg2282-A-operator-new-aligned {{candidate function not viable: requires 2 arguments, but 3 were provided}}
+}
+#endif
+} // namespace cwg2282
+
 namespace cwg2285 { // cwg2285: 4
 // Note: Clang 4 implements this DR but it set a wrong value of `__cplusplus`
 #if __cplusplus >= 201703L
diff --git a/clang/test/CXX/drs/cwg5xx.cpp b/clang/test/CXX/drs/cwg5xx.cpp
index ea05e714601fc..71793ea1be585 100644
--- a/clang/test/CXX/drs/cwg5xx.cpp
+++ b/clang/test/CXX/drs/cwg5xx.cpp
@@ -1,7 +1,7 @@
 // RUN: %clang_cc1 -std=c++98 %s -fexceptions -fcxx-exceptions -pedantic-errors -verify-directives -verify=expected,cxx98-23,cxx98-11,cxx98-14,cxx98-17,cxx98
 // RUN: %clang_cc1 -std=c++11 %s -fexceptions -fcxx-exceptions -pedantic-errors -verify-directives -verify=expected,cxx98-23,cxx98-11,cxx98-14,cxx98-17,since-cxx11
 // RUN: %clang_cc1 -std=c++14 %s -fexceptions -fcxx-exceptions -pedantic-errors -verify-directives -verify=expected,cxx98-23,cxx98-14,cxx98-17,since-cxx11
-// RUN: %clang_cc1 -std=c++17 %s -fexceptions -fcxx-exceptions -pedantic-errors -verify-directives -verify=expected,cxx98-23,since-cxx17,cxx98-17,since-cxx11
+// RUN: %clang_cc1 -std=c++17 %s -fexceptions -fcxx-exceptions -pedantic-errors -verify-directives -verify=expected,cxx98-23,since-cxx17,cxx17,cxx98-17,since-cxx11
 // RUN: %clang_cc1 -std=c++20 %s -fexceptions -fcxx-exceptions -pedantic-errors -verify-directives -verify=expected,cxx98-23,since-cxx20,since-cxx17,since-cxx11
 // RUN: %clang_cc1 -std=c++23 %s -fexceptions -fcxx-exceptions -pedantic-errors -verify-directives -verify=expected,cxx98-23,since-cxx23,since-cxx20,since-cxx17,since-cxx11
 // RUN: %clang_cc1 -std=c++2c %s -fexceptions -fcxx-exceptions -pedantic-errors -verify-directives -verify=expected,since-cxx26,since-cxx23,since-cxx20,since-cxx17,since-cxx11
@@ -682,8 +682,9 @@ namespace cwg553 {
   // "is looked up in global scope", where it is not visible.
   void *p = new (c) int;
   // expected-error at -1 {{no matching function for call to 'operator new'}}
-  //   since-cxx17-note@#cwg5xx-global-operator-new-aligned {{candidate function not viable: no known conversion from 'cwg553_class' to 'std::align_val_t' for 2nd argument}}
+  //   cxx17-note@#cwg5xx-global-operator-new-aligned {{candidate function not viable: no known conversion from 'cwg553_class' to 'std::align_val_t' for 2nd argument}}
   //   expected-note@#cwg5xx-global-operator-new {{candidate function not viable: requires 1 argument, but 2 were provided}}
+  //   since-cxx20-note@#cwg5xx-global-operator-new-aligned {{candidate function not viable: requires 2 arguments, but 3 were provided}}
 
   struct namespace_scope {
     friend void *operator new(size_t, namespace_scope);
diff --git a/clang/test/CXX/expr/expr.unary/expr.new/p14.cpp b/clang/test/CXX/expr/expr.unary/expr.new/p14.cpp
index d0b24c8fe47b7..dd1b63687f308 100644
--- a/clang/test/CXX/expr/expr.unary/expr.new/p14.cpp
+++ b/clang/test/CXX/expr/expr.unary/expr.new/p14.cpp
@@ -1,4 +1,5 @@
-// RUN: %clang_cc1 -std=c++1z -fexceptions %s -verify
+// RUN: %clang_cc1 -std=c++1z -fexceptions %s -verify=expected,cxx17
+// RUN: %clang_cc1 -std=c++20 -fexceptions %s -verify=expected,since-cxx20
 
 using size_t = decltype(sizeof(0));
 namespace std { enum class align_val_t : size_t {}; }
@@ -6,7 +7,9 @@ namespace std { enum class align_val_t : size_t {}; }
 struct Arg {} arg;
 
 // If the type is aligned, first try with an alignment argument and then
-// without. If not, never consider supplying an alignment.
+// without. If not:
+// - For C++17, never consider supplying an alignment;
+// - For C++20 and later, try without an alignment argument first, then with it.
 
 template<unsigned Align, typename ...Ts>
 struct alignas(Align) Unaligned {
@@ -19,11 +22,11 @@ auto *ubp = new (arg) Unaligned<__STDCPP_DEFAULT_NEW_ALIGNMENT__ * 2, Arg>; // e
 
 template<unsigned Align, typename ...Ts>
 struct alignas(Align) Aligned {
-  void *operator new(size_t, std::align_val_t, Ts...) = delete; // expected-note 2{{deleted}} expected-note 2{{not viable}}
+  void *operator new(size_t, std::align_val_t, Ts...) = delete; // cxx17-note 2{{deleted}} cxx17-note 2{{not viable}} since-cxx20-note 4{{deleted}}
 };
-auto *aa = new Aligned<__STDCPP_DEFAULT_NEW_ALIGNMENT__>; // expected-error {{no matching}}
+auto *aa = new Aligned<__STDCPP_DEFAULT_NEW_ALIGNMENT__>; // cxx17-error {{no matching}} since-cxx20-error {{deleted}}
 auto *ab = new Aligned<__STDCPP_DEFAULT_NEW_ALIGNMENT__ * 2>; // expected-error {{deleted}}
-auto *aap = new (arg) Aligned<__STDCPP_DEFAULT_NEW_ALIGNMENT__, Arg>; // expected-error {{no matching}}
+auto *aap = new (arg) Aligned<__STDCPP_DEFAULT_NEW_ALIGNMENT__, Arg>; // cxx17-error {{no matching}} since-cxx20-error {{deleted}}
 auto *abp = new (arg) Aligned<__STDCPP_DEFAULT_NEW_ALIGNMENT__ * 2, Arg>; // expected-error {{deleted}}
 
 // If both are available, we prefer the aligned version for an overaligned
diff --git a/clang/test/SemaCXX/new-delete.cpp b/clang/test/SemaCXX/new-delete.cpp
index 2a2f91186871e..408cce414264f 100644
--- a/clang/test/SemaCXX/new-delete.cpp
+++ b/clang/test/SemaCXX/new-delete.cpp
@@ -2,20 +2,21 @@
 // RUN: %clang_cc1 -fsyntax-only -verify=expected,cxx98-23,precxx20 %s -triple=i686-pc-linux-gnu -Wno-new-returns-null -std=c++11
 // RUN: %clang_cc1 -fsyntax-only -verify=expected,cxx98-23,precxx20 %s -triple=i686-pc-linux-gnu -Wno-new-returns-null -std=c++14
 // RUN: %clang_cc1 -fsyntax-only -verify=expected,cxx98-23,cxx17,precxx20 %s -triple=i686-pc-linux-gnu -Wno-new-returns-null -std=c++17
-// RUN: %clang_cc1 -fsyntax-only -verify=expected,cxx98-23,cxx17,cxx20 %s -triple=i686-pc-linux-gnu -Wno-new-returns-null -std=c++20
-// RUN: %clang_cc1 -fsyntax-only -verify=expected,cxx98-23,cxx17,cxx20 %s -triple=i686-pc-linux-gnu -Wno-new-returns-null -std=c++23
-// RUN: %clang_cc1 -fsyntax-only -verify=expected,since-cxx26,cxx17,cxx20 %s -triple=i686-pc-linux-gnu -Wno-new-returns-null -std=c++2c
+// RUN: %clang_cc1 -fsyntax-only -verify=expected,cxx98-23,cxx20 %s -triple=i686-pc-linux-gnu -Wno-new-returns-null -std=c++20
+// RUN: %clang_cc1 -fsyntax-only -verify=expected,cxx98-23,cxx20 %s -triple=i686-pc-linux-gnu -Wno-new-returns-null -std=c++23
+// RUN: %clang_cc1 -fsyntax-only -verify=expected,since-cxx26,cxx20 %s -triple=i686-pc-linux-gnu -Wno-new-returns-null -std=c++2c
 
 // RUN: %clang_cc1 -fsyntax-only -verify=expected,cxx98-23,precxx20 %s -triple=i686-pc-linux-gnu -Wno-new-returns-null -std=c++98 -fexperimental-new-constant-interpreter -DNEW_INTERP
 // RUN: %clang_cc1 -fsyntax-only -verify=expected,cxx98-23,precxx20 %s -triple=i686-pc-linux-gnu -Wno-new-returns-null -std=c++11 -fexperimental-new-constant-interpreter -DNEW_INTERP
 // RUN: %clang_cc1 -fsyntax-only -verify=expected,cxx98-23,precxx20 %s -triple=i686-pc-linux-gnu -Wno-new-returns-null -std=c++14 -fexperimental-new-constant-interpreter -DNEW_INTERP
 // RUN: %clang_cc1 -fsyntax-only -verify=expected,cxx98-23,cxx17,precxx20 %s -triple=i686-pc-linux-gnu -Wno-new-returns-null -std=c++17 -fexperimental-new-constant-interpreter -DNEW_INTERP
-// RUN: %clang_cc1 -fsyntax-only -verify=expected,cxx98-23,cxx17,cxx20 %s -triple=i686-pc-linux-gnu -Wno-new-returns-null -std=c++20 -fexperimental-new-constant-interpreter -DNEW_INTERP
-// RUN: %clang_cc1 -fsyntax-only -verify=expected,cxx98-23,cxx17,cxx20 %s -triple=i686-pc-linux-gnu -Wno-new-returns-null -std=c++23 -fexperimental-new-constant-interpreter -DNEW_INTERP
-// RUN: %clang_cc1 -fsyntax-only -verify=expected,since-cxx26,cxx17,cxx20 %s -triple=i686-pc-linux-gnu -Wno-new-returns-null -std=c++2c -fexperimental-new-constant-interpreter -DNEW_INTERP
+// RUN: %clang_cc1 -fsyntax-only -verify=expected,cxx98-23,cxx20 %s -triple=i686-pc-linux-gnu -Wno-new-returns-null -std=c++20 -fexperimental-new-constant-interpreter -DNEW_INTERP
+// RUN: %clang_cc1 -fsyntax-only -verify=expected,cxx98-23,cxx20 %s -triple=i686-pc-linux-gnu -Wno-new-returns-null -std=c++23 -fexperimental-new-constant-interpreter -DNEW_INTERP
+// RUN: %clang_cc1 -fsyntax-only -verify=expected,since-cxx26,cxx20 %s -triple=i686-pc-linux-gnu -Wno-new-returns-null -std=c++2c -fexperimental-new-constant-interpreter -DNEW_INTERP
 
 // FIXME Location is (frontend)
 // cxx17-note@*:* {{candidate function not viable: requires 2 arguments, but 3 were provided}}
+// cxx20-note@*:* {{candidate function not viable: requires 2 arguments, but 4 were provided}}
 
 #include <stddef.h>
 
diff --git a/clang/test/SemaCXX/std-align-val-t-in-operator-new.cpp b/clang/test/SemaCXX/std-align-val-t-in-operator-new.cpp
index 9c34cb8e0d508..dc6a8ab6471d5 100644
--- a/clang/test/SemaCXX/std-align-val-t-in-operator-new.cpp
+++ b/clang/test/SemaCXX/std-align-val-t-in-operator-new.cpp
@@ -4,6 +4,8 @@
 // RUN: %clang_cc1 -std=c++14 -faligned-allocation -fsyntax-only -verify %s
 // RUN: %clang_cc1 -std=c++17                      -fsyntax-only -verify %s
 // RUN: %clang_cc1 -std=c++17 -faligned-allocation -fsyntax-only -verify %s
+// RUN: %clang_cc1 -std=c++20                      -fsyntax-only -verify %s
+// RUN: %clang_cc1 -std=c++20 -faligned-allocation -fsyntax-only -verify %s
 
 namespace std {
 typedef __SIZE_TYPE__ size_t;
@@ -62,7 +64,11 @@ void *operator new(std::size_t, std::align_val_t, X); // #3
 // FIXME: Consider improving notes 1 and 3 here to say that these are aligned
 // allocation functions and the type is not over-aligned.
 X *p = new (123) X; // expected-error {{no matching function}}
+#if __cplusplus >= 202002L
+// expected-note@#1 {{requires 2 arguments, but 4 were provided}}
+#else
 // expected-note@#1 {{no known conversion from 'int' to 'std::align_val_t' for 2nd argument}}
+#endif
 // expected-note@#2 {{no known conversion from 'int' to 'X' for 2nd argument}}
 // expected-note@#3 {{requires 3 arguments}}
 // expected-note@* {{requires 1 argument, but 2 were provided}} (builtin)
diff --git a/clang/www/cxx_dr_status.html b/clang/www/cxx_dr_status.html
index c9f136ba26681..7cd2eee0090f4 100755
--- a/clang/www/cxx_dr_status.html
+++ b/clang/www/cxx_dr_status.html
@@ -15763,7 +15763,7 @@ <h2 id="cxxdr">C++ defect report implementation status</h2>
     <td>[<a href="https://wg21.link/expr.new">expr.new</a>]</td>
     <td>C++20</td>
     <td>Consistency with mismatched aligned/non-over-aligned allocation/deallocation functions</td>
-    <td class="unknown" align="center">Unknown</td>
+    <td class="unreleased" align="center">Clang 23</td>
   </tr>
   <tr id="2283">
     <td><a href="https://cplusplus.github.io/CWG/issues/2283.html">2283</a></td>

>From 4de1cb8321cee7771cf023c5eb71bc952e1b0134 Mon Sep 17 00:00:00 2001
From: Igor Kudrin <ikudrin at accesssoftek.com>
Date: Fri, 19 Jun 2026 21:13:14 -0700
Subject: [PATCH 2/3] fixup! do not restrict the patch to C++20

---
 clang/docs/ReleaseNotes.rst                   |  2 +-
 clang/lib/Sema/SemaExprCXX.cpp                |  7 +----
 clang/test/CXX/drs/cwg22xx.cpp                | 26 +++++++------------
 clang/test/CXX/drs/cwg5xx.cpp                 |  5 ++--
 .../test/CXX/expr/expr.unary/expr.new/p14.cpp | 13 ++++------
 clang/test/SemaCXX/new-delete.cpp             | 15 +++++------
 .../std-align-val-t-in-operator-new.cpp       |  4 +--
 7 files changed, 27 insertions(+), 45 deletions(-)

diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst
index 97e35f50f0c66..91bd571f7232c 100644
--- a/clang/docs/ReleaseNotes.rst
+++ b/clang/docs/ReleaseNotes.rst
@@ -217,7 +217,7 @@ Resolutions to C++ Defect Reports
   operator() <https://cplusplus.github.io/CWG/issues/1780.html>`_
 
 - Clang now falls back to alignment-aware allocation functions for non-overaligned
-  types in C++20 and later, implementing `CWG2282 <https://wg21.link/cwg2282>`_.
+  types, implementing `CWG2282 <https://wg21.link/cwg2282>`_.
 
 - Clang now allows omitting ``typename`` before a template name in a
   conversion operator, implementing `CWG2413 <https://wg21.link/cwg2413>`_.
diff --git a/clang/lib/Sema/SemaExprCXX.cpp b/clang/lib/Sema/SemaExprCXX.cpp
index 1201868b246a3..b88b88f69efc0 100644
--- a/clang/lib/Sema/SemaExprCXX.cpp
+++ b/clang/lib/Sema/SemaExprCXX.cpp
@@ -3052,11 +3052,6 @@ bool Sema::FindAllocationFunctions(
       IAP.PassAlignment = OriginalAlignedAllocationMode;
       auto AllocArgs = FillAllocArgs(TypeAwareAllocationMode::No,
                                      OriginalAlignedAllocationMode);
-      // C++17 [expr.new]p13:
-      //   If no matching function is found and the allocated object type has
-      //   new-extended alignment, the alignment argument is removed from the
-      //   argument list, and overload resolution is performed again.
-      //
       // C++20 [expr.new]p18:
       //   If no matching function is found then
       //     — if the allocated object type has new-extended alignment, the
@@ -3066,7 +3061,7 @@ bool Sema::FindAllocationFunctions(
       //       after the first argument;
       //   and then overload resolution is performed again.
       bool UseFallback = isAlignedAllocation(OriginalAlignedAllocationMode) ||
-                         (getLangOpts().CPlusPlus20 && getStdAlignValT());
+                         (getLangOpts().AlignedAllocation && getStdAlignValT());
       auto FallbackAlignedAllocationMode = alignedAllocationModeFromBool(
           !isAlignedAllocation(OriginalAlignedAllocationMode));
       auto FallbackAllocArgs =
diff --git a/clang/test/CXX/drs/cwg22xx.cpp b/clang/test/CXX/drs/cwg22xx.cpp
index 67500c482decd..52ca8e801b763 100644
--- a/clang/test/CXX/drs/cwg22xx.cpp
+++ b/clang/test/CXX/drs/cwg22xx.cpp
@@ -1,10 +1,10 @@
 // RUN: %clang_cc1 -std=c++98 -triple x86_64-unknown-unknown %s -fexceptions -fcxx-exceptions -pedantic-errors -verify-directives -verify=expected
 // RUN: %clang_cc1 -std=c++11 -triple x86_64-unknown-unknown %s -fexceptions -fcxx-exceptions -pedantic-errors -verify-directives -verify=expected,since-cxx11
 // RUN: %clang_cc1 -std=c++14 -triple x86_64-unknown-unknown %s -fexceptions -fcxx-exceptions -pedantic-errors -verify-directives -verify=expected,since-cxx11
-// RUN: %clang_cc1 -std=c++17 -triple x86_64-unknown-unknown %s -fexceptions -fcxx-exceptions -pedantic-errors -verify-directives -verify=expected,since-cxx11,since-cxx17,cxx17
-// RUN: %clang_cc1 -std=c++20 -triple x86_64-unknown-unknown %s -fexceptions -fcxx-exceptions -pedantic-errors -verify-directives -verify=expected,since-cxx11,since-cxx17,since-cxx20
-// RUN: %clang_cc1 -std=c++23 -triple x86_64-unknown-unknown %s -fexceptions -fcxx-exceptions -pedantic-errors -verify-directives -verify=expected,since-cxx11,since-cxx17,since-cxx20
-// RUN: %clang_cc1 -std=c++2c -triple x86_64-unknown-unknown %s -fexceptions -fcxx-exceptions -pedantic-errors -verify-directives -verify=expected,since-cxx11,since-cxx17,since-cxx20
+// RUN: %clang_cc1 -std=c++17 -triple x86_64-unknown-unknown %s -fexceptions -fcxx-exceptions -pedantic-errors -verify-directives -verify=expected,since-cxx11,since-cxx17
+// RUN: %clang_cc1 -std=c++20 -triple x86_64-unknown-unknown %s -fexceptions -fcxx-exceptions -pedantic-errors -verify-directives -verify=expected,since-cxx11,since-cxx17
+// RUN: %clang_cc1 -std=c++23 -triple x86_64-unknown-unknown %s -fexceptions -fcxx-exceptions -pedantic-errors -verify-directives -verify=expected,since-cxx11,since-cxx17
+// RUN: %clang_cc1 -std=c++2c -triple x86_64-unknown-unknown %s -fexceptions -fcxx-exceptions -pedantic-errors -verify-directives -verify=expected,since-cxx11,since-cxx17
 
 __extension__ typedef __SIZE_TYPE__ size_t;
 #if __cplusplus >= 201703L
@@ -210,18 +210,12 @@ struct A {
 };
 
 void f() {
-  (void)new A; // cxx17-error {{no matching function for call to 'operator new'}}
-  // cxx17-note@#cwg2282-A-operator-new-aligned {{candidate function not viable: requires 2 arguments, but 1 was provided}}
-  // cxx17-note@#cwg2282-A-operator-new-aligned-placement {{candidate function not viable: requires 3 arguments, but 1 was provided}}
-  // since-cxx20-error at -3 {{call to deleted function 'operator new'}}
-  // since-cxx20-note@#cwg2282-A-operator-new-aligned {{candidate function has been explicitly deleted}}
-  // since-cxx20-note@#cwg2282-A-operator-new-aligned-placement {{candidate function not viable: requires 3 arguments, but 2 were provided}}
-  (void)new (1.5) A; // cxx17-error {{no matching function for call to 'operator new'}}
-  // cxx17-note@#cwg2282-A-operator-new-aligned {{candidate function not viable: no known conversion from 'double' to 'std::align_val_t' for 2nd argument}}
-  // cxx17-note@#cwg2282-A-operator-new-aligned-placement {{candidate function not viable: requires 3 arguments, but 2 were provided}}
-  // since-cxx20-error at -3 {{call to deleted function 'operator new'}}
-  // since-cxx20-note@#cwg2282-A-operator-new-aligned-placement {{candidate function has been explicitly deleted}}
-  // since-cxx20-note@#cwg2282-A-operator-new-aligned {{candidate function not viable: requires 2 arguments, but 3 were provided}}
+  (void)new A; // since-cxx17-error {{call to deleted function 'operator new'}}
+  // since-cxx17-note@#cwg2282-A-operator-new-aligned {{candidate function has been explicitly deleted}}
+  // since-cxx17-note@#cwg2282-A-operator-new-aligned-placement {{candidate function not viable: requires 3 arguments, but 2 were provided}}
+  (void)new (1.5) A; // since-cxx17-error {{call to deleted function 'operator new'}}
+  // since-cxx17-note@#cwg2282-A-operator-new-aligned-placement {{candidate function has been explicitly deleted}}
+  // since-cxx17-note@#cwg2282-A-operator-new-aligned {{candidate function not viable: requires 2 arguments, but 3 were provided}}
 }
 #endif
 } // namespace cwg2282
diff --git a/clang/test/CXX/drs/cwg5xx.cpp b/clang/test/CXX/drs/cwg5xx.cpp
index 71793ea1be585..89a2be203766e 100644
--- a/clang/test/CXX/drs/cwg5xx.cpp
+++ b/clang/test/CXX/drs/cwg5xx.cpp
@@ -1,7 +1,7 @@
 // RUN: %clang_cc1 -std=c++98 %s -fexceptions -fcxx-exceptions -pedantic-errors -verify-directives -verify=expected,cxx98-23,cxx98-11,cxx98-14,cxx98-17,cxx98
 // RUN: %clang_cc1 -std=c++11 %s -fexceptions -fcxx-exceptions -pedantic-errors -verify-directives -verify=expected,cxx98-23,cxx98-11,cxx98-14,cxx98-17,since-cxx11
 // RUN: %clang_cc1 -std=c++14 %s -fexceptions -fcxx-exceptions -pedantic-errors -verify-directives -verify=expected,cxx98-23,cxx98-14,cxx98-17,since-cxx11
-// RUN: %clang_cc1 -std=c++17 %s -fexceptions -fcxx-exceptions -pedantic-errors -verify-directives -verify=expected,cxx98-23,since-cxx17,cxx17,cxx98-17,since-cxx11
+// RUN: %clang_cc1 -std=c++17 %s -fexceptions -fcxx-exceptions -pedantic-errors -verify-directives -verify=expected,cxx98-23,since-cxx17,cxx98-17,since-cxx11
 // RUN: %clang_cc1 -std=c++20 %s -fexceptions -fcxx-exceptions -pedantic-errors -verify-directives -verify=expected,cxx98-23,since-cxx20,since-cxx17,since-cxx11
 // RUN: %clang_cc1 -std=c++23 %s -fexceptions -fcxx-exceptions -pedantic-errors -verify-directives -verify=expected,cxx98-23,since-cxx23,since-cxx20,since-cxx17,since-cxx11
 // RUN: %clang_cc1 -std=c++2c %s -fexceptions -fcxx-exceptions -pedantic-errors -verify-directives -verify=expected,since-cxx26,since-cxx23,since-cxx20,since-cxx17,since-cxx11
@@ -682,9 +682,8 @@ namespace cwg553 {
   // "is looked up in global scope", where it is not visible.
   void *p = new (c) int;
   // expected-error at -1 {{no matching function for call to 'operator new'}}
-  //   cxx17-note@#cwg5xx-global-operator-new-aligned {{candidate function not viable: no known conversion from 'cwg553_class' to 'std::align_val_t' for 2nd argument}}
   //   expected-note@#cwg5xx-global-operator-new {{candidate function not viable: requires 1 argument, but 2 were provided}}
-  //   since-cxx20-note@#cwg5xx-global-operator-new-aligned {{candidate function not viable: requires 2 arguments, but 3 were provided}}
+  //   since-cxx17-note@#cwg5xx-global-operator-new-aligned {{candidate function not viable: requires 2 arguments, but 3 were provided}}
 
   struct namespace_scope {
     friend void *operator new(size_t, namespace_scope);
diff --git a/clang/test/CXX/expr/expr.unary/expr.new/p14.cpp b/clang/test/CXX/expr/expr.unary/expr.new/p14.cpp
index dd1b63687f308..2f8404a83c00d 100644
--- a/clang/test/CXX/expr/expr.unary/expr.new/p14.cpp
+++ b/clang/test/CXX/expr/expr.unary/expr.new/p14.cpp
@@ -1,5 +1,4 @@
-// RUN: %clang_cc1 -std=c++1z -fexceptions %s -verify=expected,cxx17
-// RUN: %clang_cc1 -std=c++20 -fexceptions %s -verify=expected,since-cxx20
+// RUN: %clang_cc1 -std=c++1z -fexceptions %s -verify
 
 using size_t = decltype(sizeof(0));
 namespace std { enum class align_val_t : size_t {}; }
@@ -7,9 +6,7 @@ namespace std { enum class align_val_t : size_t {}; }
 struct Arg {} arg;
 
 // If the type is aligned, first try with an alignment argument and then
-// without. If not:
-// - For C++17, never consider supplying an alignment;
-// - For C++20 and later, try without an alignment argument first, then with it.
+// without. If not, try in the reverse order.
 
 template<unsigned Align, typename ...Ts>
 struct alignas(Align) Unaligned {
@@ -22,11 +19,11 @@ auto *ubp = new (arg) Unaligned<__STDCPP_DEFAULT_NEW_ALIGNMENT__ * 2, Arg>; // e
 
 template<unsigned Align, typename ...Ts>
 struct alignas(Align) Aligned {
-  void *operator new(size_t, std::align_val_t, Ts...) = delete; // cxx17-note 2{{deleted}} cxx17-note 2{{not viable}} since-cxx20-note 4{{deleted}}
+  void *operator new(size_t, std::align_val_t, Ts...) = delete; // expected-note 4{{deleted}}
 };
-auto *aa = new Aligned<__STDCPP_DEFAULT_NEW_ALIGNMENT__>; // cxx17-error {{no matching}} since-cxx20-error {{deleted}}
+auto *aa = new Aligned<__STDCPP_DEFAULT_NEW_ALIGNMENT__>; // expected-error {{deleted}}
 auto *ab = new Aligned<__STDCPP_DEFAULT_NEW_ALIGNMENT__ * 2>; // expected-error {{deleted}}
-auto *aap = new (arg) Aligned<__STDCPP_DEFAULT_NEW_ALIGNMENT__, Arg>; // cxx17-error {{no matching}} since-cxx20-error {{deleted}}
+auto *aap = new (arg) Aligned<__STDCPP_DEFAULT_NEW_ALIGNMENT__, Arg>; // expected-error {{deleted}}
 auto *abp = new (arg) Aligned<__STDCPP_DEFAULT_NEW_ALIGNMENT__ * 2, Arg>; // expected-error {{deleted}}
 
 // If both are available, we prefer the aligned version for an overaligned
diff --git a/clang/test/SemaCXX/new-delete.cpp b/clang/test/SemaCXX/new-delete.cpp
index 408cce414264f..f8a1743521415 100644
--- a/clang/test/SemaCXX/new-delete.cpp
+++ b/clang/test/SemaCXX/new-delete.cpp
@@ -2,21 +2,20 @@
 // RUN: %clang_cc1 -fsyntax-only -verify=expected,cxx98-23,precxx20 %s -triple=i686-pc-linux-gnu -Wno-new-returns-null -std=c++11
 // RUN: %clang_cc1 -fsyntax-only -verify=expected,cxx98-23,precxx20 %s -triple=i686-pc-linux-gnu -Wno-new-returns-null -std=c++14
 // RUN: %clang_cc1 -fsyntax-only -verify=expected,cxx98-23,cxx17,precxx20 %s -triple=i686-pc-linux-gnu -Wno-new-returns-null -std=c++17
-// RUN: %clang_cc1 -fsyntax-only -verify=expected,cxx98-23,cxx20 %s -triple=i686-pc-linux-gnu -Wno-new-returns-null -std=c++20
-// RUN: %clang_cc1 -fsyntax-only -verify=expected,cxx98-23,cxx20 %s -triple=i686-pc-linux-gnu -Wno-new-returns-null -std=c++23
-// RUN: %clang_cc1 -fsyntax-only -verify=expected,since-cxx26,cxx20 %s -triple=i686-pc-linux-gnu -Wno-new-returns-null -std=c++2c
+// RUN: %clang_cc1 -fsyntax-only -verify=expected,cxx98-23,cxx17,cxx20 %s -triple=i686-pc-linux-gnu -Wno-new-returns-null -std=c++20
+// RUN: %clang_cc1 -fsyntax-only -verify=expected,cxx98-23,cxx17,cxx20 %s -triple=i686-pc-linux-gnu -Wno-new-returns-null -std=c++23
+// RUN: %clang_cc1 -fsyntax-only -verify=expected,since-cxx26,cxx17,cxx20 %s -triple=i686-pc-linux-gnu -Wno-new-returns-null -std=c++2c
 
 // RUN: %clang_cc1 -fsyntax-only -verify=expected,cxx98-23,precxx20 %s -triple=i686-pc-linux-gnu -Wno-new-returns-null -std=c++98 -fexperimental-new-constant-interpreter -DNEW_INTERP
 // RUN: %clang_cc1 -fsyntax-only -verify=expected,cxx98-23,precxx20 %s -triple=i686-pc-linux-gnu -Wno-new-returns-null -std=c++11 -fexperimental-new-constant-interpreter -DNEW_INTERP
 // RUN: %clang_cc1 -fsyntax-only -verify=expected,cxx98-23,precxx20 %s -triple=i686-pc-linux-gnu -Wno-new-returns-null -std=c++14 -fexperimental-new-constant-interpreter -DNEW_INTERP
 // RUN: %clang_cc1 -fsyntax-only -verify=expected,cxx98-23,cxx17,precxx20 %s -triple=i686-pc-linux-gnu -Wno-new-returns-null -std=c++17 -fexperimental-new-constant-interpreter -DNEW_INTERP
-// RUN: %clang_cc1 -fsyntax-only -verify=expected,cxx98-23,cxx20 %s -triple=i686-pc-linux-gnu -Wno-new-returns-null -std=c++20 -fexperimental-new-constant-interpreter -DNEW_INTERP
-// RUN: %clang_cc1 -fsyntax-only -verify=expected,cxx98-23,cxx20 %s -triple=i686-pc-linux-gnu -Wno-new-returns-null -std=c++23 -fexperimental-new-constant-interpreter -DNEW_INTERP
-// RUN: %clang_cc1 -fsyntax-only -verify=expected,since-cxx26,cxx20 %s -triple=i686-pc-linux-gnu -Wno-new-returns-null -std=c++2c -fexperimental-new-constant-interpreter -DNEW_INTERP
+// RUN: %clang_cc1 -fsyntax-only -verify=expected,cxx98-23,cxx17,cxx20 %s -triple=i686-pc-linux-gnu -Wno-new-returns-null -std=c++20 -fexperimental-new-constant-interpreter -DNEW_INTERP
+// RUN: %clang_cc1 -fsyntax-only -verify=expected,cxx98-23,cxx17,cxx20 %s -triple=i686-pc-linux-gnu -Wno-new-returns-null -std=c++23 -fexperimental-new-constant-interpreter -DNEW_INTERP
+// RUN: %clang_cc1 -fsyntax-only -verify=expected,since-cxx26,cxx17,cxx20 %s -triple=i686-pc-linux-gnu -Wno-new-returns-null -std=c++2c -fexperimental-new-constant-interpreter -DNEW_INTERP
 
 // FIXME Location is (frontend)
-// cxx17-note@*:* {{candidate function not viable: requires 2 arguments, but 3 were provided}}
-// cxx20-note@*:* {{candidate function not viable: requires 2 arguments, but 4 were provided}}
+// cxx17-note@*:* {{candidate function not viable: requires 2 arguments, but 4 were provided}}
 
 #include <stddef.h>
 
diff --git a/clang/test/SemaCXX/std-align-val-t-in-operator-new.cpp b/clang/test/SemaCXX/std-align-val-t-in-operator-new.cpp
index dc6a8ab6471d5..5bedb66a1e27c 100644
--- a/clang/test/SemaCXX/std-align-val-t-in-operator-new.cpp
+++ b/clang/test/SemaCXX/std-align-val-t-in-operator-new.cpp
@@ -4,8 +4,6 @@
 // RUN: %clang_cc1 -std=c++14 -faligned-allocation -fsyntax-only -verify %s
 // RUN: %clang_cc1 -std=c++17                      -fsyntax-only -verify %s
 // RUN: %clang_cc1 -std=c++17 -faligned-allocation -fsyntax-only -verify %s
-// RUN: %clang_cc1 -std=c++20                      -fsyntax-only -verify %s
-// RUN: %clang_cc1 -std=c++20 -faligned-allocation -fsyntax-only -verify %s
 
 namespace std {
 typedef __SIZE_TYPE__ size_t;
@@ -64,7 +62,7 @@ void *operator new(std::size_t, std::align_val_t, X); // #3
 // FIXME: Consider improving notes 1 and 3 here to say that these are aligned
 // allocation functions and the type is not over-aligned.
 X *p = new (123) X; // expected-error {{no matching function}}
-#if __cplusplus >= 202002L
+#if __cpp_aligned_new
 // expected-note@#1 {{requires 2 arguments, but 4 were provided}}
 #else
 // expected-note@#1 {{no known conversion from 'int' to 'std::align_val_t' for 2nd argument}}

>From 086235791614782614831ad0a624d4c395228af2 Mon Sep 17 00:00:00 2001
From: Igor Kudrin <ikudrin at accesssoftek.com>
Date: Fri, 19 Jun 2026 23:26:13 -0700
Subject: [PATCH 3/3] fixup! Do not try the msvc-specific fallback with the
 alignment argument

---
 clang/lib/Sema/SemaExprCXX.cpp | 11 +++++++++--
 1 file changed, 9 insertions(+), 2 deletions(-)

diff --git a/clang/lib/Sema/SemaExprCXX.cpp b/clang/lib/Sema/SemaExprCXX.cpp
index b88b88f69efc0..dc50899154a82 100644
--- a/clang/lib/Sema/SemaExprCXX.cpp
+++ b/clang/lib/Sema/SemaExprCXX.cpp
@@ -2785,9 +2785,16 @@ static bool resolveAllocationOverload(
       R.clear();
       R.setLookupName(S.Context.DeclarationNames.getCXXOperatorName(OO_New));
       S.LookupQualifiedName(R, S.Context.getTranslationUnitDecl());
+      // Only try this fallback without the alignment argument.
+      auto &Args =
+          (FallbackArgs.empty() || PrefArgs.size() < FallbackArgs.size())
+              ? PrefArgs
+              : FallbackArgs;
+      SmallVector<Expr *, 1> EmptyArgs;
+      PassAlignment = AlignedAllocationMode::No;
       // FIXME: This will give bad diagnostics pointing at the wrong functions.
-      return resolveAllocationOverload(S, R, Range, Mode, PrefArgs,
-                                       FallbackArgs, PassAlignment, Operator,
+      return resolveAllocationOverload(S, R, Range, Mode, Args, EmptyArgs,
+                                       PassAlignment, Operator,
                                        /*PrefCandidates=*/nullptr, Diagnose);
     }
     if (Mode == ResolveMode::Typed) {



More information about the llvm-branch-commits mailing list