AnalysisBasedWarnings.cpp revision 57080fbac1ccce702255423335d52e81bcf17b6b
1dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek//=- AnalysisBasedWarnings.cpp - Sema warnings based on libAnalysis -*- C++ -*-=// 2dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek// 3dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek// The LLVM Compiler Infrastructure 4dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek// 5dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek// This file is distributed under the University of Illinois Open Source 6dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek// License. See LICENSE.TXT for details. 7dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek// 8dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek//===----------------------------------------------------------------------===// 9dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek// 10dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek// This file defines analysis_warnings::[Policy,Executor]. 11dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek// Together they are used by Sema to issue warnings based on inexpensive 12dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek// static analysis algorithms in libAnalysis. 13dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek// 14dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek//===----------------------------------------------------------------------===// 15dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek 16e737f5041a36d0befb39ffeed8d50ba15916d3daDouglas Gregor#include "clang/Sema/AnalysisBasedWarnings.h" 172d88708cbe4e4ec5e04e4acb6bd7f5be68557379John McCall#include "clang/Sema/SemaInternal.h" 18351ba91eaa6d30e523587b2d7ed676a5172c6e56Ted Kremenek#include "clang/Sema/ScopeInfo.h" 19d068aabc484c4009282122c6ef26e66e68cfa044Ted Kremenek#include "clang/Basic/SourceManager.h" 20fbb178a0b47fca1b0fb78c5d41198614cf52aa70Ted Kremenek#include "clang/Lex/Preprocessor.h" 217cd088e519d7e6caa4c4c12db52e0e4ae35d25c2John McCall#include "clang/AST/DeclObjC.h" 22384aff8b94bb0d1ad6c5667b90621e5699815bb2John McCall#include "clang/AST/DeclCXX.h" 23dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek#include "clang/AST/ExprObjC.h" 24dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek#include "clang/AST/ExprCXX.h" 25dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek#include "clang/AST/StmtObjC.h" 26dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek#include "clang/AST/StmtCXX.h" 276f41715df2c6a31c0c3ab3088b8cd18a3c8321b8Ted Kremenek#include "clang/AST/EvaluatedExprVisitor.h" 28dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek#include "clang/Analysis/AnalysisContext.h" 29dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek#include "clang/Analysis/CFG.h" 30dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek#include "clang/Analysis/Analyses/ReachableCode.h" 31351ba91eaa6d30e523587b2d7ed676a5172c6e56Ted Kremenek#include "clang/Analysis/Analyses/CFGReachabilityAnalysis.h" 32351ba91eaa6d30e523587b2d7ed676a5172c6e56Ted Kremenek#include "clang/Analysis/CFGStmtMap.h" 336f34213f8d6ae8c77685b53664527e39bfaaca3bTed Kremenek#include "clang/Analysis/Analyses/UninitializedValues.h" 34dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek#include "llvm/ADT/BitVector.h" 35dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek#include "llvm/Support/Casting.h" 36dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek 37dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenekusing namespace clang; 38dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek 39dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek//===----------------------------------------------------------------------===// 40dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek// Unreachable code analysis. 41dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek//===----------------------------------------------------------------------===// 42dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek 43dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremeneknamespace { 44dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek class UnreachableCodeHandler : public reachable_code::Callback { 45dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek Sema &S; 46dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek public: 47dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek UnreachableCodeHandler(Sema &s) : S(s) {} 48dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek 49dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek void HandleUnreachable(SourceLocation L, SourceRange R1, SourceRange R2) { 50dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek S.Diag(L, diag::warn_unreachable) << R1 << R2; 51dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek } 52dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek }; 53dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek} 54dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek 55dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek/// CheckUnreachable - Check for unreachable code. 56dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenekstatic void CheckUnreachable(Sema &S, AnalysisContext &AC) { 57dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek UnreachableCodeHandler UC(S); 58dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek reachable_code::FindUnreachableCode(AC, UC); 59dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek} 60dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek 61dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek//===----------------------------------------------------------------------===// 62dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek// Check for missing return value. 63dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek//===----------------------------------------------------------------------===// 64dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek 6516565aa95b086fb239baf82335dccc1b1ec93942John McCallenum ControlFlowKind { 6616565aa95b086fb239baf82335dccc1b1ec93942John McCall UnknownFallThrough, 6716565aa95b086fb239baf82335dccc1b1ec93942John McCall NeverFallThrough, 6816565aa95b086fb239baf82335dccc1b1ec93942John McCall MaybeFallThrough, 6916565aa95b086fb239baf82335dccc1b1ec93942John McCall AlwaysFallThrough, 7016565aa95b086fb239baf82335dccc1b1ec93942John McCall NeverFallThroughOrReturn 7116565aa95b086fb239baf82335dccc1b1ec93942John McCall}; 72dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek 73dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek/// CheckFallThrough - Check that we don't fall off the end of a 74dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek/// Statement that should return a value. 75dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek/// 76dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek/// \returns AlwaysFallThrough iff we always fall off the end of the statement, 77dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek/// MaybeFallThrough iff we might or might not fall off the end, 78dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek/// NeverFallThroughOrReturn iff we never fall off the end of the statement or 79dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek/// return. We assume NeverFallThrough iff we never fall off the end of the 80dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek/// statement but we may return. We assume that functions not marked noreturn 81dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek/// will return. 82dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenekstatic ControlFlowKind CheckFallThrough(AnalysisContext &AC) { 83dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek CFG *cfg = AC.getCFG(); 8416565aa95b086fb239baf82335dccc1b1ec93942John McCall if (cfg == 0) return UnknownFallThrough; 85dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek 86dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek // The CFG leaves in dead things, and we don't want the dead code paths to 87dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek // confuse us, so we mark all live things first. 88dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek llvm::BitVector live(cfg->getNumBlockIDs()); 89dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek unsigned count = reachable_code::ScanReachableFromBlock(cfg->getEntry(), 90dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek live); 91dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek 92dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek bool AddEHEdges = AC.getAddEHEdges(); 93dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek if (!AddEHEdges && count != cfg->getNumBlockIDs()) 94dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek // When there are things remaining dead, and we didn't add EH edges 95dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek // from CallExprs to the catch clauses, we have to go back and 96dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek // mark them as live. 97dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek for (CFG::iterator I = cfg->begin(), E = cfg->end(); I != E; ++I) { 98dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek CFGBlock &b = **I; 99dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek if (!live[b.getBlockID()]) { 100dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek if (b.pred_begin() == b.pred_end()) { 101dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek if (b.getTerminator() && isa<CXXTryStmt>(b.getTerminator())) 102dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek // When not adding EH edges from calls, catch clauses 103dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek // can otherwise seem dead. Avoid noting them as dead. 104dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek count += reachable_code::ScanReachableFromBlock(b, live); 105dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek continue; 106dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek } 107dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek } 108dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek } 109dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek 110dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek // Now we know what is live, we check the live precessors of the exit block 111dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek // and look for fall through paths, being careful to ignore normal returns, 112dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek // and exceptional paths. 113dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek bool HasLiveReturn = false; 114dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek bool HasFakeEdge = false; 115dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek bool HasPlainEdge = false; 116dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek bool HasAbnormalEdge = false; 11790b828aa279542559f655d1af666580288cb1841Ted Kremenek 11890b828aa279542559f655d1af666580288cb1841Ted Kremenek // Ignore default cases that aren't likely to be reachable because all 11990b828aa279542559f655d1af666580288cb1841Ted Kremenek // enums in a switch(X) have explicit case statements. 12090b828aa279542559f655d1af666580288cb1841Ted Kremenek CFGBlock::FilterOptions FO; 12190b828aa279542559f655d1af666580288cb1841Ted Kremenek FO.IgnoreDefaultsWithCoveredEnums = 1; 12290b828aa279542559f655d1af666580288cb1841Ted Kremenek 12390b828aa279542559f655d1af666580288cb1841Ted Kremenek for (CFGBlock::filtered_pred_iterator 12490b828aa279542559f655d1af666580288cb1841Ted Kremenek I = cfg->getExit().filtered_pred_start_end(FO); I.hasMore(); ++I) { 12590b828aa279542559f655d1af666580288cb1841Ted Kremenek const CFGBlock& B = **I; 126dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek if (!live[B.getBlockID()]) 127dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek continue; 1285811f5978feaa7b89bd89e174fa7ad077b48413eTed Kremenek 1295811f5978feaa7b89bd89e174fa7ad077b48413eTed Kremenek // Destructors can appear after the 'return' in the CFG. This is 1305811f5978feaa7b89bd89e174fa7ad077b48413eTed Kremenek // normal. We need to look pass the destructors for the return 1315811f5978feaa7b89bd89e174fa7ad077b48413eTed Kremenek // statement (if it exists). 1325811f5978feaa7b89bd89e174fa7ad077b48413eTed Kremenek CFGBlock::const_reverse_iterator ri = B.rbegin(), re = B.rend(); 133c9f8f5a726bbb562e4b2d4b19d66e6202dcb2657Ted Kremenek bool hasNoReturnDtor = false; 134c9f8f5a726bbb562e4b2d4b19d66e6202dcb2657Ted Kremenek 1355811f5978feaa7b89bd89e174fa7ad077b48413eTed Kremenek for ( ; ri != re ; ++ri) { 1365811f5978feaa7b89bd89e174fa7ad077b48413eTed Kremenek CFGElement CE = *ri; 137c9f8f5a726bbb562e4b2d4b19d66e6202dcb2657Ted Kremenek 138c9f8f5a726bbb562e4b2d4b19d66e6202dcb2657Ted Kremenek // FIXME: The right solution is to just sever the edges in the 139c9f8f5a726bbb562e4b2d4b19d66e6202dcb2657Ted Kremenek // CFG itself. 140c9f8f5a726bbb562e4b2d4b19d66e6202dcb2657Ted Kremenek if (const CFGImplicitDtor *iDtor = ri->getAs<CFGImplicitDtor>()) 141c5aff4497e5bfd7523e00b87560c1a5aa65136ccTed Kremenek if (iDtor->isNoReturn(AC.getASTContext())) { 142c9f8f5a726bbb562e4b2d4b19d66e6202dcb2657Ted Kremenek hasNoReturnDtor = true; 143c9f8f5a726bbb562e4b2d4b19d66e6202dcb2657Ted Kremenek HasFakeEdge = true; 144c9f8f5a726bbb562e4b2d4b19d66e6202dcb2657Ted Kremenek break; 145c9f8f5a726bbb562e4b2d4b19d66e6202dcb2657Ted Kremenek } 146c9f8f5a726bbb562e4b2d4b19d66e6202dcb2657Ted Kremenek 1475811f5978feaa7b89bd89e174fa7ad077b48413eTed Kremenek if (isa<CFGStmt>(CE)) 1485811f5978feaa7b89bd89e174fa7ad077b48413eTed Kremenek break; 1495811f5978feaa7b89bd89e174fa7ad077b48413eTed Kremenek } 1505811f5978feaa7b89bd89e174fa7ad077b48413eTed Kremenek 151c9f8f5a726bbb562e4b2d4b19d66e6202dcb2657Ted Kremenek if (hasNoReturnDtor) 152c9f8f5a726bbb562e4b2d4b19d66e6202dcb2657Ted Kremenek continue; 153c9f8f5a726bbb562e4b2d4b19d66e6202dcb2657Ted Kremenek 1545811f5978feaa7b89bd89e174fa7ad077b48413eTed Kremenek // No more CFGElements in the block? 1555811f5978feaa7b89bd89e174fa7ad077b48413eTed Kremenek if (ri == re) { 156dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek if (B.getTerminator() && isa<CXXTryStmt>(B.getTerminator())) { 157dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek HasAbnormalEdge = true; 158dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek continue; 159dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek } 160dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek // A labeled empty statement, or the entry block... 161dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek HasPlainEdge = true; 162dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek continue; 163dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek } 164f39e6a388aaa2f155b46c61e655784b2473218ebTed Kremenek 1655811f5978feaa7b89bd89e174fa7ad077b48413eTed Kremenek CFGStmt CS = cast<CFGStmt>(*ri); 166b36cd3e1757fb4fcd9509f35558c847b04bef35fZhongxing Xu Stmt *S = CS.getStmt(); 167dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek if (isa<ReturnStmt>(S)) { 168dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek HasLiveReturn = true; 169dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek continue; 170dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek } 171dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek if (isa<ObjCAtThrowStmt>(S)) { 172dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek HasFakeEdge = true; 173dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek continue; 174dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek } 175dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek if (isa<CXXThrowExpr>(S)) { 176dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek HasFakeEdge = true; 177dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek continue; 178dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek } 179dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek if (const AsmStmt *AS = dyn_cast<AsmStmt>(S)) { 180dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek if (AS->isMSAsm()) { 181dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek HasFakeEdge = true; 182dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek HasLiveReturn = true; 183dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek continue; 184dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek } 185dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek } 186dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek if (isa<CXXTryStmt>(S)) { 187dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek HasAbnormalEdge = true; 188dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek continue; 189dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek } 190dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek 191dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek bool NoReturnEdge = false; 192dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek if (CallExpr *C = dyn_cast<CallExpr>(S)) { 193259d48e1486044093131c8c078f70a28b1503e70John McCall if (std::find(B.succ_begin(), B.succ_end(), &cfg->getExit()) 194259d48e1486044093131c8c078f70a28b1503e70John McCall == B.succ_end()) { 195dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek HasAbnormalEdge = true; 196dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek continue; 197dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek } 198dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek Expr *CEE = C->getCallee()->IgnoreParenCasts(); 1991de85338543dd6228eb518185e385d94d377f4cbJohn McCall QualType calleeType = CEE->getType(); 2001de85338543dd6228eb518185e385d94d377f4cbJohn McCall if (calleeType == AC.getASTContext().BoundMemberTy) { 2011de85338543dd6228eb518185e385d94d377f4cbJohn McCall calleeType = Expr::findBoundMemberType(CEE); 2021de85338543dd6228eb518185e385d94d377f4cbJohn McCall assert(!calleeType.isNull() && "analyzing unresolved call?"); 2031de85338543dd6228eb518185e385d94d377f4cbJohn McCall } 2041de85338543dd6228eb518185e385d94d377f4cbJohn McCall if (getFunctionExtInfo(calleeType).getNoReturn()) { 205dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek NoReturnEdge = true; 206dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek HasFakeEdge = true; 207dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek } else if (DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(CEE)) { 208dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek ValueDecl *VD = DRE->getDecl(); 209dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek if (VD->hasAttr<NoReturnAttr>()) { 210dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek NoReturnEdge = true; 211dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek HasFakeEdge = true; 212dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek } 213dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek } 214dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek } 215dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek // FIXME: Add noreturn message sends. 216dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek if (NoReturnEdge == false) 217dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek HasPlainEdge = true; 218dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek } 219dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek if (!HasPlainEdge) { 220dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek if (HasLiveReturn) 221dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek return NeverFallThrough; 222dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek return NeverFallThroughOrReturn; 223dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek } 224dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek if (HasAbnormalEdge || HasFakeEdge || HasLiveReturn) 225dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek return MaybeFallThrough; 226dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek // This says AlwaysFallThrough for calls to functions that are not marked 227dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek // noreturn, that don't return. If people would like this warning to be more 228dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek // accurate, such functions should be marked as noreturn. 229dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek return AlwaysFallThrough; 230dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek} 231dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek 2323c46e8db99196179b30e7ac5c20c4efd5f3926d7Dan Gohmannamespace { 2333c46e8db99196179b30e7ac5c20c4efd5f3926d7Dan Gohman 234dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenekstruct CheckFallThroughDiagnostics { 235dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek unsigned diag_MaybeFallThrough_HasNoReturn; 236dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek unsigned diag_MaybeFallThrough_ReturnsNonVoid; 237dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek unsigned diag_AlwaysFallThrough_HasNoReturn; 238dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek unsigned diag_AlwaysFallThrough_ReturnsNonVoid; 239dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek unsigned diag_NeverFallThroughOrReturn; 240dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek bool funMode; 2410827408865e32789e0ec4b8113a302ccdc531423Argyrios Kyrtzidis SourceLocation FuncLoc; 242d064fdc4b7b64ca55b40b70490c79d6f569df78eTed Kremenek 243ca7eaeeed817001dc7cee4852a7e41f0982da1efDouglas Gregor static CheckFallThroughDiagnostics MakeForFunction(const Decl *Func) { 244dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek CheckFallThroughDiagnostics D; 2450827408865e32789e0ec4b8113a302ccdc531423Argyrios Kyrtzidis D.FuncLoc = Func->getLocation(); 246dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek D.diag_MaybeFallThrough_HasNoReturn = 247dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek diag::warn_falloff_noreturn_function; 248dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek D.diag_MaybeFallThrough_ReturnsNonVoid = 249dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek diag::warn_maybe_falloff_nonvoid_function; 250dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek D.diag_AlwaysFallThrough_HasNoReturn = 251dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek diag::warn_falloff_noreturn_function; 252dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek D.diag_AlwaysFallThrough_ReturnsNonVoid = 253dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek diag::warn_falloff_nonvoid_function; 254ca7eaeeed817001dc7cee4852a7e41f0982da1efDouglas Gregor 255ca7eaeeed817001dc7cee4852a7e41f0982da1efDouglas Gregor // Don't suggest that virtual functions be marked "noreturn", since they 256ca7eaeeed817001dc7cee4852a7e41f0982da1efDouglas Gregor // might be overridden by non-noreturn functions. 257ca7eaeeed817001dc7cee4852a7e41f0982da1efDouglas Gregor bool isVirtualMethod = false; 258ca7eaeeed817001dc7cee4852a7e41f0982da1efDouglas Gregor if (const CXXMethodDecl *Method = dyn_cast<CXXMethodDecl>(Func)) 259ca7eaeeed817001dc7cee4852a7e41f0982da1efDouglas Gregor isVirtualMethod = Method->isVirtual(); 260ca7eaeeed817001dc7cee4852a7e41f0982da1efDouglas Gregor 261ca7eaeeed817001dc7cee4852a7e41f0982da1efDouglas Gregor if (!isVirtualMethod) 262ca7eaeeed817001dc7cee4852a7e41f0982da1efDouglas Gregor D.diag_NeverFallThroughOrReturn = 263ca7eaeeed817001dc7cee4852a7e41f0982da1efDouglas Gregor diag::warn_suggest_noreturn_function; 264ca7eaeeed817001dc7cee4852a7e41f0982da1efDouglas Gregor else 265ca7eaeeed817001dc7cee4852a7e41f0982da1efDouglas Gregor D.diag_NeverFallThroughOrReturn = 0; 266ca7eaeeed817001dc7cee4852a7e41f0982da1efDouglas Gregor 267dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek D.funMode = true; 268dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek return D; 269dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek } 270d064fdc4b7b64ca55b40b70490c79d6f569df78eTed Kremenek 271dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek static CheckFallThroughDiagnostics MakeForBlock() { 272dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek CheckFallThroughDiagnostics D; 273dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek D.diag_MaybeFallThrough_HasNoReturn = 274dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek diag::err_noreturn_block_has_return_expr; 275dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek D.diag_MaybeFallThrough_ReturnsNonVoid = 276dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek diag::err_maybe_falloff_nonvoid_block; 277dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek D.diag_AlwaysFallThrough_HasNoReturn = 278dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek diag::err_noreturn_block_has_return_expr; 279dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek D.diag_AlwaysFallThrough_ReturnsNonVoid = 280dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek diag::err_falloff_nonvoid_block; 281dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek D.diag_NeverFallThroughOrReturn = 282dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek diag::warn_suggest_noreturn_block; 283dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek D.funMode = false; 284dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek return D; 285dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek } 286d064fdc4b7b64ca55b40b70490c79d6f569df78eTed Kremenek 287dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek bool checkDiagnostics(Diagnostic &D, bool ReturnsVoid, 288dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek bool HasNoReturn) const { 289dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek if (funMode) { 2900827408865e32789e0ec4b8113a302ccdc531423Argyrios Kyrtzidis return (ReturnsVoid || 2910827408865e32789e0ec4b8113a302ccdc531423Argyrios Kyrtzidis D.getDiagnosticLevel(diag::warn_maybe_falloff_nonvoid_function, 2920827408865e32789e0ec4b8113a302ccdc531423Argyrios Kyrtzidis FuncLoc) == Diagnostic::Ignored) 2930827408865e32789e0ec4b8113a302ccdc531423Argyrios Kyrtzidis && (!HasNoReturn || 2940827408865e32789e0ec4b8113a302ccdc531423Argyrios Kyrtzidis D.getDiagnosticLevel(diag::warn_noreturn_function_has_return_expr, 2950827408865e32789e0ec4b8113a302ccdc531423Argyrios Kyrtzidis FuncLoc) == Diagnostic::Ignored) 2960827408865e32789e0ec4b8113a302ccdc531423Argyrios Kyrtzidis && (!ReturnsVoid || 2970827408865e32789e0ec4b8113a302ccdc531423Argyrios Kyrtzidis D.getDiagnosticLevel(diag::warn_suggest_noreturn_block, FuncLoc) 2980827408865e32789e0ec4b8113a302ccdc531423Argyrios Kyrtzidis == Diagnostic::Ignored); 299dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek } 300d064fdc4b7b64ca55b40b70490c79d6f569df78eTed Kremenek 301dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek // For blocks. 302dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek return ReturnsVoid && !HasNoReturn 3030827408865e32789e0ec4b8113a302ccdc531423Argyrios Kyrtzidis && (!ReturnsVoid || 3040827408865e32789e0ec4b8113a302ccdc531423Argyrios Kyrtzidis D.getDiagnosticLevel(diag::warn_suggest_noreturn_block, FuncLoc) 3050827408865e32789e0ec4b8113a302ccdc531423Argyrios Kyrtzidis == Diagnostic::Ignored); 306dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek } 307dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek}; 308dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek 3093c46e8db99196179b30e7ac5c20c4efd5f3926d7Dan Gohman} 3103c46e8db99196179b30e7ac5c20c4efd5f3926d7Dan Gohman 311dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek/// CheckFallThroughForFunctionDef - Check that we don't fall off the end of a 312dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek/// function that should return a value. Check that we don't fall off the end 313dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek/// of a noreturn function. We assume that functions and blocks not marked 314dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek/// noreturn will return. 315dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenekstatic void CheckFallThroughForBody(Sema &S, const Decl *D, const Stmt *Body, 3163ed6fc08a9cd293d012fa49ab2a615e618d7c3faTed Kremenek const BlockExpr *blkExpr, 317dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek const CheckFallThroughDiagnostics& CD, 318dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek AnalysisContext &AC) { 319dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek 320dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek bool ReturnsVoid = false; 321dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek bool HasNoReturn = false; 322dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek 323dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(D)) { 324dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek ReturnsVoid = FD->getResultType()->isVoidType(); 325dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek HasNoReturn = FD->hasAttr<NoReturnAttr>() || 326264ba48dc98f3f843935a485d5b086f7e0fdc4f1Rafael Espindola FD->getType()->getAs<FunctionType>()->getNoReturnAttr(); 327dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek } 328dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek else if (const ObjCMethodDecl *MD = dyn_cast<ObjCMethodDecl>(D)) { 329dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek ReturnsVoid = MD->getResultType()->isVoidType(); 330dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek HasNoReturn = MD->hasAttr<NoReturnAttr>(); 331dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek } 332dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek else if (isa<BlockDecl>(D)) { 3333ed6fc08a9cd293d012fa49ab2a615e618d7c3faTed Kremenek QualType BlockTy = blkExpr->getType(); 334d064fdc4b7b64ca55b40b70490c79d6f569df78eTed Kremenek if (const FunctionType *FT = 335dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek BlockTy->getPointeeType()->getAs<FunctionType>()) { 336dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek if (FT->getResultType()->isVoidType()) 337dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek ReturnsVoid = true; 338dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek if (FT->getNoReturnAttr()) 339dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek HasNoReturn = true; 340dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek } 341dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek } 342dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek 343dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek Diagnostic &Diags = S.getDiagnostics(); 344dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek 345dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek // Short circuit for compilation speed. 346dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek if (CD.checkDiagnostics(Diags, ReturnsVoid, HasNoReturn)) 347dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek return; 348d064fdc4b7b64ca55b40b70490c79d6f569df78eTed Kremenek 349dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek // FIXME: Function try block 350dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek if (const CompoundStmt *Compound = dyn_cast<CompoundStmt>(Body)) { 351dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek switch (CheckFallThrough(AC)) { 35216565aa95b086fb239baf82335dccc1b1ec93942John McCall case UnknownFallThrough: 35316565aa95b086fb239baf82335dccc1b1ec93942John McCall break; 35416565aa95b086fb239baf82335dccc1b1ec93942John McCall 355dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek case MaybeFallThrough: 356dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek if (HasNoReturn) 357dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek S.Diag(Compound->getRBracLoc(), 358dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek CD.diag_MaybeFallThrough_HasNoReturn); 359dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek else if (!ReturnsVoid) 360dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek S.Diag(Compound->getRBracLoc(), 361dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek CD.diag_MaybeFallThrough_ReturnsNonVoid); 362dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek break; 363dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek case AlwaysFallThrough: 364dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek if (HasNoReturn) 365dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek S.Diag(Compound->getRBracLoc(), 366dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek CD.diag_AlwaysFallThrough_HasNoReturn); 367dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek else if (!ReturnsVoid) 368dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek S.Diag(Compound->getRBracLoc(), 369dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek CD.diag_AlwaysFallThrough_ReturnsNonVoid); 370dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek break; 371dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek case NeverFallThroughOrReturn: 372ca7eaeeed817001dc7cee4852a7e41f0982da1efDouglas Gregor if (ReturnsVoid && !HasNoReturn && CD.diag_NeverFallThroughOrReturn) 373dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek S.Diag(Compound->getLBracLoc(), 374dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek CD.diag_NeverFallThroughOrReturn); 375dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek break; 376dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek case NeverFallThrough: 377dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek break; 378dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek } 379dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek } 380dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek} 381dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek 382dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek//===----------------------------------------------------------------------===// 383610068c8cd2321f90e147b12cf794e1f840b6405Ted Kremenek// -Wuninitialized 384610068c8cd2321f90e147b12cf794e1f840b6405Ted Kremenek//===----------------------------------------------------------------------===// 385610068c8cd2321f90e147b12cf794e1f840b6405Ted Kremenek 3866f41715df2c6a31c0c3ab3088b8cd18a3c8321b8Ted Kremeneknamespace { 3879f6494687c05fe1d334af76408ee056b5f80e027Chandler Carruth/// ContainsReference - A visitor class to search for references to 3889f6494687c05fe1d334af76408ee056b5f80e027Chandler Carruth/// a particular declaration (the needle) within any evaluated component of an 3899f6494687c05fe1d334af76408ee056b5f80e027Chandler Carruth/// expression (recursively). 3906f41715df2c6a31c0c3ab3088b8cd18a3c8321b8Ted Kremenekclass ContainsReference : public EvaluatedExprVisitor<ContainsReference> { 3919f6494687c05fe1d334af76408ee056b5f80e027Chandler Carruth bool FoundReference; 3929f6494687c05fe1d334af76408ee056b5f80e027Chandler Carruth const DeclRefExpr *Needle; 3939f6494687c05fe1d334af76408ee056b5f80e027Chandler Carruth 3946f41715df2c6a31c0c3ab3088b8cd18a3c8321b8Ted Kremenekpublic: 3959f6494687c05fe1d334af76408ee056b5f80e027Chandler Carruth ContainsReference(ASTContext &Context, const DeclRefExpr *Needle) 3969f6494687c05fe1d334af76408ee056b5f80e027Chandler Carruth : EvaluatedExprVisitor<ContainsReference>(Context), 3979f6494687c05fe1d334af76408ee056b5f80e027Chandler Carruth FoundReference(false), Needle(Needle) {} 3989f6494687c05fe1d334af76408ee056b5f80e027Chandler Carruth 3999f6494687c05fe1d334af76408ee056b5f80e027Chandler Carruth void VisitExpr(Expr *E) { 4006f41715df2c6a31c0c3ab3088b8cd18a3c8321b8Ted Kremenek // Stop evaluating if we already have a reference. 4019f6494687c05fe1d334af76408ee056b5f80e027Chandler Carruth if (FoundReference) 4026f41715df2c6a31c0c3ab3088b8cd18a3c8321b8Ted Kremenek return; 4039f6494687c05fe1d334af76408ee056b5f80e027Chandler Carruth 4049f6494687c05fe1d334af76408ee056b5f80e027Chandler Carruth EvaluatedExprVisitor<ContainsReference>::VisitExpr(E); 4056f41715df2c6a31c0c3ab3088b8cd18a3c8321b8Ted Kremenek } 4069f6494687c05fe1d334af76408ee056b5f80e027Chandler Carruth 4079f6494687c05fe1d334af76408ee056b5f80e027Chandler Carruth void VisitDeclRefExpr(DeclRefExpr *E) { 4089f6494687c05fe1d334af76408ee056b5f80e027Chandler Carruth if (E == Needle) 4099f6494687c05fe1d334af76408ee056b5f80e027Chandler Carruth FoundReference = true; 4109f6494687c05fe1d334af76408ee056b5f80e027Chandler Carruth else 4119f6494687c05fe1d334af76408ee056b5f80e027Chandler Carruth EvaluatedExprVisitor<ContainsReference>::VisitDeclRefExpr(E); 4126f41715df2c6a31c0c3ab3088b8cd18a3c8321b8Ted Kremenek } 4139f6494687c05fe1d334af76408ee056b5f80e027Chandler Carruth 4149f6494687c05fe1d334af76408ee056b5f80e027Chandler Carruth bool doesContainReference() const { return FoundReference; } 4156f41715df2c6a31c0c3ab3088b8cd18a3c8321b8Ted Kremenek}; 4166f41715df2c6a31c0c3ab3088b8cd18a3c8321b8Ted Kremenek} 4176f41715df2c6a31c0c3ab3088b8cd18a3c8321b8Ted Kremenek 418262d50e1dcf529317da193ad585c11c16281a7acChandler Carruth/// DiagnoseUninitializedUse -- Helper function for diagnosing uses of an 419262d50e1dcf529317da193ad585c11c16281a7acChandler Carruth/// uninitialized variable. This manages the different forms of diagnostic 420262d50e1dcf529317da193ad585c11c16281a7acChandler Carruth/// emitted for particular types of uses. Returns true if the use was diagnosed 421262d50e1dcf529317da193ad585c11c16281a7acChandler Carruth/// as a warning. If a pariticular use is one we omit warnings for, returns 422262d50e1dcf529317da193ad585c11c16281a7acChandler Carruth/// false. 423262d50e1dcf529317da193ad585c11c16281a7acChandler Carruthstatic bool DiagnoseUninitializedUse(Sema &S, const VarDecl *VD, 42464fb959beb3a0ecb84a58e6ff82660a7a669f7b8Chandler Carruth const Expr *E, bool isAlwaysUninit) { 4254c4983bbd2904670a25c840b07600f14efbafd7fChandler Carruth bool isSelfInit = false; 4264c4983bbd2904670a25c840b07600f14efbafd7fChandler Carruth 4274c4983bbd2904670a25c840b07600f14efbafd7fChandler Carruth if (const DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(E)) { 4284c4983bbd2904670a25c840b07600f14efbafd7fChandler Carruth if (isAlwaysUninit) { 4294c4983bbd2904670a25c840b07600f14efbafd7fChandler Carruth // Inspect the initializer of the variable declaration which is 4304c4983bbd2904670a25c840b07600f14efbafd7fChandler Carruth // being referenced prior to its initialization. We emit 4314c4983bbd2904670a25c840b07600f14efbafd7fChandler Carruth // specialized diagnostics for self-initialization, and we 4324c4983bbd2904670a25c840b07600f14efbafd7fChandler Carruth // specifically avoid warning about self references which take the 4334c4983bbd2904670a25c840b07600f14efbafd7fChandler Carruth // form of: 4344c4983bbd2904670a25c840b07600f14efbafd7fChandler Carruth // 4354c4983bbd2904670a25c840b07600f14efbafd7fChandler Carruth // int x = x; 4364c4983bbd2904670a25c840b07600f14efbafd7fChandler Carruth // 4374c4983bbd2904670a25c840b07600f14efbafd7fChandler Carruth // This is used to indicate to GCC that 'x' is intentionally left 4384c4983bbd2904670a25c840b07600f14efbafd7fChandler Carruth // uninitialized. Proven code paths which access 'x' in 4394c4983bbd2904670a25c840b07600f14efbafd7fChandler Carruth // an uninitialized state after this will still warn. 4404c4983bbd2904670a25c840b07600f14efbafd7fChandler Carruth // 4414c4983bbd2904670a25c840b07600f14efbafd7fChandler Carruth // TODO: Should we suppress maybe-uninitialized warnings for 4424c4983bbd2904670a25c840b07600f14efbafd7fChandler Carruth // variables initialized in this way? 4434c4983bbd2904670a25c840b07600f14efbafd7fChandler Carruth if (const Expr *Initializer = VD->getInit()) { 4444c4983bbd2904670a25c840b07600f14efbafd7fChandler Carruth if (DRE == Initializer->IgnoreParenImpCasts()) 445262d50e1dcf529317da193ad585c11c16281a7acChandler Carruth return false; 4464c4983bbd2904670a25c840b07600f14efbafd7fChandler Carruth 4474c4983bbd2904670a25c840b07600f14efbafd7fChandler Carruth ContainsReference CR(S.Context, DRE); 4484c4983bbd2904670a25c840b07600f14efbafd7fChandler Carruth CR.Visit(const_cast<Expr*>(Initializer)); 4494c4983bbd2904670a25c840b07600f14efbafd7fChandler Carruth isSelfInit = CR.doesContainReference(); 4504c4983bbd2904670a25c840b07600f14efbafd7fChandler Carruth } 4514c4983bbd2904670a25c840b07600f14efbafd7fChandler Carruth if (isSelfInit) { 4524c4983bbd2904670a25c840b07600f14efbafd7fChandler Carruth S.Diag(DRE->getLocStart(), 4534c4983bbd2904670a25c840b07600f14efbafd7fChandler Carruth diag::warn_uninit_self_reference_in_init) 4544c4983bbd2904670a25c840b07600f14efbafd7fChandler Carruth << VD->getDeclName() << VD->getLocation() << DRE->getSourceRange(); 4554c4983bbd2904670a25c840b07600f14efbafd7fChandler Carruth } else { 4564c4983bbd2904670a25c840b07600f14efbafd7fChandler Carruth S.Diag(DRE->getLocStart(), diag::warn_uninit_var) 4574c4983bbd2904670a25c840b07600f14efbafd7fChandler Carruth << VD->getDeclName() << DRE->getSourceRange(); 4584c4983bbd2904670a25c840b07600f14efbafd7fChandler Carruth } 4594c4983bbd2904670a25c840b07600f14efbafd7fChandler Carruth } else { 4604c4983bbd2904670a25c840b07600f14efbafd7fChandler Carruth S.Diag(DRE->getLocStart(), diag::warn_maybe_uninit_var) 4614c4983bbd2904670a25c840b07600f14efbafd7fChandler Carruth << VD->getDeclName() << DRE->getSourceRange(); 4624c4983bbd2904670a25c840b07600f14efbafd7fChandler Carruth } 4634c4983bbd2904670a25c840b07600f14efbafd7fChandler Carruth } else { 4644c4983bbd2904670a25c840b07600f14efbafd7fChandler Carruth const BlockExpr *BE = cast<BlockExpr>(E); 4654c4983bbd2904670a25c840b07600f14efbafd7fChandler Carruth S.Diag(BE->getLocStart(), 4664c4983bbd2904670a25c840b07600f14efbafd7fChandler Carruth isAlwaysUninit ? diag::warn_uninit_var_captured_by_block 4674c4983bbd2904670a25c840b07600f14efbafd7fChandler Carruth : diag::warn_maybe_uninit_var_captured_by_block) 4684c4983bbd2904670a25c840b07600f14efbafd7fChandler Carruth << VD->getDeclName(); 4694c4983bbd2904670a25c840b07600f14efbafd7fChandler Carruth } 4704c4983bbd2904670a25c840b07600f14efbafd7fChandler Carruth 4714c4983bbd2904670a25c840b07600f14efbafd7fChandler Carruth // Report where the variable was declared when the use wasn't within 4724c4983bbd2904670a25c840b07600f14efbafd7fChandler Carruth // the initializer of that declaration. 4734c4983bbd2904670a25c840b07600f14efbafd7fChandler Carruth if (!isSelfInit) 4744c4983bbd2904670a25c840b07600f14efbafd7fChandler Carruth S.Diag(VD->getLocStart(), diag::note_uninit_var_def) 4754c4983bbd2904670a25c840b07600f14efbafd7fChandler Carruth << VD->getDeclName(); 4764c4983bbd2904670a25c840b07600f14efbafd7fChandler Carruth 477262d50e1dcf529317da193ad585c11c16281a7acChandler Carruth return true; 47864fb959beb3a0ecb84a58e6ff82660a7a669f7b8Chandler Carruth} 47964fb959beb3a0ecb84a58e6ff82660a7a669f7b8Chandler Carruth 480262d50e1dcf529317da193ad585c11c16281a7acChandler Carruthstatic void SuggestInitializationFixit(Sema &S, const VarDecl *VD) { 4814c4983bbd2904670a25c840b07600f14efbafd7fChandler Carruth // Don't issue a fixit if there is already an initializer. 4824c4983bbd2904670a25c840b07600f14efbafd7fChandler Carruth if (VD->getInit()) 4834c4983bbd2904670a25c840b07600f14efbafd7fChandler Carruth return; 4844c4983bbd2904670a25c840b07600f14efbafd7fChandler Carruth 4854c4983bbd2904670a25c840b07600f14efbafd7fChandler Carruth // Suggest possible initialization (if any). 4864c4983bbd2904670a25c840b07600f14efbafd7fChandler Carruth const char *initialization = 0; 4874c4983bbd2904670a25c840b07600f14efbafd7fChandler Carruth QualType VariableTy = VD->getType().getCanonicalType(); 4884c4983bbd2904670a25c840b07600f14efbafd7fChandler Carruth 4898ba44264e05fe0012ecfb7bac28b171b5a50dde3Douglas Gregor if (VariableTy->isObjCObjectPointerType() || 4908ba44264e05fe0012ecfb7bac28b171b5a50dde3Douglas Gregor VariableTy->isBlockPointerType()) { 4914c4983bbd2904670a25c840b07600f14efbafd7fChandler Carruth // Check if 'nil' is defined. 4924c4983bbd2904670a25c840b07600f14efbafd7fChandler Carruth if (S.PP.getMacroInfo(&S.getASTContext().Idents.get("nil"))) 4934c4983bbd2904670a25c840b07600f14efbafd7fChandler Carruth initialization = " = nil"; 4944c4983bbd2904670a25c840b07600f14efbafd7fChandler Carruth else 4954c4983bbd2904670a25c840b07600f14efbafd7fChandler Carruth initialization = " = 0"; 4964c4983bbd2904670a25c840b07600f14efbafd7fChandler Carruth } 4974c4983bbd2904670a25c840b07600f14efbafd7fChandler Carruth else if (VariableTy->isRealFloatingType()) 4984c4983bbd2904670a25c840b07600f14efbafd7fChandler Carruth initialization = " = 0.0"; 4994c4983bbd2904670a25c840b07600f14efbafd7fChandler Carruth else if (VariableTy->isBooleanType() && S.Context.getLangOptions().CPlusPlus) 5004c4983bbd2904670a25c840b07600f14efbafd7fChandler Carruth initialization = " = false"; 5014c4983bbd2904670a25c840b07600f14efbafd7fChandler Carruth else if (VariableTy->isEnumeralType()) 5024c4983bbd2904670a25c840b07600f14efbafd7fChandler Carruth return; 5038ba44264e05fe0012ecfb7bac28b171b5a50dde3Douglas Gregor else if (VariableTy->isPointerType() || VariableTy->isMemberPointerType()) { 5048ba44264e05fe0012ecfb7bac28b171b5a50dde3Douglas Gregor // Check if 'NULL' is defined. 5058ba44264e05fe0012ecfb7bac28b171b5a50dde3Douglas Gregor if (S.PP.getMacroInfo(&S.getASTContext().Idents.get("NULL"))) 5068ba44264e05fe0012ecfb7bac28b171b5a50dde3Douglas Gregor initialization = " = NULL"; 5078ba44264e05fe0012ecfb7bac28b171b5a50dde3Douglas Gregor else 5088ba44264e05fe0012ecfb7bac28b171b5a50dde3Douglas Gregor initialization = " = 0"; 5098ba44264e05fe0012ecfb7bac28b171b5a50dde3Douglas Gregor } 5104c4983bbd2904670a25c840b07600f14efbafd7fChandler Carruth else if (VariableTy->isScalarType()) 5114c4983bbd2904670a25c840b07600f14efbafd7fChandler Carruth initialization = " = 0"; 5124c4983bbd2904670a25c840b07600f14efbafd7fChandler Carruth 5134c4983bbd2904670a25c840b07600f14efbafd7fChandler Carruth if (initialization) { 5144c4983bbd2904670a25c840b07600f14efbafd7fChandler Carruth SourceLocation loc = S.PP.getLocForEndOfToken(VD->getLocEnd()); 5154c4983bbd2904670a25c840b07600f14efbafd7fChandler Carruth S.Diag(loc, diag::note_var_fixit_add_initialization) 5164c4983bbd2904670a25c840b07600f14efbafd7fChandler Carruth << FixItHint::CreateInsertion(loc, initialization); 5174c4983bbd2904670a25c840b07600f14efbafd7fChandler Carruth } 5184c4983bbd2904670a25c840b07600f14efbafd7fChandler Carruth} 5194c4983bbd2904670a25c840b07600f14efbafd7fChandler Carruth 520f7bafc77ba12bb1beb665243a0334cd81e024728Ted Kremenektypedef std::pair<const Expr*, bool> UninitUse; 521f7bafc77ba12bb1beb665243a0334cd81e024728Ted Kremenek 522610068c8cd2321f90e147b12cf794e1f840b6405Ted Kremeneknamespace { 52394b1b4d785bc0f09f6af4be394e59d51f35dda60Ted Kremenekstruct SLocSort { 524f7bafc77ba12bb1beb665243a0334cd81e024728Ted Kremenek bool operator()(const UninitUse &a, const UninitUse &b) { 525f7bafc77ba12bb1beb665243a0334cd81e024728Ted Kremenek SourceLocation aLoc = a.first->getLocStart(); 526f7bafc77ba12bb1beb665243a0334cd81e024728Ted Kremenek SourceLocation bLoc = b.first->getLocStart(); 52794b1b4d785bc0f09f6af4be394e59d51f35dda60Ted Kremenek return aLoc.getRawEncoding() < bLoc.getRawEncoding(); 52894b1b4d785bc0f09f6af4be394e59d51f35dda60Ted Kremenek } 52994b1b4d785bc0f09f6af4be394e59d51f35dda60Ted Kremenek}; 53094b1b4d785bc0f09f6af4be394e59d51f35dda60Ted Kremenek 531610068c8cd2321f90e147b12cf794e1f840b6405Ted Kremenekclass UninitValsDiagReporter : public UninitVariablesHandler { 532610068c8cd2321f90e147b12cf794e1f840b6405Ted Kremenek Sema &S; 533f7bafc77ba12bb1beb665243a0334cd81e024728Ted Kremenek typedef llvm::SmallVector<UninitUse, 2> UsesVec; 53494b1b4d785bc0f09f6af4be394e59d51f35dda60Ted Kremenek typedef llvm::DenseMap<const VarDecl *, UsesVec*> UsesMap; 53594b1b4d785bc0f09f6af4be394e59d51f35dda60Ted Kremenek UsesMap *uses; 53694b1b4d785bc0f09f6af4be394e59d51f35dda60Ted Kremenek 537610068c8cd2321f90e147b12cf794e1f840b6405Ted Kremenekpublic: 53894b1b4d785bc0f09f6af4be394e59d51f35dda60Ted Kremenek UninitValsDiagReporter(Sema &S) : S(S), uses(0) {} 53994b1b4d785bc0f09f6af4be394e59d51f35dda60Ted Kremenek ~UninitValsDiagReporter() { 54094b1b4d785bc0f09f6af4be394e59d51f35dda60Ted Kremenek flushDiagnostics(); 54194b1b4d785bc0f09f6af4be394e59d51f35dda60Ted Kremenek } 542610068c8cd2321f90e147b12cf794e1f840b6405Ted Kremenek 543f7bafc77ba12bb1beb665243a0334cd81e024728Ted Kremenek void handleUseOfUninitVariable(const Expr *ex, const VarDecl *vd, 544f7bafc77ba12bb1beb665243a0334cd81e024728Ted Kremenek bool isAlwaysUninit) { 54594b1b4d785bc0f09f6af4be394e59d51f35dda60Ted Kremenek if (!uses) 54694b1b4d785bc0f09f6af4be394e59d51f35dda60Ted Kremenek uses = new UsesMap(); 54794b1b4d785bc0f09f6af4be394e59d51f35dda60Ted Kremenek 54894b1b4d785bc0f09f6af4be394e59d51f35dda60Ted Kremenek UsesVec *&vec = (*uses)[vd]; 54994b1b4d785bc0f09f6af4be394e59d51f35dda60Ted Kremenek if (!vec) 55094b1b4d785bc0f09f6af4be394e59d51f35dda60Ted Kremenek vec = new UsesVec(); 55194b1b4d785bc0f09f6af4be394e59d51f35dda60Ted Kremenek 552f7bafc77ba12bb1beb665243a0334cd81e024728Ted Kremenek vec->push_back(std::make_pair(ex, isAlwaysUninit)); 55394b1b4d785bc0f09f6af4be394e59d51f35dda60Ted Kremenek } 55494b1b4d785bc0f09f6af4be394e59d51f35dda60Ted Kremenek 55594b1b4d785bc0f09f6af4be394e59d51f35dda60Ted Kremenek void flushDiagnostics() { 55694b1b4d785bc0f09f6af4be394e59d51f35dda60Ted Kremenek if (!uses) 55794b1b4d785bc0f09f6af4be394e59d51f35dda60Ted Kremenek return; 558609e3170841dac81c3b7b6b9eccb9c520e42c9b2Ted Kremenek 55994b1b4d785bc0f09f6af4be394e59d51f35dda60Ted Kremenek for (UsesMap::iterator i = uses->begin(), e = uses->end(); i != e; ++i) { 56094b1b4d785bc0f09f6af4be394e59d51f35dda60Ted Kremenek const VarDecl *vd = i->first; 56194b1b4d785bc0f09f6af4be394e59d51f35dda60Ted Kremenek UsesVec *vec = i->second; 562609e3170841dac81c3b7b6b9eccb9c520e42c9b2Ted Kremenek 563609e3170841dac81c3b7b6b9eccb9c520e42c9b2Ted Kremenek bool fixitIssued = false; 564609e3170841dac81c3b7b6b9eccb9c520e42c9b2Ted Kremenek 56594b1b4d785bc0f09f6af4be394e59d51f35dda60Ted Kremenek // Sort the uses by their SourceLocations. While not strictly 56694b1b4d785bc0f09f6af4be394e59d51f35dda60Ted Kremenek // guaranteed to produce them in line/column order, this will provide 56794b1b4d785bc0f09f6af4be394e59d51f35dda60Ted Kremenek // a stable ordering. 56894b1b4d785bc0f09f6af4be394e59d51f35dda60Ted Kremenek std::sort(vec->begin(), vec->end(), SLocSort()); 56994b1b4d785bc0f09f6af4be394e59d51f35dda60Ted Kremenek 57064fb959beb3a0ecb84a58e6ff82660a7a669f7b8Chandler Carruth for (UsesVec::iterator vi = vec->begin(), ve = vec->end(); vi != ve; 57164fb959beb3a0ecb84a58e6ff82660a7a669f7b8Chandler Carruth ++vi) { 572262d50e1dcf529317da193ad585c11c16281a7acChandler Carruth if (!DiagnoseUninitializedUse(S, vd, vi->first, 573262d50e1dcf529317da193ad585c11c16281a7acChandler Carruth /*isAlwaysUninit=*/vi->second)) 574262d50e1dcf529317da193ad585c11c16281a7acChandler Carruth continue; 575262d50e1dcf529317da193ad585c11c16281a7acChandler Carruth 576262d50e1dcf529317da193ad585c11c16281a7acChandler Carruth // Suggest a fixit hint the first time we diagnose a use of a variable. 577262d50e1dcf529317da193ad585c11c16281a7acChandler Carruth if (!fixitIssued) { 578262d50e1dcf529317da193ad585c11c16281a7acChandler Carruth SuggestInitializationFixit(S, vd); 579262d50e1dcf529317da193ad585c11c16281a7acChandler Carruth fixitIssued = true; 580262d50e1dcf529317da193ad585c11c16281a7acChandler Carruth } 58164fb959beb3a0ecb84a58e6ff82660a7a669f7b8Chandler Carruth } 582fbb178a0b47fca1b0fb78c5d41198614cf52aa70Ted Kremenek 58394b1b4d785bc0f09f6af4be394e59d51f35dda60Ted Kremenek delete vec; 58494b1b4d785bc0f09f6af4be394e59d51f35dda60Ted Kremenek } 58594b1b4d785bc0f09f6af4be394e59d51f35dda60Ted Kremenek delete uses; 586610068c8cd2321f90e147b12cf794e1f840b6405Ted Kremenek } 587610068c8cd2321f90e147b12cf794e1f840b6405Ted Kremenek}; 588610068c8cd2321f90e147b12cf794e1f840b6405Ted Kremenek} 589610068c8cd2321f90e147b12cf794e1f840b6405Ted Kremenek 590610068c8cd2321f90e147b12cf794e1f840b6405Ted Kremenek//===----------------------------------------------------------------------===// 591dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek// AnalysisBasedWarnings - Worker object used by Sema to execute analysis-based 592dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek// warnings on a function, method, or block. 593dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek//===----------------------------------------------------------------------===// 594dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek 595d064fdc4b7b64ca55b40b70490c79d6f569df78eTed Kremenekclang::sema::AnalysisBasedWarnings::Policy::Policy() { 596dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek enableCheckFallThrough = 1; 597d064fdc4b7b64ca55b40b70490c79d6f569df78eTed Kremenek enableCheckUnreachable = 0; 598d064fdc4b7b64ca55b40b70490c79d6f569df78eTed Kremenek} 599dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek 6005d98994c7749312a43ce6adf45537979a98e7afdChandler Carruthclang::sema::AnalysisBasedWarnings::AnalysisBasedWarnings(Sema &s) 6015d98994c7749312a43ce6adf45537979a98e7afdChandler Carruth : S(s), 6025d98994c7749312a43ce6adf45537979a98e7afdChandler Carruth NumFunctionsAnalyzed(0), 60354cf341bd4145e5e31f91c5777fcdaf3f2400537Benjamin Kramer NumFunctionsWithBadCFGs(0), 6045d98994c7749312a43ce6adf45537979a98e7afdChandler Carruth NumCFGBlocks(0), 60554cf341bd4145e5e31f91c5777fcdaf3f2400537Benjamin Kramer MaxCFGBlocksPerFunction(0), 60654cf341bd4145e5e31f91c5777fcdaf3f2400537Benjamin Kramer NumUninitAnalysisFunctions(0), 60754cf341bd4145e5e31f91c5777fcdaf3f2400537Benjamin Kramer NumUninitAnalysisVariables(0), 60854cf341bd4145e5e31f91c5777fcdaf3f2400537Benjamin Kramer MaxUninitAnalysisVariablesPerFunction(0), 60954cf341bd4145e5e31f91c5777fcdaf3f2400537Benjamin Kramer NumUninitAnalysisBlockVisits(0), 61054cf341bd4145e5e31f91c5777fcdaf3f2400537Benjamin Kramer MaxUninitAnalysisBlockVisitsPerFunction(0) { 611d064fdc4b7b64ca55b40b70490c79d6f569df78eTed Kremenek Diagnostic &D = S.getDiagnostics(); 612d064fdc4b7b64ca55b40b70490c79d6f569df78eTed Kremenek DefaultPolicy.enableCheckUnreachable = (unsigned) 6130827408865e32789e0ec4b8113a302ccdc531423Argyrios Kyrtzidis (D.getDiagnosticLevel(diag::warn_unreachable, SourceLocation()) != 6140827408865e32789e0ec4b8113a302ccdc531423Argyrios Kyrtzidis Diagnostic::Ignored); 615dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek} 616dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek 617351ba91eaa6d30e523587b2d7ed676a5172c6e56Ted Kremenekstatic void flushDiagnostics(Sema &S, sema::FunctionScopeInfo *fscope) { 618351ba91eaa6d30e523587b2d7ed676a5172c6e56Ted Kremenek for (llvm::SmallVectorImpl<sema::PossiblyUnreachableDiag>::iterator 619351ba91eaa6d30e523587b2d7ed676a5172c6e56Ted Kremenek i = fscope->PossiblyUnreachableDiags.begin(), 620351ba91eaa6d30e523587b2d7ed676a5172c6e56Ted Kremenek e = fscope->PossiblyUnreachableDiags.end(); 621351ba91eaa6d30e523587b2d7ed676a5172c6e56Ted Kremenek i != e; ++i) { 622351ba91eaa6d30e523587b2d7ed676a5172c6e56Ted Kremenek const sema::PossiblyUnreachableDiag &D = *i; 623351ba91eaa6d30e523587b2d7ed676a5172c6e56Ted Kremenek S.Diag(D.Loc, D.PD); 624351ba91eaa6d30e523587b2d7ed676a5172c6e56Ted Kremenek } 625351ba91eaa6d30e523587b2d7ed676a5172c6e56Ted Kremenek} 626351ba91eaa6d30e523587b2d7ed676a5172c6e56Ted Kremenek 627d064fdc4b7b64ca55b40b70490c79d6f569df78eTed Kremenekvoid clang::sema:: 628d064fdc4b7b64ca55b40b70490c79d6f569df78eTed KremenekAnalysisBasedWarnings::IssueWarnings(sema::AnalysisBasedWarnings::Policy P, 629283a358aecb75e30fcd486f2206f6c03c5e7f11dTed Kremenek sema::FunctionScopeInfo *fscope, 6303ed6fc08a9cd293d012fa49ab2a615e618d7c3faTed Kremenek const Decl *D, const BlockExpr *blkExpr) { 631d068aabc484c4009282122c6ef26e66e68cfa044Ted Kremenek 632dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek // We avoid doing analysis-based warnings when there are errors for 633dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek // two reasons: 634dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek // (1) The CFGs often can't be constructed (if the body is invalid), so 635dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek // don't bother trying. 636dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek // (2) The code already has problems; running the analysis just takes more 637dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek // time. 63899e8192c4c8f1f596f9969e5f2cdafcee64ddaacTed Kremenek Diagnostic &Diags = S.getDiagnostics(); 63999e8192c4c8f1f596f9969e5f2cdafcee64ddaacTed Kremenek 640d064fdc4b7b64ca55b40b70490c79d6f569df78eTed Kremenek // Do not do any analysis for declarations in system headers if we are 641d064fdc4b7b64ca55b40b70490c79d6f569df78eTed Kremenek // going to just ignore them. 64299e8192c4c8f1f596f9969e5f2cdafcee64ddaacTed Kremenek if (Diags.getSuppressSystemWarnings() && 643d064fdc4b7b64ca55b40b70490c79d6f569df78eTed Kremenek S.SourceMgr.isInSystemHeader(D->getLocation())) 644d064fdc4b7b64ca55b40b70490c79d6f569df78eTed Kremenek return; 645d064fdc4b7b64ca55b40b70490c79d6f569df78eTed Kremenek 646e0054f61fd84133eb0d19c19ae9afaf117933274John McCall // For code in dependent contexts, we'll do this at instantiation time. 647e0054f61fd84133eb0d19c19ae9afaf117933274John McCall if (cast<DeclContext>(D)->isDependentContext()) 648e0054f61fd84133eb0d19c19ae9afaf117933274John McCall return; 649dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek 650351ba91eaa6d30e523587b2d7ed676a5172c6e56Ted Kremenek if (Diags.hasErrorOccurred() || Diags.hasFatalErrorOccurred()) { 651351ba91eaa6d30e523587b2d7ed676a5172c6e56Ted Kremenek // Flush out any possibly unreachable diagnostics. 652351ba91eaa6d30e523587b2d7ed676a5172c6e56Ted Kremenek flushDiagnostics(S, fscope); 653351ba91eaa6d30e523587b2d7ed676a5172c6e56Ted Kremenek return; 654351ba91eaa6d30e523587b2d7ed676a5172c6e56Ted Kremenek } 655351ba91eaa6d30e523587b2d7ed676a5172c6e56Ted Kremenek 656dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek const Stmt *Body = D->getBody(); 657dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek assert(Body); 658dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek 659dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek // Don't generate EH edges for CallExprs as we'd like to avoid the n^2 660dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek // explosion for destrutors that can result and the compile time hit. 661eeef924c4fcb79a3bcc8782afce343e641bbcb83Chandler Carruth AnalysisContext AC(D, 0, /*useUnoptimizedCFG=*/false, /*addehedges=*/false, 662eeef924c4fcb79a3bcc8782afce343e641bbcb83Chandler Carruth /*addImplicitDtors=*/true, /*addInitializers=*/true); 663dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek 664351ba91eaa6d30e523587b2d7ed676a5172c6e56Ted Kremenek // Emit delayed diagnostics. 665351ba91eaa6d30e523587b2d7ed676a5172c6e56Ted Kremenek if (!fscope->PossiblyUnreachableDiags.empty()) { 666351ba91eaa6d30e523587b2d7ed676a5172c6e56Ted Kremenek bool analyzed = false; 6670d28d360b5559abda755e50b855ba5e59727d9cdTed Kremenek 6680d28d360b5559abda755e50b855ba5e59727d9cdTed Kremenek // Register the expressions with the CFGBuilder. 6690d28d360b5559abda755e50b855ba5e59727d9cdTed Kremenek for (llvm::SmallVectorImpl<sema::PossiblyUnreachableDiag>::iterator 6700d28d360b5559abda755e50b855ba5e59727d9cdTed Kremenek i = fscope->PossiblyUnreachableDiags.begin(), 6710d28d360b5559abda755e50b855ba5e59727d9cdTed Kremenek e = fscope->PossiblyUnreachableDiags.end(); 6720d28d360b5559abda755e50b855ba5e59727d9cdTed Kremenek i != e; ++i) { 6730d28d360b5559abda755e50b855ba5e59727d9cdTed Kremenek if (const Stmt *stmt = i->stmt) 6740d28d360b5559abda755e50b855ba5e59727d9cdTed Kremenek AC.registerForcedBlockExpression(stmt); 6750d28d360b5559abda755e50b855ba5e59727d9cdTed Kremenek } 6760d28d360b5559abda755e50b855ba5e59727d9cdTed Kremenek 6770d28d360b5559abda755e50b855ba5e59727d9cdTed Kremenek if (AC.getCFG()) { 6780d28d360b5559abda755e50b855ba5e59727d9cdTed Kremenek analyzed = true; 6790d28d360b5559abda755e50b855ba5e59727d9cdTed Kremenek for (llvm::SmallVectorImpl<sema::PossiblyUnreachableDiag>::iterator 6800d28d360b5559abda755e50b855ba5e59727d9cdTed Kremenek i = fscope->PossiblyUnreachableDiags.begin(), 6810d28d360b5559abda755e50b855ba5e59727d9cdTed Kremenek e = fscope->PossiblyUnreachableDiags.end(); 6820d28d360b5559abda755e50b855ba5e59727d9cdTed Kremenek i != e; ++i) 6830d28d360b5559abda755e50b855ba5e59727d9cdTed Kremenek { 6840d28d360b5559abda755e50b855ba5e59727d9cdTed Kremenek const sema::PossiblyUnreachableDiag &D = *i; 6850d28d360b5559abda755e50b855ba5e59727d9cdTed Kremenek bool processed = false; 6860d28d360b5559abda755e50b855ba5e59727d9cdTed Kremenek if (const Stmt *stmt = i->stmt) { 6870d28d360b5559abda755e50b855ba5e59727d9cdTed Kremenek const CFGBlock *block = AC.getBlockForRegisteredExpression(stmt); 6880d28d360b5559abda755e50b855ba5e59727d9cdTed Kremenek assert(block); 689af13d5b25b360e698cc1cf1055ad7d14e008e505Ted Kremenek if (CFGReverseBlockReachabilityAnalysis *cra = AC.getCFGReachablityAnalysis()) { 690351ba91eaa6d30e523587b2d7ed676a5172c6e56Ted Kremenek // Can this block be reached from the entrance? 6910d28d360b5559abda755e50b855ba5e59727d9cdTed Kremenek if (cra->isReachable(&AC.getCFG()->getEntry(), block)) 692351ba91eaa6d30e523587b2d7ed676a5172c6e56Ted Kremenek S.Diag(D.Loc, D.PD); 6930d28d360b5559abda755e50b855ba5e59727d9cdTed Kremenek processed = true; 694351ba91eaa6d30e523587b2d7ed676a5172c6e56Ted Kremenek } 6950d28d360b5559abda755e50b855ba5e59727d9cdTed Kremenek } 6960d28d360b5559abda755e50b855ba5e59727d9cdTed Kremenek if (!processed) { 6970d28d360b5559abda755e50b855ba5e59727d9cdTed Kremenek // Emit the warning anyway if we cannot map to a basic block. 6980d28d360b5559abda755e50b855ba5e59727d9cdTed Kremenek S.Diag(D.Loc, D.PD); 699351ba91eaa6d30e523587b2d7ed676a5172c6e56Ted Kremenek } 700351ba91eaa6d30e523587b2d7ed676a5172c6e56Ted Kremenek } 7010d28d360b5559abda755e50b855ba5e59727d9cdTed Kremenek } 702351ba91eaa6d30e523587b2d7ed676a5172c6e56Ted Kremenek 703351ba91eaa6d30e523587b2d7ed676a5172c6e56Ted Kremenek if (!analyzed) 704351ba91eaa6d30e523587b2d7ed676a5172c6e56Ted Kremenek flushDiagnostics(S, fscope); 705351ba91eaa6d30e523587b2d7ed676a5172c6e56Ted Kremenek } 706351ba91eaa6d30e523587b2d7ed676a5172c6e56Ted Kremenek 707351ba91eaa6d30e523587b2d7ed676a5172c6e56Ted Kremenek 708dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek // Warning: check missing 'return' 709d064fdc4b7b64ca55b40b70490c79d6f569df78eTed Kremenek if (P.enableCheckFallThrough) { 710dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek const CheckFallThroughDiagnostics &CD = 711dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek (isa<BlockDecl>(D) ? CheckFallThroughDiagnostics::MakeForBlock() 712ca7eaeeed817001dc7cee4852a7e41f0982da1efDouglas Gregor : CheckFallThroughDiagnostics::MakeForFunction(D)); 7133ed6fc08a9cd293d012fa49ab2a615e618d7c3faTed Kremenek CheckFallThroughForBody(S, D, Body, blkExpr, CD, AC); 714dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek } 715dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek 716dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek // Warning: check for unreachable code 717b7e5f145f47b6ec1db1ba6fe9db9c0ed2fe38db3Ted Kremenek if (P.enableCheckUnreachable) 718dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek CheckUnreachable(S, AC); 719610068c8cd2321f90e147b12cf794e1f840b6405Ted Kremenek 720a8c17a5babab35f2db26bf218e7571d1af4afedfTed Kremenek if (Diags.getDiagnosticLevel(diag::warn_uninit_var, D->getLocStart()) 72176709bf816e5e1b70b859bb607cf3ee91db12b76Ted Kremenek != Diagnostic::Ignored || 72276709bf816e5e1b70b859bb607cf3ee91db12b76Ted Kremenek Diags.getDiagnosticLevel(diag::warn_maybe_uninit_var, D->getLocStart()) 723610068c8cd2321f90e147b12cf794e1f840b6405Ted Kremenek != Diagnostic::Ignored) { 724c5e43c19ddb40b8a1371291f73ae66fe54951ca5Ted Kremenek if (CFG *cfg = AC.getCFG()) { 725c21fed361c11f13db345cba69101578578d8fb79Ted Kremenek UninitValsDiagReporter reporter(S); 72657080fbac1ccce702255423335d52e81bcf17b6bFariborz Jahanian UninitVariablesAnalysisStats stats; 727a8c17a5babab35f2db26bf218e7571d1af4afedfTed Kremenek runUninitializedVariablesAnalysis(*cast<DeclContext>(D), *cfg, AC, 7285d98994c7749312a43ce6adf45537979a98e7afdChandler Carruth reporter, stats); 7295d98994c7749312a43ce6adf45537979a98e7afdChandler Carruth 7305d98994c7749312a43ce6adf45537979a98e7afdChandler Carruth if (S.CollectStats && stats.NumVariablesAnalyzed > 0) { 7315d98994c7749312a43ce6adf45537979a98e7afdChandler Carruth ++NumUninitAnalysisFunctions; 7325d98994c7749312a43ce6adf45537979a98e7afdChandler Carruth NumUninitAnalysisVariables += stats.NumVariablesAnalyzed; 7335d98994c7749312a43ce6adf45537979a98e7afdChandler Carruth NumUninitAnalysisBlockVisits += stats.NumBlockVisits; 7345d98994c7749312a43ce6adf45537979a98e7afdChandler Carruth MaxUninitAnalysisVariablesPerFunction = 7355d98994c7749312a43ce6adf45537979a98e7afdChandler Carruth std::max(MaxUninitAnalysisVariablesPerFunction, 7365d98994c7749312a43ce6adf45537979a98e7afdChandler Carruth stats.NumVariablesAnalyzed); 7375d98994c7749312a43ce6adf45537979a98e7afdChandler Carruth MaxUninitAnalysisBlockVisitsPerFunction = 7385d98994c7749312a43ce6adf45537979a98e7afdChandler Carruth std::max(MaxUninitAnalysisBlockVisitsPerFunction, 7395d98994c7749312a43ce6adf45537979a98e7afdChandler Carruth stats.NumBlockVisits); 7405d98994c7749312a43ce6adf45537979a98e7afdChandler Carruth } 7415d98994c7749312a43ce6adf45537979a98e7afdChandler Carruth } 7425d98994c7749312a43ce6adf45537979a98e7afdChandler Carruth } 7435d98994c7749312a43ce6adf45537979a98e7afdChandler Carruth 7445d98994c7749312a43ce6adf45537979a98e7afdChandler Carruth // Collect statistics about the CFG if it was built. 7455d98994c7749312a43ce6adf45537979a98e7afdChandler Carruth if (S.CollectStats && AC.isCFGBuilt()) { 7465d98994c7749312a43ce6adf45537979a98e7afdChandler Carruth ++NumFunctionsAnalyzed; 7475d98994c7749312a43ce6adf45537979a98e7afdChandler Carruth if (CFG *cfg = AC.getCFG()) { 7485d98994c7749312a43ce6adf45537979a98e7afdChandler Carruth // If we successfully built a CFG for this context, record some more 7495d98994c7749312a43ce6adf45537979a98e7afdChandler Carruth // detail information about it. 7503ea4c49709c5bba5f8b16c6ceb725d9b9a1c48c6Chandler Carruth NumCFGBlocks += cfg->getNumBlockIDs(); 7515d98994c7749312a43ce6adf45537979a98e7afdChandler Carruth MaxCFGBlocksPerFunction = std::max(MaxCFGBlocksPerFunction, 7523ea4c49709c5bba5f8b16c6ceb725d9b9a1c48c6Chandler Carruth cfg->getNumBlockIDs()); 7535d98994c7749312a43ce6adf45537979a98e7afdChandler Carruth } else { 7545d98994c7749312a43ce6adf45537979a98e7afdChandler Carruth ++NumFunctionsWithBadCFGs; 755610068c8cd2321f90e147b12cf794e1f840b6405Ted Kremenek } 756610068c8cd2321f90e147b12cf794e1f840b6405Ted Kremenek } 757dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek} 7585d98994c7749312a43ce6adf45537979a98e7afdChandler Carruth 7595d98994c7749312a43ce6adf45537979a98e7afdChandler Carruthvoid clang::sema::AnalysisBasedWarnings::PrintStats() const { 7605d98994c7749312a43ce6adf45537979a98e7afdChandler Carruth llvm::errs() << "\n*** Analysis Based Warnings Stats:\n"; 7615d98994c7749312a43ce6adf45537979a98e7afdChandler Carruth 7625d98994c7749312a43ce6adf45537979a98e7afdChandler Carruth unsigned NumCFGsBuilt = NumFunctionsAnalyzed - NumFunctionsWithBadCFGs; 7635d98994c7749312a43ce6adf45537979a98e7afdChandler Carruth unsigned AvgCFGBlocksPerFunction = 7645d98994c7749312a43ce6adf45537979a98e7afdChandler Carruth !NumCFGsBuilt ? 0 : NumCFGBlocks/NumCFGsBuilt; 7655d98994c7749312a43ce6adf45537979a98e7afdChandler Carruth llvm::errs() << NumFunctionsAnalyzed << " functions analyzed (" 7665d98994c7749312a43ce6adf45537979a98e7afdChandler Carruth << NumFunctionsWithBadCFGs << " w/o CFGs).\n" 7675d98994c7749312a43ce6adf45537979a98e7afdChandler Carruth << " " << NumCFGBlocks << " CFG blocks built.\n" 7685d98994c7749312a43ce6adf45537979a98e7afdChandler Carruth << " " << AvgCFGBlocksPerFunction 7695d98994c7749312a43ce6adf45537979a98e7afdChandler Carruth << " average CFG blocks per function.\n" 7705d98994c7749312a43ce6adf45537979a98e7afdChandler Carruth << " " << MaxCFGBlocksPerFunction 7715d98994c7749312a43ce6adf45537979a98e7afdChandler Carruth << " max CFG blocks per function.\n"; 7725d98994c7749312a43ce6adf45537979a98e7afdChandler Carruth 7735d98994c7749312a43ce6adf45537979a98e7afdChandler Carruth unsigned AvgUninitVariablesPerFunction = !NumUninitAnalysisFunctions ? 0 7745d98994c7749312a43ce6adf45537979a98e7afdChandler Carruth : NumUninitAnalysisVariables/NumUninitAnalysisFunctions; 7755d98994c7749312a43ce6adf45537979a98e7afdChandler Carruth unsigned AvgUninitBlockVisitsPerFunction = !NumUninitAnalysisFunctions ? 0 7765d98994c7749312a43ce6adf45537979a98e7afdChandler Carruth : NumUninitAnalysisBlockVisits/NumUninitAnalysisFunctions; 7775d98994c7749312a43ce6adf45537979a98e7afdChandler Carruth llvm::errs() << NumUninitAnalysisFunctions 7785d98994c7749312a43ce6adf45537979a98e7afdChandler Carruth << " functions analyzed for uninitialiazed variables\n" 7795d98994c7749312a43ce6adf45537979a98e7afdChandler Carruth << " " << NumUninitAnalysisVariables << " variables analyzed.\n" 7805d98994c7749312a43ce6adf45537979a98e7afdChandler Carruth << " " << AvgUninitVariablesPerFunction 7815d98994c7749312a43ce6adf45537979a98e7afdChandler Carruth << " average variables per function.\n" 7825d98994c7749312a43ce6adf45537979a98e7afdChandler Carruth << " " << MaxUninitAnalysisVariablesPerFunction 7835d98994c7749312a43ce6adf45537979a98e7afdChandler Carruth << " max variables per function.\n" 7845d98994c7749312a43ce6adf45537979a98e7afdChandler Carruth << " " << NumUninitAnalysisBlockVisits << " block visits.\n" 7855d98994c7749312a43ce6adf45537979a98e7afdChandler Carruth << " " << AvgUninitBlockVisitsPerFunction 7865d98994c7749312a43ce6adf45537979a98e7afdChandler Carruth << " average block visits per function.\n" 7875d98994c7749312a43ce6adf45537979a98e7afdChandler Carruth << " " << MaxUninitAnalysisBlockVisitsPerFunction 7885d98994c7749312a43ce6adf45537979a98e7afdChandler Carruth << " max block visits per function.\n"; 7895d98994c7749312a43ce6adf45537979a98e7afdChandler Carruth} 790