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