//===- ThreadSafety.cpp ----------------------------------------*- C++ --*-===//
//
//                     The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// A intra-procedural analysis for thread safety (e.g. deadlocks and race
// conditions), based off of an annotation system.
//
// See http://clang.llvm.org/docs/LanguageExtensions.html#threadsafety for more
// information.
//
//===----------------------------------------------------------------------===//

#include "clang/Analysis/Analyses/ThreadSafety.h"
#include "clang/Analysis/Analyses/PostOrderCFGView.h"
#include "clang/Analysis/AnalysisContext.h"
#include "clang/Analysis/CFG.h"
#include "clang/Analysis/CFGStmtMap.h"
#include "clang/AST/DeclCXX.h"
#include "clang/AST/ExprCXX.h"
#include "clang/AST/StmtCXX.h"
#include "clang/AST/StmtVisitor.h"
#include "clang/Basic/SourceManager.h"
#include "clang/Basic/SourceLocation.h"
#include "clang/Basic/OperatorKinds.h"
#include "llvm/ADT/BitVector.h"
#include "llvm/ADT/FoldingSet.h"
#include "llvm/ADT/ImmutableMap.h"
#include "llvm/ADT/PostOrderIterator.h"
#include "llvm/ADT/SmallVector.h"
#include "llvm/ADT/StringRef.h"
#include "llvm/Support/raw_ostream.h"
#include <algorithm>
#include <utility>
#include <vector>

using namespace clang;
using namespace thread_safety;

// Key method definition
ThreadSafetyHandler::~ThreadSafetyHandler() {}

namespace {

/// SExpr implements a simple expression language that is used to store,
/// compare, and pretty-print C++ expressions.  Unlike a clang Expr, a SExpr
/// does not capture surface syntax, and it does not distinguish between
/// C++ concepts, like pointers and references, that have no real semantic
/// differences.  This simplicity allows SExprs to be meaningfully compared,
/// e.g.
///        (x)          =  x
///        (*this).foo  =  this->foo
///        *&a          =  a
///
/// Thread-safety analysis works by comparing lock expressions.  Within the
/// body of a function, an expression such as "x->foo->bar.mu" will resolve to
/// a particular mutex object at run-time.  Subsequent occurrences of the same
/// expression (where "same" means syntactic equality) will refer to the same
/// run-time object if three conditions hold:
/// (1) Local variables in the expression, such as "x" have not changed.
/// (2) Values on the heap that affect the expression have not changed.
/// (3) The expression involves only pure function calls.
///
/// The current implementation assumes, but does not verify, that multiple uses
/// of the same lock expression satisfies these criteria.
class SExpr {
private:
  enum ExprOp {
    EOP_Nop,       ///< No-op
    EOP_Wildcard,  ///< Matches anything.
    EOP_Universal, ///< Universal lock.
    EOP_This,      ///< This keyword.
    EOP_NVar,      ///< Named variable.
    EOP_LVar,      ///< Local variable.
    EOP_Dot,       ///< Field access
    EOP_Call,      ///< Function call
    EOP_MCall,     ///< Method call
    EOP_Index,     ///< Array index
    EOP_Unary,     ///< Unary operation
    EOP_Binary,    ///< Binary operation
    EOP_Unknown    ///< Catchall for everything else
  };


  class SExprNode {
   private:
    unsigned char  Op;     ///< Opcode of the root node
    unsigned char  Flags;  ///< Additional opcode-specific data
    unsigned short Sz;     ///< Number of child nodes
    const void*    Data;   ///< Additional opcode-specific data

   public:
    SExprNode(ExprOp O, unsigned F, const void* D)
      : Op(static_cast<unsigned char>(O)),
        Flags(static_cast<unsigned char>(F)), Sz(1), Data(D)
    { }

    unsigned size() const        { return Sz; }
    void     setSize(unsigned S) { Sz = S;    }

    ExprOp   kind() const { return static_cast<ExprOp>(Op); }

    const NamedDecl* getNamedDecl() const {
      assert(Op == EOP_NVar || Op == EOP_LVar || Op == EOP_Dot);
      return reinterpret_cast<const NamedDecl*>(Data);
    }

    const NamedDecl* getFunctionDecl() const {
      assert(Op == EOP_Call || Op == EOP_MCall);
      return reinterpret_cast<const NamedDecl*>(Data);
    }

    bool isArrow() const { return Op == EOP_Dot && Flags == 1; }
    void setArrow(bool A) { Flags = A ? 1 : 0; }

    unsigned arity() const {
      switch (Op) {
        case EOP_Nop:       return 0;
        case EOP_Wildcard:  return 0;
        case EOP_Universal: return 0;
        case EOP_NVar:      return 0;
        case EOP_LVar:      return 0;
        case EOP_This:      return 0;
        case EOP_Dot:       return 1;
        case EOP_Call:      return Flags+1;  // First arg is function.
        case EOP_MCall:     return Flags+1;  // First arg is implicit obj.
        case EOP_Index:     return 2;
        case EOP_Unary:     return 1;
        case EOP_Binary:    return 2;
        case EOP_Unknown:   return Flags;
      }
      return 0;
    }

    bool operator==(const SExprNode& Other) const {
      // Ignore flags and size -- they don't matter.
      return (Op == Other.Op &&
              Data == Other.Data);
    }

    bool operator!=(const SExprNode& Other) const {
      return !(*this == Other);
    }

    bool matches(const SExprNode& Other) const {
      return (*this == Other) ||
             (Op == EOP_Wildcard) ||
             (Other.Op == EOP_Wildcard);
    }
  };


  /// \brief Encapsulates the lexical context of a function call.  The lexical
  /// context includes the arguments to the call, including the implicit object
  /// argument.  When an attribute containing a mutex expression is attached to
  /// a method, the expression may refer to formal parameters of the method.
  /// Actual arguments must be substituted for formal parameters to derive
  /// the appropriate mutex expression in the lexical context where the function
  /// is called.  PrevCtx holds the context in which the arguments themselves
  /// should be evaluated; multiple calling contexts can be chained together
  /// by the lock_returned attribute.
  struct CallingContext {
    const NamedDecl* AttrDecl;   // The decl to which the attribute is attached.
    Expr*            SelfArg;    // Implicit object argument -- e.g. 'this'
    bool             SelfArrow;  // is Self referred to with -> or .?
    unsigned         NumArgs;    // Number of funArgs
    Expr**           FunArgs;    // Function arguments
    CallingContext*  PrevCtx;    // The previous context; or 0 if none.

    CallingContext(const NamedDecl *D = 0, Expr *S = 0,
                   unsigned N = 0, Expr **A = 0, CallingContext *P = 0)
      : AttrDecl(D), SelfArg(S), SelfArrow(false),
        NumArgs(N), FunArgs(A), PrevCtx(P)
    { }
  };

  typedef SmallVector<SExprNode, 4> NodeVector;

private:
  // A SExpr is a list of SExprNodes in prefix order.  The Size field allows
  // the list to be traversed as a tree.
  NodeVector NodeVec;

private:
  unsigned makeNop() {
    NodeVec.push_back(SExprNode(EOP_Nop, 0, 0));
    return NodeVec.size()-1;
  }

  unsigned makeWildcard() {
    NodeVec.push_back(SExprNode(EOP_Wildcard, 0, 0));
    return NodeVec.size()-1;
  }

  unsigned makeUniversal() {
    NodeVec.push_back(SExprNode(EOP_Universal, 0, 0));
    return NodeVec.size()-1;
  }

  unsigned makeNamedVar(const NamedDecl *D) {
    NodeVec.push_back(SExprNode(EOP_NVar, 0, D));
    return NodeVec.size()-1;
  }

  unsigned makeLocalVar(const NamedDecl *D) {
    NodeVec.push_back(SExprNode(EOP_LVar, 0, D));
    return NodeVec.size()-1;
  }

  unsigned makeThis() {
    NodeVec.push_back(SExprNode(EOP_This, 0, 0));
    return NodeVec.size()-1;
  }

  unsigned makeDot(const NamedDecl *D, bool Arrow) {
    NodeVec.push_back(SExprNode(EOP_Dot, Arrow ? 1 : 0, D));
    return NodeVec.size()-1;
  }

  unsigned makeCall(unsigned NumArgs, const NamedDecl *D) {
    NodeVec.push_back(SExprNode(EOP_Call, NumArgs, D));
    return NodeVec.size()-1;
  }

  unsigned makeMCall(unsigned NumArgs, const NamedDecl *D) {
    NodeVec.push_back(SExprNode(EOP_MCall, NumArgs, D));
    return NodeVec.size()-1;
  }

  unsigned makeIndex() {
    NodeVec.push_back(SExprNode(EOP_Index, 0, 0));
    return NodeVec.size()-1;
  }

  unsigned makeUnary() {
    NodeVec.push_back(SExprNode(EOP_Unary, 0, 0));
    return NodeVec.size()-1;
  }

  unsigned makeBinary() {
    NodeVec.push_back(SExprNode(EOP_Binary, 0, 0));
    return NodeVec.size()-1;
  }

  unsigned makeUnknown(unsigned Arity) {
    NodeVec.push_back(SExprNode(EOP_Unknown, Arity, 0));
    return NodeVec.size()-1;
  }

