Index: clang/include/clang/Analysis/Analyses/LiveVariables.h =================================================================== --- clang/include/clang/Analysis/Analyses/LiveVariables.h +++ clang/include/clang/Analysis/Analyses/LiveVariables.h @@ -30,22 +30,22 @@ class LivenessValues { public: - llvm::ImmutableSet liveStmts; + llvm::ImmutableSet liveExprs; llvm::ImmutableSet liveDecls; llvm::ImmutableSet liveBindings; bool equals(const LivenessValues &V) const; LivenessValues() - : liveStmts(nullptr), liveDecls(nullptr), liveBindings(nullptr) {} + : liveExprs(nullptr), liveDecls(nullptr), liveBindings(nullptr) {} - LivenessValues(llvm::ImmutableSet LiveStmts, + LivenessValues(llvm::ImmutableSet liveExprs, llvm::ImmutableSet LiveDecls, llvm::ImmutableSet LiveBindings) - : liveStmts(LiveStmts), liveDecls(LiveDecls), + : liveExprs(liveExprs), liveDecls(LiveDecls), liveBindings(LiveBindings) {} - bool isLive(const Stmt *S) const; + bool isLive(const Expr *E) const; bool isLive(const VarDecl *D) const; friend class LiveVariables; @@ -83,17 +83,17 @@ /// only returns liveness information for block-level expressions. bool isLive(const Stmt *S, const VarDecl *D); - /// Returns true the block-level expression "value" is live + /// Returns true the block-level expression value is live /// before the given block-level expression (see runOnAllBlocks). - bool isLive(const Stmt *Loc, const Stmt *StmtVal); + bool isLive(const Stmt *Loc, const Expr *Val); /// Print to stderr the variable liveness information associated with /// each basic block. void dumpBlockLiveness(const SourceManager &M); - /// Print to stderr the statement liveness information associated with + /// Print to stderr the expression liveness information associated with /// each basic block. - void dumpStmtLiveness(const SourceManager &M); + void dumpExprLiveness(const SourceManager &M); void runOnAllBlocks(Observer &obs); Index: clang/include/clang/StaticAnalyzer/Core/PathSensitive/SymbolManager.h =================================================================== --- clang/include/clang/StaticAnalyzer/Core/PathSensitive/SymbolManager.h +++ clang/include/clang/StaticAnalyzer/Core/PathSensitive/SymbolManager.h @@ -529,7 +529,7 @@ bool isLive(SymbolRef sym); bool isLiveRegion(const MemRegion *region); - bool isLive(const Stmt *ExprVal, const LocationContext *LCtx) const; + bool isLive(const Expr *ExprVal, const LocationContext *LCtx) const; bool isLive(const VarRegion *VR, bool includeStoreBindings = false) const; /// Unconditionally marks a symbol as live. Index: clang/lib/Analysis/LiveVariables.cpp =================================================================== --- clang/lib/Analysis/LiveVariables.cpp +++ clang/lib/Analysis/LiveVariables.cpp @@ -27,7 +27,7 @@ class LiveVariablesImpl { public: AnalysisDeclContext &analysisContext; - llvm::ImmutableSet::Factory SSetFact; + llvm::ImmutableSet::Factory SSetFact; llvm::ImmutableSet::Factory DSetFact; llvm::ImmutableSet::Factory BSetFact; llvm::DenseMap blocksEndToLiveness; @@ -45,7 +45,7 @@ LiveVariables::Observer *obs = nullptr); void dumpBlockLiveness(const SourceManager& M); - void dumpStmtLiveness(const SourceManager& M); + void dumpExprLiveness(const SourceManager& M); LiveVariablesImpl(AnalysisDeclContext &ac, bool KillAtAssign) : analysisContext(ac), @@ -54,7 +54,7 @@ BSetFact(false), killAtAssign(KillAtAssign) {} }; -} +} // namespace static LiveVariablesImpl &getImpl(void *x) { return *((LiveVariablesImpl *) x); @@ -64,8 +64,8 @@ // Operations and queries on LivenessValues. //===----------------------------------------------------------------------===// -bool LiveVariables::LivenessValues::isLive(const Stmt *S) const { - return liveStmts.contains(S); +bool LiveVariables::LivenessValues::isLive(const Expr *E) const { + return liveExprs.contains(E); } bool LiveVariables::LivenessValues::isLive(const VarDecl *D) const { @@ -97,9 +97,9 @@ LiveVariablesImpl::merge(LiveVariables::LivenessValues valsA, LiveVariables::LivenessValues valsB) { - llvm::ImmutableSetRef - SSetRefA(valsA.liveStmts.getRootWithoutRetain(), SSetFact.getTreeFactory()), - SSetRefB(valsB.liveStmts.getRootWithoutRetain(), SSetFact.getTreeFactory()); + llvm::ImmutableSetRef + SSetRefA(valsA.liveExprs.getRootWithoutRetain(), SSetFact.getTreeFactory()), + SSetRefB(valsB.liveExprs.getRootWithoutRetain(), SSetFact.getTreeFactory()); llvm::ImmutableSetRef @@ -122,7 +122,7 @@ } bool LiveVariables::LivenessValues::equals(const LivenessValues &V) const { - return liveStmts == V.liveStmts && liveDecls == V.liveDecls; + return liveExprs == V.liveExprs && liveDecls == V.liveDecls; } //===----------------------------------------------------------------------===// @@ -141,8 +141,8 @@ return isAlwaysAlive(D) || getImpl(impl).stmtsToLiveness[S].isLive(D); } -bool LiveVariables::isLive(const Stmt *Loc, const Stmt *S) { - return getImpl(impl).stmtsToLiveness[Loc].isLive(S); +bool LiveVariables::isLive(const Stmt *Loc, const Expr *Val) { + return getImpl(impl).stmtsToLiveness[Loc].isLive(Val); } //===----------------------------------------------------------------------===// @@ -186,27 +186,27 @@ return nullptr; } -static const Stmt *LookThroughStmt(const Stmt *S) { - while (S) { - if (const Expr *Ex = dyn_cast(S)) - S = Ex->IgnoreParens(); - if (const FullExpr *FE = dyn_cast(S)) { - S = FE->getSubExpr(); +static const Expr *LookThroughExpr(const Expr *E) { + while (E) { + if (const Expr *Ex = dyn_cast(E)) + E = Ex->IgnoreParens(); + if (const FullExpr *FE = dyn_cast(E)) { + E = FE->getSubExpr(); continue; } - if (const OpaqueValueExpr *OVE = dyn_cast(S)) { - S = OVE->getSourceExpr(); + if (const OpaqueValueExpr *OVE = dyn_cast(E)) { + E = OVE->getSourceExpr(); continue; } break; } - return S; + return E; } -static void AddLiveStmt(llvm::ImmutableSet &Set, - llvm::ImmutableSet::Factory &F, - const Stmt *S) { - Set = F.add(Set, LookThroughStmt(S)); +static void AddLiveExpr(llvm::ImmutableSet &Set, + llvm::ImmutableSet::Factory &F, + const Expr *E) { + Set = F.add(Set, LookThroughExpr(E)); } void TransferFunctions::Visit(Stmt *S) { @@ -215,8 +215,8 @@ StmtVisitor::Visit(S); - if (isa(S)) { - val.liveStmts = LV.SSetFact.remove(val.liveStmts, S); + if (const auto *E = dyn_cast(S)) { + val.liveExprs = LV.SSetFact.remove(val.liveExprs, E); } // Mark all children expressions live. @@ -233,7 +233,7 @@ // Include the implicit "this" pointer as being live. CXXMemberCallExpr *CE = cast(S); if (Expr *ImplicitObj = CE->getImplicitObjectArgument()) { - AddLiveStmt(val.liveStmts, LV.SSetFact, ImplicitObj); + AddLiveExpr(val.liveExprs, LV.SSetFact, ImplicitObj); } break; } @@ -250,7 +250,7 @@ if (const VarDecl *VD = dyn_cast(DS->getSingleDecl())) { for (const VariableArrayType* VA = FindVA(VD->getType()); VA != nullptr; VA = FindVA(VA->getElementType())) { - AddLiveStmt(val.liveStmts, LV.SSetFact, VA->getSizeExpr()); + AddLiveExpr(val.liveExprs, LV.SSetFact, VA->getSizeExpr()); } } break; @@ -263,7 +263,7 @@ if (OpaqueValueExpr *OV = dyn_cast(child)) child = OV->getSourceExpr(); child = child->IgnoreParens(); - val.liveStmts = LV.SSetFact.add(val.liveStmts, child); + val.liveExprs = LV.SSetFact.add(val.liveExprs, child); return; } @@ -284,36 +284,39 @@ // If one of the branches is an expression rather than a compound // statement, it will be bad if we mark it as live at the terminator // of the if-statement (i.e., immediately after the condition expression). - AddLiveStmt(val.liveStmts, LV.SSetFact, cast(S)->getCond()); + AddLiveExpr(val.liveExprs, LV.SSetFact, cast(S)->getCond()); return; } case Stmt::WhileStmtClass: { // If the loop body is an expression rather than a compound statement, // it will be bad if we mark it as live at the terminator of the loop // (i.e., immediately after the condition expression). - AddLiveStmt(val.liveStmts, LV.SSetFact, cast(S)->getCond()); + AddLiveExpr(val.liveExprs, LV.SSetFact, cast(S)->getCond()); return; } case Stmt::DoStmtClass: { // If the loop body is an expression rather than a compound statement, // it will be bad if we mark it as live at the terminator of the loop // (i.e., immediately after the condition expression). - AddLiveStmt(val.liveStmts, LV.SSetFact, cast(S)->getCond()); + AddLiveExpr(val.liveExprs, LV.SSetFact, cast(S)->getCond()); return; } case Stmt::ForStmtClass: { // If the loop body is an expression rather than a compound statement, // it will be bad if we mark it as live at the terminator of the loop // (i.e., immediately after the condition expression). - AddLiveStmt(val.liveStmts, LV.SSetFact, cast(S)->getCond()); + AddLiveExpr(val.liveExprs, LV.SSetFact, cast(S)->getCond()); return; } } + // HACK + FIXME: What is this? One could only guess that this is an attempt to + // fish for live values, for example, arguments from a call expression. + // Maybe we could take inspiration from UninitializedVariable analysis? for (Stmt *Child : S->children()) { - if (Child) - AddLiveStmt(val.liveStmts, LV.SSetFact, Child); + if (const auto *E = dyn_cast_or_null(Child)) + AddLiveExpr(val.liveExprs, LV.SSetFact, E); } } @@ -416,7 +419,7 @@ const Expr *subEx = UE->getArgumentExpr(); if (subEx->getType()->isVariableArrayType()) { assert(subEx->isLValue()); - val.liveStmts = LV.SSetFact.add(val.liveStmts, subEx->IgnoreParens()); + val.liveExprs = LV.SSetFact.add(val.liveExprs, subEx->IgnoreParens()); } } @@ -613,19 +616,19 @@ llvm::errs() << "\n"; } -void LiveVariables::dumpStmtLiveness(const SourceManager &M) { - getImpl(impl).dumpStmtLiveness(M); +void LiveVariables::dumpExprLiveness(const SourceManager &M) { + getImpl(impl).dumpExprLiveness(M); } -void LiveVariablesImpl::dumpStmtLiveness(const SourceManager &M) { +void LiveVariablesImpl::dumpExprLiveness(const SourceManager &M) { // Don't iterate over blockEndsToLiveness directly because it's not sorted. - for (auto I : *analysisContext.getCFG()) { + for (const CFGBlock *B : *analysisContext.getCFG()) { - llvm::errs() << "\n[ B" << I->getBlockID() + llvm::errs() << "\n[ B" << B->getBlockID() << " (live statements at block exit) ]\n"; - for (auto S : blocksEndToLiveness[I].liveStmts) { + for (const Expr *E : blocksEndToLiveness[B].liveExprs) { llvm::errs() << "\n"; - S->dump(); + E->dump(); } llvm::errs() << "\n"; } Index: clang/lib/StaticAnalyzer/Checkers/DebugCheckers.cpp =================================================================== --- clang/lib/StaticAnalyzer/Checkers/DebugCheckers.cpp +++ clang/lib/StaticAnalyzer/Checkers/DebugCheckers.cpp @@ -136,7 +136,7 @@ void checkASTCodeBody(const Decl *D, AnalysisManager& Mgr, BugReporter &BR) const { if (LiveVariables *L = Mgr.getAnalysis(D)) - L->dumpStmtLiveness(Mgr.getSourceManager()); + L->dumpExprLiveness(Mgr.getSourceManager()); } }; } Index: clang/lib/StaticAnalyzer/Core/Environment.cpp =================================================================== --- clang/lib/StaticAnalyzer/Core/Environment.cpp +++ clang/lib/StaticAnalyzer/Core/Environment.cpp @@ -183,12 +183,15 @@ F.getTreeFactory()); // Iterate over the block-expr bindings. - for (Environment::iterator I = Env.begin(), E = Env.end(); - I != E; ++I) { + for (Environment::iterator I = Env.begin(), End = Env.end(); I != End; ++I) { const EnvironmentEntry &BlkExpr = I.getKey(); const SVal &X = I.getData(); - if (SymReaper.isLive(BlkExpr.getStmt(), BlkExpr.getLocationContext())) { + const Expr *E = dyn_cast(BlkExpr.getStmt()); + if (!E) + continue; + + if (SymReaper.isLive(E, BlkExpr.getLocationContext())) { // Copy the binding to the new map. EBMapRef = EBMapRef.add(BlkExpr, X); Index: clang/lib/StaticAnalyzer/Core/SymbolManager.cpp =================================================================== --- clang/lib/StaticAnalyzer/Core/SymbolManager.cpp +++ clang/lib/StaticAnalyzer/Core/SymbolManager.cpp @@ -482,7 +482,7 @@ } bool -SymbolReaper::isLive(const Stmt *ExprVal, const LocationContext *ELCtx) const { +SymbolReaper::isLive(const Expr *ExprVal, const LocationContext *ELCtx) const { if (LCtx == nullptr) return false;