Coverage Report

Created: 2023-09-30 09:22

/Users/buildslave/jenkins/workspace/coverage/llvm-project/clang/lib/Analysis/FlowSensitive/ControlFlowContext.cpp
Line
Count
Source (jump to first uncovered line)
1
//===- ControlFlowContext.cpp ---------------------------------------------===//
2
//
3
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4
// See https://llvm.org/LICENSE.txt for license information.
5
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6
//
7
//===----------------------------------------------------------------------===//
8
//
9
//  This file defines a ControlFlowContext class that is used by dataflow
10
//  analyses that run over Control-Flow Graphs (CFGs).
11
//
12
//===----------------------------------------------------------------------===//
13
14
#include "clang/Analysis/FlowSensitive/ControlFlowContext.h"
15
#include "clang/AST/ASTContext.h"
16
#include "clang/AST/Decl.h"
17
#include "clang/AST/Stmt.h"
18
#include "clang/Analysis/CFG.h"
19
#include "llvm/ADT/BitVector.h"
20
#include "llvm/ADT/DenseMap.h"
21
#include "llvm/Support/Error.h"
22
#include <utility>
23
24
namespace clang {
25
namespace dataflow {
26
27
/// Returns a map from statements to basic blocks that contain them.
28
static llvm::DenseMap<const Stmt *, const CFGBlock *>
29
659
buildStmtToBasicBlockMap(const CFG &Cfg) {
30
659
  llvm::DenseMap<const Stmt *, const CFGBlock *> StmtToBlock;
31
3.16k
  for (const CFGBlock *Block : Cfg) {
32
3.16k
    if (Block == nullptr)
33
0
      continue;
34
35
11.2k
    
for (const CFGElement &Element : *Block)3.16k
{
36
11.2k
      auto Stmt = Element.getAs<CFGStmt>();
37
11.2k
      if (!Stmt)
38
1.21k
        continue;
39
40
10.0k
      StmtToBlock[Stmt->getStmt()] = Block;
41
10.0k
    }
42
3.16k
    if (const Stmt *TerminatorStmt = Block->getTerminatorStmt())
43
535
      StmtToBlock[TerminatorStmt] = Block;
44
3.16k
  }
45
659
  return StmtToBlock;
46
659
}
47
48
659
static llvm::BitVector findReachableBlocks(const CFG &Cfg) {
49
659
  llvm::BitVector BlockReachable(Cfg.getNumBlockIDs(), false);
50
51
659
  llvm::SmallVector<const CFGBlock *> BlocksToVisit;
52
659
  BlocksToVisit.push_back(&Cfg.getEntry());
53
4.35k
  while (!BlocksToVisit.empty()) {
54
3.69k
    const CFGBlock *Block = BlocksToVisit.back();
55
3.69k
    BlocksToVisit.pop_back();
56
57
3.69k
    if (BlockReachable[Block->getBlockID()])
58
570
      continue;
59
60
3.12k
    BlockReachable[Block->getBlockID()] = true;
61
62
3.12k
    for (const CFGBlock *Succ : Block->succs())
63
3.05k
      if (Succ)
64
3.03k
        BlocksToVisit.push_back(Succ);
65
3.12k
  }
66
67
659
  return BlockReachable;
68
659
}
69
70
llvm::Expected<ControlFlowContext>
71
662
ControlFlowContext::build(const FunctionDecl &Func) {
72
662
  if (!Func.hasBody())
73
0
    return llvm::createStringError(
74
0
        std::make_error_code(std::errc::invalid_argument),
75
0
        "Cannot analyze function without a body");
76
77
662
  return build(Func, *Func.getBody(), Func.getASTContext());
78
662
}
79
80
llvm::Expected<ControlFlowContext>
81
662
ControlFlowContext::build(const Decl &D, Stmt &S, ASTContext &C) {
82
662
  if (D.isTemplated())
83
2
    return llvm::createStringError(
84
2
        std::make_error_code(std::errc::invalid_argument),
85
2
        "Cannot analyze templated declarations");
86
87
  // The shape of certain elements of the AST can vary depending on the
88
  // language. We currently only support C++.
89
660
  if (!C.getLangOpts().CPlusPlus)
90
1
    return llvm::createStringError(
91
1
        std::make_error_code(std::errc::invalid_argument),
92
1
        "Can only analyze C++");
93
94
659
  CFG::BuildOptions Options;
95
659
  Options.PruneTriviallyFalseEdges = true;
96
659
  Options.AddImplicitDtors = true;
97
659
  Options.AddTemporaryDtors = true;
98
659
  Options.AddInitializers = true;
99
659
  Options.AddCXXDefaultInitExprInCtors = true;
100
659
  Options.AddLifetime = true;
101
102
  // Ensure that all sub-expressions in basic blocks are evaluated.
103
659
  Options.setAllAlwaysAdd();
104
105
659
  auto Cfg = CFG::buildCFG(&D, &S, &C, Options);
106
659
  if (Cfg == nullptr)
107
0
    return llvm::createStringError(
108
0
        std::make_error_code(std::errc::invalid_argument),
109
0
        "CFG::buildCFG failed");
110
111
659
  llvm::DenseMap<const Stmt *, const CFGBlock *> StmtToBlock =
112
659
      buildStmtToBasicBlockMap(*Cfg);
113
114
659
  llvm::BitVector BlockReachable = findReachableBlocks(*Cfg);
115
116
659
  return ControlFlowContext(D, std::move(Cfg), std::move(StmtToBlock),
117
659
                            std::move(BlockReachable));
118
659
}
119
120
} // namespace dataflow
121
} // namespace clang