1402aa0698fec81e574818a0a6c2000fac0b2c4c6Caitlin Sadowski//===- ThreadSafety.cpp ----------------------------------------*- C++ --*-===//
2402aa0698fec81e574818a0a6c2000fac0b2c4c6Caitlin Sadowski//
3402aa0698fec81e574818a0a6c2000fac0b2c4c6Caitlin Sadowski//                     The LLVM Compiler Infrastructure
4402aa0698fec81e574818a0a6c2000fac0b2c4c6Caitlin Sadowski//
5402aa0698fec81e574818a0a6c2000fac0b2c4c6Caitlin Sadowski// This file is distributed under the University of Illinois Open Source
6402aa0698fec81e574818a0a6c2000fac0b2c4c6Caitlin Sadowski// License. See LICENSE.TXT for details.
7402aa0698fec81e574818a0a6c2000fac0b2c4c6Caitlin Sadowski//
8402aa0698fec81e574818a0a6c2000fac0b2c4c6Caitlin Sadowski//===----------------------------------------------------------------------===//
9402aa0698fec81e574818a0a6c2000fac0b2c4c6Caitlin Sadowski//
10402aa0698fec81e574818a0a6c2000fac0b2c4c6Caitlin Sadowski// A intra-procedural analysis for thread safety (e.g. deadlocks and race
11402aa0698fec81e574818a0a6c2000fac0b2c4c6Caitlin Sadowski// conditions), based off of an annotation system.
12402aa0698fec81e574818a0a6c2000fac0b2c4c6Caitlin Sadowski//
13b96e74f79cc9f64a8d0080d4eff5d0431d2a48cfAaron Ballman// See http://clang.llvm.org/docs/LanguageExtensions.html#thread-safety-annotation-checking
14b96e74f79cc9f64a8d0080d4eff5d0431d2a48cfAaron Ballman// for more information.
15402aa0698fec81e574818a0a6c2000fac0b2c4c6Caitlin Sadowski//
16402aa0698fec81e574818a0a6c2000fac0b2c4c6Caitlin Sadowski//===----------------------------------------------------------------------===//
17402aa0698fec81e574818a0a6c2000fac0b2c4c6Caitlin Sadowski
18402aa0698fec81e574818a0a6c2000fac0b2c4c6Caitlin Sadowski#include "clang/Analysis/Analyses/ThreadSafety.h"
192fa67efeaf66a9332c30a026dc1c21bef6c33a6cBenjamin Kramer#include "clang/AST/Attr.h"
20402aa0698fec81e574818a0a6c2000fac0b2c4c6Caitlin Sadowski#include "clang/AST/DeclCXX.h"
21402aa0698fec81e574818a0a6c2000fac0b2c4c6Caitlin Sadowski#include "clang/AST/ExprCXX.h"
22402aa0698fec81e574818a0a6c2000fac0b2c4c6Caitlin Sadowski#include "clang/AST/StmtCXX.h"
23402aa0698fec81e574818a0a6c2000fac0b2c4c6Caitlin Sadowski#include "clang/AST/StmtVisitor.h"
2455fc873017f10f6f566b182b70f6fc22aefa3464Chandler Carruth#include "clang/Analysis/Analyses/PostOrderCFGView.h"
2555fc873017f10f6f566b182b70f6fc22aefa3464Chandler Carruth#include "clang/Analysis/AnalysisContext.h"
2655fc873017f10f6f566b182b70f6fc22aefa3464Chandler Carruth#include "clang/Analysis/CFG.h"
2755fc873017f10f6f566b182b70f6fc22aefa3464Chandler Carruth#include "clang/Analysis/CFGStmtMap.h"
2896fac6a7fe89deff7860e536febbd4ae17bb57f3DeLesley Hutchins#include "clang/Basic/OperatorKinds.h"
292fa67efeaf66a9332c30a026dc1c21bef6c33a6cBenjamin Kramer#include "clang/Basic/SourceLocation.h"
302fa67efeaf66a9332c30a026dc1c21bef6c33a6cBenjamin Kramer#include "clang/Basic/SourceManager.h"
31402aa0698fec81e574818a0a6c2000fac0b2c4c6Caitlin Sadowski#include "llvm/ADT/BitVector.h"
32402aa0698fec81e574818a0a6c2000fac0b2c4c6Caitlin Sadowski#include "llvm/ADT/FoldingSet.h"
33402aa0698fec81e574818a0a6c2000fac0b2c4c6Caitlin Sadowski#include "llvm/ADT/ImmutableMap.h"
34402aa0698fec81e574818a0a6c2000fac0b2c4c6Caitlin Sadowski#include "llvm/ADT/PostOrderIterator.h"
35402aa0698fec81e574818a0a6c2000fac0b2c4c6Caitlin Sadowski#include "llvm/ADT/SmallVector.h"
36402aa0698fec81e574818a0a6c2000fac0b2c4c6Caitlin Sadowski#include "llvm/ADT/StringRef.h"
37b37d2b5c0819d9ef596c7baec1e0be0d7c45b547DeLesley Hutchins#include "llvm/Support/raw_ostream.h"
38402aa0698fec81e574818a0a6c2000fac0b2c4c6Caitlin Sadowski#include <algorithm>
39b37d2b5c0819d9ef596c7baec1e0be0d7c45b547DeLesley Hutchins#include <utility>
40402aa0698fec81e574818a0a6c2000fac0b2c4c6Caitlin Sadowski#include <vector>
41402aa0698fec81e574818a0a6c2000fac0b2c4c6Caitlin Sadowski
42402aa0698fec81e574818a0a6c2000fac0b2c4c6Caitlin Sadowskiusing namespace clang;
43402aa0698fec81e574818a0a6c2000fac0b2c4c6Caitlin Sadowskiusing namespace thread_safety;
44402aa0698fec81e574818a0a6c2000fac0b2c4c6Caitlin Sadowski
4519903465e960329c0d5d93327f4046d036b0bc75Caitlin Sadowski// Key method definition
4619903465e960329c0d5d93327f4046d036b0bc75Caitlin SadowskiThreadSafetyHandler::~ThreadSafetyHandler() {}
4719903465e960329c0d5d93327f4046d036b0bc75Caitlin Sadowski
48402aa0698fec81e574818a0a6c2000fac0b2c4c6Caitlin Sadowskinamespace {
49a60448d6dfc91f4c30987e237bf70ef50ac7705bDeLesley Hutchins
50a74b715cdc37c4523818a4018faae99d977aa537DeLesley Hutchins/// SExpr implements a simple expression language that is used to store,
51a74b715cdc37c4523818a4018faae99d977aa537DeLesley Hutchins/// compare, and pretty-print C++ expressions.  Unlike a clang Expr, a SExpr
52a74b715cdc37c4523818a4018faae99d977aa537DeLesley Hutchins/// does not capture surface syntax, and it does not distinguish between
53a74b715cdc37c4523818a4018faae99d977aa537DeLesley Hutchins/// C++ concepts, like pointers and references, that have no real semantic
54a74b715cdc37c4523818a4018faae99d977aa537DeLesley Hutchins/// differences.  This simplicity allows SExprs to be meaningfully compared,
55a74b715cdc37c4523818a4018faae99d977aa537DeLesley Hutchins/// e.g.
56a74b715cdc37c4523818a4018faae99d977aa537DeLesley Hutchins///        (x)          =  x
57a74b715cdc37c4523818a4018faae99d977aa537DeLesley Hutchins///        (*this).foo  =  this->foo
58a74b715cdc37c4523818a4018faae99d977aa537DeLesley Hutchins///        *&a          =  a
59402aa0698fec81e574818a0a6c2000fac0b2c4c6Caitlin Sadowski///
60402aa0698fec81e574818a0a6c2000fac0b2c4c6Caitlin Sadowski/// Thread-safety analysis works by comparing lock expressions.  Within the
61402aa0698fec81e574818a0a6c2000fac0b2c4c6Caitlin Sadowski/// body of a function, an expression such as "x->foo->bar.mu" will resolve to
62402aa0698fec81e574818a0a6c2000fac0b2c4c6Caitlin Sadowski/// a particular mutex object at run-time.  Subsequent occurrences of the same
63402aa0698fec81e574818a0a6c2000fac0b2c4c6Caitlin Sadowski/// expression (where "same" means syntactic equality) will refer to the same
64402aa0698fec81e574818a0a6c2000fac0b2c4c6Caitlin Sadowski/// run-time object if three conditions hold:
65402aa0698fec81e574818a0a6c2000fac0b2c4c6Caitlin Sadowski/// (1) Local variables in the expression, such as "x" have not changed.
66402aa0698fec81e574818a0a6c2000fac0b2c4c6Caitlin Sadowski/// (2) Values on the heap that affect the expression have not changed.
67402aa0698fec81e574818a0a6c2000fac0b2c4c6Caitlin Sadowski/// (3) The expression involves only pure function calls.
68e0eaa8531f8fd9189710aac3b6f3aadb62bb14d1DeLesley Hutchins///
69402aa0698fec81e574818a0a6c2000fac0b2c4c6Caitlin Sadowski/// The current implementation assumes, but does not verify, that multiple uses
70402aa0698fec81e574818a0a6c2000fac0b2c4c6Caitlin Sadowski/// of the same lock expression satisfies these criteria.
71a74b715cdc37c4523818a4018faae99d977aa537DeLesley Hutchinsclass SExpr {
72a74b715cdc37c4523818a4018faae99d977aa537DeLesley Hutchinsprivate:
73a74b715cdc37c4523818a4018faae99d977aa537DeLesley Hutchins  enum ExprOp {
740b4db3e08a201c35f0011489bd5cd5d39bbe54fbDeLesley Hutchins    EOP_Nop,       ///< No-op
750b4db3e08a201c35f0011489bd5cd5d39bbe54fbDeLesley Hutchins    EOP_Wildcard,  ///< Matches anything.
760b4db3e08a201c35f0011489bd5cd5d39bbe54fbDeLesley Hutchins    EOP_Universal, ///< Universal lock.
770b4db3e08a201c35f0011489bd5cd5d39bbe54fbDeLesley Hutchins    EOP_This,      ///< This keyword.
780b4db3e08a201c35f0011489bd5cd5d39bbe54fbDeLesley Hutchins    EOP_NVar,      ///< Named variable.
790b4db3e08a201c35f0011489bd5cd5d39bbe54fbDeLesley Hutchins    EOP_LVar,      ///< Local variable.
800b4db3e08a201c35f0011489bd5cd5d39bbe54fbDeLesley Hutchins    EOP_Dot,       ///< Field access
810b4db3e08a201c35f0011489bd5cd5d39bbe54fbDeLesley Hutchins    EOP_Call,      ///< Function call
820b4db3e08a201c35f0011489bd5cd5d39bbe54fbDeLesley Hutchins    EOP_MCall,     ///< Method call
830b4db3e08a201c35f0011489bd5cd5d39bbe54fbDeLesley Hutchins    EOP_Index,     ///< Array index
840b4db3e08a201c35f0011489bd5cd5d39bbe54fbDeLesley Hutchins    EOP_Unary,     ///< Unary operation
850b4db3e08a201c35f0011489bd5cd5d39bbe54fbDeLesley Hutchins    EOP_Binary,    ///< Binary operation
860b4db3e08a201c35f0011489bd5cd5d39bbe54fbDeLesley Hutchins    EOP_Unknown    ///< Catchall for everything else
87a74b715cdc37c4523818a4018faae99d977aa537DeLesley Hutchins  };
88a74b715cdc37c4523818a4018faae99d977aa537DeLesley Hutchins
89a74b715cdc37c4523818a4018faae99d977aa537DeLesley Hutchins
90a74b715cdc37c4523818a4018faae99d977aa537DeLesley Hutchins  class SExprNode {
91a74b715cdc37c4523818a4018faae99d977aa537DeLesley Hutchins   private:
92ad0fe03b897f9486191e75c8d90c3ffa9b4fd6a5Ted Kremenek    unsigned char  Op;     ///< Opcode of the root node
93ad0fe03b897f9486191e75c8d90c3ffa9b4fd6a5Ted Kremenek    unsigned char  Flags;  ///< Additional opcode-specific data
94ad0fe03b897f9486191e75c8d90c3ffa9b4fd6a5Ted Kremenek    unsigned short Sz;     ///< Number of child nodes
95ad0fe03b897f9486191e75c8d90c3ffa9b4fd6a5Ted Kremenek    const void*    Data;   ///< Additional opcode-specific data
96a74b715cdc37c4523818a4018faae99d977aa537DeLesley Hutchins
97a74b715cdc37c4523818a4018faae99d977aa537DeLesley Hutchins   public:
98a74b715cdc37c4523818a4018faae99d977aa537DeLesley Hutchins    SExprNode(ExprOp O, unsigned F, const void* D)
99a74b715cdc37c4523818a4018faae99d977aa537DeLesley Hutchins      : Op(static_cast<unsigned char>(O)),
100a74b715cdc37c4523818a4018faae99d977aa537DeLesley Hutchins        Flags(static_cast<unsigned char>(F)), Sz(1), Data(D)
101a74b715cdc37c4523818a4018faae99d977aa537DeLesley Hutchins    { }
102a74b715cdc37c4523818a4018faae99d977aa537DeLesley Hutchins
103a74b715cdc37c4523818a4018faae99d977aa537DeLesley Hutchins    unsigned size() const        { return Sz; }
104a74b715cdc37c4523818a4018faae99d977aa537DeLesley Hutchins    void     setSize(unsigned S) { Sz = S;    }
105a74b715cdc37c4523818a4018faae99d977aa537DeLesley Hutchins
106a74b715cdc37c4523818a4018faae99d977aa537DeLesley Hutchins    ExprOp   kind() const { return static_cast<ExprOp>(Op); }
107a74b715cdc37c4523818a4018faae99d977aa537DeLesley Hutchins
108a74b715cdc37c4523818a4018faae99d977aa537DeLesley Hutchins    const NamedDecl* getNamedDecl() const {
109a74b715cdc37c4523818a4018faae99d977aa537DeLesley Hutchins      assert(Op == EOP_NVar || Op == EOP_LVar || Op == EOP_Dot);
110a74b715cdc37c4523818a4018faae99d977aa537DeLesley Hutchins      return reinterpret_cast<const NamedDecl*>(Data);
111a74b715cdc37c4523818a4018faae99d977aa537DeLesley Hutchins    }
112a74b715cdc37c4523818a4018faae99d977aa537DeLesley Hutchins
113a74b715cdc37c4523818a4018faae99d977aa537DeLesley Hutchins    const NamedDecl* getFunctionDecl() const {
114a74b715cdc37c4523818a4018faae99d977aa537DeLesley Hutchins      assert(Op == EOP_Call || Op == EOP_MCall);
115a74b715cdc37c4523818a4018faae99d977aa537DeLesley Hutchins      return reinterpret_cast<const NamedDecl*>(Data);
116a74b715cdc37c4523818a4018faae99d977aa537DeLesley Hutchins    }
117a74b715cdc37c4523818a4018faae99d977aa537DeLesley Hutchins
118a74b715cdc37c4523818a4018faae99d977aa537DeLesley Hutchins    bool isArrow() const { return Op == EOP_Dot && Flags == 1; }
119a74b715cdc37c4523818a4018faae99d977aa537DeLesley Hutchins    void setArrow(bool A) { Flags = A ? 1 : 0; }
120a74b715cdc37c4523818a4018faae99d977aa537DeLesley Hutchins
121a74b715cdc37c4523818a4018faae99d977aa537DeLesley Hutchins    unsigned arity() const {
122a74b715cdc37c4523818a4018faae99d977aa537DeLesley Hutchins      switch (Op) {
1230b4db3e08a201c35f0011489bd5cd5d39bbe54fbDeLesley Hutchins        case EOP_Nop:       return 0;
1240b4db3e08a201c35f0011489bd5cd5d39bbe54fbDeLesley Hutchins        case EOP_Wildcard:  return 0;
1250b4db3e08a201c35f0011489bd5cd5d39bbe54fbDeLesley Hutchins        case EOP_Universal: return 0;
1260b4db3e08a201c35f0011489bd5cd5d39bbe54fbDeLesley Hutchins        case EOP_NVar:      return 0;
1270b4db3e08a201c35f0011489bd5cd5d39bbe54fbDeLesley Hutchins        case EOP_LVar:      return 0;
1280b4db3e08a201c35f0011489bd5cd5d39bbe54fbDeLesley Hutchins        case EOP_This:      return 0;
1290b4db3e08a201c35f0011489bd5cd5d39bbe54fbDeLesley Hutchins        case EOP_Dot:       return 1;
1300b4db3e08a201c35f0011489bd5cd5d39bbe54fbDeLesley Hutchins        case EOP_Call:      return Flags+1;  // First arg is function.
1310b4db3e08a201c35f0011489bd5cd5d39bbe54fbDeLesley Hutchins        case EOP_MCall:     return Flags+1;  // First arg is implicit obj.
1320b4db3e08a201c35f0011489bd5cd5d39bbe54fbDeLesley Hutchins        case EOP_Index:     return 2;
1330b4db3e08a201c35f0011489bd5cd5d39bbe54fbDeLesley Hutchins        case EOP_Unary:     return 1;
1340b4db3e08a201c35f0011489bd5cd5d39bbe54fbDeLesley Hutchins        case EOP_Binary:    return 2;
1350b4db3e08a201c35f0011489bd5cd5d39bbe54fbDeLesley Hutchins        case EOP_Unknown:   return Flags;
136a74b715cdc37c4523818a4018faae99d977aa537DeLesley Hutchins      }
137a74b715cdc37c4523818a4018faae99d977aa537DeLesley Hutchins      return 0;
138a74b715cdc37c4523818a4018faae99d977aa537DeLesley Hutchins    }
139a74b715cdc37c4523818a4018faae99d977aa537DeLesley Hutchins
140a74b715cdc37c4523818a4018faae99d977aa537DeLesley Hutchins    bool operator==(const SExprNode& Other) const {
141a74b715cdc37c4523818a4018faae99d977aa537DeLesley Hutchins      // Ignore flags and size -- they don't matter.
142ee2f032fe0fc86762608458c2a167ae504579a64DeLesley Hutchins      return (Op == Other.Op &&
143ee2f032fe0fc86762608458c2a167ae504579a64DeLesley Hutchins              Data == Other.Data);
144a74b715cdc37c4523818a4018faae99d977aa537DeLesley Hutchins    }
145a74b715cdc37c4523818a4018faae99d977aa537DeLesley Hutchins
146a74b715cdc37c4523818a4018faae99d977aa537DeLesley Hutchins    bool operator!=(const SExprNode& Other) const {
147a74b715cdc37c4523818a4018faae99d977aa537DeLesley Hutchins      return !(*this == Other);
148a74b715cdc37c4523818a4018faae99d977aa537DeLesley Hutchins    }
149ee2f032fe0fc86762608458c2a167ae504579a64DeLesley Hutchins
150ee2f032fe0fc86762608458c2a167ae504579a64DeLesley Hutchins    bool matches(const SExprNode& Other) const {
151ee2f032fe0fc86762608458c2a167ae504579a64DeLesley Hutchins      return (*this == Other) ||
152ee2f032fe0fc86762608458c2a167ae504579a64DeLesley Hutchins             (Op == EOP_Wildcard) ||
153ee2f032fe0fc86762608458c2a167ae504579a64DeLesley Hutchins             (Other.Op == EOP_Wildcard);
154ee2f032fe0fc86762608458c2a167ae504579a64DeLesley Hutchins    }
155a74b715cdc37c4523818a4018faae99d977aa537DeLesley Hutchins  };
156a74b715cdc37c4523818a4018faae99d977aa537DeLesley Hutchins
157402aa0698fec81e574818a0a6c2000fac0b2c4c6Caitlin Sadowski
158f63797c741e646b9482d204c88dee02fb41d7962DeLesley Hutchins  /// \brief Encapsulates the lexical context of a function call.  The lexical
159f63797c741e646b9482d204c88dee02fb41d7962DeLesley Hutchins  /// context includes the arguments to the call, including the implicit object
160f63797c741e646b9482d204c88dee02fb41d7962DeLesley Hutchins  /// argument.  When an attribute containing a mutex expression is attached to
161f63797c741e646b9482d204c88dee02fb41d7962DeLesley Hutchins  /// a method, the expression may refer to formal parameters of the method.
162f63797c741e646b9482d204c88dee02fb41d7962DeLesley Hutchins  /// Actual arguments must be substituted for formal parameters to derive
163f63797c741e646b9482d204c88dee02fb41d7962DeLesley Hutchins  /// the appropriate mutex expression in the lexical context where the function
164f63797c741e646b9482d204c88dee02fb41d7962DeLesley Hutchins  /// is called.  PrevCtx holds the context in which the arguments themselves
165f63797c741e646b9482d204c88dee02fb41d7962DeLesley Hutchins  /// should be evaluated; multiple calling contexts can be chained together
166f63797c741e646b9482d204c88dee02fb41d7962DeLesley Hutchins  /// by the lock_returned attribute.
167f63797c741e646b9482d204c88dee02fb41d7962DeLesley Hutchins  struct CallingContext {
16847715cc201170952029a52806bcc26f69c38272dDeLesley Hutchins    const NamedDecl*   AttrDecl;   // The decl to which the attribute is attached.
16947715cc201170952029a52806bcc26f69c38272dDeLesley Hutchins    const Expr*        SelfArg;    // Implicit object argument -- e.g. 'this'
17047715cc201170952029a52806bcc26f69c38272dDeLesley Hutchins    bool               SelfArrow;  // is Self referred to with -> or .?
17147715cc201170952029a52806bcc26f69c38272dDeLesley Hutchins    unsigned           NumArgs;    // Number of funArgs
17247715cc201170952029a52806bcc26f69c38272dDeLesley Hutchins    const Expr* const* FunArgs;    // Function arguments
17347715cc201170952029a52806bcc26f69c38272dDeLesley Hutchins    CallingContext*    PrevCtx;    // The previous context; or 0 if none.
17447715cc201170952029a52806bcc26f69c38272dDeLesley Hutchins
17547715cc201170952029a52806bcc26f69c38272dDeLesley Hutchins    CallingContext(const NamedDecl *D = 0, const Expr *S = 0,
17647715cc201170952029a52806bcc26f69c38272dDeLesley Hutchins                   unsigned N = 0, const Expr* const *A = 0,
17747715cc201170952029a52806bcc26f69c38272dDeLesley Hutchins                   CallingContext *P = 0)
178a74b715cdc37c4523818a4018faae99d977aa537DeLesley Hutchins      : AttrDecl(D), SelfArg(S), SelfArrow(false),
179a74b715cdc37c4523818a4018faae99d977aa537DeLesley Hutchins        NumArgs(N), FunArgs(A), PrevCtx(P)
180f63797c741e646b9482d204c88dee02fb41d7962DeLesley Hutchins    { }
181f63797c741e646b9482d204c88dee02fb41d7962DeLesley Hutchins  };
182f63797c741e646b9482d204c88dee02fb41d7962DeLesley Hutchins
183a74b715cdc37c4523818a4018faae99d977aa537DeLesley Hutchins  typedef SmallVector<SExprNode, 4> NodeVector;
184a74b715cdc37c4523818a4018faae99d977aa537DeLesley Hutchins
185a74b715cdc37c4523818a4018faae99d977aa537DeLesley Hutchinsprivate:
186a74b715cdc37c4523818a4018faae99d977aa537DeLesley Hutchins  // A SExpr is a list of SExprNodes in prefix order.  The Size field allows
187a74b715cdc37c4523818a4018faae99d977aa537DeLesley Hutchins  // the list to be traversed as a tree.
188a74b715cdc37c4523818a4018faae99d977aa537DeLesley Hutchins  NodeVector NodeVec;
189a74b715cdc37c4523818a4018faae99d977aa537DeLesley Hutchins
190a74b715cdc37c4523818a4018faae99d977aa537DeLesley Hutchinsprivate:
191a74b715cdc37c4523818a4018faae99d977aa537DeLesley Hutchins  unsigned makeNop() {
192a74b715cdc37c4523818a4018faae99d977aa537DeLesley Hutchins    NodeVec.push_back(SExprNode(EOP_Nop, 0, 0));
193a74b715cdc37c4523818a4018faae99d977aa537DeLesley Hutchins    return NodeVec.size()-1;
194a74b715cdc37c4523818a4018faae99d977aa537DeLesley Hutchins  }
195a74b715cdc37c4523818a4018faae99d977aa537DeLesley Hutchins
196ee2f032fe0fc86762608458c2a167ae504579a64DeLesley Hutchins  unsigned makeWildcard() {
197ee2f032fe0fc86762608458c2a167ae504579a64DeLesley Hutchins    NodeVec.push_back(SExprNode(EOP_Wildcard, 0, 0));
198ee2f032fe0fc86762608458c2a167ae504579a64DeLesley Hutchins    return NodeVec.size()-1;
199ee2f032fe0fc86762608458c2a167ae504579a64DeLesley Hutchins  }
200ee2f032fe0fc86762608458c2a167ae504579a64DeLesley Hutchins
2010b4db3e08a201c35f0011489bd5cd5d39bbe54fbDeLesley Hutchins  unsigned makeUniversal() {
2020b4db3e08a201c35f0011489bd5cd5d39bbe54fbDeLesley Hutchins    NodeVec.push_back(SExprNode(EOP_Universal, 0, 0));
2030b4db3e08a201c35f0011489bd5cd5d39bbe54fbDeLesley Hutchins    return NodeVec.size()-1;
2040b4db3e08a201c35f0011489bd5cd5d39bbe54fbDeLesley Hutchins  }
2050b4db3e08a201c35f0011489bd5cd5d39bbe54fbDeLesley Hutchins
206a74b715cdc37c4523818a4018faae99d977aa537DeLesley Hutchins  unsigned makeNamedVar(const NamedDecl *D) {
207a74b715cdc37c4523818a4018faae99d977aa537DeLesley Hutchins    NodeVec.push_back(SExprNode(EOP_NVar, 0, D));
208a74b715cdc37c4523818a4018faae99d977aa537DeLesley Hutchins    return NodeVec.size()-1;
209a74b715cdc37c4523818a4018faae99d977aa537DeLesley Hutchins  }
210a74b715cdc37c4523818a4018faae99d977aa537DeLesley Hutchins
211a74b715cdc37c4523818a4018faae99d977aa537DeLesley Hutchins  unsigned makeLocalVar(const NamedDecl *D) {
212a74b715cdc37c4523818a4018faae99d977aa537DeLesley Hutchins    NodeVec.push_back(SExprNode(EOP_LVar, 0, D));
213a74b715cdc37c4523818a4018faae99d977aa537DeLesley Hutchins    return NodeVec.size()-1;
214a74b715cdc37c4523818a4018faae99d977aa537DeLesley Hutchins  }
215a74b715cdc37c4523818a4018faae99d977aa537DeLesley Hutchins
216a74b715cdc37c4523818a4018faae99d977aa537DeLesley Hutchins  unsigned makeThis() {
217a74b715cdc37c4523818a4018faae99d977aa537DeLesley Hutchins    NodeVec.push_back(SExprNode(EOP_This, 0, 0));
218a74b715cdc37c4523818a4018faae99d977aa537DeLesley Hutchins    return NodeVec.size()-1;
219a74b715cdc37c4523818a4018faae99d977aa537DeLesley Hutchins  }
220a74b715cdc37c4523818a4018faae99d977aa537DeLesley Hutchins
221a74b715cdc37c4523818a4018faae99d977aa537DeLesley Hutchins  unsigned makeDot(const NamedDecl *D, bool Arrow) {
222a74b715cdc37c4523818a4018faae99d977aa537DeLesley Hutchins    NodeVec.push_back(SExprNode(EOP_Dot, Arrow ? 1 : 0, D));
223a74b715cdc37c4523818a4018faae99d977aa537DeLesley Hutchins    return NodeVec.size()-1;
224a74b715cdc37c4523818a4018faae99d977aa537DeLesley Hutchins  }
225a74b715cdc37c4523818a4018faae99d977aa537DeLesley Hutchins
226a74b715cdc37c4523818a4018faae99d977aa537DeLesley Hutchins  unsigned makeCall(unsigned NumArgs, const NamedDecl *D) {
227a74b715cdc37c4523818a4018faae99d977aa537DeLesley Hutchins    NodeVec.push_back(SExprNode(EOP_Call, NumArgs, D));
228a74b715cdc37c4523818a4018faae99d977aa537DeLesley Hutchins    return NodeVec.size()-1;
229a74b715cdc37c4523818a4018faae99d977aa537DeLesley Hutchins  }
230a74b715cdc37c4523818a4018faae99d977aa537DeLesley Hutchins
231186af2de86aea41d7418158e68f96c1f8620e013DeLesley Hutchins  // Grab the very first declaration of virtual method D
232186af2de86aea41d7418158e68f96c1f8620e013DeLesley Hutchins  const CXXMethodDecl* getFirstVirtualDecl(const CXXMethodDecl *D) {
233186af2de86aea41d7418158e68f96c1f8620e013DeLesley Hutchins    while (true) {
234186af2de86aea41d7418158e68f96c1f8620e013DeLesley Hutchins      D = D->getCanonicalDecl();
235186af2de86aea41d7418158e68f96c1f8620e013DeLesley Hutchins      CXXMethodDecl::method_iterator I = D->begin_overridden_methods(),
236186af2de86aea41d7418158e68f96c1f8620e013DeLesley Hutchins                                     E = D->end_overridden_methods();
237186af2de86aea41d7418158e68f96c1f8620e013DeLesley Hutchins      if (I == E)
238186af2de86aea41d7418158e68f96c1f8620e013DeLesley Hutchins        return D;  // Method does not override anything
239186af2de86aea41d7418158e68f96c1f8620e013DeLesley Hutchins      D = *I;      // FIXME: this does not work with multiple inheritance.
240186af2de86aea41d7418158e68f96c1f8620e013DeLesley Hutchins    }
241186af2de86aea41d7418158e68f96c1f8620e013DeLesley Hutchins    return 0;
242186af2de86aea41d7418158e68f96c1f8620e013DeLesley Hutchins  }
243186af2de86aea41d7418158e68f96c1f8620e013DeLesley Hutchins
244186af2de86aea41d7418158e68f96c1f8620e013DeLesley Hutchins  unsigned makeMCall(unsigned NumArgs, const CXXMethodDecl *D) {
245186af2de86aea41d7418158e68f96c1f8620e013DeLesley Hutchins    NodeVec.push_back(SExprNode(EOP_MCall, NumArgs, getFirstVirtualDecl(D)));
246a74b715cdc37c4523818a4018faae99d977aa537DeLesley Hutchins    return NodeVec.size()-1;
247a74b715cdc37c4523818a4018faae99d977aa537DeLesley Hutchins  }
248a74b715cdc37c4523818a4018faae99d977aa537DeLesley Hutchins
249a74b715cdc37c4523818a4018faae99d977aa537DeLesley Hutchins  unsigned makeIndex() {
250a74b715cdc37c4523818a4018faae99d977aa537DeLesley Hutchins    NodeVec.push_back(SExprNode(EOP_Index, 0, 0));
251a74b715cdc37c4523818a4018faae99d977aa537DeLesley Hutchins    return NodeVec.size()-1;
252a74b715cdc37c4523818a4018faae99d977aa537DeLesley Hutchins  }
253a74b715cdc37c4523818a4018faae99d977aa537DeLesley Hutchins
254a74b715cdc37c4523818a4018faae99d977aa537DeLesley Hutchins  unsigned makeUnary() {
255a74b715cdc37c4523818a4018faae99d977aa537DeLesley Hutchins    NodeVec.push_back(SExprNode(EOP_Unary, 0, 0));
256a74b715cdc37c4523818a4018faae99d977aa537DeLesley Hutchins    return NodeVec.size()-1;
257a74b715cdc37c4523818a4018faae99d977aa537DeLesley Hutchins  }
258a74b715cdc37c4523818a4018faae99d977aa537DeLesley Hutchins
259a74b715cdc37c4523818a4018faae99d977aa537DeLesley Hutchins  unsigned makeBinary() {
260a74b715cdc37c4523818a4018faae99d977aa537DeLesley Hutchins    NodeVec.push_back(SExprNode(EOP_Binary, 0, 0));
261a74b715cdc37c4523818a4018faae99d977aa537DeLesley Hutchins    return NodeVec.size()-1;
262a74b715cdc37c4523818a4018faae99d977aa537DeLesley Hutchins  }
263a74b715cdc37c4523818a4018faae99d977aa537DeLesley Hutchins
264a74b715cdc37c4523818a4018faae99d977aa537DeLesley Hutchins  unsigned makeUnknown(unsigned Arity) {
265a74b715cdc37c4523818a4018faae99d977aa537DeLesley Hutchins    NodeVec.push_back(SExprNode(EOP_Unknown, Arity, 0));
266a74b715cdc37c4523818a4018faae99d977aa537DeLesley Hutchins    return NodeVec.size()-1;
267a74b715cdc37c4523818a4018faae99d977aa537DeLesley Hutchins  }
268a74b715cdc37c4523818a4018faae99d977aa537DeLesley Hutchins
269a74b715cdc37c4523818a4018faae99d977aa537DeLesley Hutchins  /// Build an SExpr from the given C++ expression.
270e0eaa8531f8fd9189710aac3b6f3aadb62bb14d1DeLesley Hutchins  /// Recursive function that terminates on DeclRefExpr.
271a74b715cdc37c4523818a4018faae99d977aa537DeLesley Hutchins  /// Note: this function merely creates a SExpr; it does not check to
272e0eaa8531f8fd9189710aac3b6f3aadb62bb14d1DeLesley Hutchins  /// ensure that the original expression is a valid mutex expression.
273a74b715cdc37c4523818a4018faae99d977aa537DeLesley Hutchins  ///
274a74b715cdc37c4523818a4018faae99d977aa537DeLesley Hutchins  /// NDeref returns the number of Derefence and AddressOf operations
275a74b715cdc37c4523818a4018faae99d977aa537DeLesley Hutchins  /// preceeding the Expr; this is used to decide whether to pretty-print
276a74b715cdc37c4523818a4018faae99d977aa537DeLesley Hutchins  /// SExprs with . or ->.
27747715cc201170952029a52806bcc26f69c38272dDeLesley Hutchins  unsigned buildSExpr(const Expr *Exp, CallingContext* CallCtx,
27847715cc201170952029a52806bcc26f69c38272dDeLesley Hutchins                      int* NDeref = 0) {
279a74b715cdc37c4523818a4018faae99d977aa537DeLesley Hutchins    if (!Exp)
280a74b715cdc37c4523818a4018faae99d977aa537DeLesley Hutchins      return 0;
281f1ac63702143d84db778d32eb185a77fc97db5f5DeLesley Hutchins
28247715cc201170952029a52806bcc26f69c38272dDeLesley Hutchins    if (const DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(Exp)) {
28347715cc201170952029a52806bcc26f69c38272dDeLesley Hutchins      const NamedDecl *ND = cast<NamedDecl>(DRE->getDecl()->getCanonicalDecl());
28447715cc201170952029a52806bcc26f69c38272dDeLesley Hutchins      const ParmVarDecl *PV = dyn_cast_or_null<ParmVarDecl>(ND);
285e03b2b3ca9032b18fd1c3d0fca7692e4d2551277DeLesley Hutchins      if (PV) {
28647715cc201170952029a52806bcc26f69c38272dDeLesley Hutchins        const FunctionDecl *FD =
287e03b2b3ca9032b18fd1c3d0fca7692e4d2551277DeLesley Hutchins          cast<FunctionDecl>(PV->getDeclContext())->getCanonicalDecl();
288e03b2b3ca9032b18fd1c3d0fca7692e4d2551277DeLesley Hutchins        unsigned i = PV->getFunctionScopeIndex();
289e03b2b3ca9032b18fd1c3d0fca7692e4d2551277DeLesley Hutchins
290f63797c741e646b9482d204c88dee02fb41d7962DeLesley Hutchins        if (CallCtx && CallCtx->FunArgs &&
291f63797c741e646b9482d204c88dee02fb41d7962DeLesley Hutchins            FD == CallCtx->AttrDecl->getCanonicalDecl()) {
292e03b2b3ca9032b18fd1c3d0fca7692e4d2551277DeLesley Hutchins          // Substitute call arguments for references to function parameters
293f63797c741e646b9482d204c88dee02fb41d7962DeLesley Hutchins          assert(i < CallCtx->NumArgs);
294a74b715cdc37c4523818a4018faae99d977aa537DeLesley Hutchins          return buildSExpr(CallCtx->FunArgs[i], CallCtx->PrevCtx, NDeref);
2958121639910129a2b59aa85fc597e47cacad8b978DeLesley Hutchins        }
296e03b2b3ca9032b18fd1c3d0fca7692e4d2551277DeLesley Hutchins        // Map the param back to the param of the original function declaration.
297a74b715cdc37c4523818a4018faae99d977aa537DeLesley Hutchins        makeNamedVar(FD->getParamDecl(i));
298a74b715cdc37c4523818a4018faae99d977aa537DeLesley Hutchins        return 1;
2998121639910129a2b59aa85fc597e47cacad8b978DeLesley Hutchins      }
300e03b2b3ca9032b18fd1c3d0fca7692e4d2551277DeLesley Hutchins      // Not a function parameter -- just store the reference.
301a74b715cdc37c4523818a4018faae99d977aa537DeLesley Hutchins      makeNamedVar(ND);
302a74b715cdc37c4523818a4018faae99d977aa537DeLesley Hutchins      return 1;
303402aa0698fec81e574818a0a6c2000fac0b2c4c6Caitlin Sadowski    } else if (isa<CXXThisExpr>(Exp)) {
304f63797c741e646b9482d204c88dee02fb41d7962DeLesley Hutchins      // Substitute parent for 'this'
305a74b715cdc37c4523818a4018faae99d977aa537DeLesley Hutchins      if (CallCtx && CallCtx->SelfArg) {
306a74b715cdc37c4523818a4018faae99d977aa537DeLesley Hutchins        if (!CallCtx->SelfArrow && NDeref)
307a74b715cdc37c4523818a4018faae99d977aa537DeLesley Hutchins          // 'this' is a pointer, but self is not, so need to take address.
308a74b715cdc37c4523818a4018faae99d977aa537DeLesley Hutchins          --(*NDeref);
309a74b715cdc37c4523818a4018faae99d977aa537DeLesley Hutchins        return buildSExpr(CallCtx->SelfArg, CallCtx->PrevCtx, NDeref);
310a74b715cdc37c4523818a4018faae99d977aa537DeLesley Hutchins      }
3114bda3eca138d39585c9e475ad25aa9ff053f923bDeLesley Hutchins      else {
312a74b715cdc37c4523818a4018faae99d977aa537DeLesley Hutchins        makeThis();
313a74b715cdc37c4523818a4018faae99d977aa537DeLesley Hutchins        return 1;
3144bda3eca138d39585c9e475ad25aa9ff053f923bDeLesley Hutchins      }
31547715cc201170952029a52806bcc26f69c38272dDeLesley Hutchins    } else if (const MemberExpr *ME = dyn_cast<MemberExpr>(Exp)) {
31647715cc201170952029a52806bcc26f69c38272dDeLesley Hutchins      const NamedDecl *ND = ME->getMemberDecl();
317a74b715cdc37c4523818a4018faae99d977aa537DeLesley Hutchins      int ImplicitDeref = ME->isArrow() ? 1 : 0;
318a74b715cdc37c4523818a4018faae99d977aa537DeLesley Hutchins      unsigned Root = makeDot(ND, false);
319a74b715cdc37c4523818a4018faae99d977aa537DeLesley Hutchins      unsigned Sz = buildSExpr(ME->getBase(), CallCtx, &ImplicitDeref);
320a74b715cdc37c4523818a4018faae99d977aa537DeLesley Hutchins      NodeVec[Root].setArrow(ImplicitDeref > 0);
321a74b715cdc37c4523818a4018faae99d977aa537DeLesley Hutchins      NodeVec[Root].setSize(Sz + 1);
322a74b715cdc37c4523818a4018faae99d977aa537DeLesley Hutchins      return Sz + 1;
32347715cc201170952029a52806bcc26f69c38272dDeLesley Hutchins    } else if (const CXXMemberCallExpr *CMCE = dyn_cast<CXXMemberCallExpr>(Exp)) {
324f63797c741e646b9482d204c88dee02fb41d7962DeLesley Hutchins      // When calling a function with a lock_returned attribute, replace
325f63797c741e646b9482d204c88dee02fb41d7962DeLesley Hutchins      // the function call with the expression in lock_returned.
32647715cc201170952029a52806bcc26f69c38272dDeLesley Hutchins      const CXXMethodDecl* MD =
3275408153e9140f34bbca9059638c61cc12bd539cfDeLesley Hutchins        cast<CXXMethodDecl>(CMCE->getMethodDecl()->getMostRecentDecl());
3285408153e9140f34bbca9059638c61cc12bd539cfDeLesley Hutchins      if (LockReturnedAttr* At = MD->getAttr<LockReturnedAttr>()) {
329f63797c741e646b9482d204c88dee02fb41d7962DeLesley Hutchins        CallingContext LRCallCtx(CMCE->getMethodDecl());
330f63797c741e646b9482d204c88dee02fb41d7962DeLesley Hutchins        LRCallCtx.SelfArg = CMCE->getImplicitObjectArgument();
331a74b715cdc37c4523818a4018faae99d977aa537DeLesley Hutchins        LRCallCtx.SelfArrow =
332a74b715cdc37c4523818a4018faae99d977aa537DeLesley Hutchins          dyn_cast<MemberExpr>(CMCE->getCallee())->isArrow();
333f63797c741e646b9482d204c88dee02fb41d7962DeLesley Hutchins        LRCallCtx.NumArgs = CMCE->getNumArgs();
334f63797c741e646b9482d204c88dee02fb41d7962DeLesley Hutchins        LRCallCtx.FunArgs = CMCE->getArgs();
335f63797c741e646b9482d204c88dee02fb41d7962DeLesley Hutchins        LRCallCtx.PrevCtx = CallCtx;
336a74b715cdc37c4523818a4018faae99d977aa537DeLesley Hutchins        return buildSExpr(At->getArg(), &LRCallCtx);
337f63797c741e646b9482d204c88dee02fb41d7962DeLesley Hutchins      }
33896fac6a7fe89deff7860e536febbd4ae17bb57f3DeLesley Hutchins      // Hack to treat smart pointers and iterators as pointers;
33996fac6a7fe89deff7860e536febbd4ae17bb57f3DeLesley Hutchins      // ignore any method named get().
34096fac6a7fe89deff7860e536febbd4ae17bb57f3DeLesley Hutchins      if (CMCE->getMethodDecl()->getNameAsString() == "get" &&
34196fac6a7fe89deff7860e536febbd4ae17bb57f3DeLesley Hutchins          CMCE->getNumArgs() == 0) {
342a74b715cdc37c4523818a4018faae99d977aa537DeLesley Hutchins        if (NDeref && dyn_cast<MemberExpr>(CMCE->getCallee())->isArrow())
343a74b715cdc37c4523818a4018faae99d977aa537DeLesley Hutchins          ++(*NDeref);
344a74b715cdc37c4523818a4018faae99d977aa537DeLesley Hutchins        return buildSExpr(CMCE->getImplicitObjectArgument(), CallCtx, NDeref);
34596fac6a7fe89deff7860e536febbd4ae17bb57f3DeLesley Hutchins      }
3460d95dfcc0e07a81596ab7c3e9e86ab663fd4541cDeLesley Hutchins      unsigned NumCallArgs = CMCE->getNumArgs();
347186af2de86aea41d7418158e68f96c1f8620e013DeLesley Hutchins      unsigned Root = makeMCall(NumCallArgs, CMCE->getMethodDecl());
348a74b715cdc37c4523818a4018faae99d977aa537DeLesley Hutchins      unsigned Sz = buildSExpr(CMCE->getImplicitObjectArgument(), CallCtx);
34947715cc201170952029a52806bcc26f69c38272dDeLesley Hutchins      const Expr* const* CallArgs = CMCE->getArgs();
3500d95dfcc0e07a81596ab7c3e9e86ab663fd4541cDeLesley Hutchins      for (unsigned i = 0; i < NumCallArgs; ++i) {
351a74b715cdc37c4523818a4018faae99d977aa537DeLesley Hutchins        Sz += buildSExpr(CallArgs[i], CallCtx);
3520d95dfcc0e07a81596ab7c3e9e86ab663fd4541cDeLesley Hutchins      }
353a74b715cdc37c4523818a4018faae99d977aa537DeLesley Hutchins      NodeVec[Root].setSize(Sz + 1);
354a74b715cdc37c4523818a4018faae99d977aa537DeLesley Hutchins      return Sz + 1;
35547715cc201170952029a52806bcc26f69c38272dDeLesley Hutchins    } else if (const CallExpr *CE = dyn_cast<CallExpr>(Exp)) {
35647715cc201170952029a52806bcc26f69c38272dDeLesley Hutchins      const FunctionDecl* FD =
3575408153e9140f34bbca9059638c61cc12bd539cfDeLesley Hutchins        cast<FunctionDecl>(CE->getDirectCallee()->getMostRecentDecl());
3585408153e9140f34bbca9059638c61cc12bd539cfDeLesley Hutchins      if (LockReturnedAttr* At = FD->getAttr<LockReturnedAttr>()) {
359f63797c741e646b9482d204c88dee02fb41d7962DeLesley Hutchins        CallingContext LRCallCtx(CE->getDirectCallee());
360f63797c741e646b9482d204c88dee02fb41d7962DeLesley Hutchins        LRCallCtx.NumArgs = CE->getNumArgs();
361f63797c741e646b9482d204c88dee02fb41d7962DeLesley Hutchins        LRCallCtx.FunArgs = CE->getArgs();
362f63797c741e646b9482d204c88dee02fb41d7962DeLesley Hutchins        LRCallCtx.PrevCtx = CallCtx;
363a74b715cdc37c4523818a4018faae99d977aa537DeLesley Hutchins        return buildSExpr(At->getArg(), &LRCallCtx);
364f63797c741e646b9482d204c88dee02fb41d7962DeLesley Hutchins      }
36596fac6a7fe89deff7860e536febbd4ae17bb57f3DeLesley Hutchins      // Treat smart pointers and iterators as pointers;
36696fac6a7fe89deff7860e536febbd4ae17bb57f3DeLesley Hutchins      // ignore the * and -> operators.
36747715cc201170952029a52806bcc26f69c38272dDeLesley Hutchins      if (const CXXOperatorCallExpr *OE = dyn_cast<CXXOperatorCallExpr>(CE)) {
36896fac6a7fe89deff7860e536febbd4ae17bb57f3DeLesley Hutchins        OverloadedOperatorKind k = OE->getOperator();
369a74b715cdc37c4523818a4018faae99d977aa537DeLesley Hutchins        if (k == OO_Star) {
370a74b715cdc37c4523818a4018faae99d977aa537DeLesley Hutchins          if (NDeref) ++(*NDeref);
371a74b715cdc37c4523818a4018faae99d977aa537DeLesley Hutchins          return buildSExpr(OE->getArg(0), CallCtx, NDeref);
372a74b715cdc37c4523818a4018faae99d977aa537DeLesley Hutchins        }
373a74b715cdc37c4523818a4018faae99d977aa537DeLesley Hutchins        else if (k == OO_Arrow) {
374a74b715cdc37c4523818a4018faae99d977aa537DeLesley Hutchins          return buildSExpr(OE->getArg(0), CallCtx, NDeref);
37596fac6a7fe89deff7860e536febbd4ae17bb57f3DeLesley Hutchins        }
37696fac6a7fe89deff7860e536febbd4ae17bb57f3DeLesley Hutchins      }
3770d95dfcc0e07a81596ab7c3e9e86ab663fd4541cDeLesley Hutchins      unsigned NumCallArgs = CE->getNumArgs();
378a74b715cdc37c4523818a4018faae99d977aa537DeLesley Hutchins      unsigned Root = makeCall(NumCallArgs, 0);
379a74b715cdc37c4523818a4018faae99d977aa537DeLesley Hutchins      unsigned Sz = buildSExpr(CE->getCallee(), CallCtx);
38047715cc201170952029a52806bcc26f69c38272dDeLesley Hutchins      const Expr* const* CallArgs = CE->getArgs();
3810d95dfcc0e07a81596ab7c3e9e86ab663fd4541cDeLesley Hutchins      for (unsigned i = 0; i < NumCallArgs; ++i) {
382a74b715cdc37c4523818a4018faae99d977aa537DeLesley Hutchins        Sz += buildSExpr(CallArgs[i], CallCtx);
3830d95dfcc0e07a81596ab7c3e9e86ab663fd4541cDeLesley Hutchins      }
384a74b715cdc37c4523818a4018faae99d977aa537DeLesley Hutchins      NodeVec[Root].setSize(Sz+1);
385a74b715cdc37c4523818a4018faae99d977aa537DeLesley Hutchins      return Sz+1;
38647715cc201170952029a52806bcc26f69c38272dDeLesley Hutchins    } else if (const BinaryOperator *BOE = dyn_cast<BinaryOperator>(Exp)) {
387a74b715cdc37c4523818a4018faae99d977aa537DeLesley Hutchins      unsigned Root = makeBinary();
388a74b715cdc37c4523818a4018faae99d977aa537DeLesley Hutchins      unsigned Sz = buildSExpr(BOE->getLHS(), CallCtx);
389a74b715cdc37c4523818a4018faae99d977aa537DeLesley Hutchins      Sz += buildSExpr(BOE->getRHS(), CallCtx);
390a74b715cdc37c4523818a4018faae99d977aa537DeLesley Hutchins      NodeVec[Root].setSize(Sz);
391a74b715cdc37c4523818a4018faae99d977aa537DeLesley Hutchins      return Sz;
39247715cc201170952029a52806bcc26f69c38272dDeLesley Hutchins    } else if (const UnaryOperator *UOE = dyn_cast<UnaryOperator>(Exp)) {
393a74b715cdc37c4523818a4018faae99d977aa537DeLesley Hutchins      // Ignore & and * operators -- they're no-ops.
394a74b715cdc37c4523818a4018faae99d977aa537DeLesley Hutchins      // However, we try to figure out whether the expression is a pointer,
395a74b715cdc37c4523818a4018faae99d977aa537DeLesley Hutchins      // so we can use . and -> appropriately in error messages.
396a74b715cdc37c4523818a4018faae99d977aa537DeLesley Hutchins      if (UOE->getOpcode() == UO_Deref) {
397a74b715cdc37c4523818a4018faae99d977aa537DeLesley Hutchins        if (NDeref) ++(*NDeref);
398a74b715cdc37c4523818a4018faae99d977aa537DeLesley Hutchins        return buildSExpr(UOE->getSubExpr(), CallCtx, NDeref);
399a74b715cdc37c4523818a4018faae99d977aa537DeLesley Hutchins      }
400a74b715cdc37c4523818a4018faae99d977aa537DeLesley Hutchins      if (UOE->getOpcode() == UO_AddrOf) {
401ee2f032fe0fc86762608458c2a167ae504579a64DeLesley Hutchins        if (DeclRefExpr* DRE = dyn_cast<DeclRefExpr>(UOE->getSubExpr())) {
402ee2f032fe0fc86762608458c2a167ae504579a64DeLesley Hutchins          if (DRE->getDecl()->isCXXInstanceMember()) {
403ee2f032fe0fc86762608458c2a167ae504579a64DeLesley Hutchins            // This is a pointer-to-member expression, e.g. &MyClass::mu_.
404ee2f032fe0fc86762608458c2a167ae504579a64DeLesley Hutchins            // We interpret this syntax specially, as a wildcard.
405ee2f032fe0fc86762608458c2a167ae504579a64DeLesley Hutchins            unsigned Root = makeDot(DRE->getDecl(), false);
406ee2f032fe0fc86762608458c2a167ae504579a64DeLesley Hutchins            makeWildcard();
407ee2f032fe0fc86762608458c2a167ae504579a64DeLesley Hutchins            NodeVec[Root].setSize(2);
408ee2f032fe0fc86762608458c2a167ae504579a64DeLesley Hutchins            return 2;
409ee2f032fe0fc86762608458c2a167ae504579a64DeLesley Hutchins          }
410ee2f032fe0fc86762608458c2a167ae504579a64DeLesley Hutchins        }
411a74b715cdc37c4523818a4018faae99d977aa537DeLesley Hutchins        if (NDeref) --(*NDeref);
412a74b715cdc37c4523818a4018faae99d977aa537DeLesley Hutchins        return buildSExpr(UOE->getSubExpr(), CallCtx, NDeref);
413a74b715cdc37c4523818a4018faae99d977aa537DeLesley Hutchins      }
414a74b715cdc37c4523818a4018faae99d977aa537DeLesley Hutchins      unsigned Root = makeUnary();
415a74b715cdc37c4523818a4018faae99d977aa537DeLesley Hutchins      unsigned Sz = buildSExpr(UOE->getSubExpr(), CallCtx);
416a74b715cdc37c4523818a4018faae99d977aa537DeLesley Hutchins      NodeVec[Root].setSize(Sz);
417a74b715cdc37c4523818a4018faae99d977aa537DeLesley Hutchins      return Sz;
41847715cc201170952029a52806bcc26f69c38272dDeLesley Hutchins    } else if (const ArraySubscriptExpr *ASE =
41947715cc201170952029a52806bcc26f69c38272dDeLesley Hutchins               dyn_cast<ArraySubscriptExpr>(Exp)) {
420a74b715cdc37c4523818a4018faae99d977aa537DeLesley Hutchins      unsigned Root = makeIndex();
421a74b715cdc37c4523818a4018faae99d977aa537DeLesley Hutchins      unsigned Sz = buildSExpr(ASE->getBase(), CallCtx);
422a74b715cdc37c4523818a4018faae99d977aa537DeLesley Hutchins      Sz += buildSExpr(ASE->getIdx(), CallCtx);
423a74b715cdc37c4523818a4018faae99d977aa537DeLesley Hutchins      NodeVec[Root].setSize(Sz);
424a74b715cdc37c4523818a4018faae99d977aa537DeLesley Hutchins      return Sz;
42547715cc201170952029a52806bcc26f69c38272dDeLesley Hutchins    } else if (const AbstractConditionalOperator *CE =
426a74b715cdc37c4523818a4018faae99d977aa537DeLesley Hutchins               dyn_cast<AbstractConditionalOperator>(Exp)) {
427a74b715cdc37c4523818a4018faae99d977aa537DeLesley Hutchins      unsigned Root = makeUnknown(3);
428a74b715cdc37c4523818a4018faae99d977aa537DeLesley Hutchins      unsigned Sz = buildSExpr(CE->getCond(), CallCtx);
429a74b715cdc37c4523818a4018faae99d977aa537DeLesley Hutchins      Sz += buildSExpr(CE->getTrueExpr(), CallCtx);
430a74b715cdc37c4523818a4018faae99d977aa537DeLesley Hutchins      Sz += buildSExpr(CE->getFalseExpr(), CallCtx);
431a74b715cdc37c4523818a4018faae99d977aa537DeLesley Hutchins      NodeVec[Root].setSize(Sz);
432a74b715cdc37c4523818a4018faae99d977aa537DeLesley Hutchins      return Sz;
43347715cc201170952029a52806bcc26f69c38272dDeLesley Hutchins    } else if (const ChooseExpr *CE = dyn_cast<ChooseExpr>(Exp)) {
434a74b715cdc37c4523818a4018faae99d977aa537DeLesley Hutchins      unsigned Root = makeUnknown(3);
435a74b715cdc37c4523818a4018faae99d977aa537DeLesley Hutchins      unsigned Sz = buildSExpr(CE->getCond(), CallCtx);
436a74b715cdc37c4523818a4018faae99d977aa537DeLesley Hutchins      Sz += buildSExpr(CE->getLHS(), CallCtx);
437a74b715cdc37c4523818a4018faae99d977aa537DeLesley Hutchins      Sz += buildSExpr(CE->getRHS(), CallCtx);
438a74b715cdc37c4523818a4018faae99d977aa537DeLesley Hutchins      NodeVec[Root].setSize(Sz);
439a74b715cdc37c4523818a4018faae99d977aa537DeLesley Hutchins      return Sz;
44047715cc201170952029a52806bcc26f69c38272dDeLesley Hutchins    } else if (const CastExpr *CE = dyn_cast<CastExpr>(Exp)) {
441a74b715cdc37c4523818a4018faae99d977aa537DeLesley Hutchins      return buildSExpr(CE->getSubExpr(), CallCtx, NDeref);
44247715cc201170952029a52806bcc26f69c38272dDeLesley Hutchins    } else if (const ParenExpr *PE = dyn_cast<ParenExpr>(Exp)) {
443a74b715cdc37c4523818a4018faae99d977aa537DeLesley Hutchins      return buildSExpr(PE->getSubExpr(), CallCtx, NDeref);
44447715cc201170952029a52806bcc26f69c38272dDeLesley Hutchins    } else if (const ExprWithCleanups *EWC = dyn_cast<ExprWithCleanups>(Exp)) {
445a74b715cdc37c4523818a4018faae99d977aa537DeLesley Hutchins      return buildSExpr(EWC->getSubExpr(), CallCtx, NDeref);
44647715cc201170952029a52806bcc26f69c38272dDeLesley Hutchins    } else if (const CXXBindTemporaryExpr *E = dyn_cast<CXXBindTemporaryExpr>(Exp)) {
447a74b715cdc37c4523818a4018faae99d977aa537DeLesley Hutchins      return buildSExpr(E->getSubExpr(), CallCtx, NDeref);
4480d95dfcc0e07a81596ab7c3e9e86ab663fd4541cDeLesley Hutchins    } else if (isa<CharacterLiteral>(Exp) ||
4499d6e7f3e12f1a825377ace33161e80caeda8cd06DeLesley Hutchins               isa<CXXNullPtrLiteralExpr>(Exp) ||
4509d6e7f3e12f1a825377ace33161e80caeda8cd06DeLesley Hutchins               isa<GNUNullExpr>(Exp) ||
4519d6e7f3e12f1a825377ace33161e80caeda8cd06DeLesley Hutchins               isa<CXXBoolLiteralExpr>(Exp) ||
4529d6e7f3e12f1a825377ace33161e80caeda8cd06DeLesley Hutchins               isa<FloatingLiteral>(Exp) ||
4539d6e7f3e12f1a825377ace33161e80caeda8cd06DeLesley Hutchins               isa<ImaginaryLiteral>(Exp) ||
4549d6e7f3e12f1a825377ace33161e80caeda8cd06DeLesley Hutchins               isa<IntegerLiteral>(Exp) ||
4559d6e7f3e12f1a825377ace33161e80caeda8cd06DeLesley Hutchins               isa<StringLiteral>(Exp) ||
4569d6e7f3e12f1a825377ace33161e80caeda8cd06DeLesley Hutchins               isa<ObjCStringLiteral>(Exp)) {
457a74b715cdc37c4523818a4018faae99d977aa537DeLesley Hutchins      makeNop();
458a74b715cdc37c4523818a4018faae99d977aa537DeLesley Hutchins      return 1;  // FIXME: Ignore literals for now
4590d95dfcc0e07a81596ab7c3e9e86ab663fd4541cDeLesley Hutchins    } else {
460a74b715cdc37c4523818a4018faae99d977aa537DeLesley Hutchins      makeNop();
461a74b715cdc37c4523818a4018faae99d977aa537DeLesley Hutchins      return 1;  // Ignore.  FIXME: mark as invalid expression?
4620d95dfcc0e07a81596ab7c3e9e86ab663fd4541cDeLesley Hutchins    }
4639f80a97408ee0da939654d851ff42ad07d47e9c7DeLesley Hutchins  }
4649f80a97408ee0da939654d851ff42ad07d47e9c7DeLesley Hutchins
465a74b715cdc37c4523818a4018faae99d977aa537DeLesley Hutchins  /// \brief Construct a SExpr from an expression.
4669f80a97408ee0da939654d851ff42ad07d47e9c7DeLesley Hutchins  /// \param MutexExp The original mutex expression within an attribute
4679f80a97408ee0da939654d851ff42ad07d47e9c7DeLesley Hutchins  /// \param DeclExp An expression involving the Decl on which the attribute
4689f80a97408ee0da939654d851ff42ad07d47e9c7DeLesley Hutchins  ///        occurs.
4699f80a97408ee0da939654d851ff42ad07d47e9c7DeLesley Hutchins  /// \param D  The declaration to which the lock/unlock attribute is attached.
47047715cc201170952029a52806bcc26f69c38272dDeLesley Hutchins  void buildSExprFromExpr(const Expr *MutexExp, const Expr *DeclExp,
47147715cc201170952029a52806bcc26f69c38272dDeLesley Hutchins                          const NamedDecl *D, VarDecl *SelfDecl = 0) {
472f63797c741e646b9482d204c88dee02fb41d7962DeLesley Hutchins    CallingContext CallCtx(D);
4739f80a97408ee0da939654d851ff42ad07d47e9c7DeLesley Hutchins
4740b4db3e08a201c35f0011489bd5cd5d39bbe54fbDeLesley Hutchins    if (MutexExp) {
47547715cc201170952029a52806bcc26f69c38272dDeLesley Hutchins      if (const StringLiteral* SLit = dyn_cast<StringLiteral>(MutexExp)) {
4760b4db3e08a201c35f0011489bd5cd5d39bbe54fbDeLesley Hutchins        if (SLit->getString() == StringRef("*"))
4770b4db3e08a201c35f0011489bd5cd5d39bbe54fbDeLesley Hutchins          // The "*" expr is a universal lock, which essentially turns off
4780b4db3e08a201c35f0011489bd5cd5d39bbe54fbDeLesley Hutchins          // checks until it is removed from the lockset.
4790b4db3e08a201c35f0011489bd5cd5d39bbe54fbDeLesley Hutchins          makeUniversal();
4800b4db3e08a201c35f0011489bd5cd5d39bbe54fbDeLesley Hutchins        else
4810b4db3e08a201c35f0011489bd5cd5d39bbe54fbDeLesley Hutchins          // Ignore other string literals for now.
4820b4db3e08a201c35f0011489bd5cd5d39bbe54fbDeLesley Hutchins          makeNop();
4830b4db3e08a201c35f0011489bd5cd5d39bbe54fbDeLesley Hutchins        return;
4840b4db3e08a201c35f0011489bd5cd5d39bbe54fbDeLesley Hutchins      }
4854e4c15765d5f097e21dcaa30f1a94481924340f7DeLesley Hutchins    }
4864e4c15765d5f097e21dcaa30f1a94481924340f7DeLesley Hutchins
487f1ac63702143d84db778d32eb185a77fc97db5f5DeLesley Hutchins    // If we are processing a raw attribute expression, with no substitutions.
4889f80a97408ee0da939654d851ff42ad07d47e9c7DeLesley Hutchins    if (DeclExp == 0) {
489a74b715cdc37c4523818a4018faae99d977aa537DeLesley Hutchins      buildSExpr(MutexExp, 0);
4909f80a97408ee0da939654d851ff42ad07d47e9c7DeLesley Hutchins      return;
4919f80a97408ee0da939654d851ff42ad07d47e9c7DeLesley Hutchins    }
4929f80a97408ee0da939654d851ff42ad07d47e9c7DeLesley Hutchins
493f63797c741e646b9482d204c88dee02fb41d7962DeLesley Hutchins    // Examine DeclExp to find SelfArg and FunArgs, which are used to substitute
494e0eaa8531f8fd9189710aac3b6f3aadb62bb14d1DeLesley Hutchins    // for formal parameters when we call buildMutexID later.
49547715cc201170952029a52806bcc26f69c38272dDeLesley Hutchins    if (const MemberExpr *ME = dyn_cast<MemberExpr>(DeclExp)) {
496a74b715cdc37c4523818a4018faae99d977aa537DeLesley Hutchins      CallCtx.SelfArg   = ME->getBase();
497a74b715cdc37c4523818a4018faae99d977aa537DeLesley Hutchins      CallCtx.SelfArrow = ME->isArrow();
49847715cc201170952029a52806bcc26f69c38272dDeLesley Hutchins    } else if (const CXXMemberCallExpr *CE =
49947715cc201170952029a52806bcc26f69c38272dDeLesley Hutchins               dyn_cast<CXXMemberCallExpr>(DeclExp)) {
500a74b715cdc37c4523818a4018faae99d977aa537DeLesley Hutchins      CallCtx.SelfArg   = CE->getImplicitObjectArgument();
501a74b715cdc37c4523818a4018faae99d977aa537DeLesley Hutchins      CallCtx.SelfArrow = dyn_cast<MemberExpr>(CE->getCallee())->isArrow();
502a74b715cdc37c4523818a4018faae99d977aa537DeLesley Hutchins      CallCtx.NumArgs   = CE->getNumArgs();
503a74b715cdc37c4523818a4018faae99d977aa537DeLesley Hutchins      CallCtx.FunArgs   = CE->getArgs();
50447715cc201170952029a52806bcc26f69c38272dDeLesley Hutchins    } else if (const CallExpr *CE =
50547715cc201170952029a52806bcc26f69c38272dDeLesley Hutchins               dyn_cast<CallExpr>(DeclExp)) {
506f63797c741e646b9482d204c88dee02fb41d7962DeLesley Hutchins      CallCtx.NumArgs = CE->getNumArgs();
507f63797c741e646b9482d204c88dee02fb41d7962DeLesley Hutchins      CallCtx.FunArgs = CE->getArgs();
50847715cc201170952029a52806bcc26f69c38272dDeLesley Hutchins    } else if (const CXXConstructExpr *CE =
50947715cc201170952029a52806bcc26f69c38272dDeLesley Hutchins               dyn_cast<CXXConstructExpr>(DeclExp)) {
510ef2388b10c41a9696d5d81f42ca79ff005fef7fcDeLesley Hutchins      CallCtx.SelfArg = 0;  // Will be set below
511f63797c741e646b9482d204c88dee02fb41d7962DeLesley Hutchins      CallCtx.NumArgs = CE->getNumArgs();
512f63797c741e646b9482d204c88dee02fb41d7962DeLesley Hutchins      CallCtx.FunArgs = CE->getArgs();
5136db51f707e93816364039a2a904d13d3968c7f05DeLesley Hutchins    } else if (D && isa<CXXDestructorDecl>(D)) {
5146db51f707e93816364039a2a904d13d3968c7f05DeLesley Hutchins      // There's no such thing as a "destructor call" in the AST.
515f63797c741e646b9482d204c88dee02fb41d7962DeLesley Hutchins      CallCtx.SelfArg = DeclExp;
5168121639910129a2b59aa85fc597e47cacad8b978DeLesley Hutchins    }
5179f80a97408ee0da939654d851ff42ad07d47e9c7DeLesley Hutchins
518ef2388b10c41a9696d5d81f42ca79ff005fef7fcDeLesley Hutchins    // Hack to handle constructors, where self cannot be recovered from
519ef2388b10c41a9696d5d81f42ca79ff005fef7fcDeLesley Hutchins    // the expression.
520ef2388b10c41a9696d5d81f42ca79ff005fef7fcDeLesley Hutchins    if (SelfDecl && !CallCtx.SelfArg) {
521ef2388b10c41a9696d5d81f42ca79ff005fef7fcDeLesley Hutchins      DeclRefExpr SelfDRE(SelfDecl, false, SelfDecl->getType(), VK_LValue,
522ef2388b10c41a9696d5d81f42ca79ff005fef7fcDeLesley Hutchins                          SelfDecl->getLocation());
523ef2388b10c41a9696d5d81f42ca79ff005fef7fcDeLesley Hutchins      CallCtx.SelfArg = &SelfDRE;
524ef2388b10c41a9696d5d81f42ca79ff005fef7fcDeLesley Hutchins
525ef2388b10c41a9696d5d81f42ca79ff005fef7fcDeLesley Hutchins      // If the attribute has no arguments, then assume the argument is "this".
526ef2388b10c41a9696d5d81f42ca79ff005fef7fcDeLesley Hutchins      if (MutexExp == 0)
527ef2388b10c41a9696d5d81f42ca79ff005fef7fcDeLesley Hutchins        buildSExpr(CallCtx.SelfArg, 0);
528ef2388b10c41a9696d5d81f42ca79ff005fef7fcDeLesley Hutchins      else  // For most attributes.
529ef2388b10c41a9696d5d81f42ca79ff005fef7fcDeLesley Hutchins        buildSExpr(MutexExp, &CallCtx);
5309f80a97408ee0da939654d851ff42ad07d47e9c7DeLesley Hutchins      return;
5319f80a97408ee0da939654d851ff42ad07d47e9c7DeLesley Hutchins    }
5328121639910129a2b59aa85fc597e47cacad8b978DeLesley Hutchins
533ef2388b10c41a9696d5d81f42ca79ff005fef7fcDeLesley Hutchins    // If the attribute has no arguments, then assume the argument is "this".
534ef2388b10c41a9696d5d81f42ca79ff005fef7fcDeLesley Hutchins    if (MutexExp == 0)
535ef2388b10c41a9696d5d81f42ca79ff005fef7fcDeLesley Hutchins      buildSExpr(CallCtx.SelfArg, 0);
536ef2388b10c41a9696d5d81f42ca79ff005fef7fcDeLesley Hutchins    else  // For most attributes.
537ef2388b10c41a9696d5d81f42ca79ff005fef7fcDeLesley Hutchins      buildSExpr(MutexExp, &CallCtx);
538402aa0698fec81e574818a0a6c2000fac0b2c4c6Caitlin Sadowski  }
539402aa0698fec81e574818a0a6c2000fac0b2c4c6Caitlin Sadowski
540ee2f032fe0fc86762608458c2a167ae504579a64DeLesley Hutchins  /// \brief Get index of next sibling of node i.
541ee2f032fe0fc86762608458c2a167ae504579a64DeLesley Hutchins  unsigned getNextSibling(unsigned i) const {
542ee2f032fe0fc86762608458c2a167ae504579a64DeLesley Hutchins    return i + NodeVec[i].size();
543ee2f032fe0fc86762608458c2a167ae504579a64DeLesley Hutchins  }
544ee2f032fe0fc86762608458c2a167ae504579a64DeLesley Hutchins
545402aa0698fec81e574818a0a6c2000fac0b2c4c6Caitlin Sadowskipublic:
546a74b715cdc37c4523818a4018faae99d977aa537DeLesley Hutchins  explicit SExpr(clang::Decl::EmptyShell e) { NodeVec.clear(); }
5471fa3c0682a52c45c4ad0be3a82d0c85f26657072DeLesley Hutchins
5489f80a97408ee0da939654d851ff42ad07d47e9c7DeLesley Hutchins  /// \param MutexExp The original mutex expression within an attribute
5499f80a97408ee0da939654d851ff42ad07d47e9c7DeLesley Hutchins  /// \param DeclExp An expression involving the Decl on which the attribute
5509f80a97408ee0da939654d851ff42ad07d47e9c7DeLesley Hutchins  ///        occurs.
5519f80a97408ee0da939654d851ff42ad07d47e9c7DeLesley Hutchins  /// \param D  The declaration to which the lock/unlock attribute is attached.
5529f80a97408ee0da939654d851ff42ad07d47e9c7DeLesley Hutchins  /// Caller must check isValid() after construction.
55347715cc201170952029a52806bcc26f69c38272dDeLesley Hutchins  SExpr(const Expr* MutexExp, const Expr *DeclExp, const NamedDecl* D,
554ef2388b10c41a9696d5d81f42ca79ff005fef7fcDeLesley Hutchins        VarDecl *SelfDecl=0) {
555ef2388b10c41a9696d5d81f42ca79ff005fef7fcDeLesley Hutchins    buildSExprFromExpr(MutexExp, DeclExp, D, SelfDecl);
556194418f1db5f5f78bc3e614d1e10a863455d882cCaitlin Sadowski  }
557194418f1db5f5f78bc3e614d1e10a863455d882cCaitlin Sadowski
5589f80a97408ee0da939654d851ff42ad07d47e9c7DeLesley Hutchins  /// Return true if this is a valid decl sequence.
5599f80a97408ee0da939654d851ff42ad07d47e9c7DeLesley Hutchins  /// Caller must call this by hand after construction to handle errors.
560194418f1db5f5f78bc3e614d1e10a863455d882cCaitlin Sadowski  bool isValid() const {
561a74b715cdc37c4523818a4018faae99d977aa537DeLesley Hutchins    return !NodeVec.empty();
562402aa0698fec81e574818a0a6c2000fac0b2c4c6Caitlin Sadowski  }
563402aa0698fec81e574818a0a6c2000fac0b2c4c6Caitlin Sadowski
5644e4c15765d5f097e21dcaa30f1a94481924340f7DeLesley Hutchins  bool shouldIgnore() const {
5654e4c15765d5f097e21dcaa30f1a94481924340f7DeLesley Hutchins    // Nop is a mutex that we have decided to deliberately ignore.
5664e4c15765d5f097e21dcaa30f1a94481924340f7DeLesley Hutchins    assert(NodeVec.size() > 0 && "Invalid Mutex");
5674e4c15765d5f097e21dcaa30f1a94481924340f7DeLesley Hutchins    return NodeVec[0].kind() == EOP_Nop;
5684e4c15765d5f097e21dcaa30f1a94481924340f7DeLesley Hutchins  }
5694e4c15765d5f097e21dcaa30f1a94481924340f7DeLesley Hutchins
5700b4db3e08a201c35f0011489bd5cd5d39bbe54fbDeLesley Hutchins  bool isUniversal() const {
5710b4db3e08a201c35f0011489bd5cd5d39bbe54fbDeLesley Hutchins    assert(NodeVec.size() > 0 && "Invalid Mutex");
5720b4db3e08a201c35f0011489bd5cd5d39bbe54fbDeLesley Hutchins    return NodeVec[0].kind() == EOP_Universal;
5730b4db3e08a201c35f0011489bd5cd5d39bbe54fbDeLesley Hutchins  }
5740b4db3e08a201c35f0011489bd5cd5d39bbe54fbDeLesley Hutchins
575f1ac63702143d84db778d32eb185a77fc97db5f5DeLesley Hutchins  /// Issue a warning about an invalid lock expression
57647715cc201170952029a52806bcc26f69c38272dDeLesley Hutchins  static void warnInvalidLock(ThreadSafetyHandler &Handler,
57747715cc201170952029a52806bcc26f69c38272dDeLesley Hutchins                              const Expr *MutexExp,
57847715cc201170952029a52806bcc26f69c38272dDeLesley Hutchins                              const Expr *DeclExp, const NamedDecl* D) {
579f1ac63702143d84db778d32eb185a77fc97db5f5DeLesley Hutchins    SourceLocation Loc;
580f1ac63702143d84db778d32eb185a77fc97db5f5DeLesley Hutchins    if (DeclExp)
581f1ac63702143d84db778d32eb185a77fc97db5f5DeLesley Hutchins      Loc = DeclExp->getExprLoc();
582f1ac63702143d84db778d32eb185a77fc97db5f5DeLesley Hutchins
583f1ac63702143d84db778d32eb185a77fc97db5f5DeLesley Hutchins    // FIXME: add a note about the attribute location in MutexExp or D
584f1ac63702143d84db778d32eb185a77fc97db5f5DeLesley Hutchins    if (Loc.isValid())
585f1ac63702143d84db778d32eb185a77fc97db5f5DeLesley Hutchins      Handler.handleInvalidLockExp(Loc);
586f1ac63702143d84db778d32eb185a77fc97db5f5DeLesley Hutchins  }
587f1ac63702143d84db778d32eb185a77fc97db5f5DeLesley Hutchins
588a74b715cdc37c4523818a4018faae99d977aa537DeLesley Hutchins  bool operator==(const SExpr &other) const {
589a74b715cdc37c4523818a4018faae99d977aa537DeLesley Hutchins    return NodeVec == other.NodeVec;
590402aa0698fec81e574818a0a6c2000fac0b2c4c6Caitlin Sadowski  }
591402aa0698fec81e574818a0a6c2000fac0b2c4c6Caitlin Sadowski
592a74b715cdc37c4523818a4018faae99d977aa537DeLesley Hutchins  bool operator!=(const SExpr &other) const {
593402aa0698fec81e574818a0a6c2000fac0b2c4c6Caitlin Sadowski    return !(*this == other);
594402aa0698fec81e574818a0a6c2000fac0b2c4c6Caitlin Sadowski  }
595402aa0698fec81e574818a0a6c2000fac0b2c4c6Caitlin Sadowski
596ee2f032fe0fc86762608458c2a167ae504579a64DeLesley Hutchins  bool matches(const SExpr &Other, unsigned i = 0, unsigned j = 0) const {
597ee2f032fe0fc86762608458c2a167ae504579a64DeLesley Hutchins    if (NodeVec[i].matches(Other.NodeVec[j])) {
598f9ee0bacd27085417dedf1a9f5df8a4cb5a758c1DeLesley Hutchins      unsigned ni = NodeVec[i].arity();
599f9ee0bacd27085417dedf1a9f5df8a4cb5a758c1DeLesley Hutchins      unsigned nj = Other.NodeVec[j].arity();
600f9ee0bacd27085417dedf1a9f5df8a4cb5a758c1DeLesley Hutchins      unsigned n = (ni < nj) ? ni : nj;
601ee2f032fe0fc86762608458c2a167ae504579a64DeLesley Hutchins      bool Result = true;
602ee2f032fe0fc86762608458c2a167ae504579a64DeLesley Hutchins      unsigned ci = i+1;  // first child of i
603ee2f032fe0fc86762608458c2a167ae504579a64DeLesley Hutchins      unsigned cj = j+1;  // first child of j
604ee2f032fe0fc86762608458c2a167ae504579a64DeLesley Hutchins      for (unsigned k = 0; k < n;
605ee2f032fe0fc86762608458c2a167ae504579a64DeLesley Hutchins           ++k, ci=getNextSibling(ci), cj = Other.getNextSibling(cj)) {
606ee2f032fe0fc86762608458c2a167ae504579a64DeLesley Hutchins        Result = Result && matches(Other, ci, cj);
607ee2f032fe0fc86762608458c2a167ae504579a64DeLesley Hutchins      }
608ee2f032fe0fc86762608458c2a167ae504579a64DeLesley Hutchins      return Result;
609ee2f032fe0fc86762608458c2a167ae504579a64DeLesley Hutchins    }
610ee2f032fe0fc86762608458c2a167ae504579a64DeLesley Hutchins    return false;
611ee2f032fe0fc86762608458c2a167ae504579a64DeLesley Hutchins  }
612ee2f032fe0fc86762608458c2a167ae504579a64DeLesley Hutchins
6133f0ec5209726641782468bd4c7597e79dda78b15DeLesley Hutchins  // A partial match between a.mu and b.mu returns true a and b have the same
6143f0ec5209726641782468bd4c7597e79dda78b15DeLesley Hutchins  // type (and thus mu refers to the same mutex declaration), regardless of
6153f0ec5209726641782468bd4c7597e79dda78b15DeLesley Hutchins  // whether a and b are different objects or not.
6163f0ec5209726641782468bd4c7597e79dda78b15DeLesley Hutchins  bool partiallyMatches(const SExpr &Other) const {
6173f0ec5209726641782468bd4c7597e79dda78b15DeLesley Hutchins    if (NodeVec[0].kind() == EOP_Dot)
6183f0ec5209726641782468bd4c7597e79dda78b15DeLesley Hutchins      return NodeVec[0].matches(Other.NodeVec[0]);
6193f0ec5209726641782468bd4c7597e79dda78b15DeLesley Hutchins    return false;
6203f0ec5209726641782468bd4c7597e79dda78b15DeLesley Hutchins  }
6213f0ec5209726641782468bd4c7597e79dda78b15DeLesley Hutchins
622a74b715cdc37c4523818a4018faae99d977aa537DeLesley Hutchins  /// \brief Pretty print a lock expression for use in error messages.
623a74b715cdc37c4523818a4018faae99d977aa537DeLesley Hutchins  std::string toString(unsigned i = 0) const {
624194418f1db5f5f78bc3e614d1e10a863455d882cCaitlin Sadowski    assert(isValid());
625a74b715cdc37c4523818a4018faae99d977aa537DeLesley Hutchins    if (i >= NodeVec.size())
626a74b715cdc37c4523818a4018faae99d977aa537DeLesley Hutchins      return "";
627a74b715cdc37c4523818a4018faae99d977aa537DeLesley Hutchins
628a74b715cdc37c4523818a4018faae99d977aa537DeLesley Hutchins    const SExprNode* N = &NodeVec[i];
629a74b715cdc37c4523818a4018faae99d977aa537DeLesley Hutchins    switch (N->kind()) {
630a74b715cdc37c4523818a4018faae99d977aa537DeLesley Hutchins      case EOP_Nop:
631a74b715cdc37c4523818a4018faae99d977aa537DeLesley Hutchins        return "_";
632ee2f032fe0fc86762608458c2a167ae504579a64DeLesley Hutchins      case EOP_Wildcard:
633ee2f032fe0fc86762608458c2a167ae504579a64DeLesley Hutchins        return "(?)";
6340b4db3e08a201c35f0011489bd5cd5d39bbe54fbDeLesley Hutchins      case EOP_Universal:
6350b4db3e08a201c35f0011489bd5cd5d39bbe54fbDeLesley Hutchins        return "*";
636a74b715cdc37c4523818a4018faae99d977aa537DeLesley Hutchins      case EOP_This:
637a74b715cdc37c4523818a4018faae99d977aa537DeLesley Hutchins        return "this";
638a74b715cdc37c4523818a4018faae99d977aa537DeLesley Hutchins      case EOP_NVar:
639a74b715cdc37c4523818a4018faae99d977aa537DeLesley Hutchins      case EOP_LVar: {
640a74b715cdc37c4523818a4018faae99d977aa537DeLesley Hutchins        return N->getNamedDecl()->getNameAsString();
641a74b715cdc37c4523818a4018faae99d977aa537DeLesley Hutchins      }
642a74b715cdc37c4523818a4018faae99d977aa537DeLesley Hutchins      case EOP_Dot: {
643ee2f032fe0fc86762608458c2a167ae504579a64DeLesley Hutchins        if (NodeVec[i+1].kind() == EOP_Wildcard) {
644ee2f032fe0fc86762608458c2a167ae504579a64DeLesley Hutchins          std::string S = "&";
645ee2f032fe0fc86762608458c2a167ae504579a64DeLesley Hutchins          S += N->getNamedDecl()->getQualifiedNameAsString();
646ee2f032fe0fc86762608458c2a167ae504579a64DeLesley Hutchins          return S;
647ee2f032fe0fc86762608458c2a167ae504579a64DeLesley Hutchins        }
648a74b715cdc37c4523818a4018faae99d977aa537DeLesley Hutchins        std::string FieldName = N->getNamedDecl()->getNameAsString();
649a74b715cdc37c4523818a4018faae99d977aa537DeLesley Hutchins        if (NodeVec[i+1].kind() == EOP_This)
650a74b715cdc37c4523818a4018faae99d977aa537DeLesley Hutchins          return FieldName;
651ee2f032fe0fc86762608458c2a167ae504579a64DeLesley Hutchins
652a74b715cdc37c4523818a4018faae99d977aa537DeLesley Hutchins        std::string S = toString(i+1);
653a74b715cdc37c4523818a4018faae99d977aa537DeLesley Hutchins        if (N->isArrow())
654a74b715cdc37c4523818a4018faae99d977aa537DeLesley Hutchins          return S + "->" + FieldName;
655a74b715cdc37c4523818a4018faae99d977aa537DeLesley Hutchins        else
656a74b715cdc37c4523818a4018faae99d977aa537DeLesley Hutchins          return S + "." + FieldName;
657a74b715cdc37c4523818a4018faae99d977aa537DeLesley Hutchins      }
658a74b715cdc37c4523818a4018faae99d977aa537DeLesley Hutchins      case EOP_Call: {
659a74b715cdc37c4523818a4018faae99d977aa537DeLesley Hutchins        std::string S = toString(i+1) + "(";
660a74b715cdc37c4523818a4018faae99d977aa537DeLesley Hutchins        unsigned NumArgs = N->arity()-1;
661ee2f032fe0fc86762608458c2a167ae504579a64DeLesley Hutchins        unsigned ci = getNextSibling(i+1);
662ee2f032fe0fc86762608458c2a167ae504579a64DeLesley Hutchins        for (unsigned k=0; k<NumArgs; ++k, ci = getNextSibling(ci)) {
663a74b715cdc37c4523818a4018faae99d977aa537DeLesley Hutchins          S += toString(ci);
664a74b715cdc37c4523818a4018faae99d977aa537DeLesley Hutchins          if (k+1 < NumArgs) S += ",";
665a74b715cdc37c4523818a4018faae99d977aa537DeLesley Hutchins        }
666a74b715cdc37c4523818a4018faae99d977aa537DeLesley Hutchins        S += ")";
667a74b715cdc37c4523818a4018faae99d977aa537DeLesley Hutchins        return S;
668a74b715cdc37c4523818a4018faae99d977aa537DeLesley Hutchins      }
669a74b715cdc37c4523818a4018faae99d977aa537DeLesley Hutchins      case EOP_MCall: {
670a74b715cdc37c4523818a4018faae99d977aa537DeLesley Hutchins        std::string S = "";
671a74b715cdc37c4523818a4018faae99d977aa537DeLesley Hutchins        if (NodeVec[i+1].kind() != EOP_This)
672a74b715cdc37c4523818a4018faae99d977aa537DeLesley Hutchins          S = toString(i+1) + ".";
673a74b715cdc37c4523818a4018faae99d977aa537DeLesley Hutchins        if (const NamedDecl *D = N->getFunctionDecl())
674a74b715cdc37c4523818a4018faae99d977aa537DeLesley Hutchins          S += D->getNameAsString() + "(";
675a74b715cdc37c4523818a4018faae99d977aa537DeLesley Hutchins        else
676a74b715cdc37c4523818a4018faae99d977aa537DeLesley Hutchins          S += "#(";
677a74b715cdc37c4523818a4018faae99d977aa537DeLesley Hutchins        unsigned NumArgs = N->arity()-1;
678ee2f032fe0fc86762608458c2a167ae504579a64DeLesley Hutchins        unsigned ci = getNextSibling(i+1);
679ee2f032fe0fc86762608458c2a167ae504579a64DeLesley Hutchins        for (unsigned k=0; k<NumArgs; ++k, ci = getNextSibling(ci)) {
680a74b715cdc37c4523818a4018faae99d977aa537DeLesley Hutchins          S += toString(ci);
681a74b715cdc37c4523818a4018faae99d977aa537DeLesley Hutchins          if (k+1 < NumArgs) S += ",";
682a74b715cdc37c4523818a4018faae99d977aa537DeLesley Hutchins        }
683a74b715cdc37c4523818a4018faae99d977aa537DeLesley Hutchins        S += ")";
684a74b715cdc37c4523818a4018faae99d977aa537DeLesley Hutchins        return S;
685a74b715cdc37c4523818a4018faae99d977aa537DeLesley Hutchins      }
686a74b715cdc37c4523818a4018faae99d977aa537DeLesley Hutchins      case EOP_Index: {
687a74b715cdc37c4523818a4018faae99d977aa537DeLesley Hutchins        std::string S1 = toString(i+1);
688a74b715cdc37c4523818a4018faae99d977aa537DeLesley Hutchins        std::string S2 = toString(i+1 + NodeVec[i+1].size());
689a74b715cdc37c4523818a4018faae99d977aa537DeLesley Hutchins        return S1 + "[" + S2 + "]";
690a74b715cdc37c4523818a4018faae99d977aa537DeLesley Hutchins      }
691a74b715cdc37c4523818a4018faae99d977aa537DeLesley Hutchins      case EOP_Unary: {
692a74b715cdc37c4523818a4018faae99d977aa537DeLesley Hutchins        std::string S = toString(i+1);
693a74b715cdc37c4523818a4018faae99d977aa537DeLesley Hutchins        return "#" + S;
694a74b715cdc37c4523818a4018faae99d977aa537DeLesley Hutchins      }
695a74b715cdc37c4523818a4018faae99d977aa537DeLesley Hutchins      case EOP_Binary: {
696a74b715cdc37c4523818a4018faae99d977aa537DeLesley Hutchins        std::string S1 = toString(i+1);
697a74b715cdc37c4523818a4018faae99d977aa537DeLesley Hutchins        std::string S2 = toString(i+1 + NodeVec[i+1].size());
698a74b715cdc37c4523818a4018faae99d977aa537DeLesley Hutchins        return "(" + S1 + "#" + S2 + ")";
699a74b715cdc37c4523818a4018faae99d977aa537DeLesley Hutchins      }
700a74b715cdc37c4523818a4018faae99d977aa537DeLesley Hutchins      case EOP_Unknown: {
701a74b715cdc37c4523818a4018faae99d977aa537DeLesley Hutchins        unsigned NumChildren = N->arity();
702a74b715cdc37c4523818a4018faae99d977aa537DeLesley Hutchins        if (NumChildren == 0)
703a74b715cdc37c4523818a4018faae99d977aa537DeLesley Hutchins          return "(...)";
704a74b715cdc37c4523818a4018faae99d977aa537DeLesley Hutchins        std::string S = "(";
705a74b715cdc37c4523818a4018faae99d977aa537DeLesley Hutchins        unsigned ci = i+1;
706ee2f032fe0fc86762608458c2a167ae504579a64DeLesley Hutchins        for (unsigned j = 0; j < NumChildren; ++j, ci = getNextSibling(ci)) {
707a74b715cdc37c4523818a4018faae99d977aa537DeLesley Hutchins          S += toString(ci);
708a74b715cdc37c4523818a4018faae99d977aa537DeLesley Hutchins          if (j+1 < NumChildren) S += "#";
709a74b715cdc37c4523818a4018faae99d977aa537DeLesley Hutchins        }
710a74b715cdc37c4523818a4018faae99d977aa537DeLesley Hutchins        S += ")";
711a74b715cdc37c4523818a4018faae99d977aa537DeLesley Hutchins        return S;
712a74b715cdc37c4523818a4018faae99d977aa537DeLesley Hutchins      }
713402aa0698fec81e574818a0a6c2000fac0b2c4c6Caitlin Sadowski    }
714a74b715cdc37c4523818a4018faae99d977aa537DeLesley Hutchins    return "";
715402aa0698fec81e574818a0a6c2000fac0b2c4c6Caitlin Sadowski  }
716402aa0698fec81e574818a0a6c2000fac0b2c4c6Caitlin Sadowski};
717402aa0698fec81e574818a0a6c2000fac0b2c4c6Caitlin Sadowski
718a60448d6dfc91f4c30987e237bf70ef50ac7705bDeLesley Hutchins
719a74b715cdc37c4523818a4018faae99d977aa537DeLesley Hutchins
720a74b715cdc37c4523818a4018faae99d977aa537DeLesley Hutchins/// \brief A short list of SExprs
721a74b715cdc37c4523818a4018faae99d977aa537DeLesley Hutchinsclass MutexIDList : public SmallVector<SExpr, 3> {
7225381c05f51e5b7c7627f1d95b9a3425303ce086aDeLesley Hutchinspublic:
723a74b715cdc37c4523818a4018faae99d977aa537DeLesley Hutchins  /// \brief Return true if the list contains the specified SExpr
7245381c05f51e5b7c7627f1d95b9a3425303ce086aDeLesley Hutchins  /// Performs a linear search, because these lists are almost always very small.
725a74b715cdc37c4523818a4018faae99d977aa537DeLesley Hutchins  bool contains(const SExpr& M) {
7265381c05f51e5b7c7627f1d95b9a3425303ce086aDeLesley Hutchins    for (iterator I=begin(),E=end(); I != E; ++I)
7275381c05f51e5b7c7627f1d95b9a3425303ce086aDeLesley Hutchins      if ((*I) == M) return true;
7285381c05f51e5b7c7627f1d95b9a3425303ce086aDeLesley Hutchins    return false;
7295381c05f51e5b7c7627f1d95b9a3425303ce086aDeLesley Hutchins  }
7305381c05f51e5b7c7627f1d95b9a3425303ce086aDeLesley Hutchins
7315381c05f51e5b7c7627f1d95b9a3425303ce086aDeLesley Hutchins  /// \brief Push M onto list, bud discard duplicates
732a74b715cdc37c4523818a4018faae99d977aa537DeLesley Hutchins  void push_back_nodup(const SExpr& M) {
7335381c05f51e5b7c7627f1d95b9a3425303ce086aDeLesley Hutchins    if (!contains(M)) push_back(M);
7345381c05f51e5b7c7627f1d95b9a3425303ce086aDeLesley Hutchins  }
7355381c05f51e5b7c7627f1d95b9a3425303ce086aDeLesley Hutchins};
7365381c05f51e5b7c7627f1d95b9a3425303ce086aDeLesley Hutchins
7375381c05f51e5b7c7627f1d95b9a3425303ce086aDeLesley Hutchins
7385381c05f51e5b7c7627f1d95b9a3425303ce086aDeLesley Hutchins
739402aa0698fec81e574818a0a6c2000fac0b2c4c6Caitlin Sadowski/// \brief This is a helper class that stores info about the most recent
740402aa0698fec81e574818a0a6c2000fac0b2c4c6Caitlin Sadowski/// accquire of a Lock.
741402aa0698fec81e574818a0a6c2000fac0b2c4c6Caitlin Sadowski///
742402aa0698fec81e574818a0a6c2000fac0b2c4c6Caitlin Sadowski/// The main body of the analysis maps MutexIDs to LockDatas.
743402aa0698fec81e574818a0a6c2000fac0b2c4c6Caitlin Sadowskistruct LockData {
744402aa0698fec81e574818a0a6c2000fac0b2c4c6Caitlin Sadowski  SourceLocation AcquireLoc;
745402aa0698fec81e574818a0a6c2000fac0b2c4c6Caitlin Sadowski
746402aa0698fec81e574818a0a6c2000fac0b2c4c6Caitlin Sadowski  /// \brief LKind stores whether a lock is held shared or exclusively.
747402aa0698fec81e574818a0a6c2000fac0b2c4c6Caitlin Sadowski  /// Note that this analysis does not currently support either re-entrant
748402aa0698fec81e574818a0a6c2000fac0b2c4c6Caitlin Sadowski  /// locking or lock "upgrading" and "downgrading" between exclusive and
749402aa0698fec81e574818a0a6c2000fac0b2c4c6Caitlin Sadowski  /// shared.
750402aa0698fec81e574818a0a6c2000fac0b2c4c6Caitlin Sadowski  ///
751402aa0698fec81e574818a0a6c2000fac0b2c4c6Caitlin Sadowski  /// FIXME: add support for re-entrant locking and lock up/downgrading
752402aa0698fec81e574818a0a6c2000fac0b2c4c6Caitlin Sadowski  LockKind LKind;
7535c6134fd09bc5b738dafdd1c774edde13d95cb20DeLesley Hutchins  bool     Asserted;           // for asserted locks
754c99a5d820ead4e4f1f4b4a8ab61007b8da0307e6DeLesley Hutchins  bool     Managed;            // for ScopedLockable objects
755a74b715cdc37c4523818a4018faae99d977aa537DeLesley Hutchins  SExpr    UnderlyingMutex;    // for ScopedLockable objects
756402aa0698fec81e574818a0a6c2000fac0b2c4c6Caitlin Sadowski
7575c6134fd09bc5b738dafdd1c774edde13d95cb20DeLesley Hutchins  LockData(SourceLocation AcquireLoc, LockKind LKind, bool M=false,
7585c6134fd09bc5b738dafdd1c774edde13d95cb20DeLesley Hutchins           bool Asrt=false)
7595c6134fd09bc5b738dafdd1c774edde13d95cb20DeLesley Hutchins    : AcquireLoc(AcquireLoc), LKind(LKind), Asserted(Asrt), Managed(M),
760c99a5d820ead4e4f1f4b4a8ab61007b8da0307e6DeLesley Hutchins      UnderlyingMutex(Decl::EmptyShell())
7611fa3c0682a52c45c4ad0be3a82d0c85f26657072DeLesley Hutchins  {}
7621fa3c0682a52c45c4ad0be3a82d0c85f26657072DeLesley Hutchins
763a74b715cdc37c4523818a4018faae99d977aa537DeLesley Hutchins  LockData(SourceLocation AcquireLoc, LockKind LKind, const SExpr &Mu)
7645c6134fd09bc5b738dafdd1c774edde13d95cb20DeLesley Hutchins    : AcquireLoc(AcquireLoc), LKind(LKind), Asserted(false), Managed(false),
765c99a5d820ead4e4f1f4b4a8ab61007b8da0307e6DeLesley Hutchins      UnderlyingMutex(Mu)
766c99a5d820ead4e4f1f4b4a8ab61007b8da0307e6DeLesley Hutchins  {}
767402aa0698fec81e574818a0a6c2000fac0b2c4c6Caitlin Sadowski
768402aa0698fec81e574818a0a6c2000fac0b2c4c6Caitlin Sadowski  bool operator==(const LockData &other) const {
769402aa0698fec81e574818a0a6c2000fac0b2c4c6Caitlin Sadowski    return AcquireLoc == other.AcquireLoc && LKind == other.LKind;
770402aa0698fec81e574818a0a6c2000fac0b2c4c6Caitlin Sadowski  }
771402aa0698fec81e574818a0a6c2000fac0b2c4c6Caitlin Sadowski
772402aa0698fec81e574818a0a6c2000fac0b2c4c6Caitlin Sadowski  bool operator!=(const LockData &other) const {
773402aa0698fec81e574818a0a6c2000fac0b2c4c6Caitlin Sadowski    return !(*this == other);
774402aa0698fec81e574818a0a6c2000fac0b2c4c6Caitlin Sadowski  }
775402aa0698fec81e574818a0a6c2000fac0b2c4c6Caitlin Sadowski
776402aa0698fec81e574818a0a6c2000fac0b2c4c6Caitlin Sadowski  void Profile(llvm::FoldingSetNodeID &ID) const {
777a60448d6dfc91f4c30987e237bf70ef50ac7705bDeLesley Hutchins    ID.AddInteger(AcquireLoc.getRawEncoding());
778a60448d6dfc91f4c30987e237bf70ef50ac7705bDeLesley Hutchins    ID.AddInteger(LKind);
779a60448d6dfc91f4c30987e237bf70ef50ac7705bDeLesley Hutchins  }
7800b4db3e08a201c35f0011489bd5cd5d39bbe54fbDeLesley Hutchins
7810b4db3e08a201c35f0011489bd5cd5d39bbe54fbDeLesley Hutchins  bool isAtLeast(LockKind LK) {
7820b4db3e08a201c35f0011489bd5cd5d39bbe54fbDeLesley Hutchins    return (LK == LK_Shared) || (LKind == LK_Exclusive);
7830b4db3e08a201c35f0011489bd5cd5d39bbe54fbDeLesley Hutchins  }
784402aa0698fec81e574818a0a6c2000fac0b2c4c6Caitlin Sadowski};
785402aa0698fec81e574818a0a6c2000fac0b2c4c6Caitlin Sadowski
786a60448d6dfc91f4c30987e237bf70ef50ac7705bDeLesley Hutchins
787a1fa47139d6e9e7dcc40f2809605d1a258624e7fDeLesley Hutchins/// \brief A FactEntry stores a single fact that is known at a particular point
788a1fa47139d6e9e7dcc40f2809605d1a258624e7fDeLesley Hutchins/// in the program execution.  Currently, this is information regarding a lock
789dd0a1f58a505ced9674f6d31a1ff65cb87774d67DeLesley Hutchins/// that is held at that point.
790a1fa47139d6e9e7dcc40f2809605d1a258624e7fDeLesley Hutchinsstruct FactEntry {
791a74b715cdc37c4523818a4018faae99d977aa537DeLesley Hutchins  SExpr    MutID;
792a1fa47139d6e9e7dcc40f2809605d1a258624e7fDeLesley Hutchins  LockData LDat;
793a1fa47139d6e9e7dcc40f2809605d1a258624e7fDeLesley Hutchins
794a74b715cdc37c4523818a4018faae99d977aa537DeLesley Hutchins  FactEntry(const SExpr& M, const LockData& L)
795a1fa47139d6e9e7dcc40f2809605d1a258624e7fDeLesley Hutchins    : MutID(M), LDat(L)
796a1fa47139d6e9e7dcc40f2809605d1a258624e7fDeLesley Hutchins  { }
797a1fa47139d6e9e7dcc40f2809605d1a258624e7fDeLesley Hutchins};
798a1fa47139d6e9e7dcc40f2809605d1a258624e7fDeLesley Hutchins
799a1fa47139d6e9e7dcc40f2809605d1a258624e7fDeLesley Hutchins
800a1fa47139d6e9e7dcc40f2809605d1a258624e7fDeLesley Hutchinstypedef unsigned short FactID;
801a1fa47139d6e9e7dcc40f2809605d1a258624e7fDeLesley Hutchins
802dd0a1f58a505ced9674f6d31a1ff65cb87774d67DeLesley Hutchins/// \brief FactManager manages the memory for all facts that are created during
803a1fa47139d6e9e7dcc40f2809605d1a258624e7fDeLesley Hutchins/// the analysis of a single routine.
804a1fa47139d6e9e7dcc40f2809605d1a258624e7fDeLesley Hutchinsclass FactManager {
805a1fa47139d6e9e7dcc40f2809605d1a258624e7fDeLesley Hutchinsprivate:
806a1fa47139d6e9e7dcc40f2809605d1a258624e7fDeLesley Hutchins  std::vector<FactEntry> Facts;
807a1fa47139d6e9e7dcc40f2809605d1a258624e7fDeLesley Hutchins
808a1fa47139d6e9e7dcc40f2809605d1a258624e7fDeLesley Hutchinspublic:
809a74b715cdc37c4523818a4018faae99d977aa537DeLesley Hutchins  FactID newLock(const SExpr& M, const LockData& L) {
810a1fa47139d6e9e7dcc40f2809605d1a258624e7fDeLesley Hutchins    Facts.push_back(FactEntry(M,L));
811a1fa47139d6e9e7dcc40f2809605d1a258624e7fDeLesley Hutchins    return static_cast<unsigned short>(Facts.size() - 1);
812a1fa47139d6e9e7dcc40f2809605d1a258624e7fDeLesley Hutchins  }
813a1fa47139d6e9e7dcc40f2809605d1a258624e7fDeLesley Hutchins
814a1fa47139d6e9e7dcc40f2809605d1a258624e7fDeLesley Hutchins  const FactEntry& operator[](FactID F) const { return Facts[F]; }
815a1fa47139d6e9e7dcc40f2809605d1a258624e7fDeLesley Hutchins  FactEntry&       operator[](FactID F)       { return Facts[F]; }
816a1fa47139d6e9e7dcc40f2809605d1a258624e7fDeLesley Hutchins};
817a1fa47139d6e9e7dcc40f2809605d1a258624e7fDeLesley Hutchins
818a1fa47139d6e9e7dcc40f2809605d1a258624e7fDeLesley Hutchins
819a1fa47139d6e9e7dcc40f2809605d1a258624e7fDeLesley Hutchins/// \brief A FactSet is the set of facts that are known to be true at a
820dd0a1f58a505ced9674f6d31a1ff65cb87774d67DeLesley Hutchins/// particular program point.  FactSets must be small, because they are
821a1fa47139d6e9e7dcc40f2809605d1a258624e7fDeLesley Hutchins/// frequently copied, and are thus implemented as a set of indices into a
822dd0a1f58a505ced9674f6d31a1ff65cb87774d67DeLesley Hutchins/// table maintained by a FactManager.  A typical FactSet only holds 1 or 2
823a1fa47139d6e9e7dcc40f2809605d1a258624e7fDeLesley Hutchins/// locks, so we can get away with doing a linear search for lookup.  Note
824a1fa47139d6e9e7dcc40f2809605d1a258624e7fDeLesley Hutchins/// that a hashtable or map is inappropriate in this case, because lookups
825a1fa47139d6e9e7dcc40f2809605d1a258624e7fDeLesley Hutchins/// may involve partial pattern matches, rather than exact matches.
826a1fa47139d6e9e7dcc40f2809605d1a258624e7fDeLesley Hutchinsclass FactSet {
827a1fa47139d6e9e7dcc40f2809605d1a258624e7fDeLesley Hutchinsprivate:
828a1fa47139d6e9e7dcc40f2809605d1a258624e7fDeLesley Hutchins  typedef SmallVector<FactID, 4> FactVec;
829a1fa47139d6e9e7dcc40f2809605d1a258624e7fDeLesley Hutchins
830a1fa47139d6e9e7dcc40f2809605d1a258624e7fDeLesley Hutchins  FactVec FactIDs;
831a1fa47139d6e9e7dcc40f2809605d1a258624e7fDeLesley Hutchins
832a1fa47139d6e9e7dcc40f2809605d1a258624e7fDeLesley Hutchinspublic:
833a1fa47139d6e9e7dcc40f2809605d1a258624e7fDeLesley Hutchins  typedef FactVec::iterator       iterator;
834a1fa47139d6e9e7dcc40f2809605d1a258624e7fDeLesley Hutchins  typedef FactVec::const_iterator const_iterator;
835a1fa47139d6e9e7dcc40f2809605d1a258624e7fDeLesley Hutchins
836a1fa47139d6e9e7dcc40f2809605d1a258624e7fDeLesley Hutchins  iterator       begin()       { return FactIDs.begin(); }
837a1fa47139d6e9e7dcc40f2809605d1a258624e7fDeLesley Hutchins  const_iterator begin() const { return FactIDs.begin(); }
838a1fa47139d6e9e7dcc40f2809605d1a258624e7fDeLesley Hutchins
839a1fa47139d6e9e7dcc40f2809605d1a258624e7fDeLesley Hutchins  iterator       end()       { return FactIDs.end(); }
840a1fa47139d6e9e7dcc40f2809605d1a258624e7fDeLesley Hutchins  const_iterator end() const { return FactIDs.end(); }
841a1fa47139d6e9e7dcc40f2809605d1a258624e7fDeLesley Hutchins
842a1fa47139d6e9e7dcc40f2809605d1a258624e7fDeLesley Hutchins  bool isEmpty() const { return FactIDs.size() == 0; }
843a1fa47139d6e9e7dcc40f2809605d1a258624e7fDeLesley Hutchins
844a74b715cdc37c4523818a4018faae99d977aa537DeLesley Hutchins  FactID addLock(FactManager& FM, const SExpr& M, const LockData& L) {
845a1fa47139d6e9e7dcc40f2809605d1a258624e7fDeLesley Hutchins    FactID F = FM.newLock(M, L);
846a1fa47139d6e9e7dcc40f2809605d1a258624e7fDeLesley Hutchins    FactIDs.push_back(F);
847a1fa47139d6e9e7dcc40f2809605d1a258624e7fDeLesley Hutchins    return F;
848a1fa47139d6e9e7dcc40f2809605d1a258624e7fDeLesley Hutchins  }
849a1fa47139d6e9e7dcc40f2809605d1a258624e7fDeLesley Hutchins
850a74b715cdc37c4523818a4018faae99d977aa537DeLesley Hutchins  bool removeLock(FactManager& FM, const SExpr& M) {
851a1fa47139d6e9e7dcc40f2809605d1a258624e7fDeLesley Hutchins    unsigned n = FactIDs.size();
852a1fa47139d6e9e7dcc40f2809605d1a258624e7fDeLesley Hutchins    if (n == 0)
853a1fa47139d6e9e7dcc40f2809605d1a258624e7fDeLesley Hutchins      return false;
854a1fa47139d6e9e7dcc40f2809605d1a258624e7fDeLesley Hutchins
855a1fa47139d6e9e7dcc40f2809605d1a258624e7fDeLesley Hutchins    for (unsigned i = 0; i < n-1; ++i) {
856ee2f032fe0fc86762608458c2a167ae504579a64DeLesley Hutchins      if (FM[FactIDs[i]].MutID.matches(M)) {
857a1fa47139d6e9e7dcc40f2809605d1a258624e7fDeLesley Hutchins        FactIDs[i] = FactIDs[n-1];
858a1fa47139d6e9e7dcc40f2809605d1a258624e7fDeLesley Hutchins        FactIDs.pop_back();
859a1fa47139d6e9e7dcc40f2809605d1a258624e7fDeLesley Hutchins        return true;
860a1fa47139d6e9e7dcc40f2809605d1a258624e7fDeLesley Hutchins      }
861a1fa47139d6e9e7dcc40f2809605d1a258624e7fDeLesley Hutchins    }
862ee2f032fe0fc86762608458c2a167ae504579a64DeLesley Hutchins    if (FM[FactIDs[n-1]].MutID.matches(M)) {
863a1fa47139d6e9e7dcc40f2809605d1a258624e7fDeLesley Hutchins      FactIDs.pop_back();
864a1fa47139d6e9e7dcc40f2809605d1a258624e7fDeLesley Hutchins      return true;
865a1fa47139d6e9e7dcc40f2809605d1a258624e7fDeLesley Hutchins    }
866a1fa47139d6e9e7dcc40f2809605d1a258624e7fDeLesley Hutchins    return false;
867a1fa47139d6e9e7dcc40f2809605d1a258624e7fDeLesley Hutchins  }
868a1fa47139d6e9e7dcc40f2809605d1a258624e7fDeLesley Hutchins
869451f8e4ed63c97065fcbc79cf1cbbbbe1c4b6bd9DeLesley Hutchins  // Returns an iterator
870451f8e4ed63c97065fcbc79cf1cbbbbe1c4b6bd9DeLesley Hutchins  iterator findLockIter(FactManager &FM, const SExpr &M) {
871451f8e4ed63c97065fcbc79cf1cbbbbe1c4b6bd9DeLesley Hutchins    for (iterator I = begin(), E = end(); I != E; ++I) {
872451f8e4ed63c97065fcbc79cf1cbbbbe1c4b6bd9DeLesley Hutchins      const SExpr &Exp = FM[*I].MutID;
873451f8e4ed63c97065fcbc79cf1cbbbbe1c4b6bd9DeLesley Hutchins      if (Exp.matches(M))
874451f8e4ed63c97065fcbc79cf1cbbbbe1c4b6bd9DeLesley Hutchins        return I;
875451f8e4ed63c97065fcbc79cf1cbbbbe1c4b6bd9DeLesley Hutchins    }
876451f8e4ed63c97065fcbc79cf1cbbbbe1c4b6bd9DeLesley Hutchins    return end();
877451f8e4ed63c97065fcbc79cf1cbbbbe1c4b6bd9DeLesley Hutchins  }
878451f8e4ed63c97065fcbc79cf1cbbbbe1c4b6bd9DeLesley Hutchins
8793f0ec5209726641782468bd4c7597e79dda78b15DeLesley Hutchins  LockData* findLock(FactManager &FM, const SExpr &M) const {
8802de4770ec07cf3ee6f0f3fcc100c2859e35da4c7Chad Rosier    for (const_iterator I = begin(), E = end(); I != E; ++I) {
881589190b322a255c8e8b15dfde6b77ef498db7548Chad Rosier      const SExpr &Exp = FM[*I].MutID;
8822de4770ec07cf3ee6f0f3fcc100c2859e35da4c7Chad Rosier      if (Exp.matches(M))
8832de4770ec07cf3ee6f0f3fcc100c2859e35da4c7Chad Rosier        return &FM[*I].LDat;
8840b4db3e08a201c35f0011489bd5cd5d39bbe54fbDeLesley Hutchins    }
8850b4db3e08a201c35f0011489bd5cd5d39bbe54fbDeLesley Hutchins    return 0;
8860b4db3e08a201c35f0011489bd5cd5d39bbe54fbDeLesley Hutchins  }
8870b4db3e08a201c35f0011489bd5cd5d39bbe54fbDeLesley Hutchins
8883f0ec5209726641782468bd4c7597e79dda78b15DeLesley Hutchins  LockData* findLockUniv(FactManager &FM, const SExpr &M) const {
8892de4770ec07cf3ee6f0f3fcc100c2859e35da4c7Chad Rosier    for (const_iterator I = begin(), E = end(); I != E; ++I) {
890589190b322a255c8e8b15dfde6b77ef498db7548Chad Rosier      const SExpr &Exp = FM[*I].MutID;
8912de4770ec07cf3ee6f0f3fcc100c2859e35da4c7Chad Rosier      if (Exp.matches(M) || Exp.isUniversal())
8922de4770ec07cf3ee6f0f3fcc100c2859e35da4c7Chad Rosier        return &FM[*I].LDat;
893a1fa47139d6e9e7dcc40f2809605d1a258624e7fDeLesley Hutchins    }
894a1fa47139d6e9e7dcc40f2809605d1a258624e7fDeLesley Hutchins    return 0;
895a1fa47139d6e9e7dcc40f2809605d1a258624e7fDeLesley Hutchins  }
8963f0ec5209726641782468bd4c7597e79dda78b15DeLesley Hutchins
8973f0ec5209726641782468bd4c7597e79dda78b15DeLesley Hutchins  FactEntry* findPartialMatch(FactManager &FM, const SExpr &M) const {
8983f0ec5209726641782468bd4c7597e79dda78b15DeLesley Hutchins    for (const_iterator I=begin(), E=end(); I != E; ++I) {
8993f0ec5209726641782468bd4c7597e79dda78b15DeLesley Hutchins      const SExpr& Exp = FM[*I].MutID;
9003f0ec5209726641782468bd4c7597e79dda78b15DeLesley Hutchins      if (Exp.partiallyMatches(M)) return &FM[*I];
9013f0ec5209726641782468bd4c7597e79dda78b15DeLesley Hutchins    }
9023f0ec5209726641782468bd4c7597e79dda78b15DeLesley Hutchins    return 0;
9033f0ec5209726641782468bd4c7597e79dda78b15DeLesley Hutchins  }
904a1fa47139d6e9e7dcc40f2809605d1a258624e7fDeLesley Hutchins};
905a1fa47139d6e9e7dcc40f2809605d1a258624e7fDeLesley Hutchins
906a1fa47139d6e9e7dcc40f2809605d1a258624e7fDeLesley Hutchins
907a1fa47139d6e9e7dcc40f2809605d1a258624e7fDeLesley Hutchins
908a74b715cdc37c4523818a4018faae99d977aa537DeLesley Hutchins/// A Lockset maps each SExpr (defined above) to information about how it has
909402aa0698fec81e574818a0a6c2000fac0b2c4c6Caitlin Sadowski/// been locked.
910a74b715cdc37c4523818a4018faae99d977aa537DeLesley Hutchinstypedef llvm::ImmutableMap<SExpr, LockData> Lockset;
91154c350a67b47f059e1d577bdd9e2d1dc31ff82b5DeLesley Hutchinstypedef llvm::ImmutableMap<const NamedDecl*, unsigned> LocalVarContext;
912b37d2b5c0819d9ef596c7baec1e0be0d7c45b547DeLesley Hutchins
913b37d2b5c0819d9ef596c7baec1e0be0d7c45b547DeLesley Hutchinsclass LocalVariableMap;
914b37d2b5c0819d9ef596c7baec1e0be0d7c45b547DeLesley Hutchins
9152e5156274b8051217565b557bfa14c80f7990e9cRichard Smith/// A side (entry or exit) of a CFG node.
9162e5156274b8051217565b557bfa14c80f7990e9cRichard Smithenum CFGBlockSide { CBS_Entry, CBS_Exit };
917b37d2b5c0819d9ef596c7baec1e0be0d7c45b547DeLesley Hutchins
918b37d2b5c0819d9ef596c7baec1e0be0d7c45b547DeLesley Hutchins/// CFGBlockInfo is a struct which contains all the information that is
919b37d2b5c0819d9ef596c7baec1e0be0d7c45b547DeLesley Hutchins/// maintained for each block in the CFG.  See LocalVariableMap for more
920b37d2b5c0819d9ef596c7baec1e0be0d7c45b547DeLesley Hutchins/// information about the contexts.
921b37d2b5c0819d9ef596c7baec1e0be0d7c45b547DeLesley Hutchinsstruct CFGBlockInfo {
922a1fa47139d6e9e7dcc40f2809605d1a258624e7fDeLesley Hutchins  FactSet EntrySet;             // Lockset held at entry to block
923a1fa47139d6e9e7dcc40f2809605d1a258624e7fDeLesley Hutchins  FactSet ExitSet;              // Lockset held at exit from block
924b37d2b5c0819d9ef596c7baec1e0be0d7c45b547DeLesley Hutchins  LocalVarContext EntryContext; // Context held at entry to block
925b37d2b5c0819d9ef596c7baec1e0be0d7c45b547DeLesley Hutchins  LocalVarContext ExitContext;  // Context held at exit from block
9262e5156274b8051217565b557bfa14c80f7990e9cRichard Smith  SourceLocation EntryLoc;      // Location of first statement in block
9272e5156274b8051217565b557bfa14c80f7990e9cRichard Smith  SourceLocation ExitLoc;       // Location of last statement in block.
928b37d2b5c0819d9ef596c7baec1e0be0d7c45b547DeLesley Hutchins  unsigned EntryIndex;          // Used to replay contexts later
929d2f388299153d80cbe5ffaaed8a882b59a1b59bcDeLesley Hutchins  bool Reachable;               // Is this block reachable?
930b37d2b5c0819d9ef596c7baec1e0be0d7c45b547DeLesley Hutchins
931a1fa47139d6e9e7dcc40f2809605d1a258624e7fDeLesley Hutchins  const FactSet &getSet(CFGBlockSide Side) const {
9322e5156274b8051217565b557bfa14c80f7990e9cRichard Smith    return Side == CBS_Entry ? EntrySet : ExitSet;
9332e5156274b8051217565b557bfa14c80f7990e9cRichard Smith  }
9342e5156274b8051217565b557bfa14c80f7990e9cRichard Smith  SourceLocation getLocation(CFGBlockSide Side) const {
9352e5156274b8051217565b557bfa14c80f7990e9cRichard Smith    return Side == CBS_Entry ? EntryLoc : ExitLoc;
9362e5156274b8051217565b557bfa14c80f7990e9cRichard Smith  }
9372e5156274b8051217565b557bfa14c80f7990e9cRichard Smith
938b37d2b5c0819d9ef596c7baec1e0be0d7c45b547DeLesley Hutchinsprivate:
939a1fa47139d6e9e7dcc40f2809605d1a258624e7fDeLesley Hutchins  CFGBlockInfo(LocalVarContext EmptyCtx)
940d2f388299153d80cbe5ffaaed8a882b59a1b59bcDeLesley Hutchins    : EntryContext(EmptyCtx), ExitContext(EmptyCtx), Reachable(false)
941b37d2b5c0819d9ef596c7baec1e0be0d7c45b547DeLesley Hutchins  { }
942b37d2b5c0819d9ef596c7baec1e0be0d7c45b547DeLesley Hutchins
943b37d2b5c0819d9ef596c7baec1e0be0d7c45b547DeLesley Hutchinspublic:
944a1fa47139d6e9e7dcc40f2809605d1a258624e7fDeLesley Hutchins  static CFGBlockInfo getEmptyBlockInfo(LocalVariableMap &M);
945b37d2b5c0819d9ef596c7baec1e0be0d7c45b547DeLesley Hutchins};
946b37d2b5c0819d9ef596c7baec1e0be0d7c45b547DeLesley Hutchins
947b37d2b5c0819d9ef596c7baec1e0be0d7c45b547DeLesley Hutchins
948b37d2b5c0819d9ef596c7baec1e0be0d7c45b547DeLesley Hutchins
949b37d2b5c0819d9ef596c7baec1e0be0d7c45b547DeLesley Hutchins// A LocalVariableMap maintains a map from local variables to their currently
950b37d2b5c0819d9ef596c7baec1e0be0d7c45b547DeLesley Hutchins// valid definitions.  It provides SSA-like functionality when traversing the
951b37d2b5c0819d9ef596c7baec1e0be0d7c45b547DeLesley Hutchins// CFG.  Like SSA, each definition or assignment to a variable is assigned a
952b37d2b5c0819d9ef596c7baec1e0be0d7c45b547DeLesley Hutchins// unique name (an integer), which acts as the SSA name for that definition.
953b37d2b5c0819d9ef596c7baec1e0be0d7c45b547DeLesley Hutchins// The total set of names is shared among all CFG basic blocks.
954b37d2b5c0819d9ef596c7baec1e0be0d7c45b547DeLesley Hutchins// Unlike SSA, we do not rewrite expressions to replace local variables declrefs
955b37d2b5c0819d9ef596c7baec1e0be0d7c45b547DeLesley Hutchins// with their SSA-names.  Instead, we compute a Context for each point in the
956b37d2b5c0819d9ef596c7baec1e0be0d7c45b547DeLesley Hutchins// code, which maps local variables to the appropriate SSA-name.  This map
957b37d2b5c0819d9ef596c7baec1e0be0d7c45b547DeLesley Hutchins// changes with each assignment.
958b37d2b5c0819d9ef596c7baec1e0be0d7c45b547DeLesley Hutchins//
959b37d2b5c0819d9ef596c7baec1e0be0d7c45b547DeLesley Hutchins// The map is computed in a single pass over the CFG.  Subsequent analyses can
960b37d2b5c0819d9ef596c7baec1e0be0d7c45b547DeLesley Hutchins// then query the map to find the appropriate Context for a statement, and use
961b37d2b5c0819d9ef596c7baec1e0be0d7c45b547DeLesley Hutchins// that Context to look up the definitions of variables.
962b37d2b5c0819d9ef596c7baec1e0be0d7c45b547DeLesley Hutchinsclass LocalVariableMap {
963b37d2b5c0819d9ef596c7baec1e0be0d7c45b547DeLesley Hutchinspublic:
964b37d2b5c0819d9ef596c7baec1e0be0d7c45b547DeLesley Hutchins  typedef LocalVarContext Context;
965b37d2b5c0819d9ef596c7baec1e0be0d7c45b547DeLesley Hutchins
966b37d2b5c0819d9ef596c7baec1e0be0d7c45b547DeLesley Hutchins  /// A VarDefinition consists of an expression, representing the value of the
967b37d2b5c0819d9ef596c7baec1e0be0d7c45b547DeLesley Hutchins  /// variable, along with the context in which that expression should be
968b37d2b5c0819d9ef596c7baec1e0be0d7c45b547DeLesley Hutchins  /// interpreted.  A reference VarDefinition does not itself contain this
969b37d2b5c0819d9ef596c7baec1e0be0d7c45b547DeLesley Hutchins  /// information, but instead contains a pointer to a previous VarDefinition.
970b37d2b5c0819d9ef596c7baec1e0be0d7c45b547DeLesley Hutchins  struct VarDefinition {
971b37d2b5c0819d9ef596c7baec1e0be0d7c45b547DeLesley Hutchins  public:
972b37d2b5c0819d9ef596c7baec1e0be0d7c45b547DeLesley Hutchins    friend class LocalVariableMap;
973b37d2b5c0819d9ef596c7baec1e0be0d7c45b547DeLesley Hutchins
97454c350a67b47f059e1d577bdd9e2d1dc31ff82b5DeLesley Hutchins    const NamedDecl *Dec;  // The original declaration for this variable.
97554c350a67b47f059e1d577bdd9e2d1dc31ff82b5DeLesley Hutchins    const Expr *Exp;       // The expression for this variable, OR
97654c350a67b47f059e1d577bdd9e2d1dc31ff82b5DeLesley Hutchins    unsigned Ref;          // Reference to another VarDefinition
97754c350a67b47f059e1d577bdd9e2d1dc31ff82b5DeLesley Hutchins    Context Ctx;           // The map with which Exp should be interpreted.
978b37d2b5c0819d9ef596c7baec1e0be0d7c45b547DeLesley Hutchins
979b37d2b5c0819d9ef596c7baec1e0be0d7c45b547DeLesley Hutchins    bool isReference() { return !Exp; }
980b37d2b5c0819d9ef596c7baec1e0be0d7c45b547DeLesley Hutchins
981b37d2b5c0819d9ef596c7baec1e0be0d7c45b547DeLesley Hutchins  private:
982b37d2b5c0819d9ef596c7baec1e0be0d7c45b547DeLesley Hutchins    // Create ordinary variable definition
98354c350a67b47f059e1d577bdd9e2d1dc31ff82b5DeLesley Hutchins    VarDefinition(const NamedDecl *D, const Expr *E, Context C)
984b37d2b5c0819d9ef596c7baec1e0be0d7c45b547DeLesley Hutchins      : Dec(D), Exp(E), Ref(0), Ctx(C)
985b37d2b5c0819d9ef596c7baec1e0be0d7c45b547DeLesley Hutchins    { }
986b37d2b5c0819d9ef596c7baec1e0be0d7c45b547DeLesley Hutchins
987b37d2b5c0819d9ef596c7baec1e0be0d7c45b547DeLesley Hutchins    // Create reference to previous definition
98854c350a67b47f059e1d577bdd9e2d1dc31ff82b5DeLesley Hutchins    VarDefinition(const NamedDecl *D, unsigned R, Context C)
989b37d2b5c0819d9ef596c7baec1e0be0d7c45b547DeLesley Hutchins      : Dec(D), Exp(0), Ref(R), Ctx(C)
990b37d2b5c0819d9ef596c7baec1e0be0d7c45b547DeLesley Hutchins    { }
991b37d2b5c0819d9ef596c7baec1e0be0d7c45b547DeLesley Hutchins  };
992b37d2b5c0819d9ef596c7baec1e0be0d7c45b547DeLesley Hutchins
993b37d2b5c0819d9ef596c7baec1e0be0d7c45b547DeLesley Hutchinsprivate:
994b37d2b5c0819d9ef596c7baec1e0be0d7c45b547DeLesley Hutchins  Context::Factory ContextFactory;
995b37d2b5c0819d9ef596c7baec1e0be0d7c45b547DeLesley Hutchins  std::vector<VarDefinition> VarDefinitions;
996b37d2b5c0819d9ef596c7baec1e0be0d7c45b547DeLesley Hutchins  std::vector<unsigned> CtxIndices;
997b37d2b5c0819d9ef596c7baec1e0be0d7c45b547DeLesley Hutchins  std::vector<std::pair<Stmt*, Context> > SavedContexts;
998b37d2b5c0819d9ef596c7baec1e0be0d7c45b547DeLesley Hutchins
999b37d2b5c0819d9ef596c7baec1e0be0d7c45b547DeLesley Hutchinspublic:
1000b37d2b5c0819d9ef596c7baec1e0be0d7c45b547DeLesley Hutchins  LocalVariableMap() {
1001b37d2b5c0819d9ef596c7baec1e0be0d7c45b547DeLesley Hutchins    // index 0 is a placeholder for undefined variables (aka phi-nodes).
1002b37d2b5c0819d9ef596c7baec1e0be0d7c45b547DeLesley Hutchins    VarDefinitions.push_back(VarDefinition(0, 0u, getEmptyContext()));
1003b37d2b5c0819d9ef596c7baec1e0be0d7c45b547DeLesley Hutchins  }
1004b37d2b5c0819d9ef596c7baec1e0be0d7c45b547DeLesley Hutchins
1005b37d2b5c0819d9ef596c7baec1e0be0d7c45b547DeLesley Hutchins  /// Look up a definition, within the given context.
100654c350a67b47f059e1d577bdd9e2d1dc31ff82b5DeLesley Hutchins  const VarDefinition* lookup(const NamedDecl *D, Context Ctx) {
1007b37d2b5c0819d9ef596c7baec1e0be0d7c45b547DeLesley Hutchins    const unsigned *i = Ctx.lookup(D);
1008b37d2b5c0819d9ef596c7baec1e0be0d7c45b547DeLesley Hutchins    if (!i)
1009b37d2b5c0819d9ef596c7baec1e0be0d7c45b547DeLesley Hutchins      return 0;
1010b37d2b5c0819d9ef596c7baec1e0be0d7c45b547DeLesley Hutchins    assert(*i < VarDefinitions.size());
1011b37d2b5c0819d9ef596c7baec1e0be0d7c45b547DeLesley Hutchins    return &VarDefinitions[*i];
1012b37d2b5c0819d9ef596c7baec1e0be0d7c45b547DeLesley Hutchins  }
1013b37d2b5c0819d9ef596c7baec1e0be0d7c45b547DeLesley Hutchins
1014b37d2b5c0819d9ef596c7baec1e0be0d7c45b547DeLesley Hutchins  /// Look up the definition for D within the given context.  Returns
1015b4fa418a72759dfe34add850837965cbc00626e4DeLesley Hutchins  /// NULL if the expression is not statically known.  If successful, also
1016b4fa418a72759dfe34add850837965cbc00626e4DeLesley Hutchins  /// modifies Ctx to hold the context of the return Expr.
101754c350a67b47f059e1d577bdd9e2d1dc31ff82b5DeLesley Hutchins  const Expr* lookupExpr(const NamedDecl *D, Context &Ctx) {
1018b37d2b5c0819d9ef596c7baec1e0be0d7c45b547DeLesley Hutchins    const unsigned *P = Ctx.lookup(D);
1019b37d2b5c0819d9ef596c7baec1e0be0d7c45b547DeLesley Hutchins    if (!P)
1020b37d2b5c0819d9ef596c7baec1e0be0d7c45b547DeLesley Hutchins      return 0;
1021b37d2b5c0819d9ef596c7baec1e0be0d7c45b547DeLesley Hutchins
1022b37d2b5c0819d9ef596c7baec1e0be0d7c45b547DeLesley Hutchins    unsigned i = *P;
1023b37d2b5c0819d9ef596c7baec1e0be0d7c45b547DeLesley Hutchins    while (i > 0) {
1024b4fa418a72759dfe34add850837965cbc00626e4DeLesley Hutchins      if (VarDefinitions[i].Exp) {
1025b4fa418a72759dfe34add850837965cbc00626e4DeLesley Hutchins        Ctx = VarDefinitions[i].Ctx;
1026b37d2b5c0819d9ef596c7baec1e0be0d7c45b547DeLesley Hutchins        return VarDefinitions[i].Exp;
1027b4fa418a72759dfe34add850837965cbc00626e4DeLesley Hutchins      }
1028b37d2b5c0819d9ef596c7baec1e0be0d7c45b547DeLesley Hutchins      i = VarDefinitions[i].Ref;
1029b37d2b5c0819d9ef596c7baec1e0be0d7c45b547DeLesley Hutchins    }
1030b37d2b5c0819d9ef596c7baec1e0be0d7c45b547DeLesley Hutchins    return 0;
1031b37d2b5c0819d9ef596c7baec1e0be0d7c45b547DeLesley Hutchins  }
1032b37d2b5c0819d9ef596c7baec1e0be0d7c45b547DeLesley Hutchins
1033b37d2b5c0819d9ef596c7baec1e0be0d7c45b547DeLesley Hutchins  Context getEmptyContext() { return ContextFactory.getEmptyMap(); }
1034b37d2b5c0819d9ef596c7baec1e0be0d7c45b547DeLesley Hutchins
1035b37d2b5c0819d9ef596c7baec1e0be0d7c45b547DeLesley Hutchins  /// Return the next context after processing S.  This function is used by
1036b37d2b5c0819d9ef596c7baec1e0be0d7c45b547DeLesley Hutchins  /// clients of the class to get the appropriate context when traversing the
1037b37d2b5c0819d9ef596c7baec1e0be0d7c45b547DeLesley Hutchins  /// CFG.  It must be called for every assignment or DeclStmt.
1038b37d2b5c0819d9ef596c7baec1e0be0d7c45b547DeLesley Hutchins  Context getNextContext(unsigned &CtxIndex, Stmt *S, Context C) {
1039b37d2b5c0819d9ef596c7baec1e0be0d7c45b547DeLesley Hutchins    if (SavedContexts[CtxIndex+1].first == S) {
1040b37d2b5c0819d9ef596c7baec1e0be0d7c45b547DeLesley Hutchins      CtxIndex++;
1041b37d2b5c0819d9ef596c7baec1e0be0d7c45b547DeLesley Hutchins      Context Result = SavedContexts[CtxIndex].second;
1042b37d2b5c0819d9ef596c7baec1e0be0d7c45b547DeLesley Hutchins      return Result;
1043b37d2b5c0819d9ef596c7baec1e0be0d7c45b547DeLesley Hutchins    }
1044b37d2b5c0819d9ef596c7baec1e0be0d7c45b547DeLesley Hutchins    return C;
1045b37d2b5c0819d9ef596c7baec1e0be0d7c45b547DeLesley Hutchins  }
1046b37d2b5c0819d9ef596c7baec1e0be0d7c45b547DeLesley Hutchins
1047b37d2b5c0819d9ef596c7baec1e0be0d7c45b547DeLesley Hutchins  void dumpVarDefinitionName(unsigned i) {
1048b37d2b5c0819d9ef596c7baec1e0be0d7c45b547DeLesley Hutchins    if (i == 0) {
1049b37d2b5c0819d9ef596c7baec1e0be0d7c45b547DeLesley Hutchins      llvm::errs() << "Undefined";
1050b37d2b5c0819d9ef596c7baec1e0be0d7c45b547DeLesley Hutchins      return;
1051b37d2b5c0819d9ef596c7baec1e0be0d7c45b547DeLesley Hutchins    }
105254c350a67b47f059e1d577bdd9e2d1dc31ff82b5DeLesley Hutchins    const NamedDecl *Dec = VarDefinitions[i].Dec;
1053b37d2b5c0819d9ef596c7baec1e0be0d7c45b547DeLesley Hutchins    if (!Dec) {
1054b37d2b5c0819d9ef596c7baec1e0be0d7c45b547DeLesley Hutchins      llvm::errs() << "<<NULL>>";
1055b37d2b5c0819d9ef596c7baec1e0be0d7c45b547DeLesley Hutchins      return;
1056b37d2b5c0819d9ef596c7baec1e0be0d7c45b547DeLesley Hutchins    }
1057b37d2b5c0819d9ef596c7baec1e0be0d7c45b547DeLesley Hutchins    Dec->printName(llvm::errs());
105831ba6135375433b617a8587ea6cc836a014ebd86Roman Divacky    llvm::errs() << "." << i << " " << ((const void*) Dec);
1059b37d2b5c0819d9ef596c7baec1e0be0d7c45b547DeLesley Hutchins  }
1060b37d2b5c0819d9ef596c7baec1e0be0d7c45b547DeLesley Hutchins
1061b37d2b5c0819d9ef596c7baec1e0be0d7c45b547DeLesley Hutchins  /// Dumps an ASCII representation of the variable map to llvm::errs()
1062b37d2b5c0819d9ef596c7baec1e0be0d7c45b547DeLesley Hutchins  void dump() {
1063b37d2b5c0819d9ef596c7baec1e0be0d7c45b547DeLesley Hutchins    for (unsigned i = 1, e = VarDefinitions.size(); i < e; ++i) {
106454c350a67b47f059e1d577bdd9e2d1dc31ff82b5DeLesley Hutchins      const Expr *Exp = VarDefinitions[i].Exp;
1065b37d2b5c0819d9ef596c7baec1e0be0d7c45b547DeLesley Hutchins      unsigned Ref = VarDefinitions[i].Ref;
1066b37d2b5c0819d9ef596c7baec1e0be0d7c45b547DeLesley Hutchins
1067b37d2b5c0819d9ef596c7baec1e0be0d7c45b547DeLesley Hutchins      dumpVarDefinitionName(i);
1068b37d2b5c0819d9ef596c7baec1e0be0d7c45b547DeLesley Hutchins      llvm::errs() << " = ";
1069b37d2b5c0819d9ef596c7baec1e0be0d7c45b547DeLesley Hutchins      if (Exp) Exp->dump();
1070b37d2b5c0819d9ef596c7baec1e0be0d7c45b547DeLesley Hutchins      else {
1071b37d2b5c0819d9ef596c7baec1e0be0d7c45b547DeLesley Hutchins        dumpVarDefinitionName(Ref);
1072b37d2b5c0819d9ef596c7baec1e0be0d7c45b547DeLesley Hutchins        llvm::errs() << "\n";
1073b37d2b5c0819d9ef596c7baec1e0be0d7c45b547DeLesley Hutchins      }
1074b37d2b5c0819d9ef596c7baec1e0be0d7c45b547DeLesley Hutchins    }
1075b37d2b5c0819d9ef596c7baec1e0be0d7c45b547DeLesley Hutchins  }
1076b37d2b5c0819d9ef596c7baec1e0be0d7c45b547DeLesley Hutchins
1077b37d2b5c0819d9ef596c7baec1e0be0d7c45b547DeLesley Hutchins  /// Dumps an ASCII representation of a Context to llvm::errs()
1078b37d2b5c0819d9ef596c7baec1e0be0d7c45b547DeLesley Hutchins  void dumpContext(Context C) {
1079b37d2b5c0819d9ef596c7baec1e0be0d7c45b547DeLesley Hutchins    for (Context::iterator I = C.begin(), E = C.end(); I != E; ++I) {
108054c350a67b47f059e1d577bdd9e2d1dc31ff82b5DeLesley Hutchins      const NamedDecl *D = I.getKey();
1081b37d2b5c0819d9ef596c7baec1e0be0d7c45b547DeLesley Hutchins      D->printName(llvm::errs());
1082b37d2b5c0819d9ef596c7baec1e0be0d7c45b547DeLesley Hutchins      const unsigned *i = C.lookup(D);
1083b37d2b5c0819d9ef596c7baec1e0be0d7c45b547DeLesley Hutchins      llvm::errs() << " -> ";
1084b37d2b5c0819d9ef596c7baec1e0be0d7c45b547DeLesley Hutchins      dumpVarDefinitionName(*i);
1085b37d2b5c0819d9ef596c7baec1e0be0d7c45b547DeLesley Hutchins      llvm::errs() << "\n";
1086b37d2b5c0819d9ef596c7baec1e0be0d7c45b547DeLesley Hutchins    }
1087b37d2b5c0819d9ef596c7baec1e0be0d7c45b547DeLesley Hutchins  }
1088b37d2b5c0819d9ef596c7baec1e0be0d7c45b547DeLesley Hutchins
1089b37d2b5c0819d9ef596c7baec1e0be0d7c45b547DeLesley Hutchins  /// Builds the variable map.
1090b37d2b5c0819d9ef596c7baec1e0be0d7c45b547DeLesley Hutchins  void traverseCFG(CFG *CFGraph, PostOrderCFGView *SortedGraph,
1091b37d2b5c0819d9ef596c7baec1e0be0d7c45b547DeLesley Hutchins                     std::vector<CFGBlockInfo> &BlockInfo);
1092b37d2b5c0819d9ef596c7baec1e0be0d7c45b547DeLesley Hutchins
1093b37d2b5c0819d9ef596c7baec1e0be0d7c45b547DeLesley Hutchinsprotected:
1094b37d2b5c0819d9ef596c7baec1e0be0d7c45b547DeLesley Hutchins  // Get the current context index
1095b37d2b5c0819d9ef596c7baec1e0be0d7c45b547DeLesley Hutchins  unsigned getContextIndex() { return SavedContexts.size()-1; }
1096b37d2b5c0819d9ef596c7baec1e0be0d7c45b547DeLesley Hutchins
1097b37d2b5c0819d9ef596c7baec1e0be0d7c45b547DeLesley Hutchins  // Save the current context for later replay
1098b37d2b5c0819d9ef596c7baec1e0be0d7c45b547DeLesley Hutchins  void saveContext(Stmt *S, Context C) {
1099b37d2b5c0819d9ef596c7baec1e0be0d7c45b547DeLesley Hutchins    SavedContexts.push_back(std::make_pair(S,C));
1100b37d2b5c0819d9ef596c7baec1e0be0d7c45b547DeLesley Hutchins  }
1101b37d2b5c0819d9ef596c7baec1e0be0d7c45b547DeLesley Hutchins
1102b37d2b5c0819d9ef596c7baec1e0be0d7c45b547DeLesley Hutchins  // Adds a new definition to the given context, and returns a new context.
1103b37d2b5c0819d9ef596c7baec1e0be0d7c45b547DeLesley Hutchins  // This method should be called when declaring a new variable.
110454c350a67b47f059e1d577bdd9e2d1dc31ff82b5DeLesley Hutchins  Context addDefinition(const NamedDecl *D, Expr *Exp, Context Ctx) {
1105b37d2b5c0819d9ef596c7baec1e0be0d7c45b547DeLesley Hutchins    assert(!Ctx.contains(D));
1106b37d2b5c0819d9ef596c7baec1e0be0d7c45b547DeLesley Hutchins    unsigned newID = VarDefinitions.size();
1107b37d2b5c0819d9ef596c7baec1e0be0d7c45b547DeLesley Hutchins    Context NewCtx = ContextFactory.add(Ctx, D, newID);
1108b37d2b5c0819d9ef596c7baec1e0be0d7c45b547DeLesley Hutchins    VarDefinitions.push_back(VarDefinition(D, Exp, Ctx));
1109b37d2b5c0819d9ef596c7baec1e0be0d7c45b547DeLesley Hutchins    return NewCtx;
1110b37d2b5c0819d9ef596c7baec1e0be0d7c45b547DeLesley Hutchins  }
1111b37d2b5c0819d9ef596c7baec1e0be0d7c45b547DeLesley Hutchins
1112b37d2b5c0819d9ef596c7baec1e0be0d7c45b547DeLesley Hutchins  // Add a new reference to an existing definition.
111354c350a67b47f059e1d577bdd9e2d1dc31ff82b5DeLesley Hutchins  Context addReference(const NamedDecl *D, unsigned i, Context Ctx) {
1114b37d2b5c0819d9ef596c7baec1e0be0d7c45b547DeLesley Hutchins    unsigned newID = VarDefinitions.size();
1115b37d2b5c0819d9ef596c7baec1e0be0d7c45b547DeLesley Hutchins    Context NewCtx = ContextFactory.add(Ctx, D, newID);
1116b37d2b5c0819d9ef596c7baec1e0be0d7c45b547DeLesley Hutchins    VarDefinitions.push_back(VarDefinition(D, i, Ctx));
1117b37d2b5c0819d9ef596c7baec1e0be0d7c45b547DeLesley Hutchins    return NewCtx;
1118b37d2b5c0819d9ef596c7baec1e0be0d7c45b547DeLesley Hutchins  }
1119b37d2b5c0819d9ef596c7baec1e0be0d7c45b547DeLesley Hutchins
1120b37d2b5c0819d9ef596c7baec1e0be0d7c45b547DeLesley Hutchins  // Updates a definition only if that definition is already in the map.
1121b37d2b5c0819d9ef596c7baec1e0be0d7c45b547DeLesley Hutchins  // This method should be called when assigning to an existing variable.
112254c350a67b47f059e1d577bdd9e2d1dc31ff82b5DeLesley Hutchins  Context updateDefinition(const NamedDecl *D, Expr *Exp, Context Ctx) {
1123b37d2b5c0819d9ef596c7baec1e0be0d7c45b547DeLesley Hutchins    if (Ctx.contains(D)) {
1124b37d2b5c0819d9ef596c7baec1e0be0d7c45b547DeLesley Hutchins      unsigned newID = VarDefinitions.size();
1125b37d2b5c0819d9ef596c7baec1e0be0d7c45b547DeLesley Hutchins      Context NewCtx = ContextFactory.remove(Ctx, D);
1126b37d2b5c0819d9ef596c7baec1e0be0d7c45b547DeLesley Hutchins      NewCtx = ContextFactory.add(NewCtx, D, newID);
1127b37d2b5c0819d9ef596c7baec1e0be0d7c45b547DeLesley Hutchins      VarDefinitions.push_back(VarDefinition(D, Exp, Ctx));
1128b37d2b5c0819d9ef596c7baec1e0be0d7c45b547DeLesley Hutchins      return NewCtx;
1129b37d2b5c0819d9ef596c7baec1e0be0d7c45b547DeLesley Hutchins    }
1130b37d2b5c0819d9ef596c7baec1e0be0d7c45b547DeLesley Hutchins    return Ctx;
1131b37d2b5c0819d9ef596c7baec1e0be0d7c45b547DeLesley Hutchins  }
1132b37d2b5c0819d9ef596c7baec1e0be0d7c45b547DeLesley Hutchins
1133b37d2b5c0819d9ef596c7baec1e0be0d7c45b547DeLesley Hutchins  // Removes a definition from the context, but keeps the variable name
1134b37d2b5c0819d9ef596c7baec1e0be0d7c45b547DeLesley Hutchins  // as a valid variable.  The index 0 is a placeholder for cleared definitions.
113554c350a67b47f059e1d577bdd9e2d1dc31ff82b5DeLesley Hutchins  Context clearDefinition(const NamedDecl *D, Context Ctx) {
1136b37d2b5c0819d9ef596c7baec1e0be0d7c45b547DeLesley Hutchins    Context NewCtx = Ctx;
1137b37d2b5c0819d9ef596c7baec1e0be0d7c45b547DeLesley Hutchins    if (NewCtx.contains(D)) {
1138b37d2b5c0819d9ef596c7baec1e0be0d7c45b547DeLesley Hutchins      NewCtx = ContextFactory.remove(NewCtx, D);
1139b37d2b5c0819d9ef596c7baec1e0be0d7c45b547DeLesley Hutchins      NewCtx = ContextFactory.add(NewCtx, D, 0);
1140b37d2b5c0819d9ef596c7baec1e0be0d7c45b547DeLesley Hutchins    }
1141b37d2b5c0819d9ef596c7baec1e0be0d7c45b547DeLesley Hutchins    return NewCtx;
1142b37d2b5c0819d9ef596c7baec1e0be0d7c45b547DeLesley Hutchins  }
1143b37d2b5c0819d9ef596c7baec1e0be0d7c45b547DeLesley Hutchins
1144b37d2b5c0819d9ef596c7baec1e0be0d7c45b547DeLesley Hutchins  // Remove a definition entirely frmo the context.
114554c350a67b47f059e1d577bdd9e2d1dc31ff82b5DeLesley Hutchins  Context removeDefinition(const NamedDecl *D, Context Ctx) {
1146b37d2b5c0819d9ef596c7baec1e0be0d7c45b547DeLesley Hutchins    Context NewCtx = Ctx;
1147b37d2b5c0819d9ef596c7baec1e0be0d7c45b547DeLesley Hutchins    if (NewCtx.contains(D)) {
1148b37d2b5c0819d9ef596c7baec1e0be0d7c45b547DeLesley Hutchins      NewCtx = ContextFactory.remove(NewCtx, D);
1149b37d2b5c0819d9ef596c7baec1e0be0d7c45b547DeLesley Hutchins    }
1150b37d2b5c0819d9ef596c7baec1e0be0d7c45b547DeLesley Hutchins    return NewCtx;
1151b37d2b5c0819d9ef596c7baec1e0be0d7c45b547DeLesley Hutchins  }
1152b37d2b5c0819d9ef596c7baec1e0be0d7c45b547DeLesley Hutchins
1153b37d2b5c0819d9ef596c7baec1e0be0d7c45b547DeLesley Hutchins  Context intersectContexts(Context C1, Context C2);
1154b37d2b5c0819d9ef596c7baec1e0be0d7c45b547DeLesley Hutchins  Context createReferenceContext(Context C);
1155b37d2b5c0819d9ef596c7baec1e0be0d7c45b547DeLesley Hutchins  void intersectBackEdge(Context C1, Context C2);
1156b37d2b5c0819d9ef596c7baec1e0be0d7c45b547DeLesley Hutchins
1157b37d2b5c0819d9ef596c7baec1e0be0d7c45b547DeLesley Hutchins  friend class VarMapBuilder;
1158b37d2b5c0819d9ef596c7baec1e0be0d7c45b547DeLesley Hutchins};
1159b37d2b5c0819d9ef596c7baec1e0be0d7c45b547DeLesley Hutchins
1160b37d2b5c0819d9ef596c7baec1e0be0d7c45b547DeLesley Hutchins
1161b37d2b5c0819d9ef596c7baec1e0be0d7c45b547DeLesley Hutchins// This has to be defined after LocalVariableMap.
1162a1fa47139d6e9e7dcc40f2809605d1a258624e7fDeLesley HutchinsCFGBlockInfo CFGBlockInfo::getEmptyBlockInfo(LocalVariableMap &M) {
1163a1fa47139d6e9e7dcc40f2809605d1a258624e7fDeLesley Hutchins  return CFGBlockInfo(M.getEmptyContext());
1164b37d2b5c0819d9ef596c7baec1e0be0d7c45b547DeLesley Hutchins}
1165b37d2b5c0819d9ef596c7baec1e0be0d7c45b547DeLesley Hutchins
1166b37d2b5c0819d9ef596c7baec1e0be0d7c45b547DeLesley Hutchins
1167b37d2b5c0819d9ef596c7baec1e0be0d7c45b547DeLesley Hutchins/// Visitor which builds a LocalVariableMap
1168b37d2b5c0819d9ef596c7baec1e0be0d7c45b547DeLesley Hutchinsclass VarMapBuilder : public StmtVisitor<VarMapBuilder> {
1169b37d2b5c0819d9ef596c7baec1e0be0d7c45b547DeLesley Hutchinspublic:
1170b37d2b5c0819d9ef596c7baec1e0be0d7c45b547DeLesley Hutchins  LocalVariableMap* VMap;
1171b37d2b5c0819d9ef596c7baec1e0be0d7c45b547DeLesley Hutchins  LocalVariableMap::Context Ctx;
1172b37d2b5c0819d9ef596c7baec1e0be0d7c45b547DeLesley Hutchins
1173b37d2b5c0819d9ef596c7baec1e0be0d7c45b547DeLesley Hutchins  VarMapBuilder(LocalVariableMap *VM, LocalVariableMap::Context C)
1174b37d2b5c0819d9ef596c7baec1e0be0d7c45b547DeLesley Hutchins    : VMap(VM), Ctx(C) {}
1175b37d2b5c0819d9ef596c7baec1e0be0d7c45b547DeLesley Hutchins
1176b37d2b5c0819d9ef596c7baec1e0be0d7c45b547DeLesley Hutchins  void VisitDeclStmt(DeclStmt *S);
1177b37d2b5c0819d9ef596c7baec1e0be0d7c45b547DeLesley Hutchins  void VisitBinaryOperator(BinaryOperator *BO);
1178b37d2b5c0819d9ef596c7baec1e0be0d7c45b547DeLesley Hutchins};
1179b37d2b5c0819d9ef596c7baec1e0be0d7c45b547DeLesley Hutchins
1180b37d2b5c0819d9ef596c7baec1e0be0d7c45b547DeLesley Hutchins
1181b37d2b5c0819d9ef596c7baec1e0be0d7c45b547DeLesley Hutchins// Add new local variables to the variable map
1182b37d2b5c0819d9ef596c7baec1e0be0d7c45b547DeLesley Hutchinsvoid VarMapBuilder::VisitDeclStmt(DeclStmt *S) {
1183b37d2b5c0819d9ef596c7baec1e0be0d7c45b547DeLesley Hutchins  bool modifiedCtx = false;
1184b37d2b5c0819d9ef596c7baec1e0be0d7c45b547DeLesley Hutchins  DeclGroupRef DGrp = S->getDeclGroup();
1185b37d2b5c0819d9ef596c7baec1e0be0d7c45b547DeLesley Hutchins  for (DeclGroupRef::iterator I = DGrp.begin(), E = DGrp.end(); I != E; ++I) {
1186b37d2b5c0819d9ef596c7baec1e0be0d7c45b547DeLesley Hutchins    if (VarDecl *VD = dyn_cast_or_null<VarDecl>(*I)) {
1187b37d2b5c0819d9ef596c7baec1e0be0d7c45b547DeLesley Hutchins      Expr *E = VD->getInit();
1188b37d2b5c0819d9ef596c7baec1e0be0d7c45b547DeLesley Hutchins
1189b37d2b5c0819d9ef596c7baec1e0be0d7c45b547DeLesley Hutchins      // Add local variables with trivial type to the variable map
1190b37d2b5c0819d9ef596c7baec1e0be0d7c45b547DeLesley Hutchins      QualType T = VD->getType();
1191b37d2b5c0819d9ef596c7baec1e0be0d7c45b547DeLesley Hutchins      if (T.isTrivialType(VD->getASTContext())) {
1192b37d2b5c0819d9ef596c7baec1e0be0d7c45b547DeLesley Hutchins        Ctx = VMap->addDefinition(VD, E, Ctx);
1193b37d2b5c0819d9ef596c7baec1e0be0d7c45b547DeLesley Hutchins        modifiedCtx = true;
1194b37d2b5c0819d9ef596c7baec1e0be0d7c45b547DeLesley Hutchins      }
1195b37d2b5c0819d9ef596c7baec1e0be0d7c45b547DeLesley Hutchins    }
1196b37d2b5c0819d9ef596c7baec1e0be0d7c45b547DeLesley Hutchins  }
1197b37d2b5c0819d9ef596c7baec1e0be0d7c45b547DeLesley Hutchins  if (modifiedCtx)
1198b37d2b5c0819d9ef596c7baec1e0be0d7c45b547DeLesley Hutchins    VMap->saveContext(S, Ctx);
1199b37d2b5c0819d9ef596c7baec1e0be0d7c45b547DeLesley Hutchins}
1200b37d2b5c0819d9ef596c7baec1e0be0d7c45b547DeLesley Hutchins
1201b37d2b5c0819d9ef596c7baec1e0be0d7c45b547DeLesley Hutchins// Update local variable definitions in variable map
1202b37d2b5c0819d9ef596c7baec1e0be0d7c45b547DeLesley Hutchinsvoid VarMapBuilder::VisitBinaryOperator(BinaryOperator *BO) {
1203b37d2b5c0819d9ef596c7baec1e0be0d7c45b547DeLesley Hutchins  if (!BO->isAssignmentOp())
1204b37d2b5c0819d9ef596c7baec1e0be0d7c45b547DeLesley Hutchins    return;
1205b37d2b5c0819d9ef596c7baec1e0be0d7c45b547DeLesley Hutchins
1206b37d2b5c0819d9ef596c7baec1e0be0d7c45b547DeLesley Hutchins  Expr *LHSExp = BO->getLHS()->IgnoreParenCasts();
1207b37d2b5c0819d9ef596c7baec1e0be0d7c45b547DeLesley Hutchins
1208b37d2b5c0819d9ef596c7baec1e0be0d7c45b547DeLesley Hutchins  // Update the variable map and current context.
1209b37d2b5c0819d9ef596c7baec1e0be0d7c45b547DeLesley Hutchins  if (DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(LHSExp)) {
1210b37d2b5c0819d9ef596c7baec1e0be0d7c45b547DeLesley Hutchins    ValueDecl *VDec = DRE->getDecl();
1211b37d2b5c0819d9ef596c7baec1e0be0d7c45b547DeLesley Hutchins    if (Ctx.lookup(VDec)) {
1212b37d2b5c0819d9ef596c7baec1e0be0d7c45b547DeLesley Hutchins      if (BO->getOpcode() == BO_Assign)
1213b37d2b5c0819d9ef596c7baec1e0be0d7c45b547DeLesley Hutchins        Ctx = VMap->updateDefinition(VDec, BO->getRHS(), Ctx);
1214b37d2b5c0819d9ef596c7baec1e0be0d7c45b547DeLesley Hutchins      else
1215b37d2b5c0819d9ef596c7baec1e0be0d7c45b547DeLesley Hutchins        // FIXME -- handle compound assignment operators
1216b37d2b5c0819d9ef596c7baec1e0be0d7c45b547DeLesley Hutchins        Ctx = VMap->clearDefinition(VDec, Ctx);
1217b37d2b5c0819d9ef596c7baec1e0be0d7c45b547DeLesley Hutchins      VMap->saveContext(BO, Ctx);
1218b37d2b5c0819d9ef596c7baec1e0be0d7c45b547DeLesley Hutchins    }
1219b37d2b5c0819d9ef596c7baec1e0be0d7c45b547DeLesley Hutchins  }
1220b37d2b5c0819d9ef596c7baec1e0be0d7c45b547DeLesley Hutchins}
1221b37d2b5c0819d9ef596c7baec1e0be0d7c45b547DeLesley Hutchins
1222b37d2b5c0819d9ef596c7baec1e0be0d7c45b547DeLesley Hutchins
1223b37d2b5c0819d9ef596c7baec1e0be0d7c45b547DeLesley Hutchins// Computes the intersection of two contexts.  The intersection is the
1224b37d2b5c0819d9ef596c7baec1e0be0d7c45b547DeLesley Hutchins// set of variables which have the same definition in both contexts;
1225b37d2b5c0819d9ef596c7baec1e0be0d7c45b547DeLesley Hutchins// variables with different definitions are discarded.
1226b37d2b5c0819d9ef596c7baec1e0be0d7c45b547DeLesley HutchinsLocalVariableMap::Context
1227b37d2b5c0819d9ef596c7baec1e0be0d7c45b547DeLesley HutchinsLocalVariableMap::intersectContexts(Context C1, Context C2) {
1228b37d2b5c0819d9ef596c7baec1e0be0d7c45b547DeLesley Hutchins  Context Result = C1;
1229b37d2b5c0819d9ef596c7baec1e0be0d7c45b547DeLesley Hutchins  for (Context::iterator I = C1.begin(), E = C1.end(); I != E; ++I) {
123054c350a67b47f059e1d577bdd9e2d1dc31ff82b5DeLesley Hutchins    const NamedDecl *Dec = I.getKey();
1231b37d2b5c0819d9ef596c7baec1e0be0d7c45b547DeLesley Hutchins    unsigned i1 = I.getData();
1232b37d2b5c0819d9ef596c7baec1e0be0d7c45b547DeLesley Hutchins    const unsigned *i2 = C2.lookup(Dec);
1233b37d2b5c0819d9ef596c7baec1e0be0d7c45b547DeLesley Hutchins    if (!i2)             // variable doesn't exist on second path
1234b37d2b5c0819d9ef596c7baec1e0be0d7c45b547DeLesley Hutchins      Result = removeDefinition(Dec, Result);
1235b37d2b5c0819d9ef596c7baec1e0be0d7c45b547DeLesley Hutchins    else if (*i2 != i1)  // variable exists, but has different definition
1236b37d2b5c0819d9ef596c7baec1e0be0d7c45b547DeLesley Hutchins      Result = clearDefinition(Dec, Result);
1237b37d2b5c0819d9ef596c7baec1e0be0d7c45b547DeLesley Hutchins  }
1238b37d2b5c0819d9ef596c7baec1e0be0d7c45b547DeLesley Hutchins  return Result;
1239b37d2b5c0819d9ef596c7baec1e0be0d7c45b547DeLesley Hutchins}
1240b37d2b5c0819d9ef596c7baec1e0be0d7c45b547DeLesley Hutchins
1241b37d2b5c0819d9ef596c7baec1e0be0d7c45b547DeLesley Hutchins// For every variable in C, create a new variable that refers to the
1242b37d2b5c0819d9ef596c7baec1e0be0d7c45b547DeLesley Hutchins// definition in C.  Return a new context that contains these new variables.
1243b37d2b5c0819d9ef596c7baec1e0be0d7c45b547DeLesley Hutchins// (We use this for a naive implementation of SSA on loop back-edges.)
1244b37d2b5c0819d9ef596c7baec1e0be0d7c45b547DeLesley HutchinsLocalVariableMap::Context LocalVariableMap::createReferenceContext(Context C) {
1245b37d2b5c0819d9ef596c7baec1e0be0d7c45b547DeLesley Hutchins  Context Result = getEmptyContext();
1246b37d2b5c0819d9ef596c7baec1e0be0d7c45b547DeLesley Hutchins  for (Context::iterator I = C.begin(), E = C.end(); I != E; ++I) {
124754c350a67b47f059e1d577bdd9e2d1dc31ff82b5DeLesley Hutchins    const NamedDecl *Dec = I.getKey();
1248b37d2b5c0819d9ef596c7baec1e0be0d7c45b547DeLesley Hutchins    unsigned i = I.getData();
1249b37d2b5c0819d9ef596c7baec1e0be0d7c45b547DeLesley Hutchins    Result = addReference(Dec, i, Result);
1250b37d2b5c0819d9ef596c7baec1e0be0d7c45b547DeLesley Hutchins  }
1251b37d2b5c0819d9ef596c7baec1e0be0d7c45b547DeLesley Hutchins  return Result;
1252b37d2b5c0819d9ef596c7baec1e0be0d7c45b547DeLesley Hutchins}
1253b37d2b5c0819d9ef596c7baec1e0be0d7c45b547DeLesley Hutchins
1254b37d2b5c0819d9ef596c7baec1e0be0d7c45b547DeLesley Hutchins// This routine also takes the intersection of C1 and C2, but it does so by
1255b37d2b5c0819d9ef596c7baec1e0be0d7c45b547DeLesley Hutchins// altering the VarDefinitions.  C1 must be the result of an earlier call to
1256b37d2b5c0819d9ef596c7baec1e0be0d7c45b547DeLesley Hutchins// createReferenceContext.
1257b37d2b5c0819d9ef596c7baec1e0be0d7c45b547DeLesley Hutchinsvoid LocalVariableMap::intersectBackEdge(Context C1, Context C2) {
1258b37d2b5c0819d9ef596c7baec1e0be0d7c45b547DeLesley Hutchins  for (Context::iterator I = C1.begin(), E = C1.end(); I != E; ++I) {
125954c350a67b47f059e1d577bdd9e2d1dc31ff82b5DeLesley Hutchins    const NamedDecl *Dec = I.getKey();
1260b37d2b5c0819d9ef596c7baec1e0be0d7c45b547DeLesley Hutchins    unsigned i1 = I.getData();
1261b37d2b5c0819d9ef596c7baec1e0be0d7c45b547DeLesley Hutchins    VarDefinition *VDef = &VarDefinitions[i1];
1262b37d2b5c0819d9ef596c7baec1e0be0d7c45b547DeLesley Hutchins    assert(VDef->isReference());
1263b37d2b5c0819d9ef596c7baec1e0be0d7c45b547DeLesley Hutchins
1264b37d2b5c0819d9ef596c7baec1e0be0d7c45b547DeLesley Hutchins    const unsigned *i2 = C2.lookup(Dec);
1265b37d2b5c0819d9ef596c7baec1e0be0d7c45b547DeLesley Hutchins    if (!i2 || (*i2 != i1))
1266b37d2b5c0819d9ef596c7baec1e0be0d7c45b547DeLesley Hutchins      VDef->Ref = 0;    // Mark this variable as undefined
1267b37d2b5c0819d9ef596c7baec1e0be0d7c45b547DeLesley Hutchins  }
1268b37d2b5c0819d9ef596c7baec1e0be0d7c45b547DeLesley Hutchins}
1269b37d2b5c0819d9ef596c7baec1e0be0d7c45b547DeLesley Hutchins
1270b37d2b5c0819d9ef596c7baec1e0be0d7c45b547DeLesley Hutchins
1271b37d2b5c0819d9ef596c7baec1e0be0d7c45b547DeLesley Hutchins// Traverse the CFG in topological order, so all predecessors of a block
1272b37d2b5c0819d9ef596c7baec1e0be0d7c45b547DeLesley Hutchins// (excluding back-edges) are visited before the block itself.  At
1273b37d2b5c0819d9ef596c7baec1e0be0d7c45b547DeLesley Hutchins// each point in the code, we calculate a Context, which holds the set of
1274b37d2b5c0819d9ef596c7baec1e0be0d7c45b547DeLesley Hutchins// variable definitions which are visible at that point in execution.
1275b37d2b5c0819d9ef596c7baec1e0be0d7c45b547DeLesley Hutchins// Visible variables are mapped to their definitions using an array that
1276b37d2b5c0819d9ef596c7baec1e0be0d7c45b547DeLesley Hutchins// contains all definitions.
1277b37d2b5c0819d9ef596c7baec1e0be0d7c45b547DeLesley Hutchins//
1278b37d2b5c0819d9ef596c7baec1e0be0d7c45b547DeLesley Hutchins// At join points in the CFG, the set is computed as the intersection of
1279b37d2b5c0819d9ef596c7baec1e0be0d7c45b547DeLesley Hutchins// the incoming sets along each edge, E.g.
1280b37d2b5c0819d9ef596c7baec1e0be0d7c45b547DeLesley Hutchins//
1281b37d2b5c0819d9ef596c7baec1e0be0d7c45b547DeLesley Hutchins//                       { Context                 | VarDefinitions }
1282b37d2b5c0819d9ef596c7baec1e0be0d7c45b547DeLesley Hutchins//   int x = 0;          { x -> x1                 | x1 = 0 }
1283b37d2b5c0819d9ef596c7baec1e0be0d7c45b547DeLesley Hutchins//   int y = 0;          { x -> x1, y -> y1        | y1 = 0, x1 = 0 }
1284b37d2b5c0819d9ef596c7baec1e0be0d7c45b547DeLesley Hutchins//   if (b) x = 1;       { x -> x2, y -> y1        | x2 = 1, y1 = 0, ... }
1285b37d2b5c0819d9ef596c7baec1e0be0d7c45b547DeLesley Hutchins//   else   x = 2;       { x -> x3, y -> y1        | x3 = 2, x2 = 1, ... }
1286b37d2b5c0819d9ef596c7baec1e0be0d7c45b547DeLesley Hutchins//   ...                 { y -> y1  (x is unknown) | x3 = 2, x2 = 1, ... }
1287b37d2b5c0819d9ef596c7baec1e0be0d7c45b547DeLesley Hutchins//
1288b37d2b5c0819d9ef596c7baec1e0be0d7c45b547DeLesley Hutchins// This is essentially a simpler and more naive version of the standard SSA
1289b37d2b5c0819d9ef596c7baec1e0be0d7c45b547DeLesley Hutchins// algorithm.  Those definitions that remain in the intersection are from blocks
1290b37d2b5c0819d9ef596c7baec1e0be0d7c45b547DeLesley Hutchins// that strictly dominate the current block.  We do not bother to insert proper
1291b37d2b5c0819d9ef596c7baec1e0be0d7c45b547DeLesley Hutchins// phi nodes, because they are not used in our analysis; instead, wherever
1292b37d2b5c0819d9ef596c7baec1e0be0d7c45b547DeLesley Hutchins// a phi node would be required, we simply remove that definition from the
1293b37d2b5c0819d9ef596c7baec1e0be0d7c45b547DeLesley Hutchins// context (E.g. x above).
1294b37d2b5c0819d9ef596c7baec1e0be0d7c45b547DeLesley Hutchins//
1295b37d2b5c0819d9ef596c7baec1e0be0d7c45b547DeLesley Hutchins// The initial traversal does not capture back-edges, so those need to be
1296b37d2b5c0819d9ef596c7baec1e0be0d7c45b547DeLesley Hutchins// handled on a separate pass.  Whenever the first pass encounters an
1297b37d2b5c0819d9ef596c7baec1e0be0d7c45b547DeLesley Hutchins// incoming back edge, it duplicates the context, creating new definitions
1298b37d2b5c0819d9ef596c7baec1e0be0d7c45b547DeLesley Hutchins// that refer back to the originals.  (These correspond to places where SSA
1299b37d2b5c0819d9ef596c7baec1e0be0d7c45b547DeLesley Hutchins// might have to insert a phi node.)  On the second pass, these definitions are
1300bed28ac1d1463adca3ecf24fca5c30646fa9dbb2Sylvestre Ledru// set to NULL if the variable has changed on the back-edge (i.e. a phi
1301b37d2b5c0819d9ef596c7baec1e0be0d7c45b547DeLesley Hutchins// node was actually required.)  E.g.
1302b37d2b5c0819d9ef596c7baec1e0be0d7c45b547DeLesley Hutchins//
1303b37d2b5c0819d9ef596c7baec1e0be0d7c45b547DeLesley Hutchins//                       { Context           | VarDefinitions }
1304b37d2b5c0819d9ef596c7baec1e0be0d7c45b547DeLesley Hutchins//   int x = 0, y = 0;   { x -> x1, y -> y1  | y1 = 0, x1 = 0 }
1305b37d2b5c0819d9ef596c7baec1e0be0d7c45b547DeLesley Hutchins//   while (b)           { x -> x2, y -> y1  | [1st:] x2=x1; [2nd:] x2=NULL; }
1306b37d2b5c0819d9ef596c7baec1e0be0d7c45b547DeLesley Hutchins//     x = x+1;          { x -> x3, y -> y1  | x3 = x2 + 1, ... }
1307b37d2b5c0819d9ef596c7baec1e0be0d7c45b547DeLesley Hutchins//   ...                 { y -> y1           | x3 = 2, x2 = 1, ... }
1308b37d2b5c0819d9ef596c7baec1e0be0d7c45b547DeLesley Hutchins//
1309b37d2b5c0819d9ef596c7baec1e0be0d7c45b547DeLesley Hutchinsvoid LocalVariableMap::traverseCFG(CFG *CFGraph,
1310b37d2b5c0819d9ef596c7baec1e0be0d7c45b547DeLesley Hutchins                                   PostOrderCFGView *SortedGraph,
1311b37d2b5c0819d9ef596c7baec1e0be0d7c45b547DeLesley Hutchins                                   std::vector<CFGBlockInfo> &BlockInfo) {
1312b37d2b5c0819d9ef596c7baec1e0be0d7c45b547DeLesley Hutchins  PostOrderCFGView::CFGBlockSet VisitedBlocks(CFGraph);
1313b37d2b5c0819d9ef596c7baec1e0be0d7c45b547DeLesley Hutchins
1314b37d2b5c0819d9ef596c7baec1e0be0d7c45b547DeLesley Hutchins  CtxIndices.resize(CFGraph->getNumBlockIDs());
1315b37d2b5c0819d9ef596c7baec1e0be0d7c45b547DeLesley Hutchins
1316b37d2b5c0819d9ef596c7baec1e0be0d7c45b547DeLesley Hutchins  for (PostOrderCFGView::iterator I = SortedGraph->begin(),
1317b37d2b5c0819d9ef596c7baec1e0be0d7c45b547DeLesley Hutchins       E = SortedGraph->end(); I!= E; ++I) {
1318b37d2b5c0819d9ef596c7baec1e0be0d7c45b547DeLesley Hutchins    const CFGBlock *CurrBlock = *I;
1319b37d2b5c0819d9ef596c7baec1e0be0d7c45b547DeLesley Hutchins    int CurrBlockID = CurrBlock->getBlockID();
1320b37d2b5c0819d9ef596c7baec1e0be0d7c45b547DeLesley Hutchins    CFGBlockInfo *CurrBlockInfo = &BlockInfo[CurrBlockID];
1321b37d2b5c0819d9ef596c7baec1e0be0d7c45b547DeLesley Hutchins
1322b37d2b5c0819d9ef596c7baec1e0be0d7c45b547DeLesley Hutchins    VisitedBlocks.insert(CurrBlock);
1323b37d2b5c0819d9ef596c7baec1e0be0d7c45b547DeLesley Hutchins
1324b37d2b5c0819d9ef596c7baec1e0be0d7c45b547DeLesley Hutchins    // Calculate the entry context for the current block
1325b37d2b5c0819d9ef596c7baec1e0be0d7c45b547DeLesley Hutchins    bool HasBackEdges = false;
1326b37d2b5c0819d9ef596c7baec1e0be0d7c45b547DeLesley Hutchins    bool CtxInit = true;
1327b37d2b5c0819d9ef596c7baec1e0be0d7c45b547DeLesley Hutchins    for (CFGBlock::const_pred_iterator PI = CurrBlock->pred_begin(),
1328b37d2b5c0819d9ef596c7baec1e0be0d7c45b547DeLesley Hutchins         PE  = CurrBlock->pred_end(); PI != PE; ++PI) {
1329b37d2b5c0819d9ef596c7baec1e0be0d7c45b547DeLesley Hutchins      // if *PI -> CurrBlock is a back edge, so skip it
1330b37d2b5c0819d9ef596c7baec1e0be0d7c45b547DeLesley Hutchins      if (*PI == 0 || !VisitedBlocks.alreadySet(*PI)) {
1331b37d2b5c0819d9ef596c7baec1e0be0d7c45b547DeLesley Hutchins        HasBackEdges = true;
1332b37d2b5c0819d9ef596c7baec1e0be0d7c45b547DeLesley Hutchins        continue;
1333b37d2b5c0819d9ef596c7baec1e0be0d7c45b547DeLesley Hutchins      }
1334b37d2b5c0819d9ef596c7baec1e0be0d7c45b547DeLesley Hutchins
1335b37d2b5c0819d9ef596c7baec1e0be0d7c45b547DeLesley Hutchins      int PrevBlockID = (*PI)->getBlockID();
1336b37d2b5c0819d9ef596c7baec1e0be0d7c45b547DeLesley Hutchins      CFGBlockInfo *PrevBlockInfo = &BlockInfo[PrevBlockID];
1337b37d2b5c0819d9ef596c7baec1e0be0d7c45b547DeLesley Hutchins
1338b37d2b5c0819d9ef596c7baec1e0be0d7c45b547DeLesley Hutchins      if (CtxInit) {
1339b37d2b5c0819d9ef596c7baec1e0be0d7c45b547DeLesley Hutchins        CurrBlockInfo->EntryContext = PrevBlockInfo->ExitContext;
1340b37d2b5c0819d9ef596c7baec1e0be0d7c45b547DeLesley Hutchins        CtxInit = false;
1341b37d2b5c0819d9ef596c7baec1e0be0d7c45b547DeLesley Hutchins      }
1342b37d2b5c0819d9ef596c7baec1e0be0d7c45b547DeLesley Hutchins      else {
1343b37d2b5c0819d9ef596c7baec1e0be0d7c45b547DeLesley Hutchins        CurrBlockInfo->EntryContext =
1344b37d2b5c0819d9ef596c7baec1e0be0d7c45b547DeLesley Hutchins          intersectContexts(CurrBlockInfo->EntryContext,
1345b37d2b5c0819d9ef596c7baec1e0be0d7c45b547DeLesley Hutchins                            PrevBlockInfo->ExitContext);
1346b37d2b5c0819d9ef596c7baec1e0be0d7c45b547DeLesley Hutchins      }
1347b37d2b5c0819d9ef596c7baec1e0be0d7c45b547DeLesley Hutchins    }
1348b37d2b5c0819d9ef596c7baec1e0be0d7c45b547DeLesley Hutchins
1349b37d2b5c0819d9ef596c7baec1e0be0d7c45b547DeLesley Hutchins    // Duplicate the context if we have back-edges, so we can call
1350b37d2b5c0819d9ef596c7baec1e0be0d7c45b547DeLesley Hutchins    // intersectBackEdges later.
1351b37d2b5c0819d9ef596c7baec1e0be0d7c45b547DeLesley Hutchins    if (HasBackEdges)
1352b37d2b5c0819d9ef596c7baec1e0be0d7c45b547DeLesley Hutchins      CurrBlockInfo->EntryContext =
1353b37d2b5c0819d9ef596c7baec1e0be0d7c45b547DeLesley Hutchins        createReferenceContext(CurrBlockInfo->EntryContext);
1354b37d2b5c0819d9ef596c7baec1e0be0d7c45b547DeLesley Hutchins
1355b37d2b5c0819d9ef596c7baec1e0be0d7c45b547DeLesley Hutchins    // Create a starting context index for the current block
1356b37d2b5c0819d9ef596c7baec1e0be0d7c45b547DeLesley Hutchins    saveContext(0, CurrBlockInfo->EntryContext);
1357b37d2b5c0819d9ef596c7baec1e0be0d7c45b547DeLesley Hutchins    CurrBlockInfo->EntryIndex = getContextIndex();
1358b37d2b5c0819d9ef596c7baec1e0be0d7c45b547DeLesley Hutchins
1359b37d2b5c0819d9ef596c7baec1e0be0d7c45b547DeLesley Hutchins    // Visit all the statements in the basic block.
1360b37d2b5c0819d9ef596c7baec1e0be0d7c45b547DeLesley Hutchins    VarMapBuilder VMapBuilder(this, CurrBlockInfo->EntryContext);
1361b37d2b5c0819d9ef596c7baec1e0be0d7c45b547DeLesley Hutchins    for (CFGBlock::const_iterator BI = CurrBlock->begin(),
1362b37d2b5c0819d9ef596c7baec1e0be0d7c45b547DeLesley Hutchins         BE = CurrBlock->end(); BI != BE; ++BI) {
1363b37d2b5c0819d9ef596c7baec1e0be0d7c45b547DeLesley Hutchins      switch (BI->getKind()) {
1364b37d2b5c0819d9ef596c7baec1e0be0d7c45b547DeLesley Hutchins        case CFGElement::Statement: {
1365fdf6a279c9a75c778eba382d9a156697092982a1David Blaikie          CFGStmt CS = BI->castAs<CFGStmt>();
1366fdf6a279c9a75c778eba382d9a156697092982a1David Blaikie          VMapBuilder.Visit(const_cast<Stmt*>(CS.getStmt()));
1367b37d2b5c0819d9ef596c7baec1e0be0d7c45b547DeLesley Hutchins          break;
1368b37d2b5c0819d9ef596c7baec1e0be0d7c45b547DeLesley Hutchins        }
1369b37d2b5c0819d9ef596c7baec1e0be0d7c45b547DeLesley Hutchins        default:
1370b37d2b5c0819d9ef596c7baec1e0be0d7c45b547DeLesley Hutchins          break;
1371b37d2b5c0819d9ef596c7baec1e0be0d7c45b547DeLesley Hutchins      }
1372b37d2b5c0819d9ef596c7baec1e0be0d7c45b547DeLesley Hutchins    }
1373b37d2b5c0819d9ef596c7baec1e0be0d7c45b547DeLesley Hutchins    CurrBlockInfo->ExitContext = VMapBuilder.Ctx;
1374b37d2b5c0819d9ef596c7baec1e0be0d7c45b547DeLesley Hutchins
1375b37d2b5c0819d9ef596c7baec1e0be0d7c45b547DeLesley Hutchins    // Mark variables on back edges as "unknown" if they've been changed.
1376b37d2b5c0819d9ef596c7baec1e0be0d7c45b547DeLesley Hutchins    for (CFGBlock::const_succ_iterator SI = CurrBlock->succ_begin(),
1377b37d2b5c0819d9ef596c7baec1e0be0d7c45b547DeLesley Hutchins         SE  = CurrBlock->succ_end(); SI != SE; ++SI) {
1378b37d2b5c0819d9ef596c7baec1e0be0d7c45b547DeLesley Hutchins      // if CurrBlock -> *SI is *not* a back edge
1379b37d2b5c0819d9ef596c7baec1e0be0d7c45b547DeLesley Hutchins      if (*SI == 0 || !VisitedBlocks.alreadySet(*SI))
1380b37d2b5c0819d9ef596c7baec1e0be0d7c45b547DeLesley Hutchins        continue;
1381b37d2b5c0819d9ef596c7baec1e0be0d7c45b547DeLesley Hutchins
1382b37d2b5c0819d9ef596c7baec1e0be0d7c45b547DeLesley Hutchins      CFGBlock *FirstLoopBlock = *SI;
1383b37d2b5c0819d9ef596c7baec1e0be0d7c45b547DeLesley Hutchins      Context LoopBegin = BlockInfo[FirstLoopBlock->getBlockID()].EntryContext;
1384b37d2b5c0819d9ef596c7baec1e0be0d7c45b547DeLesley Hutchins      Context LoopEnd   = CurrBlockInfo->ExitContext;
1385b37d2b5c0819d9ef596c7baec1e0be0d7c45b547DeLesley Hutchins      intersectBackEdge(LoopBegin, LoopEnd);
1386b37d2b5c0819d9ef596c7baec1e0be0d7c45b547DeLesley Hutchins    }
1387b37d2b5c0819d9ef596c7baec1e0be0d7c45b547DeLesley Hutchins  }
1388b37d2b5c0819d9ef596c7baec1e0be0d7c45b547DeLesley Hutchins
1389b37d2b5c0819d9ef596c7baec1e0be0d7c45b547DeLesley Hutchins  // Put an extra entry at the end of the indexed context array
1390b37d2b5c0819d9ef596c7baec1e0be0d7c45b547DeLesley Hutchins  unsigned exitID = CFGraph->getExit().getBlockID();
1391b37d2b5c0819d9ef596c7baec1e0be0d7c45b547DeLesley Hutchins  saveContext(0, BlockInfo[exitID].ExitContext);
1392b37d2b5c0819d9ef596c7baec1e0be0d7c45b547DeLesley Hutchins}
1393b37d2b5c0819d9ef596c7baec1e0be0d7c45b547DeLesley Hutchins
13942e5156274b8051217565b557bfa14c80f7990e9cRichard Smith/// Find the appropriate source locations to use when producing diagnostics for
13952e5156274b8051217565b557bfa14c80f7990e9cRichard Smith/// each block in the CFG.
13962e5156274b8051217565b557bfa14c80f7990e9cRichard Smithstatic void findBlockLocations(CFG *CFGraph,
13972e5156274b8051217565b557bfa14c80f7990e9cRichard Smith                               PostOrderCFGView *SortedGraph,
13982e5156274b8051217565b557bfa14c80f7990e9cRichard Smith                               std::vector<CFGBlockInfo> &BlockInfo) {
13992e5156274b8051217565b557bfa14c80f7990e9cRichard Smith  for (PostOrderCFGView::iterator I = SortedGraph->begin(),
14002e5156274b8051217565b557bfa14c80f7990e9cRichard Smith       E = SortedGraph->end(); I!= E; ++I) {
14012e5156274b8051217565b557bfa14c80f7990e9cRichard Smith    const CFGBlock *CurrBlock = *I;
14022e5156274b8051217565b557bfa14c80f7990e9cRichard Smith    CFGBlockInfo *CurrBlockInfo = &BlockInfo[CurrBlock->getBlockID()];
14032e5156274b8051217565b557bfa14c80f7990e9cRichard Smith
14042e5156274b8051217565b557bfa14c80f7990e9cRichard Smith    // Find the source location of the last statement in the block, if the
14052e5156274b8051217565b557bfa14c80f7990e9cRichard Smith    // block is not empty.
14062e5156274b8051217565b557bfa14c80f7990e9cRichard Smith    if (const Stmt *S = CurrBlock->getTerminator()) {
14072e5156274b8051217565b557bfa14c80f7990e9cRichard Smith      CurrBlockInfo->EntryLoc = CurrBlockInfo->ExitLoc = S->getLocStart();
14082e5156274b8051217565b557bfa14c80f7990e9cRichard Smith    } else {
14092e5156274b8051217565b557bfa14c80f7990e9cRichard Smith      for (CFGBlock::const_reverse_iterator BI = CurrBlock->rbegin(),
14102e5156274b8051217565b557bfa14c80f7990e9cRichard Smith           BE = CurrBlock->rend(); BI != BE; ++BI) {
14112e5156274b8051217565b557bfa14c80f7990e9cRichard Smith        // FIXME: Handle other CFGElement kinds.
1412b07805485c603be3d8011f72611465324c9e664bDavid Blaikie        if (Optional<CFGStmt> CS = BI->getAs<CFGStmt>()) {
1413b07805485c603be3d8011f72611465324c9e664bDavid Blaikie          CurrBlockInfo->ExitLoc = CS->getStmt()->getLocStart();
14142e5156274b8051217565b557bfa14c80f7990e9cRichard Smith          break;
14152e5156274b8051217565b557bfa14c80f7990e9cRichard Smith        }
14162e5156274b8051217565b557bfa14c80f7990e9cRichard Smith      }
14172e5156274b8051217565b557bfa14c80f7990e9cRichard Smith    }
14182e5156274b8051217565b557bfa14c80f7990e9cRichard Smith
14192e5156274b8051217565b557bfa14c80f7990e9cRichard Smith    if (!CurrBlockInfo->ExitLoc.isInvalid()) {
14202e5156274b8051217565b557bfa14c80f7990e9cRichard Smith      // This block contains at least one statement. Find the source location
14212e5156274b8051217565b557bfa14c80f7990e9cRichard Smith      // of the first statement in the block.
14222e5156274b8051217565b557bfa14c80f7990e9cRichard Smith      for (CFGBlock::const_iterator BI = CurrBlock->begin(),
14232e5156274b8051217565b557bfa14c80f7990e9cRichard Smith           BE = CurrBlock->end(); BI != BE; ++BI) {
14242e5156274b8051217565b557bfa14c80f7990e9cRichard Smith        // FIXME: Handle other CFGElement kinds.
1425b07805485c603be3d8011f72611465324c9e664bDavid Blaikie        if (Optional<CFGStmt> CS = BI->getAs<CFGStmt>()) {
1426b07805485c603be3d8011f72611465324c9e664bDavid Blaikie          CurrBlockInfo->EntryLoc = CS->getStmt()->getLocStart();
14272e5156274b8051217565b557bfa14c80f7990e9cRichard Smith          break;
14282e5156274b8051217565b557bfa14c80f7990e9cRichard Smith        }
14292e5156274b8051217565b557bfa14c80f7990e9cRichard Smith      }
14302e5156274b8051217565b557bfa14c80f7990e9cRichard Smith    } else if (CurrBlock->pred_size() == 1 && *CurrBlock->pred_begin() &&
14312e5156274b8051217565b557bfa14c80f7990e9cRichard Smith               CurrBlock != &CFGraph->getExit()) {
14322e5156274b8051217565b557bfa14c80f7990e9cRichard Smith      // The block is empty, and has a single predecessor. Use its exit
14332e5156274b8051217565b557bfa14c80f7990e9cRichard Smith      // location.
14342e5156274b8051217565b557bfa14c80f7990e9cRichard Smith      CurrBlockInfo->EntryLoc = CurrBlockInfo->ExitLoc =
14352e5156274b8051217565b557bfa14c80f7990e9cRichard Smith          BlockInfo[(*CurrBlock->pred_begin())->getBlockID()].ExitLoc;
14362e5156274b8051217565b557bfa14c80f7990e9cRichard Smith    }
14372e5156274b8051217565b557bfa14c80f7990e9cRichard Smith  }
14382e5156274b8051217565b557bfa14c80f7990e9cRichard Smith}
1439b37d2b5c0819d9ef596c7baec1e0be0d7c45b547DeLesley Hutchins
1440b37d2b5c0819d9ef596c7baec1e0be0d7c45b547DeLesley Hutchins/// \brief Class which implements the core thread safety analysis routines.
1441b37d2b5c0819d9ef596c7baec1e0be0d7c45b547DeLesley Hutchinsclass ThreadSafetyAnalyzer {
1442b37d2b5c0819d9ef596c7baec1e0be0d7c45b547DeLesley Hutchins  friend class BuildLockset;
1443b37d2b5c0819d9ef596c7baec1e0be0d7c45b547DeLesley Hutchins
144454c350a67b47f059e1d577bdd9e2d1dc31ff82b5DeLesley Hutchins  ThreadSafetyHandler       &Handler;
144554c350a67b47f059e1d577bdd9e2d1dc31ff82b5DeLesley Hutchins  LocalVariableMap          LocalVarMap;
1446a1fa47139d6e9e7dcc40f2809605d1a258624e7fDeLesley Hutchins  FactManager               FactMan;
144754c350a67b47f059e1d577bdd9e2d1dc31ff82b5DeLesley Hutchins  std::vector<CFGBlockInfo> BlockInfo;
1448b37d2b5c0819d9ef596c7baec1e0be0d7c45b547DeLesley Hutchins
1449b37d2b5c0819d9ef596c7baec1e0be0d7c45b547DeLesley Hutchinspublic:
1450b37d2b5c0819d9ef596c7baec1e0be0d7c45b547DeLesley Hutchins  ThreadSafetyAnalyzer(ThreadSafetyHandler &H) : Handler(H) {}
1451b37d2b5c0819d9ef596c7baec1e0be0d7c45b547DeLesley Hutchins
1452a74b715cdc37c4523818a4018faae99d977aa537DeLesley Hutchins  void addLock(FactSet &FSet, const SExpr &Mutex, const LockData &LDat);
1453a74b715cdc37c4523818a4018faae99d977aa537DeLesley Hutchins  void removeLock(FactSet &FSet, const SExpr &Mutex,
1454a1fa47139d6e9e7dcc40f2809605d1a258624e7fDeLesley Hutchins                  SourceLocation UnlockLoc, bool FullyRemove=false);
1455a60448d6dfc91f4c30987e237bf70ef50ac7705bDeLesley Hutchins
14565381c05f51e5b7c7627f1d95b9a3425303ce086aDeLesley Hutchins  template <typename AttrType>
14575381c05f51e5b7c7627f1d95b9a3425303ce086aDeLesley Hutchins  void getMutexIDs(MutexIDList &Mtxs, AttrType *Attr, Expr *Exp,
1458ef2388b10c41a9696d5d81f42ca79ff005fef7fcDeLesley Hutchins                   const NamedDecl *D, VarDecl *SelfDecl=0);
1459402aa0698fec81e574818a0a6c2000fac0b2c4c6Caitlin Sadowski
1460b4fa418a72759dfe34add850837965cbc00626e4DeLesley Hutchins  template <class AttrType>
14615381c05f51e5b7c7627f1d95b9a3425303ce086aDeLesley Hutchins  void getMutexIDs(MutexIDList &Mtxs, AttrType *Attr, Expr *Exp,
14625381c05f51e5b7c7627f1d95b9a3425303ce086aDeLesley Hutchins                   const NamedDecl *D,
14635381c05f51e5b7c7627f1d95b9a3425303ce086aDeLesley Hutchins                   const CFGBlock *PredBlock, const CFGBlock *CurrBlock,
14645381c05f51e5b7c7627f1d95b9a3425303ce086aDeLesley Hutchins                   Expr *BrE, bool Neg);
14655381c05f51e5b7c7627f1d95b9a3425303ce086aDeLesley Hutchins
146654c350a67b47f059e1d577bdd9e2d1dc31ff82b5DeLesley Hutchins  const CallExpr* getTrylockCallExpr(const Stmt *Cond, LocalVarContext C,
146754c350a67b47f059e1d577bdd9e2d1dc31ff82b5DeLesley Hutchins                                     bool &Negate);
1468b4fa418a72759dfe34add850837965cbc00626e4DeLesley Hutchins
1469a1fa47139d6e9e7dcc40f2809605d1a258624e7fDeLesley Hutchins  void getEdgeLockset(FactSet &Result, const FactSet &ExitSet,
1470a1fa47139d6e9e7dcc40f2809605d1a258624e7fDeLesley Hutchins                      const CFGBlock* PredBlock,
1471a1fa47139d6e9e7dcc40f2809605d1a258624e7fDeLesley Hutchins                      const CFGBlock *CurrBlock);
14720da4414f3d30c34fafb81b13b2cec3680c0bc9e1DeLesley Hutchins
1473a1fa47139d6e9e7dcc40f2809605d1a258624e7fDeLesley Hutchins  void intersectAndWarn(FactSet &FSet1, const FactSet &FSet2,
1474a1fa47139d6e9e7dcc40f2809605d1a258624e7fDeLesley Hutchins                        SourceLocation JoinLoc,
1475a1fa47139d6e9e7dcc40f2809605d1a258624e7fDeLesley Hutchins                        LockErrorKind LEK1, LockErrorKind LEK2,
1476a1fa47139d6e9e7dcc40f2809605d1a258624e7fDeLesley Hutchins                        bool Modify=true);
1477879a4334e4c4cab0c22ba91492ffc2838bbc21fcDeLesley Hutchins
1478a1fa47139d6e9e7dcc40f2809605d1a258624e7fDeLesley Hutchins  void intersectAndWarn(FactSet &FSet1, const FactSet &FSet2,
1479a1fa47139d6e9e7dcc40f2809605d1a258624e7fDeLesley Hutchins                        SourceLocation JoinLoc, LockErrorKind LEK1,
1480a1fa47139d6e9e7dcc40f2809605d1a258624e7fDeLesley Hutchins                        bool Modify=true) {
1481a1fa47139d6e9e7dcc40f2809605d1a258624e7fDeLesley Hutchins    intersectAndWarn(FSet1, FSet2, JoinLoc, LEK1, LEK1, Modify);
1482879a4334e4c4cab0c22ba91492ffc2838bbc21fcDeLesley Hutchins  }
1483402aa0698fec81e574818a0a6c2000fac0b2c4c6Caitlin Sadowski
148454c350a67b47f059e1d577bdd9e2d1dc31ff82b5DeLesley Hutchins  void runAnalysis(AnalysisDeclContext &AC);
1485402aa0698fec81e574818a0a6c2000fac0b2c4c6Caitlin Sadowski};
1486402aa0698fec81e574818a0a6c2000fac0b2c4c6Caitlin Sadowski
148754c350a67b47f059e1d577bdd9e2d1dc31ff82b5DeLesley Hutchins
1488402aa0698fec81e574818a0a6c2000fac0b2c4c6Caitlin Sadowski/// \brief Add a new lock to the lockset, warning if the lock is already there.
14891fa3c0682a52c45c4ad0be3a82d0c85f26657072DeLesley Hutchins/// \param Mutex -- the Mutex expression for the lock
14901fa3c0682a52c45c4ad0be3a82d0c85f26657072DeLesley Hutchins/// \param LDat  -- the LockData for the lock
1491a74b715cdc37c4523818a4018faae99d977aa537DeLesley Hutchinsvoid ThreadSafetyAnalyzer::addLock(FactSet &FSet, const SExpr &Mutex,
1492a1fa47139d6e9e7dcc40f2809605d1a258624e7fDeLesley Hutchins                                   const LockData &LDat) {
14931fa3c0682a52c45c4ad0be3a82d0c85f26657072DeLesley Hutchins  // FIXME: deal with acquired before/after annotations.
1494402aa0698fec81e574818a0a6c2000fac0b2c4c6Caitlin Sadowski  // FIXME: Don't always warn when we have support for reentrant locks.
14954e4c15765d5f097e21dcaa30f1a94481924340f7DeLesley Hutchins  if (Mutex.shouldIgnore())
14964e4c15765d5f097e21dcaa30f1a94481924340f7DeLesley Hutchins    return;
14974e4c15765d5f097e21dcaa30f1a94481924340f7DeLesley Hutchins
1498a1fa47139d6e9e7dcc40f2809605d1a258624e7fDeLesley Hutchins  if (FSet.findLock(FactMan, Mutex)) {
14995c6134fd09bc5b738dafdd1c774edde13d95cb20DeLesley Hutchins    if (!LDat.Asserted)
15005c6134fd09bc5b738dafdd1c774edde13d95cb20DeLesley Hutchins      Handler.handleDoubleLock(Mutex.toString(), LDat.AcquireLoc);
150154c350a67b47f059e1d577bdd9e2d1dc31ff82b5DeLesley Hutchins  } else {
1502a1fa47139d6e9e7dcc40f2809605d1a258624e7fDeLesley Hutchins    FSet.addLock(FactMan, Mutex, LDat);
150354c350a67b47f059e1d577bdd9e2d1dc31ff82b5DeLesley Hutchins  }
150454c350a67b47f059e1d577bdd9e2d1dc31ff82b5DeLesley Hutchins}
150554c350a67b47f059e1d577bdd9e2d1dc31ff82b5DeLesley Hutchins
150654c350a67b47f059e1d577bdd9e2d1dc31ff82b5DeLesley Hutchins
1507402aa0698fec81e574818a0a6c2000fac0b2c4c6Caitlin Sadowski/// \brief Remove a lock from the lockset, warning if the lock is not there.
1508ad0fe03b897f9486191e75c8d90c3ffa9b4fd6a5Ted Kremenek/// \param Mutex The lock expression corresponding to the lock to be removed
1509402aa0698fec81e574818a0a6c2000fac0b2c4c6Caitlin Sadowski/// \param UnlockLoc The source location of the unlock (only used in error msg)
1510a1fa47139d6e9e7dcc40f2809605d1a258624e7fDeLesley Hutchinsvoid ThreadSafetyAnalyzer::removeLock(FactSet &FSet,
1511a74b715cdc37c4523818a4018faae99d977aa537DeLesley Hutchins                                      const SExpr &Mutex,
1512a1fa47139d6e9e7dcc40f2809605d1a258624e7fDeLesley Hutchins                                      SourceLocation UnlockLoc,
1513a1fa47139d6e9e7dcc40f2809605d1a258624e7fDeLesley Hutchins                                      bool FullyRemove) {
15144e4c15765d5f097e21dcaa30f1a94481924340f7DeLesley Hutchins  if (Mutex.shouldIgnore())
15154e4c15765d5f097e21dcaa30f1a94481924340f7DeLesley Hutchins    return;
15164e4c15765d5f097e21dcaa30f1a94481924340f7DeLesley Hutchins
1517a1fa47139d6e9e7dcc40f2809605d1a258624e7fDeLesley Hutchins  const LockData *LDat = FSet.findLock(FactMan, Mutex);
151854c350a67b47f059e1d577bdd9e2d1dc31ff82b5DeLesley Hutchins  if (!LDat) {
1519a74b715cdc37c4523818a4018faae99d977aa537DeLesley Hutchins    Handler.handleUnmatchedUnlock(Mutex.toString(), UnlockLoc);
1520a1fa47139d6e9e7dcc40f2809605d1a258624e7fDeLesley Hutchins    return;
152154c350a67b47f059e1d577bdd9e2d1dc31ff82b5DeLesley Hutchins  }
1522a1fa47139d6e9e7dcc40f2809605d1a258624e7fDeLesley Hutchins
15235381c05f51e5b7c7627f1d95b9a3425303ce086aDeLesley Hutchins  if (LDat->UnderlyingMutex.isValid()) {
15245381c05f51e5b7c7627f1d95b9a3425303ce086aDeLesley Hutchins    // This is scoped lockable object, which manages the real mutex.
15255381c05f51e5b7c7627f1d95b9a3425303ce086aDeLesley Hutchins    if (FullyRemove) {
15265381c05f51e5b7c7627f1d95b9a3425303ce086aDeLesley Hutchins      // We're destroying the managing object.
15275381c05f51e5b7c7627f1d95b9a3425303ce086aDeLesley Hutchins      // Remove the underlying mutex if it exists; but don't warn.
1528a1fa47139d6e9e7dcc40f2809605d1a258624e7fDeLesley Hutchins      if (FSet.findLock(FactMan, LDat->UnderlyingMutex))
1529a1fa47139d6e9e7dcc40f2809605d1a258624e7fDeLesley Hutchins        FSet.removeLock(FactMan, LDat->UnderlyingMutex);
15305381c05f51e5b7c7627f1d95b9a3425303ce086aDeLesley Hutchins    } else {
15315381c05f51e5b7c7627f1d95b9a3425303ce086aDeLesley Hutchins      // We're releasing the underlying mutex, but not destroying the
15325381c05f51e5b7c7627f1d95b9a3425303ce086aDeLesley Hutchins      // managing object.  Warn on dual release.
1533a1fa47139d6e9e7dcc40f2809605d1a258624e7fDeLesley Hutchins      if (!FSet.findLock(FactMan, LDat->UnderlyingMutex)) {
1534a74b715cdc37c4523818a4018faae99d977aa537DeLesley Hutchins        Handler.handleUnmatchedUnlock(LDat->UnderlyingMutex.toString(),
15355381c05f51e5b7c7627f1d95b9a3425303ce086aDeLesley Hutchins                                      UnlockLoc);
15365381c05f51e5b7c7627f1d95b9a3425303ce086aDeLesley Hutchins      }
1537a1fa47139d6e9e7dcc40f2809605d1a258624e7fDeLesley Hutchins      FSet.removeLock(FactMan, LDat->UnderlyingMutex);
1538a1fa47139d6e9e7dcc40f2809605d1a258624e7fDeLesley Hutchins      return;
1539c99a5d820ead4e4f1f4b4a8ab61007b8da0307e6DeLesley Hutchins    }
15401fa3c0682a52c45c4ad0be3a82d0c85f26657072DeLesley Hutchins  }
1541a1fa47139d6e9e7dcc40f2809605d1a258624e7fDeLesley Hutchins  FSet.removeLock(FactMan, Mutex);
1542402aa0698fec81e574818a0a6c2000fac0b2c4c6Caitlin Sadowski}
1543402aa0698fec81e574818a0a6c2000fac0b2c4c6Caitlin Sadowski
1544c99a5d820ead4e4f1f4b4a8ab61007b8da0307e6DeLesley Hutchins
15455381c05f51e5b7c7627f1d95b9a3425303ce086aDeLesley Hutchins/// \brief Extract the list of mutexIDs from the attribute on an expression,
15465381c05f51e5b7c7627f1d95b9a3425303ce086aDeLesley Hutchins/// and push them onto Mtxs, discarding any duplicates.
1547a60448d6dfc91f4c30987e237bf70ef50ac7705bDeLesley Hutchinstemplate <typename AttrType>
15485381c05f51e5b7c7627f1d95b9a3425303ce086aDeLesley Hutchinsvoid ThreadSafetyAnalyzer::getMutexIDs(MutexIDList &Mtxs, AttrType *Attr,
1549ef2388b10c41a9696d5d81f42ca79ff005fef7fcDeLesley Hutchins                                       Expr *Exp, const NamedDecl *D,
1550ef2388b10c41a9696d5d81f42ca79ff005fef7fcDeLesley Hutchins                                       VarDecl *SelfDecl) {
1551a60448d6dfc91f4c30987e237bf70ef50ac7705bDeLesley Hutchins  typedef typename AttrType::args_iterator iterator_type;
1552a60448d6dfc91f4c30987e237bf70ef50ac7705bDeLesley Hutchins
1553a60448d6dfc91f4c30987e237bf70ef50ac7705bDeLesley Hutchins  if (Attr->args_size() == 0) {
1554a60448d6dfc91f4c30987e237bf70ef50ac7705bDeLesley Hutchins    // The mutex held is the "this" object.
1555ef2388b10c41a9696d5d81f42ca79ff005fef7fcDeLesley Hutchins    SExpr Mu(0, Exp, D, SelfDecl);
15565381c05f51e5b7c7627f1d95b9a3425303ce086aDeLesley Hutchins    if (!Mu.isValid())
1557a74b715cdc37c4523818a4018faae99d977aa537DeLesley Hutchins      SExpr::warnInvalidLock(Handler, 0, Exp, D);
15585381c05f51e5b7c7627f1d95b9a3425303ce086aDeLesley Hutchins    else
15595381c05f51e5b7c7627f1d95b9a3425303ce086aDeLesley Hutchins      Mtxs.push_back_nodup(Mu);
15605381c05f51e5b7c7627f1d95b9a3425303ce086aDeLesley Hutchins    return;
1561a60448d6dfc91f4c30987e237bf70ef50ac7705bDeLesley Hutchins  }
1562a60448d6dfc91f4c30987e237bf70ef50ac7705bDeLesley Hutchins
1563a60448d6dfc91f4c30987e237bf70ef50ac7705bDeLesley Hutchins  for (iterator_type I=Attr->args_begin(), E=Attr->args_end(); I != E; ++I) {
1564ef2388b10c41a9696d5d81f42ca79ff005fef7fcDeLesley Hutchins    SExpr Mu(*I, Exp, D, SelfDecl);
15655381c05f51e5b7c7627f1d95b9a3425303ce086aDeLesley Hutchins    if (!Mu.isValid())
1566a74b715cdc37c4523818a4018faae99d977aa537DeLesley Hutchins      SExpr::warnInvalidLock(Handler, *I, Exp, D);
1567f1ac63702143d84db778d32eb185a77fc97db5f5DeLesley Hutchins    else
15685381c05f51e5b7c7627f1d95b9a3425303ce086aDeLesley Hutchins      Mtxs.push_back_nodup(Mu);
156954c350a67b47f059e1d577bdd9e2d1dc31ff82b5DeLesley Hutchins  }
157054c350a67b47f059e1d577bdd9e2d1dc31ff82b5DeLesley Hutchins}
157154c350a67b47f059e1d577bdd9e2d1dc31ff82b5DeLesley Hutchins
157254c350a67b47f059e1d577bdd9e2d1dc31ff82b5DeLesley Hutchins
15735381c05f51e5b7c7627f1d95b9a3425303ce086aDeLesley Hutchins/// \brief Extract the list of mutexIDs from a trylock attribute.  If the
15745381c05f51e5b7c7627f1d95b9a3425303ce086aDeLesley Hutchins/// trylock applies to the given edge, then push them onto Mtxs, discarding
15755381c05f51e5b7c7627f1d95b9a3425303ce086aDeLesley Hutchins/// any duplicates.
157654c350a67b47f059e1d577bdd9e2d1dc31ff82b5DeLesley Hutchinstemplate <class AttrType>
15775381c05f51e5b7c7627f1d95b9a3425303ce086aDeLesley Hutchinsvoid ThreadSafetyAnalyzer::getMutexIDs(MutexIDList &Mtxs, AttrType *Attr,
15785381c05f51e5b7c7627f1d95b9a3425303ce086aDeLesley Hutchins                                       Expr *Exp, const NamedDecl *D,
15795381c05f51e5b7c7627f1d95b9a3425303ce086aDeLesley Hutchins                                       const CFGBlock *PredBlock,
15805381c05f51e5b7c7627f1d95b9a3425303ce086aDeLesley Hutchins                                       const CFGBlock *CurrBlock,
15815381c05f51e5b7c7627f1d95b9a3425303ce086aDeLesley Hutchins                                       Expr *BrE, bool Neg) {
158254c350a67b47f059e1d577bdd9e2d1dc31ff82b5DeLesley Hutchins  // Find out which branch has the lock
158354c350a67b47f059e1d577bdd9e2d1dc31ff82b5DeLesley Hutchins  bool branch = 0;
158454c350a67b47f059e1d577bdd9e2d1dc31ff82b5DeLesley Hutchins  if (CXXBoolLiteralExpr *BLE = dyn_cast_or_null<CXXBoolLiteralExpr>(BrE)) {
158554c350a67b47f059e1d577bdd9e2d1dc31ff82b5DeLesley Hutchins    branch = BLE->getValue();
158654c350a67b47f059e1d577bdd9e2d1dc31ff82b5DeLesley Hutchins  }
158754c350a67b47f059e1d577bdd9e2d1dc31ff82b5DeLesley Hutchins  else if (IntegerLiteral *ILE = dyn_cast_or_null<IntegerLiteral>(BrE)) {
158854c350a67b47f059e1d577bdd9e2d1dc31ff82b5DeLesley Hutchins    branch = ILE->getValue().getBoolValue();
158954c350a67b47f059e1d577bdd9e2d1dc31ff82b5DeLesley Hutchins  }
159054c350a67b47f059e1d577bdd9e2d1dc31ff82b5DeLesley Hutchins  int branchnum = branch ? 0 : 1;
159154c350a67b47f059e1d577bdd9e2d1dc31ff82b5DeLesley Hutchins  if (Neg) branchnum = !branchnum;
159254c350a67b47f059e1d577bdd9e2d1dc31ff82b5DeLesley Hutchins
159354c350a67b47f059e1d577bdd9e2d1dc31ff82b5DeLesley Hutchins  // If we've taken the trylock branch, then add the lock
159454c350a67b47f059e1d577bdd9e2d1dc31ff82b5DeLesley Hutchins  int i = 0;
159554c350a67b47f059e1d577bdd9e2d1dc31ff82b5DeLesley Hutchins  for (CFGBlock::const_succ_iterator SI = PredBlock->succ_begin(),
159654c350a67b47f059e1d577bdd9e2d1dc31ff82b5DeLesley Hutchins       SE = PredBlock->succ_end(); SI != SE && i < 2; ++SI, ++i) {
159754c350a67b47f059e1d577bdd9e2d1dc31ff82b5DeLesley Hutchins    if (*SI == CurrBlock && i == branchnum) {
15985381c05f51e5b7c7627f1d95b9a3425303ce086aDeLesley Hutchins      getMutexIDs(Mtxs, Attr, Exp, D);
159954c350a67b47f059e1d577bdd9e2d1dc31ff82b5DeLesley Hutchins    }
160054c350a67b47f059e1d577bdd9e2d1dc31ff82b5DeLesley Hutchins  }
160154c350a67b47f059e1d577bdd9e2d1dc31ff82b5DeLesley Hutchins}
160254c350a67b47f059e1d577bdd9e2d1dc31ff82b5DeLesley Hutchins
160354c350a67b47f059e1d577bdd9e2d1dc31ff82b5DeLesley Hutchins
160413106117060c90d6f84bd2ed7a5c03e0502ff419DeLesley Hutchinsbool getStaticBooleanValue(Expr* E, bool& TCond) {
160513106117060c90d6f84bd2ed7a5c03e0502ff419DeLesley Hutchins  if (isa<CXXNullPtrLiteralExpr>(E) || isa<GNUNullExpr>(E)) {
160613106117060c90d6f84bd2ed7a5c03e0502ff419DeLesley Hutchins    TCond = false;
160713106117060c90d6f84bd2ed7a5c03e0502ff419DeLesley Hutchins    return true;
160813106117060c90d6f84bd2ed7a5c03e0502ff419DeLesley Hutchins  } else if (CXXBoolLiteralExpr *BLE = dyn_cast<CXXBoolLiteralExpr>(E)) {
160913106117060c90d6f84bd2ed7a5c03e0502ff419DeLesley Hutchins    TCond = BLE->getValue();
161013106117060c90d6f84bd2ed7a5c03e0502ff419DeLesley Hutchins    return true;
161113106117060c90d6f84bd2ed7a5c03e0502ff419DeLesley Hutchins  } else if (IntegerLiteral *ILE = dyn_cast<IntegerLiteral>(E)) {
161213106117060c90d6f84bd2ed7a5c03e0502ff419DeLesley Hutchins    TCond = ILE->getValue().getBoolValue();
161313106117060c90d6f84bd2ed7a5c03e0502ff419DeLesley Hutchins    return true;
161413106117060c90d6f84bd2ed7a5c03e0502ff419DeLesley Hutchins  } else if (ImplicitCastExpr *CE = dyn_cast<ImplicitCastExpr>(E)) {
161513106117060c90d6f84bd2ed7a5c03e0502ff419DeLesley Hutchins    return getStaticBooleanValue(CE->getSubExpr(), TCond);
161613106117060c90d6f84bd2ed7a5c03e0502ff419DeLesley Hutchins  }
161713106117060c90d6f84bd2ed7a5c03e0502ff419DeLesley Hutchins  return false;
161813106117060c90d6f84bd2ed7a5c03e0502ff419DeLesley Hutchins}
161913106117060c90d6f84bd2ed7a5c03e0502ff419DeLesley Hutchins
162013106117060c90d6f84bd2ed7a5c03e0502ff419DeLesley Hutchins
162154c350a67b47f059e1d577bdd9e2d1dc31ff82b5DeLesley Hutchins// If Cond can be traced back to a function call, return the call expression.
162254c350a67b47f059e1d577bdd9e2d1dc31ff82b5DeLesley Hutchins// The negate variable should be called with false, and will be set to true
162354c350a67b47f059e1d577bdd9e2d1dc31ff82b5DeLesley Hutchins// if the function call is negated, e.g. if (!mu.tryLock(...))
162454c350a67b47f059e1d577bdd9e2d1dc31ff82b5DeLesley Hutchinsconst CallExpr* ThreadSafetyAnalyzer::getTrylockCallExpr(const Stmt *Cond,
162554c350a67b47f059e1d577bdd9e2d1dc31ff82b5DeLesley Hutchins                                                         LocalVarContext C,
162654c350a67b47f059e1d577bdd9e2d1dc31ff82b5DeLesley Hutchins                                                         bool &Negate) {
162754c350a67b47f059e1d577bdd9e2d1dc31ff82b5DeLesley Hutchins  if (!Cond)
162854c350a67b47f059e1d577bdd9e2d1dc31ff82b5DeLesley Hutchins    return 0;
162954c350a67b47f059e1d577bdd9e2d1dc31ff82b5DeLesley Hutchins
163054c350a67b47f059e1d577bdd9e2d1dc31ff82b5DeLesley Hutchins  if (const CallExpr *CallExp = dyn_cast<CallExpr>(Cond)) {
163154c350a67b47f059e1d577bdd9e2d1dc31ff82b5DeLesley Hutchins    return CallExp;
163254c350a67b47f059e1d577bdd9e2d1dc31ff82b5DeLesley Hutchins  }
163313106117060c90d6f84bd2ed7a5c03e0502ff419DeLesley Hutchins  else if (const ParenExpr *PE = dyn_cast<ParenExpr>(Cond)) {
163413106117060c90d6f84bd2ed7a5c03e0502ff419DeLesley Hutchins    return getTrylockCallExpr(PE->getSubExpr(), C, Negate);
163513106117060c90d6f84bd2ed7a5c03e0502ff419DeLesley Hutchins  }
163654c350a67b47f059e1d577bdd9e2d1dc31ff82b5DeLesley Hutchins  else if (const ImplicitCastExpr *CE = dyn_cast<ImplicitCastExpr>(Cond)) {
163754c350a67b47f059e1d577bdd9e2d1dc31ff82b5DeLesley Hutchins    return getTrylockCallExpr(CE->getSubExpr(), C, Negate);
163854c350a67b47f059e1d577bdd9e2d1dc31ff82b5DeLesley Hutchins  }
1639fd0f11ccd51154e933fad7dfa134cb4f62c87056DeLesley Hutchins  else if (const ExprWithCleanups* EWC = dyn_cast<ExprWithCleanups>(Cond)) {
1640fd0f11ccd51154e933fad7dfa134cb4f62c87056DeLesley Hutchins    return getTrylockCallExpr(EWC->getSubExpr(), C, Negate);
1641fd0f11ccd51154e933fad7dfa134cb4f62c87056DeLesley Hutchins  }
164254c350a67b47f059e1d577bdd9e2d1dc31ff82b5DeLesley Hutchins  else if (const DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(Cond)) {
164354c350a67b47f059e1d577bdd9e2d1dc31ff82b5DeLesley Hutchins    const Expr *E = LocalVarMap.lookupExpr(DRE->getDecl(), C);
164454c350a67b47f059e1d577bdd9e2d1dc31ff82b5DeLesley Hutchins    return getTrylockCallExpr(E, C, Negate);
164554c350a67b47f059e1d577bdd9e2d1dc31ff82b5DeLesley Hutchins  }
164654c350a67b47f059e1d577bdd9e2d1dc31ff82b5DeLesley Hutchins  else if (const UnaryOperator *UOP = dyn_cast<UnaryOperator>(Cond)) {
164754c350a67b47f059e1d577bdd9e2d1dc31ff82b5DeLesley Hutchins    if (UOP->getOpcode() == UO_LNot) {
164854c350a67b47f059e1d577bdd9e2d1dc31ff82b5DeLesley Hutchins      Negate = !Negate;
164954c350a67b47f059e1d577bdd9e2d1dc31ff82b5DeLesley Hutchins      return getTrylockCallExpr(UOP->getSubExpr(), C, Negate);
165054c350a67b47f059e1d577bdd9e2d1dc31ff82b5DeLesley Hutchins    }
165113106117060c90d6f84bd2ed7a5c03e0502ff419DeLesley Hutchins    return 0;
165213106117060c90d6f84bd2ed7a5c03e0502ff419DeLesley Hutchins  }
165313106117060c90d6f84bd2ed7a5c03e0502ff419DeLesley Hutchins  else if (const BinaryOperator *BOP = dyn_cast<BinaryOperator>(Cond)) {
165413106117060c90d6f84bd2ed7a5c03e0502ff419DeLesley Hutchins    if (BOP->getOpcode() == BO_EQ || BOP->getOpcode() == BO_NE) {
165513106117060c90d6f84bd2ed7a5c03e0502ff419DeLesley Hutchins      if (BOP->getOpcode() == BO_NE)
165613106117060c90d6f84bd2ed7a5c03e0502ff419DeLesley Hutchins        Negate = !Negate;
165713106117060c90d6f84bd2ed7a5c03e0502ff419DeLesley Hutchins
165813106117060c90d6f84bd2ed7a5c03e0502ff419DeLesley Hutchins      bool TCond = false;
165913106117060c90d6f84bd2ed7a5c03e0502ff419DeLesley Hutchins      if (getStaticBooleanValue(BOP->getRHS(), TCond)) {
166013106117060c90d6f84bd2ed7a5c03e0502ff419DeLesley Hutchins        if (!TCond) Negate = !Negate;
166113106117060c90d6f84bd2ed7a5c03e0502ff419DeLesley Hutchins        return getTrylockCallExpr(BOP->getLHS(), C, Negate);
166213106117060c90d6f84bd2ed7a5c03e0502ff419DeLesley Hutchins      }
166313106117060c90d6f84bd2ed7a5c03e0502ff419DeLesley Hutchins      else if (getStaticBooleanValue(BOP->getLHS(), TCond)) {
166413106117060c90d6f84bd2ed7a5c03e0502ff419DeLesley Hutchins        if (!TCond) Negate = !Negate;
166513106117060c90d6f84bd2ed7a5c03e0502ff419DeLesley Hutchins        return getTrylockCallExpr(BOP->getRHS(), C, Negate);
166613106117060c90d6f84bd2ed7a5c03e0502ff419DeLesley Hutchins      }
166713106117060c90d6f84bd2ed7a5c03e0502ff419DeLesley Hutchins      return 0;
166813106117060c90d6f84bd2ed7a5c03e0502ff419DeLesley Hutchins    }
166913106117060c90d6f84bd2ed7a5c03e0502ff419DeLesley Hutchins    return 0;
167054c350a67b47f059e1d577bdd9e2d1dc31ff82b5DeLesley Hutchins  }
167154c350a67b47f059e1d577bdd9e2d1dc31ff82b5DeLesley Hutchins  // FIXME -- handle && and || as well.
167213106117060c90d6f84bd2ed7a5c03e0502ff419DeLesley Hutchins  return 0;
167354c350a67b47f059e1d577bdd9e2d1dc31ff82b5DeLesley Hutchins}
167454c350a67b47f059e1d577bdd9e2d1dc31ff82b5DeLesley Hutchins
167554c350a67b47f059e1d577bdd9e2d1dc31ff82b5DeLesley Hutchins
16760da4414f3d30c34fafb81b13b2cec3680c0bc9e1DeLesley Hutchins/// \brief Find the lockset that holds on the edge between PredBlock
16770da4414f3d30c34fafb81b13b2cec3680c0bc9e1DeLesley Hutchins/// and CurrBlock.  The edge set is the exit set of PredBlock (passed
16780da4414f3d30c34fafb81b13b2cec3680c0bc9e1DeLesley Hutchins/// as the ExitSet parameter) plus any trylocks, which are conditionally held.
1679a1fa47139d6e9e7dcc40f2809605d1a258624e7fDeLesley Hutchinsvoid ThreadSafetyAnalyzer::getEdgeLockset(FactSet& Result,
1680a1fa47139d6e9e7dcc40f2809605d1a258624e7fDeLesley Hutchins                                          const FactSet &ExitSet,
1681a1fa47139d6e9e7dcc40f2809605d1a258624e7fDeLesley Hutchins                                          const CFGBlock *PredBlock,
1682a1fa47139d6e9e7dcc40f2809605d1a258624e7fDeLesley Hutchins                                          const CFGBlock *CurrBlock) {
1683a1fa47139d6e9e7dcc40f2809605d1a258624e7fDeLesley Hutchins  Result = ExitSet;
1684a1fa47139d6e9e7dcc40f2809605d1a258624e7fDeLesley Hutchins
16850da4414f3d30c34fafb81b13b2cec3680c0bc9e1DeLesley Hutchins  if (!PredBlock->getTerminatorCondition())
1686a1fa47139d6e9e7dcc40f2809605d1a258624e7fDeLesley Hutchins    return;
16870da4414f3d30c34fafb81b13b2cec3680c0bc9e1DeLesley Hutchins
168854c350a67b47f059e1d577bdd9e2d1dc31ff82b5DeLesley Hutchins  bool Negate = false;
168954c350a67b47f059e1d577bdd9e2d1dc31ff82b5DeLesley Hutchins  const Stmt *Cond = PredBlock->getTerminatorCondition();
169054c350a67b47f059e1d577bdd9e2d1dc31ff82b5DeLesley Hutchins  const CFGBlockInfo *PredBlockInfo = &BlockInfo[PredBlock->getBlockID()];
169154c350a67b47f059e1d577bdd9e2d1dc31ff82b5DeLesley Hutchins  const LocalVarContext &LVarCtx = PredBlockInfo->ExitContext;
169254c350a67b47f059e1d577bdd9e2d1dc31ff82b5DeLesley Hutchins
16935381c05f51e5b7c7627f1d95b9a3425303ce086aDeLesley Hutchins  CallExpr *Exp =
16945381c05f51e5b7c7627f1d95b9a3425303ce086aDeLesley Hutchins    const_cast<CallExpr*>(getTrylockCallExpr(Cond, LVarCtx, Negate));
169554c350a67b47f059e1d577bdd9e2d1dc31ff82b5DeLesley Hutchins  if (!Exp)
1696a1fa47139d6e9e7dcc40f2809605d1a258624e7fDeLesley Hutchins    return;
169754c350a67b47f059e1d577bdd9e2d1dc31ff82b5DeLesley Hutchins
169854c350a67b47f059e1d577bdd9e2d1dc31ff82b5DeLesley Hutchins  NamedDecl *FunDecl = dyn_cast_or_null<NamedDecl>(Exp->getCalleeDecl());
169954c350a67b47f059e1d577bdd9e2d1dc31ff82b5DeLesley Hutchins  if(!FunDecl || !FunDecl->hasAttrs())
1700a1fa47139d6e9e7dcc40f2809605d1a258624e7fDeLesley Hutchins    return;
170154c350a67b47f059e1d577bdd9e2d1dc31ff82b5DeLesley Hutchins
17025381c05f51e5b7c7627f1d95b9a3425303ce086aDeLesley Hutchins
17035381c05f51e5b7c7627f1d95b9a3425303ce086aDeLesley Hutchins  MutexIDList ExclusiveLocksToAdd;
17045381c05f51e5b7c7627f1d95b9a3425303ce086aDeLesley Hutchins  MutexIDList SharedLocksToAdd;
170554c350a67b47f059e1d577bdd9e2d1dc31ff82b5DeLesley Hutchins
170654c350a67b47f059e1d577bdd9e2d1dc31ff82b5DeLesley Hutchins  // If the condition is a call to a Trylock function, then grab the attributes
170754c350a67b47f059e1d577bdd9e2d1dc31ff82b5DeLesley Hutchins  AttrVec &ArgAttrs = FunDecl->getAttrs();
170854c350a67b47f059e1d577bdd9e2d1dc31ff82b5DeLesley Hutchins  for (unsigned i = 0; i < ArgAttrs.size(); ++i) {
170954c350a67b47f059e1d577bdd9e2d1dc31ff82b5DeLesley Hutchins    Attr *Attr = ArgAttrs[i];
171054c350a67b47f059e1d577bdd9e2d1dc31ff82b5DeLesley Hutchins    switch (Attr->getKind()) {
171154c350a67b47f059e1d577bdd9e2d1dc31ff82b5DeLesley Hutchins      case attr::ExclusiveTrylockFunction: {
171254c350a67b47f059e1d577bdd9e2d1dc31ff82b5DeLesley Hutchins        ExclusiveTrylockFunctionAttr *A =
171354c350a67b47f059e1d577bdd9e2d1dc31ff82b5DeLesley Hutchins          cast<ExclusiveTrylockFunctionAttr>(Attr);
17145381c05f51e5b7c7627f1d95b9a3425303ce086aDeLesley Hutchins        getMutexIDs(ExclusiveLocksToAdd, A, Exp, FunDecl,
17155381c05f51e5b7c7627f1d95b9a3425303ce086aDeLesley Hutchins                    PredBlock, CurrBlock, A->getSuccessValue(), Negate);
171654c350a67b47f059e1d577bdd9e2d1dc31ff82b5DeLesley Hutchins        break;
171754c350a67b47f059e1d577bdd9e2d1dc31ff82b5DeLesley Hutchins      }
171854c350a67b47f059e1d577bdd9e2d1dc31ff82b5DeLesley Hutchins      case attr::SharedTrylockFunction: {
171954c350a67b47f059e1d577bdd9e2d1dc31ff82b5DeLesley Hutchins        SharedTrylockFunctionAttr *A =
172054c350a67b47f059e1d577bdd9e2d1dc31ff82b5DeLesley Hutchins          cast<SharedTrylockFunctionAttr>(Attr);
172160ff198a22815b0aec5b96eaae977de067dcd4c1DeLesley Hutchins        getMutexIDs(SharedLocksToAdd, A, Exp, FunDecl,
17225381c05f51e5b7c7627f1d95b9a3425303ce086aDeLesley Hutchins                    PredBlock, CurrBlock, A->getSuccessValue(), Negate);
172354c350a67b47f059e1d577bdd9e2d1dc31ff82b5DeLesley Hutchins        break;
172454c350a67b47f059e1d577bdd9e2d1dc31ff82b5DeLesley Hutchins      }
172554c350a67b47f059e1d577bdd9e2d1dc31ff82b5DeLesley Hutchins      default:
172654c350a67b47f059e1d577bdd9e2d1dc31ff82b5DeLesley Hutchins        break;
172754c350a67b47f059e1d577bdd9e2d1dc31ff82b5DeLesley Hutchins    }
1728f1ac63702143d84db778d32eb185a77fc97db5f5DeLesley Hutchins  }
17295381c05f51e5b7c7627f1d95b9a3425303ce086aDeLesley Hutchins
17305381c05f51e5b7c7627f1d95b9a3425303ce086aDeLesley Hutchins  // Add and remove locks.
17315381c05f51e5b7c7627f1d95b9a3425303ce086aDeLesley Hutchins  SourceLocation Loc = Exp->getExprLoc();
17325381c05f51e5b7c7627f1d95b9a3425303ce086aDeLesley Hutchins  for (unsigned i=0,n=ExclusiveLocksToAdd.size(); i<n; ++i) {
1733a1fa47139d6e9e7dcc40f2809605d1a258624e7fDeLesley Hutchins    addLock(Result, ExclusiveLocksToAdd[i],
1734a1fa47139d6e9e7dcc40f2809605d1a258624e7fDeLesley Hutchins            LockData(Loc, LK_Exclusive));
17355381c05f51e5b7c7627f1d95b9a3425303ce086aDeLesley Hutchins  }
17365381c05f51e5b7c7627f1d95b9a3425303ce086aDeLesley Hutchins  for (unsigned i=0,n=SharedLocksToAdd.size(); i<n; ++i) {
1737a1fa47139d6e9e7dcc40f2809605d1a258624e7fDeLesley Hutchins    addLock(Result, SharedLocksToAdd[i],
1738a1fa47139d6e9e7dcc40f2809605d1a258624e7fDeLesley Hutchins            LockData(Loc, LK_Shared));
17395381c05f51e5b7c7627f1d95b9a3425303ce086aDeLesley Hutchins  }
1740f1ac63702143d84db778d32eb185a77fc97db5f5DeLesley Hutchins}
1741f1ac63702143d84db778d32eb185a77fc97db5f5DeLesley Hutchins
174254c350a67b47f059e1d577bdd9e2d1dc31ff82b5DeLesley Hutchins
174354c350a67b47f059e1d577bdd9e2d1dc31ff82b5DeLesley Hutchins/// \brief We use this class to visit different types of expressions in
174454c350a67b47f059e1d577bdd9e2d1dc31ff82b5DeLesley Hutchins/// CFGBlocks, and build up the lockset.
174554c350a67b47f059e1d577bdd9e2d1dc31ff82b5DeLesley Hutchins/// An expression may cause us to add or remove locks from the lockset, or else
174654c350a67b47f059e1d577bdd9e2d1dc31ff82b5DeLesley Hutchins/// output error messages related to missing locks.
174754c350a67b47f059e1d577bdd9e2d1dc31ff82b5DeLesley Hutchins/// FIXME: In future, we may be able to not inherit from a visitor.
174854c350a67b47f059e1d577bdd9e2d1dc31ff82b5DeLesley Hutchinsclass BuildLockset : public StmtVisitor<BuildLockset> {
174954c350a67b47f059e1d577bdd9e2d1dc31ff82b5DeLesley Hutchins  friend class ThreadSafetyAnalyzer;
175054c350a67b47f059e1d577bdd9e2d1dc31ff82b5DeLesley Hutchins
175154c350a67b47f059e1d577bdd9e2d1dc31ff82b5DeLesley Hutchins  ThreadSafetyAnalyzer *Analyzer;
1752a1fa47139d6e9e7dcc40f2809605d1a258624e7fDeLesley Hutchins  FactSet FSet;
175354c350a67b47f059e1d577bdd9e2d1dc31ff82b5DeLesley Hutchins  LocalVariableMap::Context LVarCtx;
175454c350a67b47f059e1d577bdd9e2d1dc31ff82b5DeLesley Hutchins  unsigned CtxIndex;
175554c350a67b47f059e1d577bdd9e2d1dc31ff82b5DeLesley Hutchins
175654c350a67b47f059e1d577bdd9e2d1dc31ff82b5DeLesley Hutchins  // Helper functions
175747715cc201170952029a52806bcc26f69c38272dDeLesley Hutchins  const ValueDecl *getValueDecl(const Expr *Exp);
175854c350a67b47f059e1d577bdd9e2d1dc31ff82b5DeLesley Hutchins
175947715cc201170952029a52806bcc26f69c38272dDeLesley Hutchins  void warnIfMutexNotHeld(const NamedDecl *D, const Expr *Exp, AccessKind AK,
176054c350a67b47f059e1d577bdd9e2d1dc31ff82b5DeLesley Hutchins                          Expr *MutexExp, ProtectedOperationKind POK);
176147715cc201170952029a52806bcc26f69c38272dDeLesley Hutchins  void warnIfMutexHeld(const NamedDecl *D, const Expr *Exp, Expr *MutexExp);
176247715cc201170952029a52806bcc26f69c38272dDeLesley Hutchins
176347715cc201170952029a52806bcc26f69c38272dDeLesley Hutchins  void checkAccess(const Expr *Exp, AccessKind AK);
176447715cc201170952029a52806bcc26f69c38272dDeLesley Hutchins  void checkPtAccess(const Expr *Exp, AccessKind AK);
176554c350a67b47f059e1d577bdd9e2d1dc31ff82b5DeLesley Hutchins
17665381c05f51e5b7c7627f1d95b9a3425303ce086aDeLesley Hutchins  void handleCall(Expr *Exp, const NamedDecl *D, VarDecl *VD = 0);
176754c350a67b47f059e1d577bdd9e2d1dc31ff82b5DeLesley Hutchins
176854c350a67b47f059e1d577bdd9e2d1dc31ff82b5DeLesley Hutchinspublic:
176954c350a67b47f059e1d577bdd9e2d1dc31ff82b5DeLesley Hutchins  BuildLockset(ThreadSafetyAnalyzer *Anlzr, CFGBlockInfo &Info)
177054c350a67b47f059e1d577bdd9e2d1dc31ff82b5DeLesley Hutchins    : StmtVisitor<BuildLockset>(),
177154c350a67b47f059e1d577bdd9e2d1dc31ff82b5DeLesley Hutchins      Analyzer(Anlzr),
1772a1fa47139d6e9e7dcc40f2809605d1a258624e7fDeLesley Hutchins      FSet(Info.EntrySet),
177354c350a67b47f059e1d577bdd9e2d1dc31ff82b5DeLesley Hutchins      LVarCtx(Info.EntryContext),
177454c350a67b47f059e1d577bdd9e2d1dc31ff82b5DeLesley Hutchins      CtxIndex(Info.EntryIndex)
177554c350a67b47f059e1d577bdd9e2d1dc31ff82b5DeLesley Hutchins  {}
177654c350a67b47f059e1d577bdd9e2d1dc31ff82b5DeLesley Hutchins
177754c350a67b47f059e1d577bdd9e2d1dc31ff82b5DeLesley Hutchins  void VisitUnaryOperator(UnaryOperator *UO);
177854c350a67b47f059e1d577bdd9e2d1dc31ff82b5DeLesley Hutchins  void VisitBinaryOperator(BinaryOperator *BO);
177954c350a67b47f059e1d577bdd9e2d1dc31ff82b5DeLesley Hutchins  void VisitCastExpr(CastExpr *CE);
178054c350a67b47f059e1d577bdd9e2d1dc31ff82b5DeLesley Hutchins  void VisitCallExpr(CallExpr *Exp);
178154c350a67b47f059e1d577bdd9e2d1dc31ff82b5DeLesley Hutchins  void VisitCXXConstructExpr(CXXConstructExpr *Exp);
178254c350a67b47f059e1d577bdd9e2d1dc31ff82b5DeLesley Hutchins  void VisitDeclStmt(DeclStmt *S);
178354c350a67b47f059e1d577bdd9e2d1dc31ff82b5DeLesley Hutchins};
178454c350a67b47f059e1d577bdd9e2d1dc31ff82b5DeLesley Hutchins
178554c350a67b47f059e1d577bdd9e2d1dc31ff82b5DeLesley Hutchins
1786402aa0698fec81e574818a0a6c2000fac0b2c4c6Caitlin Sadowski/// \brief Gets the value decl pointer from DeclRefExprs or MemberExprs
178747715cc201170952029a52806bcc26f69c38272dDeLesley Hutchinsconst ValueDecl *BuildLockset::getValueDecl(const Expr *Exp) {
178847715cc201170952029a52806bcc26f69c38272dDeLesley Hutchins  if (const ImplicitCastExpr *CE = dyn_cast<ImplicitCastExpr>(Exp))
178947715cc201170952029a52806bcc26f69c38272dDeLesley Hutchins    return getValueDecl(CE->getSubExpr());
179047715cc201170952029a52806bcc26f69c38272dDeLesley Hutchins
1791402aa0698fec81e574818a0a6c2000fac0b2c4c6Caitlin Sadowski  if (const DeclRefExpr *DR = dyn_cast<DeclRefExpr>(Exp))
1792402aa0698fec81e574818a0a6c2000fac0b2c4c6Caitlin Sadowski    return DR->getDecl();
1793402aa0698fec81e574818a0a6c2000fac0b2c4c6Caitlin Sadowski
1794402aa0698fec81e574818a0a6c2000fac0b2c4c6Caitlin Sadowski  if (const MemberExpr *ME = dyn_cast<MemberExpr>(Exp))
1795402aa0698fec81e574818a0a6c2000fac0b2c4c6Caitlin Sadowski    return ME->getMemberDecl();
1796402aa0698fec81e574818a0a6c2000fac0b2c4c6Caitlin Sadowski
1797402aa0698fec81e574818a0a6c2000fac0b2c4c6Caitlin Sadowski  return 0;
1798402aa0698fec81e574818a0a6c2000fac0b2c4c6Caitlin Sadowski}
1799402aa0698fec81e574818a0a6c2000fac0b2c4c6Caitlin Sadowski
1800402aa0698fec81e574818a0a6c2000fac0b2c4c6Caitlin Sadowski/// \brief Warn if the LSet does not contain a lock sufficient to protect access
18019f80a97408ee0da939654d851ff42ad07d47e9c7DeLesley Hutchins/// of at least the passed in AccessKind.
180247715cc201170952029a52806bcc26f69c38272dDeLesley Hutchinsvoid BuildLockset::warnIfMutexNotHeld(const NamedDecl *D, const Expr *Exp,
1803402aa0698fec81e574818a0a6c2000fac0b2c4c6Caitlin Sadowski                                      AccessKind AK, Expr *MutexExp,
1804402aa0698fec81e574818a0a6c2000fac0b2c4c6Caitlin Sadowski                                      ProtectedOperationKind POK) {
1805402aa0698fec81e574818a0a6c2000fac0b2c4c6Caitlin Sadowski  LockKind LK = getLockKindFromAccessKind(AK);
18069f80a97408ee0da939654d851ff42ad07d47e9c7DeLesley Hutchins
1807a74b715cdc37c4523818a4018faae99d977aa537DeLesley Hutchins  SExpr Mutex(MutexExp, Exp, D);
18080b4db3e08a201c35f0011489bd5cd5d39bbe54fbDeLesley Hutchins  if (!Mutex.isValid()) {
1809a74b715cdc37c4523818a4018faae99d977aa537DeLesley Hutchins    SExpr::warnInvalidLock(Analyzer->Handler, MutexExp, Exp, D);
18100b4db3e08a201c35f0011489bd5cd5d39bbe54fbDeLesley Hutchins    return;
18110b4db3e08a201c35f0011489bd5cd5d39bbe54fbDeLesley Hutchins  } else if (Mutex.shouldIgnore()) {
18120b4db3e08a201c35f0011489bd5cd5d39bbe54fbDeLesley Hutchins    return;
18130b4db3e08a201c35f0011489bd5cd5d39bbe54fbDeLesley Hutchins  }
18140b4db3e08a201c35f0011489bd5cd5d39bbe54fbDeLesley Hutchins
18150b4db3e08a201c35f0011489bd5cd5d39bbe54fbDeLesley Hutchins  LockData* LDat = FSet.findLockUniv(Analyzer->FactMan, Mutex);
18163f0ec5209726641782468bd4c7597e79dda78b15DeLesley Hutchins  bool NoError = true;
18173f0ec5209726641782468bd4c7597e79dda78b15DeLesley Hutchins  if (!LDat) {
18183f0ec5209726641782468bd4c7597e79dda78b15DeLesley Hutchins    // No exact match found.  Look for a partial match.
18193f0ec5209726641782468bd4c7597e79dda78b15DeLesley Hutchins    FactEntry* FEntry = FSet.findPartialMatch(Analyzer->FactMan, Mutex);
18203f0ec5209726641782468bd4c7597e79dda78b15DeLesley Hutchins    if (FEntry) {
18213f0ec5209726641782468bd4c7597e79dda78b15DeLesley Hutchins      // Warn that there's no precise match.
18223f0ec5209726641782468bd4c7597e79dda78b15DeLesley Hutchins      LDat = &FEntry->LDat;
18233f0ec5209726641782468bd4c7597e79dda78b15DeLesley Hutchins      std::string PartMatchStr = FEntry->MutID.toString();
18243f0ec5209726641782468bd4c7597e79dda78b15DeLesley Hutchins      StringRef   PartMatchName(PartMatchStr);
18253f0ec5209726641782468bd4c7597e79dda78b15DeLesley Hutchins      Analyzer->Handler.handleMutexNotHeld(D, POK, Mutex.toString(), LK,
18263f0ec5209726641782468bd4c7597e79dda78b15DeLesley Hutchins                                           Exp->getExprLoc(), &PartMatchName);
18273f0ec5209726641782468bd4c7597e79dda78b15DeLesley Hutchins    } else {
18283f0ec5209726641782468bd4c7597e79dda78b15DeLesley Hutchins      // Warn that there's no match at all.
18293f0ec5209726641782468bd4c7597e79dda78b15DeLesley Hutchins      Analyzer->Handler.handleMutexNotHeld(D, POK, Mutex.toString(), LK,
18303f0ec5209726641782468bd4c7597e79dda78b15DeLesley Hutchins                                           Exp->getExprLoc());
18313f0ec5209726641782468bd4c7597e79dda78b15DeLesley Hutchins    }
18323f0ec5209726641782468bd4c7597e79dda78b15DeLesley Hutchins    NoError = false;
18333f0ec5209726641782468bd4c7597e79dda78b15DeLesley Hutchins  }
18343f0ec5209726641782468bd4c7597e79dda78b15DeLesley Hutchins  // Make sure the mutex we found is the right kind.
18353f0ec5209726641782468bd4c7597e79dda78b15DeLesley Hutchins  if (NoError && LDat && !LDat->isAtLeast(LK))
1836a74b715cdc37c4523818a4018faae99d977aa537DeLesley Hutchins    Analyzer->Handler.handleMutexNotHeld(D, POK, Mutex.toString(), LK,
183754c350a67b47f059e1d577bdd9e2d1dc31ff82b5DeLesley Hutchins                                         Exp->getExprLoc());
1838402aa0698fec81e574818a0a6c2000fac0b2c4c6Caitlin Sadowski}
1839402aa0698fec81e574818a0a6c2000fac0b2c4c6Caitlin Sadowski
18400b4db3e08a201c35f0011489bd5cd5d39bbe54fbDeLesley Hutchins/// \brief Warn if the LSet contains the given lock.
184147715cc201170952029a52806bcc26f69c38272dDeLesley Hutchinsvoid BuildLockset::warnIfMutexHeld(const NamedDecl *D, const Expr* Exp,
18420b4db3e08a201c35f0011489bd5cd5d39bbe54fbDeLesley Hutchins                                   Expr *MutexExp) {
18430b4db3e08a201c35f0011489bd5cd5d39bbe54fbDeLesley Hutchins  SExpr Mutex(MutexExp, Exp, D);
18440b4db3e08a201c35f0011489bd5cd5d39bbe54fbDeLesley Hutchins  if (!Mutex.isValid()) {
18450b4db3e08a201c35f0011489bd5cd5d39bbe54fbDeLesley Hutchins    SExpr::warnInvalidLock(Analyzer->Handler, MutexExp, Exp, D);
18460b4db3e08a201c35f0011489bd5cd5d39bbe54fbDeLesley Hutchins    return;
18470b4db3e08a201c35f0011489bd5cd5d39bbe54fbDeLesley Hutchins  }
18480b4db3e08a201c35f0011489bd5cd5d39bbe54fbDeLesley Hutchins
18490b4db3e08a201c35f0011489bd5cd5d39bbe54fbDeLesley Hutchins  LockData* LDat = FSet.findLock(Analyzer->FactMan, Mutex);
18505b280f28351bbdc103cc50d3b0f52f92d286fa0aDeLesley Hutchins  if (LDat) {
18515b280f28351bbdc103cc50d3b0f52f92d286fa0aDeLesley Hutchins    std::string DeclName = D->getNameAsString();
18525b280f28351bbdc103cc50d3b0f52f92d286fa0aDeLesley Hutchins    StringRef   DeclNameSR (DeclName);
18535b280f28351bbdc103cc50d3b0f52f92d286fa0aDeLesley Hutchins    Analyzer->Handler.handleFunExcludesLock(DeclNameSR, Mutex.toString(),
18540b4db3e08a201c35f0011489bd5cd5d39bbe54fbDeLesley Hutchins                                            Exp->getExprLoc());
18555b280f28351bbdc103cc50d3b0f52f92d286fa0aDeLesley Hutchins  }
18560b4db3e08a201c35f0011489bd5cd5d39bbe54fbDeLesley Hutchins}
18570b4db3e08a201c35f0011489bd5cd5d39bbe54fbDeLesley Hutchins
18580b4db3e08a201c35f0011489bd5cd5d39bbe54fbDeLesley Hutchins
185947715cc201170952029a52806bcc26f69c38272dDeLesley Hutchins/// \brief Checks guarded_by and pt_guarded_by attributes.
186047715cc201170952029a52806bcc26f69c38272dDeLesley Hutchins/// Whenever we identify an access (read or write) to a DeclRefExpr that is
186147715cc201170952029a52806bcc26f69c38272dDeLesley Hutchins/// marked with guarded_by, we must ensure the appropriate mutexes are held.
186247715cc201170952029a52806bcc26f69c38272dDeLesley Hutchins/// Similarly, we check if the access is to an expression that dereferences
186347715cc201170952029a52806bcc26f69c38272dDeLesley Hutchins/// a pointer marked with pt_guarded_by.
186447715cc201170952029a52806bcc26f69c38272dDeLesley Hutchinsvoid BuildLockset::checkAccess(const Expr *Exp, AccessKind AK) {
186547715cc201170952029a52806bcc26f69c38272dDeLesley Hutchins  Exp = Exp->IgnoreParenCasts();
186647715cc201170952029a52806bcc26f69c38272dDeLesley Hutchins
186747715cc201170952029a52806bcc26f69c38272dDeLesley Hutchins  if (const UnaryOperator *UO = dyn_cast<UnaryOperator>(Exp)) {
186847715cc201170952029a52806bcc26f69c38272dDeLesley Hutchins    // For dereferences
186947715cc201170952029a52806bcc26f69c38272dDeLesley Hutchins    if (UO->getOpcode() == clang::UO_Deref)
187047715cc201170952029a52806bcc26f69c38272dDeLesley Hutchins      checkPtAccess(UO->getSubExpr(), AK);
1871402aa0698fec81e574818a0a6c2000fac0b2c4c6Caitlin Sadowski    return;
187247715cc201170952029a52806bcc26f69c38272dDeLesley Hutchins  }
1873402aa0698fec81e574818a0a6c2000fac0b2c4c6Caitlin Sadowski
1874dd0a1f58a505ced9674f6d31a1ff65cb87774d67DeLesley Hutchins  if (const MemberExpr *ME = dyn_cast<MemberExpr>(Exp)) {
1875dd0a1f58a505ced9674f6d31a1ff65cb87774d67DeLesley Hutchins    if (ME->isArrow())
1876dd0a1f58a505ced9674f6d31a1ff65cb87774d67DeLesley Hutchins      checkPtAccess(ME->getBase(), AK);
1877dd0a1f58a505ced9674f6d31a1ff65cb87774d67DeLesley Hutchins    else
1878dd0a1f58a505ced9674f6d31a1ff65cb87774d67DeLesley Hutchins      checkAccess(ME->getBase(), AK);
187993699d23cd07c021eac2e26f8e32b58276bfa912DeLesley Hutchins  }
188093699d23cd07c021eac2e26f8e32b58276bfa912DeLesley Hutchins
1881402aa0698fec81e574818a0a6c2000fac0b2c4c6Caitlin Sadowski  const ValueDecl *D = getValueDecl(Exp);
188247715cc201170952029a52806bcc26f69c38272dDeLesley Hutchins  if (!D || !D->hasAttrs())
1883402aa0698fec81e574818a0a6c2000fac0b2c4c6Caitlin Sadowski    return;
1884402aa0698fec81e574818a0a6c2000fac0b2c4c6Caitlin Sadowski
188547715cc201170952029a52806bcc26f69c38272dDeLesley Hutchins  if (D->getAttr<GuardedVarAttr>() && FSet.isEmpty())
188647715cc201170952029a52806bcc26f69c38272dDeLesley Hutchins    Analyzer->Handler.handleNoMutexHeld(D, POK_VarAccess, AK,
188754c350a67b47f059e1d577bdd9e2d1dc31ff82b5DeLesley Hutchins                                        Exp->getExprLoc());
1888402aa0698fec81e574818a0a6c2000fac0b2c4c6Caitlin Sadowski
1889402aa0698fec81e574818a0a6c2000fac0b2c4c6Caitlin Sadowski  const AttrVec &ArgAttrs = D->getAttrs();
189047715cc201170952029a52806bcc26f69c38272dDeLesley Hutchins  for (unsigned i = 0, Size = ArgAttrs.size(); i < Size; ++i)
189147715cc201170952029a52806bcc26f69c38272dDeLesley Hutchins    if (GuardedByAttr *GBAttr = dyn_cast<GuardedByAttr>(ArgAttrs[i]))
189247715cc201170952029a52806bcc26f69c38272dDeLesley Hutchins      warnIfMutexNotHeld(D, Exp, AK, GBAttr->getArg(), POK_VarAccess);
1893402aa0698fec81e574818a0a6c2000fac0b2c4c6Caitlin Sadowski}
1894402aa0698fec81e574818a0a6c2000fac0b2c4c6Caitlin Sadowski
189547715cc201170952029a52806bcc26f69c38272dDeLesley Hutchins/// \brief Checks pt_guarded_by and pt_guarded_var attributes.
189647715cc201170952029a52806bcc26f69c38272dDeLesley Hutchinsvoid BuildLockset::checkPtAccess(const Expr *Exp, AccessKind AK) {
189747715cc201170952029a52806bcc26f69c38272dDeLesley Hutchins  Exp = Exp->IgnoreParenCasts();
189847715cc201170952029a52806bcc26f69c38272dDeLesley Hutchins
1899402aa0698fec81e574818a0a6c2000fac0b2c4c6Caitlin Sadowski  const ValueDecl *D = getValueDecl(Exp);
190047715cc201170952029a52806bcc26f69c38272dDeLesley Hutchins  if (!D || !D->hasAttrs())
1901402aa0698fec81e574818a0a6c2000fac0b2c4c6Caitlin Sadowski    return;
1902402aa0698fec81e574818a0a6c2000fac0b2c4c6Caitlin Sadowski
190347715cc201170952029a52806bcc26f69c38272dDeLesley Hutchins  if (D->getAttr<PtGuardedVarAttr>() && FSet.isEmpty())
190447715cc201170952029a52806bcc26f69c38272dDeLesley Hutchins    Analyzer->Handler.handleNoMutexHeld(D, POK_VarDereference, AK,
190554c350a67b47f059e1d577bdd9e2d1dc31ff82b5DeLesley Hutchins                                        Exp->getExprLoc());
1906402aa0698fec81e574818a0a6c2000fac0b2c4c6Caitlin Sadowski
1907402aa0698fec81e574818a0a6c2000fac0b2c4c6Caitlin Sadowski  const AttrVec &ArgAttrs = D->getAttrs();
190847715cc201170952029a52806bcc26f69c38272dDeLesley Hutchins  for (unsigned i = 0, Size = ArgAttrs.size(); i < Size; ++i)
190947715cc201170952029a52806bcc26f69c38272dDeLesley Hutchins    if (PtGuardedByAttr *GBAttr = dyn_cast<PtGuardedByAttr>(ArgAttrs[i]))
191047715cc201170952029a52806bcc26f69c38272dDeLesley Hutchins      warnIfMutexNotHeld(D, Exp, AK, GBAttr->getArg(), POK_VarDereference);
1911402aa0698fec81e574818a0a6c2000fac0b2c4c6Caitlin Sadowski}
1912402aa0698fec81e574818a0a6c2000fac0b2c4c6Caitlin Sadowski
191347715cc201170952029a52806bcc26f69c38272dDeLesley Hutchins
1914e0eaa8531f8fd9189710aac3b6f3aadb62bb14d1DeLesley Hutchins/// \brief Process a function call, method call, constructor call,
1915e0eaa8531f8fd9189710aac3b6f3aadb62bb14d1DeLesley Hutchins/// or destructor call.  This involves looking at the attributes on the
1916e0eaa8531f8fd9189710aac3b6f3aadb62bb14d1DeLesley Hutchins/// corresponding function/method/constructor/destructor, issuing warnings,
1917e0eaa8531f8fd9189710aac3b6f3aadb62bb14d1DeLesley Hutchins/// and updating the locksets accordingly.
1918402aa0698fec81e574818a0a6c2000fac0b2c4c6Caitlin Sadowski///
1919402aa0698fec81e574818a0a6c2000fac0b2c4c6Caitlin Sadowski/// FIXME: For classes annotated with one of the guarded annotations, we need
1920402aa0698fec81e574818a0a6c2000fac0b2c4c6Caitlin Sadowski/// to treat const method calls as reads and non-const method calls as writes,
1921402aa0698fec81e574818a0a6c2000fac0b2c4c6Caitlin Sadowski/// and check that the appropriate locks are held. Non-const method calls with
1922402aa0698fec81e574818a0a6c2000fac0b2c4c6Caitlin Sadowski/// the same signature as const method calls can be also treated as reads.
1923402aa0698fec81e574818a0a6c2000fac0b2c4c6Caitlin Sadowski///
19245381c05f51e5b7c7627f1d95b9a3425303ce086aDeLesley Hutchinsvoid BuildLockset::handleCall(Expr *Exp, const NamedDecl *D, VarDecl *VD) {
19255c6134fd09bc5b738dafdd1c774edde13d95cb20DeLesley Hutchins  SourceLocation Loc = Exp->getExprLoc();
19265381c05f51e5b7c7627f1d95b9a3425303ce086aDeLesley Hutchins  const AttrVec &ArgAttrs = D->getAttrs();
19275381c05f51e5b7c7627f1d95b9a3425303ce086aDeLesley Hutchins  MutexIDList ExclusiveLocksToAdd;
19285381c05f51e5b7c7627f1d95b9a3425303ce086aDeLesley Hutchins  MutexIDList SharedLocksToAdd;
19295381c05f51e5b7c7627f1d95b9a3425303ce086aDeLesley Hutchins  MutexIDList LocksToRemove;
19305381c05f51e5b7c7627f1d95b9a3425303ce086aDeLesley Hutchins
1931402aa0698fec81e574818a0a6c2000fac0b2c4c6Caitlin Sadowski  for(unsigned i = 0; i < ArgAttrs.size(); ++i) {
19325381c05f51e5b7c7627f1d95b9a3425303ce086aDeLesley Hutchins    Attr *At = const_cast<Attr*>(ArgAttrs[i]);
19335381c05f51e5b7c7627f1d95b9a3425303ce086aDeLesley Hutchins    switch (At->getKind()) {
1934402aa0698fec81e574818a0a6c2000fac0b2c4c6Caitlin Sadowski      // When we encounter an exclusive lock function, we need to add the lock
1935402aa0698fec81e574818a0a6c2000fac0b2c4c6Caitlin Sadowski      // to our lockset with kind exclusive.
19369f80a97408ee0da939654d851ff42ad07d47e9c7DeLesley Hutchins      case attr::ExclusiveLockFunction: {
19375381c05f51e5b7c7627f1d95b9a3425303ce086aDeLesley Hutchins        ExclusiveLockFunctionAttr *A = cast<ExclusiveLockFunctionAttr>(At);
1938ef2388b10c41a9696d5d81f42ca79ff005fef7fcDeLesley Hutchins        Analyzer->getMutexIDs(ExclusiveLocksToAdd, A, Exp, D, VD);
1939402aa0698fec81e574818a0a6c2000fac0b2c4c6Caitlin Sadowski        break;
19409f80a97408ee0da939654d851ff42ad07d47e9c7DeLesley Hutchins      }
1941402aa0698fec81e574818a0a6c2000fac0b2c4c6Caitlin Sadowski
1942402aa0698fec81e574818a0a6c2000fac0b2c4c6Caitlin Sadowski      // When we encounter a shared lock function, we need to add the lock
1943402aa0698fec81e574818a0a6c2000fac0b2c4c6Caitlin Sadowski      // to our lockset with kind shared.
19449f80a97408ee0da939654d851ff42ad07d47e9c7DeLesley Hutchins      case attr::SharedLockFunction: {
19455381c05f51e5b7c7627f1d95b9a3425303ce086aDeLesley Hutchins        SharedLockFunctionAttr *A = cast<SharedLockFunctionAttr>(At);
1946ef2388b10c41a9696d5d81f42ca79ff005fef7fcDeLesley Hutchins        Analyzer->getMutexIDs(SharedLocksToAdd, A, Exp, D, VD);
1947402aa0698fec81e574818a0a6c2000fac0b2c4c6Caitlin Sadowski        break;
19489f80a97408ee0da939654d851ff42ad07d47e9c7DeLesley Hutchins      }
1949402aa0698fec81e574818a0a6c2000fac0b2c4c6Caitlin Sadowski
19505c6134fd09bc5b738dafdd1c774edde13d95cb20DeLesley Hutchins      // An assert will add a lock to the lockset, but will not generate
19515c6134fd09bc5b738dafdd1c774edde13d95cb20DeLesley Hutchins      // a warning if it is already there, and will not generate a warning
19525c6134fd09bc5b738dafdd1c774edde13d95cb20DeLesley Hutchins      // if it is not removed.
19535c6134fd09bc5b738dafdd1c774edde13d95cb20DeLesley Hutchins      case attr::AssertExclusiveLock: {
19545c6134fd09bc5b738dafdd1c774edde13d95cb20DeLesley Hutchins        AssertExclusiveLockAttr *A = cast<AssertExclusiveLockAttr>(At);
19555c6134fd09bc5b738dafdd1c774edde13d95cb20DeLesley Hutchins
19565c6134fd09bc5b738dafdd1c774edde13d95cb20DeLesley Hutchins        MutexIDList AssertLocks;
19575c6134fd09bc5b738dafdd1c774edde13d95cb20DeLesley Hutchins        Analyzer->getMutexIDs(AssertLocks, A, Exp, D, VD);
19585c6134fd09bc5b738dafdd1c774edde13d95cb20DeLesley Hutchins        for (unsigned i=0,n=AssertLocks.size(); i<n; ++i) {
19595c6134fd09bc5b738dafdd1c774edde13d95cb20DeLesley Hutchins          Analyzer->addLock(FSet, AssertLocks[i],
19605c6134fd09bc5b738dafdd1c774edde13d95cb20DeLesley Hutchins                            LockData(Loc, LK_Exclusive, false, true));
19615c6134fd09bc5b738dafdd1c774edde13d95cb20DeLesley Hutchins        }
19625c6134fd09bc5b738dafdd1c774edde13d95cb20DeLesley Hutchins        break;
19635c6134fd09bc5b738dafdd1c774edde13d95cb20DeLesley Hutchins      }
19645c6134fd09bc5b738dafdd1c774edde13d95cb20DeLesley Hutchins      case attr::AssertSharedLock: {
19655c6134fd09bc5b738dafdd1c774edde13d95cb20DeLesley Hutchins        AssertSharedLockAttr *A = cast<AssertSharedLockAttr>(At);
19665c6134fd09bc5b738dafdd1c774edde13d95cb20DeLesley Hutchins
19675c6134fd09bc5b738dafdd1c774edde13d95cb20DeLesley Hutchins        MutexIDList AssertLocks;
19685c6134fd09bc5b738dafdd1c774edde13d95cb20DeLesley Hutchins        Analyzer->getMutexIDs(AssertLocks, A, Exp, D, VD);
19695c6134fd09bc5b738dafdd1c774edde13d95cb20DeLesley Hutchins        for (unsigned i=0,n=AssertLocks.size(); i<n; ++i) {
19705c6134fd09bc5b738dafdd1c774edde13d95cb20DeLesley Hutchins          Analyzer->addLock(FSet, AssertLocks[i],
19715c6134fd09bc5b738dafdd1c774edde13d95cb20DeLesley Hutchins                            LockData(Loc, LK_Shared, false, true));
19725c6134fd09bc5b738dafdd1c774edde13d95cb20DeLesley Hutchins        }
19735c6134fd09bc5b738dafdd1c774edde13d95cb20DeLesley Hutchins        break;
19745c6134fd09bc5b738dafdd1c774edde13d95cb20DeLesley Hutchins      }
19755c6134fd09bc5b738dafdd1c774edde13d95cb20DeLesley Hutchins
1976402aa0698fec81e574818a0a6c2000fac0b2c4c6Caitlin Sadowski      // When we encounter an unlock function, we need to remove unlocked
1977402aa0698fec81e574818a0a6c2000fac0b2c4c6Caitlin Sadowski      // mutexes from the lockset, and flag a warning if they are not there.
1978402aa0698fec81e574818a0a6c2000fac0b2c4c6Caitlin Sadowski      case attr::UnlockFunction: {
19795381c05f51e5b7c7627f1d95b9a3425303ce086aDeLesley Hutchins        UnlockFunctionAttr *A = cast<UnlockFunctionAttr>(At);
1980ef2388b10c41a9696d5d81f42ca79ff005fef7fcDeLesley Hutchins        Analyzer->getMutexIDs(LocksToRemove, A, Exp, D, VD);
1981402aa0698fec81e574818a0a6c2000fac0b2c4c6Caitlin Sadowski        break;
1982402aa0698fec81e574818a0a6c2000fac0b2c4c6Caitlin Sadowski      }
1983402aa0698fec81e574818a0a6c2000fac0b2c4c6Caitlin Sadowski
1984402aa0698fec81e574818a0a6c2000fac0b2c4c6Caitlin Sadowski      case attr::ExclusiveLocksRequired: {
19855381c05f51e5b7c7627f1d95b9a3425303ce086aDeLesley Hutchins        ExclusiveLocksRequiredAttr *A = cast<ExclusiveLocksRequiredAttr>(At);
1986402aa0698fec81e574818a0a6c2000fac0b2c4c6Caitlin Sadowski
1987402aa0698fec81e574818a0a6c2000fac0b2c4c6Caitlin Sadowski        for (ExclusiveLocksRequiredAttr::args_iterator
19885381c05f51e5b7c7627f1d95b9a3425303ce086aDeLesley Hutchins             I = A->args_begin(), E = A->args_end(); I != E; ++I)
1989402aa0698fec81e574818a0a6c2000fac0b2c4c6Caitlin Sadowski          warnIfMutexNotHeld(D, Exp, AK_Written, *I, POK_FunctionCall);
1990402aa0698fec81e574818a0a6c2000fac0b2c4c6Caitlin Sadowski        break;
1991402aa0698fec81e574818a0a6c2000fac0b2c4c6Caitlin Sadowski      }
1992402aa0698fec81e574818a0a6c2000fac0b2c4c6Caitlin Sadowski
1993402aa0698fec81e574818a0a6c2000fac0b2c4c6Caitlin Sadowski      case attr::SharedLocksRequired: {
19945381c05f51e5b7c7627f1d95b9a3425303ce086aDeLesley Hutchins        SharedLocksRequiredAttr *A = cast<SharedLocksRequiredAttr>(At);
1995402aa0698fec81e574818a0a6c2000fac0b2c4c6Caitlin Sadowski
19965381c05f51e5b7c7627f1d95b9a3425303ce086aDeLesley Hutchins        for (SharedLocksRequiredAttr::args_iterator I = A->args_begin(),
19975381c05f51e5b7c7627f1d95b9a3425303ce086aDeLesley Hutchins             E = A->args_end(); I != E; ++I)
1998402aa0698fec81e574818a0a6c2000fac0b2c4c6Caitlin Sadowski          warnIfMutexNotHeld(D, Exp, AK_Read, *I, POK_FunctionCall);
1999402aa0698fec81e574818a0a6c2000fac0b2c4c6Caitlin Sadowski        break;
2000402aa0698fec81e574818a0a6c2000fac0b2c4c6Caitlin Sadowski      }
2001402aa0698fec81e574818a0a6c2000fac0b2c4c6Caitlin Sadowski
2002402aa0698fec81e574818a0a6c2000fac0b2c4c6Caitlin Sadowski      case attr::LocksExcluded: {
20035381c05f51e5b7c7627f1d95b9a3425303ce086aDeLesley Hutchins        LocksExcludedAttr *A = cast<LocksExcludedAttr>(At);
20040b4db3e08a201c35f0011489bd5cd5d39bbe54fbDeLesley Hutchins
20055381c05f51e5b7c7627f1d95b9a3425303ce086aDeLesley Hutchins        for (LocksExcludedAttr::args_iterator I = A->args_begin(),
20065381c05f51e5b7c7627f1d95b9a3425303ce086aDeLesley Hutchins            E = A->args_end(); I != E; ++I) {
20070b4db3e08a201c35f0011489bd5cd5d39bbe54fbDeLesley Hutchins          warnIfMutexHeld(D, Exp, *I);
2008402aa0698fec81e574818a0a6c2000fac0b2c4c6Caitlin Sadowski        }
2009402aa0698fec81e574818a0a6c2000fac0b2c4c6Caitlin Sadowski        break;
2010402aa0698fec81e574818a0a6c2000fac0b2c4c6Caitlin Sadowski      }
2011402aa0698fec81e574818a0a6c2000fac0b2c4c6Caitlin Sadowski
2012402aa0698fec81e574818a0a6c2000fac0b2c4c6Caitlin Sadowski      // Ignore other (non thread-safety) attributes
2013402aa0698fec81e574818a0a6c2000fac0b2c4c6Caitlin Sadowski      default:
2014402aa0698fec81e574818a0a6c2000fac0b2c4c6Caitlin Sadowski        break;
2015402aa0698fec81e574818a0a6c2000fac0b2c4c6Caitlin Sadowski    }
2016402aa0698fec81e574818a0a6c2000fac0b2c4c6Caitlin Sadowski  }
20175381c05f51e5b7c7627f1d95b9a3425303ce086aDeLesley Hutchins
20185381c05f51e5b7c7627f1d95b9a3425303ce086aDeLesley Hutchins  // Figure out if we're calling the constructor of scoped lockable class
20195381c05f51e5b7c7627f1d95b9a3425303ce086aDeLesley Hutchins  bool isScopedVar = false;
20205381c05f51e5b7c7627f1d95b9a3425303ce086aDeLesley Hutchins  if (VD) {
20215381c05f51e5b7c7627f1d95b9a3425303ce086aDeLesley Hutchins    if (const CXXConstructorDecl *CD = dyn_cast<const CXXConstructorDecl>(D)) {
20225381c05f51e5b7c7627f1d95b9a3425303ce086aDeLesley Hutchins      const CXXRecordDecl* PD = CD->getParent();
20235381c05f51e5b7c7627f1d95b9a3425303ce086aDeLesley Hutchins      if (PD && PD->getAttr<ScopedLockableAttr>())
20245381c05f51e5b7c7627f1d95b9a3425303ce086aDeLesley Hutchins        isScopedVar = true;
20255381c05f51e5b7c7627f1d95b9a3425303ce086aDeLesley Hutchins    }
20265381c05f51e5b7c7627f1d95b9a3425303ce086aDeLesley Hutchins  }
20275381c05f51e5b7c7627f1d95b9a3425303ce086aDeLesley Hutchins
20285381c05f51e5b7c7627f1d95b9a3425303ce086aDeLesley Hutchins  // Add locks.
20295381c05f51e5b7c7627f1d95b9a3425303ce086aDeLesley Hutchins  for (unsigned i=0,n=ExclusiveLocksToAdd.size(); i<n; ++i) {
2030a1fa47139d6e9e7dcc40f2809605d1a258624e7fDeLesley Hutchins    Analyzer->addLock(FSet, ExclusiveLocksToAdd[i],
2031a1fa47139d6e9e7dcc40f2809605d1a258624e7fDeLesley Hutchins                            LockData(Loc, LK_Exclusive, isScopedVar));
20325381c05f51e5b7c7627f1d95b9a3425303ce086aDeLesley Hutchins  }
20335381c05f51e5b7c7627f1d95b9a3425303ce086aDeLesley Hutchins  for (unsigned i=0,n=SharedLocksToAdd.size(); i<n; ++i) {
2034a1fa47139d6e9e7dcc40f2809605d1a258624e7fDeLesley Hutchins    Analyzer->addLock(FSet, SharedLocksToAdd[i],
2035a1fa47139d6e9e7dcc40f2809605d1a258624e7fDeLesley Hutchins                            LockData(Loc, LK_Shared, isScopedVar));
20365381c05f51e5b7c7627f1d95b9a3425303ce086aDeLesley Hutchins  }
20375381c05f51e5b7c7627f1d95b9a3425303ce086aDeLesley Hutchins
20385381c05f51e5b7c7627f1d95b9a3425303ce086aDeLesley Hutchins  // Add the managing object as a dummy mutex, mapped to the underlying mutex.
20395381c05f51e5b7c7627f1d95b9a3425303ce086aDeLesley Hutchins  // FIXME -- this doesn't work if we acquire multiple locks.
20405381c05f51e5b7c7627f1d95b9a3425303ce086aDeLesley Hutchins  if (isScopedVar) {
20415381c05f51e5b7c7627f1d95b9a3425303ce086aDeLesley Hutchins    SourceLocation MLoc = VD->getLocation();
20425381c05f51e5b7c7627f1d95b9a3425303ce086aDeLesley Hutchins    DeclRefExpr DRE(VD, false, VD->getType(), VK_LValue, VD->getLocation());
2043a74b715cdc37c4523818a4018faae99d977aa537DeLesley Hutchins    SExpr SMutex(&DRE, 0, 0);
20445381c05f51e5b7c7627f1d95b9a3425303ce086aDeLesley Hutchins
20455381c05f51e5b7c7627f1d95b9a3425303ce086aDeLesley Hutchins    for (unsigned i=0,n=ExclusiveLocksToAdd.size(); i<n; ++i) {
2046a1fa47139d6e9e7dcc40f2809605d1a258624e7fDeLesley Hutchins      Analyzer->addLock(FSet, SMutex, LockData(MLoc, LK_Exclusive,
2047a1fa47139d6e9e7dcc40f2809605d1a258624e7fDeLesley Hutchins                                               ExclusiveLocksToAdd[i]));
20485381c05f51e5b7c7627f1d95b9a3425303ce086aDeLesley Hutchins    }
20495381c05f51e5b7c7627f1d95b9a3425303ce086aDeLesley Hutchins    for (unsigned i=0,n=SharedLocksToAdd.size(); i<n; ++i) {
2050a1fa47139d6e9e7dcc40f2809605d1a258624e7fDeLesley Hutchins      Analyzer->addLock(FSet, SMutex, LockData(MLoc, LK_Shared,
2051a1fa47139d6e9e7dcc40f2809605d1a258624e7fDeLesley Hutchins                                               SharedLocksToAdd[i]));
20525381c05f51e5b7c7627f1d95b9a3425303ce086aDeLesley Hutchins    }
20535381c05f51e5b7c7627f1d95b9a3425303ce086aDeLesley Hutchins  }
20545381c05f51e5b7c7627f1d95b9a3425303ce086aDeLesley Hutchins
20555381c05f51e5b7c7627f1d95b9a3425303ce086aDeLesley Hutchins  // Remove locks.
20565381c05f51e5b7c7627f1d95b9a3425303ce086aDeLesley Hutchins  // FIXME -- should only fully remove if the attribute refers to 'this'.
20575381c05f51e5b7c7627f1d95b9a3425303ce086aDeLesley Hutchins  bool Dtor = isa<CXXDestructorDecl>(D);
20585381c05f51e5b7c7627f1d95b9a3425303ce086aDeLesley Hutchins  for (unsigned i=0,n=LocksToRemove.size(); i<n; ++i) {
2059a1fa47139d6e9e7dcc40f2809605d1a258624e7fDeLesley Hutchins    Analyzer->removeLock(FSet, LocksToRemove[i], Loc, Dtor);
20605381c05f51e5b7c7627f1d95b9a3425303ce086aDeLesley Hutchins  }
2061402aa0698fec81e574818a0a6c2000fac0b2c4c6Caitlin Sadowski}
2062402aa0698fec81e574818a0a6c2000fac0b2c4c6Caitlin Sadowski
2063b4fa418a72759dfe34add850837965cbc00626e4DeLesley Hutchins
2064e0eaa8531f8fd9189710aac3b6f3aadb62bb14d1DeLesley Hutchins/// \brief For unary operations which read and write a variable, we need to
2065e0eaa8531f8fd9189710aac3b6f3aadb62bb14d1DeLesley Hutchins/// check whether we hold any required mutexes. Reads are checked in
2066e0eaa8531f8fd9189710aac3b6f3aadb62bb14d1DeLesley Hutchins/// VisitCastExpr.
2067e0eaa8531f8fd9189710aac3b6f3aadb62bb14d1DeLesley Hutchinsvoid BuildLockset::VisitUnaryOperator(UnaryOperator *UO) {
2068e0eaa8531f8fd9189710aac3b6f3aadb62bb14d1DeLesley Hutchins  switch (UO->getOpcode()) {
2069e0eaa8531f8fd9189710aac3b6f3aadb62bb14d1DeLesley Hutchins    case clang::UO_PostDec:
2070e0eaa8531f8fd9189710aac3b6f3aadb62bb14d1DeLesley Hutchins    case clang::UO_PostInc:
2071e0eaa8531f8fd9189710aac3b6f3aadb62bb14d1DeLesley Hutchins    case clang::UO_PreDec:
2072e0eaa8531f8fd9189710aac3b6f3aadb62bb14d1DeLesley Hutchins    case clang::UO_PreInc: {
207347715cc201170952029a52806bcc26f69c38272dDeLesley Hutchins      checkAccess(UO->getSubExpr(), AK_Written);
2074e0eaa8531f8fd9189710aac3b6f3aadb62bb14d1DeLesley Hutchins      break;
2075e0eaa8531f8fd9189710aac3b6f3aadb62bb14d1DeLesley Hutchins    }
2076e0eaa8531f8fd9189710aac3b6f3aadb62bb14d1DeLesley Hutchins    default:
2077e0eaa8531f8fd9189710aac3b6f3aadb62bb14d1DeLesley Hutchins      break;
2078e0eaa8531f8fd9189710aac3b6f3aadb62bb14d1DeLesley Hutchins  }
2079e0eaa8531f8fd9189710aac3b6f3aadb62bb14d1DeLesley Hutchins}
2080e0eaa8531f8fd9189710aac3b6f3aadb62bb14d1DeLesley Hutchins
2081e0eaa8531f8fd9189710aac3b6f3aadb62bb14d1DeLesley Hutchins/// For binary operations which assign to a variable (writes), we need to check
2082e0eaa8531f8fd9189710aac3b6f3aadb62bb14d1DeLesley Hutchins/// whether we hold any required mutexes.
2083e0eaa8531f8fd9189710aac3b6f3aadb62bb14d1DeLesley Hutchins/// FIXME: Deal with non-primitive types.
2084e0eaa8531f8fd9189710aac3b6f3aadb62bb14d1DeLesley Hutchinsvoid BuildLockset::VisitBinaryOperator(BinaryOperator *BO) {
2085e0eaa8531f8fd9189710aac3b6f3aadb62bb14d1DeLesley Hutchins  if (!BO->isAssignmentOp())
2086e0eaa8531f8fd9189710aac3b6f3aadb62bb14d1DeLesley Hutchins    return;
2087b37d2b5c0819d9ef596c7baec1e0be0d7c45b547DeLesley Hutchins
2088b37d2b5c0819d9ef596c7baec1e0be0d7c45b547DeLesley Hutchins  // adjust the context
208954c350a67b47f059e1d577bdd9e2d1dc31ff82b5DeLesley Hutchins  LVarCtx = Analyzer->LocalVarMap.getNextContext(CtxIndex, BO, LVarCtx);
2090b37d2b5c0819d9ef596c7baec1e0be0d7c45b547DeLesley Hutchins
209147715cc201170952029a52806bcc26f69c38272dDeLesley Hutchins  checkAccess(BO->getLHS(), AK_Written);
2092e0eaa8531f8fd9189710aac3b6f3aadb62bb14d1DeLesley Hutchins}
2093e0eaa8531f8fd9189710aac3b6f3aadb62bb14d1DeLesley Hutchins
2094e0eaa8531f8fd9189710aac3b6f3aadb62bb14d1DeLesley Hutchins/// Whenever we do an LValue to Rvalue cast, we are reading a variable and
2095e0eaa8531f8fd9189710aac3b6f3aadb62bb14d1DeLesley Hutchins/// need to ensure we hold any required mutexes.
2096e0eaa8531f8fd9189710aac3b6f3aadb62bb14d1DeLesley Hutchins/// FIXME: Deal with non-primitive types.
2097e0eaa8531f8fd9189710aac3b6f3aadb62bb14d1DeLesley Hutchinsvoid BuildLockset::VisitCastExpr(CastExpr *CE) {
2098e0eaa8531f8fd9189710aac3b6f3aadb62bb14d1DeLesley Hutchins  if (CE->getCastKind() != CK_LValueToRValue)
2099e0eaa8531f8fd9189710aac3b6f3aadb62bb14d1DeLesley Hutchins    return;
210047715cc201170952029a52806bcc26f69c38272dDeLesley Hutchins  checkAccess(CE->getSubExpr(), AK_Read);
2101e0eaa8531f8fd9189710aac3b6f3aadb62bb14d1DeLesley Hutchins}
2102e0eaa8531f8fd9189710aac3b6f3aadb62bb14d1DeLesley Hutchins
2103e0eaa8531f8fd9189710aac3b6f3aadb62bb14d1DeLesley Hutchins
2104df49782c54802ca1a4c1d36d66186aa039f32aecDeLesley Hutchinsvoid BuildLockset::VisitCallExpr(CallExpr *Exp) {
2105dd0a1f58a505ced9674f6d31a1ff65cb87774d67DeLesley Hutchins  if (CXXMemberCallExpr *CE = dyn_cast<CXXMemberCallExpr>(Exp)) {
2106dd0a1f58a505ced9674f6d31a1ff65cb87774d67DeLesley Hutchins    MemberExpr *ME = dyn_cast<MemberExpr>(CE->getCallee());
2107dd0a1f58a505ced9674f6d31a1ff65cb87774d67DeLesley Hutchins    // ME can be null when calling a method pointer
2108dd0a1f58a505ced9674f6d31a1ff65cb87774d67DeLesley Hutchins    CXXMethodDecl *MD = CE->getMethodDecl();
2109dd0a1f58a505ced9674f6d31a1ff65cb87774d67DeLesley Hutchins
2110dd0a1f58a505ced9674f6d31a1ff65cb87774d67DeLesley Hutchins    if (ME && MD) {
2111dd0a1f58a505ced9674f6d31a1ff65cb87774d67DeLesley Hutchins      if (ME->isArrow()) {
2112dd0a1f58a505ced9674f6d31a1ff65cb87774d67DeLesley Hutchins        if (MD->isConst()) {
2113dd0a1f58a505ced9674f6d31a1ff65cb87774d67DeLesley Hutchins          checkPtAccess(CE->getImplicitObjectArgument(), AK_Read);
2114dd0a1f58a505ced9674f6d31a1ff65cb87774d67DeLesley Hutchins        } else {  // FIXME -- should be AK_Written
2115dd0a1f58a505ced9674f6d31a1ff65cb87774d67DeLesley Hutchins          checkPtAccess(CE->getImplicitObjectArgument(), AK_Read);
211691e2061763f5e59f57e59c6f141b74b5ff0408adDeLesley Hutchins        }
2117dd0a1f58a505ced9674f6d31a1ff65cb87774d67DeLesley Hutchins      } else {
2118dd0a1f58a505ced9674f6d31a1ff65cb87774d67DeLesley Hutchins        if (MD->isConst())
2119dd0a1f58a505ced9674f6d31a1ff65cb87774d67DeLesley Hutchins          checkAccess(CE->getImplicitObjectArgument(), AK_Read);
2120dd0a1f58a505ced9674f6d31a1ff65cb87774d67DeLesley Hutchins        else     // FIXME -- should be AK_Written
2121dd0a1f58a505ced9674f6d31a1ff65cb87774d67DeLesley Hutchins          checkAccess(CE->getImplicitObjectArgument(), AK_Read);
212291e2061763f5e59f57e59c6f141b74b5ff0408adDeLesley Hutchins      }
2123dd0a1f58a505ced9674f6d31a1ff65cb87774d67DeLesley Hutchins    }
2124dd0a1f58a505ced9674f6d31a1ff65cb87774d67DeLesley Hutchins  } else if (CXXOperatorCallExpr *OE = dyn_cast<CXXOperatorCallExpr>(Exp)) {
2125dd0a1f58a505ced9674f6d31a1ff65cb87774d67DeLesley Hutchins    switch (OE->getOperator()) {
2126dd0a1f58a505ced9674f6d31a1ff65cb87774d67DeLesley Hutchins      case OO_Equal: {
2127dd0a1f58a505ced9674f6d31a1ff65cb87774d67DeLesley Hutchins        const Expr *Target = OE->getArg(0);
2128dd0a1f58a505ced9674f6d31a1ff65cb87774d67DeLesley Hutchins        const Expr *Source = OE->getArg(1);
2129dd0a1f58a505ced9674f6d31a1ff65cb87774d67DeLesley Hutchins        checkAccess(Target, AK_Written);
2130dd0a1f58a505ced9674f6d31a1ff65cb87774d67DeLesley Hutchins        checkAccess(Source, AK_Read);
2131dd0a1f58a505ced9674f6d31a1ff65cb87774d67DeLesley Hutchins        break;
2132dd0a1f58a505ced9674f6d31a1ff65cb87774d67DeLesley Hutchins      }
2133dd0a1f58a505ced9674f6d31a1ff65cb87774d67DeLesley Hutchins      default: {
2134dd0a1f58a505ced9674f6d31a1ff65cb87774d67DeLesley Hutchins        const Expr *Source = OE->getArg(0);
2135dd0a1f58a505ced9674f6d31a1ff65cb87774d67DeLesley Hutchins        checkAccess(Source, AK_Read);
2136dd0a1f58a505ced9674f6d31a1ff65cb87774d67DeLesley Hutchins        break;
213791e2061763f5e59f57e59c6f141b74b5ff0408adDeLesley Hutchins      }
213891e2061763f5e59f57e59c6f141b74b5ff0408adDeLesley Hutchins    }
213991e2061763f5e59f57e59c6f141b74b5ff0408adDeLesley Hutchins  }
2140e0eaa8531f8fd9189710aac3b6f3aadb62bb14d1DeLesley Hutchins  NamedDecl *D = dyn_cast_or_null<NamedDecl>(Exp->getCalleeDecl());
2141e0eaa8531f8fd9189710aac3b6f3aadb62bb14d1DeLesley Hutchins  if(!D || !D->hasAttrs())
2142e0eaa8531f8fd9189710aac3b6f3aadb62bb14d1DeLesley Hutchins    return;
2143e0eaa8531f8fd9189710aac3b6f3aadb62bb14d1DeLesley Hutchins  handleCall(Exp, D);
2144e0eaa8531f8fd9189710aac3b6f3aadb62bb14d1DeLesley Hutchins}
2145e0eaa8531f8fd9189710aac3b6f3aadb62bb14d1DeLesley Hutchins
2146e0eaa8531f8fd9189710aac3b6f3aadb62bb14d1DeLesley Hutchinsvoid BuildLockset::VisitCXXConstructExpr(CXXConstructExpr *Exp) {
2147dd0a1f58a505ced9674f6d31a1ff65cb87774d67DeLesley Hutchins  const CXXConstructorDecl *D = Exp->getConstructor();
2148dd0a1f58a505ced9674f6d31a1ff65cb87774d67DeLesley Hutchins  if (D && D->isCopyConstructor()) {
2149dd0a1f58a505ced9674f6d31a1ff65cb87774d67DeLesley Hutchins    const Expr* Source = Exp->getArg(0);
2150dd0a1f58a505ced9674f6d31a1ff65cb87774d67DeLesley Hutchins    checkAccess(Source, AK_Read);
215191e2061763f5e59f57e59c6f141b74b5ff0408adDeLesley Hutchins  }
21521fa3c0682a52c45c4ad0be3a82d0c85f26657072DeLesley Hutchins  // FIXME -- only handles constructors in DeclStmt below.
21531fa3c0682a52c45c4ad0be3a82d0c85f26657072DeLesley Hutchins}
21541fa3c0682a52c45c4ad0be3a82d0c85f26657072DeLesley Hutchins
21551fa3c0682a52c45c4ad0be3a82d0c85f26657072DeLesley Hutchinsvoid BuildLockset::VisitDeclStmt(DeclStmt *S) {
2156b37d2b5c0819d9ef596c7baec1e0be0d7c45b547DeLesley Hutchins  // adjust the context
215754c350a67b47f059e1d577bdd9e2d1dc31ff82b5DeLesley Hutchins  LVarCtx = Analyzer->LocalVarMap.getNextContext(CtxIndex, S, LVarCtx);
2158b37d2b5c0819d9ef596c7baec1e0be0d7c45b547DeLesley Hutchins
21591fa3c0682a52c45c4ad0be3a82d0c85f26657072DeLesley Hutchins  DeclGroupRef DGrp = S->getDeclGroup();
21601fa3c0682a52c45c4ad0be3a82d0c85f26657072DeLesley Hutchins  for (DeclGroupRef::iterator I = DGrp.begin(), E = DGrp.end(); I != E; ++I) {
21611fa3c0682a52c45c4ad0be3a82d0c85f26657072DeLesley Hutchins    Decl *D = *I;
21621fa3c0682a52c45c4ad0be3a82d0c85f26657072DeLesley Hutchins    if (VarDecl *VD = dyn_cast_or_null<VarDecl>(D)) {
21631fa3c0682a52c45c4ad0be3a82d0c85f26657072DeLesley Hutchins      Expr *E = VD->getInit();
21649d6e7f3e12f1a825377ace33161e80caeda8cd06DeLesley Hutchins      // handle constructors that involve temporaries
21659d6e7f3e12f1a825377ace33161e80caeda8cd06DeLesley Hutchins      if (ExprWithCleanups *EWC = dyn_cast_or_null<ExprWithCleanups>(E))
21669d6e7f3e12f1a825377ace33161e80caeda8cd06DeLesley Hutchins        E = EWC->getSubExpr();
21679d6e7f3e12f1a825377ace33161e80caeda8cd06DeLesley Hutchins
21681fa3c0682a52c45c4ad0be3a82d0c85f26657072DeLesley Hutchins      if (CXXConstructExpr *CE = dyn_cast_or_null<CXXConstructExpr>(E)) {
21691fa3c0682a52c45c4ad0be3a82d0c85f26657072DeLesley Hutchins        NamedDecl *CtorD = dyn_cast_or_null<NamedDecl>(CE->getConstructor());
21701fa3c0682a52c45c4ad0be3a82d0c85f26657072DeLesley Hutchins        if (!CtorD || !CtorD->hasAttrs())
21711fa3c0682a52c45c4ad0be3a82d0c85f26657072DeLesley Hutchins          return;
21721fa3c0682a52c45c4ad0be3a82d0c85f26657072DeLesley Hutchins        handleCall(CE, CtorD, VD);
21731fa3c0682a52c45c4ad0be3a82d0c85f26657072DeLesley Hutchins      }
21741fa3c0682a52c45c4ad0be3a82d0c85f26657072DeLesley Hutchins    }
21751fa3c0682a52c45c4ad0be3a82d0c85f26657072DeLesley Hutchins  }
2176e0eaa8531f8fd9189710aac3b6f3aadb62bb14d1DeLesley Hutchins}
2177e0eaa8531f8fd9189710aac3b6f3aadb62bb14d1DeLesley Hutchins
2178a60448d6dfc91f4c30987e237bf70ef50ac7705bDeLesley Hutchins
21790da4414f3d30c34fafb81b13b2cec3680c0bc9e1DeLesley Hutchins
21804e4bc75d3570835e13183c66ac08974cdc016007Caitlin Sadowski/// \brief Compute the intersection of two locksets and issue warnings for any
21814e4bc75d3570835e13183c66ac08974cdc016007Caitlin Sadowski/// locks in the symmetric difference.
21824e4bc75d3570835e13183c66ac08974cdc016007Caitlin Sadowski///
21834e4bc75d3570835e13183c66ac08974cdc016007Caitlin Sadowski/// This function is used at a merge point in the CFG when comparing the lockset
21844e4bc75d3570835e13183c66ac08974cdc016007Caitlin Sadowski/// of each branch being merged. For example, given the following sequence:
21854e4bc75d3570835e13183c66ac08974cdc016007Caitlin Sadowski/// A; if () then B; else C; D; we need to check that the lockset after B and C
21864e4bc75d3570835e13183c66ac08974cdc016007Caitlin Sadowski/// are the same. In the event of a difference, we use the intersection of these
21874e4bc75d3570835e13183c66ac08974cdc016007Caitlin Sadowski/// two locksets at the start of D.
21880da4414f3d30c34fafb81b13b2cec3680c0bc9e1DeLesley Hutchins///
2189ad0fe03b897f9486191e75c8d90c3ffa9b4fd6a5Ted Kremenek/// \param FSet1 The first lockset.
2190ad0fe03b897f9486191e75c8d90c3ffa9b4fd6a5Ted Kremenek/// \param FSet2 The second lockset.
21910da4414f3d30c34fafb81b13b2cec3680c0bc9e1DeLesley Hutchins/// \param JoinLoc The location of the join point for error reporting
2192879a4334e4c4cab0c22ba91492ffc2838bbc21fcDeLesley Hutchins/// \param LEK1 The error message to report if a mutex is missing from LSet1
2193879a4334e4c4cab0c22ba91492ffc2838bbc21fcDeLesley Hutchins/// \param LEK2 The error message to report if a mutex is missing from Lset2
2194a1fa47139d6e9e7dcc40f2809605d1a258624e7fDeLesley Hutchinsvoid ThreadSafetyAnalyzer::intersectAndWarn(FactSet &FSet1,
2195a1fa47139d6e9e7dcc40f2809605d1a258624e7fDeLesley Hutchins                                            const FactSet &FSet2,
2196a1fa47139d6e9e7dcc40f2809605d1a258624e7fDeLesley Hutchins                                            SourceLocation JoinLoc,
2197a1fa47139d6e9e7dcc40f2809605d1a258624e7fDeLesley Hutchins                                            LockErrorKind LEK1,
2198a1fa47139d6e9e7dcc40f2809605d1a258624e7fDeLesley Hutchins                                            LockErrorKind LEK2,
2199a1fa47139d6e9e7dcc40f2809605d1a258624e7fDeLesley Hutchins                                            bool Modify) {
2200a1fa47139d6e9e7dcc40f2809605d1a258624e7fDeLesley Hutchins  FactSet FSet1Orig = FSet1;
2201a1fa47139d6e9e7dcc40f2809605d1a258624e7fDeLesley Hutchins
2202451f8e4ed63c97065fcbc79cf1cbbbbe1c4b6bd9DeLesley Hutchins  // Find locks in FSet2 that conflict or are not in FSet1, and warn.
2203a1fa47139d6e9e7dcc40f2809605d1a258624e7fDeLesley Hutchins  for (FactSet::const_iterator I = FSet2.begin(), E = FSet2.end();
2204a1fa47139d6e9e7dcc40f2809605d1a258624e7fDeLesley Hutchins       I != E; ++I) {
2205a74b715cdc37c4523818a4018faae99d977aa537DeLesley Hutchins    const SExpr &FSet2Mutex = FactMan[*I].MutID;
2206a1fa47139d6e9e7dcc40f2809605d1a258624e7fDeLesley Hutchins    const LockData &LDat2 = FactMan[*I].LDat;
2207451f8e4ed63c97065fcbc79cf1cbbbbe1c4b6bd9DeLesley Hutchins    FactSet::iterator I1 = FSet1.findLockIter(FactMan, FSet2Mutex);
2208a1fa47139d6e9e7dcc40f2809605d1a258624e7fDeLesley Hutchins
2209451f8e4ed63c97065fcbc79cf1cbbbbe1c4b6bd9DeLesley Hutchins    if (I1 != FSet1.end()) {
2210451f8e4ed63c97065fcbc79cf1cbbbbe1c4b6bd9DeLesley Hutchins      const LockData* LDat1 = &FactMan[*I1].LDat;
2211bbe334142b38d2f9dad3ae2eb7b332c54a5b2cc1DeLesley Hutchins      if (LDat1->LKind != LDat2.LKind) {
2212a74b715cdc37c4523818a4018faae99d977aa537DeLesley Hutchins        Handler.handleExclusiveAndShared(FSet2Mutex.toString(),
2213bbe334142b38d2f9dad3ae2eb7b332c54a5b2cc1DeLesley Hutchins                                         LDat2.AcquireLoc,
2214bbe334142b38d2f9dad3ae2eb7b332c54a5b2cc1DeLesley Hutchins                                         LDat1->AcquireLoc);
2215a1fa47139d6e9e7dcc40f2809605d1a258624e7fDeLesley Hutchins        if (Modify && LDat1->LKind != LK_Exclusive) {
2216451f8e4ed63c97065fcbc79cf1cbbbbe1c4b6bd9DeLesley Hutchins          // Take the exclusive lock, which is the one in FSet2.
2217451f8e4ed63c97065fcbc79cf1cbbbbe1c4b6bd9DeLesley Hutchins          *I1 = *I;
2218a1fa47139d6e9e7dcc40f2809605d1a258624e7fDeLesley Hutchins        }
2219402aa0698fec81e574818a0a6c2000fac0b2c4c6Caitlin Sadowski      }
2220451f8e4ed63c97065fcbc79cf1cbbbbe1c4b6bd9DeLesley Hutchins      else if (LDat1->Asserted && !LDat2.Asserted) {
2221451f8e4ed63c97065fcbc79cf1cbbbbe1c4b6bd9DeLesley Hutchins        // The non-asserted lock in FSet2 is the one we want to track.
2222451f8e4ed63c97065fcbc79cf1cbbbbe1c4b6bd9DeLesley Hutchins        *I1 = *I;
22235c6134fd09bc5b738dafdd1c774edde13d95cb20DeLesley Hutchins      }
2224402aa0698fec81e574818a0a6c2000fac0b2c4c6Caitlin Sadowski    } else {
2225bbe334142b38d2f9dad3ae2eb7b332c54a5b2cc1DeLesley Hutchins      if (LDat2.UnderlyingMutex.isValid()) {
2226a1fa47139d6e9e7dcc40f2809605d1a258624e7fDeLesley Hutchins        if (FSet2.findLock(FactMan, LDat2.UnderlyingMutex)) {
2227bbe334142b38d2f9dad3ae2eb7b332c54a5b2cc1DeLesley Hutchins          // If this is a scoped lock that manages another mutex, and if the
2228bbe334142b38d2f9dad3ae2eb7b332c54a5b2cc1DeLesley Hutchins          // underlying mutex is still held, then warn about the underlying
2229bbe334142b38d2f9dad3ae2eb7b332c54a5b2cc1DeLesley Hutchins          // mutex.
2230a74b715cdc37c4523818a4018faae99d977aa537DeLesley Hutchins          Handler.handleMutexHeldEndOfScope(LDat2.UnderlyingMutex.toString(),
2231bbe334142b38d2f9dad3ae2eb7b332c54a5b2cc1DeLesley Hutchins                                            LDat2.AcquireLoc,
2232bbe334142b38d2f9dad3ae2eb7b332c54a5b2cc1DeLesley Hutchins                                            JoinLoc, LEK1);
2233bbe334142b38d2f9dad3ae2eb7b332c54a5b2cc1DeLesley Hutchins        }
2234bbe334142b38d2f9dad3ae2eb7b332c54a5b2cc1DeLesley Hutchins      }
22355c6134fd09bc5b738dafdd1c774edde13d95cb20DeLesley Hutchins      else if (!LDat2.Managed && !FSet2Mutex.isUniversal() && !LDat2.Asserted)
2236a74b715cdc37c4523818a4018faae99d977aa537DeLesley Hutchins        Handler.handleMutexHeldEndOfScope(FSet2Mutex.toString(),
2237bbe334142b38d2f9dad3ae2eb7b332c54a5b2cc1DeLesley Hutchins                                          LDat2.AcquireLoc,
2238879a4334e4c4cab0c22ba91492ffc2838bbc21fcDeLesley Hutchins                                          JoinLoc, LEK1);
2239402aa0698fec81e574818a0a6c2000fac0b2c4c6Caitlin Sadowski    }
2240402aa0698fec81e574818a0a6c2000fac0b2c4c6Caitlin Sadowski  }
2241402aa0698fec81e574818a0a6c2000fac0b2c4c6Caitlin Sadowski
2242451f8e4ed63c97065fcbc79cf1cbbbbe1c4b6bd9DeLesley Hutchins  // Find locks in FSet1 that are not in FSet2, and remove them.
2243451f8e4ed63c97065fcbc79cf1cbbbbe1c4b6bd9DeLesley Hutchins  for (FactSet::const_iterator I = FSet1Orig.begin(), E = FSet1Orig.end();
2244a1fa47139d6e9e7dcc40f2809605d1a258624e7fDeLesley Hutchins       I != E; ++I) {
2245a74b715cdc37c4523818a4018faae99d977aa537DeLesley Hutchins    const SExpr &FSet1Mutex = FactMan[*I].MutID;
2246a1fa47139d6e9e7dcc40f2809605d1a258624e7fDeLesley Hutchins    const LockData &LDat1 = FactMan[*I].LDat;
2247bbe334142b38d2f9dad3ae2eb7b332c54a5b2cc1DeLesley Hutchins
2248a1fa47139d6e9e7dcc40f2809605d1a258624e7fDeLesley Hutchins    if (!FSet2.findLock(FactMan, FSet1Mutex)) {
2249bbe334142b38d2f9dad3ae2eb7b332c54a5b2cc1DeLesley Hutchins      if (LDat1.UnderlyingMutex.isValid()) {
2250a1fa47139d6e9e7dcc40f2809605d1a258624e7fDeLesley Hutchins        if (FSet1Orig.findLock(FactMan, LDat1.UnderlyingMutex)) {
2251bbe334142b38d2f9dad3ae2eb7b332c54a5b2cc1DeLesley Hutchins          // If this is a scoped lock that manages another mutex, and if the
2252bbe334142b38d2f9dad3ae2eb7b332c54a5b2cc1DeLesley Hutchins          // underlying mutex is still held, then warn about the underlying
2253bbe334142b38d2f9dad3ae2eb7b332c54a5b2cc1DeLesley Hutchins          // mutex.
2254a74b715cdc37c4523818a4018faae99d977aa537DeLesley Hutchins          Handler.handleMutexHeldEndOfScope(LDat1.UnderlyingMutex.toString(),
2255bbe334142b38d2f9dad3ae2eb7b332c54a5b2cc1DeLesley Hutchins                                            LDat1.AcquireLoc,
2256bbe334142b38d2f9dad3ae2eb7b332c54a5b2cc1DeLesley Hutchins                                            JoinLoc, LEK1);
2257bbe334142b38d2f9dad3ae2eb7b332c54a5b2cc1DeLesley Hutchins        }
2258bbe334142b38d2f9dad3ae2eb7b332c54a5b2cc1DeLesley Hutchins      }
22595c6134fd09bc5b738dafdd1c774edde13d95cb20DeLesley Hutchins      else if (!LDat1.Managed && !FSet1Mutex.isUniversal() && !LDat1.Asserted)
2260a74b715cdc37c4523818a4018faae99d977aa537DeLesley Hutchins        Handler.handleMutexHeldEndOfScope(FSet1Mutex.toString(),
2261bbe334142b38d2f9dad3ae2eb7b332c54a5b2cc1DeLesley Hutchins                                          LDat1.AcquireLoc,
2262879a4334e4c4cab0c22ba91492ffc2838bbc21fcDeLesley Hutchins                                          JoinLoc, LEK2);
2263a1fa47139d6e9e7dcc40f2809605d1a258624e7fDeLesley Hutchins      if (Modify)
2264a1fa47139d6e9e7dcc40f2809605d1a258624e7fDeLesley Hutchins        FSet1.removeLock(FactMan, FSet1Mutex);
2265402aa0698fec81e574818a0a6c2000fac0b2c4c6Caitlin Sadowski    }
2266402aa0698fec81e574818a0a6c2000fac0b2c4c6Caitlin Sadowski  }
2267402aa0698fec81e574818a0a6c2000fac0b2c4c6Caitlin Sadowski}
2268402aa0698fec81e574818a0a6c2000fac0b2c4c6Caitlin Sadowski
2269cb96751b25a934b22402c1e4e0805db7608a5f2bCaitlin Sadowski
22700ecc2e9ce86b0705bc1a53a9c8f90c433bcdca1bDeLesley Hutchins// Return true if block B never continues to its successors.
22710ecc2e9ce86b0705bc1a53a9c8f90c433bcdca1bDeLesley Hutchinsinline bool neverReturns(const CFGBlock* B) {
22720ecc2e9ce86b0705bc1a53a9c8f90c433bcdca1bDeLesley Hutchins  if (B->hasNoReturnElement())
22730ecc2e9ce86b0705bc1a53a9c8f90c433bcdca1bDeLesley Hutchins    return true;
22740ecc2e9ce86b0705bc1a53a9c8f90c433bcdca1bDeLesley Hutchins  if (B->empty())
22750ecc2e9ce86b0705bc1a53a9c8f90c433bcdca1bDeLesley Hutchins    return false;
22760ecc2e9ce86b0705bc1a53a9c8f90c433bcdca1bDeLesley Hutchins
22770ecc2e9ce86b0705bc1a53a9c8f90c433bcdca1bDeLesley Hutchins  CFGElement Last = B->back();
2278b07805485c603be3d8011f72611465324c9e664bDavid Blaikie  if (Optional<CFGStmt> S = Last.getAs<CFGStmt>()) {
2279b07805485c603be3d8011f72611465324c9e664bDavid Blaikie    if (isa<CXXThrowExpr>(S->getStmt()))
22800ecc2e9ce86b0705bc1a53a9c8f90c433bcdca1bDeLesley Hutchins      return true;
22810ecc2e9ce86b0705bc1a53a9c8f90c433bcdca1bDeLesley Hutchins  }
22820ecc2e9ce86b0705bc1a53a9c8f90c433bcdca1bDeLesley Hutchins  return false;
22830ecc2e9ce86b0705bc1a53a9c8f90c433bcdca1bDeLesley Hutchins}
22840ecc2e9ce86b0705bc1a53a9c8f90c433bcdca1bDeLesley Hutchins
22855381c05f51e5b7c7627f1d95b9a3425303ce086aDeLesley Hutchins
2286402aa0698fec81e574818a0a6c2000fac0b2c4c6Caitlin Sadowski/// \brief Check a function's CFG for thread-safety violations.
2287402aa0698fec81e574818a0a6c2000fac0b2c4c6Caitlin Sadowski///
2288402aa0698fec81e574818a0a6c2000fac0b2c4c6Caitlin Sadowski/// We traverse the blocks in the CFG, compute the set of mutexes that are held
2289402aa0698fec81e574818a0a6c2000fac0b2c4c6Caitlin Sadowski/// at the end of each block, and issue warnings for thread safety violations.
2290402aa0698fec81e574818a0a6c2000fac0b2c4c6Caitlin Sadowski/// Each block in the CFG is traversed exactly once.
22911d26f48dc2eea1c07431ca1519d7034a21b9bcffTed Kremenekvoid ThreadSafetyAnalyzer::runAnalysis(AnalysisDeclContext &AC) {
2292402aa0698fec81e574818a0a6c2000fac0b2c4c6Caitlin Sadowski  CFG *CFGraph = AC.getCFG();
2293402aa0698fec81e574818a0a6c2000fac0b2c4c6Caitlin Sadowski  if (!CFGraph) return;
22949f80a97408ee0da939654d851ff42ad07d47e9c7DeLesley Hutchins  const NamedDecl *D = dyn_cast_or_null<NamedDecl>(AC.getDecl());
22959f80a97408ee0da939654d851ff42ad07d47e9c7DeLesley Hutchins
22960da4414f3d30c34fafb81b13b2cec3680c0bc9e1DeLesley Hutchins  // AC.dumpCFG(true);
22970da4414f3d30c34fafb81b13b2cec3680c0bc9e1DeLesley Hutchins
22989f80a97408ee0da939654d851ff42ad07d47e9c7DeLesley Hutchins  if (!D)
22999f80a97408ee0da939654d851ff42ad07d47e9c7DeLesley Hutchins    return;  // Ignore anonymous functions for now.
23009f80a97408ee0da939654d851ff42ad07d47e9c7DeLesley Hutchins  if (D->getAttr<NoThreadSafetyAnalysisAttr>())
23019f80a97408ee0da939654d851ff42ad07d47e9c7DeLesley Hutchins    return;
23022f13bec63b0236b169b026b7bc852da51ee029a7DeLesley Hutchins  // FIXME: Do something a bit more intelligent inside constructor and
23032f13bec63b0236b169b026b7bc852da51ee029a7DeLesley Hutchins  // destructor code.  Constructors and destructors must assume unique access
23042f13bec63b0236b169b026b7bc852da51ee029a7DeLesley Hutchins  // to 'this', so checks on member variable access is disabled, but we should
23052f13bec63b0236b169b026b7bc852da51ee029a7DeLesley Hutchins  // still enable checks on other objects.
23062f13bec63b0236b169b026b7bc852da51ee029a7DeLesley Hutchins  if (isa<CXXConstructorDecl>(D))
23072f13bec63b0236b169b026b7bc852da51ee029a7DeLesley Hutchins    return;  // Don't check inside constructors.
23082f13bec63b0236b169b026b7bc852da51ee029a7DeLesley Hutchins  if (isa<CXXDestructorDecl>(D))
23092f13bec63b0236b169b026b7bc852da51ee029a7DeLesley Hutchins    return;  // Don't check inside destructors.
2310402aa0698fec81e574818a0a6c2000fac0b2c4c6Caitlin Sadowski
231154c350a67b47f059e1d577bdd9e2d1dc31ff82b5DeLesley Hutchins  BlockInfo.resize(CFGraph->getNumBlockIDs(),
2312a1fa47139d6e9e7dcc40f2809605d1a258624e7fDeLesley Hutchins    CFGBlockInfo::getEmptyBlockInfo(LocalVarMap));
2313402aa0698fec81e574818a0a6c2000fac0b2c4c6Caitlin Sadowski
2314402aa0698fec81e574818a0a6c2000fac0b2c4c6Caitlin Sadowski  // We need to explore the CFG via a "topological" ordering.
2315402aa0698fec81e574818a0a6c2000fac0b2c4c6Caitlin Sadowski  // That way, we will be guaranteed to have information about required
2316402aa0698fec81e574818a0a6c2000fac0b2c4c6Caitlin Sadowski  // predecessor locksets when exploring a new block.
2317439ed1656664b29841f70b6c0b91460534ff4d93Ted Kremenek  PostOrderCFGView *SortedGraph = AC.getAnalysis<PostOrderCFGView>();
2318439ed1656664b29841f70b6c0b91460534ff4d93Ted Kremenek  PostOrderCFGView::CFGBlockSet VisitedBlocks(CFGraph);
2319402aa0698fec81e574818a0a6c2000fac0b2c4c6Caitlin Sadowski
2320d2f388299153d80cbe5ffaaed8a882b59a1b59bcDeLesley Hutchins  // Mark entry block as reachable
2321d2f388299153d80cbe5ffaaed8a882b59a1b59bcDeLesley Hutchins  BlockInfo[CFGraph->getEntry().getBlockID()].Reachable = true;
2322d2f388299153d80cbe5ffaaed8a882b59a1b59bcDeLesley Hutchins
2323b37d2b5c0819d9ef596c7baec1e0be0d7c45b547DeLesley Hutchins  // Compute SSA names for local variables
2324b37d2b5c0819d9ef596c7baec1e0be0d7c45b547DeLesley Hutchins  LocalVarMap.traverseCFG(CFGraph, SortedGraph, BlockInfo);
2325b37d2b5c0819d9ef596c7baec1e0be0d7c45b547DeLesley Hutchins
23262e5156274b8051217565b557bfa14c80f7990e9cRichard Smith  // Fill in source locations for all CFGBlocks.
23272e5156274b8051217565b557bfa14c80f7990e9cRichard Smith  findBlockLocations(CFGraph, SortedGraph, BlockInfo);
23282e5156274b8051217565b557bfa14c80f7990e9cRichard Smith
23295696884053b4a60dbed01ea8c7e6cd8dcf9b5de9DeLesley Hutchins  MutexIDList ExclusiveLocksAcquired;
23305696884053b4a60dbed01ea8c7e6cd8dcf9b5de9DeLesley Hutchins  MutexIDList SharedLocksAcquired;
23315696884053b4a60dbed01ea8c7e6cd8dcf9b5de9DeLesley Hutchins  MutexIDList LocksReleased;
23325696884053b4a60dbed01ea8c7e6cd8dcf9b5de9DeLesley Hutchins
2333a60448d6dfc91f4c30987e237bf70ef50ac7705bDeLesley Hutchins  // Add locks from exclusive_locks_required and shared_locks_required
23342f13bec63b0236b169b026b7bc852da51ee029a7DeLesley Hutchins  // to initial lockset. Also turn off checking for lock and unlock functions.
23352f13bec63b0236b169b026b7bc852da51ee029a7DeLesley Hutchins  // FIXME: is there a more intelligent way to check lock/unlock functions?
2336439ed1656664b29841f70b6c0b91460534ff4d93Ted Kremenek  if (!SortedGraph->empty() && D->hasAttrs()) {
2337439ed1656664b29841f70b6c0b91460534ff4d93Ted Kremenek    const CFGBlock *FirstBlock = *SortedGraph->begin();
2338a1fa47139d6e9e7dcc40f2809605d1a258624e7fDeLesley Hutchins    FactSet &InitialLockset = BlockInfo[FirstBlock->getBlockID()].EntrySet;
2339cb96751b25a934b22402c1e4e0805db7608a5f2bCaitlin Sadowski    const AttrVec &ArgAttrs = D->getAttrs();
23405381c05f51e5b7c7627f1d95b9a3425303ce086aDeLesley Hutchins
23415381c05f51e5b7c7627f1d95b9a3425303ce086aDeLesley Hutchins    MutexIDList ExclusiveLocksToAdd;
23425381c05f51e5b7c7627f1d95b9a3425303ce086aDeLesley Hutchins    MutexIDList SharedLocksToAdd;
23435381c05f51e5b7c7627f1d95b9a3425303ce086aDeLesley Hutchins
23445381c05f51e5b7c7627f1d95b9a3425303ce086aDeLesley Hutchins    SourceLocation Loc = D->getLocation();
23452f13bec63b0236b169b026b7bc852da51ee029a7DeLesley Hutchins    for (unsigned i = 0; i < ArgAttrs.size(); ++i) {
2346cb96751b25a934b22402c1e4e0805db7608a5f2bCaitlin Sadowski      Attr *Attr = ArgAttrs[i];
23475381c05f51e5b7c7627f1d95b9a3425303ce086aDeLesley Hutchins      Loc = Attr->getLocation();
23485381c05f51e5b7c7627f1d95b9a3425303ce086aDeLesley Hutchins      if (ExclusiveLocksRequiredAttr *A
23495381c05f51e5b7c7627f1d95b9a3425303ce086aDeLesley Hutchins            = dyn_cast<ExclusiveLocksRequiredAttr>(Attr)) {
23505381c05f51e5b7c7627f1d95b9a3425303ce086aDeLesley Hutchins        getMutexIDs(ExclusiveLocksToAdd, A, (Expr*) 0, D);
23515381c05f51e5b7c7627f1d95b9a3425303ce086aDeLesley Hutchins      } else if (SharedLocksRequiredAttr *A
23525381c05f51e5b7c7627f1d95b9a3425303ce086aDeLesley Hutchins                   = dyn_cast<SharedLocksRequiredAttr>(Attr)) {
23535381c05f51e5b7c7627f1d95b9a3425303ce086aDeLesley Hutchins        getMutexIDs(SharedLocksToAdd, A, (Expr*) 0, D);
23545696884053b4a60dbed01ea8c7e6cd8dcf9b5de9DeLesley Hutchins      } else if (UnlockFunctionAttr *A = dyn_cast<UnlockFunctionAttr>(Attr)) {
23555696884053b4a60dbed01ea8c7e6cd8dcf9b5de9DeLesley Hutchins        if (!Handler.issueBetaWarnings())
23565696884053b4a60dbed01ea8c7e6cd8dcf9b5de9DeLesley Hutchins          return;
23575696884053b4a60dbed01ea8c7e6cd8dcf9b5de9DeLesley Hutchins        // UNLOCK_FUNCTION() is used to hide the underlying lock implementation.
23585696884053b4a60dbed01ea8c7e6cd8dcf9b5de9DeLesley Hutchins        // We must ignore such methods.
23595696884053b4a60dbed01ea8c7e6cd8dcf9b5de9DeLesley Hutchins        if (A->args_size() == 0)
23605696884053b4a60dbed01ea8c7e6cd8dcf9b5de9DeLesley Hutchins          return;
23615696884053b4a60dbed01ea8c7e6cd8dcf9b5de9DeLesley Hutchins        // FIXME -- deal with exclusive vs. shared unlock functions?
23625696884053b4a60dbed01ea8c7e6cd8dcf9b5de9DeLesley Hutchins        getMutexIDs(ExclusiveLocksToAdd, A, (Expr*) 0, D);
23635696884053b4a60dbed01ea8c7e6cd8dcf9b5de9DeLesley Hutchins        getMutexIDs(LocksReleased, A, (Expr*) 0, D);
23645696884053b4a60dbed01ea8c7e6cd8dcf9b5de9DeLesley Hutchins      } else if (ExclusiveLockFunctionAttr *A
23655696884053b4a60dbed01ea8c7e6cd8dcf9b5de9DeLesley Hutchins                   = dyn_cast<ExclusiveLockFunctionAttr>(Attr)) {
23665696884053b4a60dbed01ea8c7e6cd8dcf9b5de9DeLesley Hutchins        if (!Handler.issueBetaWarnings())
23675696884053b4a60dbed01ea8c7e6cd8dcf9b5de9DeLesley Hutchins          return;
23685696884053b4a60dbed01ea8c7e6cd8dcf9b5de9DeLesley Hutchins        if (A->args_size() == 0)
23695696884053b4a60dbed01ea8c7e6cd8dcf9b5de9DeLesley Hutchins          return;
23705696884053b4a60dbed01ea8c7e6cd8dcf9b5de9DeLesley Hutchins        getMutexIDs(ExclusiveLocksAcquired, A, (Expr*) 0, D);
23715696884053b4a60dbed01ea8c7e6cd8dcf9b5de9DeLesley Hutchins      } else if (SharedLockFunctionAttr *A
23725696884053b4a60dbed01ea8c7e6cd8dcf9b5de9DeLesley Hutchins                   = dyn_cast<SharedLockFunctionAttr>(Attr)) {
23735696884053b4a60dbed01ea8c7e6cd8dcf9b5de9DeLesley Hutchins        if (!Handler.issueBetaWarnings())
23745696884053b4a60dbed01ea8c7e6cd8dcf9b5de9DeLesley Hutchins          return;
23755696884053b4a60dbed01ea8c7e6cd8dcf9b5de9DeLesley Hutchins        if (A->args_size() == 0)
23765696884053b4a60dbed01ea8c7e6cd8dcf9b5de9DeLesley Hutchins          return;
23775696884053b4a60dbed01ea8c7e6cd8dcf9b5de9DeLesley Hutchins        getMutexIDs(SharedLocksAcquired, A, (Expr*) 0, D);
237876f0a6e9bc9ee5aae029f959f64fae290727cca4DeLesley Hutchins      } else if (isa<ExclusiveTrylockFunctionAttr>(Attr)) {
237976f0a6e9bc9ee5aae029f959f64fae290727cca4DeLesley Hutchins        // Don't try to check trylock functions for now
238076f0a6e9bc9ee5aae029f959f64fae290727cca4DeLesley Hutchins        return;
238176f0a6e9bc9ee5aae029f959f64fae290727cca4DeLesley Hutchins      } else if (isa<SharedTrylockFunctionAttr>(Attr)) {
238276f0a6e9bc9ee5aae029f959f64fae290727cca4DeLesley Hutchins        // Don't try to check trylock functions for now
238376f0a6e9bc9ee5aae029f959f64fae290727cca4DeLesley Hutchins        return;
2384cb96751b25a934b22402c1e4e0805db7608a5f2bCaitlin Sadowski      }
2385cb96751b25a934b22402c1e4e0805db7608a5f2bCaitlin Sadowski    }
23865381c05f51e5b7c7627f1d95b9a3425303ce086aDeLesley Hutchins
23875381c05f51e5b7c7627f1d95b9a3425303ce086aDeLesley Hutchins    // FIXME -- Loc can be wrong here.
23885381c05f51e5b7c7627f1d95b9a3425303ce086aDeLesley Hutchins    for (unsigned i=0,n=ExclusiveLocksToAdd.size(); i<n; ++i) {
2389a1fa47139d6e9e7dcc40f2809605d1a258624e7fDeLesley Hutchins      addLock(InitialLockset, ExclusiveLocksToAdd[i],
2390a1fa47139d6e9e7dcc40f2809605d1a258624e7fDeLesley Hutchins              LockData(Loc, LK_Exclusive));
23915381c05f51e5b7c7627f1d95b9a3425303ce086aDeLesley Hutchins    }
23925381c05f51e5b7c7627f1d95b9a3425303ce086aDeLesley Hutchins    for (unsigned i=0,n=SharedLocksToAdd.size(); i<n; ++i) {
2393a1fa47139d6e9e7dcc40f2809605d1a258624e7fDeLesley Hutchins      addLock(InitialLockset, SharedLocksToAdd[i],
2394a1fa47139d6e9e7dcc40f2809605d1a258624e7fDeLesley Hutchins              LockData(Loc, LK_Shared));
23955381c05f51e5b7c7627f1d95b9a3425303ce086aDeLesley Hutchins    }
2396cb96751b25a934b22402c1e4e0805db7608a5f2bCaitlin Sadowski  }
2397cb96751b25a934b22402c1e4e0805db7608a5f2bCaitlin Sadowski
2398439ed1656664b29841f70b6c0b91460534ff4d93Ted Kremenek  for (PostOrderCFGView::iterator I = SortedGraph->begin(),
2399439ed1656664b29841f70b6c0b91460534ff4d93Ted Kremenek       E = SortedGraph->end(); I!= E; ++I) {
2400402aa0698fec81e574818a0a6c2000fac0b2c4c6Caitlin Sadowski    const CFGBlock *CurrBlock = *I;
2401402aa0698fec81e574818a0a6c2000fac0b2c4c6Caitlin Sadowski    int CurrBlockID = CurrBlock->getBlockID();
2402b37d2b5c0819d9ef596c7baec1e0be0d7c45b547DeLesley Hutchins    CFGBlockInfo *CurrBlockInfo = &BlockInfo[CurrBlockID];
2403402aa0698fec81e574818a0a6c2000fac0b2c4c6Caitlin Sadowski
2404402aa0698fec81e574818a0a6c2000fac0b2c4c6Caitlin Sadowski    // Use the default initial lockset in case there are no predecessors.
2405b37d2b5c0819d9ef596c7baec1e0be0d7c45b547DeLesley Hutchins    VisitedBlocks.insert(CurrBlock);
2406402aa0698fec81e574818a0a6c2000fac0b2c4c6Caitlin Sadowski
2407402aa0698fec81e574818a0a6c2000fac0b2c4c6Caitlin Sadowski    // Iterate through the predecessor blocks and warn if the lockset for all
2408402aa0698fec81e574818a0a6c2000fac0b2c4c6Caitlin Sadowski    // predecessors is not the same. We take the entry lockset of the current
2409402aa0698fec81e574818a0a6c2000fac0b2c4c6Caitlin Sadowski    // block to be the intersection of all previous locksets.
2410402aa0698fec81e574818a0a6c2000fac0b2c4c6Caitlin Sadowski    // FIXME: By keeping the intersection, we may output more errors in future
2411402aa0698fec81e574818a0a6c2000fac0b2c4c6Caitlin Sadowski    // for a lock which is not in the intersection, but was in the union. We
2412402aa0698fec81e574818a0a6c2000fac0b2c4c6Caitlin Sadowski    // may want to also keep the union in future. As an example, let's say
2413402aa0698fec81e574818a0a6c2000fac0b2c4c6Caitlin Sadowski    // the intersection contains Mutex L, and the union contains L and M.
2414402aa0698fec81e574818a0a6c2000fac0b2c4c6Caitlin Sadowski    // Later we unlock M. At this point, we would output an error because we
2415402aa0698fec81e574818a0a6c2000fac0b2c4c6Caitlin Sadowski    // never locked M; although the real error is probably that we forgot to
2416402aa0698fec81e574818a0a6c2000fac0b2c4c6Caitlin Sadowski    // lock M on all code paths. Conversely, let's say that later we lock M.
2417402aa0698fec81e574818a0a6c2000fac0b2c4c6Caitlin Sadowski    // In this case, we should compare against the intersection instead of the
2418402aa0698fec81e574818a0a6c2000fac0b2c4c6Caitlin Sadowski    // union because the real error is probably that we forgot to unlock M on
2419402aa0698fec81e574818a0a6c2000fac0b2c4c6Caitlin Sadowski    // all code paths.
2420402aa0698fec81e574818a0a6c2000fac0b2c4c6Caitlin Sadowski    bool LocksetInitialized = false;
2421cfa88f893915ceb8ae4ce2f17c46c24a4d67502fDmitri Gribenko    SmallVector<CFGBlock *, 8> SpecialBlocks;
2422402aa0698fec81e574818a0a6c2000fac0b2c4c6Caitlin Sadowski    for (CFGBlock::const_pred_iterator PI = CurrBlock->pred_begin(),
2423402aa0698fec81e574818a0a6c2000fac0b2c4c6Caitlin Sadowski         PE  = CurrBlock->pred_end(); PI != PE; ++PI) {
2424402aa0698fec81e574818a0a6c2000fac0b2c4c6Caitlin Sadowski
2425402aa0698fec81e574818a0a6c2000fac0b2c4c6Caitlin Sadowski      // if *PI -> CurrBlock is a back edge
2426402aa0698fec81e574818a0a6c2000fac0b2c4c6Caitlin Sadowski      if (*PI == 0 || !VisitedBlocks.alreadySet(*PI))
2427402aa0698fec81e574818a0a6c2000fac0b2c4c6Caitlin Sadowski        continue;
2428402aa0698fec81e574818a0a6c2000fac0b2c4c6Caitlin Sadowski
2429d2f388299153d80cbe5ffaaed8a882b59a1b59bcDeLesley Hutchins      int PrevBlockID = (*PI)->getBlockID();
2430d2f388299153d80cbe5ffaaed8a882b59a1b59bcDeLesley Hutchins      CFGBlockInfo *PrevBlockInfo = &BlockInfo[PrevBlockID];
2431d2f388299153d80cbe5ffaaed8a882b59a1b59bcDeLesley Hutchins
24322a35be803c405221f5f23c7bdedb91f09efdd3acDeLesley Hutchins      // Ignore edges from blocks that can't return.
24330ecc2e9ce86b0705bc1a53a9c8f90c433bcdca1bDeLesley Hutchins      if (neverReturns(*PI) || !PrevBlockInfo->Reachable)
24342a35be803c405221f5f23c7bdedb91f09efdd3acDeLesley Hutchins        continue;
24352a35be803c405221f5f23c7bdedb91f09efdd3acDeLesley Hutchins
2436d2f388299153d80cbe5ffaaed8a882b59a1b59bcDeLesley Hutchins      // Okay, we can reach this block from the entry.
2437d2f388299153d80cbe5ffaaed8a882b59a1b59bcDeLesley Hutchins      CurrBlockInfo->Reachable = true;
2438d2f388299153d80cbe5ffaaed8a882b59a1b59bcDeLesley Hutchins
2439aacde7174af6c5759b52dc0ceb7b167d323afb6aRichard Smith      // If the previous block ended in a 'continue' or 'break' statement, then
2440aacde7174af6c5759b52dc0ceb7b167d323afb6aRichard Smith      // a difference in locksets is probably due to a bug in that block, rather
2441aacde7174af6c5759b52dc0ceb7b167d323afb6aRichard Smith      // than in some other predecessor. In that case, keep the other
2442aacde7174af6c5759b52dc0ceb7b167d323afb6aRichard Smith      // predecessor's lockset.
2443aacde7174af6c5759b52dc0ceb7b167d323afb6aRichard Smith      if (const Stmt *Terminator = (*PI)->getTerminator()) {
2444aacde7174af6c5759b52dc0ceb7b167d323afb6aRichard Smith        if (isa<ContinueStmt>(Terminator) || isa<BreakStmt>(Terminator)) {
2445aacde7174af6c5759b52dc0ceb7b167d323afb6aRichard Smith          SpecialBlocks.push_back(*PI);
2446aacde7174af6c5759b52dc0ceb7b167d323afb6aRichard Smith          continue;
2447aacde7174af6c5759b52dc0ceb7b167d323afb6aRichard Smith        }
2448aacde7174af6c5759b52dc0ceb7b167d323afb6aRichard Smith      }
2449aacde7174af6c5759b52dc0ceb7b167d323afb6aRichard Smith
2450a1fa47139d6e9e7dcc40f2809605d1a258624e7fDeLesley Hutchins      FactSet PrevLockset;
2451a1fa47139d6e9e7dcc40f2809605d1a258624e7fDeLesley Hutchins      getEdgeLockset(PrevLockset, PrevBlockInfo->ExitSet, *PI, CurrBlock);
2452b37d2b5c0819d9ef596c7baec1e0be0d7c45b547DeLesley Hutchins
2453402aa0698fec81e574818a0a6c2000fac0b2c4c6Caitlin Sadowski      if (!LocksetInitialized) {
24540da4414f3d30c34fafb81b13b2cec3680c0bc9e1DeLesley Hutchins        CurrBlockInfo->EntrySet = PrevLockset;
2455402aa0698fec81e574818a0a6c2000fac0b2c4c6Caitlin Sadowski        LocksetInitialized = true;
2456402aa0698fec81e574818a0a6c2000fac0b2c4c6Caitlin Sadowski      } else {
2457a1fa47139d6e9e7dcc40f2809605d1a258624e7fDeLesley Hutchins        intersectAndWarn(CurrBlockInfo->EntrySet, PrevLockset,
2458a1fa47139d6e9e7dcc40f2809605d1a258624e7fDeLesley Hutchins                         CurrBlockInfo->EntryLoc,
2459a1fa47139d6e9e7dcc40f2809605d1a258624e7fDeLesley Hutchins                         LEK_LockedSomePredecessors);
2460402aa0698fec81e574818a0a6c2000fac0b2c4c6Caitlin Sadowski      }
2461402aa0698fec81e574818a0a6c2000fac0b2c4c6Caitlin Sadowski    }
2462402aa0698fec81e574818a0a6c2000fac0b2c4c6Caitlin Sadowski
2463d2f388299153d80cbe5ffaaed8a882b59a1b59bcDeLesley Hutchins    // Skip rest of block if it's not reachable.
2464d2f388299153d80cbe5ffaaed8a882b59a1b59bcDeLesley Hutchins    if (!CurrBlockInfo->Reachable)
2465d2f388299153d80cbe5ffaaed8a882b59a1b59bcDeLesley Hutchins      continue;
2466d2f388299153d80cbe5ffaaed8a882b59a1b59bcDeLesley Hutchins
2467aacde7174af6c5759b52dc0ceb7b167d323afb6aRichard Smith    // Process continue and break blocks. Assume that the lockset for the
2468aacde7174af6c5759b52dc0ceb7b167d323afb6aRichard Smith    // resulting block is unaffected by any discrepancies in them.
2469aacde7174af6c5759b52dc0ceb7b167d323afb6aRichard Smith    for (unsigned SpecialI = 0, SpecialN = SpecialBlocks.size();
2470aacde7174af6c5759b52dc0ceb7b167d323afb6aRichard Smith         SpecialI < SpecialN; ++SpecialI) {
2471aacde7174af6c5759b52dc0ceb7b167d323afb6aRichard Smith      CFGBlock *PrevBlock = SpecialBlocks[SpecialI];
2472aacde7174af6c5759b52dc0ceb7b167d323afb6aRichard Smith      int PrevBlockID = PrevBlock->getBlockID();
2473aacde7174af6c5759b52dc0ceb7b167d323afb6aRichard Smith      CFGBlockInfo *PrevBlockInfo = &BlockInfo[PrevBlockID];
2474aacde7174af6c5759b52dc0ceb7b167d323afb6aRichard Smith
2475aacde7174af6c5759b52dc0ceb7b167d323afb6aRichard Smith      if (!LocksetInitialized) {
2476aacde7174af6c5759b52dc0ceb7b167d323afb6aRichard Smith        CurrBlockInfo->EntrySet = PrevBlockInfo->ExitSet;
2477aacde7174af6c5759b52dc0ceb7b167d323afb6aRichard Smith        LocksetInitialized = true;
2478aacde7174af6c5759b52dc0ceb7b167d323afb6aRichard Smith      } else {
2479aacde7174af6c5759b52dc0ceb7b167d323afb6aRichard Smith        // Determine whether this edge is a loop terminator for diagnostic
2480aacde7174af6c5759b52dc0ceb7b167d323afb6aRichard Smith        // purposes. FIXME: A 'break' statement might be a loop terminator, but
2481aacde7174af6c5759b52dc0ceb7b167d323afb6aRichard Smith        // it might also be part of a switch. Also, a subsequent destructor
2482aacde7174af6c5759b52dc0ceb7b167d323afb6aRichard Smith        // might add to the lockset, in which case the real issue might be a
2483aacde7174af6c5759b52dc0ceb7b167d323afb6aRichard Smith        // double lock on the other path.
2484aacde7174af6c5759b52dc0ceb7b167d323afb6aRichard Smith        const Stmt *Terminator = PrevBlock->getTerminator();
2485aacde7174af6c5759b52dc0ceb7b167d323afb6aRichard Smith        bool IsLoop = Terminator && isa<ContinueStmt>(Terminator);
2486aacde7174af6c5759b52dc0ceb7b167d323afb6aRichard Smith
2487a1fa47139d6e9e7dcc40f2809605d1a258624e7fDeLesley Hutchins        FactSet PrevLockset;
2488a1fa47139d6e9e7dcc40f2809605d1a258624e7fDeLesley Hutchins        getEdgeLockset(PrevLockset, PrevBlockInfo->ExitSet,
2489a1fa47139d6e9e7dcc40f2809605d1a258624e7fDeLesley Hutchins                       PrevBlock, CurrBlock);
24900da4414f3d30c34fafb81b13b2cec3680c0bc9e1DeLesley Hutchins
2491aacde7174af6c5759b52dc0ceb7b167d323afb6aRichard Smith        // Do not update EntrySet.
24920da4414f3d30c34fafb81b13b2cec3680c0bc9e1DeLesley Hutchins        intersectAndWarn(CurrBlockInfo->EntrySet, PrevLockset,
24930da4414f3d30c34fafb81b13b2cec3680c0bc9e1DeLesley Hutchins                         PrevBlockInfo->ExitLoc,
2494aacde7174af6c5759b52dc0ceb7b167d323afb6aRichard Smith                         IsLoop ? LEK_LockedSomeLoopIterations
2495a1fa47139d6e9e7dcc40f2809605d1a258624e7fDeLesley Hutchins                                : LEK_LockedSomePredecessors,
2496a1fa47139d6e9e7dcc40f2809605d1a258624e7fDeLesley Hutchins                         false);
2497aacde7174af6c5759b52dc0ceb7b167d323afb6aRichard Smith      }
2498aacde7174af6c5759b52dc0ceb7b167d323afb6aRichard Smith    }
2499aacde7174af6c5759b52dc0ceb7b167d323afb6aRichard Smith
250054c350a67b47f059e1d577bdd9e2d1dc31ff82b5DeLesley Hutchins    BuildLockset LocksetBuilder(this, *CurrBlockInfo);
250154c350a67b47f059e1d577bdd9e2d1dc31ff82b5DeLesley Hutchins
2502b37d2b5c0819d9ef596c7baec1e0be0d7c45b547DeLesley Hutchins    // Visit all the statements in the basic block.
2503402aa0698fec81e574818a0a6c2000fac0b2c4c6Caitlin Sadowski    for (CFGBlock::const_iterator BI = CurrBlock->begin(),
2504402aa0698fec81e574818a0a6c2000fac0b2c4c6Caitlin Sadowski         BE = CurrBlock->end(); BI != BE; ++BI) {
25056db51f707e93816364039a2a904d13d3968c7f05DeLesley Hutchins      switch (BI->getKind()) {
25066db51f707e93816364039a2a904d13d3968c7f05DeLesley Hutchins        case CFGElement::Statement: {
2507fdf6a279c9a75c778eba382d9a156697092982a1David Blaikie          CFGStmt CS = BI->castAs<CFGStmt>();
2508fdf6a279c9a75c778eba382d9a156697092982a1David Blaikie          LocksetBuilder.Visit(const_cast<Stmt*>(CS.getStmt()));
25096db51f707e93816364039a2a904d13d3968c7f05DeLesley Hutchins          break;
25106db51f707e93816364039a2a904d13d3968c7f05DeLesley Hutchins        }
25116db51f707e93816364039a2a904d13d3968c7f05DeLesley Hutchins        // Ignore BaseDtor, MemberDtor, and TemporaryDtor for now.
25126db51f707e93816364039a2a904d13d3968c7f05DeLesley Hutchins        case CFGElement::AutomaticObjectDtor: {
2513fdf6a279c9a75c778eba382d9a156697092982a1David Blaikie          CFGAutomaticObjDtor AD = BI->castAs<CFGAutomaticObjDtor>();
2514fdf6a279c9a75c778eba382d9a156697092982a1David Blaikie          CXXDestructorDecl *DD = const_cast<CXXDestructorDecl *>(
2515fdf6a279c9a75c778eba382d9a156697092982a1David Blaikie              AD.getDestructorDecl(AC.getASTContext()));
25166db51f707e93816364039a2a904d13d3968c7f05DeLesley Hutchins          if (!DD->hasAttrs())
25176db51f707e93816364039a2a904d13d3968c7f05DeLesley Hutchins            break;
25186db51f707e93816364039a2a904d13d3968c7f05DeLesley Hutchins
25196db51f707e93816364039a2a904d13d3968c7f05DeLesley Hutchins          // Create a dummy expression,
2520fdf6a279c9a75c778eba382d9a156697092982a1David Blaikie          VarDecl *VD = const_cast<VarDecl*>(AD.getVarDecl());
2521f4b88a45902af1802a1cb42ba48b1c474474f228John McCall          DeclRefExpr DRE(VD, false, VD->getType(), VK_LValue,
2522fdf6a279c9a75c778eba382d9a156697092982a1David Blaikie                          AD.getTriggerStmt()->getLocEnd());
25236db51f707e93816364039a2a904d13d3968c7f05DeLesley Hutchins          LocksetBuilder.handleCall(&DRE, DD);
25246db51f707e93816364039a2a904d13d3968c7f05DeLesley Hutchins          break;
25256db51f707e93816364039a2a904d13d3968c7f05DeLesley Hutchins        }
25266db51f707e93816364039a2a904d13d3968c7f05DeLesley Hutchins        default:
25276db51f707e93816364039a2a904d13d3968c7f05DeLesley Hutchins          break;
25286db51f707e93816364039a2a904d13d3968c7f05DeLesley Hutchins      }
2529402aa0698fec81e574818a0a6c2000fac0b2c4c6Caitlin Sadowski    }
2530a1fa47139d6e9e7dcc40f2809605d1a258624e7fDeLesley Hutchins    CurrBlockInfo->ExitSet = LocksetBuilder.FSet;
2531402aa0698fec81e574818a0a6c2000fac0b2c4c6Caitlin Sadowski
2532402aa0698fec81e574818a0a6c2000fac0b2c4c6Caitlin Sadowski    // For every back edge from CurrBlock (the end of the loop) to another block
2533402aa0698fec81e574818a0a6c2000fac0b2c4c6Caitlin Sadowski    // (FirstLoopBlock) we need to check that the Lockset of Block is equal to
2534402aa0698fec81e574818a0a6c2000fac0b2c4c6Caitlin Sadowski    // the one held at the beginning of FirstLoopBlock. We can look up the
2535402aa0698fec81e574818a0a6c2000fac0b2c4c6Caitlin Sadowski    // Lockset held at the beginning of FirstLoopBlock in the EntryLockSets map.
2536402aa0698fec81e574818a0a6c2000fac0b2c4c6Caitlin Sadowski    for (CFGBlock::const_succ_iterator SI = CurrBlock->succ_begin(),
2537402aa0698fec81e574818a0a6c2000fac0b2c4c6Caitlin Sadowski         SE  = CurrBlock->succ_end(); SI != SE; ++SI) {
2538402aa0698fec81e574818a0a6c2000fac0b2c4c6Caitlin Sadowski
2539402aa0698fec81e574818a0a6c2000fac0b2c4c6Caitlin Sadowski      // if CurrBlock -> *SI is *not* a back edge
2540402aa0698fec81e574818a0a6c2000fac0b2c4c6Caitlin Sadowski      if (*SI == 0 || !VisitedBlocks.alreadySet(*SI))
2541402aa0698fec81e574818a0a6c2000fac0b2c4c6Caitlin Sadowski        continue;
2542402aa0698fec81e574818a0a6c2000fac0b2c4c6Caitlin Sadowski
2543402aa0698fec81e574818a0a6c2000fac0b2c4c6Caitlin Sadowski      CFGBlock *FirstLoopBlock = *SI;
25440da4414f3d30c34fafb81b13b2cec3680c0bc9e1DeLesley Hutchins      CFGBlockInfo *PreLoop = &BlockInfo[FirstLoopBlock->getBlockID()];
25450da4414f3d30c34fafb81b13b2cec3680c0bc9e1DeLesley Hutchins      CFGBlockInfo *LoopEnd = &BlockInfo[CurrBlockID];
25460da4414f3d30c34fafb81b13b2cec3680c0bc9e1DeLesley Hutchins      intersectAndWarn(LoopEnd->ExitSet, PreLoop->EntrySet,
25470da4414f3d30c34fafb81b13b2cec3680c0bc9e1DeLesley Hutchins                       PreLoop->EntryLoc,
2548a1fa47139d6e9e7dcc40f2809605d1a258624e7fDeLesley Hutchins                       LEK_LockedSomeLoopIterations,
2549a1fa47139d6e9e7dcc40f2809605d1a258624e7fDeLesley Hutchins                       false);
2550402aa0698fec81e574818a0a6c2000fac0b2c4c6Caitlin Sadowski    }
2551402aa0698fec81e574818a0a6c2000fac0b2c4c6Caitlin Sadowski  }
2552402aa0698fec81e574818a0a6c2000fac0b2c4c6Caitlin Sadowski
2553d2f388299153d80cbe5ffaaed8a882b59a1b59bcDeLesley Hutchins  CFGBlockInfo *Initial = &BlockInfo[CFGraph->getEntry().getBlockID()];
2554d2f388299153d80cbe5ffaaed8a882b59a1b59bcDeLesley Hutchins  CFGBlockInfo *Final   = &BlockInfo[CFGraph->getExit().getBlockID()];
25552a237e03c407ff55bd8639b18658a8751955f1dbDeLesley Hutchins
25562a237e03c407ff55bd8639b18658a8751955f1dbDeLesley Hutchins  // Skip the final check if the exit block is unreachable.
2557d2f388299153d80cbe5ffaaed8a882b59a1b59bcDeLesley Hutchins  if (!Final->Reachable)
25582a237e03c407ff55bd8639b18658a8751955f1dbDeLesley Hutchins    return;
25592a237e03c407ff55bd8639b18658a8751955f1dbDeLesley Hutchins
25605696884053b4a60dbed01ea8c7e6cd8dcf9b5de9DeLesley Hutchins  // By default, we expect all locks held on entry to be held on exit.
25615696884053b4a60dbed01ea8c7e6cd8dcf9b5de9DeLesley Hutchins  FactSet ExpectedExitSet = Initial->EntrySet;
25625696884053b4a60dbed01ea8c7e6cd8dcf9b5de9DeLesley Hutchins
25635696884053b4a60dbed01ea8c7e6cd8dcf9b5de9DeLesley Hutchins  // Adjust the expected exit set by adding or removing locks, as declared
25645696884053b4a60dbed01ea8c7e6cd8dcf9b5de9DeLesley Hutchins  // by *-LOCK_FUNCTION and UNLOCK_FUNCTION.  The intersect below will then
25655696884053b4a60dbed01ea8c7e6cd8dcf9b5de9DeLesley Hutchins  // issue the appropriate warning.
25665696884053b4a60dbed01ea8c7e6cd8dcf9b5de9DeLesley Hutchins  // FIXME: the location here is not quite right.
25675696884053b4a60dbed01ea8c7e6cd8dcf9b5de9DeLesley Hutchins  for (unsigned i=0,n=ExclusiveLocksAcquired.size(); i<n; ++i) {
25685696884053b4a60dbed01ea8c7e6cd8dcf9b5de9DeLesley Hutchins    ExpectedExitSet.addLock(FactMan, ExclusiveLocksAcquired[i],
25695696884053b4a60dbed01ea8c7e6cd8dcf9b5de9DeLesley Hutchins                            LockData(D->getLocation(), LK_Exclusive));
25705696884053b4a60dbed01ea8c7e6cd8dcf9b5de9DeLesley Hutchins  }
25715696884053b4a60dbed01ea8c7e6cd8dcf9b5de9DeLesley Hutchins  for (unsigned i=0,n=SharedLocksAcquired.size(); i<n; ++i) {
25725696884053b4a60dbed01ea8c7e6cd8dcf9b5de9DeLesley Hutchins    ExpectedExitSet.addLock(FactMan, SharedLocksAcquired[i],
25735696884053b4a60dbed01ea8c7e6cd8dcf9b5de9DeLesley Hutchins                            LockData(D->getLocation(), LK_Shared));
25745696884053b4a60dbed01ea8c7e6cd8dcf9b5de9DeLesley Hutchins  }
25755696884053b4a60dbed01ea8c7e6cd8dcf9b5de9DeLesley Hutchins  for (unsigned i=0,n=LocksReleased.size(); i<n; ++i) {
25765696884053b4a60dbed01ea8c7e6cd8dcf9b5de9DeLesley Hutchins    ExpectedExitSet.removeLock(FactMan, LocksReleased[i]);
25775696884053b4a60dbed01ea8c7e6cd8dcf9b5de9DeLesley Hutchins  }
25785696884053b4a60dbed01ea8c7e6cd8dcf9b5de9DeLesley Hutchins
25791748b1256646cf0752f172c53ad7482f7beed185Caitlin Sadowski  // FIXME: Should we call this function for all blocks which exit the function?
25805696884053b4a60dbed01ea8c7e6cd8dcf9b5de9DeLesley Hutchins  intersectAndWarn(ExpectedExitSet, Final->ExitSet,
25810da4414f3d30c34fafb81b13b2cec3680c0bc9e1DeLesley Hutchins                   Final->ExitLoc,
2582879a4334e4c4cab0c22ba91492ffc2838bbc21fcDeLesley Hutchins                   LEK_LockedAtEndOfFunction,
2583a1fa47139d6e9e7dcc40f2809605d1a258624e7fDeLesley Hutchins                   LEK_NotLockedAtEndOfFunction,
2584a1fa47139d6e9e7dcc40f2809605d1a258624e7fDeLesley Hutchins                   false);
2585a60448d6dfc91f4c30987e237bf70ef50ac7705bDeLesley Hutchins}
2586a60448d6dfc91f4c30987e237bf70ef50ac7705bDeLesley Hutchins
2587a60448d6dfc91f4c30987e237bf70ef50ac7705bDeLesley Hutchins} // end anonymous namespace
2588a60448d6dfc91f4c30987e237bf70ef50ac7705bDeLesley Hutchins
2589a60448d6dfc91f4c30987e237bf70ef50ac7705bDeLesley Hutchins
2590a60448d6dfc91f4c30987e237bf70ef50ac7705bDeLesley Hutchinsnamespace clang {
2591a60448d6dfc91f4c30987e237bf70ef50ac7705bDeLesley Hutchinsnamespace thread_safety {
2592a60448d6dfc91f4c30987e237bf70ef50ac7705bDeLesley Hutchins
2593a60448d6dfc91f4c30987e237bf70ef50ac7705bDeLesley Hutchins/// \brief Check a function's CFG for thread-safety violations.
2594a60448d6dfc91f4c30987e237bf70ef50ac7705bDeLesley Hutchins///
2595a60448d6dfc91f4c30987e237bf70ef50ac7705bDeLesley Hutchins/// We traverse the blocks in the CFG, compute the set of mutexes that are held
2596a60448d6dfc91f4c30987e237bf70ef50ac7705bDeLesley Hutchins/// at the end of each block, and issue warnings for thread safety violations.
2597a60448d6dfc91f4c30987e237bf70ef50ac7705bDeLesley Hutchins/// Each block in the CFG is traversed exactly once.
25981d26f48dc2eea1c07431ca1519d7034a21b9bcffTed Kremenekvoid runThreadSafetyAnalysis(AnalysisDeclContext &AC,
2599a60448d6dfc91f4c30987e237bf70ef50ac7705bDeLesley Hutchins                             ThreadSafetyHandler &Handler) {
2600a60448d6dfc91f4c30987e237bf70ef50ac7705bDeLesley Hutchins  ThreadSafetyAnalyzer Analyzer(Handler);
2601a60448d6dfc91f4c30987e237bf70ef50ac7705bDeLesley Hutchins  Analyzer.runAnalysis(AC);
2602402aa0698fec81e574818a0a6c2000fac0b2c4c6Caitlin Sadowski}
2603402aa0698fec81e574818a0a6c2000fac0b2c4c6Caitlin Sadowski
2604402aa0698fec81e574818a0a6c2000fac0b2c4c6Caitlin Sadowski/// \brief Helper function that returns a LockKind required for the given level
2605402aa0698fec81e574818a0a6c2000fac0b2c4c6Caitlin Sadowski/// of access.
2606402aa0698fec81e574818a0a6c2000fac0b2c4c6Caitlin SadowskiLockKind getLockKindFromAccessKind(AccessKind AK) {
2607402aa0698fec81e574818a0a6c2000fac0b2c4c6Caitlin Sadowski  switch (AK) {
2608402aa0698fec81e574818a0a6c2000fac0b2c4c6Caitlin Sadowski    case AK_Read :
2609402aa0698fec81e574818a0a6c2000fac0b2c4c6Caitlin Sadowski      return LK_Shared;
2610402aa0698fec81e574818a0a6c2000fac0b2c4c6Caitlin Sadowski    case AK_Written :
2611402aa0698fec81e574818a0a6c2000fac0b2c4c6Caitlin Sadowski      return LK_Exclusive;
2612402aa0698fec81e574818a0a6c2000fac0b2c4c6Caitlin Sadowski  }
2613afc5b15022886c9e9e84d7aa0f2168b83e712310Benjamin Kramer  llvm_unreachable("Unknown AccessKind");
2614402aa0698fec81e574818a0a6c2000fac0b2c4c6Caitlin Sadowski}
2615a60448d6dfc91f4c30987e237bf70ef50ac7705bDeLesley Hutchins
2616402aa0698fec81e574818a0a6c2000fac0b2c4c6Caitlin Sadowski}} // end namespace clang::thread_safety
2617