r205745 - Thread Safety Analysis: various fixes to new SExpr code.

DeLesley Hutchins delesley at google.com
Mon Apr 7 15:56:24 PDT 2014


Author: delesley
Date: Mon Apr  7 17:56:24 2014
New Revision: 205745

URL: http://llvm.org/viewvc/llvm-project?rev=205745&view=rev
Log:
Thread Safety Analysis: various fixes to new SExpr code.
Implemented ownership policy, updated to use nullptr, const-cleanup.

Modified:
    cfe/trunk/include/clang/Analysis/Analyses/ThreadSafetyCommon.h
    cfe/trunk/include/clang/Analysis/Analyses/ThreadSafetyTIL.h
    cfe/trunk/lib/Analysis/ThreadSafetyCommon.cpp

Modified: cfe/trunk/include/clang/Analysis/Analyses/ThreadSafetyCommon.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Analysis/Analyses/ThreadSafetyCommon.h?rev=205745&r1=205744&r2=205745&view=diff
==============================================================================
--- cfe/trunk/include/clang/Analysis/Analyses/ThreadSafetyCommon.h (original)
+++ cfe/trunk/include/clang/Analysis/Analyses/ThreadSafetyCommon.h Mon Apr  7 17:56:24 2014
@@ -19,6 +19,9 @@
 //
 //===----------------------------------------------------------------------===//
 
+#ifndef LLVM_CLANG_THREAD_SAFETY_COMMON_H
+#define LLVM_CLANG_THREAD_SAFETY_COMMON_H
+
 #include "clang/AST/Attr.h"
 #include "clang/AST/DeclCXX.h"
 #include "clang/AST/ExprCXX.h"
@@ -242,3 +245,5 @@ void printSCFG(CFGWalker &walker);
 } // end namespace threadSafety
 
 } // end namespace clang
+
+#endif  // LLVM_CLANG_THREAD_SAFETY_COMMON_H

Modified: cfe/trunk/include/clang/Analysis/Analyses/ThreadSafetyTIL.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Analysis/Analyses/ThreadSafetyTIL.h?rev=205745&r1=205744&r2=205745&view=diff
==============================================================================
--- cfe/trunk/include/clang/Analysis/Analyses/ThreadSafetyTIL.h (original)
+++ cfe/trunk/include/clang/Analysis/Analyses/ThreadSafetyTIL.h Mon Apr  7 17:56:24 2014
@@ -71,7 +71,7 @@ private:
   };
 
 public:
