DeadStoresChecker.cpp revision ebd42f40803396d63bc59b77285d088cca61f53f
11ed6d2e4fda310af2de2ec09cdfedfa280cce948Ted Kremenek//==- DeadStores.cpp - Check for stores to dead variables --------*- C++ -*-==//
21ed6d2e4fda310af2de2ec09cdfedfa280cce948Ted Kremenek//
31ed6d2e4fda310af2de2ec09cdfedfa280cce948Ted Kremenek//                     The LLVM Compiler Infrastructure
41ed6d2e4fda310af2de2ec09cdfedfa280cce948Ted Kremenek//
50bc735ffcfb223c0186419547abaa5c84482663eChris Lattner// This file is distributed under the University of Illinois Open Source
60bc735ffcfb223c0186419547abaa5c84482663eChris Lattner// License. See LICENSE.TXT for details.
71ed6d2e4fda310af2de2ec09cdfedfa280cce948Ted Kremenek//
81ed6d2e4fda310af2de2ec09cdfedfa280cce948Ted Kremenek//===----------------------------------------------------------------------===//
91ed6d2e4fda310af2de2ec09cdfedfa280cce948Ted Kremenek//
10843e934ba8c6ebc00d2f6969a50af7074597e8e3Gabor Greif//  This file defines a DeadStores, a flow-sensitive checker that looks for
111ed6d2e4fda310af2de2ec09cdfedfa280cce948Ted Kremenek//  stores to variables that are no longer live.
121ed6d2e4fda310af2de2ec09cdfedfa280cce948Ted Kremenek//
131ed6d2e4fda310af2de2ec09cdfedfa280cce948Ted Kremenek//===----------------------------------------------------------------------===//
141ed6d2e4fda310af2de2ec09cdfedfa280cce948Ted Kremenek
1597053091c0e4df12ffb662b284b6ab329ca1c40fTed Kremenek#include "clang/Checker/Checkers/LocalCheckers.h"
16cf6e41baf2b23b6b56f0f79fff5554b7745737acTed Kremenek#include "clang/Analysis/Analyses/LiveVariables.h"
17fdd225ed6f362a8550e597eb875d9c402b8a309cTed Kremenek#include "clang/Analysis/Visitors/CFGRecStmtVisitor.h"
186b67630d5df195f4fe0e4273061c016901d69681Ted Kremenek#include "clang/Checker/BugReporter/BugReporter.h"
191309f9a3b225ea846e5822691c39a77423125505Ted Kremenek#include "clang/Checker/PathSensitive/GRExprEngine.h"
20f96f16d9f529ec95c20b9a91405653554e9646d1Ted Kremenek#include "clang/Analysis/Visitors/CFGRecStmtDeclVisitor.h"
211ed6d2e4fda310af2de2ec09cdfedfa280cce948Ted Kremenek#include "clang/Basic/Diagnostic.h"
22ce1cab9fc0b4aec9cdef1b30a14e4ccdca3ac5f1Ted Kremenek#include "clang/AST/ASTContext.h"
231a654b60ef40e84f3943cdb581795c4d4dae1e45Ted Kremenek#include "clang/AST/ParentMap.h"
24f96f16d9f529ec95c20b9a91405653554e9646d1Ted Kremenek#include "llvm/ADT/SmallPtrSet.h"
251ed6d2e4fda310af2de2ec09cdfedfa280cce948Ted Kremenek
261ed6d2e4fda310af2de2ec09cdfedfa280cce948Ted Kremenekusing namespace clang;
271ed6d2e4fda310af2de2ec09cdfedfa280cce948Ted Kremenek
281ed6d2e4fda310af2de2ec09cdfedfa280cce948Ted Kremeneknamespace {
291a654b60ef40e84f3943cdb581795c4d4dae1e45Ted Kremenek
30ba5fb5a955c896815c439289fc51c03cf0635129Kovarththanan Rajaratnamclass DeadStoreObs : public LiveVariables::ObserverTy {
31c0508f9fe37a3afb1ccad39879348272545e55dbChris Lattner  ASTContext &Ctx;
328f2698621f5090db1dea691059bd0ebd79fb7f14Ted Kremenek  BugReporter& BR;
331a654b60ef40e84f3943cdb581795c4d4dae1e45Ted Kremenek  ParentMap& Parents;
34f96f16d9f529ec95c20b9a91405653554e9646d1Ted Kremenek  llvm::SmallPtrSet<VarDecl*, 20> Escaped;
351eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
362cfac226b028e5a2165af077268f70cd2ab4b1a8Ted Kremenek  enum DeadStoreKind { Standard, Enclosing, DeadIncrement, DeadInit };
371eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
381ed6d2e4fda310af2de2ec09cdfedfa280cce948Ted Kremenekpublic:
39f96f16d9f529ec95c20b9a91405653554e9646d1Ted Kremenek  DeadStoreObs(ASTContext &ctx, BugReporter& br, ParentMap& parents,
40f96f16d9f529ec95c20b9a91405653554e9646d1Ted Kremenek               llvm::SmallPtrSet<VarDecl*, 20> &escaped)
41f96f16d9f529ec95c20b9a91405653554e9646d1Ted Kremenek    : Ctx(ctx), BR(br), Parents(parents), Escaped(escaped) {}
421eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
43fdd225ed6f362a8550e597eb875d9c402b8a309cTed Kremenek  virtual ~DeadStoreObs() {}
44b930d7adb7cb7642c9c49b39df04ebd5cbfa713aTed Kremenek
452cfac226b028e5a2165af077268f70cd2ab4b1a8Ted Kremenek  void Report(VarDecl* V, DeadStoreKind dsk, SourceLocation L, SourceRange R) {
46f96f16d9f529ec95c20b9a91405653554e9646d1Ted Kremenek    if (Escaped.count(V))
47f96f16d9f529ec95c20b9a91405653554e9646d1Ted Kremenek      return;
488f2698621f5090db1dea691059bd0ebd79fb7f14Ted Kremenek
49d9d22dd9c94618490dbffb0e2caf222530ca39d3Chris Lattner    std::string name = V->getNameAsString();
501eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
512cfac226b028e5a2165af077268f70cd2ab4b1a8Ted Kremenek    const char* BugType = 0;
522cfac226b028e5a2165af077268f70cd2ab4b1a8Ted Kremenek    std::string msg;
531eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
542cfac226b028e5a2165af077268f70cd2ab4b1a8Ted Kremenek    switch (dsk) {
552cfac226b028e5a2165af077268f70cd2ab4b1a8Ted Kremenek      default:
562cfac226b028e5a2165af077268f70cd2ab4b1a8Ted Kremenek        assert(false && "Impossible dead store type.");
571eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
582cfac226b028e5a2165af077268f70cd2ab4b1a8Ted Kremenek      case DeadInit:
59efc620c4eb14d2ff59e3ec0714602997ffeddfd7Ted Kremenek        BugType = "Dead initialization";
602cfac226b028e5a2165af077268f70cd2ab4b1a8Ted Kremenek        msg = "Value stored to '" + name +
612cfac226b028e5a2165af077268f70cd2ab4b1a8Ted Kremenek          "' during its initialization is never read";
622cfac226b028e5a2165af077268f70cd2ab4b1a8Ted Kremenek        break;
631eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
642cfac226b028e5a2165af077268f70cd2ab4b1a8Ted Kremenek      case DeadIncrement:
65efc620c4eb14d2ff59e3ec0714602997ffeddfd7Ted Kremenek        BugType = "Dead increment";
662cfac226b028e5a2165af077268f70cd2ab4b1a8Ted Kremenek      case Standard:
67efc620c4eb14d2ff59e3ec0714602997ffeddfd7Ted Kremenek        if (!BugType) BugType = "Dead assignment";
682cfac226b028e5a2165af077268f70cd2ab4b1a8Ted Kremenek        msg = "Value stored to '" + name + "' is never read";
692cfac226b028e5a2165af077268f70cd2ab4b1a8Ted Kremenek        break;
701eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
712cfac226b028e5a2165af077268f70cd2ab4b1a8Ted Kremenek      case Enclosing:
72efc620c4eb14d2ff59e3ec0714602997ffeddfd7Ted Kremenek        BugType = "Dead nested assignment";
732cfac226b028e5a2165af077268f70cd2ab4b1a8Ted Kremenek        msg = "Although the value stored to '" + name +
742cfac226b028e5a2165af077268f70cd2ab4b1a8Ted Kremenek          "' is used in the enclosing expression, the value is never actually"
752cfac226b028e5a2165af077268f70cd2ab4b1a8Ted Kremenek          " read from '" + name + "'";
762cfac226b028e5a2165af077268f70cd2ab4b1a8Ted Kremenek        break;
77f9c2a5d1b49b60962b613a1dfffa23831ca298a2Ted Kremenek    }
781eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
79f0171732efb4647772ad2a45c0f31978b0e34f71Benjamin Kramer    BR.EmitBasicReport(BugType, "Dead store", msg, L, R);
801a654b60ef40e84f3943cdb581795c4d4dae1e45Ted Kremenek  }
811eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
821a654b60ef40e84f3943cdb581795c4d4dae1e45Ted Kremenek  void CheckVarDecl(VarDecl* VD, Expr* Ex, Expr* Val,
832cfac226b028e5a2165af077268f70cd2ab4b1a8Ted Kremenek                    DeadStoreKind dsk,
841a654b60ef40e84f3943cdb581795c4d4dae1e45Ted Kremenek                    const LiveVariables::AnalysisDataTy& AD,
851a654b60ef40e84f3943cdb581795c4d4dae1e45Ted Kremenek                    const LiveVariables::ValTy& Live) {
861a654b60ef40e84f3943cdb581795c4d4dae1e45Ted Kremenek
87852274d4257134906995cb252fb3dfd2d71deae8Ted Kremenek    if (!VD->hasLocalStorage())
88852274d4257134906995cb252fb3dfd2d71deae8Ted Kremenek      return;
89852274d4257134906995cb252fb3dfd2d71deae8Ted Kremenek    // Reference types confuse the dead stores checker.  Skip them
90852274d4257134906995cb252fb3dfd2d71deae8Ted Kremenek    // for now.
91852274d4257134906995cb252fb3dfd2d71deae8Ted Kremenek    if (VD->getType()->getAs<ReferenceType>())
92852274d4257134906995cb252fb3dfd2d71deae8Ted Kremenek      return;
93852274d4257134906995cb252fb3dfd2d71deae8Ted Kremenek
94852274d4257134906995cb252fb3dfd2d71deae8Ted Kremenek    if (!Live(VD, AD) &&
9574635d8cd3c367890735dc4af2c2825a7e4b434cTed Kremenek        !(VD->getAttr<UnusedAttr>() || VD->getAttr<BlocksAttr>()))
962cfac226b028e5a2165af077268f70cd2ab4b1a8Ted Kremenek      Report(VD, dsk, Ex->getSourceRange().getBegin(),
971eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump             Val->getSourceRange());
983eb817e5095d25e7bf4a8df9ed3f9b13bed6f298Ted Kremenek  }
991eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
1002cfac226b028e5a2165af077268f70cd2ab4b1a8Ted Kremenek  void CheckDeclRef(DeclRefExpr* DR, Expr* Val, DeadStoreKind dsk,
101a23157e6b9e2388edebd3d383dd7acfab6a4c0c0Ted Kremenek                    const LiveVariables::AnalysisDataTy& AD,
102a23157e6b9e2388edebd3d383dd7acfab6a4c0c0Ted Kremenek                    const LiveVariables::ValTy& Live) {
103a23157e6b9e2388edebd3d383dd7acfab6a4c0c0Ted Kremenek    if (VarDecl* VD = dyn_cast<VarDecl>(DR->getDecl()))
1042cfac226b028e5a2165af077268f70cd2ab4b1a8Ted Kremenek      CheckVarDecl(VD, DR, Val, dsk, AD, Live);
1052cfac226b028e5a2165af077268f70cd2ab4b1a8Ted Kremenek  }
1061eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
1072cfac226b028e5a2165af077268f70cd2ab4b1a8Ted Kremenek  bool isIncrement(VarDecl* VD, BinaryOperator* B) {
1082cfac226b028e5a2165af077268f70cd2ab4b1a8Ted Kremenek    if (B->isCompoundAssignmentOp())
1092cfac226b028e5a2165af077268f70cd2ab4b1a8Ted Kremenek      return true;
1101eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
1112cfac226b028e5a2165af077268f70cd2ab4b1a8Ted Kremenek    Expr* RHS = B->getRHS()->IgnoreParenCasts();
1122cfac226b028e5a2165af077268f70cd2ab4b1a8Ted Kremenek    BinaryOperator* BRHS = dyn_cast<BinaryOperator>(RHS);
1131eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
1142cfac226b028e5a2165af077268f70cd2ab4b1a8Ted Kremenek    if (!BRHS)
1152cfac226b028e5a2165af077268f70cd2ab4b1a8Ted Kremenek      return false;
1161eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
1172cfac226b028e5a2165af077268f70cd2ab4b1a8Ted Kremenek    DeclRefExpr *DR;
1181eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
1192cfac226b028e5a2165af077268f70cd2ab4b1a8Ted Kremenek    if ((DR = dyn_cast<DeclRefExpr>(BRHS->getLHS()->IgnoreParenCasts())))
1202cfac226b028e5a2165af077268f70cd2ab4b1a8Ted Kremenek      if (DR->getDecl() == VD)
1212cfac226b028e5a2165af077268f70cd2ab4b1a8Ted Kremenek        return true;
1221eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
1232cfac226b028e5a2165af077268f70cd2ab4b1a8Ted Kremenek    if ((DR = dyn_cast<DeclRefExpr>(BRHS->getRHS()->IgnoreParenCasts())))
1242cfac226b028e5a2165af077268f70cd2ab4b1a8Ted Kremenek      if (DR->getDecl() == VD)
1252cfac226b028e5a2165af077268f70cd2ab4b1a8Ted Kremenek        return true;
1261eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
1272cfac226b028e5a2165af077268f70cd2ab4b1a8Ted Kremenek    return false;
128a23157e6b9e2388edebd3d383dd7acfab6a4c0c0Ted Kremenek  }
1291eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
130fdd225ed6f362a8550e597eb875d9c402b8a309cTed Kremenek  virtual void ObserveStmt(Stmt* S,
131fdd225ed6f362a8550e597eb875d9c402b8a309cTed Kremenek                           const LiveVariables::AnalysisDataTy& AD,
132fdd225ed6f362a8550e597eb875d9c402b8a309cTed Kremenek                           const LiveVariables::ValTy& Live) {
1331eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
1341c86b156ff5b6e42319add892c0b18eb12f6b32bTed Kremenek    // Skip statements in macros.
1351c86b156ff5b6e42319add892c0b18eb12f6b32bTed Kremenek    if (S->getLocStart().isMacroID())
1361c86b156ff5b6e42319add892c0b18eb12f6b32bTed Kremenek      return;
1371eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
1381eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump    if (BinaryOperator* B = dyn_cast<BinaryOperator>(S)) {
139fdd225ed6f362a8550e597eb875d9c402b8a309cTed Kremenek      if (!B->isAssignmentOp()) return; // Skip non-assignments.
1401eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
141c0576ca6c6ba136e583985041bd324b0acc38f40Ted Kremenek      if (DeclRefExpr* DR = dyn_cast<DeclRefExpr>(B->getLHS()))
1421a654b60ef40e84f3943cdb581795c4d4dae1e45Ted Kremenek        if (VarDecl *VD = dyn_cast<VarDecl>(DR->getDecl())) {
143e12691c2a2109016df12b2cbf54d51a921e6b618Ted Kremenek          // Special case: check for assigning null to a pointer.
1441eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump          //  This is a common form of defensive programming.
145891322002b5f5886d812f6e8df12174fb2d8e73bTed Kremenek          QualType T = VD->getType();
146891322002b5f5886d812f6e8df12174fb2d8e73bTed Kremenek          if (T->isPointerType() || T->isObjCObjectPointerType()) {
14793fab7c94008d9e2b1e4ce15784544c6710945feTed Kremenek            if (B->getRHS()->isNullPointerConstant(Ctx,
14893fab7c94008d9e2b1e4ce15784544c6710945feTed Kremenek                                              Expr::NPC_ValueDependentIsNull))
14993fab7c94008d9e2b1e4ce15784544c6710945feTed Kremenek              return;
150e12691c2a2109016df12b2cbf54d51a921e6b618Ted Kremenek          }
15193fab7c94008d9e2b1e4ce15784544c6710945feTed Kremenek
15293fab7c94008d9e2b1e4ce15784544c6710945feTed Kremenek          Expr* RHS = B->getRHS()->IgnoreParenCasts();
1533b58786f85aaa173e122f6eaff0b6efa233d59a2Ted Kremenek          // Special case: self-assignments.  These are often used to shut up
1543b58786f85aaa173e122f6eaff0b6efa233d59a2Ted Kremenek          //  "unused variable" compiler warnings.
1553b58786f85aaa173e122f6eaff0b6efa233d59a2Ted Kremenek          if (DeclRefExpr* RhsDR = dyn_cast<DeclRefExpr>(RHS))
1563b58786f85aaa173e122f6eaff0b6efa233d59a2Ted Kremenek            if (VD == dyn_cast<VarDecl>(RhsDR->getDecl()))
1573b58786f85aaa173e122f6eaff0b6efa233d59a2Ted Kremenek              return;
1581eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
1593b58786f85aaa173e122f6eaff0b6efa233d59a2Ted Kremenek          // Otherwise, issue a warning.
160b930d7adb7cb7642c9c49b39df04ebd5cbfa713aTed Kremenek          DeadStoreKind dsk = Parents.isConsumedExpr(B)
1611eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump                              ? Enclosing
1627f5fce7200fdbf03f7d70134a57271e584fcb766Ted Kremenek                              : (isIncrement(VD,B) ? DeadIncrement : Standard);
1631eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
164e12691c2a2109016df12b2cbf54d51a921e6b618Ted Kremenek          CheckVarDecl(VD, DR, B->getRHS(), dsk, AD, Live);
1651eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump        }
1661ed6d2e4fda310af2de2ec09cdfedfa280cce948Ted Kremenek    }
167a23157e6b9e2388edebd3d383dd7acfab6a4c0c0Ted Kremenek    else if (UnaryOperator* U = dyn_cast<UnaryOperator>(S)) {
168a23157e6b9e2388edebd3d383dd7acfab6a4c0c0Ted Kremenek      if (!U->isIncrementOp())
169a23157e6b9e2388edebd3d383dd7acfab6a4c0c0Ted Kremenek        return;
1701eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
171380277e46ec1d2d9abedcddf357ceea935cbe576Ted Kremenek      // Handle: ++x within a subexpression.  The solution is not warn
172380277e46ec1d2d9abedcddf357ceea935cbe576Ted Kremenek      //  about preincrements to dead variables when the preincrement occurs
173380277e46ec1d2d9abedcddf357ceea935cbe576Ted Kremenek      //  as a subexpression.  This can lead to false negatives, e.g. "(++x);"
174380277e46ec1d2d9abedcddf357ceea935cbe576Ted Kremenek      //  A generalized dead code checker should find such issues.
175b930d7adb7cb7642c9c49b39df04ebd5cbfa713aTed Kremenek      if (U->isPrefix() && Parents.isConsumedExpr(U))
176380277e46ec1d2d9abedcddf357ceea935cbe576Ted Kremenek        return;
177b0f36323d9d8392075274b95816e2241f99ddb0dTed Kremenek
178a23157e6b9e2388edebd3d383dd7acfab6a4c0c0Ted Kremenek      Expr *Ex = U->getSubExpr()->IgnoreParenCasts();
1791eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
180a23157e6b9e2388edebd3d383dd7acfab6a4c0c0Ted Kremenek      if (DeclRefExpr* DR = dyn_cast<DeclRefExpr>(Ex))
1812cfac226b028e5a2165af077268f70cd2ab4b1a8Ted Kremenek        CheckDeclRef(DR, U, DeadIncrement, AD, Live);
1821eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump    }
183a23157e6b9e2388edebd3d383dd7acfab6a4c0c0Ted Kremenek    else if (DeclStmt* DS = dyn_cast<DeclStmt>(S))
184fdd225ed6f362a8550e597eb875d9c402b8a309cTed Kremenek      // Iterate through the decls.  Warn if any initializers are complex
185fdd225ed6f362a8550e597eb875d9c402b8a309cTed Kremenek      // expressions that are not live (never used).
18614f8b4ff660bcaa763974b8d0fae81857c594495Ted Kremenek      for (DeclStmt::decl_iterator DI=DS->decl_begin(), DE=DS->decl_end();
18714f8b4ff660bcaa763974b8d0fae81857c594495Ted Kremenek           DI != DE; ++DI) {
1881eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
18914f8b4ff660bcaa763974b8d0fae81857c594495Ted Kremenek        VarDecl* V = dyn_cast<VarDecl>(*DI);
190fc7ff5540412f8003024e1b4940fb8408dff2ca6Ted Kremenek
191fc7ff5540412f8003024e1b4940fb8408dff2ca6Ted Kremenek        if (!V)
192fc7ff5540412f8003024e1b4940fb8408dff2ca6Ted Kremenek          continue;
193852274d4257134906995cb252fb3dfd2d71deae8Ted Kremenek
194852274d4257134906995cb252fb3dfd2d71deae8Ted Kremenek        if (V->hasLocalStorage()) {
195852274d4257134906995cb252fb3dfd2d71deae8Ted Kremenek          // Reference types confuse the dead stores checker.  Skip them
196852274d4257134906995cb252fb3dfd2d71deae8Ted Kremenek          // for now.
197852274d4257134906995cb252fb3dfd2d71deae8Ted Kremenek          if (V->getType()->getAs<ReferenceType>())
198852274d4257134906995cb252fb3dfd2d71deae8Ted Kremenek            return;
199852274d4257134906995cb252fb3dfd2d71deae8Ted Kremenek
200fc7ff5540412f8003024e1b4940fb8408dff2ca6Ted Kremenek          if (Expr* E = V->getInit()) {
20143f19e3136a9610eeba3cdef9f9af70d93df2f7eTed Kremenek            // Don't warn on C++ objects (yet) until we can show that their
20243f19e3136a9610eeba3cdef9f9af70d93df2f7eTed Kremenek            // constructors/destructors don't have side effects.
20343f19e3136a9610eeba3cdef9f9af70d93df2f7eTed Kremenek            if (isa<CXXConstructExpr>(E))
20443f19e3136a9610eeba3cdef9f9af70d93df2f7eTed Kremenek              return;
205604d939ac15d1398761df313679673d30bb10f27Ted Kremenek
206604d939ac15d1398761df313679673d30bb10f27Ted Kremenek            if (isa<CXXExprWithTemporaries>(E))
207604d939ac15d1398761df313679673d30bb10f27Ted Kremenek              return;
208604d939ac15d1398761df313679673d30bb10f27Ted Kremenek
209fc7ff5540412f8003024e1b4940fb8408dff2ca6Ted Kremenek            // A dead initialization is a variable that is dead after it
210fc7ff5540412f8003024e1b4940fb8408dff2ca6Ted Kremenek            // is initialized.  We don't flag warnings for those variables
211fc7ff5540412f8003024e1b4940fb8408dff2ca6Ted Kremenek            // marked 'unused'.
21240b598eea1310ec9ed554d56ce3e25b34c585458Argyrios Kyrtzidis            if (!Live(V, AD) && V->getAttr<UnusedAttr>() == 0) {
213c6a1fafe4289da10487799fc745eedc73dd8e5bcTed Kremenek              // Special case: check for initializations with constants.
214c6a1fafe4289da10487799fc745eedc73dd8e5bcTed Kremenek              //
215c6a1fafe4289da10487799fc745eedc73dd8e5bcTed Kremenek              //  e.g. : int x = 0;
216c6a1fafe4289da10487799fc745eedc73dd8e5bcTed Kremenek              //
217c6a1fafe4289da10487799fc745eedc73dd8e5bcTed Kremenek              // If x is EVER assigned a new value later, don't issue
218c6a1fafe4289da10487799fc745eedc73dd8e5bcTed Kremenek              // a warning.  This is because such initialization can be
219c6a1fafe4289da10487799fc745eedc73dd8e5bcTed Kremenek              // due to defensive programming.
220d3098ee64c069a3eff4d2d0a5d655d968c7b5dd2Ted Kremenek              if (E->isConstantInitializer(Ctx))
221d3098ee64c069a3eff4d2d0a5d655d968c7b5dd2Ted Kremenek                return;
2221eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
223d3098ee64c069a3eff4d2d0a5d655d968c7b5dd2Ted Kremenek              if (DeclRefExpr *DRE=dyn_cast<DeclRefExpr>(E->IgnoreParenCasts()))
224ebd42f40803396d63bc59b77285d088cca61f53fTed Kremenek                if (VarDecl *VD = dyn_cast<VarDecl>(DRE->getDecl())) {
225ebd42f40803396d63bc59b77285d088cca61f53fTed Kremenek                  // Special case: check for initialization from constant
226ebd42f40803396d63bc59b77285d088cca61f53fTed Kremenek                  //  variables.
227ebd42f40803396d63bc59b77285d088cca61f53fTed Kremenek                  //
228ebd42f40803396d63bc59b77285d088cca61f53fTed Kremenek                  //  e.g. extern const int MyConstant;
229ebd42f40803396d63bc59b77285d088cca61f53fTed Kremenek                  //       int x = MyConstant;
230ebd42f40803396d63bc59b77285d088cca61f53fTed Kremenek                  //
231d3098ee64c069a3eff4d2d0a5d655d968c7b5dd2Ted Kremenek                  if (VD->hasGlobalStorage() &&
232ebd42f40803396d63bc59b77285d088cca61f53fTed Kremenek                      VD->getType().isConstQualified())
233ebd42f40803396d63bc59b77285d088cca61f53fTed Kremenek                    return;
234ebd42f40803396d63bc59b77285d088cca61f53fTed Kremenek                  // Special case: check for initialization from scalar
235ebd42f40803396d63bc59b77285d088cca61f53fTed Kremenek                  //  parameters.  This is often a form of defensive
236ebd42f40803396d63bc59b77285d088cca61f53fTed Kremenek                  //  programming.  Non-scalars are still an error since
237ebd42f40803396d63bc59b77285d088cca61f53fTed Kremenek                  //  because it more likely represents an actual algorithmic
238ebd42f40803396d63bc59b77285d088cca61f53fTed Kremenek                  //  bug.
239ebd42f40803396d63bc59b77285d088cca61f53fTed Kremenek                  if (isa<ParmVarDecl>(VD) && VD->getType()->isScalarType())
240ebd42f40803396d63bc59b77285d088cca61f53fTed Kremenek                    return;
241ebd42f40803396d63bc59b77285d088cca61f53fTed Kremenek                }
2421eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
243d3098ee64c069a3eff4d2d0a5d655d968c7b5dd2Ted Kremenek              Report(V, DeadInit, V->getLocation(), E->getSourceRange());
244ce1cab9fc0b4aec9cdef1b30a14e4ccdca3ac5f1Ted Kremenek            }
245fc7ff5540412f8003024e1b4940fb8408dff2ca6Ted Kremenek          }
246852274d4257134906995cb252fb3dfd2d71deae8Ted Kremenek        }
247fdd225ed6f362a8550e597eb875d9c402b8a309cTed Kremenek      }
2481ed6d2e4fda310af2de2ec09cdfedfa280cce948Ted Kremenek  }
2491ed6d2e4fda310af2de2ec09cdfedfa280cce948Ted Kremenek};
2501eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
2511ed6d2e4fda310af2de2ec09cdfedfa280cce948Ted Kremenek} // end anonymous namespace
2521ed6d2e4fda310af2de2ec09cdfedfa280cce948Ted Kremenek
253d2f642b56e87493edfc3b0dab359b5e32d5f8a5eTed Kremenek//===----------------------------------------------------------------------===//
254e207558e9dbed963eebf5cf31fdb02616f1545a3Ted Kremenek// Driver function to invoke the Dead-Stores checker on a CFG.
255e207558e9dbed963eebf5cf31fdb02616f1545a3Ted Kremenek//===----------------------------------------------------------------------===//
256e207558e9dbed963eebf5cf31fdb02616f1545a3Ted Kremenek
257f96f16d9f529ec95c20b9a91405653554e9646d1Ted Kremeneknamespace {
258ba5fb5a955c896815c439289fc51c03cf0635129Kovarththanan Rajaratnamclass FindEscaped : public CFGRecStmtDeclVisitor<FindEscaped>{
259f96f16d9f529ec95c20b9a91405653554e9646d1Ted Kremenek  CFG *cfg;
260f96f16d9f529ec95c20b9a91405653554e9646d1Ted Kremenekpublic:
261f96f16d9f529ec95c20b9a91405653554e9646d1Ted Kremenek  FindEscaped(CFG *c) : cfg(c) {}
2621eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
263f96f16d9f529ec95c20b9a91405653554e9646d1Ted Kremenek  CFG& getCFG() { return *cfg; }
2641eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
265f96f16d9f529ec95c20b9a91405653554e9646d1Ted Kremenek  llvm::SmallPtrSet<VarDecl*, 20> Escaped;
266f96f16d9f529ec95c20b9a91405653554e9646d1Ted Kremenek
267f96f16d9f529ec95c20b9a91405653554e9646d1Ted Kremenek  void VisitUnaryOperator(UnaryOperator* U) {
268f96f16d9f529ec95c20b9a91405653554e9646d1Ted Kremenek    // Check for '&'.  Any VarDecl whose value has its address-taken we
269f96f16d9f529ec95c20b9a91405653554e9646d1Ted Kremenek    // treat as escaped.
270f96f16d9f529ec95c20b9a91405653554e9646d1Ted Kremenek    Expr* E = U->getSubExpr()->IgnoreParenCasts();
271f96f16d9f529ec95c20b9a91405653554e9646d1Ted Kremenek    if (U->getOpcode() == UnaryOperator::AddrOf)
272f96f16d9f529ec95c20b9a91405653554e9646d1Ted Kremenek      if (DeclRefExpr* DR = dyn_cast<DeclRefExpr>(E))
273f96f16d9f529ec95c20b9a91405653554e9646d1Ted Kremenek        if (VarDecl* VD = dyn_cast<VarDecl>(DR->getDecl())) {
274f96f16d9f529ec95c20b9a91405653554e9646d1Ted Kremenek          Escaped.insert(VD);
275f96f16d9f529ec95c20b9a91405653554e9646d1Ted Kremenek          return;
276f96f16d9f529ec95c20b9a91405653554e9646d1Ted Kremenek        }
277f96f16d9f529ec95c20b9a91405653554e9646d1Ted Kremenek    Visit(E);
278f96f16d9f529ec95c20b9a91405653554e9646d1Ted Kremenek  }
279f96f16d9f529ec95c20b9a91405653554e9646d1Ted Kremenek};
280f96f16d9f529ec95c20b9a91405653554e9646d1Ted Kremenek} // end anonymous namespace
2811eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
282f96f16d9f529ec95c20b9a91405653554e9646d1Ted Kremenek
283b317f8f5ca8737a5bbad97a3f7566a2dbd2ed61bZhongxing Xuvoid clang::CheckDeadStores(CFG &cfg, LiveVariables &L, ParentMap &pmap,
284b317f8f5ca8737a5bbad97a3f7566a2dbd2ed61bZhongxing Xu                            BugReporter& BR) {
285b317f8f5ca8737a5bbad97a3f7566a2dbd2ed61bZhongxing Xu  FindEscaped FS(&cfg);
2861eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump  FS.getCFG().VisitBlockStmts(FS);
287b317f8f5ca8737a5bbad97a3f7566a2dbd2ed61bZhongxing Xu  DeadStoreObs A(BR.getContext(), BR, pmap, FS.Escaped);
288b317f8f5ca8737a5bbad97a3f7566a2dbd2ed61bZhongxing Xu  L.runOnAllBlocks(cfg, &A);
289d2f642b56e87493edfc3b0dab359b5e32d5f8a5eTed Kremenek}
290