summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorBruno Ricci <riccibrun@gmail.com>2019-01-07 15:04:45 +0000
committerBruno Ricci <riccibrun@gmail.com>2019-01-07 15:04:45 +0000
commit7eadfa4ba2821e7394224da7023128dc9b36eebd (patch)
tree6b1dbedb6e0174ca7ea7beb6707d658da5a7af09
parent4d27dbbf8ec35d8c58f80938a8383da37e9f3800 (diff)
[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
-rw-r--r--include/clang/AST/ExprCXX.h189
-rw-r--r--include/clang/AST/Stmt.h34
-rw-r--r--lib/AST/ASTImporter.cpp2
-rw-r--r--lib/AST/ExprCXX.cpp144
-rw-r--r--lib/CodeGen/CGExprCXX.cpp4
-rw-r--r--lib/Sema/SemaExprCXX.cpp10
-rw-r--r--lib/Serialization/ASTReaderStmt.cpp42
-rw-r--r--lib/Serialization/ASTWriterStmt.cpp19
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<CXXNewExpr, Stmt *, SourceRange> {
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<Stmt *>) 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<SourceRange>) 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<Expr*> 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<Expr *> 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<Expr *> 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<Expr>(SubExprs[0]) : nullptr;
+ return isArray()
+ ? cast<Expr>(getTrailingObjects<Stmt *>()[arraySizeOffset()])
+ : nullptr;
}
const Expr *getArraySize() const {
- return Array ? cast<Expr>(SubExprs[0]) : nullptr;
+ return isArray()
+ ? cast<Expr>(getTrailingObjects<Stmt *>()[arraySizeOffset()])
+ : nullptr;
}
- unsigned getNumPlacementArgs() const { return NumPlacementArgs; }
+ unsigned getNumPlacementArgs() const {
+ return CXXNewExprBits.NumPlacementArgs;
+ }
Expr **getPlacementArgs() {
- return reinterpret_cast<Expr **>(SubExprs + Array + hasInitializer());
+ return reinterpret_cast<Expr **>(getTrailingObjects<Stmt *>() +
+ 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<CXXNewExpr*>(this)->getPlacementArg(i);
+ const Expr *getPlacementArg(unsigned I) const {
+ return const_cast<CXXNewExpr *>(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<SourceRange>()[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<InitializationStyle>(StoredInitializationStyle-1);
+ return static_cast<InitializationStyle>(
+ CXXNewExprBits.StoredInitializationStyle - 1);
}
/// The initializer of this new-expression.
Expr *getInitializer() {
- return hasInitializer() ? cast<Expr>(SubExprs[Array]) : nullptr;
+ return hasInitializer()
+ ? cast<Expr>(getTrailingObjects<Stmt *>()[initExprOffset()])
+ : nullptr;
}
const Expr *getInitializer() const {
- return hasInitializer() ? cast<Expr>(SubExprs[Array]) : nullptr;
+ return hasInitializer()
+ ? cast<Expr>(getTrailingObjects<Stmt *>()[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<Stmt *>() + 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<Stmt *>() + 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<Stmt *>(); }
raw_arg_iterator raw_arg_end() {
- return SubExprs + Array + hasInitializer() + getNumPlacementArgs();
+ return raw_arg_begin() + numTrailingObjects(OverloadToken<Stmt *>());
+ }
+ const_arg_iterator raw_arg_begin() const {
+ return getTrailingObjects<Stmt *>();
}
- 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<Stmt *>());
}
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<Expr*> 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<Expr *> 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<Stmt *>()[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<Stmt *>()[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<Stmt *>()[placementNewArgsOffset() + I] =
+ PlacementArgs[I];
}
+ if (IsParenTypeId)
+ getTrailingObjects<SourceRange>()[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<Expr *> 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<Stmt *, SourceRange>(
+ 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<Stmt *, SourceRange>(
+ 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<FunctionProtoType>()
- ->isNothrow() &&
+bool CXXNewExpr::shouldNullCheckAllocation() const {
+ return getOperatorNew()
+ ->getType()
+ ->castAs<FunctionProtoType>()
+ ->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<FunctionDecl>());
E->setOperatorDelete(ReadDeclAs<FunctionDecl>());
E->AllocatedTypeInfo = GetTypeSourceInfo();
- E->TypeIdParens = ReadSourceRange();
+ if (IsParenTypeId)
+ E->getTrailingObjects<SourceRange>()[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;