Coverage Report

Created: 2020-02-15 09:57

/Users/buildslave/jenkins/workspace/coverage/llvm-project/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
96.6k
const FunctionDecl *SVal::getAsFunctionDecl() const {
64
96.6k
  if (Optional<loc::MemRegionVal> X = getAs<loc::MemRegionVal>()) {
65
96.2k
    const MemRegion* R = X->getRegion();
66
96.2k
    if (const FunctionCodeRegion *CTR = R->getAs<FunctionCodeRegion>())
67
95.8k
      if (const auto *FD = dyn_cast<FunctionDecl>(CTR->getDecl()))
68
95.8k
        return FD;
69
837
  }
70
837
71
837
  if (auto X = getAs<nonloc::PointerToMember>()) {
72
369
    if (const auto *MD = dyn_cast_or_null<CXXMethodDecl>(X->getDecl()))
73
369
      return MD;
74
468
  }
75
468
  return nullptr;
76
468
}
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
3.51M
SymbolRef SVal::getAsLocSymbol(bool IncludeBaseRegions) const {
86
3.51M
  // FIXME: should we consider SymbolRef wrapped in CodeTextRegion?
87
3.51M
  if (Optional<nonloc::LocAsInteger> X = getAs<nonloc::LocAsInteger>())
88
340
    return X->getLoc().getAsLocSymbol(IncludeBaseRegions);
89
3.51M
90
3.51M
  if (Optional<loc::MemRegionVal> X = getAs<loc::MemRegionVal>()) {
91
1.95M
    const MemRegion *R = X->getRegion();
92
1.95M
    if (const SymbolicRegion *SymR = IncludeBaseRegions ?
93
349k
                                      R->getSymbolicBase() :
94
349k
                                      dyn_cast<SymbolicRegion>(R->StripCasts()))
95
349k
      return SymR->getSymbol();
96
3.16M
  }
97
3.16M
  return nullptr;
98
3.16M
}
99
100
/// Get the symbol in the SVal or its base region.
101
86.2k
SymbolRef SVal::getLocSymbolInBase() const {
102
86.2k
  Optional<loc::MemRegionVal> X = getAs<loc::MemRegionVal>();
103
86.2k
104
86.2k
  if (!X)
105
4
    return nullptr;
106
86.1k
107
86.1k
  const MemRegion *R = X->getRegion();
108
86.1k
109
202k
  while (const auto *SR = dyn_cast<SubRegion>(R)) {
110
130k
    if (const auto *SymR = dyn_cast<SymbolicRegion>(SR))
111
13.9k
      return SymR->getSymbol();
112
116k
    else
113
116k
      R = SR->getSuperRegion();
114
130k
  }
115
86.1k
116
86.1k
  
return nullptr72.2k
;
117
86.1k
}
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
5.39M
SymbolRef SVal::getAsSymbol(bool IncludeBaseRegions) const {
128
5.39M
  // FIXME: should we consider SymbolRef wrapped in CodeTextRegion?
129
5.39M
  if (Optional<nonloc::SymbolVal> X = getAs<nonloc::SymbolVal>())
130
1.92M
    return X->getSymbol();
131
3.47M
132
3.47M
  return getAsLocSymbol(IncludeBaseRegions);
133
3.47M
}
134
135
/// getAsSymbolicExpression - If this Sval wraps a symbolic expression then
136
///  return that expression.  Otherwise return NULL.
137
547k
const SymExpr *SVal::getAsSymbolicExpression() const {
138
547k
  if (Optional<nonloc::SymbolVal> X = getAs<nonloc::SymbolVal>())
139
120k
    return X->getSymbol();
140
427k
141
427k
  return getAsSymbol();
142
427k
}
143
144
35.6k
const SymExpr* SVal::getAsSymExpr() const {
145
35.6k
  const SymExpr* Sym = getAsSymbol();
146
35.6k
  if (!Sym)
147
2.39k
    Sym = getAsSymbolicExpression();
148
35.6k
  return Sym;
149
35.6k
}
150
151
4.58M
const MemRegion *SVal::getAsRegion() const {
152
4.58M
  if (Optional<loc::MemRegionVal> X = getAs<loc::MemRegionVal>())
153
2.75M
    return X->getRegion();
154
1.83M
155
1.83M
  if (Optional<nonloc::LocAsInteger> X = getAs<nonloc::LocAsInteger>())
156
194
    return X->getLoc().getAsRegion();
157
1.83M
158
1.83M
  return nullptr;
159
1.83M
}
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
142k
const void *nonloc::LazyCompoundVal::getStore() const {
167
142k
  return static_cast<const LazyCompoundValData*>(Data)->getStore();
168
142k
}
169
170
157k
const TypedValueRegion *nonloc::LazyCompoundVal::getRegion() const {
171
157k
  return static_cast<const LazyCompoundValData*>(Data)->getRegion();
172
157k
}
173
174
71
bool nonloc::PointerToMember::isNullMemberPointer() const {
175
71
  return getPTMData().isNull();
176
71
}
177
178
397
const DeclaratorDecl *nonloc::PointerToMember::getDecl() const {
179
397
  const auto PTMD = this->getPTMData();
180
397
  if (PTMD.isNull())
181
0
    return nullptr;
182
397
183
397
  const DeclaratorDecl *DD = nullptr;
184
397
  if (PTMD.is<const DeclaratorDecl *>())
185
360
    DD = PTMD.get<const DeclaratorDecl *>();
186
37
  else
187
37
    DD = PTMD.get<const PointerToMemberData *>()->getDeclaratorDecl();
188
397
189
397
  return DD;
190
397
}
191
192
//===----------------------------------------------------------------------===//
193
// Other Iterators.
194
//===----------------------------------------------------------------------===//
195
196
3.24k
nonloc::CompoundVal::iterator nonloc::CompoundVal::begin() const {
197
3.24k
  return getValue()->begin();
198
3.24k
}
199
200
3.24k
nonloc::CompoundVal::iterator nonloc::CompoundVal::end() const {
201
3.24k
  return getValue()->end();
202
3.24k
}
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
877k
bool SVal::isConstant() const {
223
877k
  return getAs<nonloc::ConcreteInt>() || 
getAs<loc::ConcreteInt>()851k
;
224
877k
}
225
226
245k
bool SVal::isConstant(int I) const {
227
245k
  if (Optional<loc::ConcreteInt> LV = getAs<loc::ConcreteInt>())
228
7.37k
    return LV->getValue() == I;
229
238k
  if (Optional<nonloc::ConcreteInt> NV = getAs<nonloc::ConcreteInt>())
230
93.8k
    return NV->getValue() == I;
231
144k
  return false;
232
144k
}
233
234
245k
bool SVal::isZeroConstant() const {
235
245k
  return isConstant(0);
236
245k
}
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
1.08k
nonloc::ConcreteInt::evalMinus(SValBuilder &svalBuilder) const {
261
1.08k
  return svalBuilder.makeIntVal(-getValue());
262
1.08k
}
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
234
void SVal::printJson(raw_ostream &Out, bool AddQuotes) const {
288
234
  std::string Buf;
289
234
  llvm::raw_string_ostream TempOut(Buf);
290
234
291
234
  dumpToStream(TempOut);
292
234
293
234
  Out << JsonFormat(TempOut.str(), AddQuotes);
294
234
}
295
296
290
void SVal::dumpToStream(raw_ostream &os) const {
297
290
  switch (getBaseKind()) {
298
2
    case UnknownValKind:
299
2
      os << "Unknown";
300
2
      break;
301
103
    case NonLocKind:
302
103
      castAs<NonLoc>().dumpToStream(os);
303
103
      break;
304
185
    case LocKind:
305
185
      castAs<Loc>().dumpToStream(os);
306
185
      break;
307
0
    case UndefinedValKind:
308
0
      os << "Undefined";
309
0
      break;
310
290
  }
311
290
}
312
313
103
void NonLoc::dumpToStream(raw_ostream &os) const {
314
103
  switch (getSubKind()) {
315
57
    case nonloc::ConcreteIntKind: {
316
57
      const auto &Value = castAs<nonloc::ConcreteInt>().getValue();
317
57
      os << Value << ' ' << (Value.isSigned() ? 
'S'56
:
'U'1
)
318
57
         << Value.getBitWidth() << 'b';
319
57
      break;
320
0
    }
321
38
    case nonloc::SymbolValKind:
322
38
      os << castAs<nonloc::SymbolVal>().getSymbol();
323
38
      break;
324
0
325
0
    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
0
    }
330
0
    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
0
    }
