Index: include/clang/AST/ExprCXX.h =================================================================== --- include/clang/AST/ExprCXX.h +++ include/clang/AST/ExprCXX.h @@ -1933,54 +1933,56 @@ /// Represents a new-expression for memory allocation and constructor /// calls, e.g: "new CXXNewExpr(foo)". -class CXXNewExpr : public Expr { +class CXXNewExpr final + : public Expr, + private llvm::TrailingObjects { friend class ASTStmtReader; friend class ASTStmtWriter; - - /// Contains an optional array size expression, an optional initialization - /// expression, and any number of optional placement arguments, in that order. - Stmt **SubExprs = nullptr; + friend TrailingObjects; /// Points to the allocation function used. FunctionDecl *OperatorNew; - /// Points to the deallocation function used in case of error. May be - /// null. + /// Points to the deallocation function used in case of error. May be null. FunctionDecl *OperatorDelete; /// The allocated type-source information, as written in the source. TypeSourceInfo *AllocatedTypeInfo; - /// If the allocated type was expressed as a parenthesized type-id, - /// the source range covering the parenthesized type-id. - SourceRange TypeIdParens; - /// Range of the entire new expression. SourceRange Range; /// Source-range of a paren-delimited initializer. SourceRange DirectInitRange; - /// Was the usage ::new, i.e. is the global new to be used? - unsigned GlobalNew : 1; - - /// Do we allocate an array? If so, the first SubExpr is the size expression. - unsigned Array : 1; - - /// Should the alignment be passed to the allocation function? - unsigned PassAlignment : 1; - - /// If this is an array allocation, does the usual deallocation - /// function for the allocated type want to know the allocated size? - unsigned UsualArrayDeleteWantsSize : 1; + // CXXNewExpr is followed by several optional trailing objects. + // They are in order: + // + // * An optional "Stmt *" for the array size expression. + // Present if and ony if isArray(). + // + // * An optional "Stmt *" for the init expression. + // Present if and only if hasInitializer(). + // + // * An array of getNumPlacementArgs() "Stmt *" for the placement new + // arguments, if any. + // + // * An optional SourceRange for the range covering the parenthesized type-id + // if the allocated type was expressed as a parenthesized type-id. + // Present if and only if isParenTypeId(). + unsigned arraySizeOffset() const { return 0; } + unsigned initExprOffset() const { return arraySizeOffset() + isArray(); } + unsigned placementNewArgsOffset() const { + return initExprOffset() + hasInitializer(); + } - /// The number of placement new arguments. - unsigned NumPlacementArgs : 26; + unsigned numTrailingObjects(OverloadToken) const { + return isArray() + hasInitializer() + getNumPlacementArgs(); + } - /// What kind of initializer do we have? Could be none, parens, or braces. - /// In storage, we distinguish between "none, and no initializer expr", and - /// "none, but an implicit initializer expr". - unsigned StoredInitializationStyle : 2; + unsigned numTrailingObjects(OverloadToken) const { + return isParenTypeId(); + } public: enum InitializationStyle { @@ -1994,18 +1996,35 @@ ListInit }; - CXXNewExpr(const ASTContext &C, bool globalNew, FunctionDecl *operatorNew, - FunctionDecl *operatorDelete, bool PassAlignment, - bool usualArrayDeleteWantsSize, ArrayRef placementArgs, - SourceRange typeIdParens, Expr *arraySize, - InitializationStyle initializationStyle, Expr *initializer, - QualType ty, TypeSourceInfo *AllocatedTypeInfo, - SourceRange Range, SourceRange directInitRange); - explicit CXXNewExpr(EmptyShell Shell) - : Expr(CXXNewExprClass, Shell) {} +private: + /// Build a c++ new expression. + CXXNewExpr(bool IsGlobalNew, FunctionDecl *OperatorNew, + FunctionDecl *OperatorDelete, bool ShouldPassAlignment, + bool UsualArrayDeleteWantsSize, ArrayRef PlacementArgs, + SourceRange TypeIdParens, Expr *ArraySize, + InitializationStyle InitializationStyle, Expr *Initializer, + QualType Ty, TypeSourceInfo *AllocatedTypeInfo, SourceRange Range, + SourceRange DirectInitRange); + + /// Build an empty c++ new expression. + CXXNewExpr(EmptyShell Empty, bool IsArray, unsigned NumPlacementArgs, + bool IsParenTypeId); - void AllocateArgsArray(const ASTContext &C, bool isArray, - unsigned numPlaceArgs, bool hasInitializer); +public: + /// Create a c++ new expression. + static CXXNewExpr * + Create(const ASTContext &Ctx, bool IsGlobalNew, FunctionDecl *OperatorNew, + FunctionDecl *OperatorDelete, bool ShouldPassAlignment, + bool UsualArrayDeleteWantsSize, ArrayRef PlacementArgs, + SourceRange TypeIdParens, Expr *ArraySize, + InitializationStyle InitializationStyle, Expr *Initializer, + QualType Ty, TypeSourceInfo *AllocatedTypeInfo, SourceRange Range, + SourceRange DirectInitRange); + + /// Create an empty c++ new expression. + static CXXNewExpr *CreateEmpty(const ASTContext &Ctx, bool IsArray, + bool HasInit, unsigned NumPlacementArgs, + bool IsParenTypeId); QualType getAllocatedType() const { assert(getType()->isPointerType()); @@ -2031,58 +2050,74 @@ /// has a non-throwing exception-specification. The '03 rule is /// identical except that the definition of a non-throwing /// exception specification is just "is it throw()?". - bool shouldNullCheckAllocation(const ASTContext &Ctx) const; + bool shouldNullCheckAllocation() const; FunctionDecl *getOperatorNew() const { return OperatorNew; } void setOperatorNew(FunctionDecl *D) { OperatorNew = D; } FunctionDecl *getOperatorDelete() const { return OperatorDelete; } void setOperatorDelete(FunctionDecl *D) { OperatorDelete = D; } - bool isArray() const { return Array; } + bool isArray() const { return CXXNewExprBits.IsArray; } Expr *getArraySize() { - return Array ? cast(SubExprs[0]) : nullptr; + return isArray() + ? cast(getTrailingObjects()[arraySizeOffset()]) + : nullptr; } const Expr *getArraySize() const { - return Array ? cast(SubExprs[0]) : nullptr; + return isArray() + ? cast(getTrailingObjects()[arraySizeOffset()]) + : nullptr; } - unsigned getNumPlacementArgs() const { return NumPlacementArgs; } + unsigned getNumPlacementArgs() const { + return CXXNewExprBits.NumPlacementArgs; + } Expr **getPlacementArgs() { - return reinterpret_cast(SubExprs + Array + hasInitializer()); + return reinterpret_cast(getTrailingObjects() + + placementNewArgsOffset()); } - Expr *getPlacementArg(unsigned i) { - assert(i < NumPlacementArgs && "Index out of range"); - return getPlacementArgs()[i]; + Expr *getPlacementArg(unsigned I) { + assert((I < getNumPlacementArgs()) && "Index out of range!"); + return getPlacementArgs()[I]; } - const Expr *getPlacementArg(unsigned i) const { - assert(i < NumPlacementArgs && "Index out of range"); - return const_cast(this)->getPlacementArg(i); + const Expr *getPlacementArg(unsigned I) const { + return const_cast(this)->getPlacementArg(I); } - bool isParenTypeId() const { return TypeIdParens.isValid(); } - SourceRange getTypeIdParens() const { return TypeIdParens; } + bool isParenTypeId() const { return CXXNewExprBits.IsParenTypeId; } + SourceRange getTypeIdParens() const { + return isParenTypeId() ? getTrailingObjects()[0] + : SourceRange(); + } - bool isGlobalNew() const { return GlobalNew; } + bool isGlobalNew() const { return CXXNewExprBits.IsGlobalNew; } /// Whether this new-expression has any initializer at all. - bool hasInitializer() const { return StoredInitializationStyle > 0; } + bool hasInitializer() const { + return CXXNewExprBits.StoredInitializationStyle > 0; + } /// The kind of initializer this new-expression has. InitializationStyle getInitializationStyle() const { - if (StoredInitializationStyle == 0) + if (CXXNewExprBits.StoredInitializationStyle == 0) return NoInit; - return static_cast(StoredInitializationStyle-1); + return static_cast( + CXXNewExprBits.StoredInitializationStyle - 1); } /// The initializer of this new-expression. Expr *getInitializer() { - return hasInitializer() ? cast(SubExprs[Array]) : nullptr; + return hasInitializer() + ? cast(getTrailingObjects()[initExprOffset()]) + : nullptr; } const Expr *getInitializer() const { - return hasInitializer() ? cast(SubExprs[Array]) : nullptr; + return hasInitializer() + ? cast(getTrailingObjects()[initExprOffset()]) + : nullptr; } /// Returns the CXXConstructExpr from this new-expression, or null. @@ -2092,15 +2127,13 @@ /// Indicates whether the required alignment should be implicitly passed to /// the allocation function. - bool passAlignment() const { - return PassAlignment; - } + bool passAlignment() const { return CXXNewExprBits.ShouldPassAlignment; } /// Answers whether the usual array deallocation function for the /// allocated type expects the size of the allocation as a /// parameter. bool doesUsualArrayDeleteWantSize() const { - return UsualArrayDeleteWantsSize; + return CXXNewExprBits.UsualArrayDeleteWantsSize; } using arg_iterator = ExprIterator; @@ -2115,47 +2148,43 @@ } arg_iterator placement_arg_begin() { - return SubExprs + Array + hasInitializer(); + return getTrailingObjects() + placementNewArgsOffset(); } arg_iterator placement_arg_end() { - return SubExprs + Array + hasInitializer() + getNumPlacementArgs(); + return placement_arg_begin() + getNumPlacementArgs(); } const_arg_iterator placement_arg_begin() const { - return SubExprs + Array + hasInitializer(); + return getTrailingObjects() + placementNewArgsOffset(); } const_arg_iterator placement_arg_end() const { - return SubExprs + Array + hasInitializer() + getNumPlacementArgs(); + return placement_arg_begin() + getNumPlacementArgs(); } using raw_arg_iterator = Stmt **; - raw_arg_iterator raw_arg_begin() { return SubExprs; } + raw_arg_iterator raw_arg_begin() { return getTrailingObjects(); } raw_arg_iterator raw_arg_end() { - return SubExprs + Array + hasInitializer() + getNumPlacementArgs(); + return raw_arg_begin() + numTrailingObjects(OverloadToken()); + } + const_arg_iterator raw_arg_begin() const { + return getTrailingObjects(); } - const_arg_iterator raw_arg_begin() const { return SubExprs; } const_arg_iterator raw_arg_end() const { - return SubExprs + Array + hasInitializer() + getNumPlacementArgs(); + return raw_arg_begin() + numTrailingObjects(OverloadToken()); } SourceLocation getBeginLoc() const { return Range.getBegin(); } SourceLocation getEndLoc() const { return Range.getEnd(); } SourceRange getDirectInitRange() const { return DirectInitRange; } - - SourceRange getSourceRange() const LLVM_READONLY { - return Range; - } - + SourceRange getSourceRange() const { return Range; } static bool classof(const Stmt *T) { return T->getStmtClass() == CXXNewExprClass; } // Iterators - child_range children() { - return child_range(raw_arg_begin(), raw_arg_end()); - } + child_range children() { return child_range(raw_arg_begin(), raw_arg_end()); } }; /// Represents a \c delete expression for memory deallocation and Index: include/clang/AST/Stmt.h =================================================================== --- include/clang/AST/Stmt.h +++ include/clang/AST/Stmt.h @@ -612,6 +612,39 @@ SourceLocation Loc; }; + class CXXNewExprBitfields { + friend class ASTStmtReader; + friend class ASTStmtWriter; + friend class CXXNewExpr; + + unsigned : NumExprBits; + + /// Was the usage ::new, i.e. is the global new to be used? + unsigned IsGlobalNew : 1; + + /// Do we allocate an array? If so, the first trailing "Stmt *" is the + /// size expression. + unsigned IsArray : 1; + + /// Should the alignment be passed to the allocation function? + unsigned ShouldPassAlignment : 1; + + /// If this is an array allocation, does the usual deallocation + /// function for the allocated type want to know the allocated size? + unsigned UsualArrayDeleteWantsSize : 1; + + /// What kind of initializer do we have? Could be none, parens, or braces. + /// In storage, we distinguish between "none, and no initializer expr", and + /// "none, but an implicit initializer expr". + unsigned StoredInitializationStyle : 2; + + /// True if the allocated type was expressed as a parenthesized type-id. + unsigned IsParenTypeId : 1; + + /// The number of placement new arguments. + unsigned NumPlacementArgs; + }; + class CXXDeleteExprBitfields { friend class ASTStmtReader; friend class CXXDeleteExpr; @@ -785,6 +818,7 @@ CXXThrowExprBitfields CXXThrowExprBits; CXXDefaultArgExprBitfields CXXDefaultArgExprBits; CXXDefaultInitExprBitfields CXXDefaultInitExprBits; + CXXNewExprBitfields CXXNewExprBits; CXXDeleteExprBitfields CXXDeleteExprBits; TypeTraitExprBitfields TypeTraitExprBits; DependentScopeDeclRefExprBitfields DependentScopeDeclRefExprBits; Index: lib/AST/ASTImporter.cpp =================================================================== --- lib/AST/ASTImporter.cpp +++ lib/AST/ASTImporter.cpp @@ -6910,7 +6910,7 @@ ImportContainerChecked(E->placement_arguments(), ToPlacementArgs)) return std::move(Err); - return new (Importer.getToContext()) CXXNewExpr( + return CXXNewExpr::Create( Importer.getToContext(), E->isGlobalNew(), ToOperatorNew, ToOperatorDelete, E->passAlignment(), E->doesUsualArrayDeleteWantSize(), ToPlacementArgs, ToTypeIdParens, ToArraySize, E->getInitializationStyle(), Index: lib/AST/ExprCXX.cpp =================================================================== --- lib/AST/ExprCXX.cpp +++ lib/AST/ExprCXX.cpp @@ -94,83 +94,127 @@ } // CXXNewExpr -CXXNewExpr::CXXNewExpr(const ASTContext &C, bool globalNew, - FunctionDecl *operatorNew, FunctionDecl *operatorDelete, - bool PassAlignment, bool usualArrayDeleteWantsSize, - ArrayRef placementArgs, - SourceRange typeIdParens, Expr *arraySize, - InitializationStyle initializationStyle, - Expr *initializer, QualType ty, - TypeSourceInfo *allocatedTypeInfo, - SourceRange Range, SourceRange directInitRange) - : Expr(CXXNewExprClass, ty, VK_RValue, OK_Ordinary, ty->isDependentType(), - ty->isDependentType(), ty->isInstantiationDependentType(), - ty->containsUnexpandedParameterPack()), - OperatorNew(operatorNew), OperatorDelete(operatorDelete), - AllocatedTypeInfo(allocatedTypeInfo), TypeIdParens(typeIdParens), - Range(Range), DirectInitRange(directInitRange), GlobalNew(globalNew), - PassAlignment(PassAlignment), - UsualArrayDeleteWantsSize(usualArrayDeleteWantsSize) { - assert((initializer != nullptr || initializationStyle == NoInit) && - "Only NoInit can have no initializer."); - StoredInitializationStyle = initializer ? initializationStyle + 1 : 0; - AllocateArgsArray(C, arraySize != nullptr, placementArgs.size(), - initializer != nullptr); - unsigned i = 0; - if (Array) { - if (arraySize->isInstantiationDependent()) +CXXNewExpr::CXXNewExpr(bool IsGlobalNew, FunctionDecl *OperatorNew, + FunctionDecl *OperatorDelete, bool ShouldPassAlignment, + bool UsualArrayDeleteWantsSize, + ArrayRef PlacementArgs, SourceRange TypeIdParens, + Expr *ArraySize, InitializationStyle InitializationStyle, + Expr *Initializer, QualType Ty, + TypeSourceInfo *AllocatedTypeInfo, SourceRange Range, + SourceRange DirectInitRange) + : Expr(CXXNewExprClass, Ty, VK_RValue, OK_Ordinary, Ty->isDependentType(), + Ty->isDependentType(), Ty->isInstantiationDependentType(), + Ty->containsUnexpandedParameterPack()), + OperatorNew(OperatorNew), OperatorDelete(OperatorDelete), + AllocatedTypeInfo(AllocatedTypeInfo), Range(Range), + DirectInitRange(DirectInitRange) { + + assert((Initializer != nullptr || InitializationStyle == NoInit) && + "Only NoInit can have no initializer!"); + + CXXNewExprBits.IsGlobalNew = IsGlobalNew; + CXXNewExprBits.IsArray = ArraySize != nullptr; + CXXNewExprBits.ShouldPassAlignment = ShouldPassAlignment; + CXXNewExprBits.UsualArrayDeleteWantsSize = UsualArrayDeleteWantsSize; + CXXNewExprBits.StoredInitializationStyle = + Initializer ? InitializationStyle + 1 : 0; + bool IsParenTypeId = TypeIdParens.isValid(); + CXXNewExprBits.IsParenTypeId = IsParenTypeId; + CXXNewExprBits.NumPlacementArgs = PlacementArgs.size(); + + if (ArraySize) { + if (ArraySize->isInstantiationDependent()) ExprBits.InstantiationDependent = true; - - if (arraySize->containsUnexpandedParameterPack()) + if (ArraySize->containsUnexpandedParameterPack()) ExprBits.ContainsUnexpandedParameterPack = true; - SubExprs[i++] = arraySize; + getTrailingObjects()[arraySizeOffset()] = ArraySize; } - if (initializer) { - if (initializer->isInstantiationDependent()) + if (Initializer) { + if (Initializer->isInstantiationDependent()) ExprBits.InstantiationDependent = true; - - if (initializer->containsUnexpandedParameterPack()) + if (Initializer->containsUnexpandedParameterPack()) ExprBits.ContainsUnexpandedParameterPack = true; - SubExprs[i++] = initializer; + getTrailingObjects()[initExprOffset()] = Initializer; } - for (unsigned j = 0; j != placementArgs.size(); ++j) { - if (placementArgs[j]->isInstantiationDependent()) + for (unsigned I = 0; I != PlacementArgs.size(); ++I) { + if (PlacementArgs[I]->isInstantiationDependent()) ExprBits.InstantiationDependent = true; - if (placementArgs[j]->containsUnexpandedParameterPack()) + if (PlacementArgs[I]->containsUnexpandedParameterPack()) ExprBits.ContainsUnexpandedParameterPack = true; - SubExprs[i++] = placementArgs[j]; + getTrailingObjects()[placementNewArgsOffset() + I] = + PlacementArgs[I]; } + if (IsParenTypeId) + getTrailingObjects()[0] = TypeIdParens; + switch (getInitializationStyle()) { case CallInit: - this->Range.setEnd(DirectInitRange.getEnd()); break; + this->Range.setEnd(DirectInitRange.getEnd()); + break; case ListInit: - this->Range.setEnd(getInitializer()->getSourceRange().getEnd()); break; + this->Range.setEnd(getInitializer()->getSourceRange().getEnd()); + break; default: - if (TypeIdParens.isValid()) + if (IsParenTypeId) this->Range.setEnd(TypeIdParens.getEnd()); break; } } -void CXXNewExpr::AllocateArgsArray(const ASTContext &C, bool isArray, - unsigned numPlaceArgs, bool hasInitializer){ - assert(SubExprs == nullptr && "SubExprs already allocated"); - Array = isArray; - NumPlacementArgs = numPlaceArgs; +CXXNewExpr::CXXNewExpr(EmptyShell Empty, bool IsArray, + unsigned NumPlacementArgs, bool IsParenTypeId) + : Expr(CXXNewExprClass, Empty) { + CXXNewExprBits.IsArray = IsArray; + CXXNewExprBits.NumPlacementArgs = NumPlacementArgs; + CXXNewExprBits.IsParenTypeId = IsParenTypeId; +} + +CXXNewExpr * +CXXNewExpr::Create(const ASTContext &Ctx, bool IsGlobalNew, + FunctionDecl *OperatorNew, FunctionDecl *OperatorDelete, + bool ShouldPassAlignment, bool UsualArrayDeleteWantsSize, + ArrayRef PlacementArgs, SourceRange TypeIdParens, + Expr *ArraySize, InitializationStyle InitializationStyle, + Expr *Initializer, QualType Ty, + TypeSourceInfo *AllocatedTypeInfo, SourceRange Range, + SourceRange DirectInitRange) { + bool IsArray = ArraySize != nullptr; + bool HasInit = Initializer != nullptr; + unsigned NumPlacementArgs = PlacementArgs.size(); + bool IsParenTypeId = TypeIdParens.isValid(); + void *Mem = + Ctx.Allocate(totalSizeToAlloc( + IsArray + HasInit + NumPlacementArgs, IsParenTypeId), + alignof(CXXNewExpr)); + return new (Mem) + CXXNewExpr(IsGlobalNew, OperatorNew, OperatorDelete, ShouldPassAlignment, + UsualArrayDeleteWantsSize, PlacementArgs, TypeIdParens, + ArraySize, InitializationStyle, Initializer, Ty, + AllocatedTypeInfo, Range, DirectInitRange); +} - unsigned TotalSize = Array + hasInitializer + NumPlacementArgs; - SubExprs = new (C) Stmt*[TotalSize]; +CXXNewExpr *CXXNewExpr::CreateEmpty(const ASTContext &Ctx, bool IsArray, + bool HasInit, unsigned NumPlacementArgs, + bool IsParenTypeId) { + void *Mem = + Ctx.Allocate(totalSizeToAlloc( + IsArray + HasInit + NumPlacementArgs, IsParenTypeId), + alignof(CXXNewExpr)); + return new (Mem) + CXXNewExpr(EmptyShell(), IsArray, NumPlacementArgs, IsParenTypeId); } -bool CXXNewExpr::shouldNullCheckAllocation(const ASTContext &Ctx) const { - return getOperatorNew()->getType()->castAs() - ->isNothrow() && +bool CXXNewExpr::shouldNullCheckAllocation() const { + return getOperatorNew() + ->getType() + ->castAs() + ->isNothrow() && !getOperatorNew()->isReservedGlobalPlacementOperator(); } Index: lib/CodeGen/CGExprCXX.cpp =================================================================== --- lib/CodeGen/CGExprCXX.cpp +++ lib/CodeGen/CGExprCXX.cpp @@ -1657,8 +1657,8 @@ // function is allowed to return null (because it has a non-throwing // exception spec or is the reserved placement new) and we have an // interesting initializer. - bool nullCheck = E->shouldNullCheckAllocation(getContext()) && - (!allocType.isPODType(getContext()) || E->hasInitializer()); + bool nullCheck = E->shouldNullCheckAllocation() && + (!allocType.isPODType(getContext()) || E->hasInitializer()); llvm::BasicBlock *nullCheckBB = nullptr; llvm::BasicBlock *contBB = nullptr; Index: lib/Sema/SemaExprCXX.cpp =================================================================== --- lib/Sema/SemaExprCXX.cpp +++ lib/Sema/SemaExprCXX.cpp @@ -2179,11 +2179,11 @@ } } - return new (Context) - CXXNewExpr(Context, UseGlobal, OperatorNew, OperatorDelete, PassAlignment, - UsualArrayDeleteWantsSize, PlacementArgs, TypeIdParens, - ArraySize, initStyle, Initializer, ResultType, AllocTypeInfo, - Range, DirectInitRange); + return CXXNewExpr::Create(Context, UseGlobal, OperatorNew, OperatorDelete, + PassAlignment, UsualArrayDeleteWantsSize, + PlacementArgs, TypeIdParens, ArraySize, initStyle, + Initializer, ResultType, AllocTypeInfo, Range, + DirectInitRange); } /// Checks that a type is suitable as the allocated type Index: lib/Serialization/ASTReaderStmt.cpp =================================================================== --- lib/Serialization/ASTReaderStmt.cpp +++ lib/Serialization/ASTReaderStmt.cpp @@ -1507,25 +1507,37 @@ void ASTStmtReader::VisitCXXNewExpr(CXXNewExpr *E) { VisitExpr(E); - E->GlobalNew = Record.readInt(); - bool isArray = Record.readInt(); - E->PassAlignment = Record.readInt(); - E->UsualArrayDeleteWantsSize = Record.readInt(); + + bool IsArray = Record.readInt(); + bool HasInit = Record.readInt(); unsigned NumPlacementArgs = Record.readInt(); - E->StoredInitializationStyle = Record.readInt(); + bool IsParenTypeId = Record.readInt(); + + E->CXXNewExprBits.IsGlobalNew = Record.readInt(); + E->CXXNewExprBits.ShouldPassAlignment = Record.readInt(); + E->CXXNewExprBits.UsualArrayDeleteWantsSize = Record.readInt(); + E->CXXNewExprBits.StoredInitializationStyle = Record.readInt(); + + assert((IsArray == E->isArray()) && "Wrong IsArray!"); + assert((HasInit == E->hasInitializer()) && "Wrong HasInit!"); + assert((NumPlacementArgs == E->getNumPlacementArgs()) && + "Wrong NumPlacementArgs!"); + assert((IsParenTypeId == E->isParenTypeId()) && "Wrong IsParenTypeId!"); + (void)IsArray; + (void)HasInit; + (void)NumPlacementArgs; + E->setOperatorNew(ReadDeclAs()); E->setOperatorDelete(ReadDeclAs()); E->AllocatedTypeInfo = GetTypeSourceInfo(); - E->TypeIdParens = ReadSourceRange(); + if (IsParenTypeId) + E->getTrailingObjects()[0] = ReadSourceRange(); E->Range = ReadSourceRange(); E->DirectInitRange = ReadSourceRange(); - E->AllocateArgsArray(Record.getContext(), isArray, NumPlacementArgs, - E->StoredInitializationStyle != 0); - // Install all the subexpressions. - for (CXXNewExpr::raw_arg_iterator I = E->raw_arg_begin(),e = E->raw_arg_end(); - I != e; ++I) + for (CXXNewExpr::raw_arg_iterator I = E->raw_arg_begin(), N = E->raw_arg_end(); + I != N; ++I) *I = Record.readSubStmt(); } @@ -3189,7 +3201,12 @@ break; case EXPR_CXX_NEW: - S = new (Context) CXXNewExpr(Empty); + S = CXXNewExpr::CreateEmpty( + Context, + /*IsArray=*/Record[ASTStmtReader::NumExprFields + 0], + /*HasInit=*/Record[ASTStmtReader::NumExprFields + 1], + /*NumPlacementArgs=*/Record[ASTStmtReader::NumExprFields + 2], + /*IsParenTypeId=*/Record[ASTStmtReader::NumExprFields + 3]); break; case EXPR_CXX_DELETE: Index: lib/Serialization/ASTWriterStmt.cpp =================================================================== --- lib/Serialization/ASTWriterStmt.cpp +++ lib/Serialization/ASTWriterStmt.cpp @@ -1483,20 +1483,27 @@ void ASTStmtWriter::VisitCXXNewExpr(CXXNewExpr *E) { VisitExpr(E); - Record.push_back(E->isGlobalNew()); + Record.push_back(E->isArray()); + Record.push_back(E->hasInitializer()); + Record.push_back(E->getNumPlacementArgs()); + Record.push_back(E->isParenTypeId()); + + Record.push_back(E->isGlobalNew()); Record.push_back(E->passAlignment()); Record.push_back(E->doesUsualArrayDeleteWantSize()); - Record.push_back(E->getNumPlacementArgs()); - Record.push_back(E->StoredInitializationStyle); + Record.push_back(E->CXXNewExprBits.StoredInitializationStyle); + Record.AddDeclRef(E->getOperatorNew()); Record.AddDeclRef(E->getOperatorDelete()); Record.AddTypeSourceInfo(E->getAllocatedTypeSourceInfo()); - Record.AddSourceRange(E->getTypeIdParens()); + if (E->isParenTypeId()) + Record.AddSourceRange(E->getTypeIdParens()); Record.AddSourceRange(E->getSourceRange()); Record.AddSourceRange(E->getDirectInitRange()); - for (CXXNewExpr::arg_iterator I = E->raw_arg_begin(), e = E->raw_arg_end(); - I != e; ++I) + + for (CXXNewExpr::arg_iterator I = E->raw_arg_begin(), N = E->raw_arg_end(); + I != N; ++I) Record.AddStmt(*I); Code = serialization::EXPR_CXX_NEW;