AnalysisBasedWarnings.cpp revision c263704cb007eb95b79f37b12a8092c47146d452
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 "Sema.h" 17#include "AnalysisBasedWarnings.h" 18#include "clang/Basic/SourceManager.h" 19#include "clang/AST/ExprObjC.h" 20#include "clang/AST/ExprCXX.h" 21#include "clang/AST/StmtObjC.h" 22#include "clang/AST/StmtCXX.h" 23#include "clang/Analysis/AnalysisContext.h" 24#include "clang/Analysis/CFG.h" 25#include "clang/Analysis/Analyses/ReachableCode.h" 26#include "llvm/ADT/BitVector.h" 27#include "llvm/Support/Casting.h" 28#include <queue> 29 30using namespace clang; 31 32//===----------------------------------------------------------------------===// 33// Unreachable code analysis. 34//===----------------------------------------------------------------------===// 35 36namespace { 37 class UnreachableCodeHandler : public reachable_code::Callback { 38 Sema &S; 39 public: 40 UnreachableCodeHandler(Sema &s) : S(s) {} 41 42 void HandleUnreachable(SourceLocation L, SourceRange R1, SourceRange R2) { 43 S.Diag(L, diag::warn_unreachable) << R1 << R2; 44 } 45 }; 46} 47 48/// CheckUnreachable - Check for unreachable code. 49static void CheckUnreachable(Sema &S, AnalysisContext &AC) { 50 UnreachableCodeHandler UC(S); 51 reachable_code::FindUnreachableCode(AC, UC); 52} 53 54//===----------------------------------------------------------------------===// 55// Check for missing return value. 56//===----------------------------------------------------------------------===// 57 58enum ControlFlowKind { NeverFallThrough = 0, MaybeFallThrough = 1, 59 AlwaysFallThrough = 2, NeverFallThroughOrReturn = 3 }; 60 61/// CheckFallThrough - Check that we don't fall off the end of a 62/// Statement that should return a value. 63/// 64/// \returns AlwaysFallThrough iff we always fall off the end of the statement, 65/// MaybeFallThrough iff we might or might not fall off the end, 66/// NeverFallThroughOrReturn iff we never fall off the end of the statement or 67/// return. We assume NeverFallThrough iff we never fall off the end of the 68/// statement but we may return. We assume that functions not marked noreturn 69/// will return. 70static ControlFlowKind CheckFallThrough(AnalysisContext &AC) { 71 CFG *cfg = AC.getCFG(); 72 if (cfg == 0) 73 // FIXME: This should be NeverFallThrough 74 return NeverFallThroughOrReturn; 75 76 // The CFG leaves in dead things, and we don't want the dead code paths to 77 // confuse us, so we mark all live things first. 78 std::queue<CFGBlock*> workq; 79 llvm::BitVector live(cfg->getNumBlockIDs()); 80 unsigned count = reachable_code::ScanReachableFromBlock(cfg->getEntry(), 81 live); 82 83 bool AddEHEdges = AC.getAddEHEdges(); 84 if (!AddEHEdges && count != cfg->getNumBlockIDs()) 85 // When there are things remaining dead, and we didn't add EH edges 86 // from CallExprs to the catch clauses, we have to go back and 87 // mark them as live. 88 for (CFG::iterator I = cfg->begin(), E = cfg->end(); I != E; ++I) { 89 CFGBlock &b = **I; 90 if (!live[b.getBlockID()]) { 91 if (b.pred_begin() == b.pred_end()) { 92 if (b.getTerminator() && isa<CXXTryStmt>(b.getTerminator())) 93 // When not adding EH edges from calls, catch clauses 94 // can otherwise seem dead. Avoid noting them as dead. 95 count += reachable_code::ScanReachableFromBlock(b, live); 96 continue; 97 } 98 } 99 } 100 101 // Now we know what is live, we check the live precessors of the exit block 102 // and look for fall through paths, being careful to ignore normal returns, 103 // and exceptional paths. 104 bool HasLiveReturn = false; 105 bool HasFakeEdge = false; 106 bool HasPlainEdge = false; 107 bool HasAbnormalEdge = false; 108 for (CFGBlock::pred_iterator I=cfg->getExit().pred_begin(), 109 E = cfg->getExit().pred_end(); 110 I != E; 111 ++I) { 112 CFGBlock& B = **I; 113 if (!live[B.getBlockID()]) 114 continue; 115 if (B.size() == 0) { 116 if (B.getTerminator() && isa<CXXTryStmt>(B.getTerminator())) { 117 HasAbnormalEdge = true; 118 continue; 119 } 120 121 // A labeled empty statement, or the entry block... 122 HasPlainEdge = true; 123 continue; 124 } 125 Stmt *S = B[B.size()-1]; 126 if (isa<ReturnStmt>(S)) { 127 HasLiveReturn = true; 128 continue; 129 } 130 if (isa<ObjCAtThrowStmt>(S)) { 131 HasFakeEdge = true; 132 continue; 133 } 134 if (isa<CXXThrowExpr>(S)) { 135 HasFakeEdge = true; 136 continue; 137 } 138 if (const AsmStmt *AS = dyn_cast<AsmStmt>(S)) { 139 if (AS->isMSAsm()) { 140 HasFakeEdge = true; 141 HasLiveReturn = true; 142 continue; 143 } 144 } 145 if (isa<CXXTryStmt>(S)) { 146 HasAbnormalEdge = true; 147 continue; 148 } 149 150 bool NoReturnEdge = false; 151 if (CallExpr *C = dyn_cast<CallExpr>(S)) { 152 if (B.succ_begin()[0] != &cfg->getExit()) { 153 HasAbnormalEdge = true; 154 continue; 155 } 156 Expr *CEE = C->getCallee()->IgnoreParenCasts(); 157 if (CEE->getType().getNoReturnAttr()) { 158 NoReturnEdge = true; 159 HasFakeEdge = true; 160 } else if (DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(CEE)) { 161 ValueDecl *VD = DRE->getDecl(); 162 if (VD->hasAttr<NoReturnAttr>()) { 163 NoReturnEdge = true; 164 HasFakeEdge = true; 165 } 166 } 167 } 168 // FIXME: Add noreturn message sends. 169 if (NoReturnEdge == false) 170 HasPlainEdge = true; 171 } 172 if (!HasPlainEdge) { 173 if (HasLiveReturn) 174 return NeverFallThrough; 175 return NeverFallThroughOrReturn; 176 } 177 if (HasAbnormalEdge || HasFakeEdge || HasLiveReturn) 178 return MaybeFallThrough; 179 // This says AlwaysFallThrough for calls to functions that are not marked 180 // noreturn, that don't return. If people would like this warning to be more 181 // accurate, such functions should be marked as noreturn. 182 return AlwaysFallThrough; 183} 184 185struct CheckFallThroughDiagnostics { 186 unsigned diag_MaybeFallThrough_HasNoReturn; 187 unsigned diag_MaybeFallThrough_ReturnsNonVoid; 188 unsigned diag_AlwaysFallThrough_HasNoReturn; 189 unsigned diag_AlwaysFallThrough_ReturnsNonVoid; 190 unsigned diag_NeverFallThroughOrReturn; 191 bool funMode; 192 193 static CheckFallThroughDiagnostics MakeForFunction() { 194 CheckFallThroughDiagnostics D; 195 D.diag_MaybeFallThrough_HasNoReturn = 196 diag::warn_falloff_noreturn_function; 197 D.diag_MaybeFallThrough_ReturnsNonVoid = 198 diag::warn_maybe_falloff_nonvoid_function; 199 D.diag_AlwaysFallThrough_HasNoReturn = 200 diag::warn_falloff_noreturn_function; 201 D.diag_AlwaysFallThrough_ReturnsNonVoid = 202 diag::warn_falloff_nonvoid_function; 203 D.diag_NeverFallThroughOrReturn = 204 diag::warn_suggest_noreturn_function; 205 D.funMode = true; 206 return D; 207 } 208 209 static CheckFallThroughDiagnostics MakeForBlock() { 210 CheckFallThroughDiagnostics D; 211 D.diag_MaybeFallThrough_HasNoReturn = 212 diag::err_noreturn_block_has_return_expr; 213 D.diag_MaybeFallThrough_ReturnsNonVoid = 214 diag::err_maybe_falloff_nonvoid_block; 215 D.diag_AlwaysFallThrough_HasNoReturn = 216 diag::err_noreturn_block_has_return_expr; 217 D.diag_AlwaysFallThrough_ReturnsNonVoid = 218 diag::err_falloff_nonvoid_block; 219 D.diag_NeverFallThroughOrReturn = 220 diag::warn_suggest_noreturn_block; 221 D.funMode = false; 222 return D; 223 } 224 225 bool checkDiagnostics(Diagnostic &D, bool ReturnsVoid, 226 bool HasNoReturn) const { 227 if (funMode) { 228 return (D.getDiagnosticLevel(diag::warn_maybe_falloff_nonvoid_function) 229 == Diagnostic::Ignored || ReturnsVoid) 230 && (D.getDiagnosticLevel(diag::warn_noreturn_function_has_return_expr) 231 == Diagnostic::Ignored || !HasNoReturn) 232 && (D.getDiagnosticLevel(diag::warn_suggest_noreturn_block) 233 == Diagnostic::Ignored || !ReturnsVoid); 234 } 235 236 // For blocks. 237 return ReturnsVoid && !HasNoReturn 238 && (D.getDiagnosticLevel(diag::warn_suggest_noreturn_block) 239 == Diagnostic::Ignored || !ReturnsVoid); 240 } 241}; 242 243/// CheckFallThroughForFunctionDef - Check that we don't fall off the end of a 244/// function that should return a value. Check that we don't fall off the end 245/// of a noreturn function. We assume that functions and blocks not marked 246/// noreturn will return. 247static void CheckFallThroughForBody(Sema &S, const Decl *D, const Stmt *Body, 248 QualType BlockTy, 249 const CheckFallThroughDiagnostics& CD, 250 AnalysisContext &AC) { 251 252 bool ReturnsVoid = false; 253 bool HasNoReturn = false; 254 255 if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(D)) { 256 ReturnsVoid = FD->getResultType()->isVoidType(); 257 HasNoReturn = FD->hasAttr<NoReturnAttr>() || 258 FD->getType()->getAs<FunctionType>()->getNoReturnAttr(); 259 } 260 else if (const ObjCMethodDecl *MD = dyn_cast<ObjCMethodDecl>(D)) { 261 ReturnsVoid = MD->getResultType()->isVoidType(); 262 HasNoReturn = MD->hasAttr<NoReturnAttr>(); 263 } 264 else if (isa<BlockDecl>(D)) { 265 if (const FunctionType *FT = 266 BlockTy->getPointeeType()->getAs<FunctionType>()) { 267 if (FT->getResultType()->isVoidType()) 268 ReturnsVoid = true; 269 if (FT->getNoReturnAttr()) 270 HasNoReturn = true; 271 } 272 } 273 274 Diagnostic &Diags = S.getDiagnostics(); 275 276 // Short circuit for compilation speed. 277 if (CD.checkDiagnostics(Diags, ReturnsVoid, HasNoReturn)) 278 return; 279 280 // FIXME: Function try block 281 if (const CompoundStmt *Compound = dyn_cast<CompoundStmt>(Body)) { 282 switch (CheckFallThrough(AC)) { 283 case MaybeFallThrough: 284 if (HasNoReturn) 285 S.Diag(Compound->getRBracLoc(), 286 CD.diag_MaybeFallThrough_HasNoReturn); 287 else if (!ReturnsVoid) 288 S.Diag(Compound->getRBracLoc(), 289 CD.diag_MaybeFallThrough_ReturnsNonVoid); 290 break; 291 case AlwaysFallThrough: 292 if (HasNoReturn) 293 S.Diag(Compound->getRBracLoc(), 294 CD.diag_AlwaysFallThrough_HasNoReturn); 295 else if (!ReturnsVoid) 296 S.Diag(Compound->getRBracLoc(), 297 CD.diag_AlwaysFallThrough_ReturnsNonVoid); 298 break; 299 case NeverFallThroughOrReturn: 300 if (ReturnsVoid && !HasNoReturn) 301 S.Diag(Compound->getLBracLoc(), 302 CD.diag_NeverFallThroughOrReturn); 303 break; 304 case NeverFallThrough: 305 break; 306 } 307 } 308} 309 310//===----------------------------------------------------------------------===// 311// AnalysisBasedWarnings - Worker object used by Sema to execute analysis-based 312// warnings on a function, method, or block. 313//===----------------------------------------------------------------------===// 314 315clang::sema::AnalysisBasedWarnings::Policy::Policy() { 316 enableCheckFallThrough = 1; 317 enableCheckUnreachable = 0; 318} 319 320clang::sema::AnalysisBasedWarnings::AnalysisBasedWarnings(Sema &s) : S(s) { 321 Diagnostic &D = S.getDiagnostics(); 322 DefaultPolicy.enableCheckUnreachable = (unsigned) 323 (D.getDiagnosticLevel(diag::warn_unreachable) != Diagnostic::Ignored); 324} 325 326void clang::sema:: 327AnalysisBasedWarnings::IssueWarnings(sema::AnalysisBasedWarnings::Policy P, 328 const Decl *D, QualType BlockTy, 329 const bool analyzeStaticInline) { 330 331 assert(BlockTy.isNull() || isa<BlockDecl>(D)); 332 333 // We avoid doing analysis-based warnings when there are errors for 334 // two reasons: 335 // (1) The CFGs often can't be constructed (if the body is invalid), so 336 // don't bother trying. 337 // (2) The code already has problems; running the analysis just takes more 338 // time. 339 if (S.getDiagnostics().hasErrorOccurred()) 340 return; 341 342 // Do not do any analysis for declarations in system headers if we are 343 // going to just ignore them. 344 if (S.getDiagnostics().getSuppressSystemWarnings() && 345 S.SourceMgr.isInSystemHeader(D->getLocation())) 346 return; 347 348 if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(D)) { 349 // For function templates, class templates and member function templates 350 // we'll do the analysis at instantiation time. 351 if (FD->isDependentContext()) 352 return; 353 354 // Only analyze 'static inline' functions when explicitly asked. 355 if (!analyzeStaticInline && FD->isInlineSpecified() && 356 FD->getStorageClass() == FunctionDecl::Static) { 357 FD = FD->getCanonicalDecl(); 358 VisitFlag &visitFlag = VisitedFD[FD]; 359 if (visitFlag == Pending) 360 visitFlag = Visited; 361 else 362 return; 363 } 364 } 365 366 const Stmt *Body = D->getBody(); 367 assert(Body); 368 369 // Don't generate EH edges for CallExprs as we'd like to avoid the n^2 370 // explosion for destrutors that can result and the compile time hit. 371 AnalysisContext AC(D, false); 372 bool performedCheck = false; 373 374 // Warning: check missing 'return' 375 if (P.enableCheckFallThrough) { 376 const CheckFallThroughDiagnostics &CD = 377 (isa<BlockDecl>(D) ? CheckFallThroughDiagnostics::MakeForBlock() 378 : CheckFallThroughDiagnostics::MakeForFunction()); 379 CheckFallThroughForBody(S, D, Body, BlockTy, CD, AC); 380 performedCheck = true; 381 } 382 383 // Warning: check for unreachable code 384 if (P.enableCheckUnreachable) { 385 CheckUnreachable(S, AC); 386 performedCheck = true; 387 } 388 389 // If this block or function calls a 'static inline' function, 390 // we should analyze those functions as well. 391 if (performedCheck) { 392 // The CFG should already be constructed, so this should not 393 // incur any extra cost. We might not have a CFG, however, for 394 // invalid code. 395 if (const CFG *cfg = AC.getCFG()) { 396 // All CallExprs are block-level expressions in the CFG. This means 397 // that walking the basic blocks in the CFG is more efficient 398 // than walking the entire AST to find all calls. 399 for (CFG::const_iterator I=cfg->begin(), E=cfg->end(); I!=E; ++I) { 400 const CFGBlock *B = *I; 401 for (CFGBlock::const_iterator BI=B->begin(), BE=B->end(); BI!=BE; ++BI) 402 if (const CallExpr *CE = dyn_cast<CallExpr>(*BI)) 403 if (const DeclRefExpr *DR = 404 dyn_cast<DeclRefExpr>(CE->getCallee()->IgnoreParenCasts())) 405 if (const FunctionDecl *calleeD = 406 dyn_cast<FunctionDecl>(DR->getDecl())) { 407 calleeD = calleeD->getCanonicalDecl(); 408 if (calleeD->isInlineSpecified() && 409 calleeD->getStorageClass() == FunctionDecl::Static) { 410 // Have we analyzed this static inline function before? 411 VisitFlag &visitFlag = VisitedFD[calleeD]; 412 if (visitFlag == NotVisited) { 413 // Mark the callee visited prior to analyzing it 414 // so we terminate in case of recursion. 415 if (calleeD->getBody()) { 416 visitFlag = Visited; 417 IssueWarnings(DefaultPolicy, calleeD, QualType(), true); 418 } 419 else { 420 // Delay warnings until we encounter the definition. 421 visitFlag = Pending; 422 } 423 } 424 } 425 } 426 } 427 } 428 } 429} 430