//===- 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;
  }

  // Grab the very first declaration of virtual method D
  const CXXMethodDecl* getFirstVirtualDecl(const CXXMethodDecl *D) {
    while (true) {
      D = D->getCanonicalDecl();
      CXXMethodDecl::method_iterator I = D->begin_overridden_methods(),
                                     E = D->end_overridden_methods();
      if (I == E)
        return D;  // Method does not override anything
      D = *I;      // FIXME: this does not work with multiple inheritance.
    }
    return 0;
  }

  unsigned makeMCall(unsigned NumArgs, const CXXMethodDecl *D) {
    NodeVec.push_back(SExprNode(EOP_MCall, NumArgs, getFirstVirtualDecl(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());
      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,
                          VarDecl *SelfDecl = 0) {
    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;  // Will be set below
      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;
    }

    // Hack to handle constructors, where self cannot be recovered from
    // the expression.
    if (SelfDecl && !CallCtx.SelfArg) {
      DeclRefExpr SelfDRE(SelfDecl, false, SelfDecl->getType(), VK_LValue,
                          SelfDecl->getLocation());
      CallCtx.SelfArg = &SelfDRE;

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

    // If the attribute has no arguments, then assume the argument is "this".
    if (MutexExp == 0)
      buildSExpr(CallCtx.SelfArg, 0);
    else  // 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,
        VarDecl *SelfDecl=0) {
    buildSExprFromExpr(MutexExp, DeclExp, D, SelfDecl);
  }

  /// 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 ni = NodeVec[i].arity();
      unsigned nj = Other.NodeVec[j].arity();
      unsigned n = (ni < nj) ? ni : nj;
      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
  bool Reachable;               // Is this block reachable?

  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), Reachable(false)
  { }

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, VarDecl *SelfDecl=0);

  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,
                                       VarDecl *SelfDecl) {
  typedef typename AttrType::args_iterator iterator_type;

  if (Attr->args_size() == 0) {
    // The mutex held is the "this" object.
    SExpr Mu(0, Exp, D, SelfDecl);
    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, SelfDecl);
    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(SharedLocksToAdd, 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) {
    std::string DeclName = D->getNameAsString();
    StringRef   DeclNameSR (DeclName);
    Analyzer->Handler.handleFunExcludesLock(DeclNameSR, 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, VD);
        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, VD);
        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, VD);
        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);

  // Mark entry block as reachable
  BlockInfo[CFGraph->getEntry().getBlockID()].Reachable = true;

  // 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;

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

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

      // Okay, we can reach this block from the entry.
      CurrBlockInfo->Reachable = true;

      // 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;
        }
      }


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

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

    // Skip rest of block if it's not reachable.
    if (!CurrBlockInfo->Reachable)
      continue;

    // 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()];

  // Skip the final check if the exit block is unreachable.
  if (!Final->Reachable)
    return;

  // 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
