Store inheritance paths after CastExprs instead of inside them.
This takes some trickery since CastExpr has subclasses (and indeed,
is abstract).

Also, smoosh the CastKind into the bitfield from Expr.

Drops two words of storage from Expr in the common case of expressions
which don't need inheritance paths.  Avoids a separate allocation and
another word of overhead in cases needing inheritance paths.  Also has
the advantage of not leaking memory, since destructors for AST nodes are
never run.



git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@110507 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/lib/AST/ASTImporter.cpp b/lib/AST/ASTImporter.cpp
index b5fa362..5e8586f 100644
--- a/lib/AST/ASTImporter.cpp
+++ b/lib/AST/ASTImporter.cpp
@@ -123,6 +123,8 @@
     Expr *VisitCompoundAssignOperator(CompoundAssignOperator *E);
     Expr *VisitImplicitCastExpr(ImplicitCastExpr *E);
     Expr *VisitCStyleCastExpr(CStyleCastExpr *E);
+
+    bool ImportCasePath(CastExpr *E, CXXCastPath &Path);
   };
 }
 
@@ -2886,6 +2888,13 @@
                                           Importer.Import(E->getOperatorLoc()));
 }
 
+bool ImportCastPath(CastExpr *E, CXXCastPath &Path) {
+  if (E->path_empty()) return false;
+
+  // TODO: import cast paths
+  return true;
+}
+
 Expr *ASTNodeImporter::VisitImplicitCastExpr(ImplicitCastExpr *E) {
   QualType T = Importer.Import(E->getType());
   if (T.isNull())
@@ -2894,13 +2903,13 @@
   Expr *SubExpr = Importer.Import(E->getSubExpr());
   if (!SubExpr)
     return 0;
-  
-  // FIXME: Initialize the base path.
-  assert(E->getBasePath().empty() && "FIXME: Must copy base path!");
-  CXXBaseSpecifierArray BasePath;
-  return new (Importer.getToContext()) ImplicitCastExpr(T, E->getCastKind(),
-                                                        SubExpr, BasePath,
-                                                        E->getCategory());
+
+  CXXCastPath BasePath;
+  if (ImportCastPath(E, BasePath))
+    return 0;
+
+  return ImplicitCastExpr::Create(Importer.getToContext(), T, E->getCastKind(),
+                                  SubExpr, &BasePath, E->getCategory());
 }
 
 Expr *ASTNodeImporter::VisitCStyleCastExpr(CStyleCastExpr *E) {
@@ -2916,13 +2925,14 @@
   if (!TInfo && E->getTypeInfoAsWritten())
     return 0;
   
-  // FIXME: Initialize the base path.
-  assert(E->getBasePath().empty() && "FIXME: Must copy base path!");
-  CXXBaseSpecifierArray BasePath;
-  return new (Importer.getToContext()) CStyleCastExpr(T, E->getCastKind(),
-                                                      SubExpr, BasePath, TInfo,
-                                            Importer.Import(E->getLParenLoc()),
-                                            Importer.Import(E->getRParenLoc()));
+  CXXCastPath BasePath;
+  if (ImportCastPath(E, BasePath))
+    return 0;
+
+  return CStyleCastExpr::Create(Importer.getToContext(), T, E->getCastKind(),
+                                SubExpr, &BasePath, TInfo,
+                                Importer.Import(E->getLParenLoc()),
+                                Importer.Import(E->getRParenLoc()));
 }
 
 ASTImporter::ASTImporter(Diagnostic &Diags,
diff --git a/lib/AST/Expr.cpp b/lib/AST/Expr.cpp
index 7642c0d..d85162a 100644
--- a/lib/AST/Expr.cpp
+++ b/lib/AST/Expr.cpp
@@ -747,6 +747,66 @@
   return SubExpr;
 }
 
