Update Clang for rebase to r212749.
This also fixes a small issue with arm_neon.h not being generated always.
Includes a cherry-pick of:
r213450 - fixes mac-specific header issue
r213126 - removes a default -Bsymbolic on Android
Change-Id: I2a790a0f5d3b2aab11de596fc3a74e7cbc99081d
diff --git a/lib/Analysis/CFG.cpp b/lib/Analysis/CFG.cpp
index 5d2926c..d6361e8 100644
--- a/lib/Analysis/CFG.cpp
+++ b/lib/Analysis/CFG.cpp
@@ -3926,7 +3926,8 @@
void VisitIfStmt(IfStmt *I) {
OS << "if ";
- I->getCond()->printPretty(OS,Helper,Policy);
+ if (Stmt *C = I->getCond())
+ C->printPretty(OS, Helper, Policy);
}
// Default case.
@@ -3974,19 +3975,22 @@
}
void VisitAbstractConditionalOperator(AbstractConditionalOperator* C) {
- C->getCond()->printPretty(OS, Helper, Policy);
+ if (Stmt *Cond = C->getCond())
+ Cond->printPretty(OS, Helper, Policy);
OS << " ? ... : ...";
}
void VisitChooseExpr(ChooseExpr *C) {
OS << "__builtin_choose_expr( ";
- C->getCond()->printPretty(OS, Helper, Policy);
+ if (Stmt *Cond = C->getCond())
+ Cond->printPretty(OS, Helper, Policy);
OS << " )";
}
void VisitIndirectGotoStmt(IndirectGotoStmt *I) {
OS << "goto *";
- I->getTarget()->printPretty(OS, Helper, Policy);
+ if (Stmt *T = I->getTarget())
+ T->printPretty(OS, Helper, Policy);
}
void VisitBinaryOperator(BinaryOperator* B) {
@@ -3995,7 +3999,8 @@
return;
}
- B->getLHS()->printPretty(OS, Helper, Policy);
+ if (B->getLHS())
+ B->getLHS()->printPretty(OS, Helper, Policy);
switch (B->getOpcode()) {
case BO_LOr:
@@ -4026,7 +4031,8 @@
const CFGElement &E) {
if (Optional<CFGStmt> CS = E.getAs<CFGStmt>()) {
const Stmt *S = CS->getStmt();
-
+ assert(S != nullptr && "Expecting non-null Stmt");
+
// special printing for statement-expressions.
if (const StmtExpr *SE = dyn_cast<StmtExpr>(S)) {
const CompoundStmt *Sub = SE->getSubStmt();
@@ -4172,8 +4178,9 @@
OS << L->getName();
else if (CaseStmt *C = dyn_cast<CaseStmt>(Label)) {
OS << "case ";
- C->getLHS()->printPretty(OS, &Helper,
- PrintingPolicy(Helper.getLangOpts()));
+ if (C->getLHS())
+ C->getLHS()->printPretty(OS, &Helper,
+ PrintingPolicy(Helper.getLangOpts()));
if (C->getRHS()) {
OS << " ... ";
C->getRHS()->printPretty(OS, &Helper,
@@ -4349,6 +4356,10 @@
print(llvm::errs(), cfg, LO, ShowColors);
}
+void CFGBlock::dump() const {
+ dump(getParent(), LangOptions(), false);
+}
+
/// print - A simple pretty printer of a CFGBlock that outputs to an ostream.
/// Generally this will only be called from CFG::print.
void CFGBlock::print(raw_ostream &OS, const CFG* cfg,
diff --git a/lib/Analysis/ThreadSafetyCommon.cpp b/lib/Analysis/ThreadSafetyCommon.cpp
index 91cf849..da88b78 100644
--- a/lib/Analysis/ThreadSafetyCommon.cpp
+++ b/lib/Analysis/ThreadSafetyCommon.cpp
@@ -384,8 +384,7 @@
CallingContext *Ctx) {
til::SExpr *E0 = translate(E->getBase(), Ctx);
til::SExpr *E1 = translate(E->getIdx(), Ctx);
- auto *AA = new (Arena) til::ArrayAdd(E0, E1);
- return new (Arena) til::ArrayFirst(AA);
+ return new (Arena) til::ArrayIndex(E0, E1);
}
@@ -628,7 +627,8 @@
BlockMap.resize(NBlocks, nullptr);
// create map from clang blockID to til::BasicBlocks
for (auto *B : *Cfg) {
- auto *BB = new (Arena) til::BasicBlock(Arena, 0, B->size());
+ auto *BB = new (Arena) til::BasicBlock(Arena);
+ BB->reserveInstructions(B->size());
BlockMap[B->getBlockID()] = BB;
}
CallCtx.reset(new SExprBuilder::CallingContext(D));
@@ -654,7 +654,7 @@
void SExprBuilder::enterCFGBlock(const CFGBlock *B) {
// Intialize TIL basic block and add it to the CFG.
CurrentBB = lookupBlock(B);
- CurrentBB->setNumPredecessors(B->pred_size());
+ CurrentBB->reservePredecessors(B->pred_size());
Scfg->add(CurrentBB);
CurrentBlockInfo = &BBInfo[B->getBlockID()];
@@ -668,6 +668,7 @@
void SExprBuilder::handlePredecessor(const CFGBlock *Pred) {
// Compute CurrentLVarMap on entry from ExitMaps of predecessors
+ CurrentBB->addPredecessor(BlockMap[Pred->getBlockID()]);
BlockInfo *PredInfo = &BBInfo[Pred->getBlockID()];
assert(PredInfo->UnprocessedSuccessors > 0);
@@ -724,7 +725,8 @@
if (N == 1) {
til::BasicBlock *BB = *It ? lookupBlock(*It) : nullptr;
// TODO: set index
- til::SExpr *Tm = new (Arena) til::Goto(BB, 0);
+ unsigned Idx = BB ? BB->findPredecessorIndex(CurrentBB) : 0;
+ til::SExpr *Tm = new (Arena) til::Goto(BB, Idx);
CurrentBB->setTerminator(Tm);
}
else if (N == 2) {
@@ -732,8 +734,9 @@
til::BasicBlock *BB1 = *It ? lookupBlock(*It) : nullptr;
++It;
til::BasicBlock *BB2 = *It ? lookupBlock(*It) : nullptr;
- // TODO: set conditional, set index
- til::SExpr *Tm = new (Arena) til::Branch(C, BB1, BB2);
+ unsigned Idx1 = BB1 ? BB1->findPredecessorIndex(CurrentBB) : 0;
+ unsigned Idx2 = BB2 ? BB2->findPredecessorIndex(CurrentBB) : 0;
+ til::SExpr *Tm = new (Arena) til::Branch(C, BB1, BB2, Idx1, Idx2);
CurrentBB->setTerminator(Tm);
}
}
diff --git a/lib/Analysis/ThreadSafetyLogical.cpp b/lib/Analysis/ThreadSafetyLogical.cpp
index 51a8077..facfa11 100644
--- a/lib/Analysis/ThreadSafetyLogical.cpp
+++ b/lib/Analysis/ThreadSafetyLogical.cpp
@@ -1,112 +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);
-}
-}
-}
-}
+//===- 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);
+}
+}
+}
+}
diff --git a/lib/Analysis/ThreadSafetyTIL.cpp b/lib/Analysis/ThreadSafetyTIL.cpp
index f4da8d4..f67cbb9 100644
--- a/lib/Analysis/ThreadSafetyTIL.cpp
+++ b/lib/Analysis/ThreadSafetyTIL.cpp
@@ -48,6 +48,46 @@
}
+unsigned BasicBlock::addPredecessor(BasicBlock *Pred) {
+ unsigned Idx = Predecessors.size();
+ Predecessors.reserveCheck(1, Arena);
+ Predecessors.push_back(Pred);
+ for (Variable *V : Args) {
+ if (Phi* Ph = dyn_cast<Phi>(V->definition())) {
+ Ph->values().reserveCheck(1, Arena);
+ Ph->values().push_back(nullptr);
+ }
+ }
+ return Idx;
+}
+
+void BasicBlock::reservePredecessors(unsigned NumPreds) {
+ Predecessors.reserve(NumPreds, Arena);
+ for (Variable *V : Args) {
+ if (Phi* Ph = dyn_cast<Phi>(V->definition())) {
+ Ph->values().reserve(NumPreds, Arena);
+ }
+ }
+}
+
+void BasicBlock::renumberVars() {
+ unsigned VID = 0;
+ for (Variable *V : Args) {
+ V->setID(BlockID, VID++);
+ }
+ for (Variable *V : Instrs) {
+ V->setID(BlockID, VID++);
+ }
+}
+
+void SCFG::renumberVars() {
+ for (BasicBlock *B : Blocks) {
+ B->renumberVars();
+ }
+}
+
+
+
// If E is a variable, then trace back through any aliases or redundant
// Phi nodes to find the canonical definition.
diff --git a/lib/Analysis/UninitializedValues.cpp b/lib/Analysis/UninitializedValues.cpp
index 4b8a59c..f5c786a 100644
--- a/lib/Analysis/UninitializedValues.cpp
+++ b/lib/Analysis/UninitializedValues.cpp
@@ -34,7 +34,7 @@
static bool isTrackedVar(const VarDecl *vd, const DeclContext *dc) {
if (vd->isLocalVarDecl() && !vd->hasGlobalStorage() &&
- !vd->isExceptionVariable() &&
+ !vd->isExceptionVariable() && !vd->isInitCapture() &&
vd->getDeclContext() == dc) {
QualType ty = vd->getType();
return ty->isScalarType() || ty->isVectorType();