  /// Build an SExpr from the given C++ expression.
  /// Recursive function that terminates on DeclRefExpr.
  /// Note: this function merely creates a SExpr; it does not check to
  /// ensure that the original expression is a valid mutex expression.
  ///
  /// NDeref returns the number of Derefence and AddressOf operations
  /// preceeding the Expr; this is used to decide whether to pretty-print
  /// SExprs with . or ->.
  unsigned buildSExpr(Expr *Exp, CallingContext* CallCtx, int* NDeref = 0) {
    if (!Exp)
      return 0;

    if (DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(Exp)) {
      NamedDecl *ND = cast<NamedDecl>(DRE->getDecl()->getCanonicalDecl());
      ParmVarDecl *PV = dyn_cast_or_null<ParmVarDecl>(ND);
      if (PV) {
        FunctionDecl *FD =
          cast<FunctionDecl>(PV->getDeclContext())->getCanonicalDecl();
        unsigned i = PV->getFunctionScopeIndex();

        if (CallCtx && CallCtx->FunArgs &&
            FD == CallCtx->AttrDecl->getCanonicalDecl()) {
          // Substitute call arguments for references to function parameters
          assert(i < CallCtx->NumArgs);
          return buildSExpr(CallCtx->FunArgs[i], CallCtx->PrevCtx, NDeref);
        }
        // Map the param back to the param of the original function declaration.
        makeNamedVar(FD->getParamDecl(i));
        return 1;
      }
      // Not a function parameter -- just store the reference.
      makeNamedVar(ND);
      return 1;
    } else if (isa<CXXThisExpr>(Exp)) {
      // Substitute parent for 'this'
      if (CallCtx && CallCtx->SelfArg) {
        if (!CallCtx->SelfArrow && NDeref)
          // 'this' is a pointer, but self is not, so need to take address.
          --(*NDeref);
        return buildSExpr(CallCtx->SelfArg, CallCtx->PrevCtx, NDeref);
      }
      else {
        makeThis();
        return 1;
      }
    } else if (MemberExpr *ME = dyn_cast<MemberExpr>(Exp)) {
      NamedDecl *ND = ME->getMemberDecl();
      int ImplicitDeref = ME->isArrow() ? 1 : 0;
      unsigned Root = makeDot(ND, false);
      unsigned Sz = buildSExpr(ME->getBase(), CallCtx, &ImplicitDeref);
      NodeVec[Root].setArrow(ImplicitDeref > 0);
      NodeVec[Root].setSize(Sz + 1);
      return Sz + 1;
    } else if (CXXMemberCallExpr *CMCE = dyn_cast<CXXMemberCallExpr>(Exp)) {
      // When calling a function with a lock_returned attribute, replace
      // the function call with the expression in lock_returned.
      CXXMethodDecl* MD =
        cast<CXXMethodDecl>(CMCE->getMethodDecl()->getMostRecentDecl());
      if (LockReturnedAttr* At = MD->getAttr<LockReturnedAttr>()) {
        CallingContext LRCallCtx(CMCE->getMethodDecl());
        LRCallCtx.SelfArg = CMCE->getImplicitObjectArgument();
        LRCallCtx.SelfArrow =
          dyn_cast<MemberExpr>(CMCE->getCallee())->isArrow();
        LRCallCtx.NumArgs = CMCE->getNumArgs();
        LRCallCtx.FunArgs = CMCE->getArgs();
        LRCallCtx.PrevCtx = CallCtx;
        return buildSExpr(At->getArg(), &LRCallCtx);
      }
      // Hack to treat smart pointers and iterators as pointers;
      // ignore any method named get().
      if (CMCE->getMethodDecl()->getNameAsString() == "get" &&
          CMCE->getNumArgs() == 0) {
        if (NDeref && dyn_cast<MemberExpr>(CMCE->getCallee())->isArrow())
          ++(*NDeref);
        return buildSExpr(CMCE->getImplicitObjectArgument(), CallCtx, NDeref);
      }
      unsigned NumCallArgs = CMCE->getNumArgs();
      unsigned Root =
        makeMCall(NumCallArgs, CMCE->getMethodDecl()->getCanonicalDecl());
      unsigned Sz = buildSExpr(CMCE->getImplicitObjectArgument(), CallCtx);
      Expr** CallArgs = CMCE->getArgs();
      for (unsigned i = 0; i < NumCallArgs; ++i) {
        Sz += buildSExpr(CallArgs[i], CallCtx);
      }
      NodeVec[Root].setSize(Sz + 1);
      return Sz + 1;
    } else if (CallExpr *CE = dyn_cast<CallExpr>(Exp)) {
      FunctionDecl* FD =
        cast<FunctionDecl>(CE->getDirectCallee()->getMostRecentDecl());
      if (LockReturnedAttr* At = FD->getAttr<LockReturnedAttr>()) {
        CallingContext LRCallCtx(CE->getDirectCallee());
        LRCallCtx.NumArgs = CE->getNumArgs();
        LRCallCtx.FunArgs = CE->getArgs();
        LRCallCtx.PrevCtx = CallCtx;
        return buildSExpr(At->getArg(), &LRCallCtx);
      }
      // Treat smart pointers and iterators as pointers;
      // ignore the * and -> operators.
      if (CXXOperatorCallExpr *OE = dyn_cast<CXXOperatorCallExpr>(CE)) {
        OverloadedOperatorKind k = OE->getOperator();
        if (k == OO_Star) {
          if (NDeref) ++(*NDeref);
          return buildSExpr(OE->getArg(0), CallCtx, NDeref);
        }
        else if (k == OO_Arrow) {
          return buildSExpr(OE->getArg(0), CallCtx, NDeref);
        }
      }
      unsigned NumCallArgs = CE->getNumArgs();
      unsigned Root = makeCall(NumCallArgs, 0);
      unsigned Sz = buildSExpr(CE->getCallee(), CallCtx);
      Expr** CallArgs = CE->getArgs();
      for (unsigned i = 0; i < NumCallArgs; ++i) {
        Sz += buildSExpr(CallArgs[i], CallCtx);
      }
      NodeVec[Root].setSize(Sz+1);
      return Sz+1;
    } else if (BinaryOperator *BOE = dyn_cast<BinaryOperator>(Exp)) {
      unsigned Root = makeBinary();
      unsigned Sz = buildSExpr(BOE->getLHS(), CallCtx);
      Sz += buildSExpr(BOE->getRHS(), CallCtx);
      NodeVec[Root].setSize(Sz);
      return Sz;
    } else if (UnaryOperator *UOE = dyn_cast<UnaryOperator>(Exp)) {
      // Ignore & and * operators -- they're no-ops.
      // However, we try to figure out whether the expression is a pointer,
      // so we can use . and -> appropriately in error messages.
      if (UOE->getOpcode() == UO_Deref) {
        if (NDeref) ++(*NDeref);
        return buildSExpr(UOE->getSubExpr(), CallCtx, NDeref);
      }
      if (UOE->getOpcode() == UO_AddrOf) {
        if (DeclRefExpr* DRE = dyn_cast<DeclRefExpr>(UOE->getSubExpr())) {
          if (DRE->getDecl()->isCXXInstanceMember()) {
            // This is a pointer-to-member expression, e.g. &MyClass::mu_.
            // We interpret this syntax specially, as a wildcard.
            unsigned Root = makeDot(DRE->getDecl(), false);
            makeWildcard();
            NodeVec[Root].setSize(2);
            return 2;
          }
        }
        if (NDeref) --(*NDeref);
        return buildSExpr(UOE->getSubExpr(), CallCtx, NDeref);
      }
      unsigned Root = makeUnary();
      unsigned Sz = buildSExpr(UOE->getSubExpr(), CallCtx);
      NodeVec[Root].setSize(Sz);
      return Sz;
    } else if (ArraySubscriptExpr *ASE = dyn_cast<ArraySubscriptExpr>(Exp)) {
      unsigned Root = makeIndex();
      unsigned Sz = buildSExpr(ASE->getBase(), CallCtx);
      Sz += buildSExpr(ASE->getIdx(), CallCtx);
      NodeVec[Root].setSize(Sz);
      return Sz;
    } else if (AbstractConditionalOperator *CE =
               dyn_cast<AbstractConditionalOperator>(Exp)) {
      unsigned Root = makeUnknown(3);
      unsigned Sz = buildSExpr(CE->getCond(), CallCtx);
      Sz += buildSExpr(CE->getTrueExpr(), CallCtx);
      Sz += buildSExpr(CE->getFalseExpr(), CallCtx);
      NodeVec[Root].setSize(Sz);
      return Sz;
    } else if (ChooseExpr *CE = dyn_cast<ChooseExpr>(Exp)) {
      unsigned Root = makeUnknown(3);
      unsigned Sz = buildSExpr(CE->getCond(), CallCtx);
      Sz += buildSExpr(CE->getLHS(), CallCtx);
      Sz += buildSExpr(CE->getRHS(), CallCtx);
      NodeVec[Root].setSize(Sz);
      return Sz;
    } else if (CastExpr *CE = dyn_cast<CastExpr>(Exp)) {
      return buildSExpr(CE->getSubExpr(), CallCtx, NDeref);
    } else if (ParenExpr *PE = dyn_cast<ParenExpr>(Exp)) {
      return buildSExpr(PE->getSubExpr(), CallCtx, NDeref);
    } else if (ExprWithCleanups *EWC = dyn_cast<ExprWithCleanups>(Exp)) {
      return buildSExpr(EWC->getSubExpr(), CallCtx, NDeref);
    } else if (CXXBindTemporaryExpr *E = dyn_cast<CXXBindTemporaryExpr>(Exp)) {
      return buildSExpr(E->getSubExpr(), CallCtx, NDeref);
    } else if (isa<CharacterLiteral>(Exp) ||
               isa<CXXNullPtrLiteralExpr>(Exp) ||
               isa<GNUNullExpr>(Exp) ||
               isa<CXXBoolLiteralExpr>(Exp) ||
               isa<FloatingLiteral>(Exp) ||
               isa<ImaginaryLiteral>(Exp) ||
               isa<IntegerLiteral>(Exp) ||
               isa<StringLiteral>(Exp) ||
               isa<ObjCStringLiteral>(Exp)) {
      makeNop();
      return 1;  // FIXME: Ignore literals for now
    } else {
      makeNop();
      return 1;  // Ignore.  FIXME: mark as invalid expression?
    }
  }

  /// \brief Construct a SExpr from an expression.
  /// \param MutexExp The original mutex expression within an attribute
  /// \param DeclExp An expression involving the Decl on which the attribute
  ///        occurs.
  /// \param D  The declaration to which the lock/unlock attribute is attached.
  void buildSExprFromExpr(Expr *MutexExp, Expr *DeclExp, const NamedDecl *D) {
    CallingContext CallCtx(D);


    if (MutexExp) {
      if (StringLiteral* SLit = dyn_cast<StringLiteral>(MutexExp)) {
        if (SLit->getString() == StringRef("*"))
          // The "*" expr is a universal lock, which essentially turns off
          // checks until it is removed from the lockset.
          makeUniversal();
        else
          // Ignore other string literals for now.
          makeNop();
        return;
      }
    }

    // If we are processing a raw attribute expression, with no substitutions.
    if (DeclExp == 0) {
      buildSExpr(MutexExp, 0);
      return;
    }

    // Examine DeclExp to find SelfArg and FunArgs, which are used to substitute
    // for formal parameters when we call buildMutexID later.
    if (MemberExpr *ME = dyn_cast<MemberExpr>(DeclExp)) {
      CallCtx.SelfArg   = ME->getBase();
      CallCtx.SelfArrow = ME->isArrow();
    } else if (CXXMemberCallExpr *CE = dyn_cast<CXXMemberCallExpr>(DeclExp)) {
      CallCtx.SelfArg   = CE->getImplicitObjectArgument();
      CallCtx.SelfArrow = dyn_cast<MemberExpr>(CE->getCallee())->isArrow();
      CallCtx.NumArgs   = CE->getNumArgs();
      CallCtx.FunArgs   = CE->getArgs();
    } else if (CallExpr *CE = dyn_cast<CallExpr>(DeclExp)) {
      CallCtx.NumArgs = CE->getNumArgs();
      CallCtx.FunArgs = CE->getArgs();
    } else if (CXXConstructExpr *CE = dyn_cast<CXXConstructExpr>(DeclExp)) {
      CallCtx.SelfArg = 0;  // FIXME -- get the parent from DeclStmt
      CallCtx.NumArgs = CE->getNumArgs();
      CallCtx.FunArgs = CE->getArgs();
    } else if (D && isa<CXXDestructorDecl>(D)) {
      // There's no such thing as a "destructor call" in the AST.
      CallCtx.SelfArg = DeclExp;
    }

    // If the attribute has no arguments, then assume the argument is "this".
    if (MutexExp == 0) {
      buildSExpr(CallCtx.SelfArg, 0);
      return;
    }

    // For most attributes.
    buildSExpr(MutexExp, &CallCtx);
  }

  /// \brief Get index of next sibling of node i.
  unsigned getNextSibling(unsigned i) const {
    return i + NodeVec[i].size();
  }

public:
  explicit SExpr(clang::Decl::EmptyShell e) { NodeVec.clear(); }

  /// \param MutexExp The original mutex expression within an attribute
  /// \param DeclExp An expression involving the Decl on which the attribute
  ///        occurs.
  /// \param D  The declaration to which the lock/unlock attribute is attached.
  /// Caller must check isValid() after construction.
  SExpr(Expr* MutexExp, Expr *DeclExp, const NamedDecl* D) {
    buildSExprFromExpr(MutexExp, DeclExp, D);
  }

  /// Return true if this is a valid decl sequence.
  /// Caller must call this by hand after construction to handle errors.
  bool isValid() const {
    return !NodeVec.empty();
  }

  bool shouldIgnore() const {
    // Nop is a mutex that we have decided to deliberately ignore.
    assert(NodeVec.size() > 0 && "Invalid Mutex");
    return NodeVec[0].kind() == EOP_Nop;
  }

  bool isUniversal() const {
    assert(NodeVec.size() > 0 && "Invalid Mutex");
    return NodeVec[0].kind() == EOP_Universal;
  }

  /// Issue a warning about an invalid lock expression
  static void warnInvalidLock(ThreadSafetyHandler &Handler, Expr* MutexExp,
                              Expr *DeclExp, const NamedDecl* D) {
    SourceLocation Loc;
    if (DeclExp)
      Loc = DeclExp->getExprLoc();

    // FIXME: add a note about the attribute location in MutexExp or D
    if (Loc.isValid())
      Handler.handleInvalidLockExp(Loc);
  }

  bool operator==(const SExpr &other) const {
    return NodeVec == other.NodeVec;
  }

  bool operator!=(const SExpr &other) const {
    return !(*this == other);
  }

  bool matches(const SExpr &Other, unsigned i = 0, unsigned j = 0) const {
    if (NodeVec[i].matches(Other.NodeVec[j])) {
      unsigned n = NodeVec[i].arity();
      bool Result = true;
      unsigned ci = i+1;  // first child of i
      unsigned cj = j+1;  // first child of j
      for (unsigned k = 0; k < n;
           ++k, ci=getNextSibling(ci), cj = Other.getNextSibling(cj)) {
        Result = Result && matches(Other, ci, cj);
      }
      return Result;
    }
    return false;
  }

