AnalysisBasedWarnings.cpp revision 2c0abf4ae33ab2ba690ccae724b8d6f196e7cfda
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" 2075f23aeb1c820b49f9faebed63b1cbef76c2c907Caitlin Sadowski#include "clang/Basic/SourceLocation.h" 21fbb178a0b47fca1b0fb78c5d41198614cf52aa70Ted Kremenek#include "clang/Lex/Preprocessor.h" 227cd088e519d7e6caa4c4c12db52e0e4ae35d25c2John McCall#include "clang/AST/DeclObjC.h" 23384aff8b94bb0d1ad6c5667b90621e5699815bb2John McCall#include "clang/AST/DeclCXX.h" 24dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek#include "clang/AST/ExprObjC.h" 25dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek#include "clang/AST/ExprCXX.h" 26dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek#include "clang/AST/StmtObjC.h" 27dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek#include "clang/AST/StmtCXX.h" 286f41715df2c6a31c0c3ab3088b8cd18a3c8321b8Ted Kremenek#include "clang/AST/EvaluatedExprVisitor.h" 293ac1fbc303d22af2e11a14023ecee7bd7b7d0bfdCaitlin Sadowski#include "clang/AST/StmtVisitor.h" 30dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek#include "clang/Analysis/AnalysisContext.h" 31dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek#include "clang/Analysis/CFG.h" 32dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek#include "clang/Analysis/Analyses/ReachableCode.h" 33351ba91eaa6d30e523587b2d7ed676a5172c6e56Ted Kremenek#include "clang/Analysis/Analyses/CFGReachabilityAnalysis.h" 34402aa0698fec81e574818a0a6c2000fac0b2c4c6Caitlin Sadowski#include "clang/Analysis/Analyses/ThreadSafety.h" 35351ba91eaa6d30e523587b2d7ed676a5172c6e56Ted Kremenek#include "clang/Analysis/CFGStmtMap.h" 366f34213f8d6ae8c77685b53664527e39bfaaca3bTed Kremenek#include "clang/Analysis/Analyses/UninitializedValues.h" 37dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek#include "llvm/ADT/BitVector.h" 383ac1fbc303d22af2e11a14023ecee7bd7b7d0bfdCaitlin Sadowski#include "llvm/ADT/FoldingSet.h" 393ac1fbc303d22af2e11a14023ecee7bd7b7d0bfdCaitlin Sadowski#include "llvm/ADT/ImmutableMap.h" 403ac1fbc303d22af2e11a14023ecee7bd7b7d0bfdCaitlin Sadowski#include "llvm/ADT/PostOrderIterator.h" 413ac1fbc303d22af2e11a14023ecee7bd7b7d0bfdCaitlin Sadowski#include "llvm/ADT/SmallVector.h" 4275f23aeb1c820b49f9faebed63b1cbef76c2c907Caitlin Sadowski#include "llvm/ADT/StringRef.h" 43dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek#include "llvm/Support/Casting.h" 443ac1fbc303d22af2e11a14023ecee7bd7b7d0bfdCaitlin Sadowski#include <algorithm> 453ac1fbc303d22af2e11a14023ecee7bd7b7d0bfdCaitlin Sadowski#include <vector> 46dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek 47dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenekusing namespace clang; 48dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek 49dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek//===----------------------------------------------------------------------===// 50dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek// Unreachable code analysis. 51dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek//===----------------------------------------------------------------------===// 52dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek 53dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremeneknamespace { 54dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek class UnreachableCodeHandler : public reachable_code::Callback { 55dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek Sema &S; 56dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek public: 57dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek UnreachableCodeHandler(Sema &s) : S(s) {} 58dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek 59dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek void HandleUnreachable(SourceLocation L, SourceRange R1, SourceRange R2) { 60dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek S.Diag(L, diag::warn_unreachable) << R1 << R2; 61dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek } 62dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek }; 63dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek} 64dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek 65dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek/// CheckUnreachable - Check for unreachable code. 661d26f48dc2eea1c07431ca1519d7034a21b9bcffTed Kremenekstatic void CheckUnreachable(Sema &S, AnalysisDeclContext &AC) { 67dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek UnreachableCodeHandler UC(S); 68dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek reachable_code::FindUnreachableCode(AC, UC); 69dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek} 70dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek 71dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek//===----------------------------------------------------------------------===// 72dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek// Check for missing return value. 73dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek//===----------------------------------------------------------------------===// 74dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek 7516565aa95b086fb239baf82335dccc1b1ec93942John McCallenum ControlFlowKind { 7616565aa95b086fb239baf82335dccc1b1ec93942John McCall UnknownFallThrough, 7716565aa95b086fb239baf82335dccc1b1ec93942John McCall NeverFallThrough, 7816565aa95b086fb239baf82335dccc1b1ec93942John McCall MaybeFallThrough, 7916565aa95b086fb239baf82335dccc1b1ec93942John McCall AlwaysFallThrough, 8016565aa95b086fb239baf82335dccc1b1ec93942John McCall NeverFallThroughOrReturn 8116565aa95b086fb239baf82335dccc1b1ec93942John McCall}; 82dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek 83dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek/// CheckFallThrough - Check that we don't fall off the end of a 84dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek/// Statement that should return a value. 85dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek/// 86dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek/// \returns AlwaysFallThrough iff we always fall off the end of the statement, 87dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek/// MaybeFallThrough iff we might or might not fall off the end, 88dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek/// NeverFallThroughOrReturn iff we never fall off the end of the statement or 89dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek/// return. We assume NeverFallThrough iff we never fall off the end of the 90dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek/// statement but we may return. We assume that functions not marked noreturn 91dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek/// will return. 921d26f48dc2eea1c07431ca1519d7034a21b9bcffTed Kremenekstatic ControlFlowKind CheckFallThrough(AnalysisDeclContext &AC) { 93dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek CFG *cfg = AC.getCFG(); 9416565aa95b086fb239baf82335dccc1b1ec93942John McCall if (cfg == 0) return UnknownFallThrough; 95dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek 96dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek // The CFG leaves in dead things, and we don't want the dead code paths to 97dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek // confuse us, so we mark all live things first. 98dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek llvm::BitVector live(cfg->getNumBlockIDs()); 990f3b4ca1764cd6d457f511d340fba504f41763c3Ted Kremenek unsigned count = reachable_code::ScanReachableFromBlock(&cfg->getEntry(), 100dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek live); 101dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek 102dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek bool AddEHEdges = AC.getAddEHEdges(); 103dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek if (!AddEHEdges && count != cfg->getNumBlockIDs()) 104dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek // When there are things remaining dead, and we didn't add EH edges 105dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek // from CallExprs to the catch clauses, we have to go back and 106dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek // mark them as live. 107dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek for (CFG::iterator I = cfg->begin(), E = cfg->end(); I != E; ++I) { 108dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek CFGBlock &b = **I; 109dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek if (!live[b.getBlockID()]) { 110dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek if (b.pred_begin() == b.pred_end()) { 111dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek if (b.getTerminator() && isa<CXXTryStmt>(b.getTerminator())) 112dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek // When not adding EH edges from calls, catch clauses 113dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek // can otherwise seem dead. Avoid noting them as dead. 1140f3b4ca1764cd6d457f511d340fba504f41763c3Ted Kremenek count += reachable_code::ScanReachableFromBlock(&b, live); 115dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek continue; 116dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek } 117dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek } 118dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek } 119dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek 120dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek // Now we know what is live, we check the live precessors of the exit block 121dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek // and look for fall through paths, being careful to ignore normal returns, 122dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek // and exceptional paths. 123dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek bool HasLiveReturn = false; 124dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek bool HasFakeEdge = false; 125dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek bool HasPlainEdge = false; 126dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek bool HasAbnormalEdge = false; 12790b828aa279542559f655d1af666580288cb1841Ted Kremenek 12890b828aa279542559f655d1af666580288cb1841Ted Kremenek // Ignore default cases that aren't likely to be reachable because all 12990b828aa279542559f655d1af666580288cb1841Ted Kremenek // enums in a switch(X) have explicit case statements. 13090b828aa279542559f655d1af666580288cb1841Ted Kremenek CFGBlock::FilterOptions FO; 13190b828aa279542559f655d1af666580288cb1841Ted Kremenek FO.IgnoreDefaultsWithCoveredEnums = 1; 13290b828aa279542559f655d1af666580288cb1841Ted Kremenek 13390b828aa279542559f655d1af666580288cb1841Ted Kremenek for (CFGBlock::filtered_pred_iterator 13490b828aa279542559f655d1af666580288cb1841Ted Kremenek I = cfg->getExit().filtered_pred_start_end(FO); I.hasMore(); ++I) { 13590b828aa279542559f655d1af666580288cb1841Ted Kremenek const CFGBlock& B = **I; 136dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek if (!live[B.getBlockID()]) 137dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek continue; 1385811f5978feaa7b89bd89e174fa7ad077b48413eTed Kremenek 139e05ee6df356c25e792b0334d7a4dec3fe4f79f07Chandler Carruth // Skip blocks which contain an element marked as no-return. They don't 140e05ee6df356c25e792b0334d7a4dec3fe4f79f07Chandler Carruth // represent actually viable edges into the exit block, so mark them as 141e05ee6df356c25e792b0334d7a4dec3fe4f79f07Chandler Carruth // abnormal. 142e05ee6df356c25e792b0334d7a4dec3fe4f79f07Chandler Carruth if (B.hasNoReturnElement()) { 143e05ee6df356c25e792b0334d7a4dec3fe4f79f07Chandler Carruth HasAbnormalEdge = true; 144e05ee6df356c25e792b0334d7a4dec3fe4f79f07Chandler Carruth continue; 145e05ee6df356c25e792b0334d7a4dec3fe4f79f07Chandler Carruth } 146e05ee6df356c25e792b0334d7a4dec3fe4f79f07Chandler Carruth 1475811f5978feaa7b89bd89e174fa7ad077b48413eTed Kremenek // Destructors can appear after the 'return' in the CFG. This is 1485811f5978feaa7b89bd89e174fa7ad077b48413eTed Kremenek // normal. We need to look pass the destructors for the return 1495811f5978feaa7b89bd89e174fa7ad077b48413eTed Kremenek // statement (if it exists). 1505811f5978feaa7b89bd89e174fa7ad077b48413eTed Kremenek CFGBlock::const_reverse_iterator ri = B.rbegin(), re = B.rend(); 151e05ee6df356c25e792b0334d7a4dec3fe4f79f07Chandler Carruth 152e05ee6df356c25e792b0334d7a4dec3fe4f79f07Chandler Carruth for ( ; ri != re ; ++ri) 153e05ee6df356c25e792b0334d7a4dec3fe4f79f07Chandler Carruth if (isa<CFGStmt>(*ri)) 1545811f5978feaa7b89bd89e174fa7ad077b48413eTed Kremenek break; 155e05ee6df356c25e792b0334d7a4dec3fe4f79f07Chandler Carruth 1565811f5978feaa7b89bd89e174fa7ad077b48413eTed Kremenek // No more CFGElements in the block? 1575811f5978feaa7b89bd89e174fa7ad077b48413eTed Kremenek if (ri == re) { 158dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek if (B.getTerminator() && isa<CXXTryStmt>(B.getTerminator())) { 159dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek HasAbnormalEdge = true; 160dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek continue; 161dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek } 162dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek // A labeled empty statement, or the entry block... 163dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek HasPlainEdge = true; 164dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek continue; 165dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek } 166f39e6a388aaa2f155b46c61e655784b2473218ebTed Kremenek 1675811f5978feaa7b89bd89e174fa7ad077b48413eTed Kremenek CFGStmt CS = cast<CFGStmt>(*ri); 168f1d10d939739f1a4544926d807e4f0f9fb64be61Ted Kremenek const Stmt *S = CS.getStmt(); 169dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek if (isa<ReturnStmt>(S)) { 170dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek HasLiveReturn = true; 171dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek continue; 172dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek } 173dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek if (isa<ObjCAtThrowStmt>(S)) { 174dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek HasFakeEdge = true; 175dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek continue; 176dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek } 177dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek if (isa<CXXThrowExpr>(S)) { 178dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek HasFakeEdge = true; 179dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek continue; 180dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek } 181dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek if (const AsmStmt *AS = dyn_cast<AsmStmt>(S)) { 182dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek if (AS->isMSAsm()) { 183dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek HasFakeEdge = true; 184dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek HasLiveReturn = true; 185dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek continue; 186dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek } 187dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek } 188dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek if (isa<CXXTryStmt>(S)) { 189dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek HasAbnormalEdge = true; 190dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek continue; 191dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek } 192e05ee6df356c25e792b0334d7a4dec3fe4f79f07Chandler Carruth if (std::find(B.succ_begin(), B.succ_end(), &cfg->getExit()) 193e05ee6df356c25e792b0334d7a4dec3fe4f79f07Chandler Carruth == B.succ_end()) { 194e05ee6df356c25e792b0334d7a4dec3fe4f79f07Chandler Carruth HasAbnormalEdge = true; 195e05ee6df356c25e792b0334d7a4dec3fe4f79f07Chandler Carruth continue; 196dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek } 197e05ee6df356c25e792b0334d7a4dec3fe4f79f07Chandler Carruth 198e05ee6df356c25e792b0334d7a4dec3fe4f79f07Chandler Carruth HasPlainEdge = true; 199dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek } 200dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek if (!HasPlainEdge) { 201dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek if (HasLiveReturn) 202dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek return NeverFallThrough; 203dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek return NeverFallThroughOrReturn; 204dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek } 205dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek if (HasAbnormalEdge || HasFakeEdge || HasLiveReturn) 206dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek return MaybeFallThrough; 207dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek // This says AlwaysFallThrough for calls to functions that are not marked 208dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek // noreturn, that don't return. If people would like this warning to be more 209dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek // accurate, such functions should be marked as noreturn. 210dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek return AlwaysFallThrough; 211dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek} 212dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek 2133c46e8db99196179b30e7ac5c20c4efd5f3926d7Dan Gohmannamespace { 2143c46e8db99196179b30e7ac5c20c4efd5f3926d7Dan Gohman 215dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenekstruct CheckFallThroughDiagnostics { 216dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek unsigned diag_MaybeFallThrough_HasNoReturn; 217dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek unsigned diag_MaybeFallThrough_ReturnsNonVoid; 218dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek unsigned diag_AlwaysFallThrough_HasNoReturn; 219dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek unsigned diag_AlwaysFallThrough_ReturnsNonVoid; 220dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek unsigned diag_NeverFallThroughOrReturn; 221793cd1c4cdfaafc52e2c2ad9dae959befe4bb166Douglas Gregor enum { Function, Block, Lambda } funMode; 2220827408865e32789e0ec4b8113a302ccdc531423Argyrios Kyrtzidis SourceLocation FuncLoc; 223d064fdc4b7b64ca55b40b70490c79d6f569df78eTed Kremenek 224ca7eaeeed817001dc7cee4852a7e41f0982da1efDouglas Gregor static CheckFallThroughDiagnostics MakeForFunction(const Decl *Func) { 225dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek CheckFallThroughDiagnostics D; 2260827408865e32789e0ec4b8113a302ccdc531423Argyrios Kyrtzidis D.FuncLoc = Func->getLocation(); 227dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek D.diag_MaybeFallThrough_HasNoReturn = 228dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek diag::warn_falloff_noreturn_function; 229dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek D.diag_MaybeFallThrough_ReturnsNonVoid = 230dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek diag::warn_maybe_falloff_nonvoid_function; 231dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek D.diag_AlwaysFallThrough_HasNoReturn = 232dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek diag::warn_falloff_noreturn_function; 233dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek D.diag_AlwaysFallThrough_ReturnsNonVoid = 234dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek diag::warn_falloff_nonvoid_function; 235ca7eaeeed817001dc7cee4852a7e41f0982da1efDouglas Gregor 236ca7eaeeed817001dc7cee4852a7e41f0982da1efDouglas Gregor // Don't suggest that virtual functions be marked "noreturn", since they 237ca7eaeeed817001dc7cee4852a7e41f0982da1efDouglas Gregor // might be overridden by non-noreturn functions. 238ca7eaeeed817001dc7cee4852a7e41f0982da1efDouglas Gregor bool isVirtualMethod = false; 239ca7eaeeed817001dc7cee4852a7e41f0982da1efDouglas Gregor if (const CXXMethodDecl *Method = dyn_cast<CXXMethodDecl>(Func)) 240ca7eaeeed817001dc7cee4852a7e41f0982da1efDouglas Gregor isVirtualMethod = Method->isVirtual(); 241ca7eaeeed817001dc7cee4852a7e41f0982da1efDouglas Gregor 242fcdd2cb2fdf35f806dd800b369fe0772a1c8c26cDouglas Gregor // Don't suggest that template instantiations be marked "noreturn" 243fcdd2cb2fdf35f806dd800b369fe0772a1c8c26cDouglas Gregor bool isTemplateInstantiation = false; 24475df4eeede7b91c22c1d63fafd4dd4142844e3b9Ted Kremenek if (const FunctionDecl *Function = dyn_cast<FunctionDecl>(Func)) 24575df4eeede7b91c22c1d63fafd4dd4142844e3b9Ted Kremenek isTemplateInstantiation = Function->isTemplateInstantiation(); 246fcdd2cb2fdf35f806dd800b369fe0772a1c8c26cDouglas Gregor 247fcdd2cb2fdf35f806dd800b369fe0772a1c8c26cDouglas Gregor if (!isVirtualMethod && !isTemplateInstantiation) 248ca7eaeeed817001dc7cee4852a7e41f0982da1efDouglas Gregor D.diag_NeverFallThroughOrReturn = 249ca7eaeeed817001dc7cee4852a7e41f0982da1efDouglas Gregor diag::warn_suggest_noreturn_function; 250ca7eaeeed817001dc7cee4852a7e41f0982da1efDouglas Gregor else 251ca7eaeeed817001dc7cee4852a7e41f0982da1efDouglas Gregor D.diag_NeverFallThroughOrReturn = 0; 252ca7eaeeed817001dc7cee4852a7e41f0982da1efDouglas Gregor 253793cd1c4cdfaafc52e2c2ad9dae959befe4bb166Douglas Gregor D.funMode = Function; 254dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek return D; 255dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek } 256d064fdc4b7b64ca55b40b70490c79d6f569df78eTed Kremenek 257dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek static CheckFallThroughDiagnostics MakeForBlock() { 258dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek CheckFallThroughDiagnostics D; 259dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek D.diag_MaybeFallThrough_HasNoReturn = 260dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek diag::err_noreturn_block_has_return_expr; 261dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek D.diag_MaybeFallThrough_ReturnsNonVoid = 262dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek diag::err_maybe_falloff_nonvoid_block; 263dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek D.diag_AlwaysFallThrough_HasNoReturn = 264dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek diag::err_noreturn_block_has_return_expr; 265dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek D.diag_AlwaysFallThrough_ReturnsNonVoid = 266dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek diag::err_falloff_nonvoid_block; 267dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek D.diag_NeverFallThroughOrReturn = 268dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek diag::warn_suggest_noreturn_block; 269793cd1c4cdfaafc52e2c2ad9dae959befe4bb166Douglas Gregor D.funMode = Block; 270793cd1c4cdfaafc52e2c2ad9dae959befe4bb166Douglas Gregor return D; 271793cd1c4cdfaafc52e2c2ad9dae959befe4bb166Douglas Gregor } 272793cd1c4cdfaafc52e2c2ad9dae959befe4bb166Douglas Gregor 273793cd1c4cdfaafc52e2c2ad9dae959befe4bb166Douglas Gregor static CheckFallThroughDiagnostics MakeForLambda() { 274793cd1c4cdfaafc52e2c2ad9dae959befe4bb166Douglas Gregor CheckFallThroughDiagnostics D; 275793cd1c4cdfaafc52e2c2ad9dae959befe4bb166Douglas Gregor D.diag_MaybeFallThrough_HasNoReturn = 276793cd1c4cdfaafc52e2c2ad9dae959befe4bb166Douglas Gregor diag::err_noreturn_lambda_has_return_expr; 277793cd1c4cdfaafc52e2c2ad9dae959befe4bb166Douglas Gregor D.diag_MaybeFallThrough_ReturnsNonVoid = 278793cd1c4cdfaafc52e2c2ad9dae959befe4bb166Douglas Gregor diag::warn_maybe_falloff_nonvoid_lambda; 279793cd1c4cdfaafc52e2c2ad9dae959befe4bb166Douglas Gregor D.diag_AlwaysFallThrough_HasNoReturn = 280793cd1c4cdfaafc52e2c2ad9dae959befe4bb166Douglas Gregor diag::err_noreturn_lambda_has_return_expr; 281793cd1c4cdfaafc52e2c2ad9dae959befe4bb166Douglas Gregor D.diag_AlwaysFallThrough_ReturnsNonVoid = 282793cd1c4cdfaafc52e2c2ad9dae959befe4bb166Douglas Gregor diag::warn_falloff_nonvoid_lambda; 283793cd1c4cdfaafc52e2c2ad9dae959befe4bb166Douglas Gregor D.diag_NeverFallThroughOrReturn = 0; 284793cd1c4cdfaafc52e2c2ad9dae959befe4bb166Douglas Gregor D.funMode = Lambda; 285dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek return D; 286dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek } 287d064fdc4b7b64ca55b40b70490c79d6f569df78eTed Kremenek 288d6471f7c1921c7802804ce3ff6fe9768310f72b9David Blaikie bool checkDiagnostics(DiagnosticsEngine &D, bool ReturnsVoid, 289dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek bool HasNoReturn) const { 290793cd1c4cdfaafc52e2c2ad9dae959befe4bb166Douglas Gregor if (funMode == Function) { 2910827408865e32789e0ec4b8113a302ccdc531423Argyrios Kyrtzidis return (ReturnsVoid || 2920827408865e32789e0ec4b8113a302ccdc531423Argyrios Kyrtzidis D.getDiagnosticLevel(diag::warn_maybe_falloff_nonvoid_function, 293d6471f7c1921c7802804ce3ff6fe9768310f72b9David Blaikie FuncLoc) == DiagnosticsEngine::Ignored) 2940827408865e32789e0ec4b8113a302ccdc531423Argyrios Kyrtzidis && (!HasNoReturn || 2950827408865e32789e0ec4b8113a302ccdc531423Argyrios Kyrtzidis D.getDiagnosticLevel(diag::warn_noreturn_function_has_return_expr, 296d6471f7c1921c7802804ce3ff6fe9768310f72b9David Blaikie FuncLoc) == DiagnosticsEngine::Ignored) 2970827408865e32789e0ec4b8113a302ccdc531423Argyrios Kyrtzidis && (!ReturnsVoid || 2980827408865e32789e0ec4b8113a302ccdc531423Argyrios Kyrtzidis D.getDiagnosticLevel(diag::warn_suggest_noreturn_block, FuncLoc) 299d6471f7c1921c7802804ce3ff6fe9768310f72b9David Blaikie == DiagnosticsEngine::Ignored); 300dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek } 301d064fdc4b7b64ca55b40b70490c79d6f569df78eTed Kremenek 302793cd1c4cdfaafc52e2c2ad9dae959befe4bb166Douglas Gregor // For blocks / lambdas. 303793cd1c4cdfaafc52e2c2ad9dae959befe4bb166Douglas Gregor return ReturnsVoid && !HasNoReturn 304793cd1c4cdfaafc52e2c2ad9dae959befe4bb166Douglas Gregor && ((funMode == Lambda) || 3050827408865e32789e0ec4b8113a302ccdc531423Argyrios Kyrtzidis D.getDiagnosticLevel(diag::warn_suggest_noreturn_block, FuncLoc) 306d6471f7c1921c7802804ce3ff6fe9768310f72b9David Blaikie == DiagnosticsEngine::Ignored); 307dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek } 308dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek}; 309dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek 3103c46e8db99196179b30e7ac5c20c4efd5f3926d7Dan Gohman} 3113c46e8db99196179b30e7ac5c20c4efd5f3926d7Dan Gohman 312dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek/// CheckFallThroughForFunctionDef - Check that we don't fall off the end of a 313dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek/// function that should return a value. Check that we don't fall off the end 314dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek/// of a noreturn function. We assume that functions and blocks not marked 315dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek/// noreturn will return. 316dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenekstatic void CheckFallThroughForBody(Sema &S, const Decl *D, const Stmt *Body, 3173ed6fc08a9cd293d012fa49ab2a615e618d7c3faTed Kremenek const BlockExpr *blkExpr, 318dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek const CheckFallThroughDiagnostics& CD, 3191d26f48dc2eea1c07431ca1519d7034a21b9bcffTed Kremenek AnalysisDeclContext &AC) { 320dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek 321dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek bool ReturnsVoid = false; 322dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek bool HasNoReturn = false; 323dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek 324dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(D)) { 325dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek ReturnsVoid = FD->getResultType()->isVoidType(); 326dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek HasNoReturn = FD->hasAttr<NoReturnAttr>() || 327264ba48dc98f3f843935a485d5b086f7e0fdc4f1Rafael Espindola FD->getType()->getAs<FunctionType>()->getNoReturnAttr(); 328dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek } 329dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek else if (const ObjCMethodDecl *MD = dyn_cast<ObjCMethodDecl>(D)) { 330dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek ReturnsVoid = MD->getResultType()->isVoidType(); 331dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek HasNoReturn = MD->hasAttr<NoReturnAttr>(); 332dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek } 333dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek else if (isa<BlockDecl>(D)) { 3343ed6fc08a9cd293d012fa49ab2a615e618d7c3faTed Kremenek QualType BlockTy = blkExpr->getType(); 335d064fdc4b7b64ca55b40b70490c79d6f569df78eTed Kremenek if (const FunctionType *FT = 336dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek BlockTy->getPointeeType()->getAs<FunctionType>()) { 337dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek if (FT->getResultType()->isVoidType()) 338dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek ReturnsVoid = true; 339dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek if (FT->getNoReturnAttr()) 340dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek HasNoReturn = true; 341dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek } 342dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek } 343dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek 344d6471f7c1921c7802804ce3ff6fe9768310f72b9David Blaikie DiagnosticsEngine &Diags = S.getDiagnostics(); 345dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek 346dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek // Short circuit for compilation speed. 347dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek if (CD.checkDiagnostics(Diags, ReturnsVoid, HasNoReturn)) 348dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek return; 349d064fdc4b7b64ca55b40b70490c79d6f569df78eTed Kremenek 350dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek // FIXME: Function try block 351dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek if (const CompoundStmt *Compound = dyn_cast<CompoundStmt>(Body)) { 352dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek switch (CheckFallThrough(AC)) { 35316565aa95b086fb239baf82335dccc1b1ec93942John McCall case UnknownFallThrough: 35416565aa95b086fb239baf82335dccc1b1ec93942John McCall break; 35516565aa95b086fb239baf82335dccc1b1ec93942John McCall 356dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek case MaybeFallThrough: 357dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek if (HasNoReturn) 358dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek S.Diag(Compound->getRBracLoc(), 359dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek CD.diag_MaybeFallThrough_HasNoReturn); 360dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek else if (!ReturnsVoid) 361dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek S.Diag(Compound->getRBracLoc(), 362dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek CD.diag_MaybeFallThrough_ReturnsNonVoid); 363dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek break; 364dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek case AlwaysFallThrough: 365dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek if (HasNoReturn) 366dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek S.Diag(Compound->getRBracLoc(), 367dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek CD.diag_AlwaysFallThrough_HasNoReturn); 368dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek else if (!ReturnsVoid) 369dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek S.Diag(Compound->getRBracLoc(), 370dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek CD.diag_AlwaysFallThrough_ReturnsNonVoid); 371dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek break; 372dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek case NeverFallThroughOrReturn: 373b0656ec72e25e5c8e463c2dc39914636f0cb06d1Chandler Carruth if (ReturnsVoid && !HasNoReturn && CD.diag_NeverFallThroughOrReturn) { 374b0656ec72e25e5c8e463c2dc39914636f0cb06d1Chandler Carruth if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(D)) { 375b0656ec72e25e5c8e463c2dc39914636f0cb06d1Chandler Carruth S.Diag(Compound->getLBracLoc(), CD.diag_NeverFallThroughOrReturn) 376b3321093f6ead084427eb4a6621832fc4ee2f5deDouglas Gregor << 0 << FD; 377b3321093f6ead084427eb4a6621832fc4ee2f5deDouglas Gregor } else if (const ObjCMethodDecl *MD = dyn_cast<ObjCMethodDecl>(D)) { 378b3321093f6ead084427eb4a6621832fc4ee2f5deDouglas Gregor S.Diag(Compound->getLBracLoc(), CD.diag_NeverFallThroughOrReturn) 379b3321093f6ead084427eb4a6621832fc4ee2f5deDouglas Gregor << 1 << MD; 380b0656ec72e25e5c8e463c2dc39914636f0cb06d1Chandler Carruth } else { 381b0656ec72e25e5c8e463c2dc39914636f0cb06d1Chandler Carruth S.Diag(Compound->getLBracLoc(), CD.diag_NeverFallThroughOrReturn); 382b0656ec72e25e5c8e463c2dc39914636f0cb06d1Chandler Carruth } 383b0656ec72e25e5c8e463c2dc39914636f0cb06d1Chandler Carruth } 384dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek break; 385dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek case NeverFallThrough: 386dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek break; 387dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek } 388dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek } 389dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek} 390dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek 391dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek//===----------------------------------------------------------------------===// 392610068c8cd2321f90e147b12cf794e1f840b6405Ted Kremenek// -Wuninitialized 393610068c8cd2321f90e147b12cf794e1f840b6405Ted Kremenek//===----------------------------------------------------------------------===// 394610068c8cd2321f90e147b12cf794e1f840b6405Ted Kremenek 3956f41715df2c6a31c0c3ab3088b8cd18a3c8321b8Ted Kremeneknamespace { 3969f6494687c05fe1d334af76408ee056b5f80e027Chandler Carruth/// ContainsReference - A visitor class to search for references to 3979f6494687c05fe1d334af76408ee056b5f80e027Chandler Carruth/// a particular declaration (the needle) within any evaluated component of an 3989f6494687c05fe1d334af76408ee056b5f80e027Chandler Carruth/// expression (recursively). 3996f41715df2c6a31c0c3ab3088b8cd18a3c8321b8Ted Kremenekclass ContainsReference : public EvaluatedExprVisitor<ContainsReference> { 4009f6494687c05fe1d334af76408ee056b5f80e027Chandler Carruth bool FoundReference; 4019f6494687c05fe1d334af76408ee056b5f80e027Chandler Carruth const DeclRefExpr *Needle; 4029f6494687c05fe1d334af76408ee056b5f80e027Chandler Carruth 4036f41715df2c6a31c0c3ab3088b8cd18a3c8321b8Ted Kremenekpublic: 4049f6494687c05fe1d334af76408ee056b5f80e027Chandler Carruth ContainsReference(ASTContext &Context, const DeclRefExpr *Needle) 4059f6494687c05fe1d334af76408ee056b5f80e027Chandler Carruth : EvaluatedExprVisitor<ContainsReference>(Context), 4069f6494687c05fe1d334af76408ee056b5f80e027Chandler Carruth FoundReference(false), Needle(Needle) {} 4079f6494687c05fe1d334af76408ee056b5f80e027Chandler Carruth 4089f6494687c05fe1d334af76408ee056b5f80e027Chandler Carruth void VisitExpr(Expr *E) { 4096f41715df2c6a31c0c3ab3088b8cd18a3c8321b8Ted Kremenek // Stop evaluating if we already have a reference. 4109f6494687c05fe1d334af76408ee056b5f80e027Chandler Carruth if (FoundReference) 4116f41715df2c6a31c0c3ab3088b8cd18a3c8321b8Ted Kremenek return; 4129f6494687c05fe1d334af76408ee056b5f80e027Chandler Carruth 4139f6494687c05fe1d334af76408ee056b5f80e027Chandler Carruth EvaluatedExprVisitor<ContainsReference>::VisitExpr(E); 4146f41715df2c6a31c0c3ab3088b8cd18a3c8321b8Ted Kremenek } 4159f6494687c05fe1d334af76408ee056b5f80e027Chandler Carruth 4169f6494687c05fe1d334af76408ee056b5f80e027Chandler Carruth void VisitDeclRefExpr(DeclRefExpr *E) { 4179f6494687c05fe1d334af76408ee056b5f80e027Chandler Carruth if (E == Needle) 4189f6494687c05fe1d334af76408ee056b5f80e027Chandler Carruth FoundReference = true; 4199f6494687c05fe1d334af76408ee056b5f80e027Chandler Carruth else 4209f6494687c05fe1d334af76408ee056b5f80e027Chandler Carruth EvaluatedExprVisitor<ContainsReference>::VisitDeclRefExpr(E); 4216f41715df2c6a31c0c3ab3088b8cd18a3c8321b8Ted Kremenek } 4229f6494687c05fe1d334af76408ee056b5f80e027Chandler Carruth 4239f6494687c05fe1d334af76408ee056b5f80e027Chandler Carruth bool doesContainReference() const { return FoundReference; } 4246f41715df2c6a31c0c3ab3088b8cd18a3c8321b8Ted Kremenek}; 4256f41715df2c6a31c0c3ab3088b8cd18a3c8321b8Ted Kremenek} 4266f41715df2c6a31c0c3ab3088b8cd18a3c8321b8Ted Kremenek 4274f4f349208b2b2307454e169ac7b039e989f003fDavid Blaikiestatic bool SuggestInitializationFixit(Sema &S, const VarDecl *VD) { 428a34194f035096dd8dce10574e3a186da968aa211Fariborz Jahanian QualType VariableTy = VD->getType().getCanonicalType(); 429a34194f035096dd8dce10574e3a186da968aa211Fariborz Jahanian if (VariableTy->isBlockPointerType() && 430a34194f035096dd8dce10574e3a186da968aa211Fariborz Jahanian !VD->hasAttr<BlocksAttr>()) { 431a34194f035096dd8dce10574e3a186da968aa211Fariborz Jahanian S.Diag(VD->getLocation(), diag::note_block_var_fixit_add_initialization) << VD->getDeclName() 432a34194f035096dd8dce10574e3a186da968aa211Fariborz Jahanian << FixItHint::CreateInsertion(VD->getLocation(), "__block "); 433a34194f035096dd8dce10574e3a186da968aa211Fariborz Jahanian return true; 434a34194f035096dd8dce10574e3a186da968aa211Fariborz Jahanian } 435a34194f035096dd8dce10574e3a186da968aa211Fariborz Jahanian 4364f4f349208b2b2307454e169ac7b039e989f003fDavid Blaikie // Don't issue a fixit if there is already an initializer. 4374f4f349208b2b2307454e169ac7b039e989f003fDavid Blaikie if (VD->getInit()) 4384f4f349208b2b2307454e169ac7b039e989f003fDavid Blaikie return false; 439a34194f035096dd8dce10574e3a186da968aa211Fariborz Jahanian 4404f4f349208b2b2307454e169ac7b039e989f003fDavid Blaikie // Suggest possible initialization (if any). 4412c0abf4ae33ab2ba690ccae724b8d6f196e7cfdaDavid Blaikie std::string Init = S.getFixItZeroInitializerForType(VariableTy); 4422c0abf4ae33ab2ba690ccae724b8d6f196e7cfdaDavid Blaikie if (Init.empty()) 4434f4f349208b2b2307454e169ac7b039e989f003fDavid Blaikie return false; 4447984de35644701c0d94336da7f2215d4c26d9f5bRichard Smith SourceLocation Loc = S.PP.getLocForEndOfToken(VD->getLocEnd()); 445a34194f035096dd8dce10574e3a186da968aa211Fariborz Jahanian 4467984de35644701c0d94336da7f2215d4c26d9f5bRichard Smith S.Diag(Loc, diag::note_var_fixit_add_initialization) << VD->getDeclName() 4477984de35644701c0d94336da7f2215d4c26d9f5bRichard Smith << FixItHint::CreateInsertion(Loc, Init); 4487984de35644701c0d94336da7f2215d4c26d9f5bRichard Smith return true; 4494f4f349208b2b2307454e169ac7b039e989f003fDavid Blaikie} 4504f4f349208b2b2307454e169ac7b039e989f003fDavid Blaikie 451262d50e1dcf529317da193ad585c11c16281a7acChandler Carruth/// DiagnoseUninitializedUse -- Helper function for diagnosing uses of an 452262d50e1dcf529317da193ad585c11c16281a7acChandler Carruth/// uninitialized variable. This manages the different forms of diagnostic 453262d50e1dcf529317da193ad585c11c16281a7acChandler Carruth/// emitted for particular types of uses. Returns true if the use was diagnosed 454262d50e1dcf529317da193ad585c11c16281a7acChandler Carruth/// as a warning. If a pariticular use is one we omit warnings for, returns 455262d50e1dcf529317da193ad585c11c16281a7acChandler Carruth/// false. 456262d50e1dcf529317da193ad585c11c16281a7acChandler Carruthstatic bool DiagnoseUninitializedUse(Sema &S, const VarDecl *VD, 4579e7617220135a6f6226cf09cb242cc1b905aedb4Ted Kremenek const Expr *E, bool isAlwaysUninit, 4589e7617220135a6f6226cf09cb242cc1b905aedb4Ted Kremenek bool alwaysReportSelfInit = false) { 4594c4983bbd2904670a25c840b07600f14efbafd7fChandler Carruth bool isSelfInit = false; 4604c4983bbd2904670a25c840b07600f14efbafd7fChandler Carruth 4614c4983bbd2904670a25c840b07600f14efbafd7fChandler Carruth if (const DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(E)) { 4624c4983bbd2904670a25c840b07600f14efbafd7fChandler Carruth if (isAlwaysUninit) { 4634c4983bbd2904670a25c840b07600f14efbafd7fChandler Carruth // Inspect the initializer of the variable declaration which is 4644c4983bbd2904670a25c840b07600f14efbafd7fChandler Carruth // being referenced prior to its initialization. We emit 4654c4983bbd2904670a25c840b07600f14efbafd7fChandler Carruth // specialized diagnostics for self-initialization, and we 4664c4983bbd2904670a25c840b07600f14efbafd7fChandler Carruth // specifically avoid warning about self references which take the 4674c4983bbd2904670a25c840b07600f14efbafd7fChandler Carruth // form of: 4684c4983bbd2904670a25c840b07600f14efbafd7fChandler Carruth // 4694c4983bbd2904670a25c840b07600f14efbafd7fChandler Carruth // int x = x; 4704c4983bbd2904670a25c840b07600f14efbafd7fChandler Carruth // 4714c4983bbd2904670a25c840b07600f14efbafd7fChandler Carruth // This is used to indicate to GCC that 'x' is intentionally left 4724c4983bbd2904670a25c840b07600f14efbafd7fChandler Carruth // uninitialized. Proven code paths which access 'x' in 4734c4983bbd2904670a25c840b07600f14efbafd7fChandler Carruth // an uninitialized state after this will still warn. 4744c4983bbd2904670a25c840b07600f14efbafd7fChandler Carruth // 4754c4983bbd2904670a25c840b07600f14efbafd7fChandler Carruth // TODO: Should we suppress maybe-uninitialized warnings for 4764c4983bbd2904670a25c840b07600f14efbafd7fChandler Carruth // variables initialized in this way? 4774c4983bbd2904670a25c840b07600f14efbafd7fChandler Carruth if (const Expr *Initializer = VD->getInit()) { 4789e7617220135a6f6226cf09cb242cc1b905aedb4Ted Kremenek if (!alwaysReportSelfInit && DRE == Initializer->IgnoreParenImpCasts()) 479262d50e1dcf529317da193ad585c11c16281a7acChandler Carruth return false; 4804c4983bbd2904670a25c840b07600f14efbafd7fChandler Carruth 4814c4983bbd2904670a25c840b07600f14efbafd7fChandler Carruth ContainsReference CR(S.Context, DRE); 4824c4983bbd2904670a25c840b07600f14efbafd7fChandler Carruth CR.Visit(const_cast<Expr*>(Initializer)); 4834c4983bbd2904670a25c840b07600f14efbafd7fChandler Carruth isSelfInit = CR.doesContainReference(); 4844c4983bbd2904670a25c840b07600f14efbafd7fChandler Carruth } 4854c4983bbd2904670a25c840b07600f14efbafd7fChandler Carruth if (isSelfInit) { 4864c4983bbd2904670a25c840b07600f14efbafd7fChandler Carruth S.Diag(DRE->getLocStart(), 4874c4983bbd2904670a25c840b07600f14efbafd7fChandler Carruth diag::warn_uninit_self_reference_in_init) 4884c4983bbd2904670a25c840b07600f14efbafd7fChandler Carruth << VD->getDeclName() << VD->getLocation() << DRE->getSourceRange(); 4894c4983bbd2904670a25c840b07600f14efbafd7fChandler Carruth } else { 4904c4983bbd2904670a25c840b07600f14efbafd7fChandler Carruth S.Diag(DRE->getLocStart(), diag::warn_uninit_var) 4914c4983bbd2904670a25c840b07600f14efbafd7fChandler Carruth << VD->getDeclName() << DRE->getSourceRange(); 4924c4983bbd2904670a25c840b07600f14efbafd7fChandler Carruth } 4934c4983bbd2904670a25c840b07600f14efbafd7fChandler Carruth } else { 4944c4983bbd2904670a25c840b07600f14efbafd7fChandler Carruth S.Diag(DRE->getLocStart(), diag::warn_maybe_uninit_var) 4954c4983bbd2904670a25c840b07600f14efbafd7fChandler Carruth << VD->getDeclName() << DRE->getSourceRange(); 4964c4983bbd2904670a25c840b07600f14efbafd7fChandler Carruth } 4974c4983bbd2904670a25c840b07600f14efbafd7fChandler Carruth } else { 4984c4983bbd2904670a25c840b07600f14efbafd7fChandler Carruth const BlockExpr *BE = cast<BlockExpr>(E); 499a34194f035096dd8dce10574e3a186da968aa211Fariborz Jahanian if (VD->getType()->isBlockPointerType() && 500a34194f035096dd8dce10574e3a186da968aa211Fariborz Jahanian !VD->hasAttr<BlocksAttr>()) 501a34194f035096dd8dce10574e3a186da968aa211Fariborz Jahanian S.Diag(BE->getLocStart(), diag::warn_uninit_byref_blockvar_captured_by_block) 502a34194f035096dd8dce10574e3a186da968aa211Fariborz Jahanian << VD->getDeclName(); 503a34194f035096dd8dce10574e3a186da968aa211Fariborz Jahanian else 504a34194f035096dd8dce10574e3a186da968aa211Fariborz Jahanian S.Diag(BE->getLocStart(), 505a34194f035096dd8dce10574e3a186da968aa211Fariborz Jahanian isAlwaysUninit ? diag::warn_uninit_var_captured_by_block 506a34194f035096dd8dce10574e3a186da968aa211Fariborz Jahanian : diag::warn_maybe_uninit_var_captured_by_block) 507a34194f035096dd8dce10574e3a186da968aa211Fariborz Jahanian << VD->getDeclName(); 5084c4983bbd2904670a25c840b07600f14efbafd7fChandler Carruth } 5094c4983bbd2904670a25c840b07600f14efbafd7fChandler Carruth 5104c4983bbd2904670a25c840b07600f14efbafd7fChandler Carruth // Report where the variable was declared when the use wasn't within 5114f4f349208b2b2307454e169ac7b039e989f003fDavid Blaikie // the initializer of that declaration & we didn't already suggest 5124f4f349208b2b2307454e169ac7b039e989f003fDavid Blaikie // an initialization fixit. 5134f4f349208b2b2307454e169ac7b039e989f003fDavid Blaikie if (!isSelfInit && !SuggestInitializationFixit(S, VD)) 5144c4983bbd2904670a25c840b07600f14efbafd7fChandler Carruth S.Diag(VD->getLocStart(), diag::note_uninit_var_def) 5154c4983bbd2904670a25c840b07600f14efbafd7fChandler Carruth << VD->getDeclName(); 5164c4983bbd2904670a25c840b07600f14efbafd7fChandler Carruth 517262d50e1dcf529317da193ad585c11c16281a7acChandler Carruth return true; 51864fb959beb3a0ecb84a58e6ff82660a7a669f7b8Chandler Carruth} 51964fb959beb3a0ecb84a58e6ff82660a7a669f7b8Chandler 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; 5335f9e272e632e951b1efe824cd16acb4d96077930Chris Lattner typedef SmallVector<UninitUse, 2> UsesVec; 5349e7617220135a6f6226cf09cb242cc1b905aedb4Ted Kremenek typedef llvm::DenseMap<const VarDecl *, std::pair<UsesVec*, bool> > 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 } 5429e7617220135a6f6226cf09cb242cc1b905aedb4Ted Kremenek 5439e7617220135a6f6226cf09cb242cc1b905aedb4Ted Kremenek std::pair<UsesVec*, bool> &getUses(const VarDecl *vd) { 54494b1b4d785bc0f09f6af4be394e59d51f35dda60Ted Kremenek if (!uses) 54594b1b4d785bc0f09f6af4be394e59d51f35dda60Ted Kremenek uses = new UsesMap(); 5469e7617220135a6f6226cf09cb242cc1b905aedb4Ted Kremenek 5479e7617220135a6f6226cf09cb242cc1b905aedb4Ted Kremenek UsesMap::mapped_type &V = (*uses)[vd]; 5489e7617220135a6f6226cf09cb242cc1b905aedb4Ted Kremenek UsesVec *&vec = V.first; 54994b1b4d785bc0f09f6af4be394e59d51f35dda60Ted Kremenek if (!vec) 55094b1b4d785bc0f09f6af4be394e59d51f35dda60Ted Kremenek vec = new UsesVec(); 55194b1b4d785bc0f09f6af4be394e59d51f35dda60Ted Kremenek 5529e7617220135a6f6226cf09cb242cc1b905aedb4Ted Kremenek return V; 5539e7617220135a6f6226cf09cb242cc1b905aedb4Ted Kremenek } 5549e7617220135a6f6226cf09cb242cc1b905aedb4Ted Kremenek 5559e7617220135a6f6226cf09cb242cc1b905aedb4Ted Kremenek void handleUseOfUninitVariable(const Expr *ex, const VarDecl *vd, 5569e7617220135a6f6226cf09cb242cc1b905aedb4Ted Kremenek bool isAlwaysUninit) { 5579e7617220135a6f6226cf09cb242cc1b905aedb4Ted Kremenek getUses(vd).first->push_back(std::make_pair(ex, isAlwaysUninit)); 5589e7617220135a6f6226cf09cb242cc1b905aedb4Ted Kremenek } 5599e7617220135a6f6226cf09cb242cc1b905aedb4Ted Kremenek 5609e7617220135a6f6226cf09cb242cc1b905aedb4Ted Kremenek void handleSelfInit(const VarDecl *vd) { 5619e7617220135a6f6226cf09cb242cc1b905aedb4Ted Kremenek getUses(vd).second = true; 56294b1b4d785bc0f09f6af4be394e59d51f35dda60Ted Kremenek } 56394b1b4d785bc0f09f6af4be394e59d51f35dda60Ted Kremenek 56494b1b4d785bc0f09f6af4be394e59d51f35dda60Ted Kremenek void flushDiagnostics() { 56594b1b4d785bc0f09f6af4be394e59d51f35dda60Ted Kremenek if (!uses) 56694b1b4d785bc0f09f6af4be394e59d51f35dda60Ted Kremenek return; 567609e3170841dac81c3b7b6b9eccb9c520e42c9b2Ted Kremenek 56894b1b4d785bc0f09f6af4be394e59d51f35dda60Ted Kremenek for (UsesMap::iterator i = uses->begin(), e = uses->end(); i != e; ++i) { 56994b1b4d785bc0f09f6af4be394e59d51f35dda60Ted Kremenek const VarDecl *vd = i->first; 5709e7617220135a6f6226cf09cb242cc1b905aedb4Ted Kremenek const UsesMap::mapped_type &V = i->second; 5719e7617220135a6f6226cf09cb242cc1b905aedb4Ted Kremenek 5729e7617220135a6f6226cf09cb242cc1b905aedb4Ted Kremenek UsesVec *vec = V.first; 5739e7617220135a6f6226cf09cb242cc1b905aedb4Ted Kremenek bool hasSelfInit = V.second; 5749e7617220135a6f6226cf09cb242cc1b905aedb4Ted Kremenek 5759e7617220135a6f6226cf09cb242cc1b905aedb4Ted Kremenek // Specially handle the case where we have uses of an uninitialized 5769e7617220135a6f6226cf09cb242cc1b905aedb4Ted Kremenek // variable, but the root cause is an idiomatic self-init. We want 5779e7617220135a6f6226cf09cb242cc1b905aedb4Ted Kremenek // to report the diagnostic at the self-init since that is the root cause. 5780d381810da19dd7677b9a79fca516d298fa5addbMatt Beaumont-Gay if (!vec->empty() && hasSelfInit && hasAlwaysUninitializedUse(vec)) 5799e7617220135a6f6226cf09cb242cc1b905aedb4Ted Kremenek DiagnoseUninitializedUse(S, vd, vd->getInit()->IgnoreParenCasts(), 5800d381810da19dd7677b9a79fca516d298fa5addbMatt Beaumont-Gay /* isAlwaysUninit */ true, 5810d381810da19dd7677b9a79fca516d298fa5addbMatt Beaumont-Gay /* alwaysReportSelfInit */ true); 5829e7617220135a6f6226cf09cb242cc1b905aedb4Ted Kremenek else { 5839e7617220135a6f6226cf09cb242cc1b905aedb4Ted Kremenek // Sort the uses by their SourceLocations. While not strictly 5849e7617220135a6f6226cf09cb242cc1b905aedb4Ted Kremenek // guaranteed to produce them in line/column order, this will provide 5859e7617220135a6f6226cf09cb242cc1b905aedb4Ted Kremenek // a stable ordering. 5869e7617220135a6f6226cf09cb242cc1b905aedb4Ted Kremenek std::sort(vec->begin(), vec->end(), SLocSort()); 5879e7617220135a6f6226cf09cb242cc1b905aedb4Ted Kremenek 5889e7617220135a6f6226cf09cb242cc1b905aedb4Ted Kremenek for (UsesVec::iterator vi = vec->begin(), ve = vec->end(); vi != ve; 5899e7617220135a6f6226cf09cb242cc1b905aedb4Ted Kremenek ++vi) { 5909e7617220135a6f6226cf09cb242cc1b905aedb4Ted Kremenek if (DiagnoseUninitializedUse(S, vd, vi->first, 5919e7617220135a6f6226cf09cb242cc1b905aedb4Ted Kremenek /*isAlwaysUninit=*/vi->second)) 5929e7617220135a6f6226cf09cb242cc1b905aedb4Ted Kremenek // Skip further diagnostics for this variable. We try to warn only 5939e7617220135a6f6226cf09cb242cc1b905aedb4Ted Kremenek // on the first point at which a variable is used uninitialized. 5949e7617220135a6f6226cf09cb242cc1b905aedb4Ted Kremenek break; 5959e7617220135a6f6226cf09cb242cc1b905aedb4Ted Kremenek } 59664fb959beb3a0ecb84a58e6ff82660a7a669f7b8Chandler Carruth } 5979e7617220135a6f6226cf09cb242cc1b905aedb4Ted Kremenek 5989e7617220135a6f6226cf09cb242cc1b905aedb4Ted Kremenek // Release the uses vector. 59994b1b4d785bc0f09f6af4be394e59d51f35dda60Ted Kremenek delete vec; 60094b1b4d785bc0f09f6af4be394e59d51f35dda60Ted Kremenek } 60194b1b4d785bc0f09f6af4be394e59d51f35dda60Ted Kremenek delete uses; 602610068c8cd2321f90e147b12cf794e1f840b6405Ted Kremenek } 6030d381810da19dd7677b9a79fca516d298fa5addbMatt Beaumont-Gay 6040d381810da19dd7677b9a79fca516d298fa5addbMatt Beaumont-Gayprivate: 6050d381810da19dd7677b9a79fca516d298fa5addbMatt Beaumont-Gay static bool hasAlwaysUninitializedUse(const UsesVec* vec) { 6060d381810da19dd7677b9a79fca516d298fa5addbMatt Beaumont-Gay for (UsesVec::const_iterator i = vec->begin(), e = vec->end(); i != e; ++i) { 6070d381810da19dd7677b9a79fca516d298fa5addbMatt Beaumont-Gay if (i->second) { 6080d381810da19dd7677b9a79fca516d298fa5addbMatt Beaumont-Gay return true; 6090d381810da19dd7677b9a79fca516d298fa5addbMatt Beaumont-Gay } 6100d381810da19dd7677b9a79fca516d298fa5addbMatt Beaumont-Gay } 6110d381810da19dd7677b9a79fca516d298fa5addbMatt Beaumont-Gay return false; 6120d381810da19dd7677b9a79fca516d298fa5addbMatt Beaumont-Gay} 613610068c8cd2321f90e147b12cf794e1f840b6405Ted Kremenek}; 614610068c8cd2321f90e147b12cf794e1f840b6405Ted Kremenek} 615610068c8cd2321f90e147b12cf794e1f840b6405Ted Kremenek 6163ac1fbc303d22af2e11a14023ecee7bd7b7d0bfdCaitlin Sadowski 6173ac1fbc303d22af2e11a14023ecee7bd7b7d0bfdCaitlin Sadowski//===----------------------------------------------------------------------===// 6183ac1fbc303d22af2e11a14023ecee7bd7b7d0bfdCaitlin Sadowski// -Wthread-safety 6193ac1fbc303d22af2e11a14023ecee7bd7b7d0bfdCaitlin Sadowski//===----------------------------------------------------------------------===// 62075f23aeb1c820b49f9faebed63b1cbef76c2c907Caitlin Sadowskinamespace clang { 62175f23aeb1c820b49f9faebed63b1cbef76c2c907Caitlin Sadowskinamespace thread_safety { 6222e5156274b8051217565b557bfa14c80f7990e9cRichard Smithtypedef llvm::SmallVector<PartialDiagnosticAt, 1> OptionalNotes; 6232e5156274b8051217565b557bfa14c80f7990e9cRichard Smithtypedef std::pair<PartialDiagnosticAt, OptionalNotes> DelayedDiag; 624ecafd309b3ed2ffc6f8ae7eecd1e7eae84b26f81Benjamin Kramertypedef std::list<DelayedDiag> DiagList; 62575f23aeb1c820b49f9faebed63b1cbef76c2c907Caitlin Sadowski 62675f23aeb1c820b49f9faebed63b1cbef76c2c907Caitlin Sadowskistruct SortDiagBySourceLocation { 627ecafd309b3ed2ffc6f8ae7eecd1e7eae84b26f81Benjamin Kramer SourceManager &SM; 628ecafd309b3ed2ffc6f8ae7eecd1e7eae84b26f81Benjamin Kramer SortDiagBySourceLocation(SourceManager &SM) : SM(SM) {} 62975f23aeb1c820b49f9faebed63b1cbef76c2c907Caitlin Sadowski 63075f23aeb1c820b49f9faebed63b1cbef76c2c907Caitlin Sadowski bool operator()(const DelayedDiag &left, const DelayedDiag &right) { 63175f23aeb1c820b49f9faebed63b1cbef76c2c907Caitlin Sadowski // Although this call will be slow, this is only called when outputting 63275f23aeb1c820b49f9faebed63b1cbef76c2c907Caitlin Sadowski // multiple warnings. 633ecafd309b3ed2ffc6f8ae7eecd1e7eae84b26f81Benjamin Kramer return SM.isBeforeInTranslationUnit(left.first.first, right.first.first); 63475f23aeb1c820b49f9faebed63b1cbef76c2c907Caitlin Sadowski } 63575f23aeb1c820b49f9faebed63b1cbef76c2c907Caitlin Sadowski}; 63675f23aeb1c820b49f9faebed63b1cbef76c2c907Caitlin Sadowski 63799ba9e3bd70671f3441fb974895f226a83ce0e66David Blaikienamespace { 63875f23aeb1c820b49f9faebed63b1cbef76c2c907Caitlin Sadowskiclass ThreadSafetyReporter : public clang::thread_safety::ThreadSafetyHandler { 63975f23aeb1c820b49f9faebed63b1cbef76c2c907Caitlin Sadowski Sema &S; 64075f23aeb1c820b49f9faebed63b1cbef76c2c907Caitlin Sadowski DiagList Warnings; 6412e5156274b8051217565b557bfa14c80f7990e9cRichard Smith SourceLocation FunLocation, FunEndLocation; 64275f23aeb1c820b49f9faebed63b1cbef76c2c907Caitlin Sadowski 64375f23aeb1c820b49f9faebed63b1cbef76c2c907Caitlin Sadowski // Helper functions 64475f23aeb1c820b49f9faebed63b1cbef76c2c907Caitlin Sadowski void warnLockMismatch(unsigned DiagID, Name LockName, SourceLocation Loc) { 645f1ac63702143d84db778d32eb185a77fc97db5f5DeLesley Hutchins // Gracefully handle rare cases when the analysis can't get a more 646f1ac63702143d84db778d32eb185a77fc97db5f5DeLesley Hutchins // precise source location. 647f1ac63702143d84db778d32eb185a77fc97db5f5DeLesley Hutchins if (!Loc.isValid()) 648f1ac63702143d84db778d32eb185a77fc97db5f5DeLesley Hutchins Loc = FunLocation; 6492e5156274b8051217565b557bfa14c80f7990e9cRichard Smith PartialDiagnosticAt Warning(Loc, S.PDiag(DiagID) << LockName); 6502e5156274b8051217565b557bfa14c80f7990e9cRichard Smith Warnings.push_back(DelayedDiag(Warning, OptionalNotes())); 65175f23aeb1c820b49f9faebed63b1cbef76c2c907Caitlin Sadowski } 65275f23aeb1c820b49f9faebed63b1cbef76c2c907Caitlin Sadowski 65375f23aeb1c820b49f9faebed63b1cbef76c2c907Caitlin Sadowski public: 6542e5156274b8051217565b557bfa14c80f7990e9cRichard Smith ThreadSafetyReporter(Sema &S, SourceLocation FL, SourceLocation FEL) 6552e5156274b8051217565b557bfa14c80f7990e9cRichard Smith : S(S), FunLocation(FL), FunEndLocation(FEL) {} 65675f23aeb1c820b49f9faebed63b1cbef76c2c907Caitlin Sadowski 65775f23aeb1c820b49f9faebed63b1cbef76c2c907Caitlin Sadowski /// \brief Emit all buffered diagnostics in order of sourcelocation. 65875f23aeb1c820b49f9faebed63b1cbef76c2c907Caitlin Sadowski /// We need to output diagnostics produced while iterating through 65975f23aeb1c820b49f9faebed63b1cbef76c2c907Caitlin Sadowski /// the lockset in deterministic order, so this function orders diagnostics 66075f23aeb1c820b49f9faebed63b1cbef76c2c907Caitlin Sadowski /// and outputs them. 66175f23aeb1c820b49f9faebed63b1cbef76c2c907Caitlin Sadowski void emitDiagnostics() { 662ecafd309b3ed2ffc6f8ae7eecd1e7eae84b26f81Benjamin Kramer Warnings.sort(SortDiagBySourceLocation(S.getSourceManager())); 66375f23aeb1c820b49f9faebed63b1cbef76c2c907Caitlin Sadowski for (DiagList::iterator I = Warnings.begin(), E = Warnings.end(); 6642e5156274b8051217565b557bfa14c80f7990e9cRichard Smith I != E; ++I) { 6652e5156274b8051217565b557bfa14c80f7990e9cRichard Smith S.Diag(I->first.first, I->first.second); 6662e5156274b8051217565b557bfa14c80f7990e9cRichard Smith const OptionalNotes &Notes = I->second; 6672e5156274b8051217565b557bfa14c80f7990e9cRichard Smith for (unsigned NoteI = 0, NoteN = Notes.size(); NoteI != NoteN; ++NoteI) 6682e5156274b8051217565b557bfa14c80f7990e9cRichard Smith S.Diag(Notes[NoteI].first, Notes[NoteI].second); 6692e5156274b8051217565b557bfa14c80f7990e9cRichard Smith } 67075f23aeb1c820b49f9faebed63b1cbef76c2c907Caitlin Sadowski } 67175f23aeb1c820b49f9faebed63b1cbef76c2c907Caitlin Sadowski 67299107ebc0a5aea953b736e12757e0919d5249d43Caitlin Sadowski void handleInvalidLockExp(SourceLocation Loc) { 6732e5156274b8051217565b557bfa14c80f7990e9cRichard Smith PartialDiagnosticAt Warning(Loc, 6742e5156274b8051217565b557bfa14c80f7990e9cRichard Smith S.PDiag(diag::warn_cannot_resolve_lock) << Loc); 6752e5156274b8051217565b557bfa14c80f7990e9cRichard Smith Warnings.push_back(DelayedDiag(Warning, OptionalNotes())); 67699107ebc0a5aea953b736e12757e0919d5249d43Caitlin Sadowski } 67775f23aeb1c820b49f9faebed63b1cbef76c2c907Caitlin Sadowski void handleUnmatchedUnlock(Name LockName, SourceLocation Loc) { 67875f23aeb1c820b49f9faebed63b1cbef76c2c907Caitlin Sadowski warnLockMismatch(diag::warn_unlock_but_no_lock, LockName, Loc); 67975f23aeb1c820b49f9faebed63b1cbef76c2c907Caitlin Sadowski } 68075f23aeb1c820b49f9faebed63b1cbef76c2c907Caitlin Sadowski 68175f23aeb1c820b49f9faebed63b1cbef76c2c907Caitlin Sadowski void handleDoubleLock(Name LockName, SourceLocation Loc) { 68275f23aeb1c820b49f9faebed63b1cbef76c2c907Caitlin Sadowski warnLockMismatch(diag::warn_double_lock, LockName, Loc); 68375f23aeb1c820b49f9faebed63b1cbef76c2c907Caitlin Sadowski } 68475f23aeb1c820b49f9faebed63b1cbef76c2c907Caitlin Sadowski 6852e5156274b8051217565b557bfa14c80f7990e9cRichard Smith void handleMutexHeldEndOfScope(Name LockName, SourceLocation LocLocked, 6862e5156274b8051217565b557bfa14c80f7990e9cRichard Smith SourceLocation LocEndOfScope, 6874e4bc75d3570835e13183c66ac08974cdc016007Caitlin Sadowski LockErrorKind LEK){ 6884e4bc75d3570835e13183c66ac08974cdc016007Caitlin Sadowski unsigned DiagID = 0; 6894e4bc75d3570835e13183c66ac08974cdc016007Caitlin Sadowski switch (LEK) { 6904e4bc75d3570835e13183c66ac08974cdc016007Caitlin Sadowski case LEK_LockedSomePredecessors: 6912e5156274b8051217565b557bfa14c80f7990e9cRichard Smith DiagID = diag::warn_lock_some_predecessors; 6924e4bc75d3570835e13183c66ac08974cdc016007Caitlin Sadowski break; 6934e4bc75d3570835e13183c66ac08974cdc016007Caitlin Sadowski case LEK_LockedSomeLoopIterations: 6944e4bc75d3570835e13183c66ac08974cdc016007Caitlin Sadowski DiagID = diag::warn_expecting_lock_held_on_loop; 6954e4bc75d3570835e13183c66ac08974cdc016007Caitlin Sadowski break; 6964e4bc75d3570835e13183c66ac08974cdc016007Caitlin Sadowski case LEK_LockedAtEndOfFunction: 6974e4bc75d3570835e13183c66ac08974cdc016007Caitlin Sadowski DiagID = diag::warn_no_unlock; 6984e4bc75d3570835e13183c66ac08974cdc016007Caitlin Sadowski break; 6994e4bc75d3570835e13183c66ac08974cdc016007Caitlin Sadowski } 7002e5156274b8051217565b557bfa14c80f7990e9cRichard Smith if (LocEndOfScope.isInvalid()) 7012e5156274b8051217565b557bfa14c80f7990e9cRichard Smith LocEndOfScope = FunEndLocation; 7022e5156274b8051217565b557bfa14c80f7990e9cRichard Smith 7032e5156274b8051217565b557bfa14c80f7990e9cRichard Smith PartialDiagnosticAt Warning(LocEndOfScope, S.PDiag(DiagID) << LockName); 7042e5156274b8051217565b557bfa14c80f7990e9cRichard Smith PartialDiagnosticAt Note(LocLocked, S.PDiag(diag::note_locked_here)); 7052e5156274b8051217565b557bfa14c80f7990e9cRichard Smith Warnings.push_back(DelayedDiag(Warning, OptionalNotes(1, Note))); 70675f23aeb1c820b49f9faebed63b1cbef76c2c907Caitlin Sadowski } 70775f23aeb1c820b49f9faebed63b1cbef76c2c907Caitlin Sadowski 70875f23aeb1c820b49f9faebed63b1cbef76c2c907Caitlin Sadowski 70975f23aeb1c820b49f9faebed63b1cbef76c2c907Caitlin Sadowski void handleExclusiveAndShared(Name LockName, SourceLocation Loc1, 71075f23aeb1c820b49f9faebed63b1cbef76c2c907Caitlin Sadowski SourceLocation Loc2) { 7112e5156274b8051217565b557bfa14c80f7990e9cRichard Smith PartialDiagnosticAt Warning( 7122e5156274b8051217565b557bfa14c80f7990e9cRichard Smith Loc1, S.PDiag(diag::warn_lock_exclusive_and_shared) << LockName); 7132e5156274b8051217565b557bfa14c80f7990e9cRichard Smith PartialDiagnosticAt Note( 7142e5156274b8051217565b557bfa14c80f7990e9cRichard Smith Loc2, S.PDiag(diag::note_lock_exclusive_and_shared) << LockName); 7152e5156274b8051217565b557bfa14c80f7990e9cRichard Smith Warnings.push_back(DelayedDiag(Warning, OptionalNotes(1, Note))); 71675f23aeb1c820b49f9faebed63b1cbef76c2c907Caitlin Sadowski } 71775f23aeb1c820b49f9faebed63b1cbef76c2c907Caitlin Sadowski 71875f23aeb1c820b49f9faebed63b1cbef76c2c907Caitlin Sadowski void handleNoMutexHeld(const NamedDecl *D, ProtectedOperationKind POK, 71975f23aeb1c820b49f9faebed63b1cbef76c2c907Caitlin Sadowski AccessKind AK, SourceLocation Loc) { 720df8327c28d293cf7c6952b86dba26863235dcc0fCaitlin Sadowski assert((POK == POK_VarAccess || POK == POK_VarDereference) 721df8327c28d293cf7c6952b86dba26863235dcc0fCaitlin Sadowski && "Only works for variables"); 722df8327c28d293cf7c6952b86dba26863235dcc0fCaitlin Sadowski unsigned DiagID = POK == POK_VarAccess? 723df8327c28d293cf7c6952b86dba26863235dcc0fCaitlin Sadowski diag::warn_variable_requires_any_lock: 724df8327c28d293cf7c6952b86dba26863235dcc0fCaitlin Sadowski diag::warn_var_deref_requires_any_lock; 7252e5156274b8051217565b557bfa14c80f7990e9cRichard Smith PartialDiagnosticAt Warning(Loc, S.PDiag(DiagID) 7262e5156274b8051217565b557bfa14c80f7990e9cRichard Smith << D->getName() << getLockKindFromAccessKind(AK)); 7272e5156274b8051217565b557bfa14c80f7990e9cRichard Smith Warnings.push_back(DelayedDiag(Warning, OptionalNotes())); 72875f23aeb1c820b49f9faebed63b1cbef76c2c907Caitlin Sadowski } 72975f23aeb1c820b49f9faebed63b1cbef76c2c907Caitlin Sadowski 73075f23aeb1c820b49f9faebed63b1cbef76c2c907Caitlin Sadowski void handleMutexNotHeld(const NamedDecl *D, ProtectedOperationKind POK, 73175f23aeb1c820b49f9faebed63b1cbef76c2c907Caitlin Sadowski Name LockName, LockKind LK, SourceLocation Loc) { 732e87158dfbca01577810f301543c3cdcfc955d8b0Caitlin Sadowski unsigned DiagID = 0; 73375f23aeb1c820b49f9faebed63b1cbef76c2c907Caitlin Sadowski switch (POK) { 73475f23aeb1c820b49f9faebed63b1cbef76c2c907Caitlin Sadowski case POK_VarAccess: 73575f23aeb1c820b49f9faebed63b1cbef76c2c907Caitlin Sadowski DiagID = diag::warn_variable_requires_lock; 73675f23aeb1c820b49f9faebed63b1cbef76c2c907Caitlin Sadowski break; 73775f23aeb1c820b49f9faebed63b1cbef76c2c907Caitlin Sadowski case POK_VarDereference: 73875f23aeb1c820b49f9faebed63b1cbef76c2c907Caitlin Sadowski DiagID = diag::warn_var_deref_requires_lock; 73975f23aeb1c820b49f9faebed63b1cbef76c2c907Caitlin Sadowski break; 74075f23aeb1c820b49f9faebed63b1cbef76c2c907Caitlin Sadowski case POK_FunctionCall: 74175f23aeb1c820b49f9faebed63b1cbef76c2c907Caitlin Sadowski DiagID = diag::warn_fun_requires_lock; 74275f23aeb1c820b49f9faebed63b1cbef76c2c907Caitlin Sadowski break; 74375f23aeb1c820b49f9faebed63b1cbef76c2c907Caitlin Sadowski } 7442e5156274b8051217565b557bfa14c80f7990e9cRichard Smith PartialDiagnosticAt Warning(Loc, S.PDiag(DiagID) 7452e5156274b8051217565b557bfa14c80f7990e9cRichard Smith << D->getName() << LockName << LK); 7462e5156274b8051217565b557bfa14c80f7990e9cRichard Smith Warnings.push_back(DelayedDiag(Warning, OptionalNotes())); 74775f23aeb1c820b49f9faebed63b1cbef76c2c907Caitlin Sadowski } 74875f23aeb1c820b49f9faebed63b1cbef76c2c907Caitlin Sadowski 74975f23aeb1c820b49f9faebed63b1cbef76c2c907Caitlin Sadowski void handleFunExcludesLock(Name FunName, Name LockName, SourceLocation Loc) { 7502e5156274b8051217565b557bfa14c80f7990e9cRichard Smith PartialDiagnosticAt Warning(Loc, 7512e5156274b8051217565b557bfa14c80f7990e9cRichard Smith S.PDiag(diag::warn_fun_excludes_mutex) << FunName << LockName); 7522e5156274b8051217565b557bfa14c80f7990e9cRichard Smith Warnings.push_back(DelayedDiag(Warning, OptionalNotes())); 75375f23aeb1c820b49f9faebed63b1cbef76c2c907Caitlin Sadowski } 75475f23aeb1c820b49f9faebed63b1cbef76c2c907Caitlin Sadowski}; 75575f23aeb1c820b49f9faebed63b1cbef76c2c907Caitlin Sadowski} 75675f23aeb1c820b49f9faebed63b1cbef76c2c907Caitlin Sadowski} 75799ba9e3bd70671f3441fb974895f226a83ce0e66David Blaikie} 75875f23aeb1c820b49f9faebed63b1cbef76c2c907Caitlin Sadowski 759610068c8cd2321f90e147b12cf794e1f840b6405Ted Kremenek//===----------------------------------------------------------------------===// 760dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek// AnalysisBasedWarnings - Worker object used by Sema to execute analysis-based 761dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek// warnings on a function, method, or block. 762dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek//===----------------------------------------------------------------------===// 763dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek 764d064fdc4b7b64ca55b40b70490c79d6f569df78eTed Kremenekclang::sema::AnalysisBasedWarnings::Policy::Policy() { 765dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek enableCheckFallThrough = 1; 766d064fdc4b7b64ca55b40b70490c79d6f569df78eTed Kremenek enableCheckUnreachable = 0; 7673ac1fbc303d22af2e11a14023ecee7bd7b7d0bfdCaitlin Sadowski enableThreadSafetyAnalysis = 0; 768d064fdc4b7b64ca55b40b70490c79d6f569df78eTed Kremenek} 769dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek 7705d98994c7749312a43ce6adf45537979a98e7afdChandler Carruthclang::sema::AnalysisBasedWarnings::AnalysisBasedWarnings(Sema &s) 7715d98994c7749312a43ce6adf45537979a98e7afdChandler Carruth : S(s), 7725d98994c7749312a43ce6adf45537979a98e7afdChandler Carruth NumFunctionsAnalyzed(0), 77354cf341bd4145e5e31f91c5777fcdaf3f2400537Benjamin Kramer NumFunctionsWithBadCFGs(0), 7745d98994c7749312a43ce6adf45537979a98e7afdChandler Carruth NumCFGBlocks(0), 77554cf341bd4145e5e31f91c5777fcdaf3f2400537Benjamin Kramer MaxCFGBlocksPerFunction(0), 77654cf341bd4145e5e31f91c5777fcdaf3f2400537Benjamin Kramer NumUninitAnalysisFunctions(0), 77754cf341bd4145e5e31f91c5777fcdaf3f2400537Benjamin Kramer NumUninitAnalysisVariables(0), 77854cf341bd4145e5e31f91c5777fcdaf3f2400537Benjamin Kramer MaxUninitAnalysisVariablesPerFunction(0), 77954cf341bd4145e5e31f91c5777fcdaf3f2400537Benjamin Kramer NumUninitAnalysisBlockVisits(0), 78054cf341bd4145e5e31f91c5777fcdaf3f2400537Benjamin Kramer MaxUninitAnalysisBlockVisitsPerFunction(0) { 781d6471f7c1921c7802804ce3ff6fe9768310f72b9David Blaikie DiagnosticsEngine &D = S.getDiagnostics(); 782d064fdc4b7b64ca55b40b70490c79d6f569df78eTed Kremenek DefaultPolicy.enableCheckUnreachable = (unsigned) 7830827408865e32789e0ec4b8113a302ccdc531423Argyrios Kyrtzidis (D.getDiagnosticLevel(diag::warn_unreachable, SourceLocation()) != 784d6471f7c1921c7802804ce3ff6fe9768310f72b9David Blaikie DiagnosticsEngine::Ignored); 7853ac1fbc303d22af2e11a14023ecee7bd7b7d0bfdCaitlin Sadowski DefaultPolicy.enableThreadSafetyAnalysis = (unsigned) 7863ac1fbc303d22af2e11a14023ecee7bd7b7d0bfdCaitlin Sadowski (D.getDiagnosticLevel(diag::warn_double_lock, SourceLocation()) != 787d6471f7c1921c7802804ce3ff6fe9768310f72b9David Blaikie DiagnosticsEngine::Ignored); 7883ac1fbc303d22af2e11a14023ecee7bd7b7d0bfdCaitlin Sadowski 789dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek} 790dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek 791351ba91eaa6d30e523587b2d7ed676a5172c6e56Ted Kremenekstatic void flushDiagnostics(Sema &S, sema::FunctionScopeInfo *fscope) { 7925f9e272e632e951b1efe824cd16acb4d96077930Chris Lattner for (SmallVectorImpl<sema::PossiblyUnreachableDiag>::iterator 793351ba91eaa6d30e523587b2d7ed676a5172c6e56Ted Kremenek i = fscope->PossiblyUnreachableDiags.begin(), 794351ba91eaa6d30e523587b2d7ed676a5172c6e56Ted Kremenek e = fscope->PossiblyUnreachableDiags.end(); 795351ba91eaa6d30e523587b2d7ed676a5172c6e56Ted Kremenek i != e; ++i) { 796351ba91eaa6d30e523587b2d7ed676a5172c6e56Ted Kremenek const sema::PossiblyUnreachableDiag &D = *i; 797351ba91eaa6d30e523587b2d7ed676a5172c6e56Ted Kremenek S.Diag(D.Loc, D.PD); 798351ba91eaa6d30e523587b2d7ed676a5172c6e56Ted Kremenek } 799351ba91eaa6d30e523587b2d7ed676a5172c6e56Ted Kremenek} 800351ba91eaa6d30e523587b2d7ed676a5172c6e56Ted Kremenek 801d064fdc4b7b64ca55b40b70490c79d6f569df78eTed Kremenekvoid clang::sema:: 802d064fdc4b7b64ca55b40b70490c79d6f569df78eTed KremenekAnalysisBasedWarnings::IssueWarnings(sema::AnalysisBasedWarnings::Policy P, 803283a358aecb75e30fcd486f2206f6c03c5e7f11dTed Kremenek sema::FunctionScopeInfo *fscope, 8043ed6fc08a9cd293d012fa49ab2a615e618d7c3faTed Kremenek const Decl *D, const BlockExpr *blkExpr) { 805d068aabc484c4009282122c6ef26e66e68cfa044Ted Kremenek 806dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek // We avoid doing analysis-based warnings when there are errors for 807dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek // two reasons: 808dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek // (1) The CFGs often can't be constructed (if the body is invalid), so 809dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek // don't bother trying. 810dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek // (2) The code already has problems; running the analysis just takes more 811dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek // time. 812d6471f7c1921c7802804ce3ff6fe9768310f72b9David Blaikie DiagnosticsEngine &Diags = S.getDiagnostics(); 81399e8192c4c8f1f596f9969e5f2cdafcee64ddaacTed Kremenek 814d064fdc4b7b64ca55b40b70490c79d6f569df78eTed Kremenek // Do not do any analysis for declarations in system headers if we are 815d064fdc4b7b64ca55b40b70490c79d6f569df78eTed Kremenek // going to just ignore them. 81699e8192c4c8f1f596f9969e5f2cdafcee64ddaacTed Kremenek if (Diags.getSuppressSystemWarnings() && 817d064fdc4b7b64ca55b40b70490c79d6f569df78eTed Kremenek S.SourceMgr.isInSystemHeader(D->getLocation())) 818d064fdc4b7b64ca55b40b70490c79d6f569df78eTed Kremenek return; 819d064fdc4b7b64ca55b40b70490c79d6f569df78eTed Kremenek 820e0054f61fd84133eb0d19c19ae9afaf117933274John McCall // For code in dependent contexts, we'll do this at instantiation time. 82123661d3e348c5f44ae89b6848bbc331829bb46f2David Blaikie if (cast<DeclContext>(D)->isDependentContext()) 82223661d3e348c5f44ae89b6848bbc331829bb46f2David Blaikie return; 823dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek 824351ba91eaa6d30e523587b2d7ed676a5172c6e56Ted Kremenek if (Diags.hasErrorOccurred() || Diags.hasFatalErrorOccurred()) { 825351ba91eaa6d30e523587b2d7ed676a5172c6e56Ted Kremenek // Flush out any possibly unreachable diagnostics. 826351ba91eaa6d30e523587b2d7ed676a5172c6e56Ted Kremenek flushDiagnostics(S, fscope); 827351ba91eaa6d30e523587b2d7ed676a5172c6e56Ted Kremenek return; 828351ba91eaa6d30e523587b2d7ed676a5172c6e56Ted Kremenek } 829351ba91eaa6d30e523587b2d7ed676a5172c6e56Ted Kremenek 830dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek const Stmt *Body = D->getBody(); 831dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek assert(Body); 832dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek 833d200187bd27f9ad68699693a6e57f9ee3ff260faJordy Rose AnalysisDeclContext AC(/* AnalysisDeclContextManager */ 0, D); 834bc5cb8a5fe2b88f917d47ceb58b53696a121e57eTed Kremenek 835dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek // Don't generate EH edges for CallExprs as we'd like to avoid the n^2 836dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek // explosion for destrutors that can result and the compile time hit. 837bc5cb8a5fe2b88f917d47ceb58b53696a121e57eTed Kremenek AC.getCFGBuildOptions().PruneTriviallyFalseEdges = true; 838bc5cb8a5fe2b88f917d47ceb58b53696a121e57eTed Kremenek AC.getCFGBuildOptions().AddEHEdges = false; 839bc5cb8a5fe2b88f917d47ceb58b53696a121e57eTed Kremenek AC.getCFGBuildOptions().AddInitializers = true; 840bc5cb8a5fe2b88f917d47ceb58b53696a121e57eTed Kremenek AC.getCFGBuildOptions().AddImplicitDtors = true; 8410c8e5a0f70cbdb800d939c1807d05f380b2854d4Ted Kremenek 8420c8e5a0f70cbdb800d939c1807d05f380b2854d4Ted Kremenek // Force that certain expressions appear as CFGElements in the CFG. This 8430c8e5a0f70cbdb800d939c1807d05f380b2854d4Ted Kremenek // is used to speed up various analyses. 8440c8e5a0f70cbdb800d939c1807d05f380b2854d4Ted Kremenek // FIXME: This isn't the right factoring. This is here for initial 8450c8e5a0f70cbdb800d939c1807d05f380b2854d4Ted Kremenek // prototyping, but we need a way for analyses to say what expressions they 8460c8e5a0f70cbdb800d939c1807d05f380b2854d4Ted Kremenek // expect to always be CFGElements and then fill in the BuildOptions 8470c8e5a0f70cbdb800d939c1807d05f380b2854d4Ted Kremenek // appropriately. This is essentially a layering violation. 8481fa3c0682a52c45c4ad0be3a82d0c85f26657072DeLesley Hutchins if (P.enableCheckUnreachable || P.enableThreadSafetyAnalysis) { 8491fa3c0682a52c45c4ad0be3a82d0c85f26657072DeLesley Hutchins // Unreachable code analysis and thread safety require a linearized CFG. 8500f3b4ca1764cd6d457f511d340fba504f41763c3Ted Kremenek AC.getCFGBuildOptions().setAllAlwaysAdd(); 8510f3b4ca1764cd6d457f511d340fba504f41763c3Ted Kremenek } 8520f3b4ca1764cd6d457f511d340fba504f41763c3Ted Kremenek else { 8530f3b4ca1764cd6d457f511d340fba504f41763c3Ted Kremenek AC.getCFGBuildOptions() 8540f3b4ca1764cd6d457f511d340fba504f41763c3Ted Kremenek .setAlwaysAdd(Stmt::BinaryOperatorClass) 8550f3b4ca1764cd6d457f511d340fba504f41763c3Ted Kremenek .setAlwaysAdd(Stmt::BlockExprClass) 8560f3b4ca1764cd6d457f511d340fba504f41763c3Ted Kremenek .setAlwaysAdd(Stmt::CStyleCastExprClass) 8570f3b4ca1764cd6d457f511d340fba504f41763c3Ted Kremenek .setAlwaysAdd(Stmt::DeclRefExprClass) 8580f3b4ca1764cd6d457f511d340fba504f41763c3Ted Kremenek .setAlwaysAdd(Stmt::ImplicitCastExprClass) 8590f3b4ca1764cd6d457f511d340fba504f41763c3Ted Kremenek .setAlwaysAdd(Stmt::UnaryOperatorClass); 8600f3b4ca1764cd6d457f511d340fba504f41763c3Ted Kremenek } 861bc5cb8a5fe2b88f917d47ceb58b53696a121e57eTed Kremenek 862bc5cb8a5fe2b88f917d47ceb58b53696a121e57eTed Kremenek // Construct the analysis context with the specified CFG build options. 863bc5cb8a5fe2b88f917d47ceb58b53696a121e57eTed Kremenek 864351ba91eaa6d30e523587b2d7ed676a5172c6e56Ted Kremenek // Emit delayed diagnostics. 86523661d3e348c5f44ae89b6848bbc331829bb46f2David Blaikie if (!fscope->PossiblyUnreachableDiags.empty()) { 866351ba91eaa6d30e523587b2d7ed676a5172c6e56Ted Kremenek bool analyzed = false; 8670d28d360b5559abda755e50b855ba5e59727d9cdTed Kremenek 8680d28d360b5559abda755e50b855ba5e59727d9cdTed Kremenek // Register the expressions with the CFGBuilder. 8695f9e272e632e951b1efe824cd16acb4d96077930Chris Lattner for (SmallVectorImpl<sema::PossiblyUnreachableDiag>::iterator 8700d28d360b5559abda755e50b855ba5e59727d9cdTed Kremenek i = fscope->PossiblyUnreachableDiags.begin(), 8710d28d360b5559abda755e50b855ba5e59727d9cdTed Kremenek e = fscope->PossiblyUnreachableDiags.end(); 8720d28d360b5559abda755e50b855ba5e59727d9cdTed Kremenek i != e; ++i) { 8730d28d360b5559abda755e50b855ba5e59727d9cdTed Kremenek if (const Stmt *stmt = i->stmt) 8740d28d360b5559abda755e50b855ba5e59727d9cdTed Kremenek AC.registerForcedBlockExpression(stmt); 8750d28d360b5559abda755e50b855ba5e59727d9cdTed Kremenek } 8760d28d360b5559abda755e50b855ba5e59727d9cdTed Kremenek 8770d28d360b5559abda755e50b855ba5e59727d9cdTed Kremenek if (AC.getCFG()) { 8780d28d360b5559abda755e50b855ba5e59727d9cdTed Kremenek analyzed = true; 8795f9e272e632e951b1efe824cd16acb4d96077930Chris Lattner for (SmallVectorImpl<sema::PossiblyUnreachableDiag>::iterator 8800d28d360b5559abda755e50b855ba5e59727d9cdTed Kremenek i = fscope->PossiblyUnreachableDiags.begin(), 8810d28d360b5559abda755e50b855ba5e59727d9cdTed Kremenek e = fscope->PossiblyUnreachableDiags.end(); 8820d28d360b5559abda755e50b855ba5e59727d9cdTed Kremenek i != e; ++i) 8830d28d360b5559abda755e50b855ba5e59727d9cdTed Kremenek { 8840d28d360b5559abda755e50b855ba5e59727d9cdTed Kremenek const sema::PossiblyUnreachableDiag &D = *i; 8850d28d360b5559abda755e50b855ba5e59727d9cdTed Kremenek bool processed = false; 8860d28d360b5559abda755e50b855ba5e59727d9cdTed Kremenek if (const Stmt *stmt = i->stmt) { 8870d28d360b5559abda755e50b855ba5e59727d9cdTed Kremenek const CFGBlock *block = AC.getBlockForRegisteredExpression(stmt); 88871b8fb5d4233420d2ed2f150a54ea61431bd8684Eli Friedman CFGReverseBlockReachabilityAnalysis *cra = 88971b8fb5d4233420d2ed2f150a54ea61431bd8684Eli Friedman AC.getCFGReachablityAnalysis(); 89071b8fb5d4233420d2ed2f150a54ea61431bd8684Eli Friedman // FIXME: We should be able to assert that block is non-null, but 89171b8fb5d4233420d2ed2f150a54ea61431bd8684Eli Friedman // the CFG analysis can skip potentially-evaluated expressions in 89271b8fb5d4233420d2ed2f150a54ea61431bd8684Eli Friedman // edge cases; see test/Sema/vla-2.c. 89371b8fb5d4233420d2ed2f150a54ea61431bd8684Eli Friedman if (block && cra) { 894351ba91eaa6d30e523587b2d7ed676a5172c6e56Ted Kremenek // Can this block be reached from the entrance? 8950d28d360b5559abda755e50b855ba5e59727d9cdTed Kremenek if (cra->isReachable(&AC.getCFG()->getEntry(), block)) 896351ba91eaa6d30e523587b2d7ed676a5172c6e56Ted Kremenek S.Diag(D.Loc, D.PD); 8970d28d360b5559abda755e50b855ba5e59727d9cdTed Kremenek processed = true; 898351ba91eaa6d30e523587b2d7ed676a5172c6e56Ted Kremenek } 8990d28d360b5559abda755e50b855ba5e59727d9cdTed Kremenek } 9000d28d360b5559abda755e50b855ba5e59727d9cdTed Kremenek if (!processed) { 9010d28d360b5559abda755e50b855ba5e59727d9cdTed Kremenek // Emit the warning anyway if we cannot map to a basic block. 9020d28d360b5559abda755e50b855ba5e59727d9cdTed Kremenek S.Diag(D.Loc, D.PD); 903351ba91eaa6d30e523587b2d7ed676a5172c6e56Ted Kremenek } 904351ba91eaa6d30e523587b2d7ed676a5172c6e56Ted Kremenek } 9050d28d360b5559abda755e50b855ba5e59727d9cdTed Kremenek } 906351ba91eaa6d30e523587b2d7ed676a5172c6e56Ted Kremenek 907351ba91eaa6d30e523587b2d7ed676a5172c6e56Ted Kremenek if (!analyzed) 908351ba91eaa6d30e523587b2d7ed676a5172c6e56Ted Kremenek flushDiagnostics(S, fscope); 909351ba91eaa6d30e523587b2d7ed676a5172c6e56Ted Kremenek } 910351ba91eaa6d30e523587b2d7ed676a5172c6e56Ted Kremenek 911351ba91eaa6d30e523587b2d7ed676a5172c6e56Ted Kremenek 912dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek // Warning: check missing 'return' 91323661d3e348c5f44ae89b6848bbc331829bb46f2David Blaikie if (P.enableCheckFallThrough) { 914dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek const CheckFallThroughDiagnostics &CD = 915dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek (isa<BlockDecl>(D) ? CheckFallThroughDiagnostics::MakeForBlock() 916793cd1c4cdfaafc52e2c2ad9dae959befe4bb166Douglas Gregor : (isa<CXXMethodDecl>(D) && 917793cd1c4cdfaafc52e2c2ad9dae959befe4bb166Douglas Gregor cast<CXXMethodDecl>(D)->getOverloadedOperator() == OO_Call && 918793cd1c4cdfaafc52e2c2ad9dae959befe4bb166Douglas Gregor cast<CXXMethodDecl>(D)->getParent()->isLambda()) 919793cd1c4cdfaafc52e2c2ad9dae959befe4bb166Douglas Gregor ? CheckFallThroughDiagnostics::MakeForLambda() 920793cd1c4cdfaafc52e2c2ad9dae959befe4bb166Douglas Gregor : CheckFallThroughDiagnostics::MakeForFunction(D)); 9213ed6fc08a9cd293d012fa49ab2a615e618d7c3faTed Kremenek CheckFallThroughForBody(S, D, Body, blkExpr, CD, AC); 922dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek } 923dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek 924dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek // Warning: check for unreachable code 9255dfee06daa359bbe0f3c9de055b8a02d61a05173Ted Kremenek if (P.enableCheckUnreachable) { 9265dfee06daa359bbe0f3c9de055b8a02d61a05173Ted Kremenek // Only check for unreachable code on non-template instantiations. 9275dfee06daa359bbe0f3c9de055b8a02d61a05173Ted Kremenek // Different template instantiations can effectively change the control-flow 9285dfee06daa359bbe0f3c9de055b8a02d61a05173Ted Kremenek // and it is very difficult to prove that a snippet of code in a template 9295dfee06daa359bbe0f3c9de055b8a02d61a05173Ted Kremenek // is unreachable for all instantiations. 93075df4eeede7b91c22c1d63fafd4dd4142844e3b9Ted Kremenek bool isTemplateInstantiation = false; 93175df4eeede7b91c22c1d63fafd4dd4142844e3b9Ted Kremenek if (const FunctionDecl *Function = dyn_cast<FunctionDecl>(D)) 93275df4eeede7b91c22c1d63fafd4dd4142844e3b9Ted Kremenek isTemplateInstantiation = Function->isTemplateInstantiation(); 93375df4eeede7b91c22c1d63fafd4dd4142844e3b9Ted Kremenek if (!isTemplateInstantiation) 9345dfee06daa359bbe0f3c9de055b8a02d61a05173Ted Kremenek CheckUnreachable(S, AC); 9355dfee06daa359bbe0f3c9de055b8a02d61a05173Ted Kremenek } 93675f23aeb1c820b49f9faebed63b1cbef76c2c907Caitlin Sadowski 9373ac1fbc303d22af2e11a14023ecee7bd7b7d0bfdCaitlin Sadowski // Check for thread safety violations 93823661d3e348c5f44ae89b6848bbc331829bb46f2David Blaikie if (P.enableThreadSafetyAnalysis) { 939f1ac63702143d84db778d32eb185a77fc97db5f5DeLesley Hutchins SourceLocation FL = AC.getDecl()->getLocation(); 9402e5156274b8051217565b557bfa14c80f7990e9cRichard Smith SourceLocation FEL = AC.getDecl()->getLocEnd(); 9412e5156274b8051217565b557bfa14c80f7990e9cRichard Smith thread_safety::ThreadSafetyReporter Reporter(S, FL, FEL); 94275f23aeb1c820b49f9faebed63b1cbef76c2c907Caitlin Sadowski thread_safety::runThreadSafetyAnalysis(AC, Reporter); 94375f23aeb1c820b49f9faebed63b1cbef76c2c907Caitlin Sadowski Reporter.emitDiagnostics(); 94475f23aeb1c820b49f9faebed63b1cbef76c2c907Caitlin Sadowski } 9453ac1fbc303d22af2e11a14023ecee7bd7b7d0bfdCaitlin Sadowski 946a8c17a5babab35f2db26bf218e7571d1af4afedfTed Kremenek if (Diags.getDiagnosticLevel(diag::warn_uninit_var, D->getLocStart()) 947d6471f7c1921c7802804ce3ff6fe9768310f72b9David Blaikie != DiagnosticsEngine::Ignored || 94876709bf816e5e1b70b859bb607cf3ee91db12b76Ted Kremenek Diags.getDiagnosticLevel(diag::warn_maybe_uninit_var, D->getLocStart()) 949d6471f7c1921c7802804ce3ff6fe9768310f72b9David Blaikie != DiagnosticsEngine::Ignored) { 950c5e43c19ddb40b8a1371291f73ae66fe54951ca5Ted Kremenek if (CFG *cfg = AC.getCFG()) { 951c21fed361c11f13db345cba69101578578d8fb79Ted Kremenek UninitValsDiagReporter reporter(S); 95257080fbac1ccce702255423335d52e81bcf17b6bFariborz Jahanian UninitVariablesAnalysisStats stats; 95312efd57ee474c06880a7434ece21a39ac3f34e24Benjamin Kramer std::memset(&stats, 0, sizeof(UninitVariablesAnalysisStats)); 954a8c17a5babab35f2db26bf218e7571d1af4afedfTed Kremenek runUninitializedVariablesAnalysis(*cast<DeclContext>(D), *cfg, AC, 9555d98994c7749312a43ce6adf45537979a98e7afdChandler Carruth reporter, stats); 9565d98994c7749312a43ce6adf45537979a98e7afdChandler Carruth 9575d98994c7749312a43ce6adf45537979a98e7afdChandler Carruth if (S.CollectStats && stats.NumVariablesAnalyzed > 0) { 9585d98994c7749312a43ce6adf45537979a98e7afdChandler Carruth ++NumUninitAnalysisFunctions; 9595d98994c7749312a43ce6adf45537979a98e7afdChandler Carruth NumUninitAnalysisVariables += stats.NumVariablesAnalyzed; 9605d98994c7749312a43ce6adf45537979a98e7afdChandler Carruth NumUninitAnalysisBlockVisits += stats.NumBlockVisits; 9615d98994c7749312a43ce6adf45537979a98e7afdChandler Carruth MaxUninitAnalysisVariablesPerFunction = 9625d98994c7749312a43ce6adf45537979a98e7afdChandler Carruth std::max(MaxUninitAnalysisVariablesPerFunction, 9635d98994c7749312a43ce6adf45537979a98e7afdChandler Carruth stats.NumVariablesAnalyzed); 9645d98994c7749312a43ce6adf45537979a98e7afdChandler Carruth MaxUninitAnalysisBlockVisitsPerFunction = 9655d98994c7749312a43ce6adf45537979a98e7afdChandler Carruth std::max(MaxUninitAnalysisBlockVisitsPerFunction, 9665d98994c7749312a43ce6adf45537979a98e7afdChandler Carruth stats.NumBlockVisits); 9675d98994c7749312a43ce6adf45537979a98e7afdChandler Carruth } 9685d98994c7749312a43ce6adf45537979a98e7afdChandler Carruth } 9695d98994c7749312a43ce6adf45537979a98e7afdChandler Carruth } 9705d98994c7749312a43ce6adf45537979a98e7afdChandler Carruth 9715d98994c7749312a43ce6adf45537979a98e7afdChandler Carruth // Collect statistics about the CFG if it was built. 9725d98994c7749312a43ce6adf45537979a98e7afdChandler Carruth if (S.CollectStats && AC.isCFGBuilt()) { 9735d98994c7749312a43ce6adf45537979a98e7afdChandler Carruth ++NumFunctionsAnalyzed; 9745d98994c7749312a43ce6adf45537979a98e7afdChandler Carruth if (CFG *cfg = AC.getCFG()) { 9755d98994c7749312a43ce6adf45537979a98e7afdChandler Carruth // If we successfully built a CFG for this context, record some more 9765d98994c7749312a43ce6adf45537979a98e7afdChandler Carruth // detail information about it. 9773ea4c49709c5bba5f8b16c6ceb725d9b9a1c48c6Chandler Carruth NumCFGBlocks += cfg->getNumBlockIDs(); 9785d98994c7749312a43ce6adf45537979a98e7afdChandler Carruth MaxCFGBlocksPerFunction = std::max(MaxCFGBlocksPerFunction, 9793ea4c49709c5bba5f8b16c6ceb725d9b9a1c48c6Chandler Carruth cfg->getNumBlockIDs()); 9805d98994c7749312a43ce6adf45537979a98e7afdChandler Carruth } else { 9815d98994c7749312a43ce6adf45537979a98e7afdChandler Carruth ++NumFunctionsWithBadCFGs; 982610068c8cd2321f90e147b12cf794e1f840b6405Ted Kremenek } 983610068c8cd2321f90e147b12cf794e1f840b6405Ted Kremenek } 984dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek} 9855d98994c7749312a43ce6adf45537979a98e7afdChandler Carruth 9865d98994c7749312a43ce6adf45537979a98e7afdChandler Carruthvoid clang::sema::AnalysisBasedWarnings::PrintStats() const { 9875d98994c7749312a43ce6adf45537979a98e7afdChandler Carruth llvm::errs() << "\n*** Analysis Based Warnings Stats:\n"; 9885d98994c7749312a43ce6adf45537979a98e7afdChandler Carruth 9895d98994c7749312a43ce6adf45537979a98e7afdChandler Carruth unsigned NumCFGsBuilt = NumFunctionsAnalyzed - NumFunctionsWithBadCFGs; 9905d98994c7749312a43ce6adf45537979a98e7afdChandler Carruth unsigned AvgCFGBlocksPerFunction = 9915d98994c7749312a43ce6adf45537979a98e7afdChandler Carruth !NumCFGsBuilt ? 0 : NumCFGBlocks/NumCFGsBuilt; 9925d98994c7749312a43ce6adf45537979a98e7afdChandler Carruth llvm::errs() << NumFunctionsAnalyzed << " functions analyzed (" 9935d98994c7749312a43ce6adf45537979a98e7afdChandler Carruth << NumFunctionsWithBadCFGs << " w/o CFGs).\n" 9945d98994c7749312a43ce6adf45537979a98e7afdChandler Carruth << " " << NumCFGBlocks << " CFG blocks built.\n" 9955d98994c7749312a43ce6adf45537979a98e7afdChandler Carruth << " " << AvgCFGBlocksPerFunction 9965d98994c7749312a43ce6adf45537979a98e7afdChandler Carruth << " average CFG blocks per function.\n" 9975d98994c7749312a43ce6adf45537979a98e7afdChandler Carruth << " " << MaxCFGBlocksPerFunction 9985d98994c7749312a43ce6adf45537979a98e7afdChandler Carruth << " max CFG blocks per function.\n"; 9995d98994c7749312a43ce6adf45537979a98e7afdChandler Carruth 10005d98994c7749312a43ce6adf45537979a98e7afdChandler Carruth unsigned AvgUninitVariablesPerFunction = !NumUninitAnalysisFunctions ? 0 10015d98994c7749312a43ce6adf45537979a98e7afdChandler Carruth : NumUninitAnalysisVariables/NumUninitAnalysisFunctions; 10025d98994c7749312a43ce6adf45537979a98e7afdChandler Carruth unsigned AvgUninitBlockVisitsPerFunction = !NumUninitAnalysisFunctions ? 0 10035d98994c7749312a43ce6adf45537979a98e7afdChandler Carruth : NumUninitAnalysisBlockVisits/NumUninitAnalysisFunctions; 10045d98994c7749312a43ce6adf45537979a98e7afdChandler Carruth llvm::errs() << NumUninitAnalysisFunctions 10055d98994c7749312a43ce6adf45537979a98e7afdChandler Carruth << " functions analyzed for uninitialiazed variables\n" 10065d98994c7749312a43ce6adf45537979a98e7afdChandler Carruth << " " << NumUninitAnalysisVariables << " variables analyzed.\n" 10075d98994c7749312a43ce6adf45537979a98e7afdChandler Carruth << " " << AvgUninitVariablesPerFunction 10085d98994c7749312a43ce6adf45537979a98e7afdChandler Carruth << " average variables per function.\n" 10095d98994c7749312a43ce6adf45537979a98e7afdChandler Carruth << " " << MaxUninitAnalysisVariablesPerFunction 10105d98994c7749312a43ce6adf45537979a98e7afdChandler Carruth << " max variables per function.\n" 10115d98994c7749312a43ce6adf45537979a98e7afdChandler Carruth << " " << NumUninitAnalysisBlockVisits << " block visits.\n" 10125d98994c7749312a43ce6adf45537979a98e7afdChandler Carruth << " " << AvgUninitBlockVisitsPerFunction 10135d98994c7749312a43ce6adf45537979a98e7afdChandler Carruth << " average block visits per function.\n" 10145d98994c7749312a43ce6adf45537979a98e7afdChandler Carruth << " " << MaxUninitAnalysisBlockVisitsPerFunction 10155d98994c7749312a43ce6adf45537979a98e7afdChandler Carruth << " max block visits per function.\n"; 10165d98994c7749312a43ce6adf45537979a98e7afdChandler Carruth} 1017