-  MemRegionRef() : Allocator(0) {}
+  MemRegionRef() : Allocator(nullptr) {}
   MemRegionRef(llvm::BumpPtrAllocator *A) : Allocator(A) {}
 
   void *allocate(size_t Sz) {
@@ -110,14 +110,14 @@ using llvm::StringRef;
 // suitable for use with bump pointer allocation.
 template <class T> class SimpleArray {
 public:
-  SimpleArray() : Data(0), Size(0), Capacity(0) {}
+  SimpleArray() : Data(nullptr), Size(0), Capacity(0) {}
   SimpleArray(T *Dat, size_t Cp, size_t Sz = 0)
       : Data(Dat), Size(0), Capacity(Cp) {}
   SimpleArray(MemRegionRef A, size_t Cp)
       : Data(A.allocateT<T>(Cp)), Size(0), Capacity(Cp) {}
   SimpleArray(SimpleArray<T> &A, bool Steal)
       : Data(A.Data), Size(A.Size), Capacity(A.Capacity) {
-    A.Data = 0;
+    A.Data = nullptr;
     A.Size = 0;
     A.Capacity = 0;
   }
@@ -216,7 +216,43 @@ private:
   SExpr();
 };
 
-typedef SExpr* SExprRef;
+
+// Class for owning references to SExprs.
+// Includes attach/detach logic for counting variable references and lazy
+// rewriting strategies.
+class SExprRef {
+public:
+  SExprRef() : Ptr(nullptr) { }
+  SExprRef(std::nullptr_t P) : Ptr(nullptr) { }
+  SExprRef(SExprRef &&R) : Ptr(R.Ptr) { }
+
+  // Defined after Variable and Future, below.
+  inline SExprRef(SExpr *P);
+  inline ~SExprRef();
+
+  SExpr       *get()       { return Ptr; }
+  const SExpr *get() const { return Ptr; }
+
+  SExpr       *operator->()       { return get(); }
+  const SExpr *operator->() const { return get(); }
+
+  SExpr       &operator*()        { return *Ptr; }
+  const SExpr &operator*() const  { return *Ptr; }
+
+  bool operator==(const SExprRef& R) const { return Ptr == R.Ptr; }
+  bool operator==(const SExpr* P)    const { return Ptr == P; }
+  bool operator==(std::nullptr_t P)  const { return Ptr == nullptr; }
+
+  inline void reset(SExpr *E);
+
+private:
+  inline void attach();
+  inline void detach();
+
+  SExprRef(const SExprRef& R) : Ptr(R.Ptr) { }
+
+  SExpr *Ptr;
+};
 
 
 // Contains various helper functions for SExprs.
@@ -226,7 +262,7 @@ public:
 
   static inline bool isTrivial(SExpr *E) {
     unsigned Op = E->opcode();
-    return Op == COP_Variable || Op == COP_Literal;
+    return Op == COP_Variable || Op == COP_Literal || Op == COP_LiteralPtr;
   }
 
   static inline bool isLargeValue(SExpr *E) {
@@ -236,6 +272,85 @@ public:
 };
 
 
+class Function;
+class SFunction;
+class BasicBlock;
+
+
+// A named variable, e.g. "x".
+//
+// There are two distinct places in which a Variable can appear in the AST.
+// A variable declaration introduces a new variable, and can occur in 3 places:
+//   Let-expressions:           (Let (x = t) u)
+//   Functions:                 (Function (x : t) u)
+//   Self-applicable functions  (SFunction (x) t)
+//
+// If a variable occurs in any other location, it is a reference to an existing
+// variable declaration -- e.g. 'x' in (x * y + z). To save space, we don't
+// allocate a separate AST node for variable references; a reference is just a
+// pointer to the original declaration.
+class Variable : public SExpr {
+public:
+  static bool classof(const SExpr *E) { return E->opcode() == COP_Variable; }
+
+  // Let-variable, function parameter, or self-variable
+  enum VariableKind {
+    VK_Let,
+    VK_Fun,
+    VK_SFun
+  };
+
+  // These are defined after SExprRef contructor, below
+  inline Variable(VariableKind K, SExpr *D = nullptr,
+                  const clang::ValueDecl *Cvd = nullptr);
+  inline Variable(const clang::ValueDecl *Cvd, SExpr *D = nullptr);
+  inline Variable(const Variable &Vd, SExpr *D);
+
+  VariableKind kind() const { return static_cast<VariableKind>(Flags); }
+
+  StringRef name() const { return Cvdecl ? Cvdecl->getName() : "_x"; }
+  const clang::ValueDecl *clangDecl() const { return Cvdecl; }
+
+  // Returns the definition (for let vars) or type (for parameter & self vars)
+  SExpr *definition() { return Definition.get(); }
+
+  void attachVar() const { ++NumUses; }
+  void detachVar() const { --NumUses; }
+
+  unsigned getID() { return Id; }
+  unsigned getBlockID() { return BlockID; }
+
+  void setID(unsigned Bid, unsigned I) {
+    BlockID = static_cast<unsigned short>(Bid);
+    Id = static_cast<unsigned short>(I);
+  }
+
+  template <class V> typename V::R_SExpr traverse(V &Visitor) {
+    // This routine is only called for variable references.
+    return Visitor.reduceVariableRef(this);
+  }
+
+  template <class C> typename C::CType compare(Variable* E, C& Cmp) {
+    return Cmp.compareVariableRefs(this, E);
+  }
+
+private:
+  friend class Function;
+  friend class SFunction;
+  friend class BasicBlock;
+
+  // Function, SFunction, and BasicBlock will reset the kind.
+  void setKind(VariableKind K) { Flags = K; }
+
+  SExprRef Definition;             // The TIL type or definition
+  const clang::ValueDecl *Cvdecl;  // The clang declaration for this variable.
+
+  unsigned short BlockID;
+  unsigned short Id;
+  mutable int NumUses;
+};
+
+
 // Placeholder for an expression that has not yet been created.
 // Used to implement lazy copy and rewriting strategies.
 class Future : public SExpr {
@@ -248,18 +363,20 @@ public:
     FS_done
   };
 
-  Future() : SExpr(COP_Future), Status(FS_pending), Result(0), Location(0) {}
+  Future() :
+    SExpr(COP_Future), Status(FS_pending), Result(nullptr), Location(nullptr)
+  {}
   virtual ~Future() {}
 
   // Registers the location in the AST where this future is stored.
   // Forcing the future will automatically update the AST.
-  static inline void registerLocation(SExpr **Member) {
-    if (Future *F = dyn_cast_or_null<Future>(*Member))
+  static inline void registerLocation(SExprRef *Member) {
+    if (Future *F = dyn_cast_or_null<Future>(Member->get()))
       F->Location = Member;
   }
 
   // A lazy rewriting strategy should subclass Future and override this method.
-  virtual SExpr *create() { return 0; }
+  virtual SExpr *create() { return nullptr; }
 
   // Return the result of this future if it exists, otherwise return null.
   SExpr *maybeGetResult() {
@@ -273,7 +390,7 @@ public:
       force();
       return Result;
     case FS_evaluating:
-      return 0; // infinite loop; illegal recursion.
+      return nullptr; // infinite loop; illegal recursion.
     case FS_done:
       return Result;
     }
@@ -292,28 +409,89 @@ public:
 
 private:
   // Force the future.
-  void force() {
-    Status = FS_evaluating;
-    SExpr *R = create();
-    Result = R;
-    if (Location) {
-      *Location = R;
-    }
-    Status = FS_done;
-  }
+  inline void force();
 
   FutureStatus Status;
   SExpr *Result;
-  SExpr **Location;
+  SExprRef *Location;
 };
 
 
+
+void SExprRef::attach() {
+  if (!Ptr)
+    return;
+
+  TIL_Opcode Op = Ptr->opcode();
+  if (Op == COP_Variable) {
+    cast<Variable>(Ptr)->attachVar();
+  }
+  else if (Op == COP_Future) {
+    cast<Future>(Ptr)->registerLocation(this);
+  }
+}
+
+void SExprRef::detach() {
+  if (Ptr && Ptr->opcode() == COP_Variable) {
+    cast<Variable>(Ptr)->detachVar();
+  }
+}
+
+SExprRef::SExprRef(SExpr *P) : Ptr(P) {
+  if (P)
+    attach();
+}
+
+SExprRef::~SExprRef() {
+  detach();
+}
+
+void SExprRef::reset(SExpr *P) {
+  if (Ptr)
+    detach();
+  Ptr = P;
+  if (P)
+    attach();
+}
+
+
+Variable::Variable(VariableKind K, SExpr *D, const clang::ValueDecl *Cvd)
+    : SExpr(COP_Variable), Definition(D), Cvdecl(Cvd),
+      BlockID(0), Id(0),  NumUses(0) {
+  Flags = K;
+}
+
+Variable::Variable(const clang::ValueDecl *Cvd, SExpr *D)
+    : SExpr(COP_Variable), Definition(D), Cvdecl(Cvd),
+      BlockID(0), Id(0),  NumUses(0) {
+  Flags = VK_Let;
+}
+
+Variable::Variable(const Variable &Vd, SExpr *D) // rewrite constructor
+    : SExpr(Vd), Definition(D), Cvdecl(Vd.Cvdecl),
+      BlockID(0), Id(0), NumUses(0) {
+  Flags = Vd.kind();
+}
+
+
+void Future::force() {
+  Status = FS_evaluating;
+  SExpr *R = create();
+  Result = R;
+  if (Location) {
+    Location->reset(R);
+  }
+  Status = FS_done;
+}
+
+
+
 // Placeholder for C++ expressions that cannot be represented in the TIL.
 class Undefined : public SExpr {
 public:
   static bool classof(const SExpr *E) { return E->opcode() == COP_Undefined; }
 
-  Undefined(const clang::Stmt *S = 0) : SExpr(COP_Undefined), Cstmt(S) {}
+  Undefined(const clang::Stmt *S = nullptr) : SExpr(COP_Undefined), Cstmt(S) {}
   Undefined(const Undefined &U) : SExpr(U), Cstmt(U.Cstmt) {}
 
   template <class V> typename V::R_SExpr traverse(V &Visitor) {
@@ -397,91 +575,7 @@ private:
 };
 
 
-// A named variable, e.g. "x".
-//
-// There are two distinct places in which a Variable can appear in the AST.
-// A variable declaration introduces a new variable, and can occur in 3 places:
-//   Let-expressions:           (Let (x = t) u)
-//   Functions:                 (Function (x : t) u)
-//   Self-applicable functions  (SFunction (x) t)
-//
-// If a variable occurs in any other location, it is a reference to an existing
-// variable declaration -- e.g. 'x' in (x * y + z). To save space, we don't
-// allocate a separate AST node for variable references; a reference is just a
-// pointer to the original declaration.
-class Variable : public SExpr {
-public:
-  static bool classof(const SExpr *E) { return E->opcode() == COP_Variable; }
-
-  // Let-variable, function parameter, or self-variable
-  enum VariableKind {
-    VK_Let,
-    VK_Fun,
-    VK_SFun
-  };
-
-  Variable(VariableKind K, SExpr *D = 0, const clang::ValueDecl *Cvd = 0)
-      : SExpr(COP_Variable), Definition(D), Cvdecl(Cvd),
-        BlockID(0), Id(0),  NumUses(0) {
-    Flags = K;
-    Future::registerLocation(&Definition);
-  }
-  Variable(const clang::ValueDecl *Cvd, SExpr *D = 0)
-      : SExpr(COP_Variable), Definition(D), Cvdecl(Cvd),
-        BlockID(0), Id(0),  NumUses(0) {
-    Flags = VK_Let;
-    Future::registerLocation(&Definition);
-  }
-  Variable(const Variable &Vd, SExpr *D) // rewrite constructor
-      : SExpr(Vd), Definition(D), Cvdecl(Vd.Cvdecl),
-        BlockID(0), Id(0), NumUses(0) {
-    Flags = Vd.kind();
-    Future::registerLocation(&Definition);
-  }
-
-  VariableKind kind() const { return static_cast<VariableKind>(Flags); }
-
-  StringRef name() const { return Cvdecl ? Cvdecl->getName() : "_x"; }
-  const clang::ValueDecl *clangDecl() const { return Cvdecl; }
 
-  // Returns the definition (for let vars) or type (for parameter & self vars)
-  SExpr *definition() const { return Definition; }
-
-  void attachVar() const { ++NumUses; }
-  void detachVar() const { --NumUses; }
-
-  unsigned getID() { return Id; }
-  unsigned getBlockID() { return BlockID; }
-
-  void setID(unsigned Bid, unsigned I) {
-    BlockID = static_cast<unsigned short>(Bid);
-    Id = static_cast<unsigned short>(I);
-  }
-
-  template <class V> typename V::R_SExpr traverse(V &Visitor) {
-    // This routine is only called for variable references.
-    return Visitor.reduceVariableRef(this);
-  }
-
-  template <class C> typename C::CType compare(Variable* E, C& Cmp) {
-    return Cmp.compareVariableRefs(this, E);
-  }
-
-private:
-  friend class Function;
-  friend class SFunction;
-  friend class BasicBlock;
-
-  // Function, SFunction, and BasicBlock will reset the kind.
-  void setKind(VariableKind K) { Flags = K; }
-
-  SExpr *Definition;               // The TIL type or definition
-  const clang::ValueDecl *Cvdecl;  // The clang declaration for this variable.
-
-  unsigned short BlockID;
-  unsigned short Id;
-  mutable int NumUses;
-};
 
 
 // A function -- a.k.a. lambda abstraction.
@@ -500,8 +594,11 @@ public:
     Vd->setKind(Variable::VK_Fun);
   }
 
-  Variable *variableDecl() const { return VarDecl; }
-  SExpr *body() const { return Body; }
+  Variable *variableDecl()  { return VarDecl; }
+  const Variable *variableDecl() const { return VarDecl; }
+
+  SExpr *body() { return Body.get(); }
+  const SExpr *body() const { return Body.get(); }
 
   template <class V> typename V::R_SExpr traverse(V &Visitor) {
     // This is a variable declaration, so traverse the definition.
@@ -518,15 +615,15 @@ public:
       Cmp.compare(VarDecl->definition(), E->VarDecl->definition());
     if (Cmp.notTrue(Ct))
       return Ct;
-    Cmp.enterScope(VarDecl, E->VarDecl);
-    Ct = Cmp.compare(Body, E->Body);
+    Cmp.enterScope(variableDecl(), E->variableDecl());
+    Ct = Cmp.compare(body(), E->body());
     Cmp.leaveScope();
     return Ct;
   }
 
 private:
   Variable *VarDecl;
-  SExpr *Body;
+  SExprRef Body;
 };
 
 
