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" 28df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins#include "clang/Analysis/Analyses/Consumed.h" 2955fc873017f10f6f566b182b70f6fc22aefa3464Chandler Carruth#include "clang/Analysis/Analyses/ReachableCode.h" 30402aa0698fec81e574818a0a6c2000fac0b2c4c6Caitlin Sadowski#include "clang/Analysis/Analyses/ThreadSafety.h" 316f34213f8d6ae8c77685b53664527e39bfaaca3bTed Kremenek#include "clang/Analysis/Analyses/UninitializedValues.h" 3255fc873017f10f6f566b182b70f6fc22aefa3464Chandler Carruth#include "clang/Analysis/AnalysisContext.h" 3355fc873017f10f6f566b182b70f6fc22aefa3464Chandler Carruth#include "clang/Analysis/CFG.h" 3455fc873017f10f6f566b182b70f6fc22aefa3464Chandler Carruth#include "clang/Analysis/CFGStmtMap.h" 3555fc873017f10f6f566b182b70f6fc22aefa3464Chandler Carruth#include "clang/Basic/SourceLocation.h" 3655fc873017f10f6f566b182b70f6fc22aefa3464Chandler Carruth#include "clang/Basic/SourceManager.h" 3755fc873017f10f6f566b182b70f6fc22aefa3464Chandler Carruth#include "clang/Lex/Lexer.h" 3855fc873017f10f6f566b182b70f6fc22aefa3464Chandler Carruth#include "clang/Lex/Preprocessor.h" 3955fc873017f10f6f566b182b70f6fc22aefa3464Chandler Carruth#include "clang/Sema/ScopeInfo.h" 4055fc873017f10f6f566b182b70f6fc22aefa3464Chandler Carruth#include "clang/Sema/SemaInternal.h" 4166da0abf7ab7cd449bb1d5134b2ef97d9d34d812Alexander Kornienko#include "llvm/ADT/ArrayRef.h" 42dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek#include "llvm/ADT/BitVector.h" 433ac1fbc303d22af2e11a14023ecee7bd7b7d0bfdCaitlin Sadowski#include "llvm/ADT/FoldingSet.h" 443ac1fbc303d22af2e11a14023ecee7bd7b7d0bfdCaitlin Sadowski#include "llvm/ADT/ImmutableMap.h" 453285c78041f80a26f6a947e2922e15c4af6e00bbEnea Zaffanella#include "llvm/ADT/MapVector.h" 463ac1fbc303d22af2e11a14023ecee7bd7b7d0bfdCaitlin Sadowski#include "llvm/ADT/PostOrderIterator.h" 471952354bd376062c3ab3d328c0fc6c36530c9309Dmitri Gribenko#include "llvm/ADT/SmallString.h" 483ac1fbc303d22af2e11a14023ecee7bd7b7d0bfdCaitlin Sadowski#include "llvm/ADT/SmallVector.h" 4975f23aeb1c820b49f9faebed63b1cbef76c2c907Caitlin Sadowski#include "llvm/ADT/StringRef.h" 50dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek#include "llvm/Support/Casting.h" 513ac1fbc303d22af2e11a14023ecee7bd7b7d0bfdCaitlin Sadowski#include <algorithm> 5255fc873017f10f6f566b182b70f6fc22aefa3464Chandler Carruth#include <deque> 53e0d3b4cd2b66f1cef26cacbed5820ab7c22ad5b3Richard Smith#include <iterator> 543ac1fbc303d22af2e11a14023ecee7bd7b7d0bfdCaitlin Sadowski#include <vector> 55dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek 56dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenekusing namespace clang; 57dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek 58dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek//===----------------------------------------------------------------------===// 59dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek// Unreachable code analysis. 60dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek//===----------------------------------------------------------------------===// 61dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek 62dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremeneknamespace { 63dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek class UnreachableCodeHandler : public reachable_code::Callback { 64dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek Sema &S; 65dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek public: 66dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek UnreachableCodeHandler(Sema &s) : S(s) {} 67dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek 68651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines void HandleUnreachable(reachable_code::UnreachableKind UK, 69651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines SourceLocation L, 70651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines SourceRange SilenceableCondVal, 71651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines SourceRange R1, 72651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines SourceRange R2) override { 73651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines unsigned diag = diag::warn_unreachable; 74651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines switch (UK) { 75651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines case reachable_code::UK_Break: 76651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines diag = diag::warn_unreachable_break; 77651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines break; 78651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines case reachable_code::UK_Return: 79651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines diag = diag::warn_unreachable_return; 80651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines break; 81651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines case reachable_code::UK_Loop_Increment: 82651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines diag = diag::warn_unreachable_loop_increment; 83651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines break; 84651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines case reachable_code::UK_Other: 85651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines break; 86651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines } 87651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines 88651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines S.Diag(L, diag) << R1 << R2; 89651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines 90651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines SourceLocation Open = SilenceableCondVal.getBegin(); 91651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines if (Open.isValid()) { 926bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines SourceLocation Close = SilenceableCondVal.getEnd(); 936bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines Close = S.getLocForEndOfToken(Close); 94651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines if (Close.isValid()) { 95651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines S.Diag(Open, diag::note_unreachable_silence) 96651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines << FixItHint::CreateInsertion(Open, "/* DISABLES CODE */ (") 97651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines << FixItHint::CreateInsertion(Close, ")"); 98651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines } 99651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines } 100dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek } 101dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek }; 102dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek} 103dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek 104dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek/// CheckUnreachable - Check for unreachable code. 1051d26f48dc2eea1c07431ca1519d7034a21b9bcffTed Kremenekstatic void CheckUnreachable(Sema &S, AnalysisDeclContext &AC) { 106651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines // As a heuristic prune all diagnostics not in the main file. Currently 107651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines // the majority of warnings in headers are false positives. These 108651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines // are largely caused by configuration state, e.g. preprocessor 109651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines // defined code, etc. 110651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines // 111651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines // Note that this is also a performance optimization. Analyzing 112651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines // headers many times can be expensive. 113651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines if (!S.getSourceManager().isInMainFile(AC.getDecl()->getLocStart())) 114651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines return; 115651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines 116dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek UnreachableCodeHandler UC(S); 117651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines reachable_code::FindUnreachableCode(AC, S.getPreprocessor(), UC); 118651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines} 119651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines 1200e2c34f92f00628d48968dfea096d36381f494cbStephen Hinesnamespace { 1216bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines/// \brief Warn on logical operator errors in CFGBuilder 1226bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hinesclass LogicalErrorHandler : public CFGCallback { 1236bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines Sema &S; 1246bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines 1256bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hinespublic: 1266bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines LogicalErrorHandler(Sema &S) : CFGCallback(), S(S) {} 1276bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines 1286bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines static bool HasMacroID(const Expr *E) { 1296bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines if (E->getExprLoc().isMacroID()) 1306bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines return true; 1316bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines 1326bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines // Recurse to children. 1336bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines for (ConstStmtRange SubStmts = E->children(); SubStmts; ++SubStmts) 1346bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines if (*SubStmts) 1356bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines if (const Expr *SubExpr = dyn_cast<Expr>(*SubStmts)) 1366bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines if (HasMacroID(SubExpr)) 1376bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines return true; 1386bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines 1396bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines return false; 1406bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines } 1416bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines 14233337ca4d89605025818daf83390ab4271d598d9Pirama Arumuga Nainar void compareAlwaysTrue(const BinaryOperator *B, bool isAlwaysTrue) override { 1436bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines if (HasMacroID(B)) 1446bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines return; 1456bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines 1466bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines SourceRange DiagRange = B->getSourceRange(); 1476bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines S.Diag(B->getExprLoc(), diag::warn_tautological_overlap_comparison) 1486bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines << DiagRange << isAlwaysTrue; 1496bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines } 1506bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines 15133337ca4d89605025818daf83390ab4271d598d9Pirama Arumuga Nainar void compareBitwiseEquality(const BinaryOperator *B, 15233337ca4d89605025818daf83390ab4271d598d9Pirama Arumuga Nainar bool isAlwaysTrue) override { 1536bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines if (HasMacroID(B)) 1546bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines return; 1556bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines 1566bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines SourceRange DiagRange = B->getSourceRange(); 1576bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines S.Diag(B->getExprLoc(), diag::warn_comparison_bitwise_always) 1586bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines << DiagRange << isAlwaysTrue; 1596bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines } 1606bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines}; 1610e2c34f92f00628d48968dfea096d36381f494cbStephen Hines} // namespace 1626bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines 163651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines//===----------------------------------------------------------------------===// 164651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines// Check for infinite self-recursion in functions 165651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines//===----------------------------------------------------------------------===// 166651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines 167651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines// All blocks are in one of three states. States are ordered so that blocks 168651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines// can only move to higher states. 169651f13cea278ec967336033dd032faef0e9fc2ecStephen Hinesenum RecursiveState { 170651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines FoundNoPath, 171651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines FoundPath, 172651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines FoundPathWithNoRecursiveCall 173651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines}; 174651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines 175651f13cea278ec967336033dd032faef0e9fc2ecStephen Hinesstatic void checkForFunctionCall(Sema &S, const FunctionDecl *FD, 176651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines CFGBlock &Block, unsigned ExitID, 177651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines llvm::SmallVectorImpl<RecursiveState> &States, 178651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines RecursiveState State) { 179651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines unsigned ID = Block.getBlockID(); 180651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines 181651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines // A block's state can only move to a higher state. 182651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines if (States[ID] >= State) 183651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines return; 184651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines 185651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines States[ID] = State; 186651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines 187651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines // Found a path to the exit node without a recursive call. 188651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines if (ID == ExitID && State == FoundPathWithNoRecursiveCall) 189651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines return; 190651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines 191651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines if (State == FoundPathWithNoRecursiveCall) { 192651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines // If the current state is FoundPathWithNoRecursiveCall, the successors 193651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines // will be either FoundPathWithNoRecursiveCall or FoundPath. To determine 194651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines // which, process all the Stmt's in this block to find any recursive calls. 1956bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines for (const auto &B : Block) { 1966bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines if (B.getKind() != CFGElement::Statement) 197651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines continue; 198651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines 1996bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines const CallExpr *CE = dyn_cast<CallExpr>(B.getAs<CFGStmt>()->getStmt()); 200651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines if (CE && CE->getCalleeDecl() && 201651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines CE->getCalleeDecl()->getCanonicalDecl() == FD) { 202651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines 203651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines // Skip function calls which are qualified with a templated class. 204651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines if (const DeclRefExpr *DRE = dyn_cast<DeclRefExpr>( 205651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines CE->getCallee()->IgnoreParenImpCasts())) { 206651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines if (NestedNameSpecifier *NNS = DRE->getQualifier()) { 207651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines if (NNS->getKind() == NestedNameSpecifier::TypeSpec && 208651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines isa<TemplateSpecializationType>(NNS->getAsType())) { 209651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines continue; 210651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines } 211651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines } 212651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines } 213651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines 214651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines if (const CXXMemberCallExpr *MCE = dyn_cast<CXXMemberCallExpr>(CE)) { 215651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines if (isa<CXXThisExpr>(MCE->getImplicitObjectArgument()) || 216651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines !MCE->getMethodDecl()->isVirtual()) { 217651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines State = FoundPath; 218651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines break; 219651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines } 220651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines } else { 221651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines State = FoundPath; 222651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines break; 223651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines } 224651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines } 225651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines } 226651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines } 227651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines 228651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines for (CFGBlock::succ_iterator I = Block.succ_begin(), E = Block.succ_end(); 229651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines I != E; ++I) 230651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines if (*I) 231651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines checkForFunctionCall(S, FD, **I, ExitID, States, State); 232651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines} 233651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines 234651f13cea278ec967336033dd032faef0e9fc2ecStephen Hinesstatic void checkRecursiveFunction(Sema &S, const FunctionDecl *FD, 235651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines const Stmt *Body, 236651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines AnalysisDeclContext &AC) { 237651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines FD = FD->getCanonicalDecl(); 238651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines 239651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines // Only run on non-templated functions and non-templated members of 240651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines // templated classes. 241651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines if (FD->getTemplatedKind() != FunctionDecl::TK_NonTemplate && 242651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines FD->getTemplatedKind() != FunctionDecl::TK_MemberSpecialization) 243651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines return; 244651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines 245651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines CFG *cfg = AC.getCFG(); 2466bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines if (!cfg) return; 247651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines 248651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines // If the exit block is unreachable, skip processing the function. 249651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines if (cfg->getExit().pred_empty()) 250651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines return; 251651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines 252651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines // Mark all nodes as FoundNoPath, then begin processing the entry block. 253651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines llvm::SmallVector<RecursiveState, 16> states(cfg->getNumBlockIDs(), 254651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines FoundNoPath); 255651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines checkForFunctionCall(S, FD, cfg->getEntry(), cfg->getExit().getBlockID(), 256651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines states, FoundPathWithNoRecursiveCall); 257651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines 258651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines // Check that the exit block is reachable. This prevents triggering the 259651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines // warning on functions that do not terminate. 260651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines if (states[cfg->getExit().getBlockID()] == FoundPath) 261651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines S.Diag(Body->getLocStart(), diag::warn_infinite_recursive_function); 262dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek} 263dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek 264dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek//===----------------------------------------------------------------------===// 265dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek// Check for missing return value. 266dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek//===----------------------------------------------------------------------===// 267dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek 26816565aa95b086fb239baf82335dccc1b1ec93942John McCallenum ControlFlowKind { 26916565aa95b086fb239baf82335dccc1b1ec93942John McCall UnknownFallThrough, 27016565aa95b086fb239baf82335dccc1b1ec93942John McCall NeverFallThrough, 27116565aa95b086fb239baf82335dccc1b1ec93942John McCall MaybeFallThrough, 27216565aa95b086fb239baf82335dccc1b1ec93942John McCall AlwaysFallThrough, 27316565aa95b086fb239baf82335dccc1b1ec93942John McCall NeverFallThroughOrReturn 27416565aa95b086fb239baf82335dccc1b1ec93942John McCall}; 275dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek 276dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek/// CheckFallThrough - Check that we don't fall off the end of a 277dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek/// Statement that should return a value. 278dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek/// 279f3477c13eeaf11b32a41f181398fb5deffd0dd73Sylvestre Ledru/// \returns AlwaysFallThrough iff we always fall off the end of the statement, 280f3477c13eeaf11b32a41f181398fb5deffd0dd73Sylvestre Ledru/// MaybeFallThrough iff we might or might not fall off the end, 281f3477c13eeaf11b32a41f181398fb5deffd0dd73Sylvestre Ledru/// NeverFallThroughOrReturn iff we never fall off the end of the statement or 282f3477c13eeaf11b32a41f181398fb5deffd0dd73Sylvestre Ledru/// return. We assume NeverFallThrough iff we never fall off the end of the 283dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek/// statement but we may return. We assume that functions not marked noreturn 284dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek/// will return. 2851d26f48dc2eea1c07431ca1519d7034a21b9bcffTed Kremenekstatic ControlFlowKind CheckFallThrough(AnalysisDeclContext &AC) { 286dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek CFG *cfg = AC.getCFG(); 2876bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines if (!cfg) return UnknownFallThrough; 288dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek 289dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek // The CFG leaves in dead things, and we don't want the dead code paths to 290dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek // confuse us, so we mark all live things first. 291dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek llvm::BitVector live(cfg->getNumBlockIDs()); 2920f3b4ca1764cd6d457f511d340fba504f41763c3Ted Kremenek unsigned count = reachable_code::ScanReachableFromBlock(&cfg->getEntry(), 293dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek live); 294dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek 295dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek bool AddEHEdges = AC.getAddEHEdges(); 296dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek if (!AddEHEdges && count != cfg->getNumBlockIDs()) 297dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek // When there are things remaining dead, and we didn't add EH edges 298dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek // from CallExprs to the catch clauses, we have to go back and 299dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek // mark them as live. 3006bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines for (const auto *B : *cfg) { 3016bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines if (!live[B->getBlockID()]) { 3026bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines if (B->pred_begin() == B->pred_end()) { 3036bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines if (B->getTerminator() && isa<CXXTryStmt>(B->getTerminator())) 304dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek // When not adding EH edges from calls, catch clauses 305dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek // can otherwise seem dead. Avoid noting them as dead. 3066bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines count += reachable_code::ScanReachableFromBlock(B, live); 307dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek continue; 308dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek } 309dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek } 310dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek } 311dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek 312dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek // Now we know what is live, we check the live precessors of the exit block 313dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek // and look for fall through paths, being careful to ignore normal returns, 314dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek // and exceptional paths. 315dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek bool HasLiveReturn = false; 316dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek bool HasFakeEdge = false; 317dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek bool HasPlainEdge = false; 318dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek bool HasAbnormalEdge = false; 31990b828aa279542559f655d1af666580288cb1841Ted Kremenek 32090b828aa279542559f655d1af666580288cb1841Ted Kremenek // Ignore default cases that aren't likely to be reachable because all 32190b828aa279542559f655d1af666580288cb1841Ted Kremenek // enums in a switch(X) have explicit case statements. 32290b828aa279542559f655d1af666580288cb1841Ted Kremenek CFGBlock::FilterOptions FO; 32390b828aa279542559f655d1af666580288cb1841Ted Kremenek FO.IgnoreDefaultsWithCoveredEnums = 1; 32490b828aa279542559f655d1af666580288cb1841Ted Kremenek 32590b828aa279542559f655d1af666580288cb1841Ted Kremenek for (CFGBlock::filtered_pred_iterator 32690b828aa279542559f655d1af666580288cb1841Ted Kremenek I = cfg->getExit().filtered_pred_start_end(FO); I.hasMore(); ++I) { 32790b828aa279542559f655d1af666580288cb1841Ted Kremenek const CFGBlock& B = **I; 328dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek if (!live[B.getBlockID()]) 329dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek continue; 3305811f5978feaa7b89bd89e174fa7ad077b48413eTed Kremenek 331e05ee6df356c25e792b0334d7a4dec3fe4f79f07Chandler Carruth // Skip blocks which contain an element marked as no-return. They don't 332e05ee6df356c25e792b0334d7a4dec3fe4f79f07Chandler Carruth // represent actually viable edges into the exit block, so mark them as 333e05ee6df356c25e792b0334d7a4dec3fe4f79f07Chandler Carruth // abnormal. 334e05ee6df356c25e792b0334d7a4dec3fe4f79f07Chandler Carruth if (B.hasNoReturnElement()) { 335e05ee6df356c25e792b0334d7a4dec3fe4f79f07Chandler Carruth HasAbnormalEdge = true; 336e05ee6df356c25e792b0334d7a4dec3fe4f79f07Chandler Carruth continue; 337e05ee6df356c25e792b0334d7a4dec3fe4f79f07Chandler Carruth } 338e05ee6df356c25e792b0334d7a4dec3fe4f79f07Chandler Carruth 3395811f5978feaa7b89bd89e174fa7ad077b48413eTed Kremenek // Destructors can appear after the 'return' in the CFG. This is 3405811f5978feaa7b89bd89e174fa7ad077b48413eTed Kremenek // normal. We need to look pass the destructors for the return 3415811f5978feaa7b89bd89e174fa7ad077b48413eTed Kremenek // statement (if it exists). 3425811f5978feaa7b89bd89e174fa7ad077b48413eTed Kremenek CFGBlock::const_reverse_iterator ri = B.rbegin(), re = B.rend(); 343e05ee6df356c25e792b0334d7a4dec3fe4f79f07Chandler Carruth 344e05ee6df356c25e792b0334d7a4dec3fe4f79f07Chandler Carruth for ( ; ri != re ; ++ri) 345fdf6a279c9a75c778eba382d9a156697092982a1David Blaikie if (ri->getAs<CFGStmt>()) 3465811f5978feaa7b89bd89e174fa7ad077b48413eTed Kremenek break; 347e05ee6df356c25e792b0334d7a4dec3fe4f79f07Chandler Carruth 3485811f5978feaa7b89bd89e174fa7ad077b48413eTed Kremenek // No more CFGElements in the block? 3495811f5978feaa7b89bd89e174fa7ad077b48413eTed Kremenek if (ri == re) { 350dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek if (B.getTerminator() && isa<CXXTryStmt>(B.getTerminator())) { 351dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek HasAbnormalEdge = true; 352dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek continue; 353dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek } 354dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek // A labeled empty statement, or the entry block... 355dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek HasPlainEdge = true; 356dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek continue; 357dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek } 358f39e6a388aaa2f155b46c61e655784b2473218ebTed Kremenek 359fdf6a279c9a75c778eba382d9a156697092982a1David Blaikie CFGStmt CS = ri->castAs<CFGStmt>(); 360f1d10d939739f1a4544926d807e4f0f9fb64be61Ted Kremenek const Stmt *S = CS.getStmt(); 361dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek if (isa<ReturnStmt>(S)) { 362dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek HasLiveReturn = true; 363dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek continue; 364dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek } 365dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek if (isa<ObjCAtThrowStmt>(S)) { 366dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek HasFakeEdge = true; 367dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek continue; 368dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek } 369dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek if (isa<CXXThrowExpr>(S)) { 370dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek HasFakeEdge = true; 371dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek continue; 372dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek } 3738cd64b4c5553fa6284d248336cb7c82dc960a394Chad Rosier if (isa<MSAsmStmt>(S)) { 3748cd64b4c5553fa6284d248336cb7c82dc960a394Chad Rosier // TODO: Verify this is correct. 3758cd64b4c5553fa6284d248336cb7c82dc960a394Chad Rosier HasFakeEdge = true; 3768cd64b4c5553fa6284d248336cb7c82dc960a394Chad Rosier HasLiveReturn = true; 3778cd64b4c5553fa6284d248336cb7c82dc960a394Chad Rosier continue; 3788cd64b4c5553fa6284d248336cb7c82dc960a394Chad Rosier } 379dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek if (isa<CXXTryStmt>(S)) { 380dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek HasAbnormalEdge = true; 381dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek continue; 382dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek } 383e05ee6df356c25e792b0334d7a4dec3fe4f79f07Chandler Carruth if (std::find(B.succ_begin(), B.succ_end(), &cfg->getExit()) 384e05ee6df356c25e792b0334d7a4dec3fe4f79f07Chandler Carruth == B.succ_end()) { 385e05ee6df356c25e792b0334d7a4dec3fe4f79f07Chandler Carruth HasAbnormalEdge = true; 386e05ee6df356c25e792b0334d7a4dec3fe4f79f07Chandler Carruth continue; 387dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek } 388e05ee6df356c25e792b0334d7a4dec3fe4f79f07Chandler Carruth 389e05ee6df356c25e792b0334d7a4dec3fe4f79f07Chandler Carruth HasPlainEdge = true; 390dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek } 391dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek if (!HasPlainEdge) { 392dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek if (HasLiveReturn) 393dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek return NeverFallThrough; 394dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek return NeverFallThroughOrReturn; 395dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek } 396dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek if (HasAbnormalEdge || HasFakeEdge || HasLiveReturn) 397dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek return MaybeFallThrough; 398dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek // This says AlwaysFallThrough for calls to functions that are not marked 399dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek // noreturn, that don't return. If people would like this warning to be more 400dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek // accurate, such functions should be marked as noreturn. 401dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek return AlwaysFallThrough; 402dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek} 403dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek 4043c46e8db99196179b30e7ac5c20c4efd5f3926d7Dan Gohmannamespace { 4053c46e8db99196179b30e7ac5c20c4efd5f3926d7Dan Gohman 406dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenekstruct CheckFallThroughDiagnostics { 407dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek unsigned diag_MaybeFallThrough_HasNoReturn; 408dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek unsigned diag_MaybeFallThrough_ReturnsNonVoid; 409dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek unsigned diag_AlwaysFallThrough_HasNoReturn; 410dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek unsigned diag_AlwaysFallThrough_ReturnsNonVoid; 411dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek unsigned diag_NeverFallThroughOrReturn; 412793cd1c4cdfaafc52e2c2ad9dae959befe4bb166Douglas Gregor enum { Function, Block, Lambda } funMode; 4130827408865e32789e0ec4b8113a302ccdc531423Argyrios Kyrtzidis SourceLocation FuncLoc; 414d064fdc4b7b64ca55b40b70490c79d6f569df78eTed Kremenek 415ca7eaeeed817001dc7cee4852a7e41f0982da1efDouglas Gregor static CheckFallThroughDiagnostics MakeForFunction(const Decl *Func) { 416dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek CheckFallThroughDiagnostics D; 4170827408865e32789e0ec4b8113a302ccdc531423Argyrios Kyrtzidis D.FuncLoc = Func->getLocation(); 418dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek D.diag_MaybeFallThrough_HasNoReturn = 419dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek diag::warn_falloff_noreturn_function; 420dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek D.diag_MaybeFallThrough_ReturnsNonVoid = 421dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek diag::warn_maybe_falloff_nonvoid_function; 422dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek D.diag_AlwaysFallThrough_HasNoReturn = 423dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek diag::warn_falloff_noreturn_function; 424dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek D.diag_AlwaysFallThrough_ReturnsNonVoid = 425dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek diag::warn_falloff_nonvoid_function; 426ca7eaeeed817001dc7cee4852a7e41f0982da1efDouglas Gregor 427ca7eaeeed817001dc7cee4852a7e41f0982da1efDouglas Gregor // Don't suggest that virtual functions be marked "noreturn", since they 428ca7eaeeed817001dc7cee4852a7e41f0982da1efDouglas Gregor // might be overridden by non-noreturn functions. 429ca7eaeeed817001dc7cee4852a7e41f0982da1efDouglas Gregor bool isVirtualMethod = false; 430ca7eaeeed817001dc7cee4852a7e41f0982da1efDouglas Gregor if (const CXXMethodDecl *Method = dyn_cast<CXXMethodDecl>(Func)) 431ca7eaeeed817001dc7cee4852a7e41f0982da1efDouglas Gregor isVirtualMethod = Method->isVirtual(); 432ca7eaeeed817001dc7cee4852a7e41f0982da1efDouglas Gregor 433fcdd2cb2fdf35f806dd800b369fe0772a1c8c26cDouglas Gregor // Don't suggest that template instantiations be marked "noreturn" 434fcdd2cb2fdf35f806dd800b369fe0772a1c8c26cDouglas Gregor bool isTemplateInstantiation = false; 43575df4eeede7b91c22c1d63fafd4dd4142844e3b9Ted Kremenek if (const FunctionDecl *Function = dyn_cast<FunctionDecl>(Func)) 43675df4eeede7b91c22c1d63fafd4dd4142844e3b9Ted Kremenek isTemplateInstantiation = Function->isTemplateInstantiation(); 437fcdd2cb2fdf35f806dd800b369fe0772a1c8c26cDouglas Gregor 438fcdd2cb2fdf35f806dd800b369fe0772a1c8c26cDouglas Gregor if (!isVirtualMethod && !isTemplateInstantiation) 439ca7eaeeed817001dc7cee4852a7e41f0982da1efDouglas Gregor D.diag_NeverFallThroughOrReturn = 440ca7eaeeed817001dc7cee4852a7e41f0982da1efDouglas Gregor diag::warn_suggest_noreturn_function; 441ca7eaeeed817001dc7cee4852a7e41f0982da1efDouglas Gregor else 442ca7eaeeed817001dc7cee4852a7e41f0982da1efDouglas Gregor D.diag_NeverFallThroughOrReturn = 0; 443ca7eaeeed817001dc7cee4852a7e41f0982da1efDouglas Gregor 444793cd1c4cdfaafc52e2c2ad9dae959befe4bb166Douglas Gregor D.funMode = Function; 445dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek return D; 446dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek } 447d064fdc4b7b64ca55b40b70490c79d6f569df78eTed Kremenek 448dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek static CheckFallThroughDiagnostics MakeForBlock() { 449dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek CheckFallThroughDiagnostics D; 450dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek D.diag_MaybeFallThrough_HasNoReturn = 451dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek diag::err_noreturn_block_has_return_expr; 452dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek D.diag_MaybeFallThrough_ReturnsNonVoid = 453dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek diag::err_maybe_falloff_nonvoid_block; 454dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek D.diag_AlwaysFallThrough_HasNoReturn = 455dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek diag::err_noreturn_block_has_return_expr; 456dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek D.diag_AlwaysFallThrough_ReturnsNonVoid = 457dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek diag::err_falloff_nonvoid_block; 4586bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines D.diag_NeverFallThroughOrReturn = 0; 459793cd1c4cdfaafc52e2c2ad9dae959befe4bb166Douglas Gregor D.funMode = Block; 460793cd1c4cdfaafc52e2c2ad9dae959befe4bb166Douglas Gregor return D; 461793cd1c4cdfaafc52e2c2ad9dae959befe4bb166Douglas Gregor } 462793cd1c4cdfaafc52e2c2ad9dae959befe4bb166Douglas Gregor 463793cd1c4cdfaafc52e2c2ad9dae959befe4bb166Douglas Gregor static CheckFallThroughDiagnostics MakeForLambda() { 464793cd1c4cdfaafc52e2c2ad9dae959befe4bb166Douglas Gregor CheckFallThroughDiagnostics D; 465793cd1c4cdfaafc52e2c2ad9dae959befe4bb166Douglas Gregor D.diag_MaybeFallThrough_HasNoReturn = 466793cd1c4cdfaafc52e2c2ad9dae959befe4bb166Douglas Gregor diag::err_noreturn_lambda_has_return_expr; 467793cd1c4cdfaafc52e2c2ad9dae959befe4bb166Douglas Gregor D.diag_MaybeFallThrough_ReturnsNonVoid = 468793cd1c4cdfaafc52e2c2ad9dae959befe4bb166Douglas Gregor diag::warn_maybe_falloff_nonvoid_lambda; 469793cd1c4cdfaafc52e2c2ad9dae959befe4bb166Douglas Gregor D.diag_AlwaysFallThrough_HasNoReturn = 470793cd1c4cdfaafc52e2c2ad9dae959befe4bb166Douglas Gregor diag::err_noreturn_lambda_has_return_expr; 471793cd1c4cdfaafc52e2c2ad9dae959befe4bb166Douglas Gregor D.diag_AlwaysFallThrough_ReturnsNonVoid = 472793cd1c4cdfaafc52e2c2ad9dae959befe4bb166Douglas Gregor diag::warn_falloff_nonvoid_lambda; 473793cd1c4cdfaafc52e2c2ad9dae959befe4bb166Douglas Gregor D.diag_NeverFallThroughOrReturn = 0; 474793cd1c4cdfaafc52e2c2ad9dae959befe4bb166Douglas Gregor D.funMode = Lambda; 475dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek return D; 476dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek } 477d064fdc4b7b64ca55b40b70490c79d6f569df78eTed Kremenek 478d6471f7c1921c7802804ce3ff6fe9768310f72b9David Blaikie bool checkDiagnostics(DiagnosticsEngine &D, bool ReturnsVoid, 479dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek bool HasNoReturn) const { 480793cd1c4cdfaafc52e2c2ad9dae959befe4bb166Douglas Gregor if (funMode == Function) { 4810827408865e32789e0ec4b8113a302ccdc531423Argyrios Kyrtzidis return (ReturnsVoid || 482c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines D.isIgnored(diag::warn_maybe_falloff_nonvoid_function, 483c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines FuncLoc)) && 484c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines (!HasNoReturn || 485c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines D.isIgnored(diag::warn_noreturn_function_has_return_expr, 486c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines FuncLoc)) && 487c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines (!ReturnsVoid || 488c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines D.isIgnored(diag::warn_suggest_noreturn_block, FuncLoc)); 489dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek } 490d064fdc4b7b64ca55b40b70490c79d6f569df78eTed Kremenek 491793cd1c4cdfaafc52e2c2ad9dae959befe4bb166Douglas Gregor // For blocks / lambdas. 4926bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines return ReturnsVoid && !HasNoReturn; 493dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek } 494dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek}; 495dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek 4963c46e8db99196179b30e7ac5c20c4efd5f3926d7Dan Gohman} 4973c46e8db99196179b30e7ac5c20c4efd5f3926d7Dan Gohman 498dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek/// CheckFallThroughForFunctionDef - Check that we don't fall off the end of a 499dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek/// function that should return a value. Check that we don't fall off the end 500dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek/// of a noreturn function. We assume that functions and blocks not marked 501dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek/// noreturn will return. 502dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenekstatic void CheckFallThroughForBody(Sema &S, const Decl *D, const Stmt *Body, 5033ed6fc08a9cd293d012fa49ab2a615e618d7c3faTed Kremenek const BlockExpr *blkExpr, 504dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek const CheckFallThroughDiagnostics& CD, 5051d26f48dc2eea1c07431ca1519d7034a21b9bcffTed Kremenek AnalysisDeclContext &AC) { 506dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek 507dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek bool ReturnsVoid = false; 508dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek bool HasNoReturn = false; 509dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek 510dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(D)) { 511651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines ReturnsVoid = FD->getReturnType()->isVoidType(); 512cd8ab51a44e80625d84126780b0d85a7732e25afRichard Smith HasNoReturn = FD->isNoReturn(); 513dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek } 514dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek else if (const ObjCMethodDecl *MD = dyn_cast<ObjCMethodDecl>(D)) { 515651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines ReturnsVoid = MD->getReturnType()->isVoidType(); 516dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek HasNoReturn = MD->hasAttr<NoReturnAttr>(); 517dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek } 518dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek else if (isa<BlockDecl>(D)) { 5193ed6fc08a9cd293d012fa49ab2a615e618d7c3faTed Kremenek QualType BlockTy = blkExpr->getType(); 520d064fdc4b7b64ca55b40b70490c79d6f569df78eTed Kremenek if (const FunctionType *FT = 521dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek BlockTy->getPointeeType()->getAs<FunctionType>()) { 522651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines if (FT->getReturnType()->isVoidType()) 523dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek ReturnsVoid = true; 524dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek if (FT->getNoReturnAttr()) 525dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek HasNoReturn = true; 526dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek } 527dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek } 528dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek 529d6471f7c1921c7802804ce3ff6fe9768310f72b9David Blaikie DiagnosticsEngine &Diags = S.getDiagnostics(); 530dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek 531dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek // Short circuit for compilation speed. 532dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek if (CD.checkDiagnostics(Diags, ReturnsVoid, HasNoReturn)) 533dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek return; 534d064fdc4b7b64ca55b40b70490c79d6f569df78eTed Kremenek 535176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines SourceLocation LBrace = Body->getLocStart(), RBrace = Body->getLocEnd(); 536176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines // Either in a function body compound statement, or a function-try-block. 537176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines switch (CheckFallThrough(AC)) { 538176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines case UnknownFallThrough: 539176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines break; 54016565aa95b086fb239baf82335dccc1b1ec93942John McCall 541176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines case MaybeFallThrough: 542176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines if (HasNoReturn) 543176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines S.Diag(RBrace, CD.diag_MaybeFallThrough_HasNoReturn); 544176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines else if (!ReturnsVoid) 545176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines S.Diag(RBrace, CD.diag_MaybeFallThrough_ReturnsNonVoid); 546176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines break; 547176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines case AlwaysFallThrough: 548176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines if (HasNoReturn) 549176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines S.Diag(RBrace, CD.diag_AlwaysFallThrough_HasNoReturn); 550176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines else if (!ReturnsVoid) 551176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines S.Diag(RBrace, CD.diag_AlwaysFallThrough_ReturnsNonVoid); 552176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines break; 553176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines case NeverFallThroughOrReturn: 554176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines if (ReturnsVoid && !HasNoReturn && CD.diag_NeverFallThroughOrReturn) { 555176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(D)) { 556176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines S.Diag(LBrace, CD.diag_NeverFallThroughOrReturn) << 0 << FD; 557176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines } else if (const ObjCMethodDecl *MD = dyn_cast<ObjCMethodDecl>(D)) { 558176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines S.Diag(LBrace, CD.diag_NeverFallThroughOrReturn) << 1 << MD; 559176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines } else { 560176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines S.Diag(LBrace, CD.diag_NeverFallThroughOrReturn); 561b0656ec72e25e5c8e463c2dc39914636f0cb06d1Chandler Carruth } 562176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines } 563176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines break; 564176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines case NeverFallThrough: 565176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines break; 566dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek } 567dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek} 568dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek 569dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek//===----------------------------------------------------------------------===// 570610068c8cd2321f90e147b12cf794e1f840b6405Ted Kremenek// -Wuninitialized 571610068c8cd2321f90e147b12cf794e1f840b6405Ted Kremenek//===----------------------------------------------------------------------===// 572610068c8cd2321f90e147b12cf794e1f840b6405Ted Kremenek 5736f41715df2c6a31c0c3ab3088b8cd18a3c8321b8Ted Kremeneknamespace { 5749f6494687c05fe1d334af76408ee056b5f80e027Chandler Carruth/// ContainsReference - A visitor class to search for references to 5759f6494687c05fe1d334af76408ee056b5f80e027Chandler Carruth/// a particular declaration (the needle) within any evaluated component of an 5769f6494687c05fe1d334af76408ee056b5f80e027Chandler Carruth/// expression (recursively). 5776f41715df2c6a31c0c3ab3088b8cd18a3c8321b8Ted Kremenekclass ContainsReference : public EvaluatedExprVisitor<ContainsReference> { 5789f6494687c05fe1d334af76408ee056b5f80e027Chandler Carruth bool FoundReference; 5799f6494687c05fe1d334af76408ee056b5f80e027Chandler Carruth const DeclRefExpr *Needle; 5809f6494687c05fe1d334af76408ee056b5f80e027Chandler Carruth 5816f41715df2c6a31c0c3ab3088b8cd18a3c8321b8Ted Kremenekpublic: 5829f6494687c05fe1d334af76408ee056b5f80e027Chandler Carruth ContainsReference(ASTContext &Context, const DeclRefExpr *Needle) 5839f6494687c05fe1d334af76408ee056b5f80e027Chandler Carruth : EvaluatedExprVisitor<ContainsReference>(Context), 5849f6494687c05fe1d334af76408ee056b5f80e027Chandler Carruth FoundReference(false), Needle(Needle) {} 5859f6494687c05fe1d334af76408ee056b5f80e027Chandler Carruth 5869f6494687c05fe1d334af76408ee056b5f80e027Chandler Carruth void VisitExpr(Expr *E) { 5876f41715df2c6a31c0c3ab3088b8cd18a3c8321b8Ted Kremenek // Stop evaluating if we already have a reference. 5889f6494687c05fe1d334af76408ee056b5f80e027Chandler Carruth if (FoundReference) 5896f41715df2c6a31c0c3ab3088b8cd18a3c8321b8Ted Kremenek return; 5909f6494687c05fe1d334af76408ee056b5f80e027Chandler Carruth 5919f6494687c05fe1d334af76408ee056b5f80e027Chandler Carruth EvaluatedExprVisitor<ContainsReference>::VisitExpr(E); 5926f41715df2c6a31c0c3ab3088b8cd18a3c8321b8Ted Kremenek } 5939f6494687c05fe1d334af76408ee056b5f80e027Chandler Carruth 5949f6494687c05fe1d334af76408ee056b5f80e027Chandler Carruth void VisitDeclRefExpr(DeclRefExpr *E) { 5959f6494687c05fe1d334af76408ee056b5f80e027Chandler Carruth if (E == Needle) 5969f6494687c05fe1d334af76408ee056b5f80e027Chandler Carruth FoundReference = true; 5979f6494687c05fe1d334af76408ee056b5f80e027Chandler Carruth else 5989f6494687c05fe1d334af76408ee056b5f80e027Chandler Carruth EvaluatedExprVisitor<ContainsReference>::VisitDeclRefExpr(E); 5996f41715df2c6a31c0c3ab3088b8cd18a3c8321b8Ted Kremenek } 6009f6494687c05fe1d334af76408ee056b5f80e027Chandler Carruth 6019f6494687c05fe1d334af76408ee056b5f80e027Chandler Carruth bool doesContainReference() const { return FoundReference; } 6026f41715df2c6a31c0c3ab3088b8cd18a3c8321b8Ted Kremenek}; 6036f41715df2c6a31c0c3ab3088b8cd18a3c8321b8Ted Kremenek} 6046f41715df2c6a31c0c3ab3088b8cd18a3c8321b8Ted Kremenek 6054f4f349208b2b2307454e169ac7b039e989f003fDavid Blaikiestatic bool SuggestInitializationFixit(Sema &S, const VarDecl *VD) { 606a34194f035096dd8dce10574e3a186da968aa211Fariborz Jahanian QualType VariableTy = VD->getType().getCanonicalType(); 607a34194f035096dd8dce10574e3a186da968aa211Fariborz Jahanian if (VariableTy->isBlockPointerType() && 608a34194f035096dd8dce10574e3a186da968aa211Fariborz Jahanian !VD->hasAttr<BlocksAttr>()) { 609c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines S.Diag(VD->getLocation(), diag::note_block_var_fixit_add_initialization) 610c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines << VD->getDeclName() 611c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines << FixItHint::CreateInsertion(VD->getLocation(), "__block "); 612a34194f035096dd8dce10574e3a186da968aa211Fariborz Jahanian return true; 613a34194f035096dd8dce10574e3a186da968aa211Fariborz Jahanian } 6148adf837adc65b55a3f74643c02c1ee077dc26f06Richard Smith 6154f4f349208b2b2307454e169ac7b039e989f003fDavid Blaikie // Don't issue a fixit if there is already an initializer. 6164f4f349208b2b2307454e169ac7b039e989f003fDavid Blaikie if (VD->getInit()) 6174f4f349208b2b2307454e169ac7b039e989f003fDavid Blaikie return false; 6187b0a3e378c441cec60f929d13bd48846c267a008Richard Trieu 6197b0a3e378c441cec60f929d13bd48846c267a008Richard Trieu // Don't suggest a fixit inside macros. 6207b0a3e378c441cec60f929d13bd48846c267a008Richard Trieu if (VD->getLocEnd().isMacroID()) 6217b0a3e378c441cec60f929d13bd48846c267a008Richard Trieu return false; 6227b0a3e378c441cec60f929d13bd48846c267a008Richard Trieu 6236bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines SourceLocation Loc = S.getLocForEndOfToken(VD->getLocEnd()); 6248adf837adc65b55a3f74643c02c1ee077dc26f06Richard Smith 6258adf837adc65b55a3f74643c02c1ee077dc26f06Richard Smith // Suggest possible initialization (if any). 6268adf837adc65b55a3f74643c02c1ee077dc26f06Richard Smith std::string Init = S.getFixItZeroInitializerForType(VariableTy, Loc); 6278adf837adc65b55a3f74643c02c1ee077dc26f06Richard Smith if (Init.empty()) 6288adf837adc65b55a3f74643c02c1ee077dc26f06Richard Smith return false; 6298adf837adc65b55a3f74643c02c1ee077dc26f06Richard Smith 6307984de35644701c0d94336da7f2215d4c26d9f5bRichard Smith S.Diag(Loc, diag::note_var_fixit_add_initialization) << VD->getDeclName() 6317984de35644701c0d94336da7f2215d4c26d9f5bRichard Smith << FixItHint::CreateInsertion(Loc, Init); 6327984de35644701c0d94336da7f2215d4c26d9f5bRichard Smith return true; 6334f4f349208b2b2307454e169ac7b039e989f003fDavid Blaikie} 6344f4f349208b2b2307454e169ac7b039e989f003fDavid Blaikie 635bdb97ff687ce85e45cc728b87612ed546f48c1e7Richard Smith/// Create a fixit to remove an if-like statement, on the assumption that its 636bdb97ff687ce85e45cc728b87612ed546f48c1e7Richard Smith/// condition is CondVal. 637bdb97ff687ce85e45cc728b87612ed546f48c1e7Richard Smithstatic void CreateIfFixit(Sema &S, const Stmt *If, const Stmt *Then, 638bdb97ff687ce85e45cc728b87612ed546f48c1e7Richard Smith const Stmt *Else, bool CondVal, 639bdb97ff687ce85e45cc728b87612ed546f48c1e7Richard Smith FixItHint &Fixit1, FixItHint &Fixit2) { 640bdb97ff687ce85e45cc728b87612ed546f48c1e7Richard Smith if (CondVal) { 641bdb97ff687ce85e45cc728b87612ed546f48c1e7Richard Smith // If condition is always true, remove all but the 'then'. 642bdb97ff687ce85e45cc728b87612ed546f48c1e7Richard Smith Fixit1 = FixItHint::CreateRemoval( 643bdb97ff687ce85e45cc728b87612ed546f48c1e7Richard Smith CharSourceRange::getCharRange(If->getLocStart(), 644bdb97ff687ce85e45cc728b87612ed546f48c1e7Richard Smith Then->getLocStart())); 645bdb97ff687ce85e45cc728b87612ed546f48c1e7Richard Smith if (Else) { 646bdb97ff687ce85e45cc728b87612ed546f48c1e7Richard Smith SourceLocation ElseKwLoc = Lexer::getLocForEndOfToken( 647bdb97ff687ce85e45cc728b87612ed546f48c1e7Richard Smith Then->getLocEnd(), 0, S.getSourceManager(), S.getLangOpts()); 648bdb97ff687ce85e45cc728b87612ed546f48c1e7Richard Smith Fixit2 = FixItHint::CreateRemoval( 649bdb97ff687ce85e45cc728b87612ed546f48c1e7Richard Smith SourceRange(ElseKwLoc, Else->getLocEnd())); 650bdb97ff687ce85e45cc728b87612ed546f48c1e7Richard Smith } 651bdb97ff687ce85e45cc728b87612ed546f48c1e7Richard Smith } else { 652bdb97ff687ce85e45cc728b87612ed546f48c1e7Richard Smith // If condition is always false, remove all but the 'else'. 653bdb97ff687ce85e45cc728b87612ed546f48c1e7Richard Smith if (Else) 654bdb97ff687ce85e45cc728b87612ed546f48c1e7Richard Smith Fixit1 = FixItHint::CreateRemoval( 655bdb97ff687ce85e45cc728b87612ed546f48c1e7Richard Smith CharSourceRange::getCharRange(If->getLocStart(), 656bdb97ff687ce85e45cc728b87612ed546f48c1e7Richard Smith Else->getLocStart())); 657bdb97ff687ce85e45cc728b87612ed546f48c1e7Richard Smith else 658bdb97ff687ce85e45cc728b87612ed546f48c1e7Richard Smith Fixit1 = FixItHint::CreateRemoval(If->getSourceRange()); 659bdb97ff687ce85e45cc728b87612ed546f48c1e7Richard Smith } 660bdb97ff687ce85e45cc728b87612ed546f48c1e7Richard Smith} 661bdb97ff687ce85e45cc728b87612ed546f48c1e7Richard Smith 662bdb97ff687ce85e45cc728b87612ed546f48c1e7Richard Smith/// DiagUninitUse -- Helper function to produce a diagnostic for an 663bdb97ff687ce85e45cc728b87612ed546f48c1e7Richard Smith/// uninitialized use of a variable. 664bdb97ff687ce85e45cc728b87612ed546f48c1e7Richard Smithstatic void DiagUninitUse(Sema &S, const VarDecl *VD, const UninitUse &Use, 665bdb97ff687ce85e45cc728b87612ed546f48c1e7Richard Smith bool IsCapturedByBlock) { 666bdb97ff687ce85e45cc728b87612ed546f48c1e7Richard Smith bool Diagnosed = false; 667bdb97ff687ce85e45cc728b87612ed546f48c1e7Richard Smith 6688a1fdfc69cc6c2ccbfd57fc8ff643c589da9df9bRichard Smith switch (Use.getKind()) { 6698a1fdfc69cc6c2ccbfd57fc8ff643c589da9df9bRichard Smith case UninitUse::Always: 6708a1fdfc69cc6c2ccbfd57fc8ff643c589da9df9bRichard Smith S.Diag(Use.getUser()->getLocStart(), diag::warn_uninit_var) 6718a1fdfc69cc6c2ccbfd57fc8ff643c589da9df9bRichard Smith << VD->getDeclName() << IsCapturedByBlock 6728a1fdfc69cc6c2ccbfd57fc8ff643c589da9df9bRichard Smith << Use.getUser()->getSourceRange(); 6738a1fdfc69cc6c2ccbfd57fc8ff643c589da9df9bRichard Smith return; 6748a1fdfc69cc6c2ccbfd57fc8ff643c589da9df9bRichard Smith 6758a1fdfc69cc6c2ccbfd57fc8ff643c589da9df9bRichard Smith case UninitUse::AfterDecl: 6768a1fdfc69cc6c2ccbfd57fc8ff643c589da9df9bRichard Smith case UninitUse::AfterCall: 6778a1fdfc69cc6c2ccbfd57fc8ff643c589da9df9bRichard Smith S.Diag(VD->getLocation(), diag::warn_sometimes_uninit_var) 6788a1fdfc69cc6c2ccbfd57fc8ff643c589da9df9bRichard Smith << VD->getDeclName() << IsCapturedByBlock 6798a1fdfc69cc6c2ccbfd57fc8ff643c589da9df9bRichard Smith << (Use.getKind() == UninitUse::AfterDecl ? 4 : 5) 6808a1fdfc69cc6c2ccbfd57fc8ff643c589da9df9bRichard Smith << const_cast<DeclContext*>(VD->getLexicalDeclContext()) 6818a1fdfc69cc6c2ccbfd57fc8ff643c589da9df9bRichard Smith << VD->getSourceRange(); 6828a1fdfc69cc6c2ccbfd57fc8ff643c589da9df9bRichard Smith S.Diag(Use.getUser()->getLocStart(), diag::note_uninit_var_use) 6838a1fdfc69cc6c2ccbfd57fc8ff643c589da9df9bRichard Smith << IsCapturedByBlock << Use.getUser()->getSourceRange(); 6848a1fdfc69cc6c2ccbfd57fc8ff643c589da9df9bRichard Smith return; 6858a1fdfc69cc6c2ccbfd57fc8ff643c589da9df9bRichard Smith 6868a1fdfc69cc6c2ccbfd57fc8ff643c589da9df9bRichard Smith case UninitUse::Maybe: 6878a1fdfc69cc6c2ccbfd57fc8ff643c589da9df9bRichard Smith case UninitUse::Sometimes: 6888a1fdfc69cc6c2ccbfd57fc8ff643c589da9df9bRichard Smith // Carry on to report sometimes-uninitialized branches, if possible, 6898a1fdfc69cc6c2ccbfd57fc8ff643c589da9df9bRichard Smith // or a 'may be used uninitialized' diagnostic otherwise. 6908a1fdfc69cc6c2ccbfd57fc8ff643c589da9df9bRichard Smith break; 6918a1fdfc69cc6c2ccbfd57fc8ff643c589da9df9bRichard Smith } 6928a1fdfc69cc6c2ccbfd57fc8ff643c589da9df9bRichard Smith 693bdb97ff687ce85e45cc728b87612ed546f48c1e7Richard Smith // Diagnose each branch which leads to a sometimes-uninitialized use. 6942815e1a075c74143a0b60a632090ece1dffa5c7cRichard Smith for (UninitUse::branch_iterator I = Use.branch_begin(), E = Use.branch_end(); 6952815e1a075c74143a0b60a632090ece1dffa5c7cRichard Smith I != E; ++I) { 696bdb97ff687ce85e45cc728b87612ed546f48c1e7Richard Smith assert(Use.getKind() == UninitUse::Sometimes); 697bdb97ff687ce85e45cc728b87612ed546f48c1e7Richard Smith 698bdb97ff687ce85e45cc728b87612ed546f48c1e7Richard Smith const Expr *User = Use.getUser(); 6992815e1a075c74143a0b60a632090ece1dffa5c7cRichard Smith const Stmt *Term = I->Terminator; 700bdb97ff687ce85e45cc728b87612ed546f48c1e7Richard Smith 701bdb97ff687ce85e45cc728b87612ed546f48c1e7Richard Smith // Information used when building the diagnostic. 7022815e1a075c74143a0b60a632090ece1dffa5c7cRichard Smith unsigned DiagKind; 7030bea86307eb8c16339315a1e261fc490eb505c5bDavid Blaikie StringRef Str; 704bdb97ff687ce85e45cc728b87612ed546f48c1e7Richard Smith SourceRange Range; 705bdb97ff687ce85e45cc728b87612ed546f48c1e7Richard Smith 706fc09336a5965040736f9bc63a70416003972364eStefanus Du Toit // FixIts to suppress the diagnostic by removing the dead condition. 707bdb97ff687ce85e45cc728b87612ed546f48c1e7Richard Smith // For all binary terminators, branch 0 is taken if the condition is true, 708bdb97ff687ce85e45cc728b87612ed546f48c1e7Richard Smith // and branch 1 is taken if the condition is false. 709bdb97ff687ce85e45cc728b87612ed546f48c1e7Richard Smith int RemoveDiagKind = -1; 710bdb97ff687ce85e45cc728b87612ed546f48c1e7Richard Smith const char *FixitStr = 711bdb97ff687ce85e45cc728b87612ed546f48c1e7Richard Smith S.getLangOpts().CPlusPlus ? (I->Output ? "true" : "false") 712bdb97ff687ce85e45cc728b87612ed546f48c1e7Richard Smith : (I->Output ? "1" : "0"); 713bdb97ff687ce85e45cc728b87612ed546f48c1e7Richard Smith FixItHint Fixit1, Fixit2; 714bdb97ff687ce85e45cc728b87612ed546f48c1e7Richard Smith 7158a1fdfc69cc6c2ccbfd57fc8ff643c589da9df9bRichard Smith switch (Term ? Term->getStmtClass() : Stmt::DeclStmtClass) { 7162815e1a075c74143a0b60a632090ece1dffa5c7cRichard Smith default: 717bdb97ff687ce85e45cc728b87612ed546f48c1e7Richard Smith // Don't know how to report this. Just fall back to 'may be used 7188a1fdfc69cc6c2ccbfd57fc8ff643c589da9df9bRichard Smith // uninitialized'. FIXME: Can this happen? 7192815e1a075c74143a0b60a632090ece1dffa5c7cRichard Smith continue; 7202815e1a075c74143a0b60a632090ece1dffa5c7cRichard Smith 7212815e1a075c74143a0b60a632090ece1dffa5c7cRichard Smith // "condition is true / condition is false". 722bdb97ff687ce85e45cc728b87612ed546f48c1e7Richard Smith case Stmt::IfStmtClass: { 723bdb97ff687ce85e45cc728b87612ed546f48c1e7Richard Smith const IfStmt *IS = cast<IfStmt>(Term); 7242815e1a075c74143a0b60a632090ece1dffa5c7cRichard Smith DiagKind = 0; 7252815e1a075c74143a0b60a632090ece1dffa5c7cRichard Smith Str = "if"; 726bdb97ff687ce85e45cc728b87612ed546f48c1e7Richard Smith Range = IS->getCond()->getSourceRange(); 727bdb97ff687ce85e45cc728b87612ed546f48c1e7Richard Smith RemoveDiagKind = 0; 728bdb97ff687ce85e45cc728b87612ed546f48c1e7Richard Smith CreateIfFixit(S, IS, IS->getThen(), IS->getElse(), 729bdb97ff687ce85e45cc728b87612ed546f48c1e7Richard Smith I->Output, Fixit1, Fixit2); 7302815e1a075c74143a0b60a632090ece1dffa5c7cRichard Smith break; 731bdb97ff687ce85e45cc728b87612ed546f48c1e7Richard Smith } 732bdb97ff687ce85e45cc728b87612ed546f48c1e7Richard Smith case Stmt::ConditionalOperatorClass: { 733bdb97ff687ce85e45cc728b87612ed546f48c1e7Richard Smith const ConditionalOperator *CO = cast<ConditionalOperator>(Term); 7342815e1a075c74143a0b60a632090ece1dffa5c7cRichard Smith DiagKind = 0; 7352815e1a075c74143a0b60a632090ece1dffa5c7cRichard Smith Str = "?:"; 736bdb97ff687ce85e45cc728b87612ed546f48c1e7Richard Smith Range = CO->getCond()->getSourceRange(); 737bdb97ff687ce85e45cc728b87612ed546f48c1e7Richard Smith RemoveDiagKind = 0; 738bdb97ff687ce85e45cc728b87612ed546f48c1e7Richard Smith CreateIfFixit(S, CO, CO->getTrueExpr(), CO->getFalseExpr(), 739bdb97ff687ce85e45cc728b87612ed546f48c1e7Richard Smith I->Output, Fixit1, Fixit2); 7402815e1a075c74143a0b60a632090ece1dffa5c7cRichard Smith break; 741bdb97ff687ce85e45cc728b87612ed546f48c1e7Richard Smith } 7422815e1a075c74143a0b60a632090ece1dffa5c7cRichard Smith case Stmt::BinaryOperatorClass: { 7432815e1a075c74143a0b60a632090ece1dffa5c7cRichard Smith const BinaryOperator *BO = cast<BinaryOperator>(Term); 7442815e1a075c74143a0b60a632090ece1dffa5c7cRichard Smith if (!BO->isLogicalOp()) 7452815e1a075c74143a0b60a632090ece1dffa5c7cRichard Smith continue; 7462815e1a075c74143a0b60a632090ece1dffa5c7cRichard Smith DiagKind = 0; 7472815e1a075c74143a0b60a632090ece1dffa5c7cRichard Smith Str = BO->getOpcodeStr(); 7482815e1a075c74143a0b60a632090ece1dffa5c7cRichard Smith Range = BO->getLHS()->getSourceRange(); 749bdb97ff687ce85e45cc728b87612ed546f48c1e7Richard Smith RemoveDiagKind = 0; 750bdb97ff687ce85e45cc728b87612ed546f48c1e7Richard Smith if ((BO->getOpcode() == BO_LAnd && I->Output) || 751bdb97ff687ce85e45cc728b87612ed546f48c1e7Richard Smith (BO->getOpcode() == BO_LOr && !I->Output)) 752bdb97ff687ce85e45cc728b87612ed546f48c1e7Richard Smith // true && y -> y, false || y -> y. 753bdb97ff687ce85e45cc728b87612ed546f48c1e7Richard Smith Fixit1 = FixItHint::CreateRemoval(SourceRange(BO->getLocStart(), 754bdb97ff687ce85e45cc728b87612ed546f48c1e7Richard Smith BO->getOperatorLoc())); 755bdb97ff687ce85e45cc728b87612ed546f48c1e7Richard Smith else 756bdb97ff687ce85e45cc728b87612ed546f48c1e7Richard Smith // false && y -> false, true || y -> true. 757bdb97ff687ce85e45cc728b87612ed546f48c1e7Richard Smith Fixit1 = FixItHint::CreateReplacement(BO->getSourceRange(), FixitStr); 7582815e1a075c74143a0b60a632090ece1dffa5c7cRichard Smith break; 7592815e1a075c74143a0b60a632090ece1dffa5c7cRichard Smith } 7602815e1a075c74143a0b60a632090ece1dffa5c7cRichard Smith 7612815e1a075c74143a0b60a632090ece1dffa5c7cRichard Smith // "loop is entered / loop is exited". 7622815e1a075c74143a0b60a632090ece1dffa5c7cRichard Smith case Stmt::WhileStmtClass: 7632815e1a075c74143a0b60a632090ece1dffa5c7cRichard Smith DiagKind = 1; 7642815e1a075c74143a0b60a632090ece1dffa5c7cRichard Smith Str = "while"; 7652815e1a075c74143a0b60a632090ece1dffa5c7cRichard Smith Range = cast<WhileStmt>(Term)->getCond()->getSourceRange(); 766bdb97ff687ce85e45cc728b87612ed546f48c1e7Richard Smith RemoveDiagKind = 1; 767bdb97ff687ce85e45cc728b87612ed546f48c1e7Richard Smith Fixit1 = FixItHint::CreateReplacement(Range, FixitStr); 7682815e1a075c74143a0b60a632090ece1dffa5c7cRichard Smith break; 7692815e1a075c74143a0b60a632090ece1dffa5c7cRichard Smith case Stmt::ForStmtClass: 7702815e1a075c74143a0b60a632090ece1dffa5c7cRichard Smith DiagKind = 1; 7712815e1a075c74143a0b60a632090ece1dffa5c7cRichard Smith Str = "for"; 7722815e1a075c74143a0b60a632090ece1dffa5c7cRichard Smith Range = cast<ForStmt>(Term)->getCond()->getSourceRange(); 773bdb97ff687ce85e45cc728b87612ed546f48c1e7Richard Smith RemoveDiagKind = 1; 774bdb97ff687ce85e45cc728b87612ed546f48c1e7Richard Smith if (I->Output) 775bdb97ff687ce85e45cc728b87612ed546f48c1e7Richard Smith Fixit1 = FixItHint::CreateRemoval(Range); 776bdb97ff687ce85e45cc728b87612ed546f48c1e7Richard Smith else 777bdb97ff687ce85e45cc728b87612ed546f48c1e7Richard Smith Fixit1 = FixItHint::CreateReplacement(Range, FixitStr); 7782815e1a075c74143a0b60a632090ece1dffa5c7cRichard Smith break; 7798a1fdfc69cc6c2ccbfd57fc8ff643c589da9df9bRichard Smith case Stmt::CXXForRangeStmtClass: 7808a1fdfc69cc6c2ccbfd57fc8ff643c589da9df9bRichard Smith if (I->Output == 1) { 7818a1fdfc69cc6c2ccbfd57fc8ff643c589da9df9bRichard Smith // The use occurs if a range-based for loop's body never executes. 7828a1fdfc69cc6c2ccbfd57fc8ff643c589da9df9bRichard Smith // That may be impossible, and there's no syntactic fix for this, 7838a1fdfc69cc6c2ccbfd57fc8ff643c589da9df9bRichard Smith // so treat it as a 'may be uninitialized' case. 7848a1fdfc69cc6c2ccbfd57fc8ff643c589da9df9bRichard Smith continue; 7858a1fdfc69cc6c2ccbfd57fc8ff643c589da9df9bRichard Smith } 7868a1fdfc69cc6c2ccbfd57fc8ff643c589da9df9bRichard Smith DiagKind = 1; 7878a1fdfc69cc6c2ccbfd57fc8ff643c589da9df9bRichard Smith Str = "for"; 7888a1fdfc69cc6c2ccbfd57fc8ff643c589da9df9bRichard Smith Range = cast<CXXForRangeStmt>(Term)->getRangeInit()->getSourceRange(); 7898a1fdfc69cc6c2ccbfd57fc8ff643c589da9df9bRichard Smith break; 7902815e1a075c74143a0b60a632090ece1dffa5c7cRichard Smith 7912815e1a075c74143a0b60a632090ece1dffa5c7cRichard Smith // "condition is true / loop is exited". 7922815e1a075c74143a0b60a632090ece1dffa5c7cRichard Smith case Stmt::DoStmtClass: 7932815e1a075c74143a0b60a632090ece1dffa5c7cRichard Smith DiagKind = 2; 7942815e1a075c74143a0b60a632090ece1dffa5c7cRichard Smith Str = "do"; 7952815e1a075c74143a0b60a632090ece1dffa5c7cRichard Smith Range = cast<DoStmt>(Term)->getCond()->getSourceRange(); 796bdb97ff687ce85e45cc728b87612ed546f48c1e7Richard Smith RemoveDiagKind = 1; 797bdb97ff687ce85e45cc728b87612ed546f48c1e7Richard Smith Fixit1 = FixItHint::CreateReplacement(Range, FixitStr); 7982815e1a075c74143a0b60a632090ece1dffa5c7cRichard Smith break; 7992815e1a075c74143a0b60a632090ece1dffa5c7cRichard Smith 8002815e1a075c74143a0b60a632090ece1dffa5c7cRichard Smith // "switch case is taken". 8012815e1a075c74143a0b60a632090ece1dffa5c7cRichard Smith case Stmt::CaseStmtClass: 8022815e1a075c74143a0b60a632090ece1dffa5c7cRichard Smith DiagKind = 3; 8032815e1a075c74143a0b60a632090ece1dffa5c7cRichard Smith Str = "case"; 8042815e1a075c74143a0b60a632090ece1dffa5c7cRichard Smith Range = cast<CaseStmt>(Term)->getLHS()->getSourceRange(); 8052815e1a075c74143a0b60a632090ece1dffa5c7cRichard Smith break; 8062815e1a075c74143a0b60a632090ece1dffa5c7cRichard Smith case Stmt::DefaultStmtClass: 8072815e1a075c74143a0b60a632090ece1dffa5c7cRichard Smith DiagKind = 3; 8082815e1a075c74143a0b60a632090ece1dffa5c7cRichard Smith Str = "default"; 8092815e1a075c74143a0b60a632090ece1dffa5c7cRichard Smith Range = cast<DefaultStmt>(Term)->getDefaultLoc(); 8102815e1a075c74143a0b60a632090ece1dffa5c7cRichard Smith break; 8112815e1a075c74143a0b60a632090ece1dffa5c7cRichard Smith } 8122815e1a075c74143a0b60a632090ece1dffa5c7cRichard Smith 813bdb97ff687ce85e45cc728b87612ed546f48c1e7Richard Smith S.Diag(Range.getBegin(), diag::warn_sometimes_uninit_var) 814bdb97ff687ce85e45cc728b87612ed546f48c1e7Richard Smith << VD->getDeclName() << IsCapturedByBlock << DiagKind 815bdb97ff687ce85e45cc728b87612ed546f48c1e7Richard Smith << Str << I->Output << Range; 816bdb97ff687ce85e45cc728b87612ed546f48c1e7Richard Smith S.Diag(User->getLocStart(), diag::note_uninit_var_use) 817bdb97ff687ce85e45cc728b87612ed546f48c1e7Richard Smith << IsCapturedByBlock << User->getSourceRange(); 818bdb97ff687ce85e45cc728b87612ed546f48c1e7Richard Smith if (RemoveDiagKind != -1) 819bdb97ff687ce85e45cc728b87612ed546f48c1e7Richard Smith S.Diag(Fixit1.RemoveRange.getBegin(), diag::note_uninit_fixit_remove_cond) 820bdb97ff687ce85e45cc728b87612ed546f48c1e7Richard Smith << RemoveDiagKind << Str << I->Output << Fixit1 << Fixit2; 821bdb97ff687ce85e45cc728b87612ed546f48c1e7Richard Smith 822bdb97ff687ce85e45cc728b87612ed546f48c1e7Richard Smith Diagnosed = true; 8232815e1a075c74143a0b60a632090ece1dffa5c7cRichard Smith } 824bdb97ff687ce85e45cc728b87612ed546f48c1e7Richard Smith 825bdb97ff687ce85e45cc728b87612ed546f48c1e7Richard Smith if (!Diagnosed) 8268a1fdfc69cc6c2ccbfd57fc8ff643c589da9df9bRichard Smith S.Diag(Use.getUser()->getLocStart(), diag::warn_maybe_uninit_var) 827bdb97ff687ce85e45cc728b87612ed546f48c1e7Richard Smith << VD->getDeclName() << IsCapturedByBlock 828bdb97ff687ce85e45cc728b87612ed546f48c1e7Richard Smith << Use.getUser()->getSourceRange(); 8292815e1a075c74143a0b60a632090ece1dffa5c7cRichard Smith} 8302815e1a075c74143a0b60a632090ece1dffa5c7cRichard Smith 831262d50e1dcf529317da193ad585c11c16281a7acChandler Carruth/// DiagnoseUninitializedUse -- Helper function for diagnosing uses of an 832262d50e1dcf529317da193ad585c11c16281a7acChandler Carruth/// uninitialized variable. This manages the different forms of diagnostic 833262d50e1dcf529317da193ad585c11c16281a7acChandler Carruth/// emitted for particular types of uses. Returns true if the use was diagnosed 8342815e1a075c74143a0b60a632090ece1dffa5c7cRichard Smith/// as a warning. If a particular use is one we omit warnings for, returns 835262d50e1dcf529317da193ad585c11c16281a7acChandler Carruth/// false. 836262d50e1dcf529317da193ad585c11c16281a7acChandler Carruthstatic bool DiagnoseUninitializedUse(Sema &S, const VarDecl *VD, 8372815e1a075c74143a0b60a632090ece1dffa5c7cRichard Smith const UninitUse &Use, 8389e7617220135a6f6226cf09cb242cc1b905aedb4Ted Kremenek bool alwaysReportSelfInit = false) { 8394c4983bbd2904670a25c840b07600f14efbafd7fChandler Carruth 8402815e1a075c74143a0b60a632090ece1dffa5c7cRichard Smith if (const DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(Use.getUser())) { 841f6278e545d9bc09fb5d7579d1123f0a455352627Richard Trieu // Inspect the initializer of the variable declaration which is 842f6278e545d9bc09fb5d7579d1123f0a455352627Richard Trieu // being referenced prior to its initialization. We emit 843f6278e545d9bc09fb5d7579d1123f0a455352627Richard Trieu // specialized diagnostics for self-initialization, and we 844f6278e545d9bc09fb5d7579d1123f0a455352627Richard Trieu // specifically avoid warning about self references which take the 845f6278e545d9bc09fb5d7579d1123f0a455352627Richard Trieu // form of: 846f6278e545d9bc09fb5d7579d1123f0a455352627Richard Trieu // 847f6278e545d9bc09fb5d7579d1123f0a455352627Richard Trieu // int x = x; 848f6278e545d9bc09fb5d7579d1123f0a455352627Richard Trieu // 849f6278e545d9bc09fb5d7579d1123f0a455352627Richard Trieu // This is used to indicate to GCC that 'x' is intentionally left 850f6278e545d9bc09fb5d7579d1123f0a455352627Richard Trieu // uninitialized. Proven code paths which access 'x' in 851f6278e545d9bc09fb5d7579d1123f0a455352627Richard Trieu // an uninitialized state after this will still warn. 852f6278e545d9bc09fb5d7579d1123f0a455352627Richard Trieu if (const Expr *Initializer = VD->getInit()) { 853f6278e545d9bc09fb5d7579d1123f0a455352627Richard Trieu if (!alwaysReportSelfInit && DRE == Initializer->IgnoreParenImpCasts()) 854f6278e545d9bc09fb5d7579d1123f0a455352627Richard Trieu return false; 855f6278e545d9bc09fb5d7579d1123f0a455352627Richard Trieu 856f6278e545d9bc09fb5d7579d1123f0a455352627Richard Trieu ContainsReference CR(S.Context, DRE); 857f6278e545d9bc09fb5d7579d1123f0a455352627Richard Trieu CR.Visit(const_cast<Expr*>(Initializer)); 858f6278e545d9bc09fb5d7579d1123f0a455352627Richard Trieu if (CR.doesContainReference()) { 8594c4983bbd2904670a25c840b07600f14efbafd7fChandler Carruth S.Diag(DRE->getLocStart(), 8604c4983bbd2904670a25c840b07600f14efbafd7fChandler Carruth diag::warn_uninit_self_reference_in_init) 861f6278e545d9bc09fb5d7579d1123f0a455352627Richard Trieu << VD->getDeclName() << VD->getLocation() << DRE->getSourceRange(); 862f6278e545d9bc09fb5d7579d1123f0a455352627Richard Trieu return true; 8634c4983bbd2904670a25c840b07600f14efbafd7fChandler Carruth } 8644c4983bbd2904670a25c840b07600f14efbafd7fChandler Carruth } 865f6278e545d9bc09fb5d7579d1123f0a455352627Richard Trieu 866bdb97ff687ce85e45cc728b87612ed546f48c1e7Richard Smith DiagUninitUse(S, VD, Use, false); 8674c4983bbd2904670a25c840b07600f14efbafd7fChandler Carruth } else { 8682815e1a075c74143a0b60a632090ece1dffa5c7cRichard Smith const BlockExpr *BE = cast<BlockExpr>(Use.getUser()); 869bdb97ff687ce85e45cc728b87612ed546f48c1e7Richard Smith if (VD->getType()->isBlockPointerType() && !VD->hasAttr<BlocksAttr>()) 870bdb97ff687ce85e45cc728b87612ed546f48c1e7Richard Smith S.Diag(BE->getLocStart(), 871bdb97ff687ce85e45cc728b87612ed546f48c1e7Richard Smith diag::warn_uninit_byref_blockvar_captured_by_block) 872a34194f035096dd8dce10574e3a186da968aa211Fariborz Jahanian << VD->getDeclName(); 873bdb97ff687ce85e45cc728b87612ed546f48c1e7Richard Smith else 874bdb97ff687ce85e45cc728b87612ed546f48c1e7Richard Smith DiagUninitUse(S, VD, Use, true); 8754c4983bbd2904670a25c840b07600f14efbafd7fChandler Carruth } 8764c4983bbd2904670a25c840b07600f14efbafd7fChandler Carruth 8774c4983bbd2904670a25c840b07600f14efbafd7fChandler Carruth // Report where the variable was declared when the use wasn't within 8784f4f349208b2b2307454e169ac7b039e989f003fDavid Blaikie // the initializer of that declaration & we didn't already suggest 8794f4f349208b2b2307454e169ac7b039e989f003fDavid Blaikie // an initialization fixit. 880f6278e545d9bc09fb5d7579d1123f0a455352627Richard Trieu if (!SuggestInitializationFixit(S, VD)) 8814c4983bbd2904670a25c840b07600f14efbafd7fChandler Carruth S.Diag(VD->getLocStart(), diag::note_uninit_var_def) 8824c4983bbd2904670a25c840b07600f14efbafd7fChandler Carruth << VD->getDeclName(); 8834c4983bbd2904670a25c840b07600f14efbafd7fChandler Carruth 884262d50e1dcf529317da193ad585c11c16281a7acChandler Carruth return true; 88564fb959beb3a0ecb84a58e6ff82660a7a669f7b8Chandler Carruth} 88664fb959beb3a0ecb84a58e6ff82660a7a669f7b8Chandler Carruth 887e0d3b4cd2b66f1cef26cacbed5820ab7c22ad5b3Richard Smithnamespace { 888e0d3b4cd2b66f1cef26cacbed5820ab7c22ad5b3Richard Smith class FallthroughMapper : public RecursiveASTVisitor<FallthroughMapper> { 889e0d3b4cd2b66f1cef26cacbed5820ab7c22ad5b3Richard Smith public: 890e0d3b4cd2b66f1cef26cacbed5820ab7c22ad5b3Richard Smith FallthroughMapper(Sema &S) 891e0d3b4cd2b66f1cef26cacbed5820ab7c22ad5b3Richard Smith : FoundSwitchStatements(false), 892e0d3b4cd2b66f1cef26cacbed5820ab7c22ad5b3Richard Smith S(S) { 893e0d3b4cd2b66f1cef26cacbed5820ab7c22ad5b3Richard Smith } 894e0d3b4cd2b66f1cef26cacbed5820ab7c22ad5b3Richard Smith 895e0d3b4cd2b66f1cef26cacbed5820ab7c22ad5b3Richard Smith bool foundSwitchStatements() const { return FoundSwitchStatements; } 896e0d3b4cd2b66f1cef26cacbed5820ab7c22ad5b3Richard Smith 897e0d3b4cd2b66f1cef26cacbed5820ab7c22ad5b3Richard Smith void markFallthroughVisited(const AttributedStmt *Stmt) { 898e0d3b4cd2b66f1cef26cacbed5820ab7c22ad5b3Richard Smith bool Found = FallthroughStmts.erase(Stmt); 899e0d3b4cd2b66f1cef26cacbed5820ab7c22ad5b3Richard Smith assert(Found); 9003bb2994a7de3679fb825f3a36f3dc11ea1daf6a6Kaelyn Uhrain (void)Found; 901e0d3b4cd2b66f1cef26cacbed5820ab7c22ad5b3Richard Smith } 902e0d3b4cd2b66f1cef26cacbed5820ab7c22ad5b3Richard Smith 903e0d3b4cd2b66f1cef26cacbed5820ab7c22ad5b3Richard Smith typedef llvm::SmallPtrSet<const AttributedStmt*, 8> AttrStmts; 904e0d3b4cd2b66f1cef26cacbed5820ab7c22ad5b3Richard Smith 905e0d3b4cd2b66f1cef26cacbed5820ab7c22ad5b3Richard Smith const AttrStmts &getFallthroughStmts() const { 906e0d3b4cd2b66f1cef26cacbed5820ab7c22ad5b3Richard Smith return FallthroughStmts; 907e0d3b4cd2b66f1cef26cacbed5820ab7c22ad5b3Richard Smith } 908e0d3b4cd2b66f1cef26cacbed5820ab7c22ad5b3Richard Smith 9094874a8143dc3032205f97527ff619730db3d1f57Alexander Kornienko void fillReachableBlocks(CFG *Cfg) { 9104874a8143dc3032205f97527ff619730db3d1f57Alexander Kornienko assert(ReachableBlocks.empty() && "ReachableBlocks already filled"); 9114874a8143dc3032205f97527ff619730db3d1f57Alexander Kornienko std::deque<const CFGBlock *> BlockQueue; 9124874a8143dc3032205f97527ff619730db3d1f57Alexander Kornienko 9134874a8143dc3032205f97527ff619730db3d1f57Alexander Kornienko ReachableBlocks.insert(&Cfg->getEntry()); 9144874a8143dc3032205f97527ff619730db3d1f57Alexander Kornienko BlockQueue.push_back(&Cfg->getEntry()); 915878d0ad2c9d83ee6485fd16e21c5082acc63a890Alexander Kornienko // Mark all case blocks reachable to avoid problems with switching on 916878d0ad2c9d83ee6485fd16e21c5082acc63a890Alexander Kornienko // constants, covered enums, etc. 917878d0ad2c9d83ee6485fd16e21c5082acc63a890Alexander Kornienko // These blocks can contain fall-through annotations, and we don't want to 918878d0ad2c9d83ee6485fd16e21c5082acc63a890Alexander Kornienko // issue a warn_fallthrough_attr_unreachable for them. 9196bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines for (const auto *B : *Cfg) { 920878d0ad2c9d83ee6485fd16e21c5082acc63a890Alexander Kornienko const Stmt *L = B->getLabel(); 921176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines if (L && isa<SwitchCase>(L) && ReachableBlocks.insert(B).second) 922878d0ad2c9d83ee6485fd16e21c5082acc63a890Alexander Kornienko BlockQueue.push_back(B); 923878d0ad2c9d83ee6485fd16e21c5082acc63a890Alexander Kornienko } 924878d0ad2c9d83ee6485fd16e21c5082acc63a890Alexander Kornienko 9254874a8143dc3032205f97527ff619730db3d1f57Alexander Kornienko while (!BlockQueue.empty()) { 9264874a8143dc3032205f97527ff619730db3d1f57Alexander Kornienko const CFGBlock *P = BlockQueue.front(); 9274874a8143dc3032205f97527ff619730db3d1f57Alexander Kornienko BlockQueue.pop_front(); 9284874a8143dc3032205f97527ff619730db3d1f57Alexander Kornienko for (CFGBlock::const_succ_iterator I = P->succ_begin(), 9294874a8143dc3032205f97527ff619730db3d1f57Alexander Kornienko E = P->succ_end(); 9304874a8143dc3032205f97527ff619730db3d1f57Alexander Kornienko I != E; ++I) { 931176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines if (*I && ReachableBlocks.insert(*I).second) 9324874a8143dc3032205f97527ff619730db3d1f57Alexander Kornienko BlockQueue.push_back(*I); 9334874a8143dc3032205f97527ff619730db3d1f57Alexander Kornienko } 9344874a8143dc3032205f97527ff619730db3d1f57Alexander Kornienko } 9354874a8143dc3032205f97527ff619730db3d1f57Alexander Kornienko } 9364874a8143dc3032205f97527ff619730db3d1f57Alexander Kornienko 937e0d3b4cd2b66f1cef26cacbed5820ab7c22ad5b3Richard Smith bool checkFallThroughIntoBlock(const CFGBlock &B, int &AnnotatedCnt) { 9384874a8143dc3032205f97527ff619730db3d1f57Alexander Kornienko assert(!ReachableBlocks.empty() && "ReachableBlocks empty"); 9394874a8143dc3032205f97527ff619730db3d1f57Alexander Kornienko 940e0d3b4cd2b66f1cef26cacbed5820ab7c22ad5b3Richard Smith int UnannotatedCnt = 0; 941e0d3b4cd2b66f1cef26cacbed5820ab7c22ad5b3Richard Smith AnnotatedCnt = 0; 942e0d3b4cd2b66f1cef26cacbed5820ab7c22ad5b3Richard Smith 9436bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines std::deque<const CFGBlock*> BlockQueue(B.pred_begin(), B.pred_end()); 944e0d3b4cd2b66f1cef26cacbed5820ab7c22ad5b3Richard Smith while (!BlockQueue.empty()) { 945e0d3b4cd2b66f1cef26cacbed5820ab7c22ad5b3Richard Smith const CFGBlock *P = BlockQueue.front(); 946e0d3b4cd2b66f1cef26cacbed5820ab7c22ad5b3Richard Smith BlockQueue.pop_front(); 947651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines if (!P) continue; 948e0d3b4cd2b66f1cef26cacbed5820ab7c22ad5b3Richard Smith 949e0d3b4cd2b66f1cef26cacbed5820ab7c22ad5b3Richard Smith const Stmt *Term = P->getTerminator(); 950e0d3b4cd2b66f1cef26cacbed5820ab7c22ad5b3Richard Smith if (Term && isa<SwitchStmt>(Term)) 951e0d3b4cd2b66f1cef26cacbed5820ab7c22ad5b3Richard Smith continue; // Switch statement, good. 952e0d3b4cd2b66f1cef26cacbed5820ab7c22ad5b3Richard Smith 953e0d3b4cd2b66f1cef26cacbed5820ab7c22ad5b3Richard Smith const SwitchCase *SW = dyn_cast_or_null<SwitchCase>(P->getLabel()); 954e0d3b4cd2b66f1cef26cacbed5820ab7c22ad5b3Richard Smith if (SW && SW->getSubStmt() == B.getLabel() && P->begin() == P->end()) 955e0d3b4cd2b66f1cef26cacbed5820ab7c22ad5b3Richard Smith continue; // Previous case label has no statements, good. 956e0d3b4cd2b66f1cef26cacbed5820ab7c22ad5b3Richard Smith 957c6dcea93b499b504da22f9921fc198423ad0b13bAlexander Kornienko const LabelStmt *L = dyn_cast_or_null<LabelStmt>(P->getLabel()); 958c6dcea93b499b504da22f9921fc198423ad0b13bAlexander Kornienko if (L && L->getSubStmt() == B.getLabel() && P->begin() == P->end()) 959c6dcea93b499b504da22f9921fc198423ad0b13bAlexander Kornienko continue; // Case label is preceded with a normal label, good. 960c6dcea93b499b504da22f9921fc198423ad0b13bAlexander Kornienko 9614874a8143dc3032205f97527ff619730db3d1f57Alexander Kornienko if (!ReachableBlocks.count(P)) { 962878d0ad2c9d83ee6485fd16e21c5082acc63a890Alexander Kornienko for (CFGBlock::const_reverse_iterator ElemIt = P->rbegin(), 963878d0ad2c9d83ee6485fd16e21c5082acc63a890Alexander Kornienko ElemEnd = P->rend(); 964878d0ad2c9d83ee6485fd16e21c5082acc63a890Alexander Kornienko ElemIt != ElemEnd; ++ElemIt) { 965b07805485c603be3d8011f72611465324c9e664bDavid Blaikie if (Optional<CFGStmt> CS = ElemIt->getAs<CFGStmt>()) { 966b07805485c603be3d8011f72611465324c9e664bDavid Blaikie if (const AttributedStmt *AS = asFallThroughAttr(CS->getStmt())) { 967e0d3b4cd2b66f1cef26cacbed5820ab7c22ad5b3Richard Smith S.Diag(AS->getLocStart(), 968e0d3b4cd2b66f1cef26cacbed5820ab7c22ad5b3Richard Smith diag::warn_fallthrough_attr_unreachable); 969e0d3b4cd2b66f1cef26cacbed5820ab7c22ad5b3Richard Smith markFallthroughVisited(AS); 970e0d3b4cd2b66f1cef26cacbed5820ab7c22ad5b3Richard Smith ++AnnotatedCnt; 971878d0ad2c9d83ee6485fd16e21c5082acc63a890Alexander Kornienko break; 972e0d3b4cd2b66f1cef26cacbed5820ab7c22ad5b3Richard Smith } 973e0d3b4cd2b66f1cef26cacbed5820ab7c22ad5b3Richard Smith // Don't care about other unreachable statements. 974e0d3b4cd2b66f1cef26cacbed5820ab7c22ad5b3Richard Smith } 975e0d3b4cd2b66f1cef26cacbed5820ab7c22ad5b3Richard Smith } 976e0d3b4cd2b66f1cef26cacbed5820ab7c22ad5b3Richard Smith // If there are no unreachable statements, this may be a special 977e0d3b4cd2b66f1cef26cacbed5820ab7c22ad5b3Richard Smith // case in CFG: 978e0d3b4cd2b66f1cef26cacbed5820ab7c22ad5b3Richard Smith // case X: { 979e0d3b4cd2b66f1cef26cacbed5820ab7c22ad5b3Richard Smith // A a; // A has a destructor. 980e0d3b4cd2b66f1cef26cacbed5820ab7c22ad5b3Richard Smith // break; 981e0d3b4cd2b66f1cef26cacbed5820ab7c22ad5b3Richard Smith // } 982e0d3b4cd2b66f1cef26cacbed5820ab7c22ad5b3Richard Smith // // <<<< This place is represented by a 'hanging' CFG block. 983e0d3b4cd2b66f1cef26cacbed5820ab7c22ad5b3Richard Smith // case Y: 984e0d3b4cd2b66f1cef26cacbed5820ab7c22ad5b3Richard Smith continue; 985e0d3b4cd2b66f1cef26cacbed5820ab7c22ad5b3Richard Smith } 986e0d3b4cd2b66f1cef26cacbed5820ab7c22ad5b3Richard Smith 987e0d3b4cd2b66f1cef26cacbed5820ab7c22ad5b3Richard Smith const Stmt *LastStmt = getLastStmt(*P); 988e0d3b4cd2b66f1cef26cacbed5820ab7c22ad5b3Richard Smith if (const AttributedStmt *AS = asFallThroughAttr(LastStmt)) { 989e0d3b4cd2b66f1cef26cacbed5820ab7c22ad5b3Richard Smith markFallthroughVisited(AS); 990e0d3b4cd2b66f1cef26cacbed5820ab7c22ad5b3Richard Smith ++AnnotatedCnt; 991e0d3b4cd2b66f1cef26cacbed5820ab7c22ad5b3Richard Smith continue; // Fallthrough annotation, good. 992e0d3b4cd2b66f1cef26cacbed5820ab7c22ad5b3Richard Smith } 993e0d3b4cd2b66f1cef26cacbed5820ab7c22ad5b3Richard Smith 994e0d3b4cd2b66f1cef26cacbed5820ab7c22ad5b3Richard Smith if (!LastStmt) { // This block contains no executable statements. 995e0d3b4cd2b66f1cef26cacbed5820ab7c22ad5b3Richard Smith // Traverse its predecessors. 996e0d3b4cd2b66f1cef26cacbed5820ab7c22ad5b3Richard Smith std::copy(P->pred_begin(), P->pred_end(), 997e0d3b4cd2b66f1cef26cacbed5820ab7c22ad5b3Richard Smith std::back_inserter(BlockQueue)); 998e0d3b4cd2b66f1cef26cacbed5820ab7c22ad5b3Richard Smith continue; 999e0d3b4cd2b66f1cef26cacbed5820ab7c22ad5b3Richard Smith } 1000e0d3b4cd2b66f1cef26cacbed5820ab7c22ad5b3Richard Smith 1001e0d3b4cd2b66f1cef26cacbed5820ab7c22ad5b3Richard Smith ++UnannotatedCnt; 1002e0d3b4cd2b66f1cef26cacbed5820ab7c22ad5b3Richard Smith } 1003e0d3b4cd2b66f1cef26cacbed5820ab7c22ad5b3Richard Smith return !!UnannotatedCnt; 1004e0d3b4cd2b66f1cef26cacbed5820ab7c22ad5b3Richard Smith } 1005e0d3b4cd2b66f1cef26cacbed5820ab7c22ad5b3Richard Smith 1006e0d3b4cd2b66f1cef26cacbed5820ab7c22ad5b3Richard Smith // RecursiveASTVisitor setup. 1007e0d3b4cd2b66f1cef26cacbed5820ab7c22ad5b3Richard Smith bool shouldWalkTypesOfTypeLocs() const { return false; } 1008e0d3b4cd2b66f1cef26cacbed5820ab7c22ad5b3Richard Smith 1009e0d3b4cd2b66f1cef26cacbed5820ab7c22ad5b3Richard Smith bool VisitAttributedStmt(AttributedStmt *S) { 1010e0d3b4cd2b66f1cef26cacbed5820ab7c22ad5b3Richard Smith if (asFallThroughAttr(S)) 1011e0d3b4cd2b66f1cef26cacbed5820ab7c22ad5b3Richard Smith FallthroughStmts.insert(S); 1012e0d3b4cd2b66f1cef26cacbed5820ab7c22ad5b3Richard Smith return true; 1013e0d3b4cd2b66f1cef26cacbed5820ab7c22ad5b3Richard Smith } 1014e0d3b4cd2b66f1cef26cacbed5820ab7c22ad5b3Richard Smith 1015e0d3b4cd2b66f1cef26cacbed5820ab7c22ad5b3Richard Smith bool VisitSwitchStmt(SwitchStmt *S) { 1016e0d3b4cd2b66f1cef26cacbed5820ab7c22ad5b3Richard Smith FoundSwitchStatements = true; 1017e0d3b4cd2b66f1cef26cacbed5820ab7c22ad5b3Richard Smith return true; 1018e0d3b4cd2b66f1cef26cacbed5820ab7c22ad5b3Richard Smith } 1019e0d3b4cd2b66f1cef26cacbed5820ab7c22ad5b3Richard Smith 1020b0707c9a933b1839fa966e4c72e4dcb9a198f11fAlexander Kornienko // We don't want to traverse local type declarations. We analyze their 1021b0707c9a933b1839fa966e4c72e4dcb9a198f11fAlexander Kornienko // methods separately. 1022b0707c9a933b1839fa966e4c72e4dcb9a198f11fAlexander Kornienko bool TraverseDecl(Decl *D) { return true; } 1023b0707c9a933b1839fa966e4c72e4dcb9a198f11fAlexander Kornienko 1024c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines // We analyze lambda bodies separately. Skip them here. 1025c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines bool TraverseLambdaBody(LambdaExpr *LE) { return true; } 1026c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines 1027e0d3b4cd2b66f1cef26cacbed5820ab7c22ad5b3Richard Smith private: 1028e0d3b4cd2b66f1cef26cacbed5820ab7c22ad5b3Richard Smith 1029e0d3b4cd2b66f1cef26cacbed5820ab7c22ad5b3Richard Smith static const AttributedStmt *asFallThroughAttr(const Stmt *S) { 1030e0d3b4cd2b66f1cef26cacbed5820ab7c22ad5b3Richard Smith if (const AttributedStmt *AS = dyn_cast_or_null<AttributedStmt>(S)) { 1031e0d3b4cd2b66f1cef26cacbed5820ab7c22ad5b3Richard Smith if (hasSpecificAttr<FallThroughAttr>(AS->getAttrs())) 1032e0d3b4cd2b66f1cef26cacbed5820ab7c22ad5b3Richard Smith return AS; 1033e0d3b4cd2b66f1cef26cacbed5820ab7c22ad5b3Richard Smith } 10346bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines return nullptr; 1035e0d3b4cd2b66f1cef26cacbed5820ab7c22ad5b3Richard Smith } 1036e0d3b4cd2b66f1cef26cacbed5820ab7c22ad5b3Richard Smith 1037e0d3b4cd2b66f1cef26cacbed5820ab7c22ad5b3Richard Smith static const Stmt *getLastStmt(const CFGBlock &B) { 1038e0d3b4cd2b66f1cef26cacbed5820ab7c22ad5b3Richard Smith if (const Stmt *Term = B.getTerminator()) 1039e0d3b4cd2b66f1cef26cacbed5820ab7c22ad5b3Richard Smith return Term; 1040e0d3b4cd2b66f1cef26cacbed5820ab7c22ad5b3Richard Smith for (CFGBlock::const_reverse_iterator ElemIt = B.rbegin(), 1041e0d3b4cd2b66f1cef26cacbed5820ab7c22ad5b3Richard Smith ElemEnd = B.rend(); 1042e0d3b4cd2b66f1cef26cacbed5820ab7c22ad5b3Richard Smith ElemIt != ElemEnd; ++ElemIt) { 1043b07805485c603be3d8011f72611465324c9e664bDavid Blaikie if (Optional<CFGStmt> CS = ElemIt->getAs<CFGStmt>()) 1044b07805485c603be3d8011f72611465324c9e664bDavid Blaikie return CS->getStmt(); 1045e0d3b4cd2b66f1cef26cacbed5820ab7c22ad5b3Richard Smith } 1046e0d3b4cd2b66f1cef26cacbed5820ab7c22ad5b3Richard Smith // Workaround to detect a statement thrown out by CFGBuilder: 1047e0d3b4cd2b66f1cef26cacbed5820ab7c22ad5b3Richard Smith // case X: {} case Y: 1048e0d3b4cd2b66f1cef26cacbed5820ab7c22ad5b3Richard Smith // case X: ; case Y: 1049e0d3b4cd2b66f1cef26cacbed5820ab7c22ad5b3Richard Smith if (const SwitchCase *SW = dyn_cast_or_null<SwitchCase>(B.getLabel())) 1050e0d3b4cd2b66f1cef26cacbed5820ab7c22ad5b3Richard Smith if (!isa<SwitchCase>(SW->getSubStmt())) 1051e0d3b4cd2b66f1cef26cacbed5820ab7c22ad5b3Richard Smith return SW->getSubStmt(); 1052e0d3b4cd2b66f1cef26cacbed5820ab7c22ad5b3Richard Smith 10536bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines return nullptr; 1054e0d3b4cd2b66f1cef26cacbed5820ab7c22ad5b3Richard Smith } 1055e0d3b4cd2b66f1cef26cacbed5820ab7c22ad5b3Richard Smith 1056e0d3b4cd2b66f1cef26cacbed5820ab7c22ad5b3Richard Smith bool FoundSwitchStatements; 1057e0d3b4cd2b66f1cef26cacbed5820ab7c22ad5b3Richard Smith AttrStmts FallthroughStmts; 1058e0d3b4cd2b66f1cef26cacbed5820ab7c22ad5b3Richard Smith Sema &S; 10594874a8143dc3032205f97527ff619730db3d1f57Alexander Kornienko llvm::SmallPtrSet<const CFGBlock *, 16> ReachableBlocks; 1060e0d3b4cd2b66f1cef26cacbed5820ab7c22ad5b3Richard Smith }; 1061e0d3b4cd2b66f1cef26cacbed5820ab7c22ad5b3Richard Smith} 1062e0d3b4cd2b66f1cef26cacbed5820ab7c22ad5b3Richard Smith 10631973634e445d4f1abdeedc2809f2d281929253b6Alexander Kornienkostatic void DiagnoseSwitchLabelsFallthrough(Sema &S, AnalysisDeclContext &AC, 1064c2f51cfefd77e9b25f201ecf879343d6d9a45158Sean Hunt bool PerFunction) { 10653078353fb56772193b9304510048ac075a2c95b5Ted Kremenek // Only perform this analysis when using C++11. There is no good workflow 10663078353fb56772193b9304510048ac075a2c95b5Ted Kremenek // for this warning when not using C++11. There is no good way to silence 10673078353fb56772193b9304510048ac075a2c95b5Ted Kremenek // the warning (no attribute is available) unless we are using C++11's support 10683078353fb56772193b9304510048ac075a2c95b5Ted Kremenek // for generalized attributes. Once could use pragmas to silence the warning, 10693078353fb56772193b9304510048ac075a2c95b5Ted Kremenek // but as a general solution that is gross and not in the spirit of this 10703078353fb56772193b9304510048ac075a2c95b5Ted Kremenek // warning. 10713078353fb56772193b9304510048ac075a2c95b5Ted Kremenek // 10723078353fb56772193b9304510048ac075a2c95b5Ted Kremenek // NOTE: This an intermediate solution. There are on-going discussions on 10733078353fb56772193b9304510048ac075a2c95b5Ted Kremenek // how to properly support this warning outside of C++11 with an annotation. 107480ad52f327b532bded5c5b0ee38779d841c6cd35Richard Smith if (!AC.getASTContext().getLangOpts().CPlusPlus11) 10753078353fb56772193b9304510048ac075a2c95b5Ted Kremenek return; 10763078353fb56772193b9304510048ac075a2c95b5Ted Kremenek 1077e0d3b4cd2b66f1cef26cacbed5820ab7c22ad5b3Richard Smith FallthroughMapper FM(S); 1078e0d3b4cd2b66f1cef26cacbed5820ab7c22ad5b3Richard Smith FM.TraverseStmt(AC.getBody()); 1079e0d3b4cd2b66f1cef26cacbed5820ab7c22ad5b3Richard Smith 1080e0d3b4cd2b66f1cef26cacbed5820ab7c22ad5b3Richard Smith if (!FM.foundSwitchStatements()) 1081e0d3b4cd2b66f1cef26cacbed5820ab7c22ad5b3Richard Smith return; 1082e0d3b4cd2b66f1cef26cacbed5820ab7c22ad5b3Richard Smith 1083c2f51cfefd77e9b25f201ecf879343d6d9a45158Sean Hunt if (PerFunction && FM.getFallthroughStmts().empty()) 10841973634e445d4f1abdeedc2809f2d281929253b6Alexander Kornienko return; 10851973634e445d4f1abdeedc2809f2d281929253b6Alexander Kornienko 1086e0d3b4cd2b66f1cef26cacbed5820ab7c22ad5b3Richard Smith CFG *Cfg = AC.getCFG(); 1087e0d3b4cd2b66f1cef26cacbed5820ab7c22ad5b3Richard Smith 1088e0d3b4cd2b66f1cef26cacbed5820ab7c22ad5b3Richard Smith if (!Cfg) 1089e0d3b4cd2b66f1cef26cacbed5820ab7c22ad5b3Richard Smith return; 1090e0d3b4cd2b66f1cef26cacbed5820ab7c22ad5b3Richard Smith 10914874a8143dc3032205f97527ff619730db3d1f57Alexander Kornienko FM.fillReachableBlocks(Cfg); 1092e0d3b4cd2b66f1cef26cacbed5820ab7c22ad5b3Richard Smith 1093e0d3b4cd2b66f1cef26cacbed5820ab7c22ad5b3Richard Smith for (CFG::reverse_iterator I = Cfg->rbegin(), E = Cfg->rend(); I != E; ++I) { 1094e992ed1a065d857947b3969e6b779c41cc35c234Alexander Kornienko const CFGBlock *B = *I; 1095e992ed1a065d857947b3969e6b779c41cc35c234Alexander Kornienko const Stmt *Label = B->getLabel(); 1096e0d3b4cd2b66f1cef26cacbed5820ab7c22ad5b3Richard Smith 1097e0d3b4cd2b66f1cef26cacbed5820ab7c22ad5b3Richard Smith if (!Label || !isa<SwitchCase>(Label)) 1098e0d3b4cd2b66f1cef26cacbed5820ab7c22ad5b3Richard Smith continue; 1099e0d3b4cd2b66f1cef26cacbed5820ab7c22ad5b3Richard Smith 11004874a8143dc3032205f97527ff619730db3d1f57Alexander Kornienko int AnnotatedCnt; 11014874a8143dc3032205f97527ff619730db3d1f57Alexander Kornienko 1102e992ed1a065d857947b3969e6b779c41cc35c234Alexander Kornienko if (!FM.checkFallThroughIntoBlock(*B, AnnotatedCnt)) 1103e0d3b4cd2b66f1cef26cacbed5820ab7c22ad5b3Richard Smith continue; 1104e0d3b4cd2b66f1cef26cacbed5820ab7c22ad5b3Richard Smith 11051973634e445d4f1abdeedc2809f2d281929253b6Alexander Kornienko S.Diag(Label->getLocStart(), 1106c2f51cfefd77e9b25f201ecf879343d6d9a45158Sean Hunt PerFunction ? diag::warn_unannotated_fallthrough_per_function 1107c2f51cfefd77e9b25f201ecf879343d6d9a45158Sean Hunt : diag::warn_unannotated_fallthrough); 1108e0d3b4cd2b66f1cef26cacbed5820ab7c22ad5b3Richard Smith 1109e0d3b4cd2b66f1cef26cacbed5820ab7c22ad5b3Richard Smith if (!AnnotatedCnt) { 1110e0d3b4cd2b66f1cef26cacbed5820ab7c22ad5b3Richard Smith SourceLocation L = Label->getLocStart(); 1111e0d3b4cd2b66f1cef26cacbed5820ab7c22ad5b3Richard Smith if (L.isMacroID()) 1112e0d3b4cd2b66f1cef26cacbed5820ab7c22ad5b3Richard Smith continue; 111380ad52f327b532bded5c5b0ee38779d841c6cd35Richard Smith if (S.getLangOpts().CPlusPlus11) { 1114e992ed1a065d857947b3969e6b779c41cc35c234Alexander Kornienko const Stmt *Term = B->getTerminator(); 1115e992ed1a065d857947b3969e6b779c41cc35c234Alexander Kornienko // Skip empty cases. 1116e992ed1a065d857947b3969e6b779c41cc35c234Alexander Kornienko while (B->empty() && !Term && B->succ_size() == 1) { 1117e992ed1a065d857947b3969e6b779c41cc35c234Alexander Kornienko B = *B->succ_begin(); 1118e992ed1a065d857947b3969e6b779c41cc35c234Alexander Kornienko Term = B->getTerminator(); 1119e992ed1a065d857947b3969e6b779c41cc35c234Alexander Kornienko } 1120e992ed1a065d857947b3969e6b779c41cc35c234Alexander Kornienko if (!(B->empty() && Term && isa<BreakStmt>(Term))) { 112166da0abf7ab7cd449bb1d5134b2ef97d9d34d812Alexander Kornienko Preprocessor &PP = S.getPreprocessor(); 112266da0abf7ab7cd449bb1d5134b2ef97d9d34d812Alexander Kornienko TokenValue Tokens[] = { 112366da0abf7ab7cd449bb1d5134b2ef97d9d34d812Alexander Kornienko tok::l_square, tok::l_square, PP.getIdentifierInfo("clang"), 112466da0abf7ab7cd449bb1d5134b2ef97d9d34d812Alexander Kornienko tok::coloncolon, PP.getIdentifierInfo("fallthrough"), 112566da0abf7ab7cd449bb1d5134b2ef97d9d34d812Alexander Kornienko tok::r_square, tok::r_square 112666da0abf7ab7cd449bb1d5134b2ef97d9d34d812Alexander Kornienko }; 11271952354bd376062c3ab3d328c0fc6c36530c9309Dmitri Gribenko StringRef AnnotationSpelling = "[[clang::fallthrough]]"; 11281952354bd376062c3ab3d328c0fc6c36530c9309Dmitri Gribenko StringRef MacroName = PP.getLastMacroWithSpelling(L, Tokens); 11291952354bd376062c3ab3d328c0fc6c36530c9309Dmitri Gribenko if (!MacroName.empty()) 11301952354bd376062c3ab3d328c0fc6c36530c9309Dmitri Gribenko AnnotationSpelling = MacroName; 11311952354bd376062c3ab3d328c0fc6c36530c9309Dmitri Gribenko SmallString<64> TextToInsert(AnnotationSpelling); 11321952354bd376062c3ab3d328c0fc6c36530c9309Dmitri Gribenko TextToInsert += "; "; 1133a189d8976f1193b788508a1a29b2e9d0aca06acaAlexander Kornienko S.Diag(L, diag::note_insert_fallthrough_fixit) << 113466da0abf7ab7cd449bb1d5134b2ef97d9d34d812Alexander Kornienko AnnotationSpelling << 11351952354bd376062c3ab3d328c0fc6c36530c9309Dmitri Gribenko FixItHint::CreateInsertion(L, TextToInsert); 1136a189d8976f1193b788508a1a29b2e9d0aca06acaAlexander Kornienko } 1137e0d3b4cd2b66f1cef26cacbed5820ab7c22ad5b3Richard Smith } 1138e0d3b4cd2b66f1cef26cacbed5820ab7c22ad5b3Richard Smith S.Diag(L, diag::note_insert_break_fixit) << 1139e0d3b4cd2b66f1cef26cacbed5820ab7c22ad5b3Richard Smith FixItHint::CreateInsertion(L, "break; "); 1140e0d3b4cd2b66f1cef26cacbed5820ab7c22ad5b3Richard Smith } 1141e0d3b4cd2b66f1cef26cacbed5820ab7c22ad5b3Richard Smith } 1142e0d3b4cd2b66f1cef26cacbed5820ab7c22ad5b3Richard Smith 11436bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines for (const auto *F : FM.getFallthroughStmts()) 11446bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines S.Diag(F->getLocStart(), diag::warn_fallthrough_attr_invalid_placement); 1145e0d3b4cd2b66f1cef26cacbed5820ab7c22ad5b3Richard Smith} 1146e0d3b4cd2b66f1cef26cacbed5820ab7c22ad5b3Richard Smith 1147c0e44454bd78b8b4f3d70f08cf1edd5466b0c798Jordan Rosestatic bool isInLoop(const ASTContext &Ctx, const ParentMap &PM, 1148c0e44454bd78b8b4f3d70f08cf1edd5466b0c798Jordan Rose const Stmt *S) { 1149b5cd1220dd650a358622241237aa595c5d675506Jordan Rose assert(S); 1150b5cd1220dd650a358622241237aa595c5d675506Jordan Rose 1151b5cd1220dd650a358622241237aa595c5d675506Jordan Rose do { 1152b5cd1220dd650a358622241237aa595c5d675506Jordan Rose switch (S->getStmtClass()) { 1153b5cd1220dd650a358622241237aa595c5d675506Jordan Rose case Stmt::ForStmtClass: 1154b5cd1220dd650a358622241237aa595c5d675506Jordan Rose case Stmt::WhileStmtClass: 1155b5cd1220dd650a358622241237aa595c5d675506Jordan Rose case Stmt::CXXForRangeStmtClass: 1156b5cd1220dd650a358622241237aa595c5d675506Jordan Rose case Stmt::ObjCForCollectionStmtClass: 1157b5cd1220dd650a358622241237aa595c5d675506Jordan Rose return true; 1158c0e44454bd78b8b4f3d70f08cf1edd5466b0c798Jordan Rose case Stmt::DoStmtClass: { 1159c0e44454bd78b8b4f3d70f08cf1edd5466b0c798Jordan Rose const Expr *Cond = cast<DoStmt>(S)->getCond(); 1160c0e44454bd78b8b4f3d70f08cf1edd5466b0c798Jordan Rose llvm::APSInt Val; 1161c0e44454bd78b8b4f3d70f08cf1edd5466b0c798Jordan Rose if (!Cond->EvaluateAsInt(Val, Ctx)) 1162c0e44454bd78b8b4f3d70f08cf1edd5466b0c798Jordan Rose return true; 1163c0e44454bd78b8b4f3d70f08cf1edd5466b0c798Jordan Rose return Val.getBoolValue(); 1164c0e44454bd78b8b4f3d70f08cf1edd5466b0c798Jordan Rose } 1165b5cd1220dd650a358622241237aa595c5d675506Jordan Rose default: 1166b5cd1220dd650a358622241237aa595c5d675506Jordan Rose break; 1167b5cd1220dd650a358622241237aa595c5d675506Jordan Rose } 1168b5cd1220dd650a358622241237aa595c5d675506Jordan Rose } while ((S = PM.getParent(S))); 1169b5cd1220dd650a358622241237aa595c5d675506Jordan Rose 1170b5cd1220dd650a358622241237aa595c5d675506Jordan Rose return false; 1171b5cd1220dd650a358622241237aa595c5d675506Jordan Rose} 1172b5cd1220dd650a358622241237aa595c5d675506Jordan Rose 117358b6bdcdeb683a3504f2248a409e1f4e85876ceeJordan Rose 117458b6bdcdeb683a3504f2248a409e1f4e85876ceeJordan Rosestatic void diagnoseRepeatedUseOfWeak(Sema &S, 117558b6bdcdeb683a3504f2248a409e1f4e85876ceeJordan Rose const sema::FunctionScopeInfo *CurFn, 1176b5cd1220dd650a358622241237aa595c5d675506Jordan Rose const Decl *D, 1177b5cd1220dd650a358622241237aa595c5d675506Jordan Rose const ParentMap &PM) { 117858b6bdcdeb683a3504f2248a409e1f4e85876ceeJordan Rose typedef sema::FunctionScopeInfo::WeakObjectProfileTy WeakObjectProfileTy; 117958b6bdcdeb683a3504f2248a409e1f4e85876ceeJordan Rose typedef sema::FunctionScopeInfo::WeakObjectUseMap WeakObjectUseMap; 118058b6bdcdeb683a3504f2248a409e1f4e85876ceeJordan Rose typedef sema::FunctionScopeInfo::WeakUseVector WeakUseVector; 1181651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines typedef std::pair<const Stmt *, WeakObjectUseMap::const_iterator> 1182651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines StmtUsesPair; 118358b6bdcdeb683a3504f2248a409e1f4e85876ceeJordan Rose 1184c0e44454bd78b8b4f3d70f08cf1edd5466b0c798Jordan Rose ASTContext &Ctx = S.getASTContext(); 1185c0e44454bd78b8b4f3d70f08cf1edd5466b0c798Jordan Rose 118658b6bdcdeb683a3504f2248a409e1f4e85876ceeJordan Rose const WeakObjectUseMap &WeakMap = CurFn->getWeakObjectUses(); 118758b6bdcdeb683a3504f2248a409e1f4e85876ceeJordan Rose 118858b6bdcdeb683a3504f2248a409e1f4e85876ceeJordan Rose // Extract all weak objects that are referenced more than once. 118958b6bdcdeb683a3504f2248a409e1f4e85876ceeJordan Rose SmallVector<StmtUsesPair, 8> UsesByStmt; 119058b6bdcdeb683a3504f2248a409e1f4e85876ceeJordan Rose for (WeakObjectUseMap::const_iterator I = WeakMap.begin(), E = WeakMap.end(); 119158b6bdcdeb683a3504f2248a409e1f4e85876ceeJordan Rose I != E; ++I) { 119258b6bdcdeb683a3504f2248a409e1f4e85876ceeJordan Rose const WeakUseVector &Uses = I->second; 119358b6bdcdeb683a3504f2248a409e1f4e85876ceeJordan Rose 119458b6bdcdeb683a3504f2248a409e1f4e85876ceeJordan Rose // Find the first read of the weak object. 119558b6bdcdeb683a3504f2248a409e1f4e85876ceeJordan Rose WeakUseVector::const_iterator UI = Uses.begin(), UE = Uses.end(); 119658b6bdcdeb683a3504f2248a409e1f4e85876ceeJordan Rose for ( ; UI != UE; ++UI) { 119758b6bdcdeb683a3504f2248a409e1f4e85876ceeJordan Rose if (UI->isUnsafe()) 119858b6bdcdeb683a3504f2248a409e1f4e85876ceeJordan Rose break; 119958b6bdcdeb683a3504f2248a409e1f4e85876ceeJordan Rose } 120058b6bdcdeb683a3504f2248a409e1f4e85876ceeJordan Rose 120158b6bdcdeb683a3504f2248a409e1f4e85876ceeJordan Rose // If there were only writes to this object, don't warn. 120258b6bdcdeb683a3504f2248a409e1f4e85876ceeJordan Rose if (UI == UE) 120358b6bdcdeb683a3504f2248a409e1f4e85876ceeJordan Rose continue; 120458b6bdcdeb683a3504f2248a409e1f4e85876ceeJordan Rose 1205b5cd1220dd650a358622241237aa595c5d675506Jordan Rose // If there was only one read, followed by any number of writes, and the 1206c0e44454bd78b8b4f3d70f08cf1edd5466b0c798Jordan Rose // read is not within a loop, don't warn. Additionally, don't warn in a 1207c0e44454bd78b8b4f3d70f08cf1edd5466b0c798Jordan Rose // loop if the base object is a local variable -- local variables are often 1208c0e44454bd78b8b4f3d70f08cf1edd5466b0c798Jordan Rose // changed in loops. 1209b5cd1220dd650a358622241237aa595c5d675506Jordan Rose if (UI == Uses.begin()) { 1210b5cd1220dd650a358622241237aa595c5d675506Jordan Rose WeakUseVector::const_iterator UI2 = UI; 1211b5cd1220dd650a358622241237aa595c5d675506Jordan Rose for (++UI2; UI2 != UE; ++UI2) 1212b5cd1220dd650a358622241237aa595c5d675506Jordan Rose if (UI2->isUnsafe()) 1213b5cd1220dd650a358622241237aa595c5d675506Jordan Rose break; 1214b5cd1220dd650a358622241237aa595c5d675506Jordan Rose 1215c0e44454bd78b8b4f3d70f08cf1edd5466b0c798Jordan Rose if (UI2 == UE) { 1216c0e44454bd78b8b4f3d70f08cf1edd5466b0c798Jordan Rose if (!isInLoop(Ctx, PM, UI->getUseExpr())) 1217b5cd1220dd650a358622241237aa595c5d675506Jordan Rose continue; 1218c0e44454bd78b8b4f3d70f08cf1edd5466b0c798Jordan Rose 1219c0e44454bd78b8b4f3d70f08cf1edd5466b0c798Jordan Rose const WeakObjectProfileTy &Profile = I->first; 1220c0e44454bd78b8b4f3d70f08cf1edd5466b0c798Jordan Rose if (!Profile.isExactProfile()) 1221c0e44454bd78b8b4f3d70f08cf1edd5466b0c798Jordan Rose continue; 1222c0e44454bd78b8b4f3d70f08cf1edd5466b0c798Jordan Rose 1223c0e44454bd78b8b4f3d70f08cf1edd5466b0c798Jordan Rose const NamedDecl *Base = Profile.getBase(); 1224c0e44454bd78b8b4f3d70f08cf1edd5466b0c798Jordan Rose if (!Base) 1225c0e44454bd78b8b4f3d70f08cf1edd5466b0c798Jordan Rose Base = Profile.getProperty(); 1226c0e44454bd78b8b4f3d70f08cf1edd5466b0c798Jordan Rose assert(Base && "A profile always has a base or property."); 1227c0e44454bd78b8b4f3d70f08cf1edd5466b0c798Jordan Rose 1228c0e44454bd78b8b4f3d70f08cf1edd5466b0c798Jordan Rose if (const VarDecl *BaseVar = dyn_cast<VarDecl>(Base)) 1229c0e44454bd78b8b4f3d70f08cf1edd5466b0c798Jordan Rose if (BaseVar->hasLocalStorage() && !isa<ParmVarDecl>(Base)) 1230c0e44454bd78b8b4f3d70f08cf1edd5466b0c798Jordan Rose continue; 1231c0e44454bd78b8b4f3d70f08cf1edd5466b0c798Jordan Rose } 1232b5cd1220dd650a358622241237aa595c5d675506Jordan Rose } 1233b5cd1220dd650a358622241237aa595c5d675506Jordan Rose 123458b6bdcdeb683a3504f2248a409e1f4e85876ceeJordan Rose UsesByStmt.push_back(StmtUsesPair(UI->getUseExpr(), I)); 123558b6bdcdeb683a3504f2248a409e1f4e85876ceeJordan Rose } 123658b6bdcdeb683a3504f2248a409e1f4e85876ceeJordan Rose 123758b6bdcdeb683a3504f2248a409e1f4e85876ceeJordan Rose if (UsesByStmt.empty()) 123858b6bdcdeb683a3504f2248a409e1f4e85876ceeJordan Rose return; 123958b6bdcdeb683a3504f2248a409e1f4e85876ceeJordan Rose 124058b6bdcdeb683a3504f2248a409e1f4e85876ceeJordan Rose // Sort by first use so that we emit the warnings in a deterministic order. 1241651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines SourceManager &SM = S.getSourceManager(); 124258b6bdcdeb683a3504f2248a409e1f4e85876ceeJordan Rose std::sort(UsesByStmt.begin(), UsesByStmt.end(), 1243651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines [&SM](const StmtUsesPair &LHS, const StmtUsesPair &RHS) { 1244651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines return SM.isBeforeInTranslationUnit(LHS.first->getLocStart(), 1245651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines RHS.first->getLocStart()); 1246651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines }); 124758b6bdcdeb683a3504f2248a409e1f4e85876ceeJordan Rose 124858b6bdcdeb683a3504f2248a409e1f4e85876ceeJordan Rose // Classify the current code body for better warning text. 124958b6bdcdeb683a3504f2248a409e1f4e85876ceeJordan Rose // This enum should stay in sync with the cases in 125058b6bdcdeb683a3504f2248a409e1f4e85876ceeJordan Rose // warn_arc_repeated_use_of_weak and warn_arc_possible_repeated_use_of_weak. 125158b6bdcdeb683a3504f2248a409e1f4e85876ceeJordan Rose // FIXME: Should we use a common classification enum and the same set of 125258b6bdcdeb683a3504f2248a409e1f4e85876ceeJordan Rose // possibilities all throughout Sema? 125358b6bdcdeb683a3504f2248a409e1f4e85876ceeJordan Rose enum { 125458b6bdcdeb683a3504f2248a409e1f4e85876ceeJordan Rose Function, 125558b6bdcdeb683a3504f2248a409e1f4e85876ceeJordan Rose Method, 125658b6bdcdeb683a3504f2248a409e1f4e85876ceeJordan Rose Block, 125758b6bdcdeb683a3504f2248a409e1f4e85876ceeJordan Rose Lambda 125858b6bdcdeb683a3504f2248a409e1f4e85876ceeJordan Rose } FunctionKind; 125958b6bdcdeb683a3504f2248a409e1f4e85876ceeJordan Rose 126058b6bdcdeb683a3504f2248a409e1f4e85876ceeJordan Rose if (isa<sema::BlockScopeInfo>(CurFn)) 126158b6bdcdeb683a3504f2248a409e1f4e85876ceeJordan Rose FunctionKind = Block; 126258b6bdcdeb683a3504f2248a409e1f4e85876ceeJordan Rose else if (isa<sema::LambdaScopeInfo>(CurFn)) 126358b6bdcdeb683a3504f2248a409e1f4e85876ceeJordan Rose FunctionKind = Lambda; 126458b6bdcdeb683a3504f2248a409e1f4e85876ceeJordan Rose else if (isa<ObjCMethodDecl>(D)) 126558b6bdcdeb683a3504f2248a409e1f4e85876ceeJordan Rose FunctionKind = Method; 126658b6bdcdeb683a3504f2248a409e1f4e85876ceeJordan Rose else 126758b6bdcdeb683a3504f2248a409e1f4e85876ceeJordan Rose FunctionKind = Function; 126858b6bdcdeb683a3504f2248a409e1f4e85876ceeJordan Rose 126958b6bdcdeb683a3504f2248a409e1f4e85876ceeJordan Rose // Iterate through the sorted problems and emit warnings for each. 12706bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines for (const auto &P : UsesByStmt) { 12716bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines const Stmt *FirstRead = P.first; 12726bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines const WeakObjectProfileTy &Key = P.second->first; 12736bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines const WeakUseVector &Uses = P.second->second; 127458b6bdcdeb683a3504f2248a409e1f4e85876ceeJordan Rose 12757a2704800943fbb69207e125d28186278712af36Jordan Rose // For complicated expressions like 'a.b.c' and 'x.b.c', WeakObjectProfileTy 12767a2704800943fbb69207e125d28186278712af36Jordan Rose // may not contain enough information to determine that these are different 12777a2704800943fbb69207e125d28186278712af36Jordan Rose // properties. We can only be 100% sure of a repeated use in certain cases, 12787a2704800943fbb69207e125d28186278712af36Jordan Rose // and we adjust the diagnostic kind accordingly so that the less certain 12797a2704800943fbb69207e125d28186278712af36Jordan Rose // case can be turned off if it is too noisy. 128058b6bdcdeb683a3504f2248a409e1f4e85876ceeJordan Rose unsigned DiagKind; 128158b6bdcdeb683a3504f2248a409e1f4e85876ceeJordan Rose if (Key.isExactProfile()) 128258b6bdcdeb683a3504f2248a409e1f4e85876ceeJordan Rose DiagKind = diag::warn_arc_repeated_use_of_weak; 128358b6bdcdeb683a3504f2248a409e1f4e85876ceeJordan Rose else 128458b6bdcdeb683a3504f2248a409e1f4e85876ceeJordan Rose DiagKind = diag::warn_arc_possible_repeated_use_of_weak; 128558b6bdcdeb683a3504f2248a409e1f4e85876ceeJordan Rose 12867a2704800943fbb69207e125d28186278712af36Jordan Rose // Classify the weak object being accessed for better warning text. 12877a2704800943fbb69207e125d28186278712af36Jordan Rose // This enum should stay in sync with the cases in 12887a2704800943fbb69207e125d28186278712af36Jordan Rose // warn_arc_repeated_use_of_weak and warn_arc_possible_repeated_use_of_weak. 12897a2704800943fbb69207e125d28186278712af36Jordan Rose enum { 12907a2704800943fbb69207e125d28186278712af36Jordan Rose Variable, 12917a2704800943fbb69207e125d28186278712af36Jordan Rose Property, 12927a2704800943fbb69207e125d28186278712af36Jordan Rose ImplicitProperty, 12937a2704800943fbb69207e125d28186278712af36Jordan Rose Ivar 12947a2704800943fbb69207e125d28186278712af36Jordan Rose } ObjectKind; 12957a2704800943fbb69207e125d28186278712af36Jordan Rose 12967a2704800943fbb69207e125d28186278712af36Jordan Rose const NamedDecl *D = Key.getProperty(); 12977a2704800943fbb69207e125d28186278712af36Jordan Rose if (isa<VarDecl>(D)) 12987a2704800943fbb69207e125d28186278712af36Jordan Rose ObjectKind = Variable; 12997a2704800943fbb69207e125d28186278712af36Jordan Rose else if (isa<ObjCPropertyDecl>(D)) 13007a2704800943fbb69207e125d28186278712af36Jordan Rose ObjectKind = Property; 13017a2704800943fbb69207e125d28186278712af36Jordan Rose else if (isa<ObjCMethodDecl>(D)) 13027a2704800943fbb69207e125d28186278712af36Jordan Rose ObjectKind = ImplicitProperty; 13037a2704800943fbb69207e125d28186278712af36Jordan Rose else if (isa<ObjCIvarDecl>(D)) 13047a2704800943fbb69207e125d28186278712af36Jordan Rose ObjectKind = Ivar; 13057a2704800943fbb69207e125d28186278712af36Jordan Rose else 13067a2704800943fbb69207e125d28186278712af36Jordan Rose llvm_unreachable("Unexpected weak object kind!"); 13077a2704800943fbb69207e125d28186278712af36Jordan Rose 130858b6bdcdeb683a3504f2248a409e1f4e85876ceeJordan Rose // Show the first time the object was read. 130958b6bdcdeb683a3504f2248a409e1f4e85876ceeJordan Rose S.Diag(FirstRead->getLocStart(), DiagKind) 13107348454025693dd20a411c2bcaabd4460cb87559Joerg Sonnenberger << int(ObjectKind) << D << int(FunctionKind) 131158b6bdcdeb683a3504f2248a409e1f4e85876ceeJordan Rose << FirstRead->getSourceRange(); 131258b6bdcdeb683a3504f2248a409e1f4e85876ceeJordan Rose 131358b6bdcdeb683a3504f2248a409e1f4e85876ceeJordan Rose // Print all the other accesses as notes. 13146bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines for (const auto &Use : Uses) { 13156bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines if (Use.getUseExpr() == FirstRead) 131658b6bdcdeb683a3504f2248a409e1f4e85876ceeJordan Rose continue; 13176bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines S.Diag(Use.getUseExpr()->getLocStart(), 131858b6bdcdeb683a3504f2248a409e1f4e85876ceeJordan Rose diag::note_arc_weak_also_accessed_here) 13196bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines << Use.getUseExpr()->getSourceRange(); 132058b6bdcdeb683a3504f2248a409e1f4e85876ceeJordan Rose } 132158b6bdcdeb683a3504f2248a409e1f4e85876ceeJordan Rose } 132258b6bdcdeb683a3504f2248a409e1f4e85876ceeJordan Rose} 132358b6bdcdeb683a3504f2248a409e1f4e85876ceeJordan Rose 132458b6bdcdeb683a3504f2248a409e1f4e85876ceeJordan Rosenamespace { 1325610068c8cd2321f90e147b12cf794e1f840b6405Ted Kremenekclass UninitValsDiagReporter : public UninitVariablesHandler { 1326610068c8cd2321f90e147b12cf794e1f840b6405Ted Kremenek Sema &S; 13275f9e272e632e951b1efe824cd16acb4d96077930Chris Lattner typedef SmallVector<UninitUse, 2> UsesVec; 1328e103979ceac63c98873f3307ee897eab559356a0Benjamin Kramer typedef llvm::PointerIntPair<UsesVec *, 1, bool> MappedType; 13293285c78041f80a26f6a947e2922e15c4af6e00bbEnea Zaffanella // Prefer using MapVector to DenseMap, so that iteration order will be 13303285c78041f80a26f6a947e2922e15c4af6e00bbEnea Zaffanella // the same as insertion order. This is needed to obtain a deterministic 13313285c78041f80a26f6a947e2922e15c4af6e00bbEnea Zaffanella // order of diagnostics when calling flushDiagnostics(). 13323285c78041f80a26f6a947e2922e15c4af6e00bbEnea Zaffanella typedef llvm::MapVector<const VarDecl *, MappedType> UsesMap; 133394b1b4d785bc0f09f6af4be394e59d51f35dda60Ted Kremenek UsesMap *uses; 133494b1b4d785bc0f09f6af4be394e59d51f35dda60Ted Kremenek 1335610068c8cd2321f90e147b12cf794e1f840b6405Ted Kremenekpublic: 13366bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines UninitValsDiagReporter(Sema &S) : S(S), uses(nullptr) {} 133733337ca4d89605025818daf83390ab4271d598d9Pirama Arumuga Nainar ~UninitValsDiagReporter() override { flushDiagnostics(); } 13389e7617220135a6f6226cf09cb242cc1b905aedb4Ted Kremenek 13393285c78041f80a26f6a947e2922e15c4af6e00bbEnea Zaffanella MappedType &getUses(const VarDecl *vd) { 134094b1b4d785bc0f09f6af4be394e59d51f35dda60Ted Kremenek if (!uses) 134194b1b4d785bc0f09f6af4be394e59d51f35dda60Ted Kremenek uses = new UsesMap(); 13429e7617220135a6f6226cf09cb242cc1b905aedb4Ted Kremenek 13433285c78041f80a26f6a947e2922e15c4af6e00bbEnea Zaffanella MappedType &V = (*uses)[vd]; 1344e103979ceac63c98873f3307ee897eab559356a0Benjamin Kramer if (!V.getPointer()) 1345e103979ceac63c98873f3307ee897eab559356a0Benjamin Kramer V.setPointer(new UsesVec()); 134694b1b4d785bc0f09f6af4be394e59d51f35dda60Ted Kremenek 13479e7617220135a6f6226cf09cb242cc1b905aedb4Ted Kremenek return V; 13489e7617220135a6f6226cf09cb242cc1b905aedb4Ted Kremenek } 1349651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines 1350651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines void handleUseOfUninitVariable(const VarDecl *vd, 1351651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines const UninitUse &use) override { 1352e103979ceac63c98873f3307ee897eab559356a0Benjamin Kramer getUses(vd).getPointer()->push_back(use); 13539e7617220135a6f6226cf09cb242cc1b905aedb4Ted Kremenek } 13549e7617220135a6f6226cf09cb242cc1b905aedb4Ted Kremenek 1355651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines void handleSelfInit(const VarDecl *vd) override { 1356e103979ceac63c98873f3307ee897eab559356a0Benjamin Kramer getUses(vd).setInt(true); 135794b1b4d785bc0f09f6af4be394e59d51f35dda60Ted Kremenek } 135894b1b4d785bc0f09f6af4be394e59d51f35dda60Ted Kremenek 135994b1b4d785bc0f09f6af4be394e59d51f35dda60Ted Kremenek void flushDiagnostics() { 136094b1b4d785bc0f09f6af4be394e59d51f35dda60Ted Kremenek if (!uses) 136194b1b4d785bc0f09f6af4be394e59d51f35dda60Ted Kremenek return; 13623285c78041f80a26f6a947e2922e15c4af6e00bbEnea Zaffanella 13636bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines for (const auto &P : *uses) { 13646bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines const VarDecl *vd = P.first; 13656bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines const MappedType &V = P.second; 13669e7617220135a6f6226cf09cb242cc1b905aedb4Ted Kremenek 1367e103979ceac63c98873f3307ee897eab559356a0Benjamin Kramer UsesVec *vec = V.getPointer(); 1368e103979ceac63c98873f3307ee897eab559356a0Benjamin Kramer bool hasSelfInit = V.getInt(); 13699e7617220135a6f6226cf09cb242cc1b905aedb4Ted Kremenek 13709e7617220135a6f6226cf09cb242cc1b905aedb4Ted Kremenek // Specially handle the case where we have uses of an uninitialized 13719e7617220135a6f6226cf09cb242cc1b905aedb4Ted Kremenek // variable, but the root cause is an idiomatic self-init. We want 13729e7617220135a6f6226cf09cb242cc1b905aedb4Ted Kremenek // to report the diagnostic at the self-init since that is the root cause. 13730d381810da19dd7677b9a79fca516d298fa5addbMatt Beaumont-Gay if (!vec->empty() && hasSelfInit && hasAlwaysUninitializedUse(vec)) 13742815e1a075c74143a0b60a632090ece1dffa5c7cRichard Smith DiagnoseUninitializedUse(S, vd, 13752815e1a075c74143a0b60a632090ece1dffa5c7cRichard Smith UninitUse(vd->getInit()->IgnoreParenCasts(), 13762815e1a075c74143a0b60a632090ece1dffa5c7cRichard Smith /* isAlwaysUninit */ true), 13770d381810da19dd7677b9a79fca516d298fa5addbMatt Beaumont-Gay /* alwaysReportSelfInit */ true); 13789e7617220135a6f6226cf09cb242cc1b905aedb4Ted Kremenek else { 13799e7617220135a6f6226cf09cb242cc1b905aedb4Ted Kremenek // Sort the uses by their SourceLocations. While not strictly 13809e7617220135a6f6226cf09cb242cc1b905aedb4Ted Kremenek // guaranteed to produce them in line/column order, this will provide 13819e7617220135a6f6226cf09cb242cc1b905aedb4Ted Kremenek // a stable ordering. 1382651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines std::sort(vec->begin(), vec->end(), 1383651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines [](const UninitUse &a, const UninitUse &b) { 1384651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines // Prefer a more confident report over a less confident one. 1385651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines if (a.getKind() != b.getKind()) 1386651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines return a.getKind() > b.getKind(); 1387651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines return a.getUser()->getLocStart() < b.getUser()->getLocStart(); 1388651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines }); 1389651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines 13906bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines for (const auto &U : *vec) { 13912815e1a075c74143a0b60a632090ece1dffa5c7cRichard Smith // If we have self-init, downgrade all uses to 'may be uninitialized'. 13926bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines UninitUse Use = hasSelfInit ? UninitUse(U.getUser(), false) : U; 13932815e1a075c74143a0b60a632090ece1dffa5c7cRichard Smith 13942815e1a075c74143a0b60a632090ece1dffa5c7cRichard Smith if (DiagnoseUninitializedUse(S, vd, Use)) 13959e7617220135a6f6226cf09cb242cc1b905aedb4Ted Kremenek // Skip further diagnostics for this variable. We try to warn only 13969e7617220135a6f6226cf09cb242cc1b905aedb4Ted Kremenek // on the first point at which a variable is used uninitialized. 13979e7617220135a6f6226cf09cb242cc1b905aedb4Ted Kremenek break; 13989e7617220135a6f6226cf09cb242cc1b905aedb4Ted Kremenek } 139964fb959beb3a0ecb84a58e6ff82660a7a669f7b8Chandler Carruth } 14009e7617220135a6f6226cf09cb242cc1b905aedb4Ted Kremenek 14019e7617220135a6f6226cf09cb242cc1b905aedb4Ted Kremenek // Release the uses vector. 140294b1b4d785bc0f09f6af4be394e59d51f35dda60Ted Kremenek delete vec; 140394b1b4d785bc0f09f6af4be394e59d51f35dda60Ted Kremenek } 140494b1b4d785bc0f09f6af4be394e59d51f35dda60Ted Kremenek delete uses; 1405610068c8cd2321f90e147b12cf794e1f840b6405Ted Kremenek } 14060d381810da19dd7677b9a79fca516d298fa5addbMatt Beaumont-Gay 14070d381810da19dd7677b9a79fca516d298fa5addbMatt Beaumont-Gayprivate: 14080d381810da19dd7677b9a79fca516d298fa5addbMatt Beaumont-Gay static bool hasAlwaysUninitializedUse(const UsesVec* vec) { 14096bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines return std::any_of(vec->begin(), vec->end(), [](const UninitUse &U) { 14106bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines return U.getKind() == UninitUse::Always || 14116bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines U.getKind() == UninitUse::AfterCall || 14126bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines U.getKind() == UninitUse::AfterDecl; 14136bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines }); 14140d381810da19dd7677b9a79fca516d298fa5addbMatt Beaumont-Gay } 1415610068c8cd2321f90e147b12cf794e1f840b6405Ted Kremenek}; 1416610068c8cd2321f90e147b12cf794e1f840b6405Ted Kremenek} 1417610068c8cd2321f90e147b12cf794e1f840b6405Ted Kremenek 141875f23aeb1c820b49f9faebed63b1cbef76c2c907Caitlin Sadowskinamespace clang { 1419df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchinsnamespace { 1420cfa88f893915ceb8ae4ce2f17c46c24a4d67502fDmitri Gribenkotypedef SmallVector<PartialDiagnosticAt, 1> OptionalNotes; 14212e5156274b8051217565b557bfa14c80f7990e9cRichard Smithtypedef std::pair<PartialDiagnosticAt, OptionalNotes> DelayedDiag; 1422ecafd309b3ed2ffc6f8ae7eecd1e7eae84b26f81Benjamin Kramertypedef std::list<DelayedDiag> DiagList; 142375f23aeb1c820b49f9faebed63b1cbef76c2c907Caitlin Sadowski 142475f23aeb1c820b49f9faebed63b1cbef76c2c907Caitlin Sadowskistruct SortDiagBySourceLocation { 1425ecafd309b3ed2ffc6f8ae7eecd1e7eae84b26f81Benjamin Kramer SourceManager &SM; 1426ecafd309b3ed2ffc6f8ae7eecd1e7eae84b26f81Benjamin Kramer SortDiagBySourceLocation(SourceManager &SM) : SM(SM) {} 142775f23aeb1c820b49f9faebed63b1cbef76c2c907Caitlin Sadowski 142875f23aeb1c820b49f9faebed63b1cbef76c2c907Caitlin Sadowski bool operator()(const DelayedDiag &left, const DelayedDiag &right) { 142975f23aeb1c820b49f9faebed63b1cbef76c2c907Caitlin Sadowski // Although this call will be slow, this is only called when outputting 143075f23aeb1c820b49f9faebed63b1cbef76c2c907Caitlin Sadowski // multiple warnings. 1431ecafd309b3ed2ffc6f8ae7eecd1e7eae84b26f81Benjamin Kramer return SM.isBeforeInTranslationUnit(left.first.first, right.first.first); 143275f23aeb1c820b49f9faebed63b1cbef76c2c907Caitlin Sadowski } 143375f23aeb1c820b49f9faebed63b1cbef76c2c907Caitlin Sadowski}; 1434df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins}} 143575f23aeb1c820b49f9faebed63b1cbef76c2c907Caitlin Sadowski 1436df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins//===----------------------------------------------------------------------===// 1437df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins// -Wthread-safety 1438df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins//===----------------------------------------------------------------------===// 1439df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchinsnamespace clang { 1440176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hinesnamespace threadSafety { 14413ea9e33ea25e0c2b12db56418ba3f994eb662c04Pirama Arumuga Nainarnamespace { 1442176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hinesclass ThreadSafetyReporter : public clang::threadSafety::ThreadSafetyHandler { 144375f23aeb1c820b49f9faebed63b1cbef76c2c907Caitlin Sadowski Sema &S; 144475f23aeb1c820b49f9faebed63b1cbef76c2c907Caitlin Sadowski DiagList Warnings; 14452e5156274b8051217565b557bfa14c80f7990e9cRichard Smith SourceLocation FunLocation, FunEndLocation; 144675f23aeb1c820b49f9faebed63b1cbef76c2c907Caitlin Sadowski 1447176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines const FunctionDecl *CurrentFunction; 1448176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines bool Verbose; 1449176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines 1450176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines OptionalNotes getNotes() const { 1451176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines if (Verbose && CurrentFunction) { 1452176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines PartialDiagnosticAt FNote(CurrentFunction->getBody()->getLocStart(), 1453176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines S.PDiag(diag::note_thread_warning_in_fun) 1454176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines << CurrentFunction->getNameAsString()); 1455176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines return OptionalNotes(1, FNote); 1456176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines } 1457176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines return OptionalNotes(); 1458176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines } 1459176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines 1460176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines OptionalNotes getNotes(const PartialDiagnosticAt &Note) const { 1461176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines OptionalNotes ONS(1, Note); 1462176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines if (Verbose && CurrentFunction) { 1463176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines PartialDiagnosticAt FNote(CurrentFunction->getBody()->getLocStart(), 1464176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines S.PDiag(diag::note_thread_warning_in_fun) 1465176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines << CurrentFunction->getNameAsString()); 1466176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines ONS.push_back(FNote); 1467176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines } 1468176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines return ONS; 1469176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines } 1470176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines 1471176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines OptionalNotes getNotes(const PartialDiagnosticAt &Note1, 1472176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines const PartialDiagnosticAt &Note2) const { 1473176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines OptionalNotes ONS; 1474176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines ONS.push_back(Note1); 1475176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines ONS.push_back(Note2); 1476176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines if (Verbose && CurrentFunction) { 1477176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines PartialDiagnosticAt FNote(CurrentFunction->getBody()->getLocStart(), 1478176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines S.PDiag(diag::note_thread_warning_in_fun) 1479176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines << CurrentFunction->getNameAsString()); 1480176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines ONS.push_back(FNote); 1481176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines } 1482176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines return ONS; 1483176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines } 1484176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines 148575f23aeb1c820b49f9faebed63b1cbef76c2c907Caitlin Sadowski // Helper functions 1486651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines void warnLockMismatch(unsigned DiagID, StringRef Kind, Name LockName, 1487651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines SourceLocation Loc) { 1488f1ac63702143d84db778d32eb185a77fc97db5f5DeLesley Hutchins // Gracefully handle rare cases when the analysis can't get a more 1489f1ac63702143d84db778d32eb185a77fc97db5f5DeLesley Hutchins // precise source location. 1490f1ac63702143d84db778d32eb185a77fc97db5f5DeLesley Hutchins if (!Loc.isValid()) 1491f1ac63702143d84db778d32eb185a77fc97db5f5DeLesley Hutchins Loc = FunLocation; 1492651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines PartialDiagnosticAt Warning(Loc, S.PDiag(DiagID) << Kind << LockName); 1493176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines Warnings.push_back(DelayedDiag(Warning, getNotes())); 149475f23aeb1c820b49f9faebed63b1cbef76c2c907Caitlin Sadowski } 149575f23aeb1c820b49f9faebed63b1cbef76c2c907Caitlin Sadowski 149675f23aeb1c820b49f9faebed63b1cbef76c2c907Caitlin Sadowski public: 14972e5156274b8051217565b557bfa14c80f7990e9cRichard Smith ThreadSafetyReporter(Sema &S, SourceLocation FL, SourceLocation FEL) 1498176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines : S(S), FunLocation(FL), FunEndLocation(FEL), 1499176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines CurrentFunction(nullptr), Verbose(false) {} 1500176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines 1501176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines void setVerbose(bool b) { Verbose = b; } 150275f23aeb1c820b49f9faebed63b1cbef76c2c907Caitlin Sadowski 150375f23aeb1c820b49f9faebed63b1cbef76c2c907Caitlin Sadowski /// \brief Emit all buffered diagnostics in order of sourcelocation. 150475f23aeb1c820b49f9faebed63b1cbef76c2c907Caitlin Sadowski /// We need to output diagnostics produced while iterating through 150575f23aeb1c820b49f9faebed63b1cbef76c2c907Caitlin Sadowski /// the lockset in deterministic order, so this function orders diagnostics 150675f23aeb1c820b49f9faebed63b1cbef76c2c907Caitlin Sadowski /// and outputs them. 150775f23aeb1c820b49f9faebed63b1cbef76c2c907Caitlin Sadowski void emitDiagnostics() { 1508ecafd309b3ed2ffc6f8ae7eecd1e7eae84b26f81Benjamin Kramer Warnings.sort(SortDiagBySourceLocation(S.getSourceManager())); 15096bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines for (const auto &Diag : Warnings) { 15106bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines S.Diag(Diag.first.first, Diag.first.second); 15116bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines for (const auto &Note : Diag.second) 15126bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines S.Diag(Note.first, Note.second); 15132e5156274b8051217565b557bfa14c80f7990e9cRichard Smith } 151475f23aeb1c820b49f9faebed63b1cbef76c2c907Caitlin Sadowski } 151575f23aeb1c820b49f9faebed63b1cbef76c2c907Caitlin Sadowski 1516651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines void handleInvalidLockExp(StringRef Kind, SourceLocation Loc) override { 1517651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines PartialDiagnosticAt Warning(Loc, S.PDiag(diag::warn_cannot_resolve_lock) 1518651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines << Loc); 1519176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines Warnings.push_back(DelayedDiag(Warning, getNotes())); 152099107ebc0a5aea953b736e12757e0919d5249d43Caitlin Sadowski } 1521176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines 1522651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines void handleUnmatchedUnlock(StringRef Kind, Name LockName, 1523651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines SourceLocation Loc) override { 1524651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines warnLockMismatch(diag::warn_unlock_but_no_lock, Kind, LockName, Loc); 152575f23aeb1c820b49f9faebed63b1cbef76c2c907Caitlin Sadowski } 1526176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines 1527651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines void handleIncorrectUnlockKind(StringRef Kind, Name LockName, 1528651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines LockKind Expected, LockKind Received, 1529651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines SourceLocation Loc) override { 1530651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines if (Loc.isInvalid()) 1531651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines Loc = FunLocation; 1532651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines PartialDiagnosticAt Warning(Loc, S.PDiag(diag::warn_unlock_kind_mismatch) 1533651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines << Kind << LockName << Received 1534651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines << Expected); 1535176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines Warnings.push_back(DelayedDiag(Warning, getNotes())); 1536651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines } 1537176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines 1538651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines void handleDoubleLock(StringRef Kind, Name LockName, SourceLocation Loc) override { 1539651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines warnLockMismatch(diag::warn_double_lock, Kind, LockName, Loc); 154075f23aeb1c820b49f9faebed63b1cbef76c2c907Caitlin Sadowski } 154175f23aeb1c820b49f9faebed63b1cbef76c2c907Caitlin Sadowski 1542651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines void handleMutexHeldEndOfScope(StringRef Kind, Name LockName, 1543651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines SourceLocation LocLocked, 15442e5156274b8051217565b557bfa14c80f7990e9cRichard Smith SourceLocation LocEndOfScope, 1545651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines LockErrorKind LEK) override { 15464e4bc75d3570835e13183c66ac08974cdc016007Caitlin Sadowski unsigned DiagID = 0; 15474e4bc75d3570835e13183c66ac08974cdc016007Caitlin Sadowski switch (LEK) { 15484e4bc75d3570835e13183c66ac08974cdc016007Caitlin Sadowski case LEK_LockedSomePredecessors: 15492e5156274b8051217565b557bfa14c80f7990e9cRichard Smith DiagID = diag::warn_lock_some_predecessors; 15504e4bc75d3570835e13183c66ac08974cdc016007Caitlin Sadowski break; 15514e4bc75d3570835e13183c66ac08974cdc016007Caitlin Sadowski case LEK_LockedSomeLoopIterations: 15524e4bc75d3570835e13183c66ac08974cdc016007Caitlin Sadowski DiagID = diag::warn_expecting_lock_held_on_loop; 15534e4bc75d3570835e13183c66ac08974cdc016007Caitlin Sadowski break; 15544e4bc75d3570835e13183c66ac08974cdc016007Caitlin Sadowski case LEK_LockedAtEndOfFunction: 15554e4bc75d3570835e13183c66ac08974cdc016007Caitlin Sadowski DiagID = diag::warn_no_unlock; 15564e4bc75d3570835e13183c66ac08974cdc016007Caitlin Sadowski break; 1557879a4334e4c4cab0c22ba91492ffc2838bbc21fcDeLesley Hutchins case LEK_NotLockedAtEndOfFunction: 1558879a4334e4c4cab0c22ba91492ffc2838bbc21fcDeLesley Hutchins DiagID = diag::warn_expecting_locked; 1559879a4334e4c4cab0c22ba91492ffc2838bbc21fcDeLesley Hutchins break; 15604e4bc75d3570835e13183c66ac08974cdc016007Caitlin Sadowski } 15612e5156274b8051217565b557bfa14c80f7990e9cRichard Smith if (LocEndOfScope.isInvalid()) 15622e5156274b8051217565b557bfa14c80f7990e9cRichard Smith LocEndOfScope = FunEndLocation; 15632e5156274b8051217565b557bfa14c80f7990e9cRichard Smith 1564651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines PartialDiagnosticAt Warning(LocEndOfScope, S.PDiag(DiagID) << Kind 1565651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines << LockName); 15665696884053b4a60dbed01ea8c7e6cd8dcf9b5de9DeLesley Hutchins if (LocLocked.isValid()) { 1567651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines PartialDiagnosticAt Note(LocLocked, S.PDiag(diag::note_locked_here) 1568651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines << Kind); 1569176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines Warnings.push_back(DelayedDiag(Warning, getNotes(Note))); 15705696884053b4a60dbed01ea8c7e6cd8dcf9b5de9DeLesley Hutchins return; 15715696884053b4a60dbed01ea8c7e6cd8dcf9b5de9DeLesley Hutchins } 1572176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines Warnings.push_back(DelayedDiag(Warning, getNotes())); 157375f23aeb1c820b49f9faebed63b1cbef76c2c907Caitlin Sadowski } 157475f23aeb1c820b49f9faebed63b1cbef76c2c907Caitlin Sadowski 1575651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines void handleExclusiveAndShared(StringRef Kind, Name LockName, 1576651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines SourceLocation Loc1, 1577651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines SourceLocation Loc2) override { 1578651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines PartialDiagnosticAt Warning(Loc1, 1579651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines S.PDiag(diag::warn_lock_exclusive_and_shared) 1580651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines << Kind << LockName); 1581651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines PartialDiagnosticAt Note(Loc2, S.PDiag(diag::note_lock_exclusive_and_shared) 1582651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines << Kind << LockName); 1583176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines Warnings.push_back(DelayedDiag(Warning, getNotes(Note))); 158475f23aeb1c820b49f9faebed63b1cbef76c2c907Caitlin Sadowski } 158575f23aeb1c820b49f9faebed63b1cbef76c2c907Caitlin Sadowski 1586651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines void handleNoMutexHeld(StringRef Kind, const NamedDecl *D, 1587651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines ProtectedOperationKind POK, AccessKind AK, 1588651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines SourceLocation Loc) override { 1589651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines assert((POK == POK_VarAccess || POK == POK_VarDereference) && 1590651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines "Only works for variables"); 1591df8327c28d293cf7c6952b86dba26863235dcc0fCaitlin Sadowski unsigned DiagID = POK == POK_VarAccess? 1592df8327c28d293cf7c6952b86dba26863235dcc0fCaitlin Sadowski diag::warn_variable_requires_any_lock: 1593df8327c28d293cf7c6952b86dba26863235dcc0fCaitlin Sadowski diag::warn_var_deref_requires_any_lock; 15942e5156274b8051217565b557bfa14c80f7990e9cRichard Smith PartialDiagnosticAt Warning(Loc, S.PDiag(DiagID) 15955b280f28351bbdc103cc50d3b0f52f92d286fa0aDeLesley Hutchins << D->getNameAsString() << getLockKindFromAccessKind(AK)); 1596176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines Warnings.push_back(DelayedDiag(Warning, getNotes())); 159775f23aeb1c820b49f9faebed63b1cbef76c2c907Caitlin Sadowski } 159875f23aeb1c820b49f9faebed63b1cbef76c2c907Caitlin Sadowski 1599651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines void handleMutexNotHeld(StringRef Kind, const NamedDecl *D, 1600651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines ProtectedOperationKind POK, Name LockName, 1601651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines LockKind LK, SourceLocation Loc, 1602651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines Name *PossibleMatch) override { 1603e87158dfbca01577810f301543c3cdcfc955d8b0Caitlin Sadowski unsigned DiagID = 0; 16043f0ec5209726641782468bd4c7597e79dda78b15DeLesley Hutchins if (PossibleMatch) { 16053f0ec5209726641782468bd4c7597e79dda78b15DeLesley Hutchins switch (POK) { 16063f0ec5209726641782468bd4c7597e79dda78b15DeLesley Hutchins case POK_VarAccess: 16073f0ec5209726641782468bd4c7597e79dda78b15DeLesley Hutchins DiagID = diag::warn_variable_requires_lock_precise; 16083f0ec5209726641782468bd4c7597e79dda78b15DeLesley Hutchins break; 16093f0ec5209726641782468bd4c7597e79dda78b15DeLesley Hutchins case POK_VarDereference: 16103f0ec5209726641782468bd4c7597e79dda78b15DeLesley Hutchins DiagID = diag::warn_var_deref_requires_lock_precise; 16113f0ec5209726641782468bd4c7597e79dda78b15DeLesley Hutchins break; 16123f0ec5209726641782468bd4c7597e79dda78b15DeLesley Hutchins case POK_FunctionCall: 16133f0ec5209726641782468bd4c7597e79dda78b15DeLesley Hutchins DiagID = diag::warn_fun_requires_lock_precise; 16143f0ec5209726641782468bd4c7597e79dda78b15DeLesley Hutchins break; 1615176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines case POK_PassByRef: 1616176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines DiagID = diag::warn_guarded_pass_by_reference; 1617176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines break; 1618176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines case POK_PtPassByRef: 1619176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines DiagID = diag::warn_pt_guarded_pass_by_reference; 1620176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines break; 16213f0ec5209726641782468bd4c7597e79dda78b15DeLesley Hutchins } 1622651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines PartialDiagnosticAt Warning(Loc, S.PDiag(DiagID) << Kind 1623651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines << D->getNameAsString() 1624651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines << LockName << LK); 16253f0ec5209726641782468bd4c7597e79dda78b15DeLesley Hutchins PartialDiagnosticAt Note(Loc, S.PDiag(diag::note_found_mutex_near_match) 1626651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines << *PossibleMatch); 1627176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines if (Verbose && POK == POK_VarAccess) { 1628176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines PartialDiagnosticAt VNote(D->getLocation(), 1629176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines S.PDiag(diag::note_guarded_by_declared_here) 1630176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines << D->getNameAsString()); 1631176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines Warnings.push_back(DelayedDiag(Warning, getNotes(Note, VNote))); 1632176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines } else 1633176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines Warnings.push_back(DelayedDiag(Warning, getNotes(Note))); 16343f0ec5209726641782468bd4c7597e79dda78b15DeLesley Hutchins } else { 16353f0ec5209726641782468bd4c7597e79dda78b15DeLesley Hutchins switch (POK) { 16363f0ec5209726641782468bd4c7597e79dda78b15DeLesley Hutchins case POK_VarAccess: 16373f0ec5209726641782468bd4c7597e79dda78b15DeLesley Hutchins DiagID = diag::warn_variable_requires_lock; 16383f0ec5209726641782468bd4c7597e79dda78b15DeLesley Hutchins break; 16393f0ec5209726641782468bd4c7597e79dda78b15DeLesley Hutchins case POK_VarDereference: 16403f0ec5209726641782468bd4c7597e79dda78b15DeLesley Hutchins DiagID = diag::warn_var_deref_requires_lock; 16413f0ec5209726641782468bd4c7597e79dda78b15DeLesley Hutchins break; 16423f0ec5209726641782468bd4c7597e79dda78b15DeLesley Hutchins case POK_FunctionCall: 16433f0ec5209726641782468bd4c7597e79dda78b15DeLesley Hutchins DiagID = diag::warn_fun_requires_lock; 16443f0ec5209726641782468bd4c7597e79dda78b15DeLesley Hutchins break; 1645176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines case POK_PassByRef: 1646176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines DiagID = diag::warn_guarded_pass_by_reference; 1647176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines break; 1648176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines case POK_PtPassByRef: 1649176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines DiagID = diag::warn_pt_guarded_pass_by_reference; 1650176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines break; 16513f0ec5209726641782468bd4c7597e79dda78b15DeLesley Hutchins } 1652651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines PartialDiagnosticAt Warning(Loc, S.PDiag(DiagID) << Kind 1653651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines << D->getNameAsString() 1654651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines << LockName << LK); 1655176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines if (Verbose && POK == POK_VarAccess) { 1656176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines PartialDiagnosticAt Note(D->getLocation(), 1657176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines S.PDiag(diag::note_guarded_by_declared_here) 1658176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines << D->getNameAsString()); 1659176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines Warnings.push_back(DelayedDiag(Warning, getNotes(Note))); 1660176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines } else 1661176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines Warnings.push_back(DelayedDiag(Warning, getNotes())); 166275f23aeb1c820b49f9faebed63b1cbef76c2c907Caitlin Sadowski } 166375f23aeb1c820b49f9faebed63b1cbef76c2c907Caitlin Sadowski } 166475f23aeb1c820b49f9faebed63b1cbef76c2c907Caitlin Sadowski 166533337ca4d89605025818daf83390ab4271d598d9Pirama Arumuga Nainar void handleNegativeNotHeld(StringRef Kind, Name LockName, Name Neg, 166633337ca4d89605025818daf83390ab4271d598d9Pirama Arumuga Nainar SourceLocation Loc) override { 1667176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines PartialDiagnosticAt Warning(Loc, 1668176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines S.PDiag(diag::warn_acquire_requires_negative_cap) 1669176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines << Kind << LockName << Neg); 1670176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines Warnings.push_back(DelayedDiag(Warning, getNotes())); 1671176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines } 1672176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines 1673176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines 1674651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines void handleFunExcludesLock(StringRef Kind, Name FunName, Name LockName, 1675651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines SourceLocation Loc) override { 1676651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines PartialDiagnosticAt Warning(Loc, S.PDiag(diag::warn_fun_excludes_mutex) 1677651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines << Kind << FunName << LockName); 1678176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines Warnings.push_back(DelayedDiag(Warning, getNotes())); 1679176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines } 1680176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines 168133337ca4d89605025818daf83390ab4271d598d9Pirama Arumuga Nainar void handleLockAcquiredBefore(StringRef Kind, Name L1Name, Name L2Name, 168233337ca4d89605025818daf83390ab4271d598d9Pirama Arumuga Nainar SourceLocation Loc) override { 16830e2c34f92f00628d48968dfea096d36381f494cbStephen Hines PartialDiagnosticAt Warning(Loc, 16840e2c34f92f00628d48968dfea096d36381f494cbStephen Hines S.PDiag(diag::warn_acquired_before) << Kind << L1Name << L2Name); 16850e2c34f92f00628d48968dfea096d36381f494cbStephen Hines Warnings.push_back(DelayedDiag(Warning, getNotes())); 16860e2c34f92f00628d48968dfea096d36381f494cbStephen Hines } 16870e2c34f92f00628d48968dfea096d36381f494cbStephen Hines 168833337ca4d89605025818daf83390ab4271d598d9Pirama Arumuga Nainar void handleBeforeAfterCycle(Name L1Name, SourceLocation Loc) override { 16890e2c34f92f00628d48968dfea096d36381f494cbStephen Hines PartialDiagnosticAt Warning(Loc, 16900e2c34f92f00628d48968dfea096d36381f494cbStephen Hines S.PDiag(diag::warn_acquired_before_after_cycle) << L1Name); 16910e2c34f92f00628d48968dfea096d36381f494cbStephen Hines Warnings.push_back(DelayedDiag(Warning, getNotes())); 16920e2c34f92f00628d48968dfea096d36381f494cbStephen Hines } 16930e2c34f92f00628d48968dfea096d36381f494cbStephen Hines 1694176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines void enterFunction(const FunctionDecl* FD) override { 1695176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines CurrentFunction = FD; 1696176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines } 1697176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines 1698176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines void leaveFunction(const FunctionDecl* FD) override { 1699176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines CurrentFunction = 0; 170075f23aeb1c820b49f9faebed63b1cbef76c2c907Caitlin Sadowski } 170175f23aeb1c820b49f9faebed63b1cbef76c2c907Caitlin Sadowski}; 17023ea9e33ea25e0c2b12db56418ba3f994eb662c04Pirama Arumuga Nainar} // namespace 17033ea9e33ea25e0c2b12db56418ba3f994eb662c04Pirama Arumuga Nainar} // namespace threadSafety 17043ea9e33ea25e0c2b12db56418ba3f994eb662c04Pirama Arumuga Nainar} // namespace clang 170575f23aeb1c820b49f9faebed63b1cbef76c2c907Caitlin Sadowski 1706610068c8cd2321f90e147b12cf794e1f840b6405Ted Kremenek//===----------------------------------------------------------------------===// 1707df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins// -Wconsumed 1708df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins//===----------------------------------------------------------------------===// 1709df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins 1710df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchinsnamespace clang { 1711df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchinsnamespace consumed { 1712df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchinsnamespace { 1713df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchinsclass ConsumedWarningsHandler : public ConsumedWarningsHandlerBase { 1714df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins 1715df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins Sema &S; 1716df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins DiagList Warnings; 1717df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins 1718df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchinspublic: 17190e2c34f92f00628d48968dfea096d36381f494cbStephen Hines 1720df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins ConsumedWarningsHandler(Sema &S) : S(S) {} 1721651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines 1722651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines void emitDiagnostics() override { 1723df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins Warnings.sort(SortDiagBySourceLocation(S.getSourceManager())); 17246bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines for (const auto &Diag : Warnings) { 17256bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines S.Diag(Diag.first.first, Diag.first.second); 17266bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines for (const auto &Note : Diag.second) 17276bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines S.Diag(Note.first, Note.second); 1728df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins } 1729df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins } 1730651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines 1731651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines void warnLoopStateMismatch(SourceLocation Loc, 1732651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines StringRef VariableName) override { 17337385840b600d0e4a96d75042f612f6430e4a0390DeLesley Hutchins PartialDiagnosticAt Warning(Loc, S.PDiag(diag::warn_loop_state_mismatch) << 17347385840b600d0e4a96d75042f612f6430e4a0390DeLesley Hutchins VariableName); 17357385840b600d0e4a96d75042f612f6430e4a0390DeLesley Hutchins 17367385840b600d0e4a96d75042f612f6430e4a0390DeLesley Hutchins Warnings.push_back(DelayedDiag(Warning, OptionalNotes())); 17377385840b600d0e4a96d75042f612f6430e4a0390DeLesley Hutchins } 17387385840b600d0e4a96d75042f612f6430e4a0390DeLesley Hutchins 1739cd0f6d7600a691ad81dab308e9905fb0cce1df4dDeLesley Hutchins void warnParamReturnTypestateMismatch(SourceLocation Loc, 1740cd0f6d7600a691ad81dab308e9905fb0cce1df4dDeLesley Hutchins StringRef VariableName, 1741cd0f6d7600a691ad81dab308e9905fb0cce1df4dDeLesley Hutchins StringRef ExpectedState, 1742651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines StringRef ObservedState) override { 1743cd0f6d7600a691ad81dab308e9905fb0cce1df4dDeLesley Hutchins 1744cd0f6d7600a691ad81dab308e9905fb0cce1df4dDeLesley Hutchins PartialDiagnosticAt Warning(Loc, S.PDiag( 1745cd0f6d7600a691ad81dab308e9905fb0cce1df4dDeLesley Hutchins diag::warn_param_return_typestate_mismatch) << VariableName << 1746cd0f6d7600a691ad81dab308e9905fb0cce1df4dDeLesley Hutchins ExpectedState << ObservedState); 1747cd0f6d7600a691ad81dab308e9905fb0cce1df4dDeLesley Hutchins 1748cd0f6d7600a691ad81dab308e9905fb0cce1df4dDeLesley Hutchins Warnings.push_back(DelayedDiag(Warning, OptionalNotes())); 1749cd0f6d7600a691ad81dab308e9905fb0cce1df4dDeLesley Hutchins } 1750cd0f6d7600a691ad81dab308e9905fb0cce1df4dDeLesley Hutchins 1751d4f0e1991f42c69111213699fb2d09dedee1cd36DeLesley Hutchins void warnParamTypestateMismatch(SourceLocation Loc, StringRef ExpectedState, 1752651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines StringRef ObservedState) override { 1753d4f0e1991f42c69111213699fb2d09dedee1cd36DeLesley Hutchins 1754d4f0e1991f42c69111213699fb2d09dedee1cd36DeLesley Hutchins PartialDiagnosticAt Warning(Loc, S.PDiag( 1755d4f0e1991f42c69111213699fb2d09dedee1cd36DeLesley Hutchins diag::warn_param_typestate_mismatch) << ExpectedState << ObservedState); 1756d4f0e1991f42c69111213699fb2d09dedee1cd36DeLesley Hutchins 1757d4f0e1991f42c69111213699fb2d09dedee1cd36DeLesley Hutchins Warnings.push_back(DelayedDiag(Warning, OptionalNotes())); 1758d4f0e1991f42c69111213699fb2d09dedee1cd36DeLesley Hutchins } 1759d4f0e1991f42c69111213699fb2d09dedee1cd36DeLesley Hutchins 17600e8534efc3c536795ede0128aed86a6b8ad53ab7DeLesley Hutchins void warnReturnTypestateForUnconsumableType(SourceLocation Loc, 1761651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines StringRef TypeName) override { 17620e8534efc3c536795ede0128aed86a6b8ad53ab7DeLesley Hutchins PartialDiagnosticAt Warning(Loc, S.PDiag( 17630e8534efc3c536795ede0128aed86a6b8ad53ab7DeLesley Hutchins diag::warn_return_typestate_for_unconsumable_type) << TypeName); 17640e8534efc3c536795ede0128aed86a6b8ad53ab7DeLesley Hutchins 17650e8534efc3c536795ede0128aed86a6b8ad53ab7DeLesley Hutchins Warnings.push_back(DelayedDiag(Warning, OptionalNotes())); 17660e8534efc3c536795ede0128aed86a6b8ad53ab7DeLesley Hutchins } 17670e8534efc3c536795ede0128aed86a6b8ad53ab7DeLesley Hutchins 17680e8534efc3c536795ede0128aed86a6b8ad53ab7DeLesley Hutchins void warnReturnTypestateMismatch(SourceLocation Loc, StringRef ExpectedState, 1769651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines StringRef ObservedState) override { 17700e8534efc3c536795ede0128aed86a6b8ad53ab7DeLesley Hutchins 17710e8534efc3c536795ede0128aed86a6b8ad53ab7DeLesley Hutchins PartialDiagnosticAt Warning(Loc, S.PDiag( 17720e8534efc3c536795ede0128aed86a6b8ad53ab7DeLesley Hutchins diag::warn_return_typestate_mismatch) << ExpectedState << ObservedState); 17730e8534efc3c536795ede0128aed86a6b8ad53ab7DeLesley Hutchins 17740e8534efc3c536795ede0128aed86a6b8ad53ab7DeLesley Hutchins Warnings.push_back(DelayedDiag(Warning, OptionalNotes())); 17750e8534efc3c536795ede0128aed86a6b8ad53ab7DeLesley Hutchins } 17760e8534efc3c536795ede0128aed86a6b8ad53ab7DeLesley Hutchins 177766540857c08de7f1be9bea48381548d3942cf9d1DeLesley Hutchins void warnUseOfTempInInvalidState(StringRef MethodName, StringRef State, 1778651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines SourceLocation Loc) override { 1779df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins 1780df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins PartialDiagnosticAt Warning(Loc, S.PDiag( 178166540857c08de7f1be9bea48381548d3942cf9d1DeLesley Hutchins diag::warn_use_of_temp_in_invalid_state) << MethodName << State); 1782df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins 1783df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins Warnings.push_back(DelayedDiag(Warning, OptionalNotes())); 1784df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins } 1785df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins 178666540857c08de7f1be9bea48381548d3942cf9d1DeLesley Hutchins void warnUseInInvalidState(StringRef MethodName, StringRef VariableName, 1787651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines StringRef State, SourceLocation Loc) override { 1788df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins 178966540857c08de7f1be9bea48381548d3942cf9d1DeLesley Hutchins PartialDiagnosticAt Warning(Loc, S.PDiag(diag::warn_use_in_invalid_state) << 179066540857c08de7f1be9bea48381548d3942cf9d1DeLesley Hutchins MethodName << VariableName << State); 1791df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins 1792df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins Warnings.push_back(DelayedDiag(Warning, OptionalNotes())); 1793df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins } 1794df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins}; 1795df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins}}} 1796df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins 1797df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins//===----------------------------------------------------------------------===// 1798dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek// AnalysisBasedWarnings - Worker object used by Sema to execute analysis-based 1799dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek// warnings on a function, method, or block. 1800dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek//===----------------------------------------------------------------------===// 1801dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek 1802d064fdc4b7b64ca55b40b70490c79d6f569df78eTed Kremenekclang::sema::AnalysisBasedWarnings::Policy::Policy() { 1803dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek enableCheckFallThrough = 1; 1804d064fdc4b7b64ca55b40b70490c79d6f569df78eTed Kremenek enableCheckUnreachable = 0; 18053ac1fbc303d22af2e11a14023ecee7bd7b7d0bfdCaitlin Sadowski enableThreadSafetyAnalysis = 0; 1806df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins enableConsumedAnalysis = 0; 1807d064fdc4b7b64ca55b40b70490c79d6f569df78eTed Kremenek} 1808dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek 1809651f13cea278ec967336033dd032faef0e9fc2ecStephen Hinesstatic unsigned isEnabled(DiagnosticsEngine &D, unsigned diag) { 1810c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines return (unsigned)!D.isIgnored(diag, SourceLocation()); 1811651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines} 1812651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines 18135d98994c7749312a43ce6adf45537979a98e7afdChandler Carruthclang::sema::AnalysisBasedWarnings::AnalysisBasedWarnings(Sema &s) 18145d98994c7749312a43ce6adf45537979a98e7afdChandler Carruth : S(s), 18155d98994c7749312a43ce6adf45537979a98e7afdChandler Carruth NumFunctionsAnalyzed(0), 181654cf341bd4145e5e31f91c5777fcdaf3f2400537Benjamin Kramer NumFunctionsWithBadCFGs(0), 18175d98994c7749312a43ce6adf45537979a98e7afdChandler Carruth NumCFGBlocks(0), 181854cf341bd4145e5e31f91c5777fcdaf3f2400537Benjamin Kramer MaxCFGBlocksPerFunction(0), 181954cf341bd4145e5e31f91c5777fcdaf3f2400537Benjamin Kramer NumUninitAnalysisFunctions(0), 182054cf341bd4145e5e31f91c5777fcdaf3f2400537Benjamin Kramer NumUninitAnalysisVariables(0), 182154cf341bd4145e5e31f91c5777fcdaf3f2400537Benjamin Kramer MaxUninitAnalysisVariablesPerFunction(0), 182254cf341bd4145e5e31f91c5777fcdaf3f2400537Benjamin Kramer NumUninitAnalysisBlockVisits(0), 182354cf341bd4145e5e31f91c5777fcdaf3f2400537Benjamin Kramer MaxUninitAnalysisBlockVisitsPerFunction(0) { 1824651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines 1825651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines using namespace diag; 1826d6471f7c1921c7802804ce3ff6fe9768310f72b9David Blaikie DiagnosticsEngine &D = S.getDiagnostics(); 1827651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines 1828651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines DefaultPolicy.enableCheckUnreachable = 1829651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines isEnabled(D, warn_unreachable) || 1830651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines isEnabled(D, warn_unreachable_break) || 1831651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines isEnabled(D, warn_unreachable_return) || 1832651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines isEnabled(D, warn_unreachable_loop_increment); 1833651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines 1834651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines DefaultPolicy.enableThreadSafetyAnalysis = 1835651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines isEnabled(D, warn_double_lock); 1836651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines 1837651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines DefaultPolicy.enableConsumedAnalysis = 1838651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines isEnabled(D, warn_use_in_invalid_state); 1839dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek} 1840dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek 18416bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hinesstatic void flushDiagnostics(Sema &S, const sema::FunctionScopeInfo *fscope) { 18426bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines for (const auto &D : fscope->PossiblyUnreachableDiags) 1843351ba91eaa6d30e523587b2d7ed676a5172c6e56Ted Kremenek S.Diag(D.Loc, D.PD); 1844351ba91eaa6d30e523587b2d7ed676a5172c6e56Ted Kremenek} 1845351ba91eaa6d30e523587b2d7ed676a5172c6e56Ted Kremenek 1846d064fdc4b7b64ca55b40b70490c79d6f569df78eTed Kremenekvoid clang::sema:: 1847d064fdc4b7b64ca55b40b70490c79d6f569df78eTed KremenekAnalysisBasedWarnings::IssueWarnings(sema::AnalysisBasedWarnings::Policy P, 1848283a358aecb75e30fcd486f2206f6c03c5e7f11dTed Kremenek sema::FunctionScopeInfo *fscope, 18493ed6fc08a9cd293d012fa49ab2a615e618d7c3faTed Kremenek const Decl *D, const BlockExpr *blkExpr) { 1850d068aabc484c4009282122c6ef26e66e68cfa044Ted Kremenek 1851dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek // We avoid doing analysis-based warnings when there are errors for 1852dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek // two reasons: 1853dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek // (1) The CFGs often can't be constructed (if the body is invalid), so 1854dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek // don't bother trying. 1855dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek // (2) The code already has problems; running the analysis just takes more 1856dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek // time. 1857d6471f7c1921c7802804ce3ff6fe9768310f72b9David Blaikie DiagnosticsEngine &Diags = S.getDiagnostics(); 185899e8192c4c8f1f596f9969e5f2cdafcee64ddaacTed Kremenek 1859d064fdc4b7b64ca55b40b70490c79d6f569df78eTed Kremenek // Do not do any analysis for declarations in system headers if we are 1860d064fdc4b7b64ca55b40b70490c79d6f569df78eTed Kremenek // going to just ignore them. 186199e8192c4c8f1f596f9969e5f2cdafcee64ddaacTed Kremenek if (Diags.getSuppressSystemWarnings() && 1862d064fdc4b7b64ca55b40b70490c79d6f569df78eTed Kremenek S.SourceMgr.isInSystemHeader(D->getLocation())) 1863d064fdc4b7b64ca55b40b70490c79d6f569df78eTed Kremenek return; 1864d064fdc4b7b64ca55b40b70490c79d6f569df78eTed Kremenek 1865e0054f61fd84133eb0d19c19ae9afaf117933274John McCall // For code in dependent contexts, we'll do this at instantiation time. 186623661d3e348c5f44ae89b6848bbc331829bb46f2David Blaikie if (cast<DeclContext>(D)->isDependentContext()) 186723661d3e348c5f44ae89b6848bbc331829bb46f2David Blaikie return; 1868dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek 186912f37e411462b8388eb1309357bd62257debacacDeLesley Hutchins if (Diags.hasUncompilableErrorOccurred() || Diags.hasFatalErrorOccurred()) { 1870351ba91eaa6d30e523587b2d7ed676a5172c6e56Ted Kremenek // Flush out any possibly unreachable diagnostics. 1871351ba91eaa6d30e523587b2d7ed676a5172c6e56Ted Kremenek flushDiagnostics(S, fscope); 1872351ba91eaa6d30e523587b2d7ed676a5172c6e56Ted Kremenek return; 1873351ba91eaa6d30e523587b2d7ed676a5172c6e56Ted Kremenek } 1874351ba91eaa6d30e523587b2d7ed676a5172c6e56Ted Kremenek 1875dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek const Stmt *Body = D->getBody(); 1876dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek assert(Body); 1877dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek 18780cd72319e74899c4e5561cc70b7c4939d3767bd9Ted Kremenek // Construct the analysis context with the specified CFG build options. 18796bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines AnalysisDeclContext AC(/* AnalysisDeclContextManager */ nullptr, D); 1880bc5cb8a5fe2b88f917d47ceb58b53696a121e57eTed Kremenek 1881dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek // Don't generate EH edges for CallExprs as we'd like to avoid the n^2 1882e575359c34a9248c55ec0c03a8fc945f1ee4cb01Benjamin Kramer // explosion for destructors that can result and the compile time hit. 1883bc5cb8a5fe2b88f917d47ceb58b53696a121e57eTed Kremenek AC.getCFGBuildOptions().PruneTriviallyFalseEdges = true; 1884bc5cb8a5fe2b88f917d47ceb58b53696a121e57eTed Kremenek AC.getCFGBuildOptions().AddEHEdges = false; 1885bc5cb8a5fe2b88f917d47ceb58b53696a121e57eTed Kremenek AC.getCFGBuildOptions().AddInitializers = true; 1886bc5cb8a5fe2b88f917d47ceb58b53696a121e57eTed Kremenek AC.getCFGBuildOptions().AddImplicitDtors = true; 1887faadf48443f8c2fc53d267485d7e0e1bd382fc75Jordan Rose AC.getCFGBuildOptions().AddTemporaryDtors = true; 1888651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines AC.getCFGBuildOptions().AddCXXNewAllocator = false; 1889faadf48443f8c2fc53d267485d7e0e1bd382fc75Jordan Rose 18900c8e5a0f70cbdb800d939c1807d05f380b2854d4Ted Kremenek // Force that certain expressions appear as CFGElements in the CFG. This 18910c8e5a0f70cbdb800d939c1807d05f380b2854d4Ted Kremenek // is used to speed up various analyses. 18920c8e5a0f70cbdb800d939c1807d05f380b2854d4Ted Kremenek // FIXME: This isn't the right factoring. This is here for initial 18930c8e5a0f70cbdb800d939c1807d05f380b2854d4Ted Kremenek // prototyping, but we need a way for analyses to say what expressions they 18940c8e5a0f70cbdb800d939c1807d05f380b2854d4Ted Kremenek // expect to always be CFGElements and then fill in the BuildOptions 18950c8e5a0f70cbdb800d939c1807d05f380b2854d4Ted Kremenek // appropriately. This is essentially a layering violation. 1896df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins if (P.enableCheckUnreachable || P.enableThreadSafetyAnalysis || 1897df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins P.enableConsumedAnalysis) { 18981fa3c0682a52c45c4ad0be3a82d0c85f26657072DeLesley Hutchins // Unreachable code analysis and thread safety require a linearized CFG. 18990f3b4ca1764cd6d457f511d340fba504f41763c3Ted Kremenek AC.getCFGBuildOptions().setAllAlwaysAdd(); 19000f3b4ca1764cd6d457f511d340fba504f41763c3Ted Kremenek } 19010f3b4ca1764cd6d457f511d340fba504f41763c3Ted Kremenek else { 19020f3b4ca1764cd6d457f511d340fba504f41763c3Ted Kremenek AC.getCFGBuildOptions() 19030f3b4ca1764cd6d457f511d340fba504f41763c3Ted Kremenek .setAlwaysAdd(Stmt::BinaryOperatorClass) 19046cfa78f6bd4e7d5e23366a0907f8f8792366bc4cRichard Smith .setAlwaysAdd(Stmt::CompoundAssignOperatorClass) 19050f3b4ca1764cd6d457f511d340fba504f41763c3Ted Kremenek .setAlwaysAdd(Stmt::BlockExprClass) 19060f3b4ca1764cd6d457f511d340fba504f41763c3Ted Kremenek .setAlwaysAdd(Stmt::CStyleCastExprClass) 19070f3b4ca1764cd6d457f511d340fba504f41763c3Ted Kremenek .setAlwaysAdd(Stmt::DeclRefExprClass) 19080f3b4ca1764cd6d457f511d340fba504f41763c3Ted Kremenek .setAlwaysAdd(Stmt::ImplicitCastExprClass) 1909e0d3b4cd2b66f1cef26cacbed5820ab7c22ad5b3Richard Smith .setAlwaysAdd(Stmt::UnaryOperatorClass) 1910e0d3b4cd2b66f1cef26cacbed5820ab7c22ad5b3Richard Smith .setAlwaysAdd(Stmt::AttributedStmtClass); 19110f3b4ca1764cd6d457f511d340fba504f41763c3Ted Kremenek } 1912bc5cb8a5fe2b88f917d47ceb58b53696a121e57eTed Kremenek 19136bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines // Install the logical handler for -Wtautological-overlap-compare 19146bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines std::unique_ptr<LogicalErrorHandler> LEH; 1915c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines if (!Diags.isIgnored(diag::warn_tautological_overlap_comparison, 1916c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines D->getLocStart())) { 19176bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines LEH.reset(new LogicalErrorHandler(S)); 19186bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines AC.getCFGBuildOptions().Observer = LEH.get(); 19196bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines } 19200cd72319e74899c4e5561cc70b7c4939d3767bd9Ted Kremenek 1921351ba91eaa6d30e523587b2d7ed676a5172c6e56Ted Kremenek // Emit delayed diagnostics. 192223661d3e348c5f44ae89b6848bbc331829bb46f2David Blaikie if (!fscope->PossiblyUnreachableDiags.empty()) { 1923351ba91eaa6d30e523587b2d7ed676a5172c6e56Ted Kremenek bool analyzed = false; 19240d28d360b5559abda755e50b855ba5e59727d9cdTed Kremenek 19250d28d360b5559abda755e50b855ba5e59727d9cdTed Kremenek // Register the expressions with the CFGBuilder. 19266bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines for (const auto &D : fscope->PossiblyUnreachableDiags) { 19276bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines if (D.stmt) 19286bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines AC.registerForcedBlockExpression(D.stmt); 19290d28d360b5559abda755e50b855ba5e59727d9cdTed Kremenek } 19300d28d360b5559abda755e50b855ba5e59727d9cdTed Kremenek 19310d28d360b5559abda755e50b855ba5e59727d9cdTed Kremenek if (AC.getCFG()) { 19320d28d360b5559abda755e50b855ba5e59727d9cdTed Kremenek analyzed = true; 19336bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines for (const auto &D : fscope->PossiblyUnreachableDiags) { 19340d28d360b5559abda755e50b855ba5e59727d9cdTed Kremenek bool processed = false; 19356bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines if (D.stmt) { 19366bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines const CFGBlock *block = AC.getBlockForRegisteredExpression(D.stmt); 193771b8fb5d4233420d2ed2f150a54ea61431bd8684Eli Friedman CFGReverseBlockReachabilityAnalysis *cra = 193871b8fb5d4233420d2ed2f150a54ea61431bd8684Eli Friedman AC.getCFGReachablityAnalysis(); 193971b8fb5d4233420d2ed2f150a54ea61431bd8684Eli Friedman // FIXME: We should be able to assert that block is non-null, but 194071b8fb5d4233420d2ed2f150a54ea61431bd8684Eli Friedman // the CFG analysis can skip potentially-evaluated expressions in 194171b8fb5d4233420d2ed2f150a54ea61431bd8684Eli Friedman // edge cases; see test/Sema/vla-2.c. 194271b8fb5d4233420d2ed2f150a54ea61431bd8684Eli Friedman if (block && cra) { 1943351ba91eaa6d30e523587b2d7ed676a5172c6e56Ted Kremenek // Can this block be reached from the entrance? 19440d28d360b5559abda755e50b855ba5e59727d9cdTed Kremenek if (cra->isReachable(&AC.getCFG()->getEntry(), block)) 1945351ba91eaa6d30e523587b2d7ed676a5172c6e56Ted Kremenek S.Diag(D.Loc, D.PD); 19460d28d360b5559abda755e50b855ba5e59727d9cdTed Kremenek processed = true; 1947351ba91eaa6d30e523587b2d7ed676a5172c6e56Ted Kremenek } 19480d28d360b5559abda755e50b855ba5e59727d9cdTed Kremenek } 19490d28d360b5559abda755e50b855ba5e59727d9cdTed Kremenek if (!processed) { 19500d28d360b5559abda755e50b855ba5e59727d9cdTed Kremenek // Emit the warning anyway if we cannot map to a basic block. 19510d28d360b5559abda755e50b855ba5e59727d9cdTed Kremenek S.Diag(D.Loc, D.PD); 1952351ba91eaa6d30e523587b2d7ed676a5172c6e56Ted Kremenek } 1953351ba91eaa6d30e523587b2d7ed676a5172c6e56Ted Kremenek } 19540d28d360b5559abda755e50b855ba5e59727d9cdTed Kremenek } 1955351ba91eaa6d30e523587b2d7ed676a5172c6e56Ted Kremenek 1956351ba91eaa6d30e523587b2d7ed676a5172c6e56Ted Kremenek if (!analyzed) 1957351ba91eaa6d30e523587b2d7ed676a5172c6e56Ted Kremenek flushDiagnostics(S, fscope); 1958351ba91eaa6d30e523587b2d7ed676a5172c6e56Ted Kremenek } 1959351ba91eaa6d30e523587b2d7ed676a5172c6e56Ted Kremenek 1960351ba91eaa6d30e523587b2d7ed676a5172c6e56Ted Kremenek 1961dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek // Warning: check missing 'return' 196223661d3e348c5f44ae89b6848bbc331829bb46f2David Blaikie if (P.enableCheckFallThrough) { 1963dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek const CheckFallThroughDiagnostics &CD = 1964dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek (isa<BlockDecl>(D) ? CheckFallThroughDiagnostics::MakeForBlock() 1965793cd1c4cdfaafc52e2c2ad9dae959befe4bb166Douglas Gregor : (isa<CXXMethodDecl>(D) && 1966793cd1c4cdfaafc52e2c2ad9dae959befe4bb166Douglas Gregor cast<CXXMethodDecl>(D)->getOverloadedOperator() == OO_Call && 1967793cd1c4cdfaafc52e2c2ad9dae959befe4bb166Douglas Gregor cast<CXXMethodDecl>(D)->getParent()->isLambda()) 1968793cd1c4cdfaafc52e2c2ad9dae959befe4bb166Douglas Gregor ? CheckFallThroughDiagnostics::MakeForLambda() 1969793cd1c4cdfaafc52e2c2ad9dae959befe4bb166Douglas Gregor : CheckFallThroughDiagnostics::MakeForFunction(D)); 19703ed6fc08a9cd293d012fa49ab2a615e618d7c3faTed Kremenek CheckFallThroughForBody(S, D, Body, blkExpr, CD, AC); 1971dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek } 1972dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek 1973dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek // Warning: check for unreachable code 19745dfee06daa359bbe0f3c9de055b8a02d61a05173Ted Kremenek if (P.enableCheckUnreachable) { 19755dfee06daa359bbe0f3c9de055b8a02d61a05173Ted Kremenek // Only check for unreachable code on non-template instantiations. 19765dfee06daa359bbe0f3c9de055b8a02d61a05173Ted Kremenek // Different template instantiations can effectively change the control-flow 19775dfee06daa359bbe0f3c9de055b8a02d61a05173Ted Kremenek // and it is very difficult to prove that a snippet of code in a template 19785dfee06daa359bbe0f3c9de055b8a02d61a05173Ted Kremenek // is unreachable for all instantiations. 197975df4eeede7b91c22c1d63fafd4dd4142844e3b9Ted Kremenek bool isTemplateInstantiation = false; 198075df4eeede7b91c22c1d63fafd4dd4142844e3b9Ted Kremenek if (const FunctionDecl *Function = dyn_cast<FunctionDecl>(D)) 198175df4eeede7b91c22c1d63fafd4dd4142844e3b9Ted Kremenek isTemplateInstantiation = Function->isTemplateInstantiation(); 198275df4eeede7b91c22c1d63fafd4dd4142844e3b9Ted Kremenek if (!isTemplateInstantiation) 19835dfee06daa359bbe0f3c9de055b8a02d61a05173Ted Kremenek CheckUnreachable(S, AC); 19845dfee06daa359bbe0f3c9de055b8a02d61a05173Ted Kremenek } 198575f23aeb1c820b49f9faebed63b1cbef76c2c907Caitlin Sadowski 19863ac1fbc303d22af2e11a14023ecee7bd7b7d0bfdCaitlin Sadowski // Check for thread safety violations 198723661d3e348c5f44ae89b6848bbc331829bb46f2David Blaikie if (P.enableThreadSafetyAnalysis) { 1988f1ac63702143d84db778d32eb185a77fc97db5f5DeLesley Hutchins SourceLocation FL = AC.getDecl()->getLocation(); 19892e5156274b8051217565b557bfa14c80f7990e9cRichard Smith SourceLocation FEL = AC.getDecl()->getLocEnd(); 1990176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines threadSafety::ThreadSafetyReporter Reporter(S, FL, FEL); 1991c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines if (!Diags.isIgnored(diag::warn_thread_safety_beta, D->getLocStart())) 1992fb4afc2fc659faff43a6df4c1d0e07df9c90479dDeLesley Hutchins Reporter.setIssueBetaWarnings(true); 1993176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines if (!Diags.isIgnored(diag::warn_thread_safety_verbose, D->getLocStart())) 1994176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines Reporter.setVerbose(true); 1995fb4afc2fc659faff43a6df4c1d0e07df9c90479dDeLesley Hutchins 19960e2c34f92f00628d48968dfea096d36381f494cbStephen Hines threadSafety::runThreadSafetyAnalysis(AC, Reporter, 19970e2c34f92f00628d48968dfea096d36381f494cbStephen Hines &S.ThreadSafetyDeclCache); 199875f23aeb1c820b49f9faebed63b1cbef76c2c907Caitlin Sadowski Reporter.emitDiagnostics(); 199975f23aeb1c820b49f9faebed63b1cbef76c2c907Caitlin Sadowski } 20003ac1fbc303d22af2e11a14023ecee7bd7b7d0bfdCaitlin Sadowski 2001df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins // Check for violations of consumed properties. 2002df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins if (P.enableConsumedAnalysis) { 2003df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins consumed::ConsumedWarningsHandler WarningHandler(S); 20042d84f6b563e39c1e90e4d3d7e6846d46bc58ff5dReid Kleckner consumed::ConsumedAnalyzer Analyzer(WarningHandler); 2005df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins Analyzer.run(AC); 2006df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins } 2007df7bef07eebd5c7913e8be09c62a6a470f255fd2DeLesley Hutchins 2008c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines if (!Diags.isIgnored(diag::warn_uninit_var, D->getLocStart()) || 2009c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines !Diags.isIgnored(diag::warn_sometimes_uninit_var, D->getLocStart()) || 2010c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines !Diags.isIgnored(diag::warn_maybe_uninit_var, D->getLocStart())) { 2011c5e43c19ddb40b8a1371291f73ae66fe54951ca5Ted Kremenek if (CFG *cfg = AC.getCFG()) { 2012c21fed361c11f13db345cba69101578578d8fb79Ted Kremenek UninitValsDiagReporter reporter(S); 201357080fbac1ccce702255423335d52e81bcf17b6bFariborz Jahanian UninitVariablesAnalysisStats stats; 201412efd57ee474c06880a7434ece21a39ac3f34e24Benjamin Kramer std::memset(&stats, 0, sizeof(UninitVariablesAnalysisStats)); 2015a8c17a5babab35f2db26bf218e7571d1af4afedfTed Kremenek runUninitializedVariablesAnalysis(*cast<DeclContext>(D), *cfg, AC, 20165d98994c7749312a43ce6adf45537979a98e7afdChandler Carruth reporter, stats); 20175d98994c7749312a43ce6adf45537979a98e7afdChandler Carruth 20185d98994c7749312a43ce6adf45537979a98e7afdChandler Carruth if (S.CollectStats && stats.NumVariablesAnalyzed > 0) { 20195d98994c7749312a43ce6adf45537979a98e7afdChandler Carruth ++NumUninitAnalysisFunctions; 20205d98994c7749312a43ce6adf45537979a98e7afdChandler Carruth NumUninitAnalysisVariables += stats.NumVariablesAnalyzed; 20215d98994c7749312a43ce6adf45537979a98e7afdChandler Carruth NumUninitAnalysisBlockVisits += stats.NumBlockVisits; 20225d98994c7749312a43ce6adf45537979a98e7afdChandler Carruth MaxUninitAnalysisVariablesPerFunction = 20235d98994c7749312a43ce6adf45537979a98e7afdChandler Carruth std::max(MaxUninitAnalysisVariablesPerFunction, 20245d98994c7749312a43ce6adf45537979a98e7afdChandler Carruth stats.NumVariablesAnalyzed); 20255d98994c7749312a43ce6adf45537979a98e7afdChandler Carruth MaxUninitAnalysisBlockVisitsPerFunction = 20265d98994c7749312a43ce6adf45537979a98e7afdChandler Carruth std::max(MaxUninitAnalysisBlockVisitsPerFunction, 20275d98994c7749312a43ce6adf45537979a98e7afdChandler Carruth stats.NumBlockVisits); 20285d98994c7749312a43ce6adf45537979a98e7afdChandler Carruth } 20295d98994c7749312a43ce6adf45537979a98e7afdChandler Carruth } 20305d98994c7749312a43ce6adf45537979a98e7afdChandler Carruth } 20315d98994c7749312a43ce6adf45537979a98e7afdChandler Carruth 20321973634e445d4f1abdeedc2809f2d281929253b6Alexander Kornienko bool FallThroughDiagFull = 2033c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines !Diags.isIgnored(diag::warn_unannotated_fallthrough, D->getLocStart()); 2034c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines bool FallThroughDiagPerFunction = !Diags.isIgnored( 2035c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines diag::warn_unannotated_fallthrough_per_function, D->getLocStart()); 2036c2f51cfefd77e9b25f201ecf879343d6d9a45158Sean Hunt if (FallThroughDiagFull || FallThroughDiagPerFunction) { 20371973634e445d4f1abdeedc2809f2d281929253b6Alexander Kornienko DiagnoseSwitchLabelsFallthrough(S, AC, !FallThroughDiagFull); 2038e0d3b4cd2b66f1cef26cacbed5820ab7c22ad5b3Richard Smith } 2039e0d3b4cd2b66f1cef26cacbed5820ab7c22ad5b3Richard Smith 204058b6bdcdeb683a3504f2248a409e1f4e85876ceeJordan Rose if (S.getLangOpts().ObjCARCWeak && 2041c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines !Diags.isIgnored(diag::warn_arc_repeated_use_of_weak, D->getLocStart())) 2042b5cd1220dd650a358622241237aa595c5d675506Jordan Rose diagnoseRepeatedUseOfWeak(S, fscope, D, AC.getParentMap()); 204358b6bdcdeb683a3504f2248a409e1f4e85876ceeJordan Rose 2044651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines 2045651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines // Check for infinite self-recursion in functions 2046c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines if (!Diags.isIgnored(diag::warn_infinite_recursive_function, 2047c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines D->getLocStart())) { 2048651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(D)) { 2049651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines checkRecursiveFunction(S, FD, Body, AC); 2050651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines } 2051651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines } 2052651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines 20536bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines // If none of the previous checks caused a CFG build, trigger one here 20546bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines // for -Wtautological-overlap-compare 2055c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines if (!Diags.isIgnored(diag::warn_tautological_overlap_comparison, 20566bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines D->getLocStart())) { 20576bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines AC.getCFG(); 20586bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines } 20596bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines 20605d98994c7749312a43ce6adf45537979a98e7afdChandler Carruth // Collect statistics about the CFG if it was built. 20615d98994c7749312a43ce6adf45537979a98e7afdChandler Carruth if (S.CollectStats && AC.isCFGBuilt()) { 20625d98994c7749312a43ce6adf45537979a98e7afdChandler Carruth ++NumFunctionsAnalyzed; 20635d98994c7749312a43ce6adf45537979a98e7afdChandler Carruth if (CFG *cfg = AC.getCFG()) { 20645d98994c7749312a43ce6adf45537979a98e7afdChandler Carruth // If we successfully built a CFG for this context, record some more 20655d98994c7749312a43ce6adf45537979a98e7afdChandler Carruth // detail information about it. 20663ea4c49709c5bba5f8b16c6ceb725d9b9a1c48c6Chandler Carruth NumCFGBlocks += cfg->getNumBlockIDs(); 20675d98994c7749312a43ce6adf45537979a98e7afdChandler Carruth MaxCFGBlocksPerFunction = std::max(MaxCFGBlocksPerFunction, 20683ea4c49709c5bba5f8b16c6ceb725d9b9a1c48c6Chandler Carruth cfg->getNumBlockIDs()); 20695d98994c7749312a43ce6adf45537979a98e7afdChandler Carruth } else { 20705d98994c7749312a43ce6adf45537979a98e7afdChandler Carruth ++NumFunctionsWithBadCFGs; 2071610068c8cd2321f90e147b12cf794e1f840b6405Ted Kremenek } 2072610068c8cd2321f90e147b12cf794e1f840b6405Ted Kremenek } 2073dbdbaaf34f798fa5cabec273c4b9397b3fd6a98cTed Kremenek} 20745d98994c7749312a43ce6adf45537979a98e7afdChandler Carruth 20755d98994c7749312a43ce6adf45537979a98e7afdChandler Carruthvoid clang::sema::AnalysisBasedWarnings::PrintStats() const { 20765d98994c7749312a43ce6adf45537979a98e7afdChandler Carruth llvm::errs() << "\n*** Analysis Based Warnings Stats:\n"; 20775d98994c7749312a43ce6adf45537979a98e7afdChandler Carruth 20785d98994c7749312a43ce6adf45537979a98e7afdChandler Carruth unsigned NumCFGsBuilt = NumFunctionsAnalyzed - NumFunctionsWithBadCFGs; 20795d98994c7749312a43ce6adf45537979a98e7afdChandler Carruth unsigned AvgCFGBlocksPerFunction = 20805d98994c7749312a43ce6adf45537979a98e7afdChandler Carruth !NumCFGsBuilt ? 0 : NumCFGBlocks/NumCFGsBuilt; 20815d98994c7749312a43ce6adf45537979a98e7afdChandler Carruth llvm::errs() << NumFunctionsAnalyzed << " functions analyzed (" 20825d98994c7749312a43ce6adf45537979a98e7afdChandler Carruth << NumFunctionsWithBadCFGs << " w/o CFGs).\n" 20835d98994c7749312a43ce6adf45537979a98e7afdChandler Carruth << " " << NumCFGBlocks << " CFG blocks built.\n" 20845d98994c7749312a43ce6adf45537979a98e7afdChandler Carruth << " " << AvgCFGBlocksPerFunction 20855d98994c7749312a43ce6adf45537979a98e7afdChandler Carruth << " average CFG blocks per function.\n" 20865d98994c7749312a43ce6adf45537979a98e7afdChandler Carruth << " " << MaxCFGBlocksPerFunction 20875d98994c7749312a43ce6adf45537979a98e7afdChandler Carruth << " max CFG blocks per function.\n"; 20885d98994c7749312a43ce6adf45537979a98e7afdChandler Carruth 20895d98994c7749312a43ce6adf45537979a98e7afdChandler Carruth unsigned AvgUninitVariablesPerFunction = !NumUninitAnalysisFunctions ? 0 20905d98994c7749312a43ce6adf45537979a98e7afdChandler Carruth : NumUninitAnalysisVariables/NumUninitAnalysisFunctions; 20915d98994c7749312a43ce6adf45537979a98e7afdChandler Carruth unsigned AvgUninitBlockVisitsPerFunction = !NumUninitAnalysisFunctions ? 0 20925d98994c7749312a43ce6adf45537979a98e7afdChandler Carruth : NumUninitAnalysisBlockVisits/NumUninitAnalysisFunctions; 20935d98994c7749312a43ce6adf45537979a98e7afdChandler Carruth llvm::errs() << NumUninitAnalysisFunctions 20945d98994c7749312a43ce6adf45537979a98e7afdChandler Carruth << " functions analyzed for uninitialiazed variables\n" 20955d98994c7749312a43ce6adf45537979a98e7afdChandler Carruth << " " << NumUninitAnalysisVariables << " variables analyzed.\n" 20965d98994c7749312a43ce6adf45537979a98e7afdChandler Carruth << " " << AvgUninitVariablesPerFunction 20975d98994c7749312a43ce6adf45537979a98e7afdChandler Carruth << " average variables per function.\n" 20985d98994c7749312a43ce6adf45537979a98e7afdChandler Carruth << " " << MaxUninitAnalysisVariablesPerFunction 20995d98994c7749312a43ce6adf45537979a98e7afdChandler Carruth << " max variables per function.\n" 21005d98994c7749312a43ce6adf45537979a98e7afdChandler Carruth << " " << NumUninitAnalysisBlockVisits << " block visits.\n" 21015d98994c7749312a43ce6adf45537979a98e7afdChandler Carruth << " " << AvgUninitBlockVisitsPerFunction 21025d98994c7749312a43ce6adf45537979a98e7afdChandler Carruth << " average block visits per function.\n" 21035d98994c7749312a43ce6adf45537979a98e7afdChandler Carruth << " " << MaxUninitAnalysisBlockVisitsPerFunction 21045d98994c7749312a43ce6adf45537979a98e7afdChandler Carruth << " max block visits per function.\n"; 21055d98994c7749312a43ce6adf45537979a98e7afdChandler Carruth} 2106