diff options
| author | Kristof Umann <dkszelethus@gmail.com> | 2018-11-18 11:34:10 +0000 |
|---|---|---|
| committer | Kristof Umann <dkszelethus@gmail.com> | 2018-11-18 11:34:10 +0000 |
| commit | 4ff7769974614a0c4ef576ffa0ab46a58bb3fef4 (patch) | |
| tree | e93bffcdde424bddc7be17457cf8d4c66ca663c8 /clang/lib/StaticAnalyzer/Checkers/UninitializedObject/UninitializedObjectChecker.cpp | |
| parent | fe90e2bc5bf279dfae668b29434d0f3ece3e1d1f (diff) | |
| download | bcm5719-llvm-4ff7769974614a0c4ef576ffa0ab46a58bb3fef4.tar.gz bcm5719-llvm-4ff7769974614a0c4ef576ffa0ab46a58bb3fef4.zip | |
[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
Diffstat (limited to 'clang/lib/StaticAnalyzer/Checkers/UninitializedObject/UninitializedObjectChecker.cpp')
| -rw-r--r-- | clang/lib/StaticAnalyzer/Checkers/UninitializedObject/UninitializedObjectChecker.cpp | 57 |
1 files changed, 48 insertions, 9 deletions
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<check::EndFunction> { +class UninitializedObjectChecker + : public Checker<check::EndFunction, check::DeadSymbols> { std::unique_ptr<BuiltinBug> 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<ProgramStateRef, const UninitFieldMap &> 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<AnalyzedRegions>()) { + if (!SR.isLiveRegion(R)) + State = State->remove<AnalyzedRegions>(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<AnalyzedRegions>(FR)) + return false; + + if (PointeeR) { + if (State->contains<AnalyzedRegions>(PointeeR)) { + return false; + } + State = State->add<AnalyzedRegions>(PointeeR); + } + + State = State->add<AnalyzedRegions>(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, |

