1 //=- AnalysisBasedWarnings.cpp - Sema warnings based on libAnalysis -*- C++ -*-=//
3 // The LLVM Compiler Infrastructure
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
8 //===----------------------------------------------------------------------===//
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.
14 //===----------------------------------------------------------------------===//
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/Basic/SourceLocation.h"
21 #include "clang/Lex/Preprocessor.h"
22 #include "clang/Lex/Lexer.h"
23 #include "clang/AST/DeclObjC.h"
24 #include "clang/AST/DeclCXX.h"
25 #include "clang/AST/ExprObjC.h"
26 #include "clang/AST/ExprCXX.h"
27 #include "clang/AST/StmtObjC.h"
28 #include "clang/AST/StmtCXX.h"
29 #include "clang/AST/EvaluatedExprVisitor.h"
30 #include "clang/AST/StmtVisitor.h"
31 #include "clang/AST/RecursiveASTVisitor.h"
32 #include "clang/Analysis/AnalysisContext.h"
33 #include "clang/Analysis/CFG.h"
34 #include "clang/Analysis/Analyses/ReachableCode.h"
35 #include "clang/Analysis/Analyses/CFGReachabilityAnalysis.h"
36 #include "clang/Analysis/Analyses/ThreadSafety.h"
37 #include "clang/Analysis/CFGStmtMap.h"
38 #include "clang/Analysis/Analyses/UninitializedValues.h"
39 #include "llvm/ADT/BitVector.h"
40 #include "llvm/ADT/FoldingSet.h"
41 #include "llvm/ADT/ImmutableMap.h"
42 #include "llvm/ADT/PostOrderIterator.h"
43 #include "llvm/ADT/SmallVector.h"
44 #include "llvm/ADT/StringRef.h"
45 #include "llvm/Support/Casting.h"
51 using namespace clang;
53 //===----------------------------------------------------------------------===//
54 // Unreachable code analysis.
55 //===----------------------------------------------------------------------===//
58 class UnreachableCodeHandler : public reachable_code::Callback {
61 UnreachableCodeHandler(Sema &s) : S(s) {}
63 void HandleUnreachable(SourceLocation L, SourceRange R1, SourceRange R2) {
64 S.Diag(L, diag::warn_unreachable) << R1 << R2;
69 /// CheckUnreachable - Check for unreachable code.
70 static void CheckUnreachable(Sema &S, AnalysisDeclContext &AC) {
71 UnreachableCodeHandler UC(S);
72 reachable_code::FindUnreachableCode(AC, UC);
75 //===----------------------------------------------------------------------===//
76 // Check for missing return value.
77 //===----------------------------------------------------------------------===//
79 enum ControlFlowKind {
84 NeverFallThroughOrReturn
87 /// CheckFallThrough - Check that we don't fall off the end of a
88 /// Statement that should return a value.
90 /// \returns AlwaysFallThrough iff we always fall off the end of the statement,
91 /// MaybeFallThrough iff we might or might not fall off the end,
92 /// NeverFallThroughOrReturn iff we never fall off the end of the statement or
93 /// return. We assume NeverFallThrough iff we never fall off the end of the
94 /// statement but we may return. We assume that functions not marked noreturn
96 static ControlFlowKind CheckFallThrough(AnalysisDeclContext &AC) {
97 CFG *cfg = AC.getCFG();
98 if (cfg == 0) return UnknownFallThrough;
100 // The CFG leaves in dead things, and we don't want the dead code paths to
101 // confuse us, so we mark all live things first.
102 llvm::BitVector live(cfg->getNumBlockIDs());
103 unsigned count = reachable_code::ScanReachableFromBlock(&cfg->getEntry(),
106 bool AddEHEdges = AC.getAddEHEdges();
107 if (!AddEHEdges && count != cfg->getNumBlockIDs())
108 // When there are things remaining dead, and we didn't add EH edges
109 // from CallExprs to the catch clauses, we have to go back and
110 // mark them as live.
111 for (CFG::iterator I = cfg->begin(), E = cfg->end(); I != E; ++I) {
113 if (!live[b.getBlockID()]) {
114 if (b.pred_begin() == b.pred_end()) {
115 if (b.getTerminator() && isa<CXXTryStmt>(b.getTerminator()))
116 // When not adding EH edges from calls, catch clauses
117 // can otherwise seem dead. Avoid noting them as dead.
118 count += reachable_code::ScanReachableFromBlock(&b, live);
124 // Now we know what is live, we check the live precessors of the exit block
125 // and look for fall through paths, being careful to ignore normal returns,
126 // and exceptional paths.
127 bool HasLiveReturn = false;
128 bool HasFakeEdge = false;
129 bool HasPlainEdge = false;
130 bool HasAbnormalEdge = false;
132 // Ignore default cases that aren't likely to be reachable because all
133 // enums in a switch(X) have explicit case statements.
134 CFGBlock::FilterOptions FO;
135 FO.IgnoreDefaultsWithCoveredEnums = 1;
137 for (CFGBlock::filtered_pred_iterator
138 I = cfg->getExit().filtered_pred_start_end(FO); I.hasMore(); ++I) {
139 const CFGBlock& B = **I;
140 if (!live[B.getBlockID()])
143 // Skip blocks which contain an element marked as no-return. They don't
144 // represent actually viable edges into the exit block, so mark them as
146 if (B.hasNoReturnElement()) {
147 HasAbnormalEdge = true;
151 // Destructors can appear after the 'return' in the CFG. This is
152 // normal. We need to look pass the destructors for the return
153 // statement (if it exists).
154 CFGBlock::const_reverse_iterator ri = B.rbegin(), re = B.rend();
156 for ( ; ri != re ; ++ri)
157 if (isa<CFGStmt>(*ri))
160 // No more CFGElements in the block?
162 if (B.getTerminator() && isa<CXXTryStmt>(B.getTerminator())) {
163 HasAbnormalEdge = true;
166 // A labeled empty statement, or the entry block...
171 CFGStmt CS = cast<CFGStmt>(*ri);
172 const Stmt *S = CS.getStmt();
173 if (isa<ReturnStmt>(S)) {
174 HasLiveReturn = true;
177 if (isa<ObjCAtThrowStmt>(S)) {
181 if (isa<CXXThrowExpr>(S)) {
185 if (const AsmStmt *AS = dyn_cast<AsmStmt>(S)) {
188 HasLiveReturn = true;
192 if (isa<MSAsmStmt>(S)) {
193 // TODO: Verify this is correct.
195 HasLiveReturn = true;
198 if (isa<CXXTryStmt>(S)) {
199 HasAbnormalEdge = true;
202 if (std::find(B.succ_begin(), B.succ_end(), &cfg->getExit())
204 HasAbnormalEdge = true;
212 return NeverFallThrough;
213 return NeverFallThroughOrReturn;
215 if (HasAbnormalEdge || HasFakeEdge || HasLiveReturn)
216 return MaybeFallThrough;
217 // This says AlwaysFallThrough for calls to functions that are not marked
218 // noreturn, that don't return. If people would like this warning to be more
219 // accurate, such functions should be marked as noreturn.
220 return AlwaysFallThrough;
225 struct CheckFallThroughDiagnostics {
226 unsigned diag_MaybeFallThrough_HasNoReturn;
227 unsigned diag_MaybeFallThrough_ReturnsNonVoid;
228 unsigned diag_AlwaysFallThrough_HasNoReturn;
229 unsigned diag_AlwaysFallThrough_ReturnsNonVoid;
230 unsigned diag_NeverFallThroughOrReturn;
231 enum { Function, Block, Lambda } funMode;
232 SourceLocation FuncLoc;
234 static CheckFallThroughDiagnostics MakeForFunction(const Decl *Func) {
235 CheckFallThroughDiagnostics D;
236 D.FuncLoc = Func->getLocation();
237 D.diag_MaybeFallThrough_HasNoReturn =
238 diag::warn_falloff_noreturn_function;
239 D.diag_MaybeFallThrough_ReturnsNonVoid =
240 diag::warn_maybe_falloff_nonvoid_function;
241 D.diag_AlwaysFallThrough_HasNoReturn =
242 diag::warn_falloff_noreturn_function;
243 D.diag_AlwaysFallThrough_ReturnsNonVoid =
244 diag::warn_falloff_nonvoid_function;
246 // Don't suggest that virtual functions be marked "noreturn", since they
247 // might be overridden by non-noreturn functions.
248 bool isVirtualMethod = false;
249 if (const CXXMethodDecl *Method = dyn_cast<CXXMethodDecl>(Func))
250 isVirtualMethod = Method->isVirtual();
252 // Don't suggest that template instantiations be marked "noreturn"
253 bool isTemplateInstantiation = false;
254 if (const FunctionDecl *Function = dyn_cast<FunctionDecl>(Func))
255 isTemplateInstantiation = Function->isTemplateInstantiation();
257 if (!isVirtualMethod && !isTemplateInstantiation)
258 D.diag_NeverFallThroughOrReturn =
259 diag::warn_suggest_noreturn_function;
261 D.diag_NeverFallThroughOrReturn = 0;
263 D.funMode = Function;
267 static CheckFallThroughDiagnostics MakeForBlock() {
268 CheckFallThroughDiagnostics D;
269 D.diag_MaybeFallThrough_HasNoReturn =
270 diag::err_noreturn_block_has_return_expr;
271 D.diag_MaybeFallThrough_ReturnsNonVoid =
272 diag::err_maybe_falloff_nonvoid_block;
273 D.diag_AlwaysFallThrough_HasNoReturn =
274 diag::err_noreturn_block_has_return_expr;
275 D.diag_AlwaysFallThrough_ReturnsNonVoid =
276 diag::err_falloff_nonvoid_block;
277 D.diag_NeverFallThroughOrReturn =
278 diag::warn_suggest_noreturn_block;
283 static CheckFallThroughDiagnostics MakeForLambda() {
284 CheckFallThroughDiagnostics D;
285 D.diag_MaybeFallThrough_HasNoReturn =
286 diag::err_noreturn_lambda_has_return_expr;
287 D.diag_MaybeFallThrough_ReturnsNonVoid =
288 diag::warn_maybe_falloff_nonvoid_lambda;
289 D.diag_AlwaysFallThrough_HasNoReturn =
290 diag::err_noreturn_lambda_has_return_expr;
291 D.diag_AlwaysFallThrough_ReturnsNonVoid =
292 diag::warn_falloff_nonvoid_lambda;
293 D.diag_NeverFallThroughOrReturn = 0;
298 bool checkDiagnostics(DiagnosticsEngine &D, bool ReturnsVoid,
299 bool HasNoReturn) const {
300 if (funMode == Function) {
301 return (ReturnsVoid ||
302 D.getDiagnosticLevel(diag::warn_maybe_falloff_nonvoid_function,
303 FuncLoc) == DiagnosticsEngine::Ignored)
305 D.getDiagnosticLevel(diag::warn_noreturn_function_has_return_expr,
306 FuncLoc) == DiagnosticsEngine::Ignored)
308 D.getDiagnosticLevel(diag::warn_suggest_noreturn_block, FuncLoc)
309 == DiagnosticsEngine::Ignored);
312 // For blocks / lambdas.
313 return ReturnsVoid && !HasNoReturn
314 && ((funMode == Lambda) ||
315 D.getDiagnosticLevel(diag::warn_suggest_noreturn_block, FuncLoc)
316 == DiagnosticsEngine::Ignored);
322 /// CheckFallThroughForFunctionDef - Check that we don't fall off the end of a
323 /// function that should return a value. Check that we don't fall off the end
324 /// of a noreturn function. We assume that functions and blocks not marked
325 /// noreturn will return.
326 static void CheckFallThroughForBody(Sema &S, const Decl *D, const Stmt *Body,
327 const BlockExpr *blkExpr,
328 const CheckFallThroughDiagnostics& CD,
329 AnalysisDeclContext &AC) {
331 bool ReturnsVoid = false;
332 bool HasNoReturn = false;
334 if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(D)) {
335 ReturnsVoid = FD->getResultType()->isVoidType();
336 HasNoReturn = FD->hasAttr<NoReturnAttr>() ||
337 FD->getType()->getAs<FunctionType>()->getNoReturnAttr();
339 else if (const ObjCMethodDecl *MD = dyn_cast<ObjCMethodDecl>(D)) {
340 ReturnsVoid = MD->getResultType()->isVoidType();
341 HasNoReturn = MD->hasAttr<NoReturnAttr>();
343 else if (isa<BlockDecl>(D)) {
344 QualType BlockTy = blkExpr->getType();
345 if (const FunctionType *FT =
346 BlockTy->getPointeeType()->getAs<FunctionType>()) {
347 if (FT->getResultType()->isVoidType())
349 if (FT->getNoReturnAttr())
354 DiagnosticsEngine &Diags = S.getDiagnostics();
356 // Short circuit for compilation speed.
357 if (CD.checkDiagnostics(Diags, ReturnsVoid, HasNoReturn))
360 // FIXME: Function try block
361 if (const CompoundStmt *Compound = dyn_cast<CompoundStmt>(Body)) {
362 switch (CheckFallThrough(AC)) {
363 case UnknownFallThrough:
366 case MaybeFallThrough:
368 S.Diag(Compound->getRBracLoc(),
369 CD.diag_MaybeFallThrough_HasNoReturn);
370 else if (!ReturnsVoid)
371 S.Diag(Compound->getRBracLoc(),
372 CD.diag_MaybeFallThrough_ReturnsNonVoid);
374 case AlwaysFallThrough:
376 S.Diag(Compound->getRBracLoc(),
377 CD.diag_AlwaysFallThrough_HasNoReturn);
378 else if (!ReturnsVoid)
379 S.Diag(Compound->getRBracLoc(),
380 CD.diag_AlwaysFallThrough_ReturnsNonVoid);
382 case NeverFallThroughOrReturn:
383 if (ReturnsVoid && !HasNoReturn && CD.diag_NeverFallThroughOrReturn) {
384 if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(D)) {
385 S.Diag(Compound->getLBracLoc(), CD.diag_NeverFallThroughOrReturn)
387 } else if (const ObjCMethodDecl *MD = dyn_cast<ObjCMethodDecl>(D)) {
388 S.Diag(Compound->getLBracLoc(), CD.diag_NeverFallThroughOrReturn)
391 S.Diag(Compound->getLBracLoc(), CD.diag_NeverFallThroughOrReturn);
395 case NeverFallThrough:
401 //===----------------------------------------------------------------------===//
403 //===----------------------------------------------------------------------===//
406 /// ContainsReference - A visitor class to search for references to
407 /// a particular declaration (the needle) within any evaluated component of an
408 /// expression (recursively).
409 class ContainsReference : public EvaluatedExprVisitor<ContainsReference> {
411 const DeclRefExpr *Needle;
414 ContainsReference(ASTContext &Context, const DeclRefExpr *Needle)
415 : EvaluatedExprVisitor<ContainsReference>(Context),
416 FoundReference(false), Needle(Needle) {}
418 void VisitExpr(Expr *E) {
419 // Stop evaluating if we already have a reference.
423 EvaluatedExprVisitor<ContainsReference>::VisitExpr(E);
426 void VisitDeclRefExpr(DeclRefExpr *E) {
428 FoundReference = true;
430 EvaluatedExprVisitor<ContainsReference>::VisitDeclRefExpr(E);
433 bool doesContainReference() const { return FoundReference; }
437 static bool SuggestInitializationFixit(Sema &S, const VarDecl *VD) {
438 QualType VariableTy = VD->getType().getCanonicalType();
439 if (VariableTy->isBlockPointerType() &&
440 !VD->hasAttr<BlocksAttr>()) {
441 S.Diag(VD->getLocation(), diag::note_block_var_fixit_add_initialization) << VD->getDeclName()
442 << FixItHint::CreateInsertion(VD->getLocation(), "__block ");
446 // Don't issue a fixit if there is already an initializer.
450 // Suggest possible initialization (if any).
451 std::string Init = S.getFixItZeroInitializerForType(VariableTy);
455 // Don't suggest a fixit inside macros.
456 if (VD->getLocEnd().isMacroID())
459 SourceLocation Loc = S.PP.getLocForEndOfToken(VD->getLocEnd());
461 S.Diag(Loc, diag::note_var_fixit_add_initialization) << VD->getDeclName()
462 << FixItHint::CreateInsertion(Loc, Init);
466 /// Create a fixit to remove an if-like statement, on the assumption that its
467 /// condition is CondVal.
468 static void CreateIfFixit(Sema &S, const Stmt *If, const Stmt *Then,
469 const Stmt *Else, bool CondVal,
470 FixItHint &Fixit1, FixItHint &Fixit2) {
472 // If condition is always true, remove all but the 'then'.
473 Fixit1 = FixItHint::CreateRemoval(
474 CharSourceRange::getCharRange(If->getLocStart(),
475 Then->getLocStart()));
477 SourceLocation ElseKwLoc = Lexer::getLocForEndOfToken(
478 Then->getLocEnd(), 0, S.getSourceManager(), S.getLangOpts());
479 Fixit2 = FixItHint::CreateRemoval(
480 SourceRange(ElseKwLoc, Else->getLocEnd()));
483 // If condition is always false, remove all but the 'else'.
485 Fixit1 = FixItHint::CreateRemoval(
486 CharSourceRange::getCharRange(If->getLocStart(),
487 Else->getLocStart()));
489 Fixit1 = FixItHint::CreateRemoval(If->getSourceRange());
493 /// DiagUninitUse -- Helper function to produce a diagnostic for an
494 /// uninitialized use of a variable.
495 static void DiagUninitUse(Sema &S, const VarDecl *VD, const UninitUse &Use,
496 bool IsCapturedByBlock) {
497 bool Diagnosed = false;
499 // Diagnose each branch which leads to a sometimes-uninitialized use.
500 for (UninitUse::branch_iterator I = Use.branch_begin(), E = Use.branch_end();
502 assert(Use.getKind() == UninitUse::Sometimes);
504 const Expr *User = Use.getUser();
505 const Stmt *Term = I->Terminator;
507 // Information used when building the diagnostic.
512 // FixIts to suppress the diagnosic by removing the dead condition.
513 // For all binary terminators, branch 0 is taken if the condition is true,
514 // and branch 1 is taken if the condition is false.
515 int RemoveDiagKind = -1;
516 const char *FixitStr =
517 S.getLangOpts().CPlusPlus ? (I->Output ? "true" : "false")
518 : (I->Output ? "1" : "0");
519 FixItHint Fixit1, Fixit2;
521 switch (Term->getStmtClass()) {
523 // Don't know how to report this. Just fall back to 'may be used
524 // uninitialized'. This happens for range-based for, which the user
525 // can't explicitly fix.
526 // FIXME: This also happens if the first use of a variable is always
527 // uninitialized, eg "for (int n; n < 10; ++n)". We should report that
528 // with the 'is uninitialized' diagnostic.
531 // "condition is true / condition is false".
532 case Stmt::IfStmtClass: {
533 const IfStmt *IS = cast<IfStmt>(Term);
536 Range = IS->getCond()->getSourceRange();
538 CreateIfFixit(S, IS, IS->getThen(), IS->getElse(),
539 I->Output, Fixit1, Fixit2);
542 case Stmt::ConditionalOperatorClass: {
543 const ConditionalOperator *CO = cast<ConditionalOperator>(Term);
546 Range = CO->getCond()->getSourceRange();
548 CreateIfFixit(S, CO, CO->getTrueExpr(), CO->getFalseExpr(),
549 I->Output, Fixit1, Fixit2);
552 case Stmt::BinaryOperatorClass: {
553 const BinaryOperator *BO = cast<BinaryOperator>(Term);
554 if (!BO->isLogicalOp())
557 Str = BO->getOpcodeStr();
558 Range = BO->getLHS()->getSourceRange();
560 if ((BO->getOpcode() == BO_LAnd && I->Output) ||
561 (BO->getOpcode() == BO_LOr && !I->Output))
562 // true && y -> y, false || y -> y.
563 Fixit1 = FixItHint::CreateRemoval(SourceRange(BO->getLocStart(),
564 BO->getOperatorLoc()));
566 // false && y -> false, true || y -> true.
567 Fixit1 = FixItHint::CreateReplacement(BO->getSourceRange(), FixitStr);
571 // "loop is entered / loop is exited".
572 case Stmt::WhileStmtClass:
575 Range = cast<WhileStmt>(Term)->getCond()->getSourceRange();
577 Fixit1 = FixItHint::CreateReplacement(Range, FixitStr);
579 case Stmt::ForStmtClass:
582 Range = cast<ForStmt>(Term)->getCond()->getSourceRange();
585 Fixit1 = FixItHint::CreateRemoval(Range);
587 Fixit1 = FixItHint::CreateReplacement(Range, FixitStr);
590 // "condition is true / loop is exited".
591 case Stmt::DoStmtClass:
594 Range = cast<DoStmt>(Term)->getCond()->getSourceRange();
596 Fixit1 = FixItHint::CreateReplacement(Range, FixitStr);
599 // "switch case is taken".
600 case Stmt::CaseStmtClass:
603 Range = cast<CaseStmt>(Term)->getLHS()->getSourceRange();
605 case Stmt::DefaultStmtClass:
608 Range = cast<DefaultStmt>(Term)->getDefaultLoc();
612 S.Diag(Range.getBegin(), diag::warn_sometimes_uninit_var)
613 << VD->getDeclName() << IsCapturedByBlock << DiagKind
614 << Str << I->Output << Range;
615 S.Diag(User->getLocStart(), diag::note_uninit_var_use)
616 << IsCapturedByBlock << User->getSourceRange();
617 if (RemoveDiagKind != -1)
618 S.Diag(Fixit1.RemoveRange.getBegin(), diag::note_uninit_fixit_remove_cond)
619 << RemoveDiagKind << Str << I->Output << Fixit1 << Fixit2;
625 S.Diag(Use.getUser()->getLocStart(),
626 Use.getKind() == UninitUse::Always ? diag::warn_uninit_var
627 : diag::warn_maybe_uninit_var)
628 << VD->getDeclName() << IsCapturedByBlock
629 << Use.getUser()->getSourceRange();
632 /// DiagnoseUninitializedUse -- Helper function for diagnosing uses of an
633 /// uninitialized variable. This manages the different forms of diagnostic
634 /// emitted for particular types of uses. Returns true if the use was diagnosed
635 /// as a warning. If a particular use is one we omit warnings for, returns
637 static bool DiagnoseUninitializedUse(Sema &S, const VarDecl *VD,
638 const UninitUse &Use,
639 bool alwaysReportSelfInit = false) {
641 if (const DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(Use.getUser())) {
642 // Inspect the initializer of the variable declaration which is
643 // being referenced prior to its initialization. We emit
644 // specialized diagnostics for self-initialization, and we
645 // specifically avoid warning about self references which take the
650 // This is used to indicate to GCC that 'x' is intentionally left
651 // uninitialized. Proven code paths which access 'x' in
652 // an uninitialized state after this will still warn.
653 if (const Expr *Initializer = VD->getInit()) {
654 if (!alwaysReportSelfInit && DRE == Initializer->IgnoreParenImpCasts())
657 ContainsReference CR(S.Context, DRE);
658 CR.Visit(const_cast<Expr*>(Initializer));
659 if (CR.doesContainReference()) {
660 S.Diag(DRE->getLocStart(),
661 diag::warn_uninit_self_reference_in_init)
662 << VD->getDeclName() << VD->getLocation() << DRE->getSourceRange();
667 DiagUninitUse(S, VD, Use, false);
669 const BlockExpr *BE = cast<BlockExpr>(Use.getUser());
670 if (VD->getType()->isBlockPointerType() && !VD->hasAttr<BlocksAttr>())
671 S.Diag(BE->getLocStart(),
672 diag::warn_uninit_byref_blockvar_captured_by_block)
673 << VD->getDeclName();
675 DiagUninitUse(S, VD, Use, true);
678 // Report where the variable was declared when the use wasn't within
679 // the initializer of that declaration & we didn't already suggest
680 // an initialization fixit.
681 if (!SuggestInitializationFixit(S, VD))
682 S.Diag(VD->getLocStart(), diag::note_uninit_var_def)
683 << VD->getDeclName();
689 class FallthroughMapper : public RecursiveASTVisitor<FallthroughMapper> {
691 FallthroughMapper(Sema &S)
692 : FoundSwitchStatements(false),
696 bool foundSwitchStatements() const { return FoundSwitchStatements; }
698 void markFallthroughVisited(const AttributedStmt *Stmt) {
699 bool Found = FallthroughStmts.erase(Stmt);
704 typedef llvm::SmallPtrSet<const AttributedStmt*, 8> AttrStmts;
706 const AttrStmts &getFallthroughStmts() const {
707 return FallthroughStmts;
710 bool checkFallThroughIntoBlock(const CFGBlock &B, int &AnnotatedCnt) {
711 int UnannotatedCnt = 0;
714 std::deque<const CFGBlock*> BlockQueue;
716 std::copy(B.pred_begin(), B.pred_end(), std::back_inserter(BlockQueue));
718 while (!BlockQueue.empty()) {
719 const CFGBlock *P = BlockQueue.front();
720 BlockQueue.pop_front();
722 const Stmt *Term = P->getTerminator();
723 if (Term && isa<SwitchStmt>(Term))
724 continue; // Switch statement, good.
726 const SwitchCase *SW = dyn_cast_or_null<SwitchCase>(P->getLabel());
727 if (SW && SW->getSubStmt() == B.getLabel() && P->begin() == P->end())
728 continue; // Previous case label has no statements, good.
730 if (P->pred_begin() == P->pred_end()) { // The block is unreachable.
731 // This only catches trivially unreachable blocks.
732 for (CFGBlock::const_iterator ElIt = P->begin(), ElEnd = P->end();
733 ElIt != ElEnd; ++ElIt) {
734 if (const CFGStmt *CS = ElIt->getAs<CFGStmt>()){
735 if (const AttributedStmt *AS = asFallThroughAttr(CS->getStmt())) {
736 S.Diag(AS->getLocStart(),
737 diag::warn_fallthrough_attr_unreachable);
738 markFallthroughVisited(AS);
741 // Don't care about other unreachable statements.
744 // If there are no unreachable statements, this may be a special
747 // A a; // A has a destructor.
750 // // <<<< This place is represented by a 'hanging' CFG block.
755 const Stmt *LastStmt = getLastStmt(*P);
756 if (const AttributedStmt *AS = asFallThroughAttr(LastStmt)) {
757 markFallthroughVisited(AS);
759 continue; // Fallthrough annotation, good.
762 if (!LastStmt) { // This block contains no executable statements.
763 // Traverse its predecessors.
764 std::copy(P->pred_begin(), P->pred_end(),
765 std::back_inserter(BlockQueue));
771 return !!UnannotatedCnt;
774 // RecursiveASTVisitor setup.
775 bool shouldWalkTypesOfTypeLocs() const { return false; }
777 bool VisitAttributedStmt(AttributedStmt *S) {
778 if (asFallThroughAttr(S))
779 FallthroughStmts.insert(S);
783 bool VisitSwitchStmt(SwitchStmt *S) {
784 FoundSwitchStatements = true;
790 static const AttributedStmt *asFallThroughAttr(const Stmt *S) {
791 if (const AttributedStmt *AS = dyn_cast_or_null<AttributedStmt>(S)) {
792 if (hasSpecificAttr<FallThroughAttr>(AS->getAttrs()))
798 static const Stmt *getLastStmt(const CFGBlock &B) {
799 if (const Stmt *Term = B.getTerminator())
801 for (CFGBlock::const_reverse_iterator ElemIt = B.rbegin(),
803 ElemIt != ElemEnd; ++ElemIt) {
804 if (const CFGStmt *CS = ElemIt->getAs<CFGStmt>())
805 return CS->getStmt();
807 // Workaround to detect a statement thrown out by CFGBuilder:
808 // case X: {} case Y:
810 if (const SwitchCase *SW = dyn_cast_or_null<SwitchCase>(B.getLabel()))
811 if (!isa<SwitchCase>(SW->getSubStmt()))
812 return SW->getSubStmt();
817 bool FoundSwitchStatements;
818 AttrStmts FallthroughStmts;
823 static void DiagnoseSwitchLabelsFallthrough(Sema &S, AnalysisDeclContext &AC,
825 FallthroughMapper FM(S);
826 FM.TraverseStmt(AC.getBody());
828 if (!FM.foundSwitchStatements())
831 if (PerFunction && FM.getFallthroughStmts().empty())
834 CFG *Cfg = AC.getCFG();
841 for (CFG::reverse_iterator I = Cfg->rbegin(), E = Cfg->rend(); I != E; ++I) {
842 const CFGBlock &B = **I;
843 const Stmt *Label = B.getLabel();
845 if (!Label || !isa<SwitchCase>(Label))
848 if (!FM.checkFallThroughIntoBlock(B, AnnotatedCnt))
851 S.Diag(Label->getLocStart(),
852 PerFunction ? diag::warn_unannotated_fallthrough_per_function
853 : diag::warn_unannotated_fallthrough);
856 SourceLocation L = Label->getLocStart();
859 if (S.getLangOpts().CPlusPlus0x) {
860 const Stmt *Term = B.getTerminator();
861 if (!(B.empty() && Term && isa<BreakStmt>(Term))) {
862 S.Diag(L, diag::note_insert_fallthrough_fixit) <<
863 FixItHint::CreateInsertion(L, "[[clang::fallthrough]]; ");
866 S.Diag(L, diag::note_insert_break_fixit) <<
867 FixItHint::CreateInsertion(L, "break; ");
871 const FallthroughMapper::AttrStmts &Fallthroughs = FM.getFallthroughStmts();
872 for (FallthroughMapper::AttrStmts::const_iterator I = Fallthroughs.begin(),
873 E = Fallthroughs.end();
875 S.Diag((*I)->getLocStart(), diag::warn_fallthrough_attr_invalid_placement);
882 bool operator()(const UninitUse &a, const UninitUse &b) {
883 // Prefer a more confident report over a less confident one.
884 if (a.getKind() != b.getKind())
885 return a.getKind() > b.getKind();
886 SourceLocation aLoc = a.getUser()->getLocStart();
887 SourceLocation bLoc = b.getUser()->getLocStart();
888 return aLoc.getRawEncoding() < bLoc.getRawEncoding();
892 class UninitValsDiagReporter : public UninitVariablesHandler {
894 typedef SmallVector<UninitUse, 2> UsesVec;
895 typedef llvm::DenseMap<const VarDecl *, std::pair<UsesVec*, bool> > UsesMap;
899 UninitValsDiagReporter(Sema &S) : S(S), uses(0) {}
900 ~UninitValsDiagReporter() {
904 std::pair<UsesVec*, bool> &getUses(const VarDecl *vd) {
906 uses = new UsesMap();
908 UsesMap::mapped_type &V = (*uses)[vd];
909 UsesVec *&vec = V.first;
916 void handleUseOfUninitVariable(const VarDecl *vd, const UninitUse &use) {
917 getUses(vd).first->push_back(use);
920 void handleSelfInit(const VarDecl *vd) {
921 getUses(vd).second = true;
924 void flushDiagnostics() {
928 // FIXME: This iteration order, and thus the resulting diagnostic order,
929 // is nondeterministic.
930 for (UsesMap::iterator i = uses->begin(), e = uses->end(); i != e; ++i) {
931 const VarDecl *vd = i->first;
932 const UsesMap::mapped_type &V = i->second;
934 UsesVec *vec = V.first;
935 bool hasSelfInit = V.second;
937 // Specially handle the case where we have uses of an uninitialized
938 // variable, but the root cause is an idiomatic self-init. We want
939 // to report the diagnostic at the self-init since that is the root cause.
940 if (!vec->empty() && hasSelfInit && hasAlwaysUninitializedUse(vec))
941 DiagnoseUninitializedUse(S, vd,
942 UninitUse(vd->getInit()->IgnoreParenCasts(),
943 /* isAlwaysUninit */ true),
944 /* alwaysReportSelfInit */ true);
946 // Sort the uses by their SourceLocations. While not strictly
947 // guaranteed to produce them in line/column order, this will provide
948 // a stable ordering.
949 std::sort(vec->begin(), vec->end(), SLocSort());
951 for (UsesVec::iterator vi = vec->begin(), ve = vec->end(); vi != ve;
953 // If we have self-init, downgrade all uses to 'may be uninitialized'.
954 UninitUse Use = hasSelfInit ? UninitUse(vi->getUser(), false) : *vi;
956 if (DiagnoseUninitializedUse(S, vd, Use))
957 // Skip further diagnostics for this variable. We try to warn only
958 // on the first point at which a variable is used uninitialized.
963 // Release the uses vector.
970 static bool hasAlwaysUninitializedUse(const UsesVec* vec) {
971 for (UsesVec::const_iterator i = vec->begin(), e = vec->end(); i != e; ++i) {
972 if (i->getKind() == UninitUse::Always) {
982 //===----------------------------------------------------------------------===//
984 //===----------------------------------------------------------------------===//
986 namespace thread_safety {
987 typedef llvm::SmallVector<PartialDiagnosticAt, 1> OptionalNotes;
988 typedef std::pair<PartialDiagnosticAt, OptionalNotes> DelayedDiag;
989 typedef std::list<DelayedDiag> DiagList;
991 struct SortDiagBySourceLocation {
993 SortDiagBySourceLocation(SourceManager &SM) : SM(SM) {}
995 bool operator()(const DelayedDiag &left, const DelayedDiag &right) {
996 // Although this call will be slow, this is only called when outputting
997 // multiple warnings.
998 return SM.isBeforeInTranslationUnit(left.first.first, right.first.first);
1003 class ThreadSafetyReporter : public clang::thread_safety::ThreadSafetyHandler {
1006 SourceLocation FunLocation, FunEndLocation;
1009 void warnLockMismatch(unsigned DiagID, Name LockName, SourceLocation Loc) {
1010 // Gracefully handle rare cases when the analysis can't get a more
1011 // precise source location.
1014 PartialDiagnosticAt Warning(Loc, S.PDiag(DiagID) << LockName);
1015 Warnings.push_back(DelayedDiag(Warning, OptionalNotes()));
1019 ThreadSafetyReporter(Sema &S, SourceLocation FL, SourceLocation FEL)
1020 : S(S), FunLocation(FL), FunEndLocation(FEL) {}
1022 /// \brief Emit all buffered diagnostics in order of sourcelocation.
1023 /// We need to output diagnostics produced while iterating through
1024 /// the lockset in deterministic order, so this function orders diagnostics
1025 /// and outputs them.
1026 void emitDiagnostics() {
1027 Warnings.sort(SortDiagBySourceLocation(S.getSourceManager()));
1028 for (DiagList::iterator I = Warnings.begin(), E = Warnings.end();
1030 S.Diag(I->first.first, I->first.second);
1031 const OptionalNotes &Notes = I->second;
1032 for (unsigned NoteI = 0, NoteN = Notes.size(); NoteI != NoteN; ++NoteI)
1033 S.Diag(Notes[NoteI].first, Notes[NoteI].second);
1037 void handleInvalidLockExp(SourceLocation Loc) {
1038 PartialDiagnosticAt Warning(Loc,
1039 S.PDiag(diag::warn_cannot_resolve_lock) << Loc);
1040 Warnings.push_back(DelayedDiag(Warning, OptionalNotes()));
1042 void handleUnmatchedUnlock(Name LockName, SourceLocation Loc) {
1043 warnLockMismatch(diag::warn_unlock_but_no_lock, LockName, Loc);
1046 void handleDoubleLock(Name LockName, SourceLocation Loc) {
1047 warnLockMismatch(diag::warn_double_lock, LockName, Loc);
1050 void handleMutexHeldEndOfScope(Name LockName, SourceLocation LocLocked,
1051 SourceLocation LocEndOfScope,
1053 unsigned DiagID = 0;
1055 case LEK_LockedSomePredecessors:
1056 DiagID = diag::warn_lock_some_predecessors;
1058 case LEK_LockedSomeLoopIterations:
1059 DiagID = diag::warn_expecting_lock_held_on_loop;
1061 case LEK_LockedAtEndOfFunction:
1062 DiagID = diag::warn_no_unlock;
1064 case LEK_NotLockedAtEndOfFunction:
1065 DiagID = diag::warn_expecting_locked;
1068 if (LocEndOfScope.isInvalid())
1069 LocEndOfScope = FunEndLocation;
1071 PartialDiagnosticAt Warning(LocEndOfScope, S.PDiag(DiagID) << LockName);
1072 PartialDiagnosticAt Note(LocLocked, S.PDiag(diag::note_locked_here));
1073 Warnings.push_back(DelayedDiag(Warning, OptionalNotes(1, Note)));
1077 void handleExclusiveAndShared(Name LockName, SourceLocation Loc1,
1078 SourceLocation Loc2) {
1079 PartialDiagnosticAt Warning(
1080 Loc1, S.PDiag(diag::warn_lock_exclusive_and_shared) << LockName);
1081 PartialDiagnosticAt Note(
1082 Loc2, S.PDiag(diag::note_lock_exclusive_and_shared) << LockName);
1083 Warnings.push_back(DelayedDiag(Warning, OptionalNotes(1, Note)));
1086 void handleNoMutexHeld(const NamedDecl *D, ProtectedOperationKind POK,
1087 AccessKind AK, SourceLocation Loc) {
1088 assert((POK == POK_VarAccess || POK == POK_VarDereference)
1089 && "Only works for variables");
1090 unsigned DiagID = POK == POK_VarAccess?
1091 diag::warn_variable_requires_any_lock:
1092 diag::warn_var_deref_requires_any_lock;
1093 PartialDiagnosticAt Warning(Loc, S.PDiag(DiagID)
1094 << D->getName() << getLockKindFromAccessKind(AK));
1095 Warnings.push_back(DelayedDiag(Warning, OptionalNotes()));
1098 void handleMutexNotHeld(const NamedDecl *D, ProtectedOperationKind POK,
1099 Name LockName, LockKind LK, SourceLocation Loc) {
1100 unsigned DiagID = 0;
1103 DiagID = diag::warn_variable_requires_lock;
1105 case POK_VarDereference:
1106 DiagID = diag::warn_var_deref_requires_lock;
1108 case POK_FunctionCall:
1109 DiagID = diag::warn_fun_requires_lock;
1112 PartialDiagnosticAt Warning(Loc, S.PDiag(DiagID)
1113 << D->getName() << LockName << LK);
1114 Warnings.push_back(DelayedDiag(Warning, OptionalNotes()));
1117 void handleFunExcludesLock(Name FunName, Name LockName, SourceLocation Loc) {
1118 PartialDiagnosticAt Warning(Loc,
1119 S.PDiag(diag::warn_fun_excludes_mutex) << FunName << LockName);
1120 Warnings.push_back(DelayedDiag(Warning, OptionalNotes()));
1127 //===----------------------------------------------------------------------===//
1128 // AnalysisBasedWarnings - Worker object used by Sema to execute analysis-based
1129 // warnings on a function, method, or block.
1130 //===----------------------------------------------------------------------===//
1132 clang::sema::AnalysisBasedWarnings::Policy::Policy() {
1133 enableCheckFallThrough = 1;
1134 enableCheckUnreachable = 0;
1135 enableThreadSafetyAnalysis = 0;
1138 clang::sema::AnalysisBasedWarnings::AnalysisBasedWarnings(Sema &s)
1140 NumFunctionsAnalyzed(0),
1141 NumFunctionsWithBadCFGs(0),
1143 MaxCFGBlocksPerFunction(0),
1144 NumUninitAnalysisFunctions(0),
1145 NumUninitAnalysisVariables(0),
1146 MaxUninitAnalysisVariablesPerFunction(0),
1147 NumUninitAnalysisBlockVisits(0),
1148 MaxUninitAnalysisBlockVisitsPerFunction(0) {
1149 DiagnosticsEngine &D = S.getDiagnostics();
1150 DefaultPolicy.enableCheckUnreachable = (unsigned)
1151 (D.getDiagnosticLevel(diag::warn_unreachable, SourceLocation()) !=
1152 DiagnosticsEngine::Ignored);
1153 DefaultPolicy.enableThreadSafetyAnalysis = (unsigned)
1154 (D.getDiagnosticLevel(diag::warn_double_lock, SourceLocation()) !=
1155 DiagnosticsEngine::Ignored);
1159 static void flushDiagnostics(Sema &S, sema::FunctionScopeInfo *fscope) {
1160 for (SmallVectorImpl<sema::PossiblyUnreachableDiag>::iterator
1161 i = fscope->PossiblyUnreachableDiags.begin(),
1162 e = fscope->PossiblyUnreachableDiags.end();
1164 const sema::PossiblyUnreachableDiag &D = *i;
1165 S.Diag(D.Loc, D.PD);
1170 AnalysisBasedWarnings::IssueWarnings(sema::AnalysisBasedWarnings::Policy P,
1171 sema::FunctionScopeInfo *fscope,
1172 const Decl *D, const BlockExpr *blkExpr) {
1174 // We avoid doing analysis-based warnings when there are errors for
1176 // (1) The CFGs often can't be constructed (if the body is invalid), so
1177 // don't bother trying.
1178 // (2) The code already has problems; running the analysis just takes more
1180 DiagnosticsEngine &Diags = S.getDiagnostics();
1182 // Do not do any analysis for declarations in system headers if we are
1183 // going to just ignore them.
1184 if (Diags.getSuppressSystemWarnings() &&
1185 S.SourceMgr.isInSystemHeader(D->getLocation()))
1188 // For code in dependent contexts, we'll do this at instantiation time.
1189 if (cast<DeclContext>(D)->isDependentContext())
1192 if (Diags.hasErrorOccurred() || Diags.hasFatalErrorOccurred()) {
1193 // Flush out any possibly unreachable diagnostics.
1194 flushDiagnostics(S, fscope);
1198 const Stmt *Body = D->getBody();
1201 AnalysisDeclContext AC(/* AnalysisDeclContextManager */ 0, D);
1203 // Don't generate EH edges for CallExprs as we'd like to avoid the n^2
1204 // explosion for destrutors that can result and the compile time hit.
1205 AC.getCFGBuildOptions().PruneTriviallyFalseEdges = true;
1206 AC.getCFGBuildOptions().AddEHEdges = false;
1207 AC.getCFGBuildOptions().AddInitializers = true;
1208 AC.getCFGBuildOptions().AddImplicitDtors = true;
1210 // Force that certain expressions appear as CFGElements in the CFG. This
1211 // is used to speed up various analyses.
1212 // FIXME: This isn't the right factoring. This is here for initial
1213 // prototyping, but we need a way for analyses to say what expressions they
1214 // expect to always be CFGElements and then fill in the BuildOptions
1215 // appropriately. This is essentially a layering violation.
1216 if (P.enableCheckUnreachable || P.enableThreadSafetyAnalysis) {
1217 // Unreachable code analysis and thread safety require a linearized CFG.
1218 AC.getCFGBuildOptions().setAllAlwaysAdd();
1221 AC.getCFGBuildOptions()
1222 .setAlwaysAdd(Stmt::BinaryOperatorClass)
1223 .setAlwaysAdd(Stmt::CompoundAssignOperatorClass)
1224 .setAlwaysAdd(Stmt::BlockExprClass)
1225 .setAlwaysAdd(Stmt::CStyleCastExprClass)
1226 .setAlwaysAdd(Stmt::DeclRefExprClass)
1227 .setAlwaysAdd(Stmt::ImplicitCastExprClass)
1228 .setAlwaysAdd(Stmt::UnaryOperatorClass)
1229 .setAlwaysAdd(Stmt::AttributedStmtClass);
1232 // Construct the analysis context with the specified CFG build options.
1234 // Emit delayed diagnostics.
1235 if (!fscope->PossiblyUnreachableDiags.empty()) {
1236 bool analyzed = false;
1238 // Register the expressions with the CFGBuilder.
1239 for (SmallVectorImpl<sema::PossiblyUnreachableDiag>::iterator
1240 i = fscope->PossiblyUnreachableDiags.begin(),
1241 e = fscope->PossiblyUnreachableDiags.end();
1243 if (const Stmt *stmt = i->stmt)
1244 AC.registerForcedBlockExpression(stmt);
1249 for (SmallVectorImpl<sema::PossiblyUnreachableDiag>::iterator
1250 i = fscope->PossiblyUnreachableDiags.begin(),
1251 e = fscope->PossiblyUnreachableDiags.end();
1254 const sema::PossiblyUnreachableDiag &D = *i;
1255 bool processed = false;
1256 if (const Stmt *stmt = i->stmt) {
1257 const CFGBlock *block = AC.getBlockForRegisteredExpression(stmt);
1258 CFGReverseBlockReachabilityAnalysis *cra =
1259 AC.getCFGReachablityAnalysis();
1260 // FIXME: We should be able to assert that block is non-null, but
1261 // the CFG analysis can skip potentially-evaluated expressions in
1262 // edge cases; see test/Sema/vla-2.c.
1264 // Can this block be reached from the entrance?
1265 if (cra->isReachable(&AC.getCFG()->getEntry(), block))
1266 S.Diag(D.Loc, D.PD);
1271 // Emit the warning anyway if we cannot map to a basic block.
1272 S.Diag(D.Loc, D.PD);
1278 flushDiagnostics(S, fscope);
1282 // Warning: check missing 'return'
1283 if (P.enableCheckFallThrough) {
1284 const CheckFallThroughDiagnostics &CD =
1285 (isa<BlockDecl>(D) ? CheckFallThroughDiagnostics::MakeForBlock()
1286 : (isa<CXXMethodDecl>(D) &&
1287 cast<CXXMethodDecl>(D)->getOverloadedOperator() == OO_Call &&
1288 cast<CXXMethodDecl>(D)->getParent()->isLambda())
1289 ? CheckFallThroughDiagnostics::MakeForLambda()
1290 : CheckFallThroughDiagnostics::MakeForFunction(D));
1291 CheckFallThroughForBody(S, D, Body, blkExpr, CD, AC);
1294 // Warning: check for unreachable code
1295 if (P.enableCheckUnreachable) {
1296 // Only check for unreachable code on non-template instantiations.
1297 // Different template instantiations can effectively change the control-flow
1298 // and it is very difficult to prove that a snippet of code in a template
1299 // is unreachable for all instantiations.
1300 bool isTemplateInstantiation = false;
1301 if (const FunctionDecl *Function = dyn_cast<FunctionDecl>(D))
1302 isTemplateInstantiation = Function->isTemplateInstantiation();
1303 if (!isTemplateInstantiation)
1304 CheckUnreachable(S, AC);
1307 // Check for thread safety violations
1308 if (P.enableThreadSafetyAnalysis) {
1309 SourceLocation FL = AC.getDecl()->getLocation();
1310 SourceLocation FEL = AC.getDecl()->getLocEnd();
1311 thread_safety::ThreadSafetyReporter Reporter(S, FL, FEL);
1312 thread_safety::runThreadSafetyAnalysis(AC, Reporter);
1313 Reporter.emitDiagnostics();
1316 if (Diags.getDiagnosticLevel(diag::warn_uninit_var, D->getLocStart())
1317 != DiagnosticsEngine::Ignored ||
1318 Diags.getDiagnosticLevel(diag::warn_sometimes_uninit_var,D->getLocStart())
1319 != DiagnosticsEngine::Ignored ||
1320 Diags.getDiagnosticLevel(diag::warn_maybe_uninit_var, D->getLocStart())
1321 != DiagnosticsEngine::Ignored) {
1322 if (CFG *cfg = AC.getCFG()) {
1323 UninitValsDiagReporter reporter(S);
1324 UninitVariablesAnalysisStats stats;
1325 std::memset(&stats, 0, sizeof(UninitVariablesAnalysisStats));
1326 runUninitializedVariablesAnalysis(*cast<DeclContext>(D), *cfg, AC,
1329 if (S.CollectStats && stats.NumVariablesAnalyzed > 0) {
1330 ++NumUninitAnalysisFunctions;
1331 NumUninitAnalysisVariables += stats.NumVariablesAnalyzed;
1332 NumUninitAnalysisBlockVisits += stats.NumBlockVisits;
1333 MaxUninitAnalysisVariablesPerFunction =
1334 std::max(MaxUninitAnalysisVariablesPerFunction,
1335 stats.NumVariablesAnalyzed);
1336 MaxUninitAnalysisBlockVisitsPerFunction =
1337 std::max(MaxUninitAnalysisBlockVisitsPerFunction,
1338 stats.NumBlockVisits);
1343 bool FallThroughDiagFull =
1344 Diags.getDiagnosticLevel(diag::warn_unannotated_fallthrough,
1345 D->getLocStart()) != DiagnosticsEngine::Ignored;
1346 bool FallThroughDiagPerFunction =
1347 Diags.getDiagnosticLevel(diag::warn_unannotated_fallthrough_per_function,
1348 D->getLocStart()) != DiagnosticsEngine::Ignored;
1349 if (FallThroughDiagFull || FallThroughDiagPerFunction) {
1350 DiagnoseSwitchLabelsFallthrough(S, AC, !FallThroughDiagFull);
1353 // Collect statistics about the CFG if it was built.
1354 if (S.CollectStats && AC.isCFGBuilt()) {
1355 ++NumFunctionsAnalyzed;
1356 if (CFG *cfg = AC.getCFG()) {
1357 // If we successfully built a CFG for this context, record some more
1358 // detail information about it.
1359 NumCFGBlocks += cfg->getNumBlockIDs();
1360 MaxCFGBlocksPerFunction = std::max(MaxCFGBlocksPerFunction,
1361 cfg->getNumBlockIDs());
1363 ++NumFunctionsWithBadCFGs;
1368 void clang::sema::AnalysisBasedWarnings::PrintStats() const {
1369 llvm::errs() << "\n*** Analysis Based Warnings Stats:\n";
1371 unsigned NumCFGsBuilt = NumFunctionsAnalyzed - NumFunctionsWithBadCFGs;
1372 unsigned AvgCFGBlocksPerFunction =
1373 !NumCFGsBuilt ? 0 : NumCFGBlocks/NumCFGsBuilt;
1374 llvm::errs() << NumFunctionsAnalyzed << " functions analyzed ("
1375 << NumFunctionsWithBadCFGs << " w/o CFGs).\n"
1376 << " " << NumCFGBlocks << " CFG blocks built.\n"
1377 << " " << AvgCFGBlocksPerFunction
1378 << " average CFG blocks per function.\n"
1379 << " " << MaxCFGBlocksPerFunction
1380 << " max CFG blocks per function.\n";
1382 unsigned AvgUninitVariablesPerFunction = !NumUninitAnalysisFunctions ? 0
1383 : NumUninitAnalysisVariables/NumUninitAnalysisFunctions;
1384 unsigned AvgUninitBlockVisitsPerFunction = !NumUninitAnalysisFunctions ? 0
1385 : NumUninitAnalysisBlockVisits/NumUninitAnalysisFunctions;
1386 llvm::errs() << NumUninitAnalysisFunctions
1387 << " functions analyzed for uninitialiazed variables\n"
1388 << " " << NumUninitAnalysisVariables << " variables analyzed.\n"
1389 << " " << AvgUninitVariablesPerFunction
1390 << " average variables per function.\n"
1391 << " " << MaxUninitAnalysisVariablesPerFunction
1392 << " max variables per function.\n"
1393 << " " << NumUninitAnalysisBlockVisits << " block visits.\n"
1394 << " " << AvgUninitBlockVisitsPerFunction
1395 << " average block visits per function.\n"
1396 << " " << MaxUninitAnalysisBlockVisitsPerFunction
1397 << " max block visits per function.\n";