Coverage Report

Created: 2017-10-03 07:32

/Users/buildslave/jenkins/sharedspace/clang-stage2-coverage-R@2/llvm/tools/clang/lib/StaticAnalyzer/Core/Environment.cpp
Line
Count
Source (jump to first uncovered line)
1
//== Environment.cpp - Map from Stmt* to Locations/Values -------*- C++ -*--==//
2
//
3
//                     The LLVM Compiler Infrastructure
4
//
5
// This file is distributed under the University of Illinois Open Source
6
// License. See LICENSE.TXT for details.
7
//
8
//===----------------------------------------------------------------------===//
9
//
10
//  This file defined the Environment and EnvironmentManager classes.
11
//
12
//===----------------------------------------------------------------------===//
13
14
#include "clang/AST/ExprCXX.h"
15
#include "clang/AST/ExprObjC.h"
16
#include "clang/Analysis/AnalysisDeclContext.h"
17
#include "clang/Analysis/CFG.h"
18
#include "clang/StaticAnalyzer/Core/PathSensitive/ProgramState.h"
19
#include "llvm/Support/raw_ostream.h"
20
21
using namespace clang;
22
using namespace ento;
23
24
2.38M
static const Expr *ignoreTransparentExprs(const Expr *E) {
25
2.38M
  E = E->IgnoreParens();
26
2.38M
27
2.38M
  switch (E->getStmtClass()) {
28
2.84k
  case Stmt::OpaqueValueExprClass:
29
2.84k
    E = cast<OpaqueValueExpr>(E)->getSourceExpr();
30
2.84k
    break;
31
1.15k
  case Stmt::ExprWithCleanupsClass:
32
1.15k
    E = cast<ExprWithCleanups>(E)->getSubExpr();
33
1.15k
    break;
34
411
  case Stmt::CXXBindTemporaryExprClass:
35
411
    E = cast<CXXBindTemporaryExpr>(E)->getSubExpr();
36
411
    break;
37
11
  case Stmt::SubstNonTypeTemplateParmExprClass:
38
11
    E = cast<SubstNonTypeTemplateParmExpr>(E)->getReplacement();
39
11
    break;
40
2.38M
  default:
41
2.38M
    // This is the base case: we can't look through more than we already have.
42
2.38M
    return E;
43
4.42k
  }
44
4.42k
45
4.42k
  return ignoreTransparentExprs(E);
46
4.42k
}
47
48
2.39M
static const Stmt *ignoreTransparentExprs(const Stmt *S) {
49
2.39M
  if (const Expr *E = dyn_cast<Expr>(S))
50
2.38M
    return ignoreTransparentExprs(E);
51
6.20k
  return S;
52
6.20k
}
53
54
EnvironmentEntry::EnvironmentEntry(const Stmt *S, const LocationContext *L)
55
  : std::pair<const Stmt *,
56
              const StackFrameContext *>(ignoreTransparentExprs(S),
57
                                         L ? L->getCurrentStackFrame()
58
2.39M
                                           : nullptr) {}