  // A partial match between a.mu and b.mu returns true a and b have the same
  // type (and thus mu refers to the same mutex declaration), regardless of
  // whether a and b are different objects or not.
  bool partiallyMatches(const SExpr &Other) const {
    if (NodeVec[0].kind() == EOP_Dot)
      return NodeVec[0].matches(Other.NodeVec[0]);
    return false;
  }

  /// \brief Pretty print a lock expression for use in error messages.
  std::string toString(unsigned i = 0) const {
    assert(isValid());
    if (i >= NodeVec.size())
      return "";

    const SExprNode* N = &NodeVec[i];
    switch (N->kind()) {
      case EOP_Nop:
        return "_";
      case EOP_Wildcard:
        return "(?)";
      case EOP_Universal:
        return "*";
      case EOP_This:
        return "this";
      case EOP_NVar:
      case EOP_LVar: {
        return N->getNamedDecl()->getNameAsString();
      }
      case EOP_Dot: {
        if (NodeVec[i+1].kind() == EOP_Wildcard) {
          std::string S = "&";
          S += N->getNamedDecl()->getQualifiedNameAsString();
          return S;
        }
        std::string FieldName = N->getNamedDecl()->getNameAsString();
        if (NodeVec[i+1].kind() == EOP_This)
          return FieldName;

        std::string S = toString(i+1);
        if (N->isArrow())
          return S + "->" + FieldName;
        else
          return S + "." + FieldName;
      }
      case EOP_Call: {
        std::string S = toString(i+1) + "(";
        unsigned NumArgs = N->arity()-1;
        unsigned ci = getNextSibling(i+1);
        for (unsigned k=0; k<NumArgs; ++k, ci = getNextSibling(ci)) {
          S += toString(ci);
          if (k+1 < NumArgs) S += ",";
        }
        S += ")";
        return S;
      }
      case EOP_MCall: {
        std::string S = "";
        if (NodeVec[i+1].kind() != EOP_This)
          S = toString(i+1) + ".";
        if (const NamedDecl *D = N->getFunctionDecl())
          S += D->getNameAsString() + "(";
        else
          S += "#(";
        unsigned NumArgs = N->arity()-1;
        unsigned ci = getNextSibling(i+1);
        for (unsigned k=0; k<NumArgs; ++k, ci = getNextSibling(ci)) {
          S += toString(ci);
          if (k+1 < NumArgs) S += ",";
        }
        S += ")";
        return S;
      }
      case EOP_Index: {
        std::string S1 = toString(i+1);
        std::string S2 = toString(i+1 + NodeVec[i+1].size());
        return S1 + "[" + S2 + "]";
      }
      case EOP_Unary: {
        std::string S = toString(i+1);
        return "#" + S;
      }
      case EOP_Binary: {
        std::string S1 = toString(i+1);
        std::string S2 = toString(i+1 + NodeVec[i+1].size());
        return "(" + S1 + "#" + S2 + ")";
      }
      case EOP_Unknown: {
        unsigned NumChildren = N->arity();
        if (NumChildren == 0)
          return "(...)";
        std::string S = "(";
        unsigned ci = i+1;
        for (unsigned j = 0; j < NumChildren; ++j, ci = getNextSibling(ci)) {
          S += toString(ci);
          if (j+1 < NumChildren) S += "#";
        }
        S += ")";
        return S;
      }
    }
    return "";
  }
};



/// \brief A short list of SExprs
class MutexIDList : public SmallVector<SExpr, 3> {
public:
  /// \brief Return true if the list contains the specified SExpr
  /// Performs a linear search, because these lists are almost always very small.
  bool contains(const SExpr& M) {
    for (iterator I=begin(),E=end(); I != E; ++I)
      if ((*I) == M) return true;
    return false;
  }

  /// \brief Push M onto list, bud discard duplicates
  void push_back_nodup(const SExpr& M) {
    if (!contains(M)) push_back(M);
  }
};



/// \brief This is a helper class that stores info about the most recent
/// accquire of a Lock.
///
/// The main body of the analysis maps MutexIDs to LockDatas.
struct LockData {
  SourceLocation AcquireLoc;

  /// \brief LKind stores whether a lock is held shared or exclusively.
  /// Note that this analysis does not currently support either re-entrant
  /// locking or lock "upgrading" and "downgrading" between exclusive and
  /// shared.
  ///
  /// FIXME: add support for re-entrant locking and lock up/downgrading
  LockKind LKind;
  bool     Managed;            // for ScopedLockable objects
  SExpr    UnderlyingMutex;    // for ScopedLockable objects

  LockData(SourceLocation AcquireLoc, LockKind LKind, bool M = false)
    : AcquireLoc(AcquireLoc), LKind(LKind), Managed(M),
      UnderlyingMutex(Decl::EmptyShell())
  {}

  LockData(SourceLocation AcquireLoc, LockKind LKind, const SExpr &Mu)
    : AcquireLoc(AcquireLoc), LKind(LKind), Managed(false),
      UnderlyingMutex(Mu)
  {}

  bool operator==(const LockData &other) const {
    return AcquireLoc == other.AcquireLoc && LKind == other.LKind;
  }

  bool operator!=(const LockData &other) const {
    return !(*this == other);
  }

  void Profile(llvm::FoldingSetNodeID &ID) const {
    ID.AddInteger(AcquireLoc.getRawEncoding());
    ID.AddInteger(LKind);
  }

  bool isAtLeast(LockKind LK) {
    return (LK == LK_Shared) || (LKind == LK_Exclusive);
  }
};


/// \brief A FactEntry stores a single fact that is known at a particular point
/// in the program execution.  Currently, this is information regarding a lock
/// that is held at that point.  
struct FactEntry {
  SExpr    MutID;
  LockData LDat;

  FactEntry(const SExpr& M, const LockData& L)
    : MutID(M), LDat(L)
  { }
};


typedef unsigned short FactID;

/// \brief FactManager manages the memory for all facts that are created during 
/// the analysis of a single routine.
class FactManager {
private:
  std::vector<FactEntry> Facts;

public:
  FactID newLock(const SExpr& M, const LockData& L) {
    Facts.push_back(FactEntry(M,L));
    return static_cast<unsigned short>(Facts.size() - 1);
  }

  const FactEntry& operator[](FactID F) const { return Facts[F]; }
  FactEntry&       operator[](FactID F)       { return Facts[F]; }
};


/// \brief A FactSet is the set of facts that are known to be true at a
/// particular program point.  FactSets must be small, because they are 
/// frequently copied, and are thus implemented as a set of indices into a
/// table maintained by a FactManager.  A typical FactSet only holds 1 or 2 
/// locks, so we can get away with doing a linear search for lookup.  Note
/// that a hashtable or map is inappropriate in this case, because lookups
/// may involve partial pattern matches, rather than exact matches.
class FactSet {
private:
  typedef SmallVector<FactID, 4> FactVec;

  FactVec FactIDs;

public:
  typedef FactVec::iterator       iterator;
  typedef FactVec::const_iterator const_iterator;

  iterator       begin()       { return FactIDs.begin(); }
  const_iterator begin() const { return FactIDs.begin(); }

  iterator       end()       { return FactIDs.end(); }
  const_iterator end() const { return FactIDs.end(); }

  bool isEmpty() const { return FactIDs.size() == 0; }

  FactID addLock(FactManager& FM, const SExpr& M, const LockData& L) {
    FactID F = FM.newLock(M, L);
    FactIDs.push_back(F);
    return F;
  }

  bool removeLock(FactManager& FM, const SExpr& M) {
    unsigned n = FactIDs.size();
    if (n == 0)
      return false;

    for (unsigned i = 0; i < n-1; ++i) {
      if (FM[FactIDs[i]].MutID.matches(M)) {
        FactIDs[i] = FactIDs[n-1];
        FactIDs.pop_back();
        return true;
      }
    }
    if (FM[FactIDs[n-1]].MutID.matches(M)) {
      FactIDs.pop_back();
      return true;
    }
    return false;
  }

  LockData* findLock(FactManager &FM, const SExpr &M) const {
    for (const_iterator I = begin(), E = end(); I != E; ++I) {
      const SExpr &Exp = FM[*I].MutID;
      if (Exp.matches(M))
        return &FM[*I].LDat;
    }
    return 0;
  }

  LockData* findLockUniv(FactManager &FM, const SExpr &M) const {
    for (const_iterator I = begin(), E = end(); I != E; ++I) {
      const SExpr &Exp = FM[*I].MutID;
      if (Exp.matches(M) || Exp.isUniversal())
        return &FM[*I].LDat;
    }
    return 0;
  }

  FactEntry* findPartialMatch(FactManager &FM, const SExpr &M) const {
    for (const_iterator I=begin(), E=end(); I != E; ++I) {
      const SExpr& Exp = FM[*I].MutID;
      if (Exp.partiallyMatches(M)) return &FM[*I];
    }
    return 0;
  }
};



/// A Lockset maps each SExpr (defined above) to information about how it has
/// been locked.
typedef llvm::ImmutableMap<SExpr, LockData> Lockset;
typedef llvm::ImmutableMap<const NamedDecl*, unsigned> LocalVarContext;

class LocalVariableMap;

/// A side (entry or exit) of a CFG node.
enum CFGBlockSide { CBS_Entry, CBS_Exit };

/// CFGBlockInfo is a struct which contains all the information that is
/// maintained for each block in the CFG.  See LocalVariableMap for more
/// information about the contexts.
struct CFGBlockInfo {
  FactSet EntrySet;             // Lockset held at entry to block
  FactSet ExitSet;              // Lockset held at exit from block
  LocalVarContext EntryContext; // Context held at entry to block
  LocalVarContext ExitContext;  // Context held at exit from block
  SourceLocation EntryLoc;      // Location of first statement in block
  SourceLocation ExitLoc;       // Location of last statement in block.
  unsigned EntryIndex;          // Used to replay contexts later

  const FactSet &getSet(CFGBlockSide Side) const {
    return Side == CBS_Entry ? EntrySet : ExitSet;
  }
  SourceLocation getLocation(CFGBlockSide Side) const {
    return Side == CBS_Entry ? EntryLoc : ExitLoc;
  }

private:
  CFGBlockInfo(LocalVarContext EmptyCtx)
    : EntryContext(EmptyCtx), ExitContext(EmptyCtx)
  { }

public:
  static CFGBlockInfo getEmptyBlockInfo(LocalVariableMap &M);
};



// A LocalVariableMap maintains a map from local variables to their currently
// valid definitions.  It provides SSA-like functionality when traversing the
// CFG.  Like SSA, each definition or assignment to a variable is assigned a
// unique name (an integer), which acts as the SSA name for that definition.
// The total set of names is shared among all CFG basic blocks.
// Unlike SSA, we do not rewrite expressions to replace local variables declrefs
// with their SSA-names.  Instead, we compute a Context for each point in the
// code, which maps local variables to the appropriate SSA-name.  This map
// changes with each assignment.
//
// The map is computed in a single pass over the CFG.  Subsequent analyses can
// then query the map to find the appropriate Context for a statement, and use
// that Context to look up the definitions of variables.
class LocalVariableMap {
public:
  typedef LocalVarContext Context;

  /// A VarDefinition consists of an expression, representing the value of the
  /// variable, along with the context in which that expression should be
  /// interpreted.  A reference VarDefinition does not itself contain this
  /// information, but instead contains a pointer to a previous VarDefinition.
  struct VarDefinition {
  public:
    friend class LocalVariableMap;

    const NamedDecl *Dec;  // The original declaration for this variable.
    const Expr *Exp;       // The expression for this variable, OR
    unsigned Ref;          // Reference to another VarDefinition
    Context Ctx;           // The map with which Exp should be interpreted.

    bool isReference() { return !Exp; }

  private:
    // Create ordinary variable definition
    VarDefinition(const NamedDecl *D, const Expr *E, Context C)
      : Dec(D), Exp(E), Ref(0), Ctx(C)
    { }

    // Create reference to previous definition
    VarDefinition(const NamedDecl *D, unsigned R, Context C)
      : Dec(D), Exp(0), Ref(R), Ctx(C)
    { }
  };

private:
  Context::Factory ContextFactory;
  std::vector<VarDefinition> VarDefinitions;
  std::vector<unsigned> CtxIndices;
  std::vector<std::pair<Stmt*, Context> > SavedContexts;

public:
  LocalVariableMap() {
    // index 0 is a placeholder for undefined variables (aka phi-nodes).
    VarDefinitions.push_back(VarDefinition(0, 0u, getEmptyContext()));
  }

