[cfe-commits] r60782 - in /cfe/trunk: include/clang/Parse/Action.h include/clang/Parse/Ownership.h lib/Parse/AstGuard.h lib/Parse/Parser.cpp

Sebastian Redl sebastian.redl at getdesigned.at
Tue Dec 9 11:36:22 PST 2008


Author: cornedbee
Date: Tue Dec  9 13:36:21 2008
New Revision: 60782

URL: http://llvm.org/viewvc/llvm-project?rev=60782&view=rev
Log:
Lay the groundwork for converting the entire parser-sema chain to smart pointers.

Added:
    cfe/trunk/include/clang/Parse/Ownership.h
Modified:
    cfe/trunk/include/clang/Parse/Action.h
    cfe/trunk/lib/Parse/AstGuard.h
    cfe/trunk/lib/Parse/Parser.cpp

Modified: cfe/trunk/include/clang/Parse/Action.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Parse/Action.h?rev=60782&r1=60781&r2=60782&view=diff

==============================================================================
--- cfe/trunk/include/clang/Parse/Action.h (original)
+++ cfe/trunk/include/clang/Parse/Action.h Tue Dec  9 13:36:21 2008
@@ -17,6 +17,7 @@
 #include "clang/Basic/IdentifierTable.h"
 #include "clang/Basic/SourceLocation.h"
 #include "clang/Parse/AccessSpecifier.h"
