AnalysisBasedWarnings.cpp revision 296417
1205408Srdivacky//=- AnalysisBasedWarnings.cpp - Sema warnings based on libAnalysis -*- C++ -*-=// 2205408Srdivacky// 3205408Srdivacky// The LLVM Compiler Infrastructure 4205408Srdivacky// 5205408Srdivacky// This file is distributed under the University of Illinois Open Source 6205408Srdivacky// License. See LICENSE.TXT for details. 7205408Srdivacky// 8205408Srdivacky//===----------------------------------------------------------------------===// 9205408Srdivacky// 10205408Srdivacky// This file defines analysis_warnings::[Policy,Executor]. 11205408Srdivacky// Together they are used by Sema to issue warnings based on inexpensive 12205408Srdivacky// static analysis algorithms in libAnalysis. 13205408Srdivacky// 14205408Srdivacky//===----------------------------------------------------------------------===// 15205408Srdivacky 16212904Sdim#include "clang/Sema/AnalysisBasedWarnings.h" 17249423Sdim#include "clang/AST/DeclCXX.h" 18212904Sdim#include "clang/AST/DeclObjC.h" 19249423Sdim#include "clang/AST/EvaluatedExprVisitor.h" 20249423Sdim#include "clang/AST/ExprCXX.h" 21205408Srdivacky#include "clang/AST/ExprObjC.h" 22249423Sdim#include "clang/AST/ParentMap.h" 23249423Sdim#include "clang/AST/RecursiveASTVisitor.h" 24249423Sdim#include "clang/AST/StmtCXX.h" 25205408Srdivacky#include "clang/AST/StmtObjC.h" 26226633Sdim#include "clang/AST/StmtVisitor.h" 27249423Sdim#include "clang/Analysis/Analyses/CFGReachabilityAnalysis.h" 28261991Sdim#include "clang/Analysis/Analyses/Consumed.h" 29249423Sdim#include "clang/Analysis/Analyses/ReachableCode.h" 30249423Sdim#include "clang/Analysis/Analyses/ThreadSafety.h" 31249423Sdim#include "clang/Analysis/Analyses/UninitializedValues.h" 32205408Srdivacky#include "clang/Analysis/AnalysisContext.h" 33205408Srdivacky#include "clang/Analysis/CFG.h" 34219077Sdim#include "clang/Analysis/CFGStmtMap.h" 35249423Sdim#include "clang/Basic/SourceLocation.h" 36249423Sdim#include "clang/Basic/SourceManager.h" 37249423Sdim#include "clang/Lex/Preprocessor.h" 38249423Sdim#include "clang/Sema/ScopeInfo.h" 39249423Sdim#include "clang/Sema/SemaInternal.h" 40243830Sdim#include "llvm/ADT/ArrayRef.h" 41205408Srdivacky#include "llvm/ADT/BitVector.h" 42226633Sdim#include "llvm/ADT/FoldingSet.h" 43226633Sdim#include "llvm/ADT/ImmutableMap.h" 44249423Sdim#include "llvm/ADT/MapVector.h" 45226633Sdim#include "llvm/ADT/PostOrderIterator.h" 46243830Sdim#include "llvm/ADT/SmallString.h" 47226633Sdim#include "llvm/ADT/SmallVector.h" 48226633Sdim#include "llvm/ADT/StringRef.h" 49205408Srdivacky#include "llvm/Support/Casting.h" 50226633Sdim#include <algorithm> 51249423Sdim#include <deque> 52239462Sdim#include <iterator> 53226633Sdim#include <vector> 54205408Srdivacky 55205408Srdivackyusing namespace clang; 56205408Srdivacky 57205408Srdivacky//===----------------------------------------------------------------------===// 58205408Srdivacky// Unreachable code analysis. 59205408Srdivacky//===----------------------------------------------------------------------===// 60205408Srdivacky 61205408Srdivackynamespace { 62205408Srdivacky class UnreachableCodeHandler : public reachable_code::Callback { 63205408Srdivacky Sema &S; 64205408Srdivacky public: 65205408Srdivacky UnreachableCodeHandler(Sema &s) : S(s) {} 66205408Srdivacky 67276479Sdim void HandleUnreachable(reachable_code::UnreachableKind UK, 68276479Sdim SourceLocation L, 69276479Sdim SourceRange SilenceableCondVal, 70276479Sdim SourceRange R1, 71276479Sdim SourceRange R2) override { 72276479Sdim unsigned diag = diag::warn_unreachable; 73276479Sdim switch (UK) { 74276479Sdim case reachable_code::UK_Break: 75276479Sdim diag = diag::warn_unreachable_break; 76276479Sdim break; 77276479Sdim case reachable_code::UK_Return: 78276479Sdim diag = diag::warn_unreachable_return; 79276479Sdim break; 80276479Sdim case reachable_code::UK_Loop_Increment: 81276479Sdim diag = diag::warn_unreachable_loop_increment; 82276479Sdim break; 83276479Sdim case reachable_code::UK_Other: 84276479Sdim break; 85276479Sdim } 86276479Sdim 87276479Sdim S.Diag(L, diag) << R1 << R2; 88276479Sdim 89276479Sdim SourceLocation Open = SilenceableCondVal.getBegin(); 90276479Sdim if (Open.isValid()) { 91276479Sdim SourceLocation Close = SilenceableCondVal.getEnd(); 92276479Sdim Close = S.getLocForEndOfToken(Close); 93276479Sdim if (Close.isValid()) { 94276479Sdim S.Diag(Open, diag::note_unreachable_silence) 95276479Sdim << FixItHint::CreateInsertion(Open, "/* DISABLES CODE */ (") 96276479Sdim << FixItHint::CreateInsertion(Close, ")"); 97276479Sdim } 98276479Sdim } 99205408Srdivacky } 100205408Srdivacky }; 101296417Sdim} // anonymous namespace 102205408Srdivacky 103205408Srdivacky/// CheckUnreachable - Check for unreachable code. 104234353Sdimstatic void CheckUnreachable(Sema &S, AnalysisDeclContext &AC) { 105276479Sdim // As a heuristic prune all diagnostics not in the main file. Currently 106276479Sdim // the majority of warnings in headers are false positives. These 107276479Sdim // are largely caused by configuration state, e.g. preprocessor 108276479Sdim // defined code, etc. 109276479Sdim // 110276479Sdim // Note that this is also a performance optimization. Analyzing 111276479Sdim // headers many times can be expensive. 112276479Sdim if (!S.getSourceManager().isInMainFile(AC.getDecl()->getLocStart())) 113276479Sdim return; 114276479Sdim 115205408Srdivacky UnreachableCodeHandler UC(S); 116276479Sdim reachable_code::FindUnreachableCode(AC, S.getPreprocessor(), UC); 117205408Srdivacky} 118205408Srdivacky 119288943Sdimnamespace { 120276479Sdim/// \brief Warn on logical operator errors in CFGBuilder 121276479Sdimclass LogicalErrorHandler : public CFGCallback { 122276479Sdim Sema &S; 123276479Sdim 124276479Sdimpublic: 125276479Sdim LogicalErrorHandler(Sema &S) : CFGCallback(), S(S) {} 126276479Sdim 127276479Sdim static bool HasMacroID(const Expr *E) { 128276479Sdim if (E->getExprLoc().isMacroID()) 129276479Sdim return true; 130276479Sdim 131276479Sdim // Recurse to children. 132288943Sdim for (const Stmt *SubStmt : E->children()) 133288943Sdim if (const Expr *SubExpr = dyn_cast_or_null<Expr>(SubStmt)) 134288943Sdim if (HasMacroID(SubExpr)) 135288943Sdim return true; 136276479Sdim 137276479Sdim return false; 138276479Sdim } 139276479Sdim 140288943Sdim void compareAlwaysTrue(const BinaryOperator *B, bool isAlwaysTrue) override { 141276479Sdim if (HasMacroID(B)) 142276479Sdim return; 143276479Sdim 144276479Sdim SourceRange DiagRange = B->getSourceRange(); 145276479Sdim S.Diag(B->getExprLoc(), diag::warn_tautological_overlap_comparison) 146276479Sdim << DiagRange << isAlwaysTrue; 147276479Sdim } 148276479Sdim 149288943Sdim void compareBitwiseEquality(const BinaryOperator *B, 150288943Sdim bool isAlwaysTrue) override { 151276479Sdim if (HasMacroID(B)) 152276479Sdim return; 153276479Sdim 154276479Sdim SourceRange DiagRange = B->getSourceRange(); 155276479Sdim S.Diag(B->getExprLoc(), diag::warn_comparison_bitwise_always) 156276479Sdim << DiagRange << isAlwaysTrue; 157276479Sdim } 158276479Sdim}; 159296417Sdim} // anonymous namespace 160276479Sdim 161205408Srdivacky//===----------------------------------------------------------------------===// 162276479Sdim// Check for infinite self-recursion in functions 163276479Sdim//===----------------------------------------------------------------------===// 164276479Sdim 165296417Sdim// Returns true if the function is called anywhere within the CFGBlock. 166296417Sdim// For member functions, the additional condition of being call from the 167296417Sdim// this pointer is required. 168296417Sdimstatic bool hasRecursiveCallInPath(const FunctionDecl *FD, CFGBlock &Block) { 169296417Sdim // Process all the Stmt's in this block to find any calls to FD. 170296417Sdim for (const auto &B : Block) { 171296417Sdim if (B.getKind() != CFGElement::Statement) 172296417Sdim continue; 173296417Sdim 174296417Sdim const CallExpr *CE = dyn_cast<CallExpr>(B.getAs<CFGStmt>()->getStmt()); 175296417Sdim if (!CE || !CE->getCalleeDecl() || 176296417Sdim CE->getCalleeDecl()->getCanonicalDecl() != FD) 177296417Sdim continue; 178296417Sdim 179296417Sdim // Skip function calls which are qualified with a templated class. 180296417Sdim if (const DeclRefExpr *DRE = 181296417Sdim dyn_cast<DeclRefExpr>(CE->getCallee()->IgnoreParenImpCasts())) { 182296417Sdim if (NestedNameSpecifier *NNS = DRE->getQualifier()) { 183296417Sdim if (NNS->getKind() == NestedNameSpecifier::TypeSpec && 184296417Sdim isa<TemplateSpecializationType>(NNS->getAsType())) { 185296417Sdim continue; 186296417Sdim } 187296417Sdim } 188296417Sdim } 189296417Sdim 190296417Sdim const CXXMemberCallExpr *MCE = dyn_cast<CXXMemberCallExpr>(CE); 191296417Sdim if (!MCE || isa<CXXThisExpr>(MCE->getImplicitObjectArgument()) || 192296417Sdim !MCE->getMethodDecl()->isVirtual()) 193296417Sdim return true; 194296417Sdim } 195296417Sdim return false; 196296417Sdim} 197296417Sdim 198276479Sdim// All blocks are in one of three states. States are ordered so that blocks 199276479Sdim// can only move to higher states. 200276479Sdimenum RecursiveState { 201276479Sdim FoundNoPath, 202276479Sdim FoundPath, 203276479Sdim FoundPathWithNoRecursiveCall 204276479Sdim}; 205276479Sdim 206296417Sdim// Returns true if there exists a path to the exit block and every path 207296417Sdim// to the exit block passes through a call to FD. 208296417Sdimstatic bool checkForRecursiveFunctionCall(const FunctionDecl *FD, CFG *cfg) { 209276479Sdim 210296417Sdim const unsigned ExitID = cfg->getExit().getBlockID(); 211276479Sdim 212296417Sdim // Mark all nodes as FoundNoPath, then set the status of the entry block. 213296417Sdim SmallVector<RecursiveState, 16> States(cfg->getNumBlockIDs(), FoundNoPath); 214296417Sdim States[cfg->getEntry().getBlockID()] = FoundPathWithNoRecursiveCall; 215276479Sdim 216296417Sdim // Make the processing stack and seed it with the entry block. 217296417Sdim SmallVector<CFGBlock *, 16> Stack; 218296417Sdim Stack.push_back(&cfg->getEntry()); 219276479Sdim 220296417Sdim while (!Stack.empty()) { 221296417Sdim CFGBlock *CurBlock = Stack.back(); 222296417Sdim Stack.pop_back(); 223276479Sdim 224296417Sdim unsigned ID = CurBlock->getBlockID(); 225296417Sdim RecursiveState CurState = States[ID]; 226276479Sdim 227296417Sdim if (CurState == FoundPathWithNoRecursiveCall) { 228296417Sdim // Found a path to the exit node without a recursive call. 229296417Sdim if (ExitID == ID) 230296417Sdim return false; 231276479Sdim 232296417Sdim // Only change state if the block has a recursive call. 233296417Sdim if (hasRecursiveCallInPath(FD, *CurBlock)) 234296417Sdim CurState = FoundPath; 235296417Sdim } 236296417Sdim 237296417Sdim // Loop over successor blocks and add them to the Stack if their state 238296417Sdim // changes. 239296417Sdim for (auto I = CurBlock->succ_begin(), E = CurBlock->succ_end(); I != E; ++I) 240296417Sdim if (*I) { 241296417Sdim unsigned next_ID = (*I)->getBlockID(); 242296417Sdim if (States[next_ID] < CurState) { 243296417Sdim States[next_ID] = CurState; 244296417Sdim Stack.push_back(*I); 245276479Sdim } 246276479Sdim } 247276479Sdim } 248276479Sdim 249296417Sdim // Return true if the exit node is reachable, and only reachable through 250296417Sdim // a recursive call. 251296417Sdim return States[ExitID] == FoundPath; 252276479Sdim} 253276479Sdim 254276479Sdimstatic void checkRecursiveFunction(Sema &S, const FunctionDecl *FD, 255296417Sdim const Stmt *Body, AnalysisDeclContext &AC) { 256276479Sdim FD = FD->getCanonicalDecl(); 257276479Sdim 258276479Sdim // Only run on non-templated functions and non-templated members of 259276479Sdim // templated classes. 260276479Sdim if (FD->getTemplatedKind() != FunctionDecl::TK_NonTemplate && 261276479Sdim FD->getTemplatedKind() != FunctionDecl::TK_MemberSpecialization) 262276479Sdim return; 263276479Sdim 264276479Sdim CFG *cfg = AC.getCFG(); 265276479Sdim if (!cfg) return; 266276479Sdim 267276479Sdim // If the exit block is unreachable, skip processing the function. 268276479Sdim if (cfg->getExit().pred_empty()) 269276479Sdim return; 270276479Sdim 271296417Sdim // Emit diagnostic if a recursive function call is detected for all paths. 272296417Sdim if (checkForRecursiveFunctionCall(FD, cfg)) 273276479Sdim S.Diag(Body->getLocStart(), diag::warn_infinite_recursive_function); 274276479Sdim} 275276479Sdim 276276479Sdim//===----------------------------------------------------------------------===// 277205408Srdivacky// Check for missing return value. 278205408Srdivacky//===----------------------------------------------------------------------===// 279205408Srdivacky 280208600Srdivackyenum ControlFlowKind { 281208600Srdivacky UnknownFallThrough, 282208600Srdivacky NeverFallThrough, 283208600Srdivacky MaybeFallThrough, 284208600Srdivacky AlwaysFallThrough, 285208600Srdivacky NeverFallThroughOrReturn 286208600Srdivacky}; 287205408Srdivacky 288205408Srdivacky/// CheckFallThrough - Check that we don't fall off the end of a 289205408Srdivacky/// Statement that should return a value. 290205408Srdivacky/// 291205408Srdivacky/// \returns AlwaysFallThrough iff we always fall off the end of the statement, 292205408Srdivacky/// MaybeFallThrough iff we might or might not fall off the end, 293205408Srdivacky/// NeverFallThroughOrReturn iff we never fall off the end of the statement or 294205408Srdivacky/// return. We assume NeverFallThrough iff we never fall off the end of the 295205408Srdivacky/// statement but we may return. We assume that functions not marked noreturn 296205408Srdivacky/// will return. 297234353Sdimstatic ControlFlowKind CheckFallThrough(AnalysisDeclContext &AC) { 298205408Srdivacky CFG *cfg = AC.getCFG(); 299276479Sdim if (!cfg) return UnknownFallThrough; 300205408Srdivacky 301205408Srdivacky // The CFG leaves in dead things, and we don't want the dead code paths to 302205408Srdivacky // confuse us, so we mark all live things first. 303205408Srdivacky llvm::BitVector live(cfg->getNumBlockIDs()); 304226633Sdim unsigned count = reachable_code::ScanReachableFromBlock(&cfg->getEntry(), 305205408Srdivacky live); 306205408Srdivacky 307205408Srdivacky bool AddEHEdges = AC.getAddEHEdges(); 308205408Srdivacky if (!AddEHEdges && count != cfg->getNumBlockIDs()) 309205408Srdivacky // When there are things remaining dead, and we didn't add EH edges 310205408Srdivacky // from CallExprs to the catch clauses, we have to go back and 311205408Srdivacky // mark them as live. 312276479Sdim for (const auto *B : *cfg) { 313276479Sdim if (!live[B->getBlockID()]) { 314276479Sdim if (B->pred_begin() == B->pred_end()) { 315276479Sdim if (B->getTerminator() && isa<CXXTryStmt>(B->getTerminator())) 316205408Srdivacky // When not adding EH edges from calls, catch clauses 317205408Srdivacky // can otherwise seem dead. Avoid noting them as dead. 318276479Sdim count += reachable_code::ScanReachableFromBlock(B, live); 319205408Srdivacky continue; 320205408Srdivacky } 321205408Srdivacky } 322205408Srdivacky } 323205408Srdivacky 324205408Srdivacky // Now we know what is live, we check the live precessors of the exit block 325205408Srdivacky // and look for fall through paths, being careful to ignore normal returns, 326205408Srdivacky // and exceptional paths. 327205408Srdivacky bool HasLiveReturn = false; 328205408Srdivacky bool HasFakeEdge = false; 329205408Srdivacky bool HasPlainEdge = false; 330205408Srdivacky bool HasAbnormalEdge = false; 331218893Sdim 332218893Sdim // Ignore default cases that aren't likely to be reachable because all 333218893Sdim // enums in a switch(X) have explicit case statements. 334218893Sdim CFGBlock::FilterOptions FO; 335218893Sdim FO.IgnoreDefaultsWithCoveredEnums = 1; 336218893Sdim 337218893Sdim for (CFGBlock::filtered_pred_iterator 338218893Sdim I = cfg->getExit().filtered_pred_start_end(FO); I.hasMore(); ++I) { 339218893Sdim const CFGBlock& B = **I; 340205408Srdivacky if (!live[B.getBlockID()]) 341205408Srdivacky continue; 342218893Sdim 343226633Sdim // Skip blocks which contain an element marked as no-return. They don't 344226633Sdim // represent actually viable edges into the exit block, so mark them as 345226633Sdim // abnormal. 346226633Sdim if (B.hasNoReturnElement()) { 347226633Sdim HasAbnormalEdge = true; 348226633Sdim continue; 349226633Sdim } 350226633Sdim 351218893Sdim // Destructors can appear after the 'return' in the CFG. This is 352218893Sdim // normal. We need to look pass the destructors for the return 353218893Sdim // statement (if it exists). 354218893Sdim CFGBlock::const_reverse_iterator ri = B.rbegin(), re = B.rend(); 355221345Sdim 356226633Sdim for ( ; ri != re ; ++ri) 357249423Sdim if (ri->getAs<CFGStmt>()) 358218893Sdim break; 359226633Sdim 360218893Sdim // No more CFGElements in the block? 361218893Sdim if (ri == re) { 362205408Srdivacky if (B.getTerminator() && isa<CXXTryStmt>(B.getTerminator())) { 363205408Srdivacky HasAbnormalEdge = true; 364205408Srdivacky continue; 365205408Srdivacky } 366205408Srdivacky // A labeled empty statement, or the entry block... 367205408Srdivacky HasPlainEdge = true; 368205408Srdivacky continue; 369205408Srdivacky } 370218893Sdim 371249423Sdim CFGStmt CS = ri->castAs<CFGStmt>(); 372226633Sdim const Stmt *S = CS.getStmt(); 373205408Srdivacky if (isa<ReturnStmt>(S)) { 374205408Srdivacky HasLiveReturn = true; 375205408Srdivacky continue; 376205408Srdivacky } 377205408Srdivacky if (isa<ObjCAtThrowStmt>(S)) { 378205408Srdivacky HasFakeEdge = true; 379205408Srdivacky continue; 380205408Srdivacky } 381205408Srdivacky if (isa<CXXThrowExpr>(S)) { 382205408Srdivacky HasFakeEdge = true; 383205408Srdivacky continue; 384205408Srdivacky } 385239462Sdim if (isa<MSAsmStmt>(S)) { 386239462Sdim // TODO: Verify this is correct. 387239462Sdim HasFakeEdge = true; 388239462Sdim HasLiveReturn = true; 389239462Sdim continue; 390239462Sdim } 391205408Srdivacky if (isa<CXXTryStmt>(S)) { 392205408Srdivacky HasAbnormalEdge = true; 393205408Srdivacky continue; 394205408Srdivacky } 395226633Sdim if (std::find(B.succ_begin(), B.succ_end(), &cfg->getExit()) 396226633Sdim == B.succ_end()) { 397226633Sdim HasAbnormalEdge = true; 398226633Sdim continue; 399226633Sdim } 400205408Srdivacky 401226633Sdim HasPlainEdge = true; 402205408Srdivacky } 403205408Srdivacky if (!HasPlainEdge) { 404205408Srdivacky if (HasLiveReturn) 405205408Srdivacky return NeverFallThrough; 406205408Srdivacky return NeverFallThroughOrReturn; 407205408Srdivacky } 408205408Srdivacky if (HasAbnormalEdge || HasFakeEdge || HasLiveReturn) 409205408Srdivacky return MaybeFallThrough; 410205408Srdivacky // This says AlwaysFallThrough for calls to functions that are not marked 411205408Srdivacky // noreturn, that don't return. If people would like this warning to be more 412205408Srdivacky // accurate, such functions should be marked as noreturn. 413205408Srdivacky return AlwaysFallThrough; 414205408Srdivacky} 415205408Srdivacky 416212904Sdimnamespace { 417212904Sdim 418205408Srdivackystruct CheckFallThroughDiagnostics { 419205408Srdivacky unsigned diag_MaybeFallThrough_HasNoReturn; 420205408Srdivacky unsigned diag_MaybeFallThrough_ReturnsNonVoid; 421205408Srdivacky unsigned diag_AlwaysFallThrough_HasNoReturn; 422205408Srdivacky unsigned diag_AlwaysFallThrough_ReturnsNonVoid; 423205408Srdivacky unsigned diag_NeverFallThroughOrReturn; 424234353Sdim enum { Function, Block, Lambda } funMode; 425218893Sdim SourceLocation FuncLoc; 426206084Srdivacky 427207619Srdivacky static CheckFallThroughDiagnostics MakeForFunction(const Decl *Func) { 428205408Srdivacky CheckFallThroughDiagnostics D; 429218893Sdim D.FuncLoc = Func->getLocation(); 430205408Srdivacky D.diag_MaybeFallThrough_HasNoReturn = 431205408Srdivacky diag::warn_falloff_noreturn_function; 432205408Srdivacky D.diag_MaybeFallThrough_ReturnsNonVoid = 433205408Srdivacky diag::warn_maybe_falloff_nonvoid_function; 434205408Srdivacky D.diag_AlwaysFallThrough_HasNoReturn = 435205408Srdivacky diag::warn_falloff_noreturn_function; 436205408Srdivacky D.diag_AlwaysFallThrough_ReturnsNonVoid = 437205408Srdivacky diag::warn_falloff_nonvoid_function; 438207619Srdivacky 439207619Srdivacky // Don't suggest that virtual functions be marked "noreturn", since they 440207619Srdivacky // might be overridden by non-noreturn functions. 441207619Srdivacky bool isVirtualMethod = false; 442207619Srdivacky if (const CXXMethodDecl *Method = dyn_cast<CXXMethodDecl>(Func)) 443207619Srdivacky isVirtualMethod = Method->isVirtual(); 444207619Srdivacky 445226633Sdim // Don't suggest that template instantiations be marked "noreturn" 446226633Sdim bool isTemplateInstantiation = false; 447234353Sdim if (const FunctionDecl *Function = dyn_cast<FunctionDecl>(Func)) 448234353Sdim isTemplateInstantiation = Function->isTemplateInstantiation(); 449226633Sdim 450226633Sdim if (!isVirtualMethod && !isTemplateInstantiation) 451207619Srdivacky D.diag_NeverFallThroughOrReturn = 452207619Srdivacky diag::warn_suggest_noreturn_function; 453207619Srdivacky else 454207619Srdivacky D.diag_NeverFallThroughOrReturn = 0; 455207619Srdivacky 456234353Sdim D.funMode = Function; 457205408Srdivacky return D; 458205408Srdivacky } 459206084Srdivacky 460205408Srdivacky static CheckFallThroughDiagnostics MakeForBlock() { 461205408Srdivacky CheckFallThroughDiagnostics D; 462205408Srdivacky D.diag_MaybeFallThrough_HasNoReturn = 463205408Srdivacky diag::err_noreturn_block_has_return_expr; 464205408Srdivacky D.diag_MaybeFallThrough_ReturnsNonVoid = 465205408Srdivacky diag::err_maybe_falloff_nonvoid_block; 466205408Srdivacky D.diag_AlwaysFallThrough_HasNoReturn = 467205408Srdivacky diag::err_noreturn_block_has_return_expr; 468205408Srdivacky D.diag_AlwaysFallThrough_ReturnsNonVoid = 469205408Srdivacky diag::err_falloff_nonvoid_block; 470276479Sdim D.diag_NeverFallThroughOrReturn = 0; 471234353Sdim D.funMode = Block; 472205408Srdivacky return D; 473205408Srdivacky } 474206084Srdivacky 475234353Sdim static CheckFallThroughDiagnostics MakeForLambda() { 476234353Sdim CheckFallThroughDiagnostics D; 477234353Sdim D.diag_MaybeFallThrough_HasNoReturn = 478234353Sdim diag::err_noreturn_lambda_has_return_expr; 479234353Sdim D.diag_MaybeFallThrough_ReturnsNonVoid = 480234353Sdim diag::warn_maybe_falloff_nonvoid_lambda; 481234353Sdim D.diag_AlwaysFallThrough_HasNoReturn = 482234353Sdim diag::err_noreturn_lambda_has_return_expr; 483234353Sdim D.diag_AlwaysFallThrough_ReturnsNonVoid = 484234353Sdim diag::warn_falloff_nonvoid_lambda; 485234353Sdim D.diag_NeverFallThroughOrReturn = 0; 486234353Sdim D.funMode = Lambda; 487234353Sdim return D; 488234353Sdim } 489234353Sdim 490226633Sdim bool checkDiagnostics(DiagnosticsEngine &D, bool ReturnsVoid, 491205408Srdivacky bool HasNoReturn) const { 492234353Sdim if (funMode == Function) { 493218893Sdim return (ReturnsVoid || 494276479Sdim D.isIgnored(diag::warn_maybe_falloff_nonvoid_function, 495276479Sdim FuncLoc)) && 496276479Sdim (!HasNoReturn || 497276479Sdim D.isIgnored(diag::warn_noreturn_function_has_return_expr, 498276479Sdim FuncLoc)) && 499276479Sdim (!ReturnsVoid || 500276479Sdim D.isIgnored(diag::warn_suggest_noreturn_block, FuncLoc)); 501205408Srdivacky } 502206084Srdivacky 503234353Sdim // For blocks / lambdas. 504276479Sdim return ReturnsVoid && !HasNoReturn; 505205408Srdivacky } 506205408Srdivacky}; 507205408Srdivacky 508296417Sdim} // anonymous namespace 509212904Sdim 510205408Srdivacky/// CheckFallThroughForFunctionDef - Check that we don't fall off the end of a 511205408Srdivacky/// function that should return a value. Check that we don't fall off the end 512205408Srdivacky/// of a noreturn function. We assume that functions and blocks not marked 513205408Srdivacky/// noreturn will return. 514205408Srdivackystatic void CheckFallThroughForBody(Sema &S, const Decl *D, const Stmt *Body, 515219077Sdim const BlockExpr *blkExpr, 516205408Srdivacky const CheckFallThroughDiagnostics& CD, 517234353Sdim AnalysisDeclContext &AC) { 518205408Srdivacky 519205408Srdivacky bool ReturnsVoid = false; 520205408Srdivacky bool HasNoReturn = false; 521205408Srdivacky 522205408Srdivacky if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(D)) { 523276479Sdim ReturnsVoid = FD->getReturnType()->isVoidType(); 524249423Sdim HasNoReturn = FD->isNoReturn(); 525205408Srdivacky } 526205408Srdivacky else if (const ObjCMethodDecl *MD = dyn_cast<ObjCMethodDecl>(D)) { 527276479Sdim ReturnsVoid = MD->getReturnType()->isVoidType(); 528205408Srdivacky HasNoReturn = MD->hasAttr<NoReturnAttr>(); 529205408Srdivacky } 530205408Srdivacky else if (isa<BlockDecl>(D)) { 531219077Sdim QualType BlockTy = blkExpr->getType(); 532206084Srdivacky if (const FunctionType *FT = 533205408Srdivacky BlockTy->getPointeeType()->getAs<FunctionType>()) { 534276479Sdim if (FT->getReturnType()->isVoidType()) 535205408Srdivacky ReturnsVoid = true; 536205408Srdivacky if (FT->getNoReturnAttr()) 537205408Srdivacky HasNoReturn = true; 538205408Srdivacky } 539205408Srdivacky } 540205408Srdivacky 541226633Sdim DiagnosticsEngine &Diags = S.getDiagnostics(); 542205408Srdivacky 543205408Srdivacky // Short circuit for compilation speed. 544205408Srdivacky if (CD.checkDiagnostics(Diags, ReturnsVoid, HasNoReturn)) 545205408Srdivacky return; 546206084Srdivacky 547280031Sdim SourceLocation LBrace = Body->getLocStart(), RBrace = Body->getLocEnd(); 548280031Sdim // Either in a function body compound statement, or a function-try-block. 549280031Sdim switch (CheckFallThrough(AC)) { 550280031Sdim case UnknownFallThrough: 551280031Sdim break; 552208600Srdivacky 553280031Sdim case MaybeFallThrough: 554280031Sdim if (HasNoReturn) 555280031Sdim S.Diag(RBrace, CD.diag_MaybeFallThrough_HasNoReturn); 556280031Sdim else if (!ReturnsVoid) 557280031Sdim S.Diag(RBrace, CD.diag_MaybeFallThrough_ReturnsNonVoid); 558280031Sdim break; 559280031Sdim case AlwaysFallThrough: 560280031Sdim if (HasNoReturn) 561280031Sdim S.Diag(RBrace, CD.diag_AlwaysFallThrough_HasNoReturn); 562280031Sdim else if (!ReturnsVoid) 563280031Sdim S.Diag(RBrace, CD.diag_AlwaysFallThrough_ReturnsNonVoid); 564280031Sdim break; 565280031Sdim case NeverFallThroughOrReturn: 566280031Sdim if (ReturnsVoid && !HasNoReturn && CD.diag_NeverFallThroughOrReturn) { 567280031Sdim if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(D)) { 568280031Sdim S.Diag(LBrace, CD.diag_NeverFallThroughOrReturn) << 0 << FD; 569280031Sdim } else if (const ObjCMethodDecl *MD = dyn_cast<ObjCMethodDecl>(D)) { 570280031Sdim S.Diag(LBrace, CD.diag_NeverFallThroughOrReturn) << 1 << MD; 571280031Sdim } else { 572280031Sdim S.Diag(LBrace, CD.diag_NeverFallThroughOrReturn); 573226633Sdim } 574280031Sdim } 575280031Sdim break; 576280031Sdim case NeverFallThrough: 577280031Sdim break; 578205408Srdivacky } 579205408Srdivacky} 580205408Srdivacky 581205408Srdivacky//===----------------------------------------------------------------------===// 582218893Sdim// -Wuninitialized 583218893Sdim//===----------------------------------------------------------------------===// 584218893Sdim 585218893Sdimnamespace { 586221345Sdim/// ContainsReference - A visitor class to search for references to 587221345Sdim/// a particular declaration (the needle) within any evaluated component of an 588221345Sdim/// expression (recursively). 589288943Sdimclass ContainsReference : public ConstEvaluatedExprVisitor<ContainsReference> { 590221345Sdim bool FoundReference; 591221345Sdim const DeclRefExpr *Needle; 592221345Sdim 593221345Sdimpublic: 594288943Sdim typedef ConstEvaluatedExprVisitor<ContainsReference> Inherited; 595288943Sdim 596221345Sdim ContainsReference(ASTContext &Context, const DeclRefExpr *Needle) 597288943Sdim : Inherited(Context), FoundReference(false), Needle(Needle) {} 598221345Sdim 599288943Sdim void VisitExpr(const Expr *E) { 600221345Sdim // Stop evaluating if we already have a reference. 601221345Sdim if (FoundReference) 602221345Sdim return; 603221345Sdim 604288943Sdim Inherited::VisitExpr(E); 605221345Sdim } 606221345Sdim 607288943Sdim void VisitDeclRefExpr(const DeclRefExpr *E) { 608221345Sdim if (E == Needle) 609221345Sdim FoundReference = true; 610221345Sdim else 611288943Sdim Inherited::VisitDeclRefExpr(E); 612221345Sdim } 613221345Sdim 614221345Sdim bool doesContainReference() const { return FoundReference; } 615221345Sdim}; 616296417Sdim} // anonymous namespace 617221345Sdim 618226633Sdimstatic bool SuggestInitializationFixit(Sema &S, const VarDecl *VD) { 619234353Sdim QualType VariableTy = VD->getType().getCanonicalType(); 620234353Sdim if (VariableTy->isBlockPointerType() && 621234353Sdim !VD->hasAttr<BlocksAttr>()) { 622276479Sdim S.Diag(VD->getLocation(), diag::note_block_var_fixit_add_initialization) 623276479Sdim << VD->getDeclName() 624276479Sdim << FixItHint::CreateInsertion(VD->getLocation(), "__block "); 625234353Sdim return true; 626234353Sdim } 627261991Sdim 628226633Sdim // Don't issue a fixit if there is already an initializer. 629226633Sdim if (VD->getInit()) 630226633Sdim return false; 631239462Sdim 632239462Sdim // Don't suggest a fixit inside macros. 633239462Sdim if (VD->getLocEnd().isMacroID()) 634239462Sdim return false; 635239462Sdim 636276479Sdim SourceLocation Loc = S.getLocForEndOfToken(VD->getLocEnd()); 637261991Sdim 638261991Sdim // Suggest possible initialization (if any). 639261991Sdim std::string Init = S.getFixItZeroInitializerForType(VariableTy, Loc); 640261991Sdim if (Init.empty()) 641261991Sdim return false; 642261991Sdim 643234353Sdim S.Diag(Loc, diag::note_var_fixit_add_initialization) << VD->getDeclName() 644234353Sdim << FixItHint::CreateInsertion(Loc, Init); 645234353Sdim return true; 646226633Sdim} 647226633Sdim 648239462Sdim/// Create a fixit to remove an if-like statement, on the assumption that its 649239462Sdim/// condition is CondVal. 650239462Sdimstatic void CreateIfFixit(Sema &S, const Stmt *If, const Stmt *Then, 651239462Sdim const Stmt *Else, bool CondVal, 652239462Sdim FixItHint &Fixit1, FixItHint &Fixit2) { 653239462Sdim if (CondVal) { 654239462Sdim // If condition is always true, remove all but the 'then'. 655239462Sdim Fixit1 = FixItHint::CreateRemoval( 656239462Sdim CharSourceRange::getCharRange(If->getLocStart(), 657239462Sdim Then->getLocStart())); 658239462Sdim if (Else) { 659296417Sdim SourceLocation ElseKwLoc = S.getLocForEndOfToken(Then->getLocEnd()); 660239462Sdim Fixit2 = FixItHint::CreateRemoval( 661239462Sdim SourceRange(ElseKwLoc, Else->getLocEnd())); 662239462Sdim } 663239462Sdim } else { 664239462Sdim // If condition is always false, remove all but the 'else'. 665239462Sdim if (Else) 666239462Sdim Fixit1 = FixItHint::CreateRemoval( 667239462Sdim CharSourceRange::getCharRange(If->getLocStart(), 668239462Sdim Else->getLocStart())); 669239462Sdim else 670239462Sdim Fixit1 = FixItHint::CreateRemoval(If->getSourceRange()); 671239462Sdim } 672239462Sdim} 673239462Sdim 674239462Sdim/// DiagUninitUse -- Helper function to produce a diagnostic for an 675239462Sdim/// uninitialized use of a variable. 676239462Sdimstatic void DiagUninitUse(Sema &S, const VarDecl *VD, const UninitUse &Use, 677239462Sdim bool IsCapturedByBlock) { 678239462Sdim bool Diagnosed = false; 679239462Sdim 680261991Sdim switch (Use.getKind()) { 681261991Sdim case UninitUse::Always: 682261991Sdim S.Diag(Use.getUser()->getLocStart(), diag::warn_uninit_var) 683261991Sdim << VD->getDeclName() << IsCapturedByBlock 684261991Sdim << Use.getUser()->getSourceRange(); 685261991Sdim return; 686261991Sdim 687261991Sdim case UninitUse::AfterDecl: 688261991Sdim case UninitUse::AfterCall: 689261991Sdim S.Diag(VD->getLocation(), diag::warn_sometimes_uninit_var) 690261991Sdim << VD->getDeclName() << IsCapturedByBlock 691261991Sdim << (Use.getKind() == UninitUse::AfterDecl ? 4 : 5) 692261991Sdim << const_cast<DeclContext*>(VD->getLexicalDeclContext()) 693261991Sdim << VD->getSourceRange(); 694261991Sdim S.Diag(Use.getUser()->getLocStart(), diag::note_uninit_var_use) 695261991Sdim << IsCapturedByBlock << Use.getUser()->getSourceRange(); 696261991Sdim return; 697261991Sdim 698261991Sdim case UninitUse::Maybe: 699261991Sdim case UninitUse::Sometimes: 700261991Sdim // Carry on to report sometimes-uninitialized branches, if possible, 701261991Sdim // or a 'may be used uninitialized' diagnostic otherwise. 702261991Sdim break; 703261991Sdim } 704261991Sdim 705239462Sdim // Diagnose each branch which leads to a sometimes-uninitialized use. 706239462Sdim for (UninitUse::branch_iterator I = Use.branch_begin(), E = Use.branch_end(); 707239462Sdim I != E; ++I) { 708239462Sdim assert(Use.getKind() == UninitUse::Sometimes); 709239462Sdim 710239462Sdim const Expr *User = Use.getUser(); 711239462Sdim const Stmt *Term = I->Terminator; 712239462Sdim 713239462Sdim // Information used when building the diagnostic. 714239462Sdim unsigned DiagKind; 715243830Sdim StringRef Str; 716239462Sdim SourceRange Range; 717239462Sdim 718249423Sdim // FixIts to suppress the diagnostic by removing the dead condition. 719239462Sdim // For all binary terminators, branch 0 is taken if the condition is true, 720239462Sdim // and branch 1 is taken if the condition is false. 721239462Sdim int RemoveDiagKind = -1; 722239462Sdim const char *FixitStr = 723239462Sdim S.getLangOpts().CPlusPlus ? (I->Output ? "true" : "false") 724239462Sdim : (I->Output ? "1" : "0"); 725239462Sdim FixItHint Fixit1, Fixit2; 726239462Sdim 727261991Sdim switch (Term ? Term->getStmtClass() : Stmt::DeclStmtClass) { 728239462Sdim default: 729239462Sdim // Don't know how to report this. Just fall back to 'may be used 730261991Sdim // uninitialized'. FIXME: Can this happen? 731239462Sdim continue; 732239462Sdim 733239462Sdim // "condition is true / condition is false". 734239462Sdim case Stmt::IfStmtClass: { 735239462Sdim const IfStmt *IS = cast<IfStmt>(Term); 736239462Sdim DiagKind = 0; 737239462Sdim Str = "if"; 738239462Sdim Range = IS->getCond()->getSourceRange(); 739239462Sdim RemoveDiagKind = 0; 740239462Sdim CreateIfFixit(S, IS, IS->getThen(), IS->getElse(), 741239462Sdim I->Output, Fixit1, Fixit2); 742239462Sdim break; 743239462Sdim } 744239462Sdim case Stmt::ConditionalOperatorClass: { 745239462Sdim const ConditionalOperator *CO = cast<ConditionalOperator>(Term); 746239462Sdim DiagKind = 0; 747239462Sdim Str = "?:"; 748239462Sdim Range = CO->getCond()->getSourceRange(); 749239462Sdim RemoveDiagKind = 0; 750239462Sdim CreateIfFixit(S, CO, CO->getTrueExpr(), CO->getFalseExpr(), 751239462Sdim I->Output, Fixit1, Fixit2); 752239462Sdim break; 753239462Sdim } 754239462Sdim case Stmt::BinaryOperatorClass: { 755239462Sdim const BinaryOperator *BO = cast<BinaryOperator>(Term); 756239462Sdim if (!BO->isLogicalOp()) 757239462Sdim continue; 758239462Sdim DiagKind = 0; 759239462Sdim Str = BO->getOpcodeStr(); 760239462Sdim Range = BO->getLHS()->getSourceRange(); 761239462Sdim RemoveDiagKind = 0; 762239462Sdim if ((BO->getOpcode() == BO_LAnd && I->Output) || 763239462Sdim (BO->getOpcode() == BO_LOr && !I->Output)) 764239462Sdim // true && y -> y, false || y -> y. 765239462Sdim Fixit1 = FixItHint::CreateRemoval(SourceRange(BO->getLocStart(), 766239462Sdim BO->getOperatorLoc())); 767239462Sdim else 768239462Sdim // false && y -> false, true || y -> true. 769239462Sdim Fixit1 = FixItHint::CreateReplacement(BO->getSourceRange(), FixitStr); 770239462Sdim break; 771239462Sdim } 772239462Sdim 773239462Sdim // "loop is entered / loop is exited". 774239462Sdim case Stmt::WhileStmtClass: 775239462Sdim DiagKind = 1; 776239462Sdim Str = "while"; 777239462Sdim Range = cast<WhileStmt>(Term)->getCond()->getSourceRange(); 778239462Sdim RemoveDiagKind = 1; 779239462Sdim Fixit1 = FixItHint::CreateReplacement(Range, FixitStr); 780239462Sdim break; 781239462Sdim case Stmt::ForStmtClass: 782239462Sdim DiagKind = 1; 783239462Sdim Str = "for"; 784239462Sdim Range = cast<ForStmt>(Term)->getCond()->getSourceRange(); 785239462Sdim RemoveDiagKind = 1; 786239462Sdim if (I->Output) 787239462Sdim Fixit1 = FixItHint::CreateRemoval(Range); 788239462Sdim else 789239462Sdim Fixit1 = FixItHint::CreateReplacement(Range, FixitStr); 790239462Sdim break; 791261991Sdim case Stmt::CXXForRangeStmtClass: 792261991Sdim if (I->Output == 1) { 793261991Sdim // The use occurs if a range-based for loop's body never executes. 794261991Sdim // That may be impossible, and there's no syntactic fix for this, 795261991Sdim // so treat it as a 'may be uninitialized' case. 796261991Sdim continue; 797261991Sdim } 798261991Sdim DiagKind = 1; 799261991Sdim Str = "for"; 800261991Sdim Range = cast<CXXForRangeStmt>(Term)->getRangeInit()->getSourceRange(); 801261991Sdim break; 802239462Sdim 803239462Sdim // "condition is true / loop is exited". 804239462Sdim case Stmt::DoStmtClass: 805239462Sdim DiagKind = 2; 806239462Sdim Str = "do"; 807239462Sdim Range = cast<DoStmt>(Term)->getCond()->getSourceRange(); 808239462Sdim RemoveDiagKind = 1; 809239462Sdim Fixit1 = FixItHint::CreateReplacement(Range, FixitStr); 810239462Sdim break; 811239462Sdim 812239462Sdim // "switch case is taken". 813239462Sdim case Stmt::CaseStmtClass: 814239462Sdim DiagKind = 3; 815239462Sdim Str = "case"; 816239462Sdim Range = cast<CaseStmt>(Term)->getLHS()->getSourceRange(); 817239462Sdim break; 818239462Sdim case Stmt::DefaultStmtClass: 819239462Sdim DiagKind = 3; 820239462Sdim Str = "default"; 821239462Sdim Range = cast<DefaultStmt>(Term)->getDefaultLoc(); 822239462Sdim break; 823239462Sdim } 824239462Sdim 825239462Sdim S.Diag(Range.getBegin(), diag::warn_sometimes_uninit_var) 826239462Sdim << VD->getDeclName() << IsCapturedByBlock << DiagKind 827239462Sdim << Str << I->Output << Range; 828239462Sdim S.Diag(User->getLocStart(), diag::note_uninit_var_use) 829239462Sdim << IsCapturedByBlock << User->getSourceRange(); 830239462Sdim if (RemoveDiagKind != -1) 831239462Sdim S.Diag(Fixit1.RemoveRange.getBegin(), diag::note_uninit_fixit_remove_cond) 832239462Sdim << RemoveDiagKind << Str << I->Output << Fixit1 << Fixit2; 833239462Sdim 834239462Sdim Diagnosed = true; 835239462Sdim } 836239462Sdim 837239462Sdim if (!Diagnosed) 838261991Sdim S.Diag(Use.getUser()->getLocStart(), diag::warn_maybe_uninit_var) 839239462Sdim << VD->getDeclName() << IsCapturedByBlock 840239462Sdim << Use.getUser()->getSourceRange(); 841239462Sdim} 842239462Sdim 843221345Sdim/// DiagnoseUninitializedUse -- Helper function for diagnosing uses of an 844221345Sdim/// uninitialized variable. This manages the different forms of diagnostic 845221345Sdim/// emitted for particular types of uses. Returns true if the use was diagnosed 846239462Sdim/// as a warning. If a particular use is one we omit warnings for, returns 847221345Sdim/// false. 848221345Sdimstatic bool DiagnoseUninitializedUse(Sema &S, const VarDecl *VD, 849239462Sdim const UninitUse &Use, 850226633Sdim bool alwaysReportSelfInit = false) { 851239462Sdim if (const DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(Use.getUser())) { 852239462Sdim // Inspect the initializer of the variable declaration which is 853239462Sdim // being referenced prior to its initialization. We emit 854239462Sdim // specialized diagnostics for self-initialization, and we 855239462Sdim // specifically avoid warning about self references which take the 856239462Sdim // form of: 857239462Sdim // 858239462Sdim // int x = x; 859239462Sdim // 860239462Sdim // This is used to indicate to GCC that 'x' is intentionally left 861239462Sdim // uninitialized. Proven code paths which access 'x' in 862239462Sdim // an uninitialized state after this will still warn. 863239462Sdim if (const Expr *Initializer = VD->getInit()) { 864239462Sdim if (!alwaysReportSelfInit && DRE == Initializer->IgnoreParenImpCasts()) 865239462Sdim return false; 866221345Sdim 867239462Sdim ContainsReference CR(S.Context, DRE); 868288943Sdim CR.Visit(Initializer); 869239462Sdim if (CR.doesContainReference()) { 870221345Sdim S.Diag(DRE->getLocStart(), 871221345Sdim diag::warn_uninit_self_reference_in_init) 872239462Sdim << VD->getDeclName() << VD->getLocation() << DRE->getSourceRange(); 873239462Sdim return true; 874221345Sdim } 875221345Sdim } 876239462Sdim 877239462Sdim DiagUninitUse(S, VD, Use, false); 878221345Sdim } else { 879239462Sdim const BlockExpr *BE = cast<BlockExpr>(Use.getUser()); 880239462Sdim if (VD->getType()->isBlockPointerType() && !VD->hasAttr<BlocksAttr>()) 881239462Sdim S.Diag(BE->getLocStart(), 882239462Sdim diag::warn_uninit_byref_blockvar_captured_by_block) 883234353Sdim << VD->getDeclName(); 884234353Sdim else 885239462Sdim DiagUninitUse(S, VD, Use, true); 886221345Sdim } 887221345Sdim 888221345Sdim // Report where the variable was declared when the use wasn't within 889226633Sdim // the initializer of that declaration & we didn't already suggest 890226633Sdim // an initialization fixit. 891239462Sdim if (!SuggestInitializationFixit(S, VD)) 892221345Sdim S.Diag(VD->getLocStart(), diag::note_uninit_var_def) 893221345Sdim << VD->getDeclName(); 894221345Sdim 895221345Sdim return true; 896221345Sdim} 897221345Sdim 898239462Sdimnamespace { 899239462Sdim class FallthroughMapper : public RecursiveASTVisitor<FallthroughMapper> { 900239462Sdim public: 901239462Sdim FallthroughMapper(Sema &S) 902239462Sdim : FoundSwitchStatements(false), 903239462Sdim S(S) { 904239462Sdim } 905221345Sdim 906239462Sdim bool foundSwitchStatements() const { return FoundSwitchStatements; } 907239462Sdim 908239462Sdim void markFallthroughVisited(const AttributedStmt *Stmt) { 909239462Sdim bool Found = FallthroughStmts.erase(Stmt); 910239462Sdim assert(Found); 911239462Sdim (void)Found; 912239462Sdim } 913239462Sdim 914239462Sdim typedef llvm::SmallPtrSet<const AttributedStmt*, 8> AttrStmts; 915239462Sdim 916239462Sdim const AttrStmts &getFallthroughStmts() const { 917239462Sdim return FallthroughStmts; 918239462Sdim } 919239462Sdim 920249423Sdim void fillReachableBlocks(CFG *Cfg) { 921249423Sdim assert(ReachableBlocks.empty() && "ReachableBlocks already filled"); 922249423Sdim std::deque<const CFGBlock *> BlockQueue; 923249423Sdim 924249423Sdim ReachableBlocks.insert(&Cfg->getEntry()); 925249423Sdim BlockQueue.push_back(&Cfg->getEntry()); 926249423Sdim // Mark all case blocks reachable to avoid problems with switching on 927249423Sdim // constants, covered enums, etc. 928249423Sdim // These blocks can contain fall-through annotations, and we don't want to 929249423Sdim // issue a warn_fallthrough_attr_unreachable for them. 930276479Sdim for (const auto *B : *Cfg) { 931249423Sdim const Stmt *L = B->getLabel(); 932280031Sdim if (L && isa<SwitchCase>(L) && ReachableBlocks.insert(B).second) 933249423Sdim BlockQueue.push_back(B); 934249423Sdim } 935249423Sdim 936249423Sdim while (!BlockQueue.empty()) { 937249423Sdim const CFGBlock *P = BlockQueue.front(); 938249423Sdim BlockQueue.pop_front(); 939249423Sdim for (CFGBlock::const_succ_iterator I = P->succ_begin(), 940249423Sdim E = P->succ_end(); 941249423Sdim I != E; ++I) { 942280031Sdim if (*I && ReachableBlocks.insert(*I).second) 943249423Sdim BlockQueue.push_back(*I); 944249423Sdim } 945249423Sdim } 946249423Sdim } 947249423Sdim 948239462Sdim bool checkFallThroughIntoBlock(const CFGBlock &B, int &AnnotatedCnt) { 949249423Sdim assert(!ReachableBlocks.empty() && "ReachableBlocks empty"); 950249423Sdim 951239462Sdim int UnannotatedCnt = 0; 952239462Sdim AnnotatedCnt = 0; 953239462Sdim 954276479Sdim std::deque<const CFGBlock*> BlockQueue(B.pred_begin(), B.pred_end()); 955239462Sdim while (!BlockQueue.empty()) { 956239462Sdim const CFGBlock *P = BlockQueue.front(); 957239462Sdim BlockQueue.pop_front(); 958276479Sdim if (!P) continue; 959239462Sdim 960239462Sdim const Stmt *Term = P->getTerminator(); 961239462Sdim if (Term && isa<SwitchStmt>(Term)) 962239462Sdim continue; // Switch statement, good. 963239462Sdim 964239462Sdim const SwitchCase *SW = dyn_cast_or_null<SwitchCase>(P->getLabel()); 965239462Sdim if (SW && SW->getSubStmt() == B.getLabel() && P->begin() == P->end()) 966239462Sdim continue; // Previous case label has no statements, good. 967239462Sdim 968249423Sdim const LabelStmt *L = dyn_cast_or_null<LabelStmt>(P->getLabel()); 969249423Sdim if (L && L->getSubStmt() == B.getLabel() && P->begin() == P->end()) 970249423Sdim continue; // Case label is preceded with a normal label, good. 971249423Sdim 972249423Sdim if (!ReachableBlocks.count(P)) { 973249423Sdim for (CFGBlock::const_reverse_iterator ElemIt = P->rbegin(), 974249423Sdim ElemEnd = P->rend(); 975249423Sdim ElemIt != ElemEnd; ++ElemIt) { 976249423Sdim if (Optional<CFGStmt> CS = ElemIt->getAs<CFGStmt>()) { 977239462Sdim if (const AttributedStmt *AS = asFallThroughAttr(CS->getStmt())) { 978239462Sdim S.Diag(AS->getLocStart(), 979239462Sdim diag::warn_fallthrough_attr_unreachable); 980239462Sdim markFallthroughVisited(AS); 981239462Sdim ++AnnotatedCnt; 982249423Sdim break; 983239462Sdim } 984239462Sdim // Don't care about other unreachable statements. 985239462Sdim } 986239462Sdim } 987239462Sdim // If there are no unreachable statements, this may be a special 988239462Sdim // case in CFG: 989239462Sdim // case X: { 990239462Sdim // A a; // A has a destructor. 991239462Sdim // break; 992239462Sdim // } 993239462Sdim // // <<<< This place is represented by a 'hanging' CFG block. 994239462Sdim // case Y: 995239462Sdim continue; 996239462Sdim } 997239462Sdim 998239462Sdim const Stmt *LastStmt = getLastStmt(*P); 999239462Sdim if (const AttributedStmt *AS = asFallThroughAttr(LastStmt)) { 1000239462Sdim markFallthroughVisited(AS); 1001239462Sdim ++AnnotatedCnt; 1002239462Sdim continue; // Fallthrough annotation, good. 1003239462Sdim } 1004239462Sdim 1005239462Sdim if (!LastStmt) { // This block contains no executable statements. 1006239462Sdim // Traverse its predecessors. 1007239462Sdim std::copy(P->pred_begin(), P->pred_end(), 1008239462Sdim std::back_inserter(BlockQueue)); 1009239462Sdim continue; 1010239462Sdim } 1011239462Sdim 1012239462Sdim ++UnannotatedCnt; 1013239462Sdim } 1014239462Sdim return !!UnannotatedCnt; 1015239462Sdim } 1016239462Sdim 1017239462Sdim // RecursiveASTVisitor setup. 1018239462Sdim bool shouldWalkTypesOfTypeLocs() const { return false; } 1019239462Sdim 1020239462Sdim bool VisitAttributedStmt(AttributedStmt *S) { 1021239462Sdim if (asFallThroughAttr(S)) 1022239462Sdim FallthroughStmts.insert(S); 1023239462Sdim return true; 1024239462Sdim } 1025239462Sdim 1026239462Sdim bool VisitSwitchStmt(SwitchStmt *S) { 1027239462Sdim FoundSwitchStatements = true; 1028239462Sdim return true; 1029239462Sdim } 1030239462Sdim 1031249423Sdim // We don't want to traverse local type declarations. We analyze their 1032249423Sdim // methods separately. 1033249423Sdim bool TraverseDecl(Decl *D) { return true; } 1034249423Sdim 1035276479Sdim // We analyze lambda bodies separately. Skip them here. 1036276479Sdim bool TraverseLambdaBody(LambdaExpr *LE) { return true; } 1037276479Sdim 1038239462Sdim private: 1039239462Sdim 1040239462Sdim static const AttributedStmt *asFallThroughAttr(const Stmt *S) { 1041239462Sdim if (const AttributedStmt *AS = dyn_cast_or_null<AttributedStmt>(S)) { 1042239462Sdim if (hasSpecificAttr<FallThroughAttr>(AS->getAttrs())) 1043239462Sdim return AS; 1044239462Sdim } 1045276479Sdim return nullptr; 1046239462Sdim } 1047239462Sdim 1048239462Sdim static const Stmt *getLastStmt(const CFGBlock &B) { 1049239462Sdim if (const Stmt *Term = B.getTerminator()) 1050239462Sdim return Term; 1051239462Sdim for (CFGBlock::const_reverse_iterator ElemIt = B.rbegin(), 1052239462Sdim ElemEnd = B.rend(); 1053239462Sdim ElemIt != ElemEnd; ++ElemIt) { 1054249423Sdim if (Optional<CFGStmt> CS = ElemIt->getAs<CFGStmt>()) 1055239462Sdim return CS->getStmt(); 1056239462Sdim } 1057239462Sdim // Workaround to detect a statement thrown out by CFGBuilder: 1058239462Sdim // case X: {} case Y: 1059239462Sdim // case X: ; case Y: 1060239462Sdim if (const SwitchCase *SW = dyn_cast_or_null<SwitchCase>(B.getLabel())) 1061239462Sdim if (!isa<SwitchCase>(SW->getSubStmt())) 1062239462Sdim return SW->getSubStmt(); 1063239462Sdim 1064276479Sdim return nullptr; 1065239462Sdim } 1066239462Sdim 1067239462Sdim bool FoundSwitchStatements; 1068239462Sdim AttrStmts FallthroughStmts; 1069239462Sdim Sema &S; 1070249423Sdim llvm::SmallPtrSet<const CFGBlock *, 16> ReachableBlocks; 1071239462Sdim }; 1072296417Sdim} // anonymous namespace 1073239462Sdim 1074239462Sdimstatic void DiagnoseSwitchLabelsFallthrough(Sema &S, AnalysisDeclContext &AC, 1075239462Sdim bool PerFunction) { 1076243830Sdim // Only perform this analysis when using C++11. There is no good workflow 1077243830Sdim // for this warning when not using C++11. There is no good way to silence 1078243830Sdim // the warning (no attribute is available) unless we are using C++11's support 1079243830Sdim // for generalized attributes. Once could use pragmas to silence the warning, 1080243830Sdim // but as a general solution that is gross and not in the spirit of this 1081243830Sdim // warning. 1082243830Sdim // 1083243830Sdim // NOTE: This an intermediate solution. There are on-going discussions on 1084243830Sdim // how to properly support this warning outside of C++11 with an annotation. 1085249423Sdim if (!AC.getASTContext().getLangOpts().CPlusPlus11) 1086243830Sdim return; 1087243830Sdim 1088239462Sdim FallthroughMapper FM(S); 1089239462Sdim FM.TraverseStmt(AC.getBody()); 1090239462Sdim 1091239462Sdim if (!FM.foundSwitchStatements()) 1092239462Sdim return; 1093239462Sdim 1094239462Sdim if (PerFunction && FM.getFallthroughStmts().empty()) 1095239462Sdim return; 1096239462Sdim 1097239462Sdim CFG *Cfg = AC.getCFG(); 1098239462Sdim 1099239462Sdim if (!Cfg) 1100239462Sdim return; 1101239462Sdim 1102249423Sdim FM.fillReachableBlocks(Cfg); 1103239462Sdim 1104296417Sdim for (const CFGBlock *B : llvm::reverse(*Cfg)) { 1105249423Sdim const Stmt *Label = B->getLabel(); 1106239462Sdim 1107239462Sdim if (!Label || !isa<SwitchCase>(Label)) 1108239462Sdim continue; 1109239462Sdim 1110249423Sdim int AnnotatedCnt; 1111249423Sdim 1112249423Sdim if (!FM.checkFallThroughIntoBlock(*B, AnnotatedCnt)) 1113239462Sdim continue; 1114239462Sdim 1115239462Sdim S.Diag(Label->getLocStart(), 1116239462Sdim PerFunction ? diag::warn_unannotated_fallthrough_per_function 1117239462Sdim : diag::warn_unannotated_fallthrough); 1118239462Sdim 1119239462Sdim if (!AnnotatedCnt) { 1120239462Sdim SourceLocation L = Label->getLocStart(); 1121239462Sdim if (L.isMacroID()) 1122239462Sdim continue; 1123249423Sdim if (S.getLangOpts().CPlusPlus11) { 1124249423Sdim const Stmt *Term = B->getTerminator(); 1125249423Sdim // Skip empty cases. 1126249423Sdim while (B->empty() && !Term && B->succ_size() == 1) { 1127249423Sdim B = *B->succ_begin(); 1128249423Sdim Term = B->getTerminator(); 1129249423Sdim } 1130249423Sdim if (!(B->empty() && Term && isa<BreakStmt>(Term))) { 1131243830Sdim Preprocessor &PP = S.getPreprocessor(); 1132243830Sdim TokenValue Tokens[] = { 1133243830Sdim tok::l_square, tok::l_square, PP.getIdentifierInfo("clang"), 1134243830Sdim tok::coloncolon, PP.getIdentifierInfo("fallthrough"), 1135243830Sdim tok::r_square, tok::r_square 1136243830Sdim }; 1137243830Sdim StringRef AnnotationSpelling = "[[clang::fallthrough]]"; 1138243830Sdim StringRef MacroName = PP.getLastMacroWithSpelling(L, Tokens); 1139243830Sdim if (!MacroName.empty()) 1140243830Sdim AnnotationSpelling = MacroName; 1141243830Sdim SmallString<64> TextToInsert(AnnotationSpelling); 1142243830Sdim TextToInsert += "; "; 1143239462Sdim S.Diag(L, diag::note_insert_fallthrough_fixit) << 1144243830Sdim AnnotationSpelling << 1145243830Sdim FixItHint::CreateInsertion(L, TextToInsert); 1146239462Sdim } 1147239462Sdim } 1148239462Sdim S.Diag(L, diag::note_insert_break_fixit) << 1149239462Sdim FixItHint::CreateInsertion(L, "break; "); 1150239462Sdim } 1151239462Sdim } 1152239462Sdim 1153276479Sdim for (const auto *F : FM.getFallthroughStmts()) 1154276479Sdim S.Diag(F->getLocStart(), diag::warn_fallthrough_attr_invalid_placement); 1155239462Sdim} 1156239462Sdim 1157243830Sdimstatic bool isInLoop(const ASTContext &Ctx, const ParentMap &PM, 1158243830Sdim const Stmt *S) { 1159243830Sdim assert(S); 1160243830Sdim 1161243830Sdim do { 1162243830Sdim switch (S->getStmtClass()) { 1163243830Sdim case Stmt::ForStmtClass: 1164243830Sdim case Stmt::WhileStmtClass: 1165243830Sdim case Stmt::CXXForRangeStmtClass: 1166243830Sdim case Stmt::ObjCForCollectionStmtClass: 1167243830Sdim return true; 1168243830Sdim case Stmt::DoStmtClass: { 1169243830Sdim const Expr *Cond = cast<DoStmt>(S)->getCond(); 1170243830Sdim llvm::APSInt Val; 1171243830Sdim if (!Cond->EvaluateAsInt(Val, Ctx)) 1172243830Sdim return true; 1173243830Sdim return Val.getBoolValue(); 1174243830Sdim } 1175243830Sdim default: 1176243830Sdim break; 1177243830Sdim } 1178243830Sdim } while ((S = PM.getParent(S))); 1179243830Sdim 1180243830Sdim return false; 1181243830Sdim} 1182243830Sdim 1183243830Sdimstatic void diagnoseRepeatedUseOfWeak(Sema &S, 1184243830Sdim const sema::FunctionScopeInfo *CurFn, 1185243830Sdim const Decl *D, 1186243830Sdim const ParentMap &PM) { 1187243830Sdim typedef sema::FunctionScopeInfo::WeakObjectProfileTy WeakObjectProfileTy; 1188243830Sdim typedef sema::FunctionScopeInfo::WeakObjectUseMap WeakObjectUseMap; 1189243830Sdim typedef sema::FunctionScopeInfo::WeakUseVector WeakUseVector; 1190276479Sdim typedef std::pair<const Stmt *, WeakObjectUseMap::const_iterator> 1191276479Sdim StmtUsesPair; 1192243830Sdim 1193243830Sdim ASTContext &Ctx = S.getASTContext(); 1194243830Sdim 1195243830Sdim const WeakObjectUseMap &WeakMap = CurFn->getWeakObjectUses(); 1196243830Sdim 1197243830Sdim // Extract all weak objects that are referenced more than once. 1198243830Sdim SmallVector<StmtUsesPair, 8> UsesByStmt; 1199243830Sdim for (WeakObjectUseMap::const_iterator I = WeakMap.begin(), E = WeakMap.end(); 1200243830Sdim I != E; ++I) { 1201243830Sdim const WeakUseVector &Uses = I->second; 1202243830Sdim 1203243830Sdim // Find the first read of the weak object. 1204243830Sdim WeakUseVector::const_iterator UI = Uses.begin(), UE = Uses.end(); 1205243830Sdim for ( ; UI != UE; ++UI) { 1206243830Sdim if (UI->isUnsafe()) 1207243830Sdim break; 1208243830Sdim } 1209243830Sdim 1210243830Sdim // If there were only writes to this object, don't warn. 1211243830Sdim if (UI == UE) 1212243830Sdim continue; 1213243830Sdim 1214243830Sdim // If there was only one read, followed by any number of writes, and the 1215243830Sdim // read is not within a loop, don't warn. Additionally, don't warn in a 1216243830Sdim // loop if the base object is a local variable -- local variables are often 1217243830Sdim // changed in loops. 1218243830Sdim if (UI == Uses.begin()) { 1219243830Sdim WeakUseVector::const_iterator UI2 = UI; 1220243830Sdim for (++UI2; UI2 != UE; ++UI2) 1221243830Sdim if (UI2->isUnsafe()) 1222243830Sdim break; 1223243830Sdim 1224243830Sdim if (UI2 == UE) { 1225243830Sdim if (!isInLoop(Ctx, PM, UI->getUseExpr())) 1226243830Sdim continue; 1227243830Sdim 1228243830Sdim const WeakObjectProfileTy &Profile = I->first; 1229243830Sdim if (!Profile.isExactProfile()) 1230243830Sdim continue; 1231243830Sdim 1232243830Sdim const NamedDecl *Base = Profile.getBase(); 1233243830Sdim if (!Base) 1234243830Sdim Base = Profile.getProperty(); 1235243830Sdim assert(Base && "A profile always has a base or property."); 1236243830Sdim 1237243830Sdim if (const VarDecl *BaseVar = dyn_cast<VarDecl>(Base)) 1238243830Sdim if (BaseVar->hasLocalStorage() && !isa<ParmVarDecl>(Base)) 1239243830Sdim continue; 1240243830Sdim } 1241243830Sdim } 1242243830Sdim 1243243830Sdim UsesByStmt.push_back(StmtUsesPair(UI->getUseExpr(), I)); 1244243830Sdim } 1245243830Sdim 1246243830Sdim if (UsesByStmt.empty()) 1247243830Sdim return; 1248243830Sdim 1249243830Sdim // Sort by first use so that we emit the warnings in a deterministic order. 1250276479Sdim SourceManager &SM = S.getSourceManager(); 1251243830Sdim std::sort(UsesByStmt.begin(), UsesByStmt.end(), 1252276479Sdim [&SM](const StmtUsesPair &LHS, const StmtUsesPair &RHS) { 1253276479Sdim return SM.isBeforeInTranslationUnit(LHS.first->getLocStart(), 1254276479Sdim RHS.first->getLocStart()); 1255276479Sdim }); 1256243830Sdim 1257243830Sdim // Classify the current code body for better warning text. 1258243830Sdim // This enum should stay in sync with the cases in 1259243830Sdim // warn_arc_repeated_use_of_weak and warn_arc_possible_repeated_use_of_weak. 1260243830Sdim // FIXME: Should we use a common classification enum and the same set of 1261243830Sdim // possibilities all throughout Sema? 1262243830Sdim enum { 1263243830Sdim Function, 1264243830Sdim Method, 1265243830Sdim Block, 1266243830Sdim Lambda 1267243830Sdim } FunctionKind; 1268243830Sdim 1269243830Sdim if (isa<sema::BlockScopeInfo>(CurFn)) 1270243830Sdim FunctionKind = Block; 1271243830Sdim else if (isa<sema::LambdaScopeInfo>(CurFn)) 1272243830Sdim FunctionKind = Lambda; 1273243830Sdim else if (isa<ObjCMethodDecl>(D)) 1274243830Sdim FunctionKind = Method; 1275243830Sdim else 1276243830Sdim FunctionKind = Function; 1277243830Sdim 1278243830Sdim // Iterate through the sorted problems and emit warnings for each. 1279276479Sdim for (const auto &P : UsesByStmt) { 1280276479Sdim const Stmt *FirstRead = P.first; 1281276479Sdim const WeakObjectProfileTy &Key = P.second->first; 1282276479Sdim const WeakUseVector &Uses = P.second->second; 1283243830Sdim 1284243830Sdim // For complicated expressions like 'a.b.c' and 'x.b.c', WeakObjectProfileTy 1285243830Sdim // may not contain enough information to determine that these are different 1286243830Sdim // properties. We can only be 100% sure of a repeated use in certain cases, 1287243830Sdim // and we adjust the diagnostic kind accordingly so that the less certain 1288243830Sdim // case can be turned off if it is too noisy. 1289243830Sdim unsigned DiagKind; 1290243830Sdim if (Key.isExactProfile()) 1291243830Sdim DiagKind = diag::warn_arc_repeated_use_of_weak; 1292243830Sdim else 1293243830Sdim DiagKind = diag::warn_arc_possible_repeated_use_of_weak; 1294243830Sdim 1295243830Sdim // Classify the weak object being accessed for better warning text. 1296243830Sdim // This enum should stay in sync with the cases in 1297243830Sdim // warn_arc_repeated_use_of_weak and warn_arc_possible_repeated_use_of_weak. 1298243830Sdim enum { 1299243830Sdim Variable, 1300243830Sdim Property, 1301243830Sdim ImplicitProperty, 1302243830Sdim Ivar 1303243830Sdim } ObjectKind; 1304243830Sdim 1305243830Sdim const NamedDecl *D = Key.getProperty(); 1306243830Sdim if (isa<VarDecl>(D)) 1307243830Sdim ObjectKind = Variable; 1308243830Sdim else if (isa<ObjCPropertyDecl>(D)) 1309243830Sdim ObjectKind = Property; 1310243830Sdim else if (isa<ObjCMethodDecl>(D)) 1311243830Sdim ObjectKind = ImplicitProperty; 1312243830Sdim else if (isa<ObjCIvarDecl>(D)) 1313243830Sdim ObjectKind = Ivar; 1314243830Sdim else 1315243830Sdim llvm_unreachable("Unexpected weak object kind!"); 1316243830Sdim 1317243830Sdim // Show the first time the object was read. 1318243830Sdim S.Diag(FirstRead->getLocStart(), DiagKind) 1319261991Sdim << int(ObjectKind) << D << int(FunctionKind) 1320243830Sdim << FirstRead->getSourceRange(); 1321243830Sdim 1322243830Sdim // Print all the other accesses as notes. 1323276479Sdim for (const auto &Use : Uses) { 1324276479Sdim if (Use.getUseExpr() == FirstRead) 1325243830Sdim continue; 1326276479Sdim S.Diag(Use.getUseExpr()->getLocStart(), 1327243830Sdim diag::note_arc_weak_also_accessed_here) 1328276479Sdim << Use.getUseExpr()->getSourceRange(); 1329243830Sdim } 1330243830Sdim } 1331243830Sdim} 1332243830Sdim 1333243830Sdimnamespace { 1334218893Sdimclass UninitValsDiagReporter : public UninitVariablesHandler { 1335218893Sdim Sema &S; 1336226633Sdim typedef SmallVector<UninitUse, 2> UsesVec; 1337261991Sdim typedef llvm::PointerIntPair<UsesVec *, 1, bool> MappedType; 1338249423Sdim // Prefer using MapVector to DenseMap, so that iteration order will be 1339249423Sdim // the same as insertion order. This is needed to obtain a deterministic 1340249423Sdim // order of diagnostics when calling flushDiagnostics(). 1341249423Sdim typedef llvm::MapVector<const VarDecl *, MappedType> UsesMap; 1342296417Sdim UsesMap uses; 1343218893Sdim 1344218893Sdimpublic: 1345296417Sdim UninitValsDiagReporter(Sema &S) : S(S) {} 1346288943Sdim ~UninitValsDiagReporter() override { flushDiagnostics(); } 1347226633Sdim 1348249423Sdim MappedType &getUses(const VarDecl *vd) { 1349296417Sdim MappedType &V = uses[vd]; 1350261991Sdim if (!V.getPointer()) 1351261991Sdim V.setPointer(new UsesVec()); 1352226633Sdim return V; 1353218893Sdim } 1354276479Sdim 1355276479Sdim void handleUseOfUninitVariable(const VarDecl *vd, 1356276479Sdim const UninitUse &use) override { 1357261991Sdim getUses(vd).getPointer()->push_back(use); 1358226633Sdim } 1359226633Sdim 1360276479Sdim void handleSelfInit(const VarDecl *vd) override { 1361261991Sdim getUses(vd).setInt(true); 1362226633Sdim } 1363226633Sdim 1364218893Sdim void flushDiagnostics() { 1365296417Sdim for (const auto &P : uses) { 1366276479Sdim const VarDecl *vd = P.first; 1367276479Sdim const MappedType &V = P.second; 1368218893Sdim 1369261991Sdim UsesVec *vec = V.getPointer(); 1370261991Sdim bool hasSelfInit = V.getInt(); 1371218893Sdim 1372226633Sdim // Specially handle the case where we have uses of an uninitialized 1373226633Sdim // variable, but the root cause is an idiomatic self-init. We want 1374226633Sdim // to report the diagnostic at the self-init since that is the root cause. 1375234353Sdim if (!vec->empty() && hasSelfInit && hasAlwaysUninitializedUse(vec)) 1376239462Sdim DiagnoseUninitializedUse(S, vd, 1377239462Sdim UninitUse(vd->getInit()->IgnoreParenCasts(), 1378239462Sdim /* isAlwaysUninit */ true), 1379234353Sdim /* alwaysReportSelfInit */ true); 1380226633Sdim else { 1381226633Sdim // Sort the uses by their SourceLocations. While not strictly 1382226633Sdim // guaranteed to produce them in line/column order, this will provide 1383226633Sdim // a stable ordering. 1384276479Sdim std::sort(vec->begin(), vec->end(), 1385276479Sdim [](const UninitUse &a, const UninitUse &b) { 1386276479Sdim // Prefer a more confident report over a less confident one. 1387276479Sdim if (a.getKind() != b.getKind()) 1388276479Sdim return a.getKind() > b.getKind(); 1389276479Sdim return a.getUser()->getLocStart() < b.getUser()->getLocStart(); 1390276479Sdim }); 1391276479Sdim 1392276479Sdim for (const auto &U : *vec) { 1393239462Sdim // If we have self-init, downgrade all uses to 'may be uninitialized'. 1394276479Sdim UninitUse Use = hasSelfInit ? UninitUse(U.getUser(), false) : U; 1395239462Sdim 1396239462Sdim if (DiagnoseUninitializedUse(S, vd, Use)) 1397226633Sdim // Skip further diagnostics for this variable. We try to warn only 1398226633Sdim // on the first point at which a variable is used uninitialized. 1399226633Sdim break; 1400218893Sdim } 1401218893Sdim } 1402226633Sdim 1403226633Sdim // Release the uses vector. 1404218893Sdim delete vec; 1405218893Sdim } 1406296417Sdim 1407296417Sdim uses.clear(); 1408218893Sdim } 1409234353Sdim 1410234353Sdimprivate: 1411234353Sdim static bool hasAlwaysUninitializedUse(const UsesVec* vec) { 1412276479Sdim return std::any_of(vec->begin(), vec->end(), [](const UninitUse &U) { 1413276479Sdim return U.getKind() == UninitUse::Always || 1414276479Sdim U.getKind() == UninitUse::AfterCall || 1415276479Sdim U.getKind() == UninitUse::AfterDecl; 1416276479Sdim }); 1417234353Sdim } 1418218893Sdim}; 1419296417Sdim} // anonymous namespace 1420218893Sdim 1421226633Sdimnamespace clang { 1422261991Sdimnamespace { 1423249423Sdimtypedef SmallVector<PartialDiagnosticAt, 1> OptionalNotes; 1424234353Sdimtypedef std::pair<PartialDiagnosticAt, OptionalNotes> DelayedDiag; 1425234353Sdimtypedef std::list<DelayedDiag> DiagList; 1426226633Sdim 1427226633Sdimstruct SortDiagBySourceLocation { 1428234353Sdim SourceManager &SM; 1429234353Sdim SortDiagBySourceLocation(SourceManager &SM) : SM(SM) {} 1430226633Sdim 1431226633Sdim bool operator()(const DelayedDiag &left, const DelayedDiag &right) { 1432226633Sdim // Although this call will be slow, this is only called when outputting 1433226633Sdim // multiple warnings. 1434234353Sdim return SM.isBeforeInTranslationUnit(left.first.first, right.first.first); 1435226633Sdim } 1436226633Sdim}; 1437296417Sdim} // anonymous namespace 1438296417Sdim} // namespace clang 1439226633Sdim 1440261991Sdim//===----------------------------------------------------------------------===// 1441261991Sdim// -Wthread-safety 1442261991Sdim//===----------------------------------------------------------------------===// 1443261991Sdimnamespace clang { 1444280031Sdimnamespace threadSafety { 1445288943Sdimnamespace { 1446280031Sdimclass ThreadSafetyReporter : public clang::threadSafety::ThreadSafetyHandler { 1447226633Sdim Sema &S; 1448226633Sdim DiagList Warnings; 1449234353Sdim SourceLocation FunLocation, FunEndLocation; 1450226633Sdim 1451280031Sdim const FunctionDecl *CurrentFunction; 1452280031Sdim bool Verbose; 1453280031Sdim 1454280031Sdim OptionalNotes getNotes() const { 1455280031Sdim if (Verbose && CurrentFunction) { 1456280031Sdim PartialDiagnosticAt FNote(CurrentFunction->getBody()->getLocStart(), 1457280031Sdim S.PDiag(diag::note_thread_warning_in_fun) 1458280031Sdim << CurrentFunction->getNameAsString()); 1459280031Sdim return OptionalNotes(1, FNote); 1460280031Sdim } 1461280031Sdim return OptionalNotes(); 1462280031Sdim } 1463280031Sdim 1464280031Sdim OptionalNotes getNotes(const PartialDiagnosticAt &Note) const { 1465280031Sdim OptionalNotes ONS(1, Note); 1466280031Sdim if (Verbose && CurrentFunction) { 1467280031Sdim PartialDiagnosticAt FNote(CurrentFunction->getBody()->getLocStart(), 1468280031Sdim S.PDiag(diag::note_thread_warning_in_fun) 1469280031Sdim << CurrentFunction->getNameAsString()); 1470288943Sdim ONS.push_back(std::move(FNote)); 1471280031Sdim } 1472280031Sdim return ONS; 1473280031Sdim } 1474280031Sdim 1475280031Sdim OptionalNotes getNotes(const PartialDiagnosticAt &Note1, 1476280031Sdim const PartialDiagnosticAt &Note2) const { 1477280031Sdim OptionalNotes ONS; 1478280031Sdim ONS.push_back(Note1); 1479280031Sdim ONS.push_back(Note2); 1480280031Sdim if (Verbose && CurrentFunction) { 1481280031Sdim PartialDiagnosticAt FNote(CurrentFunction->getBody()->getLocStart(), 1482280031Sdim S.PDiag(diag::note_thread_warning_in_fun) 1483280031Sdim << CurrentFunction->getNameAsString()); 1484288943Sdim ONS.push_back(std::move(FNote)); 1485280031Sdim } 1486280031Sdim return ONS; 1487280031Sdim } 1488280031Sdim 1489226633Sdim // Helper functions 1490276479Sdim void warnLockMismatch(unsigned DiagID, StringRef Kind, Name LockName, 1491276479Sdim SourceLocation Loc) { 1492234353Sdim // Gracefully handle rare cases when the analysis can't get a more 1493234353Sdim // precise source location. 1494234353Sdim if (!Loc.isValid()) 1495234353Sdim Loc = FunLocation; 1496276479Sdim PartialDiagnosticAt Warning(Loc, S.PDiag(DiagID) << Kind << LockName); 1497288943Sdim Warnings.emplace_back(std::move(Warning), getNotes()); 1498226633Sdim } 1499226633Sdim 1500226633Sdim public: 1501234353Sdim ThreadSafetyReporter(Sema &S, SourceLocation FL, SourceLocation FEL) 1502280031Sdim : S(S), FunLocation(FL), FunEndLocation(FEL), 1503280031Sdim CurrentFunction(nullptr), Verbose(false) {} 1504226633Sdim 1505280031Sdim void setVerbose(bool b) { Verbose = b; } 1506280031Sdim 1507226633Sdim /// \brief Emit all buffered diagnostics in order of sourcelocation. 1508226633Sdim /// We need to output diagnostics produced while iterating through 1509226633Sdim /// the lockset in deterministic order, so this function orders diagnostics 1510226633Sdim /// and outputs them. 1511226633Sdim void emitDiagnostics() { 1512234353Sdim Warnings.sort(SortDiagBySourceLocation(S.getSourceManager())); 1513276479Sdim for (const auto &Diag : Warnings) { 1514276479Sdim S.Diag(Diag.first.first, Diag.first.second); 1515276479Sdim for (const auto &Note : Diag.second) 1516276479Sdim S.Diag(Note.first, Note.second); 1517234353Sdim } 1518226633Sdim } 1519226633Sdim 1520276479Sdim void handleInvalidLockExp(StringRef Kind, SourceLocation Loc) override { 1521276479Sdim PartialDiagnosticAt Warning(Loc, S.PDiag(diag::warn_cannot_resolve_lock) 1522276479Sdim << Loc); 1523288943Sdim Warnings.emplace_back(std::move(Warning), getNotes()); 1524226633Sdim } 1525280031Sdim 1526276479Sdim void handleUnmatchedUnlock(StringRef Kind, Name LockName, 1527276479Sdim SourceLocation Loc) override { 1528276479Sdim warnLockMismatch(diag::warn_unlock_but_no_lock, Kind, LockName, Loc); 1529226633Sdim } 1530280031Sdim 1531276479Sdim void handleIncorrectUnlockKind(StringRef Kind, Name LockName, 1532276479Sdim LockKind Expected, LockKind Received, 1533276479Sdim SourceLocation Loc) override { 1534276479Sdim if (Loc.isInvalid()) 1535276479Sdim Loc = FunLocation; 1536276479Sdim PartialDiagnosticAt Warning(Loc, S.PDiag(diag::warn_unlock_kind_mismatch) 1537276479Sdim << Kind << LockName << Received 1538276479Sdim << Expected); 1539288943Sdim Warnings.emplace_back(std::move(Warning), getNotes()); 1540226633Sdim } 1541280031Sdim 1542276479Sdim void handleDoubleLock(StringRef Kind, Name LockName, SourceLocation Loc) override { 1543276479Sdim warnLockMismatch(diag::warn_double_lock, Kind, LockName, Loc); 1544276479Sdim } 1545226633Sdim 1546276479Sdim void handleMutexHeldEndOfScope(StringRef Kind, Name LockName, 1547276479Sdim SourceLocation LocLocked, 1548234353Sdim SourceLocation LocEndOfScope, 1549276479Sdim LockErrorKind LEK) override { 1550226633Sdim unsigned DiagID = 0; 1551226633Sdim switch (LEK) { 1552226633Sdim case LEK_LockedSomePredecessors: 1553234353Sdim DiagID = diag::warn_lock_some_predecessors; 1554226633Sdim break; 1555226633Sdim case LEK_LockedSomeLoopIterations: 1556226633Sdim DiagID = diag::warn_expecting_lock_held_on_loop; 1557226633Sdim break; 1558226633Sdim case LEK_LockedAtEndOfFunction: 1559226633Sdim DiagID = diag::warn_no_unlock; 1560226633Sdim break; 1561239462Sdim case LEK_NotLockedAtEndOfFunction: 1562239462Sdim DiagID = diag::warn_expecting_locked; 1563239462Sdim break; 1564226633Sdim } 1565234353Sdim if (LocEndOfScope.isInvalid()) 1566234353Sdim LocEndOfScope = FunEndLocation; 1567234353Sdim 1568276479Sdim PartialDiagnosticAt Warning(LocEndOfScope, S.PDiag(DiagID) << Kind 1569276479Sdim << LockName); 1570251662Sdim if (LocLocked.isValid()) { 1571276479Sdim PartialDiagnosticAt Note(LocLocked, S.PDiag(diag::note_locked_here) 1572276479Sdim << Kind); 1573288943Sdim Warnings.emplace_back(std::move(Warning), getNotes(Note)); 1574251662Sdim return; 1575251662Sdim } 1576288943Sdim Warnings.emplace_back(std::move(Warning), getNotes()); 1577226633Sdim } 1578226633Sdim 1579276479Sdim void handleExclusiveAndShared(StringRef Kind, Name LockName, 1580276479Sdim SourceLocation Loc1, 1581276479Sdim SourceLocation Loc2) override { 1582276479Sdim PartialDiagnosticAt Warning(Loc1, 1583276479Sdim S.PDiag(diag::warn_lock_exclusive_and_shared) 1584276479Sdim << Kind << LockName); 1585276479Sdim PartialDiagnosticAt Note(Loc2, S.PDiag(diag::note_lock_exclusive_and_shared) 1586276479Sdim << Kind << LockName); 1587288943Sdim Warnings.emplace_back(std::move(Warning), getNotes(Note)); 1588226633Sdim } 1589226633Sdim 1590276479Sdim void handleNoMutexHeld(StringRef Kind, const NamedDecl *D, 1591276479Sdim ProtectedOperationKind POK, AccessKind AK, 1592276479Sdim SourceLocation Loc) override { 1593276479Sdim assert((POK == POK_VarAccess || POK == POK_VarDereference) && 1594276479Sdim "Only works for variables"); 1595226633Sdim unsigned DiagID = POK == POK_VarAccess? 1596226633Sdim diag::warn_variable_requires_any_lock: 1597226633Sdim diag::warn_var_deref_requires_any_lock; 1598234353Sdim PartialDiagnosticAt Warning(Loc, S.PDiag(DiagID) 1599243830Sdim << D->getNameAsString() << getLockKindFromAccessKind(AK)); 1600288943Sdim Warnings.emplace_back(std::move(Warning), getNotes()); 1601226633Sdim } 1602226633Sdim 1603276479Sdim void handleMutexNotHeld(StringRef Kind, const NamedDecl *D, 1604276479Sdim ProtectedOperationKind POK, Name LockName, 1605276479Sdim LockKind LK, SourceLocation Loc, 1606276479Sdim Name *PossibleMatch) override { 1607226633Sdim unsigned DiagID = 0; 1608243830Sdim if (PossibleMatch) { 1609243830Sdim switch (POK) { 1610243830Sdim case POK_VarAccess: 1611243830Sdim DiagID = diag::warn_variable_requires_lock_precise; 1612243830Sdim break; 1613243830Sdim case POK_VarDereference: 1614243830Sdim DiagID = diag::warn_var_deref_requires_lock_precise; 1615243830Sdim break; 1616243830Sdim case POK_FunctionCall: 1617243830Sdim DiagID = diag::warn_fun_requires_lock_precise; 1618243830Sdim break; 1619280031Sdim case POK_PassByRef: 1620280031Sdim DiagID = diag::warn_guarded_pass_by_reference; 1621280031Sdim break; 1622280031Sdim case POK_PtPassByRef: 1623280031Sdim DiagID = diag::warn_pt_guarded_pass_by_reference; 1624280031Sdim break; 1625243830Sdim } 1626276479Sdim PartialDiagnosticAt Warning(Loc, S.PDiag(DiagID) << Kind 1627276479Sdim << D->getNameAsString() 1628276479Sdim << LockName << LK); 1629243830Sdim PartialDiagnosticAt Note(Loc, S.PDiag(diag::note_found_mutex_near_match) 1630276479Sdim << *PossibleMatch); 1631280031Sdim if (Verbose && POK == POK_VarAccess) { 1632280031Sdim PartialDiagnosticAt VNote(D->getLocation(), 1633280031Sdim S.PDiag(diag::note_guarded_by_declared_here) 1634280031Sdim << D->getNameAsString()); 1635288943Sdim Warnings.emplace_back(std::move(Warning), getNotes(Note, VNote)); 1636280031Sdim } else 1637288943Sdim Warnings.emplace_back(std::move(Warning), getNotes(Note)); 1638243830Sdim } else { 1639243830Sdim switch (POK) { 1640243830Sdim case POK_VarAccess: 1641243830Sdim DiagID = diag::warn_variable_requires_lock; 1642243830Sdim break; 1643243830Sdim case POK_VarDereference: 1644243830Sdim DiagID = diag::warn_var_deref_requires_lock; 1645243830Sdim break; 1646243830Sdim case POK_FunctionCall: 1647243830Sdim DiagID = diag::warn_fun_requires_lock; 1648243830Sdim break; 1649280031Sdim case POK_PassByRef: 1650280031Sdim DiagID = diag::warn_guarded_pass_by_reference; 1651280031Sdim break; 1652280031Sdim case POK_PtPassByRef: 1653280031Sdim DiagID = diag::warn_pt_guarded_pass_by_reference; 1654280031Sdim break; 1655243830Sdim } 1656276479Sdim PartialDiagnosticAt Warning(Loc, S.PDiag(DiagID) << Kind 1657276479Sdim << D->getNameAsString() 1658276479Sdim << LockName << LK); 1659280031Sdim if (Verbose && POK == POK_VarAccess) { 1660280031Sdim PartialDiagnosticAt Note(D->getLocation(), 1661280031Sdim S.PDiag(diag::note_guarded_by_declared_here) 1662280031Sdim << D->getNameAsString()); 1663288943Sdim Warnings.emplace_back(std::move(Warning), getNotes(Note)); 1664280031Sdim } else 1665288943Sdim Warnings.emplace_back(std::move(Warning), getNotes()); 1666226633Sdim } 1667226633Sdim } 1668226633Sdim 1669288943Sdim void handleNegativeNotHeld(StringRef Kind, Name LockName, Name Neg, 1670288943Sdim SourceLocation Loc) override { 1671280031Sdim PartialDiagnosticAt Warning(Loc, 1672280031Sdim S.PDiag(diag::warn_acquire_requires_negative_cap) 1673280031Sdim << Kind << LockName << Neg); 1674288943Sdim Warnings.emplace_back(std::move(Warning), getNotes()); 1675280031Sdim } 1676280031Sdim 1677276479Sdim void handleFunExcludesLock(StringRef Kind, Name FunName, Name LockName, 1678276479Sdim SourceLocation Loc) override { 1679276479Sdim PartialDiagnosticAt Warning(Loc, S.PDiag(diag::warn_fun_excludes_mutex) 1680276479Sdim << Kind << FunName << LockName); 1681288943Sdim Warnings.emplace_back(std::move(Warning), getNotes()); 1682226633Sdim } 1683280031Sdim 1684288943Sdim void handleLockAcquiredBefore(StringRef Kind, Name L1Name, Name L2Name, 1685288943Sdim SourceLocation Loc) override { 1686288943Sdim PartialDiagnosticAt Warning(Loc, 1687288943Sdim S.PDiag(diag::warn_acquired_before) << Kind << L1Name << L2Name); 1688288943Sdim Warnings.emplace_back(std::move(Warning), getNotes()); 1689288943Sdim } 1690288943Sdim 1691288943Sdim void handleBeforeAfterCycle(Name L1Name, SourceLocation Loc) override { 1692288943Sdim PartialDiagnosticAt Warning(Loc, 1693288943Sdim S.PDiag(diag::warn_acquired_before_after_cycle) << L1Name); 1694288943Sdim Warnings.emplace_back(std::move(Warning), getNotes()); 1695288943Sdim } 1696288943Sdim 1697280031Sdim void enterFunction(const FunctionDecl* FD) override { 1698280031Sdim CurrentFunction = FD; 1699280031Sdim } 1700280031Sdim 1701280031Sdim void leaveFunction(const FunctionDecl* FD) override { 1702296417Sdim CurrentFunction = nullptr; 1703280031Sdim } 1704226633Sdim}; 1705296417Sdim} // anonymous namespace 1706288943Sdim} // namespace threadSafety 1707288943Sdim} // namespace clang 1708280031Sdim 1709226633Sdim//===----------------------------------------------------------------------===// 1710261991Sdim// -Wconsumed 1711261991Sdim//===----------------------------------------------------------------------===// 1712261991Sdim 1713261991Sdimnamespace clang { 1714261991Sdimnamespace consumed { 1715261991Sdimnamespace { 1716261991Sdimclass ConsumedWarningsHandler : public ConsumedWarningsHandlerBase { 1717261991Sdim 1718261991Sdim Sema &S; 1719261991Sdim DiagList Warnings; 1720261991Sdim 1721261991Sdimpublic: 1722288943Sdim 1723261991Sdim ConsumedWarningsHandler(Sema &S) : S(S) {} 1724276479Sdim 1725276479Sdim void emitDiagnostics() override { 1726261991Sdim Warnings.sort(SortDiagBySourceLocation(S.getSourceManager())); 1727276479Sdim for (const auto &Diag : Warnings) { 1728276479Sdim S.Diag(Diag.first.first, Diag.first.second); 1729276479Sdim for (const auto &Note : Diag.second) 1730276479Sdim S.Diag(Note.first, Note.second); 1731261991Sdim } 1732261991Sdim } 1733276479Sdim 1734276479Sdim void warnLoopStateMismatch(SourceLocation Loc, 1735276479Sdim StringRef VariableName) override { 1736261991Sdim PartialDiagnosticAt Warning(Loc, S.PDiag(diag::warn_loop_state_mismatch) << 1737261991Sdim VariableName); 1738288943Sdim 1739288943Sdim Warnings.emplace_back(std::move(Warning), OptionalNotes()); 1740261991Sdim } 1741261991Sdim 1742261991Sdim void warnParamReturnTypestateMismatch(SourceLocation Loc, 1743261991Sdim StringRef VariableName, 1744261991Sdim StringRef ExpectedState, 1745276479Sdim StringRef ObservedState) override { 1746261991Sdim 1747261991Sdim PartialDiagnosticAt Warning(Loc, S.PDiag( 1748261991Sdim diag::warn_param_return_typestate_mismatch) << VariableName << 1749261991Sdim ExpectedState << ObservedState); 1750288943Sdim 1751288943Sdim Warnings.emplace_back(std::move(Warning), OptionalNotes()); 1752261991Sdim } 1753261991Sdim 1754261991Sdim void warnParamTypestateMismatch(SourceLocation Loc, StringRef ExpectedState, 1755276479Sdim StringRef ObservedState) override { 1756261991Sdim 1757261991Sdim PartialDiagnosticAt Warning(Loc, S.PDiag( 1758261991Sdim diag::warn_param_typestate_mismatch) << ExpectedState << ObservedState); 1759288943Sdim 1760288943Sdim Warnings.emplace_back(std::move(Warning), OptionalNotes()); 1761261991Sdim } 1762261991Sdim 1763261991Sdim void warnReturnTypestateForUnconsumableType(SourceLocation Loc, 1764276479Sdim StringRef TypeName) override { 1765261991Sdim PartialDiagnosticAt Warning(Loc, S.PDiag( 1766261991Sdim diag::warn_return_typestate_for_unconsumable_type) << TypeName); 1767288943Sdim 1768288943Sdim Warnings.emplace_back(std::move(Warning), OptionalNotes()); 1769261991Sdim } 1770261991Sdim 1771261991Sdim void warnReturnTypestateMismatch(SourceLocation Loc, StringRef ExpectedState, 1772276479Sdim StringRef ObservedState) override { 1773261991Sdim 1774261991Sdim PartialDiagnosticAt Warning(Loc, S.PDiag( 1775261991Sdim diag::warn_return_typestate_mismatch) << ExpectedState << ObservedState); 1776288943Sdim 1777288943Sdim Warnings.emplace_back(std::move(Warning), OptionalNotes()); 1778261991Sdim } 1779261991Sdim 1780261991Sdim void warnUseOfTempInInvalidState(StringRef MethodName, StringRef State, 1781276479Sdim SourceLocation Loc) override { 1782261991Sdim 1783261991Sdim PartialDiagnosticAt Warning(Loc, S.PDiag( 1784261991Sdim diag::warn_use_of_temp_in_invalid_state) << MethodName << State); 1785288943Sdim 1786288943Sdim Warnings.emplace_back(std::move(Warning), OptionalNotes()); 1787261991Sdim } 1788261991Sdim 1789261991Sdim void warnUseInInvalidState(StringRef MethodName, StringRef VariableName, 1790276479Sdim StringRef State, SourceLocation Loc) override { 1791261991Sdim 1792261991Sdim PartialDiagnosticAt Warning(Loc, S.PDiag(diag::warn_use_in_invalid_state) << 1793261991Sdim MethodName << VariableName << State); 1794288943Sdim 1795288943Sdim Warnings.emplace_back(std::move(Warning), OptionalNotes()); 1796261991Sdim } 1797261991Sdim}; 1798296417Sdim} // anonymous namespace 1799296417Sdim} // namespace consumed 1800296417Sdim} // namespace clang 1801261991Sdim 1802261991Sdim//===----------------------------------------------------------------------===// 1803205408Srdivacky// AnalysisBasedWarnings - Worker object used by Sema to execute analysis-based 1804205408Srdivacky// warnings on a function, method, or block. 1805205408Srdivacky//===----------------------------------------------------------------------===// 1806205408Srdivacky 1807206084Srdivackyclang::sema::AnalysisBasedWarnings::Policy::Policy() { 1808206084Srdivacky enableCheckFallThrough = 1; 1809206084Srdivacky enableCheckUnreachable = 0; 1810226633Sdim enableThreadSafetyAnalysis = 0; 1811261991Sdim enableConsumedAnalysis = 0; 1812206084Srdivacky} 1813206084Srdivacky 1814276479Sdimstatic unsigned isEnabled(DiagnosticsEngine &D, unsigned diag) { 1815276479Sdim return (unsigned)!D.isIgnored(diag, SourceLocation()); 1816276479Sdim} 1817276479Sdim 1818224145Sdimclang::sema::AnalysisBasedWarnings::AnalysisBasedWarnings(Sema &s) 1819224145Sdim : S(s), 1820224145Sdim NumFunctionsAnalyzed(0), 1821224145Sdim NumFunctionsWithBadCFGs(0), 1822224145Sdim NumCFGBlocks(0), 1823224145Sdim MaxCFGBlocksPerFunction(0), 1824224145Sdim NumUninitAnalysisFunctions(0), 1825224145Sdim NumUninitAnalysisVariables(0), 1826224145Sdim MaxUninitAnalysisVariablesPerFunction(0), 1827224145Sdim NumUninitAnalysisBlockVisits(0), 1828224145Sdim MaxUninitAnalysisBlockVisitsPerFunction(0) { 1829276479Sdim 1830276479Sdim using namespace diag; 1831226633Sdim DiagnosticsEngine &D = S.getDiagnostics(); 1832276479Sdim 1833276479Sdim DefaultPolicy.enableCheckUnreachable = 1834276479Sdim isEnabled(D, warn_unreachable) || 1835276479Sdim isEnabled(D, warn_unreachable_break) || 1836276479Sdim isEnabled(D, warn_unreachable_return) || 1837276479Sdim isEnabled(D, warn_unreachable_loop_increment); 1838276479Sdim 1839276479Sdim DefaultPolicy.enableThreadSafetyAnalysis = 1840276479Sdim isEnabled(D, warn_double_lock); 1841276479Sdim 1842276479Sdim DefaultPolicy.enableConsumedAnalysis = 1843276479Sdim isEnabled(D, warn_use_in_invalid_state); 1844205408Srdivacky} 1845205408Srdivacky 1846276479Sdimstatic void flushDiagnostics(Sema &S, const sema::FunctionScopeInfo *fscope) { 1847276479Sdim for (const auto &D : fscope->PossiblyUnreachableDiags) 1848219077Sdim S.Diag(D.Loc, D.PD); 1849219077Sdim} 1850219077Sdim 1851206084Srdivackyvoid clang::sema:: 1852206084SrdivackyAnalysisBasedWarnings::IssueWarnings(sema::AnalysisBasedWarnings::Policy P, 1853219077Sdim sema::FunctionScopeInfo *fscope, 1854219077Sdim const Decl *D, const BlockExpr *blkExpr) { 1855206084Srdivacky 1856205408Srdivacky // We avoid doing analysis-based warnings when there are errors for 1857205408Srdivacky // two reasons: 1858205408Srdivacky // (1) The CFGs often can't be constructed (if the body is invalid), so 1859205408Srdivacky // don't bother trying. 1860205408Srdivacky // (2) The code already has problems; running the analysis just takes more 1861205408Srdivacky // time. 1862226633Sdim DiagnosticsEngine &Diags = S.getDiagnostics(); 1863207619Srdivacky 1864206084Srdivacky // Do not do any analysis for declarations in system headers if we are 1865206084Srdivacky // going to just ignore them. 1866207619Srdivacky if (Diags.getSuppressSystemWarnings() && 1867206084Srdivacky S.SourceMgr.isInSystemHeader(D->getLocation())) 1868206084Srdivacky return; 1869206084Srdivacky 1870212904Sdim // For code in dependent contexts, we'll do this at instantiation time. 1871212904Sdim if (cast<DeclContext>(D)->isDependentContext()) 1872212904Sdim return; 1873205408Srdivacky 1874249423Sdim if (Diags.hasUncompilableErrorOccurred() || Diags.hasFatalErrorOccurred()) { 1875219077Sdim // Flush out any possibly unreachable diagnostics. 1876219077Sdim flushDiagnostics(S, fscope); 1877219077Sdim return; 1878219077Sdim } 1879219077Sdim 1880205408Srdivacky const Stmt *Body = D->getBody(); 1881205408Srdivacky assert(Body); 1882205408Srdivacky 1883261991Sdim // Construct the analysis context with the specified CFG build options. 1884276479Sdim AnalysisDeclContext AC(/* AnalysisDeclContextManager */ nullptr, D); 1885226633Sdim 1886205408Srdivacky // Don't generate EH edges for CallExprs as we'd like to avoid the n^2 1887261991Sdim // explosion for destructors that can result and the compile time hit. 1888226633Sdim AC.getCFGBuildOptions().PruneTriviallyFalseEdges = true; 1889226633Sdim AC.getCFGBuildOptions().AddEHEdges = false; 1890226633Sdim AC.getCFGBuildOptions().AddInitializers = true; 1891226633Sdim AC.getCFGBuildOptions().AddImplicitDtors = true; 1892243830Sdim AC.getCFGBuildOptions().AddTemporaryDtors = true; 1893276479Sdim AC.getCFGBuildOptions().AddCXXNewAllocator = false; 1894288943Sdim AC.getCFGBuildOptions().AddCXXDefaultInitExprInCtors = true; 1895243830Sdim 1896226633Sdim // Force that certain expressions appear as CFGElements in the CFG. This 1897226633Sdim // is used to speed up various analyses. 1898226633Sdim // FIXME: This isn't the right factoring. This is here for initial 1899226633Sdim // prototyping, but we need a way for analyses to say what expressions they 1900226633Sdim // expect to always be CFGElements and then fill in the BuildOptions 1901226633Sdim // appropriately. This is essentially a layering violation. 1902261991Sdim if (P.enableCheckUnreachable || P.enableThreadSafetyAnalysis || 1903261991Sdim P.enableConsumedAnalysis) { 1904234353Sdim // Unreachable code analysis and thread safety require a linearized CFG. 1905226633Sdim AC.getCFGBuildOptions().setAllAlwaysAdd(); 1906226633Sdim } 1907226633Sdim else { 1908226633Sdim AC.getCFGBuildOptions() 1909226633Sdim .setAlwaysAdd(Stmt::BinaryOperatorClass) 1910239462Sdim .setAlwaysAdd(Stmt::CompoundAssignOperatorClass) 1911226633Sdim .setAlwaysAdd(Stmt::BlockExprClass) 1912226633Sdim .setAlwaysAdd(Stmt::CStyleCastExprClass) 1913226633Sdim .setAlwaysAdd(Stmt::DeclRefExprClass) 1914226633Sdim .setAlwaysAdd(Stmt::ImplicitCastExprClass) 1915239462Sdim .setAlwaysAdd(Stmt::UnaryOperatorClass) 1916239462Sdim .setAlwaysAdd(Stmt::AttributedStmtClass); 1917226633Sdim } 1918205408Srdivacky 1919276479Sdim // Install the logical handler for -Wtautological-overlap-compare 1920276479Sdim std::unique_ptr<LogicalErrorHandler> LEH; 1921276479Sdim if (!Diags.isIgnored(diag::warn_tautological_overlap_comparison, 1922276479Sdim D->getLocStart())) { 1923276479Sdim LEH.reset(new LogicalErrorHandler(S)); 1924276479Sdim AC.getCFGBuildOptions().Observer = LEH.get(); 1925276479Sdim } 1926261991Sdim 1927219077Sdim // Emit delayed diagnostics. 1928219077Sdim if (!fscope->PossiblyUnreachableDiags.empty()) { 1929219077Sdim bool analyzed = false; 1930221345Sdim 1931221345Sdim // Register the expressions with the CFGBuilder. 1932276479Sdim for (const auto &D : fscope->PossiblyUnreachableDiags) { 1933276479Sdim if (D.stmt) 1934276479Sdim AC.registerForcedBlockExpression(D.stmt); 1935221345Sdim } 1936221345Sdim 1937221345Sdim if (AC.getCFG()) { 1938221345Sdim analyzed = true; 1939276479Sdim for (const auto &D : fscope->PossiblyUnreachableDiags) { 1940221345Sdim bool processed = false; 1941276479Sdim if (D.stmt) { 1942276479Sdim const CFGBlock *block = AC.getBlockForRegisteredExpression(D.stmt); 1943234353Sdim CFGReverseBlockReachabilityAnalysis *cra = 1944234353Sdim AC.getCFGReachablityAnalysis(); 1945234353Sdim // FIXME: We should be able to assert that block is non-null, but 1946234353Sdim // the CFG analysis can skip potentially-evaluated expressions in 1947234353Sdim // edge cases; see test/Sema/vla-2.c. 1948234353Sdim if (block && cra) { 1949219077Sdim // Can this block be reached from the entrance? 1950221345Sdim if (cra->isReachable(&AC.getCFG()->getEntry(), block)) 1951219077Sdim S.Diag(D.Loc, D.PD); 1952221345Sdim processed = true; 1953219077Sdim } 1954219077Sdim } 1955221345Sdim if (!processed) { 1956221345Sdim // Emit the warning anyway if we cannot map to a basic block. 1957221345Sdim S.Diag(D.Loc, D.PD); 1958221345Sdim } 1959219077Sdim } 1960221345Sdim } 1961219077Sdim 1962219077Sdim if (!analyzed) 1963219077Sdim flushDiagnostics(S, fscope); 1964219077Sdim } 1965219077Sdim 1966205408Srdivacky // Warning: check missing 'return' 1967206084Srdivacky if (P.enableCheckFallThrough) { 1968205408Srdivacky const CheckFallThroughDiagnostics &CD = 1969205408Srdivacky (isa<BlockDecl>(D) ? CheckFallThroughDiagnostics::MakeForBlock() 1970234353Sdim : (isa<CXXMethodDecl>(D) && 1971234353Sdim cast<CXXMethodDecl>(D)->getOverloadedOperator() == OO_Call && 1972234353Sdim cast<CXXMethodDecl>(D)->getParent()->isLambda()) 1973234353Sdim ? CheckFallThroughDiagnostics::MakeForLambda() 1974234353Sdim : CheckFallThroughDiagnostics::MakeForFunction(D)); 1975219077Sdim CheckFallThroughForBody(S, D, Body, blkExpr, CD, AC); 1976205408Srdivacky } 1977205408Srdivacky 1978205408Srdivacky // Warning: check for unreachable code 1979234353Sdim if (P.enableCheckUnreachable) { 1980234353Sdim // Only check for unreachable code on non-template instantiations. 1981234353Sdim // Different template instantiations can effectively change the control-flow 1982234353Sdim // and it is very difficult to prove that a snippet of code in a template 1983234353Sdim // is unreachable for all instantiations. 1984234353Sdim bool isTemplateInstantiation = false; 1985234353Sdim if (const FunctionDecl *Function = dyn_cast<FunctionDecl>(D)) 1986234353Sdim isTemplateInstantiation = Function->isTemplateInstantiation(); 1987234353Sdim if (!isTemplateInstantiation) 1988234353Sdim CheckUnreachable(S, AC); 1989234353Sdim } 1990226633Sdim 1991226633Sdim // Check for thread safety violations 1992226633Sdim if (P.enableThreadSafetyAnalysis) { 1993234353Sdim SourceLocation FL = AC.getDecl()->getLocation(); 1994234353Sdim SourceLocation FEL = AC.getDecl()->getLocEnd(); 1995280031Sdim threadSafety::ThreadSafetyReporter Reporter(S, FL, FEL); 1996276479Sdim if (!Diags.isIgnored(diag::warn_thread_safety_beta, D->getLocStart())) 1997249423Sdim Reporter.setIssueBetaWarnings(true); 1998280031Sdim if (!Diags.isIgnored(diag::warn_thread_safety_verbose, D->getLocStart())) 1999280031Sdim Reporter.setVerbose(true); 2000249423Sdim 2001288943Sdim threadSafety::runThreadSafetyAnalysis(AC, Reporter, 2002288943Sdim &S.ThreadSafetyDeclCache); 2003226633Sdim Reporter.emitDiagnostics(); 2004226633Sdim } 2005226633Sdim 2006261991Sdim // Check for violations of consumed properties. 2007261991Sdim if (P.enableConsumedAnalysis) { 2008261991Sdim consumed::ConsumedWarningsHandler WarningHandler(S); 2009261991Sdim consumed::ConsumedAnalyzer Analyzer(WarningHandler); 2010261991Sdim Analyzer.run(AC); 2011261991Sdim } 2012261991Sdim 2013276479Sdim if (!Diags.isIgnored(diag::warn_uninit_var, D->getLocStart()) || 2014276479Sdim !Diags.isIgnored(diag::warn_sometimes_uninit_var, D->getLocStart()) || 2015276479Sdim !Diags.isIgnored(diag::warn_maybe_uninit_var, D->getLocStart())) { 2016221345Sdim if (CFG *cfg = AC.getCFG()) { 2017218893Sdim UninitValsDiagReporter reporter(S); 2018224145Sdim UninitVariablesAnalysisStats stats; 2019224145Sdim std::memset(&stats, 0, sizeof(UninitVariablesAnalysisStats)); 2020218893Sdim runUninitializedVariablesAnalysis(*cast<DeclContext>(D), *cfg, AC, 2021224145Sdim reporter, stats); 2022224145Sdim 2023224145Sdim if (S.CollectStats && stats.NumVariablesAnalyzed > 0) { 2024224145Sdim ++NumUninitAnalysisFunctions; 2025224145Sdim NumUninitAnalysisVariables += stats.NumVariablesAnalyzed; 2026224145Sdim NumUninitAnalysisBlockVisits += stats.NumBlockVisits; 2027224145Sdim MaxUninitAnalysisVariablesPerFunction = 2028224145Sdim std::max(MaxUninitAnalysisVariablesPerFunction, 2029224145Sdim stats.NumVariablesAnalyzed); 2030224145Sdim MaxUninitAnalysisBlockVisitsPerFunction = 2031224145Sdim std::max(MaxUninitAnalysisBlockVisitsPerFunction, 2032224145Sdim stats.NumBlockVisits); 2033224145Sdim } 2034218893Sdim } 2035218893Sdim } 2036224145Sdim 2037239462Sdim bool FallThroughDiagFull = 2038276479Sdim !Diags.isIgnored(diag::warn_unannotated_fallthrough, D->getLocStart()); 2039276479Sdim bool FallThroughDiagPerFunction = !Diags.isIgnored( 2040276479Sdim diag::warn_unannotated_fallthrough_per_function, D->getLocStart()); 2041239462Sdim if (FallThroughDiagFull || FallThroughDiagPerFunction) { 2042239462Sdim DiagnoseSwitchLabelsFallthrough(S, AC, !FallThroughDiagFull); 2043239462Sdim } 2044239462Sdim 2045296417Sdim if (S.getLangOpts().ObjCWeak && 2046276479Sdim !Diags.isIgnored(diag::warn_arc_repeated_use_of_weak, D->getLocStart())) 2047243830Sdim diagnoseRepeatedUseOfWeak(S, fscope, D, AC.getParentMap()); 2048243830Sdim 2049276479Sdim 2050276479Sdim // Check for infinite self-recursion in functions 2051276479Sdim if (!Diags.isIgnored(diag::warn_infinite_recursive_function, 2052276479Sdim D->getLocStart())) { 2053276479Sdim if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(D)) { 2054276479Sdim checkRecursiveFunction(S, FD, Body, AC); 2055276479Sdim } 2056276479Sdim } 2057276479Sdim 2058276479Sdim // If none of the previous checks caused a CFG build, trigger one here 2059276479Sdim // for -Wtautological-overlap-compare 2060276479Sdim if (!Diags.isIgnored(diag::warn_tautological_overlap_comparison, 2061276479Sdim D->getLocStart())) { 2062276479Sdim AC.getCFG(); 2063276479Sdim } 2064276479Sdim 2065224145Sdim // Collect statistics about the CFG if it was built. 2066224145Sdim if (S.CollectStats && AC.isCFGBuilt()) { 2067224145Sdim ++NumFunctionsAnalyzed; 2068224145Sdim if (CFG *cfg = AC.getCFG()) { 2069224145Sdim // If we successfully built a CFG for this context, record some more 2070224145Sdim // detail information about it. 2071224145Sdim NumCFGBlocks += cfg->getNumBlockIDs(); 2072224145Sdim MaxCFGBlocksPerFunction = std::max(MaxCFGBlocksPerFunction, 2073224145Sdim cfg->getNumBlockIDs()); 2074224145Sdim } else { 2075224145Sdim ++NumFunctionsWithBadCFGs; 2076224145Sdim } 2077224145Sdim } 2078205408Srdivacky} 2079224145Sdim 2080224145Sdimvoid clang::sema::AnalysisBasedWarnings::PrintStats() const { 2081224145Sdim llvm::errs() << "\n*** Analysis Based Warnings Stats:\n"; 2082224145Sdim 2083224145Sdim unsigned NumCFGsBuilt = NumFunctionsAnalyzed - NumFunctionsWithBadCFGs; 2084224145Sdim unsigned AvgCFGBlocksPerFunction = 2085224145Sdim !NumCFGsBuilt ? 0 : NumCFGBlocks/NumCFGsBuilt; 2086224145Sdim llvm::errs() << NumFunctionsAnalyzed << " functions analyzed (" 2087224145Sdim << NumFunctionsWithBadCFGs << " w/o CFGs).\n" 2088224145Sdim << " " << NumCFGBlocks << " CFG blocks built.\n" 2089224145Sdim << " " << AvgCFGBlocksPerFunction 2090224145Sdim << " average CFG blocks per function.\n" 2091224145Sdim << " " << MaxCFGBlocksPerFunction 2092224145Sdim << " max CFG blocks per function.\n"; 2093224145Sdim 2094224145Sdim unsigned AvgUninitVariablesPerFunction = !NumUninitAnalysisFunctions ? 0 2095224145Sdim : NumUninitAnalysisVariables/NumUninitAnalysisFunctions; 2096224145Sdim unsigned AvgUninitBlockVisitsPerFunction = !NumUninitAnalysisFunctions ? 0 2097224145Sdim : NumUninitAnalysisBlockVisits/NumUninitAnalysisFunctions; 2098224145Sdim llvm::errs() << NumUninitAnalysisFunctions 2099224145Sdim << " functions analyzed for uninitialiazed variables\n" 2100224145Sdim << " " << NumUninitAnalysisVariables << " variables analyzed.\n" 2101224145Sdim << " " << AvgUninitVariablesPerFunction 2102224145Sdim << " average variables per function.\n" 2103224145Sdim << " " << MaxUninitAnalysisVariablesPerFunction 2104224145Sdim << " max variables per function.\n" 2105224145Sdim << " " << NumUninitAnalysisBlockVisits << " block visits.\n" 2106224145Sdim << " " << AvgUninitBlockVisitsPerFunction 2107224145Sdim << " average block visits per function.\n" 2108224145Sdim << " " << MaxUninitAnalysisBlockVisitsPerFunction 2109224145Sdim << " max block visits per function.\n"; 2110224145Sdim} 2111