Coverage Report

Created: 2019-07-24 05:18

/Users/buildslave/jenkins/workspace/clang-stage2-coverage-R/llvm/tools/clang/lib/StaticAnalyzer/Core/SVals.cpp
Line
Count
Source (jump to first uncovered line)
1
//===-- SVals.cpp - Abstract RValues for Path-Sens. Value Tracking --------===//
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 SVal, Loc, and NonLoc, classes that represent
10
//  abstract r-values for use with path-sensitive value tracking.
11
//
12
//===----------------------------------------------------------------------===//
13
14
#include "clang/StaticAnalyzer/Core/PathSensitive/SVals.h"
15
#include "clang/AST/Decl.h"
16
#include "clang/AST/DeclCXX.h"
17
#include "clang/AST/Expr.h"
18
#include "clang/AST/Type.h"
19
#include "clang/Basic/JsonSupport.h"
20
#include "clang/Basic/LLVM.h"
21
#include "clang/StaticAnalyzer/Core/PathSensitive/BasicValueFactory.h"
22
#include "clang/StaticAnalyzer/Core/PathSensitive/MemRegion.h"
23
#include "clang/StaticAnalyzer/Core/PathSensitive/SValBuilder.h"
24
#include "clang/StaticAnalyzer/Core/PathSensitive/SymExpr.h"
25
#include "clang/StaticAnalyzer/Core/PathSensitive/SymbolManager.h"
26
#include "llvm/ADT/Optional.h"
27
#include "llvm/Support/Casting.h"
28
#include "llvm/Support/Compiler.h"
29
#include "llvm/Support/ErrorHandling.h"
30
#include "llvm/Support/raw_ostream.h"
31
#include <cassert>
32
33
using namespace clang;
34
using namespace ento;
35
36
//===----------------------------------------------------------------------===//
37
// Symbol iteration within an SVal.
38
//===----------------------------------------------------------------------===//
39
40
//===----------------------------------------------------------------------===//
41
// Utility methods.
42
//===----------------------------------------------------------------------===//
43
44
0
bool SVal::hasConjuredSymbol() const {
45
0
  if (Optional<nonloc::SymbolVal> SV = getAs<nonloc::SymbolVal>()) {
46
0
    SymbolRef sym = SV->getSymbol();
47
0
    if (isa<SymbolConjured>(sym))
48
0
      return true;
49
0
  }
50
0
51
0
  if (Optional<loc::MemRegionVal> RV = getAs<loc::MemRegionVal>()) {
52
0
    const MemRegion *R = RV->getRegion();
53
0
    if (const auto *SR = dyn_cast<SymbolicRegion>(R)) {
54
0
      SymbolRef sym = SR->getSymbol();
55
0
      if (isa<SymbolConjured>(sym))
56
0
        return true;
57
0
    }
58
0
  }
59
0
60
0
  return false;
61
0
}
62
63
70.3k
const FunctionDecl *SVal::getAsFunctionDecl() const {
64
70.3k
  if (Optional<loc::MemRegionVal> X = getAs<loc::MemRegionVal>()) {
65
70.0k
    const MemRegion* R = X->getRegion();
66
70.0k
    if (const FunctionCodeRegion *CTR = R->getAs<FunctionCodeRegion>())
67
69.7k
      if (const auto *FD = dyn_cast<FunctionDecl>(CTR->getDecl()))
68
69.7k
        return FD;
69
574
  }
70
574
71
574
  if (auto X = getAs<nonloc::PointerToMember>()) {
72
155
    if (const auto *MD = dyn_cast_or_null<CXXMethodDecl>(X->getDecl()))
73
155
      return MD;
74
419
  }
75
419
  return nullptr;
76
419
}
77
78
/// If this SVal is a location (subclasses Loc) and wraps a symbol,
79
/// return that SymbolRef.  Otherwise return 0.
80
///
81
/// Implicit casts (ex: void* -> char*) can turn Symbolic region into Element
82
/// region. If that is the case, gets the underlining region.
83
/// When IncludeBaseRegions is set to true and the SubRegion is non-symbolic,
84
/// the first symbolic parent region is returned.
85
2.59M
SymbolRef SVal::getAsLocSymbol(bool IncludeBaseRegions) const {
86
2.59M
  // FIXME: should we consider SymbolRef wrapped in CodeTextRegion?
87
2.59M
  if (Optional<nonloc::LocAsInteger> X = getAs<nonloc::LocAsInteger>())
88
283
    return X->getLoc().getAsLocSymbol(IncludeBaseRegions);
89
2.59M
90
2.59M
  if (Optional<loc::MemRegionVal> X = getAs<loc::MemRegionVal>()) {
91
1.14M
    const MemRegion *R = X->getRegion();
92
1.14M
    if (const SymbolicRegion *SymR = IncludeBaseRegions ?
93
286k
                                      R->getSymbolicBase() :
94
286k
                                      dyn_cast<SymbolicRegion>(R->StripCasts()))
95
286k
      return SymR->getSymbol();
96
2.30M
  }
97
2.30M
  return nullptr;
98
2.30M
}
99
100
/// Get the symbol in the SVal or its base region.
101
85.4k
SymbolRef SVal::getLocSymbolInBase() const {
102
85.4k
  Optional<loc::MemRegionVal> X = getAs<loc::MemRegionVal>();
103
85.4k
104
85.4k
  if (!X)
105
4
    return nullptr;
106
85.4k
107
85.4k
  const MemRegion *R = X->getRegion();
108
85.4k
109
201k
  while (const auto *SR = dyn_cast<SubRegion>(R)) {
110
129k
    if (const auto *SymR = dyn_cast<SymbolicRegion>(SR))
111
13.6k
      return SymR->getSymbol();
112
115k
    else
113
115k
      R = SR->getSuperRegion();
114
129k
  }
115
85.4k
116
85.4k
  
return nullptr71.8k
;
117
85.4k
}
118
119
// TODO: The next 3 functions have to be simplified.
120
121
/// If this SVal wraps a symbol return that SymbolRef.
122
/// Otherwise, return 0.
123
///
124
/// Casts are ignored during lookup.
125
/// \param IncludeBaseRegions The boolean that controls whether the search
126
/// should continue to the base regions if the region is not symbolic.
127
3.90M
SymbolRef SVal::getAsSymbol(bool IncludeBaseRegions) const {
128
3.90M
  // FIXME: should we consider SymbolRef wrapped in CodeTextRegion?
129
3.90M
  if (Optional<nonloc::SymbolVal> X = getAs<nonloc::SymbolVal>())
130
1.35M
    return X->getSymbol();
131
2.55M
132
2.55M
  return getAsLocSymbol(IncludeBaseRegions);
133
2.55M
}
134
135
/// getAsSymbolicExpression - If this Sval wraps a symbolic expression then
136
///  return that expression.  Otherwise return NULL.
137
517k
const SymExpr *SVal::getAsSymbolicExpression() const {
138
517k
  if (Optional<nonloc::SymbolVal> X = getAs<nonloc::SymbolVal>())
139
100k
    return X->getSymbol();
140
416k
141
416k
  return getAsSymbol();
142
416k
}
143
144
34.3k
const SymExpr* SVal::getAsSymExpr() const {
145
34.3k
  const SymExpr* Sym = getAsSymbol();
146
34.3k
  if (!Sym)
147
2.35k
    Sym = getAsSymbolicExpression();
148
34.3k
  return Sym;
149
34.3k
}
150
151
3.04M
const MemRegion *SVal::getAsRegion() const {
152
3.04M
  if (Optional<loc::MemRegionVal> X = getAs<loc::MemRegionVal>())
153
1.73M
    return X->getRegion();
154
1.31M
155
1.31M
  if (Optional<nonloc::LocAsInteger> X = getAs<nonloc::LocAsInteger>())
156
170
    return X->getLoc().getAsRegion();
157
1.31M
158
1.31M
  return nullptr;
159
1.31M
}
160
161
516
const MemRegion *loc::MemRegionVal::stripCasts(bool StripBaseCasts) const {
162
516
  const MemRegion *R = getRegion();
163
516
  return R ?  R->StripCasts(StripBaseCasts) : 
nullptr0
;
164
516
}
165
166
55.0k
const void *nonloc::LazyCompoundVal::getStore() const {
167
55.0k
  return static_cast<const LazyCompoundValData*>(Data)->getStore();
168
55.0k
}
169
170
62.2k
const TypedValueRegion *nonloc::LazyCompoundVal::getRegion() const {
171
62.2k
  return static_cast<const LazyCompoundValData*>(Data)->getRegion();
172
62.2k
}
173
174
44
bool nonloc::PointerToMember::isNullMemberPointer() const {
175
44
  return getPTMData().isNull();
176
44
}
177
178
176
const DeclaratorDecl *nonloc::PointerToMember::getDecl() const {
179
176
  const auto PTMD = this->getPTMData();
180
176
  if (PTMD.isNull())
181
0
    return nullptr;
182
176
183
176
  const DeclaratorDecl *DD = nullptr;
184
176
  if (PTMD.is<const DeclaratorDecl *>())
185
139
    DD = PTMD.get<const DeclaratorDecl *>();
186
37
  else
187
37
    DD = PTMD.get<const PointerToMemberData *>()->getDeclaratorDecl();
188
176
189
176
  return DD;
190
176
}
191
192
//===----------------------------------------------------------------------===//
193
// Other Iterators.
194
//===----------------------------------------------------------------------===//
195
196
3.19k
nonloc::CompoundVal::iterator nonloc::CompoundVal::begin() const {
197
3.19k
  return getValue()->begin();
198
3.19k
}
199
200
3.19k
nonloc::CompoundVal::iterator nonloc::CompoundVal::end() const {
201
3.19k
  return getValue()->end();
202
3.19k
}
203
204
9
nonloc::PointerToMember::iterator nonloc::PointerToMember::begin() const {
205
9
  const PTMDataType PTMD = getPTMData();
206
9
  if (PTMD.is<const DeclaratorDecl *>())
207
2
    return {};
208
7
  return PTMD.get<const PointerToMemberData *>()->begin();
209
7
}
210
211
9
nonloc::PointerToMember::iterator nonloc::PointerToMember::end() const {
212
9
  const PTMDataType PTMD = getPTMData();
213
9
  if (PTMD.is<const DeclaratorDecl *>())
214
2
    return {};
215
7
  return PTMD.get<const PointerToMemberData *>()->end();
216
7
}
217
218
//===----------------------------------------------------------------------===//
219
// Useful predicates.
220
//===----------------------------------------------------------------------===//
221
222
651k
bool SVal::isConstant() const {
223
651k
  return getAs<nonloc::ConcreteInt>() || 
getAs<loc::ConcreteInt>()630k
;
224
651k
}
225
226
197k
bool SVal::isConstant(int I) const {
227
197k
  if (Optional<loc::ConcreteInt> LV = getAs<loc::ConcreteInt>())
228
7.12k
    return LV->getValue() == I;
229
190k
  if (Optional<nonloc::ConcreteInt> NV = getAs<nonloc::ConcreteInt>())
230
68.2k
    return NV->getValue() == I;
231
121k
  return false;
232
121k
}
233
234
197k
bool SVal::isZeroConstant() const {
235
197k
  return isConstant(0);
236
197k
}
237
238
//===----------------------------------------------------------------------===//
239
// Transfer function dispatch for Non-Locs.
240
//===----------------------------------------------------------------------===//
241
242
SVal nonloc::ConcreteInt::evalBinOp(SValBuilder &svalBuilder,
243
                                    BinaryOperator::Opcode Op,
244
0
                                    const nonloc::ConcreteInt& R) const {
245
0
  const llvm::APSInt* X =
246
0
    svalBuilder.getBasicValueFactory().evalAPSInt(Op, getValue(), R.getValue());
247
0
248
0
  if (X)
249
0
    return nonloc::ConcreteInt(*X);
250
0
  else
251
0
    return UndefinedVal();
252
0
}
253
254
nonloc::ConcreteInt
255
921
nonloc::ConcreteInt::evalComplement(SValBuilder &svalBuilder) const {
256
921
  return svalBuilder.makeIntVal(~getValue());
257
921
}
258
259
nonloc::ConcreteInt
260
990
nonloc::ConcreteInt::evalMinus(SValBuilder &svalBuilder) const {
261
990
  return svalBuilder.makeIntVal(-getValue());
262
990
}
263
264
//===----------------------------------------------------------------------===//
265
// Transfer function dispatch for Locs.
266
//===----------------------------------------------------------------------===//
267
268
SVal loc::ConcreteInt::evalBinOp(BasicValueFactory& BasicVals,
269
                                 BinaryOperator::Opcode Op,
270
18
                                 const loc::ConcreteInt& R) const {
271
18
  assert(BinaryOperator::isComparisonOp(Op) || Op == BO_Sub);
272
18
273
18
  const llvm::APSInt *X = BasicVals.evalAPSInt(Op, getValue(), R.getValue());
274
18
275
18
  if (X)
276
18
    return nonloc::ConcreteInt(*X);
277
0
  else
278
0
    return UndefinedVal();
279
18
}
280
281
//===----------------------------------------------------------------------===//
282
// Pretty-Printing.
283
//===----------------------------------------------------------------------===//
284
285
0
LLVM_DUMP_METHOD void SVal::dump() const { dumpToStream(llvm::errs()); }
286
287
14
void SVal::printJson(raw_ostream &Out, bool AddQuotes) const {
288
14
  std::string Buf;
289
14
  llvm::raw_string_ostream TempOut(Buf);
290
14
291
14
  dumpToStream(TempOut);
292
14
293
14
  Out << JsonFormat(TempOut.str(), AddQuotes);
294
14
}
295
296
17
void SVal::dumpToStream(raw_ostream &os) const {
297
17
  switch (getBaseKind()) {
298
17
    case UnknownValKind:
299
2
      os << "Unknown";
300
2
      break;
301
17
    case NonLocKind:
302
11
      castAs<NonLoc>().dumpToStream(os);
303
11
      break;
304
17
    case LocKind:
305
4
      castAs<Loc>().dumpToStream(os);
306
4
      break;
307
17
    case UndefinedValKind:
308
0
      os << "Undefined";
309
0
      break;
310
17
  }
311
17
}
312
313
11
void NonLoc::dumpToStream(raw_ostream &os) const {
314
11
  switch (getSubKind()) {
315
11
    case nonloc::ConcreteIntKind: {
316
6
      const auto &Value = castAs<nonloc::ConcreteInt>().getValue();
317
6
      os << Value << ' ' << (Value.isSigned() ? 
'S'5
:
'U'1
)
318
6
         << Value.getBitWidth() << 'b';
319
6
      break;
320
11
    }
321
11
    case nonloc::SymbolValKind:
322
5
      os << castAs<nonloc::SymbolVal>().getSymbol();
323
5
      break;
324
11
325
11
    case nonloc::LocAsIntegerKind: {
326
0
      const nonloc::LocAsInteger& C = castAs<nonloc::LocAsInteger>();
327
0
      os << C.getLoc() << " [as " << C.getNumBits() << " bit integer]";
328
0
      break;
329
11
    }
330
11
    case nonloc::CompoundValKind: {
331
0
      const nonloc::CompoundVal& C = castAs<nonloc::CompoundVal>();
332
0
      os << "compoundVal{";
333
0
      bool first = true;
334
0
      for (const auto &I : C) {
335
0
        if (first) {
336
0
          os << ' '; first = false;
337
0
        }
338
0
        else
339
0
          os << ", ";
340
0
341
0
        I.dumpToStream(os);
342
0
      }
343
0
      os << "}";
344
0
      break;
345
11
    }
346
11
    case nonloc::LazyCompoundValKind: {
347
0
      const nonloc::LazyCompoundVal &C = castAs<nonloc::LazyCompoundVal>();
348
0
      os << "lazyCompoundVal{" << const_cast<void *>(C.getStore())
349
0
         << ',' << C.getRegion()
350
0
         << '}';
351
0
      break;
352
11
    }
353
11
    case nonloc::PointerToMemberKind: {
354
0
      os << "pointerToMember{";
355
0
      const nonloc::PointerToMember &CastRes =
356
0
          castAs<nonloc::PointerToMember>();
357
0
      if (CastRes.getDecl())
358
0
        os << "|" << CastRes.getDecl()->getQualifiedNameAsString() << "|";
359
0
      bool first = true;
360
0
      for (const auto &I : CastRes) {
361
0
        if (first) {
362
0
          os << ' '; first = false;
363
0
        }
364
0
        else
365
0
          os << ", ";
366
0
367
0
        os << (*I).getType().getAsString();
368
0
      }
369
0
370
0
      os << '}';
371
0
      break;
372
11
    }
373
11
    default:
374
0
      assert(false && "Pretty-printed not implemented for this NonLoc.");
375
0
      break;
376
11
  }
377
11
}
378
379
4
void Loc::dumpToStream(raw_ostream &os) const {
380
4
  switch (getSubKind()) {
381
4
    case loc::ConcreteIntKind:
382
0
      os << castAs<loc::ConcreteInt>().getValue().getZExtValue() << " (Loc)";
383
0
      break;
384
4
    case loc::GotoLabelKind:
385
0
      os << "&&" << castAs<loc::GotoLabel>().getLabel()->getName();
386
0
      break;
387
4
    case loc::MemRegionValKind:
388
4
      os << '&' << castAs<loc::MemRegionVal>().getRegion()->getString();
389
4
      break;
390
4
    default:
391
0
      llvm_unreachable("Pretty-printing not implemented for this Loc.");
392
4
  }
393
4
}