[clang] 4e02ff2 - [clang] Revert parentesized aggregate initalization patches

Alan Zhao via cfe-commits cfe-commits at lists.llvm.org
Wed Jan 4 15:09:43 PST 2023


Author: Alan Zhao
Date: 2023-01-04T15:09:36-08:00
New Revision: 4e02ff2303f8a69cc2459b77bbb879b248df6ca9

URL: https://github.com/llvm/llvm-project/commit/4e02ff2303f8a69cc2459b77bbb879b248df6ca9
DIFF: https://github.com/llvm/llvm-project/commit/4e02ff2303f8a69cc2459b77bbb879b248df6ca9.diff

LOG: [clang] Revert parentesized aggregate initalization patches

This feature causes clang to crash when compiling Chrome - see
https://crbug.com/1405031 and
https://github.com/llvm/llvm-project/issues/59675

Revert "[clang] Fix a clang crash on invalid code in C++20 mode."

This reverts commit 32d7aae04fdb58e65a952f281ff2f2c3f396d98f.

Revert "[clang] Remove overly restrictive aggregate paren init logic"

This reverts commit c77a91bb7ba793ec3a6a5da3743ed55056291658.

Revert "[clang][C++20] P0960R3 and P1975R0: Allow initializing aggregates from a parenthesized list of values"

This reverts commit 40c52159d3ee337dbed14e4c73b5616ea354c337.

Added: 
    

Modified: 
    clang/docs/ReleaseNotes.rst
    clang/include/clang-c/Index.h
    clang/include/clang/AST/ASTNodeTraverser.h
    clang/include/clang/AST/ComputeDependence.h
    clang/include/clang/AST/Decl.h
    clang/include/clang/AST/ExprCXX.h
    clang/include/clang/AST/RecursiveASTVisitor.h
    clang/include/clang/Basic/DiagnosticSemaKinds.td
    clang/include/clang/Basic/StmtNodes.td
    clang/include/clang/Sema/Initialization.h
    clang/include/clang/Serialization/ASTBitCodes.h
    clang/lib/AST/ComputeDependence.cpp
    clang/lib/AST/Expr.cpp
    clang/lib/AST/ExprCXX.cpp
    clang/lib/AST/ExprClassification.cpp
    clang/lib/AST/ExprConstant.cpp
    clang/lib/AST/ItaniumMangle.cpp
    clang/lib/AST/JSONNodeDumper.cpp
    clang/lib/AST/StmtPrinter.cpp
    clang/lib/AST/StmtProfile.cpp
    clang/lib/AST/TextNodeDumper.cpp
    clang/lib/CodeGen/CGExprAgg.cpp
    clang/lib/Frontend/InitPreprocessor.cpp
    clang/lib/Sema/SemaCast.cpp
    clang/lib/Sema/SemaDecl.cpp
    clang/lib/Sema/SemaExceptionSpec.cpp
    clang/lib/Sema/SemaInit.cpp
    clang/lib/Sema/TreeTransform.h
    clang/lib/Serialization/ASTReaderStmt.cpp
    clang/lib/Serialization/ASTWriter.cpp
    clang/lib/Serialization/ASTWriterStmt.cpp
    clang/lib/StaticAnalyzer/Core/ExprEngine.cpp
    clang/test/CXX/temp/temp.decls/temp.variadic/p4.cpp
    clang/test/Lexer/cxx-features.cpp
    clang/test/SemaCXX/cxx2a-explicit-bool.cpp
    clang/test/SemaCXX/recovery-expr-type.cpp
    clang/tools/libclang/CIndex.cpp
    clang/tools/libclang/CXCursor.cpp
    clang/www/cxx_status.html

Removed: 
    clang/test/CodeGen/paren-list-agg-init.cpp
    clang/test/PCH/cxx_paren_init.cpp
    clang/test/PCH/cxx_paren_init.h
    clang/test/SemaCXX/paren-list-agg-init.cpp


################################################################################
diff  --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst
index 0fe0097400823..a3abdf45fead1 100644
--- a/clang/docs/ReleaseNotes.rst
+++ b/clang/docs/ReleaseNotes.rst
@@ -714,10 +714,6 @@ C++20 Feature Support
   (useful specially for constrained members). Fixes `GH50886 <https://github.com/llvm/llvm-project/issues/50886>`_.
 - Implemented CWG2635 as a Defect Report, which prohibits structured bindings from being constrained.
 
-- Implemented `P0960R3: <https://www.open-std.org/jtc1/sc22/wg21/docs/papers/2019/p0960r3.html>`_
-  and `P1975R0: <https://www.open-std.org/jtc1/sc22/wg21/docs/papers/2019/p1975r0.html>`_,
-  which allows parenthesized aggregate-initialization.
-
 C++2b Feature Support
 ^^^^^^^^^^^^^^^^^^^^^
 

diff  --git a/clang/include/clang-c/Index.h b/clang/include/clang-c/Index.h
index fd758ddde085d..5260085021928 100644
--- a/clang/include/clang-c/Index.h
+++ b/clang/include/clang-c/Index.h
@@ -1531,13 +1531,7 @@ enum CXCursorKind {
    */
   CXCursor_RequiresExpr = 154,
 
-  /**
-   * Expression that references a C++20 parenthesized list aggregate
-   * initializer.
-   */
-  CXCursor_CXXParenListInitExpr = 155,
-
-  CXCursor_LastExpr = CXCursor_CXXParenListInitExpr,
+  CXCursor_LastExpr = CXCursor_RequiresExpr,
 
   /* Statements */
   CXCursor_FirstStmt = 200,

diff  --git a/clang/include/clang/AST/ASTNodeTraverser.h b/clang/include/clang/AST/ASTNodeTraverser.h
index cc60877805f98..151a9c6b58524 100644
--- a/clang/include/clang/AST/ASTNodeTraverser.h
+++ b/clang/include/clang/AST/ASTNodeTraverser.h
@@ -710,12 +710,6 @@ class ASTNodeTraverser
     }
   }
 
-  void VisitCXXParenListInitExpr(const CXXParenListInitExpr *PLIE) {
-    if (auto *Filler = PLIE->getArrayFiller()) {
-      Visit(Filler, "array_filler");
-    }
-  }
-
   void VisitBlockExpr(const BlockExpr *Node) { Visit(Node->getBlockDecl()); }
 
   void VisitOpaqueValueExpr(const OpaqueValueExpr *Node) {

diff  --git a/clang/include/clang/AST/ComputeDependence.h b/clang/include/clang/AST/ComputeDependence.h
index f62611cb4c3cf..3360fd11ab1f7 100644
--- a/clang/include/clang/AST/ComputeDependence.h
+++ b/clang/include/clang/AST/ComputeDependence.h
@@ -79,7 +79,6 @@ class CXXUnresolvedConstructExpr;
 class CXXDependentScopeMemberExpr;
 class MaterializeTemporaryExpr;
 class CXXFoldExpr;
-class CXXParenListInitExpr;
 class TypeTraitExpr;
 class ConceptSpecializationExpr;
 class SYCLUniqueStableNameExpr;
@@ -169,7 +168,6 @@ ExprDependence computeDependence(CXXUnresolvedConstructExpr *E);
 ExprDependence computeDependence(CXXDependentScopeMemberExpr *E);
 ExprDependence computeDependence(MaterializeTemporaryExpr *E);
 ExprDependence computeDependence(CXXFoldExpr *E);
-ExprDependence computeDependence(CXXParenListInitExpr *E);
 ExprDependence computeDependence(TypeTraitExpr *E);
 ExprDependence computeDependence(ConceptSpecializationExpr *E,
                                  bool ValueDependent);

diff  --git a/clang/include/clang/AST/Decl.h b/clang/include/clang/AST/Decl.h
index 858cd00efc4ec..f84ff303f235e 100644
--- a/clang/include/clang/AST/Decl.h
+++ b/clang/include/clang/AST/Decl.h
@@ -914,10 +914,7 @@ class VarDecl : public DeclaratorDecl, public Redeclarable<VarDecl> {
     CallInit,
 
     /// Direct list-initialization (C++11)
-    ListInit,
-
-    /// Parenthesized list-initialization (C++20)
-    ParenListInit
+    ListInit
   };
 
   /// Kinds of thread-local storage.

diff  --git a/clang/include/clang/AST/ExprCXX.h b/clang/include/clang/AST/ExprCXX.h
index 715dba013e1bb..c2f6751d62ede 100644
--- a/clang/include/clang/AST/ExprCXX.h
+++ b/clang/include/clang/AST/ExprCXX.h
@@ -4713,130 +4713,6 @@ class CXXFoldExpr : public Expr {
   }
 };
 
-/// Represents a list-initialization with parenthesis.
-///
-/// As per P0960R3, this is a C++20 feature that allows aggregate to
-/// be initialized with a parenthesized list of values:
-/// ```
-/// struct A {
-///   int a;
-///   double b;
-/// };
-///
-/// void foo() {
-///   A a1(0);        // Well-formed in C++20
-///   A a2(1.5, 1.0); // Well-formed in C++20
-/// }
-/// ```
-/// It has some sort of similiarity to braced
-/// list-initialization, with some 
diff erences such as
-/// it allows narrowing conversion whilst braced
-/// list-initialization doesn't.
-/// ```
-/// struct A {
-///   char a;
-/// };
-/// void foo() {
-///   A a(1.5); // Well-formed in C++20
-///   A b{1.5}; // Ill-formed !
-/// }
-/// ```
-class CXXParenListInitExpr final
-    : public Expr,
-      private llvm::TrailingObjects<CXXParenListInitExpr, Expr *> {
-  friend class TrailingObjects;
-  friend class ASTStmtReader;
-  friend class ASTStmtWriter;
-
-  unsigned NumExprs;
-  unsigned NumUserSpecifiedExprs;
-  SourceLocation InitLoc, LParenLoc, RParenLoc;
-  Expr *ArrayFiller = nullptr;
-
-  CXXParenListInitExpr(ArrayRef<Expr *> Args, QualType T,
-                       unsigned NumUserSpecifiedExprs, SourceLocation InitLoc,
-                       SourceLocation LParenLoc, SourceLocation RParenLoc)
-      : Expr(CXXParenListInitExprClass, T,
-             T->isLValueReferenceType()   ? VK_LValue
-             : T->isRValueReferenceType() ? VK_XValue
-                                          : VK_PRValue,
-             OK_Ordinary),
-        NumExprs(Args.size()), NumUserSpecifiedExprs(NumUserSpecifiedExprs),
-        InitLoc(InitLoc), LParenLoc(LParenLoc), RParenLoc(RParenLoc) {
-    std::copy(Args.begin(), Args.end(), getTrailingObjects<Expr *>());
-    assert(NumExprs >= NumUserSpecifiedExprs &&
-           "number of user specified inits is greater than the number of "
-           "passed inits");
-    setDependence(computeDependence(this));
-  }
-
-  size_t numTrailingObjects(OverloadToken<Expr *>) const { return NumExprs; }
-
-public:
-  static CXXParenListInitExpr *
-  Create(ASTContext &C, ArrayRef<Expr *> Args, QualType T,
-         unsigned NumUserSpecifiedExprs, SourceLocation InitLoc,
-         SourceLocation LParenLoc, SourceLocation RParenLoc);
-
-  static CXXParenListInitExpr *CreateEmpty(ASTContext &C, unsigned numExprs,
-                                           EmptyShell Empty);
-
-  explicit CXXParenListInitExpr(EmptyShell Empty, unsigned NumExprs)
-      : Expr(CXXParenListInitExprClass, Empty), NumExprs(NumExprs),
-        NumUserSpecifiedExprs(0) {}
-
-  void updateDependence() { setDependence(computeDependence(this)); }
-
-  ArrayRef<Expr *> getInitExprs() {
-    return llvm::makeArrayRef(getTrailingObjects<Expr *>(), NumExprs);
-  }
-
-  const ArrayRef<Expr *> getInitExprs() const {
-    return llvm::makeArrayRef(getTrailingObjects<Expr *>(), NumExprs);
-  }
-
-  ArrayRef<Expr *> getUserSpecifiedInitExprs() {
-    return llvm::makeArrayRef(getTrailingObjects<Expr *>(),
-                              NumUserSpecifiedExprs);
-  }
-
-  const ArrayRef<Expr *> getUserSpecifiedInitExprs() const {
-    return llvm::makeArrayRef(getTrailingObjects<Expr *>(),
-                              NumUserSpecifiedExprs);
-  }
-
-  SourceLocation getBeginLoc() const LLVM_READONLY { return LParenLoc; }
-
-  SourceLocation getEndLoc() const LLVM_READONLY { return RParenLoc; }
-
-  SourceLocation getInitLoc() const LLVM_READONLY { return InitLoc; }
-
-  SourceRange getSourceRange() const LLVM_READONLY {
-    return SourceRange(getBeginLoc(), getEndLoc());
-  }
-
-  void setArrayFiller(Expr *E) { ArrayFiller = E; }
-
-  Expr *getArrayFiller() { return ArrayFiller; }
-
-  const Expr *getArrayFiller() const { return ArrayFiller; }
-
-  child_range children() {
-    Stmt **Begin = reinterpret_cast<Stmt **>(getTrailingObjects<Expr *>());
-    return child_range(Begin, Begin + NumExprs);
-  }
-
-  const_child_range children() const {
-    Stmt *const *Begin =
-        reinterpret_cast<Stmt *const *>(getTrailingObjects<Expr *>());
-    return const_child_range(Begin, Begin + NumExprs);
-  }
-
-  static bool classof(const Stmt *T) {
-    return T->getStmtClass() == CXXParenListInitExprClass;
-  }
-};
-
 /// Represents an expression that might suspend coroutine execution;
 /// either a co_await or co_yield expression.
 ///

diff  --git a/clang/include/clang/AST/RecursiveASTVisitor.h b/clang/include/clang/AST/RecursiveASTVisitor.h
index 7036200c54866..127c86b163a6d 100644
--- a/clang/include/clang/AST/RecursiveASTVisitor.h
+++ b/clang/include/clang/AST/RecursiveASTVisitor.h
@@ -2852,7 +2852,6 @@ DEF_TRAVERSE_STMT(SubstNonTypeTemplateParmExpr, {})
 DEF_TRAVERSE_STMT(FunctionParmPackExpr, {})
 DEF_TRAVERSE_STMT(CXXFoldExpr, {})
 DEF_TRAVERSE_STMT(AtomicExpr, {})
