003 File Manager
Current Path:
/usr/src/contrib/llvm-project/clang/lib/StaticAnalyzer/Checkers
usr
/
src
/
contrib
/
llvm-project
/
clang
/
lib
/
StaticAnalyzer
/
Checkers
/
📁
..
📄
AllocationState.h
(1.41 KB)
📄
AnalysisOrderChecker.cpp
(8.62 KB)
📄
AnalyzerStatsChecker.cpp
(5.04 KB)
📄
ArrayBoundChecker.cpp
(3.22 KB)
📄
ArrayBoundCheckerV2.cpp
(13.07 KB)
📄
BasicObjCFoundationChecks.cpp
(43.82 KB)
📄
BlockInCriticalSectionChecker.cpp
(6.69 KB)
📄
BoolAssignmentChecker.cpp
(3.45 KB)
📄
BuiltinFunctionChecker.cpp
(5 KB)
📄
CStringChecker.cpp
(93.24 KB)
📄
CStringSyntaxChecker.cpp
(9.8 KB)
📄
CXXSelfAssignmentChecker.cpp
(3.08 KB)
📄
CallAndMessageChecker.cpp
(26.57 KB)
📄
CastSizeChecker.cpp
(4.96 KB)
📄
CastToStructChecker.cpp
(4.43 KB)
📄
CastValueChecker.cpp
(19.65 KB)
📄
CheckObjCDealloc.cpp
(37.83 KB)
📄
CheckObjCInstMethSignature.cpp
(4.8 KB)
📄
CheckPlacementNew.cpp
(11.91 KB)
📄
CheckSecuritySyntaxOnly.cpp
(38.79 KB)
📄
CheckSizeofPointer.cpp
(3.16 KB)
📄
CheckerDocumentation.cpp
(14.64 KB)
📄
ChrootChecker.cpp
(4.88 KB)
📄
CloneChecker.cpp
(8.28 KB)
📄
ContainerModeling.cpp
(39.85 KB)
📄
ConversionChecker.cpp
(7.11 KB)
📄
DeadStoresChecker.cpp
(17.82 KB)
📄
DebugCheckers.cpp
(10.41 KB)
📄
DebugContainerModeling.cpp
(4.94 KB)
📄
DebugIteratorModeling.cpp
(5.15 KB)
📄
DeleteWithNonVirtualDtorChecker.cpp
(5.35 KB)
📄
DereferenceChecker.cpp
(10.54 KB)
📄
DirectIvarAssignment.cpp
(8.02 KB)
📄
DivZeroChecker.cpp
(3.42 KB)
📄
DynamicTypeChecker.cpp
(7.31 KB)
📄
DynamicTypePropagation.cpp
(42.11 KB)
📄
EnumCastOutOfRangeChecker.cpp
(5.75 KB)
📄
ExprInspectionChecker.cpp
(15.6 KB)
📄
FixedAddressChecker.cpp
(2.33 KB)
📄
FuchsiaHandleChecker.cpp
(23.1 KB)
📄
GCDAntipatternChecker.cpp
(7.85 KB)
📄
GTestChecker.cpp
(10.52 KB)
📄
GenericTaintChecker.cpp
(34.31 KB)
📄
IdenticalExprChecker.cpp
(18.88 KB)
📄
InnerPointerChecker.cpp
(11.54 KB)
📄
InterCheckerAPI.h
(1.09 KB)
📄
InvalidatedIteratorChecker.cpp
(4.93 KB)
📄
Iterator.cpp
(10.62 KB)
📄
Iterator.h
(6.32 KB)
📄
IteratorModeling.cpp
(31.33 KB)
📄
IteratorRangeChecker.cpp
(12.64 KB)
📄
IvarInvalidationChecker.cpp
(27.63 KB)
📄
LLVMConventionsChecker.cpp
(9.9 KB)
📄
LocalizationChecker.cpp
(52.38 KB)
📄
MIGChecker.cpp
(11.3 KB)
📁
MPI-Checker
📄
MacOSKeychainAPIChecker.cpp
(25.21 KB)
📄
MacOSXAPIChecker.cpp
(6.61 KB)
📄
MallocChecker.cpp
(127.38 KB)
📄
MallocOverflowSecurityChecker.cpp
(11.91 KB)
📄
MallocSizeofChecker.cpp
(8.03 KB)
📄
MismatchedIteratorChecker.cpp
(11.01 KB)
📄
MmapWriteExecChecker.cpp
(3.22 KB)
📄
Move.h
(1.07 KB)
📄
MoveChecker.cpp
(27 KB)
📄
NSAutoreleasePoolChecker.cpp
(2.93 KB)
📄
NSErrorChecker.cpp
(10.6 KB)
📄
NoReturnFunctionChecker.cpp
(5.48 KB)
📄
NonNullParamChecker.cpp
(11.22 KB)
📄
NonnullGlobalConstantsChecker.cpp
(5.09 KB)
📄
NullabilityChecker.cpp
(46.95 KB)
📄
NumberObjectConversionChecker.cpp
(13.69 KB)
📄
OSObjectCStyleCast.cpp
(3.14 KB)
📄
ObjCAtSyncChecker.cpp
(3.34 KB)
📄
ObjCAutoreleaseWriteChecker.cpp
(8.62 KB)
📄
ObjCContainersASTChecker.cpp
(5.5 KB)
📄
ObjCContainersChecker.cpp
(6.71 KB)
📄
ObjCMissingSuperCallChecker.cpp
(9.23 KB)
📄
ObjCPropertyChecker.cpp
(3.03 KB)
📄
ObjCSelfInitChecker.cpp
(16.21 KB)
📄
ObjCSuperDeallocChecker.cpp
(9.33 KB)
📄
ObjCUnusedIVarsChecker.cpp
(6.01 KB)
📄
PaddingChecker.cpp
(14.26 KB)
📄
PointerArithChecker.cpp
(12.18 KB)
📄
PointerIterationChecker.cpp
(3.79 KB)
📄
PointerSortingChecker.cpp
(4.5 KB)
📄
PointerSubChecker.cpp
(2.56 KB)
📄
PthreadLockChecker.cpp
(28.42 KB)
📁
RetainCountChecker
📄
ReturnPointerRangeChecker.cpp
(3.39 KB)
📄
ReturnUndefChecker.cpp
(4.1 KB)
📄
ReturnValueChecker.cpp
(5.79 KB)
📄
RunLoopAutoreleaseLeakChecker.cpp
(7.2 KB)
📄
STLAlgorithmModeling.cpp
(7 KB)
📄
SimpleStreamChecker.cpp
(9.43 KB)
📄
SmartPtr.h
(1.17 KB)
📄
SmartPtrChecker.cpp
(2.68 KB)
📄
SmartPtrModeling.cpp
(8.05 KB)
📄
StackAddrEscapeChecker.cpp
(15 KB)
📄
StdLibraryFunctionsChecker.cpp
(74.86 KB)
📄
StreamChecker.cpp
(37.36 KB)
📄
Taint.cpp
(9.04 KB)
📄
Taint.h
(4.19 KB)
📄
TaintTesterChecker.cpp
(2.17 KB)
📄
TestAfterDivZeroChecker.cpp
(8.19 KB)
📄
TraversalChecker.cpp
(4.38 KB)
📄
TrustNonnullChecker.cpp
(9.12 KB)
📄
UndefBranchChecker.cpp
(3.82 KB)
📄
UndefCapturedBlockVarChecker.cpp
(3.64 KB)
📄
UndefResultChecker.cpp
(7.19 KB)
📄
UndefinedArraySubscriptChecker.cpp
(2.36 KB)
📄
UndefinedAssignmentChecker.cpp
(3.74 KB)
📁
UninitializedObject
📄
UnixAPIChecker.cpp
(18.05 KB)
📄
UnreachableCodeChecker.cpp
(9.59 KB)
📄
VLASizeChecker.cpp
(10.95 KB)
📄
ValistChecker.cpp
(15.65 KB)
📄
VforkChecker.cpp
(7.67 KB)
📄
VirtualCallChecker.cpp
(8.11 KB)
📁
WebKit
📄
Yaml.h
(2.06 KB)
📁
cert
Editing: UnreachableCodeChecker.cpp
//==- UnreachableCodeChecker.cpp - Generalized dead code checker -*- C++ -*-==// // // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. // See https://llvm.org/LICENSE.txt for license information. // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// // This file implements a generalized unreachable code checker using a // path-sensitive analysis. We mark any path visited, and then walk the CFG as a // post-analysis to determine what was never visited. // // A similar flow-sensitive only check exists in Analysis/ReachableCode.cpp //===----------------------------------------------------------------------===// #include "clang/StaticAnalyzer/Checkers/BuiltinCheckerRegistration.h" #include "clang/AST/ParentMap.h" #include "clang/Basic/Builtins.h" #include "clang/Basic/SourceManager.h" #include "clang/StaticAnalyzer/Core/BugReporter/BugReporter.h" #include "clang/StaticAnalyzer/Core/Checker.h" #include "clang/StaticAnalyzer/Core/CheckerManager.h" #include "clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h" #include "clang/StaticAnalyzer/Core/PathSensitive/CheckerHelpers.h" #include "clang/StaticAnalyzer/Core/PathSensitive/ExplodedGraph.h" #include "clang/StaticAnalyzer/Core/PathSensitive/SVals.h" #include "llvm/ADT/SmallSet.h" using namespace clang; using namespace ento; namespace { class UnreachableCodeChecker : public Checker<check::EndAnalysis> { public: void checkEndAnalysis(ExplodedGraph &G, BugReporter &B, ExprEngine &Eng) const; private: typedef llvm::SmallSet<unsigned, 32> CFGBlocksSet; static inline const Stmt *getUnreachableStmt(const CFGBlock *CB); static void FindUnreachableEntryPoints(const CFGBlock *CB, CFGBlocksSet &reachable, CFGBlocksSet &visited); static bool isInvalidPath(const CFGBlock *CB, const ParentMap &PM); static inline bool isEmptyCFGBlock(const CFGBlock *CB); }; } void UnreachableCodeChecker::checkEndAnalysis(ExplodedGraph &G, BugReporter &B, ExprEngine &Eng) const { CFGBlocksSet reachable, visited; if (Eng.hasWorkRemaining()) return; const Decl *D = nullptr; CFG *C = nullptr; const ParentMap *PM = nullptr; const LocationContext *LC = nullptr; // Iterate over ExplodedGraph for (ExplodedGraph::node_iterator I = G.nodes_begin(), E = G.nodes_end(); I != E; ++I) { const ProgramPoint &P = I->getLocation(); LC = P.getLocationContext(); if (!LC->inTopFrame()) continue; if (!D) D = LC->getAnalysisDeclContext()->getDecl(); // Save the CFG if we don't have it already if (!C) C = LC->getAnalysisDeclContext()->getUnoptimizedCFG(); if (!PM) PM = &LC->getParentMap(); if (Optional<BlockEntrance> BE = P.getAs<BlockEntrance>()) { const CFGBlock *CB = BE->getBlock(); reachable.insert(CB->getBlockID()); } } // Bail out if we didn't get the CFG or the ParentMap. if (!D || !C || !PM) return; // Don't do anything for template instantiations. Proving that code // in a template instantiation is unreachable means proving that it is // unreachable in all instantiations. if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(D)) if (FD->isTemplateInstantiation()) return; // Find CFGBlocks that were not covered by any node for (CFG::const_iterator I = C->begin(), E = C->end(); I != E; ++I) { const CFGBlock *CB = *I; // Check if the block is unreachable if (reachable.count(CB->getBlockID())) continue; // Check if the block is empty (an artificial block) if (isEmptyCFGBlock(CB)) continue; // Find the entry points for this block if (!visited.count(CB->getBlockID())) FindUnreachableEntryPoints(CB, reachable, visited); // This block may have been pruned; check if we still want to report it if (reachable.count(CB->getBlockID())) continue; // Check for false positives if (isInvalidPath(CB, *PM)) continue; // It is good practice to always have a "default" label in a "switch", even // if we should never get there. It can be used to detect errors, for // instance. Unreachable code directly under a "default" label is therefore // likely to be a false positive. if (const Stmt *label = CB->getLabel()) if (label->getStmtClass() == Stmt::DefaultStmtClass) continue; // Special case for __builtin_unreachable. // FIXME: This should be extended to include other unreachable markers, // such as llvm_unreachable. if (!CB->empty()) { bool foundUnreachable = false; for (CFGBlock::const_iterator ci = CB->begin(), ce = CB->end(); ci != ce; ++ci) { if (Optional<CFGStmt> S = (*ci).getAs<CFGStmt>()) if (const CallExpr *CE = dyn_cast<CallExpr>(S->getStmt())) { if (CE->getBuiltinCallee() == Builtin::BI__builtin_unreachable || CE->isBuiltinAssumeFalse(Eng.getContext())) { foundUnreachable = true; break; } } } if (foundUnreachable) continue; } // We found a block that wasn't covered - find the statement to report SourceRange SR; PathDiagnosticLocation DL; SourceLocation SL; if (const Stmt *S = getUnreachableStmt(CB)) { // In macros, 'do {...} while (0)' is often used. Don't warn about the // condition 0 when it is unreachable. if (S->getBeginLoc().isMacroID()) if (const auto *I = dyn_cast<IntegerLiteral>(S)) if (I->getValue() == 0ULL) if (const Stmt *Parent = PM->getParent(S)) if (isa<DoStmt>(Parent)) continue; SR = S->getSourceRange(); DL = PathDiagnosticLocation::createBegin(S, B.getSourceManager(), LC); SL = DL.asLocation(); if (SR.isInvalid() || !SL.isValid()) continue; } else continue; // Check if the SourceLocation is in a system header const SourceManager &SM = B.getSourceManager(); if (SM.isInSystemHeader(SL) || SM.isInExternCSystemHeader(SL)) continue; B.EmitBasicReport(D, this, "Unreachable code", "Dead code", "This statement is never executed", DL, SR); } } // Recursively finds the entry point(s) for this dead CFGBlock. void UnreachableCodeChecker::FindUnreachableEntryPoints(const CFGBlock *CB, CFGBlocksSet &reachable, CFGBlocksSet &visited) { visited.insert(CB->getBlockID()); for (CFGBlock::const_pred_iterator I = CB->pred_begin(), E = CB->pred_end(); I != E; ++I) { if (!*I) continue; if (!reachable.count((*I)->getBlockID())) { // If we find an unreachable predecessor, mark this block as reachable so // we don't report this block reachable.insert(CB->getBlockID()); if (!visited.count((*I)->getBlockID())) // If we haven't previously visited the unreachable predecessor, recurse FindUnreachableEntryPoints(*I, reachable, visited); } } } // Find the Stmt* in a CFGBlock for reporting a warning const Stmt *UnreachableCodeChecker::getUnreachableStmt(const CFGBlock *CB) { for (CFGBlock::const_iterator I = CB->begin(), E = CB->end(); I != E; ++I) { if (Optional<CFGStmt> S = I->getAs<CFGStmt>()) { if (!isa<DeclStmt>(S->getStmt())) return S->getStmt(); } } if (const Stmt *S = CB->getTerminatorStmt()) return S; else return nullptr; } // Determines if the path to this CFGBlock contained an element that infers this // block is a false positive. We assume that FindUnreachableEntryPoints has // already marked only the entry points to any dead code, so we need only to // find the condition that led to this block (the predecessor of this block.) // There will never be more than one predecessor. bool UnreachableCodeChecker::isInvalidPath(const CFGBlock *CB, const ParentMap &PM) { // We only expect a predecessor size of 0 or 1. If it is >1, then an external // condition has broken our assumption (for example, a sink being placed by // another check). In these cases, we choose not to report. if (CB->pred_size() > 1) return true; // If there are no predecessors, then this block is trivially unreachable if (CB->pred_size() == 0) return false; const CFGBlock *pred = *CB->pred_begin(); if (!pred) return false; // Get the predecessor block's terminator condition const Stmt *cond = pred->getTerminatorCondition(); //assert(cond && "CFGBlock's predecessor has a terminator condition"); // The previous assertion is invalid in some cases (eg do/while). Leaving // reporting of these situations on at the moment to help triage these cases. if (!cond) return false; // Run each of the checks on the conditions return containsMacro(cond) || containsEnum(cond) || containsStaticLocal(cond) || containsBuiltinOffsetOf(cond) || containsStmt<UnaryExprOrTypeTraitExpr>(cond); } // Returns true if the given CFGBlock is empty bool UnreachableCodeChecker::isEmptyCFGBlock(const CFGBlock *CB) { return CB->getLabel() == nullptr // No labels && CB->size() == 0 // No statements && !CB->getTerminatorStmt(); // No terminator } void ento::registerUnreachableCodeChecker(CheckerManager &mgr) { mgr.registerChecker<UnreachableCodeChecker>(); } bool ento::shouldRegisterUnreachableCodeChecker(const CheckerManager &mgr) { return true; }
Upload File
Create Folder