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