-DEF_TRAVERSE_STMT(CXXParenListInitExpr, {})
 
 DEF_TRAVERSE_STMT(MaterializeTemporaryExpr, {
   if (S->getLifetimeExtendedTemporaryDecl()) {

diff  --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td b/clang/include/clang/Basic/DiagnosticSemaKinds.td
index 60ff607a3edc6..16ab35fcb7a67 100644
--- a/clang/include/clang/Basic/DiagnosticSemaKinds.td
+++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td
@@ -2164,9 +2164,6 @@ def err_init_list_bad_dest_type : Error<
 def warn_cxx20_compat_aggregate_init_with_ctors : Warning<
   "aggregate initialization of type %0 with user-declared constructors "
   "is incompatible with C++20">, DefaultIgnore, InGroup<CXX20Compat>;
-def warn_cxx17_compat_aggregate_init_paren_list : Warning<
-  "aggregate initialization of type %0 from a parenthesized list of values "
-  "is a C++20 extension">, DefaultIgnore, InGroup<CXX20>;
 
 def err_reference_bind_to_bitfield : Error<
   "%select{non-const|volatile}0 reference cannot bind to "

diff  --git a/clang/include/clang/Basic/StmtNodes.td b/clang/include/clang/Basic/StmtNodes.td
index eeec01dd8c84d..c434b07c95a40 100644
--- a/clang/include/clang/Basic/StmtNodes.td
+++ b/clang/include/clang/Basic/StmtNodes.td
@@ -160,7 +160,6 @@ def FunctionParmPackExpr : StmtNode<Expr>;
 def MaterializeTemporaryExpr : StmtNode<Expr>;
 def LambdaExpr : StmtNode<Expr>;
 def CXXFoldExpr : StmtNode<Expr>;
-def CXXParenListInitExpr: StmtNode<Expr>;
 
 // C++ Coroutines TS expressions
 def CoroutineSuspendExpr : StmtNode<Expr, 1>;

diff  --git a/clang/include/clang/Sema/Initialization.h b/clang/include/clang/Sema/Initialization.h
index e5a98ba97f4f1..21adc9fa2ac0b 100644
--- a/clang/include/clang/Sema/Initialization.h
+++ b/clang/include/clang/Sema/Initialization.h
@@ -923,11 +923,7 @@ class InitializationSequence {
     SK_OCLSamplerInit,
 
     /// Initialize an opaque OpenCL type (event_t, queue_t, etc.) with zero
-    SK_OCLZeroOpaqueType,
-
-    /// Initialize an aggreagate with parenthesized list of values.
-    /// This is a C++20 feature.
-    SK_ParenthesizedListInit
+    SK_OCLZeroOpaqueType
   };
 
   /// A single step in the initialization sequence.
@@ -1103,10 +1099,6 @@ class InitializationSequence {
 
     /// List-copy-initialization chose an explicit constructor.
     FK_ExplicitConstructor,
-
-    /// Parenthesized list initialization failed at some point.
-    /// This is a C++20 feature.
-    FK_ParenthesizedListInitFailed,
   };
 
 private:
@@ -1365,8 +1357,6 @@ class InitializationSequence {
   /// from a zero constant.
   void AddOCLZeroOpaqueTypeStep(QualType T);
 
-  void AddParenthesizedListInitStep(QualType T);
-
   /// Add steps to unwrap a initializer list for a reference around a
   /// single element and rewrap it at the end.
   void RewrapReferenceInitList(QualType T, InitListExpr *Syntactic);

diff  --git a/clang/include/clang/Serialization/ASTBitCodes.h b/clang/include/clang/Serialization/ASTBitCodes.h
index 9ba94da03720e..81461e24b7a25 100644
--- a/clang/include/clang/Serialization/ASTBitCodes.h
+++ b/clang/include/clang/Serialization/ASTBitCodes.h
@@ -1861,9 +1861,6 @@ enum StmtCode {
   /// A CXXBoolLiteralExpr record.
   EXPR_CXX_BOOL_LITERAL,
 
-  /// A CXXParenListInitExpr record.
-  EXPR_CXX_PAREN_LIST_INIT,
-
   EXPR_CXX_NULL_PTR_LITERAL, // CXXNullPtrLiteralExpr
   EXPR_CXX_TYPEID_EXPR,      // CXXTypeidExpr (of expr).
   EXPR_CXX_TYPEID_TYPE,      // CXXTypeidExpr (of type).

diff  --git a/clang/lib/AST/ComputeDependence.cpp b/clang/lib/AST/ComputeDependence.cpp
index f25b62d53f85d..40ebde06d7718 100644
--- a/clang/lib/AST/ComputeDependence.cpp
+++ b/clang/lib/AST/ComputeDependence.cpp
@@ -831,13 +831,6 @@ ExprDependence clang::computeDependence(CXXFoldExpr *E) {
   return D;
 }
 
-ExprDependence clang::computeDependence(CXXParenListInitExpr *E) {
-  auto D = ExprDependence::None;
-  for (const auto *A : E->getInitExprs())
-    D |= A->getDependence();
-  return D;
-}
-
 ExprDependence clang::computeDependence(TypeTraitExpr *E) {
   auto D = ExprDependence::None;
   for (const auto *A : E->getArgs())

diff  --git a/clang/lib/AST/Expr.cpp b/clang/lib/AST/Expr.cpp
index a735f95427d16..688f760b2234e 100644
--- a/clang/lib/AST/Expr.cpp
+++ b/clang/lib/AST/Expr.cpp
@@ -3644,7 +3644,6 @@ bool Expr::HasSideEffects(const ASTContext &Ctx,
   case ShuffleVectorExprClass:
   case ConvertVectorExprClass:
   case AsTypeExprClass:
-  case CXXParenListInitExprClass:
     // These have a side-effect if any subexpression does.
     break;
 

diff  --git a/clang/lib/AST/ExprCXX.cpp b/clang/lib/AST/ExprCXX.cpp
index ea88b270b1e3f..b988f0fe13f7f 100644
--- a/clang/lib/AST/ExprCXX.cpp
+++ b/clang/lib/AST/ExprCXX.cpp
@@ -1757,21 +1757,3 @@ CUDAKernelCallExpr *CUDAKernelCallExpr::CreateEmpty(const ASTContext &Ctx,
                            alignof(CUDAKernelCallExpr));
   return new (Mem) CUDAKernelCallExpr(NumArgs, HasFPFeatures, Empty);
 }
-
-CXXParenListInitExpr *
-CXXParenListInitExpr::Create(ASTContext &C, ArrayRef<Expr *> Args, QualType T,
-                             unsigned NumUserSpecifiedExprs,
-                             SourceLocation InitLoc, SourceLocation LParenLoc,
-                             SourceLocation RParenLoc) {
-  void *Mem = C.Allocate(totalSizeToAlloc<Expr *>(Args.size()));
-  return new (Mem) CXXParenListInitExpr(Args, T, NumUserSpecifiedExprs, InitLoc,
-                                        LParenLoc, RParenLoc);
-}
-
-CXXParenListInitExpr *CXXParenListInitExpr::CreateEmpty(ASTContext &C,
-                                                        unsigned NumExprs,
-                                                        EmptyShell Empty) {
-  void *Mem = C.Allocate(totalSizeToAlloc<Expr *>(NumExprs),
-                         alignof(CXXParenListInitExpr));
-  return new (Mem) CXXParenListInitExpr(Empty, NumExprs);
-}

diff  --git a/clang/lib/AST/ExprClassification.cpp b/clang/lib/AST/ExprClassification.cpp
index 12193b7812f9b..88081d9ed73a5 100644
--- a/clang/lib/AST/ExprClassification.cpp
+++ b/clang/lib/AST/ExprClassification.cpp
@@ -445,11 +445,6 @@ static Cl::Kinds ClassifyInternal(ASTContext &Ctx, const Expr *E) {
   case Expr::SYCLUniqueStableNameExprClass:
     return Cl::CL_PRValue;
     break;
-
-  case Expr::CXXParenListInitExprClass:
-    if (isa<ArrayType>(E->getType()))
-      return Cl::CL_ArrayTemporary;
-    return Cl::CL_ClassTemporary;
   }
 
   llvm_unreachable("unhandled expression kind in classification");

diff  --git a/clang/lib/AST/ExprConstant.cpp b/clang/lib/AST/ExprConstant.cpp
index 120ceb9ad0814..78cfecbec9fd3 100644
--- a/clang/lib/AST/ExprConstant.cpp
+++ b/clang/lib/AST/ExprConstant.cpp
@@ -9836,9 +9836,6 @@ namespace {
     bool VisitCXXConstructExpr(const CXXConstructExpr *E, QualType T);
     bool VisitCXXStdInitializerListExpr(const CXXStdInitializerListExpr *E);
     bool VisitBinCmp(const BinaryOperator *E);
-    bool VisitCXXParenListInitExpr(const CXXParenListInitExpr *E);
-    bool VisitCXXParenListOrInitListExpr(const Expr *ExprToVisit,
-                                         ArrayRef<Expr *> Args);
   };
 }
 
@@ -9957,13 +9954,8 @@ bool RecordExprEvaluator::VisitCastExpr(const CastExpr *E) {
 bool RecordExprEvaluator::VisitInitListExpr(const InitListExpr *E) {
   if (E->isTransparent())
     return Visit(E->getInit(0));
-  return VisitCXXParenListOrInitListExpr(E, E->inits());
-}
 
-bool RecordExprEvaluator::VisitCXXParenListOrInitListExpr(
-    const Expr *ExprToVisit, ArrayRef<Expr *> Args) {
-  const RecordDecl *RD =
-      ExprToVisit->getType()->castAs<RecordType>()->getDecl();
+  const RecordDecl *RD = E->getType()->castAs<RecordType>()->getDecl();
   if (RD->isInvalidDecl()) return false;
   const ASTRecordLayout &Layout = Info.Ctx.getASTRecordLayout(RD);
   auto *CXXRD = dyn_cast<CXXRecordDecl>(RD);
@@ -9974,25 +9966,7 @@ bool RecordExprEvaluator::VisitCXXParenListOrInitListExpr(
       CXXRD && CXXRD->getNumBases());
 
   if (RD->isUnion()) {
-    const FieldDecl *Field;
-    if (auto *ILE = dyn_cast<InitListExpr>(ExprToVisit)) {
-      Field = ILE->getInitializedFieldInUnion();
-    } else if (isa<CXXParenListInitExpr>(ExprToVisit)) {
-      assert(Args.size() == 1 &&
-             "Unions should have exactly 1 initializer in a C++ paren list");
-
-      for (const FieldDecl *FD : RD->fields()) {
-        if (FD->isUnnamedBitfield())
-          continue;
-
-        Field = FD;
-        break;
-      }
-    } else {
-      llvm_unreachable(
-          "Expression is neither an init list nor a C++ paren list");
-    }
-
+    const FieldDecl *Field = E->getInitializedFieldInUnion();
     Result = APValue(Field);
     if (!Field)
       return true;
@@ -10003,7 +9977,7 @@ bool RecordExprEvaluator::VisitCXXParenListOrInitListExpr(
     //        Is this 
diff erence ever observable for initializer lists which
     //        we don't build?
     ImplicitValueInitExpr VIE(Field->getType());
-    const Expr *InitExpr = Args.empty() ? &VIE : Args[0];
+    const Expr *InitExpr = E->getNumInits() ? E->getInit(0) : &VIE;
 
     LValue Subobject = This;
     if (!HandleLValueMember(Info, InitExpr, Subobject, Field, &Layout))
@@ -10032,8 +10006,8 @@ bool RecordExprEvaluator::VisitCXXParenListOrInitListExpr(
   // Initialize base classes.
   if (CXXRD && CXXRD->getNumBases()) {
     for (const auto &Base : CXXRD->bases()) {
-      assert(ElementNo < Args.size() && "missing init for base class");
-      const Expr *Init = Args[ElementNo];
+      assert(ElementNo < E->getNumInits() && "missing init for base class");
+      const Expr *Init = E->getInit(ElementNo);
 
       LValue Subobject = This;
       if (!HandleLValueBase(Info, Init, Subobject, CXXRD, &Base))
@@ -10060,18 +10034,18 @@ bool RecordExprEvaluator::VisitCXXParenListOrInitListExpr(
 
     LValue Subobject = This;
 
-    bool HaveInit = ElementNo < Args.size();
+    bool HaveInit = ElementNo < E->getNumInits();
 
     // FIXME: Diagnostics here should point to the end of the initializer
     // list, not the start.
-    if (!HandleLValueMember(Info, HaveInit ? Args[ElementNo] : ExprToVisit,
+    if (!HandleLValueMember(Info, HaveInit ? E->getInit(ElementNo) : E,
                             Subobject, Field, &Layout))
       return false;
 
     // Perform an implicit value-initialization for members beyond the end of
     // the initializer list.
     ImplicitValueInitExpr VIE(HaveInit ? Info.Ctx.IntTy : Field->getType());
-    const Expr *Init = HaveInit ? Args[ElementNo++] : &VIE;
+    const Expr *Init = HaveInit ? E->getInit(ElementNo++) : &VIE;
 
     if (Field->getType()->isIncompleteArrayType()) {
       if (auto *CAT = Info.Ctx.getAsConstantArrayType(Init->getType())) {
@@ -10705,11 +10679,6 @@ namespace {
       expandStringLiteral(Info, E, Result, AllocType);
       return true;
     }
-    bool VisitCXXParenListInitExpr(const CXXParenListInitExpr *E);
-    bool VisitCXXParenListOrInitListExpr(const Expr *ExprToVisit,
-                                         ArrayRef<Expr *> Args,
-                                         const Expr *ArrayFiller,
-                                         QualType AllocType = QualType());
   };
 } // end anonymous namespace
 
@@ -10785,16 +10754,6 @@ bool ArrayExprEvaluator::VisitInitListExpr(const InitListExpr *E,
   assert(!E->isTransparent() &&
          "transparent array list initialization is not string literal init?");
 
-  return VisitCXXParenListOrInitListExpr(E, E->inits(), E->getArrayFiller(),
-                                         AllocType);
-}
-
-bool ArrayExprEvaluator::VisitCXXParenListOrInitListExpr(
-    const Expr *ExprToVisit, ArrayRef<Expr *> Args, const Expr *ArrayFiller,
-    QualType AllocType) {
-  const ConstantArrayType *CAT = Info.Ctx.getAsConstantArrayType(
-      AllocType.isNull() ? ExprToVisit->getType() : AllocType);
-
   bool Success = true;
 
   assert((!Result.isArray() || Result.getArrayInitializedElts() == 0) &&
@@ -10803,12 +10762,13 @@ bool ArrayExprEvaluator::VisitCXXParenListOrInitListExpr(
   if (Result.isArray() && Result.hasArrayFiller())
     Filler = Result.getArrayFiller();
 
-  unsigned NumEltsToInit = Args.size();
+  unsigned NumEltsToInit = E->getNumInits();
   unsigned NumElts = CAT->getSize().getZExtValue();
+  const Expr *FillerExpr = E->hasArrayFiller() ? E->getArrayFiller() : nullptr;
 
   // If the initializer might depend on the array index, run it for each
   // array element.
-  if (NumEltsToInit != NumElts && MaybeElementDependentArrayFiller(ArrayFiller))
+  if (NumEltsToInit != NumElts && MaybeElementDependentArrayFiller(FillerExpr))
     NumEltsToInit = NumElts;
 
   LLVM_DEBUG(llvm::dbgs() << "The number of elements to initialize: "
@@ -10826,9 +10786,10 @@ bool ArrayExprEvaluator::VisitCXXParenListOrInitListExpr(
   }
 
   LValue Subobject = This;
-  Subobject.addArray(Info, ExprToVisit, CAT);
+  Subobject.addArray(Info, E, CAT);
   for (unsigned Index = 0; Index != NumEltsToInit; ++Index) {
-    const Expr *Init = Index < Args.size() ? Args[Index] : ArrayFiller;
+    const Expr *Init =
+        Index < E->getNumInits() ? E->getInit(Index) : FillerExpr;
     if (!EvaluateInPlace(Result.getArrayInitializedElt(Index),
                          Info, Subobject, Init) ||
         !HandleLValueArrayAdjustment(Info, Init, Subobject,
@@ -10844,10 +10805,9 @@ bool ArrayExprEvaluator::VisitCXXParenListOrInitListExpr(
 
   // If we get here, we have a trivial filler, which we can just evaluate
   // once and splat over the rest of the array elements.
-  assert(ArrayFiller && "no array filler for incomplete init list");
+  assert(FillerExpr && "no array filler for incomplete init list");
   return EvaluateInPlace(Result.getArrayFiller(), Info, Subobject,
-                         ArrayFiller) &&
-         Success;
+                         FillerExpr) && Success;
 }
 
 bool ArrayExprEvaluator::VisitArrayInitLoopExpr(const ArrayInitLoopExpr *E) {
@@ -10964,15 +10924,6 @@ bool ArrayExprEvaluator::VisitCXXConstructExpr(const CXXConstructExpr *E,
              .VisitCXXConstructExpr(E, Type);
 }
 
-bool ArrayExprEvaluator::VisitCXXParenListInitExpr(
-    const CXXParenListInitExpr *E) {
-  assert(dyn_cast<ConstantArrayType>(E->getType()) &&
-         "Expression result is not a constant array type");
-
-  return VisitCXXParenListOrInitListExpr(E, E->getInitExprs(),
-                                         E->getArrayFiller());
-}
-
 //===----------------------------------------------------------------------===//
 // Integer Evaluation
 //
@@ -13234,11 +13185,6 @@ bool RecordExprEvaluator::VisitBinCmp(const BinaryOperator *E) {
   });
 }
 
-bool RecordExprEvaluator::VisitCXXParenListInitExpr(
-    const CXXParenListInitExpr *E) {
-  return VisitCXXParenListOrInitListExpr(E, E->getInitExprs());
-}
-
 bool IntExprEvaluator::VisitBinaryOperator(const BinaryOperator *E) {
   // We don't support assignment in C. C++ assignments don't get here because
   // assignment is an lvalue in C++.
@@ -15682,7 +15628,6 @@ static ICEDiag CheckICE(const Expr* E, const ASTContext &Ctx) {
   case Expr::DependentCoawaitExprClass:
   case Expr::CoyieldExprClass:
   case Expr::SYCLUniqueStableNameExprClass:
-  case Expr::CXXParenListInitExprClass:
     return ICEDiag(IK_NotICE, E->getBeginLoc());
 
   case Expr::InitListExprClass: {

diff  --git a/clang/lib/AST/ItaniumMangle.cpp b/clang/lib/AST/ItaniumMangle.cpp
index 0633e65f388f8..d63c626f95c82 100644
--- a/clang/lib/AST/ItaniumMangle.cpp
+++ b/clang/lib/AST/ItaniumMangle.cpp
@@ -4249,7 +4249,6 @@ void CXXNameMangler::mangleExpression(const Expr *E, unsigned Arity,
   case Expr::OMPArrayShapingExprClass:
   case Expr::OMPIteratorExprClass:
   case Expr::CXXInheritedCtorInitExprClass:
-  case Expr::CXXParenListInitExprClass:
     llvm_unreachable("unexpected statement kind");
 
   case Expr::ConstantExprClass:

diff  --git a/clang/lib/AST/JSONNodeDumper.cpp b/clang/lib/AST/JSONNodeDumper.cpp
index d174919609d79..69374f309e916 100644
--- a/clang/lib/AST/JSONNodeDumper.cpp
+++ b/clang/lib/AST/JSONNodeDumper.cpp
@@ -850,9 +850,6 @@ void JSONNodeDumper::VisitVarDecl(const VarDecl *VD) {
     case VarDecl::CInit: JOS.attribute("init", "c");  break;
     case VarDecl::CallInit: JOS.attribute("init", "call"); break;
     case VarDecl::ListInit: JOS.attribute("init", "list"); break;
-    case VarDecl::ParenListInit:
-      JOS.attribute("init", "paren-list");
-      break;
     }
   }
   attributeOnlyIfTrue("isParameterPack", VD->isParameterPack());

diff  --git a/clang/lib/AST/StmtPrinter.cpp b/clang/lib/AST/StmtPrinter.cpp
index 1e0d8a5046755..bed7e67d30f9a 100644
--- a/clang/lib/AST/StmtPrinter.cpp
+++ b/clang/lib/AST/StmtPrinter.cpp
@@ -2465,13 +2465,6 @@ void StmtPrinter::VisitCXXFoldExpr(CXXFoldExpr *E) {
   OS << ")";
 }
 
-void StmtPrinter::VisitCXXParenListInitExpr(CXXParenListInitExpr *Node) {
-  OS << "(";
-  llvm::interleaveComma(Node->getInitExprs(), OS,
-                        [&](Expr *E) { PrintExpr(E); });
-  OS << ")";
-}
-
 void StmtPrinter::VisitConceptSpecializationExpr(ConceptSpecializationExpr *E) {
   NestedNameSpecifierLoc NNS = E->getNestedNameSpecifierLoc();
   if (NNS)

diff  --git a/clang/lib/AST/StmtProfile.cpp b/clang/lib/AST/StmtProfile.cpp
index 3820a78d74f0b..93c974314c58e 100644
--- a/clang/lib/AST/StmtProfile.cpp
+++ b/clang/lib/AST/StmtProfile.cpp
@@ -2193,10 +2193,6 @@ void StmtProfiler::VisitCXXFoldExpr(const CXXFoldExpr *S) {
   ID.AddInteger(S->getOperator());
 }
 
-void StmtProfiler::VisitCXXParenListInitExpr(const CXXParenListInitExpr *S) {
-  VisitExpr(S);
-}
-
 void StmtProfiler::VisitCoroutineBodyStmt(const CoroutineBodyStmt *S) {
   VisitStmt(S);
 }

diff  --git a/clang/lib/AST/TextNodeDumper.cpp b/clang/lib/AST/TextNodeDumper.cpp
index a5573c117e629..02cd7541deb5e 100644
--- a/clang/lib/AST/TextNodeDumper.cpp
+++ b/clang/lib/AST/TextNodeDumper.cpp
@@ -1806,8 +1806,6 @@ void TextNodeDumper::VisitVarDecl(const VarDecl *D) {
     case VarDecl::ListInit:
       OS << " listinit";
       break;
-    case VarDecl::ParenListInit:
-      OS << " parenlistinit";
     }
   }
   if (D->needsDestruction(D->getASTContext()))

diff  --git a/clang/lib/CodeGen/CGExprAgg.cpp b/clang/lib/CodeGen/CGExprAgg.cpp
index 303bcc89f671c..5fdbc6a75201f 100644
--- a/clang/lib/CodeGen/CGExprAgg.cpp
+++ b/clang/lib/CodeGen/CGExprAgg.cpp
@@ -87,9 +87,8 @@ class AggExprEmitter : public StmtVisitor<AggExprEmitter> {
 
   void EmitMoveFromReturnSlot(const Expr *E, RValue Src);
 
-  void EmitArrayInit(Address DestPtr, llvm::ArrayType *AType, QualType ArrayQTy,
-                     Expr *ExprToVisit, ArrayRef<Expr *> Args,
-                     Expr *ArrayFiller);
+  void EmitArrayInit(Address DestPtr, llvm::ArrayType *AType,
+                     QualType ArrayQTy, InitListExpr *E);
 
   AggValueSlot::NeedsGCBarriers_t needsGC(QualType T) {
     if (CGF.getLangOpts().getGC() && TypeRequiresGCollection(T))
@@ -173,9 +172,6 @@ class AggExprEmitter : public StmtVisitor<AggExprEmitter> {
   void VisitAbstractConditionalOperator(const AbstractConditionalOperator *CO);
   void VisitChooseExpr(const ChooseExpr *CE);
   void VisitInitListExpr(InitListExpr *E);
-  void VisitCXXParenListOrInitListExpr(Expr *ExprToVisit, ArrayRef<Expr *> Args,
-                                       FieldDecl *InitializedFieldInUnion,
-                                       Expr *ArrayFiller);
   void VisitArrayInitLoopExpr(const ArrayInitLoopExpr *E,
                               llvm::Value *outerBegin = nullptr);
   void VisitImplicitValueInitExpr(ImplicitValueInitExpr *E);
@@ -209,9 +205,6 @@ class AggExprEmitter : public StmtVisitor<AggExprEmitter> {
   }
 
   void VisitVAArgExpr(VAArgExpr *E);
-  void VisitCXXParenListInitExpr(CXXParenListInitExpr *E);
-  void VisitCXXParenListOrInitListExpr(Expr *ExprToVisit, ArrayRef<Expr *> Args,
-                                       Expr *ArrayFiller);
 
   void EmitInitializationToLValue(Expr *E, LValue Address);
   void EmitNullInitializationToLValue(LValue Address);
@@ -478,12 +471,10 @@ static bool isTrivialFiller(Expr *E) {
   return false;
 }
 
-/// Emit initialization of an array from an initializer list. ExprToVisit must
-/// be either an InitListEpxr a CXXParenInitListExpr.
+/// Emit initialization of an array from an initializer list.
 void AggExprEmitter::EmitArrayInit(Address DestPtr, llvm::ArrayType *AType,
-                                   QualType ArrayQTy, Expr *ExprToVisit,
-                                   ArrayRef<Expr *> Args, Expr *ArrayFiller) {
-  uint64_t NumInitElements = Args.size();
+                                   QualType ArrayQTy, InitListExpr *E) {
+  uint64_t NumInitElements = E->getNumInits();
 
   uint64_t NumArrayElements = AType->getNumElements();
   assert(NumInitElements <= NumArrayElements);
@@ -512,8 +503,7 @@ void AggExprEmitter::EmitArrayInit(Address DestPtr, llvm::ArrayType *AType,
     CodeGen::CodeGenModule &CGM = CGF.CGM;
     ConstantEmitter Emitter(CGF);
     LangAS AS = ArrayQTy.getAddressSpace();
-    if (llvm::Constant *C =
-            Emitter.tryEmitForInitializer(ExprToVisit, AS, ArrayQTy)) {
+    if (llvm::Constant *C = Emitter.tryEmitForInitializer(E, AS, ArrayQTy)) {
       auto GV = new llvm::GlobalVariable(
           CGM.getModule(), C->getType(),
           CGM.isTypeConstant(ArrayQTy, /* ExcludeCtorDtor= */ true),
@@ -578,11 +568,12 @@ void AggExprEmitter::EmitArrayInit(Address DestPtr, llvm::ArrayType *AType,
 
     LValue elementLV = CGF.MakeAddrLValue(
         Address(element, llvmElementType, elementAlign), elementType);
-    EmitInitializationToLValue(Args[i], elementLV);
+    EmitInitializationToLValue(E->getInit(i), elementLV);
   }
 
   // Check whether there's a non-trivial array-fill expression.
-  bool hasTrivialFiller = isTrivialFiller(ArrayFiller);
+  Expr *filler = E->getArrayFiller();
+  bool hasTrivialFiller = isTrivialFiller(filler);
 
   // Any remaining elements need to be zero-initialized, possibly
   // using the filler expression.  We can skip this if the we're
@@ -625,8 +616,8 @@ void AggExprEmitter::EmitArrayInit(Address DestPtr, llvm::ArrayType *AType,
       CodeGenFunction::RunCleanupsScope CleanupsScope(CGF);
       LValue elementLV = CGF.MakeAddrLValue(
           Address(currentElement, llvmElementType, elementAlign), elementType);
-      if (ArrayFiller)
-        EmitInitializationToLValue(ArrayFiller, elementLV);
+      if (filler)
+        EmitInitializationToLValue(filler, elementLV);
       else
         EmitNullInitializationToLValue(elementLV);
     }
@@ -1600,76 +1591,46 @@ void AggExprEmitter::EmitNullInitializationToLValue(LValue lv) {
   }
 }
 
-void AggExprEmitter::VisitCXXParenListInitExpr(CXXParenListInitExpr *E) {
-  ArrayRef<Expr *> InitExprs = E->getInitExprs();
-  FieldDecl *InitializedFieldInUnion = nullptr;
-  if (E->getType()->isUnionType()) {
-    auto *RD =
-        dyn_cast<CXXRecordDecl>(E->getType()->castAs<RecordType>()->getDecl());
-    for (FieldDecl *FD : RD->fields()) {
-      if (FD->isUnnamedBitfield())
-        continue;
-      InitializedFieldInUnion = FD;
-      break;
-    }
-  }
-
-  VisitCXXParenListOrInitListExpr(E, InitExprs, InitializedFieldInUnion,
-                                  E->getArrayFiller());
-}
-
 void AggExprEmitter::VisitInitListExpr(InitListExpr *E) {
-  if (E->hadArrayRangeDesignator())
-    CGF.ErrorUnsupported(E, "GNU array range designator extension");
-
-  if (E->isTransparent())
-    return Visit(E->getInit(0));
-
-  VisitCXXParenListOrInitListExpr(
-      E, E->inits(), E->getInitializedFieldInUnion(), E->getArrayFiller());
-}
-
-void AggExprEmitter::VisitCXXParenListOrInitListExpr(
-    Expr *ExprToVisit, ArrayRef<Expr *> InitExprs,
-    FieldDecl *InitializedFieldInUnion, Expr *ArrayFiller) {
 #if 0
   // FIXME: Assess perf here?  Figure out what cases are worth optimizing here
   // (Length of globals? Chunks of zeroed-out space?).
   //
   // If we can, prefer a copy from a global; this is a lot less code for long
   // globals, and it's easier for the current optimizers to analyze.
-  if (llvm::Constant *C =
-          CGF.CGM.EmitConstantExpr(ExprToVisit, ExprToVisit->getType(), &CGF)) {
+  if (llvm::Constant* C = CGF.CGM.EmitConstantExpr(E, E->getType(), &CGF)) {
     llvm::GlobalVariable* GV =
     new llvm::GlobalVariable(CGF.CGM.getModule(), C->getType(), true,
                              llvm::GlobalValue::InternalLinkage, C, "");
-    EmitFinalDestCopy(ExprToVisit->getType(),
-                      CGF.MakeAddrLValue(GV, ExprToVisit->getType()));
+    EmitFinalDestCopy(E->getType(), CGF.MakeAddrLValue(GV, E->getType()));
     return;
   }
 #endif
+  if (E->hadArrayRangeDesignator())
+    CGF.ErrorUnsupported(E, "GNU array range designator extension");
 
-  AggValueSlot Dest = EnsureSlot(ExprToVisit->getType());
+  if (E->isTransparent())
+    return Visit(E->getInit(0));
 
-  LValue DestLV = CGF.MakeAddrLValue(Dest.getAddress(), ExprToVisit->getType());
+  AggValueSlot Dest = EnsureSlot(E->getType());
+
+  LValue DestLV = CGF.MakeAddrLValue(Dest.getAddress(), E->getType());
 
   // Handle initialization of an array.
-  if (ExprToVisit->getType()->isArrayType()) {
+  if (E->getType()->isArrayType()) {
     auto AType = cast<llvm::ArrayType>(Dest.getAddress().getElementType());
-    EmitArrayInit(Dest.getAddress(), AType, ExprToVisit->getType(), ExprToVisit,
-                  InitExprs, ArrayFiller);
+    EmitArrayInit(Dest.getAddress(), AType, E->getType(), E);
     return;
   }
 
-  assert(ExprToVisit->getType()->isRecordType() &&
-         "Only support structs/unions here!");
+  assert(E->getType()->isRecordType() && "Only support structs/unions here!");
 
   // Do struct initialization; this code just sets each individual member
   // to the approprate value.  This makes bitfield support automatic;
   // the disadvantage is that the generated code is more 
diff icult for
   // the optimizer, especially with bitfields.
-  unsigned NumInitElements = InitExprs.size();
-  RecordDecl *record = ExprToVisit->getType()->castAs<RecordType>()->getDecl();
+  unsigned NumInitElements = E->getNumInits();
+  RecordDecl *record = E->getType()->castAs<RecordType>()->getDecl();
 
   // We'll need to enter cleanup scopes in case any of the element
   // initializers throws an exception.
@@ -1687,7 +1648,7 @@ void AggExprEmitter::VisitCXXParenListOrInitListExpr(
 
   // Emit initialization of base classes.
   if (auto *CXXRD = dyn_cast<CXXRecordDecl>(record)) {
-    assert(NumInitElements >= CXXRD->getNumBases() &&
+    assert(E->getNumInits() >= CXXRD->getNumBases() &&
            "missing initializer for base class");
     for (auto &Base : CXXRD->bases()) {
       assert(!Base.isVirtual() && "should not see vbases here");
@@ -1701,7 +1662,7 @@ void AggExprEmitter::VisitCXXParenListOrInitListExpr(
           AggValueSlot::DoesNotNeedGCBarriers,
           AggValueSlot::IsNotAliased,
           CGF.getOverlapForBaseInit(CXXRD, BaseRD, Base.isVirtual()));
-      CGF.EmitAggExpr(InitExprs[curInitIndex++], AggSlot);
+      CGF.EmitAggExpr(E->getInit(curInitIndex++), AggSlot);
 
       if (QualType::DestructionKind dtorKind =
               Base.getType().isDestructedType()) {
@@ -1717,7 +1678,7 @@ void AggExprEmitter::VisitCXXParenListOrInitListExpr(
   if (record->isUnion()) {
     // Only initialize one field of a union. The field itself is
     // specified by the initializer list.
-    if (!InitializedFieldInUnion) {
+    if (!E->getInitializedFieldInUnion()) {
       // Empty union; we have nothing to do.
 
 #ifndef NDEBUG
@@ -1730,12 +1691,12 @@ void AggExprEmitter::VisitCXXParenListOrInitListExpr(
     }
 
     // FIXME: volatility
-    FieldDecl *Field = InitializedFieldInUnion;
+    FieldDecl *Field = E->getInitializedFieldInUnion();
 
     LValue FieldLoc = CGF.EmitLValueForFieldInitialization(DestLV, Field);
     if (NumInitElements) {
       // Store the initializer into the field
-      EmitInitializationToLValue(InitExprs[0], FieldLoc);
+      EmitInitializationToLValue(E->getInit(0), FieldLoc);
     } else {
       // Default-initialize to null.
       EmitNullInitializationToLValue(FieldLoc);
@@ -1759,7 +1720,7 @@ void AggExprEmitter::VisitCXXParenListOrInitListExpr(
     // have a zeroed object, and the rest of the fields are
     // zero-initializable.
     if (curInitIndex == NumInitElements && Dest.isZeroed() &&
-        CGF.getTypes().isZeroInitializable(ExprToVisit->getType()))
+        CGF.getTypes().isZeroInitializable(E->getType()))
       break;
 
 
@@ -1769,7 +1730,7 @@ void AggExprEmitter::VisitCXXParenListOrInitListExpr(
 
     if (curInitIndex < NumInitElements) {
       // Store the initializer into the field.
-      EmitInitializationToLValue(InitExprs[curInitIndex++], LV);
+      EmitInitializationToLValue(E->getInit(curInitIndex++), LV);
     } else {
       // We're out of initializers; default-initialize to null
       EmitNullInitializationToLValue(LV);

diff  --git a/clang/lib/Frontend/InitPreprocessor.cpp b/clang/lib/Frontend/InitPreprocessor.cpp
index 208c6a8db1598..3e33d937e6a9c 100644
--- a/clang/lib/Frontend/InitPreprocessor.cpp
+++ b/clang/lib/Frontend/InitPreprocessor.cpp
@@ -674,7 +674,7 @@ static void InitializeCPlusPlusFeatureTestMacros(const LangOptions &LangOpts,
 
   // C++20 features.
   if (LangOpts.CPlusPlus20) {
-    Builder.defineMacro("__cpp_aggregate_paren_init", "201902L");
+    // Builder.defineMacro("__cpp_aggregate_paren_init", "201902L");
 
     // P0848 is implemented, but we're still waiting for other concepts
     // issues to be addressed before bumping __cpp_concepts up to 202002L.

diff  --git a/clang/lib/Sema/SemaCast.cpp b/clang/lib/Sema/SemaCast.cpp
index 9fd9369c96418..bfdf06fc47c6f 100644
--- a/clang/lib/Sema/SemaCast.cpp
+++ b/clang/lib/Sema/SemaCast.cpp
@@ -451,7 +451,6 @@ static bool tryDiagnoseOverloadedCast(Sema &S, CastType CT,
 
   case InitializationSequence::FK_ConstructorOverloadFailed:
   case InitializationSequence::FK_UserConversionOverloadFailed:
-  case InitializationSequence::FK_ParenthesizedListInitFailed:
     break;
   }
 

diff  --git a/clang/lib/Sema/SemaDecl.cpp b/clang/lib/Sema/SemaDecl.cpp
index ae0b4c62b1998..a1bfb57168c8a 100644
--- a/clang/lib/Sema/SemaDecl.cpp
+++ b/clang/lib/Sema/SemaDecl.cpp
@@ -13145,7 +13145,6 @@ void Sema::AddInitializerToDecl(Decl *RealDecl, Expr *Init, bool DirectInit) {
 
   // Perform the initialization.
   ParenListExpr *CXXDirectInit = dyn_cast<ParenListExpr>(Init);
-  bool IsParenListInit = false;
   if (!VDecl->isInvalidDecl()) {
     InitializedEntity Entity = InitializedEntity::InitializeVariable(VDecl);
     InitializationKind Kind = InitializationKind::CreateForInit(
@@ -13188,9 +13187,6 @@ void Sema::AddInitializerToDecl(Decl *RealDecl, Expr *Init, bool DirectInit) {
     }
 
     Init = Result.getAs<Expr>();
-    IsParenListInit = !InitSeq.steps().empty() &&
-                      InitSeq.step_begin()->Kind ==
-                          InitializationSequence::SK_ParenthesizedListInit;
   }
 
   // Check for self-references within variable initializers.
@@ -13439,8 +13435,7 @@ void Sema::AddInitializerToDecl(Decl *RealDecl, Expr *Init, bool DirectInit) {
   // class type.
   if (CXXDirectInit) {
     assert(DirectInit && "Call-style initializer must be direct init.");
-    VDecl->setInitStyle(IsParenListInit ? VarDecl::ParenListInit
-                                        : VarDecl::CallInit);
+    VDecl->setInitStyle(VarDecl::CallInit);
   } else if (DirectInit) {
     // This must be list-initialization. No other way is direct-initialization.
     VDecl->setInitStyle(VarDecl::ListInit);

diff  --git a/clang/lib/Sema/SemaExceptionSpec.cpp b/clang/lib/Sema/SemaExceptionSpec.cpp
index 1786f3112d1a4..75ec180552f4f 100644
--- a/clang/lib/Sema/SemaExceptionSpec.cpp
+++ b/clang/lib/Sema/SemaExceptionSpec.cpp
@@ -1289,7 +1289,6 @@ CanThrowResult Sema::canThrow(const Stmt *S) {
   case Expr::StmtExprClass:
   case Expr::ConvertVectorExprClass:
   case Expr::VAArgExprClass:
-  case Expr::CXXParenListInitExprClass:
     return canSubStmtsThrow(*this, S);
 
   case Expr::CompoundLiteralExprClass:

diff  --git a/clang/lib/Sema/SemaInit.cpp b/clang/lib/Sema/SemaInit.cpp
index d6ca63745f171..a92c24d577baa 100644
--- a/clang/lib/Sema/SemaInit.cpp
+++ b/clang/lib/Sema/SemaInit.cpp
@@ -3529,7 +3529,6 @@ void InitializationSequence::Step::Destroy() {
   case SK_StdInitializerListConstructorCall:
   case SK_OCLSamplerInit:
   case SK_OCLZeroOpaqueType:
-  case SK_ParenthesizedListInit:
     break;
 
   case SK_ConversionSequence:
@@ -3589,7 +3588,6 @@ bool InitializationSequence::isAmbiguous() const {
   case FK_PlaceholderType:
   case FK_ExplicitConstructor:
   case FK_AddressOfUnaddressableFunction:
-  case FK_ParenthesizedListInitFailed:
     return false;
 
   case FK_ReferenceInitOverloadFailed:
@@ -3825,13 +3823,6 @@ void InitializationSequence::AddOCLZeroOpaqueTypeStep(QualType T) {
   Steps.push_back(S);
 }
 
-void InitializationSequence::AddParenthesizedListInitStep(QualType T) {
-  Step S;
-  S.Kind = SK_ParenthesizedListInit;
-  S.Type = T;
-  Steps.push_back(S);
-}
-
 void InitializationSequence::RewrapReferenceInitList(QualType T,
                                                      InitListExpr *Syntactic) {
   assert(Syntactic->getNumInits() == 1 &&
@@ -5269,198 +5260,6 @@ static void TryDefaultInitialization(Sema &S,
   }
 }
 
-static void TryOrBuildParenListInitialization(
-    Sema &S, const InitializedEntity &Entity, const InitializationKind &Kind,
-    ArrayRef<Expr *> Args, InitializationSequence &Sequence, bool VerifyOnly,
-    ExprResult *Result = nullptr) {
-  unsigned ArgIndexToProcess = 0;
-  SmallVector<Expr *, 4> InitExprs;
-  QualType ResultType;
-  Expr *ArrayFiller = nullptr;
-
-  // Process entities (i.e. array members, base classes, or class fields) by
-  // adding an initialization expression to InitExprs for each entity to
-  // initialize.
-  auto ProcessEntities = [&](auto Range) -> bool {
-    for (InitializedEntity SubEntity : Range) {
-      // Unions should only have one initializer expression.
-      // If there are more initializers than it will be caught when we check
-      // whether Index equals Args.size().
-      if (ArgIndexToProcess == 1 && Entity.getType()->isUnionType())
-        return true;
-
-      // Unnamed bitfields should not be initialized at all, either with an arg
-      // or by default.
-      if (SubEntity.getKind() == InitializedEntity::EK_Member &&
-          cast<FieldDecl>(SubEntity.getDecl())->isUnnamedBitfield())
-        continue;
-
-      if (ArgIndexToProcess < Args.size()) {
-        // There are still expressions in Args that haven't been processed.
-        // Let's match them to the current entity to initialize.
-        Expr *E = Args[ArgIndexToProcess++];
-
-        // Incomplete array types indicate flexible array members. Do not allow
-        // paren list initializations of structs with these members, as GCC
-        // doesn't either.
-        if (SubEntity.getKind() == InitializedEntity::EK_Member) {
-          auto *FD = cast<FieldDecl>(SubEntity.getDecl());
-          if (FD->getType()->isIncompleteArrayType()) {
-            if (!VerifyOnly) {
-              S.Diag(E->getBeginLoc(), diag::err_flexible_array_init)
-                  << SourceRange(E->getBeginLoc(), E->getEndLoc());
-              S.Diag(FD->getLocation(), diag::note_flexible_array_member) << FD;
-            }
-            Sequence.SetFailed(
-                InitializationSequence::FK_ParenthesizedListInitFailed);
-            return false;
-          }
-        }
-
-        InitializationKind SubKind = InitializationKind::CreateForInit(
-            E->getExprLoc(), /*isDirectInit=*/false, E);
-        InitializationSequence SubSeq(S, SubEntity, SubKind, E);
-
-        if (SubSeq.Failed()) {
-          if (!VerifyOnly)
-            SubSeq.Diagnose(S, SubEntity, SubKind, E);
-          else
-            Sequence.SetFailed(
-                InitializationSequence::FK_ParenthesizedListInitFailed);
-
-          return false;
-        }
-        if (!VerifyOnly) {
-          ExprResult ER = SubSeq.Perform(S, SubEntity, SubKind, E);
-          InitExprs.push_back(ER.get());
-        }
-      } else {
-        // We've processed all of the args, but there are still entities that
-        // have to be initialized.
-        if (SubEntity.getKind() == InitializedEntity::EK_Member) {
-          // C++ [dcl.init]p17.6.2.2
-          //   The remaining elements are initialized with their default member
-          //   initializers, if any
-          auto *FD = cast<FieldDecl>(SubEntity.getDecl());
-          if (Expr *ICE = FD->getInClassInitializer(); ICE && !VerifyOnly) {
-            ExprResult DIE = S.BuildCXXDefaultInitExpr(FD->getLocation(), FD);
-            if (DIE.isInvalid())
-              return false;
-            S.checkInitializerLifetime(SubEntity, DIE.get());
-            InitExprs.push_back(DIE.get());
-            continue;
-          };
-        }
-        // Remaining class elements without default member initializers and
-        // array elements are value initialized:
-        //
-        // C++ [dcl.init]p17.6.2.2
-        //   The remaining elements...otherwise are value initialzed
-        //
-        // C++ [dcl.init]p17.5
-        //   if the destination type is an array, the object is initialized as
-        // . follows. Let x1, . . . , xk be the elements of the expression-list
-        //   ...Let n denote the array size...the ith array element is...value-
-        //   initialized for each k < i <= n.
-        InitializationKind SubKind = InitializationKind::CreateValue(
-            Kind.getLocation(), Kind.getLocation(), Kind.getLocation(), true);
-        InitializationSequence SubSeq(S, SubEntity, SubKind, std::nullopt);
-        if (SubSeq.Failed()) {
-          if (!VerifyOnly)
-            SubSeq.Diagnose(S, SubEntity, SubKind, std::nullopt);
-          return false;
-        }
-        if (!VerifyOnly) {
-          ExprResult ER = SubSeq.Perform(S, SubEntity, SubKind, std::nullopt);
-          if (SubEntity.getKind() == InitializedEntity::EK_ArrayElement) {
-            ArrayFiller = ER.get();
-            return true;
-          }
-          InitExprs.push_back(ER.get());
-        }
-      }
-    }
-    return true;
-  };
-
-  if (const ArrayType *AT =
-          S.getASTContext().getAsArrayType(Entity.getType())) {
-
-    SmallVector<InitializedEntity, 4> ElementEntities;
-    uint64_t ArrayLength;
-    // C++ [dcl.init]p17.5
-    //   if the destination type is an array, the object is initialized as
-    //   follows. Let x1, . . . , xk be the elements of the expression-list. If
-    //   the destination type is an array of unknown bound, it is define as
-    //   having k elements.
-    if (const ConstantArrayType *CAT =
-            S.getASTContext().getAsConstantArrayType(Entity.getType()))
-      ArrayLength = CAT->getSize().getZExtValue();
-    else
-      ArrayLength = Args.size();
-
-    if (ArrayLength >= Args.size()) {
-      for (uint64_t I = 0; I < ArrayLength; ++I)
-        ElementEntities.push_back(
-            InitializedEntity::InitializeElement(S.getASTContext(), I, Entity));
-
-      if (!ProcessEntities(ElementEntities))
-        return;
-
-      ResultType = S.Context.getConstantArrayType(
-          AT->getElementType(), llvm::APInt(32, ArrayLength), nullptr,
-          ArrayType::Normal, 0);
-    }
-  } else if (auto *RT = Entity.getType()->getAs<RecordType>()) {
-    const CXXRecordDecl *RD = cast<CXXRecordDecl>(RT->getDecl());
-
-    auto BaseRange = map_range(RD->bases(), [&S](auto &base) {
-      return InitializedEntity::InitializeBase(S.getASTContext(), &base, false);
-    });
-    auto FieldRange = map_range(RD->fields(), [](auto *field) {
-      return InitializedEntity::InitializeMember(field);
-    });
-
-    if (!ProcessEntities(BaseRange))
-      return;
-
-    if (!ProcessEntities(FieldRange))
-      return;
-
-    ResultType = Entity.getType();
-  }
-
-  // Not all of the args have been processed, so there must've been more args
-  // then were required to initialize the element.
-  if (ArgIndexToProcess < Args.size()) {
-    Sequence.SetFailed(InitializationSequence::FK_ParenthesizedListInitFailed);
-    if (!VerifyOnly) {
-      QualType T = Entity.getType();
-      int InitKind = T->isArrayType() ? 0 : T->isUnionType() ? 3 : 4;
-      S.Diag(Kind.getLocation(), diag::err_excess_initializers)
-          << InitKind << Args[ArgIndexToProcess]->getSourceRange();
-    }
-    return;
-  }
-
-  if (VerifyOnly) {
-    Sequence.setSequenceKind(InitializationSequence::NormalSequence);
-    Sequence.AddParenthesizedListInitStep(Entity.getType());
-  } else if (Result) {
-    SourceRange SR = Kind.getParenOrBraceRange();
-    auto *CPLIE = CXXParenListInitExpr::Create(
-        S.getASTContext(), InitExprs, ResultType, Args.size(),
-        Kind.getLocation(), SR.getBegin(), SR.getEnd());
-    CPLIE->setArrayFiller(ArrayFiller);
-    *Result = CPLIE;
-    S.Diag(Kind.getLocation(),
-           diag::warn_cxx17_compat_aggregate_init_paren_list)
-        << Kind.getLocation() << SR << ResultType;
-  }
-
-  return;
-}
-
 /// Attempt a user-defined conversion between two types (C++ [dcl.init]),
 /// which enumerates all conversion functions and performs overload resolution
 /// to select the best.
@@ -6116,11 +5915,7 @@ void InitializationSequence::InitializeFrom(Sema &S,
       TryListInitialization(S, Entity, Kind, cast<InitListExpr>(Initializer),
                             *this, TreatUnavailableAsInvalid);
       AddParenthesizedArrayInitStep(DestType);
-    } else if (S.getLangOpts().CPlusPlus20 && !TopLevelOfInitList &&
-               Kind.getKind() == InitializationKind::IK_Direct)
-      TryOrBuildParenListInitialization(S, Entity, Kind, Args, *this,
-                                        /*VerifyOnly=*/true);
-    else if (DestAT->getElementType()->isCharType())
+    } else if (DestAT->getElementType()->isCharType())
       SetFailed(FK_ArrayNeedsInitListOrStringLiteral);
     else if (IsWideCharCompatible(DestAT->getElementType(), Context))
       SetFailed(FK_ArrayNeedsInitListOrWideStringLiteral);
@@ -6167,39 +5962,18 @@ void InitializationSequence::InitializeFrom(Sema &S,
     if (Kind.getKind() == InitializationKind::IK_Direct ||
         (Kind.getKind() == InitializationKind::IK_Copy &&
          (Context.hasSameUnqualifiedType(SourceType, DestType) ||
-          S.IsDerivedFrom(Initializer->getBeginLoc(), SourceType, DestType)))) {
-      TryConstructorInitialization(S, Entity, Kind, Args, DestType, DestType,
-                                   *this);
-
-      // We fall back to the "no matching constructor" path if the
-      // failed candidate set has functions other than the three default
-      // constructors. For example, conversion function.
-      if (const auto *RD =
-              dyn_cast<CXXRecordDecl>(DestType->getAs<RecordType>()->getDecl());
-          // In general, we should call isCompleteType for RD to check its
-          // completeness, we don't call it here as it was already called in the
-          // above TryConstructorInitialization.
-          S.getLangOpts().CPlusPlus20 && RD && RD->hasDefinition() &&
-          RD->isAggregate() && Failed() &&
-          getFailureKind() == FK_ConstructorOverloadFailed) {
-        // C++20 [dcl.init] 17.6.2.2:
-        //   - Otherwise, if no constructor is viable, the destination type is
-        //   an
-        //      aggregate class, and the initializer is a parenthesized
-        //      expression-list.
-        TryOrBuildParenListInitialization(S, Entity, Kind, Args, *this,
-                                          /*VerifyOnly=*/true);
-      }
-    } else {
-      //     - Otherwise (i.e., for the remaining copy-initialization cases),
-      //       user-defined conversion sequences that can convert from the
-      //       source type to the destination type or (when a conversion
-      //       function is used) to a derived class thereof are enumerated as
-      //       described in 13.3.1.4, and the best one is chosen through
-      //       overload resolution (13.3).
+          S.IsDerivedFrom(Initializer->getBeginLoc(), SourceType, DestType))))
+      TryConstructorInitialization(S, Entity, Kind, Args,
+                                   DestType, DestType, *this);
+    //     - Otherwise (i.e., for the remaining copy-initialization cases),
+    //       user-defined conversion sequences that can convert from the source
+    //       type to the destination type or (when a conversion function is
+    //       used) to a derived class thereof are enumerated as described in
+    //       13.3.1.4, and the best one is chosen through overload resolution
+    //       (13.3).
+    else
       TryUserDefinedConversion(S, DestType, Kind, Initializer, *this,
                                TopLevelOfInitList);
-    }
     return;
   }
 
@@ -8459,7 +8233,6 @@ ExprResult InitializationSequence::Perform(Sema &S,
   case SK_ConstructorInitializationFromList:
   case SK_StdInitializerListConstructorCall:
   case SK_ZeroInitialization:
-  case SK_ParenthesizedListInit:
     break;
   }
 
@@ -9149,14 +8922,6 @@ ExprResult InitializationSequence::Perform(Sema &S,
                                     CurInit.get()->getValueKind());
       break;
     }
-    case SK_ParenthesizedListInit: {
-      CurInit = nullptr;
-      TryOrBuildParenListInitialization(S, Entity, Kind, Args, *this,
-                                        /*VerifyOnly=*/false, &CurInit);
-      if (CurInit.get() && ResultType)
-        *ResultType = CurInit.get()->getType();
-      break;
-    }
     }
   }
 
@@ -9758,11 +9523,6 @@ bool InitializationSequence::Diagnose(Sema &S,
            diag::note_explicit_ctor_deduction_guide_here) << false;
     break;
   }
-
-  case FK_ParenthesizedListInitFailed:
-    TryOrBuildParenListInitialization(S, Entity, Kind, Args, *this,
-                                      /*VerifyOnly=*/false);
-    break;
   }
 
   PrintInitLocationNote(S, Entity);
@@ -9929,10 +9689,6 @@ void InitializationSequence::dump(raw_ostream &OS) const {
     case FK_ExplicitConstructor:
       OS << "list copy initialization chose explicit constructor";
       break;
-
-    case FK_ParenthesizedListInitFailed:
-      OS << "parenthesized list initialization failed";
-      break;
     }
     OS << '\n';
     return;
@@ -10104,9 +9860,6 @@ void InitializationSequence::dump(raw_ostream &OS) const {
     case SK_OCLZeroOpaqueType:
       OS << "OpenCL opaque type from zero";
       break;
-    case SK_ParenthesizedListInit:
-      OS << "initialization from a parenthesized list of values";
-      break;
     }
 
     OS << " [" << S->Type << ']';

diff  --git a/clang/lib/Sema/TreeTransform.h b/clang/lib/Sema/TreeTransform.h
index 36450892f9485..2ebd936b359f7 100644
--- a/clang/lib/Sema/TreeTransform.h
+++ b/clang/lib/Sema/TreeTransform.h
@@ -3859,16 +3859,6 @@ class TreeTransform {
     return getSema().BuildEmptyCXXFoldExpr(EllipsisLoc, Operator);
   }
 
-  ExprResult RebuildCXXParenListInitExpr(ArrayRef<Expr *> Args, QualType T,
-                                         unsigned NumUserSpecifiedExprs,
-                                         SourceLocation InitLoc,
-                                         SourceLocation LParenLoc,
-                                         SourceLocation RParenLoc) {
-    return CXXParenListInitExpr::Create(getSema().Context, Args, T,
-                                        NumUserSpecifiedExprs, InitLoc,
-                                        LParenLoc, RParenLoc);
-  }
-
   /// Build a new atomic operation expression.
   ///
   /// By default, performs semantic analysis to build the new expression.
@@ -14037,20 +14027,6 @@ TreeTransform<Derived>::TransformCXXFoldExpr(CXXFoldExpr *E) {
   return Result;
 }
 
-template <typename Derived>
-ExprResult
-TreeTransform<Derived>::TransformCXXParenListInitExpr(CXXParenListInitExpr *E) {
-  SmallVector<Expr *, 4> TransformedInits;
-  ArrayRef<Expr *> InitExprs = E->getInitExprs();
-  if (TransformExprs(InitExprs.data(), InitExprs.size(), true,
-                     TransformedInits))
-    return ExprError();
-
-  return getDerived().RebuildCXXParenListInitExpr(
-      TransformedInits, E->getType(), E->getUserSpecifiedInitExprs().size(),
-      E->getInitLoc(), E->getBeginLoc(), E->getEndLoc());
-}
-
 template<typename Derived>
 ExprResult
 TreeTransform<Derived>::TransformCXXStdInitializerListExpr(

diff  --git a/clang/lib/Serialization/ASTReaderStmt.cpp b/clang/lib/Serialization/ASTReaderStmt.cpp
index 4ca6998b13370..2995becb7dd8d 100644
--- a/clang/lib/Serialization/ASTReaderStmt.cpp
+++ b/clang/lib/Serialization/ASTReaderStmt.cpp
@@ -2175,26 +2175,6 @@ void ASTStmtReader::VisitCXXFoldExpr(CXXFoldExpr *E) {
   E->Opcode = (BinaryOperatorKind)Record.readInt();
 }
 
-void ASTStmtReader::VisitCXXParenListInitExpr(CXXParenListInitExpr *E) {
-  VisitExpr(E);
-  unsigned ExpectedNumExprs = Record.readInt();
-  assert(E->NumExprs == ExpectedNumExprs &&
-         "expected number of expressions does not equal the actual number of "
-         "serialized expressions.");
-  E->NumUserSpecifiedExprs = Record.readInt();
-  E->InitLoc = readSourceLocation();
-  E->LParenLoc = readSourceLocation();
-  E->RParenLoc = readSourceLocation();
-  for (unsigned I = 0; I < ExpectedNumExprs; I++)
-    E->getTrailingObjects<Expr *>()[I] = Record.readSubExpr();
-
-  bool HasArrayFiller = Record.readBool();
-  if (HasArrayFiller) {
-    E->setArrayFiller(Record.readSubExpr());
-  }
-  E->updateDependence();
-}
-
 void ASTStmtReader::VisitOpaqueValueExpr(OpaqueValueExpr *E) {
   VisitExpr(E);
   E->SourceExpr = Record.readSubExpr();
@@ -3986,11 +3966,6 @@ Stmt *ASTReader::ReadStmtFromStream(ModuleFile &F) {
       S = new (Context) CXXFoldExpr(Empty);
       break;
 
-    case EXPR_CXX_PAREN_LIST_INIT:
-      S = CXXParenListInitExpr::CreateEmpty(
-          Context, /*numExprs=*/Record[ASTStmtReader::NumExprFields], Empty);
-      break;
-
     case EXPR_OPAQUE_VALUE:
       S = new (Context) OpaqueValueExpr(Empty);
       break;

diff  --git a/clang/lib/Serialization/ASTWriter.cpp b/clang/lib/Serialization/ASTWriter.cpp
index 935f3e7535ccb..6299a48708f7d 100644
--- a/clang/lib/Serialization/ASTWriter.cpp
+++ b/clang/lib/Serialization/ASTWriter.cpp
@@ -743,7 +743,6 @@ static void AddStmtsExprs(llvm::BitstreamWriter &Stream,
   RECORD(EXPR_USER_DEFINED_LITERAL);
   RECORD(EXPR_CXX_STD_INITIALIZER_LIST);
   RECORD(EXPR_CXX_BOOL_LITERAL);
-  RECORD(EXPR_CXX_PAREN_LIST_INIT);
   RECORD(EXPR_CXX_NULL_PTR_LITERAL);
   RECORD(EXPR_CXX_TYPEID_EXPR);
   RECORD(EXPR_CXX_TYPEID_TYPE);

diff  --git a/clang/lib/Serialization/ASTWriterStmt.cpp b/clang/lib/Serialization/ASTWriterStmt.cpp
index 8ed7412070167..0dc9d4c7c859b 100644
--- a/clang/lib/Serialization/ASTWriterStmt.cpp
+++ b/clang/lib/Serialization/ASTWriterStmt.cpp
@@ -2081,23 +2081,6 @@ void ASTStmtWriter::VisitCXXFoldExpr(CXXFoldExpr *E) {
   Code = serialization::EXPR_CXX_FOLD;
 }
 
-void ASTStmtWriter::VisitCXXParenListInitExpr(CXXParenListInitExpr *E) {
-  VisitExpr(E);
-  ArrayRef<Expr *> InitExprs = E->getInitExprs();
-  Record.push_back(InitExprs.size());
-  Record.push_back(E->getUserSpecifiedInitExprs().size());
-  Record.AddSourceLocation(E->getInitLoc());
-  Record.AddSourceLocation(E->getBeginLoc());
-  Record.AddSourceLocation(E->getEndLoc());
-  for (Expr *InitExpr : E->getInitExprs())
-    Record.AddStmt(InitExpr);
-  bool HasArrayFiller = E->getArrayFiller();
-  Record.push_back(HasArrayFiller);
-  if (HasArrayFiller)
-    Record.AddStmt(E->getArrayFiller());
-  Code = serialization::EXPR_CXX_PAREN_LIST_INIT;
-}
-
 void ASTStmtWriter::VisitOpaqueValueExpr(OpaqueValueExpr *E) {
   VisitExpr(E);
   Record.AddStmt(E->getSourceExpr());

diff  --git a/clang/lib/StaticAnalyzer/Core/ExprEngine.cpp b/clang/lib/StaticAnalyzer/Core/ExprEngine.cpp
index f9e76d85efdde..87a95d46f2987 100644
--- a/clang/lib/StaticAnalyzer/Core/ExprEngine.cpp
+++ b/clang/lib/StaticAnalyzer/Core/ExprEngine.cpp
@@ -1901,7 +1901,6 @@ void ExprEngine::Visit(const Stmt *S, ExplodedNode *Pred,
     case Stmt::ConceptSpecializationExprClass:
     case Stmt::CXXRewrittenBinaryOperatorClass:
     case Stmt::RequiresExprClass:
-    case Expr::CXXParenListInitExprClass:
       // Fall through.
 
     // Cases we intentionally don't evaluate, since they don't need

diff  --git a/clang/test/CXX/temp/temp.decls/temp.variadic/p4.cpp b/clang/test/CXX/temp/temp.decls/temp.variadic/p4.cpp
index cc5a406f7640d..2aa7dbf8a7633 100644
--- a/clang/test/CXX/temp/temp.decls/temp.variadic/p4.cpp
+++ b/clang/test/CXX/temp/temp.decls/temp.variadic/p4.cpp
@@ -1,5 +1,5 @@
-// RUN: %clang_cc1 -std=c++11 -fsyntax-only -fexceptions -fcxx-exceptions -verify=expected,pre20 %s
-// RUN: %clang_cc1 -std=c++2a -fsyntax-only -fexceptions -fcxx-exceptions -verify=expected,post20 %s
+// RUN: %clang_cc1 -std=c++11 -fsyntax-only -fexceptions -fcxx-exceptions -verify %s
+// RUN: %clang_cc1 -std=c++2a -fsyntax-only -fexceptions -fcxx-exceptions -verify %s
 
 template<typename... Types> struct tuple;
 template<int I> struct int_c;
@@ -99,12 +99,12 @@ struct HasMixins : public Mixins... {
   HasMixins(int i);
 };
 
-struct A { }; // pre20-note{{candidate constructor (the implicit copy constructor) not viable: no known conversion from 'int' to 'const A' for 1st argument}} \
-// pre20-note{{candidate constructor (the implicit move constructor) not viable: no known conversion from 'int' to 'A' for 1st argument}} \
-// pre20-note{{candidate constructor (the implicit default constructor) not viable: requires 0 arguments, but 1 was provided}}
-struct B { }; // pre20-note{{candidate constructor (the implicit copy constructor) not viable: no known conversion from 'int' to 'const B' for 1st argument}} \
-// pre20-note{{candidate constructor (the implicit move constructor) not viable: no known conversion from 'int' to 'B' for 1st argument}} \
-// pre20-note{{candidate constructor (the implicit default constructor) not viable: requires 0 arguments, but 1 was provided}}
+struct A { }; // expected-note{{candidate constructor (the implicit copy constructor) not viable: no known conversion from 'int' to 'const A' for 1st argument}} \
+// expected-note{{candidate constructor (the implicit move constructor) not viable: no known conversion from 'int' to 'A' for 1st argument}} \
+// expected-note{{candidate constructor (the implicit default constructor) not viable: requires 0 arguments, but 1 was provided}}
+struct B { }; // expected-note{{candidate constructor (the implicit copy constructor) not viable: no known conversion from 'int' to 'const B' for 1st argument}} \
+// expected-note{{candidate constructor (the implicit move constructor) not viable: no known conversion from 'int' to 'B' for 1st argument}} \
+// expected-note{{candidate constructor (the implicit default constructor) not viable: requires 0 arguments, but 1 was provided}}
 struct C { };
 struct D { };
 
@@ -126,10 +126,8 @@ HasMixins<Mixins...>::HasMixins(const HasMixins &other): Mixins(other)... { }
 
 template<typename ...Mixins>
 HasMixins<Mixins...>::HasMixins(int i): Mixins(i)... { }
-// pre20-error at -1 {{no matching constructor for initialization of 'A'}}
-// pre20-error at -2 {{no matching constructor for initialization of 'B'}}
-// post20-error at -3 {{excess elements in struct initializer}}
-// post20-error at -4 {{excess elements in struct initializer}}
+// expected-error at -1 {{no matching constructor for initialization of 'A'}}
+// expected-error at -2 {{no matching constructor for initialization of 'B'}}
 
 void test_has_mixins() {
   HasMixins<A, B> ab;

diff  --git a/clang/test/CodeGen/paren-list-agg-init.cpp b/clang/test/CodeGen/paren-list-agg-init.cpp
deleted file mode 100644
index a7534fb907d2b..0000000000000
--- a/clang/test/CodeGen/paren-list-agg-init.cpp
+++ /dev/null
@@ -1,351 +0,0 @@
-// RUN: %clang_cc1 -std=c++20 %s -emit-llvm -triple x86_64-unknown-linux-gnu -o - | FileCheck %s
-
-template <typename T>
-struct IsChar {
-  constexpr operator bool() const { return false; }
-};
-
-template<>
-struct IsChar<char> {
-  constexpr operator bool() const { return true; }
-};
-
-template <typename T>
-concept SameAsChar = (bool)IsInt<T>();
-
-// CHECK-DAG: [[STRUCT_A:%.*]] = type { i8, double }
-struct A {
-  char i;
-  double j;
-
-  template <SameAsChar T>
-  operator T() const { return i; };
-};
-
-// CHECK-DAG: [[STRUCT_B:%.*]] = type { [[STRUCT_A]], i32 }
-struct B {
-  A a;
-  int b;
-};
-
-// CHECK-DAG: [[STRUCT_C:%.*]] = type <{ [[STRUCT_B]], [[STRUCT_A]], i32, [4 x i8] }>
-struct C : public B, public A {
-  int c;
-};
-
-// CHECK-DAG: [[STRUCT_D:%.*]] = type { [[STRUCT_A]], [[STRUCT_A]], i8, [[STRUCT_A]] }
-struct D {
-  A a;
-  A b = A{2, 2.0};
-  unsigned : 2;
-  A c;
-};
-
-// CHECK-DAG: [[STRUCT_E:%.*]] = type { i32, ptr }
-struct E {
-  int a;
-  const char* fn = __builtin_FUNCTION();
-  ~E() {};
-};
-
-// CHECK-DAG: [[STRUCT_F:%.*]] = type { i8 }
-struct F {
-  F (int i = 1);
-  F (const F &f) = delete;
-  F (F &&f) = default;
-};
-
-// CHECK-DAG: [[STRUCT_G:%.*]] = type <{ i32, [[STRUCT_F]], [3 x i8] }>
-struct G {
-  int a;
-  F f;
-};
-
-// CHECK-DAG: [[UNION_U:%.*]] = type { [[STRUCT_A]] }
-// CHECK-DAG: [[STR:@.*]] = private unnamed_addr constant [6 x i8] {{.*}}foo18{{.*}}, align 1
-union U {
-  unsigned : 1;
-  A a;
-  char b;
-};
-
-// CHECK-DAG: [[A1:@.*a1.*]] = internal constant [[STRUCT_A]] { i8 3, double 2.000000e+00 }, align 8
-constexpr A a1(3.1, 2.0);
-// CHECK-DAG: [[A2:@.*a2.*]] = internal constant [[STRUCT_A]] { i8 99, double 0.000000e+00 }, align 8
-constexpr auto a2 = static_cast<A>('c');
-// CHECK-DAG: [[B1:@.*b1.*]] = internal constant [[STRUCT_B]] { [[STRUCT_A]] { i8 99, double 0.000000e+00 }, i32 0 }, align 8
-constexpr B b1(A('c'));
-// CHECK-DAG: [[C1:@.*c1.*]] = internal constant { [[STRUCT_A]], i32, [4 x i8], i8, double, i32 } { [[STRUCT_A]] { i8 99, double 0.000000e+00 }, i32 0, [4 x i8] undef, i8 3, double 2.000000e+00, i32 0 }, align
-constexpr C c1(b1, a1);
-// CHECK-DAG: [[U1:@.*u1.*]] = internal constant [[UNION_U]] { [[STRUCT_A]] { i8 1, double 1.000000e+00 } }, align 8
-constexpr U u1(A(1, 1));
-// CHECK-DAG: [[D1:@.*d1.*]] = internal constant { [[STRUCT_A]], [[STRUCT_A]], [8 x i8], [[STRUCT_A]] } { [[STRUCT_A]] { i8 2, double 2.000000e+00 }, [[STRUCT_A]] { i8 2, double 2.000000e+00 }, [8 x i8] undef, [[STRUCT_A]] zeroinitializer }, align 8
-constexpr D d1(A(2, 2));
-// CHECK-DAG: [[ARR1:@.*arr1.*]] = internal constant [3 x i32] [i32 1, i32 2, i32 0], align 4
-constexpr int arr1[3](1, 2);
-// CHECK-DAG: [[ARR4:@.*arr4.*]] = internal constant [1 x i32] [i32 1], align 4
-constexpr int arr4[](1);
-// CHECK-DAG: [[ARR5:@.*arr5.*]] = internal constant [2 x i32] [i32 2, i32 0], align 4
-constexpr int arr5[2](2);
-
-// CHECK: define dso_local { i8, double } @{{.*foo1.*}}
-// CHECK-NEXT: entry:
-// CHECK-NEXT: [[RETVAL:%.*]] = alloca [[STRUCT_A]], align 8
-// CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 8 [[RETVAL]], ptr align 8 [[A1]], i64 16, i1 false)
-// CHECK-NEXT: [[TMP_0:%.*]] = load { i8, double }, ptr [[RETVAL]], align 8
-// CHECK-NEXT: ret { i8, double } [[TMP_0]]
-A foo1() {
-  return a1;
-}
-
-// CHECK: define dso_local void @{{.*foo2.*}}(ptr noalias sret([[STRUCT_B]]) align 8 [[AGG_RESULT:%.*]])
-// CHECK-NEXT: entry:
-// CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 8 [[AGG_RESULT]], ptr align 8 [[B1]], i64 24, i1 false)
-// CHECK-NEXT: ret void
-B foo2() {
-  return b1;
-}
-
-// CHECK: define dso_local void @{{.*foo3.*}}(ptr noalias sret([[STRUCT_C]]) align 8 [[AGG_RESULT:%.*]])
-// CHECK-NEXT: entry:
-// CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 8 [[AGG_RESULT]], ptr align 8 [[C1]], i64 48, i1 false)
-// CHECK-NEXT: ret void
-C foo3() {
-  return c1;
-}
-
-// CHECK: define dso_local void @{{.*foo4.*}}
-// CHECK-NEXT: entry:
-// CHECK-NEXT: [[C2:%.*]] = alloca [[STRUCT_C:%.*]], align 8
-// CHECK-NEXT: [[REF_TMP:%.*]] = alloca [[STRUCT_B:%.*]], align 8
-// CHECK-NEXT: [[REF_TMP_1:%.*]] = alloca [[STRUCT_A:%.*]], align 8
-// CHECK-NEXT: [[A:%.*]] = getelementptr inbounds [[STRUCT_B]], ptr [[REF_TMP]], i32 0, i32 0
-// CHECK-NEXT: [[I:%.*]] = getelementptr inbounds [[STRUCT_A]], ptr [[A]], i32 0, i32 0
-// CHECK-NEXT: store i8 1, ptr [[I]], align 8
-// CHECK-NEXT: [[J:%.*]] = getelementptr inbounds [[STRUCT_A]], ptr [[A]], i32 0, i32 1
-// CHECK-NEXT: store double 1.000000e+00, ptr [[J]], align 8
-// CHECK-NEXT: [[B:%.*]] = getelementptr inbounds [[STRUCT_B]], ptr [[REF_TMP]], i32 0, i32 1
-// CHECK-NEXT: store i32 1, ptr [[B]], align 8
-// CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 8 [[C2]], ptr align 8 [[REF_TMP]], i64 24, i1 false)
-// CHECK-NEXT: [[TMP_0:%.*]] = getelementptr inbounds i8, ptr [[C2]], i64 24
-// CHECK-NEXT: [[I2:%.*]] = getelementptr inbounds [[STRUCT_A]], ptr [[REF_TMP_1]], i32 0, i32 0
-// CHECK-NEXT: store i8 97, ptr [[I2]], align 8
-// CHECK-NEXT: [[J3:%.*]] = getelementptr inbounds [[STRUCT_A]], ptr [[REF_TMP_1]], i32 0, i32 1
-// CHECK-NEXT: store double 0.000000e+00, ptr [[J3]], align 8
-// CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 8 [[TMP_0]], ptr align 8 [[REF_TMP_1]], i64 16, i1 false)
-// CHECK-NEXT: [[C:%.*]] = getelementptr inbounds %struct.C, ptr %c2, i32 0, i32 2
-// CHECK-NEXT: store i32 2, ptr %c, align 8
-// CHECK-NEXT: ret void
-void foo4() {
-  C c2(B(A(1, 1), 1), A('a'), 2);
-}
-
-// CHECK: define dso_local { i64, double } @{{.*foo5.*}}
-// CHECK-NEXT: entry:
-// CHECK-NEXT [[RETVAL:%.*]] = alloca [[UNION_U]], align 8
-// CHECK-NEXT call void @llvm.memcpy.p0.p0.i64(ptr align 8 [[RETVAL]], ptr align 8 [[U1]], i64 16, i1 false)
-// CHECK-NEXT [[COERCE_DIVE:%.*]] = getelementptr inbounds [[UNION_U]], ptr %retval, i32 0, i32 0
-// CHECK-NEXT [[TMP_0:%.*]] = load { i64, double }, ptr [[COERCE_DIVE]], align 8
-// CHECK-NEXT ret { i64, double } [[TMP_0]]
-U foo5() {
-  return u1;
-}
-
-
-// CHECK: define dso_local { i64, double } @{{.*foo6.*}}(i8 [[A_COERCE_0:%.*]], double [[A_COERCE_1:%.*]])
-// CHECK-NEXT: entry:
-// CHECK-NEXT:   [[RETVAL:%.*]] = alloca [[UNION_U]], align 8
-// CHECK-NEXT:   [[A:%.*]] = alloca [[STRUCT_A]], align 8
-// CHECK-NEXT:   [[TMP_0:%.*]] = getelementptr inbounds { i8, double }, ptr [[A]], i32 0, i32 0
-// CHECK-NEXT:   store i8 [[A_COERCE_0]], ptr [[TMP_0]], align 8
-// CHECK-NEXT:   [[TMP_1:%.*]] = getelementptr inbounds { i8, double }, ptr [[A]], i32 0, i32 1
-// CHECK-NEXT:   store double [[A_COERCE_1]], ptr [[TMP_1]], align 8
-// CHECK-NEXT:   call void @llvm.memcpy.p0.p0.i64(ptr align 8 [[RETVAL]], ptr align 8 [[A]], i64 16, i1 false)
-// CHECK-NEXT:   [[COERCE_DIVE:%.*]] = getelementptr inbounds [[UNION_U]], ptr [[RETVAL]], i32 0, i32 0
-// CHECK-NEXT:   [[TMP_2:%.*]] = load { i64, double }, ptr [[COERCE_DIVE:%.*]], align 8
-// CHECK-NEXT:   ret { i64, double } [[TMP_2]]
-U foo6(A a) {
-  return U(a);
-}
-
-// CHECK: define dso_local void @{{.*foo7.*}}
-// CHECK-NEXT: entry:
-// CHECK-NEXT: [[D:%.*]] = alloca [[STRUCT_D:%.*]], align 8
-// CHECK-NEXT: [[A:%.*]] = getelementptr inbounds [[STRUCT_D]], ptr [[D]], i32 0, i32 0
-// CHECK-NEXT: [[I]] = getelementptr inbounds [[STRUCT_A:%.*]], ptr [[A]], i32 0, i32 0
-// CHECK-NEXT: store i8 1, ptr [[I]], align 8
-// CHECK-NEXT: [[J:%.*]] = getelementptr inbounds [[STRUCT_A]], ptr [[A]], i32 0, i32 1
-// CHECK-NEXT: store double 1.000000e+00, ptr [[J]], align 8
-// CHECK-NEXT: [[B:%.*]] = getelementptr inbounds [[STRUCT_D]], ptr [[D]], i32 0, i32 1
-// CHECK-NEXT: [[I1:%.*]] = getelementptr inbounds [[STRUCT_A]], ptr [[B]], i32 0, i32 0
-// CHECK-NEXT: store i8 11, ptr [[I1]], align 8
-// CHECK-NEXT: [[J2:%.*]] = getelementptr inbounds [[STRUCT_A]], ptr [[B]], i32 0, i32 1
-// CHECK-NEXT: store double 1.100000e+01, ptr [[J2]], align 8
-// CHECK-NEXT: [[C:%.*]] = getelementptr inbounds [[STRUCT_D]], ptr [[D]], i32 0, i32 3
-// CHECK-NEXT: [[I3:%.*]] = getelementptr inbounds [[STRUCT_A]], ptr [[C]], i32 0, i32 0
-// CHECK-NEXT: store i8 111, ptr [[I3]], align 8
-// CHECK-NEXT: [[J4:%.*]] = getelementptr inbounds [[STRUCT_A]], ptr [[C]], i32 0, i32 1
-// CHECK-NEXT: store double 1.110000e+02, ptr [[J4]], align 8
-// CHECK-NEXT: ret void
-void foo7() {
-  D d(A(1, 1), A(11, 11), A(111, 111));
-}
-
-// CHECK: dso_local void @{{.*foo8.*}}(ptr noalias sret([[STRUCT_D]]) align 8 [[AGG_RESULT:%.*]])
-// CHECK-NEXT: entry:
-// CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 8 [[AGG_RESULT]], ptr align 8 [[D1]], i64 56, i1 false)
-// CHECK-NEXT: ret void
-D foo8() {
-  return d1;
-}
-
-// CHECK: define dso_local void @{{.*foo9.*}}
-// CHECK-NEXT: entry:
-// CHECK-NEXT: [[D:%.*]] = alloca [[STRUCT_D:%.*]], align 8
-// CHECK-NEXT: [[A:%.*]] = getelementptr inbounds [[STRUCT_D]], ptr [[D]], i32 0, i32 0
-// CHECK-NEXT: [[I]] = getelementptr inbounds [[STRUCT_A:%.*]], ptr [[A]], i32 0, i32 0
-// CHECK-NEXT: store i8 1, ptr [[I]], align 8
-// CHECK-NEXT: [[J:%.*]] = getelementptr inbounds [[STRUCT_A]], ptr [[A]], i32 0, i32 1
-// CHECK-NEXT: store double 1.000000e+00, ptr [[J]], align 8
-// CHECK-NEXT: [[B:%.*]] = getelementptr inbounds [[STRUCT_D]], ptr [[D]], i32 0, i32 1
-// CHECK-NEXT: [[I1:%.*]] = getelementptr inbounds [[STRUCT_A]], ptr [[B]], i32 0, i32 0
-// CHECK-NEXT: store i8 2, ptr [[I1]], align 8
-// CHECK-NEXT: [[J2:%.*]] = getelementptr inbounds [[STRUCT_A]], ptr [[B]], i32 0, i32 1
-// CHECK-NEXT: store double 2.000000e+00, ptr [[J2]], align 8
-// CHECK-NEXT: [[C:%.*]] = getelementptr inbounds [[STRUCT_D]], ptr [[D]], i32 0, i32 3
-// CHECK-NEXT: call void @llvm.memset.p0.i64(ptr align 8 [[C]], i8 0, i64 16, i1 false)
-// CHECK-NEXT: ret void
-void foo9() {
-  D d(A(1, 1));
-}
-
-// CHECK: define dso_local noundef ptr @{{.*foo10.*}}()
-// CHECK-NEXT: entry:
-// CHECK-NEXT: ret ptr [[ARR1]]
-const int* foo10() {
-  return arr1;
-}
-
-// CHECK: define dso_local void @{{.*foo11.*}}
-// CHECK-NEXT: entry:
-// CHECK-NEXT: [[A_ADDR:%.*]] = alloca i32, align 4
-// CHECK-NEXT: [[B_ADDR:%.*]] = alloca i32, align 4
-// CHECK-NEXT: [[ARR_2:%.*]] = alloca [4 x i32], align 16
-// CHECK-NEXT: store i32 [[A:%.*]], ptr [[A_ADDR]], align 4
-// CHECK-NEXT: store i32 [[B:%.*]], ptr [[B_ADDR]], align 4
-// CHECK-NEXT: [[ARRINIT_BEGIN:%.*]] = getelementptr inbounds [4 x i32], ptr [[ARR_2]], i64 0, i64 0
-// CHECK-NEXT: [[TMP_0:%.*]] = load i32, ptr [[A_ADDR]], align 4
-// CHECK-NEXT: store i32 [[TMP_0]], ptr [[ARRINIT_BEGIN]], align 4
-// CHECK-NEXT: [[ARRINIT_ELEM:%.*]] = getelementptr inbounds i32, ptr [[ARRINIT_BEGIN]], i64 1
-// CHECK-NEXT: [[TMP_1:%.*]] = load i32, ptr [[B_ADDR]], align 4
-// CHECK-NEXT: store i32 [[TMP_1]], ptr [[ARRINIT_ELEM]], align 4
-// CHECK-NEXT: [[ARRINIT_START:%.*]] = getelementptr inbounds i32, ptr [[ARRINIT_ELEM]], i64 1
-// CHECK-NEXT: [[ARRINIT_END:%.*]] = getelementptr inbounds i32, ptr [[ARRINIT_BEGIN]], i64 4
-// CHECK-NEXT: br label [[ARRINIT_BODY:%.*]]
-// CHECK: [[ARRINIT_CUR:%.*]] = phi ptr [ [[ARRINIT_START]], %entry ], [ [[ARRINIT_NEXT:%.*]], [[ARRINIT_BODY]] ]
-// CHECK-NEXT: store i32 0, ptr [[ARRINIT_CUR]], align 4
-// CHECK-NEXT: [[ARRINIT_NEXT]] = getelementptr inbounds i32, ptr [[ARRINIT_CUR]], i64 1
-// CHECK-NEXT: [[ARRINIT_DONE:%.*]] = icmp eq ptr [[ARRINIT_NEXT]], [[ARRINIT_END:%.*]]
-// CHECK-NEXT: br i1 [[ARRINIT_DONE]], label [[ARRINIT_END1:%.*]], label [[ARRINIT_BODY]]
-// CHECK: ret void
-void foo11(int a, int b) {
-  int arr2[4](a, b);
-}
-
-// CHECK: define dso_local void @{{.*foo12.*}}
-// CHECK-NEXT: entry:
-// CHECK-NEXT: [[A_ADDR:%.*]] = alloca i32, align 4
-// CHECK-NEXT: [[B_ADDR:%.*]] = alloca i32, align 4
-// CHECK-NEXT: [[ARR_3:%.*]] = alloca [2 x i32], align 4
-// CHECK-NEXT: store i32 [[A:%.*]], ptr [[A_ADDR]], align 4
-// CHECK-NEXT: store i32 [[B:%.*]], ptr [[B_ADDR]], align 4
-// CHECK-NEXT: [[ARRINIT_BEGIN:%.*]] = getelementptr inbounds [2 x i32], ptr [[ARR_3]], i64 0, i64 0
-// CHECK-NEXT: [[TMP_0:%.*]] = load i32, ptr [[A_ADDR]], align 4
-// CHECK-NEXT: store i32 [[TMP_0]], ptr [[ARRINIT_BEGIN]], align 4
-// CHECK-NEXT: [[ARRINIT_ELEMENT:%.*]] = getelementptr inbounds i32, ptr [[ARRINIT_BEGIN]], i64 1
-// CHECK-NEXT: [[TMP_1:%.*]] = load i32, ptr [[B_ADDR]], align 4
-// CHECK-NEXT: store i32 [[TMP_1]], ptr [[ARRINIT_ELEMENT]], align 4
-// CHECK-NEXT: ret void
-void foo12(int a, int b) {
-  int arr3[](a, b);
-}
-
-// CHECK: define dso_local { i8, double } @{{.*foo13.*}}
-// CHECK-NEXT: entry:
-// CHECK-NEXT: [[RETVAL:%.*]] = alloca [[STRUCT_A]], align 8
-// CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 8 [[RETVAL]], ptr align 8 [[A2]], i64 16, i1 false)
-// CHECK-NEXT: [[TMP_0:%.*]] = load { i8, double }, ptr [[RETVAL]], align 8
-// CHECK-NEXT: ret { i8, double } [[TMP_0]]
-A foo13() {
-  return a2;
-}
-
-// CHECK: define dso_local noundef ptr @{{.*foo14.*}}()
-// CHECK-NEXT: entry:
-// CHECK-NEXT: ret ptr [[ARR4]]
-const int* foo14() {
-  return arr4;
-}
-
-// CHECK: define dso_local noundef ptr @{{.*foo15.*}}()
-// CHECK-NEXT: entry:
-// CHECK-NEXT: ret ptr [[ARR5]]
-const int* foo15() {
-  return arr5;
-}
-
-// CHECK: define dso_local void @{{.*foo16.*}}
-// CHECK-NEXT: entry:
-// CHECK-NEXT: [[ARR_6:%.*arr6.*]] = alloca ptr, align 8
-// CHECK-NEXT: [[REF_TMP:%.*]] = alloca [1 x i32], align 4
-// CHECK-NEXT: [[ARRINIT_BEGIN:%.*]] = getelementptr inbounds [1 x i32], ptr [[REF_TMP]], i64 0, i64 0
-// CHECK-NEXT: store i32 3, ptr [[ARRINIT_BEGIN]], align 4
-// CHECK-NEXT: store ptr [[REF_TMP]], ptr [[ARR_6]], align 8
-// CHECK-NEXT: ret void
-void foo16() {
-  int (&&arr6)[] = static_cast<int[]>(3);
-}
-
-// CHECK: define dso_local void @{{.*foo17.*}}
-// CHECK-NEXT: entry:
-// CHECK-NEXT: [[ARR_7:%.*arr7.*]] = alloca ptr, align 8
-// CHECK-NEXT: [[REF_TMP:%.*]] = alloca [2 x i32], align 4
-// CHECK-NEXT: [[ARRINIT_BEGIN:%.*]] = getelementptr inbounds [2 x i32], ptr [[REF_TMP]], i64 0, i64 0
-// CHECK-NEXT: store i32 4, ptr [[ARRINIT_BEGIN]], align 4
-// CHECK-NEXT: [[ARRINIT_START:%.*]] = getelementptr inbounds i32, ptr [[ARRINIT_BEGIN]], i64 1
-// CHECK-NEXT: [[ARRINIT_END:%.*]] = getelementptr inbounds i32, ptr [[ARRINIT_BEGIN]], i64 2
-// CHECK-NEXT: br label [[ARRINIT_BODY]]
-// CHECK: [[ARRINIT_CUR:%.*]] = phi ptr [ [[ARRINIT_START]], %entry ], [ [[ARRINIT_NEXT:%.*]], [[ARRINIT_BODY]] ]
-// CHECK-NEXT: store i32 0, ptr [[ARRINIT_CUR]], align 4
-// CHECK-NEXT: [[ARRINIT_NEXT]] = getelementptr inbounds i32, ptr [[ARRINIT_CUR]], i64 1
-// CHECK-NEXT: [[ARRINIT_DONE:%.*]] = icmp eq ptr [[ARRINIT_NEXT]], [[ARRINIT_END:%.*]]
-// CHECK-NEXT: br i1 [[ARRINIT_DONE]], label [[ARRINIT_END1:%.*]], label [[ARRINIT_BODY]]
-// CHECK: store ptr [[REF_TMP]], ptr [[ARR_7]], align 8
-// CHECK: ret void
-void foo17() {
-  int (&&arr7)[2] = static_cast<int[2]>(4);
-}
-
-// CHECK: define dso_local void @{{.*foo18.*}}
-// CHECK-NEXT: entry:
-// CHECK-NEXT: [[E:%.*e.*]] = alloca [[STRUCT_E]], align 8
-// CHECK-NEXT: [[A:%.*a.*]] = getelementptr inbounds [[STRUCT_E]], ptr [[E]], i32 0, i32 0
-// CHECK-NEXT: store i32 1, ptr [[A]], align 8
-// CHECK-NEXT: [[FN:%.*fn.*]] = getelementptr inbounds [[STRUCT_E]], ptr [[E]], i32 0, i32 1
-// CHECK-NEXT: store ptr [[STR]], ptr [[FN]], align 8
-// CHECK: ret void
-void foo18() {
-  E e(1);
-}
-
-// CHECK: define dso_local void @{{.*foo19.*}}
-// CHECK-NEXT: entry:
-// CHECK-NEXT: [[G:%.*g.*]] = alloca [[STRUCT_G]], align 4
-// CHECK-NEXT: [[A:%.*a.*]] = getelementptr inbounds [[STRUCT_G]], ptr [[G]], i32 0, i32 0
-// CHECK-NEXT: store i32 2, ptr [[A]], align 4
-// CHECK-NEXT: [[F:%.*f.*]] = getelementptr inbounds [[STRUCT_G]], ptr [[G]], i32 0, i32 1
-// CHECk-NEXT: call void @{{.*F.*}}(ptr noundef nonnull align 1 dereferenceable(1)) [[F]], ie32 noundef 1)
-// CHECK: ret void
-void foo19() {
-  G g(2);
-}

diff  --git a/clang/test/Lexer/cxx-features.cpp b/clang/test/Lexer/cxx-features.cpp
index 4a2bf56450df8..67b5265d7daf0 100644
--- a/clang/test/Lexer/cxx-features.cpp
+++ b/clang/test/Lexer/cxx-features.cpp
@@ -61,7 +61,8 @@
 
 // --- C++20 features ---
 
-#if check(aggregate_paren_init, 0, 0, 0, 0, 201902, 201902)
+#if check(aggregate_paren_init, 0, 0, 0, 0, 0, 0)
+// FIXME: 201902 in C++20
 #error "wrong value for __cpp_aggregate_paren_init"
 #endif
 

diff  --git a/clang/test/PCH/cxx_paren_init.cpp b/clang/test/PCH/cxx_paren_init.cpp
deleted file mode 100644
index 5539b160bf7a2..0000000000000
--- a/clang/test/PCH/cxx_paren_init.cpp
+++ /dev/null
@@ -1,29 +0,0 @@
-// RUN: %clang_cc1 -x c++ -std=c++20 -triple x86_64-unknown-linux-gnu -emit-pch -o %t %S/cxx_paren_init.h
-// RUN: %clang_cc1 -x c++ -std=c++20 -triple x86_64-unknown-linux-gnu -include-pch %t %s -S -emit-llvm -o - | FileCheck %s
-
-// CHECK-DAG: [[STRUCT_S:%.*]] = type { i32, i32 }
-// CHECK-DAG: @{{.*s.*}} = {{(dso_local )?}}global [[STRUCT_S]] { i32 1, i32 2 }, align 4
-S s = foo(1, 2);
-
-// CHECK: define dso_local void @{{.*bar.*}}
-// CHECK-NEXT: entry:
-// CHECK-NEXT: [[I_ADDR:%.*]] = alloca i32, align 4
-// CHECK-NEXT: [[J_ADDR:%.*]] = alloca i32, align 4
-// CHECK-NEXT: [[ARR:%.*]] = alloca [4 x i32], align 16
-// CHECK-NEXT: store i32 [[A:%.*]], ptr [[I_ADDR]], align 4
-// CHECK-NEXT: store i32 [[B:%.*]], ptr [[J_ADDR]], align 4
-// CHECK-NEXT: [[ARRINIT_BEGIN:%.*]] = getelementptr inbounds [4 x i32], ptr [[ARR]], i64 0, i64 0
-// CHECK-NEXT: [[TMP_0:%.*]] = load i32, ptr [[I_ADDR]], align 4
-// CHECK-NEXT: store i32 [[TMP_0]], ptr [[ARRINIT_BEGIN]], align 4
-// CHECK-NEXT: [[ARRINIT_ELEM:%.*]] = getelementptr inbounds i32, ptr [[ARRINIT_BEGIN]], i64 1
-// CHECK-NEXT: [[TMP_1:%.*]] = load i32, ptr [[J_ADDR]], align 4
-// CHECK-NEXT: store i32 [[TMP_1]], ptr [[ARRINIT_ELEM]], align 4
-// CHECK-NEXT: [[ARRINIT_START:%.*]] = getelementptr inbounds i32, ptr [[ARRINIT_ELEM]], i64 1
-// CHECK-NEXT: [[ARRINIT_END:%.*]] = getelementptr inbounds i32, ptr [[ARRINIT_BEGIN]], i64 4
-// CHECK-NEXT: br label [[ARRINIT_BODY:%.*]]
-// CHECK: [[ARRINIT_CUR:%.*]] = phi ptr [ [[ARRINIT_START]], %entry ], [ [[ARRINIT_NEXT:%.*]], [[ARRINIT_BODY]] ]
-// CHECK-NEXT: store i32 0, ptr [[ARRINIT_CUR]], align 4
-// CHECK-NEXT: [[ARRINIT_NEXT]] = getelementptr inbounds i32, ptr [[ARRINIT_CUR]], i64 1
-// CHECK-NEXT: [[ARRINIT_DONE:%.*]] = icmp eq ptr [[ARRINIT_NEXT]], [[ARRINIT_END:%.*]]
-// CHECK-NEXT: br i1 [[ARRINIT_DONE]], label [[ARRINIT_END1:%.*]], label [[ARRINIT_BODY]]
-// CHECK: ret void

diff  --git a/clang/test/PCH/cxx_paren_init.h b/clang/test/PCH/cxx_paren_init.h
deleted file mode 100644
index ed3cd56a5ccc2..0000000000000
--- a/clang/test/PCH/cxx_paren_init.h
+++ /dev/null
@@ -1,5 +0,0 @@
-struct S { int i, j; };
-
-constexpr S foo(int i, int j) { return S(i, j); };
-
-void bar(int i, int j) { int arr[4](i, j); };

diff  --git a/clang/test/SemaCXX/cxx2a-explicit-bool.cpp b/clang/test/SemaCXX/cxx2a-explicit-bool.cpp
index 9fdc059493aac..ad2a3a1ea75e9 100644
--- a/clang/test/SemaCXX/cxx2a-explicit-bool.cpp
+++ b/clang/test/SemaCXX/cxx2a-explicit-bool.cpp
@@ -1,5 +1,5 @@
-// RUN: %clang_cc1 -std=c++17 -fsyntax-only %s -verify=expected,pre20 -Wno-c++2a-extensions
-// RUN: %clang_cc1 -std=c++2a -fsyntax-only %s -verify=expected,post20
+// RUN: %clang_cc1 -std=c++17 -fsyntax-only %s -verify -Wno-c++2a-extensions
+// RUN: %clang_cc1 -std=c++2a -fsyntax-only %s -verify
 
 template <bool b, auto val> struct enable_ifv {};
 
@@ -20,7 +20,7 @@ namespace special_cases
 
 template<int a>
 struct A {
-// pre20-note at -1+ {{candidate constructor}}
+// expected-note at -1+ {{candidate constructor}}
   explicit(1 << a)
 // expected-note at -1 {{negative shift count -1}}
 // expected-error at -2 {{explicit specifier argument is not a constant expression}}
@@ -28,9 +28,8 @@ struct A {
 };
 
 A<-1> a(0);
-// pre20-error at -1 {{no matching constructor}}
-// post20-error at -2 {{excess elements in struct initializer}}
-// expected-note at -3 {{in instantiation of template class}}
+// expected-error at -1 {{no matching constructor}}
+// expected-note at -2 {{in instantiation of template class}}
 
 template<int a>
 struct B {

diff  --git a/clang/test/SemaCXX/paren-list-agg-init.cpp b/clang/test/SemaCXX/paren-list-agg-init.cpp
deleted file mode 100644
index 5f42b15243b95..0000000000000
--- a/clang/test/SemaCXX/paren-list-agg-init.cpp
+++ /dev/null
@@ -1,172 +0,0 @@
-// RUN: %clang_cc1 -verify -std=c++20 %s -fsyntax-only
-// RUN: %clang_cc1 -verify=expected,beforecxx20 -Wc++20-extensions -std=c++20 %s -fsyntax-only
-
-struct A { // expected-note 4{{candidate constructor}}
-  char i;
-  double j;
-};
-
-struct B {
-  A a;
-  int b[20];
-  int &&c; // expected-note {{reference member declared here}}
-};
-
-struct C { // expected-note 5{{candidate constructor}}
-  A a;
-  int b[20];
-};
-
-struct D : public C, public A {
-  int a;
-};
-
-struct E { // expected-note 3{{candidate constructor}}
-  struct F {
-    F(int, int);
-  };
-  int a;
-  F f;
-};
-
-int getint(); // expected-note {{declared here}}
-
-struct F {
-  int a;
-  int b = getint(); // expected-note {{non-constexpr function 'getint' cannot be used in a constant expression}}
-};
-
-template <typename T>
-struct G {
-  T t1;
-  T t2;
-};
-
-struct H {
-  virtual void foo() = 0;
-};
-
-struct I : public H { // expected-note 3{{candidate constructor}}
-  int i, j;
-  void foo() override {}
-};
-
-struct J {
-  int a;
-  int b[]; // expected-note {{initialized flexible array member 'b' is here}}
-};
-
-union U {
-  int a;
-  char* b;
-};
-
-template <typename T, char CH>
-void bar() {
-  T t = 0;
-  A a(CH, 1.1); // OK; C++ paren list constructors are supported in semantic tree transformations.
-  // beforecxx20-warning at -1 {{aggregate initialization of type 'A' from a parenthesized list of values is a C++20 extension}}
-}
-
-template <class T, class... Args>
-T Construct(Args... args) {
-  return T(args...); // OK; variadic arguments can be used in paren list initializers.
-  // beforecxx20-warning at -1 {{aggregate initialization of type 'A' from a parenthesized list of values is a C++20 extension}}
-}
-
-void foo() {
-  A a1(1954, 9, 21);
-  // expected-error at -1 {{excess elements in struct initializer}}
-  A a2(2.1);
-  // expected-warning at -1 {{implicit conversion from 'double' to 'char'}}
-  // beforecxx20-warning at -2 {{aggregate initialization of type 'A' from a parenthesized list of values is a C++20 extension}}
-  A a3(-1.2, 9.8);
-  // expected-warning at -1 {{implicit conversion from 'double' to 'char'}}
-  // beforecxx20-warning at -2 {{aggregate initialization of type 'A' from a parenthesized list of values is a C++20 extension}}
-  A a4 = static_cast<A>(1.1);
-  // expected-warning at -1 {{implicit conversion from 'double' to 'char'}}
-  // beforecxx20-warning at -2 {{aggregate initialization of type 'A' from a parenthesized list of values is a C++20 extension}}
-  A a5 = (A)3.1;
-  // expected-warning at -1 {{implicit conversion from 'double' to 'char'}}
-  // beforecxx20-warning at -2 {{aggregate initialization of type 'A' from a parenthesized list of values is a C++20 extension}}
-  A a6 = A(8.7);
-  // expected-warning at -1 {{implicit conversion from 'double' to 'char'}}
-  // beforecxx20-warning at -2 {{aggregate initialization of type 'A' from a parenthesized list of values is a C++20 extension}}
-
-  B b1(2022, {7, 8});
-  // expected-error at -1 {{no viable conversion from 'int' to 'A'}}
-  B b2(A(1), {}, 1);
-  // expected-error at -1 {{reference member 'c' binds to a temporary object whose lifetime would be shorter than the lifetime of the constructed object}}
-  // beforecxx20-warning at -2 {{aggregate initialization of type 'A' from a parenthesized list of values is a C++20 extension}}
-  // beforecxx20-warning at -3 {{aggregate initialization of type 'B' from a parenthesized list of values is a C++20 extension}}
-
-  C c(A(1), 1, 2, 3, 4);
-  // expected-error at -1 {{array initializer must be an initializer list}}
-  // beforecxx20-warning at -2 {{aggregate initialization of type 'A' from a parenthesized list of values is a C++20 extension}}
-  D d1(1);
-  // expected-error at -1 {{no viable conversion from 'int' to 'C'}}
-  D d2(C(1));
-  // expected-error at -1 {{no matching conversion for functional-style cast from 'int' to 'C'}}
-  // beforecxx20-warning at -2 {{aggregate initialization of type 'D' from a parenthesized list of values is a C++20 extension}}
-  D d3(C(A(1)), 1);
-  // expected-error at -1 {{no viable conversion from 'int' to 'A'}}
-  // beforecxx20-warning at -2 {{aggregate initialization of type 'A' from a parenthesized list of values is a C++20 extension}}
-  // beforecxx20-warning at -3 {{aggregate initialization of type 'C' from a parenthesized list of values is a C++20 extension}}
-
-  int arr1[](0, 1, 2, A(1));
-  // expected-error at -1 {{no viable conversion from 'A' to 'int'}}
-  // beforecxx20-warning at -2 {{aggregate initialization of type 'A' from a parenthesized list of values is a C++20 extension}}
-
-  int arr2[2](0, 1, 2);
-  // expected-error at -1 {{excess elements in array initializer}}
-
-  // We should not build paren list initilizations for IK_COPY.
-  int arr3[1] = 1;
-  // expected-error at -1 {{array initializer must be an initializer list}}
-
-  U u1("abcd");
-  // expected-error at -1 {{cannot initialize a member subobject of type 'int' with an lvalue of type 'const char[5]'}}
-  U u2(1, "efgh");
-  // expected-error at -1 {{excess elements in union initializer}}
-
-  E e1(1);
-  // expected-error at -1 {{no matching constructor for initialization of 'E'}}
-
-  constexpr F f1(1);
-  // expected-error at -1 {{constexpr variable 'f1' must be initialized by a constant expression}}
-  // beforecxx20-warning at -2 {{aggregate initialization of type 'const F' from a parenthesized list of values is a C++20 extension}}
-
-  constexpr F f2(1, 1); // OK: f2.b is initialized by a constant expression.
-  // beforecxx20-warning at -1 {{aggregate initialization of type 'const F' from a parenthesized list of values is a C++20 extension}}
-
-  bar<char, 1>();
-
-  G<char> g('b', 'b');
-  // beforecxx20-warning at -1 {{aggregate initialization of type 'G<char>' from a parenthesized list of values is a C++20 extension}}
-
-  A a7 = Construct<A>('i', 2.2);
-  // beforecxx20-note at -1 {{in instantiation of function template specialization 'Construct<A, char, double>' requested here}}
-
-  int arr4[](1, 2);
-  // beforecxx20-warning at -1 {{aggregate initialization of type 'int[2]' from a parenthesized list of values is a C++20 extension}}
-
-  int arr5[2](1, 2);
-  // beforecxx20-warning at -1 {{aggregate initialization of type 'int[2]' from a parenthesized list of values is a C++20 extension}}
-
-  I i(1, 2);
-  // expected-error at -1 {{no matching constructor for initialization of 'I'}}
-
-  J j(1, {2, 3});
-  // expected-error at -1 {{initialization of flexible array member is not allowed}}
-
-  static_assert(__is_trivially_constructible(A, char, double));
-  static_assert(__is_trivially_constructible(A, char, int));
-  static_assert(__is_trivially_constructible(A, char));
-
-  static_assert(__is_trivially_constructible(D, C, A, int));
-  static_assert(__is_trivially_constructible(D, C));
-
-  static_assert(__is_trivially_constructible(int[2], int, int));
-  static_assert(__is_trivially_constructible(int[2], int, double));
-  static_assert(__is_trivially_constructible(int[2], int));
-}

diff  --git a/clang/test/SemaCXX/recovery-expr-type.cpp b/clang/test/SemaCXX/recovery-expr-type.cpp
index 479039f284799..a5ba1ae2b8222 100644
--- a/clang/test/SemaCXX/recovery-expr-type.cpp
+++ b/clang/test/SemaCXX/recovery-expr-type.cpp
@@ -1,6 +1,4 @@
-// RUN: %clang_cc1 -triple=x86_64-unknown-unknown -o - %s -std=gnu++17 -fsyntax-only -verify
-// RUN: %clang_cc1 -triple=x86_64-unknown-unknown -o - %s -std=gnu++20 -fsyntax-only -verify
-
+// RUN: %clang_cc1 -triple=x86_64-unknown-unknown -frecovery-ast -frecovery-ast-type -o - %s -std=gnu++17 -fsyntax-only -verify
 
 namespace test0 {
 struct Indestructible {
@@ -173,13 +171,3 @@ void f() {
   S.m(1); // no crash
 }
 }
-
-namespace test16 {
-// verify we do not crash on incomplete class type.
-template<typename T, typename U> struct A; // expected-note 5{{template is declared here}}
-A<int, int> foo() { // expected-error {{implicit instantiation of undefined template}}
-  if (1 == 1)
-    return A<int, int>{1}; // expected-error 2{{implicit instantiation of undefined template}}
-  return A<int, int>(1); // expected-error 2{{implicit instantiation of undefined template}}
-}
-}

diff  --git a/clang/tools/libclang/CIndex.cpp b/clang/tools/libclang/CIndex.cpp
index 06fc65136e3bd..057fa594cc24e 100644
--- a/clang/tools/libclang/CIndex.cpp
+++ b/clang/tools/libclang/CIndex.cpp
@@ -2139,7 +2139,6 @@ class EnqueueVisitor : public ConstStmtVisitor<EnqueueVisitor, void> {
   void VisitLambdaExpr(const LambdaExpr *E);
   void VisitConceptSpecializationExpr(const ConceptSpecializationExpr *E);
   void VisitRequiresExpr(const RequiresExpr *E);
-  void VisitCXXParenListInitExpr(const CXXParenListInitExpr *E);
   void VisitOMPExecutableDirective(const OMPExecutableDirective *D);
   void VisitOMPLoopBasedDirective(const OMPLoopBasedDirective *D);
   void VisitOMPLoopDirective(const OMPLoopDirective *D);
@@ -3007,9 +3006,6 @@ void EnqueueVisitor::VisitRequiresExpr(const RequiresExpr *E) {
   for (ParmVarDecl *VD : E->getLocalParameters())
     AddDecl(VD);
 }
-void EnqueueVisitor::VisitCXXParenListInitExpr(const CXXParenListInitExpr *E) {
-  EnqueueChildren(E);
-}
 void EnqueueVisitor::VisitPseudoObjectExpr(const PseudoObjectExpr *E) {
   // Treat the expression like its syntactic form.
   Visit(E->getSyntacticForm());
@@ -5591,8 +5587,6 @@ CXString clang_getCursorKindSpelling(enum CXCursorKind Kind) {
     return cxstring::createRef("ConceptSpecializationExpr");
   case CXCursor_RequiresExpr:
     return cxstring::createRef("RequiresExpr");
-  case CXCursor_CXXParenListInitExpr:
-    return cxstring::createRef("CXXParenListInitExpr");
   case CXCursor_UnexposedStmt:
     return cxstring::createRef("UnexposedStmt");
   case CXCursor_DeclStmt:

diff  --git a/clang/tools/libclang/CXCursor.cpp b/clang/tools/libclang/CXCursor.cpp
index d48063f105f9f..3eda1e3e38d85 100644
--- a/clang/tools/libclang/CXCursor.cpp
+++ b/clang/tools/libclang/CXCursor.cpp
@@ -643,10 +643,6 @@ CXCursor cxcursor::MakeCXCursor(const Stmt *S, const Decl *Parent,
     K = CXCursor_RequiresExpr;
     break;
 
-  case Stmt::CXXParenListInitExprClass:
-    K = CXCursor_CXXParenListInitExpr;
-    break;
-
   case Stmt::MSDependentExistsStmtClass:
     K = CXCursor_UnexposedStmt;
     break;

diff  --git a/clang/www/cxx_status.html b/clang/www/cxx_status.html
index c9df1ed37350b..ab4eabb542f5b 100755
--- a/clang/www/cxx_status.html
+++ b/clang/www/cxx_status.html
@@ -1156,7 +1156,7 @@ <h2 id="cxx20">C++20 implementation status</h2>
     <tr>
       <td rowspan="2">Parenthesized initialization of aggregates</td>
       <td><a href="https://wg21.link/p0960r3">P0960R3</a></td>
-      <td rowspan="2" class="unreleased" align="center">Clang 16</td>
+      <td rowspan="2" class="none" align="center">No</td>
     </tr>
       <tr> <!-- from Belfast -->
         <td><a href="https://wg21.link/p1975r0">P1975R0</a></td>


        


More information about the cfe-commits mailing list