blob: b976d92e96ea0fae132d02b77e3cfe01a3470254 [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
Ted Kremenek1ed6d2e2007-09-06 23:01:46 +000015#include "clang/Analysis/LocalCheckers.h"
16#include "clang/Analysis/LiveVariables.h"
Ted Kremenekfdd225e2007-09-25 04:31:27 +000017#include "clang/Analysis/Visitors/CFGRecStmtVisitor.h"
Ted Kremenek1ed6d2e2007-09-06 23:01:46 +000018#include "clang/Basic/Diagnostic.h"
Ted Kremenekce1cab92007-09-11 17:24:14 +000019#include "clang/AST/ASTContext.h"
Ted Kremenekfdd225e2007-09-25 04:31:27 +000020#include "llvm/ADT/SmallPtrSet.h"
Ted Kremenek1ed6d2e2007-09-06 23:01:46 +000021
22using namespace clang;
23
24namespace {
25
Ted Kremenekfdd225e2007-09-25 04:31:27 +000026class EverKilled : public LiveVariables::ObserverTy {
27 llvm::SmallPtrSet<const VarDecl*, 10> Killed;
28public:
29 virtual void ObserveKill(DeclRefExpr* DR) {
30 Killed.insert(cast<VarDecl>(DR->getDecl()));
31 }
32
33 bool hasKill(const VarDecl* V) { return Killed.count(V) != 0; }
34};
35
36class DeadStoreObs : public LiveVariables::ObserverTy {
Chris Lattnerc0508f92007-09-15 23:21:08 +000037 ASTContext &Ctx;
38 Diagnostic &Diags;
Ted Kremenekfdd225e2007-09-25 04:31:27 +000039 EverKilled EK;
Ted Kremenek1ed6d2e2007-09-06 23:01:46 +000040public:
Ted Kremenekfdd225e2007-09-25 04:31:27 +000041 DeadStoreObs(ASTContext &ctx,Diagnostic &diags) : Ctx(ctx), Diags(diags){}
42 virtual ~DeadStoreObs() {}
43
44 virtual void ObserveStmt(Stmt* S,
45 const LiveVariables::AnalysisDataTy& AD,
46 const LiveVariables::ValTy& Live) {
Ted Kremenekce1cab92007-09-11 17:24:14 +000047
Ted Kremenek1ed6d2e2007-09-06 23:01:46 +000048 if (BinaryOperator* B = dyn_cast<BinaryOperator>(S)) {
Ted Kremenekfdd225e2007-09-25 04:31:27 +000049 if (!B->isAssignmentOp()) return; // Skip non-assignments.
Ted Kremenek1ed6d2e2007-09-06 23:01:46 +000050
Ted Kremenekc0576ca2007-09-10 17:36:42 +000051 if (DeclRefExpr* DR = dyn_cast<DeclRefExpr>(B->getLHS()))
Ted Kremenekfdd225e2007-09-25 04:31:27 +000052 // Is the variable NOT live? If so, flag a dead store.
53 if (!Live(AD,DR->getDecl())) {
Ted Kremenek1ed6d2e2007-09-06 23:01:46 +000054 SourceRange R = B->getRHS()->getSourceRange();
Chris Lattnerc0508f92007-09-15 23:21:08 +000055 Diags.Report(DR->getSourceRange().Begin(), diag::warn_dead_store,
Ted Kremenekfdd225e2007-09-25 04:31:27 +000056 0, 0, &R, 1);
Ted Kremenek1ed6d2e2007-09-06 23:01:46 +000057 }
Ted Kremenek1ed6d2e2007-09-06 23:01:46 +000058 }
Ted Kremenekfdd225e2007-09-25 04:31:27 +000059 else if(DeclStmt* DS = dyn_cast<DeclStmt>(S))
60 // Iterate through the decls. Warn if any initializers are complex
61 // expressions that are not live (never used).
Ted Kremenekc0576ca2007-09-10 17:36:42 +000062 for (VarDecl* V = cast<VarDecl>(DS->getDecl()); V != NULL ;
Ted Kremenekfdd225e2007-09-25 04:31:27 +000063 V = cast_or_null<VarDecl>(V->getNextDeclarator())) {
64 if (Expr* E = V->getInit()) {
65 if (!Live(AD,DS->getDecl())) {
Ted Kremenekce1cab92007-09-11 17:24:14 +000066 // Special case: check for initializations with constants.
67 //
68 // e.g. : int x = 0;
69 //
70 // If x is EVER assigned a new value later, don't issue
71 // a warning. This is because such initialization can be
72 // due to defensive programming.
Ted Kremenekfdd225e2007-09-25 04:31:27 +000073 if (!E->isConstantExpr(Ctx,NULL)) {
Ted Kremenekce1cab92007-09-11 17:24:14 +000074 // Flag a warning.
75 SourceRange R = E->getSourceRange();
Chris Lattnerc0508f92007-09-15 23:21:08 +000076 Diags.Report(V->getLocation(), diag::warn_dead_store, 0, 0,
77 &R,1);
Ted Kremenekce1cab92007-09-11 17:24:14 +000078 }
Ted Kremenekfdd225e2007-09-25 04:31:27 +000079 }
80 }
81 }
Ted Kremenek1ed6d2e2007-09-06 23:01:46 +000082 }
83};
84
85} // end anonymous namespace
86
87namespace clang {
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);
Ted Kremenekfdd225e2007-09-25 04:31:27 +000092 DeadStoreObs A(Ctx, Diags);
93 L.runOnAllBlocks(cfg,A);
Ted Kremenek1ed6d2e2007-09-06 23:01:46 +000094}
95
Gabor Greif84675832007-09-11 15:32:40 +000096} // end namespace clang