r206907 - Thread safety analysis: add array operations to SExpr.

DeLesley Hutchins delesley at google.com
Tue Apr 22 10:31:23 PDT 2014


Author: delesley
Date: Tue Apr 22 12:31:23 2014
New Revision: 206907

URL: http://llvm.org/viewvc/llvm-project?rev=206907&view=rev
Log:
Thread safety analysis: add array operations to SExpr.

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

Modified: cfe/trunk/include/clang/Analysis/Analyses/ThreadSafetyOps.def
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Analysis/Analyses/ThreadSafetyOps.def?rev=206907&r1=206906&r2=206907&view=diff
==============================================================================
--- cfe/trunk/include/clang/Analysis/Analyses/ThreadSafetyOps.def (original)
+++ cfe/trunk/include/clang/Analysis/Analyses/ThreadSafetyOps.def Tue Apr 22 12:31:23 2014
@@ -33,6 +33,8 @@ TIL_OPCODE_DEF(Call)
 TIL_OPCODE_DEF(Alloc)
 TIL_OPCODE_DEF(Load)
 TIL_OPCODE_DEF(Store)
+TIL_OPCODE_DEF(ArrayFirst)
+TIL_OPCODE_DEF(ArrayAdd)
 
 TIL_OPCODE_DEF(UnaryOp)
 TIL_OPCODE_DEF(BinaryOp)

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=206907&r1=206906&r2=206907&view=diff
==============================================================================
--- cfe/trunk/include/clang/Analysis/Analyses/ThreadSafetyTIL.h (original)
+++ cfe/trunk/include/clang/Analysis/Analyses/ThreadSafetyTIL.h Tue Apr 22 12:31:23 2014
@@ -798,6 +798,7 @@ private:
 
 
 // Store a value to memory.
+// Source is a pointer, destination is the value to store.
 class Store : public SExpr {
 public:
   static bool classof(const SExpr *E) { return E->opcode() == COP_Store; }
@@ -830,6 +831,68 @@ private:
 };
 
 
