1c4b5bd89e1ef611c7a31b767763030acc45274c8Tom Care//==- UnreachableCodeChecker.cpp - Generalized dead code checker -*- C++ -*-==// 2c4b5bd89e1ef611c7a31b767763030acc45274c8Tom Care// 3c4b5bd89e1ef611c7a31b767763030acc45274c8Tom Care// The LLVM Compiler Infrastructure 4c4b5bd89e1ef611c7a31b767763030acc45274c8Tom Care// 5c4b5bd89e1ef611c7a31b767763030acc45274c8Tom Care// This file is distributed under the University of Illinois Open Source 6c4b5bd89e1ef611c7a31b767763030acc45274c8Tom Care// License. See LICENSE.TXT for details. 7c4b5bd89e1ef611c7a31b767763030acc45274c8Tom Care// 8c4b5bd89e1ef611c7a31b767763030acc45274c8Tom Care//===----------------------------------------------------------------------===// 9c4b5bd89e1ef611c7a31b767763030acc45274c8Tom Care// This file implements a generalized unreachable code checker using a 10c4b5bd89e1ef611c7a31b767763030acc45274c8Tom Care// path-sensitive analysis. We mark any path visited, and then walk the CFG as a 11c4b5bd89e1ef611c7a31b767763030acc45274c8Tom Care// post-analysis to determine what was never visited. 12c4b5bd89e1ef611c7a31b767763030acc45274c8Tom Care// 135e04bdde8e74d991feffe9cf95d731f7e473dbb7Jordy Rose// A similar flow-sensitive only check exists in Analysis/ReachableCode.cpp 14c4b5bd89e1ef611c7a31b767763030acc45274c8Tom Care//===----------------------------------------------------------------------===// 15c4b5bd89e1ef611c7a31b767763030acc45274c8Tom Care 16a0decc9a2481f938e1675b4f7bbd58761a882a36Argyrios Kyrtzidis#include "ClangSACheckers.h" 17ec8605f1d7ec846dbf51047bfd5c56d32d1ff91cArgyrios Kyrtzidis#include "clang/StaticAnalyzer/Core/Checker.h" 18695fb502825a53ccd178ec1c85c77929d88acb71Argyrios Kyrtzidis#include "clang/StaticAnalyzer/Core/CheckerManager.h" 1930726c6baee1417307236e854f1474fdb3cedb98Argyrios Kyrtzidis#include "clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h" 209b663716449b618ba0390b1dbebc54fa8e971124Ted Kremenek#include "clang/StaticAnalyzer/Core/PathSensitive/ExplodedGraph.h" 219b663716449b618ba0390b1dbebc54fa8e971124Ted Kremenek#include "clang/StaticAnalyzer/Core/PathSensitive/SVals.h" 229b663716449b618ba0390b1dbebc54fa8e971124Ted Kremenek#include "clang/StaticAnalyzer/Core/PathSensitive/CheckerHelpers.h" 239b663716449b618ba0390b1dbebc54fa8e971124Ted Kremenek#include "clang/StaticAnalyzer/Core/BugReporter/BugReporter.h" 2430726c6baee1417307236e854f1474fdb3cedb98Argyrios Kyrtzidis#include "clang/AST/ParentMap.h" 2530726c6baee1417307236e854f1474fdb3cedb98Argyrios Kyrtzidis#include "clang/Basic/Builtins.h" 2630726c6baee1417307236e854f1474fdb3cedb98Argyrios Kyrtzidis#include "clang/Basic/SourceManager.h" 274a5f724538cbc275370c9504e8169ce92503256cBenjamin Kramer#include "llvm/ADT/SmallSet.h" 28c4b5bd89e1ef611c7a31b767763030acc45274c8Tom Care 29c4b5bd89e1ef611c7a31b767763030acc45274c8Tom Care// The number of CFGBlock pointers we want to reserve memory for. This is used 30c4b5bd89e1ef611c7a31b767763030acc45274c8Tom Care// once for each function we analyze. 31c4b5bd89e1ef611c7a31b767763030acc45274c8Tom Care#define DEFAULT_CFGBLOCKS 256 32c4b5bd89e1ef611c7a31b767763030acc45274c8Tom Care 33c4b5bd89e1ef611c7a31b767763030acc45274c8Tom Careusing namespace clang; 349ef6537a894c33003359b1f9b9676e9178e028b7Ted Kremenekusing namespace ento; 35c4b5bd89e1ef611c7a31b767763030acc45274c8Tom Care 36c4b5bd89e1ef611c7a31b767763030acc45274c8Tom Carenamespace { 37ec8605f1d7ec846dbf51047bfd5c56d32d1ff91cArgyrios Kyrtzidisclass UnreachableCodeChecker : public Checker<check::EndAnalysis> { 38c4b5bd89e1ef611c7a31b767763030acc45274c8Tom Carepublic: 3930726c6baee1417307236e854f1474fdb3cedb98Argyrios Kyrtzidis void checkEndAnalysis(ExplodedGraph &G, BugReporter &B, 4030726c6baee1417307236e854f1474fdb3cedb98Argyrios Kyrtzidis ExprEngine &Eng) const; 41c4b5bd89e1ef611c7a31b767763030acc45274c8Tom Careprivate: 4230726c6baee1417307236e854f1474fdb3cedb98Argyrios Kyrtzidis typedef llvm::SmallSet<unsigned, DEFAULT_CFGBLOCKS> CFGBlocksSet; 4330726c6baee1417307236e854f1474fdb3cedb98Argyrios Kyrtzidis 44f8906794f439643b688c2857f5543c9e2499f476Tom Care static inline const Stmt *getUnreachableStmt(const CFGBlock *CB); 4530726c6baee1417307236e854f1474fdb3cedb98Argyrios Kyrtzidis static void FindUnreachableEntryPoints(const CFGBlock *CB, 4630726c6baee1417307236e854f1474fdb3cedb98Argyrios Kyrtzidis CFGBlocksSet &reachable, 4730726c6baee1417307236e854f1474fdb3cedb98Argyrios Kyrtzidis CFGBlocksSet &visited); 487bce3a122296eba0e74f401c188e55c71935132fTom Care static bool isInvalidPath(const CFGBlock *CB, const ParentMap &PM); 49505a5065af704c63c2c747458e7d997dd31ae35bTom Care static inline bool isEmptyCFGBlock(const CFGBlock *CB); 50c4b5bd89e1ef611c7a31b767763030acc45274c8Tom Care}; 51c4b5bd89e1ef611c7a31b767763030acc45274c8Tom Care} 52c4b5bd89e1ef611c7a31b767763030acc45274c8Tom Care 5330726c6baee1417307236e854f1474fdb3cedb98Argyrios Kyrtzidisvoid UnreachableCodeChecker::checkEndAnalysis(ExplodedGraph &G, 54c4b5bd89e1ef611c7a31b767763030acc45274c8Tom Care BugReporter &B, 5530726c6baee1417307236e854f1474fdb3cedb98Argyrios Kyrtzidis ExprEngine &Eng) const { 5630726c6baee1417307236e854f1474fdb3cedb98Argyrios Kyrtzidis CFGBlocksSet reachable, visited; 5775df4eeede7b91c22c1d63fafd4dd4142844e3b9Ted Kremenek 58bc42c533e7d3d946704a49e242939dd232f33072Tom Care if (Eng.hasWorkRemaining()) 59c4b5bd89e1ef611c7a31b767763030acc45274c8Tom Care return; 60c4b5bd89e1ef611c7a31b767763030acc45274c8Tom Care 6175df4eeede7b91c22c1d63fafd4dd4142844e3b9Ted Kremenek const Decl *D = 0; 62c4b5bd89e1ef611c7a31b767763030acc45274c8Tom Care CFG *C = 0; 637bce3a122296eba0e74f401c188e55c71935132fTom Care ParentMap *PM = 0; 64590dd8e0959d8df5621827768987c4792b74fc06Anna Zaks const LocationContext *LC = 0; 65c4b5bd89e1ef611c7a31b767763030acc45274c8Tom Care // Iterate over ExplodedGraph 66505a5065af704c63c2c747458e7d997dd31ae35bTom Care for (ExplodedGraph::node_iterator I = G.nodes_begin(), E = G.nodes_end(); 67505a5065af704c63c2c747458e7d997dd31ae35bTom Care I != E; ++I) { 68c4b5bd89e1ef611c7a31b767763030acc45274c8Tom Care const ProgramPoint &P = I->getLocation(); 69590dd8e0959d8df5621827768987c4792b74fc06Anna Zaks LC = P.getLocationContext(); 70c4b5bd89e1ef611c7a31b767763030acc45274c8Tom Care 7175df4eeede7b91c22c1d63fafd4dd4142844e3b9Ted Kremenek if (!D) 7275df4eeede7b91c22c1d63fafd4dd4142844e3b9Ted Kremenek D = LC->getAnalysisDeclContext()->getDecl(); 73c4b5bd89e1ef611c7a31b767763030acc45274c8Tom Care // Save the CFG if we don't have it already 74c4b5bd89e1ef611c7a31b767763030acc45274c8Tom Care if (!C) 751d26f48dc2eea1c07431ca1519d7034a21b9bcffTed Kremenek C = LC->getAnalysisDeclContext()->getUnoptimizedCFG(); 767bce3a122296eba0e74f401c188e55c71935132fTom Care if (!PM) 777bce3a122296eba0e74f401c188e55c71935132fTom Care PM = &LC->getParentMap(); 78c4b5bd89e1ef611c7a31b767763030acc45274c8Tom Care 79c4b5bd89e1ef611c7a31b767763030acc45274c8Tom Care if (const BlockEntrance *BE = dyn_cast<BlockEntrance>(&P)) { 80c4b5bd89e1ef611c7a31b767763030acc45274c8Tom Care const CFGBlock *CB = BE->getBlock(); 81f8906794f439643b688c2857f5543c9e2499f476Tom Care reachable.insert(CB->getBlockID()); 82c4b5bd89e1ef611c7a31b767763030acc45274c8Tom Care } 83c4b5bd89e1ef611c7a31b767763030acc45274c8Tom Care } 84c4b5bd89e1ef611c7a31b767763030acc45274c8Tom Care 857bce3a122296eba0e74f401c188e55c71935132fTom Care // Bail out if we didn't get the CFG or the ParentMap. 8675df4eeede7b91c22c1d63fafd4dd4142844e3b9Ted Kremenek if (!D || !C || !PM) 87c4b5bd89e1ef611c7a31b767763030acc45274c8Tom Care return; 8875df4eeede7b91c22c1d63fafd4dd4142844e3b9Ted Kremenek 8975df4eeede7b91c22c1d63fafd4dd4142844e3b9Ted Kremenek // Don't do anything for template instantiations. Proving that code 9075df4eeede7b91c22c1d63fafd4dd4142844e3b9Ted Kremenek // in a template instantiation is unreachable means proving that it is 9175df4eeede7b91c22c1d63fafd4dd4142844e3b9Ted Kremenek // unreachable in all instantiations. 9275df4eeede7b91c22c1d63fafd4dd4142844e3b9Ted Kremenek if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(D)) 9375df4eeede7b91c22c1d63fafd4dd4142844e3b9Ted Kremenek if (FD->isTemplateInstantiation()) 9475df4eeede7b91c22c1d63fafd4dd4142844e3b9Ted Kremenek return; 95c4b5bd89e1ef611c7a31b767763030acc45274c8Tom Care 96c4b5bd89e1ef611c7a31b767763030acc45274c8Tom Care // Find CFGBlocks that were not covered by any node 974895b9cf34b26b20e674a88fa8104489e1d06812Tom Care for (CFG::const_iterator I = C->begin(), E = C->end(); I != E; ++I) { 98c4b5bd89e1ef611c7a31b767763030acc45274c8Tom Care const CFGBlock *CB = *I; 99c4b5bd89e1ef611c7a31b767763030acc45274c8Tom Care // Check if the block is unreachable 100f8906794f439643b688c2857f5543c9e2499f476Tom Care if (reachable.count(CB->getBlockID())) 1017bce3a122296eba0e74f401c188e55c71935132fTom Care continue; 1027bce3a122296eba0e74f401c188e55c71935132fTom Care 103505a5065af704c63c2c747458e7d997dd31ae35bTom Care // Check if the block is empty (an artificial block) 104505a5065af704c63c2c747458e7d997dd31ae35bTom Care if (isEmptyCFGBlock(CB)) 105505a5065af704c63c2c747458e7d997dd31ae35bTom Care continue; 106505a5065af704c63c2c747458e7d997dd31ae35bTom Care 1077bce3a122296eba0e74f401c188e55c71935132fTom Care // Find the entry points for this block 1084895b9cf34b26b20e674a88fa8104489e1d06812Tom Care if (!visited.count(CB->getBlockID())) 10930726c6baee1417307236e854f1474fdb3cedb98Argyrios Kyrtzidis FindUnreachableEntryPoints(CB, reachable, visited); 1107bce3a122296eba0e74f401c188e55c71935132fTom Care 1117bce3a122296eba0e74f401c188e55c71935132fTom Care // This block may have been pruned; check if we still want to report it 112f8906794f439643b688c2857f5543c9e2499f476Tom Care if (reachable.count(CB->getBlockID())) 1137bce3a122296eba0e74f401c188e55c71935132fTom Care continue; 1147bce3a122296eba0e74f401c188e55c71935132fTom Care 1157bce3a122296eba0e74f401c188e55c71935132fTom Care // Check for false positives 1167bce3a122296eba0e74f401c188e55c71935132fTom Care if (CB->size() > 0 && isInvalidPath(CB, *PM)) 1177bce3a122296eba0e74f401c188e55c71935132fTom Care continue; 1187bce3a122296eba0e74f401c188e55c71935132fTom Care 11928cd22d7c2d2458575ce9cc19dfe63c6321010ceTed Kremenek // It is good practice to always have a "default" label in a "switch", even 12028cd22d7c2d2458575ce9cc19dfe63c6321010ceTed Kremenek // if we should never get there. It can be used to detect errors, for 12128cd22d7c2d2458575ce9cc19dfe63c6321010ceTed Kremenek // instance. Unreachable code directly under a "default" label is therefore 12228cd22d7c2d2458575ce9cc19dfe63c6321010ceTed Kremenek // likely to be a false positive. 12328cd22d7c2d2458575ce9cc19dfe63c6321010ceTed Kremenek if (const Stmt *label = CB->getLabel()) 12428cd22d7c2d2458575ce9cc19dfe63c6321010ceTed Kremenek if (label->getStmtClass() == Stmt::DefaultStmtClass) 12528cd22d7c2d2458575ce9cc19dfe63c6321010ceTed Kremenek continue; 12628cd22d7c2d2458575ce9cc19dfe63c6321010ceTed Kremenek 1277bce3a122296eba0e74f401c188e55c71935132fTom Care // Special case for __builtin_unreachable. 1287bce3a122296eba0e74f401c188e55c71935132fTom Care // FIXME: This should be extended to include other unreachable markers, 1297bce3a122296eba0e74f401c188e55c71935132fTom Care // such as llvm_unreachable. 1307bce3a122296eba0e74f401c188e55c71935132fTom Care if (!CB->empty()) { 131882998923889a2fcce9b49696506c499e22cf38fTed Kremenek bool foundUnreachable = false; 132882998923889a2fcce9b49696506c499e22cf38fTed Kremenek for (CFGBlock::const_iterator ci = CB->begin(), ce = CB->end(); 133882998923889a2fcce9b49696506c499e22cf38fTed Kremenek ci != ce; ++ci) { 134882998923889a2fcce9b49696506c499e22cf38fTed Kremenek if (const CFGStmt *S = (*ci).getAs<CFGStmt>()) 135882998923889a2fcce9b49696506c499e22cf38fTed Kremenek if (const CallExpr *CE = dyn_cast<CallExpr>(S->getStmt())) { 136180f47959a066795cc0f409433023af448bb0328Richard Smith if (CE->isBuiltinCall() == Builtin::BI__builtin_unreachable) { 137882998923889a2fcce9b49696506c499e22cf38fTed Kremenek foundUnreachable = true; 138882998923889a2fcce9b49696506c499e22cf38fTed Kremenek break; 139882998923889a2fcce9b49696506c499e22cf38fTed Kremenek } 140882998923889a2fcce9b49696506c499e22cf38fTed Kremenek } 1415e04bdde8e74d991feffe9cf95d731f7e473dbb7Jordy Rose } 142882998923889a2fcce9b49696506c499e22cf38fTed Kremenek if (foundUnreachable) 143882998923889a2fcce9b49696506c499e22cf38fTed Kremenek continue; 144c4b5bd89e1ef611c7a31b767763030acc45274c8Tom Care } 1457bce3a122296eba0e74f401c188e55c71935132fTom Care 146f8906794f439643b688c2857f5543c9e2499f476Tom Care // We found a block that wasn't covered - find the statement to report 147f8906794f439643b688c2857f5543c9e2499f476Tom Care SourceRange SR; 148590dd8e0959d8df5621827768987c4792b74fc06Anna Zaks PathDiagnosticLocation DL; 149f8906794f439643b688c2857f5543c9e2499f476Tom Care SourceLocation SL; 150f8906794f439643b688c2857f5543c9e2499f476Tom Care if (const Stmt *S = getUnreachableStmt(CB)) { 151f8906794f439643b688c2857f5543c9e2499f476Tom Care SR = S->getSourceRange(); 152590dd8e0959d8df5621827768987c4792b74fc06Anna Zaks DL = PathDiagnosticLocation::createBegin(S, B.getSourceManager(), LC); 153590dd8e0959d8df5621827768987c4792b74fc06Anna Zaks SL = DL.asLocation(); 154590dd8e0959d8df5621827768987c4792b74fc06Anna Zaks if (SR.isInvalid() || !SL.isValid()) 155f8906794f439643b688c2857f5543c9e2499f476Tom Care continue; 156f8906794f439643b688c2857f5543c9e2499f476Tom Care } 157f8906794f439643b688c2857f5543c9e2499f476Tom Care else 158f8906794f439643b688c2857f5543c9e2499f476Tom Care continue; 159f8906794f439643b688c2857f5543c9e2499f476Tom Care 160f8906794f439643b688c2857f5543c9e2499f476Tom Care // Check if the SourceLocation is in a system header 161f8906794f439643b688c2857f5543c9e2499f476Tom Care const SourceManager &SM = B.getSourceManager(); 162f8906794f439643b688c2857f5543c9e2499f476Tom Care if (SM.isInSystemHeader(SL) || SM.isInExternCSystemHeader(SL)) 163f8906794f439643b688c2857f5543c9e2499f476Tom Care continue; 164f8906794f439643b688c2857f5543c9e2499f476Tom Care 16507189521a15d9c088216b943649cb9fe231cbb57Ted Kremenek B.EmitBasicReport(D, "Unreachable code", "Dead code", 16607189521a15d9c088216b943649cb9fe231cbb57Ted Kremenek "This statement is never executed", DL, SR); 167c4b5bd89e1ef611c7a31b767763030acc45274c8Tom Care } 168c4b5bd89e1ef611c7a31b767763030acc45274c8Tom Care} 169c4b5bd89e1ef611c7a31b767763030acc45274c8Tom Care 170c4b5bd89e1ef611c7a31b767763030acc45274c8Tom Care// Recursively finds the entry point(s) for this dead CFGBlock. 17130726c6baee1417307236e854f1474fdb3cedb98Argyrios Kyrtzidisvoid UnreachableCodeChecker::FindUnreachableEntryPoints(const CFGBlock *CB, 17230726c6baee1417307236e854f1474fdb3cedb98Argyrios Kyrtzidis CFGBlocksSet &reachable, 17330726c6baee1417307236e854f1474fdb3cedb98Argyrios Kyrtzidis CFGBlocksSet &visited) { 174f8906794f439643b688c2857f5543c9e2499f476Tom Care visited.insert(CB->getBlockID()); 175c4b5bd89e1ef611c7a31b767763030acc45274c8Tom Care 1764895b9cf34b26b20e674a88fa8104489e1d06812Tom Care for (CFGBlock::const_pred_iterator I = CB->pred_begin(), E = CB->pred_end(); 1774895b9cf34b26b20e674a88fa8104489e1d06812Tom Care I != E; ++I) { 1780600918d1418c2eac2c96491637946206009c4deTom Care if (!reachable.count((*I)->getBlockID())) { 1794895b9cf34b26b20e674a88fa8104489e1d06812Tom Care // If we find an unreachable predecessor, mark this block as reachable so 1804895b9cf34b26b20e674a88fa8104489e1d06812Tom Care // we don't report this block 1814895b9cf34b26b20e674a88fa8104489e1d06812Tom Care reachable.insert(CB->getBlockID()); 1820600918d1418c2eac2c96491637946206009c4deTom Care if (!visited.count((*I)->getBlockID())) 1834895b9cf34b26b20e674a88fa8104489e1d06812Tom Care // If we haven't previously visited the unreachable predecessor, recurse 18430726c6baee1417307236e854f1474fdb3cedb98Argyrios Kyrtzidis FindUnreachableEntryPoints(*I, reachable, visited); 185c4b5bd89e1ef611c7a31b767763030acc45274c8Tom Care } 186c4b5bd89e1ef611c7a31b767763030acc45274c8Tom Care } 187c4b5bd89e1ef611c7a31b767763030acc45274c8Tom Care} 188c4b5bd89e1ef611c7a31b767763030acc45274c8Tom Care 189f8906794f439643b688c2857f5543c9e2499f476Tom Care// Find the Stmt* in a CFGBlock for reporting a warning 190f8906794f439643b688c2857f5543c9e2499f476Tom Careconst Stmt *UnreachableCodeChecker::getUnreachableStmt(const CFGBlock *CB) { 191b36cd3e1757fb4fcd9509f35558c847b04bef35fZhongxing Xu for (CFGBlock::const_iterator I = CB->begin(), E = CB->end(); I != E; ++I) { 1923c0349e87cdbd7316d06d2411d86ee1086e717a5Ted Kremenek if (const CFGStmt *S = I->getAs<CFGStmt>()) 1933c0349e87cdbd7316d06d2411d86ee1086e717a5Ted Kremenek return S->getStmt(); 194b36cd3e1757fb4fcd9509f35558c847b04bef35fZhongxing Xu } 195b36cd3e1757fb4fcd9509f35558c847b04bef35fZhongxing Xu if (const Stmt *S = CB->getTerminator()) 196f8906794f439643b688c2857f5543c9e2499f476Tom Care return S; 197c4b5bd89e1ef611c7a31b767763030acc45274c8Tom Care else 198f8906794f439643b688c2857f5543c9e2499f476Tom Care return 0; 199c4b5bd89e1ef611c7a31b767763030acc45274c8Tom Care} 2007bce3a122296eba0e74f401c188e55c71935132fTom Care 201f8906794f439643b688c2857f5543c9e2499f476Tom Care// Determines if the path to this CFGBlock contained an element that infers this 202f8906794f439643b688c2857f5543c9e2499f476Tom Care// block is a false positive. We assume that FindUnreachableEntryPoints has 203f8906794f439643b688c2857f5543c9e2499f476Tom Care// already marked only the entry points to any dead code, so we need only to 204f8906794f439643b688c2857f5543c9e2499f476Tom Care// find the condition that led to this block (the predecessor of this block.) 205f8906794f439643b688c2857f5543c9e2499f476Tom Care// There will never be more than one predecessor. 2067bce3a122296eba0e74f401c188e55c71935132fTom Carebool UnreachableCodeChecker::isInvalidPath(const CFGBlock *CB, 2077bce3a122296eba0e74f401c188e55c71935132fTom Care const ParentMap &PM) { 208aaca011f78ce4d1ce08d4320da1326d4ae31609aTom Care // We only expect a predecessor size of 0 or 1. If it is >1, then an external 209aaca011f78ce4d1ce08d4320da1326d4ae31609aTom Care // condition has broken our assumption (for example, a sink being placed by 210aaca011f78ce4d1ce08d4320da1326d4ae31609aTom Care // another check). In these cases, we choose not to report. 211aaca011f78ce4d1ce08d4320da1326d4ae31609aTom Care if (CB->pred_size() > 1) 212aaca011f78ce4d1ce08d4320da1326d4ae31609aTom Care return true; 2137bce3a122296eba0e74f401c188e55c71935132fTom Care 214f8906794f439643b688c2857f5543c9e2499f476Tom Care // If there are no predecessors, then this block is trivially unreachable 215f8906794f439643b688c2857f5543c9e2499f476Tom Care if (CB->pred_size() == 0) 216f8906794f439643b688c2857f5543c9e2499f476Tom Care return false; 217f8906794f439643b688c2857f5543c9e2499f476Tom Care 218f8906794f439643b688c2857f5543c9e2499f476Tom Care const CFGBlock *pred = *CB->pred_begin(); 219f8906794f439643b688c2857f5543c9e2499f476Tom Care 220f8906794f439643b688c2857f5543c9e2499f476Tom Care // Get the predecessor block's terminator conditon 221f8906794f439643b688c2857f5543c9e2499f476Tom Care const Stmt *cond = pred->getTerminatorCondition(); 222505a5065af704c63c2c747458e7d997dd31ae35bTom Care 223505a5065af704c63c2c747458e7d997dd31ae35bTom Care //assert(cond && "CFGBlock's predecessor has a terminator condition"); 224505a5065af704c63c2c747458e7d997dd31ae35bTom Care // The previous assertion is invalid in some cases (eg do/while). Leaving 225505a5065af704c63c2c747458e7d997dd31ae35bTom Care // reporting of these situations on at the moment to help triage these cases. 226505a5065af704c63c2c747458e7d997dd31ae35bTom Care if (!cond) 227505a5065af704c63c2c747458e7d997dd31ae35bTom Care return false; 228f8906794f439643b688c2857f5543c9e2499f476Tom Care 229f8906794f439643b688c2857f5543c9e2499f476Tom Care // Run each of the checks on the conditions 230f8906794f439643b688c2857f5543c9e2499f476Tom Care if (containsMacro(cond) || containsEnum(cond) 231f8906794f439643b688c2857f5543c9e2499f476Tom Care || containsStaticLocal(cond) || containsBuiltinOffsetOf(cond) 232f4e3cfbe8abd124be6341ef5d714819b4fbd9082Peter Collingbourne || containsStmt<UnaryExprOrTypeTraitExpr>(cond)) 233f8906794f439643b688c2857f5543c9e2499f476Tom Care return true; 2347bce3a122296eba0e74f401c188e55c71935132fTom Care 2357bce3a122296eba0e74f401c188e55c71935132fTom Care return false; 2367bce3a122296eba0e74f401c188e55c71935132fTom Care} 237505a5065af704c63c2c747458e7d997dd31ae35bTom Care 238505a5065af704c63c2c747458e7d997dd31ae35bTom Care// Returns true if the given CFGBlock is empty 239505a5065af704c63c2c747458e7d997dd31ae35bTom Carebool UnreachableCodeChecker::isEmptyCFGBlock(const CFGBlock *CB) { 240505a5065af704c63c2c747458e7d997dd31ae35bTom Care return CB->getLabel() == 0 // No labels 241505a5065af704c63c2c747458e7d997dd31ae35bTom Care && CB->size() == 0 // No statements 242505a5065af704c63c2c747458e7d997dd31ae35bTom Care && CB->getTerminator() == 0; // No terminator 243505a5065af704c63c2c747458e7d997dd31ae35bTom Care} 24430726c6baee1417307236e854f1474fdb3cedb98Argyrios Kyrtzidis 24530726c6baee1417307236e854f1474fdb3cedb98Argyrios Kyrtzidisvoid ento::registerUnreachableCodeChecker(CheckerManager &mgr) { 24630726c6baee1417307236e854f1474fdb3cedb98Argyrios Kyrtzidis mgr.registerChecker<UnreachableCodeChecker>(); 24730726c6baee1417307236e854f1474fdb3cedb98Argyrios Kyrtzidis} 248