@@ -539,27 +636,30 @@ public:
 
   SFunction(Variable *Vd, SExpr *B)
       : SExpr(COP_SFunction), VarDecl(Vd), Body(B) {
-    assert(Vd->Definition == 0);
+    assert(Vd->Definition == nullptr);
     Vd->setKind(Variable::VK_SFun);
-    Vd->Definition = this;
+    Vd->Definition.reset(this);
   }
   SFunction(const SFunction &F, Variable *Vd, SExpr *B) // rewrite constructor
       : SExpr(F),
         VarDecl(Vd),
         Body(B) {
-    assert(Vd->Definition == 0);
+    assert(Vd->Definition == nullptr);
     Vd->setKind(Variable::VK_SFun);
-    Vd->Definition = this;
+    Vd->Definition.reset(this);
   }
 
-  Variable *variableDecl() const { return VarDecl; }
-  SExpr *body() const { return Body; }
+  Variable *variableDecl() { return VarDecl; }
+  const Variable *variableDecl() const { return VarDecl; }
+
+  SExpr *body() { return Body.get(); }
+  const SExpr *body() const { return Body.get(); }
 
   template <class V> typename V::R_SExpr traverse(V &Visitor) {
     // A self-variable points to the SFunction itself.
     // A rewrite must introduce the variable with a null definition, and update
     // it after 'this' has been rewritten.
-    Variable *Nvd = Visitor.enterScope(*VarDecl, 0 /* def */);
+    Variable *Nvd = Visitor.enterScope(*VarDecl, nullptr /* def */);
     typename V::R_SExpr E1 = Visitor.traverse(Body);
     Visitor.exitScope(*VarDecl);
     // A rewrite operation will call SFun constructor to set Vvd->Definition.
@@ -567,15 +667,15 @@ public:
   }
 
   template <class C> typename C::CType compare(SFunction* E, C& Cmp) {
-    Cmp.enterScope(VarDecl, E->VarDecl);
-    typename C::CType Ct = Cmp.compare(Body, E->Body);
+    Cmp.enterScope(variableDecl(), E->variableDecl());
+    typename C::CType Ct = Cmp.compare(body(), E->body());
     Cmp.leaveScope();
     return Ct;
   }
 
 private:
   Variable *VarDecl;
