aboutsummaryrefslogtreecommitdiff
path: root/clang/lib/Analysis/FlowSensitive/ControlFlowContext.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'clang/lib/Analysis/FlowSensitive/ControlFlowContext.cpp')
-rw-r--r--clang/lib/Analysis/FlowSensitive/ControlFlowContext.cpp38
1 files changed, 37 insertions, 1 deletions
diff --git a/clang/lib/Analysis/FlowSensitive/ControlFlowContext.cpp b/clang/lib/Analysis/FlowSensitive/ControlFlowContext.cpp
index 8aed195..7c9f8fb 100644
--- a/clang/lib/Analysis/FlowSensitive/ControlFlowContext.cpp
+++ b/clang/lib/Analysis/FlowSensitive/ControlFlowContext.cpp
@@ -94,6 +94,38 @@ static llvm::BitVector findReachableBlocks(const CFG &Cfg) {
return BlockReachable;
}
+static llvm::DenseSet<const CFGBlock *>
+buildContainsExprConsumedInDifferentBlock(
+ const CFG &Cfg,
+ const llvm::DenseMap<const Stmt *, const CFGBlock *> &StmtToBlock) {
+ llvm::DenseSet<const CFGBlock *> Result;
+
+ auto CheckChildExprs = [&Result, &StmtToBlock](const Stmt *S,
+ const CFGBlock *Block) {
+ for (const Stmt *Child : S->children()) {
+ if (!isa<Expr>(Child))
+ continue;
+ const CFGBlock *ChildBlock = StmtToBlock.lookup(Child);
+ if (ChildBlock != Block)
+ Result.insert(ChildBlock);
+ }
+ };
+
+ for (const CFGBlock *Block : Cfg) {
+ if (Block == nullptr)
+ continue;
+
+ for (const CFGElement &Element : *Block)
+ if (auto S = Element.getAs<CFGStmt>())
+ CheckChildExprs(S->getStmt(), Block);
+
+ if (const Stmt *TerminatorCond = Block->getTerminatorCondition())
+ CheckChildExprs(TerminatorCond, Block);
+ }
+
+ return Result;
+}
+
llvm::Expected<ControlFlowContext>
ControlFlowContext::build(const FunctionDecl &Func) {
if (!Func.doesThisDeclarationHaveABody())
@@ -140,8 +172,12 @@ ControlFlowContext::build(const Decl &D, Stmt &S, ASTContext &C) {
llvm::BitVector BlockReachable = findReachableBlocks(*Cfg);
+ llvm::DenseSet<const CFGBlock *> ContainsExprConsumedInDifferentBlock =
+ buildContainsExprConsumedInDifferentBlock(*Cfg, StmtToBlock);
+
return ControlFlowContext(D, std::move(Cfg), std::move(StmtToBlock),
- std::move(BlockReachable));
+ std::move(BlockReachable),
+ std::move(ContainsExprConsumedInDifferentBlock));
}
} // namespace dataflow