1//===- Facts.cpp - Lifetime Analysis Facts Implementation -------*- C++ -*-===//
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#include "clang/Analysis/Analyses/LifetimeSafety/Facts.h"
10#include "clang/AST/Decl.h"
11#include "clang/Analysis/Analyses/PostOrderCFGView.h"
12
13namespace clang::lifetimes::internal {
14
15void Fact::dump(llvm::raw_ostream &OS, const LoanManager &,
16 const OriginManager &) const {
17 OS << "Fact (Kind: " << static_cast<int>(K) << ")\n";
18}
19
20void IssueFact::dump(llvm::raw_ostream &OS, const LoanManager &LM,
21 const OriginManager &OM) const {
22 OS << "Issue (";
23 LM.getLoan(ID: getLoanID())->dump(OS);
24 OS << ", ToOrigin: ";
25 OM.dump(OID: getOriginID(), OS);
26 OS << ")\n";
27}
28
29void ExpireFact::dump(llvm::raw_ostream &OS, const LoanManager &LM,
30 const OriginManager &) const {
31 OS << "Expire (";
32 LM.getLoan(ID: getLoanID())->dump(OS);
33 OS << ")\n";
34}
35
36void OriginFlowFact::dump(llvm::raw_ostream &OS, const LoanManager &,
37 const OriginManager &OM) const {
38 OS << "OriginFlow: \n";
39 OS << "\tDest: ";
40 OM.dump(OID: getDestOriginID(), OS);
41 OS << "\n";
42 OS << "\tSrc: ";
43 OM.dump(OID: getSrcOriginID(), OS);
44 OS << (getKillDest() ? "" : ", Merge");
45 OS << "\n";
46}
47
48void ReturnEscapeFact::dump(llvm::raw_ostream &OS, const LoanManager &,
49 const OriginManager &OM) const {
50 OS << "OriginEscapes (";
51 OM.dump(OID: getEscapedOriginID(), OS);
52 OS << ", via Return)\n";
53}
54
55void FieldEscapeFact::dump(llvm::raw_ostream &OS, const LoanManager &,
56 const OriginManager &OM) const {
57 OS << "OriginEscapes (";
58 OM.dump(OID: getEscapedOriginID(), OS);
59 OS << ", via Field)\n";
60}
61
62void UseFact::dump(llvm::raw_ostream &OS, const LoanManager &,
63 const OriginManager &OM) const {
64 OS << "Use (";
65 size_t NumUsedOrigins = getUsedOrigins()->getLength();
66 size_t I = 0;
67 for (const OriginList *Cur = getUsedOrigins(); Cur;
68 Cur = Cur->peelOuterOrigin(), ++I) {
69 OM.dump(OID: Cur->getOuterOriginID(), OS);
70 if (I < NumUsedOrigins - 1)
71 OS << ", ";
72 }
73 OS << ", " << (isWritten() ? "Write" : "Read") << ")\n";
74}
75
76void TestPointFact::dump(llvm::raw_ostream &OS, const LoanManager &,
77 const OriginManager &) const {
78 OS << "TestPoint (Annotation: \"" << getAnnotation() << "\")\n";
79}
80
81llvm::StringMap<ProgramPoint> FactManager::getTestPoints() const {
82 llvm::StringMap<ProgramPoint> AnnotationToPointMap;
83 for (const auto &BlockFacts : BlockToFacts) {
84 for (const Fact *F : BlockFacts) {
85 if (const auto *TPF = F->getAs<TestPointFact>()) {
86 StringRef PointName = TPF->getAnnotation();
87 assert(!AnnotationToPointMap.contains(PointName) &&
88 "more than one test points with the same name");
89 AnnotationToPointMap[PointName] = F;
90 }
91 }
92 }
93 return AnnotationToPointMap;
94}
95
96void FactManager::dump(const CFG &Cfg, AnalysisDeclContext &AC) const {
97 llvm::dbgs() << "==========================================\n";
98 llvm::dbgs() << " Lifetime Analysis Facts:\n";
99 llvm::dbgs() << "==========================================\n";
100 if (const Decl *D = AC.getDecl())
101 if (const auto *ND = dyn_cast<NamedDecl>(Val: D))
102 llvm::dbgs() << "Function: " << ND->getQualifiedNameAsString() << "\n";
103 // Print blocks in the order as they appear in code for a stable ordering.
104 for (const CFGBlock *B : *AC.getAnalysis<PostOrderCFGView>()) {
105 llvm::dbgs() << " Block B" << B->getBlockID() << ":\n";
106 for (const Fact *F : getFacts(B)) {
107 llvm::dbgs() << " ";
108 F->dump(OS&: llvm::dbgs(), LoanMgr, OriginMgr);
109 }
110 llvm::dbgs() << " End of Block\n";
111 }
112}
113
114llvm::ArrayRef<const Fact *>
115FactManager::getBlockContaining(ProgramPoint P) const {
116 for (const auto &BlockToFactsVec : BlockToFacts) {
117 for (const Fact *F : BlockToFactsVec)
118 if (F == P)
119 return BlockToFactsVec;
120 }
121 return {};
122}
123
124} // namespace clang::lifetimes::internal
125