-  SExpr *Body;
+  SExprRef Body;
 };
 
 
@@ -584,20 +684,15 @@ class Code : public SExpr {
 public:
   static bool classof(const SExpr *E) { return E->opcode() == COP_Code; }
 
-  Code(SExpr *T, SExpr *B) : SExpr(COP_Code), ReturnType(T), Body(B) {
-    Future::registerLocation(&ReturnType);
-    Future::registerLocation(&Body);
-  }
+  Code(SExpr *T, SExpr *B) : SExpr(COP_Code), ReturnType(T), Body(B) {}
   Code(const Code &C, SExpr *T, SExpr *B) // rewrite constructor
-      : SExpr(C),
-        ReturnType(T),
-        Body(B) {
-    Future::registerLocation(&ReturnType);
-    Future::registerLocation(&Body);
-  }
+      : SExpr(C), ReturnType(T), Body(B) {}
+
+  SExpr *returnType() { return ReturnType.get(); }
+  const SExpr *returnType() const { return ReturnType.get(); }
 
-  SExpr *returnType() { return ReturnType; }
-  SExpr *body() { return Body; }
+  SExpr *body() { return Body.get(); }
+  const SExpr *body() const { return Body.get(); }
 
   template <class V> typename V::R_SExpr traverse(V &Visitor) {
     typename V::R_SExpr Nt = Visitor.traverse(ReturnType, TRV_Lazy);
@@ -606,15 +701,15 @@ public:
   }
 
   template <class C> typename C::CType compare(Code* E, C& Cmp) {
-    typename C::CType Ct = Cmp.compare(ReturnType, E->ReturnType);
+    typename C::CType Ct = Cmp.compare(returnType(), E->returnType());
     if (Cmp.notTrue(Ct))
       return Ct;
-    return Cmp.compare(Body, E->Body);
+    return Cmp.compare(body(), E->body());
   }
 
 private:
-  SExpr *ReturnType;
-  SExpr *Body;
+  SExprRef ReturnType;
+  SExprRef Body;
 };
 
 
@@ -628,8 +723,11 @@ public:
       : SExpr(A), Fun(F), Arg(Ar)
   {}
 
-  SExpr *fun() const { return Fun; }
-  SExpr *arg() const { return Arg; }
+  SExpr *fun() { return Fun.get(); }
+  const SExpr *fun() const { return Fun.get(); }
+
+  SExpr *arg() { return Arg.get(); }
+  const SExpr *arg() const { return Arg.get(); }
 
   template <class V> typename V::R_SExpr traverse(V &Visitor) {
     typename V::R_SExpr Nf = Visitor.traverse(Fun);
@@ -638,15 +736,15 @@ public:
   }
 
   template <class C> typename C::CType compare(Apply* E, C& Cmp) {
-    typename C::CType Ct = Cmp.compare(Fun, E->Fun);
+    typename C::CType Ct = Cmp.compare(fun(), E->fun());
     if (Cmp.notTrue(Ct))
       return Ct;
-    return Cmp.compare(Arg, E->Arg);
+    return Cmp.compare(arg(), E->arg());
   }
 
 private:
-  SExpr *Fun;
-  SExpr *Arg;
+  SExprRef Fun;
+  SExprRef Arg;
 };
 
 
