clang  9.0.0svn
SVals.cpp
Go to the documentation of this file.
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 
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/LLVM.h"
25 #include "llvm/ADT/Optional.h"
26 #include "llvm/Support/Casting.h"
27 #include "llvm/Support/Compiler.h"
28 #include "llvm/Support/ErrorHandling.h"
29 #include "llvm/Support/raw_ostream.h"
30 #include <cassert>
31 
32 using namespace clang;
33 using namespace ento;
34 
35 //===----------------------------------------------------------------------===//
36 // Symbol iteration within an SVal.
37 //===----------------------------------------------------------------------===//
38 
39 //===----------------------------------------------------------------------===//
40 // Utility methods.
41 //===----------------------------------------------------------------------===//
42 
44  if (Optional<nonloc::SymbolVal> SV = getAs<nonloc::SymbolVal>()) {
45  SymbolRef sym = SV->getSymbol();
46  if (isa<SymbolConjured>(sym))
47  return true;
48  }
49 
50  if (Optional<loc::MemRegionVal> RV = getAs<loc::MemRegionVal>()) {
51  const MemRegion *R = RV->getRegion();
52  if (const auto *SR = dyn_cast<SymbolicRegion>(R)) {
53  SymbolRef sym = SR->getSymbol();
54  if (isa<SymbolConjured>(sym))
55  return true;
56  }
57  }
58 
59  return false;
60 }
61 
63  if (Optional<loc::MemRegionVal> X = getAs<loc::MemRegionVal>()) {
64  const MemRegion* R = X->getRegion();
65  if (const FunctionCodeRegion *CTR = R->getAs<FunctionCodeRegion>())
66  if (const auto *FD = dyn_cast<FunctionDecl>(CTR->getDecl()))
67  return FD;
68  }
69 
70  if (auto X = getAs<nonloc::PointerToMember>()) {
71  if (const auto *MD = dyn_cast_or_null<CXXMethodDecl>(X->getDecl()))
72  return MD;
73  }
74  return nullptr;
75 }
76 
77 /// If this SVal is a location (subclasses Loc) and wraps a symbol,
78 /// return that SymbolRef. Otherwise return 0.
79 ///
80 /// Implicit casts (ex: void* -> char*) can turn Symbolic region into Element
81 /// region. If that is the case, gets the underlining region.
82 /// When IncludeBaseRegions is set to true and the SubRegion is non-symbolic,
83 /// the first symbolic parent region is returned.
84 SymbolRef SVal::getAsLocSymbol(bool IncludeBaseRegions) const {
85  // FIXME: should we consider SymbolRef wrapped in CodeTextRegion?
86  if (Optional<nonloc::LocAsInteger> X = getAs<nonloc::LocAsInteger>())
87  return X->getLoc().getAsLocSymbol(IncludeBaseRegions);
88 
89  if (Optional<loc::MemRegionVal> X = getAs<loc::MemRegionVal>()) {
90  const MemRegion *R = X->getRegion();
91  if (const SymbolicRegion *SymR = IncludeBaseRegions ?
92  R->getSymbolicBase() :
93  dyn_cast<SymbolicRegion>(R->StripCasts()))
94  return SymR->getSymbol();
95  }
96  return nullptr;
97 }
98 
99 /// Get the symbol in the SVal or its base region.
101  Optional<loc::MemRegionVal> X = getAs<loc::MemRegionVal>();
102 
103  if (!X)
104  return nullptr;
105 
106  const MemRegion *R = X->getRegion();
107 
108  while (const auto *SR = dyn_cast<SubRegion>(R)) {
109  if (const auto *SymR = dyn_cast<SymbolicRegion>(SR))
110  return SymR->getSymbol();
111  else
112  R = SR->getSuperRegion();
113  }
114 
115  return nullptr;
116 }
117 
118 // TODO: The next 3 functions have to be simplified.
119 
120 /// If this SVal wraps a symbol return that SymbolRef.
121 /// Otherwise, return 0.
122 ///
123 /// Casts are ignored during lookup.
124 /// \param IncludeBaseRegions The boolean that controls whether the search
125 /// should continue to the base regions if the region is not symbolic.
126 SymbolRef SVal::getAsSymbol(bool IncludeBaseRegions) const {
127  // FIXME: should we consider SymbolRef wrapped in CodeTextRegion?
128  if (Optional<nonloc::SymbolVal> X = getAs<nonloc::SymbolVal>())
129  return X->getSymbol();
130 
131  return getAsLocSymbol(IncludeBaseRegions);
132 }
133 
134 /// getAsSymbolicExpression - If this Sval wraps a symbolic expression then
135 /// return that expression. Otherwise return NULL.
137  if (Optional<nonloc::SymbolVal> X = getAs<nonloc::SymbolVal>())
138  return X->getSymbol();
139 
140  return getAsSymbol();
141 }
142 
143 const SymExpr* SVal::getAsSymExpr() const {
144  const SymExpr* Sym = getAsSymbol();
145  if (!Sym)
146  Sym = getAsSymbolicExpression();
147  return Sym;
148 }
149 
150 const MemRegion *SVal::getAsRegion() const {
151  if (Optional<loc::MemRegionVal> X = getAs<loc::MemRegionVal>())
152  return X->getRegion();
153 
154  if (Optional<nonloc::LocAsInteger> X = getAs<nonloc::LocAsInteger>())
155  return X->getLoc().getAsRegion();
156 
157  return nullptr;
158 }
159 
160 const MemRegion *loc::MemRegionVal::stripCasts(bool StripBaseCasts) const {
161  const MemRegion *R = getRegion();
162  return R ? R->StripCasts(StripBaseCasts) : nullptr;
163 }
164 
166  return static_cast<const LazyCompoundValData*>(Data)->getStore();
167 }
168 
170  return static_cast<const LazyCompoundValData*>(Data)->getRegion();
171 }
172 
174  return getPTMData().isNull();
175 }
176 
178  const auto PTMD = this->getPTMData();
179  if (PTMD.isNull())
180  return nullptr;
181 
182  const DeclaratorDecl *DD = nullptr;
183  if (PTMD.is<const DeclaratorDecl *>())
184  DD = PTMD.get<const DeclaratorDecl *>();
185  else
186  DD = PTMD.get<const PointerToMemberData *>()->getDeclaratorDecl();
187 
188  return DD;
189 }
190 
191 //===----------------------------------------------------------------------===//
192 // Other Iterators.
193 //===----------------------------------------------------------------------===//
194 
196  return getValue()->begin();
197 }
198 
200  return getValue()->end();
201 }
202 
204  const PTMDataType PTMD = getPTMData();
205  if (PTMD.is<const DeclaratorDecl *>())
206  return {};
207  return PTMD.get<const PointerToMemberData *>()->begin();
208 }
209 
211  const PTMDataType PTMD = getPTMData();
212  if (PTMD.is<const DeclaratorDecl *>())
213  return {};
214  return PTMD.get<const PointerToMemberData *>()->end();
215 }
216 
217 //===----------------------------------------------------------------------===//
218 // Useful predicates.
219 //===----------------------------------------------------------------------===//
220 
221 bool SVal::isConstant() const {
222  return getAs<nonloc::ConcreteInt>() || getAs<loc::ConcreteInt>();
223 }
224 
225 bool SVal::isConstant(int I) const {
226  if (Optional<loc::ConcreteInt> LV = getAs<loc::ConcreteInt>())
227  return LV->getValue() == I;
228  if (Optional<nonloc::ConcreteInt> NV = getAs<nonloc::ConcreteInt>())
229  return NV->getValue() == I;
230  return false;
231 }
232 
233 bool SVal::isZeroConstant() const {
234  return isConstant(0);
235 }
236 
237 //===----------------------------------------------------------------------===//
238 // Transfer function dispatch for Non-Locs.
239 //===----------------------------------------------------------------------===//
240 
243  const nonloc::ConcreteInt& R) const {
244  const llvm::APSInt* X =
245  svalBuilder.getBasicValueFactory().evalAPSInt(Op, getValue(), R.getValue());
246 
247  if (X)
248  return nonloc::ConcreteInt(*X);
249  else
250  return UndefinedVal();
251 }
252 
255  return svalBuilder.makeIntVal(~getValue());
256 }
257 
260  return svalBuilder.makeIntVal(-getValue());
261 }
262 
263 //===----------------------------------------------------------------------===//
264 // Transfer function dispatch for Locs.
265 //===----------------------------------------------------------------------===//
266 
269  const loc::ConcreteInt& R) const {
270  assert(BinaryOperator::isComparisonOp(Op) || Op == BO_Sub);
271 
272  const llvm::APSInt *X = BasicVals.evalAPSInt(Op, getValue(), R.getValue());
273 
274  if (X)
275  return nonloc::ConcreteInt(*X);
276  else
277  return UndefinedVal();
278 }
279 
280 //===----------------------------------------------------------------------===//
281 // Pretty-Printing.
282 //===----------------------------------------------------------------------===//
283 
284 LLVM_DUMP_METHOD void SVal::dump() const { dumpToStream(llvm::errs()); }
285 
286 void SVal::dumpToStream(raw_ostream &os) const {
287  switch (getBaseKind()) {
288  case UnknownValKind:
289  os << "Unknown";
290  break;
291  case NonLocKind:
292  castAs<NonLoc>().dumpToStream(os);
293  break;
294  case LocKind:
295  castAs<Loc>().dumpToStream(os);
296  break;
297  case UndefinedValKind:
298  os << "Undefined";
299  break;
300  }
301 }
302 
303 void NonLoc::dumpToStream(raw_ostream &os) const {
304  switch (getSubKind()) {
305  case nonloc::ConcreteIntKind: {
306  const auto &Value = castAs<nonloc::ConcreteInt>().getValue();
307  os << Value << ' ' << (Value.isSigned() ? 'S' : 'U')
308  << Value.getBitWidth() << 'b';
309  break;
310  }
311  case nonloc::SymbolValKind:
312  os << castAs<nonloc::SymbolVal>().getSymbol();
313  break;
314 
315  case nonloc::LocAsIntegerKind: {
316  const nonloc::LocAsInteger& C = castAs<nonloc::LocAsInteger>();
317  os << C.getLoc() << " [as " << C.getNumBits() << " bit integer]";
318  break;
319  }
320  case nonloc::CompoundValKind: {
321  const nonloc::CompoundVal& C = castAs<nonloc::CompoundVal>();
322  os << "compoundVal{";
323  bool first = true;
324  for (const auto &I : C) {
325  if (first) {
326  os << ' '; first = false;
327  }
328  else
329  os << ", ";
330 
331  I.dumpToStream(os);
332  }
333  os << "}";
334  break;
335  }
336  case nonloc::LazyCompoundValKind: {
337  const nonloc::LazyCompoundVal &C = castAs<nonloc::LazyCompoundVal>();
338  os << "lazyCompoundVal{" << const_cast<void *>(C.getStore())
339  << ',' << C.getRegion()
340  << '}';
341  break;
342  }
343  case nonloc::PointerToMemberKind: {
344  os << "pointerToMember{";
345  const nonloc::PointerToMember &CastRes =
346  castAs<nonloc::PointerToMember>();
347  if (CastRes.getDecl())
348  os << "|" << CastRes.getDecl()->getQualifiedNameAsString() << "|";
349  bool first = true;
350  for (const auto &I : CastRes) {
351  if (first) {
352  os << ' '; first = false;
353  }
354  else
355  os << ", ";
356 
357  os << (*I).getType().getAsString();
358  }
359 
360  os << '}';
361  break;
362  }
363  default:
364  assert(false && "Pretty-printed not implemented for this NonLoc.");
365  break;
366  }
367 }
368 
369 void Loc::dumpToStream(raw_ostream &os) const {
370  switch (getSubKind()) {
371  case loc::ConcreteIntKind:
372  os << castAs<loc::ConcreteInt>().getValue().getZExtValue() << " (Loc)";
373  break;
374  case loc::GotoLabelKind:
375  os << "&&" << castAs<loc::GotoLabel>().getLabel()->getName();
376  break;
377  case loc::MemRegionValKind:
378  os << '&' << castAs<loc::MemRegionVal>().getRegion()->getString();
379  break;
380  default:
381  llvm_unreachable("Pretty-printing not implemented for this Loc.");
382  }
383 }
Represents a function declaration or definition.
Definition: Decl.h:1743
TypedValueRegion - An abstract class representing regions having a typed value.
Definition: MemRegion.h:529
nonloc::ConcreteInt makeIntVal(const IntegerLiteral *integer)
Definition: SValBuilder.h:278
MemRegion - The root abstract class for all memory regions.
Definition: MemRegion.h:94
SymbolRef getLocSymbolInBase() const
Get the symbol in the SVal or its base region.
Definition: SVals.cpp:100
C Language Family Type Representation.
llvm::ImmutableList< const CXXBaseSpecifier * >::iterator iterator
Definition: SVals.h:541
Value representing integer constant.
Definition: SVals.h:376
const DeclaratorDecl * getDecl() const
Definition: SVals.cpp:177
SymbolRef getAsLocSymbol(bool IncludeBaseRegions=false) const
If this SVal is a location and wraps a symbol, return that SymbolRef.
Definition: SVals.cpp:84
Symbolic value.
Definition: SymExpr.h:29
const SymbolicRegion * getSymbolicBase() const
If this is a symbolic region, returns the region.
Definition: MemRegion.cpp:1219
void dumpToStream(raw_ostream &OS) const
Definition: SVals.cpp:286
ConcreteInt evalComplement(SValBuilder &svalBuilder) const
Definition: SVals.cpp:254
Value representing pointer-to-member.
Definition: SVals.h:521
llvm::ImmutableList< SVal >::iterator iterator
Definition: SVals.h:464
unsigned getNumBits() const
Definition: SVals.h:433
void dump() const
Definition: SVals.cpp:284
const SymExpr * getAsSymbolicExpression() const
getAsSymbolicExpression - If this Sval wraps a symbolic expression then return that expression...
Definition: SVals.cpp:136
BinaryOperatorKind
Forward-declares and imports various common LLVM datatypes that clang wants to use unqualified...
void dumpToStream(raw_ostream &Out) const
Definition: SVals.cpp:303
bool isConstant() const
Definition: SVals.cpp:221
const void * Data
Definition: SVals.h:86
void dumpToStream(raw_ostream &Out) const
Definition: SVals.cpp:369
SymbolRef getAsSymbol(bool IncludeBaseRegions=false) const
If this SVal wraps a symbol return that SymbolRef.
Definition: SVals.cpp:126
bool hasConjuredSymbol() const
hasConjuredSymbol - If this SVal wraps a conjured symbol, return true;
Definition: SVals.cpp:43
Represents a ValueDecl that came out of a declarator.
Definition: Decl.h:688
unsigned getSubKind() const
Definition: SVals.h:119
const RegionTy * getAs() const
Definition: MemRegion.h:1227
SymbolicRegion - A special, "non-concrete" region.
Definition: MemRegion.h:763
const MemRegion * stripCasts(bool StripBaseCasts=true) const
Get the underlining region and strip casts.
Definition: SVals.cpp:160
static SVal getValue(SVal val, SValBuilder &svalBuilder)
bool isComparisonOp() const
Definition: Expr.h:3409
FunctionCodeRegion - A region that represents code texts of function.
Definition: MemRegion.h:580
const MemRegion * getAsRegion() const
Definition: SVals.cpp:150
SVal - This represents a symbolic expression, which can be either an L-value or an R-value...
Definition: SVals.h:75
const llvm::APSInt * evalAPSInt(BinaryOperator::Opcode Op, const llvm::APSInt &V1, const llvm::APSInt &V2)
BaseKind getBaseKind() const
Definition: SVals.h:118
Dataflow Directional Tag Classes.
bool isZeroConstant() const
Definition: SVals.cpp:233
const void * getStore() const
Definition: SVals.cpp:165
SVal evalBinOp(BasicValueFactory &BasicVals, BinaryOperator::Opcode Op, const ConcreteInt &R) const
Definition: SVals.cpp:267
const MemRegion * StripCasts(bool StripBaseAndDerivedCasts=true) const
Definition: MemRegion.cpp:1196
const llvm::APSInt & getValue() const
Definition: SVals.h:641
const FunctionDecl * getAsFunctionDecl() const
getAsFunctionDecl - If this SVal is a MemRegionVal and wraps a CodeTextRegion wrapping a FunctionDecl...
Definition: SVals.cpp:62
BasicValueFactory & getBasicValueFactory()
Definition: SValBuilder.h:168
SVal evalBinOp(SValBuilder &svalBuilder, BinaryOperator::Opcode Op, const ConcreteInt &R) const
Definition: SVals.cpp:241
llvm::PointerUnion< const DeclaratorDecl *, const PointerToMemberData * > PTMDataType
Definition: SVals.h:526
const SymExpr * getAsSymExpr() const
Definition: SVals.cpp:143
X
Add a minimal nested name specifier fixit hint to allow lookup of a tag name from an outer enclosing ...
Definition: SemaDecl.cpp:14095
Defines the C++ Decl subclasses, other than those for templates (found in DeclTemplate.h) and friends (in DeclFriend.h).
const TypedValueRegion * getRegion() const
Definition: SVals.cpp:169
std::string getQualifiedNameAsString() const
Definition: Decl.cpp:1548
ConcreteInt evalMinus(SValBuilder &svalBuilder) const
Definition: SVals.cpp:259
const llvm::APSInt & getValue() const
Definition: SVals.h:380