  /// Look up a definition, within the given context.
  const VarDefinition* lookup(const NamedDecl *D, Context Ctx) {
    const unsigned *i = Ctx.lookup(D);
    if (!i)
      return 0;
    assert(*i < VarDefinitions.size());
    return &VarDefinitions[*i];
  }

  /// Look up the definition for D within the given context.  Returns
  /// NULL if the expression is not statically known.  If successful, also
  /// modifies Ctx to hold the context of the return Expr.
  const Expr* lookupExpr(const NamedDecl *D, Context &Ctx) {
    const unsigned *P = Ctx.lookup(D);
    if (!P)
      return 0;

    unsigned i = *P;
    while (i > 0) {
      if (VarDefinitions[i].Exp) {
        Ctx = VarDefinitions[i].Ctx;
        return VarDefinitions[i].Exp;
      }
      i = VarDefinitions[i].Ref;
    }
    return 0;
  }

  Context getEmptyContext() { return ContextFactory.getEmptyMap(); }

  /// Return the next context after processing S.  This function is used by
  /// clients of the class to get the appropriate context when traversing the
  /// CFG.  It must be called for every assignment or DeclStmt.
  Context getNextContext(unsigned &CtxIndex, Stmt *S, Context C) {
    if (SavedContexts[CtxIndex+1].first == S) {
      CtxIndex++;
      Context Result = SavedContexts[CtxIndex].second;
      return Result;
    }
    return C;
  }

  void dumpVarDefinitionName(unsigned i) {
    if (i == 0) {
      llvm::errs() << "Undefined";
      return;
    }
    const NamedDecl *Dec = VarDefinitions[i].Dec;
    if (!Dec) {
      llvm::errs() << "<<NULL>>";
      return;
    }
    Dec->printName(llvm::errs());
    llvm::errs() << "." << i << " " << ((const void*) Dec);
  }

  /// Dumps an ASCII representation of the variable map to llvm::errs()
  void dump() {
    for (unsigned i = 1, e = VarDefinitions.size(); i < e; ++i) {
      const Expr *Exp = VarDefinitions[i].Exp;
      unsigned Ref = VarDefinitions[i].Ref;

      dumpVarDefinitionName(i);
      llvm::errs() << " = ";
      if (Exp) Exp->dump();
      else {
        dumpVarDefinitionName(Ref);
        llvm::errs() << "\n";
      }
    }
  }

  /// Dumps an ASCII representation of a Context to llvm::errs()
  void dumpContext(Context C) {
    for (Context::iterator I = C.begin(), E = C.end(); I != E; ++I) {
      const NamedDecl *D = I.getKey();
      D->printName(llvm::errs());
      const unsigned *i = C.lookup(D);
      llvm::errs() << " -> ";
      dumpVarDefinitionName(*i);
      llvm::errs() << "\n";
    }
  }

  /// Builds the variable map.
  void traverseCFG(CFG *CFGraph, PostOrderCFGView *SortedGraph,
                     std::vector<CFGBlockInfo> &BlockInfo);

protected:
  // Get the current context index
  unsigned getContextIndex() { return SavedContexts.size()-1; }

  // Save the current context for later replay
  void saveContext(Stmt *S, Context C) {
    SavedContexts.push_back(std::make_pair(S,C));
  }

  // Adds a new definition to the given context, and returns a new context.
  // This method should be called when declaring a new variable.
  Context addDefinition(const NamedDecl *D, Expr *Exp, Context Ctx) {
    assert(!Ctx.contains(D));
    unsigned newID = VarDefinitions.size();
    Context NewCtx = ContextFactory.add(Ctx, D, newID);
    VarDefinitions.push_back(VarDefinition(D, Exp, Ctx));
    return NewCtx;
  }

  // Add a new reference to an existing definition.
  Context addReference(const NamedDecl *D, unsigned i, Context Ctx) {
    unsigned newID = VarDefinitions.size();
    Context NewCtx = ContextFactory.add(Ctx, D, newID);
    VarDefinitions.push_back(VarDefinition(D, i, Ctx));
    return NewCtx;
  }

  // Updates a definition only if that definition is already in the map.
  // This method should be called when assigning to an existing variable.
  Context updateDefinition(const NamedDecl *D, Expr *Exp, Context Ctx) {
    if (Ctx.contains(D)) {
      unsigned newID = VarDefinitions.size();
      Context NewCtx = ContextFactory.remove(Ctx, D);
      NewCtx = ContextFactory.add(NewCtx, D, newID);
      VarDefinitions.push_back(VarDefinition(D, Exp, Ctx));
      return NewCtx;
    }
    return Ctx;
  }

  // Removes a definition from the context, but keeps the variable name
  // as a valid variable.  The index 0 is a placeholder for cleared definitions.
  Context clearDefinition(const NamedDecl *D, Context Ctx) {
    Context NewCtx = Ctx;
    if (NewCtx.contains(D)) {
      NewCtx = ContextFactory.remove(NewCtx, D);
      NewCtx = ContextFactory.add(NewCtx, D, 0);
    }
    return NewCtx;
  }

  // Remove a definition entirely frmo the context.
  Context removeDefinition(const NamedDecl *D, Context Ctx) {
    Context NewCtx = Ctx;
    if (NewCtx.contains(D)) {
      NewCtx = ContextFactory.remove(NewCtx, D);
    }
    return NewCtx;
  }

  Context intersectContexts(Context C1, Context C2);
  Context createReferenceContext(Context C);
  void intersectBackEdge(Context C1, Context C2);

  friend class VarMapBuilder;
};


// This has to be defined after LocalVariableMap.
CFGBlockInfo CFGBlockInfo::getEmptyBlockInfo(LocalVariableMap &M) {
  return CFGBlockInfo(M.getEmptyContext());
}


/// Visitor which builds a LocalVariableMap
class VarMapBuilder : public StmtVisitor<VarMapBuilder> {
public:
  LocalVariableMap* VMap;
  LocalVariableMap::Context Ctx;

  VarMapBuilder(LocalVariableMap *VM, LocalVariableMap::Context C)
    : VMap(VM), Ctx(C) {}

  void VisitDeclStmt(DeclStmt *S);
  void VisitBinaryOperator(BinaryOperator *BO);
};


// Add new local variables to the variable map
void VarMapBuilder::VisitDeclStmt(DeclStmt *S) {
  bool modifiedCtx = false;
  DeclGroupRef DGrp = S->getDeclGroup();
  for (DeclGroupRef::iterator I = DGrp.begin(), E = DGrp.end(); I != E; ++I) {
    if (VarDecl *VD = dyn_cast_or_null<VarDecl>(*I)) {
      Expr *E = VD->getInit();

      // Add local variables with trivial type to the variable map
      QualType T = VD->getType();
      if (T.isTrivialType(VD->getASTContext())) {
        Ctx = VMap->addDefinition(VD, E, Ctx);
        modifiedCtx = true;
      }
    }
  }
  if (modifiedCtx)
    VMap->saveContext(S, Ctx);
}

// Update local variable definitions in variable map
void VarMapBuilder::VisitBinaryOperator(BinaryOperator *BO) {
  if (!BO->isAssignmentOp())
    return;

  Expr *LHSExp = BO->getLHS()->IgnoreParenCasts();

  // Update the variable map and current context.
  if (DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(LHSExp)) {
    ValueDecl *VDec = DRE->getDecl();
    if (Ctx.lookup(VDec)) {
      if (BO->getOpcode() == BO_Assign)
        Ctx = VMap->updateDefinition(VDec, BO->getRHS(), Ctx);
      else
        // FIXME -- handle compound assignment operators
        Ctx = VMap->clearDefinition(VDec, Ctx);
      VMap->saveContext(BO, Ctx);
    }
  }
}


// Computes the intersection of two contexts.  The intersection is the
// set of variables which have the same definition in both contexts;
// variables with different definitions are discarded.
LocalVariableMap::Context
LocalVariableMap::intersectContexts(Context C1, Context C2) {
  Context Result = C1;
  for (Context::iterator I = C1.begin(), E = C1.end(); I != E; ++I) {
    const NamedDecl *Dec = I.getKey();
    unsigned i1 = I.getData();
    const unsigned *i2 = C2.lookup(Dec);
    if (!i2)             // variable doesn't exist on second path
      Result = removeDefinition(Dec, Result);
    else if (*i2 != i1)  // variable exists, but has different definition
      Result = clearDefinition(Dec, Result);
  }
  return Result;
}

// For every variable in C, create a new variable that refers to the
// definition in C.  Return a new context that contains these new variables.
// (We use this for a naive implementation of SSA on loop back-edges.)
LocalVariableMap::Context LocalVariableMap::createReferenceContext(Context C) {
  Context Result = getEmptyContext();
  for (Context::iterator I = C.begin(), E = C.end(); I != E; ++I) {
    const NamedDecl *Dec = I.getKey();
    unsigned i = I.getData();
    Result = addReference(Dec, i, Result);
  }
  return Result;
}

// This routine also takes the intersection of C1 and C2, but it does so by
// altering the VarDefinitions.  C1 must be the result of an earlier call to
// createReferenceContext.
void LocalVariableMap::intersectBackEdge(Context C1, Context C2) {
  for (Context::iterator I = C1.begin(), E = C1.end(); I != E; ++I) {
    const NamedDecl *Dec = I.getKey();
    unsigned i1 = I.getData();
    VarDefinition *VDef = &VarDefinitions[i1];
    assert(VDef->isReference());

    const unsigned *i2 = C2.lookup(Dec);
    if (!i2 || (*i2 != i1))
      VDef->Ref = 0;    // Mark this variable as undefined
  }
}


// Traverse the CFG in topological order, so all predecessors of a block
// (excluding back-edges) are visited before the block itself.  At
// each point in the code, we calculate a Context, which holds the set of
// variable definitions which are visible at that point in execution.
// Visible variables are mapped to their definitions using an array that
// contains all definitions.
//
// At join points in the CFG, the set is computed as the intersection of
// the incoming sets along each edge, E.g.
//
//                       { Context                 | VarDefinitions }
//   int x = 0;          { x -> x1                 | x1 = 0 }
//   int y = 0;          { x -> x1, y -> y1        | y1 = 0, x1 = 0 }
//   if (b) x = 1;       { x -> x2, y -> y1        | x2 = 1, y1 = 0, ... }
//   else   x = 2;       { x -> x3, y -> y1        | x3 = 2, x2 = 1, ... }
//   ...                 { y -> y1  (x is unknown) | x3 = 2, x2 = 1, ... }
//
// This is essentially a simpler and more naive version of the standard SSA
// algorithm.  Those definitions that remain in the intersection are from blocks
// that strictly dominate the current block.  We do not bother to insert proper
// phi nodes, because they are not used in our analysis; instead, wherever
// a phi node would be required, we simply remove that definition from the
// context (E.g. x above).
//
// The initial traversal does not capture back-edges, so those need to be
// handled on a separate pass.  Whenever the first pass encounters an
// incoming back edge, it duplicates the context, creating new definitions
// that refer back to the originals.  (These correspond to places where SSA
// might have to insert a phi node.)  On the second pass, these definitions are
// set to NULL if the variable has changed on the back-edge (i.e. a phi
// node was actually required.)  E.g.
//
//                       { Context           | VarDefinitions }
//   int x = 0, y = 0;   { x -> x1, y -> y1  | y1 = 0, x1 = 0 }
//   while (b)           { x -> x2, y -> y1  | [1st:] x2=x1; [2nd:] x2=NULL; }
//     x = x+1;          { x -> x3, y -> y1  | x3 = x2 + 1, ... }
//   ...                 { y -> y1           | x3 = 2, x2 = 1, ... }
//
void LocalVariableMap::traverseCFG(CFG *CFGraph,
                                   PostOrderCFGView *SortedGraph,
                                   std::vector<CFGBlockInfo> &BlockInfo) {
  PostOrderCFGView::CFGBlockSet VisitedBlocks(CFGraph);

  CtxIndices.resize(CFGraph->getNumBlockIDs());

  for (PostOrderCFGView::iterator I = SortedGraph->begin(),
       E = SortedGraph->end(); I!= E; ++I) {
    const CFGBlock *CurrBlock = *I;
    int CurrBlockID = CurrBlock->getBlockID();
    CFGBlockInfo *CurrBlockInfo = &BlockInfo[CurrBlockID];

    VisitedBlocks.insert(CurrBlock);

    // Calculate the entry context for the current block
    bool HasBackEdges = false;
    bool CtxInit = true;
    for (CFGBlock::const_pred_iterator PI = CurrBlock->pred_begin(),
         PE  = CurrBlock->pred_end(); PI != PE; ++PI) {
      // if *PI -> CurrBlock is a back edge, so skip it
      if (*PI == 0 || !VisitedBlocks.alreadySet(*PI)) {
        HasBackEdges = true;
        continue;
      }

      int PrevBlockID = (*PI)->getBlockID();
      CFGBlockInfo *PrevBlockInfo = &BlockInfo[PrevBlockID];

      if (CtxInit) {
        CurrBlockInfo->EntryContext = PrevBlockInfo->ExitContext;
        CtxInit = false;
      }
      else {
        CurrBlockInfo->EntryContext =
          intersectContexts(CurrBlockInfo->EntryContext,
                            PrevBlockInfo->ExitContext);
      }
    }

    // Duplicate the context if we have back-edges, so we can call
    // intersectBackEdges later.
    if (HasBackEdges)
      CurrBlockInfo->EntryContext =
        createReferenceContext(CurrBlockInfo->EntryContext);

    // Create a starting context index for the current block
    saveContext(0, CurrBlockInfo->EntryContext);
    CurrBlockInfo->EntryIndex = getContextIndex();

    // Visit all the statements in the basic block.
    VarMapBuilder VMapBuilder(this, CurrBlockInfo->EntryContext);
    for (CFGBlock::const_iterator BI = CurrBlock->begin(),
         BE = CurrBlock->end(); BI != BE; ++BI) {
      switch (BI->getKind()) {
        case CFGElement::Statement: {
          const CFGStmt *CS = cast<CFGStmt>(&*BI);
          VMapBuilder.Visit(const_cast<Stmt*>(CS->getStmt()));
          break;
        }
        default:
          break;
      }
    }
    CurrBlockInfo->ExitContext = VMapBuilder.Ctx;

    // Mark variables on back edges as "unknown" if they've been changed.
    for (CFGBlock::const_succ_iterator SI = CurrBlock->succ_begin(),
         SE  = CurrBlock->succ_end(); SI != SE; ++SI) {
      // if CurrBlock -> *SI is *not* a back edge
      if (*SI == 0 || !VisitedBlocks.alreadySet(*SI))
        continue;

      CFGBlock *FirstLoopBlock = *SI;
      Context LoopBegin = BlockInfo[FirstLoopBlock->getBlockID()].EntryContext;
      Context LoopEnd   = CurrBlockInfo->ExitContext;
      intersectBackEdge(LoopBegin, LoopEnd);
    }
  }

  // Put an extra entry at the end of the indexed context array
  unsigned exitID = CFGraph->getExit().getBlockID();
  saveContext(0, BlockInfo[exitID].ExitContext);
}

/// Find the appropriate source locations to use when producing diagnostics for
/// each block in the CFG.
static void findBlockLocations(CFG *CFGraph,
                               PostOrderCFGView *SortedGraph,
                               std::vector<CFGBlockInfo> &BlockInfo) {
  for (PostOrderCFGView::iterator I = SortedGraph->begin(),
       E = SortedGraph->end(); I!= E; ++I) {
    const CFGBlock *CurrBlock = *I;
    CFGBlockInfo *CurrBlockInfo = &BlockInfo[CurrBlock->getBlockID()];

    // Find the source location of the last statement in the block, if the
    // block is not empty.
    if (const Stmt *S = CurrBlock->getTerminator()) {
      CurrBlockInfo->EntryLoc = CurrBlockInfo->ExitLoc = S->getLocStart();
    } else {
      for (CFGBlock::const_reverse_iterator BI = CurrBlock->rbegin(),
           BE = CurrBlock->rend(); BI != BE; ++BI) {
        // FIXME: Handle other CFGElement kinds.
        if (const CFGStmt *CS = dyn_cast<CFGStmt>(&*BI)) {
          CurrBlockInfo->ExitLoc = CS->getStmt()->getLocStart();
          break;
        }
      }
    }

    if (!CurrBlockInfo->ExitLoc.isInvalid()) {
      // This block contains at least one statement. Find the source location
      // of the first statement in the block.
      for (CFGBlock::const_iterator BI = CurrBlock->begin(),
           BE = CurrBlock->end(); BI != BE; ++BI) {
        // FIXME: Handle other CFGElement kinds.
        if (const CFGStmt *CS = dyn_cast<CFGStmt>(&*BI)) {
          CurrBlockInfo->EntryLoc = CS->getStmt()->getLocStart();
          break;
        }
      }
    } else if (CurrBlock->pred_size() == 1 && *CurrBlock->pred_begin() &&
               CurrBlock != &CFGraph->getExit()) {
      // The block is empty, and has a single predecessor. Use its exit
      // location.
      CurrBlockInfo->EntryLoc = CurrBlockInfo->ExitLoc =
          BlockInfo[(*CurrBlock->pred_begin())->getBlockID()].ExitLoc;
    }
  }
}

/// \brief Class which implements the core thread safety analysis routines.
class ThreadSafetyAnalyzer {
  friend class BuildLockset;