@@ -655,32 +753,37 @@ class SApply : public SExpr {
 public:
   static bool classof(const SExpr *E) { return E->opcode() == COP_SApply; }
 
-  SApply(SExpr *Sf, SExpr *A = 0) : SExpr(COP_SApply), Sfun(Sf), Arg(A) {}
-  SApply(SApply &A, SExpr *Sf, SExpr *Ar = 0)  // rewrite constructor
+  SApply(SExpr *Sf, SExpr *A = nullptr)
+      : SExpr(COP_SApply), Sfun(Sf), Arg(A)
+  {}
+  SApply(SApply &A, SExpr *Sf, SExpr *Ar = nullptr)  // rewrite constructor
       : SExpr(A),  Sfun(Sf), Arg(Ar)
   {}
 
-  SExpr *sfun() const { return Sfun; }
-  SExpr *arg() const { return Arg ? Arg : Sfun; }
+  SExpr *sfun() { return Sfun.get(); }
+  const SExpr *sfun() const { return Sfun.get(); }
 
-  bool isDelegation() const { return Arg == 0; }
+  SExpr *arg() { return Arg.get() ? Arg.get() : Sfun.get(); }
+  const SExpr *arg() const { return Arg.get() ? Arg.get() : Sfun.get(); }
+
+  bool isDelegation() const { return Arg == nullptr; }
 
   template <class V> typename V::R_SExpr traverse(V &Visitor) {
     typename V::R_SExpr Nf = Visitor.traverse(Sfun);
-    typename V::R_SExpr Na = Arg ? Visitor.traverse(Arg) : 0;
+    typename V::R_SExpr Na = Arg.get() ? Visitor.traverse(Arg) : nullptr;
     return Visitor.reduceSApply(*this, Nf, Na);
   }
 
   template <class C> typename C::CType compare(SApply* E, C& Cmp) {
-    typename C::CType Ct = Cmp.compare(Sfun, E->Sfun);
-    if (Cmp.notTrue(Ct) || (!Arg && !E->Arg))
+    typename C::CType Ct = Cmp.compare(sfun(), E->sfun());
+    if (Cmp.notTrue(Ct) || (!arg() && !E->arg()))
       return Ct;
     return Cmp.compare(arg(), E->arg());
   }
 
 private:
-  SExpr *Sfun;
-  SExpr *Arg;
+  SExprRef Sfun;
+  SExprRef Arg;
 };
 
 
@@ -693,8 +796,10 @@ public:
       : SExpr(COP_Project), Rec(R), Cvdecl(Cvd) {}
   Project(const Project &P, SExpr *R) : SExpr(P), Rec(R), Cvdecl(P.Cvdecl) {}
 
-  SExpr *record() const { return Rec; }
-  clang::ValueDecl *clangValueDecl() const { return Cvdecl; }
+  SExpr *record() { return Rec.get(); }
+  const SExpr *record() const { return Rec.get(); }
+
+  const clang::ValueDecl *clangValueDecl() const { return Cvdecl; }
 
   StringRef slotName() const { return Cvdecl->getName(); }
 
@@ -704,14 +809,14 @@ public:
   }
 
   template <class C> typename C::CType compare(Project* E, C& Cmp) {
-    typename C::CType Ct = Cmp.compare(Rec, E->Rec);
+    typename C::CType Ct = Cmp.compare(record(), E->record());
     if (Cmp.notTrue(Ct))
       return Ct;
     return Cmp.comparePointers(Cvdecl, E->Cvdecl);
   }
 
 private:
-  SExpr *Rec;
+  SExprRef Rec;
   clang::ValueDecl *Cvdecl;
 };
 
@@ -721,11 +826,13 @@ class Call : public SExpr {
 public:
   static bool classof(const SExpr *E) { return E->opcode() == COP_Call; }
 
-  Call(SExpr *T, const clang::CallExpr *Ce = 0)
+  Call(SExpr *T, const clang::CallExpr *Ce = nullptr)
       : SExpr(COP_Call), Target(T), Cexpr(Ce) {}
   Call(const Call &C, SExpr *T) : SExpr(C), Target(T), Cexpr(C.Cexpr) {}
 
-  SExpr *target() const { return Target; }
+  SExpr *target() { return Target.get(); }
+  const SExpr *target() const { return Target.get(); }
+
   const clang::CallExpr *clangCallExpr() { return Cexpr; }
 
   template <class V> typename V::R_SExpr traverse(V &Visitor) {
@@ -734,11 +841,11 @@ public:
   }
 
   template <class C> typename C::CType compare(Call* E, C& Cmp) {
-    return Cmp.compare(Target, E->Target);
+    return Cmp.compare(target(), E->target());
   }
 
 private:
-  SExpr *Target;
+  SExprRef Target;
   const clang::CallExpr *Cexpr;
 };
 
@@ -761,7 +868,9 @@ public:
   }
 
   AllocKind kind() const { return static_cast<AllocKind>(Flags); }
-  SExpr*    dataType() const { return Dtype; }
+
+  SExpr* dataType() { return Dtype.get(); }
+  const SExpr* dataType() const { return Dtype.get(); }
 
   template <class V> typename V::R_SExpr traverse(V &Visitor) {
     typename V::R_SExpr Nd = Visitor.traverse(Dtype);
@@ -772,11 +881,11 @@ public:
     typename C::CType Ct = Cmp.compareIntegers(kind(), E->kind());
     if (Cmp.notTrue(Ct))
       return Ct;
-    return Cmp.compare(Dtype, E->Dtype);
+    return Cmp.compare(dataType(), E->dataType());
   }
 
 private:
-  SExpr* Dtype;
+  SExprRef Dtype;
 };
 
 
