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//
136bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines// See http://clang.llvm.org/docs/ThreadSafetyAnalysis.html
14b96e74f79cc9f64a8d0080d4eff5d0431d2a48cfAaron Ballman// for more information.
15402aa0698fec81e574818a0a6c2000fac0b2c4c6Caitlin Sadowski//
16402aa0698fec81e574818a0a6c2000fac0b2c4c6Caitlin Sadowski//===----------------------------------------------------------------------===//
17402aa0698fec81e574818a0a6c2000fac0b2c4c6Caitlin Sadowski
182fa67efeaf66a9332c30a026dc1c21bef6c33a6cBenjamin Kramer#include "clang/AST/Attr.h"
19402aa0698fec81e574818a0a6c2000fac0b2c4c6Caitlin Sadowski#include "clang/AST/DeclCXX.h"
20402aa0698fec81e574818a0a6c2000fac0b2c4c6Caitlin Sadowski#include "clang/AST/ExprCXX.h"
21402aa0698fec81e574818a0a6c2000fac0b2c4c6Caitlin Sadowski#include "clang/AST/StmtCXX.h"
22402aa0698fec81e574818a0a6c2000fac0b2c4c6Caitlin Sadowski#include "clang/AST/StmtVisitor.h"
2355fc873017f10f6f566b182b70f6fc22aefa3464Chandler Carruth#include "clang/Analysis/Analyses/PostOrderCFGView.h"
246bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines#include "clang/Analysis/Analyses/ThreadSafety.h"
256bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines#include "clang/Analysis/Analyses/ThreadSafetyLogical.h"
266bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines#include "clang/Analysis/Analyses/ThreadSafetyTIL.h"
276bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines#include "clang/Analysis/Analyses/ThreadSafetyTraverse.h"
286bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines#include "clang/Analysis/Analyses/ThreadSafetyCommon.h"
2955fc873017f10f6f566b182b70f6fc22aefa3464Chandler Carruth#include "clang/Analysis/AnalysisContext.h"
3055fc873017f10f6f566b182b70f6fc22aefa3464Chandler Carruth#include "clang/Analysis/CFG.h"
3155fc873017f10f6f566b182b70f6fc22aefa3464Chandler Carruth#include "clang/Analysis/CFGStmtMap.h"
3296fac6a7fe89deff7860e536febbd4ae17bb57f3DeLesley Hutchins#include "clang/Basic/OperatorKinds.h"
332fa67efeaf66a9332c30a026dc1c21bef6c33a6cBenjamin Kramer#include "clang/Basic/SourceLocation.h"
342fa67efeaf66a9332c30a026dc1c21bef6c33a6cBenjamin Kramer#include "clang/Basic/SourceManager.h"
35402aa0698fec81e574818a0a6c2000fac0b2c4c6Caitlin Sadowski#include "llvm/ADT/BitVector.h"
36402aa0698fec81e574818a0a6c2000fac0b2c4c6Caitlin Sadowski#include "llvm/ADT/FoldingSet.h"
37402aa0698fec81e574818a0a6c2000fac0b2c4c6Caitlin Sadowski#include "llvm/ADT/ImmutableMap.h"
38402aa0698fec81e574818a0a6c2000fac0b2c4c6Caitlin Sadowski#include "llvm/ADT/PostOrderIterator.h"
39402aa0698fec81e574818a0a6c2000fac0b2c4c6Caitlin Sadowski#include "llvm/ADT/SmallVector.h"
40402aa0698fec81e574818a0a6c2000fac0b2c4c6Caitlin Sadowski#include "llvm/ADT/StringRef.h"
41b37d2b5c0819d9ef596c7baec1e0be0d7c45b547DeLesley Hutchins#include "llvm/Support/raw_ostream.h"
42402aa0698fec81e574818a0a6c2000fac0b2c4c6Caitlin Sadowski#include <algorithm>
43b37d2b5c0819d9ef596c7baec1e0be0d7c45b547DeLesley Hutchins#include <utility>
44402aa0698fec81e574818a0a6c2000fac0b2c4c6Caitlin Sadowski#include <vector>
45402aa0698fec81e574818a0a6c2000fac0b2c4c6Caitlin Sadowski
46402aa0698fec81e574818a0a6c2000fac0b2c4c6Caitlin Sadowskiusing namespace clang;
47402aa0698fec81e574818a0a6c2000fac0b2c4c6Caitlin Sadowskiusing namespace thread_safety;
48402aa0698fec81e574818a0a6c2000fac0b2c4c6Caitlin Sadowski
4919903465e960329c0d5d93327f4046d036b0bc75Caitlin Sadowski// Key method definition
5019903465e960329c0d5d93327f4046d036b0bc75Caitlin SadowskiThreadSafetyHandler::~ThreadSafetyHandler() {}
5119903465e960329c0d5d93327f4046d036b0bc75Caitlin Sadowski
52402aa0698fec81e574818a0a6c2000fac0b2c4c6Caitlin Sadowskinamespace {
53a60448d6dfc91f4c30987e237bf70ef50ac7705bDeLesley Hutchins
54a74b715cdc37c4523818a4018faae99d977aa537DeLesley Hutchins/// SExpr implements a simple expression language that is used to store,
55a74b715cdc37c4523818a4018faae99d977aa537DeLesley Hutchins/// compare, and pretty-print C++ expressions.  Unlike a clang Expr, a SExpr
56a74b715cdc37c4523818a4018faae99d977aa537DeLesley Hutchins/// does not capture surface syntax, and it does not distinguish between
57a74b715cdc37c4523818a4018faae99d977aa537DeLesley Hutchins/// C++ concepts, like pointers and references, that have no real semantic
58a74b715cdc37c4523818a4018faae99d977aa537DeLesley Hutchins/// differences.  This simplicity allows SExprs to be meaningfully compared,
59a74b715cdc37c4523818a4018faae99d977aa537DeLesley Hutchins/// e.g.
60a74b715cdc37c4523818a4018faae99d977aa537DeLesley Hutchins///        (x)          =  x
61a74b715cdc37c4523818a4018faae99d977aa537DeLesley Hutchins///        (*this).foo  =  this->foo
62a74b715cdc37c4523818a4018faae99d977aa537DeLesley Hutchins///        *&a          =  a
63402aa0698fec81e574818a0a6c2000fac0b2c4c6Caitlin Sadowski///
64402aa0698fec81e574818a0a6c2000fac0b2c4c6Caitlin Sadowski/// Thread-safety analysis works by comparing lock expressions.  Within the
65402aa0698fec81e574818a0a6c2000fac0b2c4c6Caitlin Sadowski/// body of a function, an expression such as "x->foo->bar.mu" will resolve to
66402aa0698fec81e574818a0a6c2000fac0b2c4c6Caitlin Sadowski/// a particular mutex object at run-time.  Subsequent occurrences of the same
67402aa0698fec81e574818a0a6c2000fac0b2c4c6Caitlin Sadowski/// expression (where "same" means syntactic equality) will refer to the same
68402aa0698fec81e574818a0a6c2000fac0b2c4c6Caitlin Sadowski/// run-time object if three conditions hold:
69402aa0698fec81e574818a0a6c2000fac0b2c4c6Caitlin Sadowski/// (1) Local variables in the expression, such as "x" have not changed.
70402aa0698fec81e574818a0a6c2000fac0b2c4c6Caitlin Sadowski/// (2) Values on the heap that affect the expression have not changed.
71402aa0698fec81e574818a0a6c2000fac0b2c4c6Caitlin Sadowski/// (3) The expression involves only pure function calls.
72e0eaa8531f8fd9189710aac3b6f3aadb62bb14d1DeLesley Hutchins///
73402aa0698fec81e574818a0a6c2000fac0b2c4c6Caitlin Sadowski/// The current implementation assumes, but does not verify, that multiple uses
74402aa0698fec81e574818a0a6c2000fac0b2c4c6Caitlin Sadowski/// of the same lock expression satisfies these criteria.
75a74b715cdc37c4523818a4018faae99d977aa537DeLesley Hutchinsclass SExpr {
76a74b715cdc37c4523818a4018faae99d977aa537DeLesley Hutchinsprivate:
77a74b715cdc37c4523818a4018faae99d977aa537DeLesley Hutchins  enum ExprOp {
780b4db3e08a201c35f0011489bd5cd5d39bbe54fbDeLesley Hutchins    EOP_Nop,       ///< No-op
790b4db3e08a201c35f0011489bd5cd5d39bbe54fbDeLesley Hutchins    EOP_Wildcard,  ///< Matches anything.
800b4db3e08a201c35f0011489bd5cd5d39bbe54fbDeLesley Hutchins    EOP_Universal, ///< Universal lock.
810b4db3e08a201c35f0011489bd5cd5d39bbe54fbDeLesley Hutchins    EOP_This,      ///< This keyword.
820b4db3e08a201c35f0011489bd5cd5d39bbe54fbDeLesley Hutchins    EOP_NVar,      ///< Named variable.
830b4db3e08a201c35f0011489bd5cd5d39bbe54fbDeLesley Hutchins    EOP_LVar,      ///< Local variable.
840b4db3e08a201c35f0011489bd5cd5d39bbe54fbDeLesley Hutchins    EOP_Dot,       ///< Field access
850b4db3e08a201c35f0011489bd5cd5d39bbe54fbDeLesley Hutchins    EOP_Call,      ///< Function call
860b4db3e08a201c35f0011489bd5cd5d39bbe54fbDeLesley Hutchins    EOP_MCall,     ///< Method call
870b4db3e08a201c35f0011489bd5cd5d39bbe54fbDeLesley Hutchins    EOP_Index,     ///< Array index
880b4db3e08a201c35f0011489bd5cd5d39bbe54fbDeLesley Hutchins    EOP_Unary,     ///< Unary operation
890b4db3e08a201c35f0011489bd5cd5d39bbe54fbDeLesley Hutchins    EOP_Binary,    ///< Binary operation
900b4db3e08a201c35f0011489bd5cd5d39bbe54fbDeLesley Hutchins    EOP_Unknown    ///< Catchall for everything else
91a74b715cdc37c4523818a4018faae99d977aa537DeLesley Hutchins  };
92a74b715cdc37c4523818a4018faae99d977aa537DeLesley Hutchins
93a74b715cdc37c4523818a4018faae99d977aa537DeLesley Hutchins
94a74b715cdc37c4523818a4018faae99d977aa537DeLesley Hutchins  class SExprNode {
95a74b715cdc37c4523818a4018faae99d977aa537DeLesley Hutchins   private:
96ad0fe03b897f9486191e75c8d90c3ffa9b4fd6a5Ted Kremenek    unsigned char  Op;     ///< Opcode of the root node
97ad0fe03b897f9486191e75c8d90c3ffa9b4fd6a5Ted Kremenek    unsigned char  Flags;  ///< Additional opcode-specific data
98ad0fe03b897f9486191e75c8d90c3ffa9b4fd6a5Ted Kremenek    unsigned short Sz;     ///< Number of child nodes
99ad0fe03b897f9486191e75c8d90c3ffa9b4fd6a5Ted Kremenek    const void*    Data;   ///< Additional opcode-specific data
100a74b715cdc37c4523818a4018faae99d977aa537DeLesley Hutchins
101a74b715cdc37c4523818a4018faae99d977aa537DeLesley Hutchins   public:
102a74b715cdc37c4523818a4018faae99d977aa537DeLesley Hutchins    SExprNode(ExprOp O, unsigned F, const void* D)
103a74b715cdc37c4523818a4018faae99d977aa537DeLesley Hutchins      : Op(static_cast<unsigned char>(O)),
104a74b715cdc37c4523818a4018faae99d977aa537DeLesley Hutchins        Flags(static_cast<unsigned char>(F)), Sz(1), Data(D)
105a74b715cdc37c4523818a4018faae99d977aa537DeLesley Hutchins    { }
106a74b715cdc37c4523818a4018faae99d977aa537DeLesley Hutchins
107a74b715cdc37c4523818a4018faae99d977aa537DeLesley Hutchins    unsigned size() const        { return Sz; }
108a74b715cdc37c4523818a4018faae99d977aa537DeLesley Hutchins    void     setSize(unsigned S) { Sz = S;    }
109a74b715cdc37c4523818a4018faae99d977aa537DeLesley Hutchins
110a74b715cdc37c4523818a4018faae99d977aa537DeLesley Hutchins    ExprOp   kind() const { return static_cast<ExprOp>(Op); }
111a74b715cdc37c4523818a4018faae99d977aa537DeLesley Hutchins
112a74b715cdc37c4523818a4018faae99d977aa537DeLesley Hutchins    const NamedDecl* getNamedDecl() const {
113a74b715cdc37c4523818a4018faae99d977aa537DeLesley Hutchins      assert(Op == EOP_NVar || Op == EOP_LVar || Op == EOP_Dot);
114a74b715cdc37c4523818a4018faae99d977aa537DeLesley Hutchins      return reinterpret_cast<const NamedDecl*>(Data);
115a74b715cdc37c4523818a4018faae99d977aa537DeLesley Hutchins    }
116a74b715cdc37c4523818a4018faae99d977aa537DeLesley Hutchins
117a74b715cdc37c4523818a4018faae99d977aa537DeLesley Hutchins    const NamedDecl* getFunctionDecl() const {
118a74b715cdc37c4523818a4018faae99d977aa537DeLesley Hutchins      assert(Op == EOP_Call || Op == EOP_MCall);
119a74b715cdc37c4523818a4018faae99d977aa537DeLesley Hutchins      return reinterpret_cast<const NamedDecl*>(Data);
120a74b715cdc37c4523818a4018faae99d977aa537DeLesley Hutchins    }
121a74b715cdc37c4523818a4018faae99d977aa537DeLesley Hutchins
122a74b715cdc37c4523818a4018faae99d977aa537DeLesley Hutchins    bool isArrow() const { return Op == EOP_Dot && Flags == 1; }
123a74b715cdc37c4523818a4018faae99d977aa537DeLesley Hutchins    void setArrow(bool A) { Flags = A ? 1 : 0; }
124a74b715cdc37c4523818a4018faae99d977aa537DeLesley Hutchins
125a74b715cdc37c4523818a4018faae99d977aa537DeLesley Hutchins    unsigned arity() const {
126a74b715cdc37c4523818a4018faae99d977aa537DeLesley Hutchins      switch (Op) {
1270b4db3e08a201c35f0011489bd5cd5d39bbe54fbDeLesley Hutchins        case EOP_Nop:       return 0;
1280b4db3e08a201c35f0011489bd5cd5d39bbe54fbDeLesley Hutchins        case EOP_Wildcard:  return 0;
1290b4db3e08a201c35f0011489bd5cd5d39bbe54fbDeLesley Hutchins        case EOP_Universal: return 0;
1300b4db3e08a201c35f0011489bd5cd5d39bbe54fbDeLesley Hutchins        case EOP_NVar:      return 0;
1310b4db3e08a201c35f0011489bd5cd5d39bbe54fbDeLesley Hutchins        case EOP_LVar:      return 0;
1320b4db3e08a201c35f0011489bd5cd5d39bbe54fbDeLesley Hutchins        case EOP_This:      return 0;
1330b4db3e08a201c35f0011489bd5cd5d39bbe54fbDeLesley Hutchins        case EOP_Dot:       return 1;
1340b4db3e08a201c35f0011489bd5cd5d39bbe54fbDeLesley Hutchins        case EOP_Call:      return Flags+1;  // First arg is function.
1350b4db3e08a201c35f0011489bd5cd5d39bbe54fbDeLesley Hutchins        case EOP_MCall:     return Flags+1;  // First arg is implicit obj.
1360b4db3e08a201c35f0011489bd5cd5d39bbe54fbDeLesley Hutchins        case EOP_Index:     return 2;
1370b4db3e08a201c35f0011489bd5cd5d39bbe54fbDeLesley Hutchins        case EOP_Unary:     return 1;
1380b4db3e08a201c35f0011489bd5cd5d39bbe54fbDeLesley Hutchins        case EOP_Binary:    return 2;
1390b4db3e08a201c35f0011489bd5cd5d39bbe54fbDeLesley Hutchins        case EOP_Unknown:   return Flags;
140a74b715cdc37c4523818a4018faae99d977aa537DeLesley Hutchins      }
141a74b715cdc37c4523818a4018faae99d977aa537DeLesley Hutchins      return 0;
142a74b715cdc37c4523818a4018faae99d977aa537DeLesley Hutchins    }
143a74b715cdc37c4523818a4018faae99d977aa537DeLesley Hutchins
144a74b715cdc37c4523818a4018faae99d977aa537DeLesley Hutchins    bool operator==(const SExprNode& Other) const {
145a74b715cdc37c4523818a4018faae99d977aa537DeLesley Hutchins      // Ignore flags and size -- they don't matter.
146ee2f032fe0fc86762608458c2a167ae504579a64DeLesley Hutchins      return (Op == Other.Op &&
147ee2f032fe0fc86762608458c2a167ae504579a64DeLesley Hutchins              Data == Other.Data);
148a74b715cdc37c4523818a4018faae99d977aa537DeLesley Hutchins    }
149a74b715cdc37c4523818a4018faae99d977aa537DeLesley Hutchins
150a74b715cdc37c4523818a4018faae99d977aa537DeLesley Hutchins    bool operator!=(const SExprNode& Other) const {
151a74b715cdc37c4523818a4018faae99d977aa537DeLesley Hutchins      return !(*this == Other);
152a74b715cdc37c4523818a4018faae99d977aa537DeLesley Hutchins    }
153ee2f032fe0fc86762608458c2a167ae504579a64DeLesley Hutchins
154ee2f032fe0fc86762608458c2a167ae504579a64DeLesley Hutchins    bool matches(const SExprNode& Other) const {
155ee2f032fe0fc86762608458c2a167ae504579a64DeLesley Hutchins      return (*this == Other) ||
156ee2f032fe0fc86762608458c2a167ae504579a64DeLesley Hutchins             (Op == EOP_Wildcard) ||
157ee2f032fe0fc86762608458c2a167ae504579a64DeLesley Hutchins             (Other.Op == EOP_Wildcard);
158ee2f032fe0fc86762608458c2a167ae504579a64DeLesley Hutchins    }
159a74b715cdc37c4523818a4018faae99d977aa537DeLesley Hutchins  };
160a74b715cdc37c4523818a4018faae99d977aa537DeLesley Hutchins
161402aa0698fec81e574818a0a6c2000fac0b2c4c6Caitlin Sadowski
162f63797c741e646b9482d204c88dee02fb41d7962DeLesley Hutchins  /// \brief Encapsulates the lexical context of a function call.  The lexical
163f63797c741e646b9482d204c88dee02fb41d7962DeLesley Hutchins  /// context includes the arguments to the call, including the implicit object
164f63797c741e646b9482d204c88dee02fb41d7962DeLesley Hutchins  /// argument.  When an attribute containing a mutex expression is attached to
165f63797c741e646b9482d204c88dee02fb41d7962DeLesley Hutchins  /// a method, the expression may refer to formal parameters of the method.
166f63797c741e646b9482d204c88dee02fb41d7962DeLesley Hutchins  /// Actual arguments must be substituted for formal parameters to derive
167f63797c741e646b9482d204c88dee02fb41d7962DeLesley Hutchins  /// the appropriate mutex expression in the lexical context where the function
168f63797c741e646b9482d204c88dee02fb41d7962DeLesley Hutchins  /// is called.  PrevCtx holds the context in which the arguments themselves
169f63797c741e646b9482d204c88dee02fb41d7962DeLesley Hutchins  /// should be evaluated; multiple calling contexts can be chained together
170f63797c741e646b9482d204c88dee02fb41d7962DeLesley Hutchins  /// by the lock_returned attribute.
171f63797c741e646b9482d204c88dee02fb41d7962DeLesley Hutchins  struct CallingContext {
17247715cc201170952029a52806bcc26f69c38272dDeLesley Hutchins    const NamedDecl*   AttrDecl;   // The decl to which the attribute is attached.
17347715cc201170952029a52806bcc26f69c38272dDeLesley Hutchins    const Expr*        SelfArg;    // Implicit object argument -- e.g. 'this'
17447715cc201170952029a52806bcc26f69c38272dDeLesley Hutchins    bool               SelfArrow;  // is Self referred to with -> or .?
17547715cc201170952029a52806bcc26f69c38272dDeLesley Hutchins    unsigned           NumArgs;    // Number of funArgs
17647715cc201170952029a52806bcc26f69c38272dDeLesley Hutchins    const Expr* const* FunArgs;    // Function arguments
17747715cc201170952029a52806bcc26f69c38272dDeLesley Hutchins    CallingContext*    PrevCtx;    // The previous context; or 0 if none.
17847715cc201170952029a52806bcc26f69c38272dDeLesley Hutchins
179651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines    CallingContext(const NamedDecl *D)
1806bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines        : AttrDecl(D), SelfArg(nullptr), SelfArrow(false), NumArgs(0),
1816bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines          FunArgs(nullptr), PrevCtx(nullptr) {}
182f63797c741e646b9482d204c88dee02fb41d7962DeLesley Hutchins  };
183f63797c741e646b9482d204c88dee02fb41d7962DeLesley Hutchins
184a74b715cdc37c4523818a4018faae99d977aa537DeLesley Hutchins  typedef SmallVector<SExprNode, 4> NodeVector;
185a74b715cdc37c4523818a4018faae99d977aa537DeLesley Hutchins
186a74b715cdc37c4523818a4018faae99d977aa537DeLesley Hutchinsprivate:
187a74b715cdc37c4523818a4018faae99d977aa537DeLesley Hutchins  // A SExpr is a list of SExprNodes in prefix order.  The Size field allows
188a74b715cdc37c4523818a4018faae99d977aa537DeLesley Hutchins  // the list to be traversed as a tree.
189a74b715cdc37c4523818a4018faae99d977aa537DeLesley Hutchins  NodeVector NodeVec;
190a74b715cdc37c4523818a4018faae99d977aa537DeLesley Hutchins
191a74b715cdc37c4523818a4018faae99d977aa537DeLesley Hutchinsprivate:
1926bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines  unsigned make(ExprOp O, unsigned F = 0, const void *D = nullptr) {
193651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines    NodeVec.push_back(SExprNode(O, F, D));
194651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines    return NodeVec.size() - 1;
195651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines  }
196651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines
197a74b715cdc37c4523818a4018faae99d977aa537DeLesley Hutchins  unsigned makeNop() {
198651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines    return make(EOP_Nop);
199a74b715cdc37c4523818a4018faae99d977aa537DeLesley Hutchins  }
200a74b715cdc37c4523818a4018faae99d977aa537DeLesley Hutchins
201ee2f032fe0fc86762608458c2a167ae504579a64DeLesley Hutchins  unsigned makeWildcard() {
202651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines    return make(EOP_Wildcard);
203ee2f032fe0fc86762608458c2a167ae504579a64DeLesley Hutchins  }
204ee2f032fe0fc86762608458c2a167ae504579a64DeLesley Hutchins
2050b4db3e08a201c35f0011489bd5cd5d39bbe54fbDeLesley Hutchins  unsigned makeUniversal() {
206651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines    return make(EOP_Universal);
2070b4db3e08a201c35f0011489bd5cd5d39bbe54fbDeLesley Hutchins  }
2080b4db3e08a201c35f0011489bd5cd5d39bbe54fbDeLesley Hutchins
209a74b715cdc37c4523818a4018faae99d977aa537DeLesley Hutchins  unsigned makeNamedVar(const NamedDecl *D) {
210651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines    return make(EOP_NVar, 0, D);
211a74b715cdc37c4523818a4018faae99d977aa537DeLesley Hutchins  }
212a74b715cdc37c4523818a4018faae99d977aa537DeLesley Hutchins
213a74b715cdc37c4523818a4018faae99d977aa537DeLesley Hutchins  unsigned makeLocalVar(const NamedDecl *D) {
214651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines    return make(EOP_LVar, 0, D);
215a74b715cdc37c4523818a4018faae99d977aa537DeLesley Hutchins  }
216a74b715cdc37c4523818a4018faae99d977aa537DeLesley Hutchins
217a74b715cdc37c4523818a4018faae99d977aa537DeLesley Hutchins  unsigned makeThis() {
218651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines    return make(EOP_This);
219a74b715cdc37c4523818a4018faae99d977aa537DeLesley Hutchins  }
220a74b715cdc37c4523818a4018faae99d977aa537DeLesley Hutchins
221a74b715cdc37c4523818a4018faae99d977aa537DeLesley Hutchins  unsigned makeDot(const NamedDecl *D, bool Arrow) {
222651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines    return make(EOP_Dot, Arrow ? 1 : 0, D);
223a74b715cdc37c4523818a4018faae99d977aa537DeLesley Hutchins  }
224a74b715cdc37c4523818a4018faae99d977aa537DeLesley Hutchins
225a74b715cdc37c4523818a4018faae99d977aa537DeLesley Hutchins  unsigned makeCall(unsigned NumArgs, const NamedDecl *D) {
226651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines    return make(EOP_Call, NumArgs, D);
227a74b715cdc37c4523818a4018faae99d977aa537DeLesley Hutchins  }
228a74b715cdc37c4523818a4018faae99d977aa537DeLesley Hutchins
229186af2de86aea41d7418158e68f96c1f8620e013DeLesley Hutchins  // Grab the very first declaration of virtual method D
230186af2de86aea41d7418158e68f96c1f8620e013DeLesley Hutchins  const CXXMethodDecl* getFirstVirtualDecl(const CXXMethodDecl *D) {
231186af2de86aea41d7418158e68f96c1f8620e013DeLesley Hutchins    while (true) {
232186af2de86aea41d7418158e68f96c1f8620e013DeLesley Hutchins      D = D->getCanonicalDecl();
233186af2de86aea41d7418158e68f96c1f8620e013DeLesley Hutchins      CXXMethodDecl::method_iterator I = D->begin_overridden_methods(),
234186af2de86aea41d7418158e68f96c1f8620e013DeLesley Hutchins                                     E = D->end_overridden_methods();
235186af2de86aea41d7418158e68f96c1f8620e013DeLesley Hutchins      if (I == E)
236186af2de86aea41d7418158e68f96c1f8620e013DeLesley Hutchins        return D;  // Method does not override anything
237186af2de86aea41d7418158e68f96c1f8620e013DeLesley Hutchins      D = *I;      // FIXME: this does not work with multiple inheritance.
238186af2de86aea41d7418158e68f96c1f8620e013DeLesley Hutchins    }
2396bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines    return nullptr;
240186af2de86aea41d7418158e68f96c1f8620e013DeLesley Hutchins  }
241186af2de86aea41d7418158e68f96c1f8620e013DeLesley Hutchins
242186af2de86aea41d7418158e68f96c1f8620e013DeLesley Hutchins  unsigned makeMCall(unsigned NumArgs, const CXXMethodDecl *D) {
243651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines    return make(EOP_MCall, NumArgs, getFirstVirtualDecl(D));
244a74b715cdc37c4523818a4018faae99d977aa537DeLesley Hutchins  }
245a74b715cdc37c4523818a4018faae99d977aa537DeLesley Hutchins
246a74b715cdc37c4523818a4018faae99d977aa537DeLesley Hutchins  unsigned makeIndex() {
247651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines    return make(EOP_Index);
248a74b715cdc37c4523818a4018faae99d977aa537DeLesley Hutchins  }
249a74b715cdc37c4523818a4018faae99d977aa537DeLesley Hutchins
250a74b715cdc37c4523818a4018faae99d977aa537DeLesley Hutchins  unsigned makeUnary() {
251651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines    return make(EOP_Unary);
252a74b715cdc37c4523818a4018faae99d977aa537DeLesley Hutchins  }
253a74b715cdc37c4523818a4018faae99d977aa537DeLesley Hutchins
254a74b715cdc37c4523818a4018faae99d977aa537DeLesley Hutchins  unsigned makeBinary() {
255651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines    return make(EOP_Binary);
256a74b715cdc37c4523818a4018faae99d977aa537DeLesley Hutchins  }
257a74b715cdc37c4523818a4018faae99d977aa537DeLesley Hutchins
258a74b715cdc37c4523818a4018faae99d977aa537DeLesley Hutchins  unsigned makeUnknown(unsigned Arity) {
259651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines    return make(EOP_Unknown, Arity);
260a74b715cdc37c4523818a4018faae99d977aa537DeLesley Hutchins  }
261a74b715cdc37c4523818a4018faae99d977aa537DeLesley Hutchins
2624444446abb50f7b0314d82be0afa892f945cc9bcBill Wendling  inline bool isCalleeArrow(const Expr *E) {
2634444446abb50f7b0314d82be0afa892f945cc9bcBill Wendling    const MemberExpr *ME = dyn_cast<MemberExpr>(E->IgnoreParenCasts());
2644444446abb50f7b0314d82be0afa892f945cc9bcBill Wendling    return ME ? ME->isArrow() : false;
2654444446abb50f7b0314d82be0afa892f945cc9bcBill Wendling  }
2664444446abb50f7b0314d82be0afa892f945cc9bcBill Wendling
267a74b715cdc37c4523818a4018faae99d977aa537DeLesley Hutchins  /// Build an SExpr from the given C++ expression.
268e0eaa8531f8fd9189710aac3b6f3aadb62bb14d1DeLesley Hutchins  /// Recursive function that terminates on DeclRefExpr.
269a74b715cdc37c4523818a4018faae99d977aa537DeLesley Hutchins  /// Note: this function merely creates a SExpr; it does not check to
270e0eaa8531f8fd9189710aac3b6f3aadb62bb14d1DeLesley Hutchins  /// ensure that the original expression is a valid mutex expression.
271a74b715cdc37c4523818a4018faae99d977aa537DeLesley Hutchins  ///
272a74b715cdc37c4523818a4018faae99d977aa537DeLesley Hutchins  /// NDeref returns the number of Derefence and AddressOf operations
273651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines  /// preceding the Expr; this is used to decide whether to pretty-print
274a74b715cdc37c4523818a4018faae99d977aa537DeLesley Hutchins  /// SExprs with . or ->.
2756bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines  unsigned buildSExpr(const Expr *Exp, CallingContext *CallCtx,
2766bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines                      int *NDeref = nullptr) {
277a74b715cdc37c4523818a4018faae99d977aa537DeLesley Hutchins    if (!Exp)
278a74b715cdc37c4523818a4018faae99d977aa537DeLesley Hutchins      return 0;
279f1ac63702143d84db778d32eb185a77fc97db5f5DeLesley Hutchins
28047715cc201170952029a52806bcc26f69c38272dDeLesley Hutchins    if (const DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(Exp)) {
28147715cc201170952029a52806bcc26f69c38272dDeLesley Hutchins      const NamedDecl *ND = cast<NamedDecl>(DRE->getDecl()->getCanonicalDecl());
28247715cc201170952029a52806bcc26f69c38272dDeLesley Hutchins      const ParmVarDecl *PV = dyn_cast_or_null<ParmVarDecl>(ND);
283e03b2b3ca9032b18fd1c3d0fca7692e4d2551277DeLesley Hutchins      if (PV) {
28447715cc201170952029a52806bcc26f69c38272dDeLesley Hutchins        const FunctionDecl *FD =
285e03b2b3ca9032b18fd1c3d0fca7692e4d2551277DeLesley Hutchins          cast<FunctionDecl>(PV->getDeclContext())->getCanonicalDecl();
286e03b2b3ca9032b18fd1c3d0fca7692e4d2551277DeLesley Hutchins        unsigned i = PV->getFunctionScopeIndex();
287e03b2b3ca9032b18fd1c3d0fca7692e4d2551277DeLesley Hutchins
288f63797c741e646b9482d204c88dee02fb41d7962DeLesley Hutchins        if (CallCtx && CallCtx->FunArgs &&
289f63797c741e646b9482d204c88dee02fb41d7962DeLesley Hutchins            FD == CallCtx->AttrDecl->getCanonicalDecl()) {
290e03b2b3ca9032b18fd1c3d0fca7692e4d2551277DeLesley Hutchins          // Substitute call arguments for references to function parameters
291f63797c741e646b9482d204c88dee02fb41d7962DeLesley Hutchins          assert(i < CallCtx->NumArgs);
292a74b715cdc37c4523818a4018faae99d977aa537DeLesley Hutchins          return buildSExpr(CallCtx->FunArgs[i], CallCtx->PrevCtx, NDeref);
2938121639910129a2b59aa85fc597e47cacad8b978DeLesley Hutchins        }
294e03b2b3ca9032b18fd1c3d0fca7692e4d2551277DeLesley Hutchins        // Map the param back to the param of the original function declaration.
295a74b715cdc37c4523818a4018faae99d977aa537DeLesley Hutchins        makeNamedVar(FD->getParamDecl(i));
296a74b715cdc37c4523818a4018faae99d977aa537DeLesley Hutchins        return 1;
2978121639910129a2b59aa85fc597e47cacad8b978DeLesley Hutchins      }
298e03b2b3ca9032b18fd1c3d0fca7692e4d2551277DeLesley Hutchins      // Not a function parameter -- just store the reference.
299a74b715cdc37c4523818a4018faae99d977aa537DeLesley Hutchins      makeNamedVar(ND);
300a74b715cdc37c4523818a4018faae99d977aa537DeLesley Hutchins      return 1;
301402aa0698fec81e574818a0a6c2000fac0b2c4c6Caitlin Sadowski    } else if (isa<CXXThisExpr>(Exp)) {
302f63797c741e646b9482d204c88dee02fb41d7962DeLesley Hutchins      // Substitute parent for 'this'
303a74b715cdc37c4523818a4018faae99d977aa537DeLesley Hutchins      if (CallCtx && CallCtx->SelfArg) {
304a74b715cdc37c4523818a4018faae99d977aa537DeLesley Hutchins        if (!CallCtx->SelfArrow && NDeref)
305a74b715cdc37c4523818a4018faae99d977aa537DeLesley Hutchins          // 'this' is a pointer, but self is not, so need to take address.
306a74b715cdc37c4523818a4018faae99d977aa537DeLesley Hutchins          --(*NDeref);
307a74b715cdc37c4523818a4018faae99d977aa537DeLesley Hutchins        return buildSExpr(CallCtx->SelfArg, CallCtx->PrevCtx, NDeref);
308a74b715cdc37c4523818a4018faae99d977aa537DeLesley Hutchins      }
3094bda3eca138d39585c9e475ad25aa9ff053f923bDeLesley Hutchins      else {
310a74b715cdc37c4523818a4018faae99d977aa537DeLesley Hutchins        makeThis();
311a74b715cdc37c4523818a4018faae99d977aa537DeLesley Hutchins        return 1;
3124bda3eca138d39585c9e475ad25aa9ff053f923bDeLesley Hutchins      }
31347715cc201170952029a52806bcc26f69c38272dDeLesley Hutchins    } else if (const MemberExpr *ME = dyn_cast<MemberExpr>(Exp)) {
31447715cc201170952029a52806bcc26f69c38272dDeLesley Hutchins      const NamedDecl *ND = ME->getMemberDecl();
315a74b715cdc37c4523818a4018faae99d977aa537DeLesley Hutchins      int ImplicitDeref = ME->isArrow() ? 1 : 0;
316a74b715cdc37c4523818a4018faae99d977aa537DeLesley Hutchins      unsigned Root = makeDot(ND, false);
317a74b715cdc37c4523818a4018faae99d977aa537DeLesley Hutchins      unsigned Sz = buildSExpr(ME->getBase(), CallCtx, &ImplicitDeref);
318a74b715cdc37c4523818a4018faae99d977aa537DeLesley Hutchins      NodeVec[Root].setArrow(ImplicitDeref > 0);
319a74b715cdc37c4523818a4018faae99d977aa537DeLesley Hutchins      NodeVec[Root].setSize(Sz + 1);
320a74b715cdc37c4523818a4018faae99d977aa537DeLesley Hutchins      return Sz + 1;
32147715cc201170952029a52806bcc26f69c38272dDeLesley Hutchins    } else if (const CXXMemberCallExpr *CMCE = dyn_cast<CXXMemberCallExpr>(Exp)) {
322f63797c741e646b9482d204c88dee02fb41d7962DeLesley Hutchins      // When calling a function with a lock_returned attribute, replace
323f63797c741e646b9482d204c88dee02fb41d7962DeLesley Hutchins      // the function call with the expression in lock_returned.
32487bcee88d9b49de8214aa23d07c96f7bec3198e0Rafael Espindola      const CXXMethodDecl *MD = CMCE->getMethodDecl()->getMostRecentDecl();
3255408153e9140f34bbca9059638c61cc12bd539cfDeLesley Hutchins      if (LockReturnedAttr* At = MD->getAttr<LockReturnedAttr>()) {
326f63797c741e646b9482d204c88dee02fb41d7962DeLesley Hutchins        CallingContext LRCallCtx(CMCE->getMethodDecl());
327f63797c741e646b9482d204c88dee02fb41d7962DeLesley Hutchins        LRCallCtx.SelfArg = CMCE->getImplicitObjectArgument();
3284444446abb50f7b0314d82be0afa892f945cc9bcBill Wendling        LRCallCtx.SelfArrow = isCalleeArrow(CMCE->getCallee());
329f63797c741e646b9482d204c88dee02fb41d7962DeLesley Hutchins        LRCallCtx.NumArgs = CMCE->getNumArgs();
330f63797c741e646b9482d204c88dee02fb41d7962DeLesley Hutchins        LRCallCtx.FunArgs = CMCE->getArgs();
331f63797c741e646b9482d204c88dee02fb41d7962DeLesley Hutchins        LRCallCtx.PrevCtx = CallCtx;
332a74b715cdc37c4523818a4018faae99d977aa537DeLesley Hutchins        return buildSExpr(At->getArg(), &LRCallCtx);
333f63797c741e646b9482d204c88dee02fb41d7962DeLesley Hutchins      }
33496fac6a7fe89deff7860e536febbd4ae17bb57f3DeLesley Hutchins      // Hack to treat smart pointers and iterators as pointers;
33596fac6a7fe89deff7860e536febbd4ae17bb57f3DeLesley Hutchins      // ignore any method named get().
33696fac6a7fe89deff7860e536febbd4ae17bb57f3DeLesley Hutchins      if (CMCE->getMethodDecl()->getNameAsString() == "get" &&
33796fac6a7fe89deff7860e536febbd4ae17bb57f3DeLesley Hutchins          CMCE->getNumArgs() == 0) {
3384444446abb50f7b0314d82be0afa892f945cc9bcBill Wendling        if (NDeref && isCalleeArrow(CMCE->getCallee()))
339a74b715cdc37c4523818a4018faae99d977aa537DeLesley Hutchins          ++(*NDeref);
340a74b715cdc37c4523818a4018faae99d977aa537DeLesley Hutchins        return buildSExpr(CMCE->getImplicitObjectArgument(), CallCtx, NDeref);
34196fac6a7fe89deff7860e536febbd4ae17bb57f3DeLesley Hutchins      }
3420d95dfcc0e07a81596ab7c3e9e86ab663fd4541cDeLesley Hutchins      unsigned NumCallArgs = CMCE->getNumArgs();
343186af2de86aea41d7418158e68f96c1f8620e013DeLesley Hutchins      unsigned Root = makeMCall(NumCallArgs, CMCE->getMethodDecl());
344a74b715cdc37c4523818a4018faae99d977aa537DeLesley Hutchins      unsigned Sz = buildSExpr(CMCE->getImplicitObjectArgument(), CallCtx);
34547715cc201170952029a52806bcc26f69c38272dDeLesley Hutchins      const Expr* const* CallArgs = CMCE->getArgs();
3460d95dfcc0e07a81596ab7c3e9e86ab663fd4541cDeLesley Hutchins      for (unsigned i = 0; i < NumCallArgs; ++i) {
347a74b715cdc37c4523818a4018faae99d977aa537DeLesley Hutchins        Sz += buildSExpr(CallArgs[i], CallCtx);
3480d95dfcc0e07a81596ab7c3e9e86ab663fd4541cDeLesley Hutchins      }
349a74b715cdc37c4523818a4018faae99d977aa537DeLesley Hutchins      NodeVec[Root].setSize(Sz + 1);
350a74b715cdc37c4523818a4018faae99d977aa537DeLesley Hutchins      return Sz + 1;
35147715cc201170952029a52806bcc26f69c38272dDeLesley Hutchins    } else if (const CallExpr *CE = dyn_cast<CallExpr>(Exp)) {
35287bcee88d9b49de8214aa23d07c96f7bec3198e0Rafael Espindola      const FunctionDecl *FD = CE->getDirectCallee()->getMostRecentDecl();
3535408153e9140f34bbca9059638c61cc12bd539cfDeLesley Hutchins      if (LockReturnedAttr* At = FD->getAttr<LockReturnedAttr>()) {
354f63797c741e646b9482d204c88dee02fb41d7962DeLesley Hutchins        CallingContext LRCallCtx(CE->getDirectCallee());
355f63797c741e646b9482d204c88dee02fb41d7962DeLesley Hutchins        LRCallCtx.NumArgs = CE->getNumArgs();
356f63797c741e646b9482d204c88dee02fb41d7962DeLesley Hutchins        LRCallCtx.FunArgs = CE->getArgs();
357f63797c741e646b9482d204c88dee02fb41d7962DeLesley Hutchins        LRCallCtx.PrevCtx = CallCtx;
358a74b715cdc37c4523818a4018faae99d977aa537DeLesley Hutchins        return buildSExpr(At->getArg(), &LRCallCtx);
359f63797c741e646b9482d204c88dee02fb41d7962DeLesley Hutchins      }
36096fac6a7fe89deff7860e536febbd4ae17bb57f3DeLesley Hutchins      // Treat smart pointers and iterators as pointers;
36196fac6a7fe89deff7860e536febbd4ae17bb57f3DeLesley Hutchins      // ignore the * and -> operators.
36247715cc201170952029a52806bcc26f69c38272dDeLesley Hutchins      if (const CXXOperatorCallExpr *OE = dyn_cast<CXXOperatorCallExpr>(CE)) {
36396fac6a7fe89deff7860e536febbd4ae17bb57f3DeLesley Hutchins        OverloadedOperatorKind k = OE->getOperator();
364a74b715cdc37c4523818a4018faae99d977aa537DeLesley Hutchins        if (k == OO_Star) {
365a74b715cdc37c4523818a4018faae99d977aa537DeLesley Hutchins          if (NDeref) ++(*NDeref);
366a74b715cdc37c4523818a4018faae99d977aa537DeLesley Hutchins          return buildSExpr(OE->getArg(0), CallCtx, NDeref);
367a74b715cdc37c4523818a4018faae99d977aa537DeLesley Hutchins        }
368a74b715cdc37c4523818a4018faae99d977aa537DeLesley Hutchins        else if (k == OO_Arrow) {
369a74b715cdc37c4523818a4018faae99d977aa537DeLesley Hutchins          return buildSExpr(OE->getArg(0), CallCtx, NDeref);
37096fac6a7fe89deff7860e536febbd4ae17bb57f3DeLesley Hutchins        }
37196fac6a7fe89deff7860e536febbd4ae17bb57f3DeLesley Hutchins      }
3720d95dfcc0e07a81596ab7c3e9e86ab663fd4541cDeLesley Hutchins      unsigned NumCallArgs = CE->getNumArgs();
3736bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines      unsigned Root = makeCall(NumCallArgs, nullptr);
374a74b715cdc37c4523818a4018faae99d977aa537DeLesley Hutchins      unsigned Sz = buildSExpr(CE->getCallee(), CallCtx);
37547715cc201170952029a52806bcc26f69c38272dDeLesley Hutchins      const Expr* const* CallArgs = CE->getArgs();
3760d95dfcc0e07a81596ab7c3e9e86ab663fd4541cDeLesley Hutchins      for (unsigned i = 0; i < NumCallArgs; ++i) {
377a74b715cdc37c4523818a4018faae99d977aa537DeLesley Hutchins        Sz += buildSExpr(CallArgs[i], CallCtx);
3780d95dfcc0e07a81596ab7c3e9e86ab663fd4541cDeLesley Hutchins      }
379a74b715cdc37c4523818a4018faae99d977aa537DeLesley Hutchins      NodeVec[Root].setSize(Sz+1);
380a74b715cdc37c4523818a4018faae99d977aa537DeLesley Hutchins      return Sz+1;
38147715cc201170952029a52806bcc26f69c38272dDeLesley Hutchins    } else if (const BinaryOperator *BOE = dyn_cast<BinaryOperator>(Exp)) {
382a74b715cdc37c4523818a4018faae99d977aa537DeLesley Hutchins      unsigned Root = makeBinary();
383a74b715cdc37c4523818a4018faae99d977aa537DeLesley Hutchins      unsigned Sz = buildSExpr(BOE->getLHS(), CallCtx);
384a74b715cdc37c4523818a4018faae99d977aa537DeLesley Hutchins      Sz += buildSExpr(BOE->getRHS(), CallCtx);
385a74b715cdc37c4523818a4018faae99d977aa537DeLesley Hutchins      NodeVec[Root].setSize(Sz);
386a74b715cdc37c4523818a4018faae99d977aa537DeLesley Hutchins      return Sz;
38747715cc201170952029a52806bcc26f69c38272dDeLesley Hutchins    } else if (const UnaryOperator *UOE = dyn_cast<UnaryOperator>(Exp)) {
388a74b715cdc37c4523818a4018faae99d977aa537DeLesley Hutchins      // Ignore & and * operators -- they're no-ops.
389a74b715cdc37c4523818a4018faae99d977aa537DeLesley Hutchins      // However, we try to figure out whether the expression is a pointer,
390a74b715cdc37c4523818a4018faae99d977aa537DeLesley Hutchins      // so we can use . and -> appropriately in error messages.
391a74b715cdc37c4523818a4018faae99d977aa537DeLesley Hutchins      if (UOE->getOpcode() == UO_Deref) {
392a74b715cdc37c4523818a4018faae99d977aa537DeLesley Hutchins        if (NDeref) ++(*NDeref);
393a74b715cdc37c4523818a4018faae99d977aa537DeLesley Hutchins        return buildSExpr(UOE->getSubExpr(), CallCtx, NDeref);
394a74b715cdc37c4523818a4018faae99d977aa537DeLesley Hutchins      }
395a74b715cdc37c4523818a4018faae99d977aa537DeLesley Hutchins      if (UOE->getOpcode() == UO_AddrOf) {
396ee2f032fe0fc86762608458c2a167ae504579a64DeLesley Hutchins        if (DeclRefExpr* DRE = dyn_cast<DeclRefExpr>(UOE->getSubExpr())) {
397ee2f032fe0fc86762608458c2a167ae504579a64DeLesley Hutchins          if (DRE->getDecl()->isCXXInstanceMember()) {
398ee2f032fe0fc86762608458c2a167ae504579a64DeLesley Hutchins            // This is a pointer-to-member expression, e.g. &MyClass::mu_.
399ee2f032fe0fc86762608458c2a167ae504579a64DeLesley Hutchins            // We interpret this syntax specially, as a wildcard.
400ee2f032fe0fc86762608458c2a167ae504579a64DeLesley Hutchins            unsigned Root = makeDot(DRE->getDecl(), false);
401ee2f032fe0fc86762608458c2a167ae504579a64DeLesley Hutchins            makeWildcard();
402ee2f032fe0fc86762608458c2a167ae504579a64DeLesley Hutchins            NodeVec[Root].setSize(2);
403ee2f032fe0fc86762608458c2a167ae504579a64DeLesley Hutchins            return 2;
404ee2f032fe0fc86762608458c2a167ae504579a64DeLesley Hutchins          }
405ee2f032fe0fc86762608458c2a167ae504579a64DeLesley Hutchins        }
406a74b715cdc37c4523818a4018faae99d977aa537DeLesley Hutchins        if (NDeref) --(*NDeref);
407a74b715cdc37c4523818a4018faae99d977aa537DeLesley Hutchins        return buildSExpr(UOE->getSubExpr(), CallCtx, NDeref);
408a74b715cdc37c4523818a4018faae99d977aa537DeLesley Hutchins      }
409a74b715cdc37c4523818a4018faae99d977aa537DeLesley Hutchins      unsigned Root = makeUnary();
410a74b715cdc37c4523818a4018faae99d977aa537DeLesley Hutchins      unsigned Sz = buildSExpr(UOE->getSubExpr(), CallCtx);
411a74b715cdc37c4523818a4018faae99d977aa537DeLesley Hutchins      NodeVec[Root].setSize(Sz);
412a74b715cdc37c4523818a4018faae99d977aa537DeLesley Hutchins      return Sz;
41347715cc201170952029a52806bcc26f69c38272dDeLesley Hutchins    } else if (const ArraySubscriptExpr *ASE =
41447715cc201170952029a52806bcc26f69c38272dDeLesley Hutchins               dyn_cast<ArraySubscriptExpr>(Exp)) {
415a74b715cdc37c4523818a4018faae99d977aa537DeLesley Hutchins      unsigned Root = makeIndex();
416a74b715cdc37c4523818a4018faae99d977aa537DeLesley Hutchins      unsigned Sz = buildSExpr(ASE->getBase(), CallCtx);
417a74b715cdc37c4523818a4018faae99d977aa537DeLesley Hutchins      Sz += buildSExpr(ASE->getIdx(), CallCtx);
418a74b715cdc37c4523818a4018faae99d977aa537DeLesley Hutchins      NodeVec[Root].setSize(Sz);
419a74b715cdc37c4523818a4018faae99d977aa537DeLesley Hutchins      return Sz;
42047715cc201170952029a52806bcc26f69c38272dDeLesley Hutchins    } else if (const AbstractConditionalOperator *CE =
421a74b715cdc37c4523818a4018faae99d977aa537DeLesley Hutchins               dyn_cast<AbstractConditionalOperator>(Exp)) {
422a74b715cdc37c4523818a4018faae99d977aa537DeLesley Hutchins      unsigned Root = makeUnknown(3);
423a74b715cdc37c4523818a4018faae99d977aa537DeLesley Hutchins      unsigned Sz = buildSExpr(CE->getCond(), CallCtx);
424a74b715cdc37c4523818a4018faae99d977aa537DeLesley Hutchins      Sz += buildSExpr(CE->getTrueExpr(), CallCtx);
425a74b715cdc37c4523818a4018faae99d977aa537DeLesley Hutchins      Sz += buildSExpr(CE->getFalseExpr(), CallCtx);
426a74b715cdc37c4523818a4018faae99d977aa537DeLesley Hutchins      NodeVec[Root].setSize(Sz);
427a74b715cdc37c4523818a4018faae99d977aa537DeLesley Hutchins      return Sz;
42847715cc201170952029a52806bcc26f69c38272dDeLesley Hutchins    } else if (const ChooseExpr *CE = dyn_cast<ChooseExpr>(Exp)) {
429a74b715cdc37c4523818a4018faae99d977aa537DeLesley Hutchins      unsigned Root = makeUnknown(3);
430a74b715cdc37c4523818a4018faae99d977aa537DeLesley Hutchins      unsigned Sz = buildSExpr(CE->getCond(), CallCtx);
431a74b715cdc37c4523818a4018faae99d977aa537DeLesley Hutchins      Sz += buildSExpr(CE->getLHS(), CallCtx);
432a74b715cdc37c4523818a4018faae99d977aa537DeLesley Hutchins      Sz += buildSExpr(CE->getRHS(), CallCtx);
433a74b715cdc37c4523818a4018faae99d977aa537DeLesley Hutchins      NodeVec[Root].setSize(Sz);
434a74b715cdc37c4523818a4018faae99d977aa537DeLesley Hutchins      return Sz;
43547715cc201170952029a52806bcc26f69c38272dDeLesley Hutchins    } else if (const CastExpr *CE = dyn_cast<CastExpr>(Exp)) {
436a74b715cdc37c4523818a4018faae99d977aa537DeLesley Hutchins      return buildSExpr(CE->getSubExpr(), CallCtx, NDeref);
43747715cc201170952029a52806bcc26f69c38272dDeLesley Hutchins    } else if (const ParenExpr *PE = dyn_cast<ParenExpr>(Exp)) {
438a74b715cdc37c4523818a4018faae99d977aa537DeLesley Hutchins      return buildSExpr(PE->getSubExpr(), CallCtx, NDeref);
43947715cc201170952029a52806bcc26f69c38272dDeLesley Hutchins    } else if (const ExprWithCleanups *EWC = dyn_cast<ExprWithCleanups>(Exp)) {
440a74b715cdc37c4523818a4018faae99d977aa537DeLesley Hutchins      return buildSExpr(EWC->getSubExpr(), CallCtx, NDeref);
44147715cc201170952029a52806bcc26f69c38272dDeLesley Hutchins    } else if (const CXXBindTemporaryExpr *E = dyn_cast<CXXBindTemporaryExpr>(Exp)) {
442a74b715cdc37c4523818a4018faae99d977aa537DeLesley Hutchins      return buildSExpr(E->getSubExpr(), CallCtx, NDeref);
4430d95dfcc0e07a81596ab7c3e9e86ab663fd4541cDeLesley Hutchins    } else if (isa<CharacterLiteral>(Exp) ||
4449d6e7f3e12f1a825377ace33161e80caeda8cd06DeLesley Hutchins               isa<CXXNullPtrLiteralExpr>(Exp) ||
4459d6e7f3e12f1a825377ace33161e80caeda8cd06DeLesley Hutchins               isa<GNUNullExpr>(Exp) ||
4469d6e7f3e12f1a825377ace33161e80caeda8cd06DeLesley Hutchins               isa<CXXBoolLiteralExpr>(Exp) ||
4479d6e7f3e12f1a825377ace33161e80caeda8cd06DeLesley Hutchins               isa<FloatingLiteral>(Exp) ||
4489d6e7f3e12f1a825377ace33161e80caeda8cd06DeLesley Hutchins               isa<ImaginaryLiteral>(Exp) ||
4499d6e7f3e12f1a825377ace33161e80caeda8cd06DeLesley Hutchins               isa<IntegerLiteral>(Exp) ||
4509d6e7f3e12f1a825377ace33161e80caeda8cd06DeLesley Hutchins               isa<StringLiteral>(Exp) ||
4519d6e7f3e12f1a825377ace33161e80caeda8cd06DeLesley Hutchins               isa<ObjCStringLiteral>(Exp)) {
452a74b715cdc37c4523818a4018faae99d977aa537DeLesley Hutchins      makeNop();
453a74b715cdc37c4523818a4018faae99d977aa537DeLesley Hutchins      return 1;  // FIXME: Ignore literals for now
4540d95dfcc0e07a81596ab7c3e9e86ab663fd4541cDeLesley Hutchins    } else {
455a74b715cdc37c4523818a4018faae99d977aa537DeLesley Hutchins      makeNop();
456a74b715cdc37c4523818a4018faae99d977aa537DeLesley Hutchins      return 1;  // Ignore.  FIXME: mark as invalid expression?
4570d95dfcc0e07a81596ab7c3e9e86ab663fd4541cDeLesley Hutchins    }
4589f80a97408ee0da939654d851ff42ad07d47e9c7DeLesley Hutchins  }
4599f80a97408ee0da939654d851ff42ad07d47e9c7DeLesley Hutchins
460a74b715cdc37c4523818a4018faae99d977aa537DeLesley Hutchins  /// \brief Construct a SExpr from an expression.
4619f80a97408ee0da939654d851ff42ad07d47e9c7DeLesley Hutchins  /// \param MutexExp The original mutex expression within an attribute
4629f80a97408ee0da939654d851ff42ad07d47e9c7DeLesley Hutchins  /// \param DeclExp An expression involving the Decl on which the attribute
4639f80a97408ee0da939654d851ff42ad07d47e9c7DeLesley Hutchins  ///        occurs.
4649f80a97408ee0da939654d851ff42ad07d47e9c7DeLesley Hutchins  /// \param D  The declaration to which the lock/unlock attribute is attached.
46547715cc201170952029a52806bcc26f69c38272dDeLesley Hutchins  void buildSExprFromExpr(const Expr *MutexExp, const Expr *DeclExp,
4666bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines                          const NamedDecl *D, VarDecl *SelfDecl = nullptr) {
467f63797c741e646b9482d204c88dee02fb41d7962DeLesley Hutchins    CallingContext CallCtx(D);
4689f80a97408ee0da939654d851ff42ad07d47e9c7DeLesley Hutchins
4690b4db3e08a201c35f0011489bd5cd5d39bbe54fbDeLesley Hutchins    if (MutexExp) {
47047715cc201170952029a52806bcc26f69c38272dDeLesley Hutchins      if (const StringLiteral* SLit = dyn_cast<StringLiteral>(MutexExp)) {
4710b4db3e08a201c35f0011489bd5cd5d39bbe54fbDeLesley Hutchins        if (SLit->getString() == StringRef("*"))
4720b4db3e08a201c35f0011489bd5cd5d39bbe54fbDeLesley Hutchins          // The "*" expr is a universal lock, which essentially turns off
4730b4db3e08a201c35f0011489bd5cd5d39bbe54fbDeLesley Hutchins          // checks until it is removed from the lockset.
4740b4db3e08a201c35f0011489bd5cd5d39bbe54fbDeLesley Hutchins          makeUniversal();
4750b4db3e08a201c35f0011489bd5cd5d39bbe54fbDeLesley Hutchins        else
4760b4db3e08a201c35f0011489bd5cd5d39bbe54fbDeLesley Hutchins          // Ignore other string literals for now.
4770b4db3e08a201c35f0011489bd5cd5d39bbe54fbDeLesley Hutchins          makeNop();
4780b4db3e08a201c35f0011489bd5cd5d39bbe54fbDeLesley Hutchins        return;
4790b4db3e08a201c35f0011489bd5cd5d39bbe54fbDeLesley Hutchins      }
4804e4c15765d5f097e21dcaa30f1a94481924340f7DeLesley Hutchins    }
4814e4c15765d5f097e21dcaa30f1a94481924340f7DeLesley Hutchins
482f1ac63702143d84db778d32eb185a77fc97db5f5DeLesley Hutchins    // If we are processing a raw attribute expression, with no substitutions.
4836bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines    if (!DeclExp) {
4846bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines      buildSExpr(MutexExp, nullptr);
4859f80a97408ee0da939654d851ff42ad07d47e9c7DeLesley Hutchins      return;
4869f80a97408ee0da939654d851ff42ad07d47e9c7DeLesley Hutchins    }
4879f80a97408ee0da939654d851ff42ad07d47e9c7DeLesley Hutchins
488f63797c741e646b9482d204c88dee02fb41d7962DeLesley Hutchins    // Examine DeclExp to find SelfArg and FunArgs, which are used to substitute
489e0eaa8531f8fd9189710aac3b6f3aadb62bb14d1DeLesley Hutchins    // for formal parameters when we call buildMutexID later.
49047715cc201170952029a52806bcc26f69c38272dDeLesley Hutchins    if (const MemberExpr *ME = dyn_cast<MemberExpr>(DeclExp)) {
491a74b715cdc37c4523818a4018faae99d977aa537DeLesley Hutchins      CallCtx.SelfArg   = ME->getBase();
492a74b715cdc37c4523818a4018faae99d977aa537DeLesley Hutchins      CallCtx.SelfArrow = ME->isArrow();
49347715cc201170952029a52806bcc26f69c38272dDeLesley Hutchins    } else if (const CXXMemberCallExpr *CE =
49447715cc201170952029a52806bcc26f69c38272dDeLesley Hutchins               dyn_cast<CXXMemberCallExpr>(DeclExp)) {
495a74b715cdc37c4523818a4018faae99d977aa537DeLesley Hutchins      CallCtx.SelfArg   = CE->getImplicitObjectArgument();
4964444446abb50f7b0314d82be0afa892f945cc9bcBill Wendling      CallCtx.SelfArrow = isCalleeArrow(CE->getCallee());
497a74b715cdc37c4523818a4018faae99d977aa537DeLesley Hutchins      CallCtx.NumArgs   = CE->getNumArgs();
498a74b715cdc37c4523818a4018faae99d977aa537DeLesley Hutchins      CallCtx.FunArgs   = CE->getArgs();
4994444446abb50f7b0314d82be0afa892f945cc9bcBill Wendling    } else if (const CallExpr *CE = dyn_cast<CallExpr>(DeclExp)) {
500f63797c741e646b9482d204c88dee02fb41d7962DeLesley Hutchins      CallCtx.NumArgs = CE->getNumArgs();
501f63797c741e646b9482d204c88dee02fb41d7962DeLesley Hutchins      CallCtx.FunArgs = CE->getArgs();
50247715cc201170952029a52806bcc26f69c38272dDeLesley Hutchins    } else if (const CXXConstructExpr *CE =
50347715cc201170952029a52806bcc26f69c38272dDeLesley Hutchins               dyn_cast<CXXConstructExpr>(DeclExp)) {
5046bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines      CallCtx.SelfArg = nullptr;  // Will be set below
505f63797c741e646b9482d204c88dee02fb41d7962DeLesley Hutchins      CallCtx.NumArgs = CE->getNumArgs();
506f63797c741e646b9482d204c88dee02fb41d7962DeLesley Hutchins      CallCtx.FunArgs = CE->getArgs();
5076db51f707e93816364039a2a904d13d3968c7f05DeLesley Hutchins    } else if (D && isa<CXXDestructorDecl>(D)) {
5086db51f707e93816364039a2a904d13d3968c7f05DeLesley Hutchins      // There's no such thing as a "destructor call" in the AST.
509f63797c741e646b9482d204c88dee02fb41d7962DeLesley Hutchins      CallCtx.SelfArg = DeclExp;
5108121639910129a2b59aa85fc597e47cacad8b978DeLesley Hutchins    }
5119f80a97408ee0da939654d851ff42ad07d47e9c7DeLesley Hutchins
512ef2388b10c41a9696d5d81f42ca79ff005fef7fcDeLesley Hutchins    // Hack to handle constructors, where self cannot be recovered from
513ef2388b10c41a9696d5d81f42ca79ff005fef7fcDeLesley Hutchins    // the expression.
514ef2388b10c41a9696d5d81f42ca79ff005fef7fcDeLesley Hutchins    if (SelfDecl && !CallCtx.SelfArg) {
515ef2388b10c41a9696d5d81f42ca79ff005fef7fcDeLesley Hutchins      DeclRefExpr SelfDRE(SelfDecl, false, SelfDecl->getType(), VK_LValue,
516ef2388b10c41a9696d5d81f42ca79ff005fef7fcDeLesley Hutchins                          SelfDecl->getLocation());
517ef2388b10c41a9696d5d81f42ca79ff005fef7fcDeLesley Hutchins      CallCtx.SelfArg = &SelfDRE;
518ef2388b10c41a9696d5d81f42ca79ff005fef7fcDeLesley Hutchins
519ef2388b10c41a9696d5d81f42ca79ff005fef7fcDeLesley Hutchins      // If the attribute has no arguments, then assume the argument is "this".
5206bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines      if (!MutexExp)
5216bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines        buildSExpr(CallCtx.SelfArg, nullptr);
522ef2388b10c41a9696d5d81f42ca79ff005fef7fcDeLesley Hutchins      else  // For most attributes.
523ef2388b10c41a9696d5d81f42ca79ff005fef7fcDeLesley Hutchins        buildSExpr(MutexExp, &CallCtx);
5249f80a97408ee0da939654d851ff42ad07d47e9c7DeLesley Hutchins      return;
5259f80a97408ee0da939654d851ff42ad07d47e9c7DeLesley Hutchins    }
5268121639910129a2b59aa85fc597e47cacad8b978DeLesley Hutchins
527ef2388b10c41a9696d5d81f42ca79ff005fef7fcDeLesley Hutchins    // If the attribute has no arguments, then assume the argument is "this".
5286bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines    if (!MutexExp)
5296bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines      buildSExpr(CallCtx.SelfArg, nullptr);
530ef2388b10c41a9696d5d81f42ca79ff005fef7fcDeLesley Hutchins    else  // For most attributes.
531ef2388b10c41a9696d5d81f42ca79ff005fef7fcDeLesley Hutchins      buildSExpr(MutexExp, &CallCtx);
532402aa0698fec81e574818a0a6c2000fac0b2c4c6Caitlin Sadowski  }
533402aa0698fec81e574818a0a6c2000fac0b2c4c6Caitlin Sadowski
534ee2f032fe0fc86762608458c2a167ae504579a64DeLesley Hutchins  /// \brief Get index of next sibling of node i.
535ee2f032fe0fc86762608458c2a167ae504579a64DeLesley Hutchins  unsigned getNextSibling(unsigned i) const {
536ee2f032fe0fc86762608458c2a167ae504579a64DeLesley Hutchins    return i + NodeVec[i].size();
537ee2f032fe0fc86762608458c2a167ae504579a64DeLesley Hutchins  }
538ee2f032fe0fc86762608458c2a167ae504579a64DeLesley Hutchins
539402aa0698fec81e574818a0a6c2000fac0b2c4c6Caitlin Sadowskipublic:
540a74b715cdc37c4523818a4018faae99d977aa537DeLesley Hutchins  explicit SExpr(clang::Decl::EmptyShell e) { NodeVec.clear(); }
5411fa3c0682a52c45c4ad0be3a82d0c85f26657072DeLesley Hutchins
5429f80a97408ee0da939654d851ff42ad07d47e9c7DeLesley Hutchins  /// \param MutexExp The original mutex expression within an attribute
5439f80a97408ee0da939654d851ff42ad07d47e9c7DeLesley Hutchins  /// \param DeclExp An expression involving the Decl on which the attribute
5449f80a97408ee0da939654d851ff42ad07d47e9c7DeLesley Hutchins  ///        occurs.
5459f80a97408ee0da939654d851ff42ad07d47e9c7DeLesley Hutchins  /// \param D  The declaration to which the lock/unlock attribute is attached.
5469f80a97408ee0da939654d851ff42ad07d47e9c7DeLesley Hutchins  /// Caller must check isValid() after construction.
5476bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines  SExpr(const Expr *MutexExp, const Expr *DeclExp, const NamedDecl *D,
5486bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines        VarDecl *SelfDecl = nullptr) {
549ef2388b10c41a9696d5d81f42ca79ff005fef7fcDeLesley Hutchins    buildSExprFromExpr(MutexExp, DeclExp, D, SelfDecl);
550194418f1db5f5f78bc3e614d1e10a863455d882cCaitlin Sadowski  }
551194418f1db5f5f78bc3e614d1e10a863455d882cCaitlin Sadowski
5529f80a97408ee0da939654d851ff42ad07d47e9c7DeLesley Hutchins  /// Return true if this is a valid decl sequence.
5539f80a97408ee0da939654d851ff42ad07d47e9c7DeLesley Hutchins  /// Caller must call this by hand after construction to handle errors.
554194418f1db5f5f78bc3e614d1e10a863455d882cCaitlin Sadowski  bool isValid() const {
555a74b715cdc37c4523818a4018faae99d977aa537DeLesley Hutchins    return !NodeVec.empty();
556402aa0698fec81e574818a0a6c2000fac0b2c4c6Caitlin Sadowski  }
557402aa0698fec81e574818a0a6c2000fac0b2c4c6Caitlin Sadowski
5584e4c15765d5f097e21dcaa30f1a94481924340f7DeLesley Hutchins  bool shouldIgnore() const {
5594e4c15765d5f097e21dcaa30f1a94481924340f7DeLesley Hutchins    // Nop is a mutex that we have decided to deliberately ignore.
5604e4c15765d5f097e21dcaa30f1a94481924340f7DeLesley Hutchins    assert(NodeVec.size() > 0 && "Invalid Mutex");
5614e4c15765d5f097e21dcaa30f1a94481924340f7DeLesley Hutchins    return NodeVec[0].kind() == EOP_Nop;
5624e4c15765d5f097e21dcaa30f1a94481924340f7DeLesley Hutchins  }
5634e4c15765d5f097e21dcaa30f1a94481924340f7DeLesley Hutchins
5640b4db3e08a201c35f0011489bd5cd5d39bbe54fbDeLesley Hutchins  bool isUniversal() const {
5650b4db3e08a201c35f0011489bd5cd5d39bbe54fbDeLesley Hutchins    assert(NodeVec.size() > 0 && "Invalid Mutex");
5660b4db3e08a201c35f0011489bd5cd5d39bbe54fbDeLesley Hutchins    return NodeVec[0].kind() == EOP_Universal;
5670b4db3e08a201c35f0011489bd5cd5d39bbe54fbDeLesley Hutchins  }
5680b4db3e08a201c35f0011489bd5cd5d39bbe54fbDeLesley Hutchins
569f1ac63702143d84db778d32eb185a77fc97db5f5DeLesley Hutchins  /// Issue a warning about an invalid lock expression
57047715cc201170952029a52806bcc26f69c38272dDeLesley Hutchins  static void warnInvalidLock(ThreadSafetyHandler &Handler,
571651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines                              const Expr *MutexExp, const Expr *DeclExp,
572651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines                              const NamedDecl *D, StringRef Kind) {
573f1ac63702143d84db778d32eb185a77fc97db5f5DeLesley Hutchins    SourceLocation Loc;
574f1ac63702143d84db778d32eb185a77fc97db5f5DeLesley Hutchins    if (DeclExp)
575f1ac63702143d84db778d32eb185a77fc97db5f5DeLesley Hutchins      Loc = DeclExp->getExprLoc();
576f1ac63702143d84db778d32eb185a77fc97db5f5DeLesley Hutchins
577f1ac63702143d84db778d32eb185a77fc97db5f5DeLesley Hutchins    // FIXME: add a note about the attribute location in MutexExp or D
578f1ac63702143d84db778d32eb185a77fc97db5f5DeLesley Hutchins    if (Loc.isValid())
579651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines      Handler.handleInvalidLockExp(Kind, Loc);
580f1ac63702143d84db778d32eb185a77fc97db5f5DeLesley Hutchins  }
581f1ac63702143d84db778d32eb185a77fc97db5f5DeLesley Hutchins
582a74b715cdc37c4523818a4018faae99d977aa537DeLesley Hutchins  bool operator==(const SExpr &other) const {
583a74b715cdc37c4523818a4018faae99d977aa537DeLesley Hutchins    return NodeVec == other.NodeVec;
584402aa0698fec81e574818a0a6c2000fac0b2c4c6Caitlin Sadowski  }
585402aa0698fec81e574818a0a6c2000fac0b2c4c6Caitlin Sadowski
586a74b715cdc37c4523818a4018faae99d977aa537DeLesley Hutchins  bool operator!=(const SExpr &other) const {
587402aa0698fec81e574818a0a6c2000fac0b2c4c6Caitlin Sadowski    return !(*this == other);
588402aa0698fec81e574818a0a6c2000fac0b2c4c6Caitlin Sadowski  }
589402aa0698fec81e574818a0a6c2000fac0b2c4c6Caitlin Sadowski
590ee2f032fe0fc86762608458c2a167ae504579a64DeLesley Hutchins  bool matches(const SExpr &Other, unsigned i = 0, unsigned j = 0) const {
591ee2f032fe0fc86762608458c2a167ae504579a64DeLesley Hutchins    if (NodeVec[i].matches(Other.NodeVec[j])) {
592f9ee0bacd27085417dedf1a9f5df8a4cb5a758c1DeLesley Hutchins      unsigned ni = NodeVec[i].arity();
593f9ee0bacd27085417dedf1a9f5df8a4cb5a758c1DeLesley Hutchins      unsigned nj = Other.NodeVec[j].arity();
594f9ee0bacd27085417dedf1a9f5df8a4cb5a758c1DeLesley Hutchins      unsigned n = (ni < nj) ? ni : nj;
595ee2f032fe0fc86762608458c2a167ae504579a64DeLesley Hutchins      bool Result = true;
596ee2f032fe0fc86762608458c2a167ae504579a64DeLesley Hutchins      unsigned ci = i+1;  // first child of i
597ee2f032fe0fc86762608458c2a167ae504579a64DeLesley Hutchins      unsigned cj = j+1;  // first child of j
598ee2f032fe0fc86762608458c2a167ae504579a64DeLesley Hutchins      for (unsigned k = 0; k < n;
599ee2f032fe0fc86762608458c2a167ae504579a64DeLesley Hutchins           ++k, ci=getNextSibling(ci), cj = Other.getNextSibling(cj)) {
600ee2f032fe0fc86762608458c2a167ae504579a64DeLesley Hutchins        Result = Result && matches(Other, ci, cj);
601ee2f032fe0fc86762608458c2a167ae504579a64DeLesley Hutchins      }
602ee2f032fe0fc86762608458c2a167ae504579a64DeLesley Hutchins      return Result;
603ee2f032fe0fc86762608458c2a167ae504579a64DeLesley Hutchins    }
604ee2f032fe0fc86762608458c2a167ae504579a64DeLesley Hutchins    return false;
605ee2f032fe0fc86762608458c2a167ae504579a64DeLesley Hutchins  }
606ee2f032fe0fc86762608458c2a167ae504579a64DeLesley Hutchins
6073f0ec5209726641782468bd4c7597e79dda78b15DeLesley Hutchins  // A partial match between a.mu and b.mu returns true a and b have the same
6083f0ec5209726641782468bd4c7597e79dda78b15DeLesley Hutchins  // type (and thus mu refers to the same mutex declaration), regardless of
6093f0ec5209726641782468bd4c7597e79dda78b15DeLesley Hutchins  // whether a and b are different objects or not.
6103f0ec5209726641782468bd4c7597e79dda78b15DeLesley Hutchins  bool partiallyMatches(const SExpr &Other) const {
6113f0ec5209726641782468bd4c7597e79dda78b15DeLesley Hutchins    if (NodeVec[0].kind() == EOP_Dot)
6123f0ec5209726641782468bd4c7597e79dda78b15DeLesley Hutchins      return NodeVec[0].matches(Other.NodeVec[0]);
6133f0ec5209726641782468bd4c7597e79dda78b15DeLesley Hutchins    return false;
6143f0ec5209726641782468bd4c7597e79dda78b15DeLesley Hutchins  }
6153f0ec5209726641782468bd4c7597e79dda78b15DeLesley Hutchins
616a74b715cdc37c4523818a4018faae99d977aa537DeLesley Hutchins  /// \brief Pretty print a lock expression for use in error messages.
617a74b715cdc37c4523818a4018faae99d977aa537DeLesley Hutchins  std::string toString(unsigned i = 0) const {
618194418f1db5f5f78bc3e614d1e10a863455d882cCaitlin Sadowski    assert(isValid());
619a74b715cdc37c4523818a4018faae99d977aa537DeLesley Hutchins    if (i >= NodeVec.size())
620a74b715cdc37c4523818a4018faae99d977aa537DeLesley Hutchins      return "";
621a74b715cdc37c4523818a4018faae99d977aa537DeLesley Hutchins
622a74b715cdc37c4523818a4018faae99d977aa537DeLesley Hutchins    const SExprNode* N = &NodeVec[i];
623a74b715cdc37c4523818a4018faae99d977aa537DeLesley Hutchins    switch (N->kind()) {
624a74b715cdc37c4523818a4018faae99d977aa537DeLesley Hutchins      case EOP_Nop:
625a74b715cdc37c4523818a4018faae99d977aa537DeLesley Hutchins        return "_";
626ee2f032fe0fc86762608458c2a167ae504579a64DeLesley Hutchins      case EOP_Wildcard:
627ee2f032fe0fc86762608458c2a167ae504579a64DeLesley Hutchins        return "(?)";
6280b4db3e08a201c35f0011489bd5cd5d39bbe54fbDeLesley Hutchins      case EOP_Universal:
6290b4db3e08a201c35f0011489bd5cd5d39bbe54fbDeLesley Hutchins        return "*";
630a74b715cdc37c4523818a4018faae99d977aa537DeLesley Hutchins      case EOP_This:
631a74b715cdc37c4523818a4018faae99d977aa537DeLesley Hutchins        return "this";
632a74b715cdc37c4523818a4018faae99d977aa537DeLesley Hutchins      case EOP_NVar:
633a74b715cdc37c4523818a4018faae99d977aa537DeLesley Hutchins      case EOP_LVar: {
634a74b715cdc37c4523818a4018faae99d977aa537DeLesley Hutchins        return N->getNamedDecl()->getNameAsString();
635a74b715cdc37c4523818a4018faae99d977aa537DeLesley Hutchins      }
636a74b715cdc37c4523818a4018faae99d977aa537DeLesley Hutchins      case EOP_Dot: {
637ee2f032fe0fc86762608458c2a167ae504579a64DeLesley Hutchins        if (NodeVec[i+1].kind() == EOP_Wildcard) {
638ee2f032fe0fc86762608458c2a167ae504579a64DeLesley Hutchins          std::string S = "&";
639ee2f032fe0fc86762608458c2a167ae504579a64DeLesley Hutchins          S += N->getNamedDecl()->getQualifiedNameAsString();
640ee2f032fe0fc86762608458c2a167ae504579a64DeLesley Hutchins          return S;
641ee2f032fe0fc86762608458c2a167ae504579a64DeLesley Hutchins        }
642a74b715cdc37c4523818a4018faae99d977aa537DeLesley Hutchins        std::string FieldName = N->getNamedDecl()->getNameAsString();
643a74b715cdc37c4523818a4018faae99d977aa537DeLesley Hutchins        if (NodeVec[i+1].kind() == EOP_This)
644a74b715cdc37c4523818a4018faae99d977aa537DeLesley Hutchins          return FieldName;
645ee2f032fe0fc86762608458c2a167ae504579a64DeLesley Hutchins
646a74b715cdc37c4523818a4018faae99d977aa537DeLesley Hutchins        std::string S = toString(i+1);
647a74b715cdc37c4523818a4018faae99d977aa537DeLesley Hutchins        if (N->isArrow())
648a74b715cdc37c4523818a4018faae99d977aa537DeLesley Hutchins          return S + "->" + FieldName;
649a74b715cdc37c4523818a4018faae99d977aa537DeLesley Hutchins        else
650a74b715cdc37c4523818a4018faae99d977aa537DeLesley Hutchins          return S + "." + FieldName;
651a74b715cdc37c4523818a4018faae99d977aa537DeLesley Hutchins      }
652a74b715cdc37c4523818a4018faae99d977aa537DeLesley Hutchins      case EOP_Call: {
653a74b715cdc37c4523818a4018faae99d977aa537DeLesley Hutchins        std::string S = toString(i+1) + "(";
654a74b715cdc37c4523818a4018faae99d977aa537DeLesley Hutchins        unsigned NumArgs = N->arity()-1;
655ee2f032fe0fc86762608458c2a167ae504579a64DeLesley Hutchins        unsigned ci = getNextSibling(i+1);
656ee2f032fe0fc86762608458c2a167ae504579a64DeLesley Hutchins        for (unsigned k=0; k<NumArgs; ++k, ci = getNextSibling(ci)) {
657a74b715cdc37c4523818a4018faae99d977aa537DeLesley Hutchins          S += toString(ci);
658a74b715cdc37c4523818a4018faae99d977aa537DeLesley Hutchins          if (k+1 < NumArgs) S += ",";
659a74b715cdc37c4523818a4018faae99d977aa537DeLesley Hutchins        }
660a74b715cdc37c4523818a4018faae99d977aa537DeLesley Hutchins        S += ")";
661a74b715cdc37c4523818a4018faae99d977aa537DeLesley Hutchins        return S;
662a74b715cdc37c4523818a4018faae99d977aa537DeLesley Hutchins      }
663a74b715cdc37c4523818a4018faae99d977aa537DeLesley Hutchins      case EOP_MCall: {
664a74b715cdc37c4523818a4018faae99d977aa537DeLesley Hutchins        std::string S = "";
665a74b715cdc37c4523818a4018faae99d977aa537DeLesley Hutchins        if (NodeVec[i+1].kind() != EOP_This)
666a74b715cdc37c4523818a4018faae99d977aa537DeLesley Hutchins          S = toString(i+1) + ".";
667a74b715cdc37c4523818a4018faae99d977aa537DeLesley Hutchins        if (const NamedDecl *D = N->getFunctionDecl())
668a74b715cdc37c4523818a4018faae99d977aa537DeLesley Hutchins          S += D->getNameAsString() + "(";
669a74b715cdc37c4523818a4018faae99d977aa537DeLesley Hutchins        else
670a74b715cdc37c4523818a4018faae99d977aa537DeLesley Hutchins          S += "#(";
671a74b715cdc37c4523818a4018faae99d977aa537DeLesley Hutchins        unsigned NumArgs = N->arity()-1;
672ee2f032fe0fc86762608458c2a167ae504579a64DeLesley Hutchins        unsigned ci = getNextSibling(i+1);
673ee2f032fe0fc86762608458c2a167ae504579a64DeLesley Hutchins        for (unsigned k=0; k<NumArgs; ++k, ci = getNextSibling(ci)) {
674a74b715cdc37c4523818a4018faae99d977aa537DeLesley Hutchins          S += toString(ci);
675a74b715cdc37c4523818a4018faae99d977aa537DeLesley Hutchins          if (k+1 < NumArgs) S += ",";
676a74b715cdc37c4523818a4018faae99d977aa537DeLesley Hutchins        }
677a74b715cdc37c4523818a4018faae99d977aa537DeLesley Hutchins        S += ")";
678a74b715cdc37c4523818a4018faae99d977aa537DeLesley Hutchins        return S;
679a74b715cdc37c4523818a4018faae99d977aa537DeLesley Hutchins      }
680a74b715cdc37c4523818a4018faae99d977aa537DeLesley Hutchins      case EOP_Index: {
681a74b715cdc37c4523818a4018faae99d977aa537DeLesley Hutchins        std::string S1 = toString(i+1);
682a74b715cdc37c4523818a4018faae99d977aa537DeLesley Hutchins        std::string S2 = toString(i+1 + NodeVec[i+1].size());
683a74b715cdc37c4523818a4018faae99d977aa537DeLesley Hutchins        return S1 + "[" + S2 + "]";
684a74b715cdc37c4523818a4018faae99d977aa537DeLesley Hutchins      }
685a74b715cdc37c4523818a4018faae99d977aa537DeLesley Hutchins      case EOP_Unary: {
686a74b715cdc37c4523818a4018faae99d977aa537DeLesley Hutchins        std::string S = toString(i+1);
687a74b715cdc37c4523818a4018faae99d977aa537DeLesley Hutchins        return "#" + S;
688a74b715cdc37c4523818a4018faae99d977aa537DeLesley Hutchins      }
689a74b715cdc37c4523818a4018faae99d977aa537DeLesley Hutchins      case EOP_Binary: {
690a74b715cdc37c4523818a4018faae99d977aa537DeLesley Hutchins        std::string S1 = toString(i+1);
691a74b715cdc37c4523818a4018faae99d977aa537DeLesley Hutchins        std::string S2 = toString(i+1 + NodeVec[i+1].size());
692a74b715cdc37c4523818a4018faae99d977aa537DeLesley Hutchins        return "(" + S1 + "#" + S2 + ")";
693a74b715cdc37c4523818a4018faae99d977aa537DeLesley Hutchins      }
694a74b715cdc37c4523818a4018faae99d977aa537DeLesley Hutchins      case EOP_Unknown: {
695a74b715cdc37c4523818a4018faae99d977aa537DeLesley Hutchins        unsigned NumChildren = N->arity();
696a74b715cdc37c4523818a4018faae99d977aa537DeLesley Hutchins        if (NumChildren == 0)
697a74b715cdc37c4523818a4018faae99d977aa537DeLesley Hutchins          return "(...)";
698a74b715cdc37c4523818a4018faae99d977aa537DeLesley Hutchins        std::string S = "(";
699a74b715cdc37c4523818a4018faae99d977aa537DeLesley Hutchins        unsigned ci = i+1;
700ee2f032fe0fc86762608458c2a167ae504579a64DeLesley Hutchins        for (unsigned j = 0; j < NumChildren; ++j, ci = getNextSibling(ci)) {
701a74b715cdc37c4523818a4018faae99d977aa537DeLesley Hutchins          S += toString(ci);
702a74b715cdc37c4523818a4018faae99d977aa537DeLesley Hutchins          if (j+1 < NumChildren) S += "#";
703a74b715cdc37c4523818a4018faae99d977aa537DeLesley Hutchins        }
704a74b715cdc37c4523818a4018faae99d977aa537DeLesley Hutchins        S += ")";
705a74b715cdc37c4523818a4018faae99d977aa537DeLesley Hutchins        return S;
706a74b715cdc37c4523818a4018faae99d977aa537DeLesley Hutchins      }
707402aa0698fec81e574818a0a6c2000fac0b2c4c6Caitlin Sadowski    }
708a74b715cdc37c4523818a4018faae99d977aa537DeLesley Hutchins    return "";
709402aa0698fec81e574818a0a6c2000fac0b2c4c6Caitlin Sadowski  }
710402aa0698fec81e574818a0a6c2000fac0b2c4c6Caitlin Sadowski};
711402aa0698fec81e574818a0a6c2000fac0b2c4c6Caitlin Sadowski
712a74b715cdc37c4523818a4018faae99d977aa537DeLesley Hutchins/// \brief A short list of SExprs
713a74b715cdc37c4523818a4018faae99d977aa537DeLesley Hutchinsclass MutexIDList : public SmallVector<SExpr, 3> {
7145381c05f51e5b7c7627f1d95b9a3425303ce086aDeLesley Hutchinspublic:
715651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines  /// \brief Push M onto list, but discard duplicates.
716a74b715cdc37c4523818a4018faae99d977aa537DeLesley Hutchins  void push_back_nodup(const SExpr& M) {
717651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines    if (end() == std::find(begin(), end(), M))
718651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines      push_back(M);
7195381c05f51e5b7c7627f1d95b9a3425303ce086aDeLesley Hutchins  }
7205381c05f51e5b7c7627f1d95b9a3425303ce086aDeLesley Hutchins};
7215381c05f51e5b7c7627f1d95b9a3425303ce086aDeLesley Hutchins
722402aa0698fec81e574818a0a6c2000fac0b2c4c6Caitlin Sadowski/// \brief This is a helper class that stores info about the most recent
723402aa0698fec81e574818a0a6c2000fac0b2c4c6Caitlin Sadowski/// accquire of a Lock.
724402aa0698fec81e574818a0a6c2000fac0b2c4c6Caitlin Sadowski///
725402aa0698fec81e574818a0a6c2000fac0b2c4c6Caitlin Sadowski/// The main body of the analysis maps MutexIDs to LockDatas.
726402aa0698fec81e574818a0a6c2000fac0b2c4c6Caitlin Sadowskistruct LockData {
727402aa0698fec81e574818a0a6c2000fac0b2c4c6Caitlin Sadowski  SourceLocation AcquireLoc;
728402aa0698fec81e574818a0a6c2000fac0b2c4c6Caitlin Sadowski
729402aa0698fec81e574818a0a6c2000fac0b2c4c6Caitlin Sadowski  /// \brief LKind stores whether a lock is held shared or exclusively.
730402aa0698fec81e574818a0a6c2000fac0b2c4c6Caitlin Sadowski  /// Note that this analysis does not currently support either re-entrant
731402aa0698fec81e574818a0a6c2000fac0b2c4c6Caitlin Sadowski  /// locking or lock "upgrading" and "downgrading" between exclusive and
732402aa0698fec81e574818a0a6c2000fac0b2c4c6Caitlin Sadowski  /// shared.
733402aa0698fec81e574818a0a6c2000fac0b2c4c6Caitlin Sadowski  ///
734402aa0698fec81e574818a0a6c2000fac0b2c4c6Caitlin Sadowski  /// FIXME: add support for re-entrant locking and lock up/downgrading
735402aa0698fec81e574818a0a6c2000fac0b2c4c6Caitlin Sadowski  LockKind LKind;
7365c6134fd09bc5b738dafdd1c774edde13d95cb20DeLesley Hutchins  bool     Asserted;           // for asserted locks
737c99a5d820ead4e4f1f4b4a8ab61007b8da0307e6DeLesley Hutchins  bool     Managed;            // for ScopedLockable objects
738a74b715cdc37c4523818a4018faae99d977aa537DeLesley Hutchins  SExpr    UnderlyingMutex;    // for ScopedLockable objects
739402aa0698fec81e574818a0a6c2000fac0b2c4c6Caitlin Sadowski
7405c6134fd09bc5b738dafdd1c774edde13d95cb20DeLesley Hutchins  LockData(SourceLocation AcquireLoc, LockKind LKind, bool M=false,
7415c6134fd09bc5b738dafdd1c774edde13d95cb20DeLesley Hutchins           bool Asrt=false)
7425c6134fd09bc5b738dafdd1c774edde13d95cb20DeLesley Hutchins    : AcquireLoc(AcquireLoc), LKind(LKind), Asserted(Asrt), Managed(M),
743c99a5d820ead4e4f1f4b4a8ab61007b8da0307e6DeLesley Hutchins      UnderlyingMutex(Decl::EmptyShell())
7441fa3c0682a52c45c4ad0be3a82d0c85f26657072DeLesley Hutchins  {}
7451fa3c0682a52c45c4ad0be3a82d0c85f26657072DeLesley Hutchins
746a74b715cdc37c4523818a4018faae99d977aa537DeLesley Hutchins  LockData(SourceLocation AcquireLoc, LockKind LKind, const SExpr &Mu)
7475c6134fd09bc5b738dafdd1c774edde13d95cb20DeLesley Hutchins    : AcquireLoc(AcquireLoc), LKind(LKind), Asserted(false), Managed(false),
748c99a5d820ead4e4f1f4b4a8ab61007b8da0307e6DeLesley Hutchins      UnderlyingMutex(Mu)
749c99a5d820ead4e4f1f4b4a8ab61007b8da0307e6DeLesley Hutchins  {}
750402aa0698fec81e574818a0a6c2000fac0b2c4c6Caitlin Sadowski
751402aa0698fec81e574818a0a6c2000fac0b2c4c6Caitlin Sadowski  bool operator==(const LockData &other) const {
752402aa0698fec81e574818a0a6c2000fac0b2c4c6Caitlin Sadowski    return AcquireLoc == other.AcquireLoc && LKind == other.LKind;
753402aa0698fec81e574818a0a6c2000fac0b2c4c6Caitlin Sadowski  }
754402aa0698fec81e574818a0a6c2000fac0b2c4c6Caitlin Sadowski
755402aa0698fec81e574818a0a6c2000fac0b2c4c6Caitlin Sadowski  bool operator!=(const LockData &other) const {
756402aa0698fec81e574818a0a6c2000fac0b2c4c6Caitlin Sadowski    return !(*this == other);
757402aa0698fec81e574818a0a6c2000fac0b2c4c6Caitlin Sadowski  }
758402aa0698fec81e574818a0a6c2000fac0b2c4c6Caitlin Sadowski
759402aa0698fec81e574818a0a6c2000fac0b2c4c6Caitlin Sadowski  void Profile(llvm::FoldingSetNodeID &ID) const {
760a60448d6dfc91f4c30987e237bf70ef50ac7705bDeLesley Hutchins    ID.AddInteger(AcquireLoc.getRawEncoding());
761a60448d6dfc91f4c30987e237bf70ef50ac7705bDeLesley Hutchins    ID.AddInteger(LKind);
762a60448d6dfc91f4c30987e237bf70ef50ac7705bDeLesley Hutchins  }
7630b4db3e08a201c35f0011489bd5cd5d39bbe54fbDeLesley Hutchins
7640b4db3e08a201c35f0011489bd5cd5d39bbe54fbDeLesley Hutchins  bool isAtLeast(LockKind LK) {
7650b4db3e08a201c35f0011489bd5cd5d39bbe54fbDeLesley Hutchins    return (LK == LK_Shared) || (LKind == LK_Exclusive);
7660b4db3e08a201c35f0011489bd5cd5d39bbe54fbDeLesley Hutchins  }
767402aa0698fec81e574818a0a6c2000fac0b2c4c6Caitlin Sadowski};
768402aa0698fec81e574818a0a6c2000fac0b2c4c6Caitlin Sadowski
769a60448d6dfc91f4c30987e237bf70ef50ac7705bDeLesley Hutchins
770a1fa47139d6e9e7dcc40f2809605d1a258624e7fDeLesley Hutchins/// \brief A FactEntry stores a single fact that is known at a particular point
771a1fa47139d6e9e7dcc40f2809605d1a258624e7fDeLesley Hutchins/// in the program execution.  Currently, this is information regarding a lock
772dd0a1f58a505ced9674f6d31a1ff65cb87774d67DeLesley Hutchins/// that is held at that point.
773a1fa47139d6e9e7dcc40f2809605d1a258624e7fDeLesley Hutchinsstruct FactEntry {
774a74b715cdc37c4523818a4018faae99d977aa537DeLesley Hutchins  SExpr    MutID;
775a1fa47139d6e9e7dcc40f2809605d1a258624e7fDeLesley Hutchins  LockData LDat;
776a1fa47139d6e9e7dcc40f2809605d1a258624e7fDeLesley Hutchins
777a74b715cdc37c4523818a4018faae99d977aa537DeLesley Hutchins  FactEntry(const SExpr& M, const LockData& L)
778a1fa47139d6e9e7dcc40f2809605d1a258624e7fDeLesley Hutchins    : MutID(M), LDat(L)
779a1fa47139d6e9e7dcc40f2809605d1a258624e7fDeLesley Hutchins  { }
780a1fa47139d6e9e7dcc40f2809605d1a258624e7fDeLesley Hutchins};
781a1fa47139d6e9e7dcc40f2809605d1a258624e7fDeLesley Hutchins
782a1fa47139d6e9e7dcc40f2809605d1a258624e7fDeLesley Hutchins
783a1fa47139d6e9e7dcc40f2809605d1a258624e7fDeLesley Hutchinstypedef unsigned short FactID;
784a1fa47139d6e9e7dcc40f2809605d1a258624e7fDeLesley Hutchins
785dd0a1f58a505ced9674f6d31a1ff65cb87774d67DeLesley Hutchins/// \brief FactManager manages the memory for all facts that are created during
786a1fa47139d6e9e7dcc40f2809605d1a258624e7fDeLesley Hutchins/// the analysis of a single routine.
787a1fa47139d6e9e7dcc40f2809605d1a258624e7fDeLesley Hutchinsclass FactManager {
788a1fa47139d6e9e7dcc40f2809605d1a258624e7fDeLesley Hutchinsprivate:
789a1fa47139d6e9e7dcc40f2809605d1a258624e7fDeLesley Hutchins  std::vector<FactEntry> Facts;
790a1fa47139d6e9e7dcc40f2809605d1a258624e7fDeLesley Hutchins
791a1fa47139d6e9e7dcc40f2809605d1a258624e7fDeLesley Hutchinspublic:
792a74b715cdc37c4523818a4018faae99d977aa537DeLesley Hutchins  FactID newLock(const SExpr& M, const LockData& L) {
793a1fa47139d6e9e7dcc40f2809605d1a258624e7fDeLesley Hutchins    Facts.push_back(FactEntry(M,L));
794a1fa47139d6e9e7dcc40f2809605d1a258624e7fDeLesley Hutchins    return static_cast<unsigned short>(Facts.size() - 1);
795a1fa47139d6e9e7dcc40f2809605d1a258624e7fDeLesley Hutchins  }
796a1fa47139d6e9e7dcc40f2809605d1a258624e7fDeLesley Hutchins
797a1fa47139d6e9e7dcc40f2809605d1a258624e7fDeLesley Hutchins  const FactEntry& operator[](FactID F) const { return Facts[F]; }
798a1fa47139d6e9e7dcc40f2809605d1a258624e7fDeLesley Hutchins  FactEntry&       operator[](FactID F)       { return Facts[F]; }
799a1fa47139d6e9e7dcc40f2809605d1a258624e7fDeLesley Hutchins};
800a1fa47139d6e9e7dcc40f2809605d1a258624e7fDeLesley Hutchins
801a1fa47139d6e9e7dcc40f2809605d1a258624e7fDeLesley Hutchins
802a1fa47139d6e9e7dcc40f2809605d1a258624e7fDeLesley Hutchins/// \brief A FactSet is the set of facts that are known to be true at a
803dd0a1f58a505ced9674f6d31a1ff65cb87774d67DeLesley Hutchins/// particular program point.  FactSets must be small, because they are
804a1fa47139d6e9e7dcc40f2809605d1a258624e7fDeLesley Hutchins/// frequently copied, and are thus implemented as a set of indices into a
805dd0a1f58a505ced9674f6d31a1ff65cb87774d67DeLesley Hutchins/// table maintained by a FactManager.  A typical FactSet only holds 1 or 2
806a1fa47139d6e9e7dcc40f2809605d1a258624e7fDeLesley Hutchins/// locks, so we can get away with doing a linear search for lookup.  Note
807a1fa47139d6e9e7dcc40f2809605d1a258624e7fDeLesley Hutchins/// that a hashtable or map is inappropriate in this case, because lookups
808a1fa47139d6e9e7dcc40f2809605d1a258624e7fDeLesley Hutchins/// may involve partial pattern matches, rather than exact matches.
809a1fa47139d6e9e7dcc40f2809605d1a258624e7fDeLesley Hutchinsclass FactSet {
810a1fa47139d6e9e7dcc40f2809605d1a258624e7fDeLesley Hutchinsprivate:
811a1fa47139d6e9e7dcc40f2809605d1a258624e7fDeLesley Hutchins  typedef SmallVector<FactID, 4> FactVec;
812a1fa47139d6e9e7dcc40f2809605d1a258624e7fDeLesley Hutchins
813a1fa47139d6e9e7dcc40f2809605d1a258624e7fDeLesley Hutchins  FactVec FactIDs;
814a1fa47139d6e9e7dcc40f2809605d1a258624e7fDeLesley Hutchins
815a1fa47139d6e9e7dcc40f2809605d1a258624e7fDeLesley Hutchinspublic:
816a1fa47139d6e9e7dcc40f2809605d1a258624e7fDeLesley Hutchins  typedef FactVec::iterator       iterator;
817a1fa47139d6e9e7dcc40f2809605d1a258624e7fDeLesley Hutchins  typedef FactVec::const_iterator const_iterator;
818a1fa47139d6e9e7dcc40f2809605d1a258624e7fDeLesley Hutchins
819a1fa47139d6e9e7dcc40f2809605d1a258624e7fDeLesley Hutchins  iterator       begin()       { return FactIDs.begin(); }
820a1fa47139d6e9e7dcc40f2809605d1a258624e7fDeLesley Hutchins  const_iterator begin() const { return FactIDs.begin(); }
821a1fa47139d6e9e7dcc40f2809605d1a258624e7fDeLesley Hutchins
822a1fa47139d6e9e7dcc40f2809605d1a258624e7fDeLesley Hutchins  iterator       end()       { return FactIDs.end(); }
823a1fa47139d6e9e7dcc40f2809605d1a258624e7fDeLesley Hutchins  const_iterator end() const { return FactIDs.end(); }
824a1fa47139d6e9e7dcc40f2809605d1a258624e7fDeLesley Hutchins
825a1fa47139d6e9e7dcc40f2809605d1a258624e7fDeLesley Hutchins  bool isEmpty() const { return FactIDs.size() == 0; }
826a1fa47139d6e9e7dcc40f2809605d1a258624e7fDeLesley Hutchins
827a74b715cdc37c4523818a4018faae99d977aa537DeLesley Hutchins  FactID addLock(FactManager& FM, const SExpr& M, const LockData& L) {
828a1fa47139d6e9e7dcc40f2809605d1a258624e7fDeLesley Hutchins    FactID F = FM.newLock(M, L);
829a1fa47139d6e9e7dcc40f2809605d1a258624e7fDeLesley Hutchins    FactIDs.push_back(F);
830a1fa47139d6e9e7dcc40f2809605d1a258624e7fDeLesley Hutchins    return F;
831a1fa47139d6e9e7dcc40f2809605d1a258624e7fDeLesley Hutchins  }
832a1fa47139d6e9e7dcc40f2809605d1a258624e7fDeLesley Hutchins
833a74b715cdc37c4523818a4018faae99d977aa537DeLesley Hutchins  bool removeLock(FactManager& FM, const SExpr& M) {
834a1fa47139d6e9e7dcc40f2809605d1a258624e7fDeLesley Hutchins    unsigned n = FactIDs.size();
835a1fa47139d6e9e7dcc40f2809605d1a258624e7fDeLesley Hutchins    if (n == 0)
836a1fa47139d6e9e7dcc40f2809605d1a258624e7fDeLesley Hutchins      return false;
837a1fa47139d6e9e7dcc40f2809605d1a258624e7fDeLesley Hutchins
838a1fa47139d6e9e7dcc40f2809605d1a258624e7fDeLesley Hutchins    for (unsigned i = 0; i < n-1; ++i) {
839ee2f032fe0fc86762608458c2a167ae504579a64DeLesley Hutchins      if (FM[FactIDs[i]].MutID.matches(M)) {
840a1fa47139d6e9e7dcc40f2809605d1a258624e7fDeLesley Hutchins        FactIDs[i] = FactIDs[n-1];
841a1fa47139d6e9e7dcc40f2809605d1a258624e7fDeLesley Hutchins        FactIDs.pop_back();
842a1fa47139d6e9e7dcc40f2809605d1a258624e7fDeLesley Hutchins        return true;
843a1fa47139d6e9e7dcc40f2809605d1a258624e7fDeLesley Hutchins      }
844a1fa47139d6e9e7dcc40f2809605d1a258624e7fDeLesley Hutchins    }
845ee2f032fe0fc86762608458c2a167ae504579a64DeLesley Hutchins    if (FM[FactIDs[n-1]].MutID.matches(M)) {
846a1fa47139d6e9e7dcc40f2809605d1a258624e7fDeLesley Hutchins      FactIDs.pop_back();
847a1fa47139d6e9e7dcc40f2809605d1a258624e7fDeLesley Hutchins      return true;
848a1fa47139d6e9e7dcc40f2809605d1a258624e7fDeLesley Hutchins    }
849a1fa47139d6e9e7dcc40f2809605d1a258624e7fDeLesley Hutchins    return false;
850a1fa47139d6e9e7dcc40f2809605d1a258624e7fDeLesley Hutchins  }
851a1fa47139d6e9e7dcc40f2809605d1a258624e7fDeLesley Hutchins
852451f8e4ed63c97065fcbc79cf1cbbbbe1c4b6bd9DeLesley Hutchins  iterator findLockIter(FactManager &FM, const SExpr &M) {
8536bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines    return std::find_if(begin(), end(), [&](FactID ID) {
8546bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines      return FM[ID].MutID.matches(M);
8556bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines    });
856451f8e4ed63c97065fcbc79cf1cbbbbe1c4b6bd9DeLesley Hutchins  }
857451f8e4ed63c97065fcbc79cf1cbbbbe1c4b6bd9DeLesley Hutchins
8586bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines  LockData *findLock(FactManager &FM, const SExpr &M) const {
8596bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines    auto I = std::find_if(begin(), end(), [&](FactID ID) {
8606bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines      return FM[ID].MutID.matches(M);
8616bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines    });
8620b4db3e08a201c35f0011489bd5cd5d39bbe54fbDeLesley Hutchins
8636bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines    return I != end() ? &FM[*I].LDat : nullptr;
864a1fa47139d6e9e7dcc40f2809605d1a258624e7fDeLesley Hutchins  }
8653f0ec5209726641782468bd4c7597e79dda78b15DeLesley Hutchins
8666bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines  LockData *findLockUniv(FactManager &FM, const SExpr &M) const {
8676bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines    auto I = std::find_if(begin(), end(), [&](FactID ID) -> bool {
8686bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines      const SExpr &Expr = FM[ID].MutID;
8696bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines      return Expr.isUniversal() || Expr.matches(M);
8706bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines    });
8716bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines
8726bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines    return I != end() ? &FM[*I].LDat : nullptr;
8733f0ec5209726641782468bd4c7597e79dda78b15DeLesley Hutchins  }
874a1fa47139d6e9e7dcc40f2809605d1a258624e7fDeLesley Hutchins
8756bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines  FactEntry *findPartialMatch(FactManager &FM, const SExpr &M) const {
8766bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines    auto I = std::find_if(begin(), end(), [&](FactID ID) {
8776bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines      return FM[ID].MutID.partiallyMatches(M);
8786bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines    });
879a1fa47139d6e9e7dcc40f2809605d1a258624e7fDeLesley Hutchins
8806bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines    return I != end() ? &FM[*I] : nullptr;
8816bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines  }
8826bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines};
883a1fa47139d6e9e7dcc40f2809605d1a258624e7fDeLesley Hutchins
884a74b715cdc37c4523818a4018faae99d977aa537DeLesley Hutchins/// A Lockset maps each SExpr (defined above) to information about how it has
885402aa0698fec81e574818a0a6c2000fac0b2c4c6Caitlin Sadowski/// been locked.
886a74b715cdc37c4523818a4018faae99d977aa537DeLesley Hutchinstypedef llvm::ImmutableMap<SExpr, LockData> Lockset;
88754c350a67b47f059e1d577bdd9e2d1dc31ff82b5DeLesley Hutchinstypedef llvm::ImmutableMap<const NamedDecl*, unsigned> LocalVarContext;
888b37d2b5c0819d9ef596c7baec1e0be0d7c45b547DeLesley Hutchins
889b37d2b5c0819d9ef596c7baec1e0be0d7c45b547DeLesley Hutchinsclass LocalVariableMap;
890b37d2b5c0819d9ef596c7baec1e0be0d7c45b547DeLesley Hutchins
8912e5156274b8051217565b557bfa14c80f7990e9cRichard Smith/// A side (entry or exit) of a CFG node.
8922e5156274b8051217565b557bfa14c80f7990e9cRichard Smithenum CFGBlockSide { CBS_Entry, CBS_Exit };
893b37d2b5c0819d9ef596c7baec1e0be0d7c45b547DeLesley Hutchins
894b37d2b5c0819d9ef596c7baec1e0be0d7c45b547DeLesley Hutchins/// CFGBlockInfo is a struct which contains all the information that is
895b37d2b5c0819d9ef596c7baec1e0be0d7c45b547DeLesley Hutchins/// maintained for each block in the CFG.  See LocalVariableMap for more
896b37d2b5c0819d9ef596c7baec1e0be0d7c45b547DeLesley Hutchins/// information about the contexts.
897b37d2b5c0819d9ef596c7baec1e0be0d7c45b547DeLesley Hutchinsstruct CFGBlockInfo {
898a1fa47139d6e9e7dcc40f2809605d1a258624e7fDeLesley Hutchins  FactSet EntrySet;             // Lockset held at entry to block
899a1fa47139d6e9e7dcc40f2809605d1a258624e7fDeLesley Hutchins  FactSet ExitSet;              // Lockset held at exit from block
900b37d2b5c0819d9ef596c7baec1e0be0d7c45b547DeLesley Hutchins  LocalVarContext EntryContext; // Context held at entry to block
901b37d2b5c0819d9ef596c7baec1e0be0d7c45b547DeLesley Hutchins  LocalVarContext ExitContext;  // Context held at exit from block
9022e5156274b8051217565b557bfa14c80f7990e9cRichard Smith  SourceLocation EntryLoc;      // Location of first statement in block
9032e5156274b8051217565b557bfa14c80f7990e9cRichard Smith  SourceLocation ExitLoc;       // Location of last statement in block.
904b37d2b5c0819d9ef596c7baec1e0be0d7c45b547DeLesley Hutchins  unsigned EntryIndex;          // Used to replay contexts later
905d2f388299153d80cbe5ffaaed8a882b59a1b59bcDeLesley Hutchins  bool Reachable;               // Is this block reachable?
906b37d2b5c0819d9ef596c7baec1e0be0d7c45b547DeLesley Hutchins
907a1fa47139d6e9e7dcc40f2809605d1a258624e7fDeLesley Hutchins  const FactSet &getSet(CFGBlockSide Side) const {
9082e5156274b8051217565b557bfa14c80f7990e9cRichard Smith    return Side == CBS_Entry ? EntrySet : ExitSet;
9092e5156274b8051217565b557bfa14c80f7990e9cRichard Smith  }
9102e5156274b8051217565b557bfa14c80f7990e9cRichard Smith  SourceLocation getLocation(CFGBlockSide Side) const {
9112e5156274b8051217565b557bfa14c80f7990e9cRichard Smith    return Side == CBS_Entry ? EntryLoc : ExitLoc;
9122e5156274b8051217565b557bfa14c80f7990e9cRichard Smith  }
9132e5156274b8051217565b557bfa14c80f7990e9cRichard Smith
914b37d2b5c0819d9ef596c7baec1e0be0d7c45b547DeLesley Hutchinsprivate:
915a1fa47139d6e9e7dcc40f2809605d1a258624e7fDeLesley Hutchins  CFGBlockInfo(LocalVarContext EmptyCtx)
916d2f388299153d80cbe5ffaaed8a882b59a1b59bcDeLesley Hutchins    : EntryContext(EmptyCtx), ExitContext(EmptyCtx), Reachable(false)
917b37d2b5c0819d9ef596c7baec1e0be0d7c45b547DeLesley Hutchins  { }
918b37d2b5c0819d9ef596c7baec1e0be0d7c45b547DeLesley Hutchins
919b37d2b5c0819d9ef596c7baec1e0be0d7c45b547DeLesley Hutchinspublic:
920a1fa47139d6e9e7dcc40f2809605d1a258624e7fDeLesley Hutchins  static CFGBlockInfo getEmptyBlockInfo(LocalVariableMap &M);
921b37d2b5c0819d9ef596c7baec1e0be0d7c45b547DeLesley Hutchins};
922b37d2b5c0819d9ef596c7baec1e0be0d7c45b547DeLesley Hutchins
923b37d2b5c0819d9ef596c7baec1e0be0d7c45b547DeLesley Hutchins
924b37d2b5c0819d9ef596c7baec1e0be0d7c45b547DeLesley Hutchins
925b37d2b5c0819d9ef596c7baec1e0be0d7c45b547DeLesley Hutchins// A LocalVariableMap maintains a map from local variables to their currently
926b37d2b5c0819d9ef596c7baec1e0be0d7c45b547DeLesley Hutchins// valid definitions.  It provides SSA-like functionality when traversing the
927b37d2b5c0819d9ef596c7baec1e0be0d7c45b547DeLesley Hutchins// CFG.  Like SSA, each definition or assignment to a variable is assigned a
928b37d2b5c0819d9ef596c7baec1e0be0d7c45b547DeLesley Hutchins// unique name (an integer), which acts as the SSA name for that definition.
929b37d2b5c0819d9ef596c7baec1e0be0d7c45b547DeLesley Hutchins// The total set of names is shared among all CFG basic blocks.
930b37d2b5c0819d9ef596c7baec1e0be0d7c45b547DeLesley Hutchins// Unlike SSA, we do not rewrite expressions to replace local variables declrefs
931b37d2b5c0819d9ef596c7baec1e0be0d7c45b547DeLesley Hutchins// with their SSA-names.  Instead, we compute a Context for each point in the
932b37d2b5c0819d9ef596c7baec1e0be0d7c45b547DeLesley Hutchins// code, which maps local variables to the appropriate SSA-name.  This map
933b37d2b5c0819d9ef596c7baec1e0be0d7c45b547DeLesley Hutchins// changes with each assignment.
934b37d2b5c0819d9ef596c7baec1e0be0d7c45b547DeLesley Hutchins//
935b37d2b5c0819d9ef596c7baec1e0be0d7c45b547DeLesley Hutchins// The map is computed in a single pass over the CFG.  Subsequent analyses can
936b37d2b5c0819d9ef596c7baec1e0be0d7c45b547DeLesley Hutchins// then query the map to find the appropriate Context for a statement, and use
937b37d2b5c0819d9ef596c7baec1e0be0d7c45b547DeLesley Hutchins// that Context to look up the definitions of variables.
938b37d2b5c0819d9ef596c7baec1e0be0d7c45b547DeLesley Hutchinsclass LocalVariableMap {
939b37d2b5c0819d9ef596c7baec1e0be0d7c45b547DeLesley Hutchinspublic:
940b37d2b5c0819d9ef596c7baec1e0be0d7c45b547DeLesley Hutchins  typedef LocalVarContext Context;
941b37d2b5c0819d9ef596c7baec1e0be0d7c45b547DeLesley Hutchins
942b37d2b5c0819d9ef596c7baec1e0be0d7c45b547DeLesley Hutchins  /// A VarDefinition consists of an expression, representing the value of the
943b37d2b5c0819d9ef596c7baec1e0be0d7c45b547DeLesley Hutchins  /// variable, along with the context in which that expression should be
944b37d2b5c0819d9ef596c7baec1e0be0d7c45b547DeLesley Hutchins  /// interpreted.  A reference VarDefinition does not itself contain this
945b37d2b5c0819d9ef596c7baec1e0be0d7c45b547DeLesley Hutchins  /// information, but instead contains a pointer to a previous VarDefinition.
946b37d2b5c0819d9ef596c7baec1e0be0d7c45b547DeLesley Hutchins  struct VarDefinition {
947b37d2b5c0819d9ef596c7baec1e0be0d7c45b547DeLesley Hutchins  public:
948b37d2b5c0819d9ef596c7baec1e0be0d7c45b547DeLesley Hutchins    friend class LocalVariableMap;
949b37d2b5c0819d9ef596c7baec1e0be0d7c45b547DeLesley Hutchins
95054c350a67b47f059e1d577bdd9e2d1dc31ff82b5DeLesley Hutchins    const NamedDecl *Dec;  // The original declaration for this variable.
95154c350a67b47f059e1d577bdd9e2d1dc31ff82b5DeLesley Hutchins    const Expr *Exp;       // The expression for this variable, OR
95254c350a67b47f059e1d577bdd9e2d1dc31ff82b5DeLesley Hutchins    unsigned Ref;          // Reference to another VarDefinition
95354c350a67b47f059e1d577bdd9e2d1dc31ff82b5DeLesley Hutchins    Context Ctx;           // The map with which Exp should be interpreted.
954b37d2b5c0819d9ef596c7baec1e0be0d7c45b547DeLesley Hutchins
955b37d2b5c0819d9ef596c7baec1e0be0d7c45b547DeLesley Hutchins    bool isReference() { return !Exp; }
956b37d2b5c0819d9ef596c7baec1e0be0d7c45b547DeLesley Hutchins
957b37d2b5c0819d9ef596c7baec1e0be0d7c45b547DeLesley Hutchins  private:
958b37d2b5c0819d9ef596c7baec1e0be0d7c45b547DeLesley Hutchins    // Create ordinary variable definition
95954c350a67b47f059e1d577bdd9e2d1dc31ff82b5DeLesley Hutchins    VarDefinition(const NamedDecl *D, const Expr *E, Context C)
960b37d2b5c0819d9ef596c7baec1e0be0d7c45b547DeLesley Hutchins      : Dec(D), Exp(E), Ref(0), Ctx(C)
961b37d2b5c0819d9ef596c7baec1e0be0d7c45b547DeLesley Hutchins    { }
962b37d2b5c0819d9ef596c7baec1e0be0d7c45b547DeLesley Hutchins
963b37d2b5c0819d9ef596c7baec1e0be0d7c45b547DeLesley Hutchins    // Create reference to previous definition
96454c350a67b47f059e1d577bdd9e2d1dc31ff82b5DeLesley Hutchins    VarDefinition(const NamedDecl *D, unsigned R, Context C)
9656bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines      : Dec(D), Exp(nullptr), Ref(R), Ctx(C)
966b37d2b5c0819d9ef596c7baec1e0be0d7c45b547DeLesley Hutchins    { }
967b37d2b5c0819d9ef596c7baec1e0be0d7c45b547DeLesley Hutchins  };
968b37d2b5c0819d9ef596c7baec1e0be0d7c45b547DeLesley Hutchins
969b37d2b5c0819d9ef596c7baec1e0be0d7c45b547DeLesley Hutchinsprivate:
970b37d2b5c0819d9ef596c7baec1e0be0d7c45b547DeLesley Hutchins  Context::Factory ContextFactory;
971b37d2b5c0819d9ef596c7baec1e0be0d7c45b547DeLesley Hutchins  std::vector<VarDefinition> VarDefinitions;
972b37d2b5c0819d9ef596c7baec1e0be0d7c45b547DeLesley Hutchins  std::vector<unsigned> CtxIndices;
973b37d2b5c0819d9ef596c7baec1e0be0d7c45b547DeLesley Hutchins  std::vector<std::pair<Stmt*, Context> > SavedContexts;
974b37d2b5c0819d9ef596c7baec1e0be0d7c45b547DeLesley Hutchins
975b37d2b5c0819d9ef596c7baec1e0be0d7c45b547DeLesley Hutchinspublic:
976b37d2b5c0819d9ef596c7baec1e0be0d7c45b547DeLesley Hutchins  LocalVariableMap() {
977b37d2b5c0819d9ef596c7baec1e0be0d7c45b547DeLesley Hutchins    // index 0 is a placeholder for undefined variables (aka phi-nodes).
9786bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines    VarDefinitions.push_back(VarDefinition(nullptr, 0u, getEmptyContext()));
979b37d2b5c0819d9ef596c7baec1e0be0d7c45b547DeLesley Hutchins  }
980b37d2b5c0819d9ef596c7baec1e0be0d7c45b547DeLesley Hutchins
981b37d2b5c0819d9ef596c7baec1e0be0d7c45b547DeLesley Hutchins  /// Look up a definition, within the given context.
98254c350a67b47f059e1d577bdd9e2d1dc31ff82b5DeLesley Hutchins  const VarDefinition* lookup(const NamedDecl *D, Context Ctx) {
983b37d2b5c0819d9ef596c7baec1e0be0d7c45b547DeLesley Hutchins    const unsigned *i = Ctx.lookup(D);
984b37d2b5c0819d9ef596c7baec1e0be0d7c45b547DeLesley Hutchins    if (!i)
9856bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines      return nullptr;
986b37d2b5c0819d9ef596c7baec1e0be0d7c45b547DeLesley Hutchins    assert(*i < VarDefinitions.size());
987b37d2b5c0819d9ef596c7baec1e0be0d7c45b547DeLesley Hutchins    return &VarDefinitions[*i];
988b37d2b5c0819d9ef596c7baec1e0be0d7c45b547DeLesley Hutchins  }
989b37d2b5c0819d9ef596c7baec1e0be0d7c45b547DeLesley Hutchins
990b37d2b5c0819d9ef596c7baec1e0be0d7c45b547DeLesley Hutchins  /// Look up the definition for D within the given context.  Returns
991b4fa418a72759dfe34add850837965cbc00626e4DeLesley Hutchins  /// NULL if the expression is not statically known.  If successful, also
992b4fa418a72759dfe34add850837965cbc00626e4DeLesley Hutchins  /// modifies Ctx to hold the context of the return Expr.
99354c350a67b47f059e1d577bdd9e2d1dc31ff82b5DeLesley Hutchins  const Expr* lookupExpr(const NamedDecl *D, Context &Ctx) {
994b37d2b5c0819d9ef596c7baec1e0be0d7c45b547DeLesley Hutchins    const unsigned *P = Ctx.lookup(D);
995b37d2b5c0819d9ef596c7baec1e0be0d7c45b547DeLesley Hutchins    if (!P)
9966bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines      return nullptr;
997b37d2b5c0819d9ef596c7baec1e0be0d7c45b547DeLesley Hutchins
998b37d2b5c0819d9ef596c7baec1e0be0d7c45b547DeLesley Hutchins    unsigned i = *P;
999b37d2b5c0819d9ef596c7baec1e0be0d7c45b547DeLesley Hutchins    while (i > 0) {
1000b4fa418a72759dfe34add850837965cbc00626e4DeLesley Hutchins      if (VarDefinitions[i].Exp) {
1001b4fa418a72759dfe34add850837965cbc00626e4DeLesley Hutchins        Ctx = VarDefinitions[i].Ctx;
1002b37d2b5c0819d9ef596c7baec1e0be0d7c45b547DeLesley Hutchins        return VarDefinitions[i].Exp;
1003b4fa418a72759dfe34add850837965cbc00626e4DeLesley Hutchins      }
1004b37d2b5c0819d9ef596c7baec1e0be0d7c45b547DeLesley Hutchins      i = VarDefinitions[i].Ref;
1005b37d2b5c0819d9ef596c7baec1e0be0d7c45b547DeLesley Hutchins    }
10066bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines    return nullptr;
1007b37d2b5c0819d9ef596c7baec1e0be0d7c45b547DeLesley Hutchins  }
1008b37d2b5c0819d9ef596c7baec1e0be0d7c45b547DeLesley Hutchins
1009b37d2b5c0819d9ef596c7baec1e0be0d7c45b547DeLesley Hutchins  Context getEmptyContext() { return ContextFactory.getEmptyMap(); }
1010b37d2b5c0819d9ef596c7baec1e0be0d7c45b547DeLesley Hutchins
1011b37d2b5c0819d9ef596c7baec1e0be0d7c45b547DeLesley Hutchins  /// Return the next context after processing S.  This function is used by
1012b37d2b5c0819d9ef596c7baec1e0be0d7c45b547DeLesley Hutchins  /// clients of the class to get the appropriate context when traversing the
1013b37d2b5c0819d9ef596c7baec1e0be0d7c45b547DeLesley Hutchins  /// CFG.  It must be called for every assignment or DeclStmt.
1014b37d2b5c0819d9ef596c7baec1e0be0d7c45b547DeLesley Hutchins  Context getNextContext(unsigned &CtxIndex, Stmt *S, Context C) {
1015b37d2b5c0819d9ef596c7baec1e0be0d7c45b547DeLesley Hutchins    if (SavedContexts[CtxIndex+1].first == S) {
1016b37d2b5c0819d9ef596c7baec1e0be0d7c45b547DeLesley Hutchins      CtxIndex++;
1017b37d2b5c0819d9ef596c7baec1e0be0d7c45b547DeLesley Hutchins      Context Result = SavedContexts[CtxIndex].second;
1018b37d2b5c0819d9ef596c7baec1e0be0d7c45b547DeLesley Hutchins      return Result;
1019b37d2b5c0819d9ef596c7baec1e0be0d7c45b547DeLesley Hutchins    }
1020b37d2b5c0819d9ef596c7baec1e0be0d7c45b547DeLesley Hutchins    return C;
1021b37d2b5c0819d9ef596c7baec1e0be0d7c45b547DeLesley Hutchins  }
1022b37d2b5c0819d9ef596c7baec1e0be0d7c45b547DeLesley Hutchins
1023b37d2b5c0819d9ef596c7baec1e0be0d7c45b547DeLesley Hutchins  void dumpVarDefinitionName(unsigned i) {
1024b37d2b5c0819d9ef596c7baec1e0be0d7c45b547DeLesley Hutchins    if (i == 0) {
1025b37d2b5c0819d9ef596c7baec1e0be0d7c45b547DeLesley Hutchins      llvm::errs() << "Undefined";
1026b37d2b5c0819d9ef596c7baec1e0be0d7c45b547DeLesley Hutchins      return;
1027b37d2b5c0819d9ef596c7baec1e0be0d7c45b547DeLesley Hutchins    }
102854c350a67b47f059e1d577bdd9e2d1dc31ff82b5DeLesley Hutchins    const NamedDecl *Dec = VarDefinitions[i].Dec;
1029b37d2b5c0819d9ef596c7baec1e0be0d7c45b547DeLesley Hutchins    if (!Dec) {
1030b37d2b5c0819d9ef596c7baec1e0be0d7c45b547DeLesley Hutchins      llvm::errs() << "<<NULL>>";
1031b37d2b5c0819d9ef596c7baec1e0be0d7c45b547DeLesley Hutchins      return;
1032b37d2b5c0819d9ef596c7baec1e0be0d7c45b547DeLesley Hutchins    }
1033b37d2b5c0819d9ef596c7baec1e0be0d7c45b547DeLesley Hutchins    Dec->printName(llvm::errs());
103431ba6135375433b617a8587ea6cc836a014ebd86Roman Divacky    llvm::errs() << "." << i << " " << ((const void*) Dec);
1035b37d2b5c0819d9ef596c7baec1e0be0d7c45b547DeLesley Hutchins  }
1036b37d2b5c0819d9ef596c7baec1e0be0d7c45b547DeLesley Hutchins
1037b37d2b5c0819d9ef596c7baec1e0be0d7c45b547DeLesley Hutchins  /// Dumps an ASCII representation of the variable map to llvm::errs()
1038b37d2b5c0819d9ef596c7baec1e0be0d7c45b547DeLesley Hutchins  void dump() {
1039b37d2b5c0819d9ef596c7baec1e0be0d7c45b547DeLesley Hutchins    for (unsigned i = 1, e = VarDefinitions.size(); i < e; ++i) {
104054c350a67b47f059e1d577bdd9e2d1dc31ff82b5DeLesley Hutchins      const Expr *Exp = VarDefinitions[i].Exp;
1041b37d2b5c0819d9ef596c7baec1e0be0d7c45b547DeLesley Hutchins      unsigned Ref = VarDefinitions[i].Ref;
1042b37d2b5c0819d9ef596c7baec1e0be0d7c45b547DeLesley Hutchins
1043b37d2b5c0819d9ef596c7baec1e0be0d7c45b547DeLesley Hutchins      dumpVarDefinitionName(i);
1044b37d2b5c0819d9ef596c7baec1e0be0d7c45b547DeLesley Hutchins      llvm::errs() << " = ";
1045b37d2b5c0819d9ef596c7baec1e0be0d7c45b547DeLesley Hutchins      if (Exp) Exp->dump();
1046b37d2b5c0819d9ef596c7baec1e0be0d7c45b547DeLesley Hutchins      else {
1047b37d2b5c0819d9ef596c7baec1e0be0d7c45b547DeLesley Hutchins        dumpVarDefinitionName(Ref);
1048b37d2b5c0819d9ef596c7baec1e0be0d7c45b547DeLesley Hutchins        llvm::errs() << "\n";
1049b37d2b5c0819d9ef596c7baec1e0be0d7c45b547DeLesley Hutchins      }
1050b37d2b5c0819d9ef596c7baec1e0be0d7c45b547DeLesley Hutchins    }
1051b37d2b5c0819d9ef596c7baec1e0be0d7c45b547DeLesley Hutchins  }
1052b37d2b5c0819d9ef596c7baec1e0be0d7c45b547DeLesley Hutchins
1053b37d2b5c0819d9ef596c7baec1e0be0d7c45b547DeLesley Hutchins  /// Dumps an ASCII representation of a Context to llvm::errs()
1054b37d2b5c0819d9ef596c7baec1e0be0d7c45b547DeLesley Hutchins  void dumpContext(Context C) {
1055b37d2b5c0819d9ef596c7baec1e0be0d7c45b547DeLesley Hutchins    for (Context::iterator I = C.begin(), E = C.end(); I != E; ++I) {
105654c350a67b47f059e1d577bdd9e2d1dc31ff82b5DeLesley Hutchins      const NamedDecl *D = I.getKey();
1057b37d2b5c0819d9ef596c7baec1e0be0d7c45b547DeLesley Hutchins      D->printName(llvm::errs());
1058b37d2b5c0819d9ef596c7baec1e0be0d7c45b547DeLesley Hutchins      const unsigned *i = C.lookup(D);
1059b37d2b5c0819d9ef596c7baec1e0be0d7c45b547DeLesley Hutchins      llvm::errs() << " -> ";
1060b37d2b5c0819d9ef596c7baec1e0be0d7c45b547DeLesley Hutchins      dumpVarDefinitionName(*i);
1061b37d2b5c0819d9ef596c7baec1e0be0d7c45b547DeLesley Hutchins      llvm::errs() << "\n";
1062b37d2b5c0819d9ef596c7baec1e0be0d7c45b547DeLesley Hutchins    }
1063b37d2b5c0819d9ef596c7baec1e0be0d7c45b547DeLesley Hutchins  }
1064b37d2b5c0819d9ef596c7baec1e0be0d7c45b547DeLesley Hutchins
1065b37d2b5c0819d9ef596c7baec1e0be0d7c45b547DeLesley Hutchins  /// Builds the variable map.
10666bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines  void traverseCFG(CFG *CFGraph, const PostOrderCFGView *SortedGraph,
10676bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines                   std::vector<CFGBlockInfo> &BlockInfo);
1068b37d2b5c0819d9ef596c7baec1e0be0d7c45b547DeLesley Hutchins
1069b37d2b5c0819d9ef596c7baec1e0be0d7c45b547DeLesley Hutchinsprotected:
1070b37d2b5c0819d9ef596c7baec1e0be0d7c45b547DeLesley Hutchins  // Get the current context index
1071b37d2b5c0819d9ef596c7baec1e0be0d7c45b547DeLesley Hutchins  unsigned getContextIndex() { return SavedContexts.size()-1; }
1072b37d2b5c0819d9ef596c7baec1e0be0d7c45b547DeLesley Hutchins
1073b37d2b5c0819d9ef596c7baec1e0be0d7c45b547DeLesley Hutchins  // Save the current context for later replay
1074b37d2b5c0819d9ef596c7baec1e0be0d7c45b547DeLesley Hutchins  void saveContext(Stmt *S, Context C) {
1075b37d2b5c0819d9ef596c7baec1e0be0d7c45b547DeLesley Hutchins    SavedContexts.push_back(std::make_pair(S,C));
1076b37d2b5c0819d9ef596c7baec1e0be0d7c45b547DeLesley Hutchins  }
1077b37d2b5c0819d9ef596c7baec1e0be0d7c45b547DeLesley Hutchins
1078b37d2b5c0819d9ef596c7baec1e0be0d7c45b547DeLesley Hutchins  // Adds a new definition to the given context, and returns a new context.
1079b37d2b5c0819d9ef596c7baec1e0be0d7c45b547DeLesley Hutchins  // This method should be called when declaring a new variable.
10806bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines  Context addDefinition(const NamedDecl *D, const Expr *Exp, Context Ctx) {
1081b37d2b5c0819d9ef596c7baec1e0be0d7c45b547DeLesley Hutchins    assert(!Ctx.contains(D));
1082b37d2b5c0819d9ef596c7baec1e0be0d7c45b547DeLesley Hutchins    unsigned newID = VarDefinitions.size();
1083b37d2b5c0819d9ef596c7baec1e0be0d7c45b547DeLesley Hutchins    Context NewCtx = ContextFactory.add(Ctx, D, newID);
1084b37d2b5c0819d9ef596c7baec1e0be0d7c45b547DeLesley Hutchins    VarDefinitions.push_back(VarDefinition(D, Exp, Ctx));
1085b37d2b5c0819d9ef596c7baec1e0be0d7c45b547DeLesley Hutchins    return NewCtx;
1086b37d2b5c0819d9ef596c7baec1e0be0d7c45b547DeLesley Hutchins  }
1087b37d2b5c0819d9ef596c7baec1e0be0d7c45b547DeLesley Hutchins
1088b37d2b5c0819d9ef596c7baec1e0be0d7c45b547DeLesley Hutchins  // Add a new reference to an existing definition.
108954c350a67b47f059e1d577bdd9e2d1dc31ff82b5DeLesley Hutchins  Context addReference(const NamedDecl *D, unsigned i, Context Ctx) {
1090b37d2b5c0819d9ef596c7baec1e0be0d7c45b547DeLesley Hutchins    unsigned newID = VarDefinitions.size();
1091b37d2b5c0819d9ef596c7baec1e0be0d7c45b547DeLesley Hutchins    Context NewCtx = ContextFactory.add(Ctx, D, newID);
1092b37d2b5c0819d9ef596c7baec1e0be0d7c45b547DeLesley Hutchins    VarDefinitions.push_back(VarDefinition(D, i, Ctx));
1093b37d2b5c0819d9ef596c7baec1e0be0d7c45b547DeLesley Hutchins    return NewCtx;
1094b37d2b5c0819d9ef596c7baec1e0be0d7c45b547DeLesley Hutchins  }
1095b37d2b5c0819d9ef596c7baec1e0be0d7c45b547DeLesley Hutchins
1096b37d2b5c0819d9ef596c7baec1e0be0d7c45b547DeLesley Hutchins  // Updates a definition only if that definition is already in the map.
1097b37d2b5c0819d9ef596c7baec1e0be0d7c45b547DeLesley Hutchins  // This method should be called when assigning to an existing variable.
109854c350a67b47f059e1d577bdd9e2d1dc31ff82b5DeLesley Hutchins  Context updateDefinition(const NamedDecl *D, Expr *Exp, Context Ctx) {
1099b37d2b5c0819d9ef596c7baec1e0be0d7c45b547DeLesley Hutchins    if (Ctx.contains(D)) {
1100b37d2b5c0819d9ef596c7baec1e0be0d7c45b547DeLesley Hutchins      unsigned newID = VarDefinitions.size();
1101b37d2b5c0819d9ef596c7baec1e0be0d7c45b547DeLesley Hutchins      Context NewCtx = ContextFactory.remove(Ctx, D);
1102b37d2b5c0819d9ef596c7baec1e0be0d7c45b547DeLesley Hutchins      NewCtx = ContextFactory.add(NewCtx, D, newID);
1103b37d2b5c0819d9ef596c7baec1e0be0d7c45b547DeLesley Hutchins      VarDefinitions.push_back(VarDefinition(D, Exp, Ctx));
1104b37d2b5c0819d9ef596c7baec1e0be0d7c45b547DeLesley Hutchins      return NewCtx;
1105b37d2b5c0819d9ef596c7baec1e0be0d7c45b547DeLesley Hutchins    }
1106b37d2b5c0819d9ef596c7baec1e0be0d7c45b547DeLesley Hutchins    return Ctx;
1107b37d2b5c0819d9ef596c7baec1e0be0d7c45b547DeLesley Hutchins  }
1108b37d2b5c0819d9ef596c7baec1e0be0d7c45b547DeLesley Hutchins
1109b37d2b5c0819d9ef596c7baec1e0be0d7c45b547DeLesley Hutchins  // Removes a definition from the context, but keeps the variable name
1110b37d2b5c0819d9ef596c7baec1e0be0d7c45b547DeLesley Hutchins  // as a valid variable.  The index 0 is a placeholder for cleared definitions.
111154c350a67b47f059e1d577bdd9e2d1dc31ff82b5DeLesley Hutchins  Context clearDefinition(const NamedDecl *D, Context Ctx) {
1112b37d2b5c0819d9ef596c7baec1e0be0d7c45b547DeLesley Hutchins    Context NewCtx = Ctx;
1113b37d2b5c0819d9ef596c7baec1e0be0d7c45b547DeLesley Hutchins    if (NewCtx.contains(D)) {
1114b37d2b5c0819d9ef596c7baec1e0be0d7c45b547DeLesley Hutchins      NewCtx = ContextFactory.remove(NewCtx, D);
1115b37d2b5c0819d9ef596c7baec1e0be0d7c45b547DeLesley Hutchins      NewCtx = ContextFactory.add(NewCtx, D, 0);
1116b37d2b5c0819d9ef596c7baec1e0be0d7c45b547DeLesley Hutchins    }
1117b37d2b5c0819d9ef596c7baec1e0be0d7c45b547DeLesley Hutchins    return NewCtx;
1118b37d2b5c0819d9ef596c7baec1e0be0d7c45b547DeLesley Hutchins  }
1119b37d2b5c0819d9ef596c7baec1e0be0d7c45b547DeLesley Hutchins
1120b37d2b5c0819d9ef596c7baec1e0be0d7c45b547DeLesley Hutchins  // Remove a definition entirely frmo the context.
112154c350a67b47f059e1d577bdd9e2d1dc31ff82b5DeLesley Hutchins  Context removeDefinition(const NamedDecl *D, Context Ctx) {
1122b37d2b5c0819d9ef596c7baec1e0be0d7c45b547DeLesley Hutchins    Context NewCtx = Ctx;
1123b37d2b5c0819d9ef596c7baec1e0be0d7c45b547DeLesley Hutchins    if (NewCtx.contains(D)) {
1124b37d2b5c0819d9ef596c7baec1e0be0d7c45b547DeLesley Hutchins      NewCtx = ContextFactory.remove(NewCtx, D);
1125b37d2b5c0819d9ef596c7baec1e0be0d7c45b547DeLesley Hutchins    }
1126b37d2b5c0819d9ef596c7baec1e0be0d7c45b547DeLesley Hutchins    return NewCtx;
1127b37d2b5c0819d9ef596c7baec1e0be0d7c45b547DeLesley Hutchins  }
1128b37d2b5c0819d9ef596c7baec1e0be0d7c45b547DeLesley Hutchins
1129b37d2b5c0819d9ef596c7baec1e0be0d7c45b547DeLesley Hutchins  Context intersectContexts(Context C1, Context C2);
1130b37d2b5c0819d9ef596c7baec1e0be0d7c45b547DeLesley Hutchins  Context createReferenceContext(Context C);
1131b37d2b5c0819d9ef596c7baec1e0be0d7c45b547DeLesley Hutchins  void intersectBackEdge(Context C1, Context C2);
1132b37d2b5c0819d9ef596c7baec1e0be0d7c45b547DeLesley Hutchins
1133b37d2b5c0819d9ef596c7baec1e0be0d7c45b547DeLesley Hutchins  friend class VarMapBuilder;
1134b37d2b5c0819d9ef596c7baec1e0be0d7c45b547DeLesley Hutchins};
1135b37d2b5c0819d9ef596c7baec1e0be0d7c45b547DeLesley Hutchins
1136b37d2b5c0819d9ef596c7baec1e0be0d7c45b547DeLesley Hutchins
1137b37d2b5c0819d9ef596c7baec1e0be0d7c45b547DeLesley Hutchins// This has to be defined after LocalVariableMap.
1138a1fa47139d6e9e7dcc40f2809605d1a258624e7fDeLesley HutchinsCFGBlockInfo CFGBlockInfo::getEmptyBlockInfo(LocalVariableMap &M) {
1139a1fa47139d6e9e7dcc40f2809605d1a258624e7fDeLesley Hutchins  return CFGBlockInfo(M.getEmptyContext());
1140b37d2b5c0819d9ef596c7baec1e0be0d7c45b547DeLesley Hutchins}
1141b37d2b5c0819d9ef596c7baec1e0be0d7c45b547DeLesley Hutchins
1142b37d2b5c0819d9ef596c7baec1e0be0d7c45b547DeLesley Hutchins
1143b37d2b5c0819d9ef596c7baec1e0be0d7c45b547DeLesley Hutchins/// Visitor which builds a LocalVariableMap
1144b37d2b5c0819d9ef596c7baec1e0be0d7c45b547DeLesley Hutchinsclass VarMapBuilder : public StmtVisitor<VarMapBuilder> {
1145b37d2b5c0819d9ef596c7baec1e0be0d7c45b547DeLesley Hutchinspublic:
1146b37d2b5c0819d9ef596c7baec1e0be0d7c45b547DeLesley Hutchins  LocalVariableMap* VMap;
1147b37d2b5c0819d9ef596c7baec1e0be0d7c45b547DeLesley Hutchins  LocalVariableMap::Context Ctx;
1148b37d2b5c0819d9ef596c7baec1e0be0d7c45b547DeLesley Hutchins
1149b37d2b5c0819d9ef596c7baec1e0be0d7c45b547DeLesley Hutchins  VarMapBuilder(LocalVariableMap *VM, LocalVariableMap::Context C)
1150b37d2b5c0819d9ef596c7baec1e0be0d7c45b547DeLesley Hutchins    : VMap(VM), Ctx(C) {}
1151b37d2b5c0819d9ef596c7baec1e0be0d7c45b547DeLesley Hutchins
1152b37d2b5c0819d9ef596c7baec1e0be0d7c45b547DeLesley Hutchins  void VisitDeclStmt(DeclStmt *S);
1153b37d2b5c0819d9ef596c7baec1e0be0d7c45b547DeLesley Hutchins  void VisitBinaryOperator(BinaryOperator *BO);
1154b37d2b5c0819d9ef596c7baec1e0be0d7c45b547DeLesley Hutchins};
1155b37d2b5c0819d9ef596c7baec1e0be0d7c45b547DeLesley Hutchins
1156b37d2b5c0819d9ef596c7baec1e0be0d7c45b547DeLesley Hutchins
1157b37d2b5c0819d9ef596c7baec1e0be0d7c45b547DeLesley Hutchins// Add new local variables to the variable map
1158b37d2b5c0819d9ef596c7baec1e0be0d7c45b547DeLesley Hutchinsvoid VarMapBuilder::VisitDeclStmt(DeclStmt *S) {
1159b37d2b5c0819d9ef596c7baec1e0be0d7c45b547DeLesley Hutchins  bool modifiedCtx = false;
1160b37d2b5c0819d9ef596c7baec1e0be0d7c45b547DeLesley Hutchins  DeclGroupRef DGrp = S->getDeclGroup();
11616bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines  for (const auto *D : DGrp) {
11626bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines    if (const auto *VD = dyn_cast_or_null<VarDecl>(D)) {
11636bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines      const Expr *E = VD->getInit();
1164b37d2b5c0819d9ef596c7baec1e0be0d7c45b547DeLesley Hutchins
1165b37d2b5c0819d9ef596c7baec1e0be0d7c45b547DeLesley Hutchins      // Add local variables with trivial type to the variable map
1166b37d2b5c0819d9ef596c7baec1e0be0d7c45b547DeLesley Hutchins      QualType T = VD->getType();
1167b37d2b5c0819d9ef596c7baec1e0be0d7c45b547DeLesley Hutchins      if (T.isTrivialType(VD->getASTContext())) {
1168b37d2b5c0819d9ef596c7baec1e0be0d7c45b547DeLesley Hutchins        Ctx = VMap->addDefinition(VD, E, Ctx);
1169b37d2b5c0819d9ef596c7baec1e0be0d7c45b547DeLesley Hutchins        modifiedCtx = true;
1170b37d2b5c0819d9ef596c7baec1e0be0d7c45b547DeLesley Hutchins      }
1171b37d2b5c0819d9ef596c7baec1e0be0d7c45b547DeLesley Hutchins    }
1172b37d2b5c0819d9ef596c7baec1e0be0d7c45b547DeLesley Hutchins  }
1173b37d2b5c0819d9ef596c7baec1e0be0d7c45b547DeLesley Hutchins  if (modifiedCtx)
1174b37d2b5c0819d9ef596c7baec1e0be0d7c45b547DeLesley Hutchins    VMap->saveContext(S, Ctx);
1175b37d2b5c0819d9ef596c7baec1e0be0d7c45b547DeLesley Hutchins}
1176b37d2b5c0819d9ef596c7baec1e0be0d7c45b547DeLesley Hutchins
1177b37d2b5c0819d9ef596c7baec1e0be0d7c45b547DeLesley Hutchins// Update local variable definitions in variable map
1178b37d2b5c0819d9ef596c7baec1e0be0d7c45b547DeLesley Hutchinsvoid VarMapBuilder::VisitBinaryOperator(BinaryOperator *BO) {
1179b37d2b5c0819d9ef596c7baec1e0be0d7c45b547DeLesley Hutchins  if (!BO->isAssignmentOp())
1180b37d2b5c0819d9ef596c7baec1e0be0d7c45b547DeLesley Hutchins    return;
1181b37d2b5c0819d9ef596c7baec1e0be0d7c45b547DeLesley Hutchins
1182b37d2b5c0819d9ef596c7baec1e0be0d7c45b547DeLesley Hutchins  Expr *LHSExp = BO->getLHS()->IgnoreParenCasts();
1183b37d2b5c0819d9ef596c7baec1e0be0d7c45b547DeLesley Hutchins
1184b37d2b5c0819d9ef596c7baec1e0be0d7c45b547DeLesley Hutchins  // Update the variable map and current context.
1185b37d2b5c0819d9ef596c7baec1e0be0d7c45b547DeLesley Hutchins  if (DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(LHSExp)) {
1186b37d2b5c0819d9ef596c7baec1e0be0d7c45b547DeLesley Hutchins    ValueDecl *VDec = DRE->getDecl();
1187b37d2b5c0819d9ef596c7baec1e0be0d7c45b547DeLesley Hutchins    if (Ctx.lookup(VDec)) {
1188b37d2b5c0819d9ef596c7baec1e0be0d7c45b547DeLesley Hutchins      if (BO->getOpcode() == BO_Assign)
1189b37d2b5c0819d9ef596c7baec1e0be0d7c45b547DeLesley Hutchins        Ctx = VMap->updateDefinition(VDec, BO->getRHS(), Ctx);
1190b37d2b5c0819d9ef596c7baec1e0be0d7c45b547DeLesley Hutchins      else
1191b37d2b5c0819d9ef596c7baec1e0be0d7c45b547DeLesley Hutchins        // FIXME -- handle compound assignment operators
1192b37d2b5c0819d9ef596c7baec1e0be0d7c45b547DeLesley Hutchins        Ctx = VMap->clearDefinition(VDec, Ctx);
1193b37d2b5c0819d9ef596c7baec1e0be0d7c45b547DeLesley Hutchins      VMap->saveContext(BO, Ctx);
1194b37d2b5c0819d9ef596c7baec1e0be0d7c45b547DeLesley Hutchins    }
1195b37d2b5c0819d9ef596c7baec1e0be0d7c45b547DeLesley Hutchins  }
1196b37d2b5c0819d9ef596c7baec1e0be0d7c45b547DeLesley Hutchins}
1197b37d2b5c0819d9ef596c7baec1e0be0d7c45b547DeLesley Hutchins
1198b37d2b5c0819d9ef596c7baec1e0be0d7c45b547DeLesley Hutchins
1199b37d2b5c0819d9ef596c7baec1e0be0d7c45b547DeLesley Hutchins// Computes the intersection of two contexts.  The intersection is the
1200b37d2b5c0819d9ef596c7baec1e0be0d7c45b547DeLesley Hutchins// set of variables which have the same definition in both contexts;
1201b37d2b5c0819d9ef596c7baec1e0be0d7c45b547DeLesley Hutchins// variables with different definitions are discarded.
1202b37d2b5c0819d9ef596c7baec1e0be0d7c45b547DeLesley HutchinsLocalVariableMap::Context
1203b37d2b5c0819d9ef596c7baec1e0be0d7c45b547DeLesley HutchinsLocalVariableMap::intersectContexts(Context C1, Context C2) {
1204b37d2b5c0819d9ef596c7baec1e0be0d7c45b547DeLesley Hutchins  Context Result = C1;
12056bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines  for (const auto &P : C1) {
12066bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines    const NamedDecl *Dec = P.first;
1207b37d2b5c0819d9ef596c7baec1e0be0d7c45b547DeLesley Hutchins    const unsigned *i2 = C2.lookup(Dec);
1208b37d2b5c0819d9ef596c7baec1e0be0d7c45b547DeLesley Hutchins    if (!i2)             // variable doesn't exist on second path
1209b37d2b5c0819d9ef596c7baec1e0be0d7c45b547DeLesley Hutchins      Result = removeDefinition(Dec, Result);
12106bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines    else if (*i2 != P.second)  // variable exists, but has different definition
1211b37d2b5c0819d9ef596c7baec1e0be0d7c45b547DeLesley Hutchins      Result = clearDefinition(Dec, Result);
1212b37d2b5c0819d9ef596c7baec1e0be0d7c45b547DeLesley Hutchins  }
1213b37d2b5c0819d9ef596c7baec1e0be0d7c45b547DeLesley Hutchins  return Result;
1214b37d2b5c0819d9ef596c7baec1e0be0d7c45b547DeLesley Hutchins}
1215b37d2b5c0819d9ef596c7baec1e0be0d7c45b547DeLesley Hutchins
1216b37d2b5c0819d9ef596c7baec1e0be0d7c45b547DeLesley Hutchins// For every variable in C, create a new variable that refers to the
1217b37d2b5c0819d9ef596c7baec1e0be0d7c45b547DeLesley Hutchins// definition in C.  Return a new context that contains these new variables.
1218b37d2b5c0819d9ef596c7baec1e0be0d7c45b547DeLesley Hutchins// (We use this for a naive implementation of SSA on loop back-edges.)
1219b37d2b5c0819d9ef596c7baec1e0be0d7c45b547DeLesley HutchinsLocalVariableMap::Context LocalVariableMap::createReferenceContext(Context C) {
1220b37d2b5c0819d9ef596c7baec1e0be0d7c45b547DeLesley Hutchins  Context Result = getEmptyContext();
12216bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines  for (const auto &P : C)
12226bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines    Result = addReference(P.first, P.second, Result);
1223b37d2b5c0819d9ef596c7baec1e0be0d7c45b547DeLesley Hutchins  return Result;
1224b37d2b5c0819d9ef596c7baec1e0be0d7c45b547DeLesley Hutchins}
1225b37d2b5c0819d9ef596c7baec1e0be0d7c45b547DeLesley Hutchins
1226b37d2b5c0819d9ef596c7baec1e0be0d7c45b547DeLesley Hutchins// This routine also takes the intersection of C1 and C2, but it does so by
1227b37d2b5c0819d9ef596c7baec1e0be0d7c45b547DeLesley Hutchins// altering the VarDefinitions.  C1 must be the result of an earlier call to
1228b37d2b5c0819d9ef596c7baec1e0be0d7c45b547DeLesley Hutchins// createReferenceContext.
1229b37d2b5c0819d9ef596c7baec1e0be0d7c45b547DeLesley Hutchinsvoid LocalVariableMap::intersectBackEdge(Context C1, Context C2) {
12306bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines  for (const auto &P : C1) {
12316bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines    unsigned i1 = P.second;
1232b37d2b5c0819d9ef596c7baec1e0be0d7c45b547DeLesley Hutchins    VarDefinition *VDef = &VarDefinitions[i1];
1233b37d2b5c0819d9ef596c7baec1e0be0d7c45b547DeLesley Hutchins    assert(VDef->isReference());
1234b37d2b5c0819d9ef596c7baec1e0be0d7c45b547DeLesley Hutchins
12356bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines    const unsigned *i2 = C2.lookup(P.first);
1236b37d2b5c0819d9ef596c7baec1e0be0d7c45b547DeLesley Hutchins    if (!i2 || (*i2 != i1))
1237b37d2b5c0819d9ef596c7baec1e0be0d7c45b547DeLesley Hutchins      VDef->Ref = 0;    // Mark this variable as undefined
1238b37d2b5c0819d9ef596c7baec1e0be0d7c45b547DeLesley Hutchins  }
1239b37d2b5c0819d9ef596c7baec1e0be0d7c45b547DeLesley Hutchins}
1240b37d2b5c0819d9ef596c7baec1e0be0d7c45b547DeLesley Hutchins
1241b37d2b5c0819d9ef596c7baec1e0be0d7c45b547DeLesley Hutchins
1242b37d2b5c0819d9ef596c7baec1e0be0d7c45b547DeLesley Hutchins// Traverse the CFG in topological order, so all predecessors of a block
1243b37d2b5c0819d9ef596c7baec1e0be0d7c45b547DeLesley Hutchins// (excluding back-edges) are visited before the block itself.  At
1244b37d2b5c0819d9ef596c7baec1e0be0d7c45b547DeLesley Hutchins// each point in the code, we calculate a Context, which holds the set of
1245b37d2b5c0819d9ef596c7baec1e0be0d7c45b547DeLesley Hutchins// variable definitions which are visible at that point in execution.
1246b37d2b5c0819d9ef596c7baec1e0be0d7c45b547DeLesley Hutchins// Visible variables are mapped to their definitions using an array that
1247b37d2b5c0819d9ef596c7baec1e0be0d7c45b547DeLesley Hutchins// contains all definitions.
1248b37d2b5c0819d9ef596c7baec1e0be0d7c45b547DeLesley Hutchins//
1249b37d2b5c0819d9ef596c7baec1e0be0d7c45b547DeLesley Hutchins// At join points in the CFG, the set is computed as the intersection of
1250b37d2b5c0819d9ef596c7baec1e0be0d7c45b547DeLesley Hutchins// the incoming sets along each edge, E.g.
1251b37d2b5c0819d9ef596c7baec1e0be0d7c45b547DeLesley Hutchins//
1252b37d2b5c0819d9ef596c7baec1e0be0d7c45b547DeLesley Hutchins//                       { Context                 | VarDefinitions }
1253b37d2b5c0819d9ef596c7baec1e0be0d7c45b547DeLesley Hutchins//   int x = 0;          { x -> x1                 | x1 = 0 }
1254b37d2b5c0819d9ef596c7baec1e0be0d7c45b547DeLesley Hutchins//   int y = 0;          { x -> x1, y -> y1        | y1 = 0, x1 = 0 }
1255b37d2b5c0819d9ef596c7baec1e0be0d7c45b547DeLesley Hutchins//   if (b) x = 1;       { x -> x2, y -> y1        | x2 = 1, y1 = 0, ... }
1256b37d2b5c0819d9ef596c7baec1e0be0d7c45b547DeLesley Hutchins//   else   x = 2;       { x -> x3, y -> y1        | x3 = 2, x2 = 1, ... }
1257b37d2b5c0819d9ef596c7baec1e0be0d7c45b547DeLesley Hutchins//   ...                 { y -> y1  (x is unknown) | x3 = 2, x2 = 1, ... }
1258b37d2b5c0819d9ef596c7baec1e0be0d7c45b547DeLesley Hutchins//
1259b37d2b5c0819d9ef596c7baec1e0be0d7c45b547DeLesley Hutchins// This is essentially a simpler and more naive version of the standard SSA
1260b37d2b5c0819d9ef596c7baec1e0be0d7c45b547DeLesley Hutchins// algorithm.  Those definitions that remain in the intersection are from blocks
1261b37d2b5c0819d9ef596c7baec1e0be0d7c45b547DeLesley Hutchins// that strictly dominate the current block.  We do not bother to insert proper
1262b37d2b5c0819d9ef596c7baec1e0be0d7c45b547DeLesley Hutchins// phi nodes, because they are not used in our analysis; instead, wherever
1263b37d2b5c0819d9ef596c7baec1e0be0d7c45b547DeLesley Hutchins// a phi node would be required, we simply remove that definition from the
1264b37d2b5c0819d9ef596c7baec1e0be0d7c45b547DeLesley Hutchins// context (E.g. x above).
1265b37d2b5c0819d9ef596c7baec1e0be0d7c45b547DeLesley Hutchins//
1266b37d2b5c0819d9ef596c7baec1e0be0d7c45b547DeLesley Hutchins// The initial traversal does not capture back-edges, so those need to be
1267b37d2b5c0819d9ef596c7baec1e0be0d7c45b547DeLesley Hutchins// handled on a separate pass.  Whenever the first pass encounters an
1268b37d2b5c0819d9ef596c7baec1e0be0d7c45b547DeLesley Hutchins// incoming back edge, it duplicates the context, creating new definitions
1269b37d2b5c0819d9ef596c7baec1e0be0d7c45b547DeLesley Hutchins// that refer back to the originals.  (These correspond to places where SSA
1270b37d2b5c0819d9ef596c7baec1e0be0d7c45b547DeLesley Hutchins// might have to insert a phi node.)  On the second pass, these definitions are
1271bed28ac1d1463adca3ecf24fca5c30646fa9dbb2Sylvestre Ledru// set to NULL if the variable has changed on the back-edge (i.e. a phi
1272b37d2b5c0819d9ef596c7baec1e0be0d7c45b547DeLesley Hutchins// node was actually required.)  E.g.
1273b37d2b5c0819d9ef596c7baec1e0be0d7c45b547DeLesley Hutchins//
1274b37d2b5c0819d9ef596c7baec1e0be0d7c45b547DeLesley Hutchins//                       { Context           | VarDefinitions }
1275b37d2b5c0819d9ef596c7baec1e0be0d7c45b547DeLesley Hutchins//   int x = 0, y = 0;   { x -> x1, y -> y1  | y1 = 0, x1 = 0 }
1276b37d2b5c0819d9ef596c7baec1e0be0d7c45b547DeLesley Hutchins//   while (b)           { x -> x2, y -> y1  | [1st:] x2=x1; [2nd:] x2=NULL; }
1277b37d2b5c0819d9ef596c7baec1e0be0d7c45b547DeLesley Hutchins//     x = x+1;          { x -> x3, y -> y1  | x3 = x2 + 1, ... }
1278b37d2b5c0819d9ef596c7baec1e0be0d7c45b547DeLesley Hutchins//   ...                 { y -> y1           | x3 = 2, x2 = 1, ... }
1279b37d2b5c0819d9ef596c7baec1e0be0d7c45b547DeLesley Hutchins//
1280b37d2b5c0819d9ef596c7baec1e0be0d7c45b547DeLesley Hutchinsvoid LocalVariableMap::traverseCFG(CFG *CFGraph,
12816bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines                                   const PostOrderCFGView *SortedGraph,
1282b37d2b5c0819d9ef596c7baec1e0be0d7c45b547DeLesley Hutchins                                   std::vector<CFGBlockInfo> &BlockInfo) {
1283b37d2b5c0819d9ef596c7baec1e0be0d7c45b547DeLesley Hutchins  PostOrderCFGView::CFGBlockSet VisitedBlocks(CFGraph);
1284b37d2b5c0819d9ef596c7baec1e0be0d7c45b547DeLesley Hutchins
1285b37d2b5c0819d9ef596c7baec1e0be0d7c45b547DeLesley Hutchins  CtxIndices.resize(CFGraph->getNumBlockIDs());
1286b37d2b5c0819d9ef596c7baec1e0be0d7c45b547DeLesley Hutchins
12876bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines  for (const auto *CurrBlock : *SortedGraph) {
1288b37d2b5c0819d9ef596c7baec1e0be0d7c45b547DeLesley Hutchins    int CurrBlockID = CurrBlock->getBlockID();
1289b37d2b5c0819d9ef596c7baec1e0be0d7c45b547DeLesley Hutchins    CFGBlockInfo *CurrBlockInfo = &BlockInfo[CurrBlockID];
1290b37d2b5c0819d9ef596c7baec1e0be0d7c45b547DeLesley Hutchins
1291b37d2b5c0819d9ef596c7baec1e0be0d7c45b547DeLesley Hutchins    VisitedBlocks.insert(CurrBlock);
1292b37d2b5c0819d9ef596c7baec1e0be0d7c45b547DeLesley Hutchins
1293b37d2b5c0819d9ef596c7baec1e0be0d7c45b547DeLesley Hutchins    // Calculate the entry context for the current block
1294b37d2b5c0819d9ef596c7baec1e0be0d7c45b547DeLesley Hutchins    bool HasBackEdges = false;
1295b37d2b5c0819d9ef596c7baec1e0be0d7c45b547DeLesley Hutchins    bool CtxInit = true;
1296b37d2b5c0819d9ef596c7baec1e0be0d7c45b547DeLesley Hutchins    for (CFGBlock::const_pred_iterator PI = CurrBlock->pred_begin(),
1297b37d2b5c0819d9ef596c7baec1e0be0d7c45b547DeLesley Hutchins         PE  = CurrBlock->pred_end(); PI != PE; ++PI) {
1298b37d2b5c0819d9ef596c7baec1e0be0d7c45b547DeLesley Hutchins      // if *PI -> CurrBlock is a back edge, so skip it
12996bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines      if (*PI == nullptr || !VisitedBlocks.alreadySet(*PI)) {
1300b37d2b5c0819d9ef596c7baec1e0be0d7c45b547DeLesley Hutchins        HasBackEdges = true;
1301b37d2b5c0819d9ef596c7baec1e0be0d7c45b547DeLesley Hutchins        continue;
1302b37d2b5c0819d9ef596c7baec1e0be0d7c45b547DeLesley Hutchins      }
1303b37d2b5c0819d9ef596c7baec1e0be0d7c45b547DeLesley Hutchins
1304b37d2b5c0819d9ef596c7baec1e0be0d7c45b547DeLesley Hutchins      int PrevBlockID = (*PI)->getBlockID();
1305b37d2b5c0819d9ef596c7baec1e0be0d7c45b547DeLesley Hutchins      CFGBlockInfo *PrevBlockInfo = &BlockInfo[PrevBlockID];
1306b37d2b5c0819d9ef596c7baec1e0be0d7c45b547DeLesley Hutchins
1307b37d2b5c0819d9ef596c7baec1e0be0d7c45b547DeLesley Hutchins      if (CtxInit) {
1308b37d2b5c0819d9ef596c7baec1e0be0d7c45b547DeLesley Hutchins        CurrBlockInfo->EntryContext = PrevBlockInfo->ExitContext;
1309b37d2b5c0819d9ef596c7baec1e0be0d7c45b547DeLesley Hutchins        CtxInit = false;
1310b37d2b5c0819d9ef596c7baec1e0be0d7c45b547DeLesley Hutchins      }
1311b37d2b5c0819d9ef596c7baec1e0be0d7c45b547DeLesley Hutchins      else {
1312b37d2b5c0819d9ef596c7baec1e0be0d7c45b547DeLesley Hutchins        CurrBlockInfo->EntryContext =
1313b37d2b5c0819d9ef596c7baec1e0be0d7c45b547DeLesley Hutchins          intersectContexts(CurrBlockInfo->EntryContext,
1314b37d2b5c0819d9ef596c7baec1e0be0d7c45b547DeLesley Hutchins                            PrevBlockInfo->ExitContext);
1315b37d2b5c0819d9ef596c7baec1e0be0d7c45b547DeLesley Hutchins      }
1316b37d2b5c0819d9ef596c7baec1e0be0d7c45b547DeLesley Hutchins    }
1317b37d2b5c0819d9ef596c7baec1e0be0d7c45b547DeLesley Hutchins
1318b37d2b5c0819d9ef596c7baec1e0be0d7c45b547DeLesley Hutchins    // Duplicate the context if we have back-edges, so we can call
1319b37d2b5c0819d9ef596c7baec1e0be0d7c45b547DeLesley Hutchins    // intersectBackEdges later.
1320b37d2b5c0819d9ef596c7baec1e0be0d7c45b547DeLesley Hutchins    if (HasBackEdges)
1321b37d2b5c0819d9ef596c7baec1e0be0d7c45b547DeLesley Hutchins      CurrBlockInfo->EntryContext =
1322b37d2b5c0819d9ef596c7baec1e0be0d7c45b547DeLesley Hutchins        createReferenceContext(CurrBlockInfo->EntryContext);
1323b37d2b5c0819d9ef596c7baec1e0be0d7c45b547DeLesley Hutchins
1324b37d2b5c0819d9ef596c7baec1e0be0d7c45b547DeLesley Hutchins    // Create a starting context index for the current block
13256bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines    saveContext(nullptr, CurrBlockInfo->EntryContext);
1326b37d2b5c0819d9ef596c7baec1e0be0d7c45b547DeLesley Hutchins    CurrBlockInfo->EntryIndex = getContextIndex();
1327b37d2b5c0819d9ef596c7baec1e0be0d7c45b547DeLesley Hutchins
1328b37d2b5c0819d9ef596c7baec1e0be0d7c45b547DeLesley Hutchins    // Visit all the statements in the basic block.
1329b37d2b5c0819d9ef596c7baec1e0be0d7c45b547DeLesley Hutchins    VarMapBuilder VMapBuilder(this, CurrBlockInfo->EntryContext);
1330b37d2b5c0819d9ef596c7baec1e0be0d7c45b547DeLesley Hutchins    for (CFGBlock::const_iterator BI = CurrBlock->begin(),
1331b37d2b5c0819d9ef596c7baec1e0be0d7c45b547DeLesley Hutchins         BE = CurrBlock->end(); BI != BE; ++BI) {
1332b37d2b5c0819d9ef596c7baec1e0be0d7c45b547DeLesley Hutchins      switch (BI->getKind()) {
1333b37d2b5c0819d9ef596c7baec1e0be0d7c45b547DeLesley Hutchins        case CFGElement::Statement: {
1334fdf6a279c9a75c778eba382d9a156697092982a1David Blaikie          CFGStmt CS = BI->castAs<CFGStmt>();
1335fdf6a279c9a75c778eba382d9a156697092982a1David Blaikie          VMapBuilder.Visit(const_cast<Stmt*>(CS.getStmt()));
1336b37d2b5c0819d9ef596c7baec1e0be0d7c45b547DeLesley Hutchins          break;
1337b37d2b5c0819d9ef596c7baec1e0be0d7c45b547DeLesley Hutchins        }
1338b37d2b5c0819d9ef596c7baec1e0be0d7c45b547DeLesley Hutchins        default:
1339b37d2b5c0819d9ef596c7baec1e0be0d7c45b547DeLesley Hutchins          break;
1340b37d2b5c0819d9ef596c7baec1e0be0d7c45b547DeLesley Hutchins      }
1341b37d2b5c0819d9ef596c7baec1e0be0d7c45b547DeLesley Hutchins    }
1342b37d2b5c0819d9ef596c7baec1e0be0d7c45b547DeLesley Hutchins    CurrBlockInfo->ExitContext = VMapBuilder.Ctx;
1343b37d2b5c0819d9ef596c7baec1e0be0d7c45b547DeLesley Hutchins
1344b37d2b5c0819d9ef596c7baec1e0be0d7c45b547DeLesley Hutchins    // Mark variables on back edges as "unknown" if they've been changed.
1345b37d2b5c0819d9ef596c7baec1e0be0d7c45b547DeLesley Hutchins    for (CFGBlock::const_succ_iterator SI = CurrBlock->succ_begin(),
1346b37d2b5c0819d9ef596c7baec1e0be0d7c45b547DeLesley Hutchins         SE  = CurrBlock->succ_end(); SI != SE; ++SI) {
1347b37d2b5c0819d9ef596c7baec1e0be0d7c45b547DeLesley Hutchins      // if CurrBlock -> *SI is *not* a back edge
13486bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines      if (*SI == nullptr || !VisitedBlocks.alreadySet(*SI))
1349b37d2b5c0819d9ef596c7baec1e0be0d7c45b547DeLesley Hutchins        continue;
1350b37d2b5c0819d9ef596c7baec1e0be0d7c45b547DeLesley Hutchins
1351b37d2b5c0819d9ef596c7baec1e0be0d7c45b547DeLesley Hutchins      CFGBlock *FirstLoopBlock = *SI;
1352b37d2b5c0819d9ef596c7baec1e0be0d7c45b547DeLesley Hutchins      Context LoopBegin = BlockInfo[FirstLoopBlock->getBlockID()].EntryContext;
1353b37d2b5c0819d9ef596c7baec1e0be0d7c45b547DeLesley Hutchins      Context LoopEnd   = CurrBlockInfo->ExitContext;
1354b37d2b5c0819d9ef596c7baec1e0be0d7c45b547DeLesley Hutchins      intersectBackEdge(LoopBegin, LoopEnd);
1355b37d2b5c0819d9ef596c7baec1e0be0d7c45b547DeLesley Hutchins    }
1356b37d2b5c0819d9ef596c7baec1e0be0d7c45b547DeLesley Hutchins  }
1357b37d2b5c0819d9ef596c7baec1e0be0d7c45b547DeLesley Hutchins
1358b37d2b5c0819d9ef596c7baec1e0be0d7c45b547DeLesley Hutchins  // Put an extra entry at the end of the indexed context array
1359b37d2b5c0819d9ef596c7baec1e0be0d7c45b547DeLesley Hutchins  unsigned exitID = CFGraph->getExit().getBlockID();
13606bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines  saveContext(nullptr, BlockInfo[exitID].ExitContext);
1361b37d2b5c0819d9ef596c7baec1e0be0d7c45b547DeLesley Hutchins}
1362b37d2b5c0819d9ef596c7baec1e0be0d7c45b547DeLesley Hutchins
13632e5156274b8051217565b557bfa14c80f7990e9cRichard Smith/// Find the appropriate source locations to use when producing diagnostics for
13642e5156274b8051217565b557bfa14c80f7990e9cRichard Smith/// each block in the CFG.
13652e5156274b8051217565b557bfa14c80f7990e9cRichard Smithstatic void findBlockLocations(CFG *CFGraph,
13666bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines                               const PostOrderCFGView *SortedGraph,
13672e5156274b8051217565b557bfa14c80f7990e9cRichard Smith                               std::vector<CFGBlockInfo> &BlockInfo) {
13686bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines  for (const auto *CurrBlock : *SortedGraph) {
13692e5156274b8051217565b557bfa14c80f7990e9cRichard Smith    CFGBlockInfo *CurrBlockInfo = &BlockInfo[CurrBlock->getBlockID()];
13702e5156274b8051217565b557bfa14c80f7990e9cRichard Smith
13712e5156274b8051217565b557bfa14c80f7990e9cRichard Smith    // Find the source location of the last statement in the block, if the
13722e5156274b8051217565b557bfa14c80f7990e9cRichard Smith    // block is not empty.
13732e5156274b8051217565b557bfa14c80f7990e9cRichard Smith    if (const Stmt *S = CurrBlock->getTerminator()) {
13742e5156274b8051217565b557bfa14c80f7990e9cRichard Smith      CurrBlockInfo->EntryLoc = CurrBlockInfo->ExitLoc = S->getLocStart();
13752e5156274b8051217565b557bfa14c80f7990e9cRichard Smith    } else {
13762e5156274b8051217565b557bfa14c80f7990e9cRichard Smith      for (CFGBlock::const_reverse_iterator BI = CurrBlock->rbegin(),
13772e5156274b8051217565b557bfa14c80f7990e9cRichard Smith           BE = CurrBlock->rend(); BI != BE; ++BI) {
13782e5156274b8051217565b557bfa14c80f7990e9cRichard Smith        // FIXME: Handle other CFGElement kinds.
1379b07805485c603be3d8011f72611465324c9e664bDavid Blaikie        if (Optional<CFGStmt> CS = BI->getAs<CFGStmt>()) {
1380b07805485c603be3d8011f72611465324c9e664bDavid Blaikie          CurrBlockInfo->ExitLoc = CS->getStmt()->getLocStart();
13812e5156274b8051217565b557bfa14c80f7990e9cRichard Smith          break;
13822e5156274b8051217565b557bfa14c80f7990e9cRichard Smith        }
13832e5156274b8051217565b557bfa14c80f7990e9cRichard Smith      }
13842e5156274b8051217565b557bfa14c80f7990e9cRichard Smith    }
13852e5156274b8051217565b557bfa14c80f7990e9cRichard Smith
13862e5156274b8051217565b557bfa14c80f7990e9cRichard Smith    if (!CurrBlockInfo->ExitLoc.isInvalid()) {
13872e5156274b8051217565b557bfa14c80f7990e9cRichard Smith      // This block contains at least one statement. Find the source location
13882e5156274b8051217565b557bfa14c80f7990e9cRichard Smith      // of the first statement in the block.
13892e5156274b8051217565b557bfa14c80f7990e9cRichard Smith      for (CFGBlock::const_iterator BI = CurrBlock->begin(),
13902e5156274b8051217565b557bfa14c80f7990e9cRichard Smith           BE = CurrBlock->end(); BI != BE; ++BI) {
13912e5156274b8051217565b557bfa14c80f7990e9cRichard Smith        // FIXME: Handle other CFGElement kinds.
1392b07805485c603be3d8011f72611465324c9e664bDavid Blaikie        if (Optional<CFGStmt> CS = BI->getAs<CFGStmt>()) {
1393b07805485c603be3d8011f72611465324c9e664bDavid Blaikie          CurrBlockInfo->EntryLoc = CS->getStmt()->getLocStart();
13942e5156274b8051217565b557bfa14c80f7990e9cRichard Smith          break;
13952e5156274b8051217565b557bfa14c80f7990e9cRichard Smith        }
13962e5156274b8051217565b557bfa14c80f7990e9cRichard Smith      }
13972e5156274b8051217565b557bfa14c80f7990e9cRichard Smith    } else if (CurrBlock->pred_size() == 1 && *CurrBlock->pred_begin() &&
13982e5156274b8051217565b557bfa14c80f7990e9cRichard Smith               CurrBlock != &CFGraph->getExit()) {
13992e5156274b8051217565b557bfa14c80f7990e9cRichard Smith      // The block is empty, and has a single predecessor. Use its exit
14002e5156274b8051217565b557bfa14c80f7990e9cRichard Smith      // location.
14012e5156274b8051217565b557bfa14c80f7990e9cRichard Smith      CurrBlockInfo->EntryLoc = CurrBlockInfo->ExitLoc =
14022e5156274b8051217565b557bfa14c80f7990e9cRichard Smith          BlockInfo[(*CurrBlock->pred_begin())->getBlockID()].ExitLoc;
14032e5156274b8051217565b557bfa14c80f7990e9cRichard Smith    }
14042e5156274b8051217565b557bfa14c80f7990e9cRichard Smith  }
14052e5156274b8051217565b557bfa14c80f7990e9cRichard Smith}
1406b37d2b5c0819d9ef596c7baec1e0be0d7c45b547DeLesley Hutchins
1407b37d2b5c0819d9ef596c7baec1e0be0d7c45b547DeLesley Hutchins/// \brief Class which implements the core thread safety analysis routines.
1408b37d2b5c0819d9ef596c7baec1e0be0d7c45b547DeLesley Hutchinsclass ThreadSafetyAnalyzer {
1409b37d2b5c0819d9ef596c7baec1e0be0d7c45b547DeLesley Hutchins  friend class BuildLockset;
1410b37d2b5c0819d9ef596c7baec1e0be0d7c45b547DeLesley Hutchins
141154c350a67b47f059e1d577bdd9e2d1dc31ff82b5DeLesley Hutchins  ThreadSafetyHandler       &Handler;
141254c350a67b47f059e1d577bdd9e2d1dc31ff82b5DeLesley Hutchins  LocalVariableMap          LocalVarMap;
1413a1fa47139d6e9e7dcc40f2809605d1a258624e7fDeLesley Hutchins  FactManager               FactMan;
141454c350a67b47f059e1d577bdd9e2d1dc31ff82b5DeLesley Hutchins  std::vector<CFGBlockInfo> BlockInfo;
1415b37d2b5c0819d9ef596c7baec1e0be0d7c45b547DeLesley Hutchins
1416b37d2b5c0819d9ef596c7baec1e0be0d7c45b547DeLesley Hutchinspublic:
1417b37d2b5c0819d9ef596c7baec1e0be0d7c45b547DeLesley Hutchins  ThreadSafetyAnalyzer(ThreadSafetyHandler &H) : Handler(H) {}
1418b37d2b5c0819d9ef596c7baec1e0be0d7c45b547DeLesley Hutchins
1419651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines  void addLock(FactSet &FSet, const SExpr &Mutex, const LockData &LDat,
1420651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines               StringRef DiagKind);
1421651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines  void removeLock(FactSet &FSet, const SExpr &Mutex, SourceLocation UnlockLoc,
1422651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines                  bool FullyRemove, LockKind Kind, StringRef DiagKind);
1423a60448d6dfc91f4c30987e237bf70ef50ac7705bDeLesley Hutchins
14245381c05f51e5b7c7627f1d95b9a3425303ce086aDeLesley Hutchins  template <typename AttrType>
14255381c05f51e5b7c7627f1d95b9a3425303ce086aDeLesley Hutchins  void getMutexIDs(MutexIDList &Mtxs, AttrType *Attr, Expr *Exp,
14266bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines                   const NamedDecl *D, VarDecl *SelfDecl = nullptr);
1427402aa0698fec81e574818a0a6c2000fac0b2c4c6Caitlin Sadowski
1428b4fa418a72759dfe34add850837965cbc00626e4DeLesley Hutchins  template <class AttrType>
14295381c05f51e5b7c7627f1d95b9a3425303ce086aDeLesley Hutchins  void getMutexIDs(MutexIDList &Mtxs, AttrType *Attr, Expr *Exp,
14305381c05f51e5b7c7627f1d95b9a3425303ce086aDeLesley Hutchins                   const NamedDecl *D,
14315381c05f51e5b7c7627f1d95b9a3425303ce086aDeLesley Hutchins                   const CFGBlock *PredBlock, const CFGBlock *CurrBlock,
14325381c05f51e5b7c7627f1d95b9a3425303ce086aDeLesley Hutchins                   Expr *BrE, bool Neg);
14335381c05f51e5b7c7627f1d95b9a3425303ce086aDeLesley Hutchins
143454c350a67b47f059e1d577bdd9e2d1dc31ff82b5DeLesley Hutchins  const CallExpr* getTrylockCallExpr(const Stmt *Cond, LocalVarContext C,
143554c350a67b47f059e1d577bdd9e2d1dc31ff82b5DeLesley Hutchins                                     bool &Negate);
1436b4fa418a72759dfe34add850837965cbc00626e4DeLesley Hutchins
1437a1fa47139d6e9e7dcc40f2809605d1a258624e7fDeLesley Hutchins  void getEdgeLockset(FactSet &Result, const FactSet &ExitSet,
1438a1fa47139d6e9e7dcc40f2809605d1a258624e7fDeLesley Hutchins                      const CFGBlock* PredBlock,
1439a1fa47139d6e9e7dcc40f2809605d1a258624e7fDeLesley Hutchins                      const CFGBlock *CurrBlock);
14400da4414f3d30c34fafb81b13b2cec3680c0bc9e1DeLesley Hutchins
1441a1fa47139d6e9e7dcc40f2809605d1a258624e7fDeLesley Hutchins  void intersectAndWarn(FactSet &FSet1, const FactSet &FSet2,
1442a1fa47139d6e9e7dcc40f2809605d1a258624e7fDeLesley Hutchins                        SourceLocation JoinLoc,
1443a1fa47139d6e9e7dcc40f2809605d1a258624e7fDeLesley Hutchins                        LockErrorKind LEK1, LockErrorKind LEK2,
1444a1fa47139d6e9e7dcc40f2809605d1a258624e7fDeLesley Hutchins                        bool Modify=true);
1445879a4334e4c4cab0c22ba91492ffc2838bbc21fcDeLesley Hutchins
1446a1fa47139d6e9e7dcc40f2809605d1a258624e7fDeLesley Hutchins  void intersectAndWarn(FactSet &FSet1, const FactSet &FSet2,
1447a1fa47139d6e9e7dcc40f2809605d1a258624e7fDeLesley Hutchins                        SourceLocation JoinLoc, LockErrorKind LEK1,
1448a1fa47139d6e9e7dcc40f2809605d1a258624e7fDeLesley Hutchins                        bool Modify=true) {
1449a1fa47139d6e9e7dcc40f2809605d1a258624e7fDeLesley Hutchins    intersectAndWarn(FSet1, FSet2, JoinLoc, LEK1, LEK1, Modify);
1450879a4334e4c4cab0c22ba91492ffc2838bbc21fcDeLesley Hutchins  }
1451402aa0698fec81e574818a0a6c2000fac0b2c4c6Caitlin Sadowski
145254c350a67b47f059e1d577bdd9e2d1dc31ff82b5DeLesley Hutchins  void runAnalysis(AnalysisDeclContext &AC);
1453402aa0698fec81e574818a0a6c2000fac0b2c4c6Caitlin Sadowski};
1454402aa0698fec81e574818a0a6c2000fac0b2c4c6Caitlin Sadowski
1455651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines/// \brief Gets the value decl pointer from DeclRefExprs or MemberExprs.
1456651f13cea278ec967336033dd032faef0e9fc2ecStephen Hinesstatic const ValueDecl *getValueDecl(const Expr *Exp) {
1457651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines  if (const auto *CE = dyn_cast<ImplicitCastExpr>(Exp))
1458651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines    return getValueDecl(CE->getSubExpr());
1459651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines
1460651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines  if (const auto *DR = dyn_cast<DeclRefExpr>(Exp))
1461651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines    return DR->getDecl();
1462651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines
1463651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines  if (const auto *ME = dyn_cast<MemberExpr>(Exp))
1464651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines    return ME->getMemberDecl();
1465651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines
1466651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines  return nullptr;
1467651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines}
1468651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines
1469651f13cea278ec967336033dd032faef0e9fc2ecStephen Hinestemplate <typename Ty>
14706bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hinesclass has_arg_iterator_range {
1471651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines  typedef char yes[1];
1472651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines  typedef char no[2];
1473651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines
1474651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines  template <typename Inner>
14756bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines  static yes& test(Inner *I, decltype(I->args()) * = nullptr);
1476651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines
1477651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines  template <typename>
1478651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines  static no& test(...);
1479651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines
1480651f13cea278ec967336033dd032faef0e9fc2ecStephen Hinespublic:
1481651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines  static const bool value = sizeof(test<Ty>(nullptr)) == sizeof(yes);
1482651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines};
1483651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines
1484651f13cea278ec967336033dd032faef0e9fc2ecStephen Hinesstatic StringRef ClassifyDiagnostic(const CapabilityAttr *A) {
1485651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines  return A->getName();
1486651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines}
1487651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines
1488651f13cea278ec967336033dd032faef0e9fc2ecStephen Hinesstatic StringRef ClassifyDiagnostic(QualType VDT) {
1489651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines  // We need to look at the declaration of the type of the value to determine
1490651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines  // which it is. The type should either be a record or a typedef, or a pointer
1491651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines  // or reference thereof.
1492651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines  if (const auto *RT = VDT->getAs<RecordType>()) {
1493651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines    if (const auto *RD = RT->getDecl())
1494651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines      if (const auto *CA = RD->getAttr<CapabilityAttr>())
1495651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines        return ClassifyDiagnostic(CA);
1496651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines  } else if (const auto *TT = VDT->getAs<TypedefType>()) {
1497651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines    if (const auto *TD = TT->getDecl())
1498651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines      if (const auto *CA = TD->getAttr<CapabilityAttr>())
1499651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines        return ClassifyDiagnostic(CA);
1500651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines  } else if (VDT->isPointerType() || VDT->isReferenceType())
1501651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines    return ClassifyDiagnostic(VDT->getPointeeType());
1502651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines
1503651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines  return "mutex";
1504651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines}
1505651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines
1506651f13cea278ec967336033dd032faef0e9fc2ecStephen Hinesstatic StringRef ClassifyDiagnostic(const ValueDecl *VD) {
1507651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines  assert(VD && "No ValueDecl passed");
1508651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines
1509651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines  // The ValueDecl is the declaration of a mutex or role (hopefully).
1510651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines  return ClassifyDiagnostic(VD->getType());
1511651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines}
1512651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines
1513651f13cea278ec967336033dd032faef0e9fc2ecStephen Hinestemplate <typename AttrTy>
15146bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hinesstatic typename std::enable_if<!has_arg_iterator_range<AttrTy>::value,
1515651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines                               StringRef>::type
1516651f13cea278ec967336033dd032faef0e9fc2ecStephen HinesClassifyDiagnostic(const AttrTy *A) {
1517651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines  if (const ValueDecl *VD = getValueDecl(A->getArg()))
1518651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines    return ClassifyDiagnostic(VD);
1519651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines  return "mutex";
1520651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines}
1521651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines
1522651f13cea278ec967336033dd032faef0e9fc2ecStephen Hinestemplate <typename AttrTy>
15236bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hinesstatic typename std::enable_if<has_arg_iterator_range<AttrTy>::value,
1524651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines                               StringRef>::type
1525651f13cea278ec967336033dd032faef0e9fc2ecStephen HinesClassifyDiagnostic(const AttrTy *A) {
15266bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines  for (const auto *Arg : A->args()) {
15276bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines    if (const ValueDecl *VD = getValueDecl(Arg))
1528651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines      return ClassifyDiagnostic(VD);
1529651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines  }
1530651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines  return "mutex";
1531651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines}
153254c350a67b47f059e1d577bdd9e2d1dc31ff82b5DeLesley Hutchins
1533402aa0698fec81e574818a0a6c2000fac0b2c4c6Caitlin Sadowski/// \brief Add a new lock to the lockset, warning if the lock is already there.
15341fa3c0682a52c45c4ad0be3a82d0c85f26657072DeLesley Hutchins/// \param Mutex -- the Mutex expression for the lock
15351fa3c0682a52c45c4ad0be3a82d0c85f26657072DeLesley Hutchins/// \param LDat  -- the LockData for the lock
1536a74b715cdc37c4523818a4018faae99d977aa537DeLesley Hutchinsvoid ThreadSafetyAnalyzer::addLock(FactSet &FSet, const SExpr &Mutex,
1537651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines                                   const LockData &LDat, StringRef DiagKind) {
15381fa3c0682a52c45c4ad0be3a82d0c85f26657072DeLesley Hutchins  // FIXME: deal with acquired before/after annotations.
1539402aa0698fec81e574818a0a6c2000fac0b2c4c6Caitlin Sadowski  // FIXME: Don't always warn when we have support for reentrant locks.
15404e4c15765d5f097e21dcaa30f1a94481924340f7DeLesley Hutchins  if (Mutex.shouldIgnore())
15414e4c15765d5f097e21dcaa30f1a94481924340f7DeLesley Hutchins    return;
15424e4c15765d5f097e21dcaa30f1a94481924340f7DeLesley Hutchins
1543a1fa47139d6e9e7dcc40f2809605d1a258624e7fDeLesley Hutchins  if (FSet.findLock(FactMan, Mutex)) {
15445c6134fd09bc5b738dafdd1c774edde13d95cb20DeLesley Hutchins    if (!LDat.Asserted)
1545651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines      Handler.handleDoubleLock(DiagKind, Mutex.toString(), LDat.AcquireLoc);
154654c350a67b47f059e1d577bdd9e2d1dc31ff82b5DeLesley Hutchins  } else {
1547a1fa47139d6e9e7dcc40f2809605d1a258624e7fDeLesley Hutchins    FSet.addLock(FactMan, Mutex, LDat);
154854c350a67b47f059e1d577bdd9e2d1dc31ff82b5DeLesley Hutchins  }
154954c350a67b47f059e1d577bdd9e2d1dc31ff82b5DeLesley Hutchins}
155054c350a67b47f059e1d577bdd9e2d1dc31ff82b5DeLesley Hutchins
155154c350a67b47f059e1d577bdd9e2d1dc31ff82b5DeLesley Hutchins
1552402aa0698fec81e574818a0a6c2000fac0b2c4c6Caitlin Sadowski/// \brief Remove a lock from the lockset, warning if the lock is not there.
1553ad0fe03b897f9486191e75c8d90c3ffa9b4fd6a5Ted Kremenek/// \param Mutex The lock expression corresponding to the lock to be removed
1554402aa0698fec81e574818a0a6c2000fac0b2c4c6Caitlin Sadowski/// \param UnlockLoc The source location of the unlock (only used in error msg)
1555651f13cea278ec967336033dd032faef0e9fc2ecStephen Hinesvoid ThreadSafetyAnalyzer::removeLock(FactSet &FSet, const SExpr &Mutex,
1556a1fa47139d6e9e7dcc40f2809605d1a258624e7fDeLesley Hutchins                                      SourceLocation UnlockLoc,
1557651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines                                      bool FullyRemove, LockKind ReceivedKind,
1558651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines                                      StringRef DiagKind) {
15594e4c15765d5f097e21dcaa30f1a94481924340f7DeLesley Hutchins  if (Mutex.shouldIgnore())
15604e4c15765d5f097e21dcaa30f1a94481924340f7DeLesley Hutchins    return;
15614e4c15765d5f097e21dcaa30f1a94481924340f7DeLesley Hutchins
1562a1fa47139d6e9e7dcc40f2809605d1a258624e7fDeLesley Hutchins  const LockData *LDat = FSet.findLock(FactMan, Mutex);
156354c350a67b47f059e1d577bdd9e2d1dc31ff82b5DeLesley Hutchins  if (!LDat) {
1564651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines    Handler.handleUnmatchedUnlock(DiagKind, Mutex.toString(), UnlockLoc);
1565651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines    return;
1566651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines  }
1567651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines
1568651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines  // Generic lock removal doesn't care about lock kind mismatches, but
1569651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines  // otherwise diagnose when the lock kinds are mismatched.
1570651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines  if (ReceivedKind != LK_Generic && LDat->LKind != ReceivedKind) {
1571651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines    Handler.handleIncorrectUnlockKind(DiagKind, Mutex.toString(), LDat->LKind,
1572651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines                                      ReceivedKind, UnlockLoc);
1573a1fa47139d6e9e7dcc40f2809605d1a258624e7fDeLesley Hutchins    return;
157454c350a67b47f059e1d577bdd9e2d1dc31ff82b5DeLesley Hutchins  }
1575a1fa47139d6e9e7dcc40f2809605d1a258624e7fDeLesley Hutchins
15765381c05f51e5b7c7627f1d95b9a3425303ce086aDeLesley Hutchins  if (LDat->UnderlyingMutex.isValid()) {
15775381c05f51e5b7c7627f1d95b9a3425303ce086aDeLesley Hutchins    // This is scoped lockable object, which manages the real mutex.
15785381c05f51e5b7c7627f1d95b9a3425303ce086aDeLesley Hutchins    if (FullyRemove) {
15795381c05f51e5b7c7627f1d95b9a3425303ce086aDeLesley Hutchins      // We're destroying the managing object.
15805381c05f51e5b7c7627f1d95b9a3425303ce086aDeLesley Hutchins      // Remove the underlying mutex if it exists; but don't warn.
1581a1fa47139d6e9e7dcc40f2809605d1a258624e7fDeLesley Hutchins      if (FSet.findLock(FactMan, LDat->UnderlyingMutex))
1582a1fa47139d6e9e7dcc40f2809605d1a258624e7fDeLesley Hutchins        FSet.removeLock(FactMan, LDat->UnderlyingMutex);
15835381c05f51e5b7c7627f1d95b9a3425303ce086aDeLesley Hutchins    } else {
15845381c05f51e5b7c7627f1d95b9a3425303ce086aDeLesley Hutchins      // We're releasing the underlying mutex, but not destroying the
15855381c05f51e5b7c7627f1d95b9a3425303ce086aDeLesley Hutchins      // managing object.  Warn on dual release.
1586a1fa47139d6e9e7dcc40f2809605d1a258624e7fDeLesley Hutchins      if (!FSet.findLock(FactMan, LDat->UnderlyingMutex)) {
1587651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines        Handler.handleUnmatchedUnlock(
1588651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines            DiagKind, LDat->UnderlyingMutex.toString(), UnlockLoc);
15895381c05f51e5b7c7627f1d95b9a3425303ce086aDeLesley Hutchins      }
1590a1fa47139d6e9e7dcc40f2809605d1a258624e7fDeLesley Hutchins      FSet.removeLock(FactMan, LDat->UnderlyingMutex);
1591a1fa47139d6e9e7dcc40f2809605d1a258624e7fDeLesley Hutchins      return;
1592c99a5d820ead4e4f1f4b4a8ab61007b8da0307e6DeLesley Hutchins    }
15931fa3c0682a52c45c4ad0be3a82d0c85f26657072DeLesley Hutchins  }
1594a1fa47139d6e9e7dcc40f2809605d1a258624e7fDeLesley Hutchins  FSet.removeLock(FactMan, Mutex);
1595402aa0698fec81e574818a0a6c2000fac0b2c4c6Caitlin Sadowski}
1596402aa0698fec81e574818a0a6c2000fac0b2c4c6Caitlin Sadowski
1597c99a5d820ead4e4f1f4b4a8ab61007b8da0307e6DeLesley Hutchins
15985381c05f51e5b7c7627f1d95b9a3425303ce086aDeLesley Hutchins/// \brief Extract the list of mutexIDs from the attribute on an expression,
15995381c05f51e5b7c7627f1d95b9a3425303ce086aDeLesley Hutchins/// and push them onto Mtxs, discarding any duplicates.
1600a60448d6dfc91f4c30987e237bf70ef50ac7705bDeLesley Hutchinstemplate <typename AttrType>
16015381c05f51e5b7c7627f1d95b9a3425303ce086aDeLesley Hutchinsvoid ThreadSafetyAnalyzer::getMutexIDs(MutexIDList &Mtxs, AttrType *Attr,
1602ef2388b10c41a9696d5d81f42ca79ff005fef7fcDeLesley Hutchins                                       Expr *Exp, const NamedDecl *D,
1603ef2388b10c41a9696d5d81f42ca79ff005fef7fcDeLesley Hutchins                                       VarDecl *SelfDecl) {
1604a60448d6dfc91f4c30987e237bf70ef50ac7705bDeLesley Hutchins  if (Attr->args_size() == 0) {
1605a60448d6dfc91f4c30987e237bf70ef50ac7705bDeLesley Hutchins    // The mutex held is the "this" object.
16066bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines    SExpr Mu(nullptr, Exp, D, SelfDecl);
16075381c05f51e5b7c7627f1d95b9a3425303ce086aDeLesley Hutchins    if (!Mu.isValid())
16086bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines      SExpr::warnInvalidLock(Handler, nullptr, Exp, D,
16096bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines                             ClassifyDiagnostic(Attr));
16105381c05f51e5b7c7627f1d95b9a3425303ce086aDeLesley Hutchins    else
16115381c05f51e5b7c7627f1d95b9a3425303ce086aDeLesley Hutchins      Mtxs.push_back_nodup(Mu);
16125381c05f51e5b7c7627f1d95b9a3425303ce086aDeLesley Hutchins    return;
1613a60448d6dfc91f4c30987e237bf70ef50ac7705bDeLesley Hutchins  }
1614a60448d6dfc91f4c30987e237bf70ef50ac7705bDeLesley Hutchins
16156bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines  for (const auto *Arg : Attr->args()) {
16166bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines    SExpr Mu(Arg, Exp, D, SelfDecl);
16175381c05f51e5b7c7627f1d95b9a3425303ce086aDeLesley Hutchins    if (!Mu.isValid())
16186bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines      SExpr::warnInvalidLock(Handler, Arg, Exp, D, ClassifyDiagnostic(Attr));
1619f1ac63702143d84db778d32eb185a77fc97db5f5DeLesley Hutchins    else
16205381c05f51e5b7c7627f1d95b9a3425303ce086aDeLesley Hutchins      Mtxs.push_back_nodup(Mu);
162154c350a67b47f059e1d577bdd9e2d1dc31ff82b5DeLesley Hutchins  }
162254c350a67b47f059e1d577bdd9e2d1dc31ff82b5DeLesley Hutchins}
162354c350a67b47f059e1d577bdd9e2d1dc31ff82b5DeLesley Hutchins
162454c350a67b47f059e1d577bdd9e2d1dc31ff82b5DeLesley Hutchins
16255381c05f51e5b7c7627f1d95b9a3425303ce086aDeLesley Hutchins/// \brief Extract the list of mutexIDs from a trylock attribute.  If the
16265381c05f51e5b7c7627f1d95b9a3425303ce086aDeLesley Hutchins/// trylock applies to the given edge, then push them onto Mtxs, discarding
16275381c05f51e5b7c7627f1d95b9a3425303ce086aDeLesley Hutchins/// any duplicates.
162854c350a67b47f059e1d577bdd9e2d1dc31ff82b5DeLesley Hutchinstemplate <class AttrType>
16295381c05f51e5b7c7627f1d95b9a3425303ce086aDeLesley Hutchinsvoid ThreadSafetyAnalyzer::getMutexIDs(MutexIDList &Mtxs, AttrType *Attr,
16305381c05f51e5b7c7627f1d95b9a3425303ce086aDeLesley Hutchins                                       Expr *Exp, const NamedDecl *D,
16315381c05f51e5b7c7627f1d95b9a3425303ce086aDeLesley Hutchins                                       const CFGBlock *PredBlock,
16325381c05f51e5b7c7627f1d95b9a3425303ce086aDeLesley Hutchins                                       const CFGBlock *CurrBlock,
16335381c05f51e5b7c7627f1d95b9a3425303ce086aDeLesley Hutchins                                       Expr *BrE, bool Neg) {
163454c350a67b47f059e1d577bdd9e2d1dc31ff82b5DeLesley Hutchins  // Find out which branch has the lock
16356bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines  bool branch = false;
16366bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines  if (CXXBoolLiteralExpr *BLE = dyn_cast_or_null<CXXBoolLiteralExpr>(BrE))
163754c350a67b47f059e1d577bdd9e2d1dc31ff82b5DeLesley Hutchins    branch = BLE->getValue();
16386bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines  else if (IntegerLiteral *ILE = dyn_cast_or_null<IntegerLiteral>(BrE))
163954c350a67b47f059e1d577bdd9e2d1dc31ff82b5DeLesley Hutchins    branch = ILE->getValue().getBoolValue();
16406bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines
164154c350a67b47f059e1d577bdd9e2d1dc31ff82b5DeLesley Hutchins  int branchnum = branch ? 0 : 1;
16426bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines  if (Neg)
16436bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines    branchnum = !branchnum;
164454c350a67b47f059e1d577bdd9e2d1dc31ff82b5DeLesley Hutchins
164554c350a67b47f059e1d577bdd9e2d1dc31ff82b5DeLesley Hutchins  // If we've taken the trylock branch, then add the lock
164654c350a67b47f059e1d577bdd9e2d1dc31ff82b5DeLesley Hutchins  int i = 0;
164754c350a67b47f059e1d577bdd9e2d1dc31ff82b5DeLesley Hutchins  for (CFGBlock::const_succ_iterator SI = PredBlock->succ_begin(),
164854c350a67b47f059e1d577bdd9e2d1dc31ff82b5DeLesley Hutchins       SE = PredBlock->succ_end(); SI != SE && i < 2; ++SI, ++i) {
16496bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines    if (*SI == CurrBlock && i == branchnum)
16505381c05f51e5b7c7627f1d95b9a3425303ce086aDeLesley Hutchins      getMutexIDs(Mtxs, Attr, Exp, D);
165154c350a67b47f059e1d577bdd9e2d1dc31ff82b5DeLesley Hutchins  }
165254c350a67b47f059e1d577bdd9e2d1dc31ff82b5DeLesley Hutchins}
165354c350a67b47f059e1d577bdd9e2d1dc31ff82b5DeLesley Hutchins
165454c350a67b47f059e1d577bdd9e2d1dc31ff82b5DeLesley Hutchins
165513106117060c90d6f84bd2ed7a5c03e0502ff419DeLesley Hutchinsbool getStaticBooleanValue(Expr* E, bool& TCond) {
165613106117060c90d6f84bd2ed7a5c03e0502ff419DeLesley Hutchins  if (isa<CXXNullPtrLiteralExpr>(E) || isa<GNUNullExpr>(E)) {
165713106117060c90d6f84bd2ed7a5c03e0502ff419DeLesley Hutchins    TCond = false;
165813106117060c90d6f84bd2ed7a5c03e0502ff419DeLesley Hutchins    return true;
165913106117060c90d6f84bd2ed7a5c03e0502ff419DeLesley Hutchins  } else if (CXXBoolLiteralExpr *BLE = dyn_cast<CXXBoolLiteralExpr>(E)) {
166013106117060c90d6f84bd2ed7a5c03e0502ff419DeLesley Hutchins    TCond = BLE->getValue();
166113106117060c90d6f84bd2ed7a5c03e0502ff419DeLesley Hutchins    return true;
166213106117060c90d6f84bd2ed7a5c03e0502ff419DeLesley Hutchins  } else if (IntegerLiteral *ILE = dyn_cast<IntegerLiteral>(E)) {
166313106117060c90d6f84bd2ed7a5c03e0502ff419DeLesley Hutchins    TCond = ILE->getValue().getBoolValue();
166413106117060c90d6f84bd2ed7a5c03e0502ff419DeLesley Hutchins    return true;
166513106117060c90d6f84bd2ed7a5c03e0502ff419DeLesley Hutchins  } else if (ImplicitCastExpr *CE = dyn_cast<ImplicitCastExpr>(E)) {
166613106117060c90d6f84bd2ed7a5c03e0502ff419DeLesley Hutchins    return getStaticBooleanValue(CE->getSubExpr(), TCond);
166713106117060c90d6f84bd2ed7a5c03e0502ff419DeLesley Hutchins  }
166813106117060c90d6f84bd2ed7a5c03e0502ff419DeLesley Hutchins  return false;
166913106117060c90d6f84bd2ed7a5c03e0502ff419DeLesley Hutchins}
167013106117060c90d6f84bd2ed7a5c03e0502ff419DeLesley Hutchins
167113106117060c90d6f84bd2ed7a5c03e0502ff419DeLesley Hutchins
167254c350a67b47f059e1d577bdd9e2d1dc31ff82b5DeLesley Hutchins// If Cond can be traced back to a function call, return the call expression.
167354c350a67b47f059e1d577bdd9e2d1dc31ff82b5DeLesley Hutchins// The negate variable should be called with false, and will be set to true
167454c350a67b47f059e1d577bdd9e2d1dc31ff82b5DeLesley Hutchins// if the function call is negated, e.g. if (!mu.tryLock(...))
167554c350a67b47f059e1d577bdd9e2d1dc31ff82b5DeLesley Hutchinsconst CallExpr* ThreadSafetyAnalyzer::getTrylockCallExpr(const Stmt *Cond,
167654c350a67b47f059e1d577bdd9e2d1dc31ff82b5DeLesley Hutchins                                                         LocalVarContext C,
167754c350a67b47f059e1d577bdd9e2d1dc31ff82b5DeLesley Hutchins                                                         bool &Negate) {
167854c350a67b47f059e1d577bdd9e2d1dc31ff82b5DeLesley Hutchins  if (!Cond)
16796bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines    return nullptr;
168054c350a67b47f059e1d577bdd9e2d1dc31ff82b5DeLesley Hutchins
168154c350a67b47f059e1d577bdd9e2d1dc31ff82b5DeLesley Hutchins  if (const CallExpr *CallExp = dyn_cast<CallExpr>(Cond)) {
168254c350a67b47f059e1d577bdd9e2d1dc31ff82b5DeLesley Hutchins    return CallExp;
168354c350a67b47f059e1d577bdd9e2d1dc31ff82b5DeLesley Hutchins  }
168413106117060c90d6f84bd2ed7a5c03e0502ff419DeLesley Hutchins  else if (const ParenExpr *PE = dyn_cast<ParenExpr>(Cond)) {
168513106117060c90d6f84bd2ed7a5c03e0502ff419DeLesley Hutchins    return getTrylockCallExpr(PE->getSubExpr(), C, Negate);
168613106117060c90d6f84bd2ed7a5c03e0502ff419DeLesley Hutchins  }
168754c350a67b47f059e1d577bdd9e2d1dc31ff82b5DeLesley Hutchins  else if (const ImplicitCastExpr *CE = dyn_cast<ImplicitCastExpr>(Cond)) {
168854c350a67b47f059e1d577bdd9e2d1dc31ff82b5DeLesley Hutchins    return getTrylockCallExpr(CE->getSubExpr(), C, Negate);
168954c350a67b47f059e1d577bdd9e2d1dc31ff82b5DeLesley Hutchins  }
1690fd0f11ccd51154e933fad7dfa134cb4f62c87056DeLesley Hutchins  else if (const ExprWithCleanups* EWC = dyn_cast<ExprWithCleanups>(Cond)) {
1691fd0f11ccd51154e933fad7dfa134cb4f62c87056DeLesley Hutchins    return getTrylockCallExpr(EWC->getSubExpr(), C, Negate);
1692fd0f11ccd51154e933fad7dfa134cb4f62c87056DeLesley Hutchins  }
169354c350a67b47f059e1d577bdd9e2d1dc31ff82b5DeLesley Hutchins  else if (const DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(Cond)) {
169454c350a67b47f059e1d577bdd9e2d1dc31ff82b5DeLesley Hutchins    const Expr *E = LocalVarMap.lookupExpr(DRE->getDecl(), C);
169554c350a67b47f059e1d577bdd9e2d1dc31ff82b5DeLesley Hutchins    return getTrylockCallExpr(E, C, Negate);
169654c350a67b47f059e1d577bdd9e2d1dc31ff82b5DeLesley Hutchins  }
169754c350a67b47f059e1d577bdd9e2d1dc31ff82b5DeLesley Hutchins  else if (const UnaryOperator *UOP = dyn_cast<UnaryOperator>(Cond)) {
169854c350a67b47f059e1d577bdd9e2d1dc31ff82b5DeLesley Hutchins    if (UOP->getOpcode() == UO_LNot) {
169954c350a67b47f059e1d577bdd9e2d1dc31ff82b5DeLesley Hutchins      Negate = !Negate;
170054c350a67b47f059e1d577bdd9e2d1dc31ff82b5DeLesley Hutchins      return getTrylockCallExpr(UOP->getSubExpr(), C, Negate);
170154c350a67b47f059e1d577bdd9e2d1dc31ff82b5DeLesley Hutchins    }
17026bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines    return nullptr;
170313106117060c90d6f84bd2ed7a5c03e0502ff419DeLesley Hutchins  }
170413106117060c90d6f84bd2ed7a5c03e0502ff419DeLesley Hutchins  else if (const BinaryOperator *BOP = dyn_cast<BinaryOperator>(Cond)) {
170513106117060c90d6f84bd2ed7a5c03e0502ff419DeLesley Hutchins    if (BOP->getOpcode() == BO_EQ || BOP->getOpcode() == BO_NE) {
170613106117060c90d6f84bd2ed7a5c03e0502ff419DeLesley Hutchins      if (BOP->getOpcode() == BO_NE)
170713106117060c90d6f84bd2ed7a5c03e0502ff419DeLesley Hutchins        Negate = !Negate;
170813106117060c90d6f84bd2ed7a5c03e0502ff419DeLesley Hutchins
170913106117060c90d6f84bd2ed7a5c03e0502ff419DeLesley Hutchins      bool TCond = false;
171013106117060c90d6f84bd2ed7a5c03e0502ff419DeLesley Hutchins      if (getStaticBooleanValue(BOP->getRHS(), TCond)) {
171113106117060c90d6f84bd2ed7a5c03e0502ff419DeLesley Hutchins        if (!TCond) Negate = !Negate;
171213106117060c90d6f84bd2ed7a5c03e0502ff419DeLesley Hutchins        return getTrylockCallExpr(BOP->getLHS(), C, Negate);
171313106117060c90d6f84bd2ed7a5c03e0502ff419DeLesley Hutchins      }
17147336b9f8c0b58550a74c85a64f06d0fd74e7ad0dDeLesley Hutchins      TCond = false;
17157336b9f8c0b58550a74c85a64f06d0fd74e7ad0dDeLesley Hutchins      if (getStaticBooleanValue(BOP->getLHS(), TCond)) {
171613106117060c90d6f84bd2ed7a5c03e0502ff419DeLesley Hutchins        if (!TCond) Negate = !Negate;
171713106117060c90d6f84bd2ed7a5c03e0502ff419DeLesley Hutchins        return getTrylockCallExpr(BOP->getRHS(), C, Negate);
171813106117060c90d6f84bd2ed7a5c03e0502ff419DeLesley Hutchins      }
17196bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines      return nullptr;
172013106117060c90d6f84bd2ed7a5c03e0502ff419DeLesley Hutchins    }
17217336b9f8c0b58550a74c85a64f06d0fd74e7ad0dDeLesley Hutchins    if (BOP->getOpcode() == BO_LAnd) {
17227336b9f8c0b58550a74c85a64f06d0fd74e7ad0dDeLesley Hutchins      // LHS must have been evaluated in a different block.
17237336b9f8c0b58550a74c85a64f06d0fd74e7ad0dDeLesley Hutchins      return getTrylockCallExpr(BOP->getRHS(), C, Negate);
17247336b9f8c0b58550a74c85a64f06d0fd74e7ad0dDeLesley Hutchins    }
17257336b9f8c0b58550a74c85a64f06d0fd74e7ad0dDeLesley Hutchins    if (BOP->getOpcode() == BO_LOr) {
17267336b9f8c0b58550a74c85a64f06d0fd74e7ad0dDeLesley Hutchins      return getTrylockCallExpr(BOP->getRHS(), C, Negate);
17277336b9f8c0b58550a74c85a64f06d0fd74e7ad0dDeLesley Hutchins    }
17286bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines    return nullptr;
172954c350a67b47f059e1d577bdd9e2d1dc31ff82b5DeLesley Hutchins  }
17306bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines  return nullptr;
173154c350a67b47f059e1d577bdd9e2d1dc31ff82b5DeLesley Hutchins}
173254c350a67b47f059e1d577bdd9e2d1dc31ff82b5DeLesley Hutchins
173354c350a67b47f059e1d577bdd9e2d1dc31ff82b5DeLesley Hutchins
17340da4414f3d30c34fafb81b13b2cec3680c0bc9e1DeLesley Hutchins/// \brief Find the lockset that holds on the edge between PredBlock
17350da4414f3d30c34fafb81b13b2cec3680c0bc9e1DeLesley Hutchins/// and CurrBlock.  The edge set is the exit set of PredBlock (passed
17360da4414f3d30c34fafb81b13b2cec3680c0bc9e1DeLesley Hutchins/// as the ExitSet parameter) plus any trylocks, which are conditionally held.
1737a1fa47139d6e9e7dcc40f2809605d1a258624e7fDeLesley Hutchinsvoid ThreadSafetyAnalyzer::getEdgeLockset(FactSet& Result,
1738a1fa47139d6e9e7dcc40f2809605d1a258624e7fDeLesley Hutchins                                          const FactSet &ExitSet,
1739a1fa47139d6e9e7dcc40f2809605d1a258624e7fDeLesley Hutchins                                          const CFGBlock *PredBlock,
1740a1fa47139d6e9e7dcc40f2809605d1a258624e7fDeLesley Hutchins                                          const CFGBlock *CurrBlock) {
1741a1fa47139d6e9e7dcc40f2809605d1a258624e7fDeLesley Hutchins  Result = ExitSet;
1742a1fa47139d6e9e7dcc40f2809605d1a258624e7fDeLesley Hutchins
17437336b9f8c0b58550a74c85a64f06d0fd74e7ad0dDeLesley Hutchins  const Stmt *Cond = PredBlock->getTerminatorCondition();
17447336b9f8c0b58550a74c85a64f06d0fd74e7ad0dDeLesley Hutchins  if (!Cond)
1745a1fa47139d6e9e7dcc40f2809605d1a258624e7fDeLesley Hutchins    return;
17460da4414f3d30c34fafb81b13b2cec3680c0bc9e1DeLesley Hutchins
174754c350a67b47f059e1d577bdd9e2d1dc31ff82b5DeLesley Hutchins  bool Negate = false;
174854c350a67b47f059e1d577bdd9e2d1dc31ff82b5DeLesley Hutchins  const CFGBlockInfo *PredBlockInfo = &BlockInfo[PredBlock->getBlockID()];
174954c350a67b47f059e1d577bdd9e2d1dc31ff82b5DeLesley Hutchins  const LocalVarContext &LVarCtx = PredBlockInfo->ExitContext;
1750651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines  StringRef CapDiagKind = "mutex";
175154c350a67b47f059e1d577bdd9e2d1dc31ff82b5DeLesley Hutchins
17525381c05f51e5b7c7627f1d95b9a3425303ce086aDeLesley Hutchins  CallExpr *Exp =
17535381c05f51e5b7c7627f1d95b9a3425303ce086aDeLesley Hutchins    const_cast<CallExpr*>(getTrylockCallExpr(Cond, LVarCtx, Negate));
175454c350a67b47f059e1d577bdd9e2d1dc31ff82b5DeLesley Hutchins  if (!Exp)
1755a1fa47139d6e9e7dcc40f2809605d1a258624e7fDeLesley Hutchins    return;
175654c350a67b47f059e1d577bdd9e2d1dc31ff82b5DeLesley Hutchins
175754c350a67b47f059e1d577bdd9e2d1dc31ff82b5DeLesley Hutchins  NamedDecl *FunDecl = dyn_cast_or_null<NamedDecl>(Exp->getCalleeDecl());
175854c350a67b47f059e1d577bdd9e2d1dc31ff82b5DeLesley Hutchins  if(!FunDecl || !FunDecl->hasAttrs())
1759a1fa47139d6e9e7dcc40f2809605d1a258624e7fDeLesley Hutchins    return;
176054c350a67b47f059e1d577bdd9e2d1dc31ff82b5DeLesley Hutchins
17615381c05f51e5b7c7627f1d95b9a3425303ce086aDeLesley Hutchins  MutexIDList ExclusiveLocksToAdd;
17625381c05f51e5b7c7627f1d95b9a3425303ce086aDeLesley Hutchins  MutexIDList SharedLocksToAdd;
176354c350a67b47f059e1d577bdd9e2d1dc31ff82b5DeLesley Hutchins
176454c350a67b47f059e1d577bdd9e2d1dc31ff82b5DeLesley Hutchins  // If the condition is a call to a Trylock function, then grab the attributes
17656bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines  for (auto *Attr : FunDecl->getAttrs()) {
176654c350a67b47f059e1d577bdd9e2d1dc31ff82b5DeLesley Hutchins    switch (Attr->getKind()) {
176754c350a67b47f059e1d577bdd9e2d1dc31ff82b5DeLesley Hutchins      case attr::ExclusiveTrylockFunction: {
176854c350a67b47f059e1d577bdd9e2d1dc31ff82b5DeLesley Hutchins        ExclusiveTrylockFunctionAttr *A =
176954c350a67b47f059e1d577bdd9e2d1dc31ff82b5DeLesley Hutchins          cast<ExclusiveTrylockFunctionAttr>(Attr);
17705381c05f51e5b7c7627f1d95b9a3425303ce086aDeLesley Hutchins        getMutexIDs(ExclusiveLocksToAdd, A, Exp, FunDecl,
17715381c05f51e5b7c7627f1d95b9a3425303ce086aDeLesley Hutchins                    PredBlock, CurrBlock, A->getSuccessValue(), Negate);
1772651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines        CapDiagKind = ClassifyDiagnostic(A);
177354c350a67b47f059e1d577bdd9e2d1dc31ff82b5DeLesley Hutchins        break;
177454c350a67b47f059e1d577bdd9e2d1dc31ff82b5DeLesley Hutchins      }
177554c350a67b47f059e1d577bdd9e2d1dc31ff82b5DeLesley Hutchins      case attr::SharedTrylockFunction: {
177654c350a67b47f059e1d577bdd9e2d1dc31ff82b5DeLesley Hutchins        SharedTrylockFunctionAttr *A =
177754c350a67b47f059e1d577bdd9e2d1dc31ff82b5DeLesley Hutchins          cast<SharedTrylockFunctionAttr>(Attr);
177860ff198a22815b0aec5b96eaae977de067dcd4c1DeLesley Hutchins        getMutexIDs(SharedLocksToAdd, A, Exp, FunDecl,
17795381c05f51e5b7c7627f1d95b9a3425303ce086aDeLesley Hutchins                    PredBlock, CurrBlock, A->getSuccessValue(), Negate);
1780651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines        CapDiagKind = ClassifyDiagnostic(A);
178154c350a67b47f059e1d577bdd9e2d1dc31ff82b5DeLesley Hutchins        break;
178254c350a67b47f059e1d577bdd9e2d1dc31ff82b5DeLesley Hutchins      }
178354c350a67b47f059e1d577bdd9e2d1dc31ff82b5DeLesley Hutchins      default:
178454c350a67b47f059e1d577bdd9e2d1dc31ff82b5DeLesley Hutchins        break;
178554c350a67b47f059e1d577bdd9e2d1dc31ff82b5DeLesley Hutchins    }
1786f1ac63702143d84db778d32eb185a77fc97db5f5DeLesley Hutchins  }
17875381c05f51e5b7c7627f1d95b9a3425303ce086aDeLesley Hutchins
17885381c05f51e5b7c7627f1d95b9a3425303ce086aDeLesley Hutchins  // Add and remove locks.
17895381c05f51e5b7c7627f1d95b9a3425303ce086aDeLesley Hutchins  SourceLocation Loc = Exp->getExprLoc();
1790651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines  for (const auto &ExclusiveLockToAdd : ExclusiveLocksToAdd)
1791651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines    addLock(Result, ExclusiveLockToAdd, LockData(Loc, LK_Exclusive),
1792651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines            CapDiagKind);
1793651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines  for (const auto &SharedLockToAdd : SharedLocksToAdd)
1794651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines    addLock(Result, SharedLockToAdd, LockData(Loc, LK_Shared), CapDiagKind);
1795f1ac63702143d84db778d32eb185a77fc97db5f5DeLesley Hutchins}
1796f1ac63702143d84db778d32eb185a77fc97db5f5DeLesley Hutchins
179754c350a67b47f059e1d577bdd9e2d1dc31ff82b5DeLesley Hutchins/// \brief We use this class to visit different types of expressions in
179854c350a67b47f059e1d577bdd9e2d1dc31ff82b5DeLesley Hutchins/// CFGBlocks, and build up the lockset.
179954c350a67b47f059e1d577bdd9e2d1dc31ff82b5DeLesley Hutchins/// An expression may cause us to add or remove locks from the lockset, or else
180054c350a67b47f059e1d577bdd9e2d1dc31ff82b5DeLesley Hutchins/// output error messages related to missing locks.
180154c350a67b47f059e1d577bdd9e2d1dc31ff82b5DeLesley Hutchins/// FIXME: In future, we may be able to not inherit from a visitor.
180254c350a67b47f059e1d577bdd9e2d1dc31ff82b5DeLesley Hutchinsclass BuildLockset : public StmtVisitor<BuildLockset> {
180354c350a67b47f059e1d577bdd9e2d1dc31ff82b5DeLesley Hutchins  friend class ThreadSafetyAnalyzer;
180454c350a67b47f059e1d577bdd9e2d1dc31ff82b5DeLesley Hutchins
180554c350a67b47f059e1d577bdd9e2d1dc31ff82b5DeLesley Hutchins  ThreadSafetyAnalyzer *Analyzer;
1806a1fa47139d6e9e7dcc40f2809605d1a258624e7fDeLesley Hutchins  FactSet FSet;
180754c350a67b47f059e1d577bdd9e2d1dc31ff82b5DeLesley Hutchins  LocalVariableMap::Context LVarCtx;
180854c350a67b47f059e1d577bdd9e2d1dc31ff82b5DeLesley Hutchins  unsigned CtxIndex;
180954c350a67b47f059e1d577bdd9e2d1dc31ff82b5DeLesley Hutchins
181054c350a67b47f059e1d577bdd9e2d1dc31ff82b5DeLesley Hutchins  // Helper functions
181154c350a67b47f059e1d577bdd9e2d1dc31ff82b5DeLesley Hutchins
181247715cc201170952029a52806bcc26f69c38272dDeLesley Hutchins  void warnIfMutexNotHeld(const NamedDecl *D, const Expr *Exp, AccessKind AK,
1813651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines                          Expr *MutexExp, ProtectedOperationKind POK,
1814651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines                          StringRef DiagKind);
1815651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines  void warnIfMutexHeld(const NamedDecl *D, const Expr *Exp, Expr *MutexExp,
1816651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines                       StringRef DiagKind);
181747715cc201170952029a52806bcc26f69c38272dDeLesley Hutchins
181847715cc201170952029a52806bcc26f69c38272dDeLesley Hutchins  void checkAccess(const Expr *Exp, AccessKind AK);
181947715cc201170952029a52806bcc26f69c38272dDeLesley Hutchins  void checkPtAccess(const Expr *Exp, AccessKind AK);
182054c350a67b47f059e1d577bdd9e2d1dc31ff82b5DeLesley Hutchins
18216bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines  void handleCall(Expr *Exp, const NamedDecl *D, VarDecl *VD = nullptr);
182254c350a67b47f059e1d577bdd9e2d1dc31ff82b5DeLesley Hutchins
182354c350a67b47f059e1d577bdd9e2d1dc31ff82b5DeLesley Hutchinspublic:
182454c350a67b47f059e1d577bdd9e2d1dc31ff82b5DeLesley Hutchins  BuildLockset(ThreadSafetyAnalyzer *Anlzr, CFGBlockInfo &Info)
182554c350a67b47f059e1d577bdd9e2d1dc31ff82b5DeLesley Hutchins    : StmtVisitor<BuildLockset>(),
182654c350a67b47f059e1d577bdd9e2d1dc31ff82b5DeLesley Hutchins      Analyzer(Anlzr),
1827a1fa47139d6e9e7dcc40f2809605d1a258624e7fDeLesley Hutchins      FSet(Info.EntrySet),
182854c350a67b47f059e1d577bdd9e2d1dc31ff82b5DeLesley Hutchins      LVarCtx(Info.EntryContext),
182954c350a67b47f059e1d577bdd9e2d1dc31ff82b5DeLesley Hutchins      CtxIndex(Info.EntryIndex)
183054c350a67b47f059e1d577bdd9e2d1dc31ff82b5DeLesley Hutchins  {}
183154c350a67b47f059e1d577bdd9e2d1dc31ff82b5DeLesley Hutchins
183254c350a67b47f059e1d577bdd9e2d1dc31ff82b5DeLesley Hutchins  void VisitUnaryOperator(UnaryOperator *UO);
183354c350a67b47f059e1d577bdd9e2d1dc31ff82b5DeLesley Hutchins  void VisitBinaryOperator(BinaryOperator *BO);
183454c350a67b47f059e1d577bdd9e2d1dc31ff82b5DeLesley Hutchins  void VisitCastExpr(CastExpr *CE);
183554c350a67b47f059e1d577bdd9e2d1dc31ff82b5DeLesley Hutchins  void VisitCallExpr(CallExpr *Exp);
183654c350a67b47f059e1d577bdd9e2d1dc31ff82b5DeLesley Hutchins  void VisitCXXConstructExpr(CXXConstructExpr *Exp);
183754c350a67b47f059e1d577bdd9e2d1dc31ff82b5DeLesley Hutchins  void VisitDeclStmt(DeclStmt *S);
183854c350a67b47f059e1d577bdd9e2d1dc31ff82b5DeLesley Hutchins};
183954c350a67b47f059e1d577bdd9e2d1dc31ff82b5DeLesley Hutchins
1840402aa0698fec81e574818a0a6c2000fac0b2c4c6Caitlin Sadowski/// \brief Warn if the LSet does not contain a lock sufficient to protect access
18419f80a97408ee0da939654d851ff42ad07d47e9c7DeLesley Hutchins/// of at least the passed in AccessKind.
184247715cc201170952029a52806bcc26f69c38272dDeLesley Hutchinsvoid BuildLockset::warnIfMutexNotHeld(const NamedDecl *D, const Expr *Exp,
1843402aa0698fec81e574818a0a6c2000fac0b2c4c6Caitlin Sadowski                                      AccessKind AK, Expr *MutexExp,
1844651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines                                      ProtectedOperationKind POK,
1845651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines                                      StringRef DiagKind) {
1846402aa0698fec81e574818a0a6c2000fac0b2c4c6Caitlin Sadowski  LockKind LK = getLockKindFromAccessKind(AK);
18479f80a97408ee0da939654d851ff42ad07d47e9c7DeLesley Hutchins
1848a74b715cdc37c4523818a4018faae99d977aa537DeLesley Hutchins  SExpr Mutex(MutexExp, Exp, D);
18490b4db3e08a201c35f0011489bd5cd5d39bbe54fbDeLesley Hutchins  if (!Mutex.isValid()) {
1850651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines    SExpr::warnInvalidLock(Analyzer->Handler, MutexExp, Exp, D, DiagKind);
18510b4db3e08a201c35f0011489bd5cd5d39bbe54fbDeLesley Hutchins    return;
18520b4db3e08a201c35f0011489bd5cd5d39bbe54fbDeLesley Hutchins  } else if (Mutex.shouldIgnore()) {
18530b4db3e08a201c35f0011489bd5cd5d39bbe54fbDeLesley Hutchins    return;
18540b4db3e08a201c35f0011489bd5cd5d39bbe54fbDeLesley Hutchins  }
18550b4db3e08a201c35f0011489bd5cd5d39bbe54fbDeLesley Hutchins
18560b4db3e08a201c35f0011489bd5cd5d39bbe54fbDeLesley Hutchins  LockData* LDat = FSet.findLockUniv(Analyzer->FactMan, Mutex);
18573f0ec5209726641782468bd4c7597e79dda78b15DeLesley Hutchins  bool NoError = true;
18583f0ec5209726641782468bd4c7597e79dda78b15DeLesley Hutchins  if (!LDat) {
18593f0ec5209726641782468bd4c7597e79dda78b15DeLesley Hutchins    // No exact match found.  Look for a partial match.
18603f0ec5209726641782468bd4c7597e79dda78b15DeLesley Hutchins    FactEntry* FEntry = FSet.findPartialMatch(Analyzer->FactMan, Mutex);
18613f0ec5209726641782468bd4c7597e79dda78b15DeLesley Hutchins    if (FEntry) {
18623f0ec5209726641782468bd4c7597e79dda78b15DeLesley Hutchins      // Warn that there's no precise match.
18633f0ec5209726641782468bd4c7597e79dda78b15DeLesley Hutchins      LDat = &FEntry->LDat;
18643f0ec5209726641782468bd4c7597e79dda78b15DeLesley Hutchins      std::string PartMatchStr = FEntry->MutID.toString();
18653f0ec5209726641782468bd4c7597e79dda78b15DeLesley Hutchins      StringRef   PartMatchName(PartMatchStr);
1866651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines      Analyzer->Handler.handleMutexNotHeld(DiagKind, D, POK, Mutex.toString(),
1867651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines                                           LK, Exp->getExprLoc(),
1868651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines                                           &PartMatchName);
18693f0ec5209726641782468bd4c7597e79dda78b15DeLesley Hutchins    } else {
18703f0ec5209726641782468bd4c7597e79dda78b15DeLesley Hutchins      // Warn that there's no match at all.
1871651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines      Analyzer->Handler.handleMutexNotHeld(DiagKind, D, POK, Mutex.toString(),
1872651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines                                           LK, Exp->getExprLoc());
18733f0ec5209726641782468bd4c7597e79dda78b15DeLesley Hutchins    }
18743f0ec5209726641782468bd4c7597e79dda78b15DeLesley Hutchins    NoError = false;
18753f0ec5209726641782468bd4c7597e79dda78b15DeLesley Hutchins  }
18763f0ec5209726641782468bd4c7597e79dda78b15DeLesley Hutchins  // Make sure the mutex we found is the right kind.
18773f0ec5209726641782468bd4c7597e79dda78b15DeLesley Hutchins  if (NoError && LDat && !LDat->isAtLeast(LK))
1878651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines    Analyzer->Handler.handleMutexNotHeld(DiagKind, D, POK, Mutex.toString(), LK,
187954c350a67b47f059e1d577bdd9e2d1dc31ff82b5DeLesley Hutchins                                         Exp->getExprLoc());
1880402aa0698fec81e574818a0a6c2000fac0b2c4c6Caitlin Sadowski}
1881402aa0698fec81e574818a0a6c2000fac0b2c4c6Caitlin Sadowski
18820b4db3e08a201c35f0011489bd5cd5d39bbe54fbDeLesley Hutchins/// \brief Warn if the LSet contains the given lock.
1883651f13cea278ec967336033dd032faef0e9fc2ecStephen Hinesvoid BuildLockset::warnIfMutexHeld(const NamedDecl *D, const Expr *Exp,
1884651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines                                   Expr *MutexExp,
1885651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines                                   StringRef DiagKind) {
18860b4db3e08a201c35f0011489bd5cd5d39bbe54fbDeLesley Hutchins  SExpr Mutex(MutexExp, Exp, D);
18870b4db3e08a201c35f0011489bd5cd5d39bbe54fbDeLesley Hutchins  if (!Mutex.isValid()) {
1888651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines    SExpr::warnInvalidLock(Analyzer->Handler, MutexExp, Exp, D, DiagKind);
18890b4db3e08a201c35f0011489bd5cd5d39bbe54fbDeLesley Hutchins    return;
18900b4db3e08a201c35f0011489bd5cd5d39bbe54fbDeLesley Hutchins  }
18910b4db3e08a201c35f0011489bd5cd5d39bbe54fbDeLesley Hutchins
18920b4db3e08a201c35f0011489bd5cd5d39bbe54fbDeLesley Hutchins  LockData* LDat = FSet.findLock(Analyzer->FactMan, Mutex);
1893651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines  if (LDat)
1894651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines    Analyzer->Handler.handleFunExcludesLock(
1895651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines        DiagKind, D->getNameAsString(), Mutex.toString(), Exp->getExprLoc());
18960b4db3e08a201c35f0011489bd5cd5d39bbe54fbDeLesley Hutchins}
18970b4db3e08a201c35f0011489bd5cd5d39bbe54fbDeLesley Hutchins
189847715cc201170952029a52806bcc26f69c38272dDeLesley Hutchins/// \brief Checks guarded_by and pt_guarded_by attributes.
189947715cc201170952029a52806bcc26f69c38272dDeLesley Hutchins/// Whenever we identify an access (read or write) to a DeclRefExpr that is
190047715cc201170952029a52806bcc26f69c38272dDeLesley Hutchins/// marked with guarded_by, we must ensure the appropriate mutexes are held.
190147715cc201170952029a52806bcc26f69c38272dDeLesley Hutchins/// Similarly, we check if the access is to an expression that dereferences
190247715cc201170952029a52806bcc26f69c38272dDeLesley Hutchins/// a pointer marked with pt_guarded_by.
190347715cc201170952029a52806bcc26f69c38272dDeLesley Hutchinsvoid BuildLockset::checkAccess(const Expr *Exp, AccessKind AK) {
190447715cc201170952029a52806bcc26f69c38272dDeLesley Hutchins  Exp = Exp->IgnoreParenCasts();
190547715cc201170952029a52806bcc26f69c38272dDeLesley Hutchins
190647715cc201170952029a52806bcc26f69c38272dDeLesley Hutchins  if (const UnaryOperator *UO = dyn_cast<UnaryOperator>(Exp)) {
190747715cc201170952029a52806bcc26f69c38272dDeLesley Hutchins    // For dereferences
190847715cc201170952029a52806bcc26f69c38272dDeLesley Hutchins    if (UO->getOpcode() == clang::UO_Deref)
190947715cc201170952029a52806bcc26f69c38272dDeLesley Hutchins      checkPtAccess(UO->getSubExpr(), AK);
1910402aa0698fec81e574818a0a6c2000fac0b2c4c6Caitlin Sadowski    return;
191147715cc201170952029a52806bcc26f69c38272dDeLesley Hutchins  }
1912402aa0698fec81e574818a0a6c2000fac0b2c4c6Caitlin Sadowski
1913f9495911c46a5f90d8cf14774c11ff521d505c7eDeLesley Hutchins  if (const ArraySubscriptExpr *AE = dyn_cast<ArraySubscriptExpr>(Exp)) {
1914651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines    checkPtAccess(AE->getLHS(), AK);
1915651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines    return;
1916f9495911c46a5f90d8cf14774c11ff521d505c7eDeLesley Hutchins  }
1917f9495911c46a5f90d8cf14774c11ff521d505c7eDeLesley Hutchins
1918dd0a1f58a505ced9674f6d31a1ff65cb87774d67DeLesley Hutchins  if (const MemberExpr *ME = dyn_cast<MemberExpr>(Exp)) {
1919dd0a1f58a505ced9674f6d31a1ff65cb87774d67DeLesley Hutchins    if (ME->isArrow())
1920dd0a1f58a505ced9674f6d31a1ff65cb87774d67DeLesley Hutchins      checkPtAccess(ME->getBase(), AK);
1921dd0a1f58a505ced9674f6d31a1ff65cb87774d67DeLesley Hutchins    else
1922dd0a1f58a505ced9674f6d31a1ff65cb87774d67DeLesley Hutchins      checkAccess(ME->getBase(), AK);
192393699d23cd07c021eac2e26f8e32b58276bfa912DeLesley Hutchins  }
192493699d23cd07c021eac2e26f8e32b58276bfa912DeLesley Hutchins
1925402aa0698fec81e574818a0a6c2000fac0b2c4c6Caitlin Sadowski  const ValueDecl *D = getValueDecl(Exp);
192647715cc201170952029a52806bcc26f69c38272dDeLesley Hutchins  if (!D || !D->hasAttrs())
1927402aa0698fec81e574818a0a6c2000fac0b2c4c6Caitlin Sadowski    return;
1928402aa0698fec81e574818a0a6c2000fac0b2c4c6Caitlin Sadowski
1929651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines  if (D->hasAttr<GuardedVarAttr>() && FSet.isEmpty())
1930651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines    Analyzer->Handler.handleNoMutexHeld("mutex", D, POK_VarAccess, AK,
193154c350a67b47f059e1d577bdd9e2d1dc31ff82b5DeLesley Hutchins                                        Exp->getExprLoc());
1932402aa0698fec81e574818a0a6c2000fac0b2c4c6Caitlin Sadowski
1933651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines  for (const auto *I : D->specific_attrs<GuardedByAttr>())
1934651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines    warnIfMutexNotHeld(D, Exp, AK, I->getArg(), POK_VarAccess,
1935651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines                       ClassifyDiagnostic(I));
1936402aa0698fec81e574818a0a6c2000fac0b2c4c6Caitlin Sadowski}
1937402aa0698fec81e574818a0a6c2000fac0b2c4c6Caitlin Sadowski
193847715cc201170952029a52806bcc26f69c38272dDeLesley Hutchins/// \brief Checks pt_guarded_by and pt_guarded_var attributes.
193947715cc201170952029a52806bcc26f69c38272dDeLesley Hutchinsvoid BuildLockset::checkPtAccess(const Expr *Exp, AccessKind AK) {
1940651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines  while (true) {
1941651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines    if (const ParenExpr *PE = dyn_cast<ParenExpr>(Exp)) {
1942651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines      Exp = PE->getSubExpr();
1943651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines      continue;
1944651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines    }
1945651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines    if (const CastExpr *CE = dyn_cast<CastExpr>(Exp)) {
1946651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines      if (CE->getCastKind() == CK_ArrayToPointerDecay) {
1947651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines        // If it's an actual array, and not a pointer, then it's elements
1948651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines        // are protected by GUARDED_BY, not PT_GUARDED_BY;
1949651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines        checkAccess(CE->getSubExpr(), AK);
1950651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines        return;
1951f9495911c46a5f90d8cf14774c11ff521d505c7eDeLesley Hutchins      }
1952651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines      Exp = CE->getSubExpr();
1953651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines      continue;
1954f9495911c46a5f90d8cf14774c11ff521d505c7eDeLesley Hutchins    }
1955651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines    break;
1956f9495911c46a5f90d8cf14774c11ff521d505c7eDeLesley Hutchins  }
195747715cc201170952029a52806bcc26f69c38272dDeLesley Hutchins
1958402aa0698fec81e574818a0a6c2000fac0b2c4c6Caitlin Sadowski  const ValueDecl *D = getValueDecl(Exp);
195947715cc201170952029a52806bcc26f69c38272dDeLesley Hutchins  if (!D || !D->hasAttrs())
1960402aa0698fec81e574818a0a6c2000fac0b2c4c6Caitlin Sadowski    return;
1961402aa0698fec81e574818a0a6c2000fac0b2c4c6Caitlin Sadowski
1962651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines  if (D->hasAttr<PtGuardedVarAttr>() && FSet.isEmpty())
1963651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines    Analyzer->Handler.handleNoMutexHeld("mutex", D, POK_VarDereference, AK,
196454c350a67b47f059e1d577bdd9e2d1dc31ff82b5DeLesley Hutchins                                        Exp->getExprLoc());
1965402aa0698fec81e574818a0a6c2000fac0b2c4c6Caitlin Sadowski
1966651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines  for (auto const *I : D->specific_attrs<PtGuardedByAttr>())
1967651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines    warnIfMutexNotHeld(D, Exp, AK, I->getArg(), POK_VarDereference,
1968651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines                       ClassifyDiagnostic(I));
1969402aa0698fec81e574818a0a6c2000fac0b2c4c6Caitlin Sadowski}
1970402aa0698fec81e574818a0a6c2000fac0b2c4c6Caitlin Sadowski
1971e0eaa8531f8fd9189710aac3b6f3aadb62bb14d1DeLesley Hutchins/// \brief Process a function call, method call, constructor call,
1972e0eaa8531f8fd9189710aac3b6f3aadb62bb14d1DeLesley Hutchins/// or destructor call.  This involves looking at the attributes on the
1973e0eaa8531f8fd9189710aac3b6f3aadb62bb14d1DeLesley Hutchins/// corresponding function/method/constructor/destructor, issuing warnings,
1974e0eaa8531f8fd9189710aac3b6f3aadb62bb14d1DeLesley Hutchins/// and updating the locksets accordingly.
1975402aa0698fec81e574818a0a6c2000fac0b2c4c6Caitlin Sadowski///
1976402aa0698fec81e574818a0a6c2000fac0b2c4c6Caitlin Sadowski/// FIXME: For classes annotated with one of the guarded annotations, we need
1977402aa0698fec81e574818a0a6c2000fac0b2c4c6Caitlin Sadowski/// to treat const method calls as reads and non-const method calls as writes,
1978402aa0698fec81e574818a0a6c2000fac0b2c4c6Caitlin Sadowski/// and check that the appropriate locks are held. Non-const method calls with
1979402aa0698fec81e574818a0a6c2000fac0b2c4c6Caitlin Sadowski/// the same signature as const method calls can be also treated as reads.
1980402aa0698fec81e574818a0a6c2000fac0b2c4c6Caitlin Sadowski///
19815381c05f51e5b7c7627f1d95b9a3425303ce086aDeLesley Hutchinsvoid BuildLockset::handleCall(Expr *Exp, const NamedDecl *D, VarDecl *VD) {
19825c6134fd09bc5b738dafdd1c774edde13d95cb20DeLesley Hutchins  SourceLocation Loc = Exp->getExprLoc();
19835381c05f51e5b7c7627f1d95b9a3425303ce086aDeLesley Hutchins  const AttrVec &ArgAttrs = D->getAttrs();
1984651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines  MutexIDList ExclusiveLocksToAdd, SharedLocksToAdd;
1985651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines  MutexIDList ExclusiveLocksToRemove, SharedLocksToRemove, GenericLocksToRemove;
1986651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines  StringRef CapDiagKind = "mutex";
19875381c05f51e5b7c7627f1d95b9a3425303ce086aDeLesley Hutchins
1988402aa0698fec81e574818a0a6c2000fac0b2c4c6Caitlin Sadowski  for(unsigned i = 0; i < ArgAttrs.size(); ++i) {
19895381c05f51e5b7c7627f1d95b9a3425303ce086aDeLesley Hutchins    Attr *At = const_cast<Attr*>(ArgAttrs[i]);
19905381c05f51e5b7c7627f1d95b9a3425303ce086aDeLesley Hutchins    switch (At->getKind()) {
1991651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines      // When we encounter a lock function, we need to add the lock to our
1992651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines      // lockset.
1993651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines      case attr::AcquireCapability: {
1994651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines        auto *A = cast<AcquireCapabilityAttr>(At);
1995651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines        Analyzer->getMutexIDs(A->isShared() ? SharedLocksToAdd
1996651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines                                            : ExclusiveLocksToAdd,
1997651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines                              A, Exp, D, VD);
1998651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines
1999651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines        CapDiagKind = ClassifyDiagnostic(A);
2000402aa0698fec81e574818a0a6c2000fac0b2c4c6Caitlin Sadowski        break;
20019f80a97408ee0da939654d851ff42ad07d47e9c7DeLesley Hutchins      }
2002402aa0698fec81e574818a0a6c2000fac0b2c4c6Caitlin Sadowski
20035c6134fd09bc5b738dafdd1c774edde13d95cb20DeLesley Hutchins      // An assert will add a lock to the lockset, but will not generate
20045c6134fd09bc5b738dafdd1c774edde13d95cb20DeLesley Hutchins      // a warning if it is already there, and will not generate a warning
20055c6134fd09bc5b738dafdd1c774edde13d95cb20DeLesley Hutchins      // if it is not removed.
20065c6134fd09bc5b738dafdd1c774edde13d95cb20DeLesley Hutchins      case attr::AssertExclusiveLock: {
20075c6134fd09bc5b738dafdd1c774edde13d95cb20DeLesley Hutchins        AssertExclusiveLockAttr *A = cast<AssertExclusiveLockAttr>(At);
20085c6134fd09bc5b738dafdd1c774edde13d95cb20DeLesley Hutchins
20095c6134fd09bc5b738dafdd1c774edde13d95cb20DeLesley Hutchins        MutexIDList AssertLocks;
20105c6134fd09bc5b738dafdd1c774edde13d95cb20DeLesley Hutchins        Analyzer->getMutexIDs(AssertLocks, A, Exp, D, VD);
2011651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines        for (const auto &AssertLock : AssertLocks)
2012651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines          Analyzer->addLock(FSet, AssertLock,
2013651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines                            LockData(Loc, LK_Exclusive, false, true),
2014651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines                            ClassifyDiagnostic(A));
20155c6134fd09bc5b738dafdd1c774edde13d95cb20DeLesley Hutchins        break;
20165c6134fd09bc5b738dafdd1c774edde13d95cb20DeLesley Hutchins      }
20175c6134fd09bc5b738dafdd1c774edde13d95cb20DeLesley Hutchins      case attr::AssertSharedLock: {
20185c6134fd09bc5b738dafdd1c774edde13d95cb20DeLesley Hutchins        AssertSharedLockAttr *A = cast<AssertSharedLockAttr>(At);
20195c6134fd09bc5b738dafdd1c774edde13d95cb20DeLesley Hutchins
20205c6134fd09bc5b738dafdd1c774edde13d95cb20DeLesley Hutchins        MutexIDList AssertLocks;
20215c6134fd09bc5b738dafdd1c774edde13d95cb20DeLesley Hutchins        Analyzer->getMutexIDs(AssertLocks, A, Exp, D, VD);
2022651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines        for (const auto &AssertLock : AssertLocks)
2023651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines          Analyzer->addLock(FSet, AssertLock,
2024651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines                            LockData(Loc, LK_Shared, false, true),
2025651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines                            ClassifyDiagnostic(A));
20265c6134fd09bc5b738dafdd1c774edde13d95cb20DeLesley Hutchins        break;
20275c6134fd09bc5b738dafdd1c774edde13d95cb20DeLesley Hutchins      }
20285c6134fd09bc5b738dafdd1c774edde13d95cb20DeLesley Hutchins
2029402aa0698fec81e574818a0a6c2000fac0b2c4c6Caitlin Sadowski      // When we encounter an unlock function, we need to remove unlocked
2030402aa0698fec81e574818a0a6c2000fac0b2c4c6Caitlin Sadowski      // mutexes from the lockset, and flag a warning if they are not there.
2031651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines      case attr::ReleaseCapability: {
2032651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines        auto *A = cast<ReleaseCapabilityAttr>(At);
2033651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines        if (A->isGeneric())
2034651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines          Analyzer->getMutexIDs(GenericLocksToRemove, A, Exp, D, VD);
2035651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines        else if (A->isShared())
2036651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines          Analyzer->getMutexIDs(SharedLocksToRemove, A, Exp, D, VD);
2037651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines        else
2038651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines          Analyzer->getMutexIDs(ExclusiveLocksToRemove, A, Exp, D, VD);
2039402aa0698fec81e574818a0a6c2000fac0b2c4c6Caitlin Sadowski
2040651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines        CapDiagKind = ClassifyDiagnostic(A);
2041402aa0698fec81e574818a0a6c2000fac0b2c4c6Caitlin Sadowski        break;
2042402aa0698fec81e574818a0a6c2000fac0b2c4c6Caitlin Sadowski      }
2043402aa0698fec81e574818a0a6c2000fac0b2c4c6Caitlin Sadowski
2044651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines      case attr::RequiresCapability: {
2045651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines        RequiresCapabilityAttr *A = cast<RequiresCapabilityAttr>(At);
20466bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines        for (auto *Arg : A->args())
20476bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines          warnIfMutexNotHeld(D, Exp, A->isShared() ? AK_Read : AK_Written, Arg,
2048651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines                             POK_FunctionCall, ClassifyDiagnostic(A));
2049402aa0698fec81e574818a0a6c2000fac0b2c4c6Caitlin Sadowski        break;
2050402aa0698fec81e574818a0a6c2000fac0b2c4c6Caitlin Sadowski      }
2051402aa0698fec81e574818a0a6c2000fac0b2c4c6Caitlin Sadowski
2052402aa0698fec81e574818a0a6c2000fac0b2c4c6Caitlin Sadowski      case attr::LocksExcluded: {
20535381c05f51e5b7c7627f1d95b9a3425303ce086aDeLesley Hutchins        LocksExcludedAttr *A = cast<LocksExcludedAttr>(At);
20546bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines        for (auto *Arg : A->args())
20556bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines          warnIfMutexHeld(D, Exp, Arg, ClassifyDiagnostic(A));
2056402aa0698fec81e574818a0a6c2000fac0b2c4c6Caitlin Sadowski        break;
2057402aa0698fec81e574818a0a6c2000fac0b2c4c6Caitlin Sadowski      }
2058402aa0698fec81e574818a0a6c2000fac0b2c4c6Caitlin Sadowski
2059651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines      // Ignore attributes unrelated to thread-safety
2060402aa0698fec81e574818a0a6c2000fac0b2c4c6Caitlin Sadowski      default:
2061402aa0698fec81e574818a0a6c2000fac0b2c4c6Caitlin Sadowski        break;
2062402aa0698fec81e574818a0a6c2000fac0b2c4c6Caitlin Sadowski    }
2063402aa0698fec81e574818a0a6c2000fac0b2c4c6Caitlin Sadowski  }
20645381c05f51e5b7c7627f1d95b9a3425303ce086aDeLesley Hutchins
20655381c05f51e5b7c7627f1d95b9a3425303ce086aDeLesley Hutchins  // Figure out if we're calling the constructor of scoped lockable class
20665381c05f51e5b7c7627f1d95b9a3425303ce086aDeLesley Hutchins  bool isScopedVar = false;
20675381c05f51e5b7c7627f1d95b9a3425303ce086aDeLesley Hutchins  if (VD) {
20685381c05f51e5b7c7627f1d95b9a3425303ce086aDeLesley Hutchins    if (const CXXConstructorDecl *CD = dyn_cast<const CXXConstructorDecl>(D)) {
20695381c05f51e5b7c7627f1d95b9a3425303ce086aDeLesley Hutchins      const CXXRecordDecl* PD = CD->getParent();
2070651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines      if (PD && PD->hasAttr<ScopedLockableAttr>())
20715381c05f51e5b7c7627f1d95b9a3425303ce086aDeLesley Hutchins        isScopedVar = true;
20725381c05f51e5b7c7627f1d95b9a3425303ce086aDeLesley Hutchins    }
20735381c05f51e5b7c7627f1d95b9a3425303ce086aDeLesley Hutchins  }
20745381c05f51e5b7c7627f1d95b9a3425303ce086aDeLesley Hutchins
20755381c05f51e5b7c7627f1d95b9a3425303ce086aDeLesley Hutchins  // Add locks.
2076651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines  for (const auto &M : ExclusiveLocksToAdd)
2077651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines    Analyzer->addLock(FSet, M, LockData(Loc, LK_Exclusive, isScopedVar),
2078651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines                      CapDiagKind);
2079651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines  for (const auto &M : SharedLocksToAdd)
2080651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines    Analyzer->addLock(FSet, M, LockData(Loc, LK_Shared, isScopedVar),
2081651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines                      CapDiagKind);
20825381c05f51e5b7c7627f1d95b9a3425303ce086aDeLesley Hutchins
20835381c05f51e5b7c7627f1d95b9a3425303ce086aDeLesley Hutchins  // Add the managing object as a dummy mutex, mapped to the underlying mutex.
20845381c05f51e5b7c7627f1d95b9a3425303ce086aDeLesley Hutchins  // FIXME -- this doesn't work if we acquire multiple locks.
20855381c05f51e5b7c7627f1d95b9a3425303ce086aDeLesley Hutchins  if (isScopedVar) {
20865381c05f51e5b7c7627f1d95b9a3425303ce086aDeLesley Hutchins    SourceLocation MLoc = VD->getLocation();
20875381c05f51e5b7c7627f1d95b9a3425303ce086aDeLesley Hutchins    DeclRefExpr DRE(VD, false, VD->getType(), VK_LValue, VD->getLocation());
20886bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines    SExpr SMutex(&DRE, nullptr, nullptr);
20895381c05f51e5b7c7627f1d95b9a3425303ce086aDeLesley Hutchins
2090651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines    for (const auto &M : ExclusiveLocksToAdd)
2091651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines      Analyzer->addLock(FSet, SMutex, LockData(MLoc, LK_Exclusive, M),
2092651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines                        CapDiagKind);
2093651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines    for (const auto &M : SharedLocksToAdd)
2094651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines      Analyzer->addLock(FSet, SMutex, LockData(MLoc, LK_Shared, M),
2095651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines                        CapDiagKind);
20965381c05f51e5b7c7627f1d95b9a3425303ce086aDeLesley Hutchins  }
20975381c05f51e5b7c7627f1d95b9a3425303ce086aDeLesley Hutchins
20985381c05f51e5b7c7627f1d95b9a3425303ce086aDeLesley Hutchins  // Remove locks.
20995381c05f51e5b7c7627f1d95b9a3425303ce086aDeLesley Hutchins  // FIXME -- should only fully remove if the attribute refers to 'this'.
21005381c05f51e5b7c7627f1d95b9a3425303ce086aDeLesley Hutchins  bool Dtor = isa<CXXDestructorDecl>(D);
2101651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines  for (const auto &M : ExclusiveLocksToRemove)
2102651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines    Analyzer->removeLock(FSet, M, Loc, Dtor, LK_Exclusive, CapDiagKind);
2103651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines  for (const auto &M : SharedLocksToRemove)
2104651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines    Analyzer->removeLock(FSet, M, Loc, Dtor, LK_Shared, CapDiagKind);
2105651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines  for (const auto &M : GenericLocksToRemove)
2106651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines    Analyzer->removeLock(FSet, M, Loc, Dtor, LK_Generic, CapDiagKind);
2107402aa0698fec81e574818a0a6c2000fac0b2c4c6Caitlin Sadowski}
2108402aa0698fec81e574818a0a6c2000fac0b2c4c6Caitlin Sadowski
2109b4fa418a72759dfe34add850837965cbc00626e4DeLesley Hutchins
2110e0eaa8531f8fd9189710aac3b6f3aadb62bb14d1DeLesley Hutchins/// \brief For unary operations which read and write a variable, we need to
2111e0eaa8531f8fd9189710aac3b6f3aadb62bb14d1DeLesley Hutchins/// check whether we hold any required mutexes. Reads are checked in
2112e0eaa8531f8fd9189710aac3b6f3aadb62bb14d1DeLesley Hutchins/// VisitCastExpr.
2113e0eaa8531f8fd9189710aac3b6f3aadb62bb14d1DeLesley Hutchinsvoid BuildLockset::VisitUnaryOperator(UnaryOperator *UO) {
2114e0eaa8531f8fd9189710aac3b6f3aadb62bb14d1DeLesley Hutchins  switch (UO->getOpcode()) {
2115e0eaa8531f8fd9189710aac3b6f3aadb62bb14d1DeLesley Hutchins    case clang::UO_PostDec:
2116e0eaa8531f8fd9189710aac3b6f3aadb62bb14d1DeLesley Hutchins    case clang::UO_PostInc:
2117e0eaa8531f8fd9189710aac3b6f3aadb62bb14d1DeLesley Hutchins    case clang::UO_PreDec:
2118e0eaa8531f8fd9189710aac3b6f3aadb62bb14d1DeLesley Hutchins    case clang::UO_PreInc: {
211947715cc201170952029a52806bcc26f69c38272dDeLesley Hutchins      checkAccess(UO->getSubExpr(), AK_Written);
2120e0eaa8531f8fd9189710aac3b6f3aadb62bb14d1DeLesley Hutchins      break;
2121e0eaa8531f8fd9189710aac3b6f3aadb62bb14d1DeLesley Hutchins    }
2122e0eaa8531f8fd9189710aac3b6f3aadb62bb14d1DeLesley Hutchins    default:
2123e0eaa8531f8fd9189710aac3b6f3aadb62bb14d1DeLesley Hutchins      break;
2124e0eaa8531f8fd9189710aac3b6f3aadb62bb14d1DeLesley Hutchins  }
2125e0eaa8531f8fd9189710aac3b6f3aadb62bb14d1DeLesley Hutchins}
2126e0eaa8531f8fd9189710aac3b6f3aadb62bb14d1DeLesley Hutchins
2127e0eaa8531f8fd9189710aac3b6f3aadb62bb14d1DeLesley Hutchins/// For binary operations which assign to a variable (writes), we need to check
2128e0eaa8531f8fd9189710aac3b6f3aadb62bb14d1DeLesley Hutchins/// whether we hold any required mutexes.
2129e0eaa8531f8fd9189710aac3b6f3aadb62bb14d1DeLesley Hutchins/// FIXME: Deal with non-primitive types.
2130e0eaa8531f8fd9189710aac3b6f3aadb62bb14d1DeLesley Hutchinsvoid BuildLockset::VisitBinaryOperator(BinaryOperator *BO) {
2131e0eaa8531f8fd9189710aac3b6f3aadb62bb14d1DeLesley Hutchins  if (!BO->isAssignmentOp())
2132e0eaa8531f8fd9189710aac3b6f3aadb62bb14d1DeLesley Hutchins    return;
2133b37d2b5c0819d9ef596c7baec1e0be0d7c45b547DeLesley Hutchins
2134b37d2b5c0819d9ef596c7baec1e0be0d7c45b547DeLesley Hutchins  // adjust the context
213554c350a67b47f059e1d577bdd9e2d1dc31ff82b5DeLesley Hutchins  LVarCtx = Analyzer->LocalVarMap.getNextContext(CtxIndex, BO, LVarCtx);
2136b37d2b5c0819d9ef596c7baec1e0be0d7c45b547DeLesley Hutchins
213747715cc201170952029a52806bcc26f69c38272dDeLesley Hutchins  checkAccess(BO->getLHS(), AK_Written);
2138e0eaa8531f8fd9189710aac3b6f3aadb62bb14d1DeLesley Hutchins}
2139e0eaa8531f8fd9189710aac3b6f3aadb62bb14d1DeLesley Hutchins
2140f9495911c46a5f90d8cf14774c11ff521d505c7eDeLesley Hutchins
2141e0eaa8531f8fd9189710aac3b6f3aadb62bb14d1DeLesley Hutchins/// Whenever we do an LValue to Rvalue cast, we are reading a variable and
2142e0eaa8531f8fd9189710aac3b6f3aadb62bb14d1DeLesley Hutchins/// need to ensure we hold any required mutexes.
2143e0eaa8531f8fd9189710aac3b6f3aadb62bb14d1DeLesley Hutchins/// FIXME: Deal with non-primitive types.
2144e0eaa8531f8fd9189710aac3b6f3aadb62bb14d1DeLesley Hutchinsvoid BuildLockset::VisitCastExpr(CastExpr *CE) {
2145e0eaa8531f8fd9189710aac3b6f3aadb62bb14d1DeLesley Hutchins  if (CE->getCastKind() != CK_LValueToRValue)
2146e0eaa8531f8fd9189710aac3b6f3aadb62bb14d1DeLesley Hutchins    return;
214747715cc201170952029a52806bcc26f69c38272dDeLesley Hutchins  checkAccess(CE->getSubExpr(), AK_Read);
2148e0eaa8531f8fd9189710aac3b6f3aadb62bb14d1DeLesley Hutchins}
2149e0eaa8531f8fd9189710aac3b6f3aadb62bb14d1DeLesley Hutchins
2150e0eaa8531f8fd9189710aac3b6f3aadb62bb14d1DeLesley Hutchins
2151df49782c54802ca1a4c1d36d66186aa039f32aecDeLesley Hutchinsvoid BuildLockset::VisitCallExpr(CallExpr *Exp) {
2152dd0a1f58a505ced9674f6d31a1ff65cb87774d67DeLesley Hutchins  if (CXXMemberCallExpr *CE = dyn_cast<CXXMemberCallExpr>(Exp)) {
2153dd0a1f58a505ced9674f6d31a1ff65cb87774d67DeLesley Hutchins    MemberExpr *ME = dyn_cast<MemberExpr>(CE->getCallee());
2154dd0a1f58a505ced9674f6d31a1ff65cb87774d67DeLesley Hutchins    // ME can be null when calling a method pointer
2155dd0a1f58a505ced9674f6d31a1ff65cb87774d67DeLesley Hutchins    CXXMethodDecl *MD = CE->getMethodDecl();
2156dd0a1f58a505ced9674f6d31a1ff65cb87774d67DeLesley Hutchins
2157dd0a1f58a505ced9674f6d31a1ff65cb87774d67DeLesley Hutchins    if (ME && MD) {
2158dd0a1f58a505ced9674f6d31a1ff65cb87774d67DeLesley Hutchins      if (ME->isArrow()) {
2159dd0a1f58a505ced9674f6d31a1ff65cb87774d67DeLesley Hutchins        if (MD->isConst()) {
2160dd0a1f58a505ced9674f6d31a1ff65cb87774d67DeLesley Hutchins          checkPtAccess(CE->getImplicitObjectArgument(), AK_Read);
2161dd0a1f58a505ced9674f6d31a1ff65cb87774d67DeLesley Hutchins        } else {  // FIXME -- should be AK_Written
2162dd0a1f58a505ced9674f6d31a1ff65cb87774d67DeLesley Hutchins          checkPtAccess(CE->getImplicitObjectArgument(), AK_Read);
216391e2061763f5e59f57e59c6f141b74b5ff0408adDeLesley Hutchins        }
2164dd0a1f58a505ced9674f6d31a1ff65cb87774d67DeLesley Hutchins      } else {
2165dd0a1f58a505ced9674f6d31a1ff65cb87774d67DeLesley Hutchins        if (MD->isConst())
2166dd0a1f58a505ced9674f6d31a1ff65cb87774d67DeLesley Hutchins          checkAccess(CE->getImplicitObjectArgument(), AK_Read);
2167dd0a1f58a505ced9674f6d31a1ff65cb87774d67DeLesley Hutchins        else     // FIXME -- should be AK_Written
2168dd0a1f58a505ced9674f6d31a1ff65cb87774d67DeLesley Hutchins          checkAccess(CE->getImplicitObjectArgument(), AK_Read);
216991e2061763f5e59f57e59c6f141b74b5ff0408adDeLesley Hutchins      }
2170dd0a1f58a505ced9674f6d31a1ff65cb87774d67DeLesley Hutchins    }
2171dd0a1f58a505ced9674f6d31a1ff65cb87774d67DeLesley Hutchins  } else if (CXXOperatorCallExpr *OE = dyn_cast<CXXOperatorCallExpr>(Exp)) {
2172dd0a1f58a505ced9674f6d31a1ff65cb87774d67DeLesley Hutchins    switch (OE->getOperator()) {
2173dd0a1f58a505ced9674f6d31a1ff65cb87774d67DeLesley Hutchins      case OO_Equal: {
2174dd0a1f58a505ced9674f6d31a1ff65cb87774d67DeLesley Hutchins        const Expr *Target = OE->getArg(0);
2175dd0a1f58a505ced9674f6d31a1ff65cb87774d67DeLesley Hutchins        const Expr *Source = OE->getArg(1);
2176dd0a1f58a505ced9674f6d31a1ff65cb87774d67DeLesley Hutchins        checkAccess(Target, AK_Written);
2177dd0a1f58a505ced9674f6d31a1ff65cb87774d67DeLesley Hutchins        checkAccess(Source, AK_Read);
2178dd0a1f58a505ced9674f6d31a1ff65cb87774d67DeLesley Hutchins        break;
2179dd0a1f58a505ced9674f6d31a1ff65cb87774d67DeLesley Hutchins      }
218043399fb0e79687043b7904195e95a23e44bd6ca1DeLesley Hutchins      case OO_Star:
2181f9495911c46a5f90d8cf14774c11ff521d505c7eDeLesley Hutchins      case OO_Arrow:
2182f9495911c46a5f90d8cf14774c11ff521d505c7eDeLesley Hutchins      case OO_Subscript: {
2183651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines        const Expr *Obj = OE->getArg(0);
2184651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines        checkAccess(Obj, AK_Read);
2185651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines        checkPtAccess(Obj, AK_Read);
218643399fb0e79687043b7904195e95a23e44bd6ca1DeLesley Hutchins        break;
218743399fb0e79687043b7904195e95a23e44bd6ca1DeLesley Hutchins      }
2188dd0a1f58a505ced9674f6d31a1ff65cb87774d67DeLesley Hutchins      default: {
21899a2f84b2f03e79fb21f9db9e029045fba09dedefDeLesley Hutchins        const Expr *Obj = OE->getArg(0);
21909a2f84b2f03e79fb21f9db9e029045fba09dedefDeLesley Hutchins        checkAccess(Obj, AK_Read);
2191dd0a1f58a505ced9674f6d31a1ff65cb87774d67DeLesley Hutchins        break;
219291e2061763f5e59f57e59c6f141b74b5ff0408adDeLesley Hutchins      }
219391e2061763f5e59f57e59c6f141b74b5ff0408adDeLesley Hutchins    }
219491e2061763f5e59f57e59c6f141b74b5ff0408adDeLesley Hutchins  }
2195e0eaa8531f8fd9189710aac3b6f3aadb62bb14d1DeLesley Hutchins  NamedDecl *D = dyn_cast_or_null<NamedDecl>(Exp->getCalleeDecl());
2196e0eaa8531f8fd9189710aac3b6f3aadb62bb14d1DeLesley Hutchins  if(!D || !D->hasAttrs())
2197e0eaa8531f8fd9189710aac3b6f3aadb62bb14d1DeLesley Hutchins    return;
2198e0eaa8531f8fd9189710aac3b6f3aadb62bb14d1DeLesley Hutchins  handleCall(Exp, D);
2199e0eaa8531f8fd9189710aac3b6f3aadb62bb14d1DeLesley Hutchins}
2200e0eaa8531f8fd9189710aac3b6f3aadb62bb14d1DeLesley Hutchins
2201e0eaa8531f8fd9189710aac3b6f3aadb62bb14d1DeLesley Hutchinsvoid BuildLockset::VisitCXXConstructExpr(CXXConstructExpr *Exp) {
2202dd0a1f58a505ced9674f6d31a1ff65cb87774d67DeLesley Hutchins  const CXXConstructorDecl *D = Exp->getConstructor();
2203dd0a1f58a505ced9674f6d31a1ff65cb87774d67DeLesley Hutchins  if (D && D->isCopyConstructor()) {
2204dd0a1f58a505ced9674f6d31a1ff65cb87774d67DeLesley Hutchins    const Expr* Source = Exp->getArg(0);
2205dd0a1f58a505ced9674f6d31a1ff65cb87774d67DeLesley Hutchins    checkAccess(Source, AK_Read);
220691e2061763f5e59f57e59c6f141b74b5ff0408adDeLesley Hutchins  }
22071fa3c0682a52c45c4ad0be3a82d0c85f26657072DeLesley Hutchins  // FIXME -- only handles constructors in DeclStmt below.
22081fa3c0682a52c45c4ad0be3a82d0c85f26657072DeLesley Hutchins}
22091fa3c0682a52c45c4ad0be3a82d0c85f26657072DeLesley Hutchins
22101fa3c0682a52c45c4ad0be3a82d0c85f26657072DeLesley Hutchinsvoid BuildLockset::VisitDeclStmt(DeclStmt *S) {
2211b37d2b5c0819d9ef596c7baec1e0be0d7c45b547DeLesley Hutchins  // adjust the context
221254c350a67b47f059e1d577bdd9e2d1dc31ff82b5DeLesley Hutchins  LVarCtx = Analyzer->LocalVarMap.getNextContext(CtxIndex, S, LVarCtx);
2213b37d2b5c0819d9ef596c7baec1e0be0d7c45b547DeLesley Hutchins
22146bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines  for (auto *D : S->getDeclGroup()) {
22151fa3c0682a52c45c4ad0be3a82d0c85f26657072DeLesley Hutchins    if (VarDecl *VD = dyn_cast_or_null<VarDecl>(D)) {
22161fa3c0682a52c45c4ad0be3a82d0c85f26657072DeLesley Hutchins      Expr *E = VD->getInit();
22179d6e7f3e12f1a825377ace33161e80caeda8cd06DeLesley Hutchins      // handle constructors that involve temporaries
22189d6e7f3e12f1a825377ace33161e80caeda8cd06DeLesley Hutchins      if (ExprWithCleanups *EWC = dyn_cast_or_null<ExprWithCleanups>(E))
22199d6e7f3e12f1a825377ace33161e80caeda8cd06DeLesley Hutchins        E = EWC->getSubExpr();
22209d6e7f3e12f1a825377ace33161e80caeda8cd06DeLesley Hutchins
22211fa3c0682a52c45c4ad0be3a82d0c85f26657072DeLesley Hutchins      if (CXXConstructExpr *CE = dyn_cast_or_null<CXXConstructExpr>(E)) {
22221fa3c0682a52c45c4ad0be3a82d0c85f26657072DeLesley Hutchins        NamedDecl *CtorD = dyn_cast_or_null<NamedDecl>(CE->getConstructor());
22231fa3c0682a52c45c4ad0be3a82d0c85f26657072DeLesley Hutchins        if (!CtorD || !CtorD->hasAttrs())
22241fa3c0682a52c45c4ad0be3a82d0c85f26657072DeLesley Hutchins          return;
22251fa3c0682a52c45c4ad0be3a82d0c85f26657072DeLesley Hutchins        handleCall(CE, CtorD, VD);
22261fa3c0682a52c45c4ad0be3a82d0c85f26657072DeLesley Hutchins      }
22271fa3c0682a52c45c4ad0be3a82d0c85f26657072DeLesley Hutchins    }
22281fa3c0682a52c45c4ad0be3a82d0c85f26657072DeLesley Hutchins  }
2229e0eaa8531f8fd9189710aac3b6f3aadb62bb14d1DeLesley Hutchins}
2230e0eaa8531f8fd9189710aac3b6f3aadb62bb14d1DeLesley Hutchins
2231a60448d6dfc91f4c30987e237bf70ef50ac7705bDeLesley Hutchins
22320da4414f3d30c34fafb81b13b2cec3680c0bc9e1DeLesley Hutchins
22334e4bc75d3570835e13183c66ac08974cdc016007Caitlin Sadowski/// \brief Compute the intersection of two locksets and issue warnings for any
22344e4bc75d3570835e13183c66ac08974cdc016007Caitlin Sadowski/// locks in the symmetric difference.
22354e4bc75d3570835e13183c66ac08974cdc016007Caitlin Sadowski///
22364e4bc75d3570835e13183c66ac08974cdc016007Caitlin Sadowski/// This function is used at a merge point in the CFG when comparing the lockset
22374e4bc75d3570835e13183c66ac08974cdc016007Caitlin Sadowski/// of each branch being merged. For example, given the following sequence:
22384e4bc75d3570835e13183c66ac08974cdc016007Caitlin Sadowski/// A; if () then B; else C; D; we need to check that the lockset after B and C
22394e4bc75d3570835e13183c66ac08974cdc016007Caitlin Sadowski/// are the same. In the event of a difference, we use the intersection of these
22404e4bc75d3570835e13183c66ac08974cdc016007Caitlin Sadowski/// two locksets at the start of D.
22410da4414f3d30c34fafb81b13b2cec3680c0bc9e1DeLesley Hutchins///
2242ad0fe03b897f9486191e75c8d90c3ffa9b4fd6a5Ted Kremenek/// \param FSet1 The first lockset.
2243ad0fe03b897f9486191e75c8d90c3ffa9b4fd6a5Ted Kremenek/// \param FSet2 The second lockset.
22440da4414f3d30c34fafb81b13b2cec3680c0bc9e1DeLesley Hutchins/// \param JoinLoc The location of the join point for error reporting
2245879a4334e4c4cab0c22ba91492ffc2838bbc21fcDeLesley Hutchins/// \param LEK1 The error message to report if a mutex is missing from LSet1
2246879a4334e4c4cab0c22ba91492ffc2838bbc21fcDeLesley Hutchins/// \param LEK2 The error message to report if a mutex is missing from Lset2
2247a1fa47139d6e9e7dcc40f2809605d1a258624e7fDeLesley Hutchinsvoid ThreadSafetyAnalyzer::intersectAndWarn(FactSet &FSet1,
2248a1fa47139d6e9e7dcc40f2809605d1a258624e7fDeLesley Hutchins                                            const FactSet &FSet2,
2249a1fa47139d6e9e7dcc40f2809605d1a258624e7fDeLesley Hutchins                                            SourceLocation JoinLoc,
2250a1fa47139d6e9e7dcc40f2809605d1a258624e7fDeLesley Hutchins                                            LockErrorKind LEK1,
2251a1fa47139d6e9e7dcc40f2809605d1a258624e7fDeLesley Hutchins                                            LockErrorKind LEK2,
2252a1fa47139d6e9e7dcc40f2809605d1a258624e7fDeLesley Hutchins                                            bool Modify) {
2253a1fa47139d6e9e7dcc40f2809605d1a258624e7fDeLesley Hutchins  FactSet FSet1Orig = FSet1;
2254a1fa47139d6e9e7dcc40f2809605d1a258624e7fDeLesley Hutchins
2255451f8e4ed63c97065fcbc79cf1cbbbbe1c4b6bd9DeLesley Hutchins  // Find locks in FSet2 that conflict or are not in FSet1, and warn.
22566bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines  for (const auto &Fact : FSet2) {
22576bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines    const SExpr &FSet2Mutex = FactMan[Fact].MutID;
22586bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines    const LockData &LDat2 = FactMan[Fact].LDat;
2259451f8e4ed63c97065fcbc79cf1cbbbbe1c4b6bd9DeLesley Hutchins    FactSet::iterator I1 = FSet1.findLockIter(FactMan, FSet2Mutex);
2260a1fa47139d6e9e7dcc40f2809605d1a258624e7fDeLesley Hutchins
2261451f8e4ed63c97065fcbc79cf1cbbbbe1c4b6bd9DeLesley Hutchins    if (I1 != FSet1.end()) {
2262451f8e4ed63c97065fcbc79cf1cbbbbe1c4b6bd9DeLesley Hutchins      const LockData* LDat1 = &FactMan[*I1].LDat;
2263bbe334142b38d2f9dad3ae2eb7b332c54a5b2cc1DeLesley Hutchins      if (LDat1->LKind != LDat2.LKind) {
2264651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines        Handler.handleExclusiveAndShared("mutex", FSet2Mutex.toString(),
2265651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines                                         LDat2.AcquireLoc, LDat1->AcquireLoc);
2266a1fa47139d6e9e7dcc40f2809605d1a258624e7fDeLesley Hutchins        if (Modify && LDat1->LKind != LK_Exclusive) {
2267451f8e4ed63c97065fcbc79cf1cbbbbe1c4b6bd9DeLesley Hutchins          // Take the exclusive lock, which is the one in FSet2.
22686bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines          *I1 = Fact;
2269a1fa47139d6e9e7dcc40f2809605d1a258624e7fDeLesley Hutchins        }
2270402aa0698fec81e574818a0a6c2000fac0b2c4c6Caitlin Sadowski      }
2271451f8e4ed63c97065fcbc79cf1cbbbbe1c4b6bd9DeLesley Hutchins      else if (LDat1->Asserted && !LDat2.Asserted) {
2272451f8e4ed63c97065fcbc79cf1cbbbbe1c4b6bd9DeLesley Hutchins        // The non-asserted lock in FSet2 is the one we want to track.
22736bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines        *I1 = Fact;
22745c6134fd09bc5b738dafdd1c774edde13d95cb20DeLesley Hutchins      }
2275402aa0698fec81e574818a0a6c2000fac0b2c4c6Caitlin Sadowski    } else {
2276bbe334142b38d2f9dad3ae2eb7b332c54a5b2cc1DeLesley Hutchins      if (LDat2.UnderlyingMutex.isValid()) {
2277a1fa47139d6e9e7dcc40f2809605d1a258624e7fDeLesley Hutchins        if (FSet2.findLock(FactMan, LDat2.UnderlyingMutex)) {
2278bbe334142b38d2f9dad3ae2eb7b332c54a5b2cc1DeLesley Hutchins          // If this is a scoped lock that manages another mutex, and if the
2279bbe334142b38d2f9dad3ae2eb7b332c54a5b2cc1DeLesley Hutchins          // underlying mutex is still held, then warn about the underlying
2280bbe334142b38d2f9dad3ae2eb7b332c54a5b2cc1DeLesley Hutchins          // mutex.
2281651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines          Handler.handleMutexHeldEndOfScope("mutex",
2282651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines                                            LDat2.UnderlyingMutex.toString(),
2283651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines                                            LDat2.AcquireLoc, JoinLoc, LEK1);
2284bbe334142b38d2f9dad3ae2eb7b332c54a5b2cc1DeLesley Hutchins        }
2285bbe334142b38d2f9dad3ae2eb7b332c54a5b2cc1DeLesley Hutchins      }
22865c6134fd09bc5b738dafdd1c774edde13d95cb20DeLesley Hutchins      else if (!LDat2.Managed && !FSet2Mutex.isUniversal() && !LDat2.Asserted)
2287651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines        Handler.handleMutexHeldEndOfScope("mutex", FSet2Mutex.toString(),
2288651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines                                          LDat2.AcquireLoc, JoinLoc, LEK1);
2289402aa0698fec81e574818a0a6c2000fac0b2c4c6Caitlin Sadowski    }
2290402aa0698fec81e574818a0a6c2000fac0b2c4c6Caitlin Sadowski  }
2291402aa0698fec81e574818a0a6c2000fac0b2c4c6Caitlin Sadowski
2292451f8e4ed63c97065fcbc79cf1cbbbbe1c4b6bd9DeLesley Hutchins  // Find locks in FSet1 that are not in FSet2, and remove them.
22936bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines  for (const auto &Fact : FSet1Orig) {
22946bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines    const SExpr &FSet1Mutex = FactMan[Fact].MutID;
22956bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines    const LockData &LDat1 = FactMan[Fact].LDat;
2296bbe334142b38d2f9dad3ae2eb7b332c54a5b2cc1DeLesley Hutchins
2297a1fa47139d6e9e7dcc40f2809605d1a258624e7fDeLesley Hutchins    if (!FSet2.findLock(FactMan, FSet1Mutex)) {
2298bbe334142b38d2f9dad3ae2eb7b332c54a5b2cc1DeLesley Hutchins      if (LDat1.UnderlyingMutex.isValid()) {
2299a1fa47139d6e9e7dcc40f2809605d1a258624e7fDeLesley Hutchins        if (FSet1Orig.findLock(FactMan, LDat1.UnderlyingMutex)) {
2300bbe334142b38d2f9dad3ae2eb7b332c54a5b2cc1DeLesley Hutchins          // If this is a scoped lock that manages another mutex, and if the
2301bbe334142b38d2f9dad3ae2eb7b332c54a5b2cc1DeLesley Hutchins          // underlying mutex is still held, then warn about the underlying
2302bbe334142b38d2f9dad3ae2eb7b332c54a5b2cc1DeLesley Hutchins          // mutex.
2303651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines          Handler.handleMutexHeldEndOfScope("mutex",
2304651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines                                            LDat1.UnderlyingMutex.toString(),
2305651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines                                            LDat1.AcquireLoc, JoinLoc, LEK1);
2306bbe334142b38d2f9dad3ae2eb7b332c54a5b2cc1DeLesley Hutchins        }
2307bbe334142b38d2f9dad3ae2eb7b332c54a5b2cc1DeLesley Hutchins      }
23085c6134fd09bc5b738dafdd1c774edde13d95cb20DeLesley Hutchins      else if (!LDat1.Managed && !FSet1Mutex.isUniversal() && !LDat1.Asserted)
2309651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines        Handler.handleMutexHeldEndOfScope("mutex", FSet1Mutex.toString(),
2310651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines                                          LDat1.AcquireLoc, JoinLoc, LEK2);
2311a1fa47139d6e9e7dcc40f2809605d1a258624e7fDeLesley Hutchins      if (Modify)
2312a1fa47139d6e9e7dcc40f2809605d1a258624e7fDeLesley Hutchins        FSet1.removeLock(FactMan, FSet1Mutex);
2313402aa0698fec81e574818a0a6c2000fac0b2c4c6Caitlin Sadowski    }
2314402aa0698fec81e574818a0a6c2000fac0b2c4c6Caitlin Sadowski  }
2315402aa0698fec81e574818a0a6c2000fac0b2c4c6Caitlin Sadowski}
2316402aa0698fec81e574818a0a6c2000fac0b2c4c6Caitlin Sadowski
2317cb96751b25a934b22402c1e4e0805db7608a5f2bCaitlin Sadowski
23180ecc2e9ce86b0705bc1a53a9c8f90c433bcdca1bDeLesley Hutchins// Return true if block B never continues to its successors.
23190ecc2e9ce86b0705bc1a53a9c8f90c433bcdca1bDeLesley Hutchinsinline bool neverReturns(const CFGBlock* B) {
23200ecc2e9ce86b0705bc1a53a9c8f90c433bcdca1bDeLesley Hutchins  if (B->hasNoReturnElement())
23210ecc2e9ce86b0705bc1a53a9c8f90c433bcdca1bDeLesley Hutchins    return true;
23220ecc2e9ce86b0705bc1a53a9c8f90c433bcdca1bDeLesley Hutchins  if (B->empty())
23230ecc2e9ce86b0705bc1a53a9c8f90c433bcdca1bDeLesley Hutchins    return false;
23240ecc2e9ce86b0705bc1a53a9c8f90c433bcdca1bDeLesley Hutchins
23250ecc2e9ce86b0705bc1a53a9c8f90c433bcdca1bDeLesley Hutchins  CFGElement Last = B->back();
2326b07805485c603be3d8011f72611465324c9e664bDavid Blaikie  if (Optional<CFGStmt> S = Last.getAs<CFGStmt>()) {
2327b07805485c603be3d8011f72611465324c9e664bDavid Blaikie    if (isa<CXXThrowExpr>(S->getStmt()))
23280ecc2e9ce86b0705bc1a53a9c8f90c433bcdca1bDeLesley Hutchins      return true;
23290ecc2e9ce86b0705bc1a53a9c8f90c433bcdca1bDeLesley Hutchins  }
23300ecc2e9ce86b0705bc1a53a9c8f90c433bcdca1bDeLesley Hutchins  return false;
23310ecc2e9ce86b0705bc1a53a9c8f90c433bcdca1bDeLesley Hutchins}
23320ecc2e9ce86b0705bc1a53a9c8f90c433bcdca1bDeLesley Hutchins
23335381c05f51e5b7c7627f1d95b9a3425303ce086aDeLesley Hutchins
2334402aa0698fec81e574818a0a6c2000fac0b2c4c6Caitlin Sadowski/// \brief Check a function's CFG for thread-safety violations.
2335402aa0698fec81e574818a0a6c2000fac0b2c4c6Caitlin Sadowski///
2336402aa0698fec81e574818a0a6c2000fac0b2c4c6Caitlin Sadowski/// We traverse the blocks in the CFG, compute the set of mutexes that are held
2337402aa0698fec81e574818a0a6c2000fac0b2c4c6Caitlin Sadowski/// at the end of each block, and issue warnings for thread safety violations.
2338402aa0698fec81e574818a0a6c2000fac0b2c4c6Caitlin Sadowski/// Each block in the CFG is traversed exactly once.
23391d26f48dc2eea1c07431ca1519d7034a21b9bcffTed Kremenekvoid ThreadSafetyAnalyzer::runAnalysis(AnalysisDeclContext &AC) {
23406bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines  // TODO: this whole function needs be rewritten as a visitor for CFGWalker.
23416bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines  // For now, we just use the walker to set things up.
23426bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines  threadSafety::CFGWalker walker;
23436bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines  if (!walker.init(AC))
23446bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines    return;
23459f80a97408ee0da939654d851ff42ad07d47e9c7DeLesley Hutchins
23460da4414f3d30c34fafb81b13b2cec3680c0bc9e1DeLesley Hutchins  // AC.dumpCFG(true);
23476bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines  // threadSafety::printSCFG(walker);
23486bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines
23496bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines  CFG *CFGraph = walker.getGraph();
23506bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines  const NamedDecl *D = walker.getDecl();
23510da4414f3d30c34fafb81b13b2cec3680c0bc9e1DeLesley Hutchins
2352651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines  if (D->hasAttr<NoThreadSafetyAnalysisAttr>())
23539f80a97408ee0da939654d851ff42ad07d47e9c7DeLesley Hutchins    return;
23546bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines
23552f13bec63b0236b169b026b7bc852da51ee029a7DeLesley Hutchins  // FIXME: Do something a bit more intelligent inside constructor and
23562f13bec63b0236b169b026b7bc852da51ee029a7DeLesley Hutchins  // destructor code.  Constructors and destructors must assume unique access
23572f13bec63b0236b169b026b7bc852da51ee029a7DeLesley Hutchins  // to 'this', so checks on member variable access is disabled, but we should
23582f13bec63b0236b169b026b7bc852da51ee029a7DeLesley Hutchins  // still enable checks on other objects.
23592f13bec63b0236b169b026b7bc852da51ee029a7DeLesley Hutchins  if (isa<CXXConstructorDecl>(D))
23602f13bec63b0236b169b026b7bc852da51ee029a7DeLesley Hutchins    return;  // Don't check inside constructors.
23612f13bec63b0236b169b026b7bc852da51ee029a7DeLesley Hutchins  if (isa<CXXDestructorDecl>(D))
23622f13bec63b0236b169b026b7bc852da51ee029a7DeLesley Hutchins    return;  // Don't check inside destructors.
2363402aa0698fec81e574818a0a6c2000fac0b2c4c6Caitlin Sadowski
236454c350a67b47f059e1d577bdd9e2d1dc31ff82b5DeLesley Hutchins  BlockInfo.resize(CFGraph->getNumBlockIDs(),
2365a1fa47139d6e9e7dcc40f2809605d1a258624e7fDeLesley Hutchins    CFGBlockInfo::getEmptyBlockInfo(LocalVarMap));
2366402aa0698fec81e574818a0a6c2000fac0b2c4c6Caitlin Sadowski
2367402aa0698fec81e574818a0a6c2000fac0b2c4c6Caitlin Sadowski  // We need to explore the CFG via a "topological" ordering.
2368402aa0698fec81e574818a0a6c2000fac0b2c4c6Caitlin Sadowski  // That way, we will be guaranteed to have information about required
2369402aa0698fec81e574818a0a6c2000fac0b2c4c6Caitlin Sadowski  // predecessor locksets when exploring a new block.
23706bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines  const PostOrderCFGView *SortedGraph = walker.getSortedGraph();
2371439ed1656664b29841f70b6c0b91460534ff4d93Ted Kremenek  PostOrderCFGView::CFGBlockSet VisitedBlocks(CFGraph);
2372402aa0698fec81e574818a0a6c2000fac0b2c4c6Caitlin Sadowski
2373d2f388299153d80cbe5ffaaed8a882b59a1b59bcDeLesley Hutchins  // Mark entry block as reachable
2374d2f388299153d80cbe5ffaaed8a882b59a1b59bcDeLesley Hutchins  BlockInfo[CFGraph->getEntry().getBlockID()].Reachable = true;
2375d2f388299153d80cbe5ffaaed8a882b59a1b59bcDeLesley Hutchins
2376b37d2b5c0819d9ef596c7baec1e0be0d7c45b547DeLesley Hutchins  // Compute SSA names for local variables
2377b37d2b5c0819d9ef596c7baec1e0be0d7c45b547DeLesley Hutchins  LocalVarMap.traverseCFG(CFGraph, SortedGraph, BlockInfo);
2378b37d2b5c0819d9ef596c7baec1e0be0d7c45b547DeLesley Hutchins
23792e5156274b8051217565b557bfa14c80f7990e9cRichard Smith  // Fill in source locations for all CFGBlocks.
23802e5156274b8051217565b557bfa14c80f7990e9cRichard Smith  findBlockLocations(CFGraph, SortedGraph, BlockInfo);
23812e5156274b8051217565b557bfa14c80f7990e9cRichard Smith
23825696884053b4a60dbed01ea8c7e6cd8dcf9b5de9DeLesley Hutchins  MutexIDList ExclusiveLocksAcquired;
23835696884053b4a60dbed01ea8c7e6cd8dcf9b5de9DeLesley Hutchins  MutexIDList SharedLocksAcquired;
23845696884053b4a60dbed01ea8c7e6cd8dcf9b5de9DeLesley Hutchins  MutexIDList LocksReleased;
23855696884053b4a60dbed01ea8c7e6cd8dcf9b5de9DeLesley Hutchins
2386a60448d6dfc91f4c30987e237bf70ef50ac7705bDeLesley Hutchins  // Add locks from exclusive_locks_required and shared_locks_required
23872f13bec63b0236b169b026b7bc852da51ee029a7DeLesley Hutchins  // to initial lockset. Also turn off checking for lock and unlock functions.
23882f13bec63b0236b169b026b7bc852da51ee029a7DeLesley Hutchins  // FIXME: is there a more intelligent way to check lock/unlock functions?
2389439ed1656664b29841f70b6c0b91460534ff4d93Ted Kremenek  if (!SortedGraph->empty() && D->hasAttrs()) {
2390439ed1656664b29841f70b6c0b91460534ff4d93Ted Kremenek    const CFGBlock *FirstBlock = *SortedGraph->begin();
2391a1fa47139d6e9e7dcc40f2809605d1a258624e7fDeLesley Hutchins    FactSet &InitialLockset = BlockInfo[FirstBlock->getBlockID()].EntrySet;
2392cb96751b25a934b22402c1e4e0805db7608a5f2bCaitlin Sadowski    const AttrVec &ArgAttrs = D->getAttrs();
23935381c05f51e5b7c7627f1d95b9a3425303ce086aDeLesley Hutchins
23945381c05f51e5b7c7627f1d95b9a3425303ce086aDeLesley Hutchins    MutexIDList ExclusiveLocksToAdd;
23955381c05f51e5b7c7627f1d95b9a3425303ce086aDeLesley Hutchins    MutexIDList SharedLocksToAdd;
2396651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines    StringRef CapDiagKind = "mutex";
23975381c05f51e5b7c7627f1d95b9a3425303ce086aDeLesley Hutchins
23985381c05f51e5b7c7627f1d95b9a3425303ce086aDeLesley Hutchins    SourceLocation Loc = D->getLocation();
23996bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines    for (const auto *Attr : ArgAttrs) {
24005381c05f51e5b7c7627f1d95b9a3425303ce086aDeLesley Hutchins      Loc = Attr->getLocation();
24016bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines      if (const auto *A = dyn_cast<RequiresCapabilityAttr>(Attr)) {
2402651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines        getMutexIDs(A->isShared() ? SharedLocksToAdd : ExclusiveLocksToAdd, A,
24036bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines                    nullptr, D);
2404651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines        CapDiagKind = ClassifyDiagnostic(A);
24056bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines      } else if (const auto *A = dyn_cast<ReleaseCapabilityAttr>(Attr)) {
24065696884053b4a60dbed01ea8c7e6cd8dcf9b5de9DeLesley Hutchins        // UNLOCK_FUNCTION() is used to hide the underlying lock implementation.
24075696884053b4a60dbed01ea8c7e6cd8dcf9b5de9DeLesley Hutchins        // We must ignore such methods.
24085696884053b4a60dbed01ea8c7e6cd8dcf9b5de9DeLesley Hutchins        if (A->args_size() == 0)
24095696884053b4a60dbed01ea8c7e6cd8dcf9b5de9DeLesley Hutchins          return;
24105696884053b4a60dbed01ea8c7e6cd8dcf9b5de9DeLesley Hutchins        // FIXME -- deal with exclusive vs. shared unlock functions?
24116bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines        getMutexIDs(ExclusiveLocksToAdd, A, nullptr, D);
24126bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines        getMutexIDs(LocksReleased, A, nullptr, D);
2413651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines        CapDiagKind = ClassifyDiagnostic(A);
24146bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines      } else if (const auto *A = dyn_cast<AcquireCapabilityAttr>(Attr)) {
24155696884053b4a60dbed01ea8c7e6cd8dcf9b5de9DeLesley Hutchins        if (A->args_size() == 0)
24165696884053b4a60dbed01ea8c7e6cd8dcf9b5de9DeLesley Hutchins          return;
2417651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines        getMutexIDs(A->isShared() ? SharedLocksAcquired
2418651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines                                  : ExclusiveLocksAcquired,
2419651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines                    A, nullptr, D);
2420651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines        CapDiagKind = ClassifyDiagnostic(A);
242176f0a6e9bc9ee5aae029f959f64fae290727cca4DeLesley Hutchins      } else if (isa<ExclusiveTrylockFunctionAttr>(Attr)) {
242276f0a6e9bc9ee5aae029f959f64fae290727cca4DeLesley Hutchins        // Don't try to check trylock functions for now
242376f0a6e9bc9ee5aae029f959f64fae290727cca4DeLesley Hutchins        return;
242476f0a6e9bc9ee5aae029f959f64fae290727cca4DeLesley Hutchins      } else if (isa<SharedTrylockFunctionAttr>(Attr)) {
242576f0a6e9bc9ee5aae029f959f64fae290727cca4DeLesley Hutchins        // Don't try to check trylock functions for now
242676f0a6e9bc9ee5aae029f959f64fae290727cca4DeLesley Hutchins        return;
2427cb96751b25a934b22402c1e4e0805db7608a5f2bCaitlin Sadowski      }
2428cb96751b25a934b22402c1e4e0805db7608a5f2bCaitlin Sadowski    }
24295381c05f51e5b7c7627f1d95b9a3425303ce086aDeLesley Hutchins
24305381c05f51e5b7c7627f1d95b9a3425303ce086aDeLesley Hutchins    // FIXME -- Loc can be wrong here.
2431651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines    for (const auto &ExclusiveLockToAdd : ExclusiveLocksToAdd)
2432651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines      addLock(InitialLockset, ExclusiveLockToAdd, LockData(Loc, LK_Exclusive),
2433651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines              CapDiagKind);
2434651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines    for (const auto &SharedLockToAdd : SharedLocksToAdd)
2435651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines      addLock(InitialLockset, SharedLockToAdd, LockData(Loc, LK_Shared),
2436651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines              CapDiagKind);
2437cb96751b25a934b22402c1e4e0805db7608a5f2bCaitlin Sadowski  }
2438cb96751b25a934b22402c1e4e0805db7608a5f2bCaitlin Sadowski
24396bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines  for (const auto *CurrBlock : *SortedGraph) {
2440402aa0698fec81e574818a0a6c2000fac0b2c4c6Caitlin Sadowski    int CurrBlockID = CurrBlock->getBlockID();
2441b37d2b5c0819d9ef596c7baec1e0be0d7c45b547DeLesley Hutchins    CFGBlockInfo *CurrBlockInfo = &BlockInfo[CurrBlockID];
2442402aa0698fec81e574818a0a6c2000fac0b2c4c6Caitlin Sadowski
2443402aa0698fec81e574818a0a6c2000fac0b2c4c6Caitlin Sadowski    // Use the default initial lockset in case there are no predecessors.
2444b37d2b5c0819d9ef596c7baec1e0be0d7c45b547DeLesley Hutchins    VisitedBlocks.insert(CurrBlock);
2445402aa0698fec81e574818a0a6c2000fac0b2c4c6Caitlin Sadowski
2446402aa0698fec81e574818a0a6c2000fac0b2c4c6Caitlin Sadowski    // Iterate through the predecessor blocks and warn if the lockset for all
2447402aa0698fec81e574818a0a6c2000fac0b2c4c6Caitlin Sadowski    // predecessors is not the same. We take the entry lockset of the current
2448402aa0698fec81e574818a0a6c2000fac0b2c4c6Caitlin Sadowski    // block to be the intersection of all previous locksets.
2449402aa0698fec81e574818a0a6c2000fac0b2c4c6Caitlin Sadowski    // FIXME: By keeping the intersection, we may output more errors in future
2450402aa0698fec81e574818a0a6c2000fac0b2c4c6Caitlin Sadowski    // for a lock which is not in the intersection, but was in the union. We
2451402aa0698fec81e574818a0a6c2000fac0b2c4c6Caitlin Sadowski    // may want to also keep the union in future. As an example, let's say
2452402aa0698fec81e574818a0a6c2000fac0b2c4c6Caitlin Sadowski    // the intersection contains Mutex L, and the union contains L and M.
2453402aa0698fec81e574818a0a6c2000fac0b2c4c6Caitlin Sadowski    // Later we unlock M. At this point, we would output an error because we
2454402aa0698fec81e574818a0a6c2000fac0b2c4c6Caitlin Sadowski    // never locked M; although the real error is probably that we forgot to
2455402aa0698fec81e574818a0a6c2000fac0b2c4c6Caitlin Sadowski    // lock M on all code paths. Conversely, let's say that later we lock M.
2456402aa0698fec81e574818a0a6c2000fac0b2c4c6Caitlin Sadowski    // In this case, we should compare against the intersection instead of the
2457402aa0698fec81e574818a0a6c2000fac0b2c4c6Caitlin Sadowski    // union because the real error is probably that we forgot to unlock M on
2458402aa0698fec81e574818a0a6c2000fac0b2c4c6Caitlin Sadowski    // all code paths.
2459402aa0698fec81e574818a0a6c2000fac0b2c4c6Caitlin Sadowski    bool LocksetInitialized = false;
2460cfa88f893915ceb8ae4ce2f17c46c24a4d67502fDmitri Gribenko    SmallVector<CFGBlock *, 8> SpecialBlocks;
2461402aa0698fec81e574818a0a6c2000fac0b2c4c6Caitlin Sadowski    for (CFGBlock::const_pred_iterator PI = CurrBlock->pred_begin(),
2462402aa0698fec81e574818a0a6c2000fac0b2c4c6Caitlin Sadowski         PE  = CurrBlock->pred_end(); PI != PE; ++PI) {
2463402aa0698fec81e574818a0a6c2000fac0b2c4c6Caitlin Sadowski
2464402aa0698fec81e574818a0a6c2000fac0b2c4c6Caitlin Sadowski      // if *PI -> CurrBlock is a back edge
24656bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines      if (*PI == nullptr || !VisitedBlocks.alreadySet(*PI))
2466402aa0698fec81e574818a0a6c2000fac0b2c4c6Caitlin Sadowski        continue;
2467402aa0698fec81e574818a0a6c2000fac0b2c4c6Caitlin Sadowski
2468d2f388299153d80cbe5ffaaed8a882b59a1b59bcDeLesley Hutchins      int PrevBlockID = (*PI)->getBlockID();
2469d2f388299153d80cbe5ffaaed8a882b59a1b59bcDeLesley Hutchins      CFGBlockInfo *PrevBlockInfo = &BlockInfo[PrevBlockID];
2470d2f388299153d80cbe5ffaaed8a882b59a1b59bcDeLesley Hutchins
24712a35be803c405221f5f23c7bdedb91f09efdd3acDeLesley Hutchins      // Ignore edges from blocks that can't return.
24720ecc2e9ce86b0705bc1a53a9c8f90c433bcdca1bDeLesley Hutchins      if (neverReturns(*PI) || !PrevBlockInfo->Reachable)
24732a35be803c405221f5f23c7bdedb91f09efdd3acDeLesley Hutchins        continue;
24742a35be803c405221f5f23c7bdedb91f09efdd3acDeLesley Hutchins
2475d2f388299153d80cbe5ffaaed8a882b59a1b59bcDeLesley Hutchins      // Okay, we can reach this block from the entry.
2476d2f388299153d80cbe5ffaaed8a882b59a1b59bcDeLesley Hutchins      CurrBlockInfo->Reachable = true;
2477d2f388299153d80cbe5ffaaed8a882b59a1b59bcDeLesley Hutchins
2478aacde7174af6c5759b52dc0ceb7b167d323afb6aRichard Smith      // If the previous block ended in a 'continue' or 'break' statement, then
2479aacde7174af6c5759b52dc0ceb7b167d323afb6aRichard Smith      // a difference in locksets is probably due to a bug in that block, rather
2480aacde7174af6c5759b52dc0ceb7b167d323afb6aRichard Smith      // than in some other predecessor. In that case, keep the other
2481aacde7174af6c5759b52dc0ceb7b167d323afb6aRichard Smith      // predecessor's lockset.
2482aacde7174af6c5759b52dc0ceb7b167d323afb6aRichard Smith      if (const Stmt *Terminator = (*PI)->getTerminator()) {
2483aacde7174af6c5759b52dc0ceb7b167d323afb6aRichard Smith        if (isa<ContinueStmt>(Terminator) || isa<BreakStmt>(Terminator)) {
2484aacde7174af6c5759b52dc0ceb7b167d323afb6aRichard Smith          SpecialBlocks.push_back(*PI);
2485aacde7174af6c5759b52dc0ceb7b167d323afb6aRichard Smith          continue;
2486aacde7174af6c5759b52dc0ceb7b167d323afb6aRichard Smith        }
2487aacde7174af6c5759b52dc0ceb7b167d323afb6aRichard Smith      }
2488aacde7174af6c5759b52dc0ceb7b167d323afb6aRichard Smith
2489a1fa47139d6e9e7dcc40f2809605d1a258624e7fDeLesley Hutchins      FactSet PrevLockset;
2490a1fa47139d6e9e7dcc40f2809605d1a258624e7fDeLesley Hutchins      getEdgeLockset(PrevLockset, PrevBlockInfo->ExitSet, *PI, CurrBlock);
2491b37d2b5c0819d9ef596c7baec1e0be0d7c45b547DeLesley Hutchins
2492402aa0698fec81e574818a0a6c2000fac0b2c4c6Caitlin Sadowski      if (!LocksetInitialized) {
24930da4414f3d30c34fafb81b13b2cec3680c0bc9e1DeLesley Hutchins        CurrBlockInfo->EntrySet = PrevLockset;
2494402aa0698fec81e574818a0a6c2000fac0b2c4c6Caitlin Sadowski        LocksetInitialized = true;
2495402aa0698fec81e574818a0a6c2000fac0b2c4c6Caitlin Sadowski      } else {
2496a1fa47139d6e9e7dcc40f2809605d1a258624e7fDeLesley Hutchins        intersectAndWarn(CurrBlockInfo->EntrySet, PrevLockset,
2497a1fa47139d6e9e7dcc40f2809605d1a258624e7fDeLesley Hutchins                         CurrBlockInfo->EntryLoc,
2498a1fa47139d6e9e7dcc40f2809605d1a258624e7fDeLesley Hutchins                         LEK_LockedSomePredecessors);
2499402aa0698fec81e574818a0a6c2000fac0b2c4c6Caitlin Sadowski      }
2500402aa0698fec81e574818a0a6c2000fac0b2c4c6Caitlin Sadowski    }
2501402aa0698fec81e574818a0a6c2000fac0b2c4c6Caitlin Sadowski
2502d2f388299153d80cbe5ffaaed8a882b59a1b59bcDeLesley Hutchins    // Skip rest of block if it's not reachable.
2503d2f388299153d80cbe5ffaaed8a882b59a1b59bcDeLesley Hutchins    if (!CurrBlockInfo->Reachable)
2504d2f388299153d80cbe5ffaaed8a882b59a1b59bcDeLesley Hutchins      continue;
2505d2f388299153d80cbe5ffaaed8a882b59a1b59bcDeLesley Hutchins
2506aacde7174af6c5759b52dc0ceb7b167d323afb6aRichard Smith    // Process continue and break blocks. Assume that the lockset for the
2507aacde7174af6c5759b52dc0ceb7b167d323afb6aRichard Smith    // resulting block is unaffected by any discrepancies in them.
25086bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines    for (const auto *PrevBlock : SpecialBlocks) {
2509aacde7174af6c5759b52dc0ceb7b167d323afb6aRichard Smith      int PrevBlockID = PrevBlock->getBlockID();
2510aacde7174af6c5759b52dc0ceb7b167d323afb6aRichard Smith      CFGBlockInfo *PrevBlockInfo = &BlockInfo[PrevBlockID];
2511aacde7174af6c5759b52dc0ceb7b167d323afb6aRichard Smith
2512aacde7174af6c5759b52dc0ceb7b167d323afb6aRichard Smith      if (!LocksetInitialized) {
2513aacde7174af6c5759b52dc0ceb7b167d323afb6aRichard Smith        CurrBlockInfo->EntrySet = PrevBlockInfo->ExitSet;
2514aacde7174af6c5759b52dc0ceb7b167d323afb6aRichard Smith        LocksetInitialized = true;
2515aacde7174af6c5759b52dc0ceb7b167d323afb6aRichard Smith      } else {
2516aacde7174af6c5759b52dc0ceb7b167d323afb6aRichard Smith        // Determine whether this edge is a loop terminator for diagnostic
2517aacde7174af6c5759b52dc0ceb7b167d323afb6aRichard Smith        // purposes. FIXME: A 'break' statement might be a loop terminator, but
2518aacde7174af6c5759b52dc0ceb7b167d323afb6aRichard Smith        // it might also be part of a switch. Also, a subsequent destructor
2519aacde7174af6c5759b52dc0ceb7b167d323afb6aRichard Smith        // might add to the lockset, in which case the real issue might be a
2520aacde7174af6c5759b52dc0ceb7b167d323afb6aRichard Smith        // double lock on the other path.
2521aacde7174af6c5759b52dc0ceb7b167d323afb6aRichard Smith        const Stmt *Terminator = PrevBlock->getTerminator();
2522aacde7174af6c5759b52dc0ceb7b167d323afb6aRichard Smith        bool IsLoop = Terminator && isa<ContinueStmt>(Terminator);
2523aacde7174af6c5759b52dc0ceb7b167d323afb6aRichard Smith
2524a1fa47139d6e9e7dcc40f2809605d1a258624e7fDeLesley Hutchins        FactSet PrevLockset;
2525a1fa47139d6e9e7dcc40f2809605d1a258624e7fDeLesley Hutchins        getEdgeLockset(PrevLockset, PrevBlockInfo->ExitSet,
2526a1fa47139d6e9e7dcc40f2809605d1a258624e7fDeLesley Hutchins                       PrevBlock, CurrBlock);
25270da4414f3d30c34fafb81b13b2cec3680c0bc9e1DeLesley Hutchins
2528aacde7174af6c5759b52dc0ceb7b167d323afb6aRichard Smith        // Do not update EntrySet.
25290da4414f3d30c34fafb81b13b2cec3680c0bc9e1DeLesley Hutchins        intersectAndWarn(CurrBlockInfo->EntrySet, PrevLockset,
25300da4414f3d30c34fafb81b13b2cec3680c0bc9e1DeLesley Hutchins                         PrevBlockInfo->ExitLoc,
2531aacde7174af6c5759b52dc0ceb7b167d323afb6aRichard Smith                         IsLoop ? LEK_LockedSomeLoopIterations
2532a1fa47139d6e9e7dcc40f2809605d1a258624e7fDeLesley Hutchins                                : LEK_LockedSomePredecessors,
2533a1fa47139d6e9e7dcc40f2809605d1a258624e7fDeLesley Hutchins                         false);
2534aacde7174af6c5759b52dc0ceb7b167d323afb6aRichard Smith      }
2535aacde7174af6c5759b52dc0ceb7b167d323afb6aRichard Smith    }
2536aacde7174af6c5759b52dc0ceb7b167d323afb6aRichard Smith
253754c350a67b47f059e1d577bdd9e2d1dc31ff82b5DeLesley Hutchins    BuildLockset LocksetBuilder(this, *CurrBlockInfo);
253854c350a67b47f059e1d577bdd9e2d1dc31ff82b5DeLesley Hutchins
2539b37d2b5c0819d9ef596c7baec1e0be0d7c45b547DeLesley Hutchins    // Visit all the statements in the basic block.
2540402aa0698fec81e574818a0a6c2000fac0b2c4c6Caitlin Sadowski    for (CFGBlock::const_iterator BI = CurrBlock->begin(),
2541402aa0698fec81e574818a0a6c2000fac0b2c4c6Caitlin Sadowski         BE = CurrBlock->end(); BI != BE; ++BI) {
25426db51f707e93816364039a2a904d13d3968c7f05DeLesley Hutchins      switch (BI->getKind()) {
25436db51f707e93816364039a2a904d13d3968c7f05DeLesley Hutchins        case CFGElement::Statement: {
2544fdf6a279c9a75c778eba382d9a156697092982a1David Blaikie          CFGStmt CS = BI->castAs<CFGStmt>();
2545fdf6a279c9a75c778eba382d9a156697092982a1David Blaikie          LocksetBuilder.Visit(const_cast<Stmt*>(CS.getStmt()));
25466db51f707e93816364039a2a904d13d3968c7f05DeLesley Hutchins          break;
25476db51f707e93816364039a2a904d13d3968c7f05DeLesley Hutchins        }
25486db51f707e93816364039a2a904d13d3968c7f05DeLesley Hutchins        // Ignore BaseDtor, MemberDtor, and TemporaryDtor for now.
25496db51f707e93816364039a2a904d13d3968c7f05DeLesley Hutchins        case CFGElement::AutomaticObjectDtor: {
2550fdf6a279c9a75c778eba382d9a156697092982a1David Blaikie          CFGAutomaticObjDtor AD = BI->castAs<CFGAutomaticObjDtor>();
2551fdf6a279c9a75c778eba382d9a156697092982a1David Blaikie          CXXDestructorDecl *DD = const_cast<CXXDestructorDecl *>(
2552fdf6a279c9a75c778eba382d9a156697092982a1David Blaikie              AD.getDestructorDecl(AC.getASTContext()));
25536db51f707e93816364039a2a904d13d3968c7f05DeLesley Hutchins          if (!DD->hasAttrs())
25546db51f707e93816364039a2a904d13d3968c7f05DeLesley Hutchins            break;
25556db51f707e93816364039a2a904d13d3968c7f05DeLesley Hutchins
25566db51f707e93816364039a2a904d13d3968c7f05DeLesley Hutchins          // Create a dummy expression,
2557fdf6a279c9a75c778eba382d9a156697092982a1David Blaikie          VarDecl *VD = const_cast<VarDecl*>(AD.getVarDecl());
2558f4b88a45902af1802a1cb42ba48b1c474474f228John McCall          DeclRefExpr DRE(VD, false, VD->getType(), VK_LValue,
2559fdf6a279c9a75c778eba382d9a156697092982a1David Blaikie                          AD.getTriggerStmt()->getLocEnd());
25606db51f707e93816364039a2a904d13d3968c7f05DeLesley Hutchins          LocksetBuilder.handleCall(&DRE, DD);
25616db51f707e93816364039a2a904d13d3968c7f05DeLesley Hutchins          break;
25626db51f707e93816364039a2a904d13d3968c7f05DeLesley Hutchins        }
25636db51f707e93816364039a2a904d13d3968c7f05DeLesley Hutchins        default:
25646db51f707e93816364039a2a904d13d3968c7f05DeLesley Hutchins          break;
25656db51f707e93816364039a2a904d13d3968c7f05DeLesley Hutchins      }
2566402aa0698fec81e574818a0a6c2000fac0b2c4c6Caitlin Sadowski    }
2567a1fa47139d6e9e7dcc40f2809605d1a258624e7fDeLesley Hutchins    CurrBlockInfo->ExitSet = LocksetBuilder.FSet;
2568402aa0698fec81e574818a0a6c2000fac0b2c4c6Caitlin Sadowski
2569402aa0698fec81e574818a0a6c2000fac0b2c4c6Caitlin Sadowski    // For every back edge from CurrBlock (the end of the loop) to another block
2570402aa0698fec81e574818a0a6c2000fac0b2c4c6Caitlin Sadowski    // (FirstLoopBlock) we need to check that the Lockset of Block is equal to
2571402aa0698fec81e574818a0a6c2000fac0b2c4c6Caitlin Sadowski    // the one held at the beginning of FirstLoopBlock. We can look up the
2572402aa0698fec81e574818a0a6c2000fac0b2c4c6Caitlin Sadowski    // Lockset held at the beginning of FirstLoopBlock in the EntryLockSets map.
2573402aa0698fec81e574818a0a6c2000fac0b2c4c6Caitlin Sadowski    for (CFGBlock::const_succ_iterator SI = CurrBlock->succ_begin(),
2574402aa0698fec81e574818a0a6c2000fac0b2c4c6Caitlin Sadowski         SE  = CurrBlock->succ_end(); SI != SE; ++SI) {
2575402aa0698fec81e574818a0a6c2000fac0b2c4c6Caitlin Sadowski
2576402aa0698fec81e574818a0a6c2000fac0b2c4c6Caitlin Sadowski      // if CurrBlock -> *SI is *not* a back edge
25776bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines      if (*SI == nullptr || !VisitedBlocks.alreadySet(*SI))
2578402aa0698fec81e574818a0a6c2000fac0b2c4c6Caitlin Sadowski        continue;
2579402aa0698fec81e574818a0a6c2000fac0b2c4c6Caitlin Sadowski
2580402aa0698fec81e574818a0a6c2000fac0b2c4c6Caitlin Sadowski      CFGBlock *FirstLoopBlock = *SI;
25810da4414f3d30c34fafb81b13b2cec3680c0bc9e1DeLesley Hutchins      CFGBlockInfo *PreLoop = &BlockInfo[FirstLoopBlock->getBlockID()];
25820da4414f3d30c34fafb81b13b2cec3680c0bc9e1DeLesley Hutchins      CFGBlockInfo *LoopEnd = &BlockInfo[CurrBlockID];
25830da4414f3d30c34fafb81b13b2cec3680c0bc9e1DeLesley Hutchins      intersectAndWarn(LoopEnd->ExitSet, PreLoop->EntrySet,
25840da4414f3d30c34fafb81b13b2cec3680c0bc9e1DeLesley Hutchins                       PreLoop->EntryLoc,
2585a1fa47139d6e9e7dcc40f2809605d1a258624e7fDeLesley Hutchins                       LEK_LockedSomeLoopIterations,
2586a1fa47139d6e9e7dcc40f2809605d1a258624e7fDeLesley Hutchins                       false);
2587402aa0698fec81e574818a0a6c2000fac0b2c4c6Caitlin Sadowski    }
2588402aa0698fec81e574818a0a6c2000fac0b2c4c6Caitlin Sadowski  }
2589402aa0698fec81e574818a0a6c2000fac0b2c4c6Caitlin Sadowski
2590d2f388299153d80cbe5ffaaed8a882b59a1b59bcDeLesley Hutchins  CFGBlockInfo *Initial = &BlockInfo[CFGraph->getEntry().getBlockID()];
2591d2f388299153d80cbe5ffaaed8a882b59a1b59bcDeLesley Hutchins  CFGBlockInfo *Final   = &BlockInfo[CFGraph->getExit().getBlockID()];
25922a237e03c407ff55bd8639b18658a8751955f1dbDeLesley Hutchins
25932a237e03c407ff55bd8639b18658a8751955f1dbDeLesley Hutchins  // Skip the final check if the exit block is unreachable.
2594d2f388299153d80cbe5ffaaed8a882b59a1b59bcDeLesley Hutchins  if (!Final->Reachable)
25952a237e03c407ff55bd8639b18658a8751955f1dbDeLesley Hutchins    return;
25962a237e03c407ff55bd8639b18658a8751955f1dbDeLesley Hutchins
25975696884053b4a60dbed01ea8c7e6cd8dcf9b5de9DeLesley Hutchins  // By default, we expect all locks held on entry to be held on exit.
25985696884053b4a60dbed01ea8c7e6cd8dcf9b5de9DeLesley Hutchins  FactSet ExpectedExitSet = Initial->EntrySet;
25995696884053b4a60dbed01ea8c7e6cd8dcf9b5de9DeLesley Hutchins
26005696884053b4a60dbed01ea8c7e6cd8dcf9b5de9DeLesley Hutchins  // Adjust the expected exit set by adding or removing locks, as declared
26015696884053b4a60dbed01ea8c7e6cd8dcf9b5de9DeLesley Hutchins  // by *-LOCK_FUNCTION and UNLOCK_FUNCTION.  The intersect below will then
26025696884053b4a60dbed01ea8c7e6cd8dcf9b5de9DeLesley Hutchins  // issue the appropriate warning.
26035696884053b4a60dbed01ea8c7e6cd8dcf9b5de9DeLesley Hutchins  // FIXME: the location here is not quite right.
26046bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines  for (const auto &Lock : ExclusiveLocksAcquired)
26056bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines    ExpectedExitSet.addLock(FactMan, Lock,
26065696884053b4a60dbed01ea8c7e6cd8dcf9b5de9DeLesley Hutchins                            LockData(D->getLocation(), LK_Exclusive));
26076bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines  for (const auto &Lock : SharedLocksAcquired)
26086bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines    ExpectedExitSet.addLock(FactMan, Lock,
26095696884053b4a60dbed01ea8c7e6cd8dcf9b5de9DeLesley Hutchins                            LockData(D->getLocation(), LK_Shared));
26106bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines  for (const auto &Lock : LocksReleased)
26116bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines    ExpectedExitSet.removeLock(FactMan, Lock);
26125696884053b4a60dbed01ea8c7e6cd8dcf9b5de9DeLesley Hutchins
26131748b1256646cf0752f172c53ad7482f7beed185Caitlin Sadowski  // FIXME: Should we call this function for all blocks which exit the function?
26145696884053b4a60dbed01ea8c7e6cd8dcf9b5de9DeLesley Hutchins  intersectAndWarn(ExpectedExitSet, Final->ExitSet,
26150da4414f3d30c34fafb81b13b2cec3680c0bc9e1DeLesley Hutchins                   Final->ExitLoc,
2616879a4334e4c4cab0c22ba91492ffc2838bbc21fcDeLesley Hutchins                   LEK_LockedAtEndOfFunction,
2617a1fa47139d6e9e7dcc40f2809605d1a258624e7fDeLesley Hutchins                   LEK_NotLockedAtEndOfFunction,
2618a1fa47139d6e9e7dcc40f2809605d1a258624e7fDeLesley Hutchins                   false);
2619a60448d6dfc91f4c30987e237bf70ef50ac7705bDeLesley Hutchins}
2620a60448d6dfc91f4c30987e237bf70ef50ac7705bDeLesley Hutchins
2621a60448d6dfc91f4c30987e237bf70ef50ac7705bDeLesley Hutchins} // end anonymous namespace
2622a60448d6dfc91f4c30987e237bf70ef50ac7705bDeLesley Hutchins
2623a60448d6dfc91f4c30987e237bf70ef50ac7705bDeLesley Hutchins
2624a60448d6dfc91f4c30987e237bf70ef50ac7705bDeLesley Hutchinsnamespace clang {
2625a60448d6dfc91f4c30987e237bf70ef50ac7705bDeLesley Hutchinsnamespace thread_safety {
2626a60448d6dfc91f4c30987e237bf70ef50ac7705bDeLesley Hutchins
2627a60448d6dfc91f4c30987e237bf70ef50ac7705bDeLesley Hutchins/// \brief Check a function's CFG for thread-safety violations.
2628a60448d6dfc91f4c30987e237bf70ef50ac7705bDeLesley Hutchins///
2629a60448d6dfc91f4c30987e237bf70ef50ac7705bDeLesley Hutchins/// We traverse the blocks in the CFG, compute the set of mutexes that are held
2630a60448d6dfc91f4c30987e237bf70ef50ac7705bDeLesley Hutchins/// at the end of each block, and issue warnings for thread safety violations.
2631a60448d6dfc91f4c30987e237bf70ef50ac7705bDeLesley Hutchins/// Each block in the CFG is traversed exactly once.
26321d26f48dc2eea1c07431ca1519d7034a21b9bcffTed Kremenekvoid runThreadSafetyAnalysis(AnalysisDeclContext &AC,
2633a60448d6dfc91f4c30987e237bf70ef50ac7705bDeLesley Hutchins                             ThreadSafetyHandler &Handler) {
2634a60448d6dfc91f4c30987e237bf70ef50ac7705bDeLesley Hutchins  ThreadSafetyAnalyzer Analyzer(Handler);
2635a60448d6dfc91f4c30987e237bf70ef50ac7705bDeLesley Hutchins  Analyzer.runAnalysis(AC);
2636402aa0698fec81e574818a0a6c2000fac0b2c4c6Caitlin Sadowski}
2637402aa0698fec81e574818a0a6c2000fac0b2c4c6Caitlin Sadowski
2638402aa0698fec81e574818a0a6c2000fac0b2c4c6Caitlin Sadowski/// \brief Helper function that returns a LockKind required for the given level
2639402aa0698fec81e574818a0a6c2000fac0b2c4c6Caitlin Sadowski/// of access.
2640402aa0698fec81e574818a0a6c2000fac0b2c4c6Caitlin SadowskiLockKind getLockKindFromAccessKind(AccessKind AK) {
2641402aa0698fec81e574818a0a6c2000fac0b2c4c6Caitlin Sadowski  switch (AK) {
2642402aa0698fec81e574818a0a6c2000fac0b2c4c6Caitlin Sadowski    case AK_Read :
2643402aa0698fec81e574818a0a6c2000fac0b2c4c6Caitlin Sadowski      return LK_Shared;
2644402aa0698fec81e574818a0a6c2000fac0b2c4c6Caitlin Sadowski    case AK_Written :
2645402aa0698fec81e574818a0a6c2000fac0b2c4c6Caitlin Sadowski      return LK_Exclusive;
2646402aa0698fec81e574818a0a6c2000fac0b2c4c6Caitlin Sadowski  }
2647afc5b15022886c9e9e84d7aa0f2168b83e712310Benjamin Kramer  llvm_unreachable("Unknown AccessKind");
2648402aa0698fec81e574818a0a6c2000fac0b2c4c6Caitlin Sadowski}
2649a60448d6dfc91f4c30987e237bf70ef50ac7705bDeLesley Hutchins
2650402aa0698fec81e574818a0a6c2000fac0b2c4c6Caitlin Sadowski}} // end namespace clang::thread_safety
2651