346
8
    case nonloc::LazyCompoundValKind: {
347
8
      const nonloc::LazyCompoundVal &C = castAs<nonloc::LazyCompoundVal>();
348
8
      os << "lazyCompoundVal{" << const_cast<void *>(C.getStore())
349
8
         << ',' << C.getRegion()
350
8
         << '}';
351
8
      break;
352
0
    }
353
0
    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
0
    }
373
0
    default:
374
0
      assert(false && "Pretty-printed not implemented for this NonLoc.");
375
0
      break;
376
103
  }
377
103
}
378
379
185
void Loc::dumpToStream(raw_ostream &os) const {
380
185
  switch (getSubKind()) {
381
66
    case loc::ConcreteIntKind:
382
66
      os << castAs<loc::ConcreteInt>().getValue().getZExtValue() << " (Loc)";
383
66
      break;
384
0
    case loc::GotoLabelKind:
385
0
      os << "&&" << castAs<loc::GotoLabel>().getLabel()->getName();
386
0
      break;
387
119
    case loc::MemRegionValKind:
388
119
      os << '&' << castAs<loc::MemRegionVal>().getRegion()->getString();
389
119
      break;
390
0
    default:
391
0
      llvm_unreachable("Pretty-printing not implemented for this Loc.");
392
185
  }
393
185
}