+// If p is a reference to an array, then first(p) is a reference to the first
+// element.  The usual array notation p[i]  becomes first(p + i).
+class ArrayFirst : public SExpr {
+public:
+  static bool classof(const SExpr *E) { return E->opcode() == COP_ArrayFirst; }
+
+  ArrayFirst(SExpr *A) : SExpr(COP_ArrayFirst), Array(A) {}
+  ArrayFirst(const ArrayFirst &E, SExpr *A) : SExpr(E), Array(A) {}
+
+  SExpr *array() { return Array.get(); }
+  const SExpr *array() const { return Array.get(); }
+
+  template <class V> typename V::R_SExpr traverse(V &Visitor) {
+    typename V::R_SExpr Na = Visitor.traverse(Array);
+    return Visitor.reduceArrayFirst(*this, Na);
+  }
+
+  template <class C> typename C::CType compare(ArrayFirst* E, C& Cmp) {
+    return Cmp.compare(array(), E->array());
+  }
+
+private:
+  SExprRef Array;
+};
+
+
+// Pointer arithmetic, restricted to arrays only.
+// If p is a reference to an array, then p + n, where n is an integer, is
+// a reference to a subarray.
+class ArrayAdd : public SExpr {
+public:
+  static bool classof(const SExpr *E) { return E->opcode() == COP_ArrayAdd; }
+
+  ArrayAdd(SExpr *A, SExpr *N) : SExpr(COP_ArrayAdd), Array(A), Index(N) {}
+  ArrayAdd(const ArrayAdd &E, SExpr *A, SExpr *N)
+    : SExpr(E), Array(A), Index(N) {}
+
+  SExpr *array() { return Array.get(); }
+  const SExpr *array() const { return Array.get(); }
+
+  SExpr *index() { return Index.get(); }
+  const SExpr *index() const { return Index.get(); }
+
+  template <class V> typename V::R_SExpr traverse(V &Visitor) {
+    typename V::R_SExpr Na = Visitor.traverse(Array);
+    typename V::R_SExpr Ni = Visitor.traverse(Index);
+    return Visitor.reduceArrayAdd(*this, Na, Ni);
+  }
+
+  template <class C> typename C::CType compare(ArrayAdd* E, C& Cmp) {
+    typename C::CType Ct = Cmp.compare(array(), E->array());
+    if (Cmp.notTrue(Ct))
+      return Ct;
+    return Cmp.compare(index(), E->index());
+  }
+
+private:
+  SExprRef Array;
+  SExprRef Index;
+};
+
+
 // Simple unary operation -- e.g. !, ~, etc.
 class UnaryOp : public SExpr {
 public:

Modified: cfe/trunk/include/clang/Analysis/Analyses/ThreadSafetyTraverse.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Analysis/Analyses/ThreadSafetyTraverse.h?rev=206907&r1=206906&r2=206907&view=diff
==============================================================================
--- cfe/trunk/include/clang/Analysis/Analyses/ThreadSafetyTraverse.h (original)
+++ cfe/trunk/include/clang/Analysis/Analyses/ThreadSafetyTraverse.h Tue Apr 22 12:31:23 2014
@@ -169,6 +169,12 @@ public:
   R_SExpr reduceStore(Store &Orig, R_SExpr E0, R_SExpr E1) {
     return new (Arena) Store(Orig, E0, E1);
   }
+  R_SExpr reduceArrayFirst(ArrayFirst &Orig, R_SExpr E0) {
+    return new (Arena) ArrayFirst(Orig, E0);
+  }
+  R_SExpr reduceArrayAdd(ArrayAdd &Orig, R_SExpr E0, R_SExpr E1) {
+    return new (Arena) ArrayAdd(Orig, E0, E1);
+  }
   R_SExpr reduceUnaryOp(UnaryOp &Orig, R_SExpr E0) {
     return new (Arena) UnaryOp(Orig, E0);
   }
@@ -279,6 +285,10 @@ public:
   R_SExpr reduceAlloc(Alloc &Orig, R_SExpr E0) { return E0; }
   R_SExpr reduceLoad(Load &Orig, R_SExpr E0) { return E0; }
   R_SExpr reduceStore(Store &Orig, R_SExpr E0, R_SExpr E1) { return E0 && E1; }
+  R_SExpr reduceArrayFirst(Store &Orig, R_SExpr E0) { return E0; }
+  R_SExpr reduceArrayAdd(Store &Orig, R_SExpr E0, R_SExpr E1) {
+    return E0 && E1;
+  }
   R_SExpr reduceUnaryOp(UnaryOp &Orig, R_SExpr E0) { return E0; }
   R_SExpr reduceBinaryOp(BinaryOp &Orig, R_SExpr E0, R_SExpr E1) {
     return E0 && E1;
@@ -454,6 +464,8 @@ protected:
       case COP_Alloc:      return Prec_Other;
       case COP_Load:       return Prec_Postfix;
       case COP_Store:      return Prec_Other;
+      case COP_ArrayFirst: return Prec_Postfix;
+      case COP_ArrayAdd:   return Prec_Postfix;
 
       case COP_UnaryOp:    return Prec_Unary;
       case COP_BinaryOp:   return Prec_Binary;
@@ -645,6 +657,23 @@ protected:
     self()->printSExpr(E->source(), SS, Prec_Other-1);
   }
 
+  void printArrayFirst(ArrayFirst *E, StreamType &SS) {
+    self()->printSExpr(E->array(), SS, Prec_Postfix);
+    if (ArrayAdd *A = dyn_cast_or_null<ArrayAdd>(E)) {
+      SS << "[";
+      printSExpr(A->index(), SS, Prec_MAX);
+      SS << "]";
+      return;
+    }
+    SS << "[0]";
+  }
+
+  void printArrayAdd(ArrayAdd *E, StreamType &SS) {
+    self()->printSExpr(E->array(), SS, Prec_Postfix);
+    SS << " + ";
+    self()->printSExpr(E->index(), SS, Prec_Atom);
+  }
+
   void printUnaryOp(UnaryOp *E, StreamType &SS) {
     self()->printSExpr(E->expr(), SS, Prec_Unary);
   }

Modified: cfe/trunk/lib/Analysis/ThreadSafetyCommon.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Analysis/ThreadSafetyCommon.cpp?rev=206907&r1=206906&r2=206907&view=diff
==============================================================================
--- cfe/trunk/lib/Analysis/ThreadSafetyCommon.cpp (original)
+++ cfe/trunk/lib/Analysis/ThreadSafetyCommon.cpp Tue Apr 22 12:31:23 2014
@@ -399,7 +399,10 @@ til::SExpr *SExprBuilder::translateCastE
 til::SExpr *
 SExprBuilder::translateArraySubscriptExpr(const ArraySubscriptExpr *E,
                                           CallingContext *Ctx) {
-  return new (Arena) til::Undefined(E);
+  til::SExpr *E0 = translate(E->getBase(), Ctx);
+  til::SExpr *E1 = translate(E->getIdx(), Ctx);
+  auto *AA = new (Arena) til::ArrayAdd(E0, E1);
+  return new (Arena) til::ArrayFirst(AA);
 }
 
 





More information about the cfe-commits mailing list