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