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