blob: 91034e389444e8bb303cb8f5268701ad89242f7d [file] [log] [blame]
Ted Kremeneke9646a02007-09-06 23:01:46 +00001//==- 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"
20#include "clang/Lex/Preprocessor.h"
Ted Kremenek12789292007-09-11 17:24:14 +000021#include "clang/AST/ASTContext.h"
Ted Kremeneke9646a02007-09-06 23:01:46 +000022
23using namespace clang;
24
25namespace {
26
Ted Kremenekd1d88262007-09-10 15:56:38 +000027class DeadStoreObserver : public LiveVariablesObserver {
Ted Kremeneke9646a02007-09-06 23:01:46 +000028 Preprocessor& PP;
Ted Kremenek12789292007-09-11 17:24:14 +000029 ASTContext Ctx;
Ted Kremeneke9646a02007-09-06 23:01:46 +000030public:
Ted Kremenek12789292007-09-11 17:24:14 +000031 DeadStoreObserver(Preprocessor& pp) :
32 PP(pp), Ctx(PP.getTargetInfo(), PP.getIdentifierTable()) {}
33
Ted Kremenekd1d88262007-09-10 15:56:38 +000034 virtual ~DeadStoreObserver() {}
Ted Kremeneke9646a02007-09-06 23:01:46 +000035
Ted Kremenekd1d88262007-09-10 15:56:38 +000036 virtual void ObserveStmt(Stmt* S, LiveVariables& L, llvm::BitVector& Live) {
Ted Kremeneke9646a02007-09-06 23:01:46 +000037 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 Kremenek6b2b4e32007-09-10 17:36:42 +000043 if (DeclRefExpr* DR = dyn_cast<DeclRefExpr>(B->getLHS()))
Ted Kremeneke9646a02007-09-06 23:01:46 +000044 // Is the variable live?
Ted Kremenek6b2b4e32007-09-10 17:36:42 +000045 if (!L.isLive(Live,cast<VarDecl>(DR->getDecl()))) {
Ted Kremeneke9646a02007-09-06 23:01:46 +000046 SourceRange R = B->getRHS()->getSourceRange();
47 PP.getDiagnostics().Report(DR->getSourceRange().Begin(),
48 diag::warn_dead_store, 0, 0,
49 &R,1);
50
51 }
Ted Kremeneke9646a02007-09-06 23:01:46 +000052 }
Ted Kremenek42276bc2007-09-06 23:39:53 +000053 else if(DeclStmt* DS = dyn_cast<DeclStmt>(S)) {
54 // Iterate through the decls. Warn if any of them (which have
55 // initializers) are not live.
Ted Kremenek6b2b4e32007-09-10 17:36:42 +000056 for (VarDecl* V = cast<VarDecl>(DS->getDecl()); V != NULL ;
Ted Kremenekc0c3d732007-09-11 17:00:40 +000057 V = cast_or_null<VarDecl>(V->getNextDeclarator()))
Ted Kremenek6b2b4e32007-09-10 17:36:42 +000058 if (Expr* E = V->getInit())
Ted Kremenek12789292007-09-11 17:24:14 +000059 if (!L.isLive(Live,V))
60 // Special case: check for initializations with constants.
61 //
62 // e.g. : int x = 0;
63 //
64 // If x is EVER assigned a new value later, don't issue
65 // a warning. This is because such initialization can be
66 // due to defensive programming.
67 if (!E->isConstantExpr(Ctx,NULL) ||
68 L.getVarInfo(V).Kills.size() == 0) {
69 // Flag a warning.
70 SourceRange R = E->getSourceRange();
71 PP.getDiagnostics().Report(V->getLocation(),
72 diag::warn_dead_store, 0, 0,
73 &R,1);
74 }
Ted Kremenek42276bc2007-09-06 23:39:53 +000075 }
Ted Kremeneke9646a02007-09-06 23:01:46 +000076 }
77};
78
79} // end anonymous namespace
80
81namespace clang {
82
83void CheckDeadStores(CFG& cfg, LiveVariables& L, Preprocessor& PP) {
Ted Kremenekd1d88262007-09-10 15:56:38 +000084 DeadStoreObserver A(PP);
Ted Kremeneke9646a02007-09-06 23:01:46 +000085
86 for (CFG::iterator I = cfg.begin(), E = cfg.end(); I != E; ++I)
87 L.runOnBlock(&(*I),&A);
88}
89
90void CheckDeadStores(CFG& cfg, Preprocessor& PP) {
91 LiveVariables L;
92 L.runOnCFG(cfg);
93 CheckDeadStores(cfg,L,PP);
94}
95
Gabor Greif61ce98c2007-09-11 15:32:40 +000096} // end namespace clang