AnalysisBasedWarnings.cpp revision 7348454025693dd20a411c2bcaabd4460cb87559
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" 17384aff8b94bb0d1ad6c5667b90621e5699815bb2John McCall#include "clang/AST/DeclCXX.h" 1855fc873017f10f6f566b182b70f6fc22aefa3464Chandler Carruth#include "clang/AST/DeclObjC.h" 196f41715df2c6a31c0c3ab3088b8cd18a3c8321b8Ted Kremenek#include "clang/AST/EvaluatedExprVisitor.h" 2055fc873017f10f6f566b182b70f6fc22aefa3464Chandler Carruth#include "clang/AST/ExprCXX.h" 2155fc873017f10f6f566b182b70f6fc22aefa3464Chandler Carruth#include "clang/AST/ExprObjC.h" 22b5cd1220dd650a358622241237aa595c5d675506Jordan Rose#include "clang/AST/ParentMap.h" 23e0d3b4cd2b66f1cef26cacbed5820ab7c22ad5b3Richard Smith#include "clang/AST/RecursiveASTVisitor.h" 2455fc873017f10f6f566b182b70f6fc22aefa3464Chandler Carruth#include "clang/AST/StmtCXX.h" 2555fc873017f10f6f566b182b70f6fc22aefa3464Chandler Carruth#include "clang/AST/StmtObjC.h" 2655fc873017f10f6f566b182b70f6fc22aefa3464Chandler Carruth#include "clang/AST/StmtVisitor.h" 27351ba91eaa6d30e523587b2d7ed676a5172c6e56Ted Kremenek#include "clang/Analysis/Analyses/CFGReachabilityAnalysis.h" 2855fc873017f10f6f566b182b70f6fc22aefa3464Chandler Carruth#include "clang/Analysis/Analyses/ReachableCode.h" 29402aa0698fec81e574818a0a6c2000fac0b2c4c6Caitlin Sadowski#include "clang/Analysis/Analyses/ThreadSafety.h" 306f34213f8d6ae8c77685b53664527e39bfaaca3bTed Kremenek#include "clang/Analysis/Analyses/UninitializedValues.h" 3155fc873017f10f6f566b182b70f6fc22aefa3464Chandler Carruth#include "clang/Analysis/AnalysisContext.h" 3255fc873017f10f6f566b182b70f6fc22aefa3464Chandler Carruth#include "clang/Analysis/CFG.h" 3355fc873017f10f6f566b182b70f6fc22aefa3464Chandler Carruth#include "clang/Analysis/CFGStmtMap.h" 3455fc873017f10f6f566b182b70f6fc22aefa3464Chandler Carruth#include "clang/Basic/SourceLocation.h" 3555fc873017f10f6f566b182b70f6fc22aefa3464Chandler Carruth#include "clang/Basic/SourceManager.h" 3655fc873017f10f6f566b182b70f6fc22aefa3464Chandler Carruth#include "clang/Lex/Lexer.h" 3755fc873017f10f6f566b182b70f6fc22aefa3464Chandler Carruth#include "clang/Lex/Preprocessor.h" 3855fc873017f10f6f566b182b70f6fc22aefa3464Chandler Carruth#include "clang/Sema/ScopeInfo.h" 3955fc873017f10f6f566b182b70f6fc22aefa3464Chandler Carruth#include "clang/Sema/SemaInternal.h" 4066da0abf7ab7cd449bb1d5134b2ef97d9d34d812Alexander Kornienko#include "llvm/ADT/ArrayRef.h" 41dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek#include "llvm/ADT/BitVector.h" 423ac1fbc303d22af2e11a14023ecee7bd7b7d0bfdCaitlin Sadowski#include "llvm/ADT/FoldingSet.h" 433ac1fbc303d22af2e11a14023ecee7bd7b7d0bfdCaitlin Sadowski#include "llvm/ADT/ImmutableMap.h" 443285c78041f80a26f6a947e2922e15c4af6e00bbEnea Zaffanella#include "llvm/ADT/MapVector.h" 453ac1fbc303d22af2e11a14023ecee7bd7b7d0bfdCaitlin Sadowski#include "llvm/ADT/PostOrderIterator.h" 461952354bd376062c3ab3d328c0fc6c36530c9309Dmitri Gribenko#include "llvm/ADT/SmallString.h" 473ac1fbc303d22af2e11a14023ecee7bd7b7d0bfdCaitlin Sadowski#include "llvm/ADT/SmallVector.h" 4875f23aeb1c820b49f9faebed63b1cbef76c2c907Caitlin Sadowski#include "llvm/ADT/StringRef.h" 49dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek#include "llvm/Support/Casting.h" 503ac1fbc303d22af2e11a14023ecee7bd7b7d0bfdCaitlin Sadowski#include <algorithm> 5155fc873017f10f6f566b182b70f6fc22aefa3464Chandler Carruth#include <deque> 52e0d3b4cd2b66f1cef26cacbed5820ab7c22ad5b3Richard Smith#include <iterator> 533ac1fbc303d22af2e11a14023ecee7bd7b7d0bfdCaitlin Sadowski#include <vector> 54dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek 55dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenekusing namespace clang; 56dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek 57dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek//===----------------------------------------------------------------------===// 58dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek// Unreachable code analysis. 59dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek//===----------------------------------------------------------------------===// 60dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek 61dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremeneknamespace { 62dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek class UnreachableCodeHandler : public reachable_code::Callback { 63dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek Sema &S; 64dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek public: 65dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek UnreachableCodeHandler(Sema &s) : S(s) {} 66dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek 67dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek void HandleUnreachable(SourceLocation L, SourceRange R1, SourceRange R2) { 68dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek S.Diag(L, diag::warn_unreachable) << R1 << R2; 69dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek } 70dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek }; 71dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek} 72dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek 73dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek/// CheckUnreachable - Check for unreachable code. 741d26f48dc2eea1c07431ca1519d7034a21b9bcffTed Kremenekstatic void CheckUnreachable(Sema &S, AnalysisDeclContext &AC) { 75dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek UnreachableCodeHandler UC(S); 76dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek reachable_code::FindUnreachableCode(AC, UC); 77dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek} 78dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek 79dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek//===----------------------------------------------------------------------===// 80dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek// Check for missing return value. 81dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek//===----------------------------------------------------------------------===// 82dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek 8316565aa95b086fb239baf82335dccc1b1ec93942John McCallenum ControlFlowKind { 8416565aa95b086fb239baf82335dccc1b1ec93942John McCall UnknownFallThrough, 8516565aa95b086fb239baf82335dccc1b1ec93942John McCall NeverFallThrough, 8616565aa95b086fb239baf82335dccc1b1ec93942John McCall MaybeFallThrough, 8716565aa95b086fb239baf82335dccc1b1ec93942John McCall AlwaysFallThrough, 8816565aa95b086fb239baf82335dccc1b1ec93942John McCall NeverFallThroughOrReturn 8916565aa95b086fb239baf82335dccc1b1ec93942John McCall}; 90dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek 91dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek/// CheckFallThrough - Check that we don't fall off the end of a 92dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek/// Statement that should return a value. 93dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek/// 94f3477c13eeaf11b32a41f181398fb5deffd0dd73Sylvestre Ledru/// \returns AlwaysFallThrough iff we always fall off the end of the statement, 95f3477c13eeaf11b32a41f181398fb5deffd0dd73Sylvestre Ledru/// MaybeFallThrough iff we might or might not fall off the end, 96f3477c13eeaf11b32a41f181398fb5deffd0dd73Sylvestre Ledru/// NeverFallThroughOrReturn iff we never fall off the end of the statement or 97f3477c13eeaf11b32a41f181398fb5deffd0dd73Sylvestre Ledru/// return. We assume NeverFallThrough iff we never fall off the end of the 98dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek/// statement but we may return. We assume that functions not marked noreturn 99dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek/// will return. 1001d26f48dc2eea1c07431ca1519d7034a21b9bcffTed Kremenekstatic ControlFlowKind CheckFallThrough(AnalysisDeclContext &AC) { 101dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek CFG *cfg = AC.getCFG(); 10216565aa95b086fb239baf82335dccc1b1ec93942John McCall if (cfg == 0) return UnknownFallThrough; 103dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek 104dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek // The CFG leaves in dead things, and we don't want the dead code paths to 105dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek // confuse us, so we mark all live things first. 106dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek llvm::BitVector live(cfg->getNumBlockIDs()); 1070f3b4ca1764cd6d457f511d340fba504f41763c3Ted Kremenek unsigned count = reachable_code::ScanReachableFromBlock(&cfg->getEntry(), 108dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek live); 109dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek 110dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek bool AddEHEdges = AC.getAddEHEdges(); 111dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek if (!AddEHEdges && count != cfg->getNumBlockIDs()) 112dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek // When there are things remaining dead, and we didn't add EH edges 113dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek // from CallExprs to the catch clauses, we have to go back and 114dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek // mark them as live. 115dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek for (CFG::iterator I = cfg->begin(), E = cfg->end(); I != E; ++I) { 116dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek CFGBlock &b = **I; 117dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek if (!live[b.getBlockID()]) { 118dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek if (b.pred_begin() == b.pred_end()) { 119dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek if (b.getTerminator() && isa<CXXTryStmt>(b.getTerminator())) 120dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek // When not adding EH edges from calls, catch clauses 121dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek // can otherwise seem dead. Avoid noting them as dead. 1220f3b4ca1764cd6d457f511d340fba504f41763c3Ted Kremenek count += reachable_code::ScanReachableFromBlock(&b, live); 123dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek continue; 124dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek } 125dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek } 126dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek } 127dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek 128dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek // Now we know what is live, we check the live precessors of the exit block 129dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek // and look for fall through paths, being careful to ignore normal returns, 130dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek // and exceptional paths. 131dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek bool HasLiveReturn = false; 132dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek bool HasFakeEdge = false; 133dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek bool HasPlainEdge = false; 134dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek bool HasAbnormalEdge = false; 13590b828aa279542559f655d1af666580288cb1841Ted Kremenek 13690b828aa279542559f655d1af666580288cb1841Ted Kremenek // Ignore default cases that aren't likely to be reachable because all 13790b828aa279542559f655d1af666580288cb1841Ted Kremenek // enums in a switch(X) have explicit case statements. 13890b828aa279542559f655d1af666580288cb1841Ted Kremenek CFGBlock::FilterOptions FO; 13990b828aa279542559f655d1af666580288cb1841Ted Kremenek FO.IgnoreDefaultsWithCoveredEnums = 1; 14090b828aa279542559f655d1af666580288cb1841Ted Kremenek 14190b828aa279542559f655d1af666580288cb1841Ted Kremenek for (CFGBlock::filtered_pred_iterator 14290b828aa279542559f655d1af666580288cb1841Ted Kremenek I = cfg->getExit().filtered_pred_start_end(FO); I.hasMore(); ++I) { 14390b828aa279542559f655d1af666580288cb1841Ted Kremenek const CFGBlock& B = **I; 144dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek if (!live[B.getBlockID()]) 145dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek continue; 1465811f5978feaa7b89bd89e174fa7ad077b48413eTed Kremenek 147e05ee6df356c25e792b0334d7a4dec3fe4f79f07Chandler Carruth // Skip blocks which contain an element marked as no-return. They don't 148e05ee6df356c25e792b0334d7a4dec3fe4f79f07Chandler Carruth // represent actually viable edges into the exit block, so mark them as 149e05ee6df356c25e792b0334d7a4dec3fe4f79f07Chandler Carruth // abnormal. 150e05ee6df356c25e792b0334d7a4dec3fe4f79f07Chandler Carruth if (B.hasNoReturnElement()) { 151e05ee6df356c25e792b0334d7a4dec3fe4f79f07Chandler Carruth HasAbnormalEdge = true; 152e05ee6df356c25e792b0334d7a4dec3fe4f79f07Chandler Carruth continue; 153e05ee6df356c25e792b0334d7a4dec3fe4f79f07Chandler Carruth } 154e05ee6df356c25e792b0334d7a4dec3fe4f79f07Chandler Carruth 1555811f5978feaa7b89bd89e174fa7ad077b48413eTed Kremenek // Destructors can appear after the 'return' in the CFG. This is 1565811f5978feaa7b89bd89e174fa7ad077b48413eTed Kremenek // normal. We need to look pass the destructors for the return 1575811f5978feaa7b89bd89e174fa7ad077b48413eTed Kremenek // statement (if it exists). 1585811f5978feaa7b89bd89e174fa7ad077b48413eTed Kremenek CFGBlock::const_reverse_iterator ri = B.rbegin(), re = B.rend(); 159e05ee6df356c25e792b0334d7a4dec3fe4f79f07Chandler Carruth 160e05ee6df356c25e792b0334d7a4dec3fe4f79f07Chandler Carruth for ( ; ri != re ; ++ri) 161fdf6a279c9a75c778eba382d9a156697092982a1David Blaikie if (ri->getAs<CFGStmt>()) 1625811f5978feaa7b89bd89e174fa7ad077b48413eTed Kremenek break; 163e05ee6df356c25e792b0334d7a4dec3fe4f79f07Chandler Carruth 1645811f5978feaa7b89bd89e174fa7ad077b48413eTed Kremenek // No more CFGElements in the block? 1655811f5978feaa7b89bd89e174fa7ad077b48413eTed Kremenek if (ri == re) { 166dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek if (B.getTerminator() && isa<CXXTryStmt>(B.getTerminator())) { 167dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek HasAbnormalEdge = true; 168dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek continue; 169dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek } 170dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek // A labeled empty statement, or the entry block... 171dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek HasPlainEdge = true; 172dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek continue; 173dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek } 174f39e6a388aaa2f155b46c61e655784b2473218ebTed Kremenek 175fdf6a279c9a75c778eba382d9a156697092982a1David Blaikie CFGStmt CS = ri->castAs<CFGStmt>(); 176f1d10d939739f1a4544926d807e4f0f9fb64be61Ted Kremenek const Stmt *S = CS.getStmt(); 177dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek if (isa<ReturnStmt>(S)) { 178dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek HasLiveReturn = true; 179dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek continue; 180dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek } 181dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek if (isa<ObjCAtThrowStmt>(S)) { 182dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek HasFakeEdge = true; 183dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek continue; 184dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek } 185dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek if (isa<CXXThrowExpr>(S)) { 186dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek HasFakeEdge = true; 187dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek continue; 188dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek } 1898cd64b4c5553fa6284d248336cb7c82dc960a394Chad Rosier if (isa<MSAsmStmt>(S)) { 1908cd64b4c5553fa6284d248336cb7c82dc960a394Chad Rosier // TODO: Verify this is correct. 1918cd64b4c5553fa6284d248336cb7c82dc960a394Chad Rosier HasFakeEdge = true; 1928cd64b4c5553fa6284d248336cb7c82dc960a394Chad Rosier HasLiveReturn = true; 1938cd64b4c5553fa6284d248336cb7c82dc960a394Chad Rosier continue; 1948cd64b4c5553fa6284d248336cb7c82dc960a394Chad Rosier } 195dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek if (isa<CXXTryStmt>(S)) { 196dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek HasAbnormalEdge = true; 197dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek continue; 198dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek } 199e05ee6df356c25e792b0334d7a4dec3fe4f79f07Chandler Carruth if (std::find(B.succ_begin(), B.succ_end(), &cfg->getExit()) 200e05ee6df356c25e792b0334d7a4dec3fe4f79f07Chandler Carruth == B.succ_end()) { 201e05ee6df356c25e792b0334d7a4dec3fe4f79f07Chandler Carruth HasAbnormalEdge = true; 202e05ee6df356c25e792b0334d7a4dec3fe4f79f07Chandler Carruth continue; 203dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek } 204e05ee6df356c25e792b0334d7a4dec3fe4f79f07Chandler Carruth 205e05ee6df356c25e792b0334d7a4dec3fe4f79f07Chandler Carruth HasPlainEdge = true; 206dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek } 207dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek if (!HasPlainEdge) { 208dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek if (HasLiveReturn) 209dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek return NeverFallThrough; 210dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek return NeverFallThroughOrReturn; 211dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek } 212dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek if (HasAbnormalEdge || HasFakeEdge || HasLiveReturn) 213dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek return MaybeFallThrough; 214dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek // This says AlwaysFallThrough for calls to functions that are not marked 215dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek // noreturn, that don't return. If people would like this warning to be more 216dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek // accurate, such functions should be marked as noreturn. 217dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek return AlwaysFallThrough; 218dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek} 219dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek 2203c46e8db99196179b30e7ac5c20c4efd5f3926d7Dan Gohmannamespace { 2213c46e8db99196179b30e7ac5c20c4efd5f3926d7Dan Gohman 222dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenekstruct CheckFallThroughDiagnostics { 223dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek unsigned diag_MaybeFallThrough_HasNoReturn; 224dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek unsigned diag_MaybeFallThrough_ReturnsNonVoid; 225dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek unsigned diag_AlwaysFallThrough_HasNoReturn; 226dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek unsigned diag_AlwaysFallThrough_ReturnsNonVoid; 227dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek unsigned diag_NeverFallThroughOrReturn; 228793cd1c4cdfaafc52e2c2ad9dae959befe4bb166Douglas Gregor enum { Function, Block, Lambda } funMode; 2290827408865e32789e0ec4b8113a302ccdc531423Argyrios Kyrtzidis SourceLocation FuncLoc; 230d064fdc4b7b64ca55b40b70490c79d6f569df78eTed Kremenek 231ca7eaeeed817001dc7cee4852a7e41f0982da1efDouglas Gregor static CheckFallThroughDiagnostics MakeForFunction(const Decl *Func) { 232dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek CheckFallThroughDiagnostics D; 2330827408865e32789e0ec4b8113a302ccdc531423Argyrios Kyrtzidis D.FuncLoc = Func->getLocation(); 234dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek D.diag_MaybeFallThrough_HasNoReturn = 235dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek diag::warn_falloff_noreturn_function; 236dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek D.diag_MaybeFallThrough_ReturnsNonVoid = 237dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek diag::warn_maybe_falloff_nonvoid_function; 238dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek D.diag_AlwaysFallThrough_HasNoReturn = 239dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek diag::warn_falloff_noreturn_function; 240dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek D.diag_AlwaysFallThrough_ReturnsNonVoid = 241dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek diag::warn_falloff_nonvoid_function; 242ca7eaeeed817001dc7cee4852a7e41f0982da1efDouglas Gregor 243ca7eaeeed817001dc7cee4852a7e41f0982da1efDouglas Gregor // Don't suggest that virtual functions be marked "noreturn", since they 244ca7eaeeed817001dc7cee4852a7e41f0982da1efDouglas Gregor // might be overridden by non-noreturn functions. 245ca7eaeeed817001dc7cee4852a7e41f0982da1efDouglas Gregor bool isVirtualMethod = false; 246ca7eaeeed817001dc7cee4852a7e41f0982da1efDouglas Gregor if (const CXXMethodDecl *Method = dyn_cast<CXXMethodDecl>(Func)) 247ca7eaeeed817001dc7cee4852a7e41f0982da1efDouglas Gregor isVirtualMethod = Method->isVirtual(); 248ca7eaeeed817001dc7cee4852a7e41f0982da1efDouglas Gregor 249fcdd2cb2fdf35f806dd800b369fe0772a1c8c26cDouglas Gregor // Don't suggest that template instantiations be marked "noreturn" 250fcdd2cb2fdf35f806dd800b369fe0772a1c8c26cDouglas Gregor bool isTemplateInstantiation = false; 25175df4eeede7b91c22c1d63fafd4dd4142844e3b9Ted Kremenek if (const FunctionDecl *Function = dyn_cast<FunctionDecl>(Func)) 25275df4eeede7b91c22c1d63fafd4dd4142844e3b9Ted Kremenek isTemplateInstantiation = Function->isTemplateInstantiation(); 253fcdd2cb2fdf35f806dd800b369fe0772a1c8c26cDouglas Gregor 254fcdd2cb2fdf35f806dd800b369fe0772a1c8c26cDouglas Gregor if (!isVirtualMethod && !isTemplateInstantiation) 255ca7eaeeed817001dc7cee4852a7e41f0982da1efDouglas Gregor D.diag_NeverFallThroughOrReturn = 256ca7eaeeed817001dc7cee4852a7e41f0982da1efDouglas Gregor diag::warn_suggest_noreturn_function; 257ca7eaeeed817001dc7cee4852a7e41f0982da1efDouglas Gregor else 258ca7eaeeed817001dc7cee4852a7e41f0982da1efDouglas Gregor D.diag_NeverFallThroughOrReturn = 0; 259ca7eaeeed817001dc7cee4852a7e41f0982da1efDouglas Gregor 260793cd1c4cdfaafc52e2c2ad9dae959befe4bb166Douglas Gregor D.funMode = Function; 261dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek return D; 262dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek } 263d064fdc4b7b64ca55b40b70490c79d6f569df78eTed Kremenek 264dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek static CheckFallThroughDiagnostics MakeForBlock() { 265dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek CheckFallThroughDiagnostics D; 266dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek D.diag_MaybeFallThrough_HasNoReturn = 267dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek diag::err_noreturn_block_has_return_expr; 268dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek D.diag_MaybeFallThrough_ReturnsNonVoid = 269dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek diag::err_maybe_falloff_nonvoid_block; 270dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek D.diag_AlwaysFallThrough_HasNoReturn = 271dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek diag::err_noreturn_block_has_return_expr; 272dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek D.diag_AlwaysFallThrough_ReturnsNonVoid = 273dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek diag::err_falloff_nonvoid_block; 274dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek D.diag_NeverFallThroughOrReturn = 275dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek diag::warn_suggest_noreturn_block; 276793cd1c4cdfaafc52e2c2ad9dae959befe4bb166Douglas Gregor D.funMode = Block; 277793cd1c4cdfaafc52e2c2ad9dae959befe4bb166Douglas Gregor return D; 278793cd1c4cdfaafc52e2c2ad9dae959befe4bb166Douglas Gregor } 279793cd1c4cdfaafc52e2c2ad9dae959befe4bb166Douglas Gregor 280793cd1c4cdfaafc52e2c2ad9dae959befe4bb166Douglas Gregor static CheckFallThroughDiagnostics MakeForLambda() { 281793cd1c4cdfaafc52e2c2ad9dae959befe4bb166Douglas Gregor CheckFallThroughDiagnostics D; 282793cd1c4cdfaafc52e2c2ad9dae959befe4bb166Douglas Gregor D.diag_MaybeFallThrough_HasNoReturn = 283793cd1c4cdfaafc52e2c2ad9dae959befe4bb166Douglas Gregor diag::err_noreturn_lambda_has_return_expr; 284793cd1c4cdfaafc52e2c2ad9dae959befe4bb166Douglas Gregor D.diag_MaybeFallThrough_ReturnsNonVoid = 285793cd1c4cdfaafc52e2c2ad9dae959befe4bb166Douglas Gregor diag::warn_maybe_falloff_nonvoid_lambda; 286793cd1c4cdfaafc52e2c2ad9dae959befe4bb166Douglas Gregor D.diag_AlwaysFallThrough_HasNoReturn = 287793cd1c4cdfaafc52e2c2ad9dae959befe4bb166Douglas Gregor diag::err_noreturn_lambda_has_return_expr; 288793cd1c4cdfaafc52e2c2ad9dae959befe4bb166Douglas Gregor D.diag_AlwaysFallThrough_ReturnsNonVoid = 289793cd1c4cdfaafc52e2c2ad9dae959befe4bb166Douglas Gregor diag::warn_falloff_nonvoid_lambda; 290793cd1c4cdfaafc52e2c2ad9dae959befe4bb166Douglas Gregor D.diag_NeverFallThroughOrReturn = 0; 291793cd1c4cdfaafc52e2c2ad9dae959befe4bb166Douglas Gregor D.funMode = Lambda; 292dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek return D; 293dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek } 294d064fdc4b7b64ca55b40b70490c79d6f569df78eTed Kremenek 295d6471f7c1921c7802804ce3ff6fe9768310f72b9David Blaikie bool checkDiagnostics(DiagnosticsEngine &D, bool ReturnsVoid, 296dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek bool HasNoReturn) const { 297793cd1c4cdfaafc52e2c2ad9dae959befe4bb166Douglas Gregor if (funMode == Function) { 2980827408865e32789e0ec4b8113a302ccdc531423Argyrios Kyrtzidis return (ReturnsVoid || 2990827408865e32789e0ec4b8113a302ccdc531423Argyrios Kyrtzidis D.getDiagnosticLevel(diag::warn_maybe_falloff_nonvoid_function, 300d6471f7c1921c7802804ce3ff6fe9768310f72b9David Blaikie FuncLoc) == DiagnosticsEngine::Ignored) 3010827408865e32789e0ec4b8113a302ccdc531423Argyrios Kyrtzidis && (!HasNoReturn || 3020827408865e32789e0ec4b8113a302ccdc531423Argyrios Kyrtzidis D.getDiagnosticLevel(diag::warn_noreturn_function_has_return_expr, 303d6471f7c1921c7802804ce3ff6fe9768310f72b9David Blaikie FuncLoc) == DiagnosticsEngine::Ignored) 3040827408865e32789e0ec4b8113a302ccdc531423Argyrios Kyrtzidis && (!ReturnsVoid || 3050827408865e32789e0ec4b8113a302ccdc531423Argyrios Kyrtzidis D.getDiagnosticLevel(diag::warn_suggest_noreturn_block, FuncLoc) 306d6471f7c1921c7802804ce3ff6fe9768310f72b9David Blaikie == DiagnosticsEngine::Ignored); 307dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek } 308d064fdc4b7b64ca55b40b70490c79d6f569df78eTed Kremenek 309793cd1c4cdfaafc52e2c2ad9dae959befe4bb166Douglas Gregor // For blocks / lambdas. 310793cd1c4cdfaafc52e2c2ad9dae959befe4bb166Douglas Gregor return ReturnsVoid && !HasNoReturn 311793cd1c4cdfaafc52e2c2ad9dae959befe4bb166Douglas Gregor && ((funMode == Lambda) || 3120827408865e32789e0ec4b8113a302ccdc531423Argyrios Kyrtzidis D.getDiagnosticLevel(diag::warn_suggest_noreturn_block, FuncLoc) 313d6471f7c1921c7802804ce3ff6fe9768310f72b9David Blaikie == DiagnosticsEngine::Ignored); 314dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek } 315dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek}; 316dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek 3173c46e8db99196179b30e7ac5c20c4efd5f3926d7Dan Gohman} 3183c46e8db99196179b30e7ac5c20c4efd5f3926d7Dan Gohman 319dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek/// CheckFallThroughForFunctionDef - Check that we don't fall off the end of a 320dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek/// function that should return a value. Check that we don't fall off the end 321dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek/// of a noreturn function. We assume that functions and blocks not marked 322dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek/// noreturn will return. 323dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenekstatic void CheckFallThroughForBody(Sema &S, const Decl *D, const Stmt *Body, 3243ed6fc08a9cd293d012fa49ab2a615e618d7c3faTed Kremenek const BlockExpr *blkExpr, 325dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek const CheckFallThroughDiagnostics& CD, 3261d26f48dc2eea1c07431ca1519d7034a21b9bcffTed Kremenek AnalysisDeclContext &AC) { 327dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek 328dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek bool ReturnsVoid = false; 329dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek bool HasNoReturn = false; 330dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek 331dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(D)) { 332dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek ReturnsVoid = FD->getResultType()->isVoidType(); 333cd8ab51a44e80625d84126780b0d85a7732e25afRichard Smith HasNoReturn = FD->isNoReturn(); 334dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek } 335dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek else if (const ObjCMethodDecl *MD = dyn_cast<ObjCMethodDecl>(D)) { 336dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek ReturnsVoid = MD->getResultType()->isVoidType(); 337dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek HasNoReturn = MD->hasAttr<NoReturnAttr>(); 338dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek } 339dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek else if (isa<BlockDecl>(D)) { 3403ed6fc08a9cd293d012fa49ab2a615e618d7c3faTed Kremenek QualType BlockTy = blkExpr->getType(); 341d064fdc4b7b64ca55b40b70490c79d6f569df78eTed Kremenek if (const FunctionType *FT = 342dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek BlockTy->getPointeeType()->getAs<FunctionType>()) { 343dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek if (FT->getResultType()->isVoidType()) 344dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek ReturnsVoid = true; 345dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek if (FT->getNoReturnAttr()) 346dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek HasNoReturn = true; 347dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek } 348dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek } 349dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek 350d6471f7c1921c7802804ce3ff6fe9768310f72b9David Blaikie DiagnosticsEngine &Diags = S.getDiagnostics(); 351dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek 352dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek // Short circuit for compilation speed. 353dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek if (CD.checkDiagnostics(Diags, ReturnsVoid, HasNoReturn)) 354dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek return; 355d064fdc4b7b64ca55b40b70490c79d6f569df78eTed Kremenek 356dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek // FIXME: Function try block 357dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek if (const CompoundStmt *Compound = dyn_cast<CompoundStmt>(Body)) { 358dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek switch (CheckFallThrough(AC)) { 35916565aa95b086fb239baf82335dccc1b1ec93942John McCall case UnknownFallThrough: 36016565aa95b086fb239baf82335dccc1b1ec93942John McCall break; 36116565aa95b086fb239baf82335dccc1b1ec93942John McCall 362dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek case MaybeFallThrough: 363dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek if (HasNoReturn) 364dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek S.Diag(Compound->getRBracLoc(), 365dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek CD.diag_MaybeFallThrough_HasNoReturn); 366dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek else if (!ReturnsVoid) 367dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek S.Diag(Compound->getRBracLoc(), 368dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek CD.diag_MaybeFallThrough_ReturnsNonVoid); 369dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek break; 370dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek case AlwaysFallThrough: 371dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek if (HasNoReturn) 372dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek S.Diag(Compound->getRBracLoc(), 373dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek CD.diag_AlwaysFallThrough_HasNoReturn); 374dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek else if (!ReturnsVoid) 375dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek S.Diag(Compound->getRBracLoc(), 376dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek CD.diag_AlwaysFallThrough_ReturnsNonVoid); 377dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek break; 378dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek case NeverFallThroughOrReturn: 379b0656ec72e25e5c8e463c2dc39914636f0cb06d1Chandler Carruth if (ReturnsVoid && !HasNoReturn && CD.diag_NeverFallThroughOrReturn) { 380b0656ec72e25e5c8e463c2dc39914636f0cb06d1Chandler Carruth if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(D)) { 381b0656ec72e25e5c8e463c2dc39914636f0cb06d1Chandler Carruth S.Diag(Compound->getLBracLoc(), CD.diag_NeverFallThroughOrReturn) 382b3321093f6ead084427eb4a6621832fc4ee2f5deDouglas Gregor << 0 << FD; 383b3321093f6ead084427eb4a6621832fc4ee2f5deDouglas Gregor } else if (const ObjCMethodDecl *MD = dyn_cast<ObjCMethodDecl>(D)) { 384b3321093f6ead084427eb4a6621832fc4ee2f5deDouglas Gregor S.Diag(Compound->getLBracLoc(), CD.diag_NeverFallThroughOrReturn) 385b3321093f6ead084427eb4a6621832fc4ee2f5deDouglas Gregor << 1 << MD; 386b0656ec72e25e5c8e463c2dc39914636f0cb06d1Chandler Carruth } else { 387b0656ec72e25e5c8e463c2dc39914636f0cb06d1Chandler Carruth S.Diag(Compound->getLBracLoc(), CD.diag_NeverFallThroughOrReturn); 388b0656ec72e25e5c8e463c2dc39914636f0cb06d1Chandler Carruth } 389b0656ec72e25e5c8e463c2dc39914636f0cb06d1Chandler Carruth } 390dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek break; 391dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek case NeverFallThrough: 392dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek break; 393dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek } 394dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek } 395dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek} 396dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek 397dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek//===----------------------------------------------------------------------===// 398610068c8cd2321f90e147b12cf794e1f840b6405Ted Kremenek// -Wuninitialized 399610068c8cd2321f90e147b12cf794e1f840b6405Ted Kremenek//===----------------------------------------------------------------------===// 400610068c8cd2321f90e147b12cf794e1f840b6405Ted Kremenek 4016f41715df2c6a31c0c3ab3088b8cd18a3c8321b8Ted Kremeneknamespace { 4029f6494687c05fe1d334af76408ee056b5f80e027Chandler Carruth/// ContainsReference - A visitor class to search for references to 4039f6494687c05fe1d334af76408ee056b5f80e027Chandler Carruth/// a particular declaration (the needle) within any evaluated component of an 4049f6494687c05fe1d334af76408ee056b5f80e027Chandler Carruth/// expression (recursively). 4056f41715df2c6a31c0c3ab3088b8cd18a3c8321b8Ted Kremenekclass ContainsReference : public EvaluatedExprVisitor<ContainsReference> { 4069f6494687c05fe1d334af76408ee056b5f80e027Chandler Carruth bool FoundReference; 4079f6494687c05fe1d334af76408ee056b5f80e027Chandler Carruth const DeclRefExpr *Needle; 4089f6494687c05fe1d334af76408ee056b5f80e027Chandler Carruth 4096f41715df2c6a31c0c3ab3088b8cd18a3c8321b8Ted Kremenekpublic: 4109f6494687c05fe1d334af76408ee056b5f80e027Chandler Carruth ContainsReference(ASTContext &Context, const DeclRefExpr *Needle) 4119f6494687c05fe1d334af76408ee056b5f80e027Chandler Carruth : EvaluatedExprVisitor<ContainsReference>(Context), 4129f6494687c05fe1d334af76408ee056b5f80e027Chandler Carruth FoundReference(false), Needle(Needle) {} 4139f6494687c05fe1d334af76408ee056b5f80e027Chandler Carruth 4149f6494687c05fe1d334af76408ee056b5f80e027Chandler Carruth void VisitExpr(Expr *E) { 4156f41715df2c6a31c0c3ab3088b8cd18a3c8321b8Ted Kremenek // Stop evaluating if we already have a reference. 4169f6494687c05fe1d334af76408ee056b5f80e027Chandler Carruth if (FoundReference) 4176f41715df2c6a31c0c3ab3088b8cd18a3c8321b8Ted Kremenek return; 4189f6494687c05fe1d334af76408ee056b5f80e027Chandler Carruth 4199f6494687c05fe1d334af76408ee056b5f80e027Chandler Carruth EvaluatedExprVisitor<ContainsReference>::VisitExpr(E); 4206f41715df2c6a31c0c3ab3088b8cd18a3c8321b8Ted Kremenek } 4219f6494687c05fe1d334af76408ee056b5f80e027Chandler Carruth 4229f6494687c05fe1d334af76408ee056b5f80e027Chandler Carruth void VisitDeclRefExpr(DeclRefExpr *E) { 4239f6494687c05fe1d334af76408ee056b5f80e027Chandler Carruth if (E == Needle) 4249f6494687c05fe1d334af76408ee056b5f80e027Chandler Carruth FoundReference = true; 4259f6494687c05fe1d334af76408ee056b5f80e027Chandler Carruth else 4269f6494687c05fe1d334af76408ee056b5f80e027Chandler Carruth EvaluatedExprVisitor<ContainsReference>::VisitDeclRefExpr(E); 4276f41715df2c6a31c0c3ab3088b8cd18a3c8321b8Ted Kremenek } 4289f6494687c05fe1d334af76408ee056b5f80e027Chandler Carruth 4299f6494687c05fe1d334af76408ee056b5f80e027Chandler Carruth bool doesContainReference() const { return FoundReference; } 4306f41715df2c6a31c0c3ab3088b8cd18a3c8321b8Ted Kremenek}; 4316f41715df2c6a31c0c3ab3088b8cd18a3c8321b8Ted Kremenek} 4326f41715df2c6a31c0c3ab3088b8cd18a3c8321b8Ted Kremenek 4334f4f349208b2b2307454e169ac7b039e989f003fDavid Blaikiestatic bool SuggestInitializationFixit(Sema &S, const VarDecl *VD) { 434a34194f035096dd8dce10574e3a186da968aa211Fariborz Jahanian QualType VariableTy = VD->getType().getCanonicalType(); 435a34194f035096dd8dce10574e3a186da968aa211Fariborz Jahanian if (VariableTy->isBlockPointerType() && 436a34194f035096dd8dce10574e3a186da968aa211Fariborz Jahanian !VD->hasAttr<BlocksAttr>()) { 437a34194f035096dd8dce10574e3a186da968aa211Fariborz Jahanian S.Diag(VD->getLocation(), diag::note_block_var_fixit_add_initialization) << VD->getDeclName() 438a34194f035096dd8dce10574e3a186da968aa211Fariborz Jahanian << FixItHint::CreateInsertion(VD->getLocation(), "__block "); 439a34194f035096dd8dce10574e3a186da968aa211Fariborz Jahanian return true; 440a34194f035096dd8dce10574e3a186da968aa211Fariborz Jahanian } 441a34194f035096dd8dce10574e3a186da968aa211Fariborz Jahanian 4424f4f349208b2b2307454e169ac7b039e989f003fDavid Blaikie // Don't issue a fixit if there is already an initializer. 4434f4f349208b2b2307454e169ac7b039e989f003fDavid Blaikie if (VD->getInit()) 4444f4f349208b2b2307454e169ac7b039e989f003fDavid Blaikie return false; 445a34194f035096dd8dce10574e3a186da968aa211Fariborz Jahanian 4464f4f349208b2b2307454e169ac7b039e989f003fDavid Blaikie // Suggest possible initialization (if any). 4472c0abf4ae33ab2ba690ccae724b8d6f196e7cfdaDavid Blaikie std::string Init = S.getFixItZeroInitializerForType(VariableTy); 4482c0abf4ae33ab2ba690ccae724b8d6f196e7cfdaDavid Blaikie if (Init.empty()) 4494f4f349208b2b2307454e169ac7b039e989f003fDavid Blaikie return false; 4507b0a3e378c441cec60f929d13bd48846c267a008Richard Trieu 4517b0a3e378c441cec60f929d13bd48846c267a008Richard Trieu // Don't suggest a fixit inside macros. 4527b0a3e378c441cec60f929d13bd48846c267a008Richard Trieu if (VD->getLocEnd().isMacroID()) 4537b0a3e378c441cec60f929d13bd48846c267a008Richard Trieu return false; 4547b0a3e378c441cec60f929d13bd48846c267a008Richard Trieu 4557984de35644701c0d94336da7f2215d4c26d9f5bRichard Smith SourceLocation Loc = S.PP.getLocForEndOfToken(VD->getLocEnd()); 456a34194f035096dd8dce10574e3a186da968aa211Fariborz Jahanian 4577984de35644701c0d94336da7f2215d4c26d9f5bRichard Smith S.Diag(Loc, diag::note_var_fixit_add_initialization) << VD->getDeclName() 4587984de35644701c0d94336da7f2215d4c26d9f5bRichard Smith << FixItHint::CreateInsertion(Loc, Init); 4597984de35644701c0d94336da7f2215d4c26d9f5bRichard Smith return true; 4604f4f349208b2b2307454e169ac7b039e989f003fDavid Blaikie} 4614f4f349208b2b2307454e169ac7b039e989f003fDavid Blaikie 462bdb97ff687ce85e45cc728b87612ed546f48c1e7Richard Smith/// Create a fixit to remove an if-like statement, on the assumption that its 463bdb97ff687ce85e45cc728b87612ed546f48c1e7Richard Smith/// condition is CondVal. 464bdb97ff687ce85e45cc728b87612ed546f48c1e7Richard Smithstatic void CreateIfFixit(Sema &S, const Stmt *If, const Stmt *Then, 465bdb97ff687ce85e45cc728b87612ed546f48c1e7Richard Smith const Stmt *Else, bool CondVal, 466bdb97ff687ce85e45cc728b87612ed546f48c1e7Richard Smith FixItHint &Fixit1, FixItHint &Fixit2) { 467bdb97ff687ce85e45cc728b87612ed546f48c1e7Richard Smith if (CondVal) { 468bdb97ff687ce85e45cc728b87612ed546f48c1e7Richard Smith // If condition is always true, remove all but the 'then'. 469bdb97ff687ce85e45cc728b87612ed546f48c1e7Richard Smith Fixit1 = FixItHint::CreateRemoval( 470bdb97ff687ce85e45cc728b87612ed546f48c1e7Richard Smith CharSourceRange::getCharRange(If->getLocStart(), 471bdb97ff687ce85e45cc728b87612ed546f48c1e7Richard Smith Then->getLocStart())); 472bdb97ff687ce85e45cc728b87612ed546f48c1e7Richard Smith if (Else) { 473bdb97ff687ce85e45cc728b87612ed546f48c1e7Richard Smith SourceLocation ElseKwLoc = Lexer::getLocForEndOfToken( 474bdb97ff687ce85e45cc728b87612ed546f48c1e7Richard Smith Then->getLocEnd(), 0, S.getSourceManager(), S.getLangOpts()); 475bdb97ff687ce85e45cc728b87612ed546f48c1e7Richard Smith Fixit2 = FixItHint::CreateRemoval( 476bdb97ff687ce85e45cc728b87612ed546f48c1e7Richard Smith SourceRange(ElseKwLoc, Else->getLocEnd())); 477bdb97ff687ce85e45cc728b87612ed546f48c1e7Richard Smith } 478bdb97ff687ce85e45cc728b87612ed546f48c1e7Richard Smith } else { 479bdb97ff687ce85e45cc728b87612ed546f48c1e7Richard Smith // If condition is always false, remove all but the 'else'. 480bdb97ff687ce85e45cc728b87612ed546f48c1e7Richard Smith if (Else) 481bdb97ff687ce85e45cc728b87612ed546f48c1e7Richard Smith Fixit1 = FixItHint::CreateRemoval( 482bdb97ff687ce85e45cc728b87612ed546f48c1e7Richard Smith CharSourceRange::getCharRange(If->getLocStart(), 483bdb97ff687ce85e45cc728b87612ed546f48c1e7Richard Smith Else->getLocStart())); 484bdb97ff687ce85e45cc728b87612ed546f48c1e7Richard Smith else 485bdb97ff687ce85e45cc728b87612ed546f48c1e7Richard Smith Fixit1 = FixItHint::CreateRemoval(If->getSourceRange()); 486bdb97ff687ce85e45cc728b87612ed546f48c1e7Richard Smith } 487bdb97ff687ce85e45cc728b87612ed546f48c1e7Richard Smith} 488bdb97ff687ce85e45cc728b87612ed546f48c1e7Richard Smith 489bdb97ff687ce85e45cc728b87612ed546f48c1e7Richard Smith/// DiagUninitUse -- Helper function to produce a diagnostic for an 490bdb97ff687ce85e45cc728b87612ed546f48c1e7Richard Smith/// uninitialized use of a variable. 491bdb97ff687ce85e45cc728b87612ed546f48c1e7Richard Smithstatic void DiagUninitUse(Sema &S, const VarDecl *VD, const UninitUse &Use, 492bdb97ff687ce85e45cc728b87612ed546f48c1e7Richard Smith bool IsCapturedByBlock) { 493bdb97ff687ce85e45cc728b87612ed546f48c1e7Richard Smith bool Diagnosed = false; 494bdb97ff687ce85e45cc728b87612ed546f48c1e7Richard Smith 495bdb97ff687ce85e45cc728b87612ed546f48c1e7Richard Smith // Diagnose each branch which leads to a sometimes-uninitialized use. 4962815e1a075c74143a0b60a632090ece1dffa5c7cRichard Smith for (UninitUse::branch_iterator I = Use.branch_begin(), E = Use.branch_end(); 4972815e1a075c74143a0b60a632090ece1dffa5c7cRichard Smith I != E; ++I) { 498bdb97ff687ce85e45cc728b87612ed546f48c1e7Richard Smith assert(Use.getKind() == UninitUse::Sometimes); 499bdb97ff687ce85e45cc728b87612ed546f48c1e7Richard Smith 500bdb97ff687ce85e45cc728b87612ed546f48c1e7Richard Smith const Expr *User = Use.getUser(); 5012815e1a075c74143a0b60a632090ece1dffa5c7cRichard Smith const Stmt *Term = I->Terminator; 502bdb97ff687ce85e45cc728b87612ed546f48c1e7Richard Smith 503bdb97ff687ce85e45cc728b87612ed546f48c1e7Richard Smith // Information used when building the diagnostic. 5042815e1a075c74143a0b60a632090ece1dffa5c7cRichard Smith unsigned DiagKind; 5050bea86307eb8c16339315a1e261fc490eb505c5bDavid Blaikie StringRef Str; 506bdb97ff687ce85e45cc728b87612ed546f48c1e7Richard Smith SourceRange Range; 507bdb97ff687ce85e45cc728b87612ed546f48c1e7Richard Smith 508fc09336a5965040736f9bc63a70416003972364eStefanus Du Toit // FixIts to suppress the diagnostic by removing the dead condition. 509bdb97ff687ce85e45cc728b87612ed546f48c1e7Richard Smith // For all binary terminators, branch 0 is taken if the condition is true, 510bdb97ff687ce85e45cc728b87612ed546f48c1e7Richard Smith // and branch 1 is taken if the condition is false. 511bdb97ff687ce85e45cc728b87612ed546f48c1e7Richard Smith int RemoveDiagKind = -1; 512bdb97ff687ce85e45cc728b87612ed546f48c1e7Richard Smith const char *FixitStr = 513bdb97ff687ce85e45cc728b87612ed546f48c1e7Richard Smith S.getLangOpts().CPlusPlus ? (I->Output ? "true" : "false") 514bdb97ff687ce85e45cc728b87612ed546f48c1e7Richard Smith : (I->Output ? "1" : "0"); 515bdb97ff687ce85e45cc728b87612ed546f48c1e7Richard Smith FixItHint Fixit1, Fixit2; 516bdb97ff687ce85e45cc728b87612ed546f48c1e7Richard Smith 5172815e1a075c74143a0b60a632090ece1dffa5c7cRichard Smith switch (Term->getStmtClass()) { 5182815e1a075c74143a0b60a632090ece1dffa5c7cRichard Smith default: 519bdb97ff687ce85e45cc728b87612ed546f48c1e7Richard Smith // Don't know how to report this. Just fall back to 'may be used 520bdb97ff687ce85e45cc728b87612ed546f48c1e7Richard Smith // uninitialized'. This happens for range-based for, which the user 521bdb97ff687ce85e45cc728b87612ed546f48c1e7Richard Smith // can't explicitly fix. 522bdb97ff687ce85e45cc728b87612ed546f48c1e7Richard Smith // FIXME: This also happens if the first use of a variable is always 523bdb97ff687ce85e45cc728b87612ed546f48c1e7Richard Smith // uninitialized, eg "for (int n; n < 10; ++n)". We should report that 524bdb97ff687ce85e45cc728b87612ed546f48c1e7Richard Smith // with the 'is uninitialized' diagnostic. 5252815e1a075c74143a0b60a632090ece1dffa5c7cRichard Smith continue; 5262815e1a075c74143a0b60a632090ece1dffa5c7cRichard Smith 5272815e1a075c74143a0b60a632090ece1dffa5c7cRichard Smith // "condition is true / condition is false". 528bdb97ff687ce85e45cc728b87612ed546f48c1e7Richard Smith case Stmt::IfStmtClass: { 529bdb97ff687ce85e45cc728b87612ed546f48c1e7Richard Smith const IfStmt *IS = cast<IfStmt>(Term); 5302815e1a075c74143a0b60a632090ece1dffa5c7cRichard Smith DiagKind = 0; 5312815e1a075c74143a0b60a632090ece1dffa5c7cRichard Smith Str = "if"; 532bdb97ff687ce85e45cc728b87612ed546f48c1e7Richard Smith Range = IS->getCond()->getSourceRange(); 533bdb97ff687ce85e45cc728b87612ed546f48c1e7Richard Smith RemoveDiagKind = 0; 534bdb97ff687ce85e45cc728b87612ed546f48c1e7Richard Smith CreateIfFixit(S, IS, IS->getThen(), IS->getElse(), 535bdb97ff687ce85e45cc728b87612ed546f48c1e7Richard Smith I->Output, Fixit1, Fixit2); 5362815e1a075c74143a0b60a632090ece1dffa5c7cRichard Smith break; 537bdb97ff687ce85e45cc728b87612ed546f48c1e7Richard Smith } 538bdb97ff687ce85e45cc728b87612ed546f48c1e7Richard Smith case Stmt::ConditionalOperatorClass: { 539bdb97ff687ce85e45cc728b87612ed546f48c1e7Richard Smith const ConditionalOperator *CO = cast<ConditionalOperator>(Term); 5402815e1a075c74143a0b60a632090ece1dffa5c7cRichard Smith DiagKind = 0; 5412815e1a075c74143a0b60a632090ece1dffa5c7cRichard Smith Str = "?:"; 542bdb97ff687ce85e45cc728b87612ed546f48c1e7Richard Smith Range = CO->getCond()->getSourceRange(); 543bdb97ff687ce85e45cc728b87612ed546f48c1e7Richard Smith RemoveDiagKind = 0; 544bdb97ff687ce85e45cc728b87612ed546f48c1e7Richard Smith CreateIfFixit(S, CO, CO->getTrueExpr(), CO->getFalseExpr(), 545bdb97ff687ce85e45cc728b87612ed546f48c1e7Richard Smith I->Output, Fixit1, Fixit2); 5462815e1a075c74143a0b60a632090ece1dffa5c7cRichard Smith break; 547bdb97ff687ce85e45cc728b87612ed546f48c1e7Richard Smith } 5482815e1a075c74143a0b60a632090ece1dffa5c7cRichard Smith case Stmt::BinaryOperatorClass: { 5492815e1a075c74143a0b60a632090ece1dffa5c7cRichard Smith const BinaryOperator *BO = cast<BinaryOperator>(Term); 5502815e1a075c74143a0b60a632090ece1dffa5c7cRichard Smith if (!BO->isLogicalOp()) 5512815e1a075c74143a0b60a632090ece1dffa5c7cRichard Smith continue; 5522815e1a075c74143a0b60a632090ece1dffa5c7cRichard Smith DiagKind = 0; 5532815e1a075c74143a0b60a632090ece1dffa5c7cRichard Smith Str = BO->getOpcodeStr(); 5542815e1a075c74143a0b60a632090ece1dffa5c7cRichard Smith Range = BO->getLHS()->getSourceRange(); 555bdb97ff687ce85e45cc728b87612ed546f48c1e7Richard Smith RemoveDiagKind = 0; 556bdb97ff687ce85e45cc728b87612ed546f48c1e7Richard Smith if ((BO->getOpcode() == BO_LAnd && I->Output) || 557bdb97ff687ce85e45cc728b87612ed546f48c1e7Richard Smith (BO->getOpcode() == BO_LOr && !I->Output)) 558bdb97ff687ce85e45cc728b87612ed546f48c1e7Richard Smith // true && y -> y, false || y -> y. 559bdb97ff687ce85e45cc728b87612ed546f48c1e7Richard Smith Fixit1 = FixItHint::CreateRemoval(SourceRange(BO->getLocStart(), 560bdb97ff687ce85e45cc728b87612ed546f48c1e7Richard Smith BO->getOperatorLoc())); 561bdb97ff687ce85e45cc728b87612ed546f48c1e7Richard Smith else 562bdb97ff687ce85e45cc728b87612ed546f48c1e7Richard Smith // false && y -> false, true || y -> true. 563bdb97ff687ce85e45cc728b87612ed546f48c1e7Richard Smith Fixit1 = FixItHint::CreateReplacement(BO->getSourceRange(), FixitStr); 5642815e1a075c74143a0b60a632090ece1dffa5c7cRichard Smith break; 5652815e1a075c74143a0b60a632090ece1dffa5c7cRichard Smith } 5662815e1a075c74143a0b60a632090ece1dffa5c7cRichard Smith 5672815e1a075c74143a0b60a632090ece1dffa5c7cRichard Smith // "loop is entered / loop is exited". 5682815e1a075c74143a0b60a632090ece1dffa5c7cRichard Smith case Stmt::WhileStmtClass: 5692815e1a075c74143a0b60a632090ece1dffa5c7cRichard Smith DiagKind = 1; 5702815e1a075c74143a0b60a632090ece1dffa5c7cRichard Smith Str = "while"; 5712815e1a075c74143a0b60a632090ece1dffa5c7cRichard Smith Range = cast<WhileStmt>(Term)->getCond()->getSourceRange(); 572bdb97ff687ce85e45cc728b87612ed546f48c1e7Richard Smith RemoveDiagKind = 1; 573bdb97ff687ce85e45cc728b87612ed546f48c1e7Richard Smith Fixit1 = FixItHint::CreateReplacement(Range, FixitStr); 5742815e1a075c74143a0b60a632090ece1dffa5c7cRichard Smith break; 5752815e1a075c74143a0b60a632090ece1dffa5c7cRichard Smith case Stmt::ForStmtClass: 5762815e1a075c74143a0b60a632090ece1dffa5c7cRichard Smith DiagKind = 1; 5772815e1a075c74143a0b60a632090ece1dffa5c7cRichard Smith Str = "for"; 5782815e1a075c74143a0b60a632090ece1dffa5c7cRichard Smith Range = cast<ForStmt>(Term)->getCond()->getSourceRange(); 579bdb97ff687ce85e45cc728b87612ed546f48c1e7Richard Smith RemoveDiagKind = 1; 580bdb97ff687ce85e45cc728b87612ed546f48c1e7Richard Smith if (I->Output) 581bdb97ff687ce85e45cc728b87612ed546f48c1e7Richard Smith Fixit1 = FixItHint::CreateRemoval(Range); 582bdb97ff687ce85e45cc728b87612ed546f48c1e7Richard Smith else 583bdb97ff687ce85e45cc728b87612ed546f48c1e7Richard Smith Fixit1 = FixItHint::CreateReplacement(Range, FixitStr); 5842815e1a075c74143a0b60a632090ece1dffa5c7cRichard Smith break; 5852815e1a075c74143a0b60a632090ece1dffa5c7cRichard Smith 5862815e1a075c74143a0b60a632090ece1dffa5c7cRichard Smith // "condition is true / loop is exited". 5872815e1a075c74143a0b60a632090ece1dffa5c7cRichard Smith case Stmt::DoStmtClass: 5882815e1a075c74143a0b60a632090ece1dffa5c7cRichard Smith DiagKind = 2; 5892815e1a075c74143a0b60a632090ece1dffa5c7cRichard Smith Str = "do"; 5902815e1a075c74143a0b60a632090ece1dffa5c7cRichard Smith Range = cast<DoStmt>(Term)->getCond()->getSourceRange(); 591bdb97ff687ce85e45cc728b87612ed546f48c1e7Richard Smith RemoveDiagKind = 1; 592bdb97ff687ce85e45cc728b87612ed546f48c1e7Richard Smith Fixit1 = FixItHint::CreateReplacement(Range, FixitStr); 5932815e1a075c74143a0b60a632090ece1dffa5c7cRichard Smith break; 5942815e1a075c74143a0b60a632090ece1dffa5c7cRichard Smith 5952815e1a075c74143a0b60a632090ece1dffa5c7cRichard Smith // "switch case is taken". 5962815e1a075c74143a0b60a632090ece1dffa5c7cRichard Smith case Stmt::CaseStmtClass: 5972815e1a075c74143a0b60a632090ece1dffa5c7cRichard Smith DiagKind = 3; 5982815e1a075c74143a0b60a632090ece1dffa5c7cRichard Smith Str = "case"; 5992815e1a075c74143a0b60a632090ece1dffa5c7cRichard Smith Range = cast<CaseStmt>(Term)->getLHS()->getSourceRange(); 6002815e1a075c74143a0b60a632090ece1dffa5c7cRichard Smith break; 6012815e1a075c74143a0b60a632090ece1dffa5c7cRichard Smith case Stmt::DefaultStmtClass: 6022815e1a075c74143a0b60a632090ece1dffa5c7cRichard Smith DiagKind = 3; 6032815e1a075c74143a0b60a632090ece1dffa5c7cRichard Smith Str = "default"; 6042815e1a075c74143a0b60a632090ece1dffa5c7cRichard Smith Range = cast<DefaultStmt>(Term)->getDefaultLoc(); 6052815e1a075c74143a0b60a632090ece1dffa5c7cRichard Smith break; 6062815e1a075c74143a0b60a632090ece1dffa5c7cRichard Smith } 6072815e1a075c74143a0b60a632090ece1dffa5c7cRichard Smith 608bdb97ff687ce85e45cc728b87612ed546f48c1e7Richard Smith S.Diag(Range.getBegin(), diag::warn_sometimes_uninit_var) 609bdb97ff687ce85e45cc728b87612ed546f48c1e7Richard Smith << VD->getDeclName() << IsCapturedByBlock << DiagKind 610bdb97ff687ce85e45cc728b87612ed546f48c1e7Richard Smith << Str << I->Output << Range; 611bdb97ff687ce85e45cc728b87612ed546f48c1e7Richard Smith S.Diag(User->getLocStart(), diag::note_uninit_var_use) 612bdb97ff687ce85e45cc728b87612ed546f48c1e7Richard Smith << IsCapturedByBlock << User->getSourceRange(); 613bdb97ff687ce85e45cc728b87612ed546f48c1e7Richard Smith if (RemoveDiagKind != -1) 614bdb97ff687ce85e45cc728b87612ed546f48c1e7Richard Smith S.Diag(Fixit1.RemoveRange.getBegin(), diag::note_uninit_fixit_remove_cond) 615bdb97ff687ce85e45cc728b87612ed546f48c1e7Richard Smith << RemoveDiagKind << Str << I->Output << Fixit1 << Fixit2; 616bdb97ff687ce85e45cc728b87612ed546f48c1e7Richard Smith 617bdb97ff687ce85e45cc728b87612ed546f48c1e7Richard Smith Diagnosed = true; 6182815e1a075c74143a0b60a632090ece1dffa5c7cRichard Smith } 619bdb97ff687ce85e45cc728b87612ed546f48c1e7Richard Smith 620bdb97ff687ce85e45cc728b87612ed546f48c1e7Richard Smith if (!Diagnosed) 621bdb97ff687ce85e45cc728b87612ed546f48c1e7Richard Smith S.Diag(Use.getUser()->getLocStart(), 622bdb97ff687ce85e45cc728b87612ed546f48c1e7Richard Smith Use.getKind() == UninitUse::Always ? diag::warn_uninit_var 623bdb97ff687ce85e45cc728b87612ed546f48c1e7Richard Smith : diag::warn_maybe_uninit_var) 624bdb97ff687ce85e45cc728b87612ed546f48c1e7Richard Smith << VD->getDeclName() << IsCapturedByBlock 625bdb97ff687ce85e45cc728b87612ed546f48c1e7Richard Smith << Use.getUser()->getSourceRange(); 6262815e1a075c74143a0b60a632090ece1dffa5c7cRichard Smith} 6272815e1a075c74143a0b60a632090ece1dffa5c7cRichard Smith 628262d50e1dcf529317da193ad585c11c16281a7acChandler Carruth/// DiagnoseUninitializedUse -- Helper function for diagnosing uses of an 629262d50e1dcf529317da193ad585c11c16281a7acChandler Carruth/// uninitialized variable. This manages the different forms of diagnostic 630262d50e1dcf529317da193ad585c11c16281a7acChandler Carruth/// emitted for particular types of uses. Returns true if the use was diagnosed 6312815e1a075c74143a0b60a632090ece1dffa5c7cRichard Smith/// as a warning. If a particular use is one we omit warnings for, returns 632262d50e1dcf529317da193ad585c11c16281a7acChandler Carruth/// false. 633262d50e1dcf529317da193ad585c11c16281a7acChandler Carruthstatic bool DiagnoseUninitializedUse(Sema &S, const VarDecl *VD, 6342815e1a075c74143a0b60a632090ece1dffa5c7cRichard Smith const UninitUse &Use, 6359e7617220135a6f6226cf09cb242cc1b905aedb4Ted Kremenek bool alwaysReportSelfInit = false) { 6364c4983bbd2904670a25c840b07600f14efbafd7fChandler Carruth 6372815e1a075c74143a0b60a632090ece1dffa5c7cRichard Smith if (const DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(Use.getUser())) { 638f6278e545d9bc09fb5d7579d1123f0a455352627Richard Trieu // Inspect the initializer of the variable declaration which is 639f6278e545d9bc09fb5d7579d1123f0a455352627Richard Trieu // being referenced prior to its initialization. We emit 640f6278e545d9bc09fb5d7579d1123f0a455352627Richard Trieu // specialized diagnostics for self-initialization, and we 641f6278e545d9bc09fb5d7579d1123f0a455352627Richard Trieu // specifically avoid warning about self references which take the 642f6278e545d9bc09fb5d7579d1123f0a455352627Richard Trieu // form of: 643f6278e545d9bc09fb5d7579d1123f0a455352627Richard Trieu // 644f6278e545d9bc09fb5d7579d1123f0a455352627Richard Trieu // int x = x; 645f6278e545d9bc09fb5d7579d1123f0a455352627Richard Trieu // 646f6278e545d9bc09fb5d7579d1123f0a455352627Richard Trieu // This is used to indicate to GCC that 'x' is intentionally left 647f6278e545d9bc09fb5d7579d1123f0a455352627Richard Trieu // uninitialized. Proven code paths which access 'x' in 648f6278e545d9bc09fb5d7579d1123f0a455352627Richard Trieu // an uninitialized state after this will still warn. 649f6278e545d9bc09fb5d7579d1123f0a455352627Richard Trieu if (const Expr *Initializer = VD->getInit()) { 650f6278e545d9bc09fb5d7579d1123f0a455352627Richard Trieu if (!alwaysReportSelfInit && DRE == Initializer->IgnoreParenImpCasts()) 651f6278e545d9bc09fb5d7579d1123f0a455352627Richard Trieu return false; 652f6278e545d9bc09fb5d7579d1123f0a455352627Richard Trieu 653f6278e545d9bc09fb5d7579d1123f0a455352627Richard Trieu ContainsReference CR(S.Context, DRE); 654f6278e545d9bc09fb5d7579d1123f0a455352627Richard Trieu CR.Visit(const_cast<Expr*>(Initializer)); 655f6278e545d9bc09fb5d7579d1123f0a455352627Richard Trieu if (CR.doesContainReference()) { 6564c4983bbd2904670a25c840b07600f14efbafd7fChandler Carruth S.Diag(DRE->getLocStart(), 6574c4983bbd2904670a25c840b07600f14efbafd7fChandler Carruth diag::warn_uninit_self_reference_in_init) 658f6278e545d9bc09fb5d7579d1123f0a455352627Richard Trieu << VD->getDeclName() << VD->getLocation() << DRE->getSourceRange(); 659f6278e545d9bc09fb5d7579d1123f0a455352627Richard Trieu return true; 6604c4983bbd2904670a25c840b07600f14efbafd7fChandler Carruth } 6614c4983bbd2904670a25c840b07600f14efbafd7fChandler Carruth } 662f6278e545d9bc09fb5d7579d1123f0a455352627Richard Trieu 663bdb97ff687ce85e45cc728b87612ed546f48c1e7Richard Smith DiagUninitUse(S, VD, Use, false); 6644c4983bbd2904670a25c840b07600f14efbafd7fChandler Carruth } else { 6652815e1a075c74143a0b60a632090ece1dffa5c7cRichard Smith const BlockExpr *BE = cast<BlockExpr>(Use.getUser()); 666bdb97ff687ce85e45cc728b87612ed546f48c1e7Richard Smith if (VD->getType()->isBlockPointerType() && !VD->hasAttr<BlocksAttr>()) 667bdb97ff687ce85e45cc728b87612ed546f48c1e7Richard Smith S.Diag(BE->getLocStart(), 668bdb97ff687ce85e45cc728b87612ed546f48c1e7Richard Smith diag::warn_uninit_byref_blockvar_captured_by_block) 669a34194f035096dd8dce10574e3a186da968aa211Fariborz Jahanian << VD->getDeclName(); 670bdb97ff687ce85e45cc728b87612ed546f48c1e7Richard Smith else 671bdb97ff687ce85e45cc728b87612ed546f48c1e7Richard Smith DiagUninitUse(S, VD, Use, true); 6724c4983bbd2904670a25c840b07600f14efbafd7fChandler Carruth } 6734c4983bbd2904670a25c840b07600f14efbafd7fChandler Carruth 6744c4983bbd2904670a25c840b07600f14efbafd7fChandler Carruth // Report where the variable was declared when the use wasn't within 6754f4f349208b2b2307454e169ac7b039e989f003fDavid Blaikie // the initializer of that declaration & we didn't already suggest 6764f4f349208b2b2307454e169ac7b039e989f003fDavid Blaikie // an initialization fixit. 677f6278e545d9bc09fb5d7579d1123f0a455352627Richard Trieu if (!SuggestInitializationFixit(S, VD)) 6784c4983bbd2904670a25c840b07600f14efbafd7fChandler Carruth S.Diag(VD->getLocStart(), diag::note_uninit_var_def) 6794c4983bbd2904670a25c840b07600f14efbafd7fChandler Carruth << VD->getDeclName(); 6804c4983bbd2904670a25c840b07600f14efbafd7fChandler Carruth 681262d50e1dcf529317da193ad585c11c16281a7acChandler Carruth return true; 68264fb959beb3a0ecb84a58e6ff82660a7a669f7b8Chandler Carruth} 68364fb959beb3a0ecb84a58e6ff82660a7a669f7b8Chandler Carruth 684e0d3b4cd2b66f1cef26cacbed5820ab7c22ad5b3Richard Smithnamespace { 685e0d3b4cd2b66f1cef26cacbed5820ab7c22ad5b3Richard Smith class FallthroughMapper : public RecursiveASTVisitor<FallthroughMapper> { 686e0d3b4cd2b66f1cef26cacbed5820ab7c22ad5b3Richard Smith public: 687e0d3b4cd2b66f1cef26cacbed5820ab7c22ad5b3Richard Smith FallthroughMapper(Sema &S) 688e0d3b4cd2b66f1cef26cacbed5820ab7c22ad5b3Richard Smith : FoundSwitchStatements(false), 689e0d3b4cd2b66f1cef26cacbed5820ab7c22ad5b3Richard Smith S(S) { 690e0d3b4cd2b66f1cef26cacbed5820ab7c22ad5b3Richard Smith } 691e0d3b4cd2b66f1cef26cacbed5820ab7c22ad5b3Richard Smith 692e0d3b4cd2b66f1cef26cacbed5820ab7c22ad5b3Richard Smith bool foundSwitchStatements() const { return FoundSwitchStatements; } 693e0d3b4cd2b66f1cef26cacbed5820ab7c22ad5b3Richard Smith 694e0d3b4cd2b66f1cef26cacbed5820ab7c22ad5b3Richard Smith void markFallthroughVisited(const AttributedStmt *Stmt) { 695e0d3b4cd2b66f1cef26cacbed5820ab7c22ad5b3Richard Smith bool Found = FallthroughStmts.erase(Stmt); 696e0d3b4cd2b66f1cef26cacbed5820ab7c22ad5b3Richard Smith assert(Found); 6973bb2994a7de3679fb825f3a36f3dc11ea1daf6a6Kaelyn Uhrain (void)Found; 698e0d3b4cd2b66f1cef26cacbed5820ab7c22ad5b3Richard Smith } 699e0d3b4cd2b66f1cef26cacbed5820ab7c22ad5b3Richard Smith 700e0d3b4cd2b66f1cef26cacbed5820ab7c22ad5b3Richard Smith typedef llvm::SmallPtrSet<const AttributedStmt*, 8> AttrStmts; 701e0d3b4cd2b66f1cef26cacbed5820ab7c22ad5b3Richard Smith 702e0d3b4cd2b66f1cef26cacbed5820ab7c22ad5b3Richard Smith const AttrStmts &getFallthroughStmts() const { 703e0d3b4cd2b66f1cef26cacbed5820ab7c22ad5b3Richard Smith return FallthroughStmts; 704e0d3b4cd2b66f1cef26cacbed5820ab7c22ad5b3Richard Smith } 705e0d3b4cd2b66f1cef26cacbed5820ab7c22ad5b3Richard Smith 7064874a8143dc3032205f97527ff619730db3d1f57Alexander Kornienko void fillReachableBlocks(CFG *Cfg) { 7074874a8143dc3032205f97527ff619730db3d1f57Alexander Kornienko assert(ReachableBlocks.empty() && "ReachableBlocks already filled"); 7084874a8143dc3032205f97527ff619730db3d1f57Alexander Kornienko std::deque<const CFGBlock *> BlockQueue; 7094874a8143dc3032205f97527ff619730db3d1f57Alexander Kornienko 7104874a8143dc3032205f97527ff619730db3d1f57Alexander Kornienko ReachableBlocks.insert(&Cfg->getEntry()); 7114874a8143dc3032205f97527ff619730db3d1f57Alexander Kornienko BlockQueue.push_back(&Cfg->getEntry()); 712878d0ad2c9d83ee6485fd16e21c5082acc63a890Alexander Kornienko // Mark all case blocks reachable to avoid problems with switching on 713878d0ad2c9d83ee6485fd16e21c5082acc63a890Alexander Kornienko // constants, covered enums, etc. 714878d0ad2c9d83ee6485fd16e21c5082acc63a890Alexander Kornienko // These blocks can contain fall-through annotations, and we don't want to 715878d0ad2c9d83ee6485fd16e21c5082acc63a890Alexander Kornienko // issue a warn_fallthrough_attr_unreachable for them. 716878d0ad2c9d83ee6485fd16e21c5082acc63a890Alexander Kornienko for (CFG::iterator I = Cfg->begin(), E = Cfg->end(); I != E; ++I) { 717878d0ad2c9d83ee6485fd16e21c5082acc63a890Alexander Kornienko const CFGBlock *B = *I; 718878d0ad2c9d83ee6485fd16e21c5082acc63a890Alexander Kornienko const Stmt *L = B->getLabel(); 719878d0ad2c9d83ee6485fd16e21c5082acc63a890Alexander Kornienko if (L && isa<SwitchCase>(L) && ReachableBlocks.insert(B)) 720878d0ad2c9d83ee6485fd16e21c5082acc63a890Alexander Kornienko BlockQueue.push_back(B); 721878d0ad2c9d83ee6485fd16e21c5082acc63a890Alexander Kornienko } 722878d0ad2c9d83ee6485fd16e21c5082acc63a890Alexander Kornienko 7234874a8143dc3032205f97527ff619730db3d1f57Alexander Kornienko while (!BlockQueue.empty()) { 7244874a8143dc3032205f97527ff619730db3d1f57Alexander Kornienko const CFGBlock *P = BlockQueue.front(); 7254874a8143dc3032205f97527ff619730db3d1f57Alexander Kornienko BlockQueue.pop_front(); 7264874a8143dc3032205f97527ff619730db3d1f57Alexander Kornienko for (CFGBlock::const_succ_iterator I = P->succ_begin(), 7274874a8143dc3032205f97527ff619730db3d1f57Alexander Kornienko E = P->succ_end(); 7284874a8143dc3032205f97527ff619730db3d1f57Alexander Kornienko I != E; ++I) { 7290162b832fd6450cd3a23019a3c900382d0e9415cAlexander Kornienko if (*I && ReachableBlocks.insert(*I)) 7304874a8143dc3032205f97527ff619730db3d1f57Alexander Kornienko BlockQueue.push_back(*I); 7314874a8143dc3032205f97527ff619730db3d1f57Alexander Kornienko } 7324874a8143dc3032205f97527ff619730db3d1f57Alexander Kornienko } 7334874a8143dc3032205f97527ff619730db3d1f57Alexander Kornienko } 7344874a8143dc3032205f97527ff619730db3d1f57Alexander Kornienko 735e0d3b4cd2b66f1cef26cacbed5820ab7c22ad5b3Richard Smith bool checkFallThroughIntoBlock(const CFGBlock &B, int &AnnotatedCnt) { 7364874a8143dc3032205f97527ff619730db3d1f57Alexander Kornienko assert(!ReachableBlocks.empty() && "ReachableBlocks empty"); 7374874a8143dc3032205f97527ff619730db3d1f57Alexander Kornienko 738e0d3b4cd2b66f1cef26cacbed5820ab7c22ad5b3Richard Smith int UnannotatedCnt = 0; 739e0d3b4cd2b66f1cef26cacbed5820ab7c22ad5b3Richard Smith AnnotatedCnt = 0; 740e0d3b4cd2b66f1cef26cacbed5820ab7c22ad5b3Richard Smith 741e0d3b4cd2b66f1cef26cacbed5820ab7c22ad5b3Richard Smith std::deque<const CFGBlock*> BlockQueue; 742e0d3b4cd2b66f1cef26cacbed5820ab7c22ad5b3Richard Smith 743e0d3b4cd2b66f1cef26cacbed5820ab7c22ad5b3Richard Smith std::copy(B.pred_begin(), B.pred_end(), std::back_inserter(BlockQueue)); 744e0d3b4cd2b66f1cef26cacbed5820ab7c22ad5b3Richard Smith 745e0d3b4cd2b66f1cef26cacbed5820ab7c22ad5b3Richard Smith while (!BlockQueue.empty()) { 746e0d3b4cd2b66f1cef26cacbed5820ab7c22ad5b3Richard Smith const CFGBlock *P = BlockQueue.front(); 747e0d3b4cd2b66f1cef26cacbed5820ab7c22ad5b3Richard Smith BlockQueue.pop_front(); 748e0d3b4cd2b66f1cef26cacbed5820ab7c22ad5b3Richard Smith 749e0d3b4cd2b66f1cef26cacbed5820ab7c22ad5b3Richard Smith const Stmt *Term = P->getTerminator(); 750e0d3b4cd2b66f1cef26cacbed5820ab7c22ad5b3Richard Smith if (Term && isa<SwitchStmt>(Term)) 751e0d3b4cd2b66f1cef26cacbed5820ab7c22ad5b3Richard Smith continue; // Switch statement, good. 752e0d3b4cd2b66f1cef26cacbed5820ab7c22ad5b3Richard Smith 753e0d3b4cd2b66f1cef26cacbed5820ab7c22ad5b3Richard Smith const SwitchCase *SW = dyn_cast_or_null<SwitchCase>(P->getLabel()); 754e0d3b4cd2b66f1cef26cacbed5820ab7c22ad5b3Richard Smith if (SW && SW->getSubStmt() == B.getLabel() && P->begin() == P->end()) 755e0d3b4cd2b66f1cef26cacbed5820ab7c22ad5b3Richard Smith continue; // Previous case label has no statements, good. 756e0d3b4cd2b66f1cef26cacbed5820ab7c22ad5b3Richard Smith 757c6dcea93b499b504da22f9921fc198423ad0b13bAlexander Kornienko const LabelStmt *L = dyn_cast_or_null<LabelStmt>(P->getLabel()); 758c6dcea93b499b504da22f9921fc198423ad0b13bAlexander Kornienko if (L && L->getSubStmt() == B.getLabel() && P->begin() == P->end()) 759c6dcea93b499b504da22f9921fc198423ad0b13bAlexander Kornienko continue; // Case label is preceded with a normal label, good. 760c6dcea93b499b504da22f9921fc198423ad0b13bAlexander Kornienko 7614874a8143dc3032205f97527ff619730db3d1f57Alexander Kornienko if (!ReachableBlocks.count(P)) { 762878d0ad2c9d83ee6485fd16e21c5082acc63a890Alexander Kornienko for (CFGBlock::const_reverse_iterator ElemIt = P->rbegin(), 763878d0ad2c9d83ee6485fd16e21c5082acc63a890Alexander Kornienko ElemEnd = P->rend(); 764878d0ad2c9d83ee6485fd16e21c5082acc63a890Alexander Kornienko ElemIt != ElemEnd; ++ElemIt) { 765b07805485c603be3d8011f72611465324c9e664bDavid Blaikie if (Optional<CFGStmt> CS = ElemIt->getAs<CFGStmt>()) { 766b07805485c603be3d8011f72611465324c9e664bDavid Blaikie if (const AttributedStmt *AS = asFallThroughAttr(CS->getStmt())) { 767e0d3b4cd2b66f1cef26cacbed5820ab7c22ad5b3Richard Smith S.Diag(AS->getLocStart(), 768e0d3b4cd2b66f1cef26cacbed5820ab7c22ad5b3Richard Smith diag::warn_fallthrough_attr_unreachable); 769e0d3b4cd2b66f1cef26cacbed5820ab7c22ad5b3Richard Smith markFallthroughVisited(AS); 770e0d3b4cd2b66f1cef26cacbed5820ab7c22ad5b3Richard Smith ++AnnotatedCnt; 771878d0ad2c9d83ee6485fd16e21c5082acc63a890Alexander Kornienko break; 772e0d3b4cd2b66f1cef26cacbed5820ab7c22ad5b3Richard Smith } 773e0d3b4cd2b66f1cef26cacbed5820ab7c22ad5b3Richard Smith // Don't care about other unreachable statements. 774e0d3b4cd2b66f1cef26cacbed5820ab7c22ad5b3Richard Smith } 775e0d3b4cd2b66f1cef26cacbed5820ab7c22ad5b3Richard Smith } 776e0d3b4cd2b66f1cef26cacbed5820ab7c22ad5b3Richard Smith // If there are no unreachable statements, this may be a special 777e0d3b4cd2b66f1cef26cacbed5820ab7c22ad5b3Richard Smith // case in CFG: 778e0d3b4cd2b66f1cef26cacbed5820ab7c22ad5b3Richard Smith // case X: { 779e0d3b4cd2b66f1cef26cacbed5820ab7c22ad5b3Richard Smith // A a; // A has a destructor. 780e0d3b4cd2b66f1cef26cacbed5820ab7c22ad5b3Richard Smith // break; 781e0d3b4cd2b66f1cef26cacbed5820ab7c22ad5b3Richard Smith // } 782e0d3b4cd2b66f1cef26cacbed5820ab7c22ad5b3Richard Smith // // <<<< This place is represented by a 'hanging' CFG block. 783e0d3b4cd2b66f1cef26cacbed5820ab7c22ad5b3Richard Smith // case Y: 784e0d3b4cd2b66f1cef26cacbed5820ab7c22ad5b3Richard Smith continue; 785e0d3b4cd2b66f1cef26cacbed5820ab7c22ad5b3Richard Smith } 786e0d3b4cd2b66f1cef26cacbed5820ab7c22ad5b3Richard Smith 787e0d3b4cd2b66f1cef26cacbed5820ab7c22ad5b3Richard Smith const Stmt *LastStmt = getLastStmt(*P); 788e0d3b4cd2b66f1cef26cacbed5820ab7c22ad5b3Richard Smith if (const AttributedStmt *AS = asFallThroughAttr(LastStmt)) { 789e0d3b4cd2b66f1cef26cacbed5820ab7c22ad5b3Richard Smith markFallthroughVisited(AS); 790e0d3b4cd2b66f1cef26cacbed5820ab7c22ad5b3Richard Smith ++AnnotatedCnt; 791e0d3b4cd2b66f1cef26cacbed5820ab7c22ad5b3Richard Smith continue; // Fallthrough annotation, good. 792e0d3b4cd2b66f1cef26cacbed5820ab7c22ad5b3Richard Smith } 793e0d3b4cd2b66f1cef26cacbed5820ab7c22ad5b3Richard Smith 794e0d3b4cd2b66f1cef26cacbed5820ab7c22ad5b3Richard Smith if (!LastStmt) { // This block contains no executable statements. 795e0d3b4cd2b66f1cef26cacbed5820ab7c22ad5b3Richard Smith // Traverse its predecessors. 796e0d3b4cd2b66f1cef26cacbed5820ab7c22ad5b3Richard Smith std::copy(P->pred_begin(), P->pred_end(), 797e0d3b4cd2b66f1cef26cacbed5820ab7c22ad5b3Richard Smith std::back_inserter(BlockQueue)); 798e0d3b4cd2b66f1cef26cacbed5820ab7c22ad5b3Richard Smith continue; 799e0d3b4cd2b66f1cef26cacbed5820ab7c22ad5b3Richard Smith } 800e0d3b4cd2b66f1cef26cacbed5820ab7c22ad5b3Richard Smith 801e0d3b4cd2b66f1cef26cacbed5820ab7c22ad5b3Richard Smith ++UnannotatedCnt; 802e0d3b4cd2b66f1cef26cacbed5820ab7c22ad5b3Richard Smith } 803e0d3b4cd2b66f1cef26cacbed5820ab7c22ad5b3Richard Smith return !!UnannotatedCnt; 804e0d3b4cd2b66f1cef26cacbed5820ab7c22ad5b3Richard Smith } 805e0d3b4cd2b66f1cef26cacbed5820ab7c22ad5b3Richard Smith 806e0d3b4cd2b66f1cef26cacbed5820ab7c22ad5b3Richard Smith // RecursiveASTVisitor setup. 807e0d3b4cd2b66f1cef26cacbed5820ab7c22ad5b3Richard Smith bool shouldWalkTypesOfTypeLocs() const { return false; } 808e0d3b4cd2b66f1cef26cacbed5820ab7c22ad5b3Richard Smith 809e0d3b4cd2b66f1cef26cacbed5820ab7c22ad5b3Richard Smith bool VisitAttributedStmt(AttributedStmt *S) { 810e0d3b4cd2b66f1cef26cacbed5820ab7c22ad5b3Richard Smith if (asFallThroughAttr(S)) 811e0d3b4cd2b66f1cef26cacbed5820ab7c22ad5b3Richard Smith FallthroughStmts.insert(S); 812e0d3b4cd2b66f1cef26cacbed5820ab7c22ad5b3Richard Smith return true; 813e0d3b4cd2b66f1cef26cacbed5820ab7c22ad5b3Richard Smith } 814e0d3b4cd2b66f1cef26cacbed5820ab7c22ad5b3Richard Smith 815e0d3b4cd2b66f1cef26cacbed5820ab7c22ad5b3Richard Smith bool VisitSwitchStmt(SwitchStmt *S) { 816e0d3b4cd2b66f1cef26cacbed5820ab7c22ad5b3Richard Smith FoundSwitchStatements = true; 817e0d3b4cd2b66f1cef26cacbed5820ab7c22ad5b3Richard Smith return true; 818e0d3b4cd2b66f1cef26cacbed5820ab7c22ad5b3Richard Smith } 819e0d3b4cd2b66f1cef26cacbed5820ab7c22ad5b3Richard Smith 820b0707c9a933b1839fa966e4c72e4dcb9a198f11fAlexander Kornienko // We don't want to traverse local type declarations. We analyze their 821b0707c9a933b1839fa966e4c72e4dcb9a198f11fAlexander Kornienko // methods separately. 822b0707c9a933b1839fa966e4c72e4dcb9a198f11fAlexander Kornienko bool TraverseDecl(Decl *D) { return true; } 823b0707c9a933b1839fa966e4c72e4dcb9a198f11fAlexander Kornienko 824e0d3b4cd2b66f1cef26cacbed5820ab7c22ad5b3Richard Smith private: 825e0d3b4cd2b66f1cef26cacbed5820ab7c22ad5b3Richard Smith 826e0d3b4cd2b66f1cef26cacbed5820ab7c22ad5b3Richard Smith static const AttributedStmt *asFallThroughAttr(const Stmt *S) { 827e0d3b4cd2b66f1cef26cacbed5820ab7c22ad5b3Richard Smith if (const AttributedStmt *AS = dyn_cast_or_null<AttributedStmt>(S)) { 828e0d3b4cd2b66f1cef26cacbed5820ab7c22ad5b3Richard Smith if (hasSpecificAttr<FallThroughAttr>(AS->getAttrs())) 829e0d3b4cd2b66f1cef26cacbed5820ab7c22ad5b3Richard Smith return AS; 830e0d3b4cd2b66f1cef26cacbed5820ab7c22ad5b3Richard Smith } 831e0d3b4cd2b66f1cef26cacbed5820ab7c22ad5b3Richard Smith return 0; 832e0d3b4cd2b66f1cef26cacbed5820ab7c22ad5b3Richard Smith } 833e0d3b4cd2b66f1cef26cacbed5820ab7c22ad5b3Richard Smith 834e0d3b4cd2b66f1cef26cacbed5820ab7c22ad5b3Richard Smith static const Stmt *getLastStmt(const CFGBlock &B) { 835e0d3b4cd2b66f1cef26cacbed5820ab7c22ad5b3Richard Smith if (const Stmt *Term = B.getTerminator()) 836e0d3b4cd2b66f1cef26cacbed5820ab7c22ad5b3Richard Smith return Term; 837e0d3b4cd2b66f1cef26cacbed5820ab7c22ad5b3Richard Smith for (CFGBlock::const_reverse_iterator ElemIt = B.rbegin(), 838e0d3b4cd2b66f1cef26cacbed5820ab7c22ad5b3Richard Smith ElemEnd = B.rend(); 839e0d3b4cd2b66f1cef26cacbed5820ab7c22ad5b3Richard Smith ElemIt != ElemEnd; ++ElemIt) { 840b07805485c603be3d8011f72611465324c9e664bDavid Blaikie if (Optional<CFGStmt> CS = ElemIt->getAs<CFGStmt>()) 841b07805485c603be3d8011f72611465324c9e664bDavid Blaikie return CS->getStmt(); 842e0d3b4cd2b66f1cef26cacbed5820ab7c22ad5b3Richard Smith } 843e0d3b4cd2b66f1cef26cacbed5820ab7c22ad5b3Richard Smith // Workaround to detect a statement thrown out by CFGBuilder: 844e0d3b4cd2b66f1cef26cacbed5820ab7c22ad5b3Richard Smith // case X: {} case Y: 845e0d3b4cd2b66f1cef26cacbed5820ab7c22ad5b3Richard Smith // case X: ; case Y: 846e0d3b4cd2b66f1cef26cacbed5820ab7c22ad5b3Richard Smith if (const SwitchCase *SW = dyn_cast_or_null<SwitchCase>(B.getLabel())) 847e0d3b4cd2b66f1cef26cacbed5820ab7c22ad5b3Richard Smith if (!isa<SwitchCase>(SW->getSubStmt())) 848e0d3b4cd2b66f1cef26cacbed5820ab7c22ad5b3Richard Smith return SW->getSubStmt(); 849e0d3b4cd2b66f1cef26cacbed5820ab7c22ad5b3Richard Smith 850e0d3b4cd2b66f1cef26cacbed5820ab7c22ad5b3Richard Smith return 0; 851e0d3b4cd2b66f1cef26cacbed5820ab7c22ad5b3Richard Smith } 852e0d3b4cd2b66f1cef26cacbed5820ab7c22ad5b3Richard Smith 853e0d3b4cd2b66f1cef26cacbed5820ab7c22ad5b3Richard Smith bool FoundSwitchStatements; 854e0d3b4cd2b66f1cef26cacbed5820ab7c22ad5b3Richard Smith AttrStmts FallthroughStmts; 855e0d3b4cd2b66f1cef26cacbed5820ab7c22ad5b3Richard Smith Sema &S; 8564874a8143dc3032205f97527ff619730db3d1f57Alexander Kornienko llvm::SmallPtrSet<const CFGBlock *, 16> ReachableBlocks; 857e0d3b4cd2b66f1cef26cacbed5820ab7c22ad5b3Richard Smith }; 858e0d3b4cd2b66f1cef26cacbed5820ab7c22ad5b3Richard Smith} 859e0d3b4cd2b66f1cef26cacbed5820ab7c22ad5b3Richard Smith 8601973634e445d4f1abdeedc2809f2d281929253b6Alexander Kornienkostatic void DiagnoseSwitchLabelsFallthrough(Sema &S, AnalysisDeclContext &AC, 861c2f51cfefd77e9b25f201ecf879343d6d9a45158Sean Hunt bool PerFunction) { 8623078353fb56772193b9304510048ac075a2c95b5Ted Kremenek // Only perform this analysis when using C++11. There is no good workflow 8633078353fb56772193b9304510048ac075a2c95b5Ted Kremenek // for this warning when not using C++11. There is no good way to silence 8643078353fb56772193b9304510048ac075a2c95b5Ted Kremenek // the warning (no attribute is available) unless we are using C++11's support 8653078353fb56772193b9304510048ac075a2c95b5Ted Kremenek // for generalized attributes. Once could use pragmas to silence the warning, 8663078353fb56772193b9304510048ac075a2c95b5Ted Kremenek // but as a general solution that is gross and not in the spirit of this 8673078353fb56772193b9304510048ac075a2c95b5Ted Kremenek // warning. 8683078353fb56772193b9304510048ac075a2c95b5Ted Kremenek // 8693078353fb56772193b9304510048ac075a2c95b5Ted Kremenek // NOTE: This an intermediate solution. There are on-going discussions on 8703078353fb56772193b9304510048ac075a2c95b5Ted Kremenek // how to properly support this warning outside of C++11 with an annotation. 87180ad52f327b532bded5c5b0ee38779d841c6cd35Richard Smith if (!AC.getASTContext().getLangOpts().CPlusPlus11) 8723078353fb56772193b9304510048ac075a2c95b5Ted Kremenek return; 8733078353fb56772193b9304510048ac075a2c95b5Ted Kremenek 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 8884874a8143dc3032205f97527ff619730db3d1f57Alexander Kornienko FM.fillReachableBlocks(Cfg); 889e0d3b4cd2b66f1cef26cacbed5820ab7c22ad5b3Richard Smith 890e0d3b4cd2b66f1cef26cacbed5820ab7c22ad5b3Richard Smith for (CFG::reverse_iterator I = Cfg->rbegin(), E = Cfg->rend(); I != E; ++I) { 891e992ed1a065d857947b3969e6b779c41cc35c234Alexander Kornienko const CFGBlock *B = *I; 892e992ed1a065d857947b3969e6b779c41cc35c234Alexander Kornienko const Stmt *Label = B->getLabel(); 893e0d3b4cd2b66f1cef26cacbed5820ab7c22ad5b3Richard Smith 894e0d3b4cd2b66f1cef26cacbed5820ab7c22ad5b3Richard Smith if (!Label || !isa<SwitchCase>(Label)) 895e0d3b4cd2b66f1cef26cacbed5820ab7c22ad5b3Richard Smith continue; 896e0d3b4cd2b66f1cef26cacbed5820ab7c22ad5b3Richard Smith 8974874a8143dc3032205f97527ff619730db3d1f57Alexander Kornienko int AnnotatedCnt; 8984874a8143dc3032205f97527ff619730db3d1f57Alexander Kornienko 899e992ed1a065d857947b3969e6b779c41cc35c234Alexander Kornienko if (!FM.checkFallThroughIntoBlock(*B, AnnotatedCnt)) 900e0d3b4cd2b66f1cef26cacbed5820ab7c22ad5b3Richard Smith continue; 901e0d3b4cd2b66f1cef26cacbed5820ab7c22ad5b3Richard Smith 9021973634e445d4f1abdeedc2809f2d281929253b6Alexander Kornienko S.Diag(Label->getLocStart(), 903c2f51cfefd77e9b25f201ecf879343d6d9a45158Sean Hunt PerFunction ? diag::warn_unannotated_fallthrough_per_function 904c2f51cfefd77e9b25f201ecf879343d6d9a45158Sean Hunt : diag::warn_unannotated_fallthrough); 905e0d3b4cd2b66f1cef26cacbed5820ab7c22ad5b3Richard Smith 906e0d3b4cd2b66f1cef26cacbed5820ab7c22ad5b3Richard Smith if (!AnnotatedCnt) { 907e0d3b4cd2b66f1cef26cacbed5820ab7c22ad5b3Richard Smith SourceLocation L = Label->getLocStart(); 908e0d3b4cd2b66f1cef26cacbed5820ab7c22ad5b3Richard Smith if (L.isMacroID()) 909e0d3b4cd2b66f1cef26cacbed5820ab7c22ad5b3Richard Smith continue; 91080ad52f327b532bded5c5b0ee38779d841c6cd35Richard Smith if (S.getLangOpts().CPlusPlus11) { 911e992ed1a065d857947b3969e6b779c41cc35c234Alexander Kornienko const Stmt *Term = B->getTerminator(); 912e992ed1a065d857947b3969e6b779c41cc35c234Alexander Kornienko // Skip empty cases. 913e992ed1a065d857947b3969e6b779c41cc35c234Alexander Kornienko while (B->empty() && !Term && B->succ_size() == 1) { 914e992ed1a065d857947b3969e6b779c41cc35c234Alexander Kornienko B = *B->succ_begin(); 915e992ed1a065d857947b3969e6b779c41cc35c234Alexander Kornienko Term = B->getTerminator(); 916e992ed1a065d857947b3969e6b779c41cc35c234Alexander Kornienko } 917e992ed1a065d857947b3969e6b779c41cc35c234Alexander Kornienko if (!(B->empty() && Term && isa<BreakStmt>(Term))) { 91866da0abf7ab7cd449bb1d5134b2ef97d9d34d812Alexander Kornienko Preprocessor &PP = S.getPreprocessor(); 91966da0abf7ab7cd449bb1d5134b2ef97d9d34d812Alexander Kornienko TokenValue Tokens[] = { 92066da0abf7ab7cd449bb1d5134b2ef97d9d34d812Alexander Kornienko tok::l_square, tok::l_square, PP.getIdentifierInfo("clang"), 92166da0abf7ab7cd449bb1d5134b2ef97d9d34d812Alexander Kornienko tok::coloncolon, PP.getIdentifierInfo("fallthrough"), 92266da0abf7ab7cd449bb1d5134b2ef97d9d34d812Alexander Kornienko tok::r_square, tok::r_square 92366da0abf7ab7cd449bb1d5134b2ef97d9d34d812Alexander Kornienko }; 9241952354bd376062c3ab3d328c0fc6c36530c9309Dmitri Gribenko StringRef AnnotationSpelling = "[[clang::fallthrough]]"; 9251952354bd376062c3ab3d328c0fc6c36530c9309Dmitri Gribenko StringRef MacroName = PP.getLastMacroWithSpelling(L, Tokens); 9261952354bd376062c3ab3d328c0fc6c36530c9309Dmitri Gribenko if (!MacroName.empty()) 9271952354bd376062c3ab3d328c0fc6c36530c9309Dmitri Gribenko AnnotationSpelling = MacroName; 9281952354bd376062c3ab3d328c0fc6c36530c9309Dmitri Gribenko SmallString<64> TextToInsert(AnnotationSpelling); 9291952354bd376062c3ab3d328c0fc6c36530c9309Dmitri Gribenko TextToInsert += "; "; 930a189d8976f1193b788508a1a29b2e9d0aca06acaAlexander Kornienko S.Diag(L, diag::note_insert_fallthrough_fixit) << 93166da0abf7ab7cd449bb1d5134b2ef97d9d34d812Alexander Kornienko AnnotationSpelling << 9321952354bd376062c3ab3d328c0fc6c36530c9309Dmitri Gribenko FixItHint::CreateInsertion(L, TextToInsert); 933a189d8976f1193b788508a1a29b2e9d0aca06acaAlexander Kornienko } 934e0d3b4cd2b66f1cef26cacbed5820ab7c22ad5b3Richard Smith } 935e0d3b4cd2b66f1cef26cacbed5820ab7c22ad5b3Richard Smith S.Diag(L, diag::note_insert_break_fixit) << 936e0d3b4cd2b66f1cef26cacbed5820ab7c22ad5b3Richard Smith FixItHint::CreateInsertion(L, "break; "); 937e0d3b4cd2b66f1cef26cacbed5820ab7c22ad5b3Richard Smith } 938e0d3b4cd2b66f1cef26cacbed5820ab7c22ad5b3Richard Smith } 939e0d3b4cd2b66f1cef26cacbed5820ab7c22ad5b3Richard Smith 940e0d3b4cd2b66f1cef26cacbed5820ab7c22ad5b3Richard Smith const FallthroughMapper::AttrStmts &Fallthroughs = FM.getFallthroughStmts(); 941e0d3b4cd2b66f1cef26cacbed5820ab7c22ad5b3Richard Smith for (FallthroughMapper::AttrStmts::const_iterator I = Fallthroughs.begin(), 942e0d3b4cd2b66f1cef26cacbed5820ab7c22ad5b3Richard Smith E = Fallthroughs.end(); 943e0d3b4cd2b66f1cef26cacbed5820ab7c22ad5b3Richard Smith I != E; ++I) { 944e0d3b4cd2b66f1cef26cacbed5820ab7c22ad5b3Richard Smith S.Diag((*I)->getLocStart(), diag::warn_fallthrough_attr_invalid_placement); 945e0d3b4cd2b66f1cef26cacbed5820ab7c22ad5b3Richard Smith } 946e0d3b4cd2b66f1cef26cacbed5820ab7c22ad5b3Richard Smith 947e0d3b4cd2b66f1cef26cacbed5820ab7c22ad5b3Richard Smith} 948e0d3b4cd2b66f1cef26cacbed5820ab7c22ad5b3Richard Smith 949610068c8cd2321f90e147b12cf794e1f840b6405Ted Kremeneknamespace { 95020441c59a00afb949e53121c55f8a58da17ba79eJordan Rosetypedef std::pair<const Stmt *, 95120441c59a00afb949e53121c55f8a58da17ba79eJordan Rose sema::FunctionScopeInfo::WeakObjectUseMap::const_iterator> 95220441c59a00afb949e53121c55f8a58da17ba79eJordan Rose StmtUsesPair; 95358b6bdcdeb683a3504f2248a409e1f4e85876ceeJordan Rose 95420441c59a00afb949e53121c55f8a58da17ba79eJordan Roseclass StmtUseSorter { 95558b6bdcdeb683a3504f2248a409e1f4e85876ceeJordan Rose const SourceManager &SM; 95658b6bdcdeb683a3504f2248a409e1f4e85876ceeJordan Rose 95758b6bdcdeb683a3504f2248a409e1f4e85876ceeJordan Rosepublic: 95820441c59a00afb949e53121c55f8a58da17ba79eJordan Rose explicit StmtUseSorter(const SourceManager &SM) : SM(SM) { } 95958b6bdcdeb683a3504f2248a409e1f4e85876ceeJordan Rose 96058b6bdcdeb683a3504f2248a409e1f4e85876ceeJordan Rose bool operator()(const StmtUsesPair &LHS, const StmtUsesPair &RHS) { 96158b6bdcdeb683a3504f2248a409e1f4e85876ceeJordan Rose return SM.isBeforeInTranslationUnit(LHS.first->getLocStart(), 96258b6bdcdeb683a3504f2248a409e1f4e85876ceeJordan Rose RHS.first->getLocStart()); 96358b6bdcdeb683a3504f2248a409e1f4e85876ceeJordan Rose } 96458b6bdcdeb683a3504f2248a409e1f4e85876ceeJordan Rose}; 96520441c59a00afb949e53121c55f8a58da17ba79eJordan Rose} 96658b6bdcdeb683a3504f2248a409e1f4e85876ceeJordan Rose 967c0e44454bd78b8b4f3d70f08cf1edd5466b0c798Jordan Rosestatic bool isInLoop(const ASTContext &Ctx, const ParentMap &PM, 968c0e44454bd78b8b4f3d70f08cf1edd5466b0c798Jordan Rose const Stmt *S) { 969b5cd1220dd650a358622241237aa595c5d675506Jordan Rose assert(S); 970b5cd1220dd650a358622241237aa595c5d675506Jordan Rose 971b5cd1220dd650a358622241237aa595c5d675506Jordan Rose do { 972b5cd1220dd650a358622241237aa595c5d675506Jordan Rose switch (S->getStmtClass()) { 973b5cd1220dd650a358622241237aa595c5d675506Jordan Rose case Stmt::ForStmtClass: 974b5cd1220dd650a358622241237aa595c5d675506Jordan Rose case Stmt::WhileStmtClass: 975b5cd1220dd650a358622241237aa595c5d675506Jordan Rose case Stmt::CXXForRangeStmtClass: 976b5cd1220dd650a358622241237aa595c5d675506Jordan Rose case Stmt::ObjCForCollectionStmtClass: 977b5cd1220dd650a358622241237aa595c5d675506Jordan Rose return true; 978c0e44454bd78b8b4f3d70f08cf1edd5466b0c798Jordan Rose case Stmt::DoStmtClass: { 979c0e44454bd78b8b4f3d70f08cf1edd5466b0c798Jordan Rose const Expr *Cond = cast<DoStmt>(S)->getCond(); 980c0e44454bd78b8b4f3d70f08cf1edd5466b0c798Jordan Rose llvm::APSInt Val; 981c0e44454bd78b8b4f3d70f08cf1edd5466b0c798Jordan Rose if (!Cond->EvaluateAsInt(Val, Ctx)) 982c0e44454bd78b8b4f3d70f08cf1edd5466b0c798Jordan Rose return true; 983c0e44454bd78b8b4f3d70f08cf1edd5466b0c798Jordan Rose return Val.getBoolValue(); 984c0e44454bd78b8b4f3d70f08cf1edd5466b0c798Jordan Rose } 985b5cd1220dd650a358622241237aa595c5d675506Jordan Rose default: 986b5cd1220dd650a358622241237aa595c5d675506Jordan Rose break; 987b5cd1220dd650a358622241237aa595c5d675506Jordan Rose } 988b5cd1220dd650a358622241237aa595c5d675506Jordan Rose } while ((S = PM.getParent(S))); 989b5cd1220dd650a358622241237aa595c5d675506Jordan Rose 990b5cd1220dd650a358622241237aa595c5d675506Jordan Rose return false; 991b5cd1220dd650a358622241237aa595c5d675506Jordan Rose} 992b5cd1220dd650a358622241237aa595c5d675506Jordan Rose 99358b6bdcdeb683a3504f2248a409e1f4e85876ceeJordan Rose 99458b6bdcdeb683a3504f2248a409e1f4e85876ceeJordan Rosestatic void diagnoseRepeatedUseOfWeak(Sema &S, 99558b6bdcdeb683a3504f2248a409e1f4e85876ceeJordan Rose const sema::FunctionScopeInfo *CurFn, 996b5cd1220dd650a358622241237aa595c5d675506Jordan Rose const Decl *D, 997b5cd1220dd650a358622241237aa595c5d675506Jordan Rose const ParentMap &PM) { 99858b6bdcdeb683a3504f2248a409e1f4e85876ceeJordan Rose typedef sema::FunctionScopeInfo::WeakObjectProfileTy WeakObjectProfileTy; 99958b6bdcdeb683a3504f2248a409e1f4e85876ceeJordan Rose typedef sema::FunctionScopeInfo::WeakObjectUseMap WeakObjectUseMap; 100058b6bdcdeb683a3504f2248a409e1f4e85876ceeJordan Rose typedef sema::FunctionScopeInfo::WeakUseVector WeakUseVector; 100158b6bdcdeb683a3504f2248a409e1f4e85876ceeJordan Rose 1002c0e44454bd78b8b4f3d70f08cf1edd5466b0c798Jordan Rose ASTContext &Ctx = S.getASTContext(); 1003c0e44454bd78b8b4f3d70f08cf1edd5466b0c798Jordan Rose 100458b6bdcdeb683a3504f2248a409e1f4e85876ceeJordan Rose const WeakObjectUseMap &WeakMap = CurFn->getWeakObjectUses(); 100558b6bdcdeb683a3504f2248a409e1f4e85876ceeJordan Rose 100658b6bdcdeb683a3504f2248a409e1f4e85876ceeJordan Rose // Extract all weak objects that are referenced more than once. 100758b6bdcdeb683a3504f2248a409e1f4e85876ceeJordan Rose SmallVector<StmtUsesPair, 8> UsesByStmt; 100858b6bdcdeb683a3504f2248a409e1f4e85876ceeJordan Rose for (WeakObjectUseMap::const_iterator I = WeakMap.begin(), E = WeakMap.end(); 100958b6bdcdeb683a3504f2248a409e1f4e85876ceeJordan Rose I != E; ++I) { 101058b6bdcdeb683a3504f2248a409e1f4e85876ceeJordan Rose const WeakUseVector &Uses = I->second; 101158b6bdcdeb683a3504f2248a409e1f4e85876ceeJordan Rose 101258b6bdcdeb683a3504f2248a409e1f4e85876ceeJordan Rose // Find the first read of the weak object. 101358b6bdcdeb683a3504f2248a409e1f4e85876ceeJordan Rose WeakUseVector::const_iterator UI = Uses.begin(), UE = Uses.end(); 101458b6bdcdeb683a3504f2248a409e1f4e85876ceeJordan Rose for ( ; UI != UE; ++UI) { 101558b6bdcdeb683a3504f2248a409e1f4e85876ceeJordan Rose if (UI->isUnsafe()) 101658b6bdcdeb683a3504f2248a409e1f4e85876ceeJordan Rose break; 101758b6bdcdeb683a3504f2248a409e1f4e85876ceeJordan Rose } 101858b6bdcdeb683a3504f2248a409e1f4e85876ceeJordan Rose 101958b6bdcdeb683a3504f2248a409e1f4e85876ceeJordan Rose // If there were only writes to this object, don't warn. 102058b6bdcdeb683a3504f2248a409e1f4e85876ceeJordan Rose if (UI == UE) 102158b6bdcdeb683a3504f2248a409e1f4e85876ceeJordan Rose continue; 102258b6bdcdeb683a3504f2248a409e1f4e85876ceeJordan Rose 1023b5cd1220dd650a358622241237aa595c5d675506Jordan Rose // If there was only one read, followed by any number of writes, and the 1024c0e44454bd78b8b4f3d70f08cf1edd5466b0c798Jordan Rose // read is not within a loop, don't warn. Additionally, don't warn in a 1025c0e44454bd78b8b4f3d70f08cf1edd5466b0c798Jordan Rose // loop if the base object is a local variable -- local variables are often 1026c0e44454bd78b8b4f3d70f08cf1edd5466b0c798Jordan Rose // changed in loops. 1027b5cd1220dd650a358622241237aa595c5d675506Jordan Rose if (UI == Uses.begin()) { 1028b5cd1220dd650a358622241237aa595c5d675506Jordan Rose WeakUseVector::const_iterator UI2 = UI; 1029b5cd1220dd650a358622241237aa595c5d675506Jordan Rose for (++UI2; UI2 != UE; ++UI2) 1030b5cd1220dd650a358622241237aa595c5d675506Jordan Rose if (UI2->isUnsafe()) 1031b5cd1220dd650a358622241237aa595c5d675506Jordan Rose break; 1032b5cd1220dd650a358622241237aa595c5d675506Jordan Rose 1033c0e44454bd78b8b4f3d70f08cf1edd5466b0c798Jordan Rose if (UI2 == UE) { 1034c0e44454bd78b8b4f3d70f08cf1edd5466b0c798Jordan Rose if (!isInLoop(Ctx, PM, UI->getUseExpr())) 1035b5cd1220dd650a358622241237aa595c5d675506Jordan Rose continue; 1036c0e44454bd78b8b4f3d70f08cf1edd5466b0c798Jordan Rose 1037c0e44454bd78b8b4f3d70f08cf1edd5466b0c798Jordan Rose const WeakObjectProfileTy &Profile = I->first; 1038c0e44454bd78b8b4f3d70f08cf1edd5466b0c798Jordan Rose if (!Profile.isExactProfile()) 1039c0e44454bd78b8b4f3d70f08cf1edd5466b0c798Jordan Rose continue; 1040c0e44454bd78b8b4f3d70f08cf1edd5466b0c798Jordan Rose 1041c0e44454bd78b8b4f3d70f08cf1edd5466b0c798Jordan Rose const NamedDecl *Base = Profile.getBase(); 1042c0e44454bd78b8b4f3d70f08cf1edd5466b0c798Jordan Rose if (!Base) 1043c0e44454bd78b8b4f3d70f08cf1edd5466b0c798Jordan Rose Base = Profile.getProperty(); 1044c0e44454bd78b8b4f3d70f08cf1edd5466b0c798Jordan Rose assert(Base && "A profile always has a base or property."); 1045c0e44454bd78b8b4f3d70f08cf1edd5466b0c798Jordan Rose 1046c0e44454bd78b8b4f3d70f08cf1edd5466b0c798Jordan Rose if (const VarDecl *BaseVar = dyn_cast<VarDecl>(Base)) 1047c0e44454bd78b8b4f3d70f08cf1edd5466b0c798Jordan Rose if (BaseVar->hasLocalStorage() && !isa<ParmVarDecl>(Base)) 1048c0e44454bd78b8b4f3d70f08cf1edd5466b0c798Jordan Rose continue; 1049c0e44454bd78b8b4f3d70f08cf1edd5466b0c798Jordan Rose } 1050b5cd1220dd650a358622241237aa595c5d675506Jordan Rose } 1051b5cd1220dd650a358622241237aa595c5d675506Jordan Rose 105258b6bdcdeb683a3504f2248a409e1f4e85876ceeJordan Rose UsesByStmt.push_back(StmtUsesPair(UI->getUseExpr(), I)); 105358b6bdcdeb683a3504f2248a409e1f4e85876ceeJordan Rose } 105458b6bdcdeb683a3504f2248a409e1f4e85876ceeJordan Rose 105558b6bdcdeb683a3504f2248a409e1f4e85876ceeJordan Rose if (UsesByStmt.empty()) 105658b6bdcdeb683a3504f2248a409e1f4e85876ceeJordan Rose return; 105758b6bdcdeb683a3504f2248a409e1f4e85876ceeJordan Rose 105858b6bdcdeb683a3504f2248a409e1f4e85876ceeJordan Rose // Sort by first use so that we emit the warnings in a deterministic order. 105958b6bdcdeb683a3504f2248a409e1f4e85876ceeJordan Rose std::sort(UsesByStmt.begin(), UsesByStmt.end(), 106020441c59a00afb949e53121c55f8a58da17ba79eJordan Rose StmtUseSorter(S.getSourceManager())); 106158b6bdcdeb683a3504f2248a409e1f4e85876ceeJordan Rose 106258b6bdcdeb683a3504f2248a409e1f4e85876ceeJordan Rose // Classify the current code body for better warning text. 106358b6bdcdeb683a3504f2248a409e1f4e85876ceeJordan Rose // This enum should stay in sync with the cases in 106458b6bdcdeb683a3504f2248a409e1f4e85876ceeJordan Rose // warn_arc_repeated_use_of_weak and warn_arc_possible_repeated_use_of_weak. 106558b6bdcdeb683a3504f2248a409e1f4e85876ceeJordan Rose // FIXME: Should we use a common classification enum and the same set of 106658b6bdcdeb683a3504f2248a409e1f4e85876ceeJordan Rose // possibilities all throughout Sema? 106758b6bdcdeb683a3504f2248a409e1f4e85876ceeJordan Rose enum { 106858b6bdcdeb683a3504f2248a409e1f4e85876ceeJordan Rose Function, 106958b6bdcdeb683a3504f2248a409e1f4e85876ceeJordan Rose Method, 107058b6bdcdeb683a3504f2248a409e1f4e85876ceeJordan Rose Block, 107158b6bdcdeb683a3504f2248a409e1f4e85876ceeJordan Rose Lambda 107258b6bdcdeb683a3504f2248a409e1f4e85876ceeJordan Rose } FunctionKind; 107358b6bdcdeb683a3504f2248a409e1f4e85876ceeJordan Rose 107458b6bdcdeb683a3504f2248a409e1f4e85876ceeJordan Rose if (isa<sema::BlockScopeInfo>(CurFn)) 107558b6bdcdeb683a3504f2248a409e1f4e85876ceeJordan Rose FunctionKind = Block; 107658b6bdcdeb683a3504f2248a409e1f4e85876ceeJordan Rose else if (isa<sema::LambdaScopeInfo>(CurFn)) 107758b6bdcdeb683a3504f2248a409e1f4e85876ceeJordan Rose FunctionKind = Lambda; 107858b6bdcdeb683a3504f2248a409e1f4e85876ceeJordan Rose else if (isa<ObjCMethodDecl>(D)) 107958b6bdcdeb683a3504f2248a409e1f4e85876ceeJordan Rose FunctionKind = Method; 108058b6bdcdeb683a3504f2248a409e1f4e85876ceeJordan Rose else 108158b6bdcdeb683a3504f2248a409e1f4e85876ceeJordan Rose FunctionKind = Function; 108258b6bdcdeb683a3504f2248a409e1f4e85876ceeJordan Rose 108358b6bdcdeb683a3504f2248a409e1f4e85876ceeJordan Rose // Iterate through the sorted problems and emit warnings for each. 108458b6bdcdeb683a3504f2248a409e1f4e85876ceeJordan Rose for (SmallVectorImpl<StmtUsesPair>::const_iterator I = UsesByStmt.begin(), 108558b6bdcdeb683a3504f2248a409e1f4e85876ceeJordan Rose E = UsesByStmt.end(); 108658b6bdcdeb683a3504f2248a409e1f4e85876ceeJordan Rose I != E; ++I) { 108758b6bdcdeb683a3504f2248a409e1f4e85876ceeJordan Rose const Stmt *FirstRead = I->first; 108858b6bdcdeb683a3504f2248a409e1f4e85876ceeJordan Rose const WeakObjectProfileTy &Key = I->second->first; 108958b6bdcdeb683a3504f2248a409e1f4e85876ceeJordan Rose const WeakUseVector &Uses = I->second->second; 109058b6bdcdeb683a3504f2248a409e1f4e85876ceeJordan Rose 10917a2704800943fbb69207e125d28186278712af36Jordan Rose // For complicated expressions like 'a.b.c' and 'x.b.c', WeakObjectProfileTy 10927a2704800943fbb69207e125d28186278712af36Jordan Rose // may not contain enough information to determine that these are different 10937a2704800943fbb69207e125d28186278712af36Jordan Rose // properties. We can only be 100% sure of a repeated use in certain cases, 10947a2704800943fbb69207e125d28186278712af36Jordan Rose // and we adjust the diagnostic kind accordingly so that the less certain 10957a2704800943fbb69207e125d28186278712af36Jordan Rose // case can be turned off if it is too noisy. 109658b6bdcdeb683a3504f2248a409e1f4e85876ceeJordan Rose unsigned DiagKind; 109758b6bdcdeb683a3504f2248a409e1f4e85876ceeJordan Rose if (Key.isExactProfile()) 109858b6bdcdeb683a3504f2248a409e1f4e85876ceeJordan Rose DiagKind = diag::warn_arc_repeated_use_of_weak; 109958b6bdcdeb683a3504f2248a409e1f4e85876ceeJordan Rose else 110058b6bdcdeb683a3504f2248a409e1f4e85876ceeJordan Rose DiagKind = diag::warn_arc_possible_repeated_use_of_weak; 110158b6bdcdeb683a3504f2248a409e1f4e85876ceeJordan Rose 11027a2704800943fbb69207e125d28186278712af36Jordan Rose // Classify the weak object being accessed for better warning text. 11037a2704800943fbb69207e125d28186278712af36Jordan Rose // This enum should stay in sync with the cases in 11047a2704800943fbb69207e125d28186278712af36Jordan Rose // warn_arc_repeated_use_of_weak and warn_arc_possible_repeated_use_of_weak. 11057a2704800943fbb69207e125d28186278712af36Jordan Rose enum { 11067a2704800943fbb69207e125d28186278712af36Jordan Rose Variable, 11077a2704800943fbb69207e125d28186278712af36Jordan Rose Property, 11087a2704800943fbb69207e125d28186278712af36Jordan Rose ImplicitProperty, 11097a2704800943fbb69207e125d28186278712af36Jordan Rose Ivar 11107a2704800943fbb69207e125d28186278712af36Jordan Rose } ObjectKind; 11117a2704800943fbb69207e125d28186278712af36Jordan Rose 11127a2704800943fbb69207e125d28186278712af36Jordan Rose const NamedDecl *D = Key.getProperty(); 11137a2704800943fbb69207e125d28186278712af36Jordan Rose if (isa<VarDecl>(D)) 11147a2704800943fbb69207e125d28186278712af36Jordan Rose ObjectKind = Variable; 11157a2704800943fbb69207e125d28186278712af36Jordan Rose else if (isa<ObjCPropertyDecl>(D)) 11167a2704800943fbb69207e125d28186278712af36Jordan Rose ObjectKind = Property; 11177a2704800943fbb69207e125d28186278712af36Jordan Rose else if (isa<ObjCMethodDecl>(D)) 11187a2704800943fbb69207e125d28186278712af36Jordan Rose ObjectKind = ImplicitProperty; 11197a2704800943fbb69207e125d28186278712af36Jordan Rose else if (isa<ObjCIvarDecl>(D)) 11207a2704800943fbb69207e125d28186278712af36Jordan Rose ObjectKind = Ivar; 11217a2704800943fbb69207e125d28186278712af36Jordan Rose else 11227a2704800943fbb69207e125d28186278712af36Jordan Rose llvm_unreachable("Unexpected weak object kind!"); 11237a2704800943fbb69207e125d28186278712af36Jordan Rose 112458b6bdcdeb683a3504f2248a409e1f4e85876ceeJordan Rose // Show the first time the object was read. 112558b6bdcdeb683a3504f2248a409e1f4e85876ceeJordan Rose S.Diag(FirstRead->getLocStart(), DiagKind) 11267348454025693dd20a411c2bcaabd4460cb87559Joerg Sonnenberger << int(ObjectKind) << D << int(FunctionKind) 112758b6bdcdeb683a3504f2248a409e1f4e85876ceeJordan Rose << FirstRead->getSourceRange(); 112858b6bdcdeb683a3504f2248a409e1f4e85876ceeJordan Rose 112958b6bdcdeb683a3504f2248a409e1f4e85876ceeJordan Rose // Print all the other accesses as notes. 113058b6bdcdeb683a3504f2248a409e1f4e85876ceeJordan Rose for (WeakUseVector::const_iterator UI = Uses.begin(), UE = Uses.end(); 113158b6bdcdeb683a3504f2248a409e1f4e85876ceeJordan Rose UI != UE; ++UI) { 113258b6bdcdeb683a3504f2248a409e1f4e85876ceeJordan Rose if (UI->getUseExpr() == FirstRead) 113358b6bdcdeb683a3504f2248a409e1f4e85876ceeJordan Rose continue; 113458b6bdcdeb683a3504f2248a409e1f4e85876ceeJordan Rose S.Diag(UI->getUseExpr()->getLocStart(), 113558b6bdcdeb683a3504f2248a409e1f4e85876ceeJordan Rose diag::note_arc_weak_also_accessed_here) 113658b6bdcdeb683a3504f2248a409e1f4e85876ceeJordan Rose << UI->getUseExpr()->getSourceRange(); 113758b6bdcdeb683a3504f2248a409e1f4e85876ceeJordan Rose } 113858b6bdcdeb683a3504f2248a409e1f4e85876ceeJordan Rose } 113958b6bdcdeb683a3504f2248a409e1f4e85876ceeJordan Rose} 114058b6bdcdeb683a3504f2248a409e1f4e85876ceeJordan Rose 114158b6bdcdeb683a3504f2248a409e1f4e85876ceeJordan Rose 114258b6bdcdeb683a3504f2248a409e1f4e85876ceeJordan Rosenamespace { 114394b1b4d785bc0f09f6af4be394e59d51f35dda60Ted Kremenekstruct SLocSort { 1144f7bafc77ba12bb1beb665243a0334cd81e024728Ted Kremenek bool operator()(const UninitUse &a, const UninitUse &b) { 11452815e1a075c74143a0b60a632090ece1dffa5c7cRichard Smith // Prefer a more confident report over a less confident one. 11462815e1a075c74143a0b60a632090ece1dffa5c7cRichard Smith if (a.getKind() != b.getKind()) 11472815e1a075c74143a0b60a632090ece1dffa5c7cRichard Smith return a.getKind() > b.getKind(); 11482815e1a075c74143a0b60a632090ece1dffa5c7cRichard Smith SourceLocation aLoc = a.getUser()->getLocStart(); 11492815e1a075c74143a0b60a632090ece1dffa5c7cRichard Smith SourceLocation bLoc = b.getUser()->getLocStart(); 115094b1b4d785bc0f09f6af4be394e59d51f35dda60Ted Kremenek return aLoc.getRawEncoding() < bLoc.getRawEncoding(); 115194b1b4d785bc0f09f6af4be394e59d51f35dda60Ted Kremenek } 115294b1b4d785bc0f09f6af4be394e59d51f35dda60Ted Kremenek}; 115394b1b4d785bc0f09f6af4be394e59d51f35dda60Ted Kremenek 1154610068c8cd2321f90e147b12cf794e1f840b6405Ted Kremenekclass UninitValsDiagReporter : public UninitVariablesHandler { 1155610068c8cd2321f90e147b12cf794e1f840b6405Ted Kremenek Sema &S; 11565f9e272e632e951b1efe824cd16acb4d96077930Chris Lattner typedef SmallVector<UninitUse, 2> UsesVec; 11573285c78041f80a26f6a947e2922e15c4af6e00bbEnea Zaffanella typedef std::pair<UsesVec*, bool> MappedType; 11583285c78041f80a26f6a947e2922e15c4af6e00bbEnea Zaffanella // Prefer using MapVector to DenseMap, so that iteration order will be 11593285c78041f80a26f6a947e2922e15c4af6e00bbEnea Zaffanella // the same as insertion order. This is needed to obtain a deterministic 11603285c78041f80a26f6a947e2922e15c4af6e00bbEnea Zaffanella // order of diagnostics when calling flushDiagnostics(). 11613285c78041f80a26f6a947e2922e15c4af6e00bbEnea Zaffanella typedef llvm::MapVector<const VarDecl *, MappedType> UsesMap; 116294b1b4d785bc0f09f6af4be394e59d51f35dda60Ted Kremenek UsesMap *uses; 116394b1b4d785bc0f09f6af4be394e59d51f35dda60Ted Kremenek 1164610068c8cd2321f90e147b12cf794e1f840b6405Ted Kremenekpublic: 116594b1b4d785bc0f09f6af4be394e59d51f35dda60Ted Kremenek UninitValsDiagReporter(Sema &S) : S(S), uses(0) {} 116694b1b4d785bc0f09f6af4be394e59d51f35dda60Ted Kremenek ~UninitValsDiagReporter() { 116794b1b4d785bc0f09f6af4be394e59d51f35dda60Ted Kremenek flushDiagnostics(); 116894b1b4d785bc0f09f6af4be394e59d51f35dda60Ted Kremenek } 11699e7617220135a6f6226cf09cb242cc1b905aedb4Ted Kremenek 11703285c78041f80a26f6a947e2922e15c4af6e00bbEnea Zaffanella MappedType &getUses(const VarDecl *vd) { 117194b1b4d785bc0f09f6af4be394e59d51f35dda60Ted Kremenek if (!uses) 117294b1b4d785bc0f09f6af4be394e59d51f35dda60Ted Kremenek uses = new UsesMap(); 11739e7617220135a6f6226cf09cb242cc1b905aedb4Ted Kremenek 11743285c78041f80a26f6a947e2922e15c4af6e00bbEnea Zaffanella MappedType &V = (*uses)[vd]; 11759e7617220135a6f6226cf09cb242cc1b905aedb4Ted Kremenek UsesVec *&vec = V.first; 117694b1b4d785bc0f09f6af4be394e59d51f35dda60Ted Kremenek if (!vec) 117794b1b4d785bc0f09f6af4be394e59d51f35dda60Ted Kremenek vec = new UsesVec(); 117894b1b4d785bc0f09f6af4be394e59d51f35dda60Ted Kremenek 11799e7617220135a6f6226cf09cb242cc1b905aedb4Ted Kremenek return V; 11809e7617220135a6f6226cf09cb242cc1b905aedb4Ted Kremenek } 11819e7617220135a6f6226cf09cb242cc1b905aedb4Ted Kremenek 11822815e1a075c74143a0b60a632090ece1dffa5c7cRichard Smith void handleUseOfUninitVariable(const VarDecl *vd, const UninitUse &use) { 11832815e1a075c74143a0b60a632090ece1dffa5c7cRichard Smith getUses(vd).first->push_back(use); 11849e7617220135a6f6226cf09cb242cc1b905aedb4Ted Kremenek } 11859e7617220135a6f6226cf09cb242cc1b905aedb4Ted Kremenek 11869e7617220135a6f6226cf09cb242cc1b905aedb4Ted Kremenek void handleSelfInit(const VarDecl *vd) { 11879e7617220135a6f6226cf09cb242cc1b905aedb4Ted Kremenek getUses(vd).second = true; 118894b1b4d785bc0f09f6af4be394e59d51f35dda60Ted Kremenek } 118994b1b4d785bc0f09f6af4be394e59d51f35dda60Ted Kremenek 119094b1b4d785bc0f09f6af4be394e59d51f35dda60Ted Kremenek void flushDiagnostics() { 119194b1b4d785bc0f09f6af4be394e59d51f35dda60Ted Kremenek if (!uses) 119294b1b4d785bc0f09f6af4be394e59d51f35dda60Ted Kremenek return; 11933285c78041f80a26f6a947e2922e15c4af6e00bbEnea Zaffanella 119494b1b4d785bc0f09f6af4be394e59d51f35dda60Ted Kremenek for (UsesMap::iterator i = uses->begin(), e = uses->end(); i != e; ++i) { 119594b1b4d785bc0f09f6af4be394e59d51f35dda60Ted Kremenek const VarDecl *vd = i->first; 11963285c78041f80a26f6a947e2922e15c4af6e00bbEnea Zaffanella const MappedType &V = i->second; 11979e7617220135a6f6226cf09cb242cc1b905aedb4Ted Kremenek 11989e7617220135a6f6226cf09cb242cc1b905aedb4Ted Kremenek UsesVec *vec = V.first; 11999e7617220135a6f6226cf09cb242cc1b905aedb4Ted Kremenek bool hasSelfInit = V.second; 12009e7617220135a6f6226cf09cb242cc1b905aedb4Ted Kremenek 12019e7617220135a6f6226cf09cb242cc1b905aedb4Ted Kremenek // Specially handle the case where we have uses of an uninitialized 12029e7617220135a6f6226cf09cb242cc1b905aedb4Ted Kremenek // variable, but the root cause is an idiomatic self-init. We want 12039e7617220135a6f6226cf09cb242cc1b905aedb4Ted Kremenek // to report the diagnostic at the self-init since that is the root cause. 12040d381810da19dd7677b9a79fca516d298fa5addbMatt Beaumont-Gay if (!vec->empty() && hasSelfInit && hasAlwaysUninitializedUse(vec)) 12052815e1a075c74143a0b60a632090ece1dffa5c7cRichard Smith DiagnoseUninitializedUse(S, vd, 12062815e1a075c74143a0b60a632090ece1dffa5c7cRichard Smith UninitUse(vd->getInit()->IgnoreParenCasts(), 12072815e1a075c74143a0b60a632090ece1dffa5c7cRichard Smith /* isAlwaysUninit */ true), 12080d381810da19dd7677b9a79fca516d298fa5addbMatt Beaumont-Gay /* alwaysReportSelfInit */ true); 12099e7617220135a6f6226cf09cb242cc1b905aedb4Ted Kremenek else { 12109e7617220135a6f6226cf09cb242cc1b905aedb4Ted Kremenek // Sort the uses by their SourceLocations. While not strictly 12119e7617220135a6f6226cf09cb242cc1b905aedb4Ted Kremenek // guaranteed to produce them in line/column order, this will provide 12129e7617220135a6f6226cf09cb242cc1b905aedb4Ted Kremenek // a stable ordering. 12139e7617220135a6f6226cf09cb242cc1b905aedb4Ted Kremenek std::sort(vec->begin(), vec->end(), SLocSort()); 12149e7617220135a6f6226cf09cb242cc1b905aedb4Ted Kremenek 12159e7617220135a6f6226cf09cb242cc1b905aedb4Ted Kremenek for (UsesVec::iterator vi = vec->begin(), ve = vec->end(); vi != ve; 12169e7617220135a6f6226cf09cb242cc1b905aedb4Ted Kremenek ++vi) { 12172815e1a075c74143a0b60a632090ece1dffa5c7cRichard Smith // If we have self-init, downgrade all uses to 'may be uninitialized'. 12182815e1a075c74143a0b60a632090ece1dffa5c7cRichard Smith UninitUse Use = hasSelfInit ? UninitUse(vi->getUser(), false) : *vi; 12192815e1a075c74143a0b60a632090ece1dffa5c7cRichard Smith 12202815e1a075c74143a0b60a632090ece1dffa5c7cRichard Smith if (DiagnoseUninitializedUse(S, vd, Use)) 12219e7617220135a6f6226cf09cb242cc1b905aedb4Ted Kremenek // Skip further diagnostics for this variable. We try to warn only 12229e7617220135a6f6226cf09cb242cc1b905aedb4Ted Kremenek // on the first point at which a variable is used uninitialized. 12239e7617220135a6f6226cf09cb242cc1b905aedb4Ted Kremenek break; 12249e7617220135a6f6226cf09cb242cc1b905aedb4Ted Kremenek } 122564fb959beb3a0ecb84a58e6ff82660a7a669f7b8Chandler Carruth } 12269e7617220135a6f6226cf09cb242cc1b905aedb4Ted Kremenek 12279e7617220135a6f6226cf09cb242cc1b905aedb4Ted Kremenek // Release the uses vector. 122894b1b4d785bc0f09f6af4be394e59d51f35dda60Ted Kremenek delete vec; 122994b1b4d785bc0f09f6af4be394e59d51f35dda60Ted Kremenek } 123094b1b4d785bc0f09f6af4be394e59d51f35dda60Ted Kremenek delete uses; 1231610068c8cd2321f90e147b12cf794e1f840b6405Ted Kremenek } 12320d381810da19dd7677b9a79fca516d298fa5addbMatt Beaumont-Gay 12330d381810da19dd7677b9a79fca516d298fa5addbMatt Beaumont-Gayprivate: 12340d381810da19dd7677b9a79fca516d298fa5addbMatt Beaumont-Gay static bool hasAlwaysUninitializedUse(const UsesVec* vec) { 12350d381810da19dd7677b9a79fca516d298fa5addbMatt Beaumont-Gay for (UsesVec::const_iterator i = vec->begin(), e = vec->end(); i != e; ++i) { 12362815e1a075c74143a0b60a632090ece1dffa5c7cRichard Smith if (i->getKind() == UninitUse::Always) { 12370d381810da19dd7677b9a79fca516d298fa5addbMatt Beaumont-Gay return true; 12380d381810da19dd7677b9a79fca516d298fa5addbMatt Beaumont-Gay } 12390d381810da19dd7677b9a79fca516d298fa5addbMatt Beaumont-Gay } 12400d381810da19dd7677b9a79fca516d298fa5addbMatt Beaumont-Gay return false; 12410d381810da19dd7677b9a79fca516d298fa5addbMatt Beaumont-Gay} 1242610068c8cd2321f90e147b12cf794e1f840b6405Ted Kremenek}; 1243610068c8cd2321f90e147b12cf794e1f840b6405Ted Kremenek} 1244610068c8cd2321f90e147b12cf794e1f840b6405Ted Kremenek 12453ac1fbc303d22af2e11a14023ecee7bd7b7d0bfdCaitlin Sadowski 12463ac1fbc303d22af2e11a14023ecee7bd7b7d0bfdCaitlin Sadowski//===----------------------------------------------------------------------===// 12473ac1fbc303d22af2e11a14023ecee7bd7b7d0bfdCaitlin Sadowski// -Wthread-safety 12483ac1fbc303d22af2e11a14023ecee7bd7b7d0bfdCaitlin Sadowski//===----------------------------------------------------------------------===// 124975f23aeb1c820b49f9faebed63b1cbef76c2c907Caitlin Sadowskinamespace clang { 125075f23aeb1c820b49f9faebed63b1cbef76c2c907Caitlin Sadowskinamespace thread_safety { 1251cfa88f893915ceb8ae4ce2f17c46c24a4d67502fDmitri Gribenkotypedef SmallVector<PartialDiagnosticAt, 1> OptionalNotes; 12522e5156274b8051217565b557bfa14c80f7990e9cRichard Smithtypedef std::pair<PartialDiagnosticAt, OptionalNotes> DelayedDiag; 1253ecafd309b3ed2ffc6f8ae7eecd1e7eae84b26f81Benjamin Kramertypedef std::list<DelayedDiag> DiagList; 125475f23aeb1c820b49f9faebed63b1cbef76c2c907Caitlin Sadowski 125575f23aeb1c820b49f9faebed63b1cbef76c2c907Caitlin Sadowskistruct SortDiagBySourceLocation { 1256ecafd309b3ed2ffc6f8ae7eecd1e7eae84b26f81Benjamin Kramer SourceManager &SM; 1257ecafd309b3ed2ffc6f8ae7eecd1e7eae84b26f81Benjamin Kramer SortDiagBySourceLocation(SourceManager &SM) : SM(SM) {} 125875f23aeb1c820b49f9faebed63b1cbef76c2c907Caitlin Sadowski 125975f23aeb1c820b49f9faebed63b1cbef76c2c907Caitlin Sadowski bool operator()(const DelayedDiag &left, const DelayedDiag &right) { 126075f23aeb1c820b49f9faebed63b1cbef76c2c907Caitlin Sadowski // Although this call will be slow, this is only called when outputting 126175f23aeb1c820b49f9faebed63b1cbef76c2c907Caitlin Sadowski // multiple warnings. 1262ecafd309b3ed2ffc6f8ae7eecd1e7eae84b26f81Benjamin Kramer return SM.isBeforeInTranslationUnit(left.first.first, right.first.first); 126375f23aeb1c820b49f9faebed63b1cbef76c2c907Caitlin Sadowski } 126475f23aeb1c820b49f9faebed63b1cbef76c2c907Caitlin Sadowski}; 126575f23aeb1c820b49f9faebed63b1cbef76c2c907Caitlin Sadowski 126699ba9e3bd70671f3441fb974895f226a83ce0e66David Blaikienamespace { 126775f23aeb1c820b49f9faebed63b1cbef76c2c907Caitlin Sadowskiclass ThreadSafetyReporter : public clang::thread_safety::ThreadSafetyHandler { 126875f23aeb1c820b49f9faebed63b1cbef76c2c907Caitlin Sadowski Sema &S; 126975f23aeb1c820b49f9faebed63b1cbef76c2c907Caitlin Sadowski DiagList Warnings; 12702e5156274b8051217565b557bfa14c80f7990e9cRichard Smith SourceLocation FunLocation, FunEndLocation; 127175f23aeb1c820b49f9faebed63b1cbef76c2c907Caitlin Sadowski 127275f23aeb1c820b49f9faebed63b1cbef76c2c907Caitlin Sadowski // Helper functions 127375f23aeb1c820b49f9faebed63b1cbef76c2c907Caitlin Sadowski void warnLockMismatch(unsigned DiagID, Name LockName, SourceLocation Loc) { 1274f1ac63702143d84db778d32eb185a77fc97db5f5DeLesley Hutchins // Gracefully handle rare cases when the analysis can't get a more 1275f1ac63702143d84db778d32eb185a77fc97db5f5DeLesley Hutchins // precise source location. 1276f1ac63702143d84db778d32eb185a77fc97db5f5DeLesley Hutchins if (!Loc.isValid()) 1277f1ac63702143d84db778d32eb185a77fc97db5f5DeLesley Hutchins Loc = FunLocation; 12782e5156274b8051217565b557bfa14c80f7990e9cRichard Smith PartialDiagnosticAt Warning(Loc, S.PDiag(DiagID) << LockName); 12792e5156274b8051217565b557bfa14c80f7990e9cRichard Smith Warnings.push_back(DelayedDiag(Warning, OptionalNotes())); 128075f23aeb1c820b49f9faebed63b1cbef76c2c907Caitlin Sadowski } 128175f23aeb1c820b49f9faebed63b1cbef76c2c907Caitlin Sadowski 128275f23aeb1c820b49f9faebed63b1cbef76c2c907Caitlin Sadowski public: 12832e5156274b8051217565b557bfa14c80f7990e9cRichard Smith ThreadSafetyReporter(Sema &S, SourceLocation FL, SourceLocation FEL) 12842e5156274b8051217565b557bfa14c80f7990e9cRichard Smith : S(S), FunLocation(FL), FunEndLocation(FEL) {} 128575f23aeb1c820b49f9faebed63b1cbef76c2c907Caitlin Sadowski 128675f23aeb1c820b49f9faebed63b1cbef76c2c907Caitlin Sadowski /// \brief Emit all buffered diagnostics in order of sourcelocation. 128775f23aeb1c820b49f9faebed63b1cbef76c2c907Caitlin Sadowski /// We need to output diagnostics produced while iterating through 128875f23aeb1c820b49f9faebed63b1cbef76c2c907Caitlin Sadowski /// the lockset in deterministic order, so this function orders diagnostics 128975f23aeb1c820b49f9faebed63b1cbef76c2c907Caitlin Sadowski /// and outputs them. 129075f23aeb1c820b49f9faebed63b1cbef76c2c907Caitlin Sadowski void emitDiagnostics() { 1291ecafd309b3ed2ffc6f8ae7eecd1e7eae84b26f81Benjamin Kramer Warnings.sort(SortDiagBySourceLocation(S.getSourceManager())); 129275f23aeb1c820b49f9faebed63b1cbef76c2c907Caitlin Sadowski for (DiagList::iterator I = Warnings.begin(), E = Warnings.end(); 12932e5156274b8051217565b557bfa14c80f7990e9cRichard Smith I != E; ++I) { 12942e5156274b8051217565b557bfa14c80f7990e9cRichard Smith S.Diag(I->first.first, I->first.second); 12952e5156274b8051217565b557bfa14c80f7990e9cRichard Smith const OptionalNotes &Notes = I->second; 12962e5156274b8051217565b557bfa14c80f7990e9cRichard Smith for (unsigned NoteI = 0, NoteN = Notes.size(); NoteI != NoteN; ++NoteI) 12972e5156274b8051217565b557bfa14c80f7990e9cRichard Smith S.Diag(Notes[NoteI].first, Notes[NoteI].second); 12982e5156274b8051217565b557bfa14c80f7990e9cRichard Smith } 129975f23aeb1c820b49f9faebed63b1cbef76c2c907Caitlin Sadowski } 130075f23aeb1c820b49f9faebed63b1cbef76c2c907Caitlin Sadowski 130199107ebc0a5aea953b736e12757e0919d5249d43Caitlin Sadowski void handleInvalidLockExp(SourceLocation Loc) { 13022e5156274b8051217565b557bfa14c80f7990e9cRichard Smith PartialDiagnosticAt Warning(Loc, 13032e5156274b8051217565b557bfa14c80f7990e9cRichard Smith S.PDiag(diag::warn_cannot_resolve_lock) << Loc); 13042e5156274b8051217565b557bfa14c80f7990e9cRichard Smith Warnings.push_back(DelayedDiag(Warning, OptionalNotes())); 130599107ebc0a5aea953b736e12757e0919d5249d43Caitlin Sadowski } 130675f23aeb1c820b49f9faebed63b1cbef76c2c907Caitlin Sadowski void handleUnmatchedUnlock(Name LockName, SourceLocation Loc) { 130775f23aeb1c820b49f9faebed63b1cbef76c2c907Caitlin Sadowski warnLockMismatch(diag::warn_unlock_but_no_lock, LockName, Loc); 130875f23aeb1c820b49f9faebed63b1cbef76c2c907Caitlin Sadowski } 130975f23aeb1c820b49f9faebed63b1cbef76c2c907Caitlin Sadowski 131075f23aeb1c820b49f9faebed63b1cbef76c2c907Caitlin Sadowski void handleDoubleLock(Name LockName, SourceLocation Loc) { 131175f23aeb1c820b49f9faebed63b1cbef76c2c907Caitlin Sadowski warnLockMismatch(diag::warn_double_lock, LockName, Loc); 131275f23aeb1c820b49f9faebed63b1cbef76c2c907Caitlin Sadowski } 131375f23aeb1c820b49f9faebed63b1cbef76c2c907Caitlin Sadowski 13142e5156274b8051217565b557bfa14c80f7990e9cRichard Smith void handleMutexHeldEndOfScope(Name LockName, SourceLocation LocLocked, 13152e5156274b8051217565b557bfa14c80f7990e9cRichard Smith SourceLocation LocEndOfScope, 13164e4bc75d3570835e13183c66ac08974cdc016007Caitlin Sadowski LockErrorKind LEK){ 13174e4bc75d3570835e13183c66ac08974cdc016007Caitlin Sadowski unsigned DiagID = 0; 13184e4bc75d3570835e13183c66ac08974cdc016007Caitlin Sadowski switch (LEK) { 13194e4bc75d3570835e13183c66ac08974cdc016007Caitlin Sadowski case LEK_LockedSomePredecessors: 13202e5156274b8051217565b557bfa14c80f7990e9cRichard Smith DiagID = diag::warn_lock_some_predecessors; 13214e4bc75d3570835e13183c66ac08974cdc016007Caitlin Sadowski break; 13224e4bc75d3570835e13183c66ac08974cdc016007Caitlin Sadowski case LEK_LockedSomeLoopIterations: 13234e4bc75d3570835e13183c66ac08974cdc016007Caitlin Sadowski DiagID = diag::warn_expecting_lock_held_on_loop; 13244e4bc75d3570835e13183c66ac08974cdc016007Caitlin Sadowski break; 13254e4bc75d3570835e13183c66ac08974cdc016007Caitlin Sadowski case LEK_LockedAtEndOfFunction: 13264e4bc75d3570835e13183c66ac08974cdc016007Caitlin Sadowski DiagID = diag::warn_no_unlock; 13274e4bc75d3570835e13183c66ac08974cdc016007Caitlin Sadowski break; 1328879a4334e4c4cab0c22ba91492ffc2838bbc21fcDeLesley Hutchins case LEK_NotLockedAtEndOfFunction: 1329879a4334e4c4cab0c22ba91492ffc2838bbc21fcDeLesley Hutchins DiagID = diag::warn_expecting_locked; 1330879a4334e4c4cab0c22ba91492ffc2838bbc21fcDeLesley Hutchins break; 13314e4bc75d3570835e13183c66ac08974cdc016007Caitlin Sadowski } 13322e5156274b8051217565b557bfa14c80f7990e9cRichard Smith if (LocEndOfScope.isInvalid()) 13332e5156274b8051217565b557bfa14c80f7990e9cRichard Smith LocEndOfScope = FunEndLocation; 13342e5156274b8051217565b557bfa14c80f7990e9cRichard Smith 13352e5156274b8051217565b557bfa14c80f7990e9cRichard Smith PartialDiagnosticAt Warning(LocEndOfScope, S.PDiag(DiagID) << LockName); 13365696884053b4a60dbed01ea8c7e6cd8dcf9b5de9DeLesley Hutchins if (LocLocked.isValid()) { 13375696884053b4a60dbed01ea8c7e6cd8dcf9b5de9DeLesley Hutchins PartialDiagnosticAt Note(LocLocked, S.PDiag(diag::note_locked_here)); 13385696884053b4a60dbed01ea8c7e6cd8dcf9b5de9DeLesley Hutchins Warnings.push_back(DelayedDiag(Warning, OptionalNotes(1, Note))); 13395696884053b4a60dbed01ea8c7e6cd8dcf9b5de9DeLesley Hutchins return; 13405696884053b4a60dbed01ea8c7e6cd8dcf9b5de9DeLesley Hutchins } 13415696884053b4a60dbed01ea8c7e6cd8dcf9b5de9DeLesley Hutchins Warnings.push_back(DelayedDiag(Warning, OptionalNotes())); 134275f23aeb1c820b49f9faebed63b1cbef76c2c907Caitlin Sadowski } 134375f23aeb1c820b49f9faebed63b1cbef76c2c907Caitlin Sadowski 134475f23aeb1c820b49f9faebed63b1cbef76c2c907Caitlin Sadowski 134575f23aeb1c820b49f9faebed63b1cbef76c2c907Caitlin Sadowski void handleExclusiveAndShared(Name LockName, SourceLocation Loc1, 134675f23aeb1c820b49f9faebed63b1cbef76c2c907Caitlin Sadowski SourceLocation Loc2) { 13472e5156274b8051217565b557bfa14c80f7990e9cRichard Smith PartialDiagnosticAt Warning( 13482e5156274b8051217565b557bfa14c80f7990e9cRichard Smith Loc1, S.PDiag(diag::warn_lock_exclusive_and_shared) << LockName); 13492e5156274b8051217565b557bfa14c80f7990e9cRichard Smith PartialDiagnosticAt Note( 13502e5156274b8051217565b557bfa14c80f7990e9cRichard Smith Loc2, S.PDiag(diag::note_lock_exclusive_and_shared) << LockName); 13512e5156274b8051217565b557bfa14c80f7990e9cRichard Smith Warnings.push_back(DelayedDiag(Warning, OptionalNotes(1, Note))); 135275f23aeb1c820b49f9faebed63b1cbef76c2c907Caitlin Sadowski } 135375f23aeb1c820b49f9faebed63b1cbef76c2c907Caitlin Sadowski 135475f23aeb1c820b49f9faebed63b1cbef76c2c907Caitlin Sadowski void handleNoMutexHeld(const NamedDecl *D, ProtectedOperationKind POK, 135575f23aeb1c820b49f9faebed63b1cbef76c2c907Caitlin Sadowski AccessKind AK, SourceLocation Loc) { 1356df8327c28d293cf7c6952b86dba26863235dcc0fCaitlin Sadowski assert((POK == POK_VarAccess || POK == POK_VarDereference) 1357df8327c28d293cf7c6952b86dba26863235dcc0fCaitlin Sadowski && "Only works for variables"); 1358df8327c28d293cf7c6952b86dba26863235dcc0fCaitlin Sadowski unsigned DiagID = POK == POK_VarAccess? 1359df8327c28d293cf7c6952b86dba26863235dcc0fCaitlin Sadowski diag::warn_variable_requires_any_lock: 1360df8327c28d293cf7c6952b86dba26863235dcc0fCaitlin Sadowski diag::warn_var_deref_requires_any_lock; 13612e5156274b8051217565b557bfa14c80f7990e9cRichard Smith PartialDiagnosticAt Warning(Loc, S.PDiag(DiagID) 13625b280f28351bbdc103cc50d3b0f52f92d286fa0aDeLesley Hutchins << D->getNameAsString() << getLockKindFromAccessKind(AK)); 13632e5156274b8051217565b557bfa14c80f7990e9cRichard Smith Warnings.push_back(DelayedDiag(Warning, OptionalNotes())); 136475f23aeb1c820b49f9faebed63b1cbef76c2c907Caitlin Sadowski } 136575f23aeb1c820b49f9faebed63b1cbef76c2c907Caitlin Sadowski 136675f23aeb1c820b49f9faebed63b1cbef76c2c907Caitlin Sadowski void handleMutexNotHeld(const NamedDecl *D, ProtectedOperationKind POK, 13673f0ec5209726641782468bd4c7597e79dda78b15DeLesley Hutchins Name LockName, LockKind LK, SourceLocation Loc, 13683f0ec5209726641782468bd4c7597e79dda78b15DeLesley Hutchins Name *PossibleMatch) { 1369e87158dfbca01577810f301543c3cdcfc955d8b0Caitlin Sadowski unsigned DiagID = 0; 13703f0ec5209726641782468bd4c7597e79dda78b15DeLesley Hutchins if (PossibleMatch) { 13713f0ec5209726641782468bd4c7597e79dda78b15DeLesley Hutchins switch (POK) { 13723f0ec5209726641782468bd4c7597e79dda78b15DeLesley Hutchins case POK_VarAccess: 13733f0ec5209726641782468bd4c7597e79dda78b15DeLesley Hutchins DiagID = diag::warn_variable_requires_lock_precise; 13743f0ec5209726641782468bd4c7597e79dda78b15DeLesley Hutchins break; 13753f0ec5209726641782468bd4c7597e79dda78b15DeLesley Hutchins case POK_VarDereference: 13763f0ec5209726641782468bd4c7597e79dda78b15DeLesley Hutchins DiagID = diag::warn_var_deref_requires_lock_precise; 13773f0ec5209726641782468bd4c7597e79dda78b15DeLesley Hutchins break; 13783f0ec5209726641782468bd4c7597e79dda78b15DeLesley Hutchins case POK_FunctionCall: 13793f0ec5209726641782468bd4c7597e79dda78b15DeLesley Hutchins DiagID = diag::warn_fun_requires_lock_precise; 13803f0ec5209726641782468bd4c7597e79dda78b15DeLesley Hutchins break; 13813f0ec5209726641782468bd4c7597e79dda78b15DeLesley Hutchins } 13823f0ec5209726641782468bd4c7597e79dda78b15DeLesley Hutchins PartialDiagnosticAt Warning(Loc, S.PDiag(DiagID) 13835b280f28351bbdc103cc50d3b0f52f92d286fa0aDeLesley Hutchins << D->getNameAsString() << LockName << LK); 13843f0ec5209726641782468bd4c7597e79dda78b15DeLesley Hutchins PartialDiagnosticAt Note(Loc, S.PDiag(diag::note_found_mutex_near_match) 13853f0ec5209726641782468bd4c7597e79dda78b15DeLesley Hutchins << *PossibleMatch); 13863f0ec5209726641782468bd4c7597e79dda78b15DeLesley Hutchins Warnings.push_back(DelayedDiag(Warning, OptionalNotes(1, Note))); 13873f0ec5209726641782468bd4c7597e79dda78b15DeLesley Hutchins } else { 13883f0ec5209726641782468bd4c7597e79dda78b15DeLesley Hutchins switch (POK) { 13893f0ec5209726641782468bd4c7597e79dda78b15DeLesley Hutchins case POK_VarAccess: 13903f0ec5209726641782468bd4c7597e79dda78b15DeLesley Hutchins DiagID = diag::warn_variable_requires_lock; 13913f0ec5209726641782468bd4c7597e79dda78b15DeLesley Hutchins break; 13923f0ec5209726641782468bd4c7597e79dda78b15DeLesley Hutchins case POK_VarDereference: 13933f0ec5209726641782468bd4c7597e79dda78b15DeLesley Hutchins DiagID = diag::warn_var_deref_requires_lock; 13943f0ec5209726641782468bd4c7597e79dda78b15DeLesley Hutchins break; 13953f0ec5209726641782468bd4c7597e79dda78b15DeLesley Hutchins case POK_FunctionCall: 13963f0ec5209726641782468bd4c7597e79dda78b15DeLesley Hutchins DiagID = diag::warn_fun_requires_lock; 13973f0ec5209726641782468bd4c7597e79dda78b15DeLesley Hutchins break; 13983f0ec5209726641782468bd4c7597e79dda78b15DeLesley Hutchins } 13993f0ec5209726641782468bd4c7597e79dda78b15DeLesley Hutchins PartialDiagnosticAt Warning(Loc, S.PDiag(DiagID) 14005b280f28351bbdc103cc50d3b0f52f92d286fa0aDeLesley Hutchins << D->getNameAsString() << LockName << LK); 14013f0ec5209726641782468bd4c7597e79dda78b15DeLesley Hutchins Warnings.push_back(DelayedDiag(Warning, OptionalNotes())); 140275f23aeb1c820b49f9faebed63b1cbef76c2c907Caitlin Sadowski } 140375f23aeb1c820b49f9faebed63b1cbef76c2c907Caitlin Sadowski } 140475f23aeb1c820b49f9faebed63b1cbef76c2c907Caitlin Sadowski 140575f23aeb1c820b49f9faebed63b1cbef76c2c907Caitlin Sadowski void handleFunExcludesLock(Name FunName, Name LockName, SourceLocation Loc) { 14062e5156274b8051217565b557bfa14c80f7990e9cRichard Smith PartialDiagnosticAt Warning(Loc, 14072e5156274b8051217565b557bfa14c80f7990e9cRichard Smith S.PDiag(diag::warn_fun_excludes_mutex) << FunName << LockName); 14082e5156274b8051217565b557bfa14c80f7990e9cRichard Smith Warnings.push_back(DelayedDiag(Warning, OptionalNotes())); 140975f23aeb1c820b49f9faebed63b1cbef76c2c907Caitlin Sadowski } 141075f23aeb1c820b49f9faebed63b1cbef76c2c907Caitlin Sadowski}; 141175f23aeb1c820b49f9faebed63b1cbef76c2c907Caitlin Sadowski} 141275f23aeb1c820b49f9faebed63b1cbef76c2c907Caitlin Sadowski} 141399ba9e3bd70671f3441fb974895f226a83ce0e66David Blaikie} 141475f23aeb1c820b49f9faebed63b1cbef76c2c907Caitlin Sadowski 1415610068c8cd2321f90e147b12cf794e1f840b6405Ted Kremenek//===----------------------------------------------------------------------===// 1416dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek// AnalysisBasedWarnings - Worker object used by Sema to execute analysis-based 1417dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek// warnings on a function, method, or block. 1418dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek//===----------------------------------------------------------------------===// 1419dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek 1420d064fdc4b7b64ca55b40b70490c79d6f569df78eTed Kremenekclang::sema::AnalysisBasedWarnings::Policy::Policy() { 1421dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek enableCheckFallThrough = 1; 1422d064fdc4b7b64ca55b40b70490c79d6f569df78eTed Kremenek enableCheckUnreachable = 0; 14233ac1fbc303d22af2e11a14023ecee7bd7b7d0bfdCaitlin Sadowski enableThreadSafetyAnalysis = 0; 1424d064fdc4b7b64ca55b40b70490c79d6f569df78eTed Kremenek} 1425dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek 14265d98994c7749312a43ce6adf45537979a98e7afdChandler Carruthclang::sema::AnalysisBasedWarnings::AnalysisBasedWarnings(Sema &s) 14275d98994c7749312a43ce6adf45537979a98e7afdChandler Carruth : S(s), 14285d98994c7749312a43ce6adf45537979a98e7afdChandler Carruth NumFunctionsAnalyzed(0), 142954cf341bd4145e5e31f91c5777fcdaf3f2400537Benjamin Kramer NumFunctionsWithBadCFGs(0), 14305d98994c7749312a43ce6adf45537979a98e7afdChandler Carruth NumCFGBlocks(0), 143154cf341bd4145e5e31f91c5777fcdaf3f2400537Benjamin Kramer MaxCFGBlocksPerFunction(0), 143254cf341bd4145e5e31f91c5777fcdaf3f2400537Benjamin Kramer NumUninitAnalysisFunctions(0), 143354cf341bd4145e5e31f91c5777fcdaf3f2400537Benjamin Kramer NumUninitAnalysisVariables(0), 143454cf341bd4145e5e31f91c5777fcdaf3f2400537Benjamin Kramer MaxUninitAnalysisVariablesPerFunction(0), 143554cf341bd4145e5e31f91c5777fcdaf3f2400537Benjamin Kramer NumUninitAnalysisBlockVisits(0), 143654cf341bd4145e5e31f91c5777fcdaf3f2400537Benjamin Kramer MaxUninitAnalysisBlockVisitsPerFunction(0) { 1437d6471f7c1921c7802804ce3ff6fe9768310f72b9David Blaikie DiagnosticsEngine &D = S.getDiagnostics(); 1438d064fdc4b7b64ca55b40b70490c79d6f569df78eTed Kremenek DefaultPolicy.enableCheckUnreachable = (unsigned) 14390827408865e32789e0ec4b8113a302ccdc531423Argyrios Kyrtzidis (D.getDiagnosticLevel(diag::warn_unreachable, SourceLocation()) != 1440d6471f7c1921c7802804ce3ff6fe9768310f72b9David Blaikie DiagnosticsEngine::Ignored); 14413ac1fbc303d22af2e11a14023ecee7bd7b7d0bfdCaitlin Sadowski DefaultPolicy.enableThreadSafetyAnalysis = (unsigned) 14423ac1fbc303d22af2e11a14023ecee7bd7b7d0bfdCaitlin Sadowski (D.getDiagnosticLevel(diag::warn_double_lock, SourceLocation()) != 1443d6471f7c1921c7802804ce3ff6fe9768310f72b9David Blaikie DiagnosticsEngine::Ignored); 14443ac1fbc303d22af2e11a14023ecee7bd7b7d0bfdCaitlin Sadowski 1445dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek} 1446dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek 1447351ba91eaa6d30e523587b2d7ed676a5172c6e56Ted Kremenekstatic void flushDiagnostics(Sema &S, sema::FunctionScopeInfo *fscope) { 14485f9e272e632e951b1efe824cd16acb4d96077930Chris Lattner for (SmallVectorImpl<sema::PossiblyUnreachableDiag>::iterator 1449351ba91eaa6d30e523587b2d7ed676a5172c6e56Ted Kremenek i = fscope->PossiblyUnreachableDiags.begin(), 1450351ba91eaa6d30e523587b2d7ed676a5172c6e56Ted Kremenek e = fscope->PossiblyUnreachableDiags.end(); 1451351ba91eaa6d30e523587b2d7ed676a5172c6e56Ted Kremenek i != e; ++i) { 1452351ba91eaa6d30e523587b2d7ed676a5172c6e56Ted Kremenek const sema::PossiblyUnreachableDiag &D = *i; 1453351ba91eaa6d30e523587b2d7ed676a5172c6e56Ted Kremenek S.Diag(D.Loc, D.PD); 1454351ba91eaa6d30e523587b2d7ed676a5172c6e56Ted Kremenek } 1455351ba91eaa6d30e523587b2d7ed676a5172c6e56Ted Kremenek} 1456351ba91eaa6d30e523587b2d7ed676a5172c6e56Ted Kremenek 1457d064fdc4b7b64ca55b40b70490c79d6f569df78eTed Kremenekvoid clang::sema:: 1458d064fdc4b7b64ca55b40b70490c79d6f569df78eTed KremenekAnalysisBasedWarnings::IssueWarnings(sema::AnalysisBasedWarnings::Policy P, 1459283a358aecb75e30fcd486f2206f6c03c5e7f11dTed Kremenek sema::FunctionScopeInfo *fscope, 14603ed6fc08a9cd293d012fa49ab2a615e618d7c3faTed Kremenek const Decl *D, const BlockExpr *blkExpr) { 1461d068aabc484c4009282122c6ef26e66e68cfa044Ted Kremenek 1462dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek // We avoid doing analysis-based warnings when there are errors for 1463dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek // two reasons: 1464dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek // (1) The CFGs often can't be constructed (if the body is invalid), so 1465dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek // don't bother trying. 1466dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek // (2) The code already has problems; running the analysis just takes more 1467dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek // time. 1468d6471f7c1921c7802804ce3ff6fe9768310f72b9David Blaikie DiagnosticsEngine &Diags = S.getDiagnostics(); 146999e8192c4c8f1f596f9969e5f2cdafcee64ddaacTed Kremenek 1470d064fdc4b7b64ca55b40b70490c79d6f569df78eTed Kremenek // Do not do any analysis for declarations in system headers if we are 1471d064fdc4b7b64ca55b40b70490c79d6f569df78eTed Kremenek // going to just ignore them. 147299e8192c4c8f1f596f9969e5f2cdafcee64ddaacTed Kremenek if (Diags.getSuppressSystemWarnings() && 1473d064fdc4b7b64ca55b40b70490c79d6f569df78eTed Kremenek S.SourceMgr.isInSystemHeader(D->getLocation())) 1474d064fdc4b7b64ca55b40b70490c79d6f569df78eTed Kremenek return; 1475d064fdc4b7b64ca55b40b70490c79d6f569df78eTed Kremenek 1476e0054f61fd84133eb0d19c19ae9afaf117933274John McCall // For code in dependent contexts, we'll do this at instantiation time. 147723661d3e348c5f44ae89b6848bbc331829bb46f2David Blaikie if (cast<DeclContext>(D)->isDependentContext()) 147823661d3e348c5f44ae89b6848bbc331829bb46f2David Blaikie return; 1479dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek 148012f37e411462b8388eb1309357bd62257debacacDeLesley Hutchins if (Diags.hasUncompilableErrorOccurred() || Diags.hasFatalErrorOccurred()) { 1481351ba91eaa6d30e523587b2d7ed676a5172c6e56Ted Kremenek // Flush out any possibly unreachable diagnostics. 1482351ba91eaa6d30e523587b2d7ed676a5172c6e56Ted Kremenek flushDiagnostics(S, fscope); 1483351ba91eaa6d30e523587b2d7ed676a5172c6e56Ted Kremenek return; 1484351ba91eaa6d30e523587b2d7ed676a5172c6e56Ted Kremenek } 1485351ba91eaa6d30e523587b2d7ed676a5172c6e56Ted Kremenek 1486dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek const Stmt *Body = D->getBody(); 1487dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek assert(Body); 1488dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek 1489d200187bd27f9ad68699693a6e57f9ee3ff260faJordy Rose AnalysisDeclContext AC(/* AnalysisDeclContextManager */ 0, D); 1490bc5cb8a5fe2b88f917d47ceb58b53696a121e57eTed Kremenek 1491dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek // Don't generate EH edges for CallExprs as we'd like to avoid the n^2 1492dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek // explosion for destrutors that can result and the compile time hit. 1493bc5cb8a5fe2b88f917d47ceb58b53696a121e57eTed Kremenek AC.getCFGBuildOptions().PruneTriviallyFalseEdges = true; 1494bc5cb8a5fe2b88f917d47ceb58b53696a121e57eTed Kremenek AC.getCFGBuildOptions().AddEHEdges = false; 1495bc5cb8a5fe2b88f917d47ceb58b53696a121e57eTed Kremenek AC.getCFGBuildOptions().AddInitializers = true; 1496bc5cb8a5fe2b88f917d47ceb58b53696a121e57eTed Kremenek AC.getCFGBuildOptions().AddImplicitDtors = true; 1497faadf48443f8c2fc53d267485d7e0e1bd382fc75Jordan Rose AC.getCFGBuildOptions().AddTemporaryDtors = true; 1498faadf48443f8c2fc53d267485d7e0e1bd382fc75Jordan Rose 14990c8e5a0f70cbdb800d939c1807d05f380b2854d4Ted Kremenek // Force that certain expressions appear as CFGElements in the CFG. This 15000c8e5a0f70cbdb800d939c1807d05f380b2854d4Ted Kremenek // is used to speed up various analyses. 15010c8e5a0f70cbdb800d939c1807d05f380b2854d4Ted Kremenek // FIXME: This isn't the right factoring. This is here for initial 15020c8e5a0f70cbdb800d939c1807d05f380b2854d4Ted Kremenek // prototyping, but we need a way for analyses to say what expressions they 15030c8e5a0f70cbdb800d939c1807d05f380b2854d4Ted Kremenek // expect to always be CFGElements and then fill in the BuildOptions 15040c8e5a0f70cbdb800d939c1807d05f380b2854d4Ted Kremenek // appropriately. This is essentially a layering violation. 15051fa3c0682a52c45c4ad0be3a82d0c85f26657072DeLesley Hutchins if (P.enableCheckUnreachable || P.enableThreadSafetyAnalysis) { 15061fa3c0682a52c45c4ad0be3a82d0c85f26657072DeLesley Hutchins // Unreachable code analysis and thread safety require a linearized CFG. 15070f3b4ca1764cd6d457f511d340fba504f41763c3Ted Kremenek AC.getCFGBuildOptions().setAllAlwaysAdd(); 15080f3b4ca1764cd6d457f511d340fba504f41763c3Ted Kremenek } 15090f3b4ca1764cd6d457f511d340fba504f41763c3Ted Kremenek else { 15100f3b4ca1764cd6d457f511d340fba504f41763c3Ted Kremenek AC.getCFGBuildOptions() 15110f3b4ca1764cd6d457f511d340fba504f41763c3Ted Kremenek .setAlwaysAdd(Stmt::BinaryOperatorClass) 15126cfa78f6bd4e7d5e23366a0907f8f8792366bc4cRichard Smith .setAlwaysAdd(Stmt::CompoundAssignOperatorClass) 15130f3b4ca1764cd6d457f511d340fba504f41763c3Ted Kremenek .setAlwaysAdd(Stmt::BlockExprClass) 15140f3b4ca1764cd6d457f511d340fba504f41763c3Ted Kremenek .setAlwaysAdd(Stmt::CStyleCastExprClass) 15150f3b4ca1764cd6d457f511d340fba504f41763c3Ted Kremenek .setAlwaysAdd(Stmt::DeclRefExprClass) 15160f3b4ca1764cd6d457f511d340fba504f41763c3Ted Kremenek .setAlwaysAdd(Stmt::ImplicitCastExprClass) 1517e0d3b4cd2b66f1cef26cacbed5820ab7c22ad5b3Richard Smith .setAlwaysAdd(Stmt::UnaryOperatorClass) 1518e0d3b4cd2b66f1cef26cacbed5820ab7c22ad5b3Richard Smith .setAlwaysAdd(Stmt::AttributedStmtClass); 15190f3b4ca1764cd6d457f511d340fba504f41763c3Ted Kremenek } 1520bc5cb8a5fe2b88f917d47ceb58b53696a121e57eTed Kremenek 1521bc5cb8a5fe2b88f917d47ceb58b53696a121e57eTed Kremenek // Construct the analysis context with the specified CFG build options. 1522bc5cb8a5fe2b88f917d47ceb58b53696a121e57eTed Kremenek 1523351ba91eaa6d30e523587b2d7ed676a5172c6e56Ted Kremenek // Emit delayed diagnostics. 152423661d3e348c5f44ae89b6848bbc331829bb46f2David Blaikie if (!fscope->PossiblyUnreachableDiags.empty()) { 1525351ba91eaa6d30e523587b2d7ed676a5172c6e56Ted Kremenek bool analyzed = false; 15260d28d360b5559abda755e50b855ba5e59727d9cdTed Kremenek 15270d28d360b5559abda755e50b855ba5e59727d9cdTed Kremenek // Register the expressions with the CFGBuilder. 15285f9e272e632e951b1efe824cd16acb4d96077930Chris Lattner for (SmallVectorImpl<sema::PossiblyUnreachableDiag>::iterator 15290d28d360b5559abda755e50b855ba5e59727d9cdTed Kremenek i = fscope->PossiblyUnreachableDiags.begin(), 15300d28d360b5559abda755e50b855ba5e59727d9cdTed Kremenek e = fscope->PossiblyUnreachableDiags.end(); 15310d28d360b5559abda755e50b855ba5e59727d9cdTed Kremenek i != e; ++i) { 15320d28d360b5559abda755e50b855ba5e59727d9cdTed Kremenek if (const Stmt *stmt = i->stmt) 15330d28d360b5559abda755e50b855ba5e59727d9cdTed Kremenek AC.registerForcedBlockExpression(stmt); 15340d28d360b5559abda755e50b855ba5e59727d9cdTed Kremenek } 15350d28d360b5559abda755e50b855ba5e59727d9cdTed Kremenek 15360d28d360b5559abda755e50b855ba5e59727d9cdTed Kremenek if (AC.getCFG()) { 15370d28d360b5559abda755e50b855ba5e59727d9cdTed Kremenek analyzed = true; 15385f9e272e632e951b1efe824cd16acb4d96077930Chris Lattner for (SmallVectorImpl<sema::PossiblyUnreachableDiag>::iterator 15390d28d360b5559abda755e50b855ba5e59727d9cdTed Kremenek i = fscope->PossiblyUnreachableDiags.begin(), 15400d28d360b5559abda755e50b855ba5e59727d9cdTed Kremenek e = fscope->PossiblyUnreachableDiags.end(); 15410d28d360b5559abda755e50b855ba5e59727d9cdTed Kremenek i != e; ++i) 15420d28d360b5559abda755e50b855ba5e59727d9cdTed Kremenek { 15430d28d360b5559abda755e50b855ba5e59727d9cdTed Kremenek const sema::PossiblyUnreachableDiag &D = *i; 15440d28d360b5559abda755e50b855ba5e59727d9cdTed Kremenek bool processed = false; 15450d28d360b5559abda755e50b855ba5e59727d9cdTed Kremenek if (const Stmt *stmt = i->stmt) { 15460d28d360b5559abda755e50b855ba5e59727d9cdTed Kremenek const CFGBlock *block = AC.getBlockForRegisteredExpression(stmt); 154771b8fb5d4233420d2ed2f150a54ea61431bd8684Eli Friedman CFGReverseBlockReachabilityAnalysis *cra = 154871b8fb5d4233420d2ed2f150a54ea61431bd8684Eli Friedman AC.getCFGReachablityAnalysis(); 154971b8fb5d4233420d2ed2f150a54ea61431bd8684Eli Friedman // FIXME: We should be able to assert that block is non-null, but 155071b8fb5d4233420d2ed2f150a54ea61431bd8684Eli Friedman // the CFG analysis can skip potentially-evaluated expressions in 155171b8fb5d4233420d2ed2f150a54ea61431bd8684Eli Friedman // edge cases; see test/Sema/vla-2.c. 155271b8fb5d4233420d2ed2f150a54ea61431bd8684Eli Friedman if (block && cra) { 1553351ba91eaa6d30e523587b2d7ed676a5172c6e56Ted Kremenek // Can this block be reached from the entrance? 15540d28d360b5559abda755e50b855ba5e59727d9cdTed Kremenek if (cra->isReachable(&AC.getCFG()->getEntry(), block)) 1555351ba91eaa6d30e523587b2d7ed676a5172c6e56Ted Kremenek S.Diag(D.Loc, D.PD); 15560d28d360b5559abda755e50b855ba5e59727d9cdTed Kremenek processed = true; 1557351ba91eaa6d30e523587b2d7ed676a5172c6e56Ted Kremenek } 15580d28d360b5559abda755e50b855ba5e59727d9cdTed Kremenek } 15590d28d360b5559abda755e50b855ba5e59727d9cdTed Kremenek if (!processed) { 15600d28d360b5559abda755e50b855ba5e59727d9cdTed Kremenek // Emit the warning anyway if we cannot map to a basic block. 15610d28d360b5559abda755e50b855ba5e59727d9cdTed Kremenek S.Diag(D.Loc, D.PD); 1562351ba91eaa6d30e523587b2d7ed676a5172c6e56Ted Kremenek } 1563351ba91eaa6d30e523587b2d7ed676a5172c6e56Ted Kremenek } 15640d28d360b5559abda755e50b855ba5e59727d9cdTed Kremenek } 1565351ba91eaa6d30e523587b2d7ed676a5172c6e56Ted Kremenek 1566351ba91eaa6d30e523587b2d7ed676a5172c6e56Ted Kremenek if (!analyzed) 1567351ba91eaa6d30e523587b2d7ed676a5172c6e56Ted Kremenek flushDiagnostics(S, fscope); 1568351ba91eaa6d30e523587b2d7ed676a5172c6e56Ted Kremenek } 1569351ba91eaa6d30e523587b2d7ed676a5172c6e56Ted Kremenek 1570351ba91eaa6d30e523587b2d7ed676a5172c6e56Ted Kremenek 1571dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek // Warning: check missing 'return' 157223661d3e348c5f44ae89b6848bbc331829bb46f2David Blaikie if (P.enableCheckFallThrough) { 1573dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek const CheckFallThroughDiagnostics &CD = 1574dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek (isa<BlockDecl>(D) ? CheckFallThroughDiagnostics::MakeForBlock() 1575793cd1c4cdfaafc52e2c2ad9dae959befe4bb166Douglas Gregor : (isa<CXXMethodDecl>(D) && 1576793cd1c4cdfaafc52e2c2ad9dae959befe4bb166Douglas Gregor cast<CXXMethodDecl>(D)->getOverloadedOperator() == OO_Call && 1577793cd1c4cdfaafc52e2c2ad9dae959befe4bb166Douglas Gregor cast<CXXMethodDecl>(D)->getParent()->isLambda()) 1578793cd1c4cdfaafc52e2c2ad9dae959befe4bb166Douglas Gregor ? CheckFallThroughDiagnostics::MakeForLambda() 1579793cd1c4cdfaafc52e2c2ad9dae959befe4bb166Douglas Gregor : CheckFallThroughDiagnostics::MakeForFunction(D)); 15803ed6fc08a9cd293d012fa49ab2a615e618d7c3faTed Kremenek CheckFallThroughForBody(S, D, Body, blkExpr, CD, AC); 1581dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek } 1582dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek 1583dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek // Warning: check for unreachable code 15845dfee06daa359bbe0f3c9de055b8a02d61a05173Ted Kremenek if (P.enableCheckUnreachable) { 15855dfee06daa359bbe0f3c9de055b8a02d61a05173Ted Kremenek // Only check for unreachable code on non-template instantiations. 15865dfee06daa359bbe0f3c9de055b8a02d61a05173Ted Kremenek // Different template instantiations can effectively change the control-flow 15875dfee06daa359bbe0f3c9de055b8a02d61a05173Ted Kremenek // and it is very difficult to prove that a snippet of code in a template 15885dfee06daa359bbe0f3c9de055b8a02d61a05173Ted Kremenek // is unreachable for all instantiations. 158975df4eeede7b91c22c1d63fafd4dd4142844e3b9Ted Kremenek bool isTemplateInstantiation = false; 159075df4eeede7b91c22c1d63fafd4dd4142844e3b9Ted Kremenek if (const FunctionDecl *Function = dyn_cast<FunctionDecl>(D)) 159175df4eeede7b91c22c1d63fafd4dd4142844e3b9Ted Kremenek isTemplateInstantiation = Function->isTemplateInstantiation(); 159275df4eeede7b91c22c1d63fafd4dd4142844e3b9Ted Kremenek if (!isTemplateInstantiation) 15935dfee06daa359bbe0f3c9de055b8a02d61a05173Ted Kremenek CheckUnreachable(S, AC); 15945dfee06daa359bbe0f3c9de055b8a02d61a05173Ted Kremenek } 159575f23aeb1c820b49f9faebed63b1cbef76c2c907Caitlin Sadowski 15963ac1fbc303d22af2e11a14023ecee7bd7b7d0bfdCaitlin Sadowski // Check for thread safety violations 159723661d3e348c5f44ae89b6848bbc331829bb46f2David Blaikie if (P.enableThreadSafetyAnalysis) { 1598f1ac63702143d84db778d32eb185a77fc97db5f5DeLesley Hutchins SourceLocation FL = AC.getDecl()->getLocation(); 15992e5156274b8051217565b557bfa14c80f7990e9cRichard Smith SourceLocation FEL = AC.getDecl()->getLocEnd(); 16002e5156274b8051217565b557bfa14c80f7990e9cRichard Smith thread_safety::ThreadSafetyReporter Reporter(S, FL, FEL); 1601fb4afc2fc659faff43a6df4c1d0e07df9c90479dDeLesley Hutchins if (Diags.getDiagnosticLevel(diag::warn_thread_safety_beta,D->getLocStart()) 1602fb4afc2fc659faff43a6df4c1d0e07df9c90479dDeLesley Hutchins != DiagnosticsEngine::Ignored) 1603fb4afc2fc659faff43a6df4c1d0e07df9c90479dDeLesley Hutchins Reporter.setIssueBetaWarnings(true); 1604fb4afc2fc659faff43a6df4c1d0e07df9c90479dDeLesley Hutchins 160575f23aeb1c820b49f9faebed63b1cbef76c2c907Caitlin Sadowski thread_safety::runThreadSafetyAnalysis(AC, Reporter); 160675f23aeb1c820b49f9faebed63b1cbef76c2c907Caitlin Sadowski Reporter.emitDiagnostics(); 160775f23aeb1c820b49f9faebed63b1cbef76c2c907Caitlin Sadowski } 16083ac1fbc303d22af2e11a14023ecee7bd7b7d0bfdCaitlin Sadowski 1609a8c17a5babab35f2db26bf218e7571d1af4afedfTed Kremenek if (Diags.getDiagnosticLevel(diag::warn_uninit_var, D->getLocStart()) 1610d6471f7c1921c7802804ce3ff6fe9768310f72b9David Blaikie != DiagnosticsEngine::Ignored || 16112815e1a075c74143a0b60a632090ece1dffa5c7cRichard Smith Diags.getDiagnosticLevel(diag::warn_sometimes_uninit_var,D->getLocStart()) 16122815e1a075c74143a0b60a632090ece1dffa5c7cRichard Smith != DiagnosticsEngine::Ignored || 161376709bf816e5e1b70b859bb607cf3ee91db12b76Ted Kremenek Diags.getDiagnosticLevel(diag::warn_maybe_uninit_var, D->getLocStart()) 1614d6471f7c1921c7802804ce3ff6fe9768310f72b9David Blaikie != DiagnosticsEngine::Ignored) { 1615c5e43c19ddb40b8a1371291f73ae66fe54951ca5Ted Kremenek if (CFG *cfg = AC.getCFG()) { 1616c21fed361c11f13db345cba69101578578d8fb79Ted Kremenek UninitValsDiagReporter reporter(S); 161757080fbac1ccce702255423335d52e81bcf17b6bFariborz Jahanian UninitVariablesAnalysisStats stats; 161812efd57ee474c06880a7434ece21a39ac3f34e24Benjamin Kramer std::memset(&stats, 0, sizeof(UninitVariablesAnalysisStats)); 1619a8c17a5babab35f2db26bf218e7571d1af4afedfTed Kremenek runUninitializedVariablesAnalysis(*cast<DeclContext>(D), *cfg, AC, 16205d98994c7749312a43ce6adf45537979a98e7afdChandler Carruth reporter, stats); 16215d98994c7749312a43ce6adf45537979a98e7afdChandler Carruth 16225d98994c7749312a43ce6adf45537979a98e7afdChandler Carruth if (S.CollectStats && stats.NumVariablesAnalyzed > 0) { 16235d98994c7749312a43ce6adf45537979a98e7afdChandler Carruth ++NumUninitAnalysisFunctions; 16245d98994c7749312a43ce6adf45537979a98e7afdChandler Carruth NumUninitAnalysisVariables += stats.NumVariablesAnalyzed; 16255d98994c7749312a43ce6adf45537979a98e7afdChandler Carruth NumUninitAnalysisBlockVisits += stats.NumBlockVisits; 16265d98994c7749312a43ce6adf45537979a98e7afdChandler Carruth MaxUninitAnalysisVariablesPerFunction = 16275d98994c7749312a43ce6adf45537979a98e7afdChandler Carruth std::max(MaxUninitAnalysisVariablesPerFunction, 16285d98994c7749312a43ce6adf45537979a98e7afdChandler Carruth stats.NumVariablesAnalyzed); 16295d98994c7749312a43ce6adf45537979a98e7afdChandler Carruth MaxUninitAnalysisBlockVisitsPerFunction = 16305d98994c7749312a43ce6adf45537979a98e7afdChandler Carruth std::max(MaxUninitAnalysisBlockVisitsPerFunction, 16315d98994c7749312a43ce6adf45537979a98e7afdChandler Carruth stats.NumBlockVisits); 16325d98994c7749312a43ce6adf45537979a98e7afdChandler Carruth } 16335d98994c7749312a43ce6adf45537979a98e7afdChandler Carruth } 16345d98994c7749312a43ce6adf45537979a98e7afdChandler Carruth } 16355d98994c7749312a43ce6adf45537979a98e7afdChandler Carruth 16361973634e445d4f1abdeedc2809f2d281929253b6Alexander Kornienko bool FallThroughDiagFull = 16371973634e445d4f1abdeedc2809f2d281929253b6Alexander Kornienko Diags.getDiagnosticLevel(diag::warn_unannotated_fallthrough, 16381973634e445d4f1abdeedc2809f2d281929253b6Alexander Kornienko D->getLocStart()) != DiagnosticsEngine::Ignored; 1639c2f51cfefd77e9b25f201ecf879343d6d9a45158Sean Hunt bool FallThroughDiagPerFunction = 1640c2f51cfefd77e9b25f201ecf879343d6d9a45158Sean Hunt Diags.getDiagnosticLevel(diag::warn_unannotated_fallthrough_per_function, 16411973634e445d4f1abdeedc2809f2d281929253b6Alexander Kornienko D->getLocStart()) != DiagnosticsEngine::Ignored; 1642c2f51cfefd77e9b25f201ecf879343d6d9a45158Sean Hunt if (FallThroughDiagFull || FallThroughDiagPerFunction) { 16431973634e445d4f1abdeedc2809f2d281929253b6Alexander Kornienko DiagnoseSwitchLabelsFallthrough(S, AC, !FallThroughDiagFull); 1644e0d3b4cd2b66f1cef26cacbed5820ab7c22ad5b3Richard Smith } 1645e0d3b4cd2b66f1cef26cacbed5820ab7c22ad5b3Richard Smith 164658b6bdcdeb683a3504f2248a409e1f4e85876ceeJordan Rose if (S.getLangOpts().ObjCARCWeak && 164758b6bdcdeb683a3504f2248a409e1f4e85876ceeJordan Rose Diags.getDiagnosticLevel(diag::warn_arc_repeated_use_of_weak, 164858b6bdcdeb683a3504f2248a409e1f4e85876ceeJordan Rose D->getLocStart()) != DiagnosticsEngine::Ignored) 1649b5cd1220dd650a358622241237aa595c5d675506Jordan Rose diagnoseRepeatedUseOfWeak(S, fscope, D, AC.getParentMap()); 165058b6bdcdeb683a3504f2248a409e1f4e85876ceeJordan Rose 16515d98994c7749312a43ce6adf45537979a98e7afdChandler Carruth // Collect statistics about the CFG if it was built. 16525d98994c7749312a43ce6adf45537979a98e7afdChandler Carruth if (S.CollectStats && AC.isCFGBuilt()) { 16535d98994c7749312a43ce6adf45537979a98e7afdChandler Carruth ++NumFunctionsAnalyzed; 16545d98994c7749312a43ce6adf45537979a98e7afdChandler Carruth if (CFG *cfg = AC.getCFG()) { 16555d98994c7749312a43ce6adf45537979a98e7afdChandler Carruth // If we successfully built a CFG for this context, record some more 16565d98994c7749312a43ce6adf45537979a98e7afdChandler Carruth // detail information about it. 16573ea4c49709c5bba5f8b16c6ceb725d9b9a1c48c6Chandler Carruth NumCFGBlocks += cfg->getNumBlockIDs(); 16585d98994c7749312a43ce6adf45537979a98e7afdChandler Carruth MaxCFGBlocksPerFunction = std::max(MaxCFGBlocksPerFunction, 16593ea4c49709c5bba5f8b16c6ceb725d9b9a1c48c6Chandler Carruth cfg->getNumBlockIDs()); 16605d98994c7749312a43ce6adf45537979a98e7afdChandler Carruth } else { 16615d98994c7749312a43ce6adf45537979a98e7afdChandler Carruth ++NumFunctionsWithBadCFGs; 1662610068c8cd2321f90e147b12cf794e1f840b6405Ted Kremenek } 1663610068c8cd2321f90e147b12cf794e1f840b6405Ted Kremenek } 1664dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek} 16655d98994c7749312a43ce6adf45537979a98e7afdChandler Carruth 16665d98994c7749312a43ce6adf45537979a98e7afdChandler Carruthvoid clang::sema::AnalysisBasedWarnings::PrintStats() const { 16675d98994c7749312a43ce6adf45537979a98e7afdChandler Carruth llvm::errs() << "\n*** Analysis Based Warnings Stats:\n"; 16685d98994c7749312a43ce6adf45537979a98e7afdChandler Carruth 16695d98994c7749312a43ce6adf45537979a98e7afdChandler Carruth unsigned NumCFGsBuilt = NumFunctionsAnalyzed - NumFunctionsWithBadCFGs; 16705d98994c7749312a43ce6adf45537979a98e7afdChandler Carruth unsigned AvgCFGBlocksPerFunction = 16715d98994c7749312a43ce6adf45537979a98e7afdChandler Carruth !NumCFGsBuilt ? 0 : NumCFGBlocks/NumCFGsBuilt; 16725d98994c7749312a43ce6adf45537979a98e7afdChandler Carruth llvm::errs() << NumFunctionsAnalyzed << " functions analyzed (" 16735d98994c7749312a43ce6adf45537979a98e7afdChandler Carruth << NumFunctionsWithBadCFGs << " w/o CFGs).\n" 16745d98994c7749312a43ce6adf45537979a98e7afdChandler Carruth << " " << NumCFGBlocks << " CFG blocks built.\n" 16755d98994c7749312a43ce6adf45537979a98e7afdChandler Carruth << " " << AvgCFGBlocksPerFunction 16765d98994c7749312a43ce6adf45537979a98e7afdChandler Carruth << " average CFG blocks per function.\n" 16775d98994c7749312a43ce6adf45537979a98e7afdChandler Carruth << " " << MaxCFGBlocksPerFunction 16785d98994c7749312a43ce6adf45537979a98e7afdChandler Carruth << " max CFG blocks per function.\n"; 16795d98994c7749312a43ce6adf45537979a98e7afdChandler Carruth 16805d98994c7749312a43ce6adf45537979a98e7afdChandler Carruth unsigned AvgUninitVariablesPerFunction = !NumUninitAnalysisFunctions ? 0 16815d98994c7749312a43ce6adf45537979a98e7afdChandler Carruth : NumUninitAnalysisVariables/NumUninitAnalysisFunctions; 16825d98994c7749312a43ce6adf45537979a98e7afdChandler Carruth unsigned AvgUninitBlockVisitsPerFunction = !NumUninitAnalysisFunctions ? 0 16835d98994c7749312a43ce6adf45537979a98e7afdChandler Carruth : NumUninitAnalysisBlockVisits/NumUninitAnalysisFunctions; 16845d98994c7749312a43ce6adf45537979a98e7afdChandler Carruth llvm::errs() << NumUninitAnalysisFunctions 16855d98994c7749312a43ce6adf45537979a98e7afdChandler Carruth << " functions analyzed for uninitialiazed variables\n" 16865d98994c7749312a43ce6adf45537979a98e7afdChandler Carruth << " " << NumUninitAnalysisVariables << " variables analyzed.\n" 16875d98994c7749312a43ce6adf45537979a98e7afdChandler Carruth << " " << AvgUninitVariablesPerFunction 16885d98994c7749312a43ce6adf45537979a98e7afdChandler Carruth << " average variables per function.\n" 16895d98994c7749312a43ce6adf45537979a98e7afdChandler Carruth << " " << MaxUninitAnalysisVariablesPerFunction 16905d98994c7749312a43ce6adf45537979a98e7afdChandler Carruth << " max variables per function.\n" 16915d98994c7749312a43ce6adf45537979a98e7afdChandler Carruth << " " << NumUninitAnalysisBlockVisits << " block visits.\n" 16925d98994c7749312a43ce6adf45537979a98e7afdChandler Carruth << " " << AvgUninitBlockVisitsPerFunction 16935d98994c7749312a43ce6adf45537979a98e7afdChandler Carruth << " average block visits per function.\n" 16945d98994c7749312a43ce6adf45537979a98e7afdChandler Carruth << " " << MaxUninitAnalysisBlockVisitsPerFunction 16955d98994c7749312a43ce6adf45537979a98e7afdChandler Carruth << " max block visits per function.\n"; 16965d98994c7749312a43ce6adf45537979a98e7afdChandler Carruth} 1697