@@ -788,7 +897,8 @@ public:
   Load(SExpr *P) : SExpr(COP_Load), Ptr(P) {}
   Load(const Load &L, SExpr *P) : SExpr(L), Ptr(P) {}
 
-  SExpr *pointer() { return Ptr; }
+  SExpr *pointer() { return Ptr.get(); }
+  const SExpr *pointer() const { return Ptr.get(); }
 
   template <class V> typename V::R_SExpr traverse(V &Visitor) {
     typename V::R_SExpr Np = Visitor.traverse(Ptr);
@@ -796,11 +906,11 @@ public:
   }
 
   template <class C> typename C::CType compare(Load* E, C& Cmp) {
-    return Cmp.compare(Ptr, E->Ptr);
+    return Cmp.compare(pointer(), E->pointer());
   }
 
 private:
-  SExpr *Ptr;
+  SExprRef Ptr;
 };
 
 
@@ -809,27 +919,30 @@ class Store : public SExpr {
 public:
   static bool classof(const SExpr *E) { return E->opcode() == COP_Store; }
 
-  Store(SExpr *P, SExpr *V) : SExpr(COP_Store), Ptr(P) {}
-  Store(const Store &S, SExpr *P, SExpr *V) : SExpr(S), Ptr(P) {}
+  Store(SExpr *P, SExpr *V) : SExpr(COP_Store), Dest(P), Source(V) {}
+  Store(const Store &S, SExpr *P, SExpr *V) : SExpr(S), Dest(P), Source(V) {}
+
+  SExpr *destination() { return Dest.get(); }  // Address to store to
+  const SExpr *destination() const { return Dest.get(); }
 
-  SExpr *pointer() const { return Ptr; }
-  SExpr *value() const { return Value; }
+  SExpr *source() { return Source.get(); }     // Value to store
+  const SExpr *source() const { return Source.get(); }
 
   template <class V> typename V::R_SExpr traverse(V &Visitor) {
-    typename V::R_SExpr Np = Visitor.traverse(Ptr);
-    typename V::R_SExpr Nv = Visitor.traverse(Value);
+    typename V::R_SExpr Np = Visitor.traverse(Dest);
+    typename V::R_SExpr Nv = Visitor.traverse(Source);
     return Visitor.reduceStore(*this, Np, Nv);
   }
 
   template <class C> typename C::CType compare(Store* E, C& Cmp) {
-    typename C::CType Ct = Cmp.compare(Ptr, E->Ptr);
+    typename C::CType Ct = Cmp.compare(destination(), E->destination());
     if (Cmp.notTrue(Ct))
       return Ct;
-    return Cmp.compare(Value, E->Value);
+    return Cmp.compare(source(), E->source());
   }
 
-  SExpr *Ptr;
-  SExpr *Value;
+  SExprRef Dest;
+  SExprRef Source;
 };
 
 
@@ -845,7 +958,8 @@ public:
 
   TIL_UnaryOpcode unaryOpcode() { return static_cast<TIL_UnaryOpcode>(Flags); }
 
-  SExpr *expr() const { return Expr0; }
+  SExpr *expr() { return Expr0.get(); }
+  const SExpr *expr() const { return Expr0.get(); }
 
   template <class V> typename V::R_SExpr traverse(V &Visitor) {
     typename V::R_SExpr Ne = Visitor.traverse(Expr0);
@@ -857,11 +971,11 @@ public:
       Cmp.compareIntegers(unaryOpcode(), E->unaryOpcode());
     if (Cmp.notTrue(Ct))
       return Ct;
-    return Cmp.compare(Expr0, E->Expr0);
+    return Cmp.compare(expr(), E->expr());
   }
 
 private:
-  SExpr *Expr0;
+  SExprRef Expr0;
 };
 
 
@@ -883,8 +997,11 @@ public:
     return static_cast<TIL_BinaryOpcode>(Flags);
   }
 
-  SExpr *expr0() const { return Expr0; }
-  SExpr *expr1() const { return Expr1; }
+  SExpr *expr0() { return Expr0.get(); }
+  const SExpr *expr0() const { return Expr0.get(); }
+
+  SExpr *expr1() { return Expr1.get(); }
+  const SExpr *expr1() const { return Expr1.get(); }
 
   template <class V> typename V::R_SExpr traverse(V &Visitor) {
     typename V::R_SExpr Ne0 = Visitor.traverse(Expr0);
@@ -897,15 +1014,15 @@ public:
       Cmp.compareIntegers(binaryOpcode(), E->binaryOpcode());
     if (Cmp.notTrue(Ct))
       return Ct;
-    Ct = Cmp.compare(Expr0, E->Expr0);
+    Ct = Cmp.compare(expr0(), E->expr0());
     if (Cmp.notTrue(Ct))
       return Ct;
-    return Cmp.compare(Expr1, E->Expr1);
+    return Cmp.compare(expr1(), E->expr1());
   }
 
 private:
-  SExpr *Expr0;
-  SExpr *Expr1;
+  SExprRef Expr0;
+  SExprRef Expr1;
 };
 
 
@@ -917,9 +1034,12 @@ public:
   Cast(TIL_CastOpcode Op, SExpr *E) : SExpr(COP_Cast), Expr0(E) { Flags = Op; }
   Cast(const Cast &C, SExpr *E) : SExpr(C), Expr0(E) { Flags = C.Flags; }
 
-  TIL_BinaryOpcode castOpcode() { return static_cast<TIL_BinaryOpcode>(Flags); }
+  TIL_BinaryOpcode castOpcode() {
+    return static_cast<TIL_BinaryOpcode>(Flags);
+  }
 
