Coverage Report

Created: 2021-01-19 06:58

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