Update Clang for 3.5 rebase (r209713).

Change-Id: I8c9133b0f8f776dc915f270b60f94962e771bc83
diff --git a/lib/Analysis/ThreadSafetyLogical.cpp b/lib/Analysis/ThreadSafetyLogical.cpp
new file mode 100644
index 0000000..51a8077
--- /dev/null
+++ b/lib/Analysis/ThreadSafetyLogical.cpp
@@ -0,0 +1,112 @@
+//===- ThreadSafetyLogical.cpp ---------------------------------*- C++ --*-===//

+//

+//                     The LLVM Compiler Infrastructure

+//

+// This file is distributed under the University of Illinois Open Source

+// License. See LICENSE.TXT for details.

+//

+//===----------------------------------------------------------------------===//

+// This file defines a representation for logical expressions with SExpr leaves

+// that are used as part of fact-checking capability expressions.

+//===----------------------------------------------------------------------===//

+

+#include "clang/Analysis/Analyses/ThreadSafetyLogical.h"

+

+using namespace llvm;

+using namespace clang::threadSafety::lexpr;

+

+// Implication.  We implement De Morgan's Laws by maintaining LNeg and RNeg

+// to keep track of whether LHS and RHS are negated.

+static bool implies(const LExpr *LHS, bool LNeg, const LExpr *RHS, bool RNeg) {

+  // In comments below, we write => for implication.

+

+  // Calculates the logical AND implication operator.

+  const auto LeftAndOperator = [=](const BinOp *A) {

+    return implies(A->left(), LNeg, RHS, RNeg) &&

+           implies(A->right(), LNeg, RHS, RNeg);

+  };

+  const auto RightAndOperator = [=](const BinOp *A) {

+    return implies(LHS, LNeg, A->left(), RNeg) &&

+           implies(LHS, LNeg, A->right(), RNeg);

+  };

+

+  // Calculates the logical OR implication operator.

+  const auto LeftOrOperator = [=](const BinOp *A) {

+    return implies(A->left(), LNeg, RHS, RNeg) ||

+           implies(A->right(), LNeg, RHS, RNeg);

+  };

+  const auto RightOrOperator = [=](const BinOp *A) {

+    return implies(LHS, LNeg, A->left(), RNeg) ||

+           implies(LHS, LNeg, A->right(), RNeg);

+  };

+

+  // Recurse on right.

+  switch (RHS->kind()) {

+  case LExpr::And:

+    // When performing right recursion:

+    //   C => A & B  [if]  C => A and C => B

+    // When performing right recursion (negated):

+    //   C => !(A & B)  [if]  C => !A | !B  [===]  C => !A or C => !B

+    return RNeg ? RightOrOperator(cast<And>(RHS))

+                : RightAndOperator(cast<And>(RHS));

+  case LExpr::Or:

+    // When performing right recursion:

+    //   C => (A | B)  [if]  C => A or C => B

+    // When performing right recursion (negated):

+    //   C => !(A | B)  [if]  C => !A & !B  [===]  C => !A and C => !B

+    return RNeg ? RightAndOperator(cast<Or>(RHS))

+                : RightOrOperator(cast<Or>(RHS));

+  case LExpr::Not:

+    // Note that C => !A is very different from !(C => A). It would be incorrect

+    // to return !implies(LHS, RHS).

+    return implies(LHS, LNeg, cast<Not>(RHS)->exp(), !RNeg);

+  case LExpr::Terminal:

+    // After reaching the terminal, it's time to recurse on the left.

+    break;

+  }

+

+  // RHS is now a terminal.  Recurse on Left.

+  switch (LHS->kind()) {

+  case LExpr::And:

+    // When performing left recursion:

+    //   A & B => C  [if]  A => C or B => C

+    // When performing left recursion (negated):

+    //   !(A & B) => C  [if]  !A | !B => C  [===]  !A => C and !B => C

+    return LNeg ? LeftAndOperator(cast<And>(LHS))

+                : LeftOrOperator(cast<And>(LHS));

+  case LExpr::Or:

+    // When performing left recursion:

+    //   A | B => C  [if]  A => C and B => C

+    // When performing left recursion (negated):

+    //   !(A | B) => C  [if]  !A & !B => C  [===]  !A => C or !B => C

+    return LNeg ? LeftOrOperator(cast<Or>(LHS))

+                : LeftAndOperator(cast<Or>(LHS));

+  case LExpr::Not:

+    // Note that A => !C is very different from !(A => C). It would be incorrect

+    // to return !implies(LHS, RHS).

+    return implies(cast<Not>(LHS)->exp(), !LNeg, RHS, RNeg);

+  case LExpr::Terminal:

+    // After reaching the terminal, it's time to perform identity comparisons.

+    break;

+  }

+

+  // A => A

+  // !A => !A

+  if (LNeg != RNeg)

+    return false;

+

+  // FIXME -- this should compare SExprs for equality, not pointer equality.

+  return cast<Terminal>(LHS)->expr() == cast<Terminal>(RHS)->expr();

+}

+

+namespace clang {

+namespace threadSafety {

+namespace lexpr {

+

+bool implies(const LExpr *LHS, const LExpr *RHS) {

+  // Start out by assuming that LHS and RHS are not negated.

+  return ::implies(LHS, false, RHS, false);

+}

+}

+}

+}