+CXXBaseSpecifier **CastExpr::path_buffer() {
+  switch (getStmtClass()) {
+#define ABSTRACT_STMT(x)
+#define CASTEXPR(Type, Base) \
+  case Stmt::Type##Class: \
+    return reinterpret_cast<CXXBaseSpecifier**>(static_cast<Type*>(this)+1);
+#define STMT(Type, Base)
+#include "clang/AST/StmtNodes.inc"
+  default:
+    llvm_unreachable("non-cast expressions not possible here");
+    return 0;
+  }
+}
+
+void CastExpr::setCastPath(const CXXCastPath &Path) {
+  assert(Path.size() == path_size());
+  memcpy(path_buffer(), Path.data(), Path.size() * sizeof(CXXBaseSpecifier*));
+}
+
+ImplicitCastExpr *ImplicitCastExpr::Create(ASTContext &C, QualType T,
+                                           CastKind Kind, Expr *Operand,
+                                           const CXXCastPath *BasePath,
+                                           ResultCategory Cat) {
+  unsigned PathSize = (BasePath ? BasePath->size() : 0);
+  void *Buffer =
+    C.Allocate(sizeof(ImplicitCastExpr) + PathSize * sizeof(CXXBaseSpecifier*));
+  ImplicitCastExpr *E =
+    new (Buffer) ImplicitCastExpr(T, Kind, Operand, PathSize, Cat);
+  if (PathSize) E->setCastPath(*BasePath);
+  return E;
+}
+
+ImplicitCastExpr *ImplicitCastExpr::CreateEmpty(ASTContext &C,
+                                                unsigned PathSize) {
+  void *Buffer =
+    C.Allocate(sizeof(ImplicitCastExpr) + PathSize * sizeof(CXXBaseSpecifier*));
+  return new (Buffer) ImplicitCastExpr(EmptyShell(), PathSize);
+}
+
+
+CStyleCastExpr *CStyleCastExpr::Create(ASTContext &C, QualType T,
+                                       CastKind K, Expr *Op,
+                                       const CXXCastPath *BasePath,
+                                       TypeSourceInfo *WrittenTy,
+                                       SourceLocation L, SourceLocation R) {
+  unsigned PathSize = (BasePath ? BasePath->size() : 0);
+  void *Buffer =
+    C.Allocate(sizeof(CStyleCastExpr) + PathSize * sizeof(CXXBaseSpecifier*));
+  CStyleCastExpr *E =
+    new (Buffer) CStyleCastExpr(T, K, Op, PathSize, WrittenTy, L, R);
+  if (PathSize) E->setCastPath(*BasePath);
+  return E;
+}
+
+CStyleCastExpr *CStyleCastExpr::CreateEmpty(ASTContext &C, unsigned PathSize) {
+  void *Buffer =
+    C.Allocate(sizeof(CStyleCastExpr) + PathSize * sizeof(CXXBaseSpecifier*));
+  return new (Buffer) CStyleCastExpr(EmptyShell(), PathSize);
+}
+
 /// getOpcodeStr - Turn an Opcode enum value into the punctuation char it
 /// corresponds to, e.g. "<<=".
 const char *BinaryOperator::getOpcodeStr(Opcode Op) {
diff --git a/lib/AST/ExprCXX.cpp b/lib/AST/ExprCXX.cpp
index 7c2a893..4907833 100644
--- a/lib/AST/ExprCXX.cpp
+++ b/lib/AST/ExprCXX.cpp
@@ -460,6 +460,100 @@
   }
 }
 
