blob: 8e2e3628e076f4a263130c86ad04bc6bb2451341 [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"
Ted Kremenekce1cab92007-09-11 17:24:14 +000020#include "clang/AST/ASTContext.h"
Ted Kremenek1ed6d2e2007-09-06 23:01:46 +000021
22using namespace clang;
23
24namespace {
25
Ted Kremenekb00c95e2007-09-10 15:56:38 +000026class DeadStoreObserver : public LiveVariablesObserver {
Chris Lattnerc0508f92007-09-15 23:21:08 +000027 ASTContext &Ctx;
28 Diagnostic &Diags;
Ted Kremenek1ed6d2e2007-09-06 23:01:46 +000029public:
Chris Lattnerc0508f92007-09-15 23:21:08 +000030 DeadStoreObserver(ASTContext &ctx, Diagnostic &diags)
31 : Ctx(ctx), Diags(diags) {
Chris Lattnerb800dc22007-09-13 01:14:03 +000032 }
Ted Kremenekce1cab92007-09-11 17:24:14 +000033
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();
Chris Lattnerc0508f92007-09-15 23:21:08 +000047 Diags.Report(DR->getSourceRange().Begin(), diag::warn_dead_store,
48 0, 0, &R, 1);
Ted Kremenek1ed6d2e2007-09-06 23:01:46 +000049
50 }
Ted Kremenek1ed6d2e2007-09-06 23:01:46 +000051 }
Ted Kremenek83522a32007-09-06 23:39:53 +000052 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 Kremenekc0576ca2007-09-10 17:36:42 +000055 for (VarDecl* V = cast<VarDecl>(DS->getDecl()); V != NULL ;
Ted Kremeneka5965332007-09-11 17:00:40 +000056 V = cast_or_null<VarDecl>(V->getNextDeclarator()))
Ted Kremenekc0576ca2007-09-10 17:36:42 +000057 if (Expr* E = V->getInit())
Ted Kremenekce1cab92007-09-11 17:24:14 +000058 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 Lattnerc0508f92007-09-15 23:21:08 +000070 Diags.Report(V->getLocation(), diag::warn_dead_store, 0, 0,
71 &R,1);
Ted Kremenekce1cab92007-09-11 17:24:14 +000072 }
Ted Kremenek83522a32007-09-06 23:39:53 +000073 }
Ted Kremenek1ed6d2e2007-09-06 23:01:46 +000074 }
75};
76
77} // end anonymous namespace
78
79namespace clang {
80
Chris Lattnerc0508f92007-09-15 23:21:08 +000081void CheckDeadStores(CFG& cfg, LiveVariables& L,
82 ASTContext &Ctx, Diagnostic &Diags) {
83 DeadStoreObserver A(Ctx, Diags);
Ted Kremenek1ed6d2e2007-09-06 23:01:46 +000084
85 for (CFG::iterator I = cfg.begin(), E = cfg.end(); I != E; ++I)
86 L.runOnBlock(&(*I),&A);
87}
88
Chris Lattnerc0508f92007-09-15 23:21:08 +000089void CheckDeadStores(CFG& cfg, ASTContext &Ctx, Diagnostic &Diags) {
Ted Kremenek1ed6d2e2007-09-06 23:01:46 +000090 LiveVariables L;
91 L.runOnCFG(cfg);
Chris Lattnerc0508f92007-09-15 23:21:08 +000092 CheckDeadStores(cfg,L, Ctx, Diags);
Ted Kremenek1ed6d2e2007-09-06 23:01:46 +000093}
94
Gabor Greif84675832007-09-11 15:32:40 +000095} // end namespace clang