clang  9.0.0svn
UninitializedObjectChecker.cpp
Go to the documentation of this file.
1 //===----- UninitializedObjectChecker.cpp ------------------------*- 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 file defines a checker that reports uninitialized fields in objects
10 // created after a constructor call.
11 //
12 // To read about command line options and how the checker works, refer to the
13 // top of the file and inline comments in UninitializedObject.h.
14 //
15 // Some of the logic is implemented in UninitializedPointee.cpp, to reduce the
16 // complexity of this file.
17 //
18 //===----------------------------------------------------------------------===//
19 
21 #include "UninitializedObject.h"
27 
28 using namespace clang;
29 using namespace clang::ento;
30 using namespace clang::ast_matchers;
31 
32 /// We'll mark fields (and pointee of fields) that are confirmed to be
33 /// uninitialized as already analyzed.
34 REGISTER_SET_WITH_PROGRAMSTATE(AnalyzedRegions, const MemRegion *)
35 
36 namespace {
37 
38 class UninitializedObjectChecker
39  : public Checker<check::EndFunction, check::DeadSymbols> {
40  std::unique_ptr<BuiltinBug> BT_uninitField;
41 
42 public:
43  // The fields of this struct will be initialized when registering the checker.
45 
46  UninitializedObjectChecker()
47  : BT_uninitField(new BuiltinBug(this, "Uninitialized fields")) {}
48 
49  void checkEndFunction(const ReturnStmt *RS, CheckerContext &C) const;
50  void checkDeadSymbols(SymbolReaper &SR, CheckerContext &C) const;
51 };
52 
53 /// A basic field type, that is not a pointer or a reference, it's dynamic and
54 /// static type is the same.
55 class RegularField final : public FieldNode {
56 public:
57  RegularField(const FieldRegion *FR) : FieldNode(FR) {}
58 
59  virtual void printNoteMsg(llvm::raw_ostream &Out) const override {
60  Out << "uninitialized field ";
61  }
62 
63  virtual void printPrefix(llvm::raw_ostream &Out) const override {}
64 
65  virtual void printNode(llvm::raw_ostream &Out) const override {
66  Out << getVariableName(getDecl());
67  }
68 
69  virtual void printSeparator(llvm::raw_ostream &Out) const override {
70  Out << '.';
71  }
72 };
73 
74 /// Represents that the FieldNode that comes after this is declared in a base
75 /// of the previous FieldNode. As such, this descendant doesn't wrap a
76 /// FieldRegion, and is purely a tool to describe a relation between two other
77 /// FieldRegion wrapping descendants.
78 class BaseClass final : public FieldNode {
79  const QualType BaseClassT;
80 
81 public:
82  BaseClass(const QualType &T) : FieldNode(nullptr), BaseClassT(T) {
83  assert(!T.isNull());
84  assert(T->getAsCXXRecordDecl());
85  }
86 
87  virtual void printNoteMsg(llvm::raw_ostream &Out) const override {
88  llvm_unreachable("This node can never be the final node in the "
89  "fieldchain!");
90  }
91 
92  virtual void printPrefix(llvm::raw_ostream &Out) const override {}
93 
94  virtual void printNode(llvm::raw_ostream &Out) const override {
95  Out << BaseClassT->getAsCXXRecordDecl()->getName() << "::";
96  }
97 
98  virtual void printSeparator(llvm::raw_ostream &Out) const override {}
99 
100  virtual bool isBase() const override { return true; }
101 };
102 
103 } // end of anonymous namespace
104 
105 // Utility function declarations.
106 
107 /// Returns the region that was constructed by CtorDecl, or nullptr if that
108 /// isn't possible.
109 static const TypedValueRegion *
111  CheckerContext &Context);
112 
113 /// Checks whether the object constructed by \p Ctor will be analyzed later
114 /// (e.g. if the object is a field of another object, in which case we'd check
115 /// it multiple times).
116 static bool willObjectBeAnalyzedLater(const CXXConstructorDecl *Ctor,
117  CheckerContext &Context);
118 
119 /// Checks whether RD contains a field with a name or type name that matches
120 /// \p Pattern.
121 static bool shouldIgnoreRecord(const RecordDecl *RD, StringRef Pattern);
122 
123 /// Checks _syntactically_ whether it is possible to access FD from the record
124 /// that contains it without a preceding assert (even if that access happens
125 /// inside a method). This is mainly used for records that act like unions, like
126 /// having multiple bit fields, with only a fraction being properly initialized.
127 /// If these fields are properly guarded with asserts, this method returns
128 /// false.
129 ///
130 /// Since this check is done syntactically, this method could be inaccurate.
131 static bool hasUnguardedAccess(const FieldDecl *FD, ProgramStateRef State);
132 
133 //===----------------------------------------------------------------------===//
134 // Methods for UninitializedObjectChecker.
135 //===----------------------------------------------------------------------===//
136 
137 void UninitializedObjectChecker::checkEndFunction(
138  const ReturnStmt *RS, CheckerContext &Context) const {
139 
140  const auto *CtorDecl = dyn_cast_or_null<CXXConstructorDecl>(
141  Context.getLocationContext()->getDecl());
142  if (!CtorDecl)
143  return;
144 
145  if (!CtorDecl->isUserProvided())
146  return;
147 
148  if (CtorDecl->getParent()->isUnion())
149  return;
150 
151  // This avoids essentially the same error being reported multiple times.
152  if (willObjectBeAnalyzedLater(CtorDecl, Context))
153  return;
154 
155  const TypedValueRegion *R = getConstructedRegion(CtorDecl, Context);
156  if (!R)
157  return;
158 
159  FindUninitializedFields F(Context.getState(), R, Opts);
160 
161  std::pair<ProgramStateRef, const UninitFieldMap &> UninitInfo =
162  F.getResults();
163 
164  ProgramStateRef UpdatedState = UninitInfo.first;
165  const UninitFieldMap &UninitFields = UninitInfo.second;
166 
167  if (UninitFields.empty()) {
168  Context.addTransition(UpdatedState);
169  return;
170  }
171 
172  // There are uninitialized fields in the record.
173 
174  ExplodedNode *Node = Context.generateNonFatalErrorNode(UpdatedState);
175  if (!Node)
176  return;
177 
178  PathDiagnosticLocation LocUsedForUniqueing;
179  const Stmt *CallSite = Context.getStackFrame()->getCallSite();
180  if (CallSite)
181  LocUsedForUniqueing = PathDiagnosticLocation::createBegin(
182  CallSite, Context.getSourceManager(), Node->getLocationContext());
183 
184  // For Plist consumers that don't support notes just yet, we'll convert notes
185  // to warnings.
186  if (Opts.ShouldConvertNotesToWarnings) {
187  for (const auto &Pair : UninitFields) {
188 
189  auto Report = llvm::make_unique<BugReport>(
190  *BT_uninitField, Pair.second, Node, LocUsedForUniqueing,
191  Node->getLocationContext()->getDecl());
192  Context.emitReport(std::move(Report));
193  }
194  return;
195  }
196 
197  SmallString<100> WarningBuf;
198  llvm::raw_svector_ostream WarningOS(WarningBuf);
199  WarningOS << UninitFields.size() << " uninitialized field"
200  << (UninitFields.size() == 1 ? "" : "s")
201  << " at the end of the constructor call";
202 
203  auto Report = llvm::make_unique<BugReport>(
204  *BT_uninitField, WarningOS.str(), Node, LocUsedForUniqueing,
205  Node->getLocationContext()->getDecl());
206 
207  for (const auto &Pair : UninitFields) {
208  Report->addNote(Pair.second,
209  PathDiagnosticLocation::create(Pair.first->getDecl(),
210  Context.getSourceManager()));
211  }
212  Context.emitReport(std::move(Report));
213 }
214 
215 void UninitializedObjectChecker::checkDeadSymbols(SymbolReaper &SR,
216  CheckerContext &C) const {
218  for (const MemRegion *R : State->get<AnalyzedRegions>()) {
219  if (!SR.isLiveRegion(R))
220  State = State->remove<AnalyzedRegions>(R);
221  }
222 }
223 
224 //===----------------------------------------------------------------------===//
225 // Methods for FindUninitializedFields.
226 //===----------------------------------------------------------------------===//
227 
229  ProgramStateRef State, const TypedValueRegion *const R,
230  const UninitObjCheckerOptions &Opts)
231  : State(State), ObjectR(R), Opts(Opts) {
232 
233  isNonUnionUninit(ObjectR, FieldChainInfo(ChainFactory));
234 
235  // In non-pedantic mode, if ObjectR doesn't contain a single initialized
236  // field, we'll assume that Object was intentionally left uninitialized.
237  if (!Opts.IsPedantic && !isAnyFieldInitialized())
238  UninitFields.clear();
239 }
240 
241 bool FindUninitializedFields::addFieldToUninits(FieldChainInfo Chain,
242  const MemRegion *PointeeR) {
243  const FieldRegion *FR = Chain.getUninitRegion();
244 
245  assert((PointeeR || !isDereferencableType(FR->getDecl()->getType())) &&
246  "One must also pass the pointee region as a parameter for "
247  "dereferenceable fields!");
248 
249  if (State->getStateManager().getContext().getSourceManager().isInSystemHeader(
250  FR->getDecl()->getLocation()))
251  return false;
252 
253  if (Opts.IgnoreGuardedFields && !hasUnguardedAccess(FR->getDecl(), State))
254  return false;
255 
256  if (State->contains<AnalyzedRegions>(FR))
257  return false;
258 
259  if (PointeeR) {
260  if (State->contains<AnalyzedRegions>(PointeeR)) {
261  return false;
262  }
263  State = State->add<AnalyzedRegions>(PointeeR);
264  }
265 
266  State = State->add<AnalyzedRegions>(FR);
267 
268  UninitFieldMap::mapped_type NoteMsgBuf;
269  llvm::raw_svector_ostream OS(NoteMsgBuf);
270  Chain.printNoteMsg(OS);
271 
272  return UninitFields.insert({FR, std::move(NoteMsgBuf)}).second;
273 }
274 
275 bool FindUninitializedFields::isNonUnionUninit(const TypedValueRegion *R,
276  FieldChainInfo LocalChain) {
277  assert(R->getValueType()->isRecordType() &&
278  !R->getValueType()->isUnionType() &&
279  "This method only checks non-union record objects!");
280 
281  const RecordDecl *RD = R->getValueType()->getAsRecordDecl()->getDefinition();
282 
283  if (!RD) {
284  IsAnyFieldInitialized = true;
285  return true;
286  }
287 
288  if (!Opts.IgnoredRecordsWithFieldPattern.empty() &&
290  IsAnyFieldInitialized = true;
291  return false;
292  }
293 
294  bool ContainsUninitField = false;
295 
296  // Are all of this non-union's fields initialized?
297  for (const FieldDecl *I : RD->fields()) {
298 
299  const auto FieldVal =
300  State->getLValue(I, loc::MemRegionVal(R)).castAs<loc::MemRegionVal>();
301  const auto *FR = FieldVal.getRegionAs<FieldRegion>();
302  QualType T = I->getType();
303 
304  // If LocalChain already contains FR, then we encountered a cyclic
305  // reference. In this case, region FR is already under checking at an
306  // earlier node in the directed tree.
307  if (LocalChain.contains(FR))
308  return false;
309 
310  if (T->isStructureOrClassType()) {
311  if (isNonUnionUninit(FR, LocalChain.add(RegularField(FR))))
312  ContainsUninitField = true;
313  continue;
314  }
315 
316  if (T->isUnionType()) {
317  if (isUnionUninit(FR)) {
318  if (addFieldToUninits(LocalChain.add(RegularField(FR))))
319  ContainsUninitField = true;
320  } else
321  IsAnyFieldInitialized = true;
322  continue;
323  }
324 
325  if (T->isArrayType()) {
326  IsAnyFieldInitialized = true;
327  continue;
328  }
329 
330  SVal V = State->getSVal(FieldVal);
331 
333  if (isDereferencableUninit(FR, LocalChain))
334  ContainsUninitField = true;
335  continue;
336  }
337 
338  if (isPrimitiveType(T)) {
339  if (isPrimitiveUninit(V)) {
340  if (addFieldToUninits(LocalChain.add(RegularField(FR))))
341  ContainsUninitField = true;
342  }
343  continue;
344  }
345 
346  llvm_unreachable("All cases are handled!");
347  }
348 
349  // Checking bases. The checker will regard inherited data members as direct
350  // fields.
351  const auto *CXXRD = dyn_cast<CXXRecordDecl>(RD);
352  if (!CXXRD)
353  return ContainsUninitField;
354 
355  for (const CXXBaseSpecifier &BaseSpec : CXXRD->bases()) {
356  const auto *BaseRegion = State->getLValue(BaseSpec, R)
357  .castAs<loc::MemRegionVal>()
358  .getRegionAs<TypedValueRegion>();
359 
360  // If the head of the list is also a BaseClass, we'll overwrite it to avoid
361  // note messages like 'this->A::B::x'.
362  if (!LocalChain.isEmpty() && LocalChain.getHead().isBase()) {
363  if (isNonUnionUninit(BaseRegion, LocalChain.replaceHead(
364  BaseClass(BaseSpec.getType()))))
365  ContainsUninitField = true;
366  } else {
367  if (isNonUnionUninit(BaseRegion,
368  LocalChain.add(BaseClass(BaseSpec.getType()))))
369  ContainsUninitField = true;
370  }
371  }
372 
373  return ContainsUninitField;
374 }
375 
376 bool FindUninitializedFields::isUnionUninit(const TypedValueRegion *R) {
377  assert(R->getValueType()->isUnionType() &&
378  "This method only checks union objects!");
379  // TODO: Implement support for union fields.
380  return false;
381 }
382 
383 bool FindUninitializedFields::isPrimitiveUninit(const SVal &V) {
384  if (V.isUndef())
385  return true;
386 
387  IsAnyFieldInitialized = true;
388  return false;
389 }
390 
391 //===----------------------------------------------------------------------===//
392 // Methods for FieldChainInfo.
393 //===----------------------------------------------------------------------===//
394 
395 bool FieldChainInfo::contains(const FieldRegion *FR) const {
396  for (const FieldNode &Node : Chain) {
397  if (Node.isSameRegion(FR))
398  return true;
399  }
400  return false;
401 }
402 
403 /// Prints every element except the last to `Out`. Since ImmutableLists store
404 /// elements in reverse order, and have no reverse iterators, we use a
405 /// recursive function to print the fieldchain correctly. The last element in
406 /// the chain is to be printed by `FieldChainInfo::print`.
407 static void printTail(llvm::raw_ostream &Out,
409 
410 // FIXME: This function constructs an incorrect string in the following case:
411 //
412 // struct Base { int x; };
413 // struct D1 : Base {}; struct D2 : Base {};
414 //
415 // struct MostDerived : D1, D2 {
416 // MostDerived() {}
417 // }
418 //
419 // A call to MostDerived::MostDerived() will cause two notes that say
420 // "uninitialized field 'this->x'", but we can't refer to 'x' directly,
421 // we need an explicit namespace resolution whether the uninit field was
422 // 'D1::x' or 'D2::x'.
423 void FieldChainInfo::printNoteMsg(llvm::raw_ostream &Out) const {
424  if (Chain.isEmpty())
425  return;
426 
427  const FieldNode &LastField = getHead();
428 
429  LastField.printNoteMsg(Out);
430  Out << '\'';
431 
432  for (const FieldNode &Node : Chain)
433  Node.printPrefix(Out);
434 
435  Out << "this->";
436  printTail(Out, Chain.getTail());
437  LastField.printNode(Out);
438  Out << '\'';
439 }
440 
441 static void printTail(llvm::raw_ostream &Out,
442  const FieldChainInfo::FieldChain L) {
443  if (L.isEmpty())
444  return;
445 
446  printTail(Out, L.getTail());
447 
448  L.getHead().printNode(Out);
449  L.getHead().printSeparator(Out);
450 }
451 
452 //===----------------------------------------------------------------------===//
453 // Utility functions.
454 //===----------------------------------------------------------------------===//
455 
456 static const TypedValueRegion *
458  CheckerContext &Context) {
459 
460  Loc ThisLoc =
461  Context.getSValBuilder().getCXXThis(CtorDecl, Context.getStackFrame());
462 
463  SVal ObjectV = Context.getState()->getSVal(ThisLoc);
464 
465  auto *R = ObjectV.getAsRegion()->getAs<TypedValueRegion>();
466  if (R && !R->getValueType()->getAsCXXRecordDecl())
467  return nullptr;
468 
469  return R;
470 }
471 
473  CheckerContext &Context) {
474 
475  const TypedValueRegion *CurrRegion = getConstructedRegion(Ctor, Context);
476  if (!CurrRegion)
477  return false;
478 
479  const LocationContext *LC = Context.getLocationContext();
480  while ((LC = LC->getParent())) {
481 
482  // If \p Ctor was called by another constructor.
483  const auto *OtherCtor = dyn_cast<CXXConstructorDecl>(LC->getDecl());
484  if (!OtherCtor)
485  continue;
486 
487  const TypedValueRegion *OtherRegion =
488  getConstructedRegion(OtherCtor, Context);
489  if (!OtherRegion)
490  continue;
491 
492  // If the CurrRegion is a subregion of OtherRegion, it will be analyzed
493  // during the analysis of OtherRegion.
494  if (CurrRegion->isSubRegionOf(OtherRegion))
495  return true;
496  }
497 
498  return false;
499 }
500 
501 static bool shouldIgnoreRecord(const RecordDecl *RD, StringRef Pattern) {
502  llvm::Regex R(Pattern);
503 
504  for (const FieldDecl *FD : RD->fields()) {
505  if (R.match(FD->getType().getAsString()))
506  return true;
507  if (R.match(FD->getName()))
508  return true;
509  }
510 
511  return false;
512 }
513 
514 static const Stmt *getMethodBody(const CXXMethodDecl *M) {
515  if (isa<CXXConstructorDecl>(M))
516  return nullptr;
517 
518  if (!M->isDefined())
519  return nullptr;
520 
521  return M->getDefinition()->getBody();
522 }
523 
524 static bool hasUnguardedAccess(const FieldDecl *FD, ProgramStateRef State) {
525 
527  return true;
528 
529  const auto *Parent = dyn_cast<CXXRecordDecl>(FD->getParent());
530 
531  if (!Parent)
532  return true;
533 
534  Parent = Parent->getDefinition();
535  assert(Parent && "The record's definition must be avaible if an uninitialized"
536  " field of it was found!");
537 
538  ASTContext &AC = State->getStateManager().getContext();
539 
540  auto FieldAccessM = memberExpr(hasDeclaration(equalsNode(FD))).bind("access");
541 
542  auto AssertLikeM = callExpr(callee(functionDecl(
543  anyOf(hasName("exit"), hasName("panic"), hasName("error"),
544  hasName("Assert"), hasName("assert"), hasName("ziperr"),
545  hasName("assfail"), hasName("db_error"), hasName("__assert"),
546  hasName("__assert2"), hasName("_wassert"), hasName("__assert_rtn"),
547  hasName("__assert_fail"), hasName("dtrace_assfail"),
548  hasName("yy_fatal_error"), hasName("_XCAssertionFailureHandler"),
549  hasName("_DTAssertionFailureHandler"),
550  hasName("_TSAssertionFailureHandler")))));
551 
552  auto NoReturnFuncM = callExpr(callee(functionDecl(isNoReturn())));
553 
554  auto GuardM =
555  stmt(anyOf(ifStmt(), switchStmt(), conditionalOperator(), AssertLikeM,
556  NoReturnFuncM))
557  .bind("guard");
558 
559  for (const CXXMethodDecl *M : Parent->methods()) {
560  const Stmt *MethodBody = getMethodBody(M);
561  if (!MethodBody)
562  continue;
563 
564  auto Accesses = match(stmt(hasDescendant(FieldAccessM)), *MethodBody, AC);
565  if (Accesses.empty())
566  continue;
567  const auto *FirstAccess = Accesses[0].getNodeAs<MemberExpr>("access");
568  assert(FirstAccess);
569 
570  auto Guards = match(stmt(hasDescendant(GuardM)), *MethodBody, AC);
571  if (Guards.empty())
572  return true;
573  const auto *FirstGuard = Guards[0].getNodeAs<Stmt>("guard");
574  assert(FirstGuard);
575 
576  if (FirstAccess->getBeginLoc() < FirstGuard->getBeginLoc())
577  return true;
578  }
579 
580  return false;
581 }
582 
583 std::string clang::ento::getVariableName(const FieldDecl *Field) {
584  // If Field is a captured lambda variable, Field->getName() will return with
585  // an empty string. We can however acquire it's name from the lambda's
586  // captures.
587  const auto *CXXParent = dyn_cast<CXXRecordDecl>(Field->getParent());
588 
589  if (CXXParent && CXXParent->isLambda()) {
590  assert(CXXParent->captures_begin());
591  auto It = CXXParent->captures_begin() + Field->getFieldIndex();
592 
593  if (It->capturesVariable())
594  return llvm::Twine("/*captured variable*/" +
595  It->getCapturedVar()->getName())
596  .str();
597 
598  if (It->capturesThis())
599  return "/*'this' capture*/";
600 
601  llvm_unreachable("No other capture type is expected!");
602  }
603 
604  return Field->getName();
605 }
606 
607 void ento::registerUninitializedObjectChecker(CheckerManager &Mgr) {
608  auto Chk = Mgr.registerChecker<UninitializedObjectChecker>();
609 
610  AnalyzerOptions &AnOpts = Mgr.getAnalyzerOptions();
611  UninitObjCheckerOptions &ChOpts = Chk->Opts;
612 
613  ChOpts.IsPedantic =
614  AnOpts.getCheckerBooleanOption("Pedantic", /*DefaultVal*/ false, Chk);
616  AnOpts.getCheckerBooleanOption("NotesAsWarnings",
617  /*DefaultVal*/ false, Chk);
618  ChOpts.CheckPointeeInitialization = AnOpts.getCheckerBooleanOption(
619  "CheckPointeeInitialization", /*DefaultVal*/ false, Chk);
621  AnOpts.getCheckerStringOption("IgnoreRecordsWithField",
622  /*DefaultVal*/ "", Chk);
623  ChOpts.IgnoreGuardedFields =
624  AnOpts.getCheckerBooleanOption("IgnoreGuardedFields",
625  /*DefaultVal*/ false, Chk);
626 }
627 
628 bool ento::shouldRegisterUninitializedObjectChecker(const LangOptions &LO) {
629  return true;
630 }
FunctionDecl * getDefinition()
Get the definition for this declaration.
Definition: Decl.h:1954
const internal::VariadicDynCastAllOfMatcher< Stmt, CallExpr > callExpr
Matches call expressions.
TypedValueRegion - An abstract class representing regions having a typed value.
Definition: MemRegion.h:529
A (possibly-)qualified type.
Definition: Type.h:634
MemRegion - The root abstract class for all memory regions.
Definition: MemRegion.h:94
const internal::VariadicAllOfMatcher< Stmt > stmt
Matches statements.
const FieldRegion * getUninitRegion() const
Stmt - This represents one statement.
Definition: Stmt.h:65
internal::PolymorphicMatcherWithParam1< internal::HasDeclarationMatcher, internal::Matcher< Decl >, void(internal::HasDeclarationSupportedTypes)> hasDeclaration(const internal::Matcher< Decl > &InnerMatcher)
Matches a node if the declaration associated with that node matches the given matcher.
Definition: ASTMatchers.h:2864
const REGION * getRegionAs() const
Definition: SVals.h:610
bool isRecordType() const
Definition: Type.h:6374
const internal::VariadicOperatorMatcherFunc< 2, std::numeric_limits< unsigned >::max()> anyOf
Matches if any of the given matchers matches.
ExplodedNode * addTransition(ProgramStateRef State=nullptr, const ProgramPointTag *Tag=nullptr)
Generates a new transition in the program state graph (ExplodedGraph).
virtual QualType getValueType() const =0
bool contains(const FieldRegion *FR) const
bool isPrimitiveType(const QualType &T)
Returns true if T is a primitive type.
unsigned getFieldIndex() const
Returns the index of this field within its record, as appropriate for passing to ASTRecordLayout::get...
Definition: Decl.cpp:3802
const internal::ArgumentAdaptingMatcherFunc< internal::HasDescendantMatcher > hasDescendant
Matches AST nodes that have descendant AST nodes that match the provided matcher. ...
const RecordDecl * getParent() const
Returns the parent of this field declaration, which is the struct in which this field is defined...
Definition: Decl.h:2762
bool isDefined(const FunctionDecl *&Definition) const
Returns true if the function has a definition that does not need to be instantiated.
Definition: Decl.cpp:2719
Represents a C++ constructor within a class.
Definition: DeclCXX.h:2491
bool isAnyFieldInitialized()
Returns whether the analyzed region contains at least one initialized field.
static bool hasUnguardedAccess(const FieldDecl *FD, ProgramStateRef State)
Checks syntactically whether it is possible to access FD from the record that contains it without a p...
loc::MemRegionVal getCXXThis(const CXXMethodDecl *D, const StackFrameContext *SFC)
Return a memory region for the &#39;this&#39; object reference.
const internal::VariadicDynCastAllOfMatcher< Decl, FunctionDecl > functionDecl
Matches function declarations.
Represents a struct/union/class.
Definition: Decl.h:3592
Holds long-lived AST nodes (such as types and decls) that can be referred to throughout the semantic ...
Definition: ASTContext.h:154
LineState State
RecordDecl * getDefinition() const
Returns the RecordDecl that actually defines this struct/union/class.
Definition: Decl.h:3773
FieldChainInfo add(const FieldNodeT &FN)
Constructs a new FieldChainInfo object with FN appended.
field_range fields() const
Definition: Decl.h:3783
const FieldDecl * getDecl() const
Definition: MemRegion.h:1016
const FieldNode & getHead() const
Represents a member of a struct/union/class.
Definition: Decl.h:2578
static void printTail(llvm::raw_ostream &Out, const FieldChainInfo::FieldChain L)
Prints every element except the last to Out.
Keeps track of the various options that can be enabled, which controls the dialect of C or C++ that i...
Definition: LangOptions.h:49
Stmt * getBody(const FunctionDecl *&Definition) const
Retrieve the body (definition) of the function.
Definition: Decl.cpp:2730
FindUninitializedFields(ProgramStateRef State, const TypedValueRegion *const R, const UninitObjCheckerOptions &Opts)
Constructs the FindUninitializedField object, searches for and stores uninitialized fields in R...
const internal::VariadicDynCastAllOfMatcher< Stmt, IfStmt > ifStmt
Matches if statements.
bool isLiveRegion(const MemRegion *region)
static bool willObjectBeAnalyzedLater(const CXXConstructorDecl *Ctor, CheckerContext &Context)
Checks whether the object constructed by Ctor will be analyzed later (e.g.
const LocationContext * getLocationContext() const
const LocationContext * getParent() const
virtual void printNode(llvm::raw_ostream &Out) const =0
Print the node. Should contain the name of the field stored in FR.
static PathDiagnosticLocation create(const Decl *D, const SourceManager &SM)
Create a location corresponding to the given declaration.
bool isDereferencableType(const QualType &T)
SmallVector< BoundNodes, 1 > match(MatcherT Matcher, const NodeT &Node, ASTContext &Context)
Returns the results of matching Matcher on Node.
NodeId Parent
Definition: ASTDiff.cpp:191
static const TypedValueRegion * getConstructedRegion(const CXXConstructorDecl *CtorDecl, CheckerContext &Context)
Returns the region that was constructed by CtorDecl, or nullptr if that isn&#39;t possible.
RecordDecl * getAsRecordDecl() const
Retrieves the RecordDecl this type refers to.
Definition: Type.cpp:1617
return Out str()
CXXRecordDecl * getAsCXXRecordDecl() const
Retrieves the CXXRecordDecl that this type refers to, either because the type is a RecordType or beca...
Definition: Type.cpp:1613
const Stmt * getCallSite() const
const RegionTy * getAs() const
Definition: MemRegion.h:1227
virtual void printNoteMsg(llvm::raw_ostream &Out) const =0
If this is the last element of the fieldchain, this method will print the note message associated wit...
const internal::VariadicDynCastAllOfMatcher< Stmt, MemberExpr > memberExpr
Matches member expressions.
const internal::VariadicDynCastAllOfMatcher< Stmt, SwitchStmt > switchStmt
Matches switch statements.
std::string getVariableName(const FieldDecl *Field)
Returns with Field&#39;s name.
Searches for and stores uninitialized fields in a non-union object.
const internal::VariadicDynCastAllOfMatcher< Stmt, ConditionalOperator > conditionalOperator
Matches conditional operator expressions.
ReturnStmt - This represents a return, optionally of an expression: return; return 4;...
Definition: Stmt.h:2462
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:475
bool isNull() const
Return true if this QualType doesn&#39;t point to a type yet.
Definition: Type.h:699
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
void emitReport(std::unique_ptr< BugReport > R)
Emit the diagnostics report.
static PathDiagnosticLocation createBegin(const Decl *D, const SourceManager &SM)
Create a location for the beginning of the declaration.
CHECKER * registerChecker(AT &&... Args)
Used to register checkers.
const MemRegion * getAsRegion() const
Definition: SVals.cpp:150
bool isSubRegionOf(const MemRegion *R) const override
Check if the region is a subregion of the given region.
Definition: MemRegion.cpp:132
Represents a static or instance method of a struct/union/class.
Definition: DeclCXX.h:2048
static bool shouldIgnoreRecord(const RecordDecl *RD, StringRef Pattern)
Checks whether RD contains a field with a name or type name that matches Pattern. ...
SVal - This represents a symbolic expression, which can be either an L-value or an R-value...
Definition: SVals.h:75
A class responsible for cleaning up unused symbols.
virtual bool isBase() const
Represents a field chain.
ast_type_traits::DynTypedNode Node
#define REGISTER_SET_WITH_PROGRAMSTATE(Name, Elem)
Declares an immutable set of type NameTy, suitable for placement into the ProgramState.
Dataflow Directional Tag Classes.
AccessSpecifier getAccess() const
Definition: DeclBase.h:464
static const Stmt * getMethodBody(const CXXMethodDecl *M)
AnalyzerOptions & getAnalyzerOptions()
llvm::ImmutableList< const FieldNode & > FieldChain
const Decl * getDecl() const
std::map< const FieldRegion *, llvm::SmallString< 50 > > UninitFieldMap
const StackFrameContext * getStackFrame() const
Indicates that the tracking object is a descendant of a referenced-counted OSObject, used in the Darwin kernel.
const ProgramStateRef & getState() const
Stores options for the analyzer from the command line.
Represents a base class of a C++ class.
Definition: DeclCXX.h:191
FieldChainInfo replaceHead(const FieldNodeT &FN)
Constructs a new FieldChainInfo object with FN as the new head of the list.
A lightweight polymorphic wrapper around FieldRegion *.
MemberExpr - [C99 6.5.2.3] Structure and Union Members.
Definition: Expr.h:2720
Represents a C++ struct/union/class.
Definition: DeclCXX.h:299
std::pair< ProgramStateRef, const UninitFieldMap & > getResults()
Returns with the modified state and a map of (uninitialized region, note message) pairs...
SourceManager & getSourceManager()
internal::Matcher< NamedDecl > hasName(const std::string &Name)
Matches NamedDecl nodes that have the specified name.
Definition: ASTMatchers.h:2525
SValBuilder & getSValBuilder()
bool isUndef() const
Definition: SVals.h:140
StringRef getName() const
Get the name of identifier for this declaration as a StringRef.
Definition: Decl.h:275
capture_const_iterator captures_begin() const
Definition: DeclCXX.h:1251
QualType getType() const
Definition: Decl.h:647
const LocationContext * getLocationContext() const
SourceLocation getLocation() const
Definition: DeclBase.h:420
void printNoteMsg(llvm::raw_ostream &Out) const