r350527 - [AST] Store some data of CXXNewExpr as trailing objects

Bruno Ricci via cfe-commits cfe-commits at lists.llvm.org
Mon Jan 7 07:04:45 PST 2019


Author: brunoricci
Date: Mon Jan  7 07:04:45 2019
New Revision: 350527

URL: http://llvm.org/viewvc/llvm-project?rev=350527&view=rev
Log:
[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


Modified:
    cfe/trunk/include/clang/AST/ExprCXX.h
    cfe/trunk/include/clang/AST/Stmt.h
    cfe/trunk/lib/AST/ASTImporter.cpp
    cfe/trunk/lib/AST/ExprCXX.cpp
    cfe/trunk/lib/CodeGen/CGExprCXX.cpp
    cfe/trunk/lib/Sema/SemaExprCXX.cpp
    cfe/trunk/lib/Serialization/ASTReaderStmt.cpp
    cfe/trunk/lib/Serialization/ASTWriterStmt.cpp

Modified: cfe/trunk/include/clang/AST/ExprCXX.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/ExprCXX.h?rev=350527&r1=350526&r2=350527&view=diff
==============================================================================
--- cfe/trunk/include/clang/AST/ExprCXX.h (original)
+++ cfe/trunk/include/clang/AST/ExprCXX.h Mon Jan  7 07:04:45 2019
@@ -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;
+  // 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();
+  }
 
-  /// Should the alignment be passed to the allocation function?
-  unsigned PassAlignment : 1;
+  unsigned numTrailingObjects(OverloadToken<Stmt *>) const {
+    return isArray() + hasInitializer() + getNumPlacementArgs();
+  }
 
-  /// If this is an array allocation, does the usual deallocation
-  /// function for the allocated type want to know the allocated size?
-  unsigned UsualArrayDeleteWantsSize : 1;
-
-  /// The number of placement new arguments.
-  unsigned NumPlacementArgs : 26;
-
-  /// 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

Modified: cfe/trunk/include/clang/AST/Stmt.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/Stmt.h?rev=350527&r1=350526&r2=350527&view=diff
==============================================================================
--- cfe/trunk/include/clang/AST/Stmt.h (original)
+++ cfe/trunk/include/clang/AST/Stmt.h Mon Jan  7 07:04:45 2019
@@ -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;

Modified: cfe/trunk/lib/AST/ASTImporter.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/ASTImporter.cpp?rev=350527&r1=350526&r2=350527&view=diff
==============================================================================
--- cfe/trunk/lib/AST/ASTImporter.cpp (original)
+++ cfe/trunk/lib/AST/ASTImporter.cpp Mon Jan  7 07:04:45 2019
@@ -6910,7 +6910,7 @@ ExpectedStmt ASTNodeImporter::VisitCXXNe
       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(),

Modified: cfe/trunk/lib/AST/ExprCXX.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/ExprCXX.cpp?rev=350527&r1=350526&r2=350527&view=diff
==============================================================================
--- cfe/trunk/lib/AST/ExprCXX.cpp (original)
+++ cfe/trunk/lib/AST/ExprCXX.cpp Mon Jan  7 07:04:45 2019
@@ -94,83 +94,127 @@ SourceLocation CXXScalarValueInitExpr::g
 }
 
 // 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())
-      ExprBits.InstantiationDependent = true;
+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->containsUnexpandedParameterPack())
+  if (ArraySize) {
+    if (ArraySize->isInstantiationDependent())
+      ExprBits.InstantiationDependent = true;
+    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;
-
-  unsigned TotalSize = Array + hasInitializer + NumPlacementArgs;
-  SubExprs = new (C) Stmt*[TotalSize];
+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);
+}
+
+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();
 }
 

Modified: cfe/trunk/lib/CodeGen/CGExprCXX.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CGExprCXX.cpp?rev=350527&r1=350526&r2=350527&view=diff
==============================================================================
--- cfe/trunk/lib/CodeGen/CGExprCXX.cpp (original)
+++ cfe/trunk/lib/CodeGen/CGExprCXX.cpp Mon Jan  7 07:04:45 2019
@@ -1657,8 +1657,8 @@ llvm::Value *CodeGenFunction::EmitCXXNew
   // 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;

Modified: cfe/trunk/lib/Sema/SemaExprCXX.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaExprCXX.cpp?rev=350527&r1=350526&r2=350527&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaExprCXX.cpp (original)
+++ cfe/trunk/lib/Sema/SemaExprCXX.cpp Mon Jan  7 07:04:45 2019
@@ -2179,11 +2179,11 @@ Sema::BuildCXXNew(SourceRange Range, boo
     }
   }
 
-  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

Modified: cfe/trunk/lib/Serialization/ASTReaderStmt.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Serialization/ASTReaderStmt.cpp?rev=350527&r1=350526&r2=350527&view=diff
==============================================================================
--- cfe/trunk/lib/Serialization/ASTReaderStmt.cpp (original)
+++ cfe/trunk/lib/Serialization/ASTReaderStmt.cpp Mon Jan  7 07:04:45 2019
@@ -1507,25 +1507,38 @@ void ASTStmtReader::VisitCXXScalarValueI
 
 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(Modu
       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:

Modified: cfe/trunk/lib/Serialization/ASTWriterStmt.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Serialization/ASTWriterStmt.cpp?rev=350527&r1=350526&r2=350527&view=diff
==============================================================================
--- cfe/trunk/lib/Serialization/ASTWriterStmt.cpp (original)
+++ cfe/trunk/lib/Serialization/ASTWriterStmt.cpp Mon Jan  7 07:04:45 2019
@@ -1483,20 +1483,27 @@ void ASTStmtWriter::VisitCXXScalarValueI
 
 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;




More information about the cfe-commits mailing list