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@-1 {{no matching constructor for initialization of 'A'}} -// pre20-error@-2 {{no matching constructor for initialization of 'B'}} -// post20-error@-3 {{excess elements in struct initializer}} -// post20-error@-4 {{excess elements in struct initializer}} +// expected-error@-1 {{no matching constructor for initialization of 'A'}} +// expected-error@-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@-1+ {{candidate constructor}} +// expected-note@-1+ {{candidate constructor}} explicit(1 << a) // expected-note@-1 {{negative shift count -1}} // expected-error@-2 {{explicit specifier argument is not a constant expression}} @@ -28,9 +28,8 @@ struct A { }; A<-1> a(0); -// pre20-error@-1 {{no matching constructor}} -// post20-error@-2 {{excess elements in struct initializer}} -// expected-note@-3 {{in instantiation of template class}} +// expected-error@-1 {{no matching constructor}} +// expected-note@-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@-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@-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@-1 {{excess elements in struct initializer}} - A a2(2.1); - // expected-warning@-1 {{implicit conversion from 'double' to 'char'}} - // beforecxx20-warning@-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@-1 {{implicit conversion from 'double' to 'char'}} - // beforecxx20-warning@-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@-1 {{implicit conversion from 'double' to 'char'}} - // beforecxx20-warning@-2 {{aggregate initialization of type 'A' from a parenthesized list of values is a C++20 extension}} - A a5 = (A)3.1; - // expected-warning@-1 {{implicit conversion from 'double' to 'char'}} - // beforecxx20-warning@-2 {{aggregate initialization of type 'A' from a parenthesized list of values is a C++20 extension}} - A a6 = A(8.7); - // expected-warning@-1 {{implicit conversion from 'double' to 'char'}} - // beforecxx20-warning@-2 {{aggregate initialization of type 'A' from a parenthesized list of values is a C++20 extension}} - - B b1(2022, {7, 8}); - // expected-error@-1 {{no viable conversion from 'int' to 'A'}} - B b2(A(1), {}, 1); - // expected-error@-1 {{reference member 'c' binds to a temporary object whose lifetime would be shorter than the lifetime of the constructed object}} - // beforecxx20-warning@-2 {{aggregate initialization of type 'A' from a parenthesized list of values is a C++20 extension}} - // beforecxx20-warning@-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@-1 {{array initializer must be an initializer list}} - // beforecxx20-warning@-2 {{aggregate initialization of type 'A' from a parenthesized list of values is a C++20 extension}} - D d1(1); - // expected-error@-1 {{no viable conversion from 'int' to 'C'}} - D d2(C(1)); - // expected-error@-1 {{no matching conversion for functional-style cast from 'int' to 'C'}} - // beforecxx20-warning@-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@-1 {{no viable conversion from 'int' to 'A'}} - // beforecxx20-warning@-2 {{aggregate initialization of type 'A' from a parenthesized list of values is a C++20 extension}} - // beforecxx20-warning@-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@-1 {{no viable conversion from 'A' to 'int'}} - // beforecxx20-warning@-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@-1 {{excess elements in array initializer}} - - // We should not build paren list initilizations for IK_COPY. - int arr3[1] = 1; - // expected-error@-1 {{array initializer must be an initializer list}} - - U u1("abcd"); - // expected-error@-1 {{cannot initialize a member subobject of type 'int' with an lvalue of type 'const char[5]'}} - U u2(1, "efgh"); - // expected-error@-1 {{excess elements in union initializer}} - - E e1(1); - // expected-error@-1 {{no matching constructor for initialization of 'E'}} - - constexpr F f1(1); - // expected-error@-1 {{constexpr variable 'f1' must be initialized by a constant expression}} - // beforecxx20-warning@-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@-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@-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@-1 {{in instantiation of function template specialization 'Construct<A, char, double>' requested here}} - - int arr4[](1, 2); - // beforecxx20-warning@-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@-1 {{aggregate initialization of type 'int[2]' from a parenthesized list of values is a C++20 extension}} - - I i(1, 2); - // expected-error@-1 {{no matching constructor for initialization of 'I'}} - - J j(1, {2, 3}); - // expected-error@-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> _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits