[cfe-commits] r144263 - in /cfe/trunk: include/clang/AST/Decl.h include/clang/AST/ExprCXX.h include/clang/AST/Stmt.h include/clang/Sema/Sema.h lib/AST/Decl.cpp lib/AST/ExprCXX.cpp lib/AST/StmtDumper.cpp lib/Sema/Sema.cpp lib/Sema/SemaChecking.cpp lib/Sema/SemaDecl.cpp lib/Sema/SemaExpr.cpp lib/Sema/SemaExprCXX.cpp lib/Serialization/ASTReaderStmt.cpp lib/Serialization/ASTWriterStmt.cpp

John McCall rjmccall at apple.com
Wed Nov 9 21:35:25 PST 2011


Author: rjmccall
Date: Wed Nov  9 23:35:25 2011
New Revision: 144263

URL: http://llvm.org/viewvc/llvm-project?rev=144263&view=rev
Log:
There's no good reason to track temporaries in ExprWithCleanups,
but it is sometimes useful to track blocks.  Do so.  Also
optimize the storage of these expressions.


Modified:
    cfe/trunk/include/clang/AST/Decl.h
    cfe/trunk/include/clang/AST/ExprCXX.h
    cfe/trunk/include/clang/AST/Stmt.h
    cfe/trunk/include/clang/Sema/Sema.h
    cfe/trunk/lib/AST/Decl.cpp
    cfe/trunk/lib/AST/ExprCXX.cpp
    cfe/trunk/lib/AST/StmtDumper.cpp
    cfe/trunk/lib/Sema/Sema.cpp
    cfe/trunk/lib/Sema/SemaChecking.cpp
    cfe/trunk/lib/Sema/SemaDecl.cpp
    cfe/trunk/lib/Sema/SemaExpr.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/Decl.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/Decl.h?rev=144263&r1=144262&r2=144263&view=diff
==============================================================================
--- cfe/trunk/include/clang/AST/Decl.h (original)
+++ cfe/trunk/include/clang/AST/Decl.h Wed Nov  9 23:35:25 2011
@@ -1285,12 +1285,6 @@
     Init = reinterpret_cast<Stmt *>(defarg);
   }
 
-  unsigned getNumDefaultArgTemporaries() const;
-  CXXTemporary *getDefaultArgTemporary(unsigned i);
-  const CXXTemporary *getDefaultArgTemporary(unsigned i) const {
-    return const_cast<ParmVarDecl *>(this)->getDefaultArgTemporary(i);
-  }
-
   /// \brief Retrieve the source range that covers the entire default
   /// argument.
   SourceRange getDefaultArgRange() const;

Modified: cfe/trunk/include/clang/AST/ExprCXX.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/ExprCXX.h?rev=144263&r1=144262&r2=144263&view=diff
==============================================================================
--- cfe/trunk/include/clang/AST/ExprCXX.h (original)
+++ cfe/trunk/include/clang/AST/ExprCXX.h Wed Nov  9 23:35:25 2011
@@ -2179,43 +2179,58 @@
 /// Represents an expression --- generally a full-expression --- which
 /// introduces cleanups to be run at the end of the sub-expression's
 /// evaluation.  The most common source of expression-introduced
-/// cleanups is temporary objects in C++, but several other C++
-/// expressions can create cleanups.
+/// cleanups is temporary objects in C++, but several other kinds of
+/// expressions can create cleanups, including basically every
+/// call in ARC that returns an Objective-C pointer.
+///
+/// This expression also tracks whether the sub-expression contains a
+/// potentially-evaluated block literal.  The lifetime of a block
+/// literal is the extent of the enclosing scope.
 class ExprWithCleanups : public Expr {
+public:
+  /// The type of objects that are kept in the cleanup.
+  /// It's useful to remember the set of blocks;  we could also
+  /// remember the set of temporaries, but there's currently
+  /// no need.
+  typedef BlockDecl *CleanupObject;
+
+private:
   Stmt *SubExpr;
 
-  CXXTemporary **Temps;
-  unsigned NumTemps;
+  ExprWithCleanups(EmptyShell, unsigned NumObjects);
+  ExprWithCleanups(Expr *SubExpr, ArrayRef<CleanupObject> Objects);
 
-  ExprWithCleanups(ASTContext &C, Expr *SubExpr,
-                   CXXTemporary **Temps, unsigned NumTemps);
+  CleanupObject *getObjectsBuffer() {
+    return reinterpret_cast<CleanupObject*>(this + 1);
+  }
+  const CleanupObject *getObjectsBuffer() const {
+    return reinterpret_cast<const CleanupObject*>(this + 1);
+  }
+  friend class ASTStmtReader;
 
 public:
-  ExprWithCleanups(EmptyShell Empty)
-    : Expr(ExprWithCleanupsClass, Empty),
-      SubExpr(0), Temps(0), NumTemps(0) {}
+  static ExprWithCleanups *Create(ASTContext &C, EmptyShell empty,
+                                  unsigned numObjects);
 
-  static ExprWithCleanups *Create(ASTContext &C, Expr *SubExpr,
-                                        CXXTemporary **Temps,
-                                        unsigned NumTemps);
+  static ExprWithCleanups *Create(ASTContext &C, Expr *subexpr,
+                                  ArrayRef<CleanupObject> objects);
 
-  unsigned getNumTemporaries() const { return NumTemps; }
-  void setNumTemporaries(ASTContext &C, unsigned N);
-
-  CXXTemporary *getTemporary(unsigned i) {
-    assert(i < NumTemps && "Index out of range");
-    return Temps[i];
-  }
-  const CXXTemporary *getTemporary(unsigned i) const {
-    return const_cast<ExprWithCleanups*>(this)->getTemporary(i);
+  ArrayRef<CleanupObject> getObjects() const {
+    return ArrayRef<CleanupObject>(getObjectsBuffer(), getNumObjects());
   }
-  void setTemporary(unsigned i, CXXTemporary *T) {
-    assert(i < NumTemps && "Index out of range");
-    Temps[i] = T;
+
+  unsigned getNumObjects() const { return ExprWithCleanupsBits.NumObjects; }
+
+  CleanupObject getObject(unsigned i) const {
+    assert(i < getNumObjects() && "Index out of range");
+    return getObjects()[i];
   }
 
   Expr *getSubExpr() { return cast<Expr>(SubExpr); }
   const Expr *getSubExpr() const { return cast<Expr>(SubExpr); }
+
+  /// setSubExpr - As with any mutator of the AST, be very careful
+  /// when modifying an existing AST to preserve its invariants.
   void setSubExpr(Expr *E) { SubExpr = E; }
 
   SourceRange getSourceRange() const {

Modified: cfe/trunk/include/clang/AST/Stmt.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/Stmt.h?rev=144263&r1=144262&r2=144263&view=diff
==============================================================================
--- cfe/trunk/include/clang/AST/Stmt.h (original)
+++ cfe/trunk/include/clang/AST/Stmt.h Wed Nov  9 23:35:25 2011
@@ -185,6 +185,15 @@
     unsigned NumPreArgs : 1;
   };
 
+  class ExprWithCleanupsBitfields {
+    friend class ExprWithCleanups;
+    friend class ASTStmtReader; // deserialization
+
+    unsigned : NumExprBits;
+
+    unsigned NumObjects : 32 - NumExprBits;
+  };
+
   class PseudoObjectExprBitfields {
     friend class PseudoObjectExpr;
     friend class ASTStmtReader; // deserialization
@@ -214,6 +223,7 @@
     DeclRefExprBitfields DeclRefExprBits;
     CastExprBitfields CastExprBits;
     CallExprBitfields CallExprBits;
+    ExprWithCleanupsBitfields ExprWithCleanupsBits;
     PseudoObjectExprBitfields PseudoObjectExprBits;
     ObjCIndirectCopyRestoreExprBitfields ObjCIndirectCopyRestoreExprBits;
   };

Modified: cfe/trunk/include/clang/Sema/Sema.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Sema/Sema.h?rev=144263&r1=144262&r2=144263&view=diff
==============================================================================
--- cfe/trunk/include/clang/Sema/Sema.h (original)
+++ cfe/trunk/include/clang/Sema/Sema.h Wed Nov  9 23:35:25 2011
@@ -223,6 +223,11 @@
   /// requires cleanups to be run at its conclusion.
   bool ExprNeedsCleanups;
 
+  /// ExprCleanupObjects - This is the stack of objects requiring
+  /// cleanup that are created by the current full expression.  The
+  /// element type here is ExprWithCleanups::Object.
+  SmallVector<BlockDecl*, 8> ExprCleanupObjects;
+
   /// \brief Stack containing information about each of the nested
   /// function, block, and method scopes that are currently active.
   ///
@@ -231,10 +236,6 @@
   /// that's used to parse every top-level function.
   SmallVector<sema::FunctionScopeInfo *, 4> FunctionScopes;
 
-  /// ExprTemporaries - This is the stack of temporaries that are created by
-  /// the current full expression.
-  SmallVector<CXXTemporary*, 8> ExprTemporaries;
-
   typedef LazyVector<TypedefNameDecl *, ExternalSemaSource,
                      &ExternalSemaSource::ReadExtVectorDecls, 2, 2>
     ExtVectorDeclsType;
@@ -547,9 +548,9 @@
     /// \brief Whether the enclosing context needed a cleanup.
     bool ParentNeedsCleanups;
 
-    /// \brief The number of temporaries that were active when we
-    /// entered this expression evaluation context.
-    unsigned NumTemporaries;
+    /// \brief The number of active cleanup objects when we entered
+    /// this expression evaluation context.
+    unsigned NumCleanupObjects;
 
     /// \brief The set of declarations referenced within a
     /// potentially potentially-evaluated context.
@@ -565,10 +566,10 @@
     PotentiallyEmittedDiagnostics *PotentiallyDiagnosed;
 
     ExpressionEvaluationContextRecord(ExpressionEvaluationContext Context,
-                                      unsigned NumTemporaries,
+                                      unsigned NumCleanupObjects,
                                       bool ParentNeedsCleanups)
       : Context(Context), ParentNeedsCleanups(ParentNeedsCleanups),
-        NumTemporaries(NumTemporaries),
+        NumCleanupObjects(NumCleanupObjects),
         PotentiallyReferenced(0), PotentiallyDiagnosed(0) { }
 
     void addReferencedDecl(SourceLocation Loc, Decl *Decl) {

Modified: cfe/trunk/lib/AST/Decl.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/Decl.cpp?rev=144263&r1=144262&r2=144263&view=diff
==============================================================================
--- cfe/trunk/lib/AST/Decl.cpp (original)
+++ cfe/trunk/lib/AST/Decl.cpp Wed Nov  9 23:35:25 2011
@@ -1412,21 +1412,6 @@
   return Arg;
 }
 
-unsigned ParmVarDecl::getNumDefaultArgTemporaries() const {
-  if (const ExprWithCleanups *E = dyn_cast<ExprWithCleanups>(getInit()))
-    return E->getNumTemporaries();
-
-  return 0;
-}
-
-CXXTemporary *ParmVarDecl::getDefaultArgTemporary(unsigned i) {
-  assert(getNumDefaultArgTemporaries() && 
-         "Default arguments does not have any temporaries!");
-
-  ExprWithCleanups *E = cast<ExprWithCleanups>(getInit());
-  return E->getTemporary(i);
-}
-
 SourceRange ParmVarDecl::getDefaultArgRange() const {
   if (const Expr *E = getInit())
     return E->getSourceRange();

Modified: cfe/trunk/lib/AST/ExprCXX.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/ExprCXX.cpp?rev=144263&r1=144262&r2=144263&view=diff
==============================================================================
--- cfe/trunk/lib/AST/ExprCXX.cpp (original)
+++ cfe/trunk/lib/AST/ExprCXX.cpp Wed Nov  9 23:35:25 2011
@@ -695,35 +695,37 @@
   }
 }
 
-ExprWithCleanups::ExprWithCleanups(ASTContext &C,
-                                   Expr *subexpr,
-                                   CXXTemporary **temps,
-                                   unsigned numtemps)
+ExprWithCleanups::ExprWithCleanups(Expr *subexpr,
+                                   ArrayRef<CleanupObject> objects)
   : Expr(ExprWithCleanupsClass, subexpr->getType(),
          subexpr->getValueKind(), subexpr->getObjectKind(),
          subexpr->isTypeDependent(), subexpr->isValueDependent(),
          subexpr->isInstantiationDependent(),
          subexpr->containsUnexpandedParameterPack()),
-    SubExpr(subexpr), Temps(0), NumTemps(0) {
-  if (numtemps) {
-    setNumTemporaries(C, numtemps);
-    for (unsigned i = 0; i != numtemps; ++i)
-      Temps[i] = temps[i];
-  }
-}
-
-void ExprWithCleanups::setNumTemporaries(ASTContext &C, unsigned N) {
-  assert(Temps == 0 && "Cannot resize with this");
-  NumTemps = N;
-  Temps = new (C) CXXTemporary*[NumTemps];
-}
-
-
-ExprWithCleanups *ExprWithCleanups::Create(ASTContext &C,
-                                           Expr *SubExpr,
-                                           CXXTemporary **Temps,
-                                           unsigned NumTemps) {
-  return new (C) ExprWithCleanups(C, SubExpr, Temps, NumTemps);
+    SubExpr(subexpr) {
+  ExprWithCleanupsBits.NumObjects = objects.size();
+  for (unsigned i = 0, e = objects.size(); i != e; ++i)
+    getObjectsBuffer()[i] = objects[i];
+}
+
+ExprWithCleanups *ExprWithCleanups::Create(ASTContext &C, Expr *subexpr,
+                                           ArrayRef<CleanupObject> objects) {
+  size_t size = sizeof(ExprWithCleanups)
+              + objects.size() * sizeof(CleanupObject);
+  void *buffer = C.Allocate(size, llvm::alignOf<ExprWithCleanups>());
+  return new (buffer) ExprWithCleanups(subexpr, objects);
+}
+
+ExprWithCleanups::ExprWithCleanups(EmptyShell empty, unsigned numObjects)
+  : Expr(ExprWithCleanupsClass, empty) {
+  ExprWithCleanupsBits.NumObjects = numObjects;
+}
+
+ExprWithCleanups *ExprWithCleanups::Create(ASTContext &C, EmptyShell empty,
+                                           unsigned numObjects) {
+  size_t size = sizeof(ExprWithCleanups) + numObjects * sizeof(CleanupObject);
+  void *buffer = C.Allocate(size, llvm::alignOf<ExprWithCleanups>());
+  return new (buffer) ExprWithCleanups(empty, numObjects);
 }
 
 CXXUnresolvedConstructExpr::CXXUnresolvedConstructExpr(TypeSourceInfo *Type,

Modified: cfe/trunk/lib/AST/StmtDumper.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/StmtDumper.cpp?rev=144263&r1=144262&r2=144263&view=diff
==============================================================================
--- cfe/trunk/lib/AST/StmtDumper.cpp (original)
+++ cfe/trunk/lib/AST/StmtDumper.cpp Wed Nov  9 23:35:25 2011
@@ -590,10 +590,12 @@
 void StmtDumper::VisitExprWithCleanups(ExprWithCleanups *Node) {
   DumpExpr(Node);
   ++IndentLevel;
-  for (unsigned i = 0, e = Node->getNumTemporaries(); i != e; ++i) {
+  for (unsigned i = 0, e = Node->getNumObjects(); i != e; ++i) {
     OS << "\n";
     Indent();
-    DumpCXXTemporary(Node->getTemporary(i));
+    OS << "(cleanup ";
+    DumpDeclRef(Node->getObject(i));
+    OS << ")";
   }
   --IndentLevel;
 }

Modified: cfe/trunk/lib/Sema/Sema.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/Sema.cpp?rev=144263&r1=144262&r2=144263&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/Sema.cpp (original)
+++ cfe/trunk/lib/Sema/Sema.cpp Wed Nov  9 23:35:25 2011
@@ -97,7 +97,7 @@
     CollectStats(false), ExternalSource(0), CodeCompleter(CodeCompleter),
     CurContext(0), OriginalLexicalContext(0),
     PackContext(0), MSStructPragmaOn(false), VisContext(0),
-    ExprNeedsCleanups(0), LateTemplateParser(0), OpaqueParser(0),
+    ExprNeedsCleanups(false), LateTemplateParser(0), OpaqueParser(0),
     IdResolver(pp), CXXTypeInfoDecl(0), MSVCGuidDecl(0),
     GlobalNewDeleteDeclared(false), 
     ObjCShouldCallSuperDealloc(false),

Modified: cfe/trunk/lib/Sema/SemaChecking.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaChecking.cpp?rev=144263&r1=144262&r2=144263&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaChecking.cpp (original)
+++ cfe/trunk/lib/Sema/SemaChecking.cpp Wed Nov  9 23:35:25 2011
@@ -2676,6 +2676,9 @@
   case Stmt::AddrLabelExprClass:
     return E; // address of label.
 
+  case Stmt::ExprWithCleanupsClass:
+    return EvalAddr(cast<ExprWithCleanups>(E)->getSubExpr(), refVars);
+
   // For casts, we need to handle conversions from arrays to
   // pointer values, and pointer-to-pointer conversions.
   case Stmt::ImplicitCastExprClass:
@@ -2752,6 +2755,9 @@
     return NULL;
   }
 
+  case Stmt::ExprWithCleanupsClass:
+    return EvalVal(cast<ExprWithCleanups>(E)->getSubExpr(), refVars);
+
   case Stmt::DeclRefExprClass: {
     // When we hit a DeclRefExpr we are looking at code that refers to a
     // variable's name. If it's not a reference variable we check if it has

Modified: cfe/trunk/lib/Sema/SemaDecl.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaDecl.cpp?rev=144263&r1=144262&r2=144263&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaDecl.cpp (original)
+++ cfe/trunk/lib/Sema/SemaDecl.cpp Wed Nov  9 23:35:25 2011
@@ -7190,8 +7190,7 @@
     // deletion in some later function.
     if (PP.getDiagnostics().hasErrorOccurred() ||
         PP.getDiagnostics().getSuppressAllDiagnostics()) {
-      ExprTemporaries.clear();
-      ExprNeedsCleanups = false;
+      DiscardCleanupsInEvaluationContext();
     } else if (!isa<FunctionTemplateDecl>(dcl)) {
       // Since the body is valid, issue any analysis-based warnings that are
       // enabled.
@@ -7202,7 +7201,7 @@
         !CheckConstexprFunctionBody(FD, Body))
       FD->setInvalidDecl();
 
-    assert(ExprTemporaries.empty() && "Leftover temporaries in function");
+    assert(ExprCleanupObjects.empty() && "Leftover temporaries in function");
     assert(!ExprNeedsCleanups && "Unaccounted cleanups in function");
   }
   
@@ -7215,8 +7214,7 @@
   // been leftover. This ensures that these temporaries won't be picked up for
   // deletion in some later function.
   if (getDiagnostics().hasErrorOccurred()) {
-    ExprTemporaries.clear();
-    ExprNeedsCleanups = false;
+    DiscardCleanupsInEvaluationContext();
   }
 
   return dcl;

Modified: cfe/trunk/lib/Sema/SemaExpr.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaExpr.cpp?rev=144263&r1=144262&r2=144263&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaExpr.cpp (original)
+++ cfe/trunk/lib/Sema/SemaExpr.cpp Wed Nov  9 23:35:25 2011
@@ -3291,12 +3291,18 @@
   // be properly destroyed.
   // FIXME: We should really be rebuilding the default argument with new
   // bound temporaries; see the comment in PR5810.
-  for (unsigned i = 0, e = Param->getNumDefaultArgTemporaries(); i != e; ++i) {
-    CXXTemporary *Temporary = Param->getDefaultArgTemporary(i);
-    MarkDeclarationReferenced(Param->getDefaultArg()->getLocStart(), 
-                    const_cast<CXXDestructorDecl*>(Temporary->getDestructor()));
-    ExprTemporaries.push_back(Temporary);
+  // We don't need to do that with block decls, though, because
+  // blocks in default argument expression can never capture anything.
+  if (isa<ExprWithCleanups>(Param->getInit())) {
+    // Set the "needs cleanups" bit regardless of whether there are
+    // any explicit objects.
     ExprNeedsCleanups = true;
+
+    // Append all the objects to the cleanup list.  Right now, this
+    // should always be a no-op, because blocks in default argument
+    // expressions should never be able to capture anything.
+    assert(!cast<ExprWithCleanups>(Param->getInit())->getNumObjects() &&
+           "default argument expression has capturing blocks?");
   }
 
   // We already type-checked the argument, so we know it works. 
@@ -8828,6 +8834,13 @@
   const AnalysisBasedWarnings::Policy &WP = AnalysisWarnings.getDefaultPolicy();
   PopFunctionOrBlockScope(&WP, Result->getBlockDecl(), Result);
 
+  // If the block isn't obviously global, i.e. it captures anything at
+  // all, mark this full-expression as needing a cleanup.
+  if (Result->getBlockDecl()->hasCaptures()) {
+    ExprCleanupObjects.push_back(Result->getBlockDecl());
+    ExprNeedsCleanups = true;
+  }
+
   return Owned(Result);
 }
 
@@ -9158,7 +9171,7 @@
 Sema::PushExpressionEvaluationContext(ExpressionEvaluationContext NewContext) {
   ExprEvalContexts.push_back(
              ExpressionEvaluationContextRecord(NewContext,
-                                               ExprTemporaries.size(),
+                                               ExprCleanupObjects.size(),
                                                ExprNeedsCleanups));
   ExprNeedsCleanups = false;
 }
@@ -9195,8 +9208,8 @@
   // the expression in that context: they aren't relevant because they
   // will never be constructed.
   if (Rec.Context == Unevaluated) {
-    ExprTemporaries.erase(ExprTemporaries.begin() + Rec.NumTemporaries,
-                          ExprTemporaries.end());
+    ExprCleanupObjects.erase(ExprCleanupObjects.begin() + Rec.NumCleanupObjects,
+                             ExprCleanupObjects.end());
     ExprNeedsCleanups = Rec.ParentNeedsCleanups;
 
   // Otherwise, merge the contexts together.
@@ -9209,9 +9222,9 @@
 }
 
 void Sema::DiscardCleanupsInEvaluationContext() {
-  ExprTemporaries.erase(
-              ExprTemporaries.begin() + ExprEvalContexts.back().NumTemporaries,
-              ExprTemporaries.end());
+  ExprCleanupObjects.erase(
+         ExprCleanupObjects.begin() + ExprEvalContexts.back().NumCleanupObjects,
+         ExprCleanupObjects.end());
   ExprNeedsCleanups = false;
 }
 
@@ -9454,6 +9467,12 @@
       Inherited::VisitMemberExpr(E);
     }
     
+    void VisitCXXBindTemporaryExpr(CXXBindTemporaryExpr *E) {
+      S.MarkDeclarationReferenced(E->getLocStart(),
+            const_cast<CXXDestructorDecl*>(E->getTemporary()->getDestructor()));
+      Visit(E->getSubExpr());
+    }
+    
     void VisitCXXNewExpr(CXXNewExpr *E) {
       if (E->getConstructor())
         S.MarkDeclarationReferenced(E->getLocStart(), E->getConstructor());

Modified: cfe/trunk/lib/Sema/SemaExprCXX.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaExprCXX.cpp?rev=144263&r1=144262&r2=144263&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaExprCXX.cpp (original)
+++ cfe/trunk/lib/Sema/SemaExprCXX.cpp Wed Nov  9 23:35:25 2011
@@ -4122,37 +4122,37 @@
                           PDiag(diag::err_access_dtor_temp)
                             << E->getType());
 
-    ExprTemporaries.push_back(Temp);
+    // We need a cleanup, but we don't need to remember the temporary.
     ExprNeedsCleanups = true;
   }
   return Owned(CXXBindTemporaryExpr::Create(Context, Temp, E));
 }
 
+ExprResult
+Sema::MaybeCreateExprWithCleanups(ExprResult SubExpr) {
+  if (SubExpr.isInvalid())
+    return ExprError();
+
+  return Owned(MaybeCreateExprWithCleanups(SubExpr.take()));
+}
+
 Expr *Sema::MaybeCreateExprWithCleanups(Expr *SubExpr) {
   assert(SubExpr && "sub expression can't be null!");
 
-  unsigned FirstTemporary = ExprEvalContexts.back().NumTemporaries;
-  assert(ExprTemporaries.size() >= FirstTemporary);
-  assert(ExprNeedsCleanups || ExprTemporaries.size() == FirstTemporary);
+  unsigned FirstCleanup = ExprEvalContexts.back().NumCleanupObjects;
+  assert(ExprCleanupObjects.size() >= FirstCleanup);
+  assert(ExprNeedsCleanups || ExprCleanupObjects.size() == FirstCleanup);
   if (!ExprNeedsCleanups)
     return SubExpr;
 
-  Expr *E = ExprWithCleanups::Create(Context, SubExpr,
-                                     ExprTemporaries.begin() + FirstTemporary,
-                                     ExprTemporaries.size() - FirstTemporary);
-  ExprTemporaries.erase(ExprTemporaries.begin() + FirstTemporary,
-                        ExprTemporaries.end());
-  ExprNeedsCleanups = false;
+  ArrayRef<ExprWithCleanups::CleanupObject> Cleanups
+    = llvm::makeArrayRef(ExprCleanupObjects.begin() + FirstCleanup,
+                         ExprCleanupObjects.size() - FirstCleanup);
 
-  return E;
-}
-
-ExprResult
-Sema::MaybeCreateExprWithCleanups(ExprResult SubExpr) {
-  if (SubExpr.isInvalid())
-    return ExprError();
+  Expr *E = ExprWithCleanups::Create(Context, SubExpr, Cleanups);
+  DiscardCleanupsInEvaluationContext();
 
-  return Owned(MaybeCreateExprWithCleanups(SubExpr.take()));
+  return E;
 }
 
 Stmt *Sema::MaybeCreateStmtWithCleanups(Stmt *SubStmt) {

Modified: cfe/trunk/lib/Serialization/ASTReaderStmt.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Serialization/ASTReaderStmt.cpp?rev=144263&r1=144262&r2=144263&view=diff
==============================================================================
--- cfe/trunk/lib/Serialization/ASTReaderStmt.cpp (original)
+++ cfe/trunk/lib/Serialization/ASTReaderStmt.cpp Wed Nov  9 23:35:25 2011
@@ -1195,13 +1195,13 @@
 
 void ASTStmtReader::VisitExprWithCleanups(ExprWithCleanups *E) {
   VisitExpr(E);
-  unsigned NumTemps = Record[Idx++];
-  if (NumTemps) {
-    E->setNumTemporaries(Reader.getContext(), NumTemps);
-    for (unsigned i = 0; i != NumTemps; ++i)
-      E->setTemporary(i, Reader.ReadCXXTemporary(F, Record, Idx));
-  }
-  E->setSubExpr(Reader.ReadSubExpr());
+
+  unsigned NumObjects = Record[Idx++];
+  assert(NumObjects == E->getNumObjects());
+  for (unsigned i = 0; i != NumObjects; ++i)
+    E->getObjectsBuffer()[i] = ReadDeclAs<BlockDecl>(Record, Idx);
+
+  E->SubExpr = Reader.ReadSubExpr();
 }
 
 void
@@ -1974,7 +1974,8 @@
       break;
         
     case EXPR_EXPR_WITH_CLEANUPS:
-      S = new (Context) ExprWithCleanups(Empty);
+      S = ExprWithCleanups::Create(Context, Empty,
+                                   Record[ASTStmtReader::NumExprFields]);
       break;
       
     case EXPR_CXX_DEPENDENT_SCOPE_MEMBER:

Modified: cfe/trunk/lib/Serialization/ASTWriterStmt.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Serialization/ASTWriterStmt.cpp?rev=144263&r1=144262&r2=144263&view=diff
==============================================================================
--- cfe/trunk/lib/Serialization/ASTWriterStmt.cpp (original)
+++ cfe/trunk/lib/Serialization/ASTWriterStmt.cpp Wed Nov  9 23:35:25 2011
@@ -1180,9 +1180,9 @@
 
 void ASTStmtWriter::VisitExprWithCleanups(ExprWithCleanups *E) {
   VisitExpr(E);
-  Record.push_back(E->getNumTemporaries());
-  for (unsigned i = 0, e = E->getNumTemporaries(); i != e; ++i)
-    Writer.AddCXXTemporary(E->getTemporary(i), Record);
+  Record.push_back(E->getNumObjects());
+  for (unsigned i = 0, e = E->getNumObjects(); i != e; ++i)
+    Writer.AddDeclRef(E->getObject(i), Record);
   
   Writer.AddStmt(E->getSubExpr());
   Code = serialization::EXPR_EXPR_WITH_CLEANUPS;





More information about the cfe-commits mailing list