From 7eadfa4ba2821e7394224da7023128dc9b36eebd Mon Sep 17 00:00:00 2001 From: Bruno Ricci Date: Mon, 7 Jan 2019 15:04:45 +0000 Subject: [PATCH] [AST] Store some data of CXXNewExpr as trailing objects Store the optional array size expression, optional initialization expression and optional placement new arguments in a trailing array. Additionally store the range for the parenthesized type-id in a trailing object if needed since in the vast majority of cases the type is not parenthesized (not a single new expression in the translation unit of SemaDecl.cpp has a parenthesized type-id). This saves 2 pointers per CXXNewExpr in all cases, and 2 pointers + 8 bytes per CXXNewExpr in the common case where the type is not parenthesized. Differential Revision: https://reviews.llvm.org/D56134 Reviewed By: rjmccall git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@350527 91177308-0d34-0410-b5e6-96231b3b80d8 --- include/clang/AST/ExprCXX.h | 189 ++++++++++++++++------------ include/clang/AST/Stmt.h | 34 +++++ lib/AST/ASTImporter.cpp | 2 +- lib/AST/ExprCXX.cpp | 144 +++++++++++++-------- lib/CodeGen/CGExprCXX.cpp | 4 +- lib/Sema/SemaExprCXX.cpp | 10 +- lib/Serialization/ASTReaderStmt.cpp | 42 +++++-- lib/Serialization/ASTWriterStmt.cpp | 19 ++- 8 files changed, 288 insertions(+), 156 deletions(-) diff --git a/include/clang/AST/ExprCXX.h b/include/clang/AST/ExprCXX.h index f7d5d13637..5155b6095e 100644 --- a/include/clang/AST/ExprCXX.h +++ b/include/clang/AST/ExprCXX.h @@ -1933,54 +1933,56 @@ public: /// 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 @@ public: 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 @@ public: /// 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 @@ public: /// 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 @@ public: } 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 diff --git a/include/clang/AST/Stmt.h b/include/clang/AST/Stmt.h index 4515d527a9..2f94faee2c 100644 --- a/include/clang/AST/Stmt.h +++ b/include/clang/AST/Stmt.h @@ -612,6 +612,39 @@ protected: 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 @@ protected: CXXThrowExprBitfields CXXThrowExprBits; CXXDefaultArgExprBitfields CXXDefaultArgExprBits; CXXDefaultInitExprBitfields CXXDefaultInitExprBits; + CXXNewExprBitfields CXXNewExprBits; CXXDeleteExprBitfields CXXDeleteExprBits; TypeTraitExprBitfields TypeTraitExprBits; DependentScopeDeclRefExprBitfields DependentScopeDeclRefExprBits; diff --git a/lib/AST/ASTImporter.cpp b/lib/AST/ASTImporter.cpp index 251d078635..44832557e9 100644 --- a/lib/AST/ASTImporter.cpp +++ b/lib/AST/ASTImporter.cpp @@ -6910,7 +6910,7 @@ ExpectedStmt ASTNodeImporter::VisitCXXNewExpr(CXXNewExpr *E) { 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(), diff --git a/lib/AST/ExprCXX.cpp b/lib/AST/ExprCXX.cpp index 7aa80c0392..4eb3d333bc 100644 --- a/lib/AST/ExprCXX.cpp +++ b/lib/AST/ExprCXX.cpp @@ -94,83 +94,127 @@ SourceLocation CXXScalarValueInitExpr::getBeginLoc() const { } // 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(); } diff --git a/lib/CodeGen/CGExprCXX.cpp b/lib/CodeGen/CGExprCXX.cpp index 2e0d4ca767..fabbb4ca54 100644 --- a/lib/CodeGen/CGExprCXX.cpp +++ b/lib/CodeGen/CGExprCXX.cpp @@ -1657,8 +1657,8 @@ llvm::Value *CodeGenFunction::EmitCXXNewExpr(const CXXNewExpr *E) { // 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; diff --git a/lib/Sema/SemaExprCXX.cpp b/lib/Sema/SemaExprCXX.cpp index 1c210d332e..e963058b73 100644 --- a/lib/Sema/SemaExprCXX.cpp +++ b/lib/Sema/SemaExprCXX.cpp @@ -2179,11 +2179,11 @@ Sema::BuildCXXNew(SourceRange Range, bool UseGlobal, } } - 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 diff --git a/lib/Serialization/ASTReaderStmt.cpp b/lib/Serialization/ASTReaderStmt.cpp index e789e20f57..80b987a662 100644 --- a/lib/Serialization/ASTReaderStmt.cpp +++ b/lib/Serialization/ASTReaderStmt.cpp @@ -1507,25 +1507,38 @@ void ASTStmtReader::VisitCXXScalarValueInitExpr(CXXScalarValueInitExpr *E) { 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 +3202,12 @@ Stmt *ASTReader::ReadStmtFromStream(ModuleFile &F) { break; case EXPR_CXX_NEW: - S = new (Context) CXXNewExpr(Empty); + S = CXXNewExpr::CreateEmpty( + Context, + /*IsArray=*/Record[ASTStmtReader::NumExprFields], + /*HasInit=*/Record[ASTStmtReader::NumExprFields + 1], + /*NumPlacementArgs=*/Record[ASTStmtReader::NumExprFields + 2], + /*IsParenTypeId=*/Record[ASTStmtReader::NumExprFields + 3]); break; case EXPR_CXX_DELETE: diff --git a/lib/Serialization/ASTWriterStmt.cpp b/lib/Serialization/ASTWriterStmt.cpp index 26a01706dc..14c3b3278e 100644 --- a/lib/Serialization/ASTWriterStmt.cpp +++ b/lib/Serialization/ASTWriterStmt.cpp @@ -1483,20 +1483,27 @@ void ASTStmtWriter::VisitCXXScalarValueInitExpr(CXXScalarValueInitExpr *E) { 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; -- 2.40.0