From 4ff7769974614a0c4ef576ffa0ab46a58bb3fef4 Mon Sep 17 00:00:00 2001 From: Kristof Umann Date: Sun, 18 Nov 2018 11:34:10 +0000 Subject: [analyzer][UninitializedObjectChecker] Uninit regions are only reported once Especially with pointees, a lot of meaningless reports came from uninitialized regions that were already reported. This is fixed by storing all reported fields to the GDM. Differential Revision: https://reviews.llvm.org/D51531 llvm-svn: 347153 --- .../UninitializedObjectChecker.cpp | 57 ++++++++++++++++++---- 1 file changed, 48 insertions(+), 9 deletions(-) (limited to 'clang/lib/StaticAnalyzer/Checkers/UninitializedObject/UninitializedObjectChecker.cpp') diff --git a/clang/lib/StaticAnalyzer/Checkers/UninitializedObject/UninitializedObjectChecker.cpp b/clang/lib/StaticAnalyzer/Checkers/UninitializedObject/UninitializedObjectChecker.cpp index e4a17a9dd28..e3942818c6c 100644 --- a/clang/lib/StaticAnalyzer/Checkers/UninitializedObject/UninitializedObjectChecker.cpp +++ b/clang/lib/StaticAnalyzer/Checkers/UninitializedObject/UninitializedObjectChecker.cpp @@ -28,9 +28,14 @@ using namespace clang; using namespace clang::ento; +/// We'll mark fields (and pointee of fields) that are confirmed to be +/// uninitialized as already analyzed. +REGISTER_SET_WITH_PROGRAMSTATE(AnalyzedRegions, const MemRegion *) + namespace { -class UninitializedObjectChecker : public Checker { +class UninitializedObjectChecker + : public Checker { std::unique_ptr BT_uninitField; public: @@ -39,7 +44,9 @@ public: UninitializedObjectChecker() : BT_uninitField(new BuiltinBug(this, "Uninitialized fields")) {} + void checkEndFunction(const ReturnStmt *RS, CheckerContext &C) const; + void checkDeadSymbols(SymbolReaper &SR, CheckerContext &C) const; }; /// A basic field type, that is not a pointer or a reference, it's dynamic and @@ -140,14 +147,20 @@ void UninitializedObjectChecker::checkEndFunction( FindUninitializedFields F(Context.getState(), R, Opts); - const UninitFieldMap &UninitFields = F.getUninitFields(); + std::pair UninitInfo = + F.getResults(); - if (UninitFields.empty()) + ProgramStateRef UpdatedState = UninitInfo.first; + const UninitFieldMap &UninitFields = UninitInfo.second; + + if (UninitFields.empty()) { + Context.addTransition(UpdatedState); return; + } // There are uninitialized fields in the record. - ExplodedNode *Node = Context.generateNonFatalErrorNode(Context.getState()); + ExplodedNode *Node = Context.generateNonFatalErrorNode(UpdatedState); if (!Node) return; @@ -188,6 +201,15 @@ void UninitializedObjectChecker::checkEndFunction( Context.emitReport(std::move(Report)); } +void UninitializedObjectChecker::checkDeadSymbols(SymbolReaper &SR, + CheckerContext &C) const { + ProgramStateRef State = C.getState(); + for (const MemRegion *R : State->get()) { + if (!SR.isLiveRegion(R)) + State = State->remove(R); + } +} + //===----------------------------------------------------------------------===// // Methods for FindUninitializedFields. //===----------------------------------------------------------------------===// @@ -205,17 +227,34 @@ FindUninitializedFields::FindUninitializedFields( UninitFields.clear(); } -bool FindUninitializedFields::addFieldToUninits(FieldChainInfo Chain) { +bool FindUninitializedFields::addFieldToUninits(FieldChainInfo Chain, + const MemRegion *PointeeR) { + const FieldRegion *FR = Chain.getUninitRegion(); + + assert((PointeeR || !isDereferencableType(FR->getDecl()->getType())) && + "One must also pass the pointee region as a parameter for " + "dereferencable fields!"); + + if (State->contains(FR)) + return false; + + if (PointeeR) { + if (State->contains(PointeeR)) { + return false; + } + State = State->add(PointeeR); + } + + State = State->add(FR); + if (State->getStateManager().getContext().getSourceManager().isInSystemHeader( - Chain.getUninitRegion()->getDecl()->getLocation())) + FR->getDecl()->getLocation())) return false; UninitFieldMap::mapped_type NoteMsgBuf; llvm::raw_svector_ostream OS(NoteMsgBuf); Chain.printNoteMsg(OS); - return UninitFields - .insert(std::make_pair(Chain.getUninitRegion(), std::move(NoteMsgBuf))) - .second; + return UninitFields.insert({FR, std::move(NoteMsgBuf)}).second; } bool FindUninitializedFields::isNonUnionUninit(const TypedValueRegion *R, -- cgit v1.2.3