diff --git a/clang/docs/analyzer/developer-docs/DebugChecks.rst b/clang/docs/analyzer/developer-docs/DebugChecks.rst --- a/clang/docs/analyzer/developer-docs/DebugChecks.rst +++ b/clang/docs/analyzer/developer-docs/DebugChecks.rst @@ -30,7 +30,7 @@ - debug.DumpLiveVars: Show the results of live variable analysis for each top-level function being analyzed. -- debug.DumpLiveStmts: Show the results of live statement analysis for each +- debug.DumpLiveExprs: Show the results of live expression analysis for each top-level function being analyzed. - debug.ViewExplodedGraph: Show the Exploded Graphs generated for the diff --git a/clang/include/clang/Analysis/Analyses/LiveVariables.h b/clang/include/clang/Analysis/Analyses/LiveVariables.h --- a/clang/include/clang/Analysis/Analyses/LiveVariables.h +++ b/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); diff --git a/clang/include/clang/StaticAnalyzer/Checkers/Checkers.td b/clang/include/clang/StaticAnalyzer/Checkers/Checkers.td --- a/clang/include/clang/StaticAnalyzer/Checkers/Checkers.td +++ b/clang/include/clang/StaticAnalyzer/Checkers/Checkers.td @@ -1478,8 +1478,8 @@ HelpText<"Print results of live variable analysis">, Documentation; -def LiveStatementsDumper : Checker<"DumpLiveStmts">, - HelpText<"Print results of live statement analysis">, +def LiveExpressionsDumper : Checker<"DumpLiveExprs">, + HelpText<"Print results of live expression analysis">, Documentation; def CFGViewer : Checker<"ViewCFG">, diff --git a/clang/include/clang/StaticAnalyzer/Core/PathSensitive/SymbolManager.h b/clang/include/clang/StaticAnalyzer/Core/PathSensitive/SymbolManager.h --- a/clang/include/clang/StaticAnalyzer/Core/PathSensitive/SymbolManager.h +++ b/clang/include/clang/StaticAnalyzer/Core/PathSensitive/SymbolManager.h @@ -539,7 +539,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. diff --git a/clang/lib/Analysis/LiveVariables.cpp b/clang/lib/Analysis/LiveVariables.cpp --- a/clang/lib/Analysis/LiveVariables.cpp +++ b/clang/lib/Analysis/LiveVariables.cpp @@ -27,7 +27,7 @@ class LiveVariablesImpl { public: AnalysisDeclContext &analysisContext; - llvm::ImmutableSet::Factory SSetFact; + llvm::ImmutableSet::Factory ESetFact; llvm::ImmutableSet::Factory DSetFact; llvm::ImmutableSet::Factory BSetFact; llvm::DenseMap blocksEndToLiveness; @@ -45,16 +45,15 @@ 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), - SSetFact(false), // Do not canonicalize ImmutableSets by default. - DSetFact(false), // This is a *major* performance win. - BSetFact(false), - killAtAssign(KillAtAssign) {} + : analysisContext(ac), + ESetFact(false), // Do not canonicalize ImmutableSets by default. + DSetFact(false), // This is a *major* performance win. + BSetFact(false), killAtAssign(KillAtAssign) {} }; -} +} // namespace static LiveVariablesImpl &getImpl(void *x) { return *((LiveVariablesImpl *) x); @@ -64,8 +63,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,10 +96,10 @@ 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(), ESetFact.getTreeFactory()), + SSetRefB(valsB.liveExprs.getRootWithoutRetain(), + ESetFact.getTreeFactory()); llvm::ImmutableSetRef DSetRefA(valsA.liveDecls.getRootWithoutRetain(), DSetFact.getTreeFactory()), @@ -122,7 +121,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 +140,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 +185,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 +214,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.ESetFact.remove(val.liveExprs, E); } // Mark all children expressions live. @@ -233,7 +232,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.ESetFact, ImplicitObj); } break; } @@ -250,7 +249,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.ESetFact, VA->getSizeExpr()); } } break; @@ -263,7 +262,7 @@ if (OpaqueValueExpr *OV = dyn_cast(child)) child = OV->getSourceExpr(); child = child->IgnoreParens(); - val.liveStmts = LV.SSetFact.add(val.liveStmts, child); + val.liveExprs = LV.ESetFact.add(val.liveExprs, child); return; } @@ -284,36 +283,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.ESetFact, 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.ESetFact, 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.ESetFact, 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.ESetFact, 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.ESetFact, E); } } @@ -416,7 +418,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.ESetFact.add(val.liveExprs, subEx->IgnoreParens()); } } @@ -613,19 +615,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() - << " (live statements at block exit) ]\n"; - for (auto S : blocksEndToLiveness[I].liveStmts) { + llvm::errs() << "\n[ B" << B->getBlockID() + << " (live expressions at block exit) ]\n"; + for (const Expr *E : blocksEndToLiveness[B].liveExprs) { llvm::errs() << "\n"; - S->dump(); + E->dump(); } llvm::errs() << "\n"; } diff --git a/clang/lib/StaticAnalyzer/Checkers/DebugCheckers.cpp b/clang/lib/StaticAnalyzer/Checkers/DebugCheckers.cpp --- a/clang/lib/StaticAnalyzer/Checkers/DebugCheckers.cpp +++ b/clang/lib/StaticAnalyzer/Checkers/DebugCheckers.cpp @@ -131,21 +131,21 @@ //===----------------------------------------------------------------------===// namespace { -class LiveStatementsDumper : public Checker { +class LiveExpressionsDumper : public Checker { public: void checkASTCodeBody(const Decl *D, AnalysisManager& Mgr, BugReporter &BR) const { if (LiveVariables *L = Mgr.getAnalysis(D)) - L->dumpStmtLiveness(Mgr.getSourceManager()); + L->dumpExprLiveness(Mgr.getSourceManager()); } }; } -void ento::registerLiveStatementsDumper(CheckerManager &mgr) { - mgr.registerChecker(); +void ento::registerLiveExpressionsDumper(CheckerManager &mgr) { + mgr.registerChecker(); } -bool ento::shouldRegisterLiveStatementsDumper(const CheckerManager &mgr) { +bool ento::shouldRegisterLiveExpressionsDumper(const CheckerManager &mgr) { return true; } diff --git a/clang/lib/StaticAnalyzer/Core/Environment.cpp b/clang/lib/StaticAnalyzer/Core/Environment.cpp --- a/clang/lib/StaticAnalyzer/Core/Environment.cpp +++ b/clang/lib/StaticAnalyzer/Core/Environment.cpp @@ -191,19 +191,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(); - const bool IsBlkExprLive = - SymReaper.isLive(BlkExpr.getStmt(), BlkExpr.getLocationContext()); + const Expr *E = dyn_cast(BlkExpr.getStmt()); + if (!E) + continue; - assert((isa(BlkExpr.getStmt()) || !IsBlkExprLive) && - "Only Exprs can be live, LivenessAnalysis argues about the liveness " - "of *values*!"); - - if (IsBlkExprLive) { + if (SymReaper.isLive(E, BlkExpr.getLocationContext())) { // Copy the binding to the new map. EBMapRef = EBMapRef.add(BlkExpr, X); diff --git a/clang/lib/StaticAnalyzer/Core/SymbolManager.cpp b/clang/lib/StaticAnalyzer/Core/SymbolManager.cpp --- a/clang/lib/StaticAnalyzer/Core/SymbolManager.cpp +++ b/clang/lib/StaticAnalyzer/Core/SymbolManager.cpp @@ -489,7 +489,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; diff --git a/clang/test/Analysis/live-stmts.cpp b/clang/test/Analysis/live-stmts.cpp --- a/clang/test/Analysis/live-stmts.cpp +++ b/clang/test/Analysis/live-stmts.cpp @@ -1,4 +1,4 @@ -// RUN: %clang_analyze_cc1 -w -analyzer-checker=debug.DumpLiveStmts %s 2>&1\ +// RUN: %clang_analyze_cc1 -w -analyzer-checker=debug.DumpLiveExprs %s 2>&1\ // RUN: | FileCheck %s int coin(); @@ -7,13 +7,24 @@ int testThatDumperWorks(int x, int y, int z) { return x ? y : z; } -// CHECK: [ B0 (live statements at block exit) ] + +// [B5 (ENTRY)] +// | +// V +// [B4 (x)] ? [B2 (y)] : [B3 (z)] +// \ / +// ---|---- +// V +// [B1] --> [B0 (EXIT)] +// return + +// CHECK: [ B0 (live expressions at block exit) ] // CHECK-EMPTY: // CHECK-EMPTY: -// CHECK: [ B1 (live statements at block exit) ] +// CHECK: [ B1 (live expressions at block exit) ] // CHECK-EMPTY: // CHECK-EMPTY: -// CHECK: [ B2 (live statements at block exit) ] +// CHECK: [ B2 (live expressions at block exit) ] // CHECK-EMPTY: // CHECK-NEXT: DeclRefExpr {{.*}} 'y' 'int' // CHECK-EMPTY: @@ -24,7 +35,7 @@ // CHECK-NEXT: `-DeclRefExpr {{.*}} 'x' 'int' // CHECK-EMPTY: // CHECK-EMPTY: -// CHECK: [ B3 (live statements at block exit) ] +// CHECK: [ B3 (live expressions at block exit) ] // CHECK-EMPTY: // CHECK-NEXT: DeclRefExpr {{.*}} 'y' 'int' // CHECK-EMPTY: @@ -33,7 +44,7 @@ // CHECK-NEXT: ImplicitCastExpr {{.*}} // CHECK-NEXT: `-ImplicitCastExpr {{.*}} // CHECK-NEXT: `-DeclRefExpr {{.*}} 'x' 'int' -// CHECK: [ B4 (live statements at block exit) ] +// CHECK: [ B4 (live expressions at block exit) ] // CHECK-EMPTY: // CHECK-NEXT: DeclRefExpr {{.*}} 'y' 'int' // CHECK-EMPTY: @@ -44,7 +55,7 @@ // CHECK-NEXT: `-DeclRefExpr {{.*}} 'x' 'int' // CHECK-EMPTY: // CHECK-EMPTY: -// CHECK: [ B5 (live statements at block exit) ] +// CHECK: [ B5 (live expressions at block exit) ] // CHECK-EMPTY: // CHECK-NEXT: DeclRefExpr {{.*}} 'y' 'int' // CHECK-EMPTY: @@ -61,22 +72,22 @@ e; } } -// CHECK: [ B0 (live statements at block exit) ] +// CHECK: [ B0 (live expressions at block exit) ] // CHECK-EMPTY: // CHECK-EMPTY: -// CHECK: [ B1 (live statements at block exit) ] +// CHECK: [ B1 (live expressions at block exit) ] // CHECK-EMPTY: // CHECK-EMPTY: -// CHECK: [ B2 (live statements at block exit) ] +// CHECK: [ B2 (live expressions at block exit) ] // CHECK-EMPTY: // CHECK-EMPTY: -// CHECK: [ B3 (live statements at block exit) ] +// CHECK: [ B3 (live expressions at block exit) ] // CHECK-EMPTY: // CHECK-EMPTY: -// CHECK: [ B4 (live statements at block exit) ] +// CHECK: [ B4 (live expressions at block exit) ] // CHECK-EMPTY: // CHECK-EMPTY: -// CHECK: [ B5 (live statements at block exit) ] +// CHECK: [ B5 (live expressions at block exit) ] // CHECK-EMPTY: // CHECK-EMPTY: @@ -89,22 +100,22 @@ e; } } -// CHECK: [ B0 (live statements at block exit) ] +// CHECK: [ B0 (live expressions at block exit) ] // CHECK-EMPTY: // CHECK-EMPTY: -// CHECK: [ B1 (live statements at block exit) ] +// CHECK: [ B1 (live expressions at block exit) ] // CHECK-EMPTY: // CHECK-EMPTY: -// CHECK: [ B2 (live statements at block exit) ] +// CHECK: [ B2 (live expressions at block exit) ] // CHECK-EMPTY: // CHECK-EMPTY: -// CHECK: [ B3 (live statements at block exit) ] +// CHECK: [ B3 (live expressions at block exit) ] // CHECK-EMPTY: // CHECK-EMPTY: -// CHECK: [ B4 (live statements at block exit) ] +// CHECK: [ B4 (live expressions at block exit) ] // CHECK-EMPTY: // CHECK-EMPTY: -// CHECK: [ B5 (live statements at block exit) ] +// CHECK: [ B5 (live expressions at block exit) ] // CHECK-EMPTY: // CHECK-EMPTY: @@ -118,22 +129,22 @@ while (coin()); } } -// CHECK: [ B0 (live statements at block exit) ] +// CHECK: [ B0 (live expressions at block exit) ] // CHECK-EMPTY: // CHECK-EMPTY: -// CHECK: [ B1 (live statements at block exit) ] +// CHECK: [ B1 (live expressions at block exit) ] // CHECK-EMPTY: // CHECK-EMPTY: -// CHECK: [ B2 (live statements at block exit) ] +// CHECK: [ B2 (live expressions at block exit) ] // CHECK-EMPTY: // CHECK-EMPTY: -// CHECK: [ B3 (live statements at block exit) ] +// CHECK: [ B3 (live expressions at block exit) ] // CHECK-EMPTY: // CHECK-EMPTY: -// CHECK: [ B4 (live statements at block exit) ] +// CHECK: [ B4 (live expressions at block exit) ] // CHECK-EMPTY: // CHECK-EMPTY: -// CHECK: [ B5 (live statements at block exit) ] +// CHECK: [ B5 (live expressions at block exit) ] // CHECK-EMPTY: // CHECK-EMPTY: @@ -146,22 +157,39 @@ e; } } -// CHECK: [ B0 (live statements at block exit) ] +// CHECK: [ B0 (live expressions at block exit) ] // CHECK-EMPTY: // CHECK-EMPTY: -// CHECK: [ B1 (live statements at block exit) ] +// CHECK: [ B1 (live expressions at block exit) ] // CHECK-EMPTY: // CHECK-EMPTY: -// CHECK: [ B2 (live statements at block exit) ] +// CHECK: [ B2 (live expressions at block exit) ] // CHECK-EMPTY: // CHECK-EMPTY: -// CHECK: [ B3 (live statements at block exit) ] +// CHECK: [ B3 (live expressions at block exit) ] // CHECK-EMPTY: // CHECK-EMPTY: -// CHECK: [ B4 (live statements at block exit) ] +// CHECK: [ B4 (live expressions at block exit) ] // CHECK-EMPTY: // CHECK-EMPTY: -// CHECK: [ B5 (live statements at block exit) ] +// CHECK: [ B5 (live expressions at block exit) ] // CHECK-EMPTY: // CHECK-EMPTY: +void clang_analyzer_eval(bool); + +void test_lambda_refcapture() { + int a = 6; + [&](int &a) { a = 42; }(a); + clang_analyzer_eval(a == 42); // expected-warning{{TRUE}} +} + +// CHECK: [ B0 (live expressions at block exit) ] +// CHECK-EMPTY: +// CHECK-EMPTY: +// CHECK-NEXT: [ B1 (live expressions at block exit) ] +// CHECK-EMPTY: +// CHECK-EMPTY: +// CHECK-NEXT: [ B2 (live expressions at block exit) ] +// CHECK-EMPTY: +// CHECK-EMPTY: diff --git a/clang/test/Analysis/live-stmts.mm b/clang/test/Analysis/live-stmts.mm --- a/clang/test/Analysis/live-stmts.mm +++ b/clang/test/Analysis/live-stmts.mm @@ -1,5 +1,5 @@ // RUN: %clang_analyze_cc1 -w -fblocks %s \ -// RUN: -analyzer-checker=debug.DumpLiveStmts \ +// RUN: -analyzer-checker=debug.DumpLiveExprs \ // RUN: 2>&1 | FileCheck %s @interface Item @@ -18,25 +18,25 @@ public: RAII(Blk blk): blk(blk) {} -// CHECK: [ B0 (live statements at block exit) ] +// CHECK: [ B0 (live expressions at block exit) ] // CHECK-EMPTY: // CHECK-EMPTY: -// CHECK-NEXT: [ B1 (live statements at block exit) ] +// CHECK-NEXT: [ B1 (live expressions at block exit) ] // CHECK-EMPTY: // CHECK-EMPTY: -// CHECK-NEXT: [ B2 (live statements at block exit) ] +// CHECK-NEXT: [ B2 (live expressions at block exit) ] // CHECK-EMPTY: // CHECK-EMPTY: ~RAII() { blk(); } -// CHECK-NEXT: [ B0 (live statements at block exit) ] +// CHECK-NEXT: [ B0 (live expressions at block exit) ] // CHECK-EMPTY: // CHECK-EMPTY: -// CHECK-NEXT: [ B1 (live statements at block exit) ] +// CHECK-NEXT: [ B1 (live expressions at block exit) ] // CHECK-EMPTY: // CHECK-EMPTY: -// CHECK-NEXT: [ B2 (live statements at block exit) ] +// CHECK-NEXT: [ B2 (live expressions at block exit) ] // CHECK-EMPTY: // CHECK-EMPTY: }; @@ -45,57 +45,37 @@ RAII raii(^{}); for (Item *item in coll) {} } -// CHECK-NEXT: [ B0 (live statements at block exit) ] +// CHECK-NEXT: [ B0 (live expressions at block exit) ] // CHECK-EMPTY: // CHECK-EMPTY: -// CHECK-NEXT: [ B1 (live statements at block exit) ] +// CHECK-NEXT: [ B1 (live expressions at block exit) ] // CHECK-EMPTY: // CHECK-EMPTY: -// CHECK-NEXT: [ B2 (live statements at block exit) ] -// CHECK-EMPTY: -// CHECK-NEXT: DeclStmt {{.*}} -// CHECK-NEXT: `-VarDecl {{.*}} item 'Item *' +// CHECK-NEXT: [ B2 (live expressions at block exit) ] // CHECK-EMPTY: // CHECK-NEXT: ImplicitCastExpr {{.*}} 'Collection *' // CHECK-NEXT: `-DeclRefExpr {{.*}} 'Collection *' lvalue ParmVar {{.*}} 'coll' 'Collection *' // CHECK-EMPTY: -// CHECK-NEXT: CompoundStmt {{.*}} -// CHECK-EMPTY: // CHECK-EMPTY: -// CHECK-NEXT: [ B3 (live statements at block exit) ] -// CHECK-EMPTY: -// CHECK-NEXT: DeclStmt {{.*}} -// CHECK-NEXT: `-VarDecl {{.*}} item 'Item *' +// CHECK-NEXT: [ B3 (live expressions at block exit) ] // CHECK-EMPTY: // CHECK-NEXT: ImplicitCastExpr {{.*}} 'Collection *' // CHECK-NEXT: `-DeclRefExpr {{.*}} 'Collection *' lvalue ParmVar {{.*}} 'coll' 'Collection *' // CHECK-EMPTY: -// CHECK-NEXT: CompoundStmt {{.*}} -// CHECK-EMPTY: // CHECK-EMPTY: -// CHECK-NEXT: [ B4 (live statements at block exit) ] -// CHECK-EMPTY: -// CHECK-NEXT: DeclStmt {{.*}} -// CHECK-NEXT: `-VarDecl {{.*}} item 'Item *' +// CHECK-NEXT: [ B4 (live expressions at block exit) ] // CHECK-EMPTY: // CHECK-NEXT: ImplicitCastExpr {{.*}} 'Collection *' // CHECK-NEXT: `-DeclRefExpr {{.*}} 'Collection *' lvalue ParmVar {{.*}} 'coll' 'Collection *' // CHECK-EMPTY: -// CHECK-NEXT: CompoundStmt {{.*}} -// CHECK-EMPTY: -// CHECK-EMPTY: -// CHECK-NEXT: [ B5 (live statements at block exit) ] -// CHECK-EMPTY: -// CHECK-NEXT: DeclStmt {{.*}} -// CHECK-NEXT: `-VarDecl {{.*}} item 'Item *' // CHECK-EMPTY: -// CHECK-NEXT: CompoundStmt {{.*}} +// CHECK-NEXT: [ B5 (live expressions at block exit) ] // CHECK-EMPTY: // CHECK-EMPTY: -// CHECK-NEXT: [ B0 (live statements at block exit) ] +// CHECK-NEXT: [ B0 (live expressions at block exit) ] // CHECK-EMPTY: // CHECK-EMPTY: -// CHECK-NEXT: [ B1 (live statements at block exit) ] +// CHECK-NEXT: [ B1 (live expressions at block exit) ] // CHECK-EMPTY: // CHECK-EMPTY: