| Ted Kremenek | 1ed6d2e | 2007-09-06 23:01:46 +0000 | [diff] [blame] | 1 | //==- DeadStores.cpp - Check for stores to dead variables --------*- C++ -*-==// | 
 | 2 | // | 
 | 3 | //                     The LLVM Compiler Infrastructure | 
 | 4 | // | 
 | 5 | // This file was developed by Ted Kremenek and is distributed under | 
 | 6 | // the University of Illinois Open Source License. See LICENSE.TXT for details. | 
 | 7 | // | 
 | 8 | //===----------------------------------------------------------------------===// | 
 | 9 | // | 
 | 10 | //  This files defines a DeadStores, a flow-sensitive checker that looks for | 
 | 11 | //  stores to variables that are no longer live. | 
 | 12 | // | 
 | 13 | //===----------------------------------------------------------------------===// | 
 | 14 |  | 
 | 15 | #include "clang/AST/Expr.h" | 
 | 16 | #include "clang/Analysis/LocalCheckers.h" | 
 | 17 | #include "clang/Analysis/LiveVariables.h" | 
 | 18 | #include "clang/AST/CFG.h" | 
 | 19 | #include "clang/Basic/Diagnostic.h" | 
| Ted Kremenek | ce1cab9 | 2007-09-11 17:24:14 +0000 | [diff] [blame] | 20 | #include "clang/AST/ASTContext.h" | 
| Ted Kremenek | 1ed6d2e | 2007-09-06 23:01:46 +0000 | [diff] [blame] | 21 |  | 
 | 22 | using namespace clang; | 
 | 23 |  | 
 | 24 | namespace { | 
 | 25 |  | 
| Ted Kremenek | b00c95e | 2007-09-10 15:56:38 +0000 | [diff] [blame] | 26 | class DeadStoreObserver : public LiveVariablesObserver { | 
| Chris Lattner | c0508f9 | 2007-09-15 23:21:08 +0000 | [diff] [blame^] | 27 |   ASTContext &Ctx; | 
 | 28 |   Diagnostic &Diags; | 
| Ted Kremenek | 1ed6d2e | 2007-09-06 23:01:46 +0000 | [diff] [blame] | 29 | public: | 
| Chris Lattner | c0508f9 | 2007-09-15 23:21:08 +0000 | [diff] [blame^] | 30 |   DeadStoreObserver(ASTContext &ctx, Diagnostic &diags) | 
 | 31 |     : Ctx(ctx), Diags(diags) { | 
| Chris Lattner | b800dc2 | 2007-09-13 01:14:03 +0000 | [diff] [blame] | 32 |   } | 
| Ted Kremenek | ce1cab9 | 2007-09-11 17:24:14 +0000 | [diff] [blame] | 33 |      | 
| Ted Kremenek | b00c95e | 2007-09-10 15:56:38 +0000 | [diff] [blame] | 34 |   virtual ~DeadStoreObserver() {} | 
| Ted Kremenek | 1ed6d2e | 2007-09-06 23:01:46 +0000 | [diff] [blame] | 35 |  | 
| Ted Kremenek | b00c95e | 2007-09-10 15:56:38 +0000 | [diff] [blame] | 36 |   virtual void ObserveStmt(Stmt* S, LiveVariables& L, llvm::BitVector& Live) {                                  | 
| Ted Kremenek | 1ed6d2e | 2007-09-06 23:01:46 +0000 | [diff] [blame] | 37 |     if (BinaryOperator* B = dyn_cast<BinaryOperator>(S)) {     | 
 | 38 |       // Is this an assignment? | 
 | 39 |       if (!B->isAssignmentOp()) | 
 | 40 |         return; | 
 | 41 |        | 
 | 42 |       // Is this an assignment to a variable? | 
| Ted Kremenek | c0576ca | 2007-09-10 17:36:42 +0000 | [diff] [blame] | 43 |       if (DeclRefExpr* DR = dyn_cast<DeclRefExpr>(B->getLHS())) | 
| Ted Kremenek | 1ed6d2e | 2007-09-06 23:01:46 +0000 | [diff] [blame] | 44 |         // Is the variable live? | 
| Ted Kremenek | c0576ca | 2007-09-10 17:36:42 +0000 | [diff] [blame] | 45 |         if (!L.isLive(Live,cast<VarDecl>(DR->getDecl()))) { | 
| Ted Kremenek | 1ed6d2e | 2007-09-06 23:01:46 +0000 | [diff] [blame] | 46 |           SourceRange R = B->getRHS()->getSourceRange(); | 
| Chris Lattner | c0508f9 | 2007-09-15 23:21:08 +0000 | [diff] [blame^] | 47 |           Diags.Report(DR->getSourceRange().Begin(), diag::warn_dead_store, | 
 | 48 |                        0, 0, &R, 1); | 
| Ted Kremenek | 1ed6d2e | 2007-09-06 23:01:46 +0000 | [diff] [blame] | 49 |                                                                          | 
 | 50 |         } | 
| Ted Kremenek | 1ed6d2e | 2007-09-06 23:01:46 +0000 | [diff] [blame] | 51 |     } | 
| Ted Kremenek | 83522a3 | 2007-09-06 23:39:53 +0000 | [diff] [blame] | 52 |     else if(DeclStmt* DS = dyn_cast<DeclStmt>(S)) { | 
 | 53 |       // Iterate through the decls.  Warn if any of them (which have | 
 | 54 |       // initializers) are not live. | 
| Ted Kremenek | c0576ca | 2007-09-10 17:36:42 +0000 | [diff] [blame] | 55 |       for (VarDecl* V = cast<VarDecl>(DS->getDecl()); V != NULL ;  | 
| Ted Kremenek | a596533 | 2007-09-11 17:00:40 +0000 | [diff] [blame] | 56 |                     V = cast_or_null<VarDecl>(V->getNextDeclarator())) | 
| Ted Kremenek | c0576ca | 2007-09-10 17:36:42 +0000 | [diff] [blame] | 57 |         if (Expr* E = V->getInit()) | 
| Ted Kremenek | ce1cab9 | 2007-09-11 17:24:14 +0000 | [diff] [blame] | 58 |           if (!L.isLive(Live,V)) | 
 | 59 |             // Special case: check for initializations with constants. | 
 | 60 |             // | 
 | 61 |             //  e.g. : int x = 0; | 
 | 62 |             // | 
 | 63 |             // If x is EVER assigned a new value later, don't issue | 
 | 64 |             // a warning.  This is because such initialization can be | 
 | 65 |             // due to defensive programming. | 
 | 66 |             if (!E->isConstantExpr(Ctx,NULL) ||  | 
 | 67 |                 L.getVarInfo(V).Kills.size() == 0) { | 
 | 68 |               // Flag a warning. | 
 | 69 |               SourceRange R = E->getSourceRange(); | 
| Chris Lattner | c0508f9 | 2007-09-15 23:21:08 +0000 | [diff] [blame^] | 70 |               Diags.Report(V->getLocation(), diag::warn_dead_store, 0, 0, | 
 | 71 |                            &R,1); | 
| Ted Kremenek | ce1cab9 | 2007-09-11 17:24:14 +0000 | [diff] [blame] | 72 |             } | 
| Ted Kremenek | 83522a3 | 2007-09-06 23:39:53 +0000 | [diff] [blame] | 73 |     } | 
| Ted Kremenek | 1ed6d2e | 2007-09-06 23:01:46 +0000 | [diff] [blame] | 74 |   } | 
 | 75 | }; | 
 | 76 |    | 
 | 77 | } // end anonymous namespace | 
 | 78 |  | 
 | 79 | namespace clang { | 
 | 80 |  | 
| Chris Lattner | c0508f9 | 2007-09-15 23:21:08 +0000 | [diff] [blame^] | 81 | void CheckDeadStores(CFG& cfg, LiveVariables& L, | 
 | 82 |                      ASTContext &Ctx, Diagnostic &Diags) { | 
 | 83 |   DeadStoreObserver A(Ctx, Diags); | 
| Ted Kremenek | 1ed6d2e | 2007-09-06 23:01:46 +0000 | [diff] [blame] | 84 |    | 
 | 85 |   for (CFG::iterator I = cfg.begin(), E = cfg.end(); I != E; ++I) | 
 | 86 |     L.runOnBlock(&(*I),&A); | 
 | 87 | } | 
 | 88 |  | 
| Chris Lattner | c0508f9 | 2007-09-15 23:21:08 +0000 | [diff] [blame^] | 89 | void CheckDeadStores(CFG& cfg, ASTContext &Ctx, Diagnostic &Diags) { | 
| Ted Kremenek | 1ed6d2e | 2007-09-06 23:01:46 +0000 | [diff] [blame] | 90 |   LiveVariables L; | 
 | 91 |   L.runOnCFG(cfg); | 
| Chris Lattner | c0508f9 | 2007-09-15 23:21:08 +0000 | [diff] [blame^] | 92 |   CheckDeadStores(cfg,L, Ctx, Diags); | 
| Ted Kremenek | 1ed6d2e | 2007-09-06 23:01:46 +0000 | [diff] [blame] | 93 | } | 
 | 94 |  | 
| Gabor Greif | 8467583 | 2007-09-11 15:32:40 +0000 | [diff] [blame] | 95 | } // end namespace clang |