1 //=- LiveVariables.cpp - Live Variable Analysis for Source CFGs ----------*-==//
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
7 //===----------------------------------------------------------------------===//
9 // This file implements Live Variables analysis for source-level CFGs.
11 //===----------------------------------------------------------------------===//
13 #include "clang/Analysis/Analyses/LiveVariables.h"
14 #include "clang/AST/Stmt.h"
15 #include "clang/AST/StmtVisitor.h"
16 #include "clang/Analysis/AnalysisDeclContext.h"
17 #include "clang/Analysis/CFG.h"
18 #include "clang/Analysis/FlowSensitive/DataflowWorklist.h"
19 #include "llvm/ADT/DenseMap.h"
20 #include "llvm/Support/raw_ostream.h"
25 using namespace clang
;
28 class LiveVariablesImpl
{
30 AnalysisDeclContext
&analysisContext
;
31 llvm::ImmutableSet
<const Expr
*>::Factory ESetFact
;
32 llvm::ImmutableSet
<const VarDecl
*>::Factory DSetFact
;
33 llvm::ImmutableSet
<const BindingDecl
*>::Factory BSetFact
;
34 llvm::DenseMap
<const CFGBlock
*, LiveVariables::LivenessValues
> blocksEndToLiveness
;
35 llvm::DenseMap
<const CFGBlock
*, LiveVariables::LivenessValues
> blocksBeginToLiveness
;
36 llvm::DenseMap
<const Stmt
*, LiveVariables::LivenessValues
> stmtsToLiveness
;
37 llvm::DenseMap
<const DeclRefExpr
*, unsigned> inAssignment
;
38 const bool killAtAssign
;
40 LiveVariables::LivenessValues
41 merge(LiveVariables::LivenessValues valsA
,
42 LiveVariables::LivenessValues valsB
);
44 LiveVariables::LivenessValues
45 runOnBlock(const CFGBlock
*block
, LiveVariables::LivenessValues val
,
46 LiveVariables::Observer
*obs
= nullptr);
48 void dumpBlockLiveness(const SourceManager
& M
);
49 void dumpExprLiveness(const SourceManager
& M
);
51 LiveVariablesImpl(AnalysisDeclContext
&ac
, bool KillAtAssign
)
52 : analysisContext(ac
),
53 ESetFact(false), // Do not canonicalize ImmutableSets by default.
54 DSetFact(false), // This is a *major* performance win.
55 BSetFact(false), killAtAssign(KillAtAssign
) {}
59 static LiveVariablesImpl
&getImpl(void *x
) {
60 return *((LiveVariablesImpl
*) x
);
63 //===----------------------------------------------------------------------===//
64 // Operations and queries on LivenessValues.
65 //===----------------------------------------------------------------------===//
67 bool LiveVariables::LivenessValues::isLive(const Expr
*E
) const {
68 return liveExprs
.contains(E
);
71 bool LiveVariables::LivenessValues::isLive(const VarDecl
*D
) const {
72 if (const auto *DD
= dyn_cast
<DecompositionDecl
>(D
)) {
74 for (const BindingDecl
*BD
: DD
->bindings())
75 alive
|= liveBindings
.contains(BD
);
77 // Note: the only known case this condition is necessary, is when a bindig
78 // to a tuple-like structure is created. The HoldingVar initializers have a
79 // DeclRefExpr to the DecompositionDecl.
80 alive
|= liveDecls
.contains(DD
);
83 return liveDecls
.contains(D
);
87 template <typename SET
>
88 SET
mergeSets(SET A
, SET B
) {
92 for (typename
SET::iterator it
= B
.begin(), ei
= B
.end(); it
!= ei
; ++it
) {
99 void LiveVariables::Observer::anchor() { }
101 LiveVariables::LivenessValues
102 LiveVariablesImpl::merge(LiveVariables::LivenessValues valsA
,
103 LiveVariables::LivenessValues valsB
) {
105 llvm::ImmutableSetRef
<const Expr
*> SSetRefA(
106 valsA
.liveExprs
.getRootWithoutRetain(), ESetFact
.getTreeFactory()),
107 SSetRefB(valsB
.liveExprs
.getRootWithoutRetain(),
108 ESetFact
.getTreeFactory());
110 llvm::ImmutableSetRef
<const VarDecl
*>
111 DSetRefA(valsA
.liveDecls
.getRootWithoutRetain(), DSetFact
.getTreeFactory()),
112 DSetRefB(valsB
.liveDecls
.getRootWithoutRetain(), DSetFact
.getTreeFactory());
114 llvm::ImmutableSetRef
<const BindingDecl
*>
115 BSetRefA(valsA
.liveBindings
.getRootWithoutRetain(), BSetFact
.getTreeFactory()),
116 BSetRefB(valsB
.liveBindings
.getRootWithoutRetain(), BSetFact
.getTreeFactory());
118 SSetRefA
= mergeSets(SSetRefA
, SSetRefB
);
119 DSetRefA
= mergeSets(DSetRefA
, DSetRefB
);
120 BSetRefA
= mergeSets(BSetRefA
, BSetRefB
);
122 // asImmutableSet() canonicalizes the tree, allowing us to do an easy
123 // comparison afterwards.
124 return LiveVariables::LivenessValues(SSetRefA
.asImmutableSet(),
125 DSetRefA
.asImmutableSet(),
126 BSetRefA
.asImmutableSet());
129 bool LiveVariables::LivenessValues::equals(const LivenessValues
&V
) const {
130 return liveExprs
== V
.liveExprs
&& liveDecls
== V
.liveDecls
;
133 //===----------------------------------------------------------------------===//
135 //===----------------------------------------------------------------------===//
137 static bool isAlwaysAlive(const VarDecl
*D
) {
138 return D
->hasGlobalStorage();
141 bool LiveVariables::isLive(const CFGBlock
*B
, const VarDecl
*D
) {
142 return isAlwaysAlive(D
) || getImpl(impl
).blocksEndToLiveness
[B
].isLive(D
);
145 bool LiveVariables::isLive(const Stmt
*S
, const VarDecl
*D
) {
146 return isAlwaysAlive(D
) || getImpl(impl
).stmtsToLiveness
[S
].isLive(D
);
149 bool LiveVariables::isLive(const Stmt
*Loc
, const Expr
*Val
) {
150 return getImpl(impl
).stmtsToLiveness
[Loc
].isLive(Val
);
153 //===----------------------------------------------------------------------===//
154 // Dataflow computation.
155 //===----------------------------------------------------------------------===//
158 class TransferFunctions
: public StmtVisitor
<TransferFunctions
> {
159 LiveVariablesImpl
&LV
;
160 LiveVariables::LivenessValues
&val
;
161 LiveVariables::Observer
*observer
;
162 const CFGBlock
*currentBlock
;
164 TransferFunctions(LiveVariablesImpl
&im
,
165 LiveVariables::LivenessValues
&Val
,
166 LiveVariables::Observer
*Observer
,
167 const CFGBlock
*CurrentBlock
)
168 : LV(im
), val(Val
), observer(Observer
), currentBlock(CurrentBlock
) {}
170 void VisitBinaryOperator(BinaryOperator
*BO
);
171 void VisitBlockExpr(BlockExpr
*BE
);
172 void VisitDeclRefExpr(DeclRefExpr
*DR
);
173 void VisitDeclStmt(DeclStmt
*DS
);
174 void VisitObjCForCollectionStmt(ObjCForCollectionStmt
*OS
);
175 void VisitUnaryExprOrTypeTraitExpr(UnaryExprOrTypeTraitExpr
*UE
);
176 void VisitUnaryOperator(UnaryOperator
*UO
);
181 static const VariableArrayType
*FindVA(QualType Ty
) {
182 const Type
*ty
= Ty
.getTypePtr();
183 while (const ArrayType
*VT
= dyn_cast
<ArrayType
>(ty
)) {
184 if (const VariableArrayType
*VAT
= dyn_cast
<VariableArrayType
>(VT
))
185 if (VAT
->getSizeExpr())
188 ty
= VT
->getElementType().getTypePtr();
194 static const Expr
*LookThroughExpr(const Expr
*E
) {
196 if (const Expr
*Ex
= dyn_cast
<Expr
>(E
))
197 E
= Ex
->IgnoreParens();
198 if (const FullExpr
*FE
= dyn_cast
<FullExpr
>(E
)) {
199 E
= FE
->getSubExpr();
202 if (const OpaqueValueExpr
*OVE
= dyn_cast
<OpaqueValueExpr
>(E
)) {
203 E
= OVE
->getSourceExpr();
211 static void AddLiveExpr(llvm::ImmutableSet
<const Expr
*> &Set
,
212 llvm::ImmutableSet
<const Expr
*>::Factory
&F
,
214 Set
= F
.add(Set
, LookThroughExpr(E
));
217 void TransferFunctions::Visit(Stmt
*S
) {
219 observer
->observeStmt(S
, currentBlock
, val
);
221 StmtVisitor
<TransferFunctions
>::Visit(S
);
223 if (const auto *E
= dyn_cast
<Expr
>(S
)) {
224 val
.liveExprs
= LV
.ESetFact
.remove(val
.liveExprs
, E
);
227 // Mark all children expressions live.
229 switch (S
->getStmtClass()) {
232 case Stmt::StmtExprClass
: {
233 // For statement expressions, look through the compound statement.
234 S
= cast
<StmtExpr
>(S
)->getSubStmt();
237 case Stmt::CXXMemberCallExprClass
: {
238 // Include the implicit "this" pointer as being live.
239 CXXMemberCallExpr
*CE
= cast
<CXXMemberCallExpr
>(S
);
240 if (Expr
*ImplicitObj
= CE
->getImplicitObjectArgument()) {
241 AddLiveExpr(val
.liveExprs
, LV
.ESetFact
, ImplicitObj
);
245 case Stmt::ObjCMessageExprClass
: {
246 // In calls to super, include the implicit "self" pointer as being live.
247 ObjCMessageExpr
*CE
= cast
<ObjCMessageExpr
>(S
);
248 if (CE
->getReceiverKind() == ObjCMessageExpr::SuperInstance
)
249 val
.liveDecls
= LV
.DSetFact
.add(val
.liveDecls
,
250 LV
.analysisContext
.getSelfDecl());
253 case Stmt::DeclStmtClass
: {
254 const DeclStmt
*DS
= cast
<DeclStmt
>(S
);
255 if (const VarDecl
*VD
= dyn_cast
<VarDecl
>(DS
->getSingleDecl())) {
256 for (const VariableArrayType
* VA
= FindVA(VD
->getType());
257 VA
!= nullptr; VA
= FindVA(VA
->getElementType())) {
258 AddLiveExpr(val
.liveExprs
, LV
.ESetFact
, VA
->getSizeExpr());
263 case Stmt::PseudoObjectExprClass
: {
264 // A pseudo-object operation only directly consumes its result
266 Expr
*child
= cast
<PseudoObjectExpr
>(S
)->getResultExpr();
268 if (OpaqueValueExpr
*OV
= dyn_cast
<OpaqueValueExpr
>(child
))
269 child
= OV
->getSourceExpr();
270 child
= child
->IgnoreParens();
271 val
.liveExprs
= LV
.ESetFact
.add(val
.liveExprs
, child
);
275 // FIXME: These cases eventually shouldn't be needed.
276 case Stmt::ExprWithCleanupsClass
: {
277 S
= cast
<ExprWithCleanups
>(S
)->getSubExpr();
280 case Stmt::CXXBindTemporaryExprClass
: {
281 S
= cast
<CXXBindTemporaryExpr
>(S
)->getSubExpr();
284 case Stmt::UnaryExprOrTypeTraitExprClass
: {
285 // No need to unconditionally visit subexpressions.
288 case Stmt::IfStmtClass
: {
289 // If one of the branches is an expression rather than a compound
290 // statement, it will be bad if we mark it as live at the terminator
291 // of the if-statement (i.e., immediately after the condition expression).
292 AddLiveExpr(val
.liveExprs
, LV
.ESetFact
, cast
<IfStmt
>(S
)->getCond());
295 case Stmt::WhileStmtClass
: {
296 // If the loop body is an expression rather than a compound statement,
297 // it will be bad if we mark it as live at the terminator of the loop
298 // (i.e., immediately after the condition expression).
299 AddLiveExpr(val
.liveExprs
, LV
.ESetFact
, cast
<WhileStmt
>(S
)->getCond());
302 case Stmt::DoStmtClass
: {
303 // If the loop body is an expression rather than a compound statement,
304 // it will be bad if we mark it as live at the terminator of the loop
305 // (i.e., immediately after the condition expression).
306 AddLiveExpr(val
.liveExprs
, LV
.ESetFact
, cast
<DoStmt
>(S
)->getCond());
309 case Stmt::ForStmtClass
: {
310 // If the loop body is an expression rather than a compound statement,
311 // it will be bad if we mark it as live at the terminator of the loop
312 // (i.e., immediately after the condition expression).
313 AddLiveExpr(val
.liveExprs
, LV
.ESetFact
, cast
<ForStmt
>(S
)->getCond());
319 // HACK + FIXME: What is this? One could only guess that this is an attempt to
320 // fish for live values, for example, arguments from a call expression.
321 // Maybe we could take inspiration from UninitializedVariable analysis?
322 for (Stmt
*Child
: S
->children()) {
323 if (const auto *E
= dyn_cast_or_null
<Expr
>(Child
))
324 AddLiveExpr(val
.liveExprs
, LV
.ESetFact
, E
);
328 static bool writeShouldKill(const VarDecl
*VD
) {
329 return VD
&& !VD
->getType()->isReferenceType() &&
333 void TransferFunctions::VisitBinaryOperator(BinaryOperator
*B
) {
334 if (LV
.killAtAssign
&& B
->getOpcode() == BO_Assign
) {
335 if (const auto *DR
= dyn_cast
<DeclRefExpr
>(B
->getLHS()->IgnoreParens())) {
336 LV
.inAssignment
[DR
] = 1;
339 if (B
->isAssignmentOp()) {
340 if (!LV
.killAtAssign
)
343 // Assigning to a variable?
344 Expr
*LHS
= B
->getLHS()->IgnoreParens();
346 if (DeclRefExpr
*DR
= dyn_cast
<DeclRefExpr
>(LHS
)) {
347 const Decl
* D
= DR
->getDecl();
350 if (const BindingDecl
* BD
= dyn_cast
<BindingDecl
>(D
)) {
351 Killed
= !BD
->getType()->isReferenceType();
353 if (const auto *HV
= BD
->getHoldingVar())
354 val
.liveDecls
= LV
.DSetFact
.remove(val
.liveDecls
, HV
);
356 val
.liveBindings
= LV
.BSetFact
.remove(val
.liveBindings
, BD
);
358 } else if (const auto *VD
= dyn_cast
<VarDecl
>(D
)) {
359 Killed
= writeShouldKill(VD
);
361 val
.liveDecls
= LV
.DSetFact
.remove(val
.liveDecls
, VD
);
365 if (Killed
&& observer
)
366 observer
->observerKill(DR
);
371 void TransferFunctions::VisitBlockExpr(BlockExpr
*BE
) {
372 for (const VarDecl
*VD
:
373 LV
.analysisContext
.getReferencedBlockVars(BE
->getBlockDecl())) {
374 if (isAlwaysAlive(VD
))
376 val
.liveDecls
= LV
.DSetFact
.add(val
.liveDecls
, VD
);
380 void TransferFunctions::VisitDeclRefExpr(DeclRefExpr
*DR
) {
381 const Decl
* D
= DR
->getDecl();
382 bool InAssignment
= LV
.inAssignment
[DR
];
383 if (const auto *BD
= dyn_cast
<BindingDecl
>(D
)) {
385 if (const auto *HV
= BD
->getHoldingVar())
386 val
.liveDecls
= LV
.DSetFact
.add(val
.liveDecls
, HV
);
388 val
.liveBindings
= LV
.BSetFact
.add(val
.liveBindings
, BD
);
390 } else if (const auto *VD
= dyn_cast
<VarDecl
>(D
)) {
391 if (!InAssignment
&& !isAlwaysAlive(VD
))
392 val
.liveDecls
= LV
.DSetFact
.add(val
.liveDecls
, VD
);
396 void TransferFunctions::VisitDeclStmt(DeclStmt
*DS
) {
397 for (const auto *DI
: DS
->decls()) {
398 if (const auto *DD
= dyn_cast
<DecompositionDecl
>(DI
)) {
399 for (const auto *BD
: DD
->bindings()) {
400 if (const auto *HV
= BD
->getHoldingVar())
401 val
.liveDecls
= LV
.DSetFact
.remove(val
.liveDecls
, HV
);
403 val
.liveBindings
= LV
.BSetFact
.remove(val
.liveBindings
, BD
);
406 // When a bindig to a tuple-like structure is created, the HoldingVar
407 // initializers have a DeclRefExpr to the DecompositionDecl.
408 val
.liveDecls
= LV
.DSetFact
.remove(val
.liveDecls
, DD
);
409 } else if (const auto *VD
= dyn_cast
<VarDecl
>(DI
)) {
410 if (!isAlwaysAlive(VD
))
411 val
.liveDecls
= LV
.DSetFact
.remove(val
.liveDecls
, VD
);
416 void TransferFunctions::VisitObjCForCollectionStmt(ObjCForCollectionStmt
*OS
) {
417 // Kill the iteration variable.
418 DeclRefExpr
*DR
= nullptr;
419 const VarDecl
*VD
= nullptr;
421 Stmt
*element
= OS
->getElement();
422 if (DeclStmt
*DS
= dyn_cast
<DeclStmt
>(element
)) {
423 VD
= cast
<VarDecl
>(DS
->getSingleDecl());
425 else if ((DR
= dyn_cast
<DeclRefExpr
>(cast
<Expr
>(element
)->IgnoreParens()))) {
426 VD
= cast
<VarDecl
>(DR
->getDecl());
430 val
.liveDecls
= LV
.DSetFact
.remove(val
.liveDecls
, VD
);
432 observer
->observerKill(DR
);
436 void TransferFunctions::
437 VisitUnaryExprOrTypeTraitExpr(UnaryExprOrTypeTraitExpr
*UE
)
439 // While sizeof(var) doesn't technically extend the liveness of 'var', it
440 // does extent the liveness of metadata if 'var' is a VariableArrayType.
441 // We handle that special case here.
442 if (UE
->getKind() != UETT_SizeOf
|| UE
->isArgumentType())
445 const Expr
*subEx
= UE
->getArgumentExpr();
446 if (subEx
->getType()->isVariableArrayType()) {
447 assert(subEx
->isLValue());
448 val
.liveExprs
= LV
.ESetFact
.add(val
.liveExprs
, subEx
->IgnoreParens());
452 void TransferFunctions::VisitUnaryOperator(UnaryOperator
*UO
) {
453 // Treat ++/-- as a kill.
454 // Note we don't actually have to do anything if we don't have an observer,
455 // since a ++/-- acts as both a kill and a "use".
459 switch (UO
->getOpcode()) {
469 if (auto *DR
= dyn_cast
<DeclRefExpr
>(UO
->getSubExpr()->IgnoreParens())) {
470 const Decl
*D
= DR
->getDecl();
471 if (isa
<VarDecl
>(D
) || isa
<BindingDecl
>(D
)) {
472 // Treat ++/-- as a kill.
473 observer
->observerKill(DR
);
478 LiveVariables::LivenessValues
479 LiveVariablesImpl::runOnBlock(const CFGBlock
*block
,
480 LiveVariables::LivenessValues val
,
481 LiveVariables::Observer
*obs
) {
483 TransferFunctions
TF(*this, val
, obs
, block
);
485 // Visit the terminator (if any).
486 if (const Stmt
*term
= block
->getTerminatorStmt())
487 TF
.Visit(const_cast<Stmt
*>(term
));
489 // Apply the transfer function for all Stmts in the block.
490 for (CFGBlock::const_reverse_iterator it
= block
->rbegin(),
491 ei
= block
->rend(); it
!= ei
; ++it
) {
492 const CFGElement
&elem
= *it
;
494 if (std::optional
<CFGAutomaticObjDtor
> Dtor
=
495 elem
.getAs
<CFGAutomaticObjDtor
>()) {
496 val
.liveDecls
= DSetFact
.add(val
.liveDecls
, Dtor
->getVarDecl());
500 if (!elem
.getAs
<CFGStmt
>())
503 const Stmt
*S
= elem
.castAs
<CFGStmt
>().getStmt();
504 TF
.Visit(const_cast<Stmt
*>(S
));
505 stmtsToLiveness
[S
] = val
;
510 void LiveVariables::runOnAllBlocks(LiveVariables::Observer
&obs
) {
511 const CFG
*cfg
= getImpl(impl
).analysisContext
.getCFG();
512 for (CFG::const_iterator it
= cfg
->begin(), ei
= cfg
->end(); it
!= ei
; ++it
)
513 getImpl(impl
).runOnBlock(*it
, getImpl(impl
).blocksEndToLiveness
[*it
], &obs
);
516 LiveVariables::LiveVariables(void *im
) : impl(im
) {}
518 LiveVariables::~LiveVariables() {
519 delete (LiveVariablesImpl
*) impl
;
522 std::unique_ptr
<LiveVariables
>
523 LiveVariables::computeLiveness(AnalysisDeclContext
&AC
, bool killAtAssign
) {
526 CFG
*cfg
= AC
.getCFG();
530 // The analysis currently has scalability issues for very large CFGs.
531 // Bail out if it looks too large.
532 if (cfg
->getNumBlockIDs() > 300000)
535 LiveVariablesImpl
*LV
= new LiveVariablesImpl(AC
, killAtAssign
);
537 // Construct the dataflow worklist. Enqueue the exit block as the
538 // start of the analysis.
539 BackwardDataflowWorklist
worklist(*cfg
, AC
);
540 llvm::BitVector
everAnalyzedBlock(cfg
->getNumBlockIDs());
542 // FIXME: we should enqueue using post order.
543 for (const CFGBlock
*B
: cfg
->nodes()) {
544 worklist
.enqueueBlock(B
);
547 while (const CFGBlock
*block
= worklist
.dequeue()) {
548 // Determine if the block's end value has changed. If not, we
549 // have nothing left to do for this block.
550 LivenessValues
&prevVal
= LV
->blocksEndToLiveness
[block
];
552 // Merge the values of all successor blocks.
554 for (CFGBlock::const_succ_iterator it
= block
->succ_begin(),
555 ei
= block
->succ_end(); it
!= ei
; ++it
) {
556 if (const CFGBlock
*succ
= *it
) {
557 val
= LV
->merge(val
, LV
->blocksBeginToLiveness
[succ
]);
561 if (!everAnalyzedBlock
[block
->getBlockID()])
562 everAnalyzedBlock
[block
->getBlockID()] = true;
563 else if (prevVal
.equals(val
))
568 // Update the dataflow value for the start of this block.
569 LV
->blocksBeginToLiveness
[block
] = LV
->runOnBlock(block
, val
);
571 // Enqueue the value to the predecessors.
572 worklist
.enqueuePredecessors(block
);
575 return std::unique_ptr
<LiveVariables
>(new LiveVariables(LV
));
578 void LiveVariables::dumpBlockLiveness(const SourceManager
&M
) {
579 getImpl(impl
).dumpBlockLiveness(M
);
582 void LiveVariablesImpl::dumpBlockLiveness(const SourceManager
&M
) {
583 std::vector
<const CFGBlock
*> vec
;
584 for (llvm::DenseMap
<const CFGBlock
*, LiveVariables::LivenessValues
>::iterator
585 it
= blocksEndToLiveness
.begin(), ei
= blocksEndToLiveness
.end();
587 vec
.push_back(it
->first
);
589 llvm::sort(vec
, [](const CFGBlock
*A
, const CFGBlock
*B
) {
590 return A
->getBlockID() < B
->getBlockID();
593 std::vector
<const VarDecl
*> declVec
;
595 for (std::vector
<const CFGBlock
*>::iterator
596 it
= vec
.begin(), ei
= vec
.end(); it
!= ei
; ++it
) {
597 llvm::errs() << "\n[ B" << (*it
)->getBlockID()
598 << " (live variables at block exit) ]\n";
600 LiveVariables::LivenessValues vals
= blocksEndToLiveness
[*it
];
603 for (llvm::ImmutableSet
<const VarDecl
*>::iterator si
=
604 vals
.liveDecls
.begin(),
605 se
= vals
.liveDecls
.end(); si
!= se
; ++si
) {
606 declVec
.push_back(*si
);
609 llvm::sort(declVec
, [](const Decl
*A
, const Decl
*B
) {
610 return A
->getBeginLoc() < B
->getBeginLoc();
613 for (std::vector
<const VarDecl
*>::iterator di
= declVec
.begin(),
614 de
= declVec
.end(); di
!= de
; ++di
) {
615 llvm::errs() << " " << (*di
)->getDeclName().getAsString()
617 (*di
)->getLocation().print(llvm::errs(), M
);
618 llvm::errs() << ">\n";
621 llvm::errs() << "\n";
624 void LiveVariables::dumpExprLiveness(const SourceManager
&M
) {
625 getImpl(impl
).dumpExprLiveness(M
);
628 void LiveVariablesImpl::dumpExprLiveness(const SourceManager
&M
) {
629 // Don't iterate over blockEndsToLiveness directly because it's not sorted.
630 for (const CFGBlock
*B
: *analysisContext
.getCFG()) {
632 llvm::errs() << "\n[ B" << B
->getBlockID()
633 << " (live expressions at block exit) ]\n";
634 for (const Expr
*E
: blocksEndToLiveness
[B
].liveExprs
) {
635 llvm::errs() << "\n";
638 llvm::errs() << "\n";
642 const void *LiveVariables::getTag() { static int x
; return &x
; }
643 const void *RelaxedLiveVariables::getTag() { static int x
; return &x
; }