Coverage Report

Created: 2020-09-22 08:39

/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
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
60
0
  return false;
61
0
}
62
63
109k
const FunctionDecl *SVal::getAsFunctionDecl() const {
64
109k
  if (Optional<loc::MemRegionVal> X = getAs<loc::MemRegionVal>()) {
65
109k
    const MemRegion* R = X->getRegion();
66
109k
    if (const FunctionCodeRegion *CTR = R->getAs<FunctionCodeRegion>())
67
108k
      if (const auto *FD = dyn_cast<FunctionDecl>(CTR->getDecl()))
68
108k
        return FD;
69
1.24k
  }
70
71
1.24k
  if (auto X = getAs<nonloc::PointerToMember>()) {
72
405
    if (const auto *MD = dyn_cast_or_null<CXXMethodDecl>(X->getDecl()))
73
405
      return MD;
74
836
  }
75
836
  return nullptr;
76
836
}
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.36M
SymbolRef SVal::getAsLocSymbol(bool IncludeBaseRegions) const {
86
  // FIXME: should we consider SymbolRef wrapped in CodeTextRegion?
87
2.36M
  if (Optional<nonloc::LocAsInteger> X = getAs<nonloc::LocAsInteger>())
88
336
    return X->getLoc().getAsLocSymbol(IncludeBaseRegions);
89
90
2.36M
  if (Optional<loc::MemRegionVal> X = getAs<loc::MemRegionVal>()) {
91
1.27M
    const MemRegion *R = X->getRegion();
92
1.27M
    if (const SymbolicRegion *SymR = IncludeBaseRegions ?
93
357k
                                      R->getSymbolicBase() :
94
357k
                                      dyn_cast<SymbolicRegion>(R->StripCasts()))
95
357k
      return SymR->getSymbol();
96
2.01M
  }
97
2.01M
  return nullptr;
98
2.01M
}
99
100
/// Get the symbol in the SVal or its base region.
101
75.7k
SymbolRef SVal::getLocSymbolInBase() const {
102
75.7k
  Optional<loc::MemRegionVal> X = getAs<loc::MemRegionVal>();
103
104
75.7k
  if (!X)
105
4
    return nullptr;
106
107
75.7k
  const MemRegion *R = X->getRegion();
108
109
175k
  while (const auto *SR = dyn_cast<SubRegion>(R)) {
110
113k
    if (const auto *SymR = dyn_cast<SymbolicRegion>(SR))
111
13.6k
      return SymR->getSymbol();
112
99.7k
    else
113
99.7k
      R = SR->getSuperRegion();
114
113k
  }
115
116
62.1k
  return nullptr;
117
75.7k
}
118
119
/// If this SVal wraps a symbol return that SymbolRef.
120
/// Otherwise, return 0.
121
///
122
/// Casts are ignored during lookup.
123
/// \param IncludeBaseRegions The boolean that controls whether the search
124
/// should continue to the base regions if the region is not symbolic.
125
3.82M
SymbolRef SVal::getAsSymbol(bool IncludeBaseRegions) const {
126
  // FIXME: should we consider SymbolRef wrapped in CodeTextRegion?
127
3.82M
  if (Optional<nonloc::SymbolVal> X = getAs<nonloc::SymbolVal>())
128
1.49M
    return X->getSymbol();
129
130
2.32M
  return getAsLocSymbol(IncludeBaseRegions);
131
2.32M
}
132
133
3.34M
const MemRegion *SVal::getAsRegion() const {
134
3.34M
  if (Optional<loc::MemRegionVal> X = getAs<loc::MemRegionVal>())
135
1.95M
    return X->getRegion();
136
137
1.39M
  if (Optional<nonloc::LocAsInteger> X = getAs<nonloc::LocAsInteger>())
138
190
    return X->getLoc().getAsRegion();
139
140
1.39M
  return nullptr;
141
1.39M
}
142
143
517
const MemRegion *loc::MemRegionVal::stripCasts(bool StripBaseCasts) const {
144
517
  const MemRegion *R = getRegion();
145
517
  return R ?  R->StripCasts(StripBaseCasts) : 
nullptr0
;
146
517
}
147
148
69.6k
const void *nonloc::LazyCompoundVal::getStore() const {
149
69.6k
  return static_cast<const LazyCompoundValData*>(Data)->getStore();
150
69.6k
}
151
152
93.1k
const TypedValueRegion *nonloc::LazyCompoundVal::getRegion() const {
153
93.1k
  return static_cast<const LazyCompoundValData*>(Data)->getRegion();
154
93.1k
}
155
156
90
bool nonloc::PointerToMember::isNullMemberPointer() const {
157
90
  return getPTMData().isNull();
158
90
}
159
160
461
const NamedDecl *nonloc::PointerToMember::getDecl() const {
161
461
  const auto PTMD = this->getPTMData();
162
461
  if (PTMD.isNull())
163
0
    return nullptr;
164
165
461
  const NamedDecl *ND = nullptr;
166
461
  if (PTMD.is<const NamedDecl *>())
167
418
    ND = PTMD.get<const NamedDecl *>();
168
43
  else
169
43
    ND = PTMD.get<const PointerToMemberData *>()->getDeclaratorDecl();
170
171
461
  return ND;
172
461
}
173
174
//===----------------------------------------------------------------------===//
175
// Other Iterators.
176
//===----------------------------------------------------------------------===//
177
178
3.18k
nonloc::CompoundVal::iterator nonloc::CompoundVal::begin() const {
179
3.18k
  return getValue()->begin();
180
3.18k
}
181
182
3.17k
nonloc::CompoundVal::iterator nonloc::CompoundVal::end() const {
183
3.17k
  return getValue()->end();
184
3.17k
}
185
186
14
nonloc::PointerToMember::iterator nonloc::PointerToMember::begin() const {
187
14
  const PTMDataType PTMD = getPTMData();
188
14
  if (PTMD.is<const NamedDecl *>())
189
7
    return {};
190
7
  return PTMD.get<const PointerToMemberData *>()->begin();
191
7
}
192
193
14
nonloc::PointerToMember::iterator nonloc::PointerToMember::end() const {
194
14
  const PTMDataType PTMD = getPTMData();
195
14
  if (PTMD.is<const NamedDecl *>())
196
7
    return {};
197
7
  return PTMD.get<const PointerToMemberData *>()->end();
198
7
}
199
200
//===----------------------------------------------------------------------===//
201
// Useful predicates.
202
//===----------------------------------------------------------------------===//
203
204
721k
bool SVal::isConstant() const {
205
721k
  return getAs<nonloc::ConcreteInt>() || 
getAs<loc::ConcreteInt>()694k
;
206
721k
}
207
208
223k
bool SVal::isConstant(int I) const {
209
223k
  if (Optional<loc::ConcreteInt> LV = getAs<loc::ConcreteInt>())
210
7.67k
    return LV->getValue() == I;
211
215k
  if (Optional<nonloc::ConcreteInt> NV = getAs<nonloc::ConcreteInt>())
212
73.1k
    return NV->getValue() == I;
213
142k
  return false;
214
142k
}
215
216
223k
bool SVal::isZeroConstant() const {
217
223k
  return isConstant(0);
218
223k
}
219
220
//===----------------------------------------------------------------------===//
221
// Transfer function dispatch for Non-Locs.
222
//===----------------------------------------------------------------------===//
223
224
SVal nonloc::ConcreteInt::evalBinOp(SValBuilder &svalBuilder,
225
                                    BinaryOperator::Opcode Op,
226
0
                                    const nonloc::ConcreteInt& R) const {
227
0
  const llvm::APSInt* X =
228
0
    svalBuilder.getBasicValueFactory().evalAPSInt(Op, getValue(), R.getValue());
229
230
0
  if (X)
231
0
    return nonloc::ConcreteInt(*X);
232
0
  else
233
0
    return UndefinedVal();
234
0
}
235
236
nonloc::ConcreteInt
237
992
nonloc::ConcreteInt::evalComplement(SValBuilder &svalBuilder) const {
238
992
  return svalBuilder.makeIntVal(~getValue());
239
992
}
240
241
nonloc::ConcreteInt
242
1.52k
nonloc::ConcreteInt::evalMinus(SValBuilder &svalBuilder) const {
243
1.52k
  return svalBuilder.makeIntVal(-getValue());
244
1.52k
}
245
246
//===----------------------------------------------------------------------===//
247
// Transfer function dispatch for Locs.
248
//===----------------------------------------------------------------------===//
249
250
SVal loc::ConcreteInt::evalBinOp(BasicValueFactory& BasicVals,
251
                                 BinaryOperator::Opcode Op,
252
18
                                 const loc::ConcreteInt& R) const {
253
18
  assert(BinaryOperator::isComparisonOp(Op) || Op == BO_Sub);
254
255
18
  const llvm::APSInt *X = BasicVals.evalAPSInt(Op, getValue(), R.getValue());
256
257
18
  if (X)
258
18
    return nonloc::ConcreteInt(*X);
259
0
  else
260
0
    return UndefinedVal();
261
18
}
262
263
//===----------------------------------------------------------------------===//
264
// Pretty-Printing.
265
//===----------------------------------------------------------------------===//
266
267
0
LLVM_DUMP_METHOD void SVal::dump() const { dumpToStream(llvm::errs()); }
268
269
274
void SVal::printJson(raw_ostream &Out, bool AddQuotes) const {
270
274
  std::string Buf;
271
274
  llvm::raw_string_ostream TempOut(Buf);
272
273
274
  dumpToStream(TempOut);
274
275
274
  Out << JsonFormat(TempOut.str(), AddQuotes);
276
274
}
277
278
418
void SVal::dumpToStream(raw_ostream &os) const {
279
418
  switch (getBaseKind()) {
280
2
    case UnknownValKind:
281
2
      os << "Unknown";
282
2
      break;
283
156
    case NonLocKind:
284
156
      castAs<NonLoc>().dumpToStream(os);
285
156
      break;
286
260
    case LocKind:
287
260
      castAs<Loc>().dumpToStream(os);
288
260
      break;
289
0
    case UndefinedValKind:
290
0
      os << "Undefined";
291
0
      break;
292
418
  }
293
418
}
294
295
156
void NonLoc::dumpToStream(raw_ostream &os) const {
296
156
  switch (getSubKind()) {
297
101
    case nonloc::ConcreteIntKind: {
298
101
      const auto &Value = castAs<nonloc::ConcreteInt>().getValue();
299
100
      os << Value << ' ' << (Value.isSigned() ? 'S' : 
'U'1
)
300
101
         << Value.getBitWidth() << 'b';
301
101
      break;
302
0
    }
303
45
    case nonloc::SymbolValKind:
304
45
      os << castAs<nonloc::SymbolVal>().getSymbol();
305
45
      break;
306
307
0
    case nonloc::LocAsIntegerKind: {
308
0
      const nonloc::LocAsInteger& C = castAs<nonloc::LocAsInteger>();
309
0
      os << C.getLoc() << " [as " << C.getNumBits() << " bit integer]";
310
0
      break;
311
0
    }
312
0
    case nonloc::CompoundValKind: {
313
0
      const nonloc::CompoundVal& C = castAs<nonloc::CompoundVal>();
314
0
      os << "compoundVal{";
315
0
      bool first = true;
316
0
      for (const auto &I : C) {
317
0
        if (first) {
318
0
          os << ' '; first = false;
319
0
        }
320
0
        else
321
0
          os << ", ";
322
323
0
        I.dumpToStream(os);
324
0
      }
325
0
      os << "}";
326
0
      break;
327
0
    }
328
10
    case nonloc::LazyCompoundValKind: {
329
10
      const nonloc::LazyCompoundVal &C = castAs<nonloc::LazyCompoundVal>();
330
10
      os << "lazyCompoundVal{" << const_cast<void *>(C.getStore())
331
10
         << ',' << C.getRegion()
332
10
         << '}';
333
10
      break;
334
0
    }
335
0
    case nonloc::PointerToMemberKind: {
336
0
      os << "pointerToMember{";
337
0
      const nonloc::PointerToMember &CastRes =
338
0
          castAs<nonloc::PointerToMember>();
339
0
      if (CastRes.getDecl())
340
0
        os << "|" << CastRes.getDecl()->getQualifiedNameAsString() << "|";
341
0
      bool first = true;
342
0
      for (const auto &I : CastRes) {
343
0
        if (first) {
344
0
          os << ' '; first = false;
345
0
        }
346
0
        else
347
0
          os << ", ";
348
349
0
        os << (*I).getType().getAsString();
350
0
      }
351
352
0
      os << '}';
353
0
      break;
354
0
    }
355
0
    default:
356
0
      assert(false && "Pretty-printed not implemented for this NonLoc.");
357
0
      break;
358
156
  }
359
156
}
360
361
260
void Loc::dumpToStream(raw_ostream &os) const {
362
260
  switch (getSubKind()) {
363
66
    case loc::ConcreteIntKind:
364
66
      os << castAs<loc::ConcreteInt>().getValue().getZExtValue() << " (Loc)";
365
66
      break;
366
0
    case loc::GotoLabelKind:
367
0
      os << "&&" << castAs<loc::GotoLabel>().getLabel()->getName();
368
0
      break;
369
194
    case loc::MemRegionValKind:
370
194
      os << '&' << castAs<loc::MemRegionVal>().getRegion()->getString();
371
194
      break;
372
0
    default:
373
0
      llvm_unreachable("Pretty-printing not implemented for this Loc.");
374
260
  }
375
260
}