+CXXStaticCastExpr *CXXStaticCastExpr::Create(ASTContext &C, QualType T,
+                                             CastKind K, Expr *Op,
+                                             const CXXCastPath *BasePath,
+                                             TypeSourceInfo *WrittenTy,
+                                             SourceLocation L) {
+  unsigned PathSize = (BasePath ? BasePath->size() : 0);
+  void *Buffer = C.Allocate(sizeof(CXXStaticCastExpr)
+                            + PathSize * sizeof(CXXBaseSpecifier*));
+  CXXStaticCastExpr *E =
+    new (Buffer) CXXStaticCastExpr(T, K, Op, PathSize, WrittenTy, L);
+  if (PathSize) E->setCastPath(*BasePath);
+  return E;
+}
+
+CXXStaticCastExpr *CXXStaticCastExpr::CreateEmpty(ASTContext &C,
+                                                  unsigned PathSize) {
+  void *Buffer =
+    C.Allocate(sizeof(CXXStaticCastExpr) + PathSize * sizeof(CXXBaseSpecifier*));
+  return new (Buffer) CXXStaticCastExpr(EmptyShell(), PathSize);
+}
+
+CXXDynamicCastExpr *CXXDynamicCastExpr::Create(ASTContext &C, QualType T,
+                                               CastKind K, Expr *Op,
+                                               const CXXCastPath *BasePath,
+                                               TypeSourceInfo *WrittenTy,
+                                               SourceLocation L) {
+  unsigned PathSize = (BasePath ? BasePath->size() : 0);
+  void *Buffer = C.Allocate(sizeof(CXXDynamicCastExpr)
+                            + PathSize * sizeof(CXXBaseSpecifier*));
+  CXXDynamicCastExpr *E =
+    new (Buffer) CXXDynamicCastExpr(T, K, Op, PathSize, WrittenTy, L);
+  if (PathSize) E->setCastPath(*BasePath);
+  return E;
+}
+
+CXXDynamicCastExpr *CXXDynamicCastExpr::CreateEmpty(ASTContext &C,
+                                                    unsigned PathSize) {
+  void *Buffer =
+    C.Allocate(sizeof(CXXDynamicCastExpr) + PathSize * sizeof(CXXBaseSpecifier*));
+  return new (Buffer) CXXDynamicCastExpr(EmptyShell(), PathSize);
+}
+
+CXXReinterpretCastExpr *
+CXXReinterpretCastExpr::Create(ASTContext &C, QualType T, CastKind K, Expr *Op,
+                               const CXXCastPath *BasePath,
+                               TypeSourceInfo *WrittenTy, SourceLocation L) {
+  unsigned PathSize = (BasePath ? BasePath->size() : 0);
+  void *Buffer =
+    C.Allocate(sizeof(CXXReinterpretCastExpr) + PathSize * sizeof(CXXBaseSpecifier*));
+  CXXReinterpretCastExpr *E =
+    new (Buffer) CXXReinterpretCastExpr(T, K, Op, PathSize, WrittenTy, L);
+  if (PathSize) E->setCastPath(*BasePath);
+  return E;
+}
+
+CXXReinterpretCastExpr *
+CXXReinterpretCastExpr::CreateEmpty(ASTContext &C, unsigned PathSize) {
+  void *Buffer = C.Allocate(sizeof(CXXReinterpretCastExpr)
+                            + PathSize * sizeof(CXXBaseSpecifier*));
+  return new (Buffer) CXXReinterpretCastExpr(EmptyShell(), PathSize);
+}
+
+CXXConstCastExpr *CXXConstCastExpr::Create(ASTContext &C, QualType T, Expr *Op,
+                                           TypeSourceInfo *WrittenTy,
+                                           SourceLocation L) {
+  return new (C) CXXConstCastExpr(T, Op, WrittenTy, L);
+}
+
+CXXConstCastExpr *CXXConstCastExpr::CreateEmpty(ASTContext &C) {
+  return new (C) CXXConstCastExpr(EmptyShell());
+}
+
+CXXFunctionalCastExpr *
+CXXFunctionalCastExpr::Create(ASTContext &C, QualType T,
+                              TypeSourceInfo *Written, SourceLocation L,
+                              CastKind K, Expr *Op, const CXXCastPath *BasePath,
+                               SourceLocation R) {
+  unsigned PathSize = (BasePath ? BasePath->size() : 0);
+  void *Buffer = C.Allocate(sizeof(CXXFunctionalCastExpr)
+                            + PathSize * sizeof(CXXBaseSpecifier*));
+  CXXFunctionalCastExpr *E =
+    new (Buffer) CXXFunctionalCastExpr(T, Written, L, K, Op, PathSize, R);
+  if (PathSize) E->setCastPath(*BasePath);
+  return E;
+}
+
+CXXFunctionalCastExpr *
+CXXFunctionalCastExpr::CreateEmpty(ASTContext &C, unsigned PathSize) {
+  void *Buffer = C.Allocate(sizeof(CXXFunctionalCastExpr)
+                            + PathSize * sizeof(CXXBaseSpecifier*));
+  return new (Buffer) CXXFunctionalCastExpr(EmptyShell(), PathSize);
+}
+
+
 CXXDefaultArgExpr *
 CXXDefaultArgExpr::Create(ASTContext &C, SourceLocation Loc, 
                           ParmVarDecl *Param, Expr *SubExpr) {
diff --git a/lib/AST/StmtDumper.cpp b/lib/AST/StmtDumper.cpp
index c878a55..f8f1495 100644
--- a/lib/AST/StmtDumper.cpp
+++ b/lib/AST/StmtDumper.cpp
@@ -308,13 +308,13 @@
 }
 
 static void DumpBasePath(llvm::raw_ostream &OS, CastExpr *Node) {
-  if (Node->getBasePath().empty())
+  if (Node->path_empty())
     return;
 
   OS << " (";
   bool First = true;
-  for (CXXBaseSpecifierArray::iterator I = Node->getBasePath().begin(),
-       E = Node->getBasePath().end(); I != E; ++I) {
+  for (CastExpr::path_iterator
+         I = Node->path_begin(), E = Node->path_end(); I != E; ++I) {
     const CXXBaseSpecifier *Base = *I;
     if (!First)
       OS << " -> ";