  ThreadSafetyHandler       &Handler;
  LocalVariableMap          LocalVarMap;
  FactManager               FactMan;
  std::vector<CFGBlockInfo> BlockInfo;

public:
  ThreadSafetyAnalyzer(ThreadSafetyHandler &H) : Handler(H) {}

  void addLock(FactSet &FSet, const SExpr &Mutex, const LockData &LDat);
  void removeLock(FactSet &FSet, const SExpr &Mutex,
                  SourceLocation UnlockLoc, bool FullyRemove=false);

  template <typename AttrType>
  void getMutexIDs(MutexIDList &Mtxs, AttrType *Attr, Expr *Exp,
                   const NamedDecl *D);

  template <class AttrType>
  void getMutexIDs(MutexIDList &Mtxs, AttrType *Attr, Expr *Exp,
                   const NamedDecl *D,
                   const CFGBlock *PredBlock, const CFGBlock *CurrBlock,
                   Expr *BrE, bool Neg);

  const CallExpr* getTrylockCallExpr(const Stmt *Cond, LocalVarContext C,
                                     bool &Negate);

  void getEdgeLockset(FactSet &Result, const FactSet &ExitSet,
                      const CFGBlock* PredBlock,
                      const CFGBlock *CurrBlock);

  void intersectAndWarn(FactSet &FSet1, const FactSet &FSet2,
                        SourceLocation JoinLoc,
                        LockErrorKind LEK1, LockErrorKind LEK2,
                        bool Modify=true);

  void intersectAndWarn(FactSet &FSet1, const FactSet &FSet2,
                        SourceLocation JoinLoc, LockErrorKind LEK1,
                        bool Modify=true) {
    intersectAndWarn(FSet1, FSet2, JoinLoc, LEK1, LEK1, Modify);
  }

