]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - lib/Sema/AnalysisBasedWarnings.cpp
Update clang to r103004.
[FreeBSD/FreeBSD.git] / lib / Sema / AnalysisBasedWarnings.cpp
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
29 using namespace clang;
30
31 //===----------------------------------------------------------------------===//
32 // Unreachable code analysis.
33 //===----------------------------------------------------------------------===//
34
35 namespace {
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.
48 static 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
57 enum 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.
69 static 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::BitVector live(cfg->getNumBlockIDs());
78   unsigned count = reachable_code::ScanReachableFromBlock(cfg->getEntry(),
79                                                           live);
80
81   bool AddEHEdges = AC.getAddEHEdges();
82   if (!AddEHEdges && count != cfg->getNumBlockIDs())
83     // When there are things remaining dead, and we didn't add EH edges
84     // from CallExprs to the catch clauses, we have to go back and
85     // mark them as live.
86     for (CFG::iterator I = cfg->begin(), E = cfg->end(); I != E; ++I) {
87       CFGBlock &b = **I;
88       if (!live[b.getBlockID()]) {
89         if (b.pred_begin() == b.pred_end()) {
90           if (b.getTerminator() && isa<CXXTryStmt>(b.getTerminator()))
91             // When not adding EH edges from calls, catch clauses
92             // can otherwise seem dead.  Avoid noting them as dead.
93             count += reachable_code::ScanReachableFromBlock(b, live);
94           continue;
95         }
96       }
97     }
98
99   // Now we know what is live, we check the live precessors of the exit block
100   // and look for fall through paths, being careful to ignore normal returns,
101   // and exceptional paths.
102   bool HasLiveReturn = false;
103   bool HasFakeEdge = false;
104   bool HasPlainEdge = false;
105   bool HasAbnormalEdge = false;
106   for (CFGBlock::pred_iterator I=cfg->getExit().pred_begin(),
107        E = cfg->getExit().pred_end();
108        I != E;
109        ++I) {
110     CFGBlock& B = **I;
111     if (!live[B.getBlockID()])
112       continue;
113     if (B.size() == 0) {
114       if (B.getTerminator() && isa<CXXTryStmt>(B.getTerminator())) {
115         HasAbnormalEdge = true;
116         continue;
117       }
118
119       // A labeled empty statement, or the entry block...
120       HasPlainEdge = true;
121       continue;
122     }
123     Stmt *S = B[B.size()-1];
124     if (isa<ReturnStmt>(S)) {
125       HasLiveReturn = true;
126       continue;
127     }
128     if (isa<ObjCAtThrowStmt>(S)) {
129       HasFakeEdge = true;
130       continue;
131     }
132     if (isa<CXXThrowExpr>(S)) {
133       HasFakeEdge = true;
134       continue;
135     }
136     if (const AsmStmt *AS = dyn_cast<AsmStmt>(S)) {
137       if (AS->isMSAsm()) {
138         HasFakeEdge = true;
139         HasLiveReturn = true;
140         continue;
141       }
142     }
143     if (isa<CXXTryStmt>(S)) {
144       HasAbnormalEdge = true;
145       continue;
146     }
147
148     bool NoReturnEdge = false;
149     if (CallExpr *C = dyn_cast<CallExpr>(S)) {
150       if (std::find(B.succ_begin(), B.succ_end(), &cfg->getExit())
151             == B.succ_end()) {
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
184 struct 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(const Decl *Func) {
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
203     // Don't suggest that virtual functions be marked "noreturn", since they
204     // might be overridden by non-noreturn functions.
205     bool isVirtualMethod = false;
206     if (const CXXMethodDecl *Method = dyn_cast<CXXMethodDecl>(Func))
207       isVirtualMethod = Method->isVirtual();
208     
209     if (!isVirtualMethod)
210       D.diag_NeverFallThroughOrReturn =
211         diag::warn_suggest_noreturn_function;
212     else
213       D.diag_NeverFallThroughOrReturn = 0;
214     
215     D.funMode = true;
216     return D;
217   }
218
219   static CheckFallThroughDiagnostics MakeForBlock() {
220     CheckFallThroughDiagnostics D;
221     D.diag_MaybeFallThrough_HasNoReturn =
222       diag::err_noreturn_block_has_return_expr;
223     D.diag_MaybeFallThrough_ReturnsNonVoid =
224       diag::err_maybe_falloff_nonvoid_block;
225     D.diag_AlwaysFallThrough_HasNoReturn =
226       diag::err_noreturn_block_has_return_expr;
227     D.diag_AlwaysFallThrough_ReturnsNonVoid =
228       diag::err_falloff_nonvoid_block;
229     D.diag_NeverFallThroughOrReturn =
230       diag::warn_suggest_noreturn_block;
231     D.funMode = false;
232     return D;
233   }
234
235   bool checkDiagnostics(Diagnostic &D, bool ReturnsVoid,
236                         bool HasNoReturn) const {
237     if (funMode) {
238       return (D.getDiagnosticLevel(diag::warn_maybe_falloff_nonvoid_function)
239               == Diagnostic::Ignored || ReturnsVoid)
240         && (D.getDiagnosticLevel(diag::warn_noreturn_function_has_return_expr)
241               == Diagnostic::Ignored || !HasNoReturn)
242         && (D.getDiagnosticLevel(diag::warn_suggest_noreturn_block)
243               == Diagnostic::Ignored || !ReturnsVoid);
244     }
245
246     // For blocks.
247     return  ReturnsVoid && !HasNoReturn
248             && (D.getDiagnosticLevel(diag::warn_suggest_noreturn_block)
249                 == Diagnostic::Ignored || !ReturnsVoid);
250   }
251 };
252
253 /// CheckFallThroughForFunctionDef - Check that we don't fall off the end of a
254 /// function that should return a value.  Check that we don't fall off the end
255 /// of a noreturn function.  We assume that functions and blocks not marked
256 /// noreturn will return.
257 static void CheckFallThroughForBody(Sema &S, const Decl *D, const Stmt *Body,
258                                     QualType BlockTy,
259                                     const CheckFallThroughDiagnostics& CD,
260                                     AnalysisContext &AC) {
261
262   bool ReturnsVoid = false;
263   bool HasNoReturn = false;
264
265   if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(D)) {
266     ReturnsVoid = FD->getResultType()->isVoidType();
267     HasNoReturn = FD->hasAttr<NoReturnAttr>() ||
268        FD->getType()->getAs<FunctionType>()->getNoReturnAttr();
269   }
270   else if (const ObjCMethodDecl *MD = dyn_cast<ObjCMethodDecl>(D)) {
271     ReturnsVoid = MD->getResultType()->isVoidType();
272     HasNoReturn = MD->hasAttr<NoReturnAttr>();
273   }
274   else if (isa<BlockDecl>(D)) {
275     if (const FunctionType *FT =
276           BlockTy->getPointeeType()->getAs<FunctionType>()) {
277       if (FT->getResultType()->isVoidType())
278         ReturnsVoid = true;
279       if (FT->getNoReturnAttr())
280         HasNoReturn = true;
281     }
282   }
283
284   Diagnostic &Diags = S.getDiagnostics();
285
286   // Short circuit for compilation speed.
287   if (CD.checkDiagnostics(Diags, ReturnsVoid, HasNoReturn))
288       return;
289
290   // FIXME: Function try block
291   if (const CompoundStmt *Compound = dyn_cast<CompoundStmt>(Body)) {
292     switch (CheckFallThrough(AC)) {
293       case MaybeFallThrough:
294         if (HasNoReturn)
295           S.Diag(Compound->getRBracLoc(),
296                  CD.diag_MaybeFallThrough_HasNoReturn);
297         else if (!ReturnsVoid)
298           S.Diag(Compound->getRBracLoc(),
299                  CD.diag_MaybeFallThrough_ReturnsNonVoid);
300         break;
301       case AlwaysFallThrough:
302         if (HasNoReturn)
303           S.Diag(Compound->getRBracLoc(),
304                  CD.diag_AlwaysFallThrough_HasNoReturn);
305         else if (!ReturnsVoid)
306           S.Diag(Compound->getRBracLoc(),
307                  CD.diag_AlwaysFallThrough_ReturnsNonVoid);
308         break;
309       case NeverFallThroughOrReturn:
310         if (ReturnsVoid && !HasNoReturn && CD.diag_NeverFallThroughOrReturn)
311           S.Diag(Compound->getLBracLoc(),
312                  CD.diag_NeverFallThroughOrReturn);
313         break;
314       case NeverFallThrough:
315         break;
316     }
317   }
318 }
319
320 //===----------------------------------------------------------------------===//
321 // AnalysisBasedWarnings - Worker object used by Sema to execute analysis-based
322 //  warnings on a function, method, or block.
323 //===----------------------------------------------------------------------===//
324
325 clang::sema::AnalysisBasedWarnings::Policy::Policy() {
326   enableCheckFallThrough = 1;
327   enableCheckUnreachable = 0;
328 }
329
330 clang::sema::AnalysisBasedWarnings::AnalysisBasedWarnings(Sema &s) : S(s) {
331   Diagnostic &D = S.getDiagnostics();
332   DefaultPolicy.enableCheckUnreachable = (unsigned)
333     (D.getDiagnosticLevel(diag::warn_unreachable) != Diagnostic::Ignored);
334 }
335
336 void clang::sema::
337 AnalysisBasedWarnings::IssueWarnings(sema::AnalysisBasedWarnings::Policy P,
338                                      const Decl *D, QualType BlockTy) {
339
340   assert(BlockTy.isNull() || isa<BlockDecl>(D));
341
342   // We avoid doing analysis-based warnings when there are errors for
343   // two reasons:
344   // (1) The CFGs often can't be constructed (if the body is invalid), so
345   //     don't bother trying.
346   // (2) The code already has problems; running the analysis just takes more
347   //     time.
348   Diagnostic &Diags = S.getDiagnostics();
349
350   if (Diags.hasErrorOccurred() || Diags.hasFatalErrorOccurred())
351     return;
352
353   // Do not do any analysis for declarations in system headers if we are
354   // going to just ignore them.
355   if (Diags.getSuppressSystemWarnings() &&
356       S.SourceMgr.isInSystemHeader(D->getLocation()))
357     return;
358
359   if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(D)) {
360     // For function templates, class templates and member function templates
361     // we'll do the analysis at instantiation time.
362     if (FD->isDependentContext())
363       return;
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
373   // Warning: check missing 'return'
374   if (P.enableCheckFallThrough) {
375     const CheckFallThroughDiagnostics &CD =
376       (isa<BlockDecl>(D) ? CheckFallThroughDiagnostics::MakeForBlock()
377                          : CheckFallThroughDiagnostics::MakeForFunction(D));
378     CheckFallThroughForBody(S, D, Body, BlockTy, CD, AC);
379   }
380
381   // Warning: check for unreachable code
382   if (P.enableCheckUnreachable)
383     CheckUnreachable(S, AC);
384 }