clang API Documentation
00001 //=- AnalysisBasedWarnings.cpp - Sema warnings based on libAnalysis -*- C++ -*-=// 00002 // 00003 // The LLVM Compiler Infrastructure 00004 // 00005 // This file is distributed under the University of Illinois Open Source 00006 // License. See LICENSE.TXT for details. 00007 // 00008 //===----------------------------------------------------------------------===// 00009 // 00010 // This file defines analysis_warnings::[Policy,Executor]. 00011 // Together they are used by Sema to issue warnings based on inexpensive 00012 // static analysis algorithms in libAnalysis. 00013 // 00014 //===----------------------------------------------------------------------===// 00015 00016 #include "clang/Sema/AnalysisBasedWarnings.h" 00017 #include "clang/Sema/SemaInternal.h" 00018 #include "clang/Sema/ScopeInfo.h" 00019 #include "clang/Basic/SourceManager.h" 00020 #include "clang/Basic/SourceLocation.h" 00021 #include "clang/Lex/Preprocessor.h" 00022 #include "clang/AST/DeclObjC.h" 00023 #include "clang/AST/DeclCXX.h" 00024 #include "clang/AST/ExprObjC.h" 00025 #include "clang/AST/ExprCXX.h" 00026 #include "clang/AST/StmtObjC.h" 00027 #include "clang/AST/StmtCXX.h" 00028 #include "clang/AST/EvaluatedExprVisitor.h" 00029 #include "clang/AST/StmtVisitor.h" 00030 #include "clang/AST/RecursiveASTVisitor.h" 00031 #include "clang/Analysis/AnalysisContext.h" 00032 #include "clang/Analysis/CFG.h" 00033 #include "clang/Analysis/Analyses/ReachableCode.h" 00034 #include "clang/Analysis/Analyses/CFGReachabilityAnalysis.h" 00035 #include "clang/Analysis/Analyses/ThreadSafety.h" 00036 #include "clang/Analysis/CFGStmtMap.h" 00037 #include "clang/Analysis/Analyses/UninitializedValues.h" 00038 #include "llvm/ADT/BitVector.h" 00039 #include "llvm/ADT/FoldingSet.h" 00040 #include "llvm/ADT/ImmutableMap.h" 00041 #include "llvm/ADT/PostOrderIterator.h" 00042 #include "llvm/ADT/SmallVector.h" 00043 #include "llvm/ADT/StringRef.h" 00044 #include "llvm/Support/Casting.h" 00045 #include <algorithm> 00046 #include <iterator> 00047 #include <vector> 00048 #include <deque> 00049 00050 using namespace clang; 00051 00052 //===----------------------------------------------------------------------===// 00053 // Unreachable code analysis. 00054 //===----------------------------------------------------------------------===// 00055 00056 namespace { 00057 class UnreachableCodeHandler : public reachable_code::Callback { 00058 Sema &S; 00059 public: 00060 UnreachableCodeHandler(Sema &s) : S(s) {} 00061 00062 void HandleUnreachable(SourceLocation L, SourceRange R1, SourceRange R2) { 00063 S.Diag(L, diag::warn_unreachable) << R1 << R2; 00064 } 00065 }; 00066 } 00067 00068 /// CheckUnreachable - Check for unreachable code. 00069 static void CheckUnreachable(Sema &S, AnalysisDeclContext &AC) { 00070 UnreachableCodeHandler UC(S); 00071 reachable_code::FindUnreachableCode(AC, UC); 00072 } 00073 00074 //===----------------------------------------------------------------------===// 00075 // Check for missing return value. 00076 //===----------------------------------------------------------------------===// 00077 00078 enum ControlFlowKind { 00079 UnknownFallThrough, 00080 NeverFallThrough, 00081 MaybeFallThrough, 00082 AlwaysFallThrough, 00083 NeverFallThroughOrReturn 00084 }; 00085 00086 /// CheckFallThrough - Check that we don't fall off the end of a 00087 /// Statement that should return a value. 00088 /// 00089 /// \returns AlwaysFallThrough iff we always fall off the end of the statement, 00090 /// MaybeFallThrough iff we might or might not fall off the end, 00091 /// NeverFallThroughOrReturn iff we never fall off the end of the statement or 00092 /// return. We assume NeverFallThrough iff we never fall off the end of the 00093 /// statement but we may return. We assume that functions not marked noreturn 00094 /// will return. 00095 static ControlFlowKind CheckFallThrough(AnalysisDeclContext &AC) { 00096 CFG *cfg = AC.getCFG(); 00097 if (cfg == 0) return UnknownFallThrough; 00098 00099 // The CFG leaves in dead things, and we don't want the dead code paths to 00100 // confuse us, so we mark all live things first. 00101 llvm::BitVector live(cfg->getNumBlockIDs()); 00102 unsigned count = reachable_code::ScanReachableFromBlock(&cfg->getEntry(), 00103 live); 00104 00105 bool AddEHEdges = AC.getAddEHEdges(); 00106 if (!AddEHEdges && count != cfg->getNumBlockIDs()) 00107 // When there are things remaining dead, and we didn't add EH edges 00108 // from CallExprs to the catch clauses, we have to go back and 00109 // mark them as live. 00110 for (CFG::iterator I = cfg->begin(), E = cfg->end(); I != E; ++I) { 00111 CFGBlock &b = **I; 00112 if (!live[b.getBlockID()]) { 00113 if (b.pred_begin() == b.pred_end()) { 00114 if (b.getTerminator() && isa<CXXTryStmt>(b.getTerminator())) 00115 // When not adding EH edges from calls, catch clauses 00116 // can otherwise seem dead. Avoid noting them as dead. 00117 count += reachable_code::ScanReachableFromBlock(&b, live); 00118 continue; 00119 } 00120 } 00121 } 00122 00123 // Now we know what is live, we check the live precessors of the exit block 00124 // and look for fall through paths, being careful to ignore normal returns, 00125 // and exceptional paths. 00126 bool HasLiveReturn = false; 00127 bool HasFakeEdge = false; 00128 bool HasPlainEdge = false; 00129 bool HasAbnormalEdge = false; 00130 00131 // Ignore default cases that aren't likely to be reachable because all 00132 // enums in a switch(X) have explicit case statements. 00133 CFGBlock::FilterOptions FO; 00134 FO.IgnoreDefaultsWithCoveredEnums = 1; 00135 00136 for (CFGBlock::filtered_pred_iterator 00137 I = cfg->getExit().filtered_pred_start_end(FO); I.hasMore(); ++I) { 00138 const CFGBlock& B = **I; 00139 if (!live[B.getBlockID()]) 00140 continue; 00141 00142 // Skip blocks which contain an element marked as no-return. They don't 00143 // represent actually viable edges into the exit block, so mark them as 00144 // abnormal. 00145 if (B.hasNoReturnElement()) { 00146 HasAbnormalEdge = true; 00147 continue; 00148 } 00149 00150 // Destructors can appear after the 'return' in the CFG. This is 00151 // normal. We need to look pass the destructors for the return 00152 // statement (if it exists). 00153 CFGBlock::const_reverse_iterator ri = B.rbegin(), re = B.rend(); 00154 00155 for ( ; ri != re ; ++ri) 00156 if (isa<CFGStmt>(*ri)) 00157 break; 00158 00159 // No more CFGElements in the block? 00160 if (ri == re) { 00161 if (B.getTerminator() && isa<CXXTryStmt>(B.getTerminator())) { 00162 HasAbnormalEdge = true; 00163 continue; 00164 } 00165 // A labeled empty statement, or the entry block... 00166 HasPlainEdge = true; 00167 continue; 00168 } 00169 00170 CFGStmt CS = cast<CFGStmt>(*ri); 00171 const Stmt *S = CS.getStmt(); 00172 if (isa<ReturnStmt>(S)) { 00173 HasLiveReturn = true; 00174 continue; 00175 } 00176 if (isa<ObjCAtThrowStmt>(S)) { 00177 HasFakeEdge = true; 00178 continue; 00179 } 00180 if (isa<CXXThrowExpr>(S)) { 00181 HasFakeEdge = true; 00182 continue; 00183 } 00184 if (const AsmStmt *AS = dyn_cast<AsmStmt>(S)) { 00185 if (AS->isMSAsm()) { 00186 HasFakeEdge = true; 00187 HasLiveReturn = true; 00188 continue; 00189 } 00190 } 00191 if (isa<CXXTryStmt>(S)) { 00192 HasAbnormalEdge = true; 00193 continue; 00194 } 00195 if (std::find(B.succ_begin(), B.succ_end(), &cfg->getExit()) 00196 == B.succ_end()) { 00197 HasAbnormalEdge = true; 00198 continue; 00199 } 00200 00201 HasPlainEdge = true; 00202 } 00203 if (!HasPlainEdge) { 00204 if (HasLiveReturn) 00205 return NeverFallThrough; 00206 return NeverFallThroughOrReturn; 00207 } 00208 if (HasAbnormalEdge || HasFakeEdge || HasLiveReturn) 00209 return MaybeFallThrough; 00210 // This says AlwaysFallThrough for calls to functions that are not marked 00211 // noreturn, that don't return. If people would like this warning to be more 00212 // accurate, such functions should be marked as noreturn. 00213 return AlwaysFallThrough; 00214 } 00215 00216 namespace { 00217 00218 struct CheckFallThroughDiagnostics { 00219 unsigned diag_MaybeFallThrough_HasNoReturn; 00220 unsigned diag_MaybeFallThrough_ReturnsNonVoid; 00221 unsigned diag_AlwaysFallThrough_HasNoReturn; 00222 unsigned diag_AlwaysFallThrough_ReturnsNonVoid; 00223 unsigned diag_NeverFallThroughOrReturn; 00224 enum { Function, Block, Lambda } funMode; 00225 SourceLocation FuncLoc; 00226 00227 static CheckFallThroughDiagnostics MakeForFunction(const Decl *Func) { 00228 CheckFallThroughDiagnostics D; 00229 D.FuncLoc = Func->getLocation(); 00230 D.diag_MaybeFallThrough_HasNoReturn = 00231 diag::warn_falloff_noreturn_function; 00232 D.diag_MaybeFallThrough_ReturnsNonVoid = 00233 diag::warn_maybe_falloff_nonvoid_function; 00234 D.diag_AlwaysFallThrough_HasNoReturn = 00235 diag::warn_falloff_noreturn_function; 00236 D.diag_AlwaysFallThrough_ReturnsNonVoid = 00237 diag::warn_falloff_nonvoid_function; 00238 00239 // Don't suggest that virtual functions be marked "noreturn", since they 00240 // might be overridden by non-noreturn functions. 00241 bool isVirtualMethod = false; 00242 if (const CXXMethodDecl *Method = dyn_cast<CXXMethodDecl>(Func)) 00243 isVirtualMethod = Method->isVirtual(); 00244 00245 // Don't suggest that template instantiations be marked "noreturn" 00246 bool isTemplateInstantiation = false; 00247 if (const FunctionDecl *Function = dyn_cast<FunctionDecl>(Func)) 00248 isTemplateInstantiation = Function->isTemplateInstantiation(); 00249 00250 if (!isVirtualMethod && !isTemplateInstantiation) 00251 D.diag_NeverFallThroughOrReturn = 00252 diag::warn_suggest_noreturn_function; 00253 else 00254 D.diag_NeverFallThroughOrReturn = 0; 00255 00256 D.funMode = Function; 00257 return D; 00258 } 00259 00260 static CheckFallThroughDiagnostics MakeForBlock() { 00261 CheckFallThroughDiagnostics D; 00262 D.diag_MaybeFallThrough_HasNoReturn = 00263 diag::err_noreturn_block_has_return_expr; 00264 D.diag_MaybeFallThrough_ReturnsNonVoid = 00265 diag::err_maybe_falloff_nonvoid_block; 00266 D.diag_AlwaysFallThrough_HasNoReturn = 00267 diag::err_noreturn_block_has_return_expr; 00268 D.diag_AlwaysFallThrough_ReturnsNonVoid = 00269 diag::err_falloff_nonvoid_block; 00270 D.diag_NeverFallThroughOrReturn = 00271 diag::warn_suggest_noreturn_block; 00272 D.funMode = Block; 00273 return D; 00274 } 00275 00276 static CheckFallThroughDiagnostics MakeForLambda() { 00277 CheckFallThroughDiagnostics D; 00278 D.diag_MaybeFallThrough_HasNoReturn = 00279 diag::err_noreturn_lambda_has_return_expr; 00280 D.diag_MaybeFallThrough_ReturnsNonVoid = 00281 diag::warn_maybe_falloff_nonvoid_lambda; 00282 D.diag_AlwaysFallThrough_HasNoReturn = 00283 diag::err_noreturn_lambda_has_return_expr; 00284 D.diag_AlwaysFallThrough_ReturnsNonVoid = 00285 diag::warn_falloff_nonvoid_lambda; 00286 D.diag_NeverFallThroughOrReturn = 0; 00287 D.funMode = Lambda; 00288 return D; 00289 } 00290 00291 bool checkDiagnostics(DiagnosticsEngine &D, bool ReturnsVoid, 00292 bool HasNoReturn) const { 00293 if (funMode == Function) { 00294 return (ReturnsVoid || 00295 D.getDiagnosticLevel(diag::warn_maybe_falloff_nonvoid_function, 00296 FuncLoc) == DiagnosticsEngine::Ignored) 00297 && (!HasNoReturn || 00298 D.getDiagnosticLevel(diag::warn_noreturn_function_has_return_expr, 00299 FuncLoc) == DiagnosticsEngine::Ignored) 00300 && (!ReturnsVoid || 00301 D.getDiagnosticLevel(diag::warn_suggest_noreturn_block, FuncLoc) 00302 == DiagnosticsEngine::Ignored); 00303 } 00304 00305 // For blocks / lambdas. 00306 return ReturnsVoid && !HasNoReturn 00307 && ((funMode == Lambda) || 00308 D.getDiagnosticLevel(diag::warn_suggest_noreturn_block, FuncLoc) 00309 == DiagnosticsEngine::Ignored); 00310 } 00311 }; 00312 00313 } 00314 00315 /// CheckFallThroughForFunctionDef - Check that we don't fall off the end of a 00316 /// function that should return a value. Check that we don't fall off the end 00317 /// of a noreturn function. We assume that functions and blocks not marked 00318 /// noreturn will return. 00319 static void CheckFallThroughForBody(Sema &S, const Decl *D, const Stmt *Body, 00320 const BlockExpr *blkExpr, 00321 const CheckFallThroughDiagnostics& CD, 00322 AnalysisDeclContext &AC) { 00323 00324 bool ReturnsVoid = false; 00325 bool HasNoReturn = false; 00326 00327 if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(D)) { 00328 ReturnsVoid = FD->getResultType()->isVoidType(); 00329 HasNoReturn = FD->hasAttr<NoReturnAttr>() || 00330 FD->getType()->getAs<FunctionType>()->getNoReturnAttr(); 00331 } 00332 else if (const ObjCMethodDecl *MD = dyn_cast<ObjCMethodDecl>(D)) { 00333 ReturnsVoid = MD->getResultType()->isVoidType(); 00334 HasNoReturn = MD->hasAttr<NoReturnAttr>(); 00335 } 00336 else if (isa<BlockDecl>(D)) { 00337 QualType BlockTy = blkExpr->getType(); 00338 if (const FunctionType *FT = 00339 BlockTy->getPointeeType()->getAs<FunctionType>()) { 00340 if (FT->getResultType()->isVoidType()) 00341 ReturnsVoid = true; 00342 if (FT->getNoReturnAttr()) 00343 HasNoReturn = true; 00344 } 00345 } 00346 00347 DiagnosticsEngine &Diags = S.getDiagnostics(); 00348 00349 // Short circuit for compilation speed. 00350 if (CD.checkDiagnostics(Diags, ReturnsVoid, HasNoReturn)) 00351 return; 00352 00353 // FIXME: Function try block 00354 if (const CompoundStmt *Compound = dyn_cast<CompoundStmt>(Body)) { 00355 switch (CheckFallThrough(AC)) { 00356 case UnknownFallThrough: 00357 break; 00358 00359 case MaybeFallThrough: 00360 if (HasNoReturn) 00361 S.Diag(Compound->getRBracLoc(), 00362 CD.diag_MaybeFallThrough_HasNoReturn); 00363 else if (!ReturnsVoid) 00364 S.Diag(Compound->getRBracLoc(), 00365 CD.diag_MaybeFallThrough_ReturnsNonVoid); 00366 break; 00367 case AlwaysFallThrough: 00368 if (HasNoReturn) 00369 S.Diag(Compound->getRBracLoc(), 00370 CD.diag_AlwaysFallThrough_HasNoReturn); 00371 else if (!ReturnsVoid) 00372 S.Diag(Compound->getRBracLoc(), 00373 CD.diag_AlwaysFallThrough_ReturnsNonVoid); 00374 break; 00375 case NeverFallThroughOrReturn: 00376 if (ReturnsVoid && !HasNoReturn && CD.diag_NeverFallThroughOrReturn) { 00377 if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(D)) { 00378 S.Diag(Compound->getLBracLoc(), CD.diag_NeverFallThroughOrReturn) 00379 << 0 << FD; 00380 } else if (const ObjCMethodDecl *MD = dyn_cast<ObjCMethodDecl>(D)) { 00381 S.Diag(Compound->getLBracLoc(), CD.diag_NeverFallThroughOrReturn) 00382 << 1 << MD; 00383 } else { 00384 S.Diag(Compound->getLBracLoc(), CD.diag_NeverFallThroughOrReturn); 00385 } 00386 } 00387 break; 00388 case NeverFallThrough: 00389 break; 00390 } 00391 } 00392 } 00393 00394 //===----------------------------------------------------------------------===// 00395 // -Wuninitialized 00396 //===----------------------------------------------------------------------===// 00397 00398 namespace { 00399 /// ContainsReference - A visitor class to search for references to 00400 /// a particular declaration (the needle) within any evaluated component of an 00401 /// expression (recursively). 00402 class ContainsReference : public EvaluatedExprVisitor<ContainsReference> { 00403 bool FoundReference; 00404 const DeclRefExpr *Needle; 00405 00406 public: 00407 ContainsReference(ASTContext &Context, const DeclRefExpr *Needle) 00408 : EvaluatedExprVisitor<ContainsReference>(Context), 00409 FoundReference(false), Needle(Needle) {} 00410 00411 void VisitExpr(Expr *E) { 00412 // Stop evaluating if we already have a reference. 00413 if (FoundReference) 00414 return; 00415 00416 EvaluatedExprVisitor<ContainsReference>::VisitExpr(E); 00417 } 00418 00419 void VisitDeclRefExpr(DeclRefExpr *E) { 00420 if (E == Needle) 00421 FoundReference = true; 00422 else 00423 EvaluatedExprVisitor<ContainsReference>::VisitDeclRefExpr(E); 00424 } 00425 00426 bool doesContainReference() const { return FoundReference; } 00427 }; 00428 } 00429 00430 static bool SuggestInitializationFixit(Sema &S, const VarDecl *VD) { 00431 QualType VariableTy = VD->getType().getCanonicalType(); 00432 if (VariableTy->isBlockPointerType() && 00433 !VD->hasAttr<BlocksAttr>()) { 00434 S.Diag(VD->getLocation(), diag::note_block_var_fixit_add_initialization) << VD->getDeclName() 00435 << FixItHint::CreateInsertion(VD->getLocation(), "__block "); 00436 return true; 00437 } 00438 00439 // Don't issue a fixit if there is already an initializer. 00440 if (VD->getInit()) 00441 return false; 00442 00443 // Suggest possible initialization (if any). 00444 std::string Init = S.getFixItZeroInitializerForType(VariableTy); 00445 if (Init.empty()) 00446 return false; 00447 00448 // Don't suggest a fixit inside macros. 00449 if (VD->getLocEnd().isMacroID()) 00450 return false; 00451 00452 SourceLocation Loc = S.PP.getLocForEndOfToken(VD->getLocEnd()); 00453 00454 S.Diag(Loc, diag::note_var_fixit_add_initialization) << VD->getDeclName() 00455 << FixItHint::CreateInsertion(Loc, Init); 00456 return true; 00457 } 00458 00459 /// DiagnoseUninitializedUse -- Helper function for diagnosing uses of an 00460 /// uninitialized variable. This manages the different forms of diagnostic 00461 /// emitted for particular types of uses. Returns true if the use was diagnosed 00462 /// as a warning. If a pariticular use is one we omit warnings for, returns 00463 /// false. 00464 static bool DiagnoseUninitializedUse(Sema &S, const VarDecl *VD, 00465 const Expr *E, bool isAlwaysUninit, 00466 bool alwaysReportSelfInit = false) { 00467 00468 if (const DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(E)) { 00469 // Inspect the initializer of the variable declaration which is 00470 // being referenced prior to its initialization. We emit 00471 // specialized diagnostics for self-initialization, and we 00472 // specifically avoid warning about self references which take the 00473 // form of: 00474 // 00475 // int x = x; 00476 // 00477 // This is used to indicate to GCC that 'x' is intentionally left 00478 // uninitialized. Proven code paths which access 'x' in 00479 // an uninitialized state after this will still warn. 00480 if (const Expr *Initializer = VD->getInit()) { 00481 if (!alwaysReportSelfInit && DRE == Initializer->IgnoreParenImpCasts()) 00482 return false; 00483 00484 ContainsReference CR(S.Context, DRE); 00485 CR.Visit(const_cast<Expr*>(Initializer)); 00486 if (CR.doesContainReference()) { 00487 S.Diag(DRE->getLocStart(), 00488 diag::warn_uninit_self_reference_in_init) 00489 << VD->getDeclName() << VD->getLocation() << DRE->getSourceRange(); 00490 return true; 00491 } 00492 } 00493 00494 S.Diag(DRE->getLocStart(), isAlwaysUninit ? diag::warn_uninit_var 00495 : diag::warn_maybe_uninit_var) 00496 << VD->getDeclName() << DRE->getSourceRange(); 00497 } else { 00498 const BlockExpr *BE = cast<BlockExpr>(E); 00499 if (VD->getType()->isBlockPointerType() && 00500 !VD->hasAttr<BlocksAttr>()) 00501 S.Diag(BE->getLocStart(), diag::warn_uninit_byref_blockvar_captured_by_block) 00502 << VD->getDeclName(); 00503 else 00504 S.Diag(BE->getLocStart(), 00505 isAlwaysUninit ? diag::warn_uninit_var_captured_by_block 00506 : diag::warn_maybe_uninit_var_captured_by_block) 00507 << VD->getDeclName(); 00508 } 00509 00510 // Report where the variable was declared when the use wasn't within 00511 // the initializer of that declaration & we didn't already suggest 00512 // an initialization fixit. 00513 if (!SuggestInitializationFixit(S, VD)) 00514 S.Diag(VD->getLocStart(), diag::note_uninit_var_def) 00515 << VD->getDeclName(); 00516 00517 return true; 00518 } 00519 00520 namespace { 00521 class FallthroughMapper : public RecursiveASTVisitor<FallthroughMapper> { 00522 public: 00523 FallthroughMapper(Sema &S) 00524 : FoundSwitchStatements(false), 00525 S(S) { 00526 } 00527 00528 bool foundSwitchStatements() const { return FoundSwitchStatements; } 00529 00530 void markFallthroughVisited(const AttributedStmt *Stmt) { 00531 bool Found = FallthroughStmts.erase(Stmt); 00532 assert(Found); 00533 (void)Found; 00534 } 00535 00536 typedef llvm::SmallPtrSet<const AttributedStmt*, 8> AttrStmts; 00537 00538 const AttrStmts &getFallthroughStmts() const { 00539 return FallthroughStmts; 00540 } 00541 00542 bool checkFallThroughIntoBlock(const CFGBlock &B, int &AnnotatedCnt) { 00543 int UnannotatedCnt = 0; 00544 AnnotatedCnt = 0; 00545 00546 std::deque<const CFGBlock*> BlockQueue; 00547 00548 std::copy(B.pred_begin(), B.pred_end(), std::back_inserter(BlockQueue)); 00549 00550 while (!BlockQueue.empty()) { 00551 const CFGBlock *P = BlockQueue.front(); 00552 BlockQueue.pop_front(); 00553 00554 const Stmt *Term = P->getTerminator(); 00555 if (Term && isa<SwitchStmt>(Term)) 00556 continue; // Switch statement, good. 00557 00558 const SwitchCase *SW = dyn_cast_or_null<SwitchCase>(P->getLabel()); 00559 if (SW && SW->getSubStmt() == B.getLabel() && P->begin() == P->end()) 00560 continue; // Previous case label has no statements, good. 00561 00562 if (P->pred_begin() == P->pred_end()) { // The block is unreachable. 00563 // This only catches trivially unreachable blocks. 00564 for (CFGBlock::const_iterator ElIt = P->begin(), ElEnd = P->end(); 00565 ElIt != ElEnd; ++ElIt) { 00566 if (const CFGStmt *CS = ElIt->getAs<CFGStmt>()){ 00567 if (const AttributedStmt *AS = asFallThroughAttr(CS->getStmt())) { 00568 S.Diag(AS->getLocStart(), 00569 diag::warn_fallthrough_attr_unreachable); 00570 markFallthroughVisited(AS); 00571 ++AnnotatedCnt; 00572 } 00573 // Don't care about other unreachable statements. 00574 } 00575 } 00576 // If there are no unreachable statements, this may be a special 00577 // case in CFG: 00578 // case X: { 00579 // A a; // A has a destructor. 00580 // break; 00581 // } 00582 // // <<<< This place is represented by a 'hanging' CFG block. 00583 // case Y: 00584 continue; 00585 } 00586 00587 const Stmt *LastStmt = getLastStmt(*P); 00588 if (const AttributedStmt *AS = asFallThroughAttr(LastStmt)) { 00589 markFallthroughVisited(AS); 00590 ++AnnotatedCnt; 00591 continue; // Fallthrough annotation, good. 00592 } 00593 00594 if (!LastStmt) { // This block contains no executable statements. 00595 // Traverse its predecessors. 00596 std::copy(P->pred_begin(), P->pred_end(), 00597 std::back_inserter(BlockQueue)); 00598 continue; 00599 } 00600 00601 ++UnannotatedCnt; 00602 } 00603 return !!UnannotatedCnt; 00604 } 00605 00606 // RecursiveASTVisitor setup. 00607 bool shouldWalkTypesOfTypeLocs() const { return false; } 00608 00609 bool VisitAttributedStmt(AttributedStmt *S) { 00610 if (asFallThroughAttr(S)) 00611 FallthroughStmts.insert(S); 00612 return true; 00613 } 00614 00615 bool VisitSwitchStmt(SwitchStmt *S) { 00616 FoundSwitchStatements = true; 00617 return true; 00618 } 00619 00620 private: 00621 00622 static const AttributedStmt *asFallThroughAttr(const Stmt *S) { 00623 if (const AttributedStmt *AS = dyn_cast_or_null<AttributedStmt>(S)) { 00624 if (hasSpecificAttr<FallThroughAttr>(AS->getAttrs())) 00625 return AS; 00626 } 00627 return 0; 00628 } 00629 00630 static const Stmt *getLastStmt(const CFGBlock &B) { 00631 if (const Stmt *Term = B.getTerminator()) 00632 return Term; 00633 for (CFGBlock::const_reverse_iterator ElemIt = B.rbegin(), 00634 ElemEnd = B.rend(); 00635 ElemIt != ElemEnd; ++ElemIt) { 00636 if (const CFGStmt *CS = ElemIt->getAs<CFGStmt>()) 00637 return CS->getStmt(); 00638 } 00639 // Workaround to detect a statement thrown out by CFGBuilder: 00640 // case X: {} case Y: 00641 // case X: ; case Y: 00642 if (const SwitchCase *SW = dyn_cast_or_null<SwitchCase>(B.getLabel())) 00643 if (!isa<SwitchCase>(SW->getSubStmt())) 00644 return SW->getSubStmt(); 00645 00646 return 0; 00647 } 00648 00649 bool FoundSwitchStatements; 00650 AttrStmts FallthroughStmts; 00651 Sema &S; 00652 }; 00653 } 00654 00655 static void DiagnoseSwitchLabelsFallthrough(Sema &S, AnalysisDeclContext &AC) { 00656 FallthroughMapper FM(S); 00657 FM.TraverseStmt(AC.getBody()); 00658 00659 if (!FM.foundSwitchStatements()) 00660 return; 00661 00662 CFG *Cfg = AC.getCFG(); 00663 00664 if (!Cfg) 00665 return; 00666 00667 int AnnotatedCnt; 00668 00669 for (CFG::reverse_iterator I = Cfg->rbegin(), E = Cfg->rend(); I != E; ++I) { 00670 const CFGBlock &B = **I; 00671 const Stmt *Label = B.getLabel(); 00672 00673 if (!Label || !isa<SwitchCase>(Label)) 00674 continue; 00675 00676 if (!FM.checkFallThroughIntoBlock(B, AnnotatedCnt)) 00677 continue; 00678 00679 S.Diag(Label->getLocStart(), diag::warn_unannotated_fallthrough); 00680 00681 if (!AnnotatedCnt) { 00682 SourceLocation L = Label->getLocStart(); 00683 if (L.isMacroID()) 00684 continue; 00685 if (S.getLangOpts().CPlusPlus0x) { 00686 S.Diag(L, diag::note_insert_fallthrough_fixit) << 00687 FixItHint::CreateInsertion(L, "[[clang::fallthrough]]; "); 00688 } 00689 S.Diag(L, diag::note_insert_break_fixit) << 00690 FixItHint::CreateInsertion(L, "break; "); 00691 } 00692 } 00693 00694 const FallthroughMapper::AttrStmts &Fallthroughs = FM.getFallthroughStmts(); 00695 for (FallthroughMapper::AttrStmts::const_iterator I = Fallthroughs.begin(), 00696 E = Fallthroughs.end(); 00697 I != E; ++I) { 00698 S.Diag((*I)->getLocStart(), diag::warn_fallthrough_attr_invalid_placement); 00699 } 00700 00701 } 00702 00703 typedef std::pair<const Expr*, bool> UninitUse; 00704 00705 namespace { 00706 struct SLocSort { 00707 bool operator()(const UninitUse &a, const UninitUse &b) { 00708 SourceLocation aLoc = a.first->getLocStart(); 00709 SourceLocation bLoc = b.first->getLocStart(); 00710 return aLoc.getRawEncoding() < bLoc.getRawEncoding(); 00711 } 00712 }; 00713 00714 class UninitValsDiagReporter : public UninitVariablesHandler { 00715 Sema &S; 00716 typedef SmallVector<UninitUse, 2> UsesVec; 00717 typedef llvm::DenseMap<const VarDecl *, std::pair<UsesVec*, bool> > UsesMap; 00718 UsesMap *uses; 00719 00720 public: 00721 UninitValsDiagReporter(Sema &S) : S(S), uses(0) {} 00722 ~UninitValsDiagReporter() { 00723 flushDiagnostics(); 00724 } 00725 00726 std::pair<UsesVec*, bool> &getUses(const VarDecl *vd) { 00727 if (!uses) 00728 uses = new UsesMap(); 00729 00730 UsesMap::mapped_type &V = (*uses)[vd]; 00731 UsesVec *&vec = V.first; 00732 if (!vec) 00733 vec = new UsesVec(); 00734 00735 return V; 00736 } 00737 00738 void handleUseOfUninitVariable(const Expr *ex, const VarDecl *vd, 00739 bool isAlwaysUninit) { 00740 getUses(vd).first->push_back(std::make_pair(ex, isAlwaysUninit)); 00741 } 00742 00743 void handleSelfInit(const VarDecl *vd) { 00744 getUses(vd).second = true; 00745 } 00746 00747 void flushDiagnostics() { 00748 if (!uses) 00749 return; 00750 00751 for (UsesMap::iterator i = uses->begin(), e = uses->end(); i != e; ++i) { 00752 const VarDecl *vd = i->first; 00753 const UsesMap::mapped_type &V = i->second; 00754 00755 UsesVec *vec = V.first; 00756 bool hasSelfInit = V.second; 00757 00758 // Specially handle the case where we have uses of an uninitialized 00759 // variable, but the root cause is an idiomatic self-init. We want 00760 // to report the diagnostic at the self-init since that is the root cause. 00761 if (!vec->empty() && hasSelfInit && hasAlwaysUninitializedUse(vec)) 00762 DiagnoseUninitializedUse(S, vd, vd->getInit()->IgnoreParenCasts(), 00763 /* isAlwaysUninit */ true, 00764 /* alwaysReportSelfInit */ true); 00765 else { 00766 // Sort the uses by their SourceLocations. While not strictly 00767 // guaranteed to produce them in line/column order, this will provide 00768 // a stable ordering. 00769 std::sort(vec->begin(), vec->end(), SLocSort()); 00770 00771 for (UsesVec::iterator vi = vec->begin(), ve = vec->end(); vi != ve; 00772 ++vi) { 00773 if (DiagnoseUninitializedUse(S, vd, vi->first, 00774 /*isAlwaysUninit=*/vi->second)) 00775 // Skip further diagnostics for this variable. We try to warn only 00776 // on the first point at which a variable is used uninitialized. 00777 break; 00778 } 00779 } 00780 00781 // Release the uses vector. 00782 delete vec; 00783 } 00784 delete uses; 00785 } 00786 00787 private: 00788 static bool hasAlwaysUninitializedUse(const UsesVec* vec) { 00789 for (UsesVec::const_iterator i = vec->begin(), e = vec->end(); i != e; ++i) { 00790 if (i->second) { 00791 return true; 00792 } 00793 } 00794 return false; 00795 } 00796 }; 00797 } 00798 00799 00800 //===----------------------------------------------------------------------===// 00801 // -Wthread-safety 00802 //===----------------------------------------------------------------------===// 00803 namespace clang { 00804 namespace thread_safety { 00805 typedef llvm::SmallVector<PartialDiagnosticAt, 1> OptionalNotes; 00806 typedef std::pair<PartialDiagnosticAt, OptionalNotes> DelayedDiag; 00807 typedef std::list<DelayedDiag> DiagList; 00808 00809 struct SortDiagBySourceLocation { 00810 SourceManager &SM; 00811 SortDiagBySourceLocation(SourceManager &SM) : SM(SM) {} 00812 00813 bool operator()(const DelayedDiag &left, const DelayedDiag &right) { 00814 // Although this call will be slow, this is only called when outputting 00815 // multiple warnings. 00816 return SM.isBeforeInTranslationUnit(left.first.first, right.first.first); 00817 } 00818 }; 00819 00820 namespace { 00821 class ThreadSafetyReporter : public clang::thread_safety::ThreadSafetyHandler { 00822 Sema &S; 00823 DiagList Warnings; 00824 SourceLocation FunLocation, FunEndLocation; 00825 00826 // Helper functions 00827 void warnLockMismatch(unsigned DiagID, Name LockName, SourceLocation Loc) { 00828 // Gracefully handle rare cases when the analysis can't get a more 00829 // precise source location. 00830 if (!Loc.isValid()) 00831 Loc = FunLocation; 00832 PartialDiagnosticAt Warning(Loc, S.PDiag(DiagID) << LockName); 00833 Warnings.push_back(DelayedDiag(Warning, OptionalNotes())); 00834 } 00835 00836 public: 00837 ThreadSafetyReporter(Sema &S, SourceLocation FL, SourceLocation FEL) 00838 : S(S), FunLocation(FL), FunEndLocation(FEL) {} 00839 00840 /// \brief Emit all buffered diagnostics in order of sourcelocation. 00841 /// We need to output diagnostics produced while iterating through 00842 /// the lockset in deterministic order, so this function orders diagnostics 00843 /// and outputs them. 00844 void emitDiagnostics() { 00845 Warnings.sort(SortDiagBySourceLocation(S.getSourceManager())); 00846 for (DiagList::iterator I = Warnings.begin(), E = Warnings.end(); 00847 I != E; ++I) { 00848 S.Diag(I->first.first, I->first.second); 00849 const OptionalNotes &Notes = I->second; 00850 for (unsigned NoteI = 0, NoteN = Notes.size(); NoteI != NoteN; ++NoteI) 00851 S.Diag(Notes[NoteI].first, Notes[NoteI].second); 00852 } 00853 } 00854 00855 void handleInvalidLockExp(SourceLocation Loc) { 00856 PartialDiagnosticAt Warning(Loc, 00857 S.PDiag(diag::warn_cannot_resolve_lock) << Loc); 00858 Warnings.push_back(DelayedDiag(Warning, OptionalNotes())); 00859 } 00860 void handleUnmatchedUnlock(Name LockName, SourceLocation Loc) { 00861 warnLockMismatch(diag::warn_unlock_but_no_lock, LockName, Loc); 00862 } 00863 00864 void handleDoubleLock(Name LockName, SourceLocation Loc) { 00865 warnLockMismatch(diag::warn_double_lock, LockName, Loc); 00866 } 00867 00868 void handleMutexHeldEndOfScope(Name LockName, SourceLocation LocLocked, 00869 SourceLocation LocEndOfScope, 00870 LockErrorKind LEK){ 00871 unsigned DiagID = 0; 00872 switch (LEK) { 00873 case LEK_LockedSomePredecessors: 00874 DiagID = diag::warn_lock_some_predecessors; 00875 break; 00876 case LEK_LockedSomeLoopIterations: 00877 DiagID = diag::warn_expecting_lock_held_on_loop; 00878 break; 00879 case LEK_LockedAtEndOfFunction: 00880 DiagID = diag::warn_no_unlock; 00881 break; 00882 } 00883 if (LocEndOfScope.isInvalid()) 00884 LocEndOfScope = FunEndLocation; 00885 00886 PartialDiagnosticAt Warning(LocEndOfScope, S.PDiag(DiagID) << LockName); 00887 PartialDiagnosticAt Note(LocLocked, S.PDiag(diag::note_locked_here)); 00888 Warnings.push_back(DelayedDiag(Warning, OptionalNotes(1, Note))); 00889 } 00890 00891 00892 void handleExclusiveAndShared(Name LockName, SourceLocation Loc1, 00893 SourceLocation Loc2) { 00894 PartialDiagnosticAt Warning( 00895 Loc1, S.PDiag(diag::warn_lock_exclusive_and_shared) << LockName); 00896 PartialDiagnosticAt Note( 00897 Loc2, S.PDiag(diag::note_lock_exclusive_and_shared) << LockName); 00898 Warnings.push_back(DelayedDiag(Warning, OptionalNotes(1, Note))); 00899 } 00900 00901 void handleNoMutexHeld(const NamedDecl *D, ProtectedOperationKind POK, 00902 AccessKind AK, SourceLocation Loc) { 00903 assert((POK == POK_VarAccess || POK == POK_VarDereference) 00904 && "Only works for variables"); 00905 unsigned DiagID = POK == POK_VarAccess? 00906 diag::warn_variable_requires_any_lock: 00907 diag::warn_var_deref_requires_any_lock; 00908 PartialDiagnosticAt Warning(Loc, S.PDiag(DiagID) 00909 << D->getName() << getLockKindFromAccessKind(AK)); 00910 Warnings.push_back(DelayedDiag(Warning, OptionalNotes())); 00911 } 00912 00913 void handleMutexNotHeld(const NamedDecl *D, ProtectedOperationKind POK, 00914 Name LockName, LockKind LK, SourceLocation Loc) { 00915 unsigned DiagID = 0; 00916 switch (POK) { 00917 case POK_VarAccess: 00918 DiagID = diag::warn_variable_requires_lock; 00919 break; 00920 case POK_VarDereference: 00921 DiagID = diag::warn_var_deref_requires_lock; 00922 break; 00923 case POK_FunctionCall: 00924 DiagID = diag::warn_fun_requires_lock; 00925 break; 00926 } 00927 PartialDiagnosticAt Warning(Loc, S.PDiag(DiagID) 00928 << D->getName() << LockName << LK); 00929 Warnings.push_back(DelayedDiag(Warning, OptionalNotes())); 00930 } 00931 00932 void handleFunExcludesLock(Name FunName, Name LockName, SourceLocation Loc) { 00933 PartialDiagnosticAt Warning(Loc, 00934 S.PDiag(diag::warn_fun_excludes_mutex) << FunName << LockName); 00935 Warnings.push_back(DelayedDiag(Warning, OptionalNotes())); 00936 } 00937 }; 00938 } 00939 } 00940 } 00941 00942 //===----------------------------------------------------------------------===// 00943 // AnalysisBasedWarnings - Worker object used by Sema to execute analysis-based 00944 // warnings on a function, method, or block. 00945 //===----------------------------------------------------------------------===// 00946 00947 clang::sema::AnalysisBasedWarnings::Policy::Policy() { 00948 enableCheckFallThrough = 1; 00949 enableCheckUnreachable = 0; 00950 enableThreadSafetyAnalysis = 0; 00951 } 00952 00953 clang::sema::AnalysisBasedWarnings::AnalysisBasedWarnings(Sema &s) 00954 : S(s), 00955 NumFunctionsAnalyzed(0), 00956 NumFunctionsWithBadCFGs(0), 00957 NumCFGBlocks(0), 00958 MaxCFGBlocksPerFunction(0), 00959 NumUninitAnalysisFunctions(0), 00960 NumUninitAnalysisVariables(0), 00961 MaxUninitAnalysisVariablesPerFunction(0), 00962 NumUninitAnalysisBlockVisits(0), 00963 MaxUninitAnalysisBlockVisitsPerFunction(0) { 00964 DiagnosticsEngine &D = S.getDiagnostics(); 00965 DefaultPolicy.enableCheckUnreachable = (unsigned) 00966 (D.getDiagnosticLevel(diag::warn_unreachable, SourceLocation()) != 00967 DiagnosticsEngine::Ignored); 00968 DefaultPolicy.enableThreadSafetyAnalysis = (unsigned) 00969 (D.getDiagnosticLevel(diag::warn_double_lock, SourceLocation()) != 00970 DiagnosticsEngine::Ignored); 00971 00972 } 00973 00974 static void flushDiagnostics(Sema &S, sema::FunctionScopeInfo *fscope) { 00975 for (SmallVectorImpl<sema::PossiblyUnreachableDiag>::iterator 00976 i = fscope->PossiblyUnreachableDiags.begin(), 00977 e = fscope->PossiblyUnreachableDiags.end(); 00978 i != e; ++i) { 00979 const sema::PossiblyUnreachableDiag &D = *i; 00980 S.Diag(D.Loc, D.PD); 00981 } 00982 } 00983 00984 void clang::sema:: 00985 AnalysisBasedWarnings::IssueWarnings(sema::AnalysisBasedWarnings::Policy P, 00986 sema::FunctionScopeInfo *fscope, 00987 const Decl *D, const BlockExpr *blkExpr) { 00988 00989 // We avoid doing analysis-based warnings when there are errors for 00990 // two reasons: 00991 // (1) The CFGs often can't be constructed (if the body is invalid), so 00992 // don't bother trying. 00993 // (2) The code already has problems; running the analysis just takes more 00994 // time. 00995 DiagnosticsEngine &Diags = S.getDiagnostics(); 00996 00997 // Do not do any analysis for declarations in system headers if we are 00998 // going to just ignore them. 00999 if (Diags.getSuppressSystemWarnings() && 01000 S.SourceMgr.isInSystemHeader(D->getLocation())) 01001 return; 01002 01003 // For code in dependent contexts, we'll do this at instantiation time. 01004 if (cast<DeclContext>(D)->isDependentContext()) 01005 return; 01006 01007 if (Diags.hasErrorOccurred() || Diags.hasFatalErrorOccurred()) { 01008 // Flush out any possibly unreachable diagnostics. 01009 flushDiagnostics(S, fscope); 01010 return; 01011 } 01012 01013 const Stmt *Body = D->getBody(); 01014 assert(Body); 01015 01016 AnalysisDeclContext AC(/* AnalysisDeclContextManager */ 0, D); 01017 01018 // Don't generate EH edges for CallExprs as we'd like to avoid the n^2 01019 // explosion for destrutors that can result and the compile time hit. 01020 AC.getCFGBuildOptions().PruneTriviallyFalseEdges = true; 01021 AC.getCFGBuildOptions().AddEHEdges = false; 01022 AC.getCFGBuildOptions().AddInitializers = true; 01023 AC.getCFGBuildOptions().AddImplicitDtors = true; 01024 01025 // Force that certain expressions appear as CFGElements in the CFG. This 01026 // is used to speed up various analyses. 01027 // FIXME: This isn't the right factoring. This is here for initial 01028 // prototyping, but we need a way for analyses to say what expressions they 01029 // expect to always be CFGElements and then fill in the BuildOptions 01030 // appropriately. This is essentially a layering violation. 01031 if (P.enableCheckUnreachable || P.enableThreadSafetyAnalysis) { 01032 // Unreachable code analysis and thread safety require a linearized CFG. 01033 AC.getCFGBuildOptions().setAllAlwaysAdd(); 01034 } 01035 else { 01036 AC.getCFGBuildOptions() 01037 .setAlwaysAdd(Stmt::BinaryOperatorClass) 01038 .setAlwaysAdd(Stmt::BlockExprClass) 01039 .setAlwaysAdd(Stmt::CStyleCastExprClass) 01040 .setAlwaysAdd(Stmt::DeclRefExprClass) 01041 .setAlwaysAdd(Stmt::ImplicitCastExprClass) 01042 .setAlwaysAdd(Stmt::UnaryOperatorClass) 01043 .setAlwaysAdd(Stmt::AttributedStmtClass); 01044 } 01045 01046 // Construct the analysis context with the specified CFG build options. 01047 01048 // Emit delayed diagnostics. 01049 if (!fscope->PossiblyUnreachableDiags.empty()) { 01050 bool analyzed = false; 01051 01052 // Register the expressions with the CFGBuilder. 01053 for (SmallVectorImpl<sema::PossiblyUnreachableDiag>::iterator 01054 i = fscope->PossiblyUnreachableDiags.begin(), 01055 e = fscope->PossiblyUnreachableDiags.end(); 01056 i != e; ++i) { 01057 if (const Stmt *stmt = i->stmt) 01058 AC.registerForcedBlockExpression(stmt); 01059 } 01060 01061 if (AC.getCFG()) { 01062 analyzed = true; 01063 for (SmallVectorImpl<sema::PossiblyUnreachableDiag>::iterator 01064 i = fscope->PossiblyUnreachableDiags.begin(), 01065 e = fscope->PossiblyUnreachableDiags.end(); 01066 i != e; ++i) 01067 { 01068 const sema::PossiblyUnreachableDiag &D = *i; 01069 bool processed = false; 01070 if (const Stmt *stmt = i->stmt) { 01071 const CFGBlock *block = AC.getBlockForRegisteredExpression(stmt); 01072 CFGReverseBlockReachabilityAnalysis *cra = 01073 AC.getCFGReachablityAnalysis(); 01074 // FIXME: We should be able to assert that block is non-null, but 01075 // the CFG analysis can skip potentially-evaluated expressions in 01076 // edge cases; see test/Sema/vla-2.c. 01077 if (block && cra) { 01078 // Can this block be reached from the entrance? 01079 if (cra->isReachable(&AC.getCFG()->getEntry(), block)) 01080 S.Diag(D.Loc, D.PD); 01081 processed = true; 01082 } 01083 } 01084 if (!processed) { 01085 // Emit the warning anyway if we cannot map to a basic block. 01086 S.Diag(D.Loc, D.PD); 01087 } 01088 } 01089 } 01090 01091 if (!analyzed) 01092 flushDiagnostics(S, fscope); 01093 } 01094 01095 01096 // Warning: check missing 'return' 01097 if (P.enableCheckFallThrough) { 01098 const CheckFallThroughDiagnostics &CD = 01099 (isa<BlockDecl>(D) ? CheckFallThroughDiagnostics::MakeForBlock() 01100 : (isa<CXXMethodDecl>(D) && 01101 cast<CXXMethodDecl>(D)->getOverloadedOperator() == OO_Call && 01102 cast<CXXMethodDecl>(D)->getParent()->isLambda()) 01103 ? CheckFallThroughDiagnostics::MakeForLambda() 01104 : CheckFallThroughDiagnostics::MakeForFunction(D)); 01105 CheckFallThroughForBody(S, D, Body, blkExpr, CD, AC); 01106 } 01107 01108 // Warning: check for unreachable code 01109 if (P.enableCheckUnreachable) { 01110 // Only check for unreachable code on non-template instantiations. 01111 // Different template instantiations can effectively change the control-flow 01112 // and it is very difficult to prove that a snippet of code in a template 01113 // is unreachable for all instantiations. 01114 bool isTemplateInstantiation = false; 01115 if (const FunctionDecl *Function = dyn_cast<FunctionDecl>(D)) 01116 isTemplateInstantiation = Function->isTemplateInstantiation(); 01117 if (!isTemplateInstantiation) 01118 CheckUnreachable(S, AC); 01119 } 01120 01121 // Check for thread safety violations 01122 if (P.enableThreadSafetyAnalysis) { 01123 SourceLocation FL = AC.getDecl()->getLocation(); 01124 SourceLocation FEL = AC.getDecl()->getLocEnd(); 01125 thread_safety::ThreadSafetyReporter Reporter(S, FL, FEL); 01126 thread_safety::runThreadSafetyAnalysis(AC, Reporter); 01127 Reporter.emitDiagnostics(); 01128 } 01129 01130 if (Diags.getDiagnosticLevel(diag::warn_uninit_var, D->getLocStart()) 01131 != DiagnosticsEngine::Ignored || 01132 Diags.getDiagnosticLevel(diag::warn_maybe_uninit_var, D->getLocStart()) 01133 != DiagnosticsEngine::Ignored) { 01134 if (CFG *cfg = AC.getCFG()) { 01135 UninitValsDiagReporter reporter(S); 01136 UninitVariablesAnalysisStats stats; 01137 std::memset(&stats, 0, sizeof(UninitVariablesAnalysisStats)); 01138 runUninitializedVariablesAnalysis(*cast<DeclContext>(D), *cfg, AC, 01139 reporter, stats); 01140 01141 if (S.CollectStats && stats.NumVariablesAnalyzed > 0) { 01142 ++NumUninitAnalysisFunctions; 01143 NumUninitAnalysisVariables += stats.NumVariablesAnalyzed; 01144 NumUninitAnalysisBlockVisits += stats.NumBlockVisits; 01145 MaxUninitAnalysisVariablesPerFunction = 01146 std::max(MaxUninitAnalysisVariablesPerFunction, 01147 stats.NumVariablesAnalyzed); 01148 MaxUninitAnalysisBlockVisitsPerFunction = 01149 std::max(MaxUninitAnalysisBlockVisitsPerFunction, 01150 stats.NumBlockVisits); 01151 } 01152 } 01153 } 01154 01155 if (Diags.getDiagnosticLevel(diag::warn_unannotated_fallthrough, 01156 D->getLocStart()) != DiagnosticsEngine::Ignored) { 01157 DiagnoseSwitchLabelsFallthrough(S, AC); 01158 } 01159 01160 // Collect statistics about the CFG if it was built. 01161 if (S.CollectStats && AC.isCFGBuilt()) { 01162 ++NumFunctionsAnalyzed; 01163 if (CFG *cfg = AC.getCFG()) { 01164 // If we successfully built a CFG for this context, record some more 01165 // detail information about it. 01166 NumCFGBlocks += cfg->getNumBlockIDs(); 01167 MaxCFGBlocksPerFunction = std::max(MaxCFGBlocksPerFunction, 01168 cfg->getNumBlockIDs()); 01169 } else { 01170 ++NumFunctionsWithBadCFGs; 01171 } 01172 } 01173 } 01174 01175 void clang::sema::AnalysisBasedWarnings::PrintStats() const { 01176 llvm::errs() << "\n*** Analysis Based Warnings Stats:\n"; 01177 01178 unsigned NumCFGsBuilt = NumFunctionsAnalyzed - NumFunctionsWithBadCFGs; 01179 unsigned AvgCFGBlocksPerFunction = 01180 !NumCFGsBuilt ? 0 : NumCFGBlocks/NumCFGsBuilt; 01181 llvm::errs() << NumFunctionsAnalyzed << " functions analyzed (" 01182 << NumFunctionsWithBadCFGs << " w/o CFGs).\n" 01183 << " " << NumCFGBlocks << " CFG blocks built.\n" 01184 << " " << AvgCFGBlocksPerFunction 01185 << " average CFG blocks per function.\n" 01186 << " " << MaxCFGBlocksPerFunction 01187 << " max CFG blocks per function.\n"; 01188 01189 unsigned AvgUninitVariablesPerFunction = !NumUninitAnalysisFunctions ? 0 01190 : NumUninitAnalysisVariables/NumUninitAnalysisFunctions; 01191 unsigned AvgUninitBlockVisitsPerFunction = !NumUninitAnalysisFunctions ? 0 01192 : NumUninitAnalysisBlockVisits/NumUninitAnalysisFunctions; 01193 llvm::errs() << NumUninitAnalysisFunctions 01194 << " functions analyzed for uninitialiazed variables\n" 01195 << " " << NumUninitAnalysisVariables << " variables analyzed.\n" 01196 << " " << AvgUninitVariablesPerFunction 01197 << " average variables per function.\n" 01198 << " " << MaxUninitAnalysisVariablesPerFunction 01199 << " max variables per function.\n" 01200 << " " << NumUninitAnalysisBlockVisits << " block visits.\n" 01201 << " " << AvgUninitBlockVisitsPerFunction 01202 << " average block visits per function.\n" 01203 << " " << MaxUninitAnalysisBlockVisitsPerFunction 01204 << " max block visits per function.\n"; 01205 }