  void runAnalysis(AnalysisDeclContext &AC);
};


/// \brief Add a new lock to the lockset, warning if the lock is already there.
/// \param Mutex -- the Mutex expression for the lock
/// \param LDat  -- the LockData for the lock
void ThreadSafetyAnalyzer::addLock(FactSet &FSet, const SExpr &Mutex,
                                   const LockData &LDat) {
  // FIXME: deal with acquired before/after annotations.
  // FIXME: Don't always warn when we have support for reentrant locks.
  if (Mutex.shouldIgnore())
    return;

  if (FSet.findLock(FactMan, Mutex)) {
    Handler.handleDoubleLock(Mutex.toString(), LDat.AcquireLoc);
  } else {
    FSet.addLock(FactMan, Mutex, LDat);
  }
}


/// \brief Remove a lock from the lockset, warning if the lock is not there.
/// \param Mutex The lock expression corresponding to the lock to be removed
/// \param UnlockLoc The source location of the unlock (only used in error msg)
void ThreadSafetyAnalyzer::removeLock(FactSet &FSet,
                                      const SExpr &Mutex,
                                      SourceLocation UnlockLoc,
                                      bool FullyRemove) {
  if (Mutex.shouldIgnore())
    return;

  const LockData *LDat = FSet.findLock(FactMan, Mutex);
  if (!LDat) {
    Handler.handleUnmatchedUnlock(Mutex.toString(), UnlockLoc);
    return;
  }

  if (LDat->UnderlyingMutex.isValid()) {
    // This is scoped lockable object, which manages the real mutex.
    if (FullyRemove) {
      // We're destroying the managing object.
      // Remove the underlying mutex if it exists; but don't warn.
      if (FSet.findLock(FactMan, LDat->UnderlyingMutex))
        FSet.removeLock(FactMan, LDat->UnderlyingMutex);
    } else {
      // We're releasing the underlying mutex, but not destroying the
      // managing object.  Warn on dual release.
      if (!FSet.findLock(FactMan, LDat->UnderlyingMutex)) {
        Handler.handleUnmatchedUnlock(LDat->UnderlyingMutex.toString(),
                                      UnlockLoc);
      }
      FSet.removeLock(FactMan, LDat->UnderlyingMutex);
      return;
    }
  }
  FSet.removeLock(FactMan, Mutex);
}


/// \brief Extract the list of mutexIDs from the attribute on an expression,
/// and push them onto Mtxs, discarding any duplicates.
template <typename AttrType>
void ThreadSafetyAnalyzer::getMutexIDs(MutexIDList &Mtxs, AttrType *Attr,
                                       Expr *Exp, const NamedDecl *D) {
  typedef typename AttrType::args_iterator iterator_type;

  if (Attr->args_size() == 0) {
    // The mutex held is the "this" object.
    SExpr Mu(0, Exp, D);
    if (!Mu.isValid())
      SExpr::warnInvalidLock(Handler, 0, Exp, D);
    else
      Mtxs.push_back_nodup(Mu);
    return;
  }

  for (iterator_type I=Attr->args_begin(), E=Attr->args_end(); I != E; ++I) {
    SExpr Mu(*I, Exp, D);
    if (!Mu.isValid())
      SExpr::warnInvalidLock(Handler, *I, Exp, D);
    else
      Mtxs.push_back_nodup(Mu);
  }
}


/// \brief Extract the list of mutexIDs from a trylock attribute.  If the
/// trylock applies to the given edge, then push them onto Mtxs, discarding
/// any duplicates.
template <class AttrType>
void ThreadSafetyAnalyzer::getMutexIDs(MutexIDList &Mtxs, AttrType *Attr,
                                       Expr *Exp, const NamedDecl *D,
                                       const CFGBlock *PredBlock,
                                       const CFGBlock *CurrBlock,
                                       Expr *BrE, bool Neg) {
  // Find out which branch has the lock
  bool branch = 0;
  if (CXXBoolLiteralExpr *BLE = dyn_cast_or_null<CXXBoolLiteralExpr>(BrE)) {
    branch = BLE->getValue();
  }
  else if (IntegerLiteral *ILE = dyn_cast_or_null<IntegerLiteral>(BrE)) {
    branch = ILE->getValue().getBoolValue();
  }
  int branchnum = branch ? 0 : 1;
  if (Neg) branchnum = !branchnum;

  // If we've taken the trylock branch, then add the lock
  int i = 0;
  for (CFGBlock::const_succ_iterator SI = PredBlock->succ_begin(),
       SE = PredBlock->succ_end(); SI != SE && i < 2; ++SI, ++i) {
    if (*SI == CurrBlock && i == branchnum) {
      getMutexIDs(Mtxs, Attr, Exp, D);
    }
  }
}


bool getStaticBooleanValue(Expr* E, bool& TCond) {
  if (isa<CXXNullPtrLiteralExpr>(E) || isa<GNUNullExpr>(E)) {
    TCond = false;
    return true;
  } else if (CXXBoolLiteralExpr *BLE = dyn_cast<CXXBoolLiteralExpr>(E)) {
    TCond = BLE->getValue();
    return true;
  } else if (IntegerLiteral *ILE = dyn_cast<IntegerLiteral>(E)) {
    TCond = ILE->getValue().getBoolValue();
    return true;
  } else if (ImplicitCastExpr *CE = dyn_cast<ImplicitCastExpr>(E)) {
    return getStaticBooleanValue(CE->getSubExpr(), TCond);
  }
  return false;
}


// If Cond can be traced back to a function call, return the call expression.
// The negate variable should be called with false, and will be set to true
// if the function call is negated, e.g. if (!mu.tryLock(...))
const CallExpr* ThreadSafetyAnalyzer::getTrylockCallExpr(const Stmt *Cond,
                                                         LocalVarContext C,
                                                         bool &Negate) {
  if (!Cond)
    return 0;

  if (const CallExpr *CallExp = dyn_cast<CallExpr>(Cond)) {
    return CallExp;
  }
  else if (const ParenExpr *PE = dyn_cast<ParenExpr>(Cond)) {
    return getTrylockCallExpr(PE->getSubExpr(), C, Negate);
  }
  else if (const ImplicitCastExpr *CE = dyn_cast<ImplicitCastExpr>(Cond)) {
    return getTrylockCallExpr(CE->getSubExpr(), C, Negate);
  }
  else if (const ExprWithCleanups* EWC = dyn_cast<ExprWithCleanups>(Cond)) {
    return getTrylockCallExpr(EWC->getSubExpr(), C, Negate);
  }
  else if (const DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(Cond)) {
    const Expr *E = LocalVarMap.lookupExpr(DRE->getDecl(), C);
    return getTrylockCallExpr(E, C, Negate);
  }
  else if (const UnaryOperator *UOP = dyn_cast<UnaryOperator>(Cond)) {
    if (UOP->getOpcode() == UO_LNot) {
      Negate = !Negate;
      return getTrylockCallExpr(UOP->getSubExpr(), C, Negate);
    }
    return 0;
  }
  else if (const BinaryOperator *BOP = dyn_cast<BinaryOperator>(Cond)) {
    if (BOP->getOpcode() == BO_EQ || BOP->getOpcode() == BO_NE) {
      if (BOP->getOpcode() == BO_NE)
        Negate = !Negate;

      bool TCond = false;
      if (getStaticBooleanValue(BOP->getRHS(), TCond)) {
        if (!TCond) Negate = !Negate;
        return getTrylockCallExpr(BOP->getLHS(), C, Negate);
      }
      else if (getStaticBooleanValue(BOP->getLHS(), TCond)) {
        if (!TCond) Negate = !Negate;
        return getTrylockCallExpr(BOP->getRHS(), C, Negate);
      }
      return 0;
    }
    return 0;
  }
  // FIXME -- handle && and || as well.
  return 0;
}


/// \brief Find the lockset that holds on the edge between PredBlock
/// and CurrBlock.  The edge set is the exit set of PredBlock (passed
/// as the ExitSet parameter) plus any trylocks, which are conditionally held.
void ThreadSafetyAnalyzer::getEdgeLockset(FactSet& Result,
                                          const FactSet &ExitSet,
                                          const CFGBlock *PredBlock,
                                          const CFGBlock *CurrBlock) {
  Result = ExitSet;

  if (!PredBlock->getTerminatorCondition())
    return;

  bool Negate = false;
  const Stmt *Cond = PredBlock->getTerminatorCondition();
  const CFGBlockInfo *PredBlockInfo = &BlockInfo[PredBlock->getBlockID()];
  const LocalVarContext &LVarCtx = PredBlockInfo->ExitContext;

  CallExpr *Exp =
    const_cast<CallExpr*>(getTrylockCallExpr(Cond, LVarCtx, Negate));
  if (!Exp)
    return;

  NamedDecl *FunDecl = dyn_cast_or_null<NamedDecl>(Exp->getCalleeDecl());
  if(!FunDecl || !FunDecl->hasAttrs())
    return;


  MutexIDList ExclusiveLocksToAdd;
  MutexIDList SharedLocksToAdd;

  // If the condition is a call to a Trylock function, then grab the attributes
  AttrVec &ArgAttrs = FunDecl->getAttrs();
  for (unsigned i = 0; i < ArgAttrs.size(); ++i) {
    Attr *Attr = ArgAttrs[i];
    switch (Attr->getKind()) {
      case attr::ExclusiveTrylockFunction: {
        ExclusiveTrylockFunctionAttr *A =
          cast<ExclusiveTrylockFunctionAttr>(Attr);
        getMutexIDs(ExclusiveLocksToAdd, A, Exp, FunDecl,
                    PredBlock, CurrBlock, A->getSuccessValue(), Negate);
        break;
      }
      case attr::SharedTrylockFunction: {
        SharedTrylockFunctionAttr *A =
          cast<SharedTrylockFunctionAttr>(Attr);
        getMutexIDs(ExclusiveLocksToAdd, A, Exp, FunDecl,
                    PredBlock, CurrBlock, A->getSuccessValue(), Negate);
        break;
      }
      default:
        break;
    }
  }

  // Add and remove locks.
  SourceLocation Loc = Exp->getExprLoc();
  for (unsigned i=0,n=ExclusiveLocksToAdd.size(); i<n; ++i) {
    addLock(Result, ExclusiveLocksToAdd[i],
            LockData(Loc, LK_Exclusive));
  }
  for (unsigned i=0,n=SharedLocksToAdd.size(); i<n; ++i) {
    addLock(Result, SharedLocksToAdd[i],
            LockData(Loc, LK_Shared));
  }
}


/// \brief We use this class to visit different types of expressions in
/// CFGBlocks, and build up the lockset.
/// An expression may cause us to add or remove locks from the lockset, or else
/// output error messages related to missing locks.
/// FIXME: In future, we may be able to not inherit from a visitor.
class BuildLockset : public StmtVisitor<BuildLockset> {
  friend class ThreadSafetyAnalyzer;

  ThreadSafetyAnalyzer *Analyzer;
  FactSet FSet;
  LocalVariableMap::Context LVarCtx;
  unsigned CtxIndex;

  // Helper functions
  const ValueDecl *getValueDecl(Expr *Exp);

  void warnIfMutexNotHeld(const NamedDecl *D, Expr *Exp, AccessKind AK,
                          Expr *MutexExp, ProtectedOperationKind POK);
  void warnIfMutexHeld(const NamedDecl *D, Expr *Exp, Expr *MutexExp);

  void checkAccess(Expr *Exp, AccessKind AK);
  void checkDereference(Expr *Exp, AccessKind AK);
  void handleCall(Expr *Exp, const NamedDecl *D, VarDecl *VD = 0);

public:
  BuildLockset(ThreadSafetyAnalyzer *Anlzr, CFGBlockInfo &Info)
    : StmtVisitor<BuildLockset>(),
      Analyzer(Anlzr),
      FSet(Info.EntrySet),
      LVarCtx(Info.EntryContext),
      CtxIndex(Info.EntryIndex)
  {}

