blob: 91034e389444e8bb303cb8f5268701ad89242f7d [file] [log] [blame]
Ted Kremenek1ed6d2e2007-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 Kremenekce1cab92007-09-11 17:24:14 +000021#include "clang/AST/ASTContext.h"
Ted Kremenek1ed6d2e2007-09-06 23:01:46 +000022
23using namespace clang;
24
25namespace {
26
Ted Kremenekb00c95e2007-09-10 15:56:38 +000027class DeadStoreObserver : public LiveVariablesObserver {
Ted Kremenek1ed6d2e2007-09-06 23:01:46 +000028 Preprocessor& PP;
Ted Kremenekce1cab92007-09-11 17:24:14 +000029 ASTContext Ctx;
Ted Kremenek1ed6d2e2007-09-06 23:01:46 +000030public:
Ted Kremenekce1cab92007-09-11 17:24:14 +000031 DeadStoreObserver(Preprocessor& pp) :
32 PP(pp), Ctx(PP.getTargetInfo(), PP.getIdentifierTable()) {}
33
Ted Kremenekb00c95e2007-09-10 15:56:38 +000034 virtual ~DeadStoreObserver() {}
Ted Kremenek1ed6d2e2007-09-06 23:01:46 +000035
Ted Kremenekb00c95e2007-09-10 15:56:38 +000036 virtual void ObserveStmt(Stmt* S, LiveVariables& L, llvm::BitVector& Live) {
Ted Kremenek1ed6d2e2007-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 Kremenekc0576ca2007-09-10 17:36:42 +000043 if (DeclRefExpr* DR = dyn_cast<DeclRefExpr>(B->getLHS()))
Ted Kremenek1ed6d2e2007-09-06 23:01:46 +000044 // Is the variable live?
Ted Kremenekc0576ca2007-09-10 17:36:42 +000045 if (!L.isLive(Live,cast<VarDecl>(DR->getDecl()))) {
Ted Kremenek1ed6d2e2007-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 Kremenek1ed6d2e2007-09-06 23:01:46 +000052 }
Ted Kremenek83522a32007-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 Kremenekc0576ca2007-09-10 17:36:42 +000056 for (VarDecl* V = cast<VarDecl>(DS->getDecl()); V != NULL ;
Ted Kremeneka5965332007-09-11 17:00:40 +000057 V = cast_or_null<VarDecl>(V->getNextDeclarator()))
Ted Kremenekc0576ca2007-09-10 17:36:42 +000058 if (Expr* E = V->getInit())
Ted Kremenekce1cab92007-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 Kremenek83522a32007-09-06 23:39:53 +000075 }
Ted Kremenek1ed6d2e2007-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 Kremenekb00c95e2007-09-10 15:56:38 +000084 DeadStoreObserver A(PP);
Ted Kremenek1ed6d2e2007-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 Greif84675832007-09-11 15:32:40 +000096} // end namespace clang