Index: cfe/trunk/include/clang/AST/Expr.h =================================================================== --- cfe/trunk/include/clang/AST/Expr.h +++ cfe/trunk/include/clang/AST/Expr.h @@ -4844,31 +4844,46 @@ } }; -class ParenListExpr : public Expr { - Stmt **Exprs; - unsigned NumExprs; +class ParenListExpr final + : public Expr, + private llvm::TrailingObjects { + friend class ASTStmtReader; + friend TrailingObjects; + + /// The location of the left and right parentheses. SourceLocation LParenLoc, RParenLoc; -public: - ParenListExpr(const ASTContext& C, SourceLocation lparenloc, - ArrayRef exprs, SourceLocation rparenloc); + /// Build a paren list. + ParenListExpr(SourceLocation LParenLoc, ArrayRef Exprs, + SourceLocation RParenLoc); /// Build an empty paren list. - explicit ParenListExpr(EmptyShell Empty) : Expr(ParenListExprClass, Empty) { } + ParenListExpr(EmptyShell Empty, unsigned NumExprs); + +public: + /// Create a paren list. + static ParenListExpr *Create(const ASTContext &Ctx, SourceLocation LParenLoc, + ArrayRef Exprs, + SourceLocation RParenLoc); + + /// Create an empty paren list. + static ParenListExpr *CreateEmpty(const ASTContext &Ctx, unsigned NumExprs); - unsigned getNumExprs() const { return NumExprs; } + /// Return the number of expressions in this paren list. + unsigned getNumExprs() const { return ParenListExprBits.NumExprs; } - const Expr* getExpr(unsigned Init) const { + Expr *getExpr(unsigned Init) { assert(Init < getNumExprs() && "Initializer access out of range!"); - return cast_or_null(Exprs[Init]); + return getExprs()[Init]; } - Expr* getExpr(unsigned Init) { - assert(Init < getNumExprs() && "Initializer access out of range!"); - return cast_or_null(Exprs[Init]); + const Expr *getExpr(unsigned Init) const { + return const_cast(this)->getExpr(Init); } - Expr **getExprs() { return reinterpret_cast(Exprs); } + Expr **getExprs() { + return reinterpret_cast(getTrailingObjects()); + } ArrayRef exprs() { return llvm::makeArrayRef(getExprs(), getNumExprs()); @@ -4876,9 +4891,8 @@ SourceLocation getLParenLoc() const { return LParenLoc; } SourceLocation getRParenLoc() const { return RParenLoc; } - - SourceLocation getBeginLoc() const LLVM_READONLY { return LParenLoc; } - SourceLocation getEndLoc() const LLVM_READONLY { return RParenLoc; } + SourceLocation getBeginLoc() const { return getLParenLoc(); } + SourceLocation getEndLoc() const { return getRParenLoc(); } static bool classof(const Stmt *T) { return T->getStmtClass() == ParenListExprClass; @@ -4886,14 +4900,13 @@ // Iterators child_range children() { - return child_range(&Exprs[0], &Exprs[0]+NumExprs); + return child_range(getTrailingObjects(), + getTrailingObjects() + getNumExprs()); } const_child_range children() const { - return const_child_range(&Exprs[0], &Exprs[0] + NumExprs); + return const_child_range(getTrailingObjects(), + getTrailingObjects() + getNumExprs()); } - - friend class ASTStmtReader; - friend class ASTStmtWriter; }; /// Represents a C11 generic selection. Index: cfe/trunk/include/clang/AST/Stmt.h =================================================================== --- cfe/trunk/include/clang/AST/Stmt.h +++ cfe/trunk/include/clang/AST/Stmt.h @@ -496,6 +496,16 @@ unsigned HadArrayRangeDesignator : 1; }; + class ParenListExprBitfields { + friend class ASTStmtReader; + friend class ParenListExpr; + + unsigned : NumExprBits; + + /// The number of expressions in the paren list. + unsigned NumExprs; + }; + class PseudoObjectExprBitfields { friend class ASTStmtReader; // deserialization friend class PseudoObjectExpr; @@ -672,6 +682,7 @@ CastExprBitfields CastExprBits; BinaryOperatorBitfields BinaryOperatorBits; InitListExprBitfields InitListExprBits; + ParenListExprBitfields ParenListExprBits; PseudoObjectExprBitfields PseudoObjectExprBits; // C++ Expressions Index: cfe/trunk/lib/AST/ASTImporter.cpp =================================================================== --- cfe/trunk/lib/AST/ASTImporter.cpp +++ cfe/trunk/lib/AST/ASTImporter.cpp @@ -6409,8 +6409,8 @@ if (!ToRParenLocOrErr) return ToRParenLocOrErr.takeError(); - return new (Importer.getToContext()) ParenListExpr( - Importer.getToContext(), *ToLParenLocOrErr, ToExprs, *ToRParenLocOrErr); + return ParenListExpr::Create(Importer.getToContext(), *ToLParenLocOrErr, + ToExprs, *ToRParenLocOrErr); } ExpectedStmt ASTNodeImporter::VisitStmtExpr(StmtExpr *E) { Index: cfe/trunk/lib/AST/Expr.cpp =================================================================== --- cfe/trunk/lib/AST/Expr.cpp +++ cfe/trunk/lib/AST/Expr.cpp @@ -4004,27 +4004,48 @@ return getBase()->getEndLoc(); } -ParenListExpr::ParenListExpr(const ASTContext& C, SourceLocation lparenloc, - ArrayRef exprs, - SourceLocation rparenloc) - : Expr(ParenListExprClass, QualType(), VK_RValue, OK_Ordinary, - false, false, false, false), - NumExprs(exprs.size()), LParenLoc(lparenloc), RParenLoc(rparenloc) { - Exprs = new (C) Stmt*[exprs.size()]; - for (unsigned i = 0; i != exprs.size(); ++i) { - if (exprs[i]->isTypeDependent()) +ParenListExpr::ParenListExpr(SourceLocation LParenLoc, ArrayRef Exprs, + SourceLocation RParenLoc) + : Expr(ParenListExprClass, QualType(), VK_RValue, OK_Ordinary, false, false, + false, false), + LParenLoc(LParenLoc), RParenLoc(RParenLoc) { + ParenListExprBits.NumExprs = Exprs.size(); + + for (unsigned I = 0, N = Exprs.size(); I != N; ++I) { + if (Exprs[I]->isTypeDependent()) ExprBits.TypeDependent = true; - if (exprs[i]->isValueDependent()) + if (Exprs[I]->isValueDependent()) ExprBits.ValueDependent = true; - if (exprs[i]->isInstantiationDependent()) + if (Exprs[I]->isInstantiationDependent()) ExprBits.InstantiationDependent = true; - if (exprs[i]->containsUnexpandedParameterPack()) + if (Exprs[I]->containsUnexpandedParameterPack()) ExprBits.ContainsUnexpandedParameterPack = true; - Exprs[i] = exprs[i]; + getTrailingObjects()[I] = Exprs[I]; } } +ParenListExpr::ParenListExpr(EmptyShell Empty, unsigned NumExprs) + : Expr(ParenListExprClass, Empty) { + ParenListExprBits.NumExprs = NumExprs; +} + +ParenListExpr *ParenListExpr::Create(const ASTContext &Ctx, + SourceLocation LParenLoc, + ArrayRef Exprs, + SourceLocation RParenLoc) { + void *Mem = Ctx.Allocate(totalSizeToAlloc(Exprs.size()), + alignof(ParenListExpr)); + return new (Mem) ParenListExpr(LParenLoc, Exprs, RParenLoc); +} + +ParenListExpr *ParenListExpr::CreateEmpty(const ASTContext &Ctx, + unsigned NumExprs) { + void *Mem = + Ctx.Allocate(totalSizeToAlloc(NumExprs), alignof(ParenListExpr)); + return new (Mem) ParenListExpr(EmptyShell(), NumExprs); +} + const OpaqueValueExpr *OpaqueValueExpr::findInCopyConstruct(const Expr *e) { if (const ExprWithCleanups *ewc = dyn_cast(e)) e = ewc->getSubExpr(); Index: cfe/trunk/lib/Sema/SemaCoroutine.cpp =================================================================== --- cfe/trunk/lib/Sema/SemaCoroutine.cpp +++ cfe/trunk/lib/Sema/SemaCoroutine.cpp @@ -565,8 +565,8 @@ // Create an initialization sequence for the promise type using the // constructor arguments, wrapped in a parenthesized list expression. - Expr *PLE = new (Context) ParenListExpr(Context, FD->getLocation(), - CtorArgExprs, FD->getLocation()); + Expr *PLE = ParenListExpr::Create(Context, FD->getLocation(), + CtorArgExprs, FD->getLocation()); InitializedEntity Entity = InitializedEntity::InitializeVariable(VD); InitializationKind Kind = InitializationKind::CreateForInit( VD->getLocation(), /*DirectInit=*/true, PLE); Index: cfe/trunk/lib/Sema/SemaDeclCXX.cpp =================================================================== --- cfe/trunk/lib/Sema/SemaDeclCXX.cpp +++ cfe/trunk/lib/Sema/SemaDeclCXX.cpp @@ -3731,8 +3731,7 @@ ArrayRef Args, SourceLocation RParenLoc, SourceLocation EllipsisLoc) { - Expr *List = new (Context) ParenListExpr(Context, LParenLoc, - Args, RParenLoc); + Expr *List = ParenListExpr::Create(Context, LParenLoc, Args, RParenLoc); return BuildMemInitializer(ConstructorD, S, SS, MemberOrBase, TemplateTypeTy, DS, IdLoc, List, EllipsisLoc); } Index: cfe/trunk/lib/Sema/SemaExpr.cpp =================================================================== --- cfe/trunk/lib/Sema/SemaExpr.cpp +++ cfe/trunk/lib/Sema/SemaExpr.cpp @@ -6410,8 +6410,7 @@ ExprResult Sema::ActOnParenListExpr(SourceLocation L, SourceLocation R, MultiExprArg Val) { - Expr *expr = new (Context) ParenListExpr(Context, L, Val, R); - return expr; + return ParenListExpr::Create(Context, L, Val, R); } /// Emit a specialized diagnostic when one expression is a null pointer Index: cfe/trunk/lib/Serialization/ASTReaderStmt.cpp =================================================================== --- cfe/trunk/lib/Serialization/ASTReaderStmt.cpp +++ cfe/trunk/lib/Serialization/ASTReaderStmt.cpp @@ -643,10 +643,9 @@ void ASTStmtReader::VisitParenListExpr(ParenListExpr *E) { VisitExpr(E); unsigned NumExprs = Record.readInt(); - E->Exprs = new (Record.getContext()) Stmt*[NumExprs]; - for (unsigned i = 0; i != NumExprs; ++i) - E->Exprs[i] = Record.readSubStmt(); - E->NumExprs = NumExprs; + assert((NumExprs == E->getNumExprs()) && "Wrong NumExprs!"); + for (unsigned I = 0; I != NumExprs; ++I) + E->getTrailingObjects()[I] = Record.readSubStmt(); E->LParenLoc = ReadSourceLocation(); E->RParenLoc = ReadSourceLocation(); } @@ -2452,7 +2451,9 @@ break; case EXPR_PAREN_LIST: - S = new (Context) ParenListExpr(Empty); + S = ParenListExpr::CreateEmpty( + Context, + /* NumExprs=*/Record[ASTStmtReader::NumExprFields + 0]); break; case EXPR_UNARY_OPERATOR: Index: cfe/trunk/lib/Serialization/ASTWriterStmt.cpp =================================================================== --- cfe/trunk/lib/Serialization/ASTWriterStmt.cpp +++ cfe/trunk/lib/Serialization/ASTWriterStmt.cpp @@ -559,11 +559,11 @@ void ASTStmtWriter::VisitParenListExpr(ParenListExpr *E) { VisitExpr(E); - Record.push_back(E->NumExprs); - for (unsigned i=0; i != E->NumExprs; ++i) - Record.AddStmt(E->Exprs[i]); - Record.AddSourceLocation(E->LParenLoc); - Record.AddSourceLocation(E->RParenLoc); + Record.push_back(E->getNumExprs()); + for (auto *SubStmt : E->exprs()) + Record.AddStmt(SubStmt); + Record.AddSourceLocation(E->getLParenLoc()); + Record.AddSourceLocation(E->getRParenLoc()); Code = serialization::EXPR_PAREN_LIST; }