AnalysisBasedWarnings.cpp revision d837c0dc361a000b951593eaaa80c46b73d15b1d
1//=- AnalysisBasedWarnings.cpp - Sema warnings based on libAnalysis -*- C++ -*-=// 2// 3// The LLVM Compiler Infrastructure 4// 5// This file is distributed under the University of Illinois Open Source 6// License. See LICENSE.TXT for details. 7// 8//===----------------------------------------------------------------------===// 9// 10// This file defines analysis_warnings::[Policy,Executor]. 11// Together they are used by Sema to issue warnings based on inexpensive 12// static analysis algorithms in libAnalysis. 13// 14//===----------------------------------------------------------------------===// 15 16#include "clang/Sema/AnalysisBasedWarnings.h" 17#include "clang/Sema/SemaInternal.h" 18#include "clang/Sema/ScopeInfo.h" 19#include "clang/Basic/SourceManager.h" 20#include "clang/Lex/Preprocessor.h" 21#include "clang/AST/DeclObjC.h" 22#include "clang/AST/DeclCXX.h" 23#include "clang/AST/ExprObjC.h" 24#include "clang/AST/ExprCXX.h" 25#include "clang/AST/StmtObjC.h" 26#include "clang/AST/StmtCXX.h" 27#include "clang/AST/EvaluatedExprVisitor.h" 28#include "clang/Analysis/AnalysisContext.h" 29#include "clang/Analysis/CFG.h" 30#include "clang/Analysis/Analyses/ReachableCode.h" 31#include "clang/Analysis/Analyses/CFGReachabilityAnalysis.h" 32#include "clang/Analysis/CFGStmtMap.h" 33#include "clang/Analysis/Analyses/UninitializedValues.h" 34#include "llvm/ADT/BitVector.h" 35#include "llvm/Support/Casting.h" 36 37using namespace clang; 38 39//===----------------------------------------------------------------------===// 40// Unreachable code analysis. 41//===----------------------------------------------------------------------===// 42 43namespace { 44 class UnreachableCodeHandler : public reachable_code::Callback { 45 Sema &S; 46 public: 47 UnreachableCodeHandler(Sema &s) : S(s) {} 48 49 void HandleUnreachable(SourceLocation L, SourceRange R1, SourceRange R2) { 50 S.Diag(L, diag::warn_unreachable) << R1 << R2; 51 } 52 }; 53} 54 55/// CheckUnreachable - Check for unreachable code. 56static void CheckUnreachable(Sema &S, AnalysisContext &AC) { 57 UnreachableCodeHandler UC(S); 58 reachable_code::FindUnreachableCode(AC, UC); 59} 60 61//===----------------------------------------------------------------------===// 62// Check for missing return value. 63//===----------------------------------------------------------------------===// 64 65enum ControlFlowKind { 66 UnknownFallThrough, 67 NeverFallThrough, 68 MaybeFallThrough, 69 AlwaysFallThrough, 70 NeverFallThroughOrReturn 71}; 72 73/// CheckFallThrough - Check that we don't fall off the end of a 74/// Statement that should return a value. 75/// 76/// \returns AlwaysFallThrough iff we always fall off the end of the statement, 77/// MaybeFallThrough iff we might or might not fall off the end, 78/// NeverFallThroughOrReturn iff we never fall off the end of the statement or 79/// return. We assume NeverFallThrough iff we never fall off the end of the 80/// statement but we may return. We assume that functions not marked noreturn 81/// will return. 82static ControlFlowKind CheckFallThrough(AnalysisContext &AC) { 83 CFG *cfg = AC.getCFG(); 84 if (cfg == 0) return UnknownFallThrough; 85 86 // The CFG leaves in dead things, and we don't want the dead code paths to 87 // confuse us, so we mark all live things first. 88 llvm::BitVector live(cfg->getNumBlockIDs()); 89 unsigned count = reachable_code::ScanReachableFromBlock(cfg->getEntry(), 90 live); 91 92 bool AddEHEdges = AC.getAddEHEdges(); 93 if (!AddEHEdges && count != cfg->getNumBlockIDs()) 94 // When there are things remaining dead, and we didn't add EH edges 95 // from CallExprs to the catch clauses, we have to go back and 96 // mark them as live. 97 for (CFG::iterator I = cfg->begin(), E = cfg->end(); I != E; ++I) { 98 CFGBlock &b = **I; 99 if (!live[b.getBlockID()]) { 100 if (b.pred_begin() == b.pred_end()) { 101 if (b.getTerminator() && isa<CXXTryStmt>(b.getTerminator())) 102 // When not adding EH edges from calls, catch clauses 103 // can otherwise seem dead. Avoid noting them as dead. 104 count += reachable_code::ScanReachableFromBlock(b, live); 105 continue; 106 } 107 } 108 } 109 110 // Now we know what is live, we check the live precessors of the exit block 111 // and look for fall through paths, being careful to ignore normal returns, 112 // and exceptional paths. 113 bool HasLiveReturn = false; 114 bool HasFakeEdge = false; 115 bool HasPlainEdge = false; 116 bool HasAbnormalEdge = false; 117 118 // Ignore default cases that aren't likely to be reachable because all 119 // enums in a switch(X) have explicit case statements. 120 CFGBlock::FilterOptions FO; 121 FO.IgnoreDefaultsWithCoveredEnums = 1; 122 123 for (CFGBlock::filtered_pred_iterator 124 I = cfg->getExit().filtered_pred_start_end(FO); I.hasMore(); ++I) { 125 const CFGBlock& B = **I; 126 if (!live[B.getBlockID()]) 127 continue; 128 129 // Destructors can appear after the 'return' in the CFG. This is 130 // normal. We need to look pass the destructors for the return 131 // statement (if it exists). 132 CFGBlock::const_reverse_iterator ri = B.rbegin(), re = B.rend(); 133 bool hasNoReturnDtor = false; 134 135 for ( ; ri != re ; ++ri) { 136 CFGElement CE = *ri; 137 138 // FIXME: The right solution is to just sever the edges in the 139 // CFG itself. 140 if (const CFGImplicitDtor *iDtor = ri->getAs<CFGImplicitDtor>()) 141 if (iDtor->isNoReturn(AC.getASTContext())) { 142 hasNoReturnDtor = true; 143 HasFakeEdge = true; 144 break; 145 } 146 147 if (isa<CFGStmt>(CE)) 148 break; 149 } 150 151 if (hasNoReturnDtor) 152 continue; 153 154 // No more CFGElements in the block? 155 if (ri == re) { 156 if (B.getTerminator() && isa<CXXTryStmt>(B.getTerminator())) { 157 HasAbnormalEdge = true; 158 continue; 159 } 160 // A labeled empty statement, or the entry block... 161 HasPlainEdge = true; 162 continue; 163 } 164 165 CFGStmt CS = cast<CFGStmt>(*ri); 166 Stmt *S = CS.getStmt(); 167 if (isa<ReturnStmt>(S)) { 168 HasLiveReturn = true; 169 continue; 170 } 171 if (isa<ObjCAtThrowStmt>(S)) { 172 HasFakeEdge = true; 173 continue; 174 } 175 if (isa<CXXThrowExpr>(S)) { 176 HasFakeEdge = true; 177 continue; 178 } 179 if (const AsmStmt *AS = dyn_cast<AsmStmt>(S)) { 180 if (AS->isMSAsm()) { 181 HasFakeEdge = true; 182 HasLiveReturn = true; 183 continue; 184 } 185 } 186 if (isa<CXXTryStmt>(S)) { 187 HasAbnormalEdge = true; 188 continue; 189 } 190 191 bool NoReturnEdge = false; 192 if (CallExpr *C = dyn_cast<CallExpr>(S)) { 193 if (std::find(B.succ_begin(), B.succ_end(), &cfg->getExit()) 194 == B.succ_end()) { 195 HasAbnormalEdge = true; 196 continue; 197 } 198 Expr *CEE = C->getCallee()->IgnoreParenCasts(); 199 QualType calleeType = CEE->getType(); 200 if (calleeType == AC.getASTContext().BoundMemberTy) { 201 calleeType = Expr::findBoundMemberType(CEE); 202 assert(!calleeType.isNull() && "analyzing unresolved call?"); 203 } 204 if (getFunctionExtInfo(calleeType).getNoReturn()) { 205 NoReturnEdge = true; 206 HasFakeEdge = true; 207 } else if (DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(CEE)) { 208 ValueDecl *VD = DRE->getDecl(); 209 if (VD->hasAttr<NoReturnAttr>()) { 210 NoReturnEdge = true; 211 HasFakeEdge = true; 212 } 213 } 214 } 215 // FIXME: Add noreturn message sends. 216 if (NoReturnEdge == false) 217 HasPlainEdge = true; 218 } 219 if (!HasPlainEdge) { 220 if (HasLiveReturn) 221 return NeverFallThrough; 222 return NeverFallThroughOrReturn; 223 } 224 if (HasAbnormalEdge || HasFakeEdge || HasLiveReturn) 225 return MaybeFallThrough; 226 // This says AlwaysFallThrough for calls to functions that are not marked 227 // noreturn, that don't return. If people would like this warning to be more 228 // accurate, such functions should be marked as noreturn. 229 return AlwaysFallThrough; 230} 231 232namespace { 233 234struct CheckFallThroughDiagnostics { 235 unsigned diag_MaybeFallThrough_HasNoReturn; 236 unsigned diag_MaybeFallThrough_ReturnsNonVoid; 237 unsigned diag_AlwaysFallThrough_HasNoReturn; 238 unsigned diag_AlwaysFallThrough_ReturnsNonVoid; 239 unsigned diag_NeverFallThroughOrReturn; 240 bool funMode; 241 SourceLocation FuncLoc; 242 243 static CheckFallThroughDiagnostics MakeForFunction(const Decl *Func) { 244 CheckFallThroughDiagnostics D; 245 D.FuncLoc = Func->getLocation(); 246 D.diag_MaybeFallThrough_HasNoReturn = 247 diag::warn_falloff_noreturn_function; 248 D.diag_MaybeFallThrough_ReturnsNonVoid = 249 diag::warn_maybe_falloff_nonvoid_function; 250 D.diag_AlwaysFallThrough_HasNoReturn = 251 diag::warn_falloff_noreturn_function; 252 D.diag_AlwaysFallThrough_ReturnsNonVoid = 253 diag::warn_falloff_nonvoid_function; 254 255 // Don't suggest that virtual functions be marked "noreturn", since they 256 // might be overridden by non-noreturn functions. 257 bool isVirtualMethod = false; 258 if (const CXXMethodDecl *Method = dyn_cast<CXXMethodDecl>(Func)) 259 isVirtualMethod = Method->isVirtual(); 260 261 if (!isVirtualMethod) 262 D.diag_NeverFallThroughOrReturn = 263 diag::warn_suggest_noreturn_function; 264 else 265 D.diag_NeverFallThroughOrReturn = 0; 266 267 D.funMode = true; 268 return D; 269 } 270 271 static CheckFallThroughDiagnostics MakeForBlock() { 272 CheckFallThroughDiagnostics D; 273 D.diag_MaybeFallThrough_HasNoReturn = 274 diag::err_noreturn_block_has_return_expr; 275 D.diag_MaybeFallThrough_ReturnsNonVoid = 276 diag::err_maybe_falloff_nonvoid_block; 277 D.diag_AlwaysFallThrough_HasNoReturn = 278 diag::err_noreturn_block_has_return_expr; 279 D.diag_AlwaysFallThrough_ReturnsNonVoid = 280 diag::err_falloff_nonvoid_block; 281 D.diag_NeverFallThroughOrReturn = 282 diag::warn_suggest_noreturn_block; 283 D.funMode = false; 284 return D; 285 } 286 287 bool checkDiagnostics(Diagnostic &D, bool ReturnsVoid, 288 bool HasNoReturn) const { 289 if (funMode) { 290 return (ReturnsVoid || 291 D.getDiagnosticLevel(diag::warn_maybe_falloff_nonvoid_function, 292 FuncLoc) == Diagnostic::Ignored) 293 && (!HasNoReturn || 294 D.getDiagnosticLevel(diag::warn_noreturn_function_has_return_expr, 295 FuncLoc) == Diagnostic::Ignored) 296 && (!ReturnsVoid || 297 D.getDiagnosticLevel(diag::warn_suggest_noreturn_block, FuncLoc) 298 == Diagnostic::Ignored); 299 } 300 301 // For blocks. 302 return ReturnsVoid && !HasNoReturn 303 && (!ReturnsVoid || 304 D.getDiagnosticLevel(diag::warn_suggest_noreturn_block, FuncLoc) 305 == Diagnostic::Ignored); 306 } 307}; 308 309} 310 311/// CheckFallThroughForFunctionDef - Check that we don't fall off the end of a 312/// function that should return a value. Check that we don't fall off the end 313/// of a noreturn function. We assume that functions and blocks not marked 314/// noreturn will return. 315static void CheckFallThroughForBody(Sema &S, const Decl *D, const Stmt *Body, 316 const BlockExpr *blkExpr, 317 const CheckFallThroughDiagnostics& CD, 318 AnalysisContext &AC) { 319 320 bool ReturnsVoid = false; 321 bool HasNoReturn = false; 322 323 if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(D)) { 324 ReturnsVoid = FD->getResultType()->isVoidType(); 325 HasNoReturn = FD->hasAttr<NoReturnAttr>() || 326 FD->getType()->getAs<FunctionType>()->getNoReturnAttr(); 327 } 328 else if (const ObjCMethodDecl *MD = dyn_cast<ObjCMethodDecl>(D)) { 329 ReturnsVoid = MD->getResultType()->isVoidType(); 330 HasNoReturn = MD->hasAttr<NoReturnAttr>(); 331 } 332 else if (isa<BlockDecl>(D)) { 333 QualType BlockTy = blkExpr->getType(); 334 if (const FunctionType *FT = 335 BlockTy->getPointeeType()->getAs<FunctionType>()) { 336 if (FT->getResultType()->isVoidType()) 337 ReturnsVoid = true; 338 if (FT->getNoReturnAttr()) 339 HasNoReturn = true; 340 } 341 } 342 343 Diagnostic &Diags = S.getDiagnostics(); 344 345 // Short circuit for compilation speed. 346 if (CD.checkDiagnostics(Diags, ReturnsVoid, HasNoReturn)) 347 return; 348 349 // FIXME: Function try block 350 if (const CompoundStmt *Compound = dyn_cast<CompoundStmt>(Body)) { 351 switch (CheckFallThrough(AC)) { 352 case UnknownFallThrough: 353 break; 354 355 case MaybeFallThrough: 356 if (HasNoReturn) 357 S.Diag(Compound->getRBracLoc(), 358 CD.diag_MaybeFallThrough_HasNoReturn); 359 else if (!ReturnsVoid) 360 S.Diag(Compound->getRBracLoc(), 361 CD.diag_MaybeFallThrough_ReturnsNonVoid); 362 break; 363 case AlwaysFallThrough: 364 if (HasNoReturn) 365 S.Diag(Compound->getRBracLoc(), 366 CD.diag_AlwaysFallThrough_HasNoReturn); 367 else if (!ReturnsVoid) 368 S.Diag(Compound->getRBracLoc(), 369 CD.diag_AlwaysFallThrough_ReturnsNonVoid); 370 break; 371 case NeverFallThroughOrReturn: 372 if (ReturnsVoid && !HasNoReturn && CD.diag_NeverFallThroughOrReturn) 373 S.Diag(Compound->getLBracLoc(), 374 CD.diag_NeverFallThroughOrReturn); 375 break; 376 case NeverFallThrough: 377 break; 378 } 379 } 380} 381 382//===----------------------------------------------------------------------===// 383// -Wuninitialized 384//===----------------------------------------------------------------------===// 385 386namespace { 387/// ContainsReference - A visitor class to search for references to 388/// a particular declaration (the needle) within any evaluated component of an 389/// expression (recursively). 390class ContainsReference : public EvaluatedExprVisitor<ContainsReference> { 391 bool FoundReference; 392 const DeclRefExpr *Needle; 393 394public: 395 ContainsReference(ASTContext &Context, const DeclRefExpr *Needle) 396 : EvaluatedExprVisitor<ContainsReference>(Context), 397 FoundReference(false), Needle(Needle) {} 398 399 void VisitExpr(Expr *E) { 400 // Stop evaluating if we already have a reference. 401 if (FoundReference) 402 return; 403 404 EvaluatedExprVisitor<ContainsReference>::VisitExpr(E); 405 } 406 407 void VisitDeclRefExpr(DeclRefExpr *E) { 408 if (E == Needle) 409 FoundReference = true; 410 else 411 EvaluatedExprVisitor<ContainsReference>::VisitDeclRefExpr(E); 412 } 413 414 bool doesContainReference() const { return FoundReference; } 415}; 416} 417 418/// DiagnoseUninitializedUse -- Helper function for diagnosing uses of an 419/// uninitialized variable. This manages the different forms of diagnostic 420/// emitted for particular types of uses. Returns true if the use was diagnosed 421/// as a warning. If a pariticular use is one we omit warnings for, returns 422/// false. 423static bool DiagnoseUninitializedUse(Sema &S, const VarDecl *VD, 424 const Expr *E, bool isAlwaysUninit) { 425 bool isSelfInit = false; 426 427 if (const DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(E)) { 428 if (isAlwaysUninit) { 429 // Inspect the initializer of the variable declaration which is 430 // being referenced prior to its initialization. We emit 431 // specialized diagnostics for self-initialization, and we 432 // specifically avoid warning about self references which take the 433 // form of: 434 // 435 // int x = x; 436 // 437 // This is used to indicate to GCC that 'x' is intentionally left 438 // uninitialized. Proven code paths which access 'x' in 439 // an uninitialized state after this will still warn. 440 // 441 // TODO: Should we suppress maybe-uninitialized warnings for 442 // variables initialized in this way? 443 if (const Expr *Initializer = VD->getInit()) { 444 if (DRE == Initializer->IgnoreParenImpCasts()) 445 return false; 446 447 ContainsReference CR(S.Context, DRE); 448 CR.Visit(const_cast<Expr*>(Initializer)); 449 isSelfInit = CR.doesContainReference(); 450 } 451 if (isSelfInit) { 452 S.Diag(DRE->getLocStart(), 453 diag::warn_uninit_self_reference_in_init) 454 << VD->getDeclName() << VD->getLocation() << DRE->getSourceRange(); 455 } else { 456 S.Diag(DRE->getLocStart(), diag::warn_uninit_var) 457 << VD->getDeclName() << DRE->getSourceRange(); 458 } 459 } else { 460 S.Diag(DRE->getLocStart(), diag::warn_maybe_uninit_var) 461 << VD->getDeclName() << DRE->getSourceRange(); 462 } 463 } else { 464 const BlockExpr *BE = cast<BlockExpr>(E); 465 S.Diag(BE->getLocStart(), 466 isAlwaysUninit ? diag::warn_uninit_var_captured_by_block 467 : diag::warn_maybe_uninit_var_captured_by_block) 468 << VD->getDeclName(); 469 } 470 471 // Report where the variable was declared when the use wasn't within 472 // the initializer of that declaration. 473 if (!isSelfInit) 474 S.Diag(VD->getLocStart(), diag::note_uninit_var_def) 475 << VD->getDeclName(); 476 477 return true; 478} 479 480static void SuggestInitializationFixit(Sema &S, const VarDecl *VD) { 481 // Don't issue a fixit if there is already an initializer. 482 if (VD->getInit()) 483 return; 484 485 // Suggest possible initialization (if any). 486 const char *initialization = 0; 487 QualType VariableTy = VD->getType().getCanonicalType(); 488 489 if (VariableTy->isObjCObjectPointerType() || 490 VariableTy->isBlockPointerType()) { 491 // Check if 'nil' is defined. 492 if (S.PP.getMacroInfo(&S.getASTContext().Idents.get("nil"))) 493 initialization = " = nil"; 494 else 495 initialization = " = 0"; 496 } 497 else if (VariableTy->isRealFloatingType()) 498 initialization = " = 0.0"; 499 else if (VariableTy->isBooleanType() && S.Context.getLangOptions().CPlusPlus) 500 initialization = " = false"; 501 else if (VariableTy->isEnumeralType()) 502 return; 503 else if (VariableTy->isPointerType() || VariableTy->isMemberPointerType()) { 504 // Check if 'NULL' is defined. 505 if (S.PP.getMacroInfo(&S.getASTContext().Idents.get("NULL"))) 506 initialization = " = NULL"; 507 else 508 initialization = " = 0"; 509 } 510 else if (VariableTy->isScalarType()) 511 initialization = " = 0"; 512 513 if (initialization) { 514 SourceLocation loc = S.PP.getLocForEndOfToken(VD->getLocEnd()); 515 S.Diag(loc, diag::note_var_fixit_add_initialization) 516 << FixItHint::CreateInsertion(loc, initialization); 517 } 518} 519 520typedef std::pair<const Expr*, bool> UninitUse; 521 522namespace { 523struct SLocSort { 524 bool operator()(const UninitUse &a, const UninitUse &b) { 525 SourceLocation aLoc = a.first->getLocStart(); 526 SourceLocation bLoc = b.first->getLocStart(); 527 return aLoc.getRawEncoding() < bLoc.getRawEncoding(); 528 } 529}; 530 531class UninitValsDiagReporter : public UninitVariablesHandler { 532 Sema &S; 533 typedef llvm::SmallVector<UninitUse, 2> UsesVec; 534 typedef llvm::DenseMap<const VarDecl *, UsesVec*> UsesMap; 535 UsesMap *uses; 536 537public: 538 UninitValsDiagReporter(Sema &S) : S(S), uses(0) {} 539 ~UninitValsDiagReporter() { 540 flushDiagnostics(); 541 } 542 543 void handleUseOfUninitVariable(const Expr *ex, const VarDecl *vd, 544 bool isAlwaysUninit) { 545 if (!uses) 546 uses = new UsesMap(); 547 548 UsesVec *&vec = (*uses)[vd]; 549 if (!vec) 550 vec = new UsesVec(); 551 552 vec->push_back(std::make_pair(ex, isAlwaysUninit)); 553 } 554 555 void flushDiagnostics() { 556 if (!uses) 557 return; 558 559 for (UsesMap::iterator i = uses->begin(), e = uses->end(); i != e; ++i) { 560 const VarDecl *vd = i->first; 561 UsesVec *vec = i->second; 562 563 // Sort the uses by their SourceLocations. While not strictly 564 // guaranteed to produce them in line/column order, this will provide 565 // a stable ordering. 566 std::sort(vec->begin(), vec->end(), SLocSort()); 567 568 for (UsesVec::iterator vi = vec->begin(), ve = vec->end(); vi != ve; 569 ++vi) { 570 if (!DiagnoseUninitializedUse(S, vd, vi->first, 571 /*isAlwaysUninit=*/vi->second)) 572 continue; 573 574 SuggestInitializationFixit(S, vd); 575 576 // Skip further diagnostics for this variable. We try to warn only on 577 // the first point at which a variable is used uninitialized. 578 break; 579 } 580 581 delete vec; 582 } 583 delete uses; 584 } 585}; 586} 587 588//===----------------------------------------------------------------------===// 589// AnalysisBasedWarnings - Worker object used by Sema to execute analysis-based 590// warnings on a function, method, or block. 591//===----------------------------------------------------------------------===// 592 593clang::sema::AnalysisBasedWarnings::Policy::Policy() { 594 enableCheckFallThrough = 1; 595 enableCheckUnreachable = 0; 596} 597 598clang::sema::AnalysisBasedWarnings::AnalysisBasedWarnings(Sema &s) 599 : S(s), 600 NumFunctionsAnalyzed(0), 601 NumFunctionsWithBadCFGs(0), 602 NumCFGBlocks(0), 603 MaxCFGBlocksPerFunction(0), 604 NumUninitAnalysisFunctions(0), 605 NumUninitAnalysisVariables(0), 606 MaxUninitAnalysisVariablesPerFunction(0), 607 NumUninitAnalysisBlockVisits(0), 608 MaxUninitAnalysisBlockVisitsPerFunction(0) { 609 Diagnostic &D = S.getDiagnostics(); 610 DefaultPolicy.enableCheckUnreachable = (unsigned) 611 (D.getDiagnosticLevel(diag::warn_unreachable, SourceLocation()) != 612 Diagnostic::Ignored); 613} 614 615static void flushDiagnostics(Sema &S, sema::FunctionScopeInfo *fscope) { 616 for (llvm::SmallVectorImpl<sema::PossiblyUnreachableDiag>::iterator 617 i = fscope->PossiblyUnreachableDiags.begin(), 618 e = fscope->PossiblyUnreachableDiags.end(); 619 i != e; ++i) { 620 const sema::PossiblyUnreachableDiag &D = *i; 621 S.Diag(D.Loc, D.PD); 622 } 623} 624 625void clang::sema:: 626AnalysisBasedWarnings::IssueWarnings(sema::AnalysisBasedWarnings::Policy P, 627 sema::FunctionScopeInfo *fscope, 628 const Decl *D, const BlockExpr *blkExpr) { 629 630 // We avoid doing analysis-based warnings when there are errors for 631 // two reasons: 632 // (1) The CFGs often can't be constructed (if the body is invalid), so 633 // don't bother trying. 634 // (2) The code already has problems; running the analysis just takes more 635 // time. 636 Diagnostic &Diags = S.getDiagnostics(); 637 638 // Do not do any analysis for declarations in system headers if we are 639 // going to just ignore them. 640 if (Diags.getSuppressSystemWarnings() && 641 S.SourceMgr.isInSystemHeader(D->getLocation())) 642 return; 643 644 // For code in dependent contexts, we'll do this at instantiation time. 645 if (cast<DeclContext>(D)->isDependentContext()) 646 return; 647 648 if (Diags.hasErrorOccurred() || Diags.hasFatalErrorOccurred()) { 649 // Flush out any possibly unreachable diagnostics. 650 flushDiagnostics(S, fscope); 651 return; 652 } 653 654 const Stmt *Body = D->getBody(); 655 assert(Body); 656 657 AnalysisContext AC(D, 0); 658 659 // Don't generate EH edges for CallExprs as we'd like to avoid the n^2 660 // explosion for destrutors that can result and the compile time hit. 661 AC.getCFGBuildOptions().PruneTriviallyFalseEdges = true; 662 AC.getCFGBuildOptions().AddEHEdges = false; 663 AC.getCFGBuildOptions().AddInitializers = true; 664 AC.getCFGBuildOptions().AddImplicitDtors = true; 665 666 // Force that certain expressions appear as CFGElements in the CFG. This 667 // is used to speed up various analyses. 668 // FIXME: This isn't the right factoring. This is here for initial 669 // prototyping, but we need a way for analyses to say what expressions they 670 // expect to always be CFGElements and then fill in the BuildOptions 671 // appropriately. This is essentially a layering violation. 672 AC.getCFGBuildOptions() 673 .setAlwaysAdd(Stmt::BinaryOperatorClass) 674 .setAlwaysAdd(Stmt::BlockExprClass) 675 .setAlwaysAdd(Stmt::CStyleCastExprClass) 676 .setAlwaysAdd(Stmt::DeclRefExprClass) 677 .setAlwaysAdd(Stmt::ImplicitCastExprClass) 678 .setAlwaysAdd(Stmt::UnaryOperatorClass); 679 680 // Construct the analysis context with the specified CFG build options. 681 682 // Emit delayed diagnostics. 683 if (!fscope->PossiblyUnreachableDiags.empty()) { 684 bool analyzed = false; 685 686 // Register the expressions with the CFGBuilder. 687 for (llvm::SmallVectorImpl<sema::PossiblyUnreachableDiag>::iterator 688 i = fscope->PossiblyUnreachableDiags.begin(), 689 e = fscope->PossiblyUnreachableDiags.end(); 690 i != e; ++i) { 691 if (const Stmt *stmt = i->stmt) 692 AC.registerForcedBlockExpression(stmt); 693 } 694 695 if (AC.getCFG()) { 696 analyzed = true; 697 for (llvm::SmallVectorImpl<sema::PossiblyUnreachableDiag>::iterator 698 i = fscope->PossiblyUnreachableDiags.begin(), 699 e = fscope->PossiblyUnreachableDiags.end(); 700 i != e; ++i) 701 { 702 const sema::PossiblyUnreachableDiag &D = *i; 703 bool processed = false; 704 if (const Stmt *stmt = i->stmt) { 705 const CFGBlock *block = AC.getBlockForRegisteredExpression(stmt); 706 assert(block); 707 if (CFGReverseBlockReachabilityAnalysis *cra = AC.getCFGReachablityAnalysis()) { 708 // Can this block be reached from the entrance? 709 if (cra->isReachable(&AC.getCFG()->getEntry(), block)) 710 S.Diag(D.Loc, D.PD); 711 processed = true; 712 } 713 } 714 if (!processed) { 715 // Emit the warning anyway if we cannot map to a basic block. 716 S.Diag(D.Loc, D.PD); 717 } 718 } 719 } 720 721 if (!analyzed) 722 flushDiagnostics(S, fscope); 723 } 724 725 726 // Warning: check missing 'return' 727 if (P.enableCheckFallThrough) { 728 const CheckFallThroughDiagnostics &CD = 729 (isa<BlockDecl>(D) ? CheckFallThroughDiagnostics::MakeForBlock() 730 : CheckFallThroughDiagnostics::MakeForFunction(D)); 731 CheckFallThroughForBody(S, D, Body, blkExpr, CD, AC); 732 } 733 734 // Warning: check for unreachable code 735 if (P.enableCheckUnreachable) 736 CheckUnreachable(S, AC); 737 738 if (Diags.getDiagnosticLevel(diag::warn_uninit_var, D->getLocStart()) 739 != Diagnostic::Ignored || 740 Diags.getDiagnosticLevel(diag::warn_maybe_uninit_var, D->getLocStart()) 741 != Diagnostic::Ignored) { 742 if (CFG *cfg = AC.getCFG()) { 743 UninitValsDiagReporter reporter(S); 744 UninitVariablesAnalysisStats stats; 745 std::memset(&stats, 0, sizeof(UninitVariablesAnalysisStats)); 746 runUninitializedVariablesAnalysis(*cast<DeclContext>(D), *cfg, AC, 747 reporter, stats); 748 749 if (S.CollectStats && stats.NumVariablesAnalyzed > 0) { 750 ++NumUninitAnalysisFunctions; 751 NumUninitAnalysisVariables += stats.NumVariablesAnalyzed; 752 NumUninitAnalysisBlockVisits += stats.NumBlockVisits; 753 MaxUninitAnalysisVariablesPerFunction = 754 std::max(MaxUninitAnalysisVariablesPerFunction, 755 stats.NumVariablesAnalyzed); 756 MaxUninitAnalysisBlockVisitsPerFunction = 757 std::max(MaxUninitAnalysisBlockVisitsPerFunction, 758 stats.NumBlockVisits); 759 } 760 } 761 } 762 763 // Collect statistics about the CFG if it was built. 764 if (S.CollectStats && AC.isCFGBuilt()) { 765 ++NumFunctionsAnalyzed; 766 if (CFG *cfg = AC.getCFG()) { 767 // If we successfully built a CFG for this context, record some more 768 // detail information about it. 769 NumCFGBlocks += cfg->getNumBlockIDs(); 770 MaxCFGBlocksPerFunction = std::max(MaxCFGBlocksPerFunction, 771 cfg->getNumBlockIDs()); 772 } else { 773 ++NumFunctionsWithBadCFGs; 774 } 775 } 776} 777 778void clang::sema::AnalysisBasedWarnings::PrintStats() const { 779 llvm::errs() << "\n*** Analysis Based Warnings Stats:\n"; 780 781 unsigned NumCFGsBuilt = NumFunctionsAnalyzed - NumFunctionsWithBadCFGs; 782 unsigned AvgCFGBlocksPerFunction = 783 !NumCFGsBuilt ? 0 : NumCFGBlocks/NumCFGsBuilt; 784 llvm::errs() << NumFunctionsAnalyzed << " functions analyzed (" 785 << NumFunctionsWithBadCFGs << " w/o CFGs).\n" 786 << " " << NumCFGBlocks << " CFG blocks built.\n" 787 << " " << AvgCFGBlocksPerFunction 788 << " average CFG blocks per function.\n" 789 << " " << MaxCFGBlocksPerFunction 790 << " max CFG blocks per function.\n"; 791 792 unsigned AvgUninitVariablesPerFunction = !NumUninitAnalysisFunctions ? 0 793 : NumUninitAnalysisVariables/NumUninitAnalysisFunctions; 794 unsigned AvgUninitBlockVisitsPerFunction = !NumUninitAnalysisFunctions ? 0 795 : NumUninitAnalysisBlockVisits/NumUninitAnalysisFunctions; 796 llvm::errs() << NumUninitAnalysisFunctions 797 << " functions analyzed for uninitialiazed variables\n" 798 << " " << NumUninitAnalysisVariables << " variables analyzed.\n" 799 << " " << AvgUninitVariablesPerFunction 800 << " average variables per function.\n" 801 << " " << MaxUninitAnalysisVariablesPerFunction 802 << " max variables per function.\n" 803 << " " << NumUninitAnalysisBlockVisits << " block visits.\n" 804 << " " << AvgUninitBlockVisitsPerFunction 805 << " average block visits per function.\n" 806 << " " << MaxUninitAnalysisBlockVisitsPerFunction 807 << " max block visits per function.\n"; 808} 809