  void VisitUnaryOperator(UnaryOperator *UO);
  void VisitBinaryOperator(BinaryOperator *BO);
  void VisitCastExpr(CastExpr *CE);
  void VisitCallExpr(CallExpr *Exp);
  void VisitCXXConstructExpr(CXXConstructExpr *Exp);
  void VisitDeclStmt(DeclStmt *S);
};


/// \brief Gets the value decl pointer from DeclRefExprs or MemberExprs
const ValueDecl *BuildLockset::getValueDecl(Expr *Exp) {
  if (const DeclRefExpr *DR = dyn_cast<DeclRefExpr>(Exp))
    return DR->getDecl();

  if (const MemberExpr *ME = dyn_cast<MemberExpr>(Exp))
    return ME->getMemberDecl();

  return 0;
}

/// \brief Warn if the LSet does not contain a lock sufficient to protect access
/// of at least the passed in AccessKind.
void BuildLockset::warnIfMutexNotHeld(const NamedDecl *D, Expr *Exp,
                                      AccessKind AK, Expr *MutexExp,
                                      ProtectedOperationKind POK) {
  LockKind LK = getLockKindFromAccessKind(AK);

  SExpr Mutex(MutexExp, Exp, D);
  if (!Mutex.isValid()) {
    SExpr::warnInvalidLock(Analyzer->Handler, MutexExp, Exp, D);
    return;
  } else if (Mutex.shouldIgnore()) {
    return;
  }

  LockData* LDat = FSet.findLockUniv(Analyzer->FactMan, Mutex);
  bool NoError = true;
  if (!LDat) {
    // No exact match found.  Look for a partial match.
    FactEntry* FEntry = FSet.findPartialMatch(Analyzer->FactMan, Mutex);
    if (FEntry) {
      // Warn that there's no precise match.
      LDat = &FEntry->LDat;
      std::string PartMatchStr = FEntry->MutID.toString();
      StringRef   PartMatchName(PartMatchStr);
      Analyzer->Handler.handleMutexNotHeld(D, POK, Mutex.toString(), LK,
                                           Exp->getExprLoc(), &PartMatchName);
    } else {
      // Warn that there's no match at all.
      Analyzer->Handler.handleMutexNotHeld(D, POK, Mutex.toString(), LK,
                                           Exp->getExprLoc());
    }
    NoError = false;
  }
  // Make sure the mutex we found is the right kind.
  if (NoError && LDat && !LDat->isAtLeast(LK))
    Analyzer->Handler.handleMutexNotHeld(D, POK, Mutex.toString(), LK,
                                         Exp->getExprLoc());
}

/// \brief Warn if the LSet contains the given lock.
void BuildLockset::warnIfMutexHeld(const NamedDecl *D, Expr* Exp,
                                   Expr *MutexExp) {
  SExpr Mutex(MutexExp, Exp, D);
  if (!Mutex.isValid()) {
    SExpr::warnInvalidLock(Analyzer->Handler, MutexExp, Exp, D);
    return;
  }

  LockData* LDat = FSet.findLock(Analyzer->FactMan, Mutex);
  if (LDat)
    Analyzer->Handler.handleFunExcludesLock(D->getName(), Mutex.toString(),
                                            Exp->getExprLoc());
}


/// \brief This method identifies variable dereferences and checks pt_guarded_by
/// and pt_guarded_var annotations. Note that we only check these annotations
/// at the time a pointer is dereferenced.
/// FIXME: We need to check for other types of pointer dereferences
/// (e.g. [], ->) and deal with them here.
/// \param Exp An expression that has been read or written.
void BuildLockset::checkDereference(Expr *Exp, AccessKind AK) {
  UnaryOperator *UO = dyn_cast<UnaryOperator>(Exp);
  if (!UO || UO->getOpcode() != clang::UO_Deref)
    return;
  Exp = UO->getSubExpr()->IgnoreParenCasts();

  const ValueDecl *D = getValueDecl(Exp);
  if(!D || !D->hasAttrs())
    return;

  if (D->getAttr<PtGuardedVarAttr>() && FSet.isEmpty())
    Analyzer->Handler.handleNoMutexHeld(D, POK_VarDereference, AK,
                                        Exp->getExprLoc());

  const AttrVec &ArgAttrs = D->getAttrs();
  for(unsigned i = 0, Size = ArgAttrs.size(); i < Size; ++i)
    if (PtGuardedByAttr *PGBAttr = dyn_cast<PtGuardedByAttr>(ArgAttrs[i]))
      warnIfMutexNotHeld(D, Exp, AK, PGBAttr->getArg(), POK_VarDereference);
}

/// \brief Checks guarded_by and guarded_var attributes.
/// Whenever we identify an access (read or write) of a DeclRefExpr or
/// MemberExpr, we need to check whether there are any guarded_by or
/// guarded_var attributes, and make sure we hold the appropriate mutexes.
void BuildLockset::checkAccess(Expr *Exp, AccessKind AK) {
  const ValueDecl *D = getValueDecl(Exp);
  if(!D || !D->hasAttrs())
    return;

  if (D->getAttr<GuardedVarAttr>() && FSet.isEmpty())
    Analyzer->Handler.handleNoMutexHeld(D, POK_VarAccess, AK,
                                        Exp->getExprLoc());

  const AttrVec &ArgAttrs = D->getAttrs();
  for(unsigned i = 0, Size = ArgAttrs.size(); i < Size; ++i)
    if (GuardedByAttr *GBAttr = dyn_cast<GuardedByAttr>(ArgAttrs[i]))
      warnIfMutexNotHeld(D, Exp, AK, GBAttr->getArg(), POK_VarAccess);
}

/// \brief Process a function call, method call, constructor call,
/// or destructor call.  This involves looking at the attributes on the
/// corresponding function/method/constructor/destructor, issuing warnings,
/// and updating the locksets accordingly.
///
/// FIXME: For classes annotated with one of the guarded annotations, we need
/// to treat const method calls as reads and non-const method calls as writes,
/// and check that the appropriate locks are held. Non-const method calls with
/// the same signature as const method calls can be also treated as reads.
///
void BuildLockset::handleCall(Expr *Exp, const NamedDecl *D, VarDecl *VD) {
  const AttrVec &ArgAttrs = D->getAttrs();
  MutexIDList ExclusiveLocksToAdd;
  MutexIDList SharedLocksToAdd;
  MutexIDList LocksToRemove;

  for(unsigned i = 0; i < ArgAttrs.size(); ++i) {
    Attr *At = const_cast<Attr*>(ArgAttrs[i]);
    switch (At->getKind()) {
      // When we encounter an exclusive lock function, we need to add the lock
      // to our lockset with kind exclusive.
      case attr::ExclusiveLockFunction: {
        ExclusiveLockFunctionAttr *A = cast<ExclusiveLockFunctionAttr>(At);
        Analyzer->getMutexIDs(ExclusiveLocksToAdd, A, Exp, D);
        break;
      }

      // When we encounter a shared lock function, we need to add the lock
      // to our lockset with kind shared.
      case attr::SharedLockFunction: {
        SharedLockFunctionAttr *A = cast<SharedLockFunctionAttr>(At);
        Analyzer->getMutexIDs(SharedLocksToAdd, A, Exp, D);
        break;
      }

      // When we encounter an unlock function, we need to remove unlocked
      // mutexes from the lockset, and flag a warning if they are not there.
      case attr::UnlockFunction: {
        UnlockFunctionAttr *A = cast<UnlockFunctionAttr>(At);
        Analyzer->getMutexIDs(LocksToRemove, A, Exp, D);
        break;
      }

      case attr::ExclusiveLocksRequired: {
        ExclusiveLocksRequiredAttr *A = cast<ExclusiveLocksRequiredAttr>(At);

        for (ExclusiveLocksRequiredAttr::args_iterator
             I = A->args_begin(), E = A->args_end(); I != E; ++I)
          warnIfMutexNotHeld(D, Exp, AK_Written, *I, POK_FunctionCall);
        break;
      }

      case attr::SharedLocksRequired: {
        SharedLocksRequiredAttr *A = cast<SharedLocksRequiredAttr>(At);

        for (SharedLocksRequiredAttr::args_iterator I = A->args_begin(),
             E = A->args_end(); I != E; ++I)
          warnIfMutexNotHeld(D, Exp, AK_Read, *I, POK_FunctionCall);
        break;
      }

      case attr::LocksExcluded: {
        LocksExcludedAttr *A = cast<LocksExcludedAttr>(At);

        for (LocksExcludedAttr::args_iterator I = A->args_begin(),
            E = A->args_end(); I != E; ++I) {
          warnIfMutexHeld(D, Exp, *I);
        }
        break;
      }

      // Ignore other (non thread-safety) attributes
      default:
        break;
    }
  }

  // Figure out if we're calling the constructor of scoped lockable class
  bool isScopedVar = false;
  if (VD) {
    if (const CXXConstructorDecl *CD = dyn_cast<const CXXConstructorDecl>(D)) {
      const CXXRecordDecl* PD = CD->getParent();
      if (PD && PD->getAttr<ScopedLockableAttr>())
        isScopedVar = true;
    }
  }

  // Add locks.
  SourceLocation Loc = Exp->getExprLoc();
  for (unsigned i=0,n=ExclusiveLocksToAdd.size(); i<n; ++i) {
    Analyzer->addLock(FSet, ExclusiveLocksToAdd[i],
                            LockData(Loc, LK_Exclusive, isScopedVar));
  }
  for (unsigned i=0,n=SharedLocksToAdd.size(); i<n; ++i) {
    Analyzer->addLock(FSet, SharedLocksToAdd[i],
                            LockData(Loc, LK_Shared, isScopedVar));
  }

  // Add the managing object as a dummy mutex, mapped to the underlying mutex.
  // FIXME -- this doesn't work if we acquire multiple locks.
  if (isScopedVar) {
    SourceLocation MLoc = VD->getLocation();
    DeclRefExpr DRE(VD, false, VD->getType(), VK_LValue, VD->getLocation());
    SExpr SMutex(&DRE, 0, 0);

    for (unsigned i=0,n=ExclusiveLocksToAdd.size(); i<n; ++i) {
      Analyzer->addLock(FSet, SMutex, LockData(MLoc, LK_Exclusive,
                                               ExclusiveLocksToAdd[i]));
    }
    for (unsigned i=0,n=SharedLocksToAdd.size(); i<n; ++i) {
      Analyzer->addLock(FSet, SMutex, LockData(MLoc, LK_Shared,
                                               SharedLocksToAdd[i]));
    }
  }

  // Remove locks.
  // FIXME -- should only fully remove if the attribute refers to 'this'.
  bool Dtor = isa<CXXDestructorDecl>(D);
  for (unsigned i=0,n=LocksToRemove.size(); i<n; ++i) {
    Analyzer->removeLock(FSet, LocksToRemove[i], Loc, Dtor);
  }
}


/// \brief For unary operations which read and write a variable, we need to
/// check whether we hold any required mutexes. Reads are checked in
/// VisitCastExpr.
void BuildLockset::VisitUnaryOperator(UnaryOperator *UO) {
  switch (UO->getOpcode()) {
    case clang::UO_PostDec:
    case clang::UO_PostInc:
    case clang::UO_PreDec:
    case clang::UO_PreInc: {
      Expr *SubExp = UO->getSubExpr()->IgnoreParenCasts();
      checkAccess(SubExp, AK_Written);
      checkDereference(SubExp, AK_Written);
      break;
    }
    default:
      break;
  }
}

/// For binary operations which assign to a variable (writes), we need to check
/// whether we hold any required mutexes.
/// FIXME: Deal with non-primitive types.
void BuildLockset::VisitBinaryOperator(BinaryOperator *BO) {
  if (!BO->isAssignmentOp())
    return;

  // adjust the context
  LVarCtx = Analyzer->LocalVarMap.getNextContext(CtxIndex, BO, LVarCtx);

  Expr *LHSExp = BO->getLHS()->IgnoreParenCasts();
  checkAccess(LHSExp, AK_Written);
  checkDereference(LHSExp, AK_Written);
}

/// Whenever we do an LValue to Rvalue cast, we are reading a variable and
/// need to ensure we hold any required mutexes.
/// FIXME: Deal with non-primitive types.
void BuildLockset::VisitCastExpr(CastExpr *CE) {
  if (CE->getCastKind() != CK_LValueToRValue)
    return;
  Expr *SubExp = CE->getSubExpr()->IgnoreParenCasts();
  checkAccess(SubExp, AK_Read);
  checkDereference(SubExp, AK_Read);
}


void BuildLockset::VisitCallExpr(CallExpr *Exp) {
  NamedDecl *D = dyn_cast_or_null<NamedDecl>(Exp->getCalleeDecl());
  if(!D || !D->hasAttrs())
    return;
  handleCall(Exp, D);
}

void BuildLockset::VisitCXXConstructExpr(CXXConstructExpr *Exp) {
  // FIXME -- only handles constructors in DeclStmt below.
}

void BuildLockset::VisitDeclStmt(DeclStmt *S) {
  // adjust the context
  LVarCtx = Analyzer->LocalVarMap.getNextContext(CtxIndex, S, LVarCtx);

  DeclGroupRef DGrp = S->getDeclGroup();
  for (DeclGroupRef::iterator I = DGrp.begin(), E = DGrp.end(); I != E; ++I) {
    Decl *D = *I;
    if (VarDecl *VD = dyn_cast_or_null<VarDecl>(D)) {
      Expr *E = VD->getInit();
      // handle constructors that involve temporaries
      if (ExprWithCleanups *EWC = dyn_cast_or_null<ExprWithCleanups>(E))
        E = EWC->getSubExpr();

      if (CXXConstructExpr *CE = dyn_cast_or_null<CXXConstructExpr>(E)) {
        NamedDecl *CtorD = dyn_cast_or_null<NamedDecl>(CE->getConstructor());
        if (!CtorD || !CtorD->hasAttrs())
          return;
        handleCall(CE, CtorD, VD);
      }
    }
  }
}



/// \brief Compute the intersection of two locksets and issue warnings for any
/// locks in the symmetric difference.
///
/// This function is used at a merge point in the CFG when comparing the lockset
/// of each branch being merged. For example, given the following sequence:
/// A; if () then B; else C; D; we need to check that the lockset after B and C
/// are the same. In the event of a difference, we use the intersection of these
/// two locksets at the start of D.
///
/// \param FSet1 The first lockset.
/// \param FSet2 The second lockset.
/// \param JoinLoc The location of the join point for error reporting
/// \param LEK1 The error message to report if a mutex is missing from LSet1
/// \param LEK2 The error message to report if a mutex is missing from Lset2
void ThreadSafetyAnalyzer::intersectAndWarn(FactSet &FSet1,
                                            const FactSet &FSet2,
                                            SourceLocation JoinLoc,
                                            LockErrorKind LEK1,
                                            LockErrorKind LEK2,
                                            bool Modify) {
  FactSet FSet1Orig = FSet1;

  for (FactSet::const_iterator I = FSet2.begin(), E = FSet2.end();
       I != E; ++I) {
    const SExpr &FSet2Mutex = FactMan[*I].MutID;
    const LockData &LDat2 = FactMan[*I].LDat;

    if (const LockData *LDat1 = FSet1.findLock(FactMan, FSet2Mutex)) {
      if (LDat1->LKind != LDat2.LKind) {
        Handler.handleExclusiveAndShared(FSet2Mutex.toString(),
                                         LDat2.AcquireLoc,
                                         LDat1->AcquireLoc);
        if (Modify && LDat1->LKind != LK_Exclusive) {
          FSet1.removeLock(FactMan, FSet2Mutex);
          FSet1.addLock(FactMan, FSet2Mutex, LDat2);
        }
      }
    } else {
      if (LDat2.UnderlyingMutex.isValid()) {
        if (FSet2.findLock(FactMan, LDat2.UnderlyingMutex)) {
          // If this is a scoped lock that manages another mutex, and if the
          // underlying mutex is still held, then warn about the underlying
          // mutex.
          Handler.handleMutexHeldEndOfScope(LDat2.UnderlyingMutex.toString(),
                                            LDat2.AcquireLoc,
                                            JoinLoc, LEK1);
        }
      }
      else if (!LDat2.Managed && !FSet2Mutex.isUniversal())
        Handler.handleMutexHeldEndOfScope(FSet2Mutex.toString(),
                                          LDat2.AcquireLoc,
                                          JoinLoc, LEK1);
    }
  }

  for (FactSet::const_iterator I = FSet1.begin(), E = FSet1.end();
       I != E; ++I) {
    const SExpr &FSet1Mutex = FactMan[*I].MutID;
    const LockData &LDat1 = FactMan[*I].LDat;

    if (!FSet2.findLock(FactMan, FSet1Mutex)) {
      if (LDat1.UnderlyingMutex.isValid()) {
        if (FSet1Orig.findLock(FactMan, LDat1.UnderlyingMutex)) {
          // If this is a scoped lock that manages another mutex, and if the
          // underlying mutex is still held, then warn about the underlying
          // mutex.
          Handler.handleMutexHeldEndOfScope(LDat1.UnderlyingMutex.toString(),
                                            LDat1.AcquireLoc,
                                            JoinLoc, LEK1);
        }
      }
      else if (!LDat1.Managed && !FSet1Mutex.isUniversal())
        Handler.handleMutexHeldEndOfScope(FSet1Mutex.toString(),
                                          LDat1.AcquireLoc,
                                          JoinLoc, LEK2);
      if (Modify)
        FSet1.removeLock(FactMan, FSet1Mutex);
    }
  }
}



/// \brief Check a function's CFG for thread-safety violations.
///
/// We traverse the blocks in the CFG, compute the set of mutexes that are held
/// at the end of each block, and issue warnings for thread safety violations.
/// Each block in the CFG is traversed exactly once.
void ThreadSafetyAnalyzer::runAnalysis(AnalysisDeclContext &AC) {
  CFG *CFGraph = AC.getCFG();
  if (!CFGraph) return;
  const NamedDecl *D = dyn_cast_or_null<NamedDecl>(AC.getDecl());

  // AC.dumpCFG(true);

  if (!D)
    return;  // Ignore anonymous functions for now.
  if (D->getAttr<NoThreadSafetyAnalysisAttr>())
    return;
  // FIXME: Do something a bit more intelligent inside constructor and
  // destructor code.  Constructors and destructors must assume unique access
  // to 'this', so checks on member variable access is disabled, but we should
  // still enable checks on other objects.
  if (isa<CXXConstructorDecl>(D))
    return;  // Don't check inside constructors.
  if (isa<CXXDestructorDecl>(D))
    return;  // Don't check inside destructors.

  BlockInfo.resize(CFGraph->getNumBlockIDs(),
    CFGBlockInfo::getEmptyBlockInfo(LocalVarMap));

  // We need to explore the CFG via a "topological" ordering.
  // That way, we will be guaranteed to have information about required
  // predecessor locksets when exploring a new block.
  PostOrderCFGView *SortedGraph = AC.getAnalysis<PostOrderCFGView>();
  PostOrderCFGView::CFGBlockSet VisitedBlocks(CFGraph);

  // Compute SSA names for local variables
  LocalVarMap.traverseCFG(CFGraph, SortedGraph, BlockInfo);

  // Fill in source locations for all CFGBlocks.
  findBlockLocations(CFGraph, SortedGraph, BlockInfo);

  // Add locks from exclusive_locks_required and shared_locks_required
  // to initial lockset. Also turn off checking for lock and unlock functions.
  // FIXME: is there a more intelligent way to check lock/unlock functions?
  if (!SortedGraph->empty() && D->hasAttrs()) {
    const CFGBlock *FirstBlock = *SortedGraph->begin();
    FactSet &InitialLockset = BlockInfo[FirstBlock->getBlockID()].EntrySet;
    const AttrVec &ArgAttrs = D->getAttrs();

    MutexIDList ExclusiveLocksToAdd;
    MutexIDList SharedLocksToAdd;

    SourceLocation Loc = D->getLocation();
    for (unsigned i = 0; i < ArgAttrs.size(); ++i) {
      Attr *Attr = ArgAttrs[i];
      Loc = Attr->getLocation();
      if (ExclusiveLocksRequiredAttr *A
            = dyn_cast<ExclusiveLocksRequiredAttr>(Attr)) {
        getMutexIDs(ExclusiveLocksToAdd, A, (Expr*) 0, D);
      } else if (SharedLocksRequiredAttr *A
                   = dyn_cast<SharedLocksRequiredAttr>(Attr)) {
        getMutexIDs(SharedLocksToAdd, A, (Expr*) 0, D);
      } else if (isa<UnlockFunctionAttr>(Attr)) {
        // Don't try to check unlock functions for now
        return;
      } else if (isa<ExclusiveLockFunctionAttr>(Attr)) {
        // Don't try to check lock functions for now
        return;
      } else if (isa<SharedLockFunctionAttr>(Attr)) {
        // Don't try to check lock functions for now
        return;
      } else if (isa<ExclusiveTrylockFunctionAttr>(Attr)) {
        // Don't try to check trylock functions for now
        return;
      } else if (isa<SharedTrylockFunctionAttr>(Attr)) {
        // Don't try to check trylock functions for now
        return;
      }
    }

    // FIXME -- Loc can be wrong here.
    for (unsigned i=0,n=ExclusiveLocksToAdd.size(); i<n; ++i) {
      addLock(InitialLockset, ExclusiveLocksToAdd[i],
              LockData(Loc, LK_Exclusive));
    }
    for (unsigned i=0,n=SharedLocksToAdd.size(); i<n; ++i) {
      addLock(InitialLockset, SharedLocksToAdd[i],
              LockData(Loc, LK_Shared));
    }
  }

  for (PostOrderCFGView::iterator I = SortedGraph->begin(),
       E = SortedGraph->end(); I!= E; ++I) {
    const CFGBlock *CurrBlock = *I;
    int CurrBlockID = CurrBlock->getBlockID();
    CFGBlockInfo *CurrBlockInfo = &BlockInfo[CurrBlockID];

    // Use the default initial lockset in case there are no predecessors.
    VisitedBlocks.insert(CurrBlock);

    // Iterate through the predecessor blocks and warn if the lockset for all
    // predecessors is not the same. We take the entry lockset of the current
    // block to be the intersection of all previous locksets.
    // FIXME: By keeping the intersection, we may output more errors in future
    // for a lock which is not in the intersection, but was in the union. We
    // may want to also keep the union in future. As an example, let's say
    // the intersection contains Mutex L, and the union contains L and M.
    // Later we unlock M. At this point, we would output an error because we
    // never locked M; although the real error is probably that we forgot to
    // lock M on all code paths. Conversely, let's say that later we lock M.
    // In this case, we should compare against the intersection instead of the
    // union because the real error is probably that we forgot to unlock M on
    // all code paths.
    bool LocksetInitialized = false;
    llvm::SmallVector<CFGBlock*, 8> SpecialBlocks;
    for (CFGBlock::const_pred_iterator PI = CurrBlock->pred_begin(),
         PE  = CurrBlock->pred_end(); PI != PE; ++PI) {

      // if *PI -> CurrBlock is a back edge
      if (*PI == 0 || !VisitedBlocks.alreadySet(*PI))
        continue;

      // Ignore edges from blocks that can't return.
      if ((*PI)->hasNoReturnElement())
        continue;

      // If the previous block ended in a 'continue' or 'break' statement, then
      // a difference in locksets is probably due to a bug in that block, rather
      // than in some other predecessor. In that case, keep the other
      // predecessor's lockset.
      if (const Stmt *Terminator = (*PI)->getTerminator()) {
        if (isa<ContinueStmt>(Terminator) || isa<BreakStmt>(Terminator)) {
          SpecialBlocks.push_back(*PI);
          continue;
        }
      }

      int PrevBlockID = (*PI)->getBlockID();
      CFGBlockInfo *PrevBlockInfo = &BlockInfo[PrevBlockID];
      FactSet PrevLockset;
      getEdgeLockset(PrevLockset, PrevBlockInfo->ExitSet, *PI, CurrBlock);

      if (!LocksetInitialized) {
        CurrBlockInfo->EntrySet = PrevLockset;
        LocksetInitialized = true;
      } else {
        intersectAndWarn(CurrBlockInfo->EntrySet, PrevLockset,
                         CurrBlockInfo->EntryLoc,
                         LEK_LockedSomePredecessors);
      }
    }

    // Process continue and break blocks. Assume that the lockset for the
    // resulting block is unaffected by any discrepancies in them.
    for (unsigned SpecialI = 0, SpecialN = SpecialBlocks.size();
         SpecialI < SpecialN; ++SpecialI) {
      CFGBlock *PrevBlock = SpecialBlocks[SpecialI];
      int PrevBlockID = PrevBlock->getBlockID();
      CFGBlockInfo *PrevBlockInfo = &BlockInfo[PrevBlockID];

      if (!LocksetInitialized) {
        CurrBlockInfo->EntrySet = PrevBlockInfo->ExitSet;
        LocksetInitialized = true;
      } else {
        // Determine whether this edge is a loop terminator for diagnostic
        // purposes. FIXME: A 'break' statement might be a loop terminator, but
        // it might also be part of a switch. Also, a subsequent destructor
        // might add to the lockset, in which case the real issue might be a
        // double lock on the other path.
        const Stmt *Terminator = PrevBlock->getTerminator();
        bool IsLoop = Terminator && isa<ContinueStmt>(Terminator);

        FactSet PrevLockset;
        getEdgeLockset(PrevLockset, PrevBlockInfo->ExitSet,
                       PrevBlock, CurrBlock);

        // Do not update EntrySet.
        intersectAndWarn(CurrBlockInfo->EntrySet, PrevLockset,
                         PrevBlockInfo->ExitLoc,
                         IsLoop ? LEK_LockedSomeLoopIterations
                                : LEK_LockedSomePredecessors,
                         false);
      }
    }

    BuildLockset LocksetBuilder(this, *CurrBlockInfo);

    // Visit all the statements in the basic block.
    for (CFGBlock::const_iterator BI = CurrBlock->begin(),
         BE = CurrBlock->end(); BI != BE; ++BI) {
      switch (BI->getKind()) {
        case CFGElement::Statement: {
          const CFGStmt *CS = cast<CFGStmt>(&*BI);
          LocksetBuilder.Visit(const_cast<Stmt*>(CS->getStmt()));
          break;
        }
        // Ignore BaseDtor, MemberDtor, and TemporaryDtor for now.
        case CFGElement::AutomaticObjectDtor: {
          const CFGAutomaticObjDtor *AD = cast<CFGAutomaticObjDtor>(&*BI);
          CXXDestructorDecl *DD = const_cast<CXXDestructorDecl*>(
            AD->getDestructorDecl(AC.getASTContext()));
          if (!DD->hasAttrs())
            break;

          // Create a dummy expression,
          VarDecl *VD = const_cast<VarDecl*>(AD->getVarDecl());
          DeclRefExpr DRE(VD, false, VD->getType(), VK_LValue,
                          AD->getTriggerStmt()->getLocEnd());
          LocksetBuilder.handleCall(&DRE, DD);
          break;
        }
        default:
          break;
      }
    }
    CurrBlockInfo->ExitSet = LocksetBuilder.FSet;

    // For every back edge from CurrBlock (the end of the loop) to another block
    // (FirstLoopBlock) we need to check that the Lockset of Block is equal to
    // the one held at the beginning of FirstLoopBlock. We can look up the
    // Lockset held at the beginning of FirstLoopBlock in the EntryLockSets map.
    for (CFGBlock::const_succ_iterator SI = CurrBlock->succ_begin(),
         SE  = CurrBlock->succ_end(); SI != SE; ++SI) {

      // if CurrBlock -> *SI is *not* a back edge
      if (*SI == 0 || !VisitedBlocks.alreadySet(*SI))
        continue;

      CFGBlock *FirstLoopBlock = *SI;
      CFGBlockInfo *PreLoop = &BlockInfo[FirstLoopBlock->getBlockID()];
      CFGBlockInfo *LoopEnd = &BlockInfo[CurrBlockID];
      intersectAndWarn(LoopEnd->ExitSet, PreLoop->EntrySet,
                       PreLoop->EntryLoc,
                       LEK_LockedSomeLoopIterations,
                       false);
    }
  }

  CFGBlockInfo *Initial = &BlockInfo[CFGraph->getEntry().getBlockID()];
  CFGBlockInfo *Final   = &BlockInfo[CFGraph->getExit().getBlockID()];

  // FIXME: Should we call this function for all blocks which exit the function?
  intersectAndWarn(Initial->EntrySet, Final->ExitSet,
                   Final->ExitLoc,
                   LEK_LockedAtEndOfFunction,
                   LEK_NotLockedAtEndOfFunction,
                   false);
}

} // end anonymous namespace


namespace clang {
namespace thread_safety {

/// \brief Check a function's CFG for thread-safety violations.
///
/// We traverse the blocks in the CFG, compute the set of mutexes that are held
/// at the end of each block, and issue warnings for thread safety violations.
/// Each block in the CFG is traversed exactly once.
void runThreadSafetyAnalysis(AnalysisDeclContext &AC,
                             ThreadSafetyHandler &Handler) {
  ThreadSafetyAnalyzer Analyzer(Handler);
  Analyzer.runAnalysis(AC);
}

/// \brief Helper function that returns a LockKind required for the given level
/// of access.
LockKind getLockKindFromAccessKind(AccessKind AK) {
  switch (AK) {
    case AK_Read :
      return LK_Shared;
    case AK_Written :
      return LK_Exclusive;
  }
  llvm_unreachable("Unknown AccessKind");
}

}} // end namespace clang::thread_safety