+#include "clang/Parse/Ownership.h"
 
 namespace clang {
   // Semantic.
@@ -49,15 +50,15 @@
 /// isCurrentClassName(), which must be specified in order for the
 /// parse to complete accurately.  The MinimalAction class does this
 /// bare-minimum of tracking to implement this functionality.
-class Action {
+class Action : public ActionBase {
 public:
   /// Out-of-line virtual destructor to provide home for this class.
   virtual ~Action();
-  
+
   // Types - Though these don't actually enforce strong typing, they document
   // what types are required to be identical for the actions.
-  typedef void ExprTy;
-  typedef void StmtTy;
+  typedef ActionBase::ExprTy ExprTy;
+  typedef ActionBase::StmtTy StmtTy;
   typedef void DeclTy;
   typedef void TypeTy;
   typedef void AttrTy;
@@ -65,26 +66,6 @@
   typedef void MemInitTy;
   typedef void CXXScopeTy;
 
-  /// ActionResult - This structure is used while parsing/acting on expressions,
-  /// stmts, etc.  It encapsulates both the object returned by the action, plus
-  /// a sense of whether or not it is valid.
-  template<unsigned UID>
-  struct ActionResult {
-    void *Val;
-    bool isInvalid;
-    
-    ActionResult(bool Invalid = false) : Val(0), isInvalid(Invalid) {}
-    template<typename ActualExprTy>
-    ActionResult(ActualExprTy *val) : Val(val), isInvalid(false) {}
-    ActionResult(const DiagnosticBuilder &) : Val(0), isInvalid(true) {}
-    
-    const ActionResult &operator=(void *RHS) {
-      Val = RHS;
-      isInvalid = false;
-      return *this;
-    }
-  };
-
   /// Expr/Stmt/Type/BaseResult - Provide a unique type to wrap
   /// ExprTy/StmtTy/TypeTy/BaseTy, providing strong typing and
   /// allowing for failure.
@@ -94,12 +75,20 @@
   typedef ActionResult<3> BaseResult;
   typedef ActionResult<4> MemInitResult;
 
-  /// Deletion callbacks - Since the parser doesn't know the concrete types of
-  /// the AST nodes being generated, it must do callbacks to delete objects when
-  /// recovering from errors.
-  virtual void DeleteExpr(ExprTy *E) {}
-  virtual void DeleteStmt(StmtTy *E) {}
-  
+  /// Same, but with ownership.
+  typedef ASTOwningResult<&ActionBase::DeleteExpr> OwningExprResult;
+  typedef ASTOwningResult<&ActionBase::DeleteStmt> OwningStmtResult;
+  // Note that these will replace ExprResult and StmtResult when the transition
+  // is complete.
+
+  /// Single expressions or statements as arguments.
+  typedef ASTOwningPtr<&ActionBase::DeleteExpr> ExprArg;
+  typedef ASTOwningPtr<&ActionBase::DeleteStmt> StmtArg;
+
+  /// Multiple expressions or statements as arguments.
+  typedef ASTMultiPtr<&ActionBase::DeleteExpr> MultiExprArg;
+  typedef ASTMultiPtr<&ActionBase::DeleteStmt> MultiStmtArg;
+
   /// Statistics.
   virtual void PrintStats() const {}
   //===--------------------------------------------------------------------===//

Added: cfe/trunk/include/clang/Parse/Ownership.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Parse/Ownership.h?rev=60782&view=auto

==============================================================================
--- cfe/trunk/include/clang/Parse/Ownership.h (added)
+++ cfe/trunk/include/clang/Parse/Ownership.h Tue Dec  9 13:36:21 2008
@@ -0,0 +1,374 @@
+//===--- Ownership.h - Parser Ownership Helpers -----------------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+//  This file contains classes for managing ownership of Stmt and Expr nodes.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_PARSE_OWNERSHIP_H
+#define LLVM_CLANG_PARSE_OWNERSHIP_H
+
+namespace clang
+{
+  class DiagnosticBuilder;
+
+  /// ActionBase - A small part split from Action because of the horrible
+  /// definition order dependencies between Action and the smart pointers.
+  class ActionBase {
+  public:
+    /// Out-of-line virtual destructor to provide home for this class.
+    virtual ~ActionBase();
+
+    // Types - Though these don't actually enforce strong typing, they document
+    // what types are required to be identical for the actions.
+    typedef void ExprTy;
+    typedef void StmtTy;
+
+    /// ActionResult - This structure is used while parsing/acting on
+    /// expressions, stmts, etc.  It encapsulates both the object returned by
+    /// the action, plus a sense of whether or not it is valid.
+    template<unsigned UID>
+    struct ActionResult {
+      void *Val;
+      bool isInvalid;
+
+      ActionResult(bool Invalid = false) : Val(0), isInvalid(Invalid) {}
+      template<typename ActualExprTy>
+      ActionResult(ActualExprTy *val) : Val(val), isInvalid(false) {}
+      ActionResult(const DiagnosticBuilder &) : Val(0), isInvalid(true) {}
+
+      const ActionResult &operator=(void *RHS) {
+        Val = RHS;
+        isInvalid = false;
+        return *this;
+      }
+    };
+
+    /// Deletion callbacks - Since the parser doesn't know the concrete types of
+    /// the AST nodes being generated, it must do callbacks to delete objects
+    /// when recovering from errors. These are in ActionBase because the smart
+    /// pointers need access to them.
+    virtual void DeleteExpr(ExprTy *E) {}
+    virtual void DeleteStmt(StmtTy *E) {}
+  };
+
+  /// ASTDestroyer - The type of an AST node destruction function pointer.
+  typedef void (ActionBase::*ASTDestroyer)(void *);
+
+  /// For the transition phase: translate from an ASTDestroyer to its
+  /// ActionResult UID.
+  template <ASTDestroyer Destroyer> struct DestroyerToUID;
+  template <> struct DestroyerToUID<&ActionBase::DeleteExpr> {
+    static const unsigned UID = 0;
+  };
+  template <> struct DestroyerToUID<&ActionBase::DeleteStmt> {
+    static const unsigned UID = 1;
+  };
+
+  /// ASTOwningResult - A moveable smart pointer for AST nodes that also
+  /// has an extra flag to indicate an additional success status.
+  template <ASTDestroyer Destroyer> class ASTOwningResult;
+
+  /// ASTOwningPtr - A moveable smart pointer for AST nodes.
+  template <ASTDestroyer Destroyer> class ASTOwningPtr;
+
+  /// ASTMultiPtr - A moveable smart pointer to multiple AST nodes. Only owns
+  /// the individual pointers, not the array holding them.
+  template <ASTDestroyer Destroyer> class ASTMultiPtr;
+
+  /// Move emulation helper for ASTOwningResult
+  template <ASTDestroyer Destroyer>
+  class ASTResultMover
+  {
+    ASTOwningResult<Destroyer> &Moved;
+
+  public:
+    ASTResultMover(ASTOwningResult<Destroyer> &moved) : Moved(moved) {}
+
+    ASTOwningResult<Destroyer> * operator ->() { return &Moved; }
+
+    // For the transition phase.
+    operator void*();
+
+    // For the transition phase.
+    operator ActionBase::ActionResult<DestroyerToUID<Destroyer>::UID>();
+  };
+
+  /// Move emulation helper for ASTOwningPtr
+  template <ASTDestroyer Destroyer>
+  class ASTPtrMover
+  {
+    ASTOwningPtr<Destroyer> &Moved;
+
+  public:
+    ASTPtrMover(ASTOwningPtr<Destroyer> &moved) : Moved(moved) {}
+
+    ASTOwningPtr<Destroyer> * operator ->() { return &Moved; }
+
+    operator void*();
+  };
+
+  /// Move emulation helper for ASTMultiPtr
+  template <ASTDestroyer Destroyer>
+  class ASTMultiMover
+  {
+    ASTMultiPtr<Destroyer> &Moved;
+
+  public:
+    ASTMultiMover(ASTMultiPtr<Destroyer> &moved) : Moved(moved) {}
+
+    /// Reset the moved object's internal structures.
+    void release();
+  };
+
+  template <ASTDestroyer Destroyer>
+  class ASTOwningResult
+  {
+    ActionBase *Actions;
+    void *Node;
+    bool Invalid;
+
+    friend class ASTResultMover<Destroyer>;
+    friend class ASTOwningPtr<Destroyer>;
+
+    ASTOwningResult(const ASTOwningResult&); // DO NOT IMPLEMENT
+    ASTOwningResult& operator =(const ASTOwningResult&); // DO NOT IMPLEMENT
+
+    void destroy() {
+      if (Node) {
+        assert(Actions && "Owning pointer without Action owns node.");
+        (Actions->*Destroyer)(Node);
+      }
+    }
+
+    void * take() {
+      if (Invalid)
+        return 0;
+      return Node;
+    }
+
+  public:
+    // For convenience and compatibility.
+    ASTOwningResult(bool invalid = false)
+      : Actions(0), Node(0), Invalid(invalid) {}
+    // Same
+    ASTOwningResult(const DiagnosticBuilder &)
+      : Actions(0), Node(0), Invalid(true) {}
+    explicit ASTOwningResult(ActionBase &actions, bool invalid = false)
+      : Actions(&actions), Node(0), Invalid(invalid) {}
+    ASTOwningResult(ActionBase &actions, void *node)
+      : Actions(&actions), Node(node), Invalid(false) {}
+    /// Move from another owning result
+    ASTOwningResult(ASTResultMover<Destroyer> mover)
+      : Actions(mover->Actions), Node(mover->take()), Invalid(mover->Invalid) {}
+    /// Move from an owning pointer
+    ASTOwningResult(ASTPtrMover<Destroyer> mover);
+
+    /// Move assignment from another owning result
+    ASTOwningResult & operator =(ASTResultMover<Destroyer> mover) {
+      Actions = mover->Actions;
+      Node = mover->take();
+      Invalid = mover->Invalid;
+      return *this;
+    }
+
+    /// Move assignment from an owning ptr
+    ASTOwningResult & operator =(ASTPtrMover<Destroyer> mover);
+
+    /// Assignment from a raw pointer. Takes ownership - beware!
+    ASTOwningResult & operator =(void *raw)
+    {
+      assert((!raw || Actions) &&
+             "Cannot have raw assignment when there's no Action");
+      Node = raw;
+      Invalid = false;
+      return *this;
+    }
+
+    /// Assignment from an ActionResult. Takes ownership - beware!
+    ASTOwningResult & operator =(
+        const ActionBase::ActionResult<DestroyerToUID<Destroyer>::UID> &res) {
+      assert((!res.Val || Actions) &&
+             "Cannot assign from ActionResult when there's no Action");
+      Node = res.Val;
+      Invalid = res.isInvalid;
+      return *this;
+    }
+
+    /// Access to the raw pointer.
+    void * get() const { return Node; }
+
+    bool isInvalid() const { return Invalid; }
+
+    /// Does this point to a usable AST node? To be usable, the node must be
+    /// valid and non-null.
+    bool isUsable() const { return !Invalid && Node; }
+
+    /// Move hook
+    ASTResultMover<Destroyer> move() {
+      return ASTResultMover<Destroyer>(*this);
+    }
+  };
+
+  template <ASTDestroyer Destroyer>
+  class ASTOwningPtr
+  {
+    ActionBase *Actions;
+    void *Node;
+
+    friend class ASTPtrMover<Destroyer>;
+    friend class ASTOwningResult<Destroyer>;
+
+    ASTOwningPtr(const ASTOwningPtr&); // DO NOT IMPLEMENT
+    ASTOwningPtr& operator =(const ASTOwningPtr&); // DO NOT IMPLEMENT
+
+    void destroy() {
+      if (Node) {
+        assert(Actions && "Owning pointer without Action owns node.");
+        (Actions->*Destroyer)(Node);
+      }
+    }
+
+  public:
+    explicit ASTOwningPtr(ActionBase &actions)
+      : Actions(&actions), Node(0) {}
+    ASTOwningPtr(ActionBase &actions, void *node)
+      : Actions(&actions), Node(node) {}
+    /// Move from another owning pointer
+    ASTOwningPtr(ASTPtrMover<Destroyer> mover)
+      : Actions(mover->Actions), Node(mover->take()) {}
+    /// Move from an owning result
+    ASTOwningPtr(ASTResultMover<Destroyer> mover);
+
+    /// Move assignment from another owning pointer
+    ASTOwningPtr & operator =(ASTPtrMover<Destroyer> mover) {
+      Actions = mover->Actions;
+      Node = mover->take();
+      return *this;
+    }
+
+    /// Move assignment from an owning result
+    ASTOwningPtr & operator =(ASTResultMover<Destroyer> mover);
+
+    /// Assignment from a raw pointer. Takes ownership - beware!
+    ASTOwningPtr & operator =(void *raw)
+    {
+      assert((Actions || !raw) && "Cannot assign non-null raw without Action");
+      Node = raw;
+      return *this;
+    }
+
+    /// Access to the raw pointer.
+    void * get() const { return Node; }
+
+    /// Move hook
+    ASTPtrMover<Destroyer> move() {
+      return ASTPtrMover<Destroyer>(*this);
+    }
+  };
+
+  template <ASTDestroyer Destroyer>
+  class ASTMultiPtr
+  {
+    ActionBase &Actions;
+    void **Nodes;
+    unsigned Count;
+
+    friend class ASTMultiMover<Destroyer>;
+
+    ASTMultiPtr(const ASTMultiPtr&); // DO NOT IMPLEMENT
+    // Reference member prevents copy assignment.
+
+    void destroy() {
+      assert((Count == 0 || Nodes) && "No nodes when count is not zero.");
+      for (unsigned i = 0; i < Count; ++i) {
+        if (Nodes[i])
+          (Actions.*Destroyer)(Nodes[i]);
+      }
+    }
+
+  public:
+    explicit ASTMultiPtr(ActionBase &actions)
+      : Actions(actions), Nodes(0), Count(0) {}
+    ASTMultiPtr(ActionBase &actions, void **nodes, unsigned count)
+      : Actions(actions), Nodes(nodes), Count(count) {}
+    /// Move constructor
+    ASTMultiPtr(ASTMultiMover<Destroyer> mover)
+      : Actions(mover->Actions), Nodes(mover->Nodes), Count(mover->Count) {
+      mover->Nodes = 0;
+      mover->Count = 0;
+    }
+
+    /// Move assignment
+    ASTMultiPtr & operator =(ASTMultiMover<Destroyer> mover) {
+      Actions = mover->Actions;
+      Nodes = mover->Nodes;
+      Count = mover->Count;
+      mover.release();
+      return *this;
+    }
+
+    /// Access to the raw pointers.
+    void ** get() const { return Nodes; }
+
+    /// Access to the count.
+    unsigned size() const { return Count; }
+
+    /// Move hook
+    ASTMultiMover<Destroyer> move() {
+      return ASTMultiMover<Destroyer>(*this);
+    }
+  };
+
+  // Out-of-line implementations due to definition dependencies
+
+  template <ASTDestroyer Destroyer> inline
+  ASTResultMover<Destroyer>::operator void*() {
+    return Moved.take();
+  }
+
+  template <ASTDestroyer Destroyer> inline
+  ASTPtrMover<Destroyer>::operator void*() {
+    return Moved.take();
+  }
+
+  template <ASTDestroyer Destroyer> inline
+  void ASTMultiMover<Destroyer>::release() {
+    Moved.Nodes = 0;
+    Moved.Count = 0;
+  }
+
+  template <ASTDestroyer Destroyer> inline
+  ASTOwningResult<Destroyer>::ASTOwningResult(ASTPtrMover<Destroyer> mover)
+    : Actions(mover->Actions), Node(mover->take()), Invalid(false) {}
+
+  template <ASTDestroyer Destroyer> inline
+  ASTOwningResult<Destroyer> &
+  ASTOwningResult<Destroyer>::operator =(ASTPtrMover<Destroyer> mover) {
+    Actions = mover->Actions;
+    Node = mover->take();
+    Invalid = false;
+    return *this;
+  }
+
+  template <ASTDestroyer Destroyer> inline
+  ASTOwningPtr<Destroyer>::ASTOwningPtr(ASTResultMover<Destroyer> mover)
+    : Actions(mover->Actions), Node(mover->take()) {
+  }
+
+  template <ASTDestroyer Destroyer> inline
+  ASTOwningPtr<Destroyer> &
+  ASTOwningPtr<Destroyer>::operator =(ASTResultMover<Destroyer> mover) {
+    Actions = mover->Actions;
+    Node = mover->take();
+    return *this;
+  }
+}
+
+#endif

Modified: cfe/trunk/lib/Parse/AstGuard.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Parse/AstGuard.h?rev=60782&r1=60781&r2=60782&view=diff

==============================================================================
--- cfe/trunk/lib/Parse/AstGuard.h (original)
+++ cfe/trunk/lib/Parse/AstGuard.h Tue Dec  9 13:36:21 2008
@@ -19,11 +19,11 @@
 
 namespace clang
 {
-  template <void (Action::*Destroyer)(void*)>
+  template <void (ActionBase::*Destroyer)(void*)>
   class ASTOwner;
 
-  typedef ASTOwner<&Action::DeleteStmt> StmtOwner;
-  typedef ASTOwner<&Action::DeleteExpr> ExprOwner;
+  typedef ASTOwner<&ActionBase::DeleteStmt> StmtOwner;
+  typedef ASTOwner<&ActionBase::DeleteExpr> ExprOwner;
 
   /// Some trickery to switch between an ActionResult and an ASTOwner
   template <typename Owner> struct ResultOfOwner;
@@ -36,7 +36,7 @@
 
   /// Move emulation helper for ASTOwner. Implicitly convertible to ActionResult
   /// and void*, which means ASTOwner::move() can be used universally.
-  template <void (Action::*Destroyer)(void*)>
+  template <void (ActionBase::*Destroyer)(void*)>
   class ASTMove {
     ASTOwner<Destroyer> &Moved;
 
@@ -62,7 +62,7 @@
   };
 
   /// RAII owning pointer for StmtTys and ExprTys. Simple move emulation.
-  template <void (Action::*Destroyer)(void*)>
+  template <void (ActionBase::*Destroyer)(void*)>
   class ASTOwner {
     typedef typename ResultOfOwner<ASTOwner>::type Result;
 
@@ -136,7 +136,7 @@
   /// automatically freeing them on destruction unless it's been disowned.
   /// Instantiated for statements and expressions (Action::DeleteStmt and
   /// Action::DeleteExpr).
-  template <void (Action::*Destroyer)(void*), unsigned N>
+  template <void (ActionBase::*Destroyer)(void*), unsigned N>
   class ASTVector : public llvm::SmallVector<void*, N> {
   private:
     Action &Actions;

Modified: cfe/trunk/lib/Parse/Parser.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Parse/Parser.cpp?rev=60782&r1=60781&r2=60782&view=diff

==============================================================================
--- cfe/trunk/lib/Parse/Parser.cpp (original)
+++ cfe/trunk/lib/Parse/Parser.cpp Tue Dec  9 13:36:21 2008
@@ -39,6 +39,9 @@
 }
 
 ///  Out-of-line virtual destructor to provide home for Action class.
+ActionBase::~ActionBase() {}
+
+///  Out-of-line virtual destructor to provide home for Action class.
 Action::~Action() {}
 
 





More information about the cfe-commits mailing list