clang  10.0.0git
StdLibraryFunctionsChecker.cpp
Go to the documentation of this file.
1 //=== StdLibraryFunctionsChecker.cpp - Model standard functions -*- C++ -*-===//
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 checker improves modeling of a few simple library functions.
10 // It does not generate warnings.
11 //
12 // This checker provides a specification format - `FunctionSummaryTy' - and
13 // contains descriptions of some library functions in this format. Each
14 // specification contains a list of branches for splitting the program state
15 // upon call, and range constraints on argument and return-value symbols that
16 // are satisfied on each branch. This spec can be expanded to include more
17 // items, like external effects of the function.
18 //
19 // The main difference between this approach and the body farms technique is
20 // in more explicit control over how many branches are produced. For example,
21 // consider standard C function `ispunct(int x)', which returns a non-zero value
22 // iff `x' is a punctuation character, that is, when `x' is in range
23 // ['!', '/'] [':', '@'] U ['[', '\`'] U ['{', '~'].
24 // `FunctionSummaryTy' provides only two branches for this function. However,
25 // any attempt to describe this range with if-statements in the body farm
26 // would result in many more branches. Because each branch needs to be analyzed
27 // independently, this significantly reduces performance. Additionally,
28 // once we consider a branch on which `x' is in range, say, ['!', '/'],
29 // we assume that such branch is an important separate path through the program,
30 // which may lead to false positives because considering this particular path
31 // was not consciously intended, and therefore it might have been unreachable.
32 //
33 // This checker uses eval::Call for modeling "pure" functions, for which
34 // their `FunctionSummaryTy' is a precise model. This avoids unnecessary
35 // invalidation passes. Conflicts with other checkers are unlikely because
36 // if the function has no other effects, other checkers would probably never
37 // want to improve upon the modeling done by this checker.
38 //
39 // Non-"pure" functions, for which only partial improvement over the default
40 // behavior is expected, are modeled via check::PostCall, non-intrusively.
41 //
42 // The following standard C functions are currently supported:
43 //
44 // fgetc getline isdigit isupper
45 // fread isalnum isgraph isxdigit
46 // fwrite isalpha islower read
47 // getc isascii isprint write
48 // getchar isblank ispunct
49 // getdelim iscntrl isspace
50 //
51 //===----------------------------------------------------------------------===//
52 
58 
59 using namespace clang;
60 using namespace clang::ento;
61 
62 namespace {
63 class StdLibraryFunctionsChecker : public Checker<check::PostCall, eval::Call> {
64  /// Below is a series of typedefs necessary to define function specs.
65  /// We avoid nesting types here because each additional qualifier
66  /// would need to be repeated in every function spec.
67  struct FunctionSummaryTy;
68 
69  /// Specify how much the analyzer engine should entrust modeling this function
70  /// to us. If he doesn't, he performs additional invalidations.
71  enum InvalidationKindTy { NoEvalCall, EvalCallAsPure };
72 
73  /// A pair of ValueRangeKindTy and IntRangeVectorTy would describe a range
74  /// imposed on a particular argument or return value symbol.
75  ///
76  /// Given a range, should the argument stay inside or outside this range?
77  /// The special `ComparesToArgument' value indicates that we should
78  /// impose a constraint that involves other argument or return value symbols.
79  enum ValueRangeKindTy { OutOfRange, WithinRange, ComparesToArgument };
80 
81  // The universal integral type to use in value range descriptions.
82  // Unsigned to make sure overflows are well-defined.
83  typedef uint64_t RangeIntTy;
84 
85  /// Normally, describes a single range constraint, eg. {{0, 1}, {3, 4}} is
86  /// a non-negative integer, which less than 5 and not equal to 2. For
87  /// `ComparesToArgument', holds information about how exactly to compare to
88  /// the argument.
89  typedef std::vector<std::pair<RangeIntTy, RangeIntTy>> IntRangeVectorTy;
90 
91  /// A reference to an argument or return value by its number.
92  /// ArgNo in CallExpr and CallEvent is defined as Unsigned, but
93  /// obviously uint32_t should be enough for all practical purposes.
94  typedef uint32_t ArgNoTy;
95  static const ArgNoTy Ret = std::numeric_limits<ArgNoTy>::max();
96 
97  /// Incapsulates a single range on a single symbol within a branch.
98  class ValueRange {
99  ArgNoTy ArgNo; // Argument to which we apply the range.
100  ValueRangeKindTy Kind; // Kind of range definition.
101  IntRangeVectorTy Args; // Polymorphic arguments.
102 
103  public:
104  ValueRange(ArgNoTy ArgNo, ValueRangeKindTy Kind,
105  const IntRangeVectorTy &Args)
106  : ArgNo(ArgNo), Kind(Kind), Args(Args) {}
107 
108  ArgNoTy getArgNo() const { return ArgNo; }
109  ValueRangeKindTy getKind() const { return Kind; }
110 
111  BinaryOperator::Opcode getOpcode() const {
112  assert(Kind == ComparesToArgument);
113  assert(Args.size() == 1);
115  static_cast<BinaryOperator::Opcode>(Args[0].first);
116  assert(BinaryOperator::isComparisonOp(Op) &&
117  "Only comparison ops are supported for ComparesToArgument");
118  return Op;
119  }
120 
121  ArgNoTy getOtherArgNo() const {
122  assert(Kind == ComparesToArgument);
123  assert(Args.size() == 1);
124  return static_cast<ArgNoTy>(Args[0].second);
125  }
126 
127  const IntRangeVectorTy &getRanges() const {
128  assert(Kind != ComparesToArgument);
129  return Args;
130  }
131 
132  // We avoid creating a virtual apply() method because
133  // it makes initializer lists harder to write.
134  private:
136  applyAsOutOfRange(ProgramStateRef State, const CallEvent &Call,
137  const FunctionSummaryTy &Summary) const;
139  applyAsWithinRange(ProgramStateRef State, const CallEvent &Call,
140  const FunctionSummaryTy &Summary) const;
142  applyAsComparesToArgument(ProgramStateRef State, const CallEvent &Call,
143  const FunctionSummaryTy &Summary) const;
144 
145  public:
146  ProgramStateRef apply(ProgramStateRef State, const CallEvent &Call,
147  const FunctionSummaryTy &Summary) const {
148  switch (Kind) {
149  case OutOfRange:
150  return applyAsOutOfRange(State, Call, Summary);
151  case WithinRange:
152  return applyAsWithinRange(State, Call, Summary);
153  case ComparesToArgument:
154  return applyAsComparesToArgument(State, Call, Summary);
155  }
156  llvm_unreachable("Unknown ValueRange kind!");
157  }
158  };
159 
160  /// The complete list of ranges that defines a single branch.
161  typedef std::vector<ValueRange> ValueRangeSet;
162 
163  /// Includes information about function prototype (which is necessary to
164  /// ensure we're modeling the right function and casting values properly),
165  /// approach to invalidation, and a list of branches - essentially, a list
166  /// of list of ranges - essentially, a list of lists of lists of segments.
167  struct FunctionSummaryTy {
168  const std::vector<QualType> ArgTypes;
169  const QualType RetType;
170  const InvalidationKindTy InvalidationKind;
171  const std::vector<ValueRangeSet> Ranges;
172 
173  private:
174  static void assertTypeSuitableForSummary(QualType T) {
175  assert(!T->isVoidType() &&
176  "We should have had no significant void types in the spec");
177  assert(T.isCanonical() &&
178  "We should only have canonical types in the spec");
179  // FIXME: lift this assert (but not the ones above!)
180  assert(T->isIntegralOrEnumerationType() &&
181  "We only support integral ranges in the spec");
182  }
183 
184  public:
185  QualType getArgType(ArgNoTy ArgNo) const {
186  QualType T = (ArgNo == Ret) ? RetType : ArgTypes[ArgNo];
187  assertTypeSuitableForSummary(T);
188  return T;
189  }
190 
191  /// Try our best to figure out if the call expression is the call of
192  /// *the* library function to which this specification applies.
193  bool matchesCall(const CallExpr *CE) const;
194  };
195 
196  // The same function (as in, function identifier) may have different
197  // summaries assigned to it, with different argument and return value types.
198  // We call these "variants" of the function. This can be useful for handling
199  // C++ function overloads, and also it can be used when the same function
200  // may have different definitions on different platforms.
201  typedef std::vector<FunctionSummaryTy> FunctionVariantsTy;
202 
203  // The map of all functions supported by the checker. It is initialized
204  // lazily, and it doesn't change after initialization.
205  typedef llvm::StringMap<FunctionVariantsTy> FunctionSummaryMapTy;
206  mutable FunctionSummaryMapTy FunctionSummaryMap;
207 
208  // Auxiliary functions to support ArgNoTy within all structures
209  // in a unified manner.
210  static QualType getArgType(const FunctionSummaryTy &Summary, ArgNoTy ArgNo) {
211  return Summary.getArgType(ArgNo);
212  }
213  static QualType getArgType(const CallEvent &Call, ArgNoTy ArgNo) {
214  return ArgNo == Ret ? Call.getResultType().getCanonicalType()
215  : Call.getArgExpr(ArgNo)->getType().getCanonicalType();
216  }
217  static QualType getArgType(const CallExpr *CE, ArgNoTy ArgNo) {
218  return ArgNo == Ret ? CE->getType().getCanonicalType()
219  : CE->getArg(ArgNo)->getType().getCanonicalType();
220  }
221  static SVal getArgSVal(const CallEvent &Call, ArgNoTy ArgNo) {
222  return ArgNo == Ret ? Call.getReturnValue() : Call.getArgSVal(ArgNo);
223  }
224 
225 public:
226  void checkPostCall(const CallEvent &Call, CheckerContext &C) const;
227  bool evalCall(const CallEvent &Call, CheckerContext &C) const;
228 
229 private:
230  Optional<FunctionSummaryTy> findFunctionSummary(const FunctionDecl *FD,
231  const CallExpr *CE,
232  CheckerContext &C) const;
233 
234  void initFunctionSummaries(BasicValueFactory &BVF) const;
235 };
236 } // end of anonymous namespace
237 
238 ProgramStateRef StdLibraryFunctionsChecker::ValueRange::applyAsOutOfRange(
239  ProgramStateRef State, const CallEvent &Call,
240  const FunctionSummaryTy &Summary) const {
241 
242  ProgramStateManager &Mgr = State->getStateManager();
243  SValBuilder &SVB = Mgr.getSValBuilder();
246  QualType T = getArgType(Summary, getArgNo());
247  SVal V = getArgSVal(Call, getArgNo());
248 
249  if (auto N = V.getAs<NonLoc>()) {
250  const IntRangeVectorTy &R = getRanges();
251  size_t E = R.size();
252  for (size_t I = 0; I != E; ++I) {
253  const llvm::APSInt &Min = BVF.getValue(R[I].first, T);
254  const llvm::APSInt &Max = BVF.getValue(R[I].second, T);
255  assert(Min <= Max);
256  State = CM.assumeInclusiveRange(State, *N, Min, Max, false);
257  if (!State)
258  break;
259  }
260  }
261 
262  return State;
263 }
264 
266 StdLibraryFunctionsChecker::ValueRange::applyAsWithinRange(
267  ProgramStateRef State, const CallEvent &Call,
268  const FunctionSummaryTy &Summary) const {
269 
270  ProgramStateManager &Mgr = State->getStateManager();
271  SValBuilder &SVB = Mgr.getSValBuilder();
274  QualType T = getArgType(Summary, getArgNo());
275  SVal V = getArgSVal(Call, getArgNo());
276 
277  // "WithinRange R" is treated as "outside [T_MIN, T_MAX] \ R".
278  // We cut off [T_MIN, min(R) - 1] and [max(R) + 1, T_MAX] if necessary,
279  // and then cut away all holes in R one by one.
280  if (auto N = V.getAs<NonLoc>()) {
281  const IntRangeVectorTy &R = getRanges();
282  size_t E = R.size();
283 
284  const llvm::APSInt &MinusInf = BVF.getMinValue(T);
285  const llvm::APSInt &PlusInf = BVF.getMaxValue(T);
286 
287  const llvm::APSInt &Left = BVF.getValue(R[0].first - 1ULL, T);
288  if (Left != PlusInf) {
289  assert(MinusInf <= Left);
290  State = CM.assumeInclusiveRange(State, *N, MinusInf, Left, false);
291  if (!State)
292  return nullptr;
293  }
294 
295  const llvm::APSInt &Right = BVF.getValue(R[E - 1].second + 1ULL, T);
296  if (Right != MinusInf) {
297  assert(Right <= PlusInf);
298  State = CM.assumeInclusiveRange(State, *N, Right, PlusInf, false);
299  if (!State)
300  return nullptr;
301  }
302 
303  for (size_t I = 1; I != E; ++I) {
304  const llvm::APSInt &Min = BVF.getValue(R[I - 1].second + 1ULL, T);
305  const llvm::APSInt &Max = BVF.getValue(R[I].first - 1ULL, T);
306  assert(Min <= Max);
307  State = CM.assumeInclusiveRange(State, *N, Min, Max, false);
308  if (!State)
309  return nullptr;
310  }
311  }
312 
313  return State;
314 }
315 
317 StdLibraryFunctionsChecker::ValueRange::applyAsComparesToArgument(
318  ProgramStateRef State, const CallEvent &Call,
319  const FunctionSummaryTy &Summary) const {
320 
321  ProgramStateManager &Mgr = State->getStateManager();
322  SValBuilder &SVB = Mgr.getSValBuilder();
323  QualType CondT = SVB.getConditionType();
324  QualType T = getArgType(Summary, getArgNo());
325  SVal V = getArgSVal(Call, getArgNo());
326 
327  BinaryOperator::Opcode Op = getOpcode();
328  ArgNoTy OtherArg = getOtherArgNo();
329  SVal OtherV = getArgSVal(Call, OtherArg);
330  QualType OtherT = getArgType(Call, OtherArg);
331  // Note: we avoid integral promotion for comparison.
332  OtherV = SVB.evalCast(OtherV, T, OtherT);
333  if (auto CompV = SVB.evalBinOp(State, Op, V, OtherV, CondT)
335  State = State->assume(*CompV, true);
336  return State;
337 }
338 
339 void StdLibraryFunctionsChecker::checkPostCall(const CallEvent &Call,
340  CheckerContext &C) const {
341  const FunctionDecl *FD = dyn_cast_or_null<FunctionDecl>(Call.getDecl());
342  if (!FD)
343  return;
344 
345  const CallExpr *CE = dyn_cast_or_null<CallExpr>(Call.getOriginExpr());
346  if (!CE)
347  return;
348 
349  Optional<FunctionSummaryTy> FoundSummary = findFunctionSummary(FD, CE, C);
350  if (!FoundSummary)
351  return;
352 
353  // Now apply ranges.
354  const FunctionSummaryTy &Summary = *FoundSummary;
355  ProgramStateRef State = C.getState();
356 
357  for (const auto &VRS: Summary.Ranges) {
358  ProgramStateRef NewState = State;
359  for (const auto &VR: VRS) {
360  NewState = VR.apply(NewState, Call, Summary);
361  if (!NewState)
362  break;
363  }
364 
365  if (NewState && NewState != State)
366  C.addTransition(NewState);
367  }
368 }
369 
370 bool StdLibraryFunctionsChecker::evalCall(const CallEvent &Call,
371  CheckerContext &C) const {
372  const auto *FD = dyn_cast_or_null<FunctionDecl>(Call.getDecl());
373  if (!FD)
374  return false;
375 
376  const auto *CE = dyn_cast_or_null<CallExpr>(Call.getOriginExpr());
377  if (!CE)
378  return false;
379 
380  Optional<FunctionSummaryTy> FoundSummary = findFunctionSummary(FD, CE, C);
381  if (!FoundSummary)
382  return false;
383 
384  const FunctionSummaryTy &Summary = *FoundSummary;
385  switch (Summary.InvalidationKind) {
386  case EvalCallAsPure: {
387  ProgramStateRef State = C.getState();
388  const LocationContext *LC = C.getLocationContext();
390  CE, LC, CE->getType().getCanonicalType(), C.blockCount());
391  State = State->BindExpr(CE, LC, V);
392  C.addTransition(State);
393  return true;
394  }
395  case NoEvalCall:
396  // Summary tells us to avoid performing eval::Call. The function is possibly
397  // evaluated by another checker, or evaluated conservatively.
398  return false;
399  }
400  llvm_unreachable("Unknown invalidation kind!");
401 }
402 
403 bool StdLibraryFunctionsChecker::FunctionSummaryTy::matchesCall(
404  const CallExpr *CE) const {
405  // Check number of arguments:
406  if (CE->getNumArgs() != ArgTypes.size())
407  return false;
408 
409  // Check return type if relevant:
410  if (!RetType.isNull() && RetType != CE->getType().getCanonicalType())
411  return false;
412 
413  // Check argument types when relevant:
414  for (size_t I = 0, E = ArgTypes.size(); I != E; ++I) {
415  QualType FormalT = ArgTypes[I];
416  // Null type marks irrelevant arguments.
417  if (FormalT.isNull())
418  continue;
419 
420  assertTypeSuitableForSummary(FormalT);
421 
422  QualType ActualT = StdLibraryFunctionsChecker::getArgType(CE, I);
423  assert(ActualT.isCanonical());
424  if (ActualT != FormalT)
425  return false;
426  }
427 
428  return true;
429 }
430 
432 StdLibraryFunctionsChecker::findFunctionSummary(const FunctionDecl *FD,
433  const CallExpr *CE,
434  CheckerContext &C) const {
435  // Note: we cannot always obtain FD from CE
436  // (eg. virtual call, or call by pointer).
437  assert(CE);
438 
439  if (!FD)
440  return None;
441 
442  SValBuilder &SVB = C.getSValBuilder();
444  initFunctionSummaries(BVF);
445 
446  IdentifierInfo *II = FD->getIdentifier();
447  if (!II)
448  return None;
449  StringRef Name = II->getName();
450  if (Name.empty() || !C.isCLibraryFunction(FD, Name))
451  return None;
452 
453  auto FSMI = FunctionSummaryMap.find(Name);
454  if (FSMI == FunctionSummaryMap.end())
455  return None;
456 
457  // Verify that function signature matches the spec in advance.
458  // Otherwise we might be modeling the wrong function.
459  // Strict checking is important because we will be conducting
460  // very integral-type-sensitive operations on arguments and
461  // return values.
462  const FunctionVariantsTy &SpecVariants = FSMI->second;
463  for (const FunctionSummaryTy &Spec : SpecVariants)
464  if (Spec.matchesCall(CE))
465  return Spec;
466 
467  return None;
468 }
469 
470 void StdLibraryFunctionsChecker::initFunctionSummaries(
471  BasicValueFactory &BVF) const {
472  if (!FunctionSummaryMap.empty())
473  return;
474 
475  ASTContext &ACtx = BVF.getContext();
476 
477  // These types are useful for writing specifications quickly,
478  // New specifications should probably introduce more types.
479  // Some types are hard to obtain from the AST, eg. "ssize_t".
480  // In such cases it should be possible to provide multiple variants
481  // of function summary for common cases (eg. ssize_t could be int or long
482  // or long long, so three summary variants would be enough).
483  // Of course, function variants are also useful for C++ overloads.
484  QualType Irrelevant; // A placeholder, whenever we do not care about the type.
485  QualType IntTy = ACtx.IntTy;
486  QualType LongTy = ACtx.LongTy;
487  QualType LongLongTy = ACtx.LongLongTy;
488  QualType SizeTy = ACtx.getSizeType();
489 
490  RangeIntTy IntMax = BVF.getMaxValue(IntTy).getLimitedValue();
491  RangeIntTy LongMax = BVF.getMaxValue(LongTy).getLimitedValue();
492  RangeIntTy LongLongMax = BVF.getMaxValue(LongLongTy).getLimitedValue();
493 
494  // We are finally ready to define specifications for all supported functions.
495  //
496  // The signature needs to have the correct number of arguments.
497  // However, we insert `Irrelevant' when the type is insignificant.
498  //
499  // Argument ranges should always cover all variants. If return value
500  // is completely unknown, omit it from the respective range set.
501  //
502  // All types in the spec need to be canonical.
503  //
504  // Every item in the list of range sets represents a particular
505  // execution path the analyzer would need to explore once
506  // the call is modeled - a new program state is constructed
507  // for every range set, and each range line in the range set
508  // corresponds to a specific constraint within this state.
509  //
510  // Upon comparing to another argument, the other argument is casted
511  // to the current argument's type. This avoids proper promotion but
512  // seems useful. For example, read() receives size_t argument,
513  // and its return value, which is of type ssize_t, cannot be greater
514  // than this argument. If we made a promotion, and the size argument
515  // is equal to, say, 10, then we'd impose a range of [0, 10] on the
516  // return value, however the correct range is [-1, 10].
517  //
518  // Please update the list of functions in the header after editing!
519  //
520  // The format is as follows:
521  //
522  //{ "function name",
523  // { spec:
524  // { argument types list, ... },
525  // return type, purity, { range set list:
526  // { range list:
527  // { argument index, within or out of, {{from, to}, ...} },
528  // { argument index, compares to argument, {{how, which}} },
529  // ...
530  // }
531  // }
532  // }
533  //}
534 
535 #define SUMMARY_WITH_VARIANTS(identifier) {#identifier, {
536 #define END_SUMMARY_WITH_VARIANTS }},
537 #define VARIANT(argument_types, return_type, invalidation_approach) \
538  { argument_types, return_type, invalidation_approach, {
539 #define END_VARIANT } },
540 #define SUMMARY(identifier, argument_types, return_type, \
541  invalidation_approach) \
542  { #identifier, { { argument_types, return_type, invalidation_approach, {
543 #define END_SUMMARY } } } },
544 #define ARGUMENT_TYPES(...) { __VA_ARGS__ }
545 #define RETURN_TYPE(x) x
546 #define INVALIDATION_APPROACH(x) x
547 #define CASE {
548 #define END_CASE },
549 #define ARGUMENT_CONDITION(argument_number, condition_kind) \
550  { argument_number, condition_kind, {
551 #define END_ARGUMENT_CONDITION }},
552 #define RETURN_VALUE_CONDITION(condition_kind) \
553  { Ret, condition_kind, {
554 #define END_RETURN_VALUE_CONDITION }},
555 #define ARG_NO(x) x##U
556 #define RANGE(x, y) { x, y },
557 #define SINGLE_VALUE(x) RANGE(x, x)
558 #define IS_LESS_THAN(arg) { BO_LE, arg }
559 
560  FunctionSummaryMap = {
561  // The isascii() family of functions.
562  SUMMARY(isalnum, ARGUMENT_TYPES(IntTy), RETURN_TYPE(IntTy),
563  INVALIDATION_APPROACH(EvalCallAsPure))
564  CASE // Boils down to isupper() or islower() or isdigit()
565  ARGUMENT_CONDITION(ARG_NO(0), WithinRange)
566  RANGE('0', '9')
567  RANGE('A', 'Z')
568  RANGE('a', 'z')
570  RETURN_VALUE_CONDITION(OutOfRange)
571  SINGLE_VALUE(0)
573  END_CASE
574  CASE // The locale-specific range.
575  ARGUMENT_CONDITION(ARG_NO(0), WithinRange)
576  RANGE(128, 255)
578  // No post-condition. We are completely unaware of
579  // locale-specific return values.
580  END_CASE
581  CASE
582  ARGUMENT_CONDITION(ARG_NO(0), OutOfRange)
583  RANGE('0', '9')
584  RANGE('A', 'Z')
585  RANGE('a', 'z')
586  RANGE(128, 255)
588  RETURN_VALUE_CONDITION(WithinRange)
589  SINGLE_VALUE(0)
591  END_CASE
593  SUMMARY(isalpha, ARGUMENT_TYPES(IntTy), RETURN_TYPE(IntTy),
594  INVALIDATION_APPROACH(EvalCallAsPure))
595  CASE // isupper() or islower(). Note that 'Z' is less than 'a'.
596  ARGUMENT_CONDITION(ARG_NO(0), WithinRange)
597  RANGE('A', 'Z')
598  RANGE('a', 'z')
600  RETURN_VALUE_CONDITION(OutOfRange)
601  SINGLE_VALUE(0)
603  END_CASE
604  CASE // The locale-specific range.
605  ARGUMENT_CONDITION(ARG_NO(0), WithinRange)
606  RANGE(128, 255)
608  END_CASE
609  CASE // Other.
610  ARGUMENT_CONDITION(ARG_NO(0), OutOfRange)
611  RANGE('A', 'Z')
612  RANGE('a', 'z')
613  RANGE(128, 255)
615  RETURN_VALUE_CONDITION(WithinRange)
616  SINGLE_VALUE(0)
618  END_CASE
620  SUMMARY(isascii, ARGUMENT_TYPES(IntTy), RETURN_TYPE(IntTy),
621  INVALIDATION_APPROACH(EvalCallAsPure))
622  CASE // Is ASCII.
623  ARGUMENT_CONDITION(ARG_NO(0), WithinRange)
624  RANGE(0, 127)
626  RETURN_VALUE_CONDITION(OutOfRange)
627  SINGLE_VALUE(0)
629  END_CASE
630  CASE
631  ARGUMENT_CONDITION(ARG_NO(0), OutOfRange)
632  RANGE(0, 127)
634  RETURN_VALUE_CONDITION(WithinRange)
635  SINGLE_VALUE(0)
637  END_CASE
639  SUMMARY(isblank, ARGUMENT_TYPES(IntTy), RETURN_TYPE(IntTy),
640  INVALIDATION_APPROACH(EvalCallAsPure))
641  CASE
642  ARGUMENT_CONDITION(ARG_NO(0), WithinRange)
643  SINGLE_VALUE('\t')
644  SINGLE_VALUE(' ')
646  RETURN_VALUE_CONDITION(OutOfRange)
647  SINGLE_VALUE(0)
649  END_CASE
650  CASE
651  ARGUMENT_CONDITION(ARG_NO(0), OutOfRange)
652  SINGLE_VALUE('\t')
653  SINGLE_VALUE(' ')
655  RETURN_VALUE_CONDITION(WithinRange)
656  SINGLE_VALUE(0)
658  END_CASE
660  SUMMARY(iscntrl, ARGUMENT_TYPES(IntTy), RETURN_TYPE(IntTy),
661  INVALIDATION_APPROACH(EvalCallAsPure))
662  CASE // 0..31 or 127
663  ARGUMENT_CONDITION(ARG_NO(0), WithinRange)
664  RANGE(0, 32)
665  SINGLE_VALUE(127)
667  RETURN_VALUE_CONDITION(OutOfRange)
668  SINGLE_VALUE(0)
670  END_CASE
671  CASE
672  ARGUMENT_CONDITION(ARG_NO(0), OutOfRange)
673  RANGE(0, 32)
674  SINGLE_VALUE(127)
676  RETURN_VALUE_CONDITION(WithinRange)
677  SINGLE_VALUE(0)
679  END_CASE
681  SUMMARY(isdigit, ARGUMENT_TYPES(IntTy), RETURN_TYPE(IntTy),
682  INVALIDATION_APPROACH(EvalCallAsPure))
683  CASE // Is a digit.
684  ARGUMENT_CONDITION(ARG_NO(0), WithinRange)
685  RANGE('0', '9')
687  RETURN_VALUE_CONDITION(OutOfRange)
688  SINGLE_VALUE(0)
690  END_CASE
691  CASE
692  ARGUMENT_CONDITION(ARG_NO(0), OutOfRange)
693  RANGE('0', '9')
695  RETURN_VALUE_CONDITION(WithinRange)
696  SINGLE_VALUE(0)
698  END_CASE
700  SUMMARY(isgraph, ARGUMENT_TYPES(IntTy), RETURN_TYPE(IntTy),
701  INVALIDATION_APPROACH(EvalCallAsPure))
702  CASE
703  ARGUMENT_CONDITION(ARG_NO(0), WithinRange)
704  RANGE(33, 126)
706  RETURN_VALUE_CONDITION(OutOfRange)
707  SINGLE_VALUE(0)
709  END_CASE
710  CASE
711  ARGUMENT_CONDITION(ARG_NO(0), OutOfRange)
712  RANGE(33, 126)
714  RETURN_VALUE_CONDITION(WithinRange)
715  SINGLE_VALUE(0)
717  END_CASE
719  SUMMARY(islower, ARGUMENT_TYPES(IntTy), RETURN_TYPE(IntTy),
720  INVALIDATION_APPROACH(EvalCallAsPure))
721  CASE // Is certainly lowercase.
722  ARGUMENT_CONDITION(ARG_NO(0), WithinRange)
723  RANGE('a', 'z')
725  RETURN_VALUE_CONDITION(OutOfRange)
726  SINGLE_VALUE(0)
728  END_CASE
729  CASE // Is ascii but not lowercase.
730  ARGUMENT_CONDITION(ARG_NO(0), WithinRange)
731  RANGE(0, 127)
733  ARGUMENT_CONDITION(ARG_NO(0), OutOfRange)
734  RANGE('a', 'z')
736  RETURN_VALUE_CONDITION(WithinRange)
737  SINGLE_VALUE(0)
739  END_CASE
740  CASE // The locale-specific range.
741  ARGUMENT_CONDITION(ARG_NO(0), WithinRange)
742  RANGE(128, 255)
744  END_CASE
745  CASE // Is not an unsigned char.
746  ARGUMENT_CONDITION(ARG_NO(0), OutOfRange)
747  RANGE(0, 255)
749  RETURN_VALUE_CONDITION(WithinRange)
750  SINGLE_VALUE(0)
752  END_CASE
754  SUMMARY(isprint, ARGUMENT_TYPES(IntTy), RETURN_TYPE(IntTy),
755  INVALIDATION_APPROACH(EvalCallAsPure))
756  CASE
757  ARGUMENT_CONDITION(ARG_NO(0), WithinRange)
758  RANGE(32, 126)
760  RETURN_VALUE_CONDITION(OutOfRange)
761  SINGLE_VALUE(0)
763  END_CASE
764  CASE
765  ARGUMENT_CONDITION(ARG_NO(0), OutOfRange)
766  RANGE(32, 126)
768  RETURN_VALUE_CONDITION(WithinRange)
769  SINGLE_VALUE(0)
771  END_CASE
773  SUMMARY(ispunct, ARGUMENT_TYPES(IntTy), RETURN_TYPE(IntTy),
774  INVALIDATION_APPROACH(EvalCallAsPure))
775  CASE
776  ARGUMENT_CONDITION(ARG_NO(0), WithinRange)
777  RANGE('!', '/')
778  RANGE(':', '@')
779  RANGE('[', '`')
780  RANGE('{', '~')
781  END_ARGUMENT_CONDITION
782  RETURN_VALUE_CONDITION(OutOfRange)
783  SINGLE_VALUE(0)
784  END_RETURN_VALUE_CONDITION
785  END_CASE
786  CASE
787  ARGUMENT_CONDITION(ARG_NO(0), OutOfRange)
788  RANGE('!', '/')
789  RANGE(':', '@')
790  RANGE('[', '`')
791  RANGE('{', '~')
792  END_ARGUMENT_CONDITION
793  RETURN_VALUE_CONDITION(WithinRange)
794  SINGLE_VALUE(0)
795  END_RETURN_VALUE_CONDITION
796  END_CASE
797  END_SUMMARY
798  SUMMARY(isspace, ARGUMENT_TYPES(IntTy), RETURN_TYPE(IntTy),
799  INVALIDATION_APPROACH(EvalCallAsPure))
800  CASE // Space, '\f', '\n', '\r', '\t', '\v'.
801  ARGUMENT_CONDITION(ARG_NO(0), WithinRange)
802  RANGE(9, 13)
803  SINGLE_VALUE(' ')
804  END_ARGUMENT_CONDITION
805  RETURN_VALUE_CONDITION(OutOfRange)
806  SINGLE_VALUE(0)
807  END_RETURN_VALUE_CONDITION
808  END_CASE
809  CASE // The locale-specific range.
810  ARGUMENT_CONDITION(ARG_NO(0), WithinRange)
811  RANGE(128, 255)
812  END_ARGUMENT_CONDITION
813  END_CASE
814  CASE
815  ARGUMENT_CONDITION(ARG_NO(0), OutOfRange)
816  RANGE(9, 13)
817  SINGLE_VALUE(' ')
818  RANGE(128, 255)
819  END_ARGUMENT_CONDITION
820  RETURN_VALUE_CONDITION(WithinRange)
821  SINGLE_VALUE(0)
822  END_RETURN_VALUE_CONDITION
823  END_CASE
824  END_SUMMARY
825  SUMMARY(isupper, ARGUMENT_TYPES(IntTy), RETURN_TYPE (IntTy),
826  INVALIDATION_APPROACH(EvalCallAsPure))
827  CASE // Is certainly uppercase.
828  ARGUMENT_CONDITION(ARG_NO(0), WithinRange)
829  RANGE('A', 'Z')
830  END_ARGUMENT_CONDITION
831  RETURN_VALUE_CONDITION(OutOfRange)
832  SINGLE_VALUE(0)
833  END_RETURN_VALUE_CONDITION
834  END_CASE
835  CASE // The locale-specific range.
836  ARGUMENT_CONDITION(ARG_NO(0), WithinRange)
837  RANGE(128, 255)
838  END_ARGUMENT_CONDITION
839  END_CASE
840  CASE // Other.
841  ARGUMENT_CONDITION(ARG_NO(0), OutOfRange)
842  RANGE('A', 'Z') RANGE(128, 255)
843  END_ARGUMENT_CONDITION
844  RETURN_VALUE_CONDITION(WithinRange)
845  SINGLE_VALUE(0)
846  END_RETURN_VALUE_CONDITION
847  END_CASE
848  END_SUMMARY
849  SUMMARY(isxdigit, ARGUMENT_TYPES(IntTy), RETURN_TYPE(IntTy),
850  INVALIDATION_APPROACH(EvalCallAsPure))
851  CASE
852  ARGUMENT_CONDITION(ARG_NO(0), WithinRange)
853  RANGE('0', '9')
854  RANGE('A', 'F')
855  RANGE('a', 'f')
856  END_ARGUMENT_CONDITION
857  RETURN_VALUE_CONDITION(OutOfRange)
858  SINGLE_VALUE(0)
859  END_RETURN_VALUE_CONDITION
860  END_CASE
861  CASE
862  ARGUMENT_CONDITION(ARG_NO(0), OutOfRange)
863  RANGE('0', '9')
864  RANGE('A', 'F')
865  RANGE('a', 'f')
866  END_ARGUMENT_CONDITION
867  RETURN_VALUE_CONDITION(WithinRange)
868  SINGLE_VALUE(0)
869  END_RETURN_VALUE_CONDITION
870  END_CASE
871  END_SUMMARY
872 
873  // The getc() family of functions that returns either a char or an EOF.
874  SUMMARY(getc, ARGUMENT_TYPES(Irrelevant), RETURN_TYPE(IntTy),
875  INVALIDATION_APPROACH(NoEvalCall))
876  CASE // FIXME: EOF is assumed to be defined as -1.
877  RETURN_VALUE_CONDITION(WithinRange)
878  RANGE(-1, 255)
879  END_RETURN_VALUE_CONDITION
880  END_CASE
881  END_SUMMARY
882  SUMMARY(fgetc, ARGUMENT_TYPES(Irrelevant), RETURN_TYPE(IntTy),
883  INVALIDATION_APPROACH(NoEvalCall))
884  CASE // FIXME: EOF is assumed to be defined as -1.
885  RETURN_VALUE_CONDITION(WithinRange)
886  RANGE(-1, 255)
887  END_RETURN_VALUE_CONDITION
888  END_CASE
889  END_SUMMARY
890  SUMMARY(getchar, ARGUMENT_TYPES(), RETURN_TYPE(IntTy),
891  INVALIDATION_APPROACH(NoEvalCall))
892  CASE // FIXME: EOF is assumed to be defined as -1.
893  RETURN_VALUE_CONDITION(WithinRange)
894  RANGE(-1, 255)
895  END_RETURN_VALUE_CONDITION
896  END_CASE
897  END_SUMMARY
898 
899  // read()-like functions that never return more than buffer size.
900  // We are not sure how ssize_t is defined on every platform, so we provide
901  // three variants that should cover common cases.
902  SUMMARY_WITH_VARIANTS(read)
903  VARIANT(ARGUMENT_TYPES(Irrelevant, Irrelevant, SizeTy),
904  RETURN_TYPE(IntTy), INVALIDATION_APPROACH(NoEvalCall))
905  CASE
906  RETURN_VALUE_CONDITION(ComparesToArgument)
907  IS_LESS_THAN(ARG_NO(2))
908  END_RETURN_VALUE_CONDITION
909  RETURN_VALUE_CONDITION(WithinRange)
910  RANGE(-1, IntMax)
911  END_RETURN_VALUE_CONDITION
912  END_CASE
913  END_VARIANT
914  VARIANT(ARGUMENT_TYPES(Irrelevant, Irrelevant, SizeTy),
915  RETURN_TYPE(LongTy), INVALIDATION_APPROACH(NoEvalCall))
916  CASE
917  RETURN_VALUE_CONDITION(ComparesToArgument)
918  IS_LESS_THAN(ARG_NO(2))
919  END_RETURN_VALUE_CONDITION
920  RETURN_VALUE_CONDITION(WithinRange)
921  RANGE(-1, LongMax)
922  END_RETURN_VALUE_CONDITION
923  END_CASE
924  END_VARIANT
925  VARIANT(ARGUMENT_TYPES(Irrelevant, Irrelevant, SizeTy),
926  RETURN_TYPE(LongLongTy), INVALIDATION_APPROACH(NoEvalCall))
927  CASE
928  RETURN_VALUE_CONDITION(ComparesToArgument)
929  IS_LESS_THAN(ARG_NO(2))
930  END_RETURN_VALUE_CONDITION
931  RETURN_VALUE_CONDITION(WithinRange)
932  RANGE(-1, LongLongMax)
933  END_RETURN_VALUE_CONDITION
934  END_CASE
935  END_VARIANT
936  END_SUMMARY_WITH_VARIANTS
937  SUMMARY_WITH_VARIANTS(write)
938  // Again, due to elusive nature of ssize_t, we have duplicate
939  // our summaries to cover different variants.
940  VARIANT(ARGUMENT_TYPES(Irrelevant, Irrelevant, SizeTy),
941  RETURN_TYPE(IntTy), INVALIDATION_APPROACH(NoEvalCall))
942  CASE
943  RETURN_VALUE_CONDITION(ComparesToArgument)
944  IS_LESS_THAN(ARG_NO(2))
945  END_RETURN_VALUE_CONDITION
946  RETURN_VALUE_CONDITION(WithinRange)
947  RANGE(-1, IntMax)
948  END_RETURN_VALUE_CONDITION
949  END_CASE
950  END_VARIANT
951  VARIANT(ARGUMENT_TYPES(Irrelevant, Irrelevant, SizeTy),
952  RETURN_TYPE(LongTy), INVALIDATION_APPROACH(NoEvalCall))
953  CASE
954  RETURN_VALUE_CONDITION(ComparesToArgument)
955  IS_LESS_THAN(ARG_NO(2))
956  END_RETURN_VALUE_CONDITION
957  RETURN_VALUE_CONDITION(WithinRange)
958  RANGE(-1, LongMax)
959  END_RETURN_VALUE_CONDITION
960  END_CASE
961  END_VARIANT
962  VARIANT(ARGUMENT_TYPES(Irrelevant, Irrelevant, SizeTy),
963  RETURN_TYPE(LongLongTy), INVALIDATION_APPROACH(NoEvalCall))
964  CASE
965  RETURN_VALUE_CONDITION(ComparesToArgument)
966  IS_LESS_THAN(ARG_NO(2))
967  END_RETURN_VALUE_CONDITION
968  RETURN_VALUE_CONDITION(WithinRange)
969  RANGE(-1, LongLongMax)
970  END_RETURN_VALUE_CONDITION
971  END_CASE
972  END_VARIANT
973  END_SUMMARY_WITH_VARIANTS
974  SUMMARY(fread,
975  ARGUMENT_TYPES(Irrelevant, Irrelevant, SizeTy, Irrelevant),
976  RETURN_TYPE(SizeTy), INVALIDATION_APPROACH(NoEvalCall))
977  CASE
978  RETURN_VALUE_CONDITION(ComparesToArgument)
979  IS_LESS_THAN(ARG_NO(2))
980  END_RETURN_VALUE_CONDITION
981  END_CASE
982  END_SUMMARY
983  SUMMARY(fwrite,
984  ARGUMENT_TYPES(Irrelevant, Irrelevant, SizeTy, Irrelevant),
985  RETURN_TYPE(SizeTy), INVALIDATION_APPROACH(NoEvalCall))
986  CASE
987  RETURN_VALUE_CONDITION(ComparesToArgument)
988  IS_LESS_THAN(ARG_NO(2))
989  END_RETURN_VALUE_CONDITION
990  END_CASE
991  END_SUMMARY
992 
993  // getline()-like functions either fail or read at least the delimiter.
994  SUMMARY_WITH_VARIANTS(getline)
995  VARIANT(ARGUMENT_TYPES(Irrelevant, Irrelevant, Irrelevant),
996  RETURN_TYPE(IntTy), INVALIDATION_APPROACH(NoEvalCall))
997  CASE
998  RETURN_VALUE_CONDITION(WithinRange)
999  SINGLE_VALUE(-1)
1000  RANGE(1, IntMax)
1001  END_RETURN_VALUE_CONDITION
1002  END_CASE
1003  END_VARIANT
1004  VARIANT(ARGUMENT_TYPES(Irrelevant, Irrelevant, Irrelevant),
1005  RETURN_TYPE(LongTy), INVALIDATION_APPROACH(NoEvalCall))
1006  CASE
1007  RETURN_VALUE_CONDITION(WithinRange)
1008  SINGLE_VALUE(-1)
1009  RANGE(1, LongMax)
1010  END_RETURN_VALUE_CONDITION
1011  END_CASE
1012  END_VARIANT
1013  VARIANT(ARGUMENT_TYPES(Irrelevant, Irrelevant, Irrelevant),
1014  RETURN_TYPE(LongLongTy), INVALIDATION_APPROACH(NoEvalCall))
1015  CASE
1016  RETURN_VALUE_CONDITION(WithinRange)
1017  SINGLE_VALUE(-1)
1018  RANGE(1, LongLongMax)
1019  END_RETURN_VALUE_CONDITION
1020  END_CASE
1021  END_VARIANT
1022  END_SUMMARY_WITH_VARIANTS
1023  SUMMARY_WITH_VARIANTS(getdelim)
1024  VARIANT(ARGUMENT_TYPES(Irrelevant, Irrelevant, Irrelevant, Irrelevant),
1025  RETURN_TYPE(IntTy), INVALIDATION_APPROACH(NoEvalCall))
1026  CASE
1027  RETURN_VALUE_CONDITION(WithinRange)
1028  SINGLE_VALUE(-1)
1029  RANGE(1, IntMax)
1030  END_RETURN_VALUE_CONDITION
1031  END_CASE
1032  END_VARIANT
1033  VARIANT(ARGUMENT_TYPES(Irrelevant, Irrelevant, Irrelevant, Irrelevant),
1034  RETURN_TYPE(LongTy), INVALIDATION_APPROACH(NoEvalCall))
1035  CASE
1036  RETURN_VALUE_CONDITION(WithinRange)
1037  SINGLE_VALUE(-1)
1038  RANGE(1, LongMax)
1039  END_RETURN_VALUE_CONDITION
1040  END_CASE
1041  END_VARIANT
1042  VARIANT(ARGUMENT_TYPES(Irrelevant, Irrelevant, Irrelevant, Irrelevant),
1043  RETURN_TYPE(LongLongTy), INVALIDATION_APPROACH(NoEvalCall))
1044  CASE
1045  RETURN_VALUE_CONDITION(WithinRange)
1046  SINGLE_VALUE(-1)
1047  RANGE(1, LongLongMax)
1048  END_RETURN_VALUE_CONDITION
1049  END_CASE
1050  END_VARIANT
1051  END_SUMMARY_WITH_VARIANTS
1052  };
1053 }
1054 
1055 void ento::registerStdCLibraryFunctionsChecker(CheckerManager &mgr) {
1056  // If this checker grows large enough to support C++, Objective-C, or other
1057  // standard libraries, we could use multiple register...Checker() functions,
1058  // which would register various checkers with the help of the same Checker
1059  // class, turning on different function summaries.
1060  mgr.registerChecker<StdLibraryFunctionsChecker>();
1061 }
1062 
1063 bool ento::shouldRegisterStdCLibraryFunctionsChecker(const LangOptions &LO) {
1064  return true;
1065 }
CanQualType LongLongTy
Definition: ASTContext.h:1025
Represents a function declaration or definition.
Definition: Decl.h:1783
A (possibly-)qualified type.
Definition: Type.h:654
Expr * getArg(unsigned Arg)
getArg - Return the specified argument.
Definition: Expr.h:2702
#define END_CASE
unsigned getNumArgs() const
getNumArgs - Return the number of actual arguments to this call.
Definition: Expr.h:2689
#define RETURN_TYPE(x)
ExplodedNode * addTransition(ProgramStateRef State=nullptr, const ProgramPointTag *Tag=nullptr)
Generates a new transition in the program state graph (ExplodedGraph).
CanQualType LongTy
Definition: ASTContext.h:1025
SVal evalCast(SVal val, QualType castTy, QualType originalType)
const Expr * getOriginExpr() const
Returns the expression whose value will be the result of this call.
Definition: CallEvent.h:222
IdentifierInfo * getIdentifier() const
Get the identifier that names this declaration, if there is one.
Definition: Decl.h:244
#define END_SUMMARY
One of these records is kept for each identifier that is lexed.
Holds long-lived AST nodes (such as types and decls) that can be referred to throughout the semantic ...
Definition: ASTContext.h:168
LineState State
virtual const Expr * getArgExpr(unsigned Index) const
Returns the expression associated with a given argument.
Definition: CallEvent.h:272
__DEVICE__ int max(int __a, int __b)
bool isIntegralOrEnumerationType() const
Determine whether this type is an integral or enumeration type.
Definition: Type.h:6881
BinaryOperatorKind
#define END_RETURN_VALUE_CONDITION
#define SUMMARY(identifier, argument_types, return_type, invalidation_approach)
SVal getReturnValue() const
Returns the return value of the call.
Definition: CallEvent.cpp:430
#define RETURN_VALUE_CONDITION(condition_kind)
#define ARG_NO(x)
static bool isCLibraryFunction(const FunctionDecl *FD, StringRef Name=StringRef())
Returns true if the callee is an externally-visible function in the top-level namespace, such as malloc.
#define V(N, I)
Definition: ASTContext.h:2941
QualType getConditionType() const
Definition: SValBuilder.h:160
QualType getType() const
Definition: Expr.h:137
virtual const Decl * getDecl() const
Returns the declaration of the function or method that will be called.
Definition: CallEvent.h:202
SVal evalBinOp(ProgramStateRef state, BinaryOperator::Opcode op, SVal lhs, SVal rhs, QualType type)
bool isNull() const
Return true if this QualType doesn&#39;t point to a type yet.
Definition: Type.h:719
do v
Definition: arm_acle.h:64
Optional< T > getAs() const
Convert to the specified SVal type, returning None if this SVal is not of the desired type...
Definition: SVals.h:111
virtual ProgramStateRef assumeInclusiveRange(ProgramStateRef State, NonLoc Value, const llvm::APSInt &From, const llvm::APSInt &To, bool InBound)=0
bool isComparisonOp() const
Definition: Expr.h:3525
#define RANGE(x, y)
Kind
QualType getCanonicalType() const
Definition: Type.h:6295
DefinedOrUnknownSVal conjureSymbolVal(const void *symbolTag, const Expr *expr, const LocationContext *LCtx, unsigned count)
Create a new symbol with a unique &#39;name&#39;.
#define SINGLE_VALUE(x)
llvm::APSInt APSInt
static bool Ret(InterpState &S, CodePtr &PC, APValue &Result)
Definition: Interp.cpp:34
SVal - This represents a symbolic expression, which can be either an L-value or an R-value...
Definition: SVals.h:75
#define ARGUMENT_CONDITION(argument_number, condition_kind)
#define ARGUMENT_TYPES(...)
constexpr XRayInstrMask None
Definition: XRayInstr.h:37
bool isCanonical() const
Definition: Type.h:6300
unsigned blockCount() const
Returns the number of times the current block has been visited along the analyzed path...
StringRef getName() const
Return the actual identifier string.
Dataflow Directional Tag Classes.
Represents an abstract call to a function or method along a particular path.
Definition: CallEvent.h:138
const llvm::APSInt & getMinValue(const llvm::APSInt &v)
ConstraintManager & getConstraintManager()
Definition: ProgramState.h:533
BasicValueFactory & getBasicValueFactory()
Definition: SValBuilder.h:168
const ProgramStateRef & getState() const
QualType getResultType() const
Returns the result type, adjusted for references.
Definition: CallEvent.cpp:70
bool isVoidType() const
Definition: Type.h:6777
#define CASE
SValBuilder & getSValBuilder()
CallExpr - Represents a function call (C99 6.5.2.2, C++ [expr.call]).
Definition: Expr.h:2546
const llvm::APSInt & getMaxValue(const llvm::APSInt &v)
static Decl::Kind getKind(const Decl *D)
Definition: DeclBase.cpp:947
CanQualType IntTy
Definition: ASTContext.h:1025
#define INVALIDATION_APPROACH(x)
virtual SVal getArgSVal(unsigned Index) const
Returns the value of a given argument at the time of the call.
Definition: CallEvent.cpp:416
#define END_ARGUMENT_CONDITION
const LocationContext * getLocationContext() const
CanQualType getSizeType() const
Return the unique type for "size_t" (C99 7.17), defined in <stddef.h>.