clang 24.0.0git
LiveVariables.cpp
Go to the documentation of this file.
1//=- LiveVariables.cpp - Live Variable Analysis for Source CFGs ----------*-==//
2//
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
6//
7//===----------------------------------------------------------------------===//
8//
9// This file implements Live Variables analysis for source-level CFGs.
10//
11//===----------------------------------------------------------------------===//
12
14#include "clang/AST/Stmt.h"
17#include "clang/Analysis/CFG.h"
20#include "llvm/ADT/DenseMap.h"
21#include "llvm/ADT/DenseSet.h"
22#include "llvm/ADT/STLExtras.h"
23#include "llvm/Support/raw_ostream.h"
24#include <optional>
25#include <vector>
26
27using namespace clang;
28
29namespace {
30class LiveVariablesImpl {
31public:
32 template <typename T> using SetTy = LiveVariables::SetTy<T>;
33
34 AnalysisDeclContext &analysisContext;
35 SetTy<const Expr *>::Factory ESetFact;
36 SetTy<const VarDecl *>::Factory DSetFact;
37 SetTy<const BindingDecl *>::Factory BSetFact;
38 llvm::DenseMap<const CFGBlock *, LiveVariables::LivenessValues> blocksEndToLiveness;
39 llvm::DenseMap<const CFGBlock *, LiveVariables::LivenessValues> blocksBeginToLiveness;
40 llvm::DenseMap<const Stmt *, LiveVariables::LivenessValues> stmtsToLiveness;
41 llvm::DenseSet<const DeclRefExpr *> inAssignment;
42 const bool killAtAssign;
43
44 LiveVariables::LivenessValues
45 merge(LiveVariables::LivenessValues valsA,
46 LiveVariables::LivenessValues valsB);
47
48 LiveVariables::LivenessValues
49 runOnBlock(const CFGBlock *block, LiveVariables::LivenessValues val,
50 LiveVariables::Observer *obs = nullptr);
51
52 void dumpBlockLiveness(const SourceManager& M);
53 void dumpExprLiveness(const SourceManager& M);
54
55 LiveVariablesImpl(AnalysisDeclContext &ac, bool KillAtAssign)
56 : analysisContext(ac), killAtAssign(KillAtAssign) {}
57};
58} // namespace
59
60static LiveVariablesImpl &getImpl(void *x) {
61 return *((LiveVariablesImpl *) x);
62}
63
64//===----------------------------------------------------------------------===//
65// Operations and queries on LivenessValues.
66//===----------------------------------------------------------------------===//
67
69 return liveExprs.contains(E);
70}
71
73 if (const auto *DD = dyn_cast<DecompositionDecl>(D)) {
74 // Note: the only known case this condition is necessary, is when a bindig
75 // to a tuple-like structure is created. The HoldingVar initializers have a
76 // DeclRefExpr to the DecompositionDecl.
77 if (liveDecls.contains(DD))
78 return true;
79
80 for (const BindingDecl *BD : DD->bindings()) {
81 if (liveBindings.contains(BD))
82 return true;
83 }
84 return false;
85 }
86 return liveDecls.contains(D);
87}
88
89void LiveVariables::Observer::anchor() { }
90
92LiveVariablesImpl::merge(LiveVariables::LivenessValues valsA,
94 // Liveness at a merge point is the union of the successors' live sets. These
95 // sets are not canonicalized; LivenessValues::operator== compares them
96 // structurally.
98 ESetFact.unionSets(valsA.liveExprs, valsB.liveExprs),
99 DSetFact.unionSets(valsA.liveDecls, valsB.liveDecls),
100 BSetFact.unionSets(valsA.liveBindings, valsB.liveBindings));
101}
102
104 return liveExprs == V.liveExprs && liveDecls == V.liveDecls &&
105 liveBindings == V.liveBindings;
106}
107
108//===----------------------------------------------------------------------===//
109// Query methods.
110//===----------------------------------------------------------------------===//
111
112static bool isAlwaysAlive(const VarDecl *D) {
113 return D->hasGlobalStorage();
114}
115
116bool LiveVariables::isLive(const CFGBlock *B, const VarDecl *D) {
117 return isAlwaysAlive(D) || getImpl(impl).blocksEndToLiveness[B].isLive(D);
118}
119
120bool LiveVariables::isLive(const Stmt *S, const VarDecl *D) {
121 return isAlwaysAlive(D) || getImpl(impl).stmtsToLiveness[S].isLive(D);
122}
123
124bool LiveVariables::isLive(const Stmt *Loc, const Expr *Val) {
125 return getImpl(impl).stmtsToLiveness[Loc].isLive(Val);
126}
127
128//===----------------------------------------------------------------------===//
129// Dataflow computation.
130//===----------------------------------------------------------------------===//
131
132namespace {
133class TransferFunctions : public StmtVisitor<TransferFunctions> {
134 LiveVariablesImpl &LV;
136 LiveVariables::Observer *observer;
137 const CFGBlock *currentBlock;
138public:
139 TransferFunctions(LiveVariablesImpl &im,
141 LiveVariables::Observer *Observer,
142 const CFGBlock *CurrentBlock)
143 : LV(im), val(Val), observer(Observer), currentBlock(CurrentBlock) {}
144
145 void VisitBinaryOperator(BinaryOperator *BO);
146 void VisitBlockExpr(BlockExpr *BE);
147 void VisitDeclRefExpr(DeclRefExpr *DR);
148 void VisitDeclStmt(DeclStmt *DS);
149 void VisitObjCForCollectionStmt(ObjCForCollectionStmt *OS);
150 void VisitUnaryExprOrTypeTraitExpr(UnaryExprOrTypeTraitExpr *UE);
151 void Visit(Stmt *S);
152};
153} // namespace
154
156 const Type *ty = Ty.getTypePtr();
157 while (const ArrayType *VT = dyn_cast<ArrayType>(ty)) {
158 if (const VariableArrayType *VAT = dyn_cast<VariableArrayType>(VT))
159 if (VAT->getSizeExpr())
160 return VAT;
161
162 ty = VT->getElementType().getTypePtr();
163 }
164
165 return nullptr;
166}
167
168static const Expr *LookThroughExpr(const Expr *E) {
169 while (E) {
170 E = E->IgnoreParens();
171 if (const FullExpr *FE = dyn_cast<FullExpr>(E)) {
172 E = FE->getSubExpr();
173 continue;
174 }
175 if (const OpaqueValueExpr *OVE = dyn_cast<OpaqueValueExpr>(E)) {
176 E = OVE->getSourceExpr();
177 continue;
178 }
179 break;
180 }
181 return E;
182}
183
189
190/// Add as a live expression all individual conditions in a logical expression.
191/// For example, for the expression:
192/// "(a < b) || (c && d && ((e || f) != (g && h)))"
193/// the following expressions will be added as live:
194/// "a < b", "c", "d", "((e || f) != (g && h))"
195static void
198 const Expr *Cond) {
199 AddLiveExpr(Set, F, Cond);
200 if (auto const *BO = dyn_cast<BinaryOperator>(Cond->IgnoreParens());
201 BO && BO->isLogicalOp()) {
202 AddAllConditionalTerms(Set, F, BO->getLHS());
203 AddAllConditionalTerms(Set, F, BO->getRHS());
204 }
205}
206
207void TransferFunctions::Visit(Stmt *S) {
208 if (observer)
209 observer->observeStmt(S, currentBlock, val);
210
212
213 if (const auto *E = dyn_cast<Expr>(S)) {
214 val.liveExprs = LV.ESetFact.remove(val.liveExprs, E);
215 }
216
217 // Mark all children expressions live.
218 // The "normal" case will be handled by iterating over 'S->children()' but
219 // before that we need this big 'switch' to handle the statement kinds where
220 // 'S->children()' isn't the exactly equal to the set of child expressions
221 // that we want to keep alive. (In some cases we need to skip some of the
222 // children, in other cases there are unusual child expressions that do not
223 // appear in 'S->children()'.)
224
225 switch (S->getStmtClass()) {
226 default:
227 break;
228 case Stmt::StmtExprClass: {
229 // For statement expressions, look through the compound statement.
230 S = cast<StmtExpr>(S)->getSubStmt();
231 break;
232 }
233 case Stmt::CXXMemberCallExprClass: {
234 // Include the implicit "this" pointer as being live.
235 CXXMemberCallExpr *CE = cast<CXXMemberCallExpr>(S);
236 if (Expr *ImplicitObj = CE->getImplicitObjectArgument()) {
237 AddLiveExpr(val.liveExprs, LV.ESetFact, ImplicitObj);
238 }
239 break;
240 }
241 case Stmt::ObjCMessageExprClass: {
242 // In calls to super, include the implicit "self" pointer as being live.
243 ObjCMessageExpr *CE = cast<ObjCMessageExpr>(S);
245 val.liveDecls = LV.DSetFact.add(val.liveDecls,
246 LV.analysisContext.getSelfDecl());
247 break;
248 }
249 case Stmt::DeclStmtClass: {
250 const DeclStmt *DS = cast<DeclStmt>(S);
251 if (const VarDecl *VD = dyn_cast<VarDecl>(DS->getSingleDecl())) {
252 for (const VariableArrayType* VA = FindVA(VD->getType());
253 VA != nullptr; VA = FindVA(VA->getElementType())) {
254 AddLiveExpr(val.liveExprs, LV.ESetFact, VA->getSizeExpr());
255 }
256 }
257 break;
258 }
259 case Stmt::AttributedStmtClass: {
260 // In an attributed statement, include the assumptions of the
261 // [[assume(...)]] attributes as being live.
262 AttributedStmt *AS = cast<AttributedStmt>(S);
263 for (const auto *Attr : getSpecificAttrs<CXXAssumeAttr>(AS->getAttrs())) {
264 AddLiveExpr(val.liveExprs, LV.ESetFact, Attr->getAssumption());
265 }
266 break;
267 }
268 case Stmt::PseudoObjectExprClass: {
269 // A pseudo-object operation only directly consumes its result
270 // expression.
271 Expr *child = cast<PseudoObjectExpr>(S)->getResultExpr();
272 if (!child) return;
273 if (OpaqueValueExpr *OV = dyn_cast<OpaqueValueExpr>(child))
274 child = OV->getSourceExpr();
275 child = child->IgnoreParens();
276 val.liveExprs = LV.ESetFact.add(val.liveExprs, child);
277 return;
278 }
279
280 // FIXME: These cases eventually shouldn't be needed.
281 case Stmt::ExprWithCleanupsClass: {
282 S = cast<ExprWithCleanups>(S)->getSubExpr();
283 break;
284 }
285 case Stmt::CXXBindTemporaryExprClass: {
286 S = cast<CXXBindTemporaryExpr>(S)->getSubExpr();
287 break;
288 }
289 case Stmt::UnaryExprOrTypeTraitExprClass: {
290 // No need to unconditionally visit subexpressions.
291 return;
292 }
293 case Stmt::IfStmtClass: {
294 // If one of the branches is an expression rather than a compound
295 // statement, it will be bad if we mark it as live at the terminator
296 // of the if-statement (i.e., immediately after the condition expression).
297 AddLiveExpr(val.liveExprs, LV.ESetFact, cast<IfStmt>(S)->getCond());
298 return;
299 }
300 case Stmt::WhileStmtClass: {
301 // If the loop body is an expression rather than a compound statement,
302 // it will be bad if we mark it as live at the terminator of the loop
303 // (i.e., immediately after the condition expression).
304 AddLiveExpr(val.liveExprs, LV.ESetFact, cast<WhileStmt>(S)->getCond());
305 return;
306 }
307 case Stmt::DoStmtClass: {
308 // If the loop body is an expression rather than a compound statement,
309 // it will be bad if we mark it as live at the terminator of the loop
310 // (i.e., immediately after the condition expression).
311 AddLiveExpr(val.liveExprs, LV.ESetFact, cast<DoStmt>(S)->getCond());
312 return;
313 }
314 case Stmt::ForStmtClass: {
315 // If the loop body is an expression rather than a compound statement,
316 // it will be bad if we mark it as live at the terminator of the loop
317 // (i.e., immediately after the condition expression).
318 AddLiveExpr(val.liveExprs, LV.ESetFact, cast<ForStmt>(S)->getCond());
319 return;
320 }
321 case Stmt::ConditionalOperatorClass: {
322 // Keep not only direct children alive, but also all the short-circuited
323 // parts of the condition. Short-circuiting evaluation may cause the
324 // conditional operator evaluation to skip the evaluation of the entire
325 // condtion expression, so the value of the entire condition expression is
326 // never computed.
327 //
328 // This makes a difference when we compare exploded nodes coming from true
329 // and false expressions with no side effects: the only difference in the
330 // state is the value of (part of) the condition.
331 //
332 // BinaryConditionalOperatorClass ('x ?: y') is not affected because it
333 // explicitly calculates the value of the entire condition expression (to
334 // possibly use as a value for the "true expr") even if it is
335 // short-circuited.
336 auto const *CO = cast<ConditionalOperator>(S);
337 AddAllConditionalTerms(val.liveExprs, LV.ESetFact, CO->getCond());
338 AddLiveExpr(val.liveExprs, LV.ESetFact, CO->getTrueExpr());
339 AddLiveExpr(val.liveExprs, LV.ESetFact, CO->getFalseExpr());
340 return;
341 }
342 case Stmt::BinaryOperatorClass: {
343 auto const *BO = cast<BinaryOperator>(S);
344 if (BO->isLogicalOp()) {
345 AddAllConditionalTerms(val.liveExprs, LV.ESetFact, BO->getLHS());
346 AddAllConditionalTerms(val.liveExprs, LV.ESetFact, BO->getRHS());
347 return;
348 }
349 break;
350 }
351 }
352
353 // Mark all child expressions live -- "normal" case.
354 for (Stmt *Child : S->children()) {
355 if (const auto *E = dyn_cast_or_null<Expr>(Child))
356 AddLiveExpr(val.liveExprs, LV.ESetFact, E);
357 }
358}
359
360static bool writeShouldKill(const VarDecl *VD) {
361 return VD && !VD->getType()->isReferenceType() &&
362 !isAlwaysAlive(VD);
363}
364
365void TransferFunctions::VisitBinaryOperator(BinaryOperator *B) {
366 if (LV.killAtAssign && B->getOpcode() == BO_Assign) {
367 if (const auto *DR = dyn_cast<DeclRefExpr>(B->getLHS()->IgnoreParens())) {
368 LV.inAssignment.insert(DR);
369 }
370 }
371 if (B->isAssignmentOp()) {
372 if (!LV.killAtAssign)
373 return;
374
375 // Assigning to a variable?
376 Expr *LHS = B->getLHS()->IgnoreParens();
377
378 if (DeclRefExpr *DR = dyn_cast<DeclRefExpr>(LHS)) {
379 const Decl* D = DR->getDecl();
380 bool Killed = false;
381
382 if (const BindingDecl* BD = dyn_cast<BindingDecl>(D)) {
383 Killed = !BD->getType()->isReferenceType();
384 if (Killed) {
385 if (const auto *HV = BD->getHoldingVar())
386 val.liveDecls = LV.DSetFact.remove(val.liveDecls, HV);
387
388 val.liveBindings = LV.BSetFact.remove(val.liveBindings, BD);
389 }
390 } else if (const auto *VD = dyn_cast<VarDecl>(D)) {
391 Killed = writeShouldKill(VD);
392 if (Killed)
393 val.liveDecls = LV.DSetFact.remove(val.liveDecls, VD);
394 }
395 }
396 }
397}
398
399void TransferFunctions::VisitBlockExpr(BlockExpr *BE) {
400 for (const VarDecl *VD :
401 LV.analysisContext.getReferencedBlockVars(BE->getBlockDecl())) {
402 if (isAlwaysAlive(VD))
403 continue;
404 val.liveDecls = LV.DSetFact.add(val.liveDecls, VD);
405 }
406}
407
408void TransferFunctions::VisitDeclRefExpr(DeclRefExpr *DR) {
409 const Decl* D = DR->getDecl();
410 bool InAssignment = LV.inAssignment.contains(DR);
411 if (const auto *BD = dyn_cast<BindingDecl>(D)) {
412 if (!InAssignment) {
413 if (const auto *HV = BD->getHoldingVar())
414 val.liveDecls = LV.DSetFact.add(val.liveDecls, HV);
415
416 val.liveBindings = LV.BSetFact.add(val.liveBindings, BD);
417 }
418 } else if (const auto *VD = dyn_cast<VarDecl>(D)) {
419 if (!InAssignment && !isAlwaysAlive(VD))
420 val.liveDecls = LV.DSetFact.add(val.liveDecls, VD);
421 }
422}
423
424void TransferFunctions::VisitDeclStmt(DeclStmt *DS) {
425 for (const auto *DI : DS->decls()) {
426 if (const auto *DD = dyn_cast<DecompositionDecl>(DI)) {
427 for (const auto *BD : DD->bindings()) {
428 if (const auto *HV = BD->getHoldingVar())
429 val.liveDecls = LV.DSetFact.remove(val.liveDecls, HV);
430
431 val.liveBindings = LV.BSetFact.remove(val.liveBindings, BD);
432 }
433
434 // When a bindig to a tuple-like structure is created, the HoldingVar
435 // initializers have a DeclRefExpr to the DecompositionDecl.
436 val.liveDecls = LV.DSetFact.remove(val.liveDecls, DD);
437 } else if (const auto *VD = dyn_cast<VarDecl>(DI)) {
438 if (!isAlwaysAlive(VD))
439 val.liveDecls = LV.DSetFact.remove(val.liveDecls, VD);
440 }
441 }
442}
443
444void TransferFunctions::VisitObjCForCollectionStmt(ObjCForCollectionStmt *OS) {
445 // Kill the iteration variable.
446 DeclRefExpr *DR = nullptr;
447 const VarDecl *VD = nullptr;
448
449 Stmt *element = OS->getElement();
450 if (DeclStmt *DS = dyn_cast<DeclStmt>(element)) {
451 VD = cast<VarDecl>(DS->getSingleDecl());
452 }
453 else if ((DR = dyn_cast<DeclRefExpr>(cast<Expr>(element)->IgnoreParens()))) {
454 VD = cast<VarDecl>(DR->getDecl());
455 }
456
457 if (VD) {
458 val.liveDecls = LV.DSetFact.remove(val.liveDecls, VD);
459 }
460}
461
462void TransferFunctions::
463VisitUnaryExprOrTypeTraitExpr(UnaryExprOrTypeTraitExpr *UE)
464{
465 // While sizeof(var) doesn't technically extend the liveness of 'var', it
466 // does extent the liveness of metadata if 'var' is a VariableArrayType.
467 // We handle that special case here.
468 if (UE->getKind() != UETT_SizeOf || UE->isArgumentType())
469 return;
470
471 const Expr *subEx = UE->getArgumentExpr();
472 if (subEx->getType()->isVariableArrayType()) {
473 assert(subEx->isLValue());
474 val.liveExprs = LV.ESetFact.add(val.liveExprs, subEx->IgnoreParens());
475 }
476}
477
478LiveVariables::LivenessValues
479LiveVariablesImpl::runOnBlock(const CFGBlock *block,
480 LiveVariables::LivenessValues val,
481 LiveVariables::Observer *obs) {
482
483 TransferFunctions TF(*this, val, obs, block);
484
485 // Visit the terminator (if any).
486 if (const Stmt *term = block->getTerminatorStmt())
487 TF.Visit(const_cast<Stmt*>(term));
488
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;
493
494 if (std::optional<CFGAutomaticObjDtor> Dtor =
495 elem.getAs<CFGAutomaticObjDtor>()) {
496 val.liveDecls = DSetFact.add(val.liveDecls, Dtor->getVarDecl());
497 continue;
498 }
499
500 if (!elem.getAs<CFGStmt>())
501 continue;
502
503 const Stmt *S = elem.castAs<CFGStmt>().getStmt();
504 TF.Visit(const_cast<Stmt*>(S));
505 stmtsToLiveness[S] = val;
506 }
507 return val;
508}
509
511 const CFG *cfg = getImpl(impl).analysisContext.getCFG();
512 for (CFGBlock *B : *cfg)
513 getImpl(impl).runOnBlock(B, getImpl(impl).blocksEndToLiveness[B], &obs);
514}
515
516LiveVariables::LiveVariables(void *im) : impl(im) {}
517
519 delete (LiveVariablesImpl*) impl;
520}
521
522std::unique_ptr<LiveVariables>
524
525 // No CFG? Bail out.
526 CFG *cfg = AC.getCFG();
527 if (!cfg)
528 return nullptr;
529
530 // The analysis currently has scalability issues for very large CFGs.
531 // Bail out if it looks too large.
532 if (cfg->getNumBlockIDs() > 300000)
533 return nullptr;
534
535 LiveVariablesImpl *LV = new LiveVariablesImpl(AC, killAtAssign);
536
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());
541
542 // FIXME: we should enqueue using post order.
543 for (const CFGBlock *B : cfg->nodes()) {
544 worklist.enqueueBlock(B);
545 }
546
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];
551
552 // Merge the values of all successor blocks.
553 LivenessValues val;
554 for (const CFGBlock *succ : block->succs()) {
555 if (succ) {
556 val = LV->merge(val, LV->blocksBeginToLiveness[succ]);
557 }
558 }
559
560 if (!everAnalyzedBlock[block->getBlockID()])
561 everAnalyzedBlock[block->getBlockID()] = true;
562 else if (prevVal == val)
563 continue;
564
565 prevVal = val;
566
567 // Update the dataflow value for the start of this block.
568 LV->blocksBeginToLiveness[block] = LV->runOnBlock(block, val);
569
570 // Enqueue the value to the predecessors.
571 worklist.enqueuePredecessors(block);
572 }
573
574 return std::unique_ptr<LiveVariables>(new LiveVariables(LV));
575}
576
578 getImpl(impl).dumpBlockLiveness(M);
579}
580
581void LiveVariablesImpl::dumpBlockLiveness(const SourceManager &M) {
582 std::vector<const CFGBlock *> vec;
583 vec.reserve(blocksEndToLiveness.size());
584 llvm::append_range(vec, llvm::make_first_range(blocksEndToLiveness));
585 llvm::sort(vec, [](const CFGBlock *A, const CFGBlock *B) {
586 return A->getBlockID() < B->getBlockID();
587 });
588
589 std::vector<const VarDecl*> declVec;
590
591 for (const CFGBlock *block : vec) {
592 llvm::errs() << "\n[ B" << block->getBlockID()
593 << " (live variables at block exit) ]\n";
594 declVec.clear();
595 llvm::append_range(declVec, blocksEndToLiveness[block].liveDecls);
596 llvm::sort(declVec, [](const Decl *A, const Decl *B) {
597 return A->getBeginLoc() < B->getBeginLoc();
598 });
599
600 for (const VarDecl *VD : declVec) {
601 llvm::errs() << " " << VD->getDeclName().getAsString() << " <";
602 VD->getLocation().print(llvm::errs(), M);
603 llvm::errs() << ">\n";
604 }
605 }
606 llvm::errs() << "\n";
607}
608
610 getImpl(impl).dumpExprLiveness(M);
611}
612
613void LiveVariablesImpl::dumpExprLiveness(const SourceManager &M) {
614 const ASTContext &Ctx = analysisContext.getASTContext();
615 auto ByIDs = [&Ctx](const Expr *L, const Expr *R) {
616 return L->getID(Ctx) < R->getID(Ctx);
617 };
618
619 // Don't iterate over blockEndsToLiveness directly because it's not sorted.
620 for (const CFGBlock *B : *analysisContext.getCFG()) {
621 llvm::errs() << "\n[ B" << B->getBlockID()
622 << " (live expressions at block exit) ]\n";
623 std::vector<const Expr *> LiveExprs;
624 llvm::append_range(LiveExprs, blocksEndToLiveness[B].liveExprs);
625 llvm::sort(LiveExprs, ByIDs);
626 for (const Expr *E : LiveExprs) {
627 llvm::errs() << "\n";
628 E->dump();
629 }
630 llvm::errs() << "\n";
631 }
632}
633
634const void *LiveVariables::getTag() { static int x; return &x; }
635const void *RelaxedLiveVariables::getTag() { static int x; return &x; }
#define V(N, I)
This file defines AnalysisDeclContext, a class that manages the analysis context data for context sen...
static const VariableArrayType * FindVA(const Type *t)
Definition CFG.cpp:1514
static bool writeShouldKill(const VarDecl *VD)
static void AddLiveExpr(LiveVariables::SetTy< const Expr * > &Set, LiveVariables::SetTy< const Expr * >::Factory &F, const Expr *E)
static LiveVariablesImpl & getImpl(void *x)
static const Expr * LookThroughExpr(const Expr *E)
static void AddAllConditionalTerms(LiveVariables::SetTy< const Expr * > &Set, LiveVariables::SetTy< const Expr * >::Factory &F, const Expr *Cond)
Add as a live expression all individual conditions in a logical expression.
static bool isAlwaysAlive(const VarDecl *D)
Defines the SourceManager interface.
static bool runOnBlock(const CFGBlock *block, const CFG &cfg, AnalysisDeclContext &ac, CFGBlockValues &vals, const ClassifyRefs &classification, llvm::BitVector &wasAnalyzed, UninitVariablesHandler &handler)
Holds long-lived AST nodes (such as types and decls) that can be referred to throughout the semantic ...
Definition ASTContext.h:245
AnalysisDeclContext contains the context data for the function, method or block under analysis.
Represents an array type, per C99 6.7.5.2 - Array Declarators.
Definition TypeBase.h:3820
ArrayRef< const Attr * > getAttrs() const
Definition Stmt.h:2247
A builtin binary operation expression such as "x + y" or "x <= y".
Definition Expr.h:4086
Expr * getLHS() const
Definition Expr.h:4136
static bool isAssignmentOp(Opcode Opc)
Definition Expr.h:4222
Opcode getOpcode() const
Definition Expr.h:4131
A binding in a decomposition declaration.
Definition DeclCXX.h:4215
BlockExpr - Adaptor class for mixing a BlockDecl with expressions.
Definition Expr.h:6726
const BlockDecl * getBlockDecl() const
Definition Expr.h:6738
Represents a single basic block in a source-level CFG.
Definition CFG.h:652
reverse_iterator rbegin()
Definition CFG.h:971
reverse_iterator rend()
Definition CFG.h:972
ElementList::const_reverse_iterator const_reverse_iterator
Definition CFG.h:959
succ_range succs()
Definition CFG.h:1056
Stmt * getTerminatorStmt()
Definition CFG.h:1148
unsigned getBlockID() const
Definition CFG.h:1178
T castAs() const
Convert to the specified CFGElement type, asserting that this CFGElement is of the desired type.
Definition CFG.h:103
std::optional< T > getAs() const
Convert to the specified CFGElement type, returning std::nullopt if this CFGElement is not of the des...
Definition CFG.h:113
Represents a source-level, intra-procedural CFG that represents the control-flow of a Stmt.
Definition CFG.h:1295
unsigned getNumBlockIDs() const
Returns the total number of BlockIDs allocated (which start at 0).
Definition CFG.h:1488
llvm::iterator_range< iterator > nodes()
Definition CFG.h:1389
Expr * getImplicitObjectArgument() const
Retrieve the implicit object argument for the member call.
Definition ExprCXX.cpp:754
void enqueueBlock(const CFGBlock *Block)
A reference to a declared variable, function, enum, etc.
Definition Expr.h:1294
ValueDecl * getDecl()
Definition Expr.h:1362
DeclStmt - Adaptor class for mixing declarations with statements and expressions.
Definition Stmt.h:1643
decl_range decls()
Definition Stmt.h:1691
const Decl * getSingleDecl() const
Definition Stmt.h:1658
Decl - This represents one declaration (or definition), e.g.
Definition DeclBase.h:86
SourceLocation getLocation() const
Definition DeclBase.h:447
SourceLocation getBeginLoc() const LLVM_READONLY
Definition DeclBase.h:439
std::string getAsString() const
Retrieve the human-readable string for this name.
This represents one expression.
Definition Expr.h:113
Expr * IgnoreParens() LLVM_READONLY
Skip past any parentheses which might surround this expression until reaching a fixed point.
Definition Expr.cpp:3125
bool isLValue() const
isLValue - True if this expression is an "l-value" according to the rules of the current language.
Definition Expr.h:285
QualType getType() const
Definition Expr.h:145
FullExpr - Represents a "full-expression" node.
Definition Expr.h:1073
bool operator==(const LivenessValues &V) const
SetTy< const BindingDecl * > liveBindings
bool isLive(const Expr *E) const
SetTy< const VarDecl * > liveDecls
llvm::ImmutableSet< T, llvm::ImutContainerInfo< T >, false > SetTy
void dumpExprLiveness(const SourceManager &M)
Print to stderr the expression liveness information associated with each basic block.
void dumpBlockLiveness(const SourceManager &M)
Print to stderr the variable liveness information associated with each basic block.
void runOnAllBlocks(Observer &obs)
static const void * getTag()
bool isLive(const CFGBlock *B, const VarDecl *D)
Return true if a variable is live at the end of a specified block.
static std::unique_ptr< LiveVariables > computeLiveness(AnalysisDeclContext &analysisContext, bool killAtAssign)
Compute the liveness information for a given CFG.
DeclarationName getDeclName() const
Get the actual, stored name of the declaration, which may be a special name.
Definition Decl.h:341
Represents Objective-C's collection statement.
Definition StmtObjC.h:23
@ SuperInstance
The receiver is the instance of the superclass object.
Definition ExprObjC.h:986
ReceiverKind getReceiverKind() const
Determine the kind of receiver that this message is being sent to.
Definition ExprObjC.h:1261
OpaqueValueExpr - An expression referring to an opaque object of a fixed type and value class.
Definition Expr.h:1202
A (possibly-)qualified type.
Definition TypeBase.h:938
const Type * getTypePtr() const
Retrieves a pointer to the underlying (unqualified) type.
Definition TypeBase.h:8446
static const void * getTag()
void print(raw_ostream &OS, const SourceManager &SM) const
This class handles loading and caching of source files into memory.
StmtVisitor - This class implements a simple visitor for Stmt subclasses.
Stmt - This represents one statement.
Definition Stmt.h:85
child_range children()
Definition Stmt.cpp:304
StmtClass getStmtClass() const
Definition Stmt.h:1505
int64_t getID(const ASTContext &Context) const
Definition Stmt.cpp:379
The base class of the type hierarchy.
Definition TypeBase.h:1879
bool isReferenceType() const
Definition TypeBase.h:8707
bool isVariableArrayType() const
Definition TypeBase.h:8794
UnaryExprOrTypeTraitExpr - expression with either a type or (unevaluated) expression operand.
Definition Expr.h:2673
UnaryExprOrTypeTrait getKind() const
Definition Expr.h:2705
QualType getType() const
Definition Decl.h:724
Represents a variable declaration or definition.
Definition Decl.h:933
bool hasGlobalStorage() const
Returns true for all variables that do not have local storage.
Definition Decl.h:1248
Represents a C array with a specified size that is not an integer-constant-expression.
Definition TypeBase.h:4064
@ OS
Indicates that the tracking object is a descendant of a referenced-counted OSObject,...
std::variant< struct RequiresDecl, struct HeaderDecl, struct UmbrellaDirDecl, struct ModuleDecl, struct ExcludeDecl, struct ExportDecl, struct ExportAsDecl, struct ExternModuleDecl, struct UseDecl, struct LinkDecl, struct ConfigMacrosDecl, struct ConflictDecl > Decl
All declarations that can appear in a module declaration.
RangeSelector merge(RangeSelector First, RangeSelector Second)
Selects the merge of the two ranges, i.e.
Top level wrappers for InstallAPI frontend operations.
auto getSpecificAttrs(const Container &container)
U cast(CodeGen::Address addr)
Definition Address.h:327
A worklist implementation for backward dataflow analysis.
void enqueuePredecessors(const CFGBlock *Block)