-  SExpr *expr() const { return Expr0; }
+  SExpr *expr() { return Expr0.get(); }
+  const SExpr *expr() const { return Expr0.get(); }
 
   template <class V> typename V::R_SExpr traverse(V &Visitor) {
     typename V::R_SExpr Ne = Visitor.traverse(Expr0);
@@ -931,11 +1051,11 @@ public:
       Cmp.compareIntegers(castOpcode(), E->castOpcode());
     if (Cmp.notTrue(Ct))
       return Ct;
-    return Cmp.compare(Expr0, E->Expr0);
+    return Cmp.compare(expr(), E->expr());
   }
 
 private:
-  SExpr *Expr0;
+  SExprRef Expr0;
 };
 
 
@@ -954,12 +1074,13 @@ public:
   static bool classof(const SExpr *E) { return E->opcode() == COP_SCFG; }
 
   SCFG(MemRegionRef A, unsigned Nblocks)
-      : SExpr(COP_SCFG), Blocks(A, Nblocks), Entry(0), Exit(0) {}
+      : SExpr(COP_SCFG), Blocks(A, Nblocks), Entry(nullptr), Exit(nullptr) {}
   SCFG(const SCFG &Cfg, BlockArray &Ba) // steals memory from ba
       : SExpr(COP_SCFG),
         Blocks(Ba, true),
-        Entry(0),
-        Exit(0) { /* TODO: set entry and exit! */
+        Entry(nullptr),
+        Exit(nullptr) {
+    // TODO: set entry and exit!
   }
 
   typedef BlockArray::iterator iterator;
@@ -1001,11 +1122,13 @@ class BasicBlock {
 public:
   typedef SimpleArray<Variable*> VarArray;
 
-  BasicBlock(MemRegionRef A, unsigned Nargs, unsigned Nins, SExpr *Term = 0)
-      : BlockID(0), Parent(0), Args(A, Nargs), Instrs(A, Nins),
+  BasicBlock(MemRegionRef A, unsigned Nargs, unsigned Nins,
+             SExpr *Term = nullptr)
+      : BlockID(0), Parent(nullptr), Args(A, Nargs), Instrs(A, Nins),
         Terminator(Term) {}
   BasicBlock(const BasicBlock &B, VarArray &As, VarArray &Is, SExpr *T)
-      : BlockID(0), Parent(0), Args(As, true), Instrs(Is, true), Terminator(T)
+      : BlockID(0), Parent(nullptr), Args(As, true), Instrs(Is, true),
+        Terminator(T)
   {}
 
   unsigned blockID() const { return BlockID; }
@@ -1017,12 +1140,12 @@ public:
   const VarArray &instructions() const { return Instrs; }
   VarArray &instructions() { return Instrs; }
 
-  const SExpr *terminator() const { return Terminator; }
-  SExpr *terminator() { return Terminator; }
+  const SExpr *terminator() const { return Terminator.get(); }
+  SExpr *terminator() { return Terminator.get(); }
 
   void setParent(BasicBlock *P) { Parent = P; }
   void setBlockID(unsigned i) { BlockID = i; }
-  void setTerminator(SExpr *E) { Terminator = E; }
+  void setTerminator(SExpr *E) { Terminator.reset(E); }
   void addArgument(Variable *V) { Args.push_back(V); }
   void addInstr(Variable *V) { Args.push_back(V); }
 
@@ -1063,7 +1186,7 @@ private:
                         // The parent dominates this block.
   VarArray Args;        // Phi nodes
   VarArray Instrs;
-  SExpr *Terminator;
+  SExprRef Terminator;
 };
 
 
@@ -1083,7 +1206,8 @@ typename V::R_SExpr SCFG::traverse(V &Vi
 
 class Phi : public SExpr {
 public:
-  typedef SimpleArray<SExpr *> ValArray;
+  // TODO: change to SExprRef
+  typedef SimpleArray<SExpr*> ValArray;
 
   static bool classof(const SExpr *E) { return E->opcode() == COP_Phi; }
 
@@ -1097,7 +1221,8 @@ public:
   template <class V> typename V::R_SExpr traverse(V &Visitor) {
     typename V::template Container<typename V::R_SExpr> Nvs(Visitor,
                                                             Values.size());
-    for (ValArray::iterator I = Values.begin(), E = Values.end(); I != E; ++I) {
+    for (ValArray::iterator I = Values.begin(), E = Values.end();
+         I != E; ++I) {
       typename V::R_SExpr Nv = Visitor.traverse(*I);
       Nvs.push_back(Nv);
     }
@@ -1211,6 +1336,10 @@ public:
   //   TRV_Normal
   //   TRV_Lazy   -- e may need to be traversed lazily, using a Future.
   //   TRV_Tail   -- e occurs in a tail position
+  typename R::R_SExpr traverse(SExprRef &E, TIL_TraversalKind K = TRV_Normal) {
+    return traverse(E.get(), K);
+  }
+
   typename R::R_SExpr traverse(SExpr *E, TIL_TraversalKind K = TRV_Normal) {
     return traverseByCase(E);
   }
@@ -1268,7 +1397,7 @@ public:
 
 public:
   R_SExpr reduceNull() {
-    return 0;
+    return nullptr;
   }
   // R_SExpr reduceFuture(...)  is never used.
 
@@ -1319,7 +1448,7 @@ public:
     return new (Arena) Store(Orig, E0, E1);
   }
   R_SExpr reduceUnaryOp(UnaryOp &Orig, R_SExpr E0) {
-    return new (Arena) UnaryOp(Orig);
+    return new (Arena) UnaryOp(Orig, E0);
   }
   R_SExpr reduceBinaryOp(BinaryOp &Orig, R_SExpr E0, R_SExpr E1) {
     return new (Arena) BinaryOp(Orig, E0, E1);
@@ -1448,10 +1577,12 @@ public:
 
   BasicBlock *reduceBasicBlock(BasicBlock &Orig, Container<Variable *> &As,
                                Container<Variable *> &Is, R_SExpr T) {
-    return (As.Success && Is.Success && T) ? &Orig : 0;
+    return (As.Success && Is.Success && T) ? &Orig : nullptr;
   }
 
-  Variable *enterScope(Variable &Orig, R_SExpr E0) { return E0 ? &Orig : 0; }
+  Variable *enterScope(Variable &Orig, R_SExpr E0) {
+    return E0 ? &Orig : nullptr;
+  }
   void exitScope(const Variable &Orig) {}
 
   void enterCFG(SCFG &Cfg) {}
@@ -1739,9 +1870,9 @@ protected:
   }
 
   void printStore(Store *E, StreamType &SS) {
-    self()->printSExpr(E->pointer(), SS, Prec_Other-1);
+    self()->printSExpr(E->destination(), SS, Prec_Other-1);
     SS << " = ";
-    self()->printSExpr(E->value(), SS, Prec_Other-1);
+    self()->printSExpr(E->source(), SS, Prec_Other-1);
   }
 
   void printUnaryOp(UnaryOp *E, StreamType &SS) {

Modified: cfe/trunk/lib/Analysis/ThreadSafetyCommon.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Analysis/ThreadSafetyCommon.cpp?rev=205745&r1=205744&r2=205745&view=diff
==============================================================================
--- cfe/trunk/lib/Analysis/ThreadSafetyCommon.cpp (original)
+++ cfe/trunk/lib/Analysis/ThreadSafetyCommon.cpp Mon Apr  7 17:56:24 2014
@@ -312,26 +312,29 @@ til::SExpr *SExprBuilder::translateBinar
 // Build a complete SCFG from a clang CFG.
 class SCFGBuilder : public CFGVisitor {
 public:
-  // return true if E should be included in the SCFG
-  bool includeExpr(til::SExpr* E) {
+  til::Variable *addStatement(til::SExpr* E, const Stmt *S) {
     if (!E)
-      return false;
-    if (E->opcode() == til::COP_Variable)
-      return false;
-    if (E->opcode() == til::COP_LiteralPtr)
-      return false;
-    return true;
+      return 0;
+    if (til::ThreadSafetyTIL::isTrivial(E))
+      return 0;
+
+    til::Variable *V = new (Arena) til::Variable(til::Variable::VK_Let, E);
+    V->setID(CurrentBlockID, CurrentVarID++);
+    CurrentBB->addInstr(V);
+    if (S)
+      BuildEx.insertStmt(S, V);
+    return V;
   }
 
   // Enter the CFG for Decl D, and perform any initial setup operations.
   void enterCFG(CFG *Cfg, const NamedDecl *D, const CFGBlock *First) {
-    Scfg = new til::SCFG(Arena, Cfg->getNumBlockIDs());
+    Scfg = new (Arena) til::SCFG(Arena, Cfg->getNumBlockIDs());
     CallCtx = new SExprBuilder::CallingContext(D);
   }
 
   // Enter a CFGBlock.
   void enterCFGBlock(const CFGBlock *B) {
-    CurrentBB = new til::BasicBlock(Arena, 0, B->size());
+    CurrentBB = new (Arena) til::BasicBlock(Arena, 0, B->size());
     CurrentBB->setBlockID(CurrentBlockID);
     CurrentVarID = 0;
     Scfg->add(CurrentBB);
@@ -340,16 +343,17 @@ public:
   // Process an ordinary statement.
   void handleStatement(const Stmt *S) {
     til::SExpr *E = BuildEx.translate(S, CallCtx);
-    if (includeExpr(E)) {
-      til::Variable *V = new til::Variable(til::Variable::VK_Let, E);
-      V->setID(CurrentBlockID, CurrentVarID++);
-      CurrentBB->addInstr(V);
-      BuildEx.insertStmt(S, V);
-    }
+    addStatement(E, S);
   }
 
   // Process a destructor call
-  void handleDestructorCall(const VarDecl *VD, const CXXDestructorDecl *DD) {}
+  void handleDestructorCall(const VarDecl *VD, const CXXDestructorDecl *DD) {
+    til::SExpr *Sf = new (Arena) til::LiteralPtr(VD);
+    til::SExpr *Dr = new (Arena) til::LiteralPtr(DD);
+    til::SExpr *Ap = new (Arena) til::Apply(Dr, Sf);
+    til::SExpr *E = new (Arena) til::Call(Ap, 0);
+    addStatement(E, nullptr);
+  }
 
   // Process a successor edge.
   void handleSuccessor(const CFGBlock *Succ) {}
@@ -364,12 +368,21 @@ public:
   }
 
   // Leave the CFG, and perform any final cleanup operations.
-  void exitCFG(const CFGBlock *Last) {}
+  void exitCFG(const CFGBlock *Last) {
+    if (CallCtx) {
+      delete CallCtx;
+      CallCtx = nullptr;
+    }
+  }
 
   SCFGBuilder(til::MemRegionRef A)
       : Arena(A), Scfg(0), CurrentBB(0), CurrentBlockID(0),
-        BuildEx(A, new SExprBuilder::StatementMap())
+        CallCtx(0), SMap(new SExprBuilder::StatementMap()),
+        BuildEx(A, SMap)
   { }
+  ~SCFGBuilder() {
+    delete SMap;
+  }
 
   til::SCFG *getCFG() const { return Scfg; }
 
@@ -380,8 +393,9 @@ private:
   unsigned CurrentBlockID;
   unsigned CurrentVarID;
 
-  SExprBuilder BuildEx;
   SExprBuilder::CallingContext *CallCtx;
+  SExprBuilder::StatementMap *SMap;
+  SExprBuilder BuildEx;
 };
 
 





More information about the cfe-commits mailing list