AnalysisBasedWarnings.cpp revision 66da0abf7ab7cd449bb1d5134b2ef97d9d34d812
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" 22bdb97ff687ce85e45cc728b87612ed546f48c1e7Richard Smith#include "clang/Lex/Lexer.h" 237cd088e519d7e6caa4c4c12db52e0e4ae35d25c2John McCall#include "clang/AST/DeclObjC.h" 24384aff8b94bb0d1ad6c5667b90621e5699815bb2John McCall#include "clang/AST/DeclCXX.h" 25dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek#include "clang/AST/ExprObjC.h" 26dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek#include "clang/AST/ExprCXX.h" 27dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek#include "clang/AST/StmtObjC.h" 28dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek#include "clang/AST/StmtCXX.h" 296f41715df2c6a31c0c3ab3088b8cd18a3c8321b8Ted Kremenek#include "clang/AST/EvaluatedExprVisitor.h" 303ac1fbc303d22af2e11a14023ecee7bd7b7d0bfdCaitlin Sadowski#include "clang/AST/StmtVisitor.h" 31e0d3b4cd2b66f1cef26cacbed5820ab7c22ad5b3Richard Smith#include "clang/AST/RecursiveASTVisitor.h" 32dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek#include "clang/Analysis/AnalysisContext.h" 33dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek#include "clang/Analysis/CFG.h" 34dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek#include "clang/Analysis/Analyses/ReachableCode.h" 35351ba91eaa6d30e523587b2d7ed676a5172c6e56Ted Kremenek#include "clang/Analysis/Analyses/CFGReachabilityAnalysis.h" 36402aa0698fec81e574818a0a6c2000fac0b2c4c6Caitlin Sadowski#include "clang/Analysis/Analyses/ThreadSafety.h" 37351ba91eaa6d30e523587b2d7ed676a5172c6e56Ted Kremenek#include "clang/Analysis/CFGStmtMap.h" 386f34213f8d6ae8c77685b53664527e39bfaaca3bTed Kremenek#include "clang/Analysis/Analyses/UninitializedValues.h" 3966da0abf7ab7cd449bb1d5134b2ef97d9d34d812Alexander Kornienko#include "llvm/ADT/ArrayRef.h" 40dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek#include "llvm/ADT/BitVector.h" 413ac1fbc303d22af2e11a14023ecee7bd7b7d0bfdCaitlin Sadowski#include "llvm/ADT/FoldingSet.h" 423ac1fbc303d22af2e11a14023ecee7bd7b7d0bfdCaitlin Sadowski#include "llvm/ADT/ImmutableMap.h" 433ac1fbc303d22af2e11a14023ecee7bd7b7d0bfdCaitlin Sadowski#include "llvm/ADT/PostOrderIterator.h" 443ac1fbc303d22af2e11a14023ecee7bd7b7d0bfdCaitlin Sadowski#include "llvm/ADT/SmallVector.h" 4575f23aeb1c820b49f9faebed63b1cbef76c2c907Caitlin Sadowski#include "llvm/ADT/StringRef.h" 46dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek#include "llvm/Support/Casting.h" 473ac1fbc303d22af2e11a14023ecee7bd7b7d0bfdCaitlin Sadowski#include <algorithm> 48e0d3b4cd2b66f1cef26cacbed5820ab7c22ad5b3Richard Smith#include <iterator> 493ac1fbc303d22af2e11a14023ecee7bd7b7d0bfdCaitlin Sadowski#include <vector> 50e0d3b4cd2b66f1cef26cacbed5820ab7c22ad5b3Richard Smith#include <deque> 51dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek 52dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenekusing namespace clang; 53dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek 54dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek//===----------------------------------------------------------------------===// 55dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek// Unreachable code analysis. 56dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek//===----------------------------------------------------------------------===// 57dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek 58dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremeneknamespace { 59dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek class UnreachableCodeHandler : public reachable_code::Callback { 60dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek Sema &S; 61dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek public: 62dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek UnreachableCodeHandler(Sema &s) : S(s) {} 63dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek 64dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek void HandleUnreachable(SourceLocation L, SourceRange R1, SourceRange R2) { 65dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek S.Diag(L, diag::warn_unreachable) << R1 << R2; 66dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek } 67dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek }; 68dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek} 69dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek 70dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek/// CheckUnreachable - Check for unreachable code. 711d26f48dc2eea1c07431ca1519d7034a21b9bcffTed Kremenekstatic void CheckUnreachable(Sema &S, AnalysisDeclContext &AC) { 72dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek UnreachableCodeHandler UC(S); 73dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek reachable_code::FindUnreachableCode(AC, UC); 74dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek} 75dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek 76dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek//===----------------------------------------------------------------------===// 77dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek// Check for missing return value. 78dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek//===----------------------------------------------------------------------===// 79dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek 8016565aa95b086fb239baf82335dccc1b1ec93942John McCallenum ControlFlowKind { 8116565aa95b086fb239baf82335dccc1b1ec93942John McCall UnknownFallThrough, 8216565aa95b086fb239baf82335dccc1b1ec93942John McCall NeverFallThrough, 8316565aa95b086fb239baf82335dccc1b1ec93942John McCall MaybeFallThrough, 8416565aa95b086fb239baf82335dccc1b1ec93942John McCall AlwaysFallThrough, 8516565aa95b086fb239baf82335dccc1b1ec93942John McCall NeverFallThroughOrReturn 8616565aa95b086fb239baf82335dccc1b1ec93942John McCall}; 87dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek 88dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek/// CheckFallThrough - Check that we don't fall off the end of a 89dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek/// Statement that should return a value. 90dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek/// 91f3477c13eeaf11b32a41f181398fb5deffd0dd73Sylvestre Ledru/// \returns AlwaysFallThrough iff we always fall off the end of the statement, 92f3477c13eeaf11b32a41f181398fb5deffd0dd73Sylvestre Ledru/// MaybeFallThrough iff we might or might not fall off the end, 93f3477c13eeaf11b32a41f181398fb5deffd0dd73Sylvestre Ledru/// NeverFallThroughOrReturn iff we never fall off the end of the statement or 94f3477c13eeaf11b32a41f181398fb5deffd0dd73Sylvestre Ledru/// return. We assume NeverFallThrough iff we never fall off the end of the 95dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek/// statement but we may return. We assume that functions not marked noreturn 96dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek/// will return. 971d26f48dc2eea1c07431ca1519d7034a21b9bcffTed Kremenekstatic ControlFlowKind CheckFallThrough(AnalysisDeclContext &AC) { 98dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek CFG *cfg = AC.getCFG(); 9916565aa95b086fb239baf82335dccc1b1ec93942John McCall if (cfg == 0) return UnknownFallThrough; 100dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek 101dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek // The CFG leaves in dead things, and we don't want the dead code paths to 102dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek // confuse us, so we mark all live things first. 103dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek llvm::BitVector live(cfg->getNumBlockIDs()); 1040f3b4ca1764cd6d457f511d340fba504f41763c3Ted Kremenek unsigned count = reachable_code::ScanReachableFromBlock(&cfg->getEntry(), 105dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek live); 106dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek 107dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek bool AddEHEdges = AC.getAddEHEdges(); 108dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek if (!AddEHEdges && count != cfg->getNumBlockIDs()) 109dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek // When there are things remaining dead, and we didn't add EH edges 110dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek // from CallExprs to the catch clauses, we have to go back and 111dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek // mark them as live. 112dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek for (CFG::iterator I = cfg->begin(), E = cfg->end(); I != E; ++I) { 113dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek CFGBlock &b = **I; 114dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek if (!live[b.getBlockID()]) { 115dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek if (b.pred_begin() == b.pred_end()) { 116dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek if (b.getTerminator() && isa<CXXTryStmt>(b.getTerminator())) 117dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek // When not adding EH edges from calls, catch clauses 118dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek // can otherwise seem dead. Avoid noting them as dead. 1190f3b4ca1764cd6d457f511d340fba504f41763c3Ted Kremenek count += reachable_code::ScanReachableFromBlock(&b, live); 120dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek continue; 121dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek } 122dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek } 123dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek } 124dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek 125dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek // Now we know what is live, we check the live precessors of the exit block 126dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek // and look for fall through paths, being careful to ignore normal returns, 127dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek // and exceptional paths. 128dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek bool HasLiveReturn = false; 129dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek bool HasFakeEdge = false; 130dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek bool HasPlainEdge = false; 131dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek bool HasAbnormalEdge = false; 13290b828aa279542559f655d1af666580288cb1841Ted Kremenek 13390b828aa279542559f655d1af666580288cb1841Ted Kremenek // Ignore default cases that aren't likely to be reachable because all 13490b828aa279542559f655d1af666580288cb1841Ted Kremenek // enums in a switch(X) have explicit case statements. 13590b828aa279542559f655d1af666580288cb1841Ted Kremenek CFGBlock::FilterOptions FO; 13690b828aa279542559f655d1af666580288cb1841Ted Kremenek FO.IgnoreDefaultsWithCoveredEnums = 1; 13790b828aa279542559f655d1af666580288cb1841Ted Kremenek 13890b828aa279542559f655d1af666580288cb1841Ted Kremenek for (CFGBlock::filtered_pred_iterator 13990b828aa279542559f655d1af666580288cb1841Ted Kremenek I = cfg->getExit().filtered_pred_start_end(FO); I.hasMore(); ++I) { 14090b828aa279542559f655d1af666580288cb1841Ted Kremenek const CFGBlock& B = **I; 141dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek if (!live[B.getBlockID()]) 142dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek continue; 1435811f5978feaa7b89bd89e174fa7ad077b48413eTed Kremenek 144e05ee6df356c25e792b0334d7a4dec3fe4f79f07Chandler Carruth // Skip blocks which contain an element marked as no-return. They don't 145e05ee6df356c25e792b0334d7a4dec3fe4f79f07Chandler Carruth // represent actually viable edges into the exit block, so mark them as 146e05ee6df356c25e792b0334d7a4dec3fe4f79f07Chandler Carruth // abnormal. 147e05ee6df356c25e792b0334d7a4dec3fe4f79f07Chandler Carruth if (B.hasNoReturnElement()) { 148e05ee6df356c25e792b0334d7a4dec3fe4f79f07Chandler Carruth HasAbnormalEdge = true; 149e05ee6df356c25e792b0334d7a4dec3fe4f79f07Chandler Carruth continue; 150e05ee6df356c25e792b0334d7a4dec3fe4f79f07Chandler Carruth } 151e05ee6df356c25e792b0334d7a4dec3fe4f79f07Chandler Carruth 1525811f5978feaa7b89bd89e174fa7ad077b48413eTed Kremenek // Destructors can appear after the 'return' in the CFG. This is 1535811f5978feaa7b89bd89e174fa7ad077b48413eTed Kremenek // normal. We need to look pass the destructors for the return 1545811f5978feaa7b89bd89e174fa7ad077b48413eTed Kremenek // statement (if it exists). 1555811f5978feaa7b89bd89e174fa7ad077b48413eTed Kremenek CFGBlock::const_reverse_iterator ri = B.rbegin(), re = B.rend(); 156e05ee6df356c25e792b0334d7a4dec3fe4f79f07Chandler Carruth 157e05ee6df356c25e792b0334d7a4dec3fe4f79f07Chandler Carruth for ( ; ri != re ; ++ri) 158e05ee6df356c25e792b0334d7a4dec3fe4f79f07Chandler Carruth if (isa<CFGStmt>(*ri)) 1595811f5978feaa7b89bd89e174fa7ad077b48413eTed Kremenek break; 160e05ee6df356c25e792b0334d7a4dec3fe4f79f07Chandler Carruth 1615811f5978feaa7b89bd89e174fa7ad077b48413eTed Kremenek // No more CFGElements in the block? 1625811f5978feaa7b89bd89e174fa7ad077b48413eTed Kremenek if (ri == re) { 163dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek if (B.getTerminator() && isa<CXXTryStmt>(B.getTerminator())) { 164dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek HasAbnormalEdge = true; 165dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek continue; 166dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek } 167dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek // A labeled empty statement, or the entry block... 168dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek HasPlainEdge = true; 169dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek continue; 170dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek } 171f39e6a388aaa2f155b46c61e655784b2473218ebTed Kremenek 1725811f5978feaa7b89bd89e174fa7ad077b48413eTed Kremenek CFGStmt CS = cast<CFGStmt>(*ri); 173f1d10d939739f1a4544926d807e4f0f9fb64be61Ted Kremenek const Stmt *S = CS.getStmt(); 174dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek if (isa<ReturnStmt>(S)) { 175dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek HasLiveReturn = true; 176dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek continue; 177dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek } 178dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek if (isa<ObjCAtThrowStmt>(S)) { 179dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek HasFakeEdge = true; 180dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek continue; 181dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek } 182dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek if (isa<CXXThrowExpr>(S)) { 183dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek HasFakeEdge = true; 184dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek continue; 185dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek } 1868cd64b4c5553fa6284d248336cb7c82dc960a394Chad Rosier if (isa<MSAsmStmt>(S)) { 1878cd64b4c5553fa6284d248336cb7c82dc960a394Chad Rosier // TODO: Verify this is correct. 1888cd64b4c5553fa6284d248336cb7c82dc960a394Chad Rosier HasFakeEdge = true; 1898cd64b4c5553fa6284d248336cb7c82dc960a394Chad Rosier HasLiveReturn = true; 1908cd64b4c5553fa6284d248336cb7c82dc960a394Chad Rosier continue; 1918cd64b4c5553fa6284d248336cb7c82dc960a394Chad Rosier } 192dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek if (isa<CXXTryStmt>(S)) { 193dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek HasAbnormalEdge = true; 194dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek continue; 195dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek } 196e05ee6df356c25e792b0334d7a4dec3fe4f79f07Chandler Carruth if (std::find(B.succ_begin(), B.succ_end(), &cfg->getExit()) 197e05ee6df356c25e792b0334d7a4dec3fe4f79f07Chandler Carruth == B.succ_end()) { 198e05ee6df356c25e792b0334d7a4dec3fe4f79f07Chandler Carruth HasAbnormalEdge = true; 199e05ee6df356c25e792b0334d7a4dec3fe4f79f07Chandler Carruth continue; 200dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek } 201e05ee6df356c25e792b0334d7a4dec3fe4f79f07Chandler Carruth 202e05ee6df356c25e792b0334d7a4dec3fe4f79f07Chandler Carruth HasPlainEdge = true; 203dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek } 204dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek if (!HasPlainEdge) { 205dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek if (HasLiveReturn) 206dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek return NeverFallThrough; 207dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek return NeverFallThroughOrReturn; 208dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek } 209dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek if (HasAbnormalEdge || HasFakeEdge || HasLiveReturn) 210dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek return MaybeFallThrough; 211dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek // This says AlwaysFallThrough for calls to functions that are not marked 212dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek // noreturn, that don't return. If people would like this warning to be more 213dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek // accurate, such functions should be marked as noreturn. 214dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek return AlwaysFallThrough; 215dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek} 216dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek 2173c46e8db99196179b30e7ac5c20c4efd5f3926d7Dan Gohmannamespace { 2183c46e8db99196179b30e7ac5c20c4efd5f3926d7Dan Gohman 219dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenekstruct CheckFallThroughDiagnostics { 220dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek unsigned diag_MaybeFallThrough_HasNoReturn; 221dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek unsigned diag_MaybeFallThrough_ReturnsNonVoid; 222dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek unsigned diag_AlwaysFallThrough_HasNoReturn; 223dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek unsigned diag_AlwaysFallThrough_ReturnsNonVoid; 224dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek unsigned diag_NeverFallThroughOrReturn; 225793cd1c4cdfaafc52e2c2ad9dae959befe4bb166Douglas Gregor enum { Function, Block, Lambda } funMode; 2260827408865e32789e0ec4b8113a302ccdc531423Argyrios Kyrtzidis SourceLocation FuncLoc; 227d064fdc4b7b64ca55b40b70490c79d6f569df78eTed Kremenek 228ca7eaeeed817001dc7cee4852a7e41f0982da1efDouglas Gregor static CheckFallThroughDiagnostics MakeForFunction(const Decl *Func) { 229dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek CheckFallThroughDiagnostics D; 2300827408865e32789e0ec4b8113a302ccdc531423Argyrios Kyrtzidis D.FuncLoc = Func->getLocation(); 231dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek D.diag_MaybeFallThrough_HasNoReturn = 232dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek diag::warn_falloff_noreturn_function; 233dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek D.diag_MaybeFallThrough_ReturnsNonVoid = 234dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek diag::warn_maybe_falloff_nonvoid_function; 235dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek D.diag_AlwaysFallThrough_HasNoReturn = 236dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek diag::warn_falloff_noreturn_function; 237dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek D.diag_AlwaysFallThrough_ReturnsNonVoid = 238dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek diag::warn_falloff_nonvoid_function; 239ca7eaeeed817001dc7cee4852a7e41f0982da1efDouglas Gregor 240ca7eaeeed817001dc7cee4852a7e41f0982da1efDouglas Gregor // Don't suggest that virtual functions be marked "noreturn", since they 241ca7eaeeed817001dc7cee4852a7e41f0982da1efDouglas Gregor // might be overridden by non-noreturn functions. 242ca7eaeeed817001dc7cee4852a7e41f0982da1efDouglas Gregor bool isVirtualMethod = false; 243ca7eaeeed817001dc7cee4852a7e41f0982da1efDouglas Gregor if (const CXXMethodDecl *Method = dyn_cast<CXXMethodDecl>(Func)) 244ca7eaeeed817001dc7cee4852a7e41f0982da1efDouglas Gregor isVirtualMethod = Method->isVirtual(); 245ca7eaeeed817001dc7cee4852a7e41f0982da1efDouglas Gregor 246fcdd2cb2fdf35f806dd800b369fe0772a1c8c26cDouglas Gregor // Don't suggest that template instantiations be marked "noreturn" 247fcdd2cb2fdf35f806dd800b369fe0772a1c8c26cDouglas Gregor bool isTemplateInstantiation = false; 24875df4eeede7b91c22c1d63fafd4dd4142844e3b9Ted Kremenek if (const FunctionDecl *Function = dyn_cast<FunctionDecl>(Func)) 24975df4eeede7b91c22c1d63fafd4dd4142844e3b9Ted Kremenek isTemplateInstantiation = Function->isTemplateInstantiation(); 250fcdd2cb2fdf35f806dd800b369fe0772a1c8c26cDouglas Gregor 251fcdd2cb2fdf35f806dd800b369fe0772a1c8c26cDouglas Gregor if (!isVirtualMethod && !isTemplateInstantiation) 252ca7eaeeed817001dc7cee4852a7e41f0982da1efDouglas Gregor D.diag_NeverFallThroughOrReturn = 253ca7eaeeed817001dc7cee4852a7e41f0982da1efDouglas Gregor diag::warn_suggest_noreturn_function; 254ca7eaeeed817001dc7cee4852a7e41f0982da1efDouglas Gregor else 255ca7eaeeed817001dc7cee4852a7e41f0982da1efDouglas Gregor D.diag_NeverFallThroughOrReturn = 0; 256ca7eaeeed817001dc7cee4852a7e41f0982da1efDouglas Gregor 257793cd1c4cdfaafc52e2c2ad9dae959befe4bb166Douglas Gregor D.funMode = Function; 258dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek return D; 259dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek } 260d064fdc4b7b64ca55b40b70490c79d6f569df78eTed Kremenek 261dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek static CheckFallThroughDiagnostics MakeForBlock() { 262dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek CheckFallThroughDiagnostics D; 263dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek D.diag_MaybeFallThrough_HasNoReturn = 264dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek diag::err_noreturn_block_has_return_expr; 265dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek D.diag_MaybeFallThrough_ReturnsNonVoid = 266dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek diag::err_maybe_falloff_nonvoid_block; 267dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek D.diag_AlwaysFallThrough_HasNoReturn = 268dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek diag::err_noreturn_block_has_return_expr; 269dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek D.diag_AlwaysFallThrough_ReturnsNonVoid = 270dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek diag::err_falloff_nonvoid_block; 271dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek D.diag_NeverFallThroughOrReturn = 272dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek diag::warn_suggest_noreturn_block; 273793cd1c4cdfaafc52e2c2ad9dae959befe4bb166Douglas Gregor D.funMode = Block; 274793cd1c4cdfaafc52e2c2ad9dae959befe4bb166Douglas Gregor return D; 275793cd1c4cdfaafc52e2c2ad9dae959befe4bb166Douglas Gregor } 276793cd1c4cdfaafc52e2c2ad9dae959befe4bb166Douglas Gregor 277793cd1c4cdfaafc52e2c2ad9dae959befe4bb166Douglas Gregor static CheckFallThroughDiagnostics MakeForLambda() { 278793cd1c4cdfaafc52e2c2ad9dae959befe4bb166Douglas Gregor CheckFallThroughDiagnostics D; 279793cd1c4cdfaafc52e2c2ad9dae959befe4bb166Douglas Gregor D.diag_MaybeFallThrough_HasNoReturn = 280793cd1c4cdfaafc52e2c2ad9dae959befe4bb166Douglas Gregor diag::err_noreturn_lambda_has_return_expr; 281793cd1c4cdfaafc52e2c2ad9dae959befe4bb166Douglas Gregor D.diag_MaybeFallThrough_ReturnsNonVoid = 282793cd1c4cdfaafc52e2c2ad9dae959befe4bb166Douglas Gregor diag::warn_maybe_falloff_nonvoid_lambda; 283793cd1c4cdfaafc52e2c2ad9dae959befe4bb166Douglas Gregor D.diag_AlwaysFallThrough_HasNoReturn = 284793cd1c4cdfaafc52e2c2ad9dae959befe4bb166Douglas Gregor diag::err_noreturn_lambda_has_return_expr; 285793cd1c4cdfaafc52e2c2ad9dae959befe4bb166Douglas Gregor D.diag_AlwaysFallThrough_ReturnsNonVoid = 286793cd1c4cdfaafc52e2c2ad9dae959befe4bb166Douglas Gregor diag::warn_falloff_nonvoid_lambda; 287793cd1c4cdfaafc52e2c2ad9dae959befe4bb166Douglas Gregor D.diag_NeverFallThroughOrReturn = 0; 288793cd1c4cdfaafc52e2c2ad9dae959befe4bb166Douglas Gregor D.funMode = Lambda; 289dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek return D; 290dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek } 291d064fdc4b7b64ca55b40b70490c79d6f569df78eTed Kremenek 292d6471f7c1921c7802804ce3ff6fe9768310f72b9David Blaikie bool checkDiagnostics(DiagnosticsEngine &D, bool ReturnsVoid, 293dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek bool HasNoReturn) const { 294793cd1c4cdfaafc52e2c2ad9dae959befe4bb166Douglas Gregor if (funMode == Function) { 2950827408865e32789e0ec4b8113a302ccdc531423Argyrios Kyrtzidis return (ReturnsVoid || 2960827408865e32789e0ec4b8113a302ccdc531423Argyrios Kyrtzidis D.getDiagnosticLevel(diag::warn_maybe_falloff_nonvoid_function, 297d6471f7c1921c7802804ce3ff6fe9768310f72b9David Blaikie FuncLoc) == DiagnosticsEngine::Ignored) 2980827408865e32789e0ec4b8113a302ccdc531423Argyrios Kyrtzidis && (!HasNoReturn || 2990827408865e32789e0ec4b8113a302ccdc531423Argyrios Kyrtzidis D.getDiagnosticLevel(diag::warn_noreturn_function_has_return_expr, 300d6471f7c1921c7802804ce3ff6fe9768310f72b9David Blaikie FuncLoc) == DiagnosticsEngine::Ignored) 3010827408865e32789e0ec4b8113a302ccdc531423Argyrios Kyrtzidis && (!ReturnsVoid || 3020827408865e32789e0ec4b8113a302ccdc531423Argyrios Kyrtzidis D.getDiagnosticLevel(diag::warn_suggest_noreturn_block, FuncLoc) 303d6471f7c1921c7802804ce3ff6fe9768310f72b9David Blaikie == DiagnosticsEngine::Ignored); 304dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek } 305d064fdc4b7b64ca55b40b70490c79d6f569df78eTed Kremenek 306793cd1c4cdfaafc52e2c2ad9dae959befe4bb166Douglas Gregor // For blocks / lambdas. 307793cd1c4cdfaafc52e2c2ad9dae959befe4bb166Douglas Gregor return ReturnsVoid && !HasNoReturn 308793cd1c4cdfaafc52e2c2ad9dae959befe4bb166Douglas Gregor && ((funMode == Lambda) || 3090827408865e32789e0ec4b8113a302ccdc531423Argyrios Kyrtzidis D.getDiagnosticLevel(diag::warn_suggest_noreturn_block, FuncLoc) 310d6471f7c1921c7802804ce3ff6fe9768310f72b9David Blaikie == DiagnosticsEngine::Ignored); 311dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek } 312dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek}; 313dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek 3143c46e8db99196179b30e7ac5c20c4efd5f3926d7Dan Gohman} 3153c46e8db99196179b30e7ac5c20c4efd5f3926d7Dan Gohman 316dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek/// CheckFallThroughForFunctionDef - Check that we don't fall off the end of a 317dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek/// function that should return a value. Check that we don't fall off the end 318dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek/// of a noreturn function. We assume that functions and blocks not marked 319dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek/// noreturn will return. 320dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenekstatic void CheckFallThroughForBody(Sema &S, const Decl *D, const Stmt *Body, 3213ed6fc08a9cd293d012fa49ab2a615e618d7c3faTed Kremenek const BlockExpr *blkExpr, 322dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek const CheckFallThroughDiagnostics& CD, 3231d26f48dc2eea1c07431ca1519d7034a21b9bcffTed Kremenek AnalysisDeclContext &AC) { 324dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek 325dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek bool ReturnsVoid = false; 326dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek bool HasNoReturn = false; 327dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek 328dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(D)) { 329dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek ReturnsVoid = FD->getResultType()->isVoidType(); 330dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek HasNoReturn = FD->hasAttr<NoReturnAttr>() || 331264ba48dc98f3f843935a485d5b086f7e0fdc4f1Rafael Espindola FD->getType()->getAs<FunctionType>()->getNoReturnAttr(); 332dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek } 333dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek else if (const ObjCMethodDecl *MD = dyn_cast<ObjCMethodDecl>(D)) { 334dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek ReturnsVoid = MD->getResultType()->isVoidType(); 335dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek HasNoReturn = MD->hasAttr<NoReturnAttr>(); 336dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek } 337dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek else if (isa<BlockDecl>(D)) { 3383ed6fc08a9cd293d012fa49ab2a615e618d7c3faTed Kremenek QualType BlockTy = blkExpr->getType(); 339d064fdc4b7b64ca55b40b70490c79d6f569df78eTed Kremenek if (const FunctionType *FT = 340dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek BlockTy->getPointeeType()->getAs<FunctionType>()) { 341dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek if (FT->getResultType()->isVoidType()) 342dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek ReturnsVoid = true; 343dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek if (FT->getNoReturnAttr()) 344dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek HasNoReturn = true; 345dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek } 346dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek } 347dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek 348d6471f7c1921c7802804ce3ff6fe9768310f72b9David Blaikie DiagnosticsEngine &Diags = S.getDiagnostics(); 349dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek 350dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek // Short circuit for compilation speed. 351dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek if (CD.checkDiagnostics(Diags, ReturnsVoid, HasNoReturn)) 352dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek return; 353d064fdc4b7b64ca55b40b70490c79d6f569df78eTed Kremenek 354dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek // FIXME: Function try block 355dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek if (const CompoundStmt *Compound = dyn_cast<CompoundStmt>(Body)) { 356dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek switch (CheckFallThrough(AC)) { 35716565aa95b086fb239baf82335dccc1b1ec93942John McCall case UnknownFallThrough: 35816565aa95b086fb239baf82335dccc1b1ec93942John McCall break; 35916565aa95b086fb239baf82335dccc1b1ec93942John McCall 360dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek case MaybeFallThrough: 361dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek if (HasNoReturn) 362dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek S.Diag(Compound->getRBracLoc(), 363dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek CD.diag_MaybeFallThrough_HasNoReturn); 364dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek else if (!ReturnsVoid) 365dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek S.Diag(Compound->getRBracLoc(), 366dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek CD.diag_MaybeFallThrough_ReturnsNonVoid); 367dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek break; 368dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek case AlwaysFallThrough: 369dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek if (HasNoReturn) 370dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek S.Diag(Compound->getRBracLoc(), 371dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek CD.diag_AlwaysFallThrough_HasNoReturn); 372dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek else if (!ReturnsVoid) 373dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek S.Diag(Compound->getRBracLoc(), 374dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek CD.diag_AlwaysFallThrough_ReturnsNonVoid); 375dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek break; 376dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek case NeverFallThroughOrReturn: 377b0656ec72e25e5c8e463c2dc39914636f0cb06d1Chandler Carruth if (ReturnsVoid && !HasNoReturn && CD.diag_NeverFallThroughOrReturn) { 378b0656ec72e25e5c8e463c2dc39914636f0cb06d1Chandler Carruth if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(D)) { 379b0656ec72e25e5c8e463c2dc39914636f0cb06d1Chandler Carruth S.Diag(Compound->getLBracLoc(), CD.diag_NeverFallThroughOrReturn) 380b3321093f6ead084427eb4a6621832fc4ee2f5deDouglas Gregor << 0 << FD; 381b3321093f6ead084427eb4a6621832fc4ee2f5deDouglas Gregor } else if (const ObjCMethodDecl *MD = dyn_cast<ObjCMethodDecl>(D)) { 382b3321093f6ead084427eb4a6621832fc4ee2f5deDouglas Gregor S.Diag(Compound->getLBracLoc(), CD.diag_NeverFallThroughOrReturn) 383b3321093f6ead084427eb4a6621832fc4ee2f5deDouglas Gregor << 1 << MD; 384b0656ec72e25e5c8e463c2dc39914636f0cb06d1Chandler Carruth } else { 385b0656ec72e25e5c8e463c2dc39914636f0cb06d1Chandler Carruth S.Diag(Compound->getLBracLoc(), CD.diag_NeverFallThroughOrReturn); 386b0656ec72e25e5c8e463c2dc39914636f0cb06d1Chandler Carruth } 387b0656ec72e25e5c8e463c2dc39914636f0cb06d1Chandler Carruth } 388dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek break; 389dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek case NeverFallThrough: 390dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek break; 391dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek } 392dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek } 393dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek} 394dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek 395dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek//===----------------------------------------------------------------------===// 396610068c8cd2321f90e147b12cf794e1f840b6405Ted Kremenek// -Wuninitialized 397610068c8cd2321f90e147b12cf794e1f840b6405Ted Kremenek//===----------------------------------------------------------------------===// 398610068c8cd2321f90e147b12cf794e1f840b6405Ted Kremenek 3996f41715df2c6a31c0c3ab3088b8cd18a3c8321b8Ted Kremeneknamespace { 4009f6494687c05fe1d334af76408ee056b5f80e027Chandler Carruth/// ContainsReference - A visitor class to search for references to 4019f6494687c05fe1d334af76408ee056b5f80e027Chandler Carruth/// a particular declaration (the needle) within any evaluated component of an 4029f6494687c05fe1d334af76408ee056b5f80e027Chandler Carruth/// expression (recursively). 4036f41715df2c6a31c0c3ab3088b8cd18a3c8321b8Ted Kremenekclass ContainsReference : public EvaluatedExprVisitor<ContainsReference> { 4049f6494687c05fe1d334af76408ee056b5f80e027Chandler Carruth bool FoundReference; 4059f6494687c05fe1d334af76408ee056b5f80e027Chandler Carruth const DeclRefExpr *Needle; 4069f6494687c05fe1d334af76408ee056b5f80e027Chandler Carruth 4076f41715df2c6a31c0c3ab3088b8cd18a3c8321b8Ted Kremenekpublic: 4089f6494687c05fe1d334af76408ee056b5f80e027Chandler Carruth ContainsReference(ASTContext &Context, const DeclRefExpr *Needle) 4099f6494687c05fe1d334af76408ee056b5f80e027Chandler Carruth : EvaluatedExprVisitor<ContainsReference>(Context), 4109f6494687c05fe1d334af76408ee056b5f80e027Chandler Carruth FoundReference(false), Needle(Needle) {} 4119f6494687c05fe1d334af76408ee056b5f80e027Chandler Carruth 4129f6494687c05fe1d334af76408ee056b5f80e027Chandler Carruth void VisitExpr(Expr *E) { 4136f41715df2c6a31c0c3ab3088b8cd18a3c8321b8Ted Kremenek // Stop evaluating if we already have a reference. 4149f6494687c05fe1d334af76408ee056b5f80e027Chandler Carruth if (FoundReference) 4156f41715df2c6a31c0c3ab3088b8cd18a3c8321b8Ted Kremenek return; 4169f6494687c05fe1d334af76408ee056b5f80e027Chandler Carruth 4179f6494687c05fe1d334af76408ee056b5f80e027Chandler Carruth EvaluatedExprVisitor<ContainsReference>::VisitExpr(E); 4186f41715df2c6a31c0c3ab3088b8cd18a3c8321b8Ted Kremenek } 4199f6494687c05fe1d334af76408ee056b5f80e027Chandler Carruth 4209f6494687c05fe1d334af76408ee056b5f80e027Chandler Carruth void VisitDeclRefExpr(DeclRefExpr *E) { 4219f6494687c05fe1d334af76408ee056b5f80e027Chandler Carruth if (E == Needle) 4229f6494687c05fe1d334af76408ee056b5f80e027Chandler Carruth FoundReference = true; 4239f6494687c05fe1d334af76408ee056b5f80e027Chandler Carruth else 4249f6494687c05fe1d334af76408ee056b5f80e027Chandler Carruth EvaluatedExprVisitor<ContainsReference>::VisitDeclRefExpr(E); 4256f41715df2c6a31c0c3ab3088b8cd18a3c8321b8Ted Kremenek } 4269f6494687c05fe1d334af76408ee056b5f80e027Chandler Carruth 4279f6494687c05fe1d334af76408ee056b5f80e027Chandler Carruth bool doesContainReference() const { return FoundReference; } 4286f41715df2c6a31c0c3ab3088b8cd18a3c8321b8Ted Kremenek}; 4296f41715df2c6a31c0c3ab3088b8cd18a3c8321b8Ted Kremenek} 4306f41715df2c6a31c0c3ab3088b8cd18a3c8321b8Ted Kremenek 4314f4f349208b2b2307454e169ac7b039e989f003fDavid Blaikiestatic bool SuggestInitializationFixit(Sema &S, const VarDecl *VD) { 432a34194f035096dd8dce10574e3a186da968aa211Fariborz Jahanian QualType VariableTy = VD->getType().getCanonicalType(); 433a34194f035096dd8dce10574e3a186da968aa211Fariborz Jahanian if (VariableTy->isBlockPointerType() && 434a34194f035096dd8dce10574e3a186da968aa211Fariborz Jahanian !VD->hasAttr<BlocksAttr>()) { 435a34194f035096dd8dce10574e3a186da968aa211Fariborz Jahanian S.Diag(VD->getLocation(), diag::note_block_var_fixit_add_initialization) << VD->getDeclName() 436a34194f035096dd8dce10574e3a186da968aa211Fariborz Jahanian << FixItHint::CreateInsertion(VD->getLocation(), "__block "); 437a34194f035096dd8dce10574e3a186da968aa211Fariborz Jahanian return true; 438a34194f035096dd8dce10574e3a186da968aa211Fariborz Jahanian } 439a34194f035096dd8dce10574e3a186da968aa211Fariborz Jahanian 4404f4f349208b2b2307454e169ac7b039e989f003fDavid Blaikie // Don't issue a fixit if there is already an initializer. 4414f4f349208b2b2307454e169ac7b039e989f003fDavid Blaikie if (VD->getInit()) 4424f4f349208b2b2307454e169ac7b039e989f003fDavid Blaikie return false; 443a34194f035096dd8dce10574e3a186da968aa211Fariborz Jahanian 4444f4f349208b2b2307454e169ac7b039e989f003fDavid Blaikie // Suggest possible initialization (if any). 4452c0abf4ae33ab2ba690ccae724b8d6f196e7cfdaDavid Blaikie std::string Init = S.getFixItZeroInitializerForType(VariableTy); 4462c0abf4ae33ab2ba690ccae724b8d6f196e7cfdaDavid Blaikie if (Init.empty()) 4474f4f349208b2b2307454e169ac7b039e989f003fDavid Blaikie return false; 4487b0a3e378c441cec60f929d13bd48846c267a008Richard Trieu 4497b0a3e378c441cec60f929d13bd48846c267a008Richard Trieu // Don't suggest a fixit inside macros. 4507b0a3e378c441cec60f929d13bd48846c267a008Richard Trieu if (VD->getLocEnd().isMacroID()) 4517b0a3e378c441cec60f929d13bd48846c267a008Richard Trieu return false; 4527b0a3e378c441cec60f929d13bd48846c267a008Richard Trieu 4537984de35644701c0d94336da7f2215d4c26d9f5bRichard Smith SourceLocation Loc = S.PP.getLocForEndOfToken(VD->getLocEnd()); 454a34194f035096dd8dce10574e3a186da968aa211Fariborz Jahanian 4557984de35644701c0d94336da7f2215d4c26d9f5bRichard Smith S.Diag(Loc, diag::note_var_fixit_add_initialization) << VD->getDeclName() 4567984de35644701c0d94336da7f2215d4c26d9f5bRichard Smith << FixItHint::CreateInsertion(Loc, Init); 4577984de35644701c0d94336da7f2215d4c26d9f5bRichard Smith return true; 4584f4f349208b2b2307454e169ac7b039e989f003fDavid Blaikie} 4594f4f349208b2b2307454e169ac7b039e989f003fDavid Blaikie 460bdb97ff687ce85e45cc728b87612ed546f48c1e7Richard Smith/// Create a fixit to remove an if-like statement, on the assumption that its 461bdb97ff687ce85e45cc728b87612ed546f48c1e7Richard Smith/// condition is CondVal. 462bdb97ff687ce85e45cc728b87612ed546f48c1e7Richard Smithstatic void CreateIfFixit(Sema &S, const Stmt *If, const Stmt *Then, 463bdb97ff687ce85e45cc728b87612ed546f48c1e7Richard Smith const Stmt *Else, bool CondVal, 464bdb97ff687ce85e45cc728b87612ed546f48c1e7Richard Smith FixItHint &Fixit1, FixItHint &Fixit2) { 465bdb97ff687ce85e45cc728b87612ed546f48c1e7Richard Smith if (CondVal) { 466bdb97ff687ce85e45cc728b87612ed546f48c1e7Richard Smith // If condition is always true, remove all but the 'then'. 467bdb97ff687ce85e45cc728b87612ed546f48c1e7Richard Smith Fixit1 = FixItHint::CreateRemoval( 468bdb97ff687ce85e45cc728b87612ed546f48c1e7Richard Smith CharSourceRange::getCharRange(If->getLocStart(), 469bdb97ff687ce85e45cc728b87612ed546f48c1e7Richard Smith Then->getLocStart())); 470bdb97ff687ce85e45cc728b87612ed546f48c1e7Richard Smith if (Else) { 471bdb97ff687ce85e45cc728b87612ed546f48c1e7Richard Smith SourceLocation ElseKwLoc = Lexer::getLocForEndOfToken( 472bdb97ff687ce85e45cc728b87612ed546f48c1e7Richard Smith Then->getLocEnd(), 0, S.getSourceManager(), S.getLangOpts()); 473bdb97ff687ce85e45cc728b87612ed546f48c1e7Richard Smith Fixit2 = FixItHint::CreateRemoval( 474bdb97ff687ce85e45cc728b87612ed546f48c1e7Richard Smith SourceRange(ElseKwLoc, Else->getLocEnd())); 475bdb97ff687ce85e45cc728b87612ed546f48c1e7Richard Smith } 476bdb97ff687ce85e45cc728b87612ed546f48c1e7Richard Smith } else { 477bdb97ff687ce85e45cc728b87612ed546f48c1e7Richard Smith // If condition is always false, remove all but the 'else'. 478bdb97ff687ce85e45cc728b87612ed546f48c1e7Richard Smith if (Else) 479bdb97ff687ce85e45cc728b87612ed546f48c1e7Richard Smith Fixit1 = FixItHint::CreateRemoval( 480bdb97ff687ce85e45cc728b87612ed546f48c1e7Richard Smith CharSourceRange::getCharRange(If->getLocStart(), 481bdb97ff687ce85e45cc728b87612ed546f48c1e7Richard Smith Else->getLocStart())); 482bdb97ff687ce85e45cc728b87612ed546f48c1e7Richard Smith else 483bdb97ff687ce85e45cc728b87612ed546f48c1e7Richard Smith Fixit1 = FixItHint::CreateRemoval(If->getSourceRange()); 484bdb97ff687ce85e45cc728b87612ed546f48c1e7Richard Smith } 485bdb97ff687ce85e45cc728b87612ed546f48c1e7Richard Smith} 486bdb97ff687ce85e45cc728b87612ed546f48c1e7Richard Smith 487bdb97ff687ce85e45cc728b87612ed546f48c1e7Richard Smith/// DiagUninitUse -- Helper function to produce a diagnostic for an 488bdb97ff687ce85e45cc728b87612ed546f48c1e7Richard Smith/// uninitialized use of a variable. 489bdb97ff687ce85e45cc728b87612ed546f48c1e7Richard Smithstatic void DiagUninitUse(Sema &S, const VarDecl *VD, const UninitUse &Use, 490bdb97ff687ce85e45cc728b87612ed546f48c1e7Richard Smith bool IsCapturedByBlock) { 491bdb97ff687ce85e45cc728b87612ed546f48c1e7Richard Smith bool Diagnosed = false; 492bdb97ff687ce85e45cc728b87612ed546f48c1e7Richard Smith 493bdb97ff687ce85e45cc728b87612ed546f48c1e7Richard Smith // Diagnose each branch which leads to a sometimes-uninitialized use. 4942815e1a075c74143a0b60a632090ece1dffa5c7cRichard Smith for (UninitUse::branch_iterator I = Use.branch_begin(), E = Use.branch_end(); 4952815e1a075c74143a0b60a632090ece1dffa5c7cRichard Smith I != E; ++I) { 496bdb97ff687ce85e45cc728b87612ed546f48c1e7Richard Smith assert(Use.getKind() == UninitUse::Sometimes); 497bdb97ff687ce85e45cc728b87612ed546f48c1e7Richard Smith 498bdb97ff687ce85e45cc728b87612ed546f48c1e7Richard Smith const Expr *User = Use.getUser(); 4992815e1a075c74143a0b60a632090ece1dffa5c7cRichard Smith const Stmt *Term = I->Terminator; 500bdb97ff687ce85e45cc728b87612ed546f48c1e7Richard Smith 501bdb97ff687ce85e45cc728b87612ed546f48c1e7Richard Smith // Information used when building the diagnostic. 5022815e1a075c74143a0b60a632090ece1dffa5c7cRichard Smith unsigned DiagKind; 5032815e1a075c74143a0b60a632090ece1dffa5c7cRichard Smith const char *Str; 504bdb97ff687ce85e45cc728b87612ed546f48c1e7Richard Smith SourceRange Range; 505bdb97ff687ce85e45cc728b87612ed546f48c1e7Richard Smith 506bdb97ff687ce85e45cc728b87612ed546f48c1e7Richard Smith // FixIts to suppress the diagnosic by removing the dead condition. 507bdb97ff687ce85e45cc728b87612ed546f48c1e7Richard Smith // For all binary terminators, branch 0 is taken if the condition is true, 508bdb97ff687ce85e45cc728b87612ed546f48c1e7Richard Smith // and branch 1 is taken if the condition is false. 509bdb97ff687ce85e45cc728b87612ed546f48c1e7Richard Smith int RemoveDiagKind = -1; 510bdb97ff687ce85e45cc728b87612ed546f48c1e7Richard Smith const char *FixitStr = 511bdb97ff687ce85e45cc728b87612ed546f48c1e7Richard Smith S.getLangOpts().CPlusPlus ? (I->Output ? "true" : "false") 512bdb97ff687ce85e45cc728b87612ed546f48c1e7Richard Smith : (I->Output ? "1" : "0"); 513bdb97ff687ce85e45cc728b87612ed546f48c1e7Richard Smith FixItHint Fixit1, Fixit2; 514bdb97ff687ce85e45cc728b87612ed546f48c1e7Richard Smith 5152815e1a075c74143a0b60a632090ece1dffa5c7cRichard Smith switch (Term->getStmtClass()) { 5162815e1a075c74143a0b60a632090ece1dffa5c7cRichard Smith default: 517bdb97ff687ce85e45cc728b87612ed546f48c1e7Richard Smith // Don't know how to report this. Just fall back to 'may be used 518bdb97ff687ce85e45cc728b87612ed546f48c1e7Richard Smith // uninitialized'. This happens for range-based for, which the user 519bdb97ff687ce85e45cc728b87612ed546f48c1e7Richard Smith // can't explicitly fix. 520bdb97ff687ce85e45cc728b87612ed546f48c1e7Richard Smith // FIXME: This also happens if the first use of a variable is always 521bdb97ff687ce85e45cc728b87612ed546f48c1e7Richard Smith // uninitialized, eg "for (int n; n < 10; ++n)". We should report that 522bdb97ff687ce85e45cc728b87612ed546f48c1e7Richard Smith // with the 'is uninitialized' diagnostic. 5232815e1a075c74143a0b60a632090ece1dffa5c7cRichard Smith continue; 5242815e1a075c74143a0b60a632090ece1dffa5c7cRichard Smith 5252815e1a075c74143a0b60a632090ece1dffa5c7cRichard Smith // "condition is true / condition is false". 526bdb97ff687ce85e45cc728b87612ed546f48c1e7Richard Smith case Stmt::IfStmtClass: { 527bdb97ff687ce85e45cc728b87612ed546f48c1e7Richard Smith const IfStmt *IS = cast<IfStmt>(Term); 5282815e1a075c74143a0b60a632090ece1dffa5c7cRichard Smith DiagKind = 0; 5292815e1a075c74143a0b60a632090ece1dffa5c7cRichard Smith Str = "if"; 530bdb97ff687ce85e45cc728b87612ed546f48c1e7Richard Smith Range = IS->getCond()->getSourceRange(); 531bdb97ff687ce85e45cc728b87612ed546f48c1e7Richard Smith RemoveDiagKind = 0; 532bdb97ff687ce85e45cc728b87612ed546f48c1e7Richard Smith CreateIfFixit(S, IS, IS->getThen(), IS->getElse(), 533bdb97ff687ce85e45cc728b87612ed546f48c1e7Richard Smith I->Output, Fixit1, Fixit2); 5342815e1a075c74143a0b60a632090ece1dffa5c7cRichard Smith break; 535bdb97ff687ce85e45cc728b87612ed546f48c1e7Richard Smith } 536bdb97ff687ce85e45cc728b87612ed546f48c1e7Richard Smith case Stmt::ConditionalOperatorClass: { 537bdb97ff687ce85e45cc728b87612ed546f48c1e7Richard Smith const ConditionalOperator *CO = cast<ConditionalOperator>(Term); 5382815e1a075c74143a0b60a632090ece1dffa5c7cRichard Smith DiagKind = 0; 5392815e1a075c74143a0b60a632090ece1dffa5c7cRichard Smith Str = "?:"; 540bdb97ff687ce85e45cc728b87612ed546f48c1e7Richard Smith Range = CO->getCond()->getSourceRange(); 541bdb97ff687ce85e45cc728b87612ed546f48c1e7Richard Smith RemoveDiagKind = 0; 542bdb97ff687ce85e45cc728b87612ed546f48c1e7Richard Smith CreateIfFixit(S, CO, CO->getTrueExpr(), CO->getFalseExpr(), 543bdb97ff687ce85e45cc728b87612ed546f48c1e7Richard Smith I->Output, Fixit1, Fixit2); 5442815e1a075c74143a0b60a632090ece1dffa5c7cRichard Smith break; 545bdb97ff687ce85e45cc728b87612ed546f48c1e7Richard Smith } 5462815e1a075c74143a0b60a632090ece1dffa5c7cRichard Smith case Stmt::BinaryOperatorClass: { 5472815e1a075c74143a0b60a632090ece1dffa5c7cRichard Smith const BinaryOperator *BO = cast<BinaryOperator>(Term); 5482815e1a075c74143a0b60a632090ece1dffa5c7cRichard Smith if (!BO->isLogicalOp()) 5492815e1a075c74143a0b60a632090ece1dffa5c7cRichard Smith continue; 5502815e1a075c74143a0b60a632090ece1dffa5c7cRichard Smith DiagKind = 0; 5512815e1a075c74143a0b60a632090ece1dffa5c7cRichard Smith Str = BO->getOpcodeStr(); 5522815e1a075c74143a0b60a632090ece1dffa5c7cRichard Smith Range = BO->getLHS()->getSourceRange(); 553bdb97ff687ce85e45cc728b87612ed546f48c1e7Richard Smith RemoveDiagKind = 0; 554bdb97ff687ce85e45cc728b87612ed546f48c1e7Richard Smith if ((BO->getOpcode() == BO_LAnd && I->Output) || 555bdb97ff687ce85e45cc728b87612ed546f48c1e7Richard Smith (BO->getOpcode() == BO_LOr && !I->Output)) 556bdb97ff687ce85e45cc728b87612ed546f48c1e7Richard Smith // true && y -> y, false || y -> y. 557bdb97ff687ce85e45cc728b87612ed546f48c1e7Richard Smith Fixit1 = FixItHint::CreateRemoval(SourceRange(BO->getLocStart(), 558bdb97ff687ce85e45cc728b87612ed546f48c1e7Richard Smith BO->getOperatorLoc())); 559bdb97ff687ce85e45cc728b87612ed546f48c1e7Richard Smith else 560bdb97ff687ce85e45cc728b87612ed546f48c1e7Richard Smith // false && y -> false, true || y -> true. 561bdb97ff687ce85e45cc728b87612ed546f48c1e7Richard Smith Fixit1 = FixItHint::CreateReplacement(BO->getSourceRange(), FixitStr); 5622815e1a075c74143a0b60a632090ece1dffa5c7cRichard Smith break; 5632815e1a075c74143a0b60a632090ece1dffa5c7cRichard Smith } 5642815e1a075c74143a0b60a632090ece1dffa5c7cRichard Smith 5652815e1a075c74143a0b60a632090ece1dffa5c7cRichard Smith // "loop is entered / loop is exited". 5662815e1a075c74143a0b60a632090ece1dffa5c7cRichard Smith case Stmt::WhileStmtClass: 5672815e1a075c74143a0b60a632090ece1dffa5c7cRichard Smith DiagKind = 1; 5682815e1a075c74143a0b60a632090ece1dffa5c7cRichard Smith Str = "while"; 5692815e1a075c74143a0b60a632090ece1dffa5c7cRichard Smith Range = cast<WhileStmt>(Term)->getCond()->getSourceRange(); 570bdb97ff687ce85e45cc728b87612ed546f48c1e7Richard Smith RemoveDiagKind = 1; 571bdb97ff687ce85e45cc728b87612ed546f48c1e7Richard Smith Fixit1 = FixItHint::CreateReplacement(Range, FixitStr); 5722815e1a075c74143a0b60a632090ece1dffa5c7cRichard Smith break; 5732815e1a075c74143a0b60a632090ece1dffa5c7cRichard Smith case Stmt::ForStmtClass: 5742815e1a075c74143a0b60a632090ece1dffa5c7cRichard Smith DiagKind = 1; 5752815e1a075c74143a0b60a632090ece1dffa5c7cRichard Smith Str = "for"; 5762815e1a075c74143a0b60a632090ece1dffa5c7cRichard Smith Range = cast<ForStmt>(Term)->getCond()->getSourceRange(); 577bdb97ff687ce85e45cc728b87612ed546f48c1e7Richard Smith RemoveDiagKind = 1; 578bdb97ff687ce85e45cc728b87612ed546f48c1e7Richard Smith if (I->Output) 579bdb97ff687ce85e45cc728b87612ed546f48c1e7Richard Smith Fixit1 = FixItHint::CreateRemoval(Range); 580bdb97ff687ce85e45cc728b87612ed546f48c1e7Richard Smith else 581bdb97ff687ce85e45cc728b87612ed546f48c1e7Richard Smith Fixit1 = FixItHint::CreateReplacement(Range, FixitStr); 5822815e1a075c74143a0b60a632090ece1dffa5c7cRichard Smith break; 5832815e1a075c74143a0b60a632090ece1dffa5c7cRichard Smith 5842815e1a075c74143a0b60a632090ece1dffa5c7cRichard Smith // "condition is true / loop is exited". 5852815e1a075c74143a0b60a632090ece1dffa5c7cRichard Smith case Stmt::DoStmtClass: 5862815e1a075c74143a0b60a632090ece1dffa5c7cRichard Smith DiagKind = 2; 5872815e1a075c74143a0b60a632090ece1dffa5c7cRichard Smith Str = "do"; 5882815e1a075c74143a0b60a632090ece1dffa5c7cRichard Smith Range = cast<DoStmt>(Term)->getCond()->getSourceRange(); 589bdb97ff687ce85e45cc728b87612ed546f48c1e7Richard Smith RemoveDiagKind = 1; 590bdb97ff687ce85e45cc728b87612ed546f48c1e7Richard Smith Fixit1 = FixItHint::CreateReplacement(Range, FixitStr); 5912815e1a075c74143a0b60a632090ece1dffa5c7cRichard Smith break; 5922815e1a075c74143a0b60a632090ece1dffa5c7cRichard Smith 5932815e1a075c74143a0b60a632090ece1dffa5c7cRichard Smith // "switch case is taken". 5942815e1a075c74143a0b60a632090ece1dffa5c7cRichard Smith case Stmt::CaseStmtClass: 5952815e1a075c74143a0b60a632090ece1dffa5c7cRichard Smith DiagKind = 3; 5962815e1a075c74143a0b60a632090ece1dffa5c7cRichard Smith Str = "case"; 5972815e1a075c74143a0b60a632090ece1dffa5c7cRichard Smith Range = cast<CaseStmt>(Term)->getLHS()->getSourceRange(); 5982815e1a075c74143a0b60a632090ece1dffa5c7cRichard Smith break; 5992815e1a075c74143a0b60a632090ece1dffa5c7cRichard Smith case Stmt::DefaultStmtClass: 6002815e1a075c74143a0b60a632090ece1dffa5c7cRichard Smith DiagKind = 3; 6012815e1a075c74143a0b60a632090ece1dffa5c7cRichard Smith Str = "default"; 6022815e1a075c74143a0b60a632090ece1dffa5c7cRichard Smith Range = cast<DefaultStmt>(Term)->getDefaultLoc(); 6032815e1a075c74143a0b60a632090ece1dffa5c7cRichard Smith break; 6042815e1a075c74143a0b60a632090ece1dffa5c7cRichard Smith } 6052815e1a075c74143a0b60a632090ece1dffa5c7cRichard Smith 606bdb97ff687ce85e45cc728b87612ed546f48c1e7Richard Smith S.Diag(Range.getBegin(), diag::warn_sometimes_uninit_var) 607bdb97ff687ce85e45cc728b87612ed546f48c1e7Richard Smith << VD->getDeclName() << IsCapturedByBlock << DiagKind 608bdb97ff687ce85e45cc728b87612ed546f48c1e7Richard Smith << Str << I->Output << Range; 609bdb97ff687ce85e45cc728b87612ed546f48c1e7Richard Smith S.Diag(User->getLocStart(), diag::note_uninit_var_use) 610bdb97ff687ce85e45cc728b87612ed546f48c1e7Richard Smith << IsCapturedByBlock << User->getSourceRange(); 611bdb97ff687ce85e45cc728b87612ed546f48c1e7Richard Smith if (RemoveDiagKind != -1) 612bdb97ff687ce85e45cc728b87612ed546f48c1e7Richard Smith S.Diag(Fixit1.RemoveRange.getBegin(), diag::note_uninit_fixit_remove_cond) 613bdb97ff687ce85e45cc728b87612ed546f48c1e7Richard Smith << RemoveDiagKind << Str << I->Output << Fixit1 << Fixit2; 614bdb97ff687ce85e45cc728b87612ed546f48c1e7Richard Smith 615bdb97ff687ce85e45cc728b87612ed546f48c1e7Richard Smith Diagnosed = true; 6162815e1a075c74143a0b60a632090ece1dffa5c7cRichard Smith } 617bdb97ff687ce85e45cc728b87612ed546f48c1e7Richard Smith 618bdb97ff687ce85e45cc728b87612ed546f48c1e7Richard Smith if (!Diagnosed) 619bdb97ff687ce85e45cc728b87612ed546f48c1e7Richard Smith S.Diag(Use.getUser()->getLocStart(), 620bdb97ff687ce85e45cc728b87612ed546f48c1e7Richard Smith Use.getKind() == UninitUse::Always ? diag::warn_uninit_var 621bdb97ff687ce85e45cc728b87612ed546f48c1e7Richard Smith : diag::warn_maybe_uninit_var) 622bdb97ff687ce85e45cc728b87612ed546f48c1e7Richard Smith << VD->getDeclName() << IsCapturedByBlock 623bdb97ff687ce85e45cc728b87612ed546f48c1e7Richard Smith << Use.getUser()->getSourceRange(); 6242815e1a075c74143a0b60a632090ece1dffa5c7cRichard Smith} 6252815e1a075c74143a0b60a632090ece1dffa5c7cRichard Smith 626262d50e1dcf529317da193ad585c11c16281a7acChandler Carruth/// DiagnoseUninitializedUse -- Helper function for diagnosing uses of an 627262d50e1dcf529317da193ad585c11c16281a7acChandler Carruth/// uninitialized variable. This manages the different forms of diagnostic 628262d50e1dcf529317da193ad585c11c16281a7acChandler Carruth/// emitted for particular types of uses. Returns true if the use was diagnosed 6292815e1a075c74143a0b60a632090ece1dffa5c7cRichard Smith/// as a warning. If a particular use is one we omit warnings for, returns 630262d50e1dcf529317da193ad585c11c16281a7acChandler Carruth/// false. 631262d50e1dcf529317da193ad585c11c16281a7acChandler Carruthstatic bool DiagnoseUninitializedUse(Sema &S, const VarDecl *VD, 6322815e1a075c74143a0b60a632090ece1dffa5c7cRichard Smith const UninitUse &Use, 6339e7617220135a6f6226cf09cb242cc1b905aedb4Ted Kremenek bool alwaysReportSelfInit = false) { 6344c4983bbd2904670a25c840b07600f14efbafd7fChandler Carruth 6352815e1a075c74143a0b60a632090ece1dffa5c7cRichard Smith if (const DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(Use.getUser())) { 636f6278e545d9bc09fb5d7579d1123f0a455352627Richard Trieu // Inspect the initializer of the variable declaration which is 637f6278e545d9bc09fb5d7579d1123f0a455352627Richard Trieu // being referenced prior to its initialization. We emit 638f6278e545d9bc09fb5d7579d1123f0a455352627Richard Trieu // specialized diagnostics for self-initialization, and we 639f6278e545d9bc09fb5d7579d1123f0a455352627Richard Trieu // specifically avoid warning about self references which take the 640f6278e545d9bc09fb5d7579d1123f0a455352627Richard Trieu // form of: 641f6278e545d9bc09fb5d7579d1123f0a455352627Richard Trieu // 642f6278e545d9bc09fb5d7579d1123f0a455352627Richard Trieu // int x = x; 643f6278e545d9bc09fb5d7579d1123f0a455352627Richard Trieu // 644f6278e545d9bc09fb5d7579d1123f0a455352627Richard Trieu // This is used to indicate to GCC that 'x' is intentionally left 645f6278e545d9bc09fb5d7579d1123f0a455352627Richard Trieu // uninitialized. Proven code paths which access 'x' in 646f6278e545d9bc09fb5d7579d1123f0a455352627Richard Trieu // an uninitialized state after this will still warn. 647f6278e545d9bc09fb5d7579d1123f0a455352627Richard Trieu if (const Expr *Initializer = VD->getInit()) { 648f6278e545d9bc09fb5d7579d1123f0a455352627Richard Trieu if (!alwaysReportSelfInit && DRE == Initializer->IgnoreParenImpCasts()) 649f6278e545d9bc09fb5d7579d1123f0a455352627Richard Trieu return false; 650f6278e545d9bc09fb5d7579d1123f0a455352627Richard Trieu 651f6278e545d9bc09fb5d7579d1123f0a455352627Richard Trieu ContainsReference CR(S.Context, DRE); 652f6278e545d9bc09fb5d7579d1123f0a455352627Richard Trieu CR.Visit(const_cast<Expr*>(Initializer)); 653f6278e545d9bc09fb5d7579d1123f0a455352627Richard Trieu if (CR.doesContainReference()) { 6544c4983bbd2904670a25c840b07600f14efbafd7fChandler Carruth S.Diag(DRE->getLocStart(), 6554c4983bbd2904670a25c840b07600f14efbafd7fChandler Carruth diag::warn_uninit_self_reference_in_init) 656f6278e545d9bc09fb5d7579d1123f0a455352627Richard Trieu << VD->getDeclName() << VD->getLocation() << DRE->getSourceRange(); 657f6278e545d9bc09fb5d7579d1123f0a455352627Richard Trieu return true; 6584c4983bbd2904670a25c840b07600f14efbafd7fChandler Carruth } 6594c4983bbd2904670a25c840b07600f14efbafd7fChandler Carruth } 660f6278e545d9bc09fb5d7579d1123f0a455352627Richard Trieu 661bdb97ff687ce85e45cc728b87612ed546f48c1e7Richard Smith DiagUninitUse(S, VD, Use, false); 6624c4983bbd2904670a25c840b07600f14efbafd7fChandler Carruth } else { 6632815e1a075c74143a0b60a632090ece1dffa5c7cRichard Smith const BlockExpr *BE = cast<BlockExpr>(Use.getUser()); 664bdb97ff687ce85e45cc728b87612ed546f48c1e7Richard Smith if (VD->getType()->isBlockPointerType() && !VD->hasAttr<BlocksAttr>()) 665bdb97ff687ce85e45cc728b87612ed546f48c1e7Richard Smith S.Diag(BE->getLocStart(), 666bdb97ff687ce85e45cc728b87612ed546f48c1e7Richard Smith diag::warn_uninit_byref_blockvar_captured_by_block) 667a34194f035096dd8dce10574e3a186da968aa211Fariborz Jahanian << VD->getDeclName(); 668bdb97ff687ce85e45cc728b87612ed546f48c1e7Richard Smith else 669bdb97ff687ce85e45cc728b87612ed546f48c1e7Richard Smith DiagUninitUse(S, VD, Use, true); 6704c4983bbd2904670a25c840b07600f14efbafd7fChandler Carruth } 6714c4983bbd2904670a25c840b07600f14efbafd7fChandler Carruth 6724c4983bbd2904670a25c840b07600f14efbafd7fChandler Carruth // Report where the variable was declared when the use wasn't within 6734f4f349208b2b2307454e169ac7b039e989f003fDavid Blaikie // the initializer of that declaration & we didn't already suggest 6744f4f349208b2b2307454e169ac7b039e989f003fDavid Blaikie // an initialization fixit. 675f6278e545d9bc09fb5d7579d1123f0a455352627Richard Trieu if (!SuggestInitializationFixit(S, VD)) 6764c4983bbd2904670a25c840b07600f14efbafd7fChandler Carruth S.Diag(VD->getLocStart(), diag::note_uninit_var_def) 6774c4983bbd2904670a25c840b07600f14efbafd7fChandler Carruth << VD->getDeclName(); 6784c4983bbd2904670a25c840b07600f14efbafd7fChandler Carruth 679262d50e1dcf529317da193ad585c11c16281a7acChandler Carruth return true; 68064fb959beb3a0ecb84a58e6ff82660a7a669f7b8Chandler Carruth} 68164fb959beb3a0ecb84a58e6ff82660a7a669f7b8Chandler Carruth 68266da0abf7ab7cd449bb1d5134b2ef97d9d34d812Alexander Kornienko/// \brief Stores token information for comparing actual tokens with 68366da0abf7ab7cd449bb1d5134b2ef97d9d34d812Alexander Kornienko/// predefined values. Only handles simple tokens and identifiers. 68466da0abf7ab7cd449bb1d5134b2ef97d9d34d812Alexander Kornienkoclass TokenValue { 68566da0abf7ab7cd449bb1d5134b2ef97d9d34d812Alexander Kornienko tok::TokenKind Kind; 68666da0abf7ab7cd449bb1d5134b2ef97d9d34d812Alexander Kornienko IdentifierInfo *II; 68766da0abf7ab7cd449bb1d5134b2ef97d9d34d812Alexander Kornienko 68866da0abf7ab7cd449bb1d5134b2ef97d9d34d812Alexander Kornienkopublic: 68966da0abf7ab7cd449bb1d5134b2ef97d9d34d812Alexander Kornienko TokenValue(tok::TokenKind Kind) : Kind(Kind), II(0) { 69066da0abf7ab7cd449bb1d5134b2ef97d9d34d812Alexander Kornienko assert(Kind != tok::raw_identifier && "Raw identifiers are not supported."); 69166da0abf7ab7cd449bb1d5134b2ef97d9d34d812Alexander Kornienko assert(Kind != tok::identifier && 69266da0abf7ab7cd449bb1d5134b2ef97d9d34d812Alexander Kornienko "Identifiers should be created by TokenValue(IdentifierInfo *)"); 69366da0abf7ab7cd449bb1d5134b2ef97d9d34d812Alexander Kornienko assert(!tok::isLiteral(Kind) && "Literals are not supported."); 69466da0abf7ab7cd449bb1d5134b2ef97d9d34d812Alexander Kornienko assert(!tok::isAnnotation(Kind) && "Annotations are not supported."); 69566da0abf7ab7cd449bb1d5134b2ef97d9d34d812Alexander Kornienko } 69666da0abf7ab7cd449bb1d5134b2ef97d9d34d812Alexander Kornienko TokenValue(IdentifierInfo *II) : Kind(tok::identifier), II(II) {} 69766da0abf7ab7cd449bb1d5134b2ef97d9d34d812Alexander Kornienko bool operator==(const Token &Tok) const { 69866da0abf7ab7cd449bb1d5134b2ef97d9d34d812Alexander Kornienko return Tok.getKind() == Kind && 69966da0abf7ab7cd449bb1d5134b2ef97d9d34d812Alexander Kornienko (!II || II == Tok.getIdentifierInfo()); 70066da0abf7ab7cd449bb1d5134b2ef97d9d34d812Alexander Kornienko } 70166da0abf7ab7cd449bb1d5134b2ef97d9d34d812Alexander Kornienko}; 70266da0abf7ab7cd449bb1d5134b2ef97d9d34d812Alexander Kornienko 70366da0abf7ab7cd449bb1d5134b2ef97d9d34d812Alexander Kornienko/// \brief Compares macro tokens with a specified token value sequence. 70466da0abf7ab7cd449bb1d5134b2ef97d9d34d812Alexander Kornienkostatic bool MacroDefinitionEquals(const MacroInfo *MI, 70566da0abf7ab7cd449bb1d5134b2ef97d9d34d812Alexander Kornienko llvm::ArrayRef<TokenValue> Tokens) { 70666da0abf7ab7cd449bb1d5134b2ef97d9d34d812Alexander Kornienko return Tokens.size() == MI->getNumTokens() && 70766da0abf7ab7cd449bb1d5134b2ef97d9d34d812Alexander Kornienko std::equal(Tokens.begin(), Tokens.end(), MI->tokens_begin()); 70866da0abf7ab7cd449bb1d5134b2ef97d9d34d812Alexander Kornienko} 70966da0abf7ab7cd449bb1d5134b2ef97d9d34d812Alexander Kornienko 71066da0abf7ab7cd449bb1d5134b2ef97d9d34d812Alexander Kornienkostatic std::string GetSuitableSpelling(Preprocessor &PP, SourceLocation L, 71166da0abf7ab7cd449bb1d5134b2ef97d9d34d812Alexander Kornienko llvm::ArrayRef<TokenValue> Tokens, 71266da0abf7ab7cd449bb1d5134b2ef97d9d34d812Alexander Kornienko const char *Spelling) { 71366da0abf7ab7cd449bb1d5134b2ef97d9d34d812Alexander Kornienko SourceManager &SM = PP.getSourceManager(); 71466da0abf7ab7cd449bb1d5134b2ef97d9d34d812Alexander Kornienko SourceLocation BestLocation; 71566da0abf7ab7cd449bb1d5134b2ef97d9d34d812Alexander Kornienko std::string BestSpelling = Spelling; 71666da0abf7ab7cd449bb1d5134b2ef97d9d34d812Alexander Kornienko for (Preprocessor::macro_iterator I = PP.macro_begin(), E = PP.macro_end(); 71766da0abf7ab7cd449bb1d5134b2ef97d9d34d812Alexander Kornienko I != E; ++I) { 71866da0abf7ab7cd449bb1d5134b2ef97d9d34d812Alexander Kornienko if (!I->second->isObjectLike()) 71966da0abf7ab7cd449bb1d5134b2ef97d9d34d812Alexander Kornienko continue; 72066da0abf7ab7cd449bb1d5134b2ef97d9d34d812Alexander Kornienko const MacroInfo *MI = I->second->findDefinitionAtLoc(L, SM); 72166da0abf7ab7cd449bb1d5134b2ef97d9d34d812Alexander Kornienko if (!MI) 72266da0abf7ab7cd449bb1d5134b2ef97d9d34d812Alexander Kornienko continue; 72366da0abf7ab7cd449bb1d5134b2ef97d9d34d812Alexander Kornienko if (!MacroDefinitionEquals(MI, Tokens)) 72466da0abf7ab7cd449bb1d5134b2ef97d9d34d812Alexander Kornienko continue; 72566da0abf7ab7cd449bb1d5134b2ef97d9d34d812Alexander Kornienko SourceLocation Location = I->second->getDefinitionLoc(); 72666da0abf7ab7cd449bb1d5134b2ef97d9d34d812Alexander Kornienko // Choose the macro defined latest. 72766da0abf7ab7cd449bb1d5134b2ef97d9d34d812Alexander Kornienko if (BestLocation.isInvalid() || 72866da0abf7ab7cd449bb1d5134b2ef97d9d34d812Alexander Kornienko (Location.isValid() && 72966da0abf7ab7cd449bb1d5134b2ef97d9d34d812Alexander Kornienko SM.isBeforeInTranslationUnit(BestLocation, Location))) { 73066da0abf7ab7cd449bb1d5134b2ef97d9d34d812Alexander Kornienko BestLocation = Location; 73166da0abf7ab7cd449bb1d5134b2ef97d9d34d812Alexander Kornienko BestSpelling = I->first->getName(); 73266da0abf7ab7cd449bb1d5134b2ef97d9d34d812Alexander Kornienko } 73366da0abf7ab7cd449bb1d5134b2ef97d9d34d812Alexander Kornienko } 73466da0abf7ab7cd449bb1d5134b2ef97d9d34d812Alexander Kornienko return BestSpelling; 73566da0abf7ab7cd449bb1d5134b2ef97d9d34d812Alexander Kornienko} 73666da0abf7ab7cd449bb1d5134b2ef97d9d34d812Alexander Kornienko 737e0d3b4cd2b66f1cef26cacbed5820ab7c22ad5b3Richard Smithnamespace { 738e0d3b4cd2b66f1cef26cacbed5820ab7c22ad5b3Richard Smith class FallthroughMapper : public RecursiveASTVisitor<FallthroughMapper> { 739e0d3b4cd2b66f1cef26cacbed5820ab7c22ad5b3Richard Smith public: 740e0d3b4cd2b66f1cef26cacbed5820ab7c22ad5b3Richard Smith FallthroughMapper(Sema &S) 741e0d3b4cd2b66f1cef26cacbed5820ab7c22ad5b3Richard Smith : FoundSwitchStatements(false), 742e0d3b4cd2b66f1cef26cacbed5820ab7c22ad5b3Richard Smith S(S) { 743e0d3b4cd2b66f1cef26cacbed5820ab7c22ad5b3Richard Smith } 744e0d3b4cd2b66f1cef26cacbed5820ab7c22ad5b3Richard Smith 745e0d3b4cd2b66f1cef26cacbed5820ab7c22ad5b3Richard Smith bool foundSwitchStatements() const { return FoundSwitchStatements; } 746e0d3b4cd2b66f1cef26cacbed5820ab7c22ad5b3Richard Smith 747e0d3b4cd2b66f1cef26cacbed5820ab7c22ad5b3Richard Smith void markFallthroughVisited(const AttributedStmt *Stmt) { 748e0d3b4cd2b66f1cef26cacbed5820ab7c22ad5b3Richard Smith bool Found = FallthroughStmts.erase(Stmt); 749e0d3b4cd2b66f1cef26cacbed5820ab7c22ad5b3Richard Smith assert(Found); 7503bb2994a7de3679fb825f3a36f3dc11ea1daf6a6Kaelyn Uhrain (void)Found; 751e0d3b4cd2b66f1cef26cacbed5820ab7c22ad5b3Richard Smith } 752e0d3b4cd2b66f1cef26cacbed5820ab7c22ad5b3Richard Smith 753e0d3b4cd2b66f1cef26cacbed5820ab7c22ad5b3Richard Smith typedef llvm::SmallPtrSet<const AttributedStmt*, 8> AttrStmts; 754e0d3b4cd2b66f1cef26cacbed5820ab7c22ad5b3Richard Smith 755e0d3b4cd2b66f1cef26cacbed5820ab7c22ad5b3Richard Smith const AttrStmts &getFallthroughStmts() const { 756e0d3b4cd2b66f1cef26cacbed5820ab7c22ad5b3Richard Smith return FallthroughStmts; 757e0d3b4cd2b66f1cef26cacbed5820ab7c22ad5b3Richard Smith } 758e0d3b4cd2b66f1cef26cacbed5820ab7c22ad5b3Richard Smith 759e0d3b4cd2b66f1cef26cacbed5820ab7c22ad5b3Richard Smith bool checkFallThroughIntoBlock(const CFGBlock &B, int &AnnotatedCnt) { 760e0d3b4cd2b66f1cef26cacbed5820ab7c22ad5b3Richard Smith int UnannotatedCnt = 0; 761e0d3b4cd2b66f1cef26cacbed5820ab7c22ad5b3Richard Smith AnnotatedCnt = 0; 762e0d3b4cd2b66f1cef26cacbed5820ab7c22ad5b3Richard Smith 763e0d3b4cd2b66f1cef26cacbed5820ab7c22ad5b3Richard Smith std::deque<const CFGBlock*> BlockQueue; 764e0d3b4cd2b66f1cef26cacbed5820ab7c22ad5b3Richard Smith 765e0d3b4cd2b66f1cef26cacbed5820ab7c22ad5b3Richard Smith std::copy(B.pred_begin(), B.pred_end(), std::back_inserter(BlockQueue)); 766e0d3b4cd2b66f1cef26cacbed5820ab7c22ad5b3Richard Smith 767e0d3b4cd2b66f1cef26cacbed5820ab7c22ad5b3Richard Smith while (!BlockQueue.empty()) { 768e0d3b4cd2b66f1cef26cacbed5820ab7c22ad5b3Richard Smith const CFGBlock *P = BlockQueue.front(); 769e0d3b4cd2b66f1cef26cacbed5820ab7c22ad5b3Richard Smith BlockQueue.pop_front(); 770e0d3b4cd2b66f1cef26cacbed5820ab7c22ad5b3Richard Smith 771e0d3b4cd2b66f1cef26cacbed5820ab7c22ad5b3Richard Smith const Stmt *Term = P->getTerminator(); 772e0d3b4cd2b66f1cef26cacbed5820ab7c22ad5b3Richard Smith if (Term && isa<SwitchStmt>(Term)) 773e0d3b4cd2b66f1cef26cacbed5820ab7c22ad5b3Richard Smith continue; // Switch statement, good. 774e0d3b4cd2b66f1cef26cacbed5820ab7c22ad5b3Richard Smith 775e0d3b4cd2b66f1cef26cacbed5820ab7c22ad5b3Richard Smith const SwitchCase *SW = dyn_cast_or_null<SwitchCase>(P->getLabel()); 776e0d3b4cd2b66f1cef26cacbed5820ab7c22ad5b3Richard Smith if (SW && SW->getSubStmt() == B.getLabel() && P->begin() == P->end()) 777e0d3b4cd2b66f1cef26cacbed5820ab7c22ad5b3Richard Smith continue; // Previous case label has no statements, good. 778e0d3b4cd2b66f1cef26cacbed5820ab7c22ad5b3Richard Smith 779e0d3b4cd2b66f1cef26cacbed5820ab7c22ad5b3Richard Smith if (P->pred_begin() == P->pred_end()) { // The block is unreachable. 780e0d3b4cd2b66f1cef26cacbed5820ab7c22ad5b3Richard Smith // This only catches trivially unreachable blocks. 781e0d3b4cd2b66f1cef26cacbed5820ab7c22ad5b3Richard Smith for (CFGBlock::const_iterator ElIt = P->begin(), ElEnd = P->end(); 782e0d3b4cd2b66f1cef26cacbed5820ab7c22ad5b3Richard Smith ElIt != ElEnd; ++ElIt) { 783e0d3b4cd2b66f1cef26cacbed5820ab7c22ad5b3Richard Smith if (const CFGStmt *CS = ElIt->getAs<CFGStmt>()){ 784e0d3b4cd2b66f1cef26cacbed5820ab7c22ad5b3Richard Smith if (const AttributedStmt *AS = asFallThroughAttr(CS->getStmt())) { 785e0d3b4cd2b66f1cef26cacbed5820ab7c22ad5b3Richard Smith S.Diag(AS->getLocStart(), 786e0d3b4cd2b66f1cef26cacbed5820ab7c22ad5b3Richard Smith diag::warn_fallthrough_attr_unreachable); 787e0d3b4cd2b66f1cef26cacbed5820ab7c22ad5b3Richard Smith markFallthroughVisited(AS); 788e0d3b4cd2b66f1cef26cacbed5820ab7c22ad5b3Richard Smith ++AnnotatedCnt; 789e0d3b4cd2b66f1cef26cacbed5820ab7c22ad5b3Richard Smith } 790e0d3b4cd2b66f1cef26cacbed5820ab7c22ad5b3Richard Smith // Don't care about other unreachable statements. 791e0d3b4cd2b66f1cef26cacbed5820ab7c22ad5b3Richard Smith } 792e0d3b4cd2b66f1cef26cacbed5820ab7c22ad5b3Richard Smith } 793e0d3b4cd2b66f1cef26cacbed5820ab7c22ad5b3Richard Smith // If there are no unreachable statements, this may be a special 794e0d3b4cd2b66f1cef26cacbed5820ab7c22ad5b3Richard Smith // case in CFG: 795e0d3b4cd2b66f1cef26cacbed5820ab7c22ad5b3Richard Smith // case X: { 796e0d3b4cd2b66f1cef26cacbed5820ab7c22ad5b3Richard Smith // A a; // A has a destructor. 797e0d3b4cd2b66f1cef26cacbed5820ab7c22ad5b3Richard Smith // break; 798e0d3b4cd2b66f1cef26cacbed5820ab7c22ad5b3Richard Smith // } 799e0d3b4cd2b66f1cef26cacbed5820ab7c22ad5b3Richard Smith // // <<<< This place is represented by a 'hanging' CFG block. 800e0d3b4cd2b66f1cef26cacbed5820ab7c22ad5b3Richard Smith // case Y: 801e0d3b4cd2b66f1cef26cacbed5820ab7c22ad5b3Richard Smith continue; 802e0d3b4cd2b66f1cef26cacbed5820ab7c22ad5b3Richard Smith } 803e0d3b4cd2b66f1cef26cacbed5820ab7c22ad5b3Richard Smith 804e0d3b4cd2b66f1cef26cacbed5820ab7c22ad5b3Richard Smith const Stmt *LastStmt = getLastStmt(*P); 805e0d3b4cd2b66f1cef26cacbed5820ab7c22ad5b3Richard Smith if (const AttributedStmt *AS = asFallThroughAttr(LastStmt)) { 806e0d3b4cd2b66f1cef26cacbed5820ab7c22ad5b3Richard Smith markFallthroughVisited(AS); 807e0d3b4cd2b66f1cef26cacbed5820ab7c22ad5b3Richard Smith ++AnnotatedCnt; 808e0d3b4cd2b66f1cef26cacbed5820ab7c22ad5b3Richard Smith continue; // Fallthrough annotation, good. 809e0d3b4cd2b66f1cef26cacbed5820ab7c22ad5b3Richard Smith } 810e0d3b4cd2b66f1cef26cacbed5820ab7c22ad5b3Richard Smith 811e0d3b4cd2b66f1cef26cacbed5820ab7c22ad5b3Richard Smith if (!LastStmt) { // This block contains no executable statements. 812e0d3b4cd2b66f1cef26cacbed5820ab7c22ad5b3Richard Smith // Traverse its predecessors. 813e0d3b4cd2b66f1cef26cacbed5820ab7c22ad5b3Richard Smith std::copy(P->pred_begin(), P->pred_end(), 814e0d3b4cd2b66f1cef26cacbed5820ab7c22ad5b3Richard Smith std::back_inserter(BlockQueue)); 815e0d3b4cd2b66f1cef26cacbed5820ab7c22ad5b3Richard Smith continue; 816e0d3b4cd2b66f1cef26cacbed5820ab7c22ad5b3Richard Smith } 817e0d3b4cd2b66f1cef26cacbed5820ab7c22ad5b3Richard Smith 818e0d3b4cd2b66f1cef26cacbed5820ab7c22ad5b3Richard Smith ++UnannotatedCnt; 819e0d3b4cd2b66f1cef26cacbed5820ab7c22ad5b3Richard Smith } 820e0d3b4cd2b66f1cef26cacbed5820ab7c22ad5b3Richard Smith return !!UnannotatedCnt; 821e0d3b4cd2b66f1cef26cacbed5820ab7c22ad5b3Richard Smith } 822e0d3b4cd2b66f1cef26cacbed5820ab7c22ad5b3Richard Smith 823e0d3b4cd2b66f1cef26cacbed5820ab7c22ad5b3Richard Smith // RecursiveASTVisitor setup. 824e0d3b4cd2b66f1cef26cacbed5820ab7c22ad5b3Richard Smith bool shouldWalkTypesOfTypeLocs() const { return false; } 825e0d3b4cd2b66f1cef26cacbed5820ab7c22ad5b3Richard Smith 826e0d3b4cd2b66f1cef26cacbed5820ab7c22ad5b3Richard Smith bool VisitAttributedStmt(AttributedStmt *S) { 827e0d3b4cd2b66f1cef26cacbed5820ab7c22ad5b3Richard Smith if (asFallThroughAttr(S)) 828e0d3b4cd2b66f1cef26cacbed5820ab7c22ad5b3Richard Smith FallthroughStmts.insert(S); 829e0d3b4cd2b66f1cef26cacbed5820ab7c22ad5b3Richard Smith return true; 830e0d3b4cd2b66f1cef26cacbed5820ab7c22ad5b3Richard Smith } 831e0d3b4cd2b66f1cef26cacbed5820ab7c22ad5b3Richard Smith 832e0d3b4cd2b66f1cef26cacbed5820ab7c22ad5b3Richard Smith bool VisitSwitchStmt(SwitchStmt *S) { 833e0d3b4cd2b66f1cef26cacbed5820ab7c22ad5b3Richard Smith FoundSwitchStatements = true; 834e0d3b4cd2b66f1cef26cacbed5820ab7c22ad5b3Richard Smith return true; 835e0d3b4cd2b66f1cef26cacbed5820ab7c22ad5b3Richard Smith } 836e0d3b4cd2b66f1cef26cacbed5820ab7c22ad5b3Richard Smith 837e0d3b4cd2b66f1cef26cacbed5820ab7c22ad5b3Richard Smith private: 838e0d3b4cd2b66f1cef26cacbed5820ab7c22ad5b3Richard Smith 839e0d3b4cd2b66f1cef26cacbed5820ab7c22ad5b3Richard Smith static const AttributedStmt *asFallThroughAttr(const Stmt *S) { 840e0d3b4cd2b66f1cef26cacbed5820ab7c22ad5b3Richard Smith if (const AttributedStmt *AS = dyn_cast_or_null<AttributedStmt>(S)) { 841e0d3b4cd2b66f1cef26cacbed5820ab7c22ad5b3Richard Smith if (hasSpecificAttr<FallThroughAttr>(AS->getAttrs())) 842e0d3b4cd2b66f1cef26cacbed5820ab7c22ad5b3Richard Smith return AS; 843e0d3b4cd2b66f1cef26cacbed5820ab7c22ad5b3Richard Smith } 844e0d3b4cd2b66f1cef26cacbed5820ab7c22ad5b3Richard Smith return 0; 845e0d3b4cd2b66f1cef26cacbed5820ab7c22ad5b3Richard Smith } 846e0d3b4cd2b66f1cef26cacbed5820ab7c22ad5b3Richard Smith 847e0d3b4cd2b66f1cef26cacbed5820ab7c22ad5b3Richard Smith static const Stmt *getLastStmt(const CFGBlock &B) { 848e0d3b4cd2b66f1cef26cacbed5820ab7c22ad5b3Richard Smith if (const Stmt *Term = B.getTerminator()) 849e0d3b4cd2b66f1cef26cacbed5820ab7c22ad5b3Richard Smith return Term; 850e0d3b4cd2b66f1cef26cacbed5820ab7c22ad5b3Richard Smith for (CFGBlock::const_reverse_iterator ElemIt = B.rbegin(), 851e0d3b4cd2b66f1cef26cacbed5820ab7c22ad5b3Richard Smith ElemEnd = B.rend(); 852e0d3b4cd2b66f1cef26cacbed5820ab7c22ad5b3Richard Smith ElemIt != ElemEnd; ++ElemIt) { 853e0d3b4cd2b66f1cef26cacbed5820ab7c22ad5b3Richard Smith if (const CFGStmt *CS = ElemIt->getAs<CFGStmt>()) 854e0d3b4cd2b66f1cef26cacbed5820ab7c22ad5b3Richard Smith return CS->getStmt(); 855e0d3b4cd2b66f1cef26cacbed5820ab7c22ad5b3Richard Smith } 856e0d3b4cd2b66f1cef26cacbed5820ab7c22ad5b3Richard Smith // Workaround to detect a statement thrown out by CFGBuilder: 857e0d3b4cd2b66f1cef26cacbed5820ab7c22ad5b3Richard Smith // case X: {} case Y: 858e0d3b4cd2b66f1cef26cacbed5820ab7c22ad5b3Richard Smith // case X: ; case Y: 859e0d3b4cd2b66f1cef26cacbed5820ab7c22ad5b3Richard Smith if (const SwitchCase *SW = dyn_cast_or_null<SwitchCase>(B.getLabel())) 860e0d3b4cd2b66f1cef26cacbed5820ab7c22ad5b3Richard Smith if (!isa<SwitchCase>(SW->getSubStmt())) 861e0d3b4cd2b66f1cef26cacbed5820ab7c22ad5b3Richard Smith return SW->getSubStmt(); 862e0d3b4cd2b66f1cef26cacbed5820ab7c22ad5b3Richard Smith 863e0d3b4cd2b66f1cef26cacbed5820ab7c22ad5b3Richard Smith return 0; 864e0d3b4cd2b66f1cef26cacbed5820ab7c22ad5b3Richard Smith } 865e0d3b4cd2b66f1cef26cacbed5820ab7c22ad5b3Richard Smith 866e0d3b4cd2b66f1cef26cacbed5820ab7c22ad5b3Richard Smith bool FoundSwitchStatements; 867e0d3b4cd2b66f1cef26cacbed5820ab7c22ad5b3Richard Smith AttrStmts FallthroughStmts; 868e0d3b4cd2b66f1cef26cacbed5820ab7c22ad5b3Richard Smith Sema &S; 869e0d3b4cd2b66f1cef26cacbed5820ab7c22ad5b3Richard Smith }; 870e0d3b4cd2b66f1cef26cacbed5820ab7c22ad5b3Richard Smith} 871e0d3b4cd2b66f1cef26cacbed5820ab7c22ad5b3Richard Smith 8721973634e445d4f1abdeedc2809f2d281929253b6Alexander Kornienkostatic void DiagnoseSwitchLabelsFallthrough(Sema &S, AnalysisDeclContext &AC, 873c2f51cfefd77e9b25f201ecf879343d6d9a45158Sean Hunt bool PerFunction) { 874e0d3b4cd2b66f1cef26cacbed5820ab7c22ad5b3Richard Smith FallthroughMapper FM(S); 875e0d3b4cd2b66f1cef26cacbed5820ab7c22ad5b3Richard Smith FM.TraverseStmt(AC.getBody()); 876e0d3b4cd2b66f1cef26cacbed5820ab7c22ad5b3Richard Smith 877e0d3b4cd2b66f1cef26cacbed5820ab7c22ad5b3Richard Smith if (!FM.foundSwitchStatements()) 878e0d3b4cd2b66f1cef26cacbed5820ab7c22ad5b3Richard Smith return; 879e0d3b4cd2b66f1cef26cacbed5820ab7c22ad5b3Richard Smith 880c2f51cfefd77e9b25f201ecf879343d6d9a45158Sean Hunt if (PerFunction && FM.getFallthroughStmts().empty()) 8811973634e445d4f1abdeedc2809f2d281929253b6Alexander Kornienko return; 8821973634e445d4f1abdeedc2809f2d281929253b6Alexander Kornienko 883e0d3b4cd2b66f1cef26cacbed5820ab7c22ad5b3Richard Smith CFG *Cfg = AC.getCFG(); 884e0d3b4cd2b66f1cef26cacbed5820ab7c22ad5b3Richard Smith 885e0d3b4cd2b66f1cef26cacbed5820ab7c22ad5b3Richard Smith if (!Cfg) 886e0d3b4cd2b66f1cef26cacbed5820ab7c22ad5b3Richard Smith return; 887e0d3b4cd2b66f1cef26cacbed5820ab7c22ad5b3Richard Smith 888e0d3b4cd2b66f1cef26cacbed5820ab7c22ad5b3Richard Smith int AnnotatedCnt; 889e0d3b4cd2b66f1cef26cacbed5820ab7c22ad5b3Richard Smith 890e0d3b4cd2b66f1cef26cacbed5820ab7c22ad5b3Richard Smith for (CFG::reverse_iterator I = Cfg->rbegin(), E = Cfg->rend(); I != E; ++I) { 891e0d3b4cd2b66f1cef26cacbed5820ab7c22ad5b3Richard Smith const CFGBlock &B = **I; 892e0d3b4cd2b66f1cef26cacbed5820ab7c22ad5b3Richard Smith const Stmt *Label = B.getLabel(); 893e0d3b4cd2b66f1cef26cacbed5820ab7c22ad5b3Richard Smith 894e0d3b4cd2b66f1cef26cacbed5820ab7c22ad5b3Richard Smith if (!Label || !isa<SwitchCase>(Label)) 895e0d3b4cd2b66f1cef26cacbed5820ab7c22ad5b3Richard Smith continue; 896e0d3b4cd2b66f1cef26cacbed5820ab7c22ad5b3Richard Smith 897e0d3b4cd2b66f1cef26cacbed5820ab7c22ad5b3Richard Smith if (!FM.checkFallThroughIntoBlock(B, AnnotatedCnt)) 898e0d3b4cd2b66f1cef26cacbed5820ab7c22ad5b3Richard Smith continue; 899e0d3b4cd2b66f1cef26cacbed5820ab7c22ad5b3Richard Smith 9001973634e445d4f1abdeedc2809f2d281929253b6Alexander Kornienko S.Diag(Label->getLocStart(), 901c2f51cfefd77e9b25f201ecf879343d6d9a45158Sean Hunt PerFunction ? diag::warn_unannotated_fallthrough_per_function 902c2f51cfefd77e9b25f201ecf879343d6d9a45158Sean Hunt : diag::warn_unannotated_fallthrough); 903e0d3b4cd2b66f1cef26cacbed5820ab7c22ad5b3Richard Smith 904e0d3b4cd2b66f1cef26cacbed5820ab7c22ad5b3Richard Smith if (!AnnotatedCnt) { 905e0d3b4cd2b66f1cef26cacbed5820ab7c22ad5b3Richard Smith SourceLocation L = Label->getLocStart(); 906e0d3b4cd2b66f1cef26cacbed5820ab7c22ad5b3Richard Smith if (L.isMacroID()) 907e0d3b4cd2b66f1cef26cacbed5820ab7c22ad5b3Richard Smith continue; 908e0d3b4cd2b66f1cef26cacbed5820ab7c22ad5b3Richard Smith if (S.getLangOpts().CPlusPlus0x) { 909a189d8976f1193b788508a1a29b2e9d0aca06acaAlexander Kornienko const Stmt *Term = B.getTerminator(); 910a189d8976f1193b788508a1a29b2e9d0aca06acaAlexander Kornienko if (!(B.empty() && Term && isa<BreakStmt>(Term))) { 91166da0abf7ab7cd449bb1d5134b2ef97d9d34d812Alexander Kornienko Preprocessor &PP = S.getPreprocessor(); 91266da0abf7ab7cd449bb1d5134b2ef97d9d34d812Alexander Kornienko TokenValue Tokens[] = { 91366da0abf7ab7cd449bb1d5134b2ef97d9d34d812Alexander Kornienko tok::l_square, tok::l_square, PP.getIdentifierInfo("clang"), 91466da0abf7ab7cd449bb1d5134b2ef97d9d34d812Alexander Kornienko tok::coloncolon, PP.getIdentifierInfo("fallthrough"), 91566da0abf7ab7cd449bb1d5134b2ef97d9d34d812Alexander Kornienko tok::r_square, tok::r_square 91666da0abf7ab7cd449bb1d5134b2ef97d9d34d812Alexander Kornienko }; 91766da0abf7ab7cd449bb1d5134b2ef97d9d34d812Alexander Kornienko std::string AnnotationSpelling = GetSuitableSpelling( 91866da0abf7ab7cd449bb1d5134b2ef97d9d34d812Alexander Kornienko PP, L, Tokens, "[[clang::fallthrough]]"); 919a189d8976f1193b788508a1a29b2e9d0aca06acaAlexander Kornienko S.Diag(L, diag::note_insert_fallthrough_fixit) << 92066da0abf7ab7cd449bb1d5134b2ef97d9d34d812Alexander Kornienko AnnotationSpelling << 92166da0abf7ab7cd449bb1d5134b2ef97d9d34d812Alexander Kornienko FixItHint::CreateInsertion(L, AnnotationSpelling + "; "); 922a189d8976f1193b788508a1a29b2e9d0aca06acaAlexander Kornienko } 923e0d3b4cd2b66f1cef26cacbed5820ab7c22ad5b3Richard Smith } 924e0d3b4cd2b66f1cef26cacbed5820ab7c22ad5b3Richard Smith S.Diag(L, diag::note_insert_break_fixit) << 925e0d3b4cd2b66f1cef26cacbed5820ab7c22ad5b3Richard Smith FixItHint::CreateInsertion(L, "break; "); 926e0d3b4cd2b66f1cef26cacbed5820ab7c22ad5b3Richard Smith } 927e0d3b4cd2b66f1cef26cacbed5820ab7c22ad5b3Richard Smith } 928e0d3b4cd2b66f1cef26cacbed5820ab7c22ad5b3Richard Smith 929e0d3b4cd2b66f1cef26cacbed5820ab7c22ad5b3Richard Smith const FallthroughMapper::AttrStmts &Fallthroughs = FM.getFallthroughStmts(); 930e0d3b4cd2b66f1cef26cacbed5820ab7c22ad5b3Richard Smith for (FallthroughMapper::AttrStmts::const_iterator I = Fallthroughs.begin(), 931e0d3b4cd2b66f1cef26cacbed5820ab7c22ad5b3Richard Smith E = Fallthroughs.end(); 932e0d3b4cd2b66f1cef26cacbed5820ab7c22ad5b3Richard Smith I != E; ++I) { 933e0d3b4cd2b66f1cef26cacbed5820ab7c22ad5b3Richard Smith S.Diag((*I)->getLocStart(), diag::warn_fallthrough_attr_invalid_placement); 934e0d3b4cd2b66f1cef26cacbed5820ab7c22ad5b3Richard Smith } 935e0d3b4cd2b66f1cef26cacbed5820ab7c22ad5b3Richard Smith 936e0d3b4cd2b66f1cef26cacbed5820ab7c22ad5b3Richard Smith} 937e0d3b4cd2b66f1cef26cacbed5820ab7c22ad5b3Richard Smith 938610068c8cd2321f90e147b12cf794e1f840b6405Ted Kremeneknamespace { 93958b6bdcdeb683a3504f2248a409e1f4e85876ceeJordan Rose typedef std::pair<const Stmt *, 94058b6bdcdeb683a3504f2248a409e1f4e85876ceeJordan Rose sema::FunctionScopeInfo::WeakObjectUseMap::const_iterator> 94158b6bdcdeb683a3504f2248a409e1f4e85876ceeJordan Rose StmtUsesPair; 94258b6bdcdeb683a3504f2248a409e1f4e85876ceeJordan Rose} 94358b6bdcdeb683a3504f2248a409e1f4e85876ceeJordan Rose 94458b6bdcdeb683a3504f2248a409e1f4e85876ceeJordan Rosetemplate<> 94558b6bdcdeb683a3504f2248a409e1f4e85876ceeJordan Roseclass BeforeThanCompare<StmtUsesPair> { 94658b6bdcdeb683a3504f2248a409e1f4e85876ceeJordan Rose const SourceManager &SM; 94758b6bdcdeb683a3504f2248a409e1f4e85876ceeJordan Rose 94858b6bdcdeb683a3504f2248a409e1f4e85876ceeJordan Rosepublic: 94958b6bdcdeb683a3504f2248a409e1f4e85876ceeJordan Rose explicit BeforeThanCompare(const SourceManager &SM) : SM(SM) { } 95058b6bdcdeb683a3504f2248a409e1f4e85876ceeJordan Rose 95158b6bdcdeb683a3504f2248a409e1f4e85876ceeJordan Rose bool operator()(const StmtUsesPair &LHS, const StmtUsesPair &RHS) { 95258b6bdcdeb683a3504f2248a409e1f4e85876ceeJordan Rose return SM.isBeforeInTranslationUnit(LHS.first->getLocStart(), 95358b6bdcdeb683a3504f2248a409e1f4e85876ceeJordan Rose RHS.first->getLocStart()); 95458b6bdcdeb683a3504f2248a409e1f4e85876ceeJordan Rose } 95558b6bdcdeb683a3504f2248a409e1f4e85876ceeJordan Rose}; 95658b6bdcdeb683a3504f2248a409e1f4e85876ceeJordan Rose 95758b6bdcdeb683a3504f2248a409e1f4e85876ceeJordan Rose 95858b6bdcdeb683a3504f2248a409e1f4e85876ceeJordan Rosestatic void diagnoseRepeatedUseOfWeak(Sema &S, 95958b6bdcdeb683a3504f2248a409e1f4e85876ceeJordan Rose const sema::FunctionScopeInfo *CurFn, 96058b6bdcdeb683a3504f2248a409e1f4e85876ceeJordan Rose const Decl *D) { 96158b6bdcdeb683a3504f2248a409e1f4e85876ceeJordan Rose typedef sema::FunctionScopeInfo::WeakObjectProfileTy WeakObjectProfileTy; 96258b6bdcdeb683a3504f2248a409e1f4e85876ceeJordan Rose typedef sema::FunctionScopeInfo::WeakObjectUseMap WeakObjectUseMap; 96358b6bdcdeb683a3504f2248a409e1f4e85876ceeJordan Rose typedef sema::FunctionScopeInfo::WeakUseVector WeakUseVector; 96458b6bdcdeb683a3504f2248a409e1f4e85876ceeJordan Rose 96558b6bdcdeb683a3504f2248a409e1f4e85876ceeJordan Rose const WeakObjectUseMap &WeakMap = CurFn->getWeakObjectUses(); 96658b6bdcdeb683a3504f2248a409e1f4e85876ceeJordan Rose 96758b6bdcdeb683a3504f2248a409e1f4e85876ceeJordan Rose // Extract all weak objects that are referenced more than once. 96858b6bdcdeb683a3504f2248a409e1f4e85876ceeJordan Rose SmallVector<StmtUsesPair, 8> UsesByStmt; 96958b6bdcdeb683a3504f2248a409e1f4e85876ceeJordan Rose for (WeakObjectUseMap::const_iterator I = WeakMap.begin(), E = WeakMap.end(); 97058b6bdcdeb683a3504f2248a409e1f4e85876ceeJordan Rose I != E; ++I) { 97158b6bdcdeb683a3504f2248a409e1f4e85876ceeJordan Rose const WeakUseVector &Uses = I->second; 97258b6bdcdeb683a3504f2248a409e1f4e85876ceeJordan Rose if (Uses.size() <= 1) 97358b6bdcdeb683a3504f2248a409e1f4e85876ceeJordan Rose continue; 97458b6bdcdeb683a3504f2248a409e1f4e85876ceeJordan Rose 97558b6bdcdeb683a3504f2248a409e1f4e85876ceeJordan Rose // Find the first read of the weak object. 97658b6bdcdeb683a3504f2248a409e1f4e85876ceeJordan Rose WeakUseVector::const_iterator UI = Uses.begin(), UE = Uses.end(); 97758b6bdcdeb683a3504f2248a409e1f4e85876ceeJordan Rose for ( ; UI != UE; ++UI) { 97858b6bdcdeb683a3504f2248a409e1f4e85876ceeJordan Rose if (UI->isUnsafe()) 97958b6bdcdeb683a3504f2248a409e1f4e85876ceeJordan Rose break; 98058b6bdcdeb683a3504f2248a409e1f4e85876ceeJordan Rose } 98158b6bdcdeb683a3504f2248a409e1f4e85876ceeJordan Rose 98258b6bdcdeb683a3504f2248a409e1f4e85876ceeJordan Rose // If there were only writes to this object, don't warn. 98358b6bdcdeb683a3504f2248a409e1f4e85876ceeJordan Rose if (UI == UE) 98458b6bdcdeb683a3504f2248a409e1f4e85876ceeJordan Rose continue; 98558b6bdcdeb683a3504f2248a409e1f4e85876ceeJordan Rose 98658b6bdcdeb683a3504f2248a409e1f4e85876ceeJordan Rose UsesByStmt.push_back(StmtUsesPair(UI->getUseExpr(), I)); 98758b6bdcdeb683a3504f2248a409e1f4e85876ceeJordan Rose } 98858b6bdcdeb683a3504f2248a409e1f4e85876ceeJordan Rose 98958b6bdcdeb683a3504f2248a409e1f4e85876ceeJordan Rose if (UsesByStmt.empty()) 99058b6bdcdeb683a3504f2248a409e1f4e85876ceeJordan Rose return; 99158b6bdcdeb683a3504f2248a409e1f4e85876ceeJordan Rose 99258b6bdcdeb683a3504f2248a409e1f4e85876ceeJordan Rose // Sort by first use so that we emit the warnings in a deterministic order. 99358b6bdcdeb683a3504f2248a409e1f4e85876ceeJordan Rose std::sort(UsesByStmt.begin(), UsesByStmt.end(), 99458b6bdcdeb683a3504f2248a409e1f4e85876ceeJordan Rose BeforeThanCompare<StmtUsesPair>(S.getSourceManager())); 99558b6bdcdeb683a3504f2248a409e1f4e85876ceeJordan Rose 99658b6bdcdeb683a3504f2248a409e1f4e85876ceeJordan Rose // Classify the current code body for better warning text. 99758b6bdcdeb683a3504f2248a409e1f4e85876ceeJordan Rose // This enum should stay in sync with the cases in 99858b6bdcdeb683a3504f2248a409e1f4e85876ceeJordan Rose // warn_arc_repeated_use_of_weak and warn_arc_possible_repeated_use_of_weak. 99958b6bdcdeb683a3504f2248a409e1f4e85876ceeJordan Rose // FIXME: Should we use a common classification enum and the same set of 100058b6bdcdeb683a3504f2248a409e1f4e85876ceeJordan Rose // possibilities all throughout Sema? 100158b6bdcdeb683a3504f2248a409e1f4e85876ceeJordan Rose enum { 100258b6bdcdeb683a3504f2248a409e1f4e85876ceeJordan Rose Function, 100358b6bdcdeb683a3504f2248a409e1f4e85876ceeJordan Rose Method, 100458b6bdcdeb683a3504f2248a409e1f4e85876ceeJordan Rose Block, 100558b6bdcdeb683a3504f2248a409e1f4e85876ceeJordan Rose Lambda 100658b6bdcdeb683a3504f2248a409e1f4e85876ceeJordan Rose } FunctionKind; 100758b6bdcdeb683a3504f2248a409e1f4e85876ceeJordan Rose 100858b6bdcdeb683a3504f2248a409e1f4e85876ceeJordan Rose if (isa<sema::BlockScopeInfo>(CurFn)) 100958b6bdcdeb683a3504f2248a409e1f4e85876ceeJordan Rose FunctionKind = Block; 101058b6bdcdeb683a3504f2248a409e1f4e85876ceeJordan Rose else if (isa<sema::LambdaScopeInfo>(CurFn)) 101158b6bdcdeb683a3504f2248a409e1f4e85876ceeJordan Rose FunctionKind = Lambda; 101258b6bdcdeb683a3504f2248a409e1f4e85876ceeJordan Rose else if (isa<ObjCMethodDecl>(D)) 101358b6bdcdeb683a3504f2248a409e1f4e85876ceeJordan Rose FunctionKind = Method; 101458b6bdcdeb683a3504f2248a409e1f4e85876ceeJordan Rose else 101558b6bdcdeb683a3504f2248a409e1f4e85876ceeJordan Rose FunctionKind = Function; 101658b6bdcdeb683a3504f2248a409e1f4e85876ceeJordan Rose 101758b6bdcdeb683a3504f2248a409e1f4e85876ceeJordan Rose // Iterate through the sorted problems and emit warnings for each. 101858b6bdcdeb683a3504f2248a409e1f4e85876ceeJordan Rose for (SmallVectorImpl<StmtUsesPair>::const_iterator I = UsesByStmt.begin(), 101958b6bdcdeb683a3504f2248a409e1f4e85876ceeJordan Rose E = UsesByStmt.end(); 102058b6bdcdeb683a3504f2248a409e1f4e85876ceeJordan Rose I != E; ++I) { 102158b6bdcdeb683a3504f2248a409e1f4e85876ceeJordan Rose const Stmt *FirstRead = I->first; 102258b6bdcdeb683a3504f2248a409e1f4e85876ceeJordan Rose const WeakObjectProfileTy &Key = I->second->first; 102358b6bdcdeb683a3504f2248a409e1f4e85876ceeJordan Rose const WeakUseVector &Uses = I->second->second; 102458b6bdcdeb683a3504f2248a409e1f4e85876ceeJordan Rose 10257a2704800943fbb69207e125d28186278712af36Jordan Rose // For complicated expressions like 'a.b.c' and 'x.b.c', WeakObjectProfileTy 10267a2704800943fbb69207e125d28186278712af36Jordan Rose // may not contain enough information to determine that these are different 10277a2704800943fbb69207e125d28186278712af36Jordan Rose // properties. We can only be 100% sure of a repeated use in certain cases, 10287a2704800943fbb69207e125d28186278712af36Jordan Rose // and we adjust the diagnostic kind accordingly so that the less certain 10297a2704800943fbb69207e125d28186278712af36Jordan Rose // case can be turned off if it is too noisy. 103058b6bdcdeb683a3504f2248a409e1f4e85876ceeJordan Rose unsigned DiagKind; 103158b6bdcdeb683a3504f2248a409e1f4e85876ceeJordan Rose if (Key.isExactProfile()) 103258b6bdcdeb683a3504f2248a409e1f4e85876ceeJordan Rose DiagKind = diag::warn_arc_repeated_use_of_weak; 103358b6bdcdeb683a3504f2248a409e1f4e85876ceeJordan Rose else 103458b6bdcdeb683a3504f2248a409e1f4e85876ceeJordan Rose DiagKind = diag::warn_arc_possible_repeated_use_of_weak; 103558b6bdcdeb683a3504f2248a409e1f4e85876ceeJordan Rose 10367a2704800943fbb69207e125d28186278712af36Jordan Rose // Classify the weak object being accessed for better warning text. 10377a2704800943fbb69207e125d28186278712af36Jordan Rose // This enum should stay in sync with the cases in 10387a2704800943fbb69207e125d28186278712af36Jordan Rose // warn_arc_repeated_use_of_weak and warn_arc_possible_repeated_use_of_weak. 10397a2704800943fbb69207e125d28186278712af36Jordan Rose enum { 10407a2704800943fbb69207e125d28186278712af36Jordan Rose Variable, 10417a2704800943fbb69207e125d28186278712af36Jordan Rose Property, 10427a2704800943fbb69207e125d28186278712af36Jordan Rose ImplicitProperty, 10437a2704800943fbb69207e125d28186278712af36Jordan Rose Ivar 10447a2704800943fbb69207e125d28186278712af36Jordan Rose } ObjectKind; 10457a2704800943fbb69207e125d28186278712af36Jordan Rose 10467a2704800943fbb69207e125d28186278712af36Jordan Rose const NamedDecl *D = Key.getProperty(); 10477a2704800943fbb69207e125d28186278712af36Jordan Rose if (isa<VarDecl>(D)) 10487a2704800943fbb69207e125d28186278712af36Jordan Rose ObjectKind = Variable; 10497a2704800943fbb69207e125d28186278712af36Jordan Rose else if (isa<ObjCPropertyDecl>(D)) 10507a2704800943fbb69207e125d28186278712af36Jordan Rose ObjectKind = Property; 10517a2704800943fbb69207e125d28186278712af36Jordan Rose else if (isa<ObjCMethodDecl>(D)) 10527a2704800943fbb69207e125d28186278712af36Jordan Rose ObjectKind = ImplicitProperty; 10537a2704800943fbb69207e125d28186278712af36Jordan Rose else if (isa<ObjCIvarDecl>(D)) 10547a2704800943fbb69207e125d28186278712af36Jordan Rose ObjectKind = Ivar; 10557a2704800943fbb69207e125d28186278712af36Jordan Rose else 10567a2704800943fbb69207e125d28186278712af36Jordan Rose llvm_unreachable("Unexpected weak object kind!"); 10577a2704800943fbb69207e125d28186278712af36Jordan Rose 105858b6bdcdeb683a3504f2248a409e1f4e85876ceeJordan Rose // Show the first time the object was read. 105958b6bdcdeb683a3504f2248a409e1f4e85876ceeJordan Rose S.Diag(FirstRead->getLocStart(), DiagKind) 10607a2704800943fbb69207e125d28186278712af36Jordan Rose << ObjectKind << D << FunctionKind 106158b6bdcdeb683a3504f2248a409e1f4e85876ceeJordan Rose << FirstRead->getSourceRange(); 106258b6bdcdeb683a3504f2248a409e1f4e85876ceeJordan Rose 106358b6bdcdeb683a3504f2248a409e1f4e85876ceeJordan Rose // Print all the other accesses as notes. 106458b6bdcdeb683a3504f2248a409e1f4e85876ceeJordan Rose for (WeakUseVector::const_iterator UI = Uses.begin(), UE = Uses.end(); 106558b6bdcdeb683a3504f2248a409e1f4e85876ceeJordan Rose UI != UE; ++UI) { 106658b6bdcdeb683a3504f2248a409e1f4e85876ceeJordan Rose if (UI->getUseExpr() == FirstRead) 106758b6bdcdeb683a3504f2248a409e1f4e85876ceeJordan Rose continue; 106858b6bdcdeb683a3504f2248a409e1f4e85876ceeJordan Rose S.Diag(UI->getUseExpr()->getLocStart(), 106958b6bdcdeb683a3504f2248a409e1f4e85876ceeJordan Rose diag::note_arc_weak_also_accessed_here) 107058b6bdcdeb683a3504f2248a409e1f4e85876ceeJordan Rose << UI->getUseExpr()->getSourceRange(); 107158b6bdcdeb683a3504f2248a409e1f4e85876ceeJordan Rose } 107258b6bdcdeb683a3504f2248a409e1f4e85876ceeJordan Rose } 107358b6bdcdeb683a3504f2248a409e1f4e85876ceeJordan Rose} 107458b6bdcdeb683a3504f2248a409e1f4e85876ceeJordan Rose 107558b6bdcdeb683a3504f2248a409e1f4e85876ceeJordan Rose 107658b6bdcdeb683a3504f2248a409e1f4e85876ceeJordan Rosenamespace { 107794b1b4d785bc0f09f6af4be394e59d51f35dda60Ted Kremenekstruct SLocSort { 1078f7bafc77ba12bb1beb665243a0334cd81e024728Ted Kremenek bool operator()(const UninitUse &a, const UninitUse &b) { 10792815e1a075c74143a0b60a632090ece1dffa5c7cRichard Smith // Prefer a more confident report over a less confident one. 10802815e1a075c74143a0b60a632090ece1dffa5c7cRichard Smith if (a.getKind() != b.getKind()) 10812815e1a075c74143a0b60a632090ece1dffa5c7cRichard Smith return a.getKind() > b.getKind(); 10822815e1a075c74143a0b60a632090ece1dffa5c7cRichard Smith SourceLocation aLoc = a.getUser()->getLocStart(); 10832815e1a075c74143a0b60a632090ece1dffa5c7cRichard Smith SourceLocation bLoc = b.getUser()->getLocStart(); 108494b1b4d785bc0f09f6af4be394e59d51f35dda60Ted Kremenek return aLoc.getRawEncoding() < bLoc.getRawEncoding(); 108594b1b4d785bc0f09f6af4be394e59d51f35dda60Ted Kremenek } 108694b1b4d785bc0f09f6af4be394e59d51f35dda60Ted Kremenek}; 108794b1b4d785bc0f09f6af4be394e59d51f35dda60Ted Kremenek 1088610068c8cd2321f90e147b12cf794e1f840b6405Ted Kremenekclass UninitValsDiagReporter : public UninitVariablesHandler { 1089610068c8cd2321f90e147b12cf794e1f840b6405Ted Kremenek Sema &S; 10905f9e272e632e951b1efe824cd16acb4d96077930Chris Lattner typedef SmallVector<UninitUse, 2> UsesVec; 10919e7617220135a6f6226cf09cb242cc1b905aedb4Ted Kremenek typedef llvm::DenseMap<const VarDecl *, std::pair<UsesVec*, bool> > UsesMap; 109294b1b4d785bc0f09f6af4be394e59d51f35dda60Ted Kremenek UsesMap *uses; 109394b1b4d785bc0f09f6af4be394e59d51f35dda60Ted Kremenek 1094610068c8cd2321f90e147b12cf794e1f840b6405Ted Kremenekpublic: 109594b1b4d785bc0f09f6af4be394e59d51f35dda60Ted Kremenek UninitValsDiagReporter(Sema &S) : S(S), uses(0) {} 109694b1b4d785bc0f09f6af4be394e59d51f35dda60Ted Kremenek ~UninitValsDiagReporter() { 109794b1b4d785bc0f09f6af4be394e59d51f35dda60Ted Kremenek flushDiagnostics(); 109894b1b4d785bc0f09f6af4be394e59d51f35dda60Ted Kremenek } 10999e7617220135a6f6226cf09cb242cc1b905aedb4Ted Kremenek 11009e7617220135a6f6226cf09cb242cc1b905aedb4Ted Kremenek std::pair<UsesVec*, bool> &getUses(const VarDecl *vd) { 110194b1b4d785bc0f09f6af4be394e59d51f35dda60Ted Kremenek if (!uses) 110294b1b4d785bc0f09f6af4be394e59d51f35dda60Ted Kremenek uses = new UsesMap(); 11039e7617220135a6f6226cf09cb242cc1b905aedb4Ted Kremenek 11049e7617220135a6f6226cf09cb242cc1b905aedb4Ted Kremenek UsesMap::mapped_type &V = (*uses)[vd]; 11059e7617220135a6f6226cf09cb242cc1b905aedb4Ted Kremenek UsesVec *&vec = V.first; 110694b1b4d785bc0f09f6af4be394e59d51f35dda60Ted Kremenek if (!vec) 110794b1b4d785bc0f09f6af4be394e59d51f35dda60Ted Kremenek vec = new UsesVec(); 110894b1b4d785bc0f09f6af4be394e59d51f35dda60Ted Kremenek 11099e7617220135a6f6226cf09cb242cc1b905aedb4Ted Kremenek return V; 11109e7617220135a6f6226cf09cb242cc1b905aedb4Ted Kremenek } 11119e7617220135a6f6226cf09cb242cc1b905aedb4Ted Kremenek 11122815e1a075c74143a0b60a632090ece1dffa5c7cRichard Smith void handleUseOfUninitVariable(const VarDecl *vd, const UninitUse &use) { 11132815e1a075c74143a0b60a632090ece1dffa5c7cRichard Smith getUses(vd).first->push_back(use); 11149e7617220135a6f6226cf09cb242cc1b905aedb4Ted Kremenek } 11159e7617220135a6f6226cf09cb242cc1b905aedb4Ted Kremenek 11169e7617220135a6f6226cf09cb242cc1b905aedb4Ted Kremenek void handleSelfInit(const VarDecl *vd) { 11179e7617220135a6f6226cf09cb242cc1b905aedb4Ted Kremenek getUses(vd).second = true; 111894b1b4d785bc0f09f6af4be394e59d51f35dda60Ted Kremenek } 111994b1b4d785bc0f09f6af4be394e59d51f35dda60Ted Kremenek 112094b1b4d785bc0f09f6af4be394e59d51f35dda60Ted Kremenek void flushDiagnostics() { 112194b1b4d785bc0f09f6af4be394e59d51f35dda60Ted Kremenek if (!uses) 112294b1b4d785bc0f09f6af4be394e59d51f35dda60Ted Kremenek return; 1123609e3170841dac81c3b7b6b9eccb9c520e42c9b2Ted Kremenek 1124818918855d84e3db1af5a0807070d4995ca2cf75Richard Smith // FIXME: This iteration order, and thus the resulting diagnostic order, 1125818918855d84e3db1af5a0807070d4995ca2cf75Richard Smith // is nondeterministic. 112694b1b4d785bc0f09f6af4be394e59d51f35dda60Ted Kremenek for (UsesMap::iterator i = uses->begin(), e = uses->end(); i != e; ++i) { 112794b1b4d785bc0f09f6af4be394e59d51f35dda60Ted Kremenek const VarDecl *vd = i->first; 11289e7617220135a6f6226cf09cb242cc1b905aedb4Ted Kremenek const UsesMap::mapped_type &V = i->second; 11299e7617220135a6f6226cf09cb242cc1b905aedb4Ted Kremenek 11309e7617220135a6f6226cf09cb242cc1b905aedb4Ted Kremenek UsesVec *vec = V.first; 11319e7617220135a6f6226cf09cb242cc1b905aedb4Ted Kremenek bool hasSelfInit = V.second; 11329e7617220135a6f6226cf09cb242cc1b905aedb4Ted Kremenek 11339e7617220135a6f6226cf09cb242cc1b905aedb4Ted Kremenek // Specially handle the case where we have uses of an uninitialized 11349e7617220135a6f6226cf09cb242cc1b905aedb4Ted Kremenek // variable, but the root cause is an idiomatic self-init. We want 11359e7617220135a6f6226cf09cb242cc1b905aedb4Ted Kremenek // to report the diagnostic at the self-init since that is the root cause. 11360d381810da19dd7677b9a79fca516d298fa5addbMatt Beaumont-Gay if (!vec->empty() && hasSelfInit && hasAlwaysUninitializedUse(vec)) 11372815e1a075c74143a0b60a632090ece1dffa5c7cRichard Smith DiagnoseUninitializedUse(S, vd, 11382815e1a075c74143a0b60a632090ece1dffa5c7cRichard Smith UninitUse(vd->getInit()->IgnoreParenCasts(), 11392815e1a075c74143a0b60a632090ece1dffa5c7cRichard Smith /* isAlwaysUninit */ true), 11400d381810da19dd7677b9a79fca516d298fa5addbMatt Beaumont-Gay /* alwaysReportSelfInit */ true); 11419e7617220135a6f6226cf09cb242cc1b905aedb4Ted Kremenek else { 11429e7617220135a6f6226cf09cb242cc1b905aedb4Ted Kremenek // Sort the uses by their SourceLocations. While not strictly 11439e7617220135a6f6226cf09cb242cc1b905aedb4Ted Kremenek // guaranteed to produce them in line/column order, this will provide 11449e7617220135a6f6226cf09cb242cc1b905aedb4Ted Kremenek // a stable ordering. 11459e7617220135a6f6226cf09cb242cc1b905aedb4Ted Kremenek std::sort(vec->begin(), vec->end(), SLocSort()); 11469e7617220135a6f6226cf09cb242cc1b905aedb4Ted Kremenek 11479e7617220135a6f6226cf09cb242cc1b905aedb4Ted Kremenek for (UsesVec::iterator vi = vec->begin(), ve = vec->end(); vi != ve; 11489e7617220135a6f6226cf09cb242cc1b905aedb4Ted Kremenek ++vi) { 11492815e1a075c74143a0b60a632090ece1dffa5c7cRichard Smith // If we have self-init, downgrade all uses to 'may be uninitialized'. 11502815e1a075c74143a0b60a632090ece1dffa5c7cRichard Smith UninitUse Use = hasSelfInit ? UninitUse(vi->getUser(), false) : *vi; 11512815e1a075c74143a0b60a632090ece1dffa5c7cRichard Smith 11522815e1a075c74143a0b60a632090ece1dffa5c7cRichard Smith if (DiagnoseUninitializedUse(S, vd, Use)) 11539e7617220135a6f6226cf09cb242cc1b905aedb4Ted Kremenek // Skip further diagnostics for this variable. We try to warn only 11549e7617220135a6f6226cf09cb242cc1b905aedb4Ted Kremenek // on the first point at which a variable is used uninitialized. 11559e7617220135a6f6226cf09cb242cc1b905aedb4Ted Kremenek break; 11569e7617220135a6f6226cf09cb242cc1b905aedb4Ted Kremenek } 115764fb959beb3a0ecb84a58e6ff82660a7a669f7b8Chandler Carruth } 11589e7617220135a6f6226cf09cb242cc1b905aedb4Ted Kremenek 11599e7617220135a6f6226cf09cb242cc1b905aedb4Ted Kremenek // Release the uses vector. 116094b1b4d785bc0f09f6af4be394e59d51f35dda60Ted Kremenek delete vec; 116194b1b4d785bc0f09f6af4be394e59d51f35dda60Ted Kremenek } 116294b1b4d785bc0f09f6af4be394e59d51f35dda60Ted Kremenek delete uses; 1163610068c8cd2321f90e147b12cf794e1f840b6405Ted Kremenek } 11640d381810da19dd7677b9a79fca516d298fa5addbMatt Beaumont-Gay 11650d381810da19dd7677b9a79fca516d298fa5addbMatt Beaumont-Gayprivate: 11660d381810da19dd7677b9a79fca516d298fa5addbMatt Beaumont-Gay static bool hasAlwaysUninitializedUse(const UsesVec* vec) { 11670d381810da19dd7677b9a79fca516d298fa5addbMatt Beaumont-Gay for (UsesVec::const_iterator i = vec->begin(), e = vec->end(); i != e; ++i) { 11682815e1a075c74143a0b60a632090ece1dffa5c7cRichard Smith if (i->getKind() == UninitUse::Always) { 11690d381810da19dd7677b9a79fca516d298fa5addbMatt Beaumont-Gay return true; 11700d381810da19dd7677b9a79fca516d298fa5addbMatt Beaumont-Gay } 11710d381810da19dd7677b9a79fca516d298fa5addbMatt Beaumont-Gay } 11720d381810da19dd7677b9a79fca516d298fa5addbMatt Beaumont-Gay return false; 11730d381810da19dd7677b9a79fca516d298fa5addbMatt Beaumont-Gay} 1174610068c8cd2321f90e147b12cf794e1f840b6405Ted Kremenek}; 1175610068c8cd2321f90e147b12cf794e1f840b6405Ted Kremenek} 1176610068c8cd2321f90e147b12cf794e1f840b6405Ted Kremenek 11773ac1fbc303d22af2e11a14023ecee7bd7b7d0bfdCaitlin Sadowski 11783ac1fbc303d22af2e11a14023ecee7bd7b7d0bfdCaitlin Sadowski//===----------------------------------------------------------------------===// 11793ac1fbc303d22af2e11a14023ecee7bd7b7d0bfdCaitlin Sadowski// -Wthread-safety 11803ac1fbc303d22af2e11a14023ecee7bd7b7d0bfdCaitlin Sadowski//===----------------------------------------------------------------------===// 118175f23aeb1c820b49f9faebed63b1cbef76c2c907Caitlin Sadowskinamespace clang { 118275f23aeb1c820b49f9faebed63b1cbef76c2c907Caitlin Sadowskinamespace thread_safety { 11832e5156274b8051217565b557bfa14c80f7990e9cRichard Smithtypedef llvm::SmallVector<PartialDiagnosticAt, 1> OptionalNotes; 11842e5156274b8051217565b557bfa14c80f7990e9cRichard Smithtypedef std::pair<PartialDiagnosticAt, OptionalNotes> DelayedDiag; 1185ecafd309b3ed2ffc6f8ae7eecd1e7eae84b26f81Benjamin Kramertypedef std::list<DelayedDiag> DiagList; 118675f23aeb1c820b49f9faebed63b1cbef76c2c907Caitlin Sadowski 118775f23aeb1c820b49f9faebed63b1cbef76c2c907Caitlin Sadowskistruct SortDiagBySourceLocation { 1188ecafd309b3ed2ffc6f8ae7eecd1e7eae84b26f81Benjamin Kramer SourceManager &SM; 1189ecafd309b3ed2ffc6f8ae7eecd1e7eae84b26f81Benjamin Kramer SortDiagBySourceLocation(SourceManager &SM) : SM(SM) {} 119075f23aeb1c820b49f9faebed63b1cbef76c2c907Caitlin Sadowski 119175f23aeb1c820b49f9faebed63b1cbef76c2c907Caitlin Sadowski bool operator()(const DelayedDiag &left, const DelayedDiag &right) { 119275f23aeb1c820b49f9faebed63b1cbef76c2c907Caitlin Sadowski // Although this call will be slow, this is only called when outputting 119375f23aeb1c820b49f9faebed63b1cbef76c2c907Caitlin Sadowski // multiple warnings. 1194ecafd309b3ed2ffc6f8ae7eecd1e7eae84b26f81Benjamin Kramer return SM.isBeforeInTranslationUnit(left.first.first, right.first.first); 119575f23aeb1c820b49f9faebed63b1cbef76c2c907Caitlin Sadowski } 119675f23aeb1c820b49f9faebed63b1cbef76c2c907Caitlin Sadowski}; 119775f23aeb1c820b49f9faebed63b1cbef76c2c907Caitlin Sadowski 119899ba9e3bd70671f3441fb974895f226a83ce0e66David Blaikienamespace { 119975f23aeb1c820b49f9faebed63b1cbef76c2c907Caitlin Sadowskiclass ThreadSafetyReporter : public clang::thread_safety::ThreadSafetyHandler { 120075f23aeb1c820b49f9faebed63b1cbef76c2c907Caitlin Sadowski Sema &S; 120175f23aeb1c820b49f9faebed63b1cbef76c2c907Caitlin Sadowski DiagList Warnings; 12022e5156274b8051217565b557bfa14c80f7990e9cRichard Smith SourceLocation FunLocation, FunEndLocation; 120375f23aeb1c820b49f9faebed63b1cbef76c2c907Caitlin Sadowski 120475f23aeb1c820b49f9faebed63b1cbef76c2c907Caitlin Sadowski // Helper functions 120575f23aeb1c820b49f9faebed63b1cbef76c2c907Caitlin Sadowski void warnLockMismatch(unsigned DiagID, Name LockName, SourceLocation Loc) { 1206f1ac63702143d84db778d32eb185a77fc97db5f5DeLesley Hutchins // Gracefully handle rare cases when the analysis can't get a more 1207f1ac63702143d84db778d32eb185a77fc97db5f5DeLesley Hutchins // precise source location. 1208f1ac63702143d84db778d32eb185a77fc97db5f5DeLesley Hutchins if (!Loc.isValid()) 1209f1ac63702143d84db778d32eb185a77fc97db5f5DeLesley Hutchins Loc = FunLocation; 12102e5156274b8051217565b557bfa14c80f7990e9cRichard Smith PartialDiagnosticAt Warning(Loc, S.PDiag(DiagID) << LockName); 12112e5156274b8051217565b557bfa14c80f7990e9cRichard Smith Warnings.push_back(DelayedDiag(Warning, OptionalNotes())); 121275f23aeb1c820b49f9faebed63b1cbef76c2c907Caitlin Sadowski } 121375f23aeb1c820b49f9faebed63b1cbef76c2c907Caitlin Sadowski 121475f23aeb1c820b49f9faebed63b1cbef76c2c907Caitlin Sadowski public: 12152e5156274b8051217565b557bfa14c80f7990e9cRichard Smith ThreadSafetyReporter(Sema &S, SourceLocation FL, SourceLocation FEL) 12162e5156274b8051217565b557bfa14c80f7990e9cRichard Smith : S(S), FunLocation(FL), FunEndLocation(FEL) {} 121775f23aeb1c820b49f9faebed63b1cbef76c2c907Caitlin Sadowski 121875f23aeb1c820b49f9faebed63b1cbef76c2c907Caitlin Sadowski /// \brief Emit all buffered diagnostics in order of sourcelocation. 121975f23aeb1c820b49f9faebed63b1cbef76c2c907Caitlin Sadowski /// We need to output diagnostics produced while iterating through 122075f23aeb1c820b49f9faebed63b1cbef76c2c907Caitlin Sadowski /// the lockset in deterministic order, so this function orders diagnostics 122175f23aeb1c820b49f9faebed63b1cbef76c2c907Caitlin Sadowski /// and outputs them. 122275f23aeb1c820b49f9faebed63b1cbef76c2c907Caitlin Sadowski void emitDiagnostics() { 1223ecafd309b3ed2ffc6f8ae7eecd1e7eae84b26f81Benjamin Kramer Warnings.sort(SortDiagBySourceLocation(S.getSourceManager())); 122475f23aeb1c820b49f9faebed63b1cbef76c2c907Caitlin Sadowski for (DiagList::iterator I = Warnings.begin(), E = Warnings.end(); 12252e5156274b8051217565b557bfa14c80f7990e9cRichard Smith I != E; ++I) { 12262e5156274b8051217565b557bfa14c80f7990e9cRichard Smith S.Diag(I->first.first, I->first.second); 12272e5156274b8051217565b557bfa14c80f7990e9cRichard Smith const OptionalNotes &Notes = I->second; 12282e5156274b8051217565b557bfa14c80f7990e9cRichard Smith for (unsigned NoteI = 0, NoteN = Notes.size(); NoteI != NoteN; ++NoteI) 12292e5156274b8051217565b557bfa14c80f7990e9cRichard Smith S.Diag(Notes[NoteI].first, Notes[NoteI].second); 12302e5156274b8051217565b557bfa14c80f7990e9cRichard Smith } 123175f23aeb1c820b49f9faebed63b1cbef76c2c907Caitlin Sadowski } 123275f23aeb1c820b49f9faebed63b1cbef76c2c907Caitlin Sadowski 123399107ebc0a5aea953b736e12757e0919d5249d43Caitlin Sadowski void handleInvalidLockExp(SourceLocation Loc) { 12342e5156274b8051217565b557bfa14c80f7990e9cRichard Smith PartialDiagnosticAt Warning(Loc, 12352e5156274b8051217565b557bfa14c80f7990e9cRichard Smith S.PDiag(diag::warn_cannot_resolve_lock) << Loc); 12362e5156274b8051217565b557bfa14c80f7990e9cRichard Smith Warnings.push_back(DelayedDiag(Warning, OptionalNotes())); 123799107ebc0a5aea953b736e12757e0919d5249d43Caitlin Sadowski } 123875f23aeb1c820b49f9faebed63b1cbef76c2c907Caitlin Sadowski void handleUnmatchedUnlock(Name LockName, SourceLocation Loc) { 123975f23aeb1c820b49f9faebed63b1cbef76c2c907Caitlin Sadowski warnLockMismatch(diag::warn_unlock_but_no_lock, LockName, Loc); 124075f23aeb1c820b49f9faebed63b1cbef76c2c907Caitlin Sadowski } 124175f23aeb1c820b49f9faebed63b1cbef76c2c907Caitlin Sadowski 124275f23aeb1c820b49f9faebed63b1cbef76c2c907Caitlin Sadowski void handleDoubleLock(Name LockName, SourceLocation Loc) { 124375f23aeb1c820b49f9faebed63b1cbef76c2c907Caitlin Sadowski warnLockMismatch(diag::warn_double_lock, LockName, Loc); 124475f23aeb1c820b49f9faebed63b1cbef76c2c907Caitlin Sadowski } 124575f23aeb1c820b49f9faebed63b1cbef76c2c907Caitlin Sadowski 12462e5156274b8051217565b557bfa14c80f7990e9cRichard Smith void handleMutexHeldEndOfScope(Name LockName, SourceLocation LocLocked, 12472e5156274b8051217565b557bfa14c80f7990e9cRichard Smith SourceLocation LocEndOfScope, 12484e4bc75d3570835e13183c66ac08974cdc016007Caitlin Sadowski LockErrorKind LEK){ 12494e4bc75d3570835e13183c66ac08974cdc016007Caitlin Sadowski unsigned DiagID = 0; 12504e4bc75d3570835e13183c66ac08974cdc016007Caitlin Sadowski switch (LEK) { 12514e4bc75d3570835e13183c66ac08974cdc016007Caitlin Sadowski case LEK_LockedSomePredecessors: 12522e5156274b8051217565b557bfa14c80f7990e9cRichard Smith DiagID = diag::warn_lock_some_predecessors; 12534e4bc75d3570835e13183c66ac08974cdc016007Caitlin Sadowski break; 12544e4bc75d3570835e13183c66ac08974cdc016007Caitlin Sadowski case LEK_LockedSomeLoopIterations: 12554e4bc75d3570835e13183c66ac08974cdc016007Caitlin Sadowski DiagID = diag::warn_expecting_lock_held_on_loop; 12564e4bc75d3570835e13183c66ac08974cdc016007Caitlin Sadowski break; 12574e4bc75d3570835e13183c66ac08974cdc016007Caitlin Sadowski case LEK_LockedAtEndOfFunction: 12584e4bc75d3570835e13183c66ac08974cdc016007Caitlin Sadowski DiagID = diag::warn_no_unlock; 12594e4bc75d3570835e13183c66ac08974cdc016007Caitlin Sadowski break; 1260879a4334e4c4cab0c22ba91492ffc2838bbc21fcDeLesley Hutchins case LEK_NotLockedAtEndOfFunction: 1261879a4334e4c4cab0c22ba91492ffc2838bbc21fcDeLesley Hutchins DiagID = diag::warn_expecting_locked; 1262879a4334e4c4cab0c22ba91492ffc2838bbc21fcDeLesley Hutchins break; 12634e4bc75d3570835e13183c66ac08974cdc016007Caitlin Sadowski } 12642e5156274b8051217565b557bfa14c80f7990e9cRichard Smith if (LocEndOfScope.isInvalid()) 12652e5156274b8051217565b557bfa14c80f7990e9cRichard Smith LocEndOfScope = FunEndLocation; 12662e5156274b8051217565b557bfa14c80f7990e9cRichard Smith 12672e5156274b8051217565b557bfa14c80f7990e9cRichard Smith PartialDiagnosticAt Warning(LocEndOfScope, S.PDiag(DiagID) << LockName); 12682e5156274b8051217565b557bfa14c80f7990e9cRichard Smith PartialDiagnosticAt Note(LocLocked, S.PDiag(diag::note_locked_here)); 12692e5156274b8051217565b557bfa14c80f7990e9cRichard Smith Warnings.push_back(DelayedDiag(Warning, OptionalNotes(1, Note))); 127075f23aeb1c820b49f9faebed63b1cbef76c2c907Caitlin Sadowski } 127175f23aeb1c820b49f9faebed63b1cbef76c2c907Caitlin Sadowski 127275f23aeb1c820b49f9faebed63b1cbef76c2c907Caitlin Sadowski 127375f23aeb1c820b49f9faebed63b1cbef76c2c907Caitlin Sadowski void handleExclusiveAndShared(Name LockName, SourceLocation Loc1, 127475f23aeb1c820b49f9faebed63b1cbef76c2c907Caitlin Sadowski SourceLocation Loc2) { 12752e5156274b8051217565b557bfa14c80f7990e9cRichard Smith PartialDiagnosticAt Warning( 12762e5156274b8051217565b557bfa14c80f7990e9cRichard Smith Loc1, S.PDiag(diag::warn_lock_exclusive_and_shared) << LockName); 12772e5156274b8051217565b557bfa14c80f7990e9cRichard Smith PartialDiagnosticAt Note( 12782e5156274b8051217565b557bfa14c80f7990e9cRichard Smith Loc2, S.PDiag(diag::note_lock_exclusive_and_shared) << LockName); 12792e5156274b8051217565b557bfa14c80f7990e9cRichard Smith Warnings.push_back(DelayedDiag(Warning, OptionalNotes(1, Note))); 128075f23aeb1c820b49f9faebed63b1cbef76c2c907Caitlin Sadowski } 128175f23aeb1c820b49f9faebed63b1cbef76c2c907Caitlin Sadowski 128275f23aeb1c820b49f9faebed63b1cbef76c2c907Caitlin Sadowski void handleNoMutexHeld(const NamedDecl *D, ProtectedOperationKind POK, 128375f23aeb1c820b49f9faebed63b1cbef76c2c907Caitlin Sadowski AccessKind AK, SourceLocation Loc) { 1284df8327c28d293cf7c6952b86dba26863235dcc0fCaitlin Sadowski assert((POK == POK_VarAccess || POK == POK_VarDereference) 1285df8327c28d293cf7c6952b86dba26863235dcc0fCaitlin Sadowski && "Only works for variables"); 1286df8327c28d293cf7c6952b86dba26863235dcc0fCaitlin Sadowski unsigned DiagID = POK == POK_VarAccess? 1287df8327c28d293cf7c6952b86dba26863235dcc0fCaitlin Sadowski diag::warn_variable_requires_any_lock: 1288df8327c28d293cf7c6952b86dba26863235dcc0fCaitlin Sadowski diag::warn_var_deref_requires_any_lock; 12892e5156274b8051217565b557bfa14c80f7990e9cRichard Smith PartialDiagnosticAt Warning(Loc, S.PDiag(DiagID) 12905b280f28351bbdc103cc50d3b0f52f92d286fa0aDeLesley Hutchins << D->getNameAsString() << getLockKindFromAccessKind(AK)); 12912e5156274b8051217565b557bfa14c80f7990e9cRichard Smith Warnings.push_back(DelayedDiag(Warning, OptionalNotes())); 129275f23aeb1c820b49f9faebed63b1cbef76c2c907Caitlin Sadowski } 129375f23aeb1c820b49f9faebed63b1cbef76c2c907Caitlin Sadowski 129475f23aeb1c820b49f9faebed63b1cbef76c2c907Caitlin Sadowski void handleMutexNotHeld(const NamedDecl *D, ProtectedOperationKind POK, 12953f0ec5209726641782468bd4c7597e79dda78b15DeLesley Hutchins Name LockName, LockKind LK, SourceLocation Loc, 12963f0ec5209726641782468bd4c7597e79dda78b15DeLesley Hutchins Name *PossibleMatch) { 1297e87158dfbca01577810f301543c3cdcfc955d8b0Caitlin Sadowski unsigned DiagID = 0; 12983f0ec5209726641782468bd4c7597e79dda78b15DeLesley Hutchins if (PossibleMatch) { 12993f0ec5209726641782468bd4c7597e79dda78b15DeLesley Hutchins switch (POK) { 13003f0ec5209726641782468bd4c7597e79dda78b15DeLesley Hutchins case POK_VarAccess: 13013f0ec5209726641782468bd4c7597e79dda78b15DeLesley Hutchins DiagID = diag::warn_variable_requires_lock_precise; 13023f0ec5209726641782468bd4c7597e79dda78b15DeLesley Hutchins break; 13033f0ec5209726641782468bd4c7597e79dda78b15DeLesley Hutchins case POK_VarDereference: 13043f0ec5209726641782468bd4c7597e79dda78b15DeLesley Hutchins DiagID = diag::warn_var_deref_requires_lock_precise; 13053f0ec5209726641782468bd4c7597e79dda78b15DeLesley Hutchins break; 13063f0ec5209726641782468bd4c7597e79dda78b15DeLesley Hutchins case POK_FunctionCall: 13073f0ec5209726641782468bd4c7597e79dda78b15DeLesley Hutchins DiagID = diag::warn_fun_requires_lock_precise; 13083f0ec5209726641782468bd4c7597e79dda78b15DeLesley Hutchins break; 13093f0ec5209726641782468bd4c7597e79dda78b15DeLesley Hutchins } 13103f0ec5209726641782468bd4c7597e79dda78b15DeLesley Hutchins PartialDiagnosticAt Warning(Loc, S.PDiag(DiagID) 13115b280f28351bbdc103cc50d3b0f52f92d286fa0aDeLesley Hutchins << D->getNameAsString() << LockName << LK); 13123f0ec5209726641782468bd4c7597e79dda78b15DeLesley Hutchins PartialDiagnosticAt Note(Loc, S.PDiag(diag::note_found_mutex_near_match) 13133f0ec5209726641782468bd4c7597e79dda78b15DeLesley Hutchins << *PossibleMatch); 13143f0ec5209726641782468bd4c7597e79dda78b15DeLesley Hutchins Warnings.push_back(DelayedDiag(Warning, OptionalNotes(1, Note))); 13153f0ec5209726641782468bd4c7597e79dda78b15DeLesley Hutchins } else { 13163f0ec5209726641782468bd4c7597e79dda78b15DeLesley Hutchins switch (POK) { 13173f0ec5209726641782468bd4c7597e79dda78b15DeLesley Hutchins case POK_VarAccess: 13183f0ec5209726641782468bd4c7597e79dda78b15DeLesley Hutchins DiagID = diag::warn_variable_requires_lock; 13193f0ec5209726641782468bd4c7597e79dda78b15DeLesley Hutchins break; 13203f0ec5209726641782468bd4c7597e79dda78b15DeLesley Hutchins case POK_VarDereference: 13213f0ec5209726641782468bd4c7597e79dda78b15DeLesley Hutchins DiagID = diag::warn_var_deref_requires_lock; 13223f0ec5209726641782468bd4c7597e79dda78b15DeLesley Hutchins break; 13233f0ec5209726641782468bd4c7597e79dda78b15DeLesley Hutchins case POK_FunctionCall: 13243f0ec5209726641782468bd4c7597e79dda78b15DeLesley Hutchins DiagID = diag::warn_fun_requires_lock; 13253f0ec5209726641782468bd4c7597e79dda78b15DeLesley Hutchins break; 13263f0ec5209726641782468bd4c7597e79dda78b15DeLesley Hutchins } 13273f0ec5209726641782468bd4c7597e79dda78b15DeLesley Hutchins PartialDiagnosticAt Warning(Loc, S.PDiag(DiagID) 13285b280f28351bbdc103cc50d3b0f52f92d286fa0aDeLesley Hutchins << D->getNameAsString() << LockName << LK); 13293f0ec5209726641782468bd4c7597e79dda78b15DeLesley Hutchins Warnings.push_back(DelayedDiag(Warning, OptionalNotes())); 133075f23aeb1c820b49f9faebed63b1cbef76c2c907Caitlin Sadowski } 133175f23aeb1c820b49f9faebed63b1cbef76c2c907Caitlin Sadowski } 133275f23aeb1c820b49f9faebed63b1cbef76c2c907Caitlin Sadowski 133375f23aeb1c820b49f9faebed63b1cbef76c2c907Caitlin Sadowski void handleFunExcludesLock(Name FunName, Name LockName, SourceLocation Loc) { 13342e5156274b8051217565b557bfa14c80f7990e9cRichard Smith PartialDiagnosticAt Warning(Loc, 13352e5156274b8051217565b557bfa14c80f7990e9cRichard Smith S.PDiag(diag::warn_fun_excludes_mutex) << FunName << LockName); 13362e5156274b8051217565b557bfa14c80f7990e9cRichard Smith Warnings.push_back(DelayedDiag(Warning, OptionalNotes())); 133775f23aeb1c820b49f9faebed63b1cbef76c2c907Caitlin Sadowski } 133875f23aeb1c820b49f9faebed63b1cbef76c2c907Caitlin Sadowski}; 133975f23aeb1c820b49f9faebed63b1cbef76c2c907Caitlin Sadowski} 134075f23aeb1c820b49f9faebed63b1cbef76c2c907Caitlin Sadowski} 134199ba9e3bd70671f3441fb974895f226a83ce0e66David Blaikie} 134275f23aeb1c820b49f9faebed63b1cbef76c2c907Caitlin Sadowski 1343610068c8cd2321f90e147b12cf794e1f840b6405Ted Kremenek//===----------------------------------------------------------------------===// 1344dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek// AnalysisBasedWarnings - Worker object used by Sema to execute analysis-based 1345dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek// warnings on a function, method, or block. 1346dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek//===----------------------------------------------------------------------===// 1347dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek 1348d064fdc4b7b64ca55b40b70490c79d6f569df78eTed Kremenekclang::sema::AnalysisBasedWarnings::Policy::Policy() { 1349dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek enableCheckFallThrough = 1; 1350d064fdc4b7b64ca55b40b70490c79d6f569df78eTed Kremenek enableCheckUnreachable = 0; 13513ac1fbc303d22af2e11a14023ecee7bd7b7d0bfdCaitlin Sadowski enableThreadSafetyAnalysis = 0; 1352d064fdc4b7b64ca55b40b70490c79d6f569df78eTed Kremenek} 1353dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek 13545d98994c7749312a43ce6adf45537979a98e7afdChandler Carruthclang::sema::AnalysisBasedWarnings::AnalysisBasedWarnings(Sema &s) 13555d98994c7749312a43ce6adf45537979a98e7afdChandler Carruth : S(s), 13565d98994c7749312a43ce6adf45537979a98e7afdChandler Carruth NumFunctionsAnalyzed(0), 135754cf341bd4145e5e31f91c5777fcdaf3f2400537Benjamin Kramer NumFunctionsWithBadCFGs(0), 13585d98994c7749312a43ce6adf45537979a98e7afdChandler Carruth NumCFGBlocks(0), 135954cf341bd4145e5e31f91c5777fcdaf3f2400537Benjamin Kramer MaxCFGBlocksPerFunction(0), 136054cf341bd4145e5e31f91c5777fcdaf3f2400537Benjamin Kramer NumUninitAnalysisFunctions(0), 136154cf341bd4145e5e31f91c5777fcdaf3f2400537Benjamin Kramer NumUninitAnalysisVariables(0), 136254cf341bd4145e5e31f91c5777fcdaf3f2400537Benjamin Kramer MaxUninitAnalysisVariablesPerFunction(0), 136354cf341bd4145e5e31f91c5777fcdaf3f2400537Benjamin Kramer NumUninitAnalysisBlockVisits(0), 136454cf341bd4145e5e31f91c5777fcdaf3f2400537Benjamin Kramer MaxUninitAnalysisBlockVisitsPerFunction(0) { 1365d6471f7c1921c7802804ce3ff6fe9768310f72b9David Blaikie DiagnosticsEngine &D = S.getDiagnostics(); 1366d064fdc4b7b64ca55b40b70490c79d6f569df78eTed Kremenek DefaultPolicy.enableCheckUnreachable = (unsigned) 13670827408865e32789e0ec4b8113a302ccdc531423Argyrios Kyrtzidis (D.getDiagnosticLevel(diag::warn_unreachable, SourceLocation()) != 1368d6471f7c1921c7802804ce3ff6fe9768310f72b9David Blaikie DiagnosticsEngine::Ignored); 13693ac1fbc303d22af2e11a14023ecee7bd7b7d0bfdCaitlin Sadowski DefaultPolicy.enableThreadSafetyAnalysis = (unsigned) 13703ac1fbc303d22af2e11a14023ecee7bd7b7d0bfdCaitlin Sadowski (D.getDiagnosticLevel(diag::warn_double_lock, SourceLocation()) != 1371d6471f7c1921c7802804ce3ff6fe9768310f72b9David Blaikie DiagnosticsEngine::Ignored); 13723ac1fbc303d22af2e11a14023ecee7bd7b7d0bfdCaitlin Sadowski 1373dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek} 1374dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek 1375351ba91eaa6d30e523587b2d7ed676a5172c6e56Ted Kremenekstatic void flushDiagnostics(Sema &S, sema::FunctionScopeInfo *fscope) { 13765f9e272e632e951b1efe824cd16acb4d96077930Chris Lattner for (SmallVectorImpl<sema::PossiblyUnreachableDiag>::iterator 1377351ba91eaa6d30e523587b2d7ed676a5172c6e56Ted Kremenek i = fscope->PossiblyUnreachableDiags.begin(), 1378351ba91eaa6d30e523587b2d7ed676a5172c6e56Ted Kremenek e = fscope->PossiblyUnreachableDiags.end(); 1379351ba91eaa6d30e523587b2d7ed676a5172c6e56Ted Kremenek i != e; ++i) { 1380351ba91eaa6d30e523587b2d7ed676a5172c6e56Ted Kremenek const sema::PossiblyUnreachableDiag &D = *i; 1381351ba91eaa6d30e523587b2d7ed676a5172c6e56Ted Kremenek S.Diag(D.Loc, D.PD); 1382351ba91eaa6d30e523587b2d7ed676a5172c6e56Ted Kremenek } 1383351ba91eaa6d30e523587b2d7ed676a5172c6e56Ted Kremenek} 1384351ba91eaa6d30e523587b2d7ed676a5172c6e56Ted Kremenek 1385d064fdc4b7b64ca55b40b70490c79d6f569df78eTed Kremenekvoid clang::sema:: 1386d064fdc4b7b64ca55b40b70490c79d6f569df78eTed KremenekAnalysisBasedWarnings::IssueWarnings(sema::AnalysisBasedWarnings::Policy P, 1387283a358aecb75e30fcd486f2206f6c03c5e7f11dTed Kremenek sema::FunctionScopeInfo *fscope, 13883ed6fc08a9cd293d012fa49ab2a615e618d7c3faTed Kremenek const Decl *D, const BlockExpr *blkExpr) { 1389d068aabc484c4009282122c6ef26e66e68cfa044Ted Kremenek 1390dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek // We avoid doing analysis-based warnings when there are errors for 1391dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek // two reasons: 1392dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek // (1) The CFGs often can't be constructed (if the body is invalid), so 1393dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek // don't bother trying. 1394dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek // (2) The code already has problems; running the analysis just takes more 1395dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek // time. 1396d6471f7c1921c7802804ce3ff6fe9768310f72b9David Blaikie DiagnosticsEngine &Diags = S.getDiagnostics(); 139799e8192c4c8f1f596f9969e5f2cdafcee64ddaacTed Kremenek 1398d064fdc4b7b64ca55b40b70490c79d6f569df78eTed Kremenek // Do not do any analysis for declarations in system headers if we are 1399d064fdc4b7b64ca55b40b70490c79d6f569df78eTed Kremenek // going to just ignore them. 140099e8192c4c8f1f596f9969e5f2cdafcee64ddaacTed Kremenek if (Diags.getSuppressSystemWarnings() && 1401d064fdc4b7b64ca55b40b70490c79d6f569df78eTed Kremenek S.SourceMgr.isInSystemHeader(D->getLocation())) 1402d064fdc4b7b64ca55b40b70490c79d6f569df78eTed Kremenek return; 1403d064fdc4b7b64ca55b40b70490c79d6f569df78eTed Kremenek 1404e0054f61fd84133eb0d19c19ae9afaf117933274John McCall // For code in dependent contexts, we'll do this at instantiation time. 140523661d3e348c5f44ae89b6848bbc331829bb46f2David Blaikie if (cast<DeclContext>(D)->isDependentContext()) 140623661d3e348c5f44ae89b6848bbc331829bb46f2David Blaikie return; 1407dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek 1408351ba91eaa6d30e523587b2d7ed676a5172c6e56Ted Kremenek if (Diags.hasErrorOccurred() || Diags.hasFatalErrorOccurred()) { 1409351ba91eaa6d30e523587b2d7ed676a5172c6e56Ted Kremenek // Flush out any possibly unreachable diagnostics. 1410351ba91eaa6d30e523587b2d7ed676a5172c6e56Ted Kremenek flushDiagnostics(S, fscope); 1411351ba91eaa6d30e523587b2d7ed676a5172c6e56Ted Kremenek return; 1412351ba91eaa6d30e523587b2d7ed676a5172c6e56Ted Kremenek } 1413351ba91eaa6d30e523587b2d7ed676a5172c6e56Ted Kremenek 1414dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek const Stmt *Body = D->getBody(); 1415dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek assert(Body); 1416dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek 1417d200187bd27f9ad68699693a6e57f9ee3ff260faJordy Rose AnalysisDeclContext AC(/* AnalysisDeclContextManager */ 0, D); 1418bc5cb8a5fe2b88f917d47ceb58b53696a121e57eTed Kremenek 1419dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek // Don't generate EH edges for CallExprs as we'd like to avoid the n^2 1420dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek // explosion for destrutors that can result and the compile time hit. 1421bc5cb8a5fe2b88f917d47ceb58b53696a121e57eTed Kremenek AC.getCFGBuildOptions().PruneTriviallyFalseEdges = true; 1422bc5cb8a5fe2b88f917d47ceb58b53696a121e57eTed Kremenek AC.getCFGBuildOptions().AddEHEdges = false; 1423bc5cb8a5fe2b88f917d47ceb58b53696a121e57eTed Kremenek AC.getCFGBuildOptions().AddInitializers = true; 1424bc5cb8a5fe2b88f917d47ceb58b53696a121e57eTed Kremenek AC.getCFGBuildOptions().AddImplicitDtors = true; 1425faadf48443f8c2fc53d267485d7e0e1bd382fc75Jordan Rose AC.getCFGBuildOptions().AddTemporaryDtors = true; 1426faadf48443f8c2fc53d267485d7e0e1bd382fc75Jordan Rose 14270c8e5a0f70cbdb800d939c1807d05f380b2854d4Ted Kremenek // Force that certain expressions appear as CFGElements in the CFG. This 14280c8e5a0f70cbdb800d939c1807d05f380b2854d4Ted Kremenek // is used to speed up various analyses. 14290c8e5a0f70cbdb800d939c1807d05f380b2854d4Ted Kremenek // FIXME: This isn't the right factoring. This is here for initial 14300c8e5a0f70cbdb800d939c1807d05f380b2854d4Ted Kremenek // prototyping, but we need a way for analyses to say what expressions they 14310c8e5a0f70cbdb800d939c1807d05f380b2854d4Ted Kremenek // expect to always be CFGElements and then fill in the BuildOptions 14320c8e5a0f70cbdb800d939c1807d05f380b2854d4Ted Kremenek // appropriately. This is essentially a layering violation. 14331fa3c0682a52c45c4ad0be3a82d0c85f26657072DeLesley Hutchins if (P.enableCheckUnreachable || P.enableThreadSafetyAnalysis) { 14341fa3c0682a52c45c4ad0be3a82d0c85f26657072DeLesley Hutchins // Unreachable code analysis and thread safety require a linearized CFG. 14350f3b4ca1764cd6d457f511d340fba504f41763c3Ted Kremenek AC.getCFGBuildOptions().setAllAlwaysAdd(); 14360f3b4ca1764cd6d457f511d340fba504f41763c3Ted Kremenek } 14370f3b4ca1764cd6d457f511d340fba504f41763c3Ted Kremenek else { 14380f3b4ca1764cd6d457f511d340fba504f41763c3Ted Kremenek AC.getCFGBuildOptions() 14390f3b4ca1764cd6d457f511d340fba504f41763c3Ted Kremenek .setAlwaysAdd(Stmt::BinaryOperatorClass) 14406cfa78f6bd4e7d5e23366a0907f8f8792366bc4cRichard Smith .setAlwaysAdd(Stmt::CompoundAssignOperatorClass) 14410f3b4ca1764cd6d457f511d340fba504f41763c3Ted Kremenek .setAlwaysAdd(Stmt::BlockExprClass) 14420f3b4ca1764cd6d457f511d340fba504f41763c3Ted Kremenek .setAlwaysAdd(Stmt::CStyleCastExprClass) 14430f3b4ca1764cd6d457f511d340fba504f41763c3Ted Kremenek .setAlwaysAdd(Stmt::DeclRefExprClass) 14440f3b4ca1764cd6d457f511d340fba504f41763c3Ted Kremenek .setAlwaysAdd(Stmt::ImplicitCastExprClass) 1445e0d3b4cd2b66f1cef26cacbed5820ab7c22ad5b3Richard Smith .setAlwaysAdd(Stmt::UnaryOperatorClass) 1446e0d3b4cd2b66f1cef26cacbed5820ab7c22ad5b3Richard Smith .setAlwaysAdd(Stmt::AttributedStmtClass); 14470f3b4ca1764cd6d457f511d340fba504f41763c3Ted Kremenek } 1448bc5cb8a5fe2b88f917d47ceb58b53696a121e57eTed Kremenek 1449bc5cb8a5fe2b88f917d47ceb58b53696a121e57eTed Kremenek // Construct the analysis context with the specified CFG build options. 1450bc5cb8a5fe2b88f917d47ceb58b53696a121e57eTed Kremenek 1451351ba91eaa6d30e523587b2d7ed676a5172c6e56Ted Kremenek // Emit delayed diagnostics. 145223661d3e348c5f44ae89b6848bbc331829bb46f2David Blaikie if (!fscope->PossiblyUnreachableDiags.empty()) { 1453351ba91eaa6d30e523587b2d7ed676a5172c6e56Ted Kremenek bool analyzed = false; 14540d28d360b5559abda755e50b855ba5e59727d9cdTed Kremenek 14550d28d360b5559abda755e50b855ba5e59727d9cdTed Kremenek // Register the expressions with the CFGBuilder. 14565f9e272e632e951b1efe824cd16acb4d96077930Chris Lattner for (SmallVectorImpl<sema::PossiblyUnreachableDiag>::iterator 14570d28d360b5559abda755e50b855ba5e59727d9cdTed Kremenek i = fscope->PossiblyUnreachableDiags.begin(), 14580d28d360b5559abda755e50b855ba5e59727d9cdTed Kremenek e = fscope->PossiblyUnreachableDiags.end(); 14590d28d360b5559abda755e50b855ba5e59727d9cdTed Kremenek i != e; ++i) { 14600d28d360b5559abda755e50b855ba5e59727d9cdTed Kremenek if (const Stmt *stmt = i->stmt) 14610d28d360b5559abda755e50b855ba5e59727d9cdTed Kremenek AC.registerForcedBlockExpression(stmt); 14620d28d360b5559abda755e50b855ba5e59727d9cdTed Kremenek } 14630d28d360b5559abda755e50b855ba5e59727d9cdTed Kremenek 14640d28d360b5559abda755e50b855ba5e59727d9cdTed Kremenek if (AC.getCFG()) { 14650d28d360b5559abda755e50b855ba5e59727d9cdTed Kremenek analyzed = true; 14665f9e272e632e951b1efe824cd16acb4d96077930Chris Lattner for (SmallVectorImpl<sema::PossiblyUnreachableDiag>::iterator 14670d28d360b5559abda755e50b855ba5e59727d9cdTed Kremenek i = fscope->PossiblyUnreachableDiags.begin(), 14680d28d360b5559abda755e50b855ba5e59727d9cdTed Kremenek e = fscope->PossiblyUnreachableDiags.end(); 14690d28d360b5559abda755e50b855ba5e59727d9cdTed Kremenek i != e; ++i) 14700d28d360b5559abda755e50b855ba5e59727d9cdTed Kremenek { 14710d28d360b5559abda755e50b855ba5e59727d9cdTed Kremenek const sema::PossiblyUnreachableDiag &D = *i; 14720d28d360b5559abda755e50b855ba5e59727d9cdTed Kremenek bool processed = false; 14730d28d360b5559abda755e50b855ba5e59727d9cdTed Kremenek if (const Stmt *stmt = i->stmt) { 14740d28d360b5559abda755e50b855ba5e59727d9cdTed Kremenek const CFGBlock *block = AC.getBlockForRegisteredExpression(stmt); 147571b8fb5d4233420d2ed2f150a54ea61431bd8684Eli Friedman CFGReverseBlockReachabilityAnalysis *cra = 147671b8fb5d4233420d2ed2f150a54ea61431bd8684Eli Friedman AC.getCFGReachablityAnalysis(); 147771b8fb5d4233420d2ed2f150a54ea61431bd8684Eli Friedman // FIXME: We should be able to assert that block is non-null, but 147871b8fb5d4233420d2ed2f150a54ea61431bd8684Eli Friedman // the CFG analysis can skip potentially-evaluated expressions in 147971b8fb5d4233420d2ed2f150a54ea61431bd8684Eli Friedman // edge cases; see test/Sema/vla-2.c. 148071b8fb5d4233420d2ed2f150a54ea61431bd8684Eli Friedman if (block && cra) { 1481351ba91eaa6d30e523587b2d7ed676a5172c6e56Ted Kremenek // Can this block be reached from the entrance? 14820d28d360b5559abda755e50b855ba5e59727d9cdTed Kremenek if (cra->isReachable(&AC.getCFG()->getEntry(), block)) 1483351ba91eaa6d30e523587b2d7ed676a5172c6e56Ted Kremenek S.Diag(D.Loc, D.PD); 14840d28d360b5559abda755e50b855ba5e59727d9cdTed Kremenek processed = true; 1485351ba91eaa6d30e523587b2d7ed676a5172c6e56Ted Kremenek } 14860d28d360b5559abda755e50b855ba5e59727d9cdTed Kremenek } 14870d28d360b5559abda755e50b855ba5e59727d9cdTed Kremenek if (!processed) { 14880d28d360b5559abda755e50b855ba5e59727d9cdTed Kremenek // Emit the warning anyway if we cannot map to a basic block. 14890d28d360b5559abda755e50b855ba5e59727d9cdTed Kremenek S.Diag(D.Loc, D.PD); 1490351ba91eaa6d30e523587b2d7ed676a5172c6e56Ted Kremenek } 1491351ba91eaa6d30e523587b2d7ed676a5172c6e56Ted Kremenek } 14920d28d360b5559abda755e50b855ba5e59727d9cdTed Kremenek } 1493351ba91eaa6d30e523587b2d7ed676a5172c6e56Ted Kremenek 1494351ba91eaa6d30e523587b2d7ed676a5172c6e56Ted Kremenek if (!analyzed) 1495351ba91eaa6d30e523587b2d7ed676a5172c6e56Ted Kremenek flushDiagnostics(S, fscope); 1496351ba91eaa6d30e523587b2d7ed676a5172c6e56Ted Kremenek } 1497351ba91eaa6d30e523587b2d7ed676a5172c6e56Ted Kremenek 1498351ba91eaa6d30e523587b2d7ed676a5172c6e56Ted Kremenek 1499dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek // Warning: check missing 'return' 150023661d3e348c5f44ae89b6848bbc331829bb46f2David Blaikie if (P.enableCheckFallThrough) { 1501dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek const CheckFallThroughDiagnostics &CD = 1502dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek (isa<BlockDecl>(D) ? CheckFallThroughDiagnostics::MakeForBlock() 1503793cd1c4cdfaafc52e2c2ad9dae959befe4bb166Douglas Gregor : (isa<CXXMethodDecl>(D) && 1504793cd1c4cdfaafc52e2c2ad9dae959befe4bb166Douglas Gregor cast<CXXMethodDecl>(D)->getOverloadedOperator() == OO_Call && 1505793cd1c4cdfaafc52e2c2ad9dae959befe4bb166Douglas Gregor cast<CXXMethodDecl>(D)->getParent()->isLambda()) 1506793cd1c4cdfaafc52e2c2ad9dae959befe4bb166Douglas Gregor ? CheckFallThroughDiagnostics::MakeForLambda() 1507793cd1c4cdfaafc52e2c2ad9dae959befe4bb166Douglas Gregor : CheckFallThroughDiagnostics::MakeForFunction(D)); 15083ed6fc08a9cd293d012fa49ab2a615e618d7c3faTed Kremenek CheckFallThroughForBody(S, D, Body, blkExpr, CD, AC); 1509dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek } 1510dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek 1511dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek // Warning: check for unreachable code 15125dfee06daa359bbe0f3c9de055b8a02d61a05173Ted Kremenek if (P.enableCheckUnreachable) { 15135dfee06daa359bbe0f3c9de055b8a02d61a05173Ted Kremenek // Only check for unreachable code on non-template instantiations. 15145dfee06daa359bbe0f3c9de055b8a02d61a05173Ted Kremenek // Different template instantiations can effectively change the control-flow 15155dfee06daa359bbe0f3c9de055b8a02d61a05173Ted Kremenek // and it is very difficult to prove that a snippet of code in a template 15165dfee06daa359bbe0f3c9de055b8a02d61a05173Ted Kremenek // is unreachable for all instantiations. 151775df4eeede7b91c22c1d63fafd4dd4142844e3b9Ted Kremenek bool isTemplateInstantiation = false; 151875df4eeede7b91c22c1d63fafd4dd4142844e3b9Ted Kremenek if (const FunctionDecl *Function = dyn_cast<FunctionDecl>(D)) 151975df4eeede7b91c22c1d63fafd4dd4142844e3b9Ted Kremenek isTemplateInstantiation = Function->isTemplateInstantiation(); 152075df4eeede7b91c22c1d63fafd4dd4142844e3b9Ted Kremenek if (!isTemplateInstantiation) 15215dfee06daa359bbe0f3c9de055b8a02d61a05173Ted Kremenek CheckUnreachable(S, AC); 15225dfee06daa359bbe0f3c9de055b8a02d61a05173Ted Kremenek } 152375f23aeb1c820b49f9faebed63b1cbef76c2c907Caitlin Sadowski 15243ac1fbc303d22af2e11a14023ecee7bd7b7d0bfdCaitlin Sadowski // Check for thread safety violations 152523661d3e348c5f44ae89b6848bbc331829bb46f2David Blaikie if (P.enableThreadSafetyAnalysis) { 1526f1ac63702143d84db778d32eb185a77fc97db5f5DeLesley Hutchins SourceLocation FL = AC.getDecl()->getLocation(); 15272e5156274b8051217565b557bfa14c80f7990e9cRichard Smith SourceLocation FEL = AC.getDecl()->getLocEnd(); 15282e5156274b8051217565b557bfa14c80f7990e9cRichard Smith thread_safety::ThreadSafetyReporter Reporter(S, FL, FEL); 152975f23aeb1c820b49f9faebed63b1cbef76c2c907Caitlin Sadowski thread_safety::runThreadSafetyAnalysis(AC, Reporter); 153075f23aeb1c820b49f9faebed63b1cbef76c2c907Caitlin Sadowski Reporter.emitDiagnostics(); 153175f23aeb1c820b49f9faebed63b1cbef76c2c907Caitlin Sadowski } 15323ac1fbc303d22af2e11a14023ecee7bd7b7d0bfdCaitlin Sadowski 1533a8c17a5babab35f2db26bf218e7571d1af4afedfTed Kremenek if (Diags.getDiagnosticLevel(diag::warn_uninit_var, D->getLocStart()) 1534d6471f7c1921c7802804ce3ff6fe9768310f72b9David Blaikie != DiagnosticsEngine::Ignored || 15352815e1a075c74143a0b60a632090ece1dffa5c7cRichard Smith Diags.getDiagnosticLevel(diag::warn_sometimes_uninit_var,D->getLocStart()) 15362815e1a075c74143a0b60a632090ece1dffa5c7cRichard Smith != DiagnosticsEngine::Ignored || 153776709bf816e5e1b70b859bb607cf3ee91db12b76Ted Kremenek Diags.getDiagnosticLevel(diag::warn_maybe_uninit_var, D->getLocStart()) 1538d6471f7c1921c7802804ce3ff6fe9768310f72b9David Blaikie != DiagnosticsEngine::Ignored) { 1539c5e43c19ddb40b8a1371291f73ae66fe54951ca5Ted Kremenek if (CFG *cfg = AC.getCFG()) { 1540c21fed361c11f13db345cba69101578578d8fb79Ted Kremenek UninitValsDiagReporter reporter(S); 154157080fbac1ccce702255423335d52e81bcf17b6bFariborz Jahanian UninitVariablesAnalysisStats stats; 154212efd57ee474c06880a7434ece21a39ac3f34e24Benjamin Kramer std::memset(&stats, 0, sizeof(UninitVariablesAnalysisStats)); 1543a8c17a5babab35f2db26bf218e7571d1af4afedfTed Kremenek runUninitializedVariablesAnalysis(*cast<DeclContext>(D), *cfg, AC, 15445d98994c7749312a43ce6adf45537979a98e7afdChandler Carruth reporter, stats); 15455d98994c7749312a43ce6adf45537979a98e7afdChandler Carruth 15465d98994c7749312a43ce6adf45537979a98e7afdChandler Carruth if (S.CollectStats && stats.NumVariablesAnalyzed > 0) { 15475d98994c7749312a43ce6adf45537979a98e7afdChandler Carruth ++NumUninitAnalysisFunctions; 15485d98994c7749312a43ce6adf45537979a98e7afdChandler Carruth NumUninitAnalysisVariables += stats.NumVariablesAnalyzed; 15495d98994c7749312a43ce6adf45537979a98e7afdChandler Carruth NumUninitAnalysisBlockVisits += stats.NumBlockVisits; 15505d98994c7749312a43ce6adf45537979a98e7afdChandler Carruth MaxUninitAnalysisVariablesPerFunction = 15515d98994c7749312a43ce6adf45537979a98e7afdChandler Carruth std::max(MaxUninitAnalysisVariablesPerFunction, 15525d98994c7749312a43ce6adf45537979a98e7afdChandler Carruth stats.NumVariablesAnalyzed); 15535d98994c7749312a43ce6adf45537979a98e7afdChandler Carruth MaxUninitAnalysisBlockVisitsPerFunction = 15545d98994c7749312a43ce6adf45537979a98e7afdChandler Carruth std::max(MaxUninitAnalysisBlockVisitsPerFunction, 15555d98994c7749312a43ce6adf45537979a98e7afdChandler Carruth stats.NumBlockVisits); 15565d98994c7749312a43ce6adf45537979a98e7afdChandler Carruth } 15575d98994c7749312a43ce6adf45537979a98e7afdChandler Carruth } 15585d98994c7749312a43ce6adf45537979a98e7afdChandler Carruth } 15595d98994c7749312a43ce6adf45537979a98e7afdChandler Carruth 15601973634e445d4f1abdeedc2809f2d281929253b6Alexander Kornienko bool FallThroughDiagFull = 15611973634e445d4f1abdeedc2809f2d281929253b6Alexander Kornienko Diags.getDiagnosticLevel(diag::warn_unannotated_fallthrough, 15621973634e445d4f1abdeedc2809f2d281929253b6Alexander Kornienko D->getLocStart()) != DiagnosticsEngine::Ignored; 1563c2f51cfefd77e9b25f201ecf879343d6d9a45158Sean Hunt bool FallThroughDiagPerFunction = 1564c2f51cfefd77e9b25f201ecf879343d6d9a45158Sean Hunt Diags.getDiagnosticLevel(diag::warn_unannotated_fallthrough_per_function, 15651973634e445d4f1abdeedc2809f2d281929253b6Alexander Kornienko D->getLocStart()) != DiagnosticsEngine::Ignored; 1566c2f51cfefd77e9b25f201ecf879343d6d9a45158Sean Hunt if (FallThroughDiagFull || FallThroughDiagPerFunction) { 15671973634e445d4f1abdeedc2809f2d281929253b6Alexander Kornienko DiagnoseSwitchLabelsFallthrough(S, AC, !FallThroughDiagFull); 1568e0d3b4cd2b66f1cef26cacbed5820ab7c22ad5b3Richard Smith } 1569e0d3b4cd2b66f1cef26cacbed5820ab7c22ad5b3Richard Smith 157058b6bdcdeb683a3504f2248a409e1f4e85876ceeJordan Rose if (S.getLangOpts().ObjCARCWeak && 157158b6bdcdeb683a3504f2248a409e1f4e85876ceeJordan Rose Diags.getDiagnosticLevel(diag::warn_arc_repeated_use_of_weak, 157258b6bdcdeb683a3504f2248a409e1f4e85876ceeJordan Rose D->getLocStart()) != DiagnosticsEngine::Ignored) 157358b6bdcdeb683a3504f2248a409e1f4e85876ceeJordan Rose diagnoseRepeatedUseOfWeak(S, fscope, D); 157458b6bdcdeb683a3504f2248a409e1f4e85876ceeJordan Rose 15755d98994c7749312a43ce6adf45537979a98e7afdChandler Carruth // Collect statistics about the CFG if it was built. 15765d98994c7749312a43ce6adf45537979a98e7afdChandler Carruth if (S.CollectStats && AC.isCFGBuilt()) { 15775d98994c7749312a43ce6adf45537979a98e7afdChandler Carruth ++NumFunctionsAnalyzed; 15785d98994c7749312a43ce6adf45537979a98e7afdChandler Carruth if (CFG *cfg = AC.getCFG()) { 15795d98994c7749312a43ce6adf45537979a98e7afdChandler Carruth // If we successfully built a CFG for this context, record some more 15805d98994c7749312a43ce6adf45537979a98e7afdChandler Carruth // detail information about it. 15813ea4c49709c5bba5f8b16c6ceb725d9b9a1c48c6Chandler Carruth NumCFGBlocks += cfg->getNumBlockIDs(); 15825d98994c7749312a43ce6adf45537979a98e7afdChandler Carruth MaxCFGBlocksPerFunction = std::max(MaxCFGBlocksPerFunction, 15833ea4c49709c5bba5f8b16c6ceb725d9b9a1c48c6Chandler Carruth cfg->getNumBlockIDs()); 15845d98994c7749312a43ce6adf45537979a98e7afdChandler Carruth } else { 15855d98994c7749312a43ce6adf45537979a98e7afdChandler Carruth ++NumFunctionsWithBadCFGs; 1586610068c8cd2321f90e147b12cf794e1f840b6405Ted Kremenek } 1587610068c8cd2321f90e147b12cf794e1f840b6405Ted Kremenek } 1588dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek} 15895d98994c7749312a43ce6adf45537979a98e7afdChandler Carruth 15905d98994c7749312a43ce6adf45537979a98e7afdChandler Carruthvoid clang::sema::AnalysisBasedWarnings::PrintStats() const { 15915d98994c7749312a43ce6adf45537979a98e7afdChandler Carruth llvm::errs() << "\n*** Analysis Based Warnings Stats:\n"; 15925d98994c7749312a43ce6adf45537979a98e7afdChandler Carruth 15935d98994c7749312a43ce6adf45537979a98e7afdChandler Carruth unsigned NumCFGsBuilt = NumFunctionsAnalyzed - NumFunctionsWithBadCFGs; 15945d98994c7749312a43ce6adf45537979a98e7afdChandler Carruth unsigned AvgCFGBlocksPerFunction = 15955d98994c7749312a43ce6adf45537979a98e7afdChandler Carruth !NumCFGsBuilt ? 0 : NumCFGBlocks/NumCFGsBuilt; 15965d98994c7749312a43ce6adf45537979a98e7afdChandler Carruth llvm::errs() << NumFunctionsAnalyzed << " functions analyzed (" 15975d98994c7749312a43ce6adf45537979a98e7afdChandler Carruth << NumFunctionsWithBadCFGs << " w/o CFGs).\n" 15985d98994c7749312a43ce6adf45537979a98e7afdChandler Carruth << " " << NumCFGBlocks << " CFG blocks built.\n" 15995d98994c7749312a43ce6adf45537979a98e7afdChandler Carruth << " " << AvgCFGBlocksPerFunction 16005d98994c7749312a43ce6adf45537979a98e7afdChandler Carruth << " average CFG blocks per function.\n" 16015d98994c7749312a43ce6adf45537979a98e7afdChandler Carruth << " " << MaxCFGBlocksPerFunction 16025d98994c7749312a43ce6adf45537979a98e7afdChandler Carruth << " max CFG blocks per function.\n"; 16035d98994c7749312a43ce6adf45537979a98e7afdChandler Carruth 16045d98994c7749312a43ce6adf45537979a98e7afdChandler Carruth unsigned AvgUninitVariablesPerFunction = !NumUninitAnalysisFunctions ? 0 16055d98994c7749312a43ce6adf45537979a98e7afdChandler Carruth : NumUninitAnalysisVariables/NumUninitAnalysisFunctions; 16065d98994c7749312a43ce6adf45537979a98e7afdChandler Carruth unsigned AvgUninitBlockVisitsPerFunction = !NumUninitAnalysisFunctions ? 0 16075d98994c7749312a43ce6adf45537979a98e7afdChandler Carruth : NumUninitAnalysisBlockVisits/NumUninitAnalysisFunctions; 16085d98994c7749312a43ce6adf45537979a98e7afdChandler Carruth llvm::errs() << NumUninitAnalysisFunctions 16095d98994c7749312a43ce6adf45537979a98e7afdChandler Carruth << " functions analyzed for uninitialiazed variables\n" 16105d98994c7749312a43ce6adf45537979a98e7afdChandler Carruth << " " << NumUninitAnalysisVariables << " variables analyzed.\n" 16115d98994c7749312a43ce6adf45537979a98e7afdChandler Carruth << " " << AvgUninitVariablesPerFunction 16125d98994c7749312a43ce6adf45537979a98e7afdChandler Carruth << " average variables per function.\n" 16135d98994c7749312a43ce6adf45537979a98e7afdChandler Carruth << " " << MaxUninitAnalysisVariablesPerFunction 16145d98994c7749312a43ce6adf45537979a98e7afdChandler Carruth << " max variables per function.\n" 16155d98994c7749312a43ce6adf45537979a98e7afdChandler Carruth << " " << NumUninitAnalysisBlockVisits << " block visits.\n" 16165d98994c7749312a43ce6adf45537979a98e7afdChandler Carruth << " " << AvgUninitBlockVisitsPerFunction 16175d98994c7749312a43ce6adf45537979a98e7afdChandler Carruth << " average block visits per function.\n" 16185d98994c7749312a43ce6adf45537979a98e7afdChandler Carruth << " " << MaxUninitAnalysisBlockVisitsPerFunction 16195d98994c7749312a43ce6adf45537979a98e7afdChandler Carruth << " max block visits per function.\n"; 16205d98994c7749312a43ce6adf45537979a98e7afdChandler Carruth} 1621