clang  7.0.0
UninitializedObjectChecker.cpp
Go to the documentation of this file.
1 //===----- UninitializedObjectChecker.cpp ------------------------*- C++ -*-==//
2 //
3 // The LLVM Compiler Infrastructure
4 //
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
7 //
8 //===----------------------------------------------------------------------===//
9 //
10 // This file defines a checker that reports uninitialized fields in objects
11 // created after a constructor call.
12 //
13 // This checker has two options:
14 // - "Pedantic" (boolean). If its not set or is set to false, the checker
15 // won't emit warnings for objects that don't have at least one initialized
16 // field. This may be set with
17 //
18 // `-analyzer-config alpha.cplusplus.UninitializedObject:Pedantic=true`.
19 //
20 // - "NotesAsWarnings" (boolean). If set to true, the checker will emit a
21 // warning for each uninitalized field, as opposed to emitting one warning
22 // per constructor call, and listing the uninitialized fields that belongs
23 // to it in notes. Defaults to false.
24 //
25 // `-analyzer-config alpha.cplusplus.UninitializedObject:NotesAsWarnings=true`.
26 //
27 //===----------------------------------------------------------------------===//
28 
29 #include "ClangSACheckers.h"
33 #include <algorithm>
34 
35 using namespace clang;
36 using namespace clang::ento;
37 
38 namespace {
39 
40 class UninitializedObjectChecker : public Checker<check::EndFunction> {
41  std::unique_ptr<BuiltinBug> BT_uninitField;
42 
43 public:
44  // These fields will be initialized when registering the checker.
45  bool IsPedantic;
46  bool ShouldConvertNotesToWarnings;
47 
48  UninitializedObjectChecker()
49  : BT_uninitField(new BuiltinBug(this, "Uninitialized fields")) {}
50  void checkEndFunction(const ReturnStmt *RS, CheckerContext &C) const;
51 };
52 
53 /// Represents a field chain. A field chain is a vector of fields where the
54 /// first element of the chain is the object under checking (not stored), and
55 /// every other element is a field, and the element that precedes it is the
56 /// object that contains it.
57 ///
58 /// Note that this class is immutable, and new fields may only be added through
59 /// constructor calls.
60 class FieldChainInfo {
61  using FieldChain = llvm::ImmutableList<const FieldRegion *>;
62 
63  FieldChain Chain;
64 
65  const bool IsDereferenced = false;
66 
67 public:
68  FieldChainInfo() = default;
69 
70  FieldChainInfo(const FieldChainInfo &Other, const bool IsDereferenced)
71  : Chain(Other.Chain), IsDereferenced(IsDereferenced) {}
72 
73  FieldChainInfo(const FieldChainInfo &Other, const FieldRegion *FR,
74  const bool IsDereferenced = false);
75 
76  bool contains(const FieldRegion *FR) const { return Chain.contains(FR); }
77  bool isPointer() const;
78 
79  /// If this is a fieldchain whose last element is an uninitialized region of a
80  /// pointer type, `IsDereferenced` will store whether the pointer itself or
81  /// the pointee is uninitialized.
82  bool isDereferenced() const;
83  const FieldDecl *getEndOfChain() const;
84  void print(llvm::raw_ostream &Out) const;
85 
86 private:
87  /// Prints every element except the last to `Out`. Since ImmutableLists store
88  /// elements in reverse order, and have no reverse iterators, we use a
89  /// recursive function to print the fieldchain correctly. The last element in
90  /// the chain is to be printed by `print`.
91  static void printTail(llvm::raw_ostream &Out,
92  const llvm::ImmutableListImpl<const FieldRegion *> *L);
93  friend struct FieldChainInfoComparator;
94 };
95 
96 struct FieldChainInfoComparator {
97  bool operator()(const FieldChainInfo &lhs, const FieldChainInfo &rhs) const {
98  assert(!lhs.Chain.isEmpty() && !rhs.Chain.isEmpty() &&
99  "Attempted to store an empty fieldchain!");
100  return *lhs.Chain.begin() < *rhs.Chain.begin();
101  }
102 };
103 
104 using UninitFieldSet = std::set<FieldChainInfo, FieldChainInfoComparator>;
105 
106 /// Searches for and stores uninitialized fields in a non-union object.
107 class FindUninitializedFields {
109  const TypedValueRegion *const ObjectR;
110 
111  const bool IsPedantic;
112  bool IsAnyFieldInitialized = false;
113 
114  UninitFieldSet UninitFields;
115 
116 public:
117  FindUninitializedFields(ProgramStateRef State,
118  const TypedValueRegion *const R, bool IsPedantic);
119  const UninitFieldSet &getUninitFields();
120 
121 private:
122  /// Adds a FieldChainInfo object to UninitFields. Return true if an insertion
123  /// took place.
124  bool addFieldToUninits(FieldChainInfo LocalChain);
125 
126  // For the purposes of this checker, we'll regard the object under checking as
127  // a directed tree, where
128  // * the root is the object under checking
129  // * every node is an object that is
130  // - a union
131  // - a non-union record
132  // - a pointer/reference
133  // - an array
134  // - of a primitive type, which we'll define later in a helper function.
135  // * the parent of each node is the object that contains it
136  // * every leaf is an array, a primitive object, a nullptr or an undefined
137  // pointer.
138  //
139  // Example:
140  //
141  // struct A {
142  // struct B {
143  // int x, y = 0;
144  // };
145  // B b;
146  // int *iptr = new int;
147  // B* bptr;
148  //
149  // A() {}
150  // };
151  //
152  // The directed tree:
153  //
154  // ->x
155  // /
156  // ->b--->y
157  // /
158  // A-->iptr->(int value)
159  // \
160  // ->bptr
161  //
162  // From this we'll construct a vector of fieldchains, where each fieldchain
163  // represents an uninitialized field. An uninitialized field may be a
164  // primitive object, a pointer, a pointee or a union without a single
165  // initialized field.
166  // In the above example, for the default constructor call we'll end up with
167  // these fieldchains:
168  //
169  // this->b.x
170  // this->iptr (pointee uninit)
171  // this->bptr (pointer uninit)
172  //
173  // We'll traverse each node of the above graph with the appropiate one of
174  // these methods:
175 
176  /// This method checks a region of a union object, and returns true if no
177  /// field is initialized within the region.
178  bool isUnionUninit(const TypedValueRegion *R);
179 
180  /// This method checks a region of a non-union object, and returns true if
181  /// an uninitialized field is found within the region.
182  bool isNonUnionUninit(const TypedValueRegion *R, FieldChainInfo LocalChain);
183 
184  /// This method checks a region of a pointer or reference object, and returns
185  /// true if the ptr/ref object itself or any field within the pointee's region
186  /// is uninitialized.
187  bool isPointerOrReferenceUninit(const FieldRegion *FR,
188  FieldChainInfo LocalChain);
189 
190  /// This method returns true if the value of a primitive object is
191  /// uninitialized.
192  bool isPrimitiveUninit(const SVal &V);
193 
194  // Note that we don't have a method for arrays -- the elements of an array are
195  // often left uninitialized intentionally even when it is of a C++ record
196  // type, so we'll assume that an array is always initialized.
197  // TODO: Add a support for nonloc::LocAsInteger.
198 };
199 
200 } // end of anonymous namespace
201 
202 // Static variable instantionations.
203 
204 static llvm::ImmutableListFactory<const FieldRegion *> Factory;
205 
206 // Utility function declarations.
207 
208 /// Returns the object that was constructed by CtorDecl, or None if that isn't
209 /// possible.
211 getObjectVal(const CXXConstructorDecl *CtorDecl, CheckerContext &Context);
212 
213 /// Checks whether the constructor under checking is called by another
214 /// constructor.
215 static bool isCalledByConstructor(const CheckerContext &Context);
216 
217 /// Returns whether FD can be (transitively) dereferenced to a void pointer type
218 /// (void*, void**, ...). The type of the region behind a void pointer isn't
219 /// known, and thus FD can not be analyzed.
220 static bool isVoidPointer(const FieldDecl *FD);
221 
222 /// Returns true if T is a primitive type. We defined this type so that for
223 /// objects that we'd only like analyze as much as checking whether their
224 /// value is undefined or not, such as ints and doubles, can be analyzed with
225 /// ease. This also helps ensuring that every special field type is handled
226 /// correctly.
227 static bool isPrimitiveType(const QualType &T) {
228  return T->isBuiltinType() || T->isEnumeralType() || T->isMemberPointerType();
229 }
230 
231 /// Constructs a note message for a given FieldChainInfo object.
232 static void printNoteMessage(llvm::raw_ostream &Out,
233  const FieldChainInfo &Chain);
234 
235 /// Returns with Field's name. This is a helper function to get the correct name
236 /// even if Field is a captured lambda variable.
237 static StringRef getVariableName(const FieldDecl *Field);
238 
239 //===----------------------------------------------------------------------===//
240 // Methods for UninitializedObjectChecker.
241 //===----------------------------------------------------------------------===//
242 
243 void UninitializedObjectChecker::checkEndFunction(
244  const ReturnStmt *RS, CheckerContext &Context) const {
245 
246  const auto *CtorDecl = dyn_cast_or_null<CXXConstructorDecl>(
247  Context.getLocationContext()->getDecl());
248  if (!CtorDecl)
249  return;
250 
251  if (!CtorDecl->isUserProvided())
252  return;
253 
254  if (CtorDecl->getParent()->isUnion())
255  return;
256 
257  // This avoids essentially the same error being reported multiple times.
258  if (isCalledByConstructor(Context))
259  return;
260 
261  Optional<nonloc::LazyCompoundVal> Object = getObjectVal(CtorDecl, Context);
262  if (!Object)
263  return;
264 
265  FindUninitializedFields F(Context.getState(), Object->getRegion(),
266  IsPedantic);
267 
268  const UninitFieldSet &UninitFields = F.getUninitFields();
269 
270  if (UninitFields.empty())
271  return;
272 
273  // There are uninitialized fields in the record.
274 
275  ExplodedNode *Node = Context.generateNonFatalErrorNode(Context.getState());
276  if (!Node)
277  return;
278 
279  PathDiagnosticLocation LocUsedForUniqueing;
280  const Stmt *CallSite = Context.getStackFrame()->getCallSite();
281  if (CallSite)
282  LocUsedForUniqueing = PathDiagnosticLocation::createBegin(
283  CallSite, Context.getSourceManager(), Node->getLocationContext());
284 
285  // For Plist consumers that don't support notes just yet, we'll convert notes
286  // to warnings.
287  if (ShouldConvertNotesToWarnings) {
288  for (const auto &Chain : UninitFields) {
289  SmallString<100> WarningBuf;
290  llvm::raw_svector_ostream WarningOS(WarningBuf);
291 
292  printNoteMessage(WarningOS, Chain);
293 
294  auto Report = llvm::make_unique<BugReport>(
295  *BT_uninitField, WarningOS.str(), Node, LocUsedForUniqueing,
296  Node->getLocationContext()->getDecl());
297  Context.emitReport(std::move(Report));
298  }
299  return;
300  }
301 
302  SmallString<100> WarningBuf;
303  llvm::raw_svector_ostream WarningOS(WarningBuf);
304  WarningOS << UninitFields.size() << " uninitialized field"
305  << (UninitFields.size() == 1 ? "" : "s")
306  << " at the end of the constructor call";
307 
308  auto Report = llvm::make_unique<BugReport>(
309  *BT_uninitField, WarningOS.str(), Node, LocUsedForUniqueing,
310  Node->getLocationContext()->getDecl());
311 
312  for (const auto &Chain : UninitFields) {
313  SmallString<200> NoteBuf;
314  llvm::raw_svector_ostream NoteOS(NoteBuf);
315 
316  printNoteMessage(NoteOS, Chain);
317 
318  Report->addNote(NoteOS.str(),
319  PathDiagnosticLocation::create(Chain.getEndOfChain(),
320  Context.getSourceManager()));
321  }
322  Context.emitReport(std::move(Report));
323 }
324 
325 //===----------------------------------------------------------------------===//
326 // Methods for FindUninitializedFields.
327 //===----------------------------------------------------------------------===//
328 
329 FindUninitializedFields::FindUninitializedFields(
330  ProgramStateRef State, const TypedValueRegion *const R, bool IsPedantic)
331  : State(State), ObjectR(R), IsPedantic(IsPedantic) {}
332 
333 const UninitFieldSet &FindUninitializedFields::getUninitFields() {
334  isNonUnionUninit(ObjectR, FieldChainInfo());
335 
336  if (!IsPedantic && !IsAnyFieldInitialized)
337  UninitFields.clear();
338 
339  return UninitFields;
340 }
341 
342 bool FindUninitializedFields::addFieldToUninits(FieldChainInfo Chain) {
343  if (State->getStateManager().getContext().getSourceManager().isInSystemHeader(
344  Chain.getEndOfChain()->getLocation()))
345  return false;
346 
347  return UninitFields.insert(Chain).second;
348 }
349 
350 bool FindUninitializedFields::isNonUnionUninit(const TypedValueRegion *R,
351  FieldChainInfo LocalChain) {
352  assert(R->getValueType()->isRecordType() &&
353  !R->getValueType()->isUnionType() &&
354  "This method only checks non-union record objects!");
355 
356  const RecordDecl *RD =
357  R->getValueType()->getAs<RecordType>()->getDecl()->getDefinition();
358  assert(RD && "Referred record has no definition");
359 
360  bool ContainsUninitField = false;
361 
362  // Are all of this non-union's fields initialized?
363  for (const FieldDecl *I : RD->fields()) {
364 
365  const auto FieldVal =
366  State->getLValue(I, loc::MemRegionVal(R)).castAs<loc::MemRegionVal>();
367  const auto *FR = FieldVal.getRegionAs<FieldRegion>();
368  QualType T = I->getType();
369 
370  // If LocalChain already contains FR, then we encountered a cyclic
371  // reference. In this case, region FR is already under checking at an
372  // earlier node in the directed tree.
373  if (LocalChain.contains(FR))
374  return false;
375 
376  if (T->isStructureOrClassType()) {
377  if (isNonUnionUninit(FR, {LocalChain, FR}))
378  ContainsUninitField = true;
379  continue;
380  }
381 
382  if (T->isUnionType()) {
383  if (isUnionUninit(FR)) {
384  if (addFieldToUninits({LocalChain, FR}))
385  ContainsUninitField = true;
386  } else
387  IsAnyFieldInitialized = true;
388  continue;
389  }
390 
391  if (T->isArrayType()) {
392  IsAnyFieldInitialized = true;
393  continue;
394  }
395 
396  if (T->isPointerType() || T->isReferenceType()) {
397  if (isPointerOrReferenceUninit(FR, LocalChain))
398  ContainsUninitField = true;
399  continue;
400  }
401 
402  if (isPrimitiveType(T)) {
403  SVal V = State->getSVal(FieldVal);
404 
405  if (isPrimitiveUninit(V)) {
406  if (addFieldToUninits({LocalChain, FR}))
407  ContainsUninitField = true;
408  }
409  continue;
410  }
411 
412  llvm_unreachable("All cases are handled!");
413  }
414 
415  // Checking bases.
416  // FIXME: As of now, because of `isCalledByConstructor`, objects whose type
417  // is a descendant of another type will emit warnings for uninitalized
418  // inherited members.
419  // This is not the only way to analyze bases of an object -- if we didn't
420  // filter them out, and didn't analyze the bases, this checker would run for
421  // each base of the object in order of base initailization and in theory would
422  // find every uninitalized field. This approach could also make handling
423  // diamond inheritances more easily.
424  //
425  // This rule (that a descendant type's cunstructor is responsible for
426  // initializing inherited data members) is not obvious, and should it should
427  // be.
428  const auto *CXXRD = dyn_cast<CXXRecordDecl>(RD);
429  if (!CXXRD)
430  return ContainsUninitField;
431 
432  for (const CXXBaseSpecifier &BaseSpec : CXXRD->bases()) {
433  const auto *BaseRegion = State->getLValue(BaseSpec, R)
434  .castAs<loc::MemRegionVal>()
435  .getRegionAs<TypedValueRegion>();
436 
437  if (isNonUnionUninit(BaseRegion, LocalChain))
438  ContainsUninitField = true;
439  }
440 
441  return ContainsUninitField;
442 }
443 
444 bool FindUninitializedFields::isUnionUninit(const TypedValueRegion *R) {
445  assert(R->getValueType()->isUnionType() &&
446  "This method only checks union objects!");
447  // TODO: Implement support for union fields.
448  return false;
449 }
450 
451 // Note that pointers/references don't contain fields themselves, so in this
452 // function we won't add anything to LocalChain.
453 bool FindUninitializedFields::isPointerOrReferenceUninit(
454  const FieldRegion *FR, FieldChainInfo LocalChain) {
455 
456  assert((FR->getDecl()->getType()->isPointerType() ||
457  FR->getDecl()->getType()->isReferenceType()) &&
458  "This method only checks pointer/reference objects!");
459 
460  SVal V = State->getSVal(FR);
461 
462  if (V.isUnknown() || V.isZeroConstant()) {
463  IsAnyFieldInitialized = true;
464  return false;
465  }
466 
467  if (V.isUndef()) {
468  return addFieldToUninits({LocalChain, FR});
469  }
470 
471  const FieldDecl *FD = FR->getDecl();
472 
473  // TODO: The dynamic type of a void pointer may be retrieved with
474  // `getDynamicTypeInfo`.
475  if (isVoidPointer(FD)) {
476  IsAnyFieldInitialized = true;
477  return false;
478  }
479 
480  assert(V.getAs<Loc>() && "V should be Loc at this point!");
481 
482  // At this point the pointer itself is initialized and points to a valid
483  // location, we'll now check the pointee.
484  SVal DerefdV = State->getSVal(V.castAs<Loc>());
485 
486  // TODO: Dereferencing should be done according to the dynamic type.
487  while (Optional<Loc> L = DerefdV.getAs<Loc>()) {
488  DerefdV = State->getSVal(*L);
489  }
490 
491  // If V is a pointer pointing to a record type.
493  DerefdV.getAs<nonloc::LazyCompoundVal>()) {
494 
495  const TypedValueRegion *R = RecordV->getRegion();
496 
497  // We can't reason about symbolic regions, assume its initialized.
498  // Note that this also avoids a potential infinite recursion, because
499  // constructors for list-like classes are checked without being called, and
500  // the Static Analyzer will construct a symbolic region for Node *next; or
501  // similar code snippets.
502  if (R->getSymbolicBase()) {
503  IsAnyFieldInitialized = true;
504  return false;
505  }
506 
507  const QualType T = R->getValueType();
508 
509  if (T->isStructureOrClassType())
510  return isNonUnionUninit(R, {LocalChain, FR});
511 
512  if (T->isUnionType()) {
513  if (isUnionUninit(R)) {
514  return addFieldToUninits({LocalChain, FR, /*IsDereferenced*/ true});
515  } else {
516  IsAnyFieldInitialized = true;
517  return false;
518  }
519  }
520 
521  if (T->isArrayType()) {
522  IsAnyFieldInitialized = true;
523  return false;
524  }
525 
526  llvm_unreachable("All cases are handled!");
527  }
528 
529  // TODO: If possible, it should be asserted that the DerefdV at this point is
530  // primitive.
531 
532  if (isPrimitiveUninit(DerefdV))
533  return addFieldToUninits({LocalChain, FR, /*IsDereferenced*/ true});
534 
535  IsAnyFieldInitialized = true;
536  return false;
537 }
538 
539 bool FindUninitializedFields::isPrimitiveUninit(const SVal &V) {
540  if (V.isUndef())
541  return true;
542 
543  IsAnyFieldInitialized = true;
544  return false;
545 }
546 
547 //===----------------------------------------------------------------------===//
548 // Methods for FieldChainInfo.
549 //===----------------------------------------------------------------------===//
550 
551 FieldChainInfo::FieldChainInfo(const FieldChainInfo &Other,
552  const FieldRegion *FR, const bool IsDereferenced)
553  : FieldChainInfo(Other, IsDereferenced) {
554  assert(!contains(FR) && "Can't add a field that is already a part of the "
555  "fieldchain! Is this a cyclic reference?");
556  Chain = Factory.add(FR, Other.Chain);
557 }
558 
559 bool FieldChainInfo::isPointer() const {
560  assert(!Chain.isEmpty() && "Empty fieldchain!");
561  return (*Chain.begin())->getDecl()->getType()->isPointerType();
562 }
563 
564 bool FieldChainInfo::isDereferenced() const {
565  assert(isPointer() && "Only pointers may or may not be dereferenced!");
566  return IsDereferenced;
567 }
568 
569 const FieldDecl *FieldChainInfo::getEndOfChain() const {
570  assert(!Chain.isEmpty() && "Empty fieldchain!");
571  return (*Chain.begin())->getDecl();
572 }
573 
574 // TODO: This function constructs an incorrect fieldchain string in the
575 // following case:
576 //
577 // struct Base { int x; };
578 // struct D1 : Base {}; struct D2 : Base {};
579 //
580 // struct MostDerived : D1, D2 {
581 // MostDerived() {}
582 // }
583 //
584 // A call to MostDerived::MostDerived() will cause two notes that say
585 // "uninitialized field 'this->x'", but we can't refer to 'x' directly,
586 // we need an explicit namespace resolution whether the uninit field was
587 // 'D1::x' or 'D2::x'.
588 void FieldChainInfo::print(llvm::raw_ostream &Out) const {
589  if (Chain.isEmpty())
590  return;
591 
592  const llvm::ImmutableListImpl<const FieldRegion *> *L =
593  Chain.getInternalPointer();
594  printTail(Out, L->getTail());
595  Out << getVariableName(L->getHead()->getDecl());
596 }
597 
598 void FieldChainInfo::printTail(
599  llvm::raw_ostream &Out,
600  const llvm::ImmutableListImpl<const FieldRegion *> *L) {
601  if (!L)
602  return;
603 
604  printTail(Out, L->getTail());
605  const FieldDecl *Field = L->getHead()->getDecl();
606  Out << getVariableName(Field);
607  Out << (Field->getType()->isPointerType() ? "->" : ".");
608 }
609 
610 //===----------------------------------------------------------------------===//
611 // Utility functions.
612 //===----------------------------------------------------------------------===//
613 
614 static bool isVoidPointer(const FieldDecl *FD) {
615  QualType T = FD->getType();
616 
617  while (!T.isNull()) {
618  if (T->isVoidPointerType())
619  return true;
620  T = T->getPointeeType();
621  }
622  return false;
623 }
624 
626 getObjectVal(const CXXConstructorDecl *CtorDecl, CheckerContext &Context) {
627 
628  Loc ThisLoc = Context.getSValBuilder().getCXXThis(CtorDecl->getParent(),
629  Context.getStackFrame());
630  // Getting the value for 'this'.
631  SVal This = Context.getState()->getSVal(ThisLoc);
632 
633  // Getting the value for '*this'.
634  SVal Object = Context.getState()->getSVal(This.castAs<Loc>());
635 
636  return Object.getAs<nonloc::LazyCompoundVal>();
637 }
638 
639 // TODO: We should also check that if the constructor was called by another
640 // constructor, whether those two are in any relation to one another. In it's
641 // current state, this introduces some false negatives.
642 static bool isCalledByConstructor(const CheckerContext &Context) {
643  const LocationContext *LC = Context.getLocationContext()->getParent();
644 
645  while (LC) {
646  if (isa<CXXConstructorDecl>(LC->getDecl()))
647  return true;
648 
649  LC = LC->getParent();
650  }
651  return false;
652 }
653 
654 static void printNoteMessage(llvm::raw_ostream &Out,
655  const FieldChainInfo &Chain) {
656  if (Chain.isPointer()) {
657  if (Chain.isDereferenced())
658  Out << "uninitialized pointee 'this->";
659  else
660  Out << "uninitialized pointer 'this->";
661  } else
662  Out << "uninitialized field 'this->";
663  Chain.print(Out);
664  Out << "'";
665 }
666 
667 static StringRef getVariableName(const FieldDecl *Field) {
668  // If Field is a captured lambda variable, Field->getName() will return with
669  // an empty string. We can however acquire it's name from the lambda's
670  // captures.
671  const auto *CXXParent = dyn_cast<CXXRecordDecl>(Field->getParent());
672 
673  if (CXXParent && CXXParent->isLambda()) {
674  assert(CXXParent->captures_begin());
675  auto It = CXXParent->captures_begin() + Field->getFieldIndex();
676  return It->getCapturedVar()->getName();
677  }
678 
679  return Field->getName();
680 }
681 
682 void ento::registerUninitializedObjectChecker(CheckerManager &Mgr) {
683  auto Chk = Mgr.registerChecker<UninitializedObjectChecker>();
684  Chk->IsPedantic = Mgr.getAnalyzerOptions().getBooleanOption(
685  "Pedantic", /*DefaultVal*/ false, Chk);
686  Chk->ShouldConvertNotesToWarnings = Mgr.getAnalyzerOptions().getBooleanOption(
687  "NotesAsWarnings", /*DefaultVal*/ false, Chk);
688 }
TypedValueRegion - An abstract class representing regions having a typed value.
Definition: MemRegion.h:525
static StringRef getVariableName(const FieldDecl *Field)
Returns with Field&#39;s name.
A (possibly-)qualified type.
Definition: Type.h:655
bool isArrayType() const
Definition: Type.h:6162
bool isMemberPointerType() const
Definition: Type.h:6144
Stmt - This represents one statement.
Definition: Stmt.h:66
QualType getPointeeType() const
If this is a pointer, ObjC object pointer, or block pointer, this returns the respective pointee...
Definition: Type.cpp:497
const REGION * getRegionAs() const
Definition: SVals.h:613
bool isRecordType() const
Definition: Type.h:6186
virtual QualType getValueType() const =0
unsigned getFieldIndex() const
Returns the index of this field within its record, as appropriate for passing to ASTRecordLayout::get...
Definition: Decl.cpp:3727
const RecordDecl * getParent() const
Returns the parent of this field declaration, which is the struct in which this field is defined...
Definition: Decl.h:2718
Represents a C++ constructor within a class.
Definition: DeclCXX.h:2477
bool isEnumeralType() const
Definition: Type.h:6190
const T * getAs() const
Member-template getAs<specific type>&#39;.
Definition: Type.h:6526
loc::MemRegionVal getCXXThis(const CXXMethodDecl *D, const StackFrameContext *SFC)
Return a memory region for the &#39;this&#39; object reference.
Represents a struct/union/class.
Definition: Decl.h:3570
const SymbolicRegion * getSymbolicBase() const
If this is a symbolic region, returns the region.
Definition: MemRegion.cpp:1174
LineState State
const FieldDecl * getDecl() const
Definition: MemRegion.h:1010
Represents a member of a struct/union/class.
Definition: Decl.h:2534
bool isReferenceType() const
Definition: Type.h:6125
static bool isCalledByConstructor(const CheckerContext &Context)
Checks whether the constructor under checking is called by another constructor.
const LocationContext * getLocationContext() const
const LocationContext * getParent() const
bool isUnknown() const
Definition: SVals.h:137
static PathDiagnosticLocation create(const Decl *D, const SourceManager &SM)
Create a location corresponding to the given declaration.
static Optional< nonloc::LazyCompoundVal > getObjectVal(const CXXConstructorDecl *CtorDecl, CheckerContext &Context)
Returns the object that was constructed by CtorDecl, or None if that isn&#39;t possible.
const Stmt * getCallSite() const
ReturnStmt - This represents a return, optionally of an expression: return; return 4;...
Definition: Stmt.h:1476
ExplodedNode * generateNonFatalErrorNode(ProgramStateRef State=nullptr, const ProgramPointTag *Tag=nullptr)
Generate a transition to a node that will be used to report an error.
bool isUnionType() const
Definition: Type.cpp:467
bool isNull() const
Return true if this QualType doesn&#39;t point to a type yet.
Definition: Type.h:720
bool getBooleanOption(StringRef Name, bool DefaultVal, const ento::CheckerBase *C=nullptr, bool SearchInParents=false)
Interprets an option&#39;s string value as a boolean.
Optional< T > getAs() const
Convert to the specified SVal type, returning None if this SVal is not of the desired type...
Definition: SVals.h:112
CHECKER * registerChecker(AT... Args)
Used to register checkers.
bool isVoidPointerType() const
Definition: Type.cpp:461
void emitReport(std::unique_ptr< BugReport > R)
Emit the diagnostics report.
bool isStructureOrClassType() const
Definition: Type.cpp:453
static PathDiagnosticLocation createBegin(const Decl *D, const SourceManager &SM)
Create a location for the beginning of the declaration.
static bool isVoidPointer(const FieldDecl *FD)
Returns whether FD can be (transitively) dereferenced to a void pointer type (void*, void**, ...).
bool isBuiltinType() const
Helper methods to distinguish type categories.
Definition: Type.h:6182
SVal - This represents a symbolic expression, which can be either an L-value or an R-value...
Definition: SVals.h:76
ast_type_traits::DynTypedNode Node
static void printNoteMessage(llvm::raw_ostream &Out, const FieldChainInfo &Chain)
Constructs a note message for a given FieldChainInfo object.
Dataflow Directional Tag Classes.
bool isZeroConstant() const
Definition: SVals.cpp:230
const CXXRecordDecl * getParent() const
Returns the parent of this method declaration, which is the class in which this method is defined...
Definition: DeclCXX.h:2165
static bool isPrimitiveType(const QualType &T)
Returns true if T is a primitive type.
AnalyzerOptions & getAnalyzerOptions()
const Decl * getDecl() const
const StackFrameContext * getStackFrame() const
A helper class that allows the use of isa/cast/dyncast to detect TagType objects of structs/unions/cl...
Definition: Type.h:4135
T castAs() const
Convert to the specified SVal type, asserting that this SVal is of the desired type.
Definition: SVals.h:104
const ProgramStateRef & getState() const
Represents a base class of a C++ class.
Definition: DeclCXX.h:192
Represents a C++ struct/union/class.
Definition: DeclCXX.h:302
SourceManager & getSourceManager()
SValBuilder & getSValBuilder()
bool isUndef() const
Definition: SVals.h:141
StringRef getName() const
Get the name of identifier for this declaration as a StringRef.
Definition: Decl.h:275
bool isPointerType() const
Definition: Type.h:6113
static llvm::ImmutableListFactory< const FieldRegion * > Factory
capture_const_iterator captures_begin() const
Definition: DeclCXX.h:1256
QualType getType() const
Definition: Decl.h:648
const LocationContext * getLocationContext() const