59
60
922k
SVal Environment::lookupExpr(const EnvironmentEntry &E) const {
61
922k
  const SVal* X = ExprBindings.lookup(E);
62
922k
  if (
X922k
) {
63
894k
    SVal V = *X;
64
894k
    return V;
65
894k
  }
66
28.0k
  return UnknownVal();
67
28.0k
}
68
69
SVal Environment::getSVal(const EnvironmentEntry &Entry,
70
976k
                          SValBuilder& svalBuilder) const {
71
976k
  const Stmt *S = Entry.getStmt();
72
976k
  const LocationContext *LCtx = Entry.getLocationContext();
73
976k
74
976k
  switch (S->getStmtClass()) {
75
0
  case Stmt::CXXBindTemporaryExprClass:
76
0
  case Stmt::ExprWithCleanupsClass:
77
0
  case Stmt::GenericSelectionExprClass:
78
0
  case Stmt::OpaqueValueExprClass:
79
0
  case Stmt::ParenExprClass:
80
0
  case Stmt::SubstNonTypeTemplateParmExprClass:
81
0
    llvm_unreachable("Should have been handled by ignoreTransparentExprs");
82
0
83
50.3k
  case Stmt::AddrLabelExprClass:
84
50.3k
  case Stmt::CharacterLiteralClass:
85
50.3k
  case Stmt::CXXBoolLiteralExprClass:
86
50.3k
  case Stmt::CXXScalarValueInitExprClass:
87
50.3k
  case Stmt::ImplicitValueInitExprClass:
88
50.3k
  case Stmt::IntegerLiteralClass:
89
50.3k
  case Stmt::ObjCBoolLiteralExprClass:
90
50.3k
  case Stmt::CXXNullPtrLiteralExprClass:
91
50.3k
  case Stmt::ObjCStringLiteralClass:
92
50.3k
  case Stmt::StringLiteralClass:
93
50.3k
  case Stmt::TypeTraitExprClass:
94
50.3k
    // Known constants; defer to SValBuilder.
95
50.3k
    return svalBuilder.getConstantVal(cast<Expr>(S)).getValue();
96
50.3k
97
3.22k
  case Stmt::ReturnStmtClass: {
98
3.22k
    const ReturnStmt *RS = cast<ReturnStmt>(S);
99
3.22k
    if (const Expr *RE = RS->getRetValue())
100
2.97k
      return getSVal(EnvironmentEntry(RE, LCtx), svalBuilder);
101
250
    return UndefinedVal();
102
250
  }
103
250
104
250
  // Handle all other Stmt* using a lookup.
105
922k
  default:
106
922k
    return lookupExpr(EnvironmentEntry(S, LCtx));
107
0
  }
108
0
}
109
110
Environment EnvironmentManager::bindExpr(Environment Env,
111
                                         const EnvironmentEntry &E,
112
                                         SVal V,
113
493k
                                         bool Invalidate) {
114
493k
  if (
V.isUnknown()493k
) {
115
5.86k
    if (Invalidate)
116
5.86k
      return Environment(F.remove(Env.ExprBindings, E));
117
5.86k
    else
118
0
      return Env;
119
487k
  }
120
487k
  return Environment(F.add(Env.ExprBindings, E, V));
121
487k
}
122
123
namespace {
124
class MarkLiveCallback final : public SymbolVisitor {
125
  SymbolReaper &SymReaper;
126
public:
127
179k
  MarkLiveCallback(SymbolReaper &symreaper) : SymReaper(symreaper) {}
128
384k
  bool VisitSymbol(SymbolRef sym) override {
129
384k
    SymReaper.markLive(sym);
130
384k
    return true;
131
384k
  }
132
421k
  bool VisitMemRegion(const MemRegion *R) override {
133
421k
    SymReaper.markLive(R);
134
421k
    return true;
135
421k
  }
136
};
137
} // end anonymous namespace
138
139
// removeDeadBindings:
140
//  - Remove subexpression bindings.
141
//  - Remove dead block expression bindings.
142
//  - Keep live block expression bindings:
143
//   - Mark their reachable symbols live in SymbolReaper,
144
//     see ScanReachableSymbols.
145
//   - Mark the region in DRoots if the binding is a loc::MemRegionVal.
146
Environment
147
EnvironmentManager::removeDeadBindings(Environment Env,
148
                                       SymbolReaper &SymReaper,
149
179k
                                       ProgramStateRef ST) {
150
179k
151
179k
  // We construct a new Environment object entirely, as this is cheaper than
152
179k
  // individually removing all the subexpression bindings (which will greatly
153
179k
  // outnumber block-level expression bindings).
154
179k
  Environment NewEnv = getInitialEnvironment();
155
179k
156
179k
  MarkLiveCallback CB(SymReaper);
157
179k
  ScanReachableSymbols RSScaner(ST, CB);
158
179k
159
179k
  llvm::ImmutableMapRef<EnvironmentEntry,SVal>
160
179k
    EBMapRef(NewEnv.ExprBindings.getRootWithoutRetain(),
161
179k
             F.getTreeFactory());
162
179k
163
179k
  // Iterate over the block-expr bindings.
164
179k
  for (Environment::iterator I = Env.begin(), E = Env.end();
165
1.29M
       
I != E1.29M
;
++I1.11M
) {
166
1.11M
167
1.11M
    const EnvironmentEntry &BlkExpr = I.getKey();
168
1.11M
    const SVal &X = I.getData();
169
1.11M
170
1.11M
    if (
SymReaper.isLive(BlkExpr.getStmt(), BlkExpr.getLocationContext())1.11M
) {
171
497k
      // Copy the binding to the new map.
172
497k
      EBMapRef = EBMapRef.add(BlkExpr, X);
173
497k
174
497k
      // Mark all symbols in the block expr's value live.
175
497k
      RSScaner.scan(X);
176
497k
      continue;
177
0
    } else {
178
617k
      SymExpr::symbol_iterator SI = X.symbol_begin(), SE = X.symbol_end();
179
1.45M
      for (; 
SI != SE1.45M
;
++SI839k
)
180
839k
        SymReaper.maybeDead(*SI);
181
617k
    }
182
1.11M
  }
183
179k
184
179k
  NewEnv.ExprBindings = EBMapRef.asImmutableMap();
185
179k
  return NewEnv;
186
179k
}
187
188
void Environment::print(raw_ostream &Out, const char *NL,
189
1
                        const char *Sep) const {
190
1
  bool isFirst = true;
191
1
192
2
  for (Environment::iterator I = begin(), E = end(); 
I != E2
;
++I1
) {
193
1
    const EnvironmentEntry &En = I.getKey();
194
1
195
1
    if (
isFirst1
) {
196
1
      Out << NL << NL
197
1
          << "Expressions:"
198
1
          << NL;
199
1
      isFirst = false;
200
1
    } else {
201
0
      Out << NL;
202
0
    }
203
1
204
1
    const Stmt *S = En.getStmt();
205
1
    assert(S != nullptr && "Expected non-null Stmt");
206
1
207
1
    Out << " (" << (const void*) En.getLocationContext() << ','
208
1
      << (const void*) S << ") ";
209
1
    LangOptions LO; // FIXME.
210
1
    S->printPretty(Out, nullptr, PrintingPolicy(LO));
211
1
    Out << " : " << I.getData();
212
1
  }
213
1
}