1b8b9af2aSEugene Zelenko //===- SymbolManager.h - Management of Symbolic Values --------------------===//
2fa0734ecSArgyrios Kyrtzidis //
32946cd70SChandler Carruth // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
42946cd70SChandler Carruth // See https://llvm.org/LICENSE.txt for license information.
52946cd70SChandler Carruth // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6fa0734ecSArgyrios Kyrtzidis //
7fa0734ecSArgyrios Kyrtzidis //===----------------------------------------------------------------------===//
8fa0734ecSArgyrios Kyrtzidis //
9fa0734ecSArgyrios Kyrtzidis // This file defines SymbolManager, a class that manages symbolic values
10fa0734ecSArgyrios Kyrtzidis // created for use by ExprEngine and related classes.
11fa0734ecSArgyrios Kyrtzidis //
12fa0734ecSArgyrios Kyrtzidis //===----------------------------------------------------------------------===//
13fa0734ecSArgyrios Kyrtzidis
14f8cbac4bSTed Kremenek #include "clang/StaticAnalyzer/Core/PathSensitive/SymbolManager.h"
15b8b9af2aSEugene Zelenko #include "clang/AST/ASTContext.h"
16b8b9af2aSEugene Zelenko #include "clang/AST/Expr.h"
17b9bca883SKristóf Umann #include "clang/AST/StmtObjC.h"
18fa0734ecSArgyrios Kyrtzidis #include "clang/Analysis/Analyses/LiveVariables.h"
19b8b9af2aSEugene Zelenko #include "clang/Analysis/AnalysisDeclContext.h"
20b8b9af2aSEugene Zelenko #include "clang/Basic/LLVM.h"
21f8cbac4bSTed Kremenek #include "clang/StaticAnalyzer/Core/PathSensitive/MemRegion.h"
22b8b9af2aSEugene Zelenko #include "clang/StaticAnalyzer/Core/PathSensitive/SVals.h"
23e9fda1e4STed Kremenek #include "clang/StaticAnalyzer/Core/PathSensitive/Store.h"
24b8b9af2aSEugene Zelenko #include "clang/StaticAnalyzer/Core/PathSensitive/SymExpr.h"
25b8b9af2aSEugene Zelenko #include "llvm/ADT/FoldingSet.h"
26b8b9af2aSEugene Zelenko #include "llvm/ADT/STLExtras.h"
27b8b9af2aSEugene Zelenko #include "llvm/Support/Casting.h"
28b8b9af2aSEugene Zelenko #include "llvm/Support/Compiler.h"
29b8b9af2aSEugene Zelenko #include "llvm/Support/ErrorHandling.h"
30fa0734ecSArgyrios Kyrtzidis #include "llvm/Support/raw_ostream.h"
31b8b9af2aSEugene Zelenko #include <cassert>
32fa0734ecSArgyrios Kyrtzidis
33fa0734ecSArgyrios Kyrtzidis using namespace clang;
34fa0734ecSArgyrios Kyrtzidis using namespace ento;
35fa0734ecSArgyrios Kyrtzidis
anchor()3668e081d6SDavid Blaikie void SymExpr::anchor() {}
3768e081d6SDavid Blaikie
getKindStr() const38cdacffe4SBalazs Benics StringRef SymbolConjured::getKindStr() const { return "conj_$"; }
getKindStr() const39cdacffe4SBalazs Benics StringRef SymbolDerived::getKindStr() const { return "derived_$"; }
getKindStr() const40cdacffe4SBalazs Benics StringRef SymbolExtent::getKindStr() const { return "extent_$"; }
getKindStr() const41cdacffe4SBalazs Benics StringRef SymbolMetadata::getKindStr() const { return "meta_$"; }
getKindStr() const42cdacffe4SBalazs Benics StringRef SymbolRegionValue::getKindStr() const { return "reg_$"; }
43cdacffe4SBalazs Benics
dump() const44bb2ae747SValeriy Savchenko LLVM_DUMP_METHOD void SymExpr::dump() const { dumpToStream(llvm::errs()); }
45bb2ae747SValeriy Savchenko
dumpToStreamImpl(raw_ostream & OS,const SymExpr * Sym)46bb2ae747SValeriy Savchenko void BinarySymExpr::dumpToStreamImpl(raw_ostream &OS, const SymExpr *Sym) {
47bb2ae747SValeriy Savchenko OS << '(';
48bb2ae747SValeriy Savchenko Sym->dumpToStream(OS);
49bb2ae747SValeriy Savchenko OS << ')';
50fa0734ecSArgyrios Kyrtzidis }
51fa0734ecSArgyrios Kyrtzidis
dumpToStreamImpl(raw_ostream & OS,const llvm::APSInt & Value)52bb2ae747SValeriy Savchenko void BinarySymExpr::dumpToStreamImpl(raw_ostream &OS,
53bb2ae747SValeriy Savchenko const llvm::APSInt &Value) {
54bb2ae747SValeriy Savchenko if (Value.isUnsigned())
55bb2ae747SValeriy Savchenko OS << Value.getZExtValue();
56d3a85702SGabor Horvath else
57bb2ae747SValeriy Savchenko OS << Value.getSExtValue();
58bb2ae747SValeriy Savchenko if (Value.isUnsigned())
59bb2ae747SValeriy Savchenko OS << 'U';
60fa0734ecSArgyrios Kyrtzidis }
61fa0734ecSArgyrios Kyrtzidis
dumpToStreamImpl(raw_ostream & OS,BinaryOperator::Opcode Op)62bb2ae747SValeriy Savchenko void BinarySymExpr::dumpToStreamImpl(raw_ostream &OS,
63bb2ae747SValeriy Savchenko BinaryOperator::Opcode Op) {
64bb2ae747SValeriy Savchenko OS << ' ' << BinaryOperator::getOpcodeStr(Op) << ' ';
65fa0734ecSArgyrios Kyrtzidis }
66fa0734ecSArgyrios Kyrtzidis
dumpToStream(raw_ostream & os) const67c25efcccSAnna Zaks void SymbolCast::dumpToStream(raw_ostream &os) const {
68cfb81690SNathan James os << '(' << ToTy << ") (";
69c25efcccSAnna Zaks Operand->dumpToStream(os);
70c25efcccSAnna Zaks os << ')';
71c25efcccSAnna Zaks }
72c25efcccSAnna Zaks
dumpToStream(raw_ostream & os) const73*b5b2aec1SGabor Marton void UnarySymExpr::dumpToStream(raw_ostream &os) const {
74*b5b2aec1SGabor Marton os << UnaryOperator::getOpcodeStr(Op);
75*b5b2aec1SGabor Marton bool Binary = isa<BinarySymExpr>(Operand);
76*b5b2aec1SGabor Marton if (Binary)
77*b5b2aec1SGabor Marton os << '(';
78*b5b2aec1SGabor Marton Operand->dumpToStream(os);
79*b5b2aec1SGabor Marton if (Binary)
80*b5b2aec1SGabor Marton os << ')';
81*b5b2aec1SGabor Marton }
82*b5b2aec1SGabor Marton
dumpToStream(raw_ostream & os) const830e62c1ccSChris Lattner void SymbolConjured::dumpToStream(raw_ostream &os) const {
84cfb81690SNathan James os << getKindStr() << getSymbolID() << '{' << T << ", LC" << LCtx->getID();
857e4edbddSArtem Dergachev if (S)
867e4edbddSArtem Dergachev os << ", S" << S->getID(LCtx->getDecl()->getASTContext());
877e4edbddSArtem Dergachev else
887e4edbddSArtem Dergachev os << ", no stmt";
897e4edbddSArtem Dergachev os << ", #" << Count << '}';
90fa0734ecSArgyrios Kyrtzidis }
91fa0734ecSArgyrios Kyrtzidis
dumpToStream(raw_ostream & os) const920e62c1ccSChris Lattner void SymbolDerived::dumpToStream(raw_ostream &os) const {
93cdacffe4SBalazs Benics os << getKindStr() << getSymbolID() << '{' << getParentSymbol() << ','
94cdacffe4SBalazs Benics << getRegion() << '}';
95fa0734ecSArgyrios Kyrtzidis }
96fa0734ecSArgyrios Kyrtzidis
dumpToStream(raw_ostream & os) const970e62c1ccSChris Lattner void SymbolExtent::dumpToStream(raw_ostream &os) const {
98cdacffe4SBalazs Benics os << getKindStr() << getSymbolID() << '{' << getRegion() << '}';
99fa0734ecSArgyrios Kyrtzidis }
100fa0734ecSArgyrios Kyrtzidis
dumpToStream(raw_ostream & os) const1010e62c1ccSChris Lattner void SymbolMetadata::dumpToStream(raw_ostream &os) const {
102cfb81690SNathan James os << getKindStr() << getSymbolID() << '{' << getRegion() << ',' << T << '}';
103fa0734ecSArgyrios Kyrtzidis }
104fa0734ecSArgyrios Kyrtzidis
anchor()10568e081d6SDavid Blaikie void SymbolData::anchor() {}
10668e081d6SDavid Blaikie
dumpToStream(raw_ostream & os) const1070e62c1ccSChris Lattner void SymbolRegionValue::dumpToStream(raw_ostream &os) const {
108cfb81690SNathan James os << getKindStr() << getSymbolID() << '<' << getType() << ' ' << R << '>';
109fa0734ecSArgyrios Kyrtzidis }
110fa0734ecSArgyrios Kyrtzidis
operator ==(const symbol_iterator & X) const111ee1a4353SAnna Zaks bool SymExpr::symbol_iterator::operator==(const symbol_iterator &X) const {
112ee1a4353SAnna Zaks return itr == X.itr;
113ee1a4353SAnna Zaks }
114ee1a4353SAnna Zaks
operator !=(const symbol_iterator & X) const115ee1a4353SAnna Zaks bool SymExpr::symbol_iterator::operator!=(const symbol_iterator &X) const {
116ee1a4353SAnna Zaks return itr != X.itr;
117ee1a4353SAnna Zaks }
118ee1a4353SAnna Zaks
symbol_iterator(const SymExpr * SE)119ee1a4353SAnna Zaks SymExpr::symbol_iterator::symbol_iterator(const SymExpr *SE) {
120ee1a4353SAnna Zaks itr.push_back(SE);
121ee1a4353SAnna Zaks }
122ee1a4353SAnna Zaks
operator ++()123ee1a4353SAnna Zaks SymExpr::symbol_iterator &SymExpr::symbol_iterator::operator++() {
124ee1a4353SAnna Zaks assert(!itr.empty() && "attempting to iterate on an 'end' iterator");
125db72e2fcSJordan Rose expand();
126ee1a4353SAnna Zaks return *this;
127ee1a4353SAnna Zaks }
128ee1a4353SAnna Zaks
operator *()129ee1a4353SAnna Zaks SymbolRef SymExpr::symbol_iterator::operator*() {
130ee1a4353SAnna Zaks assert(!itr.empty() && "attempting to dereference an 'end' iterator");
131db72e2fcSJordan Rose return itr.back();
132ee1a4353SAnna Zaks }
133ee1a4353SAnna Zaks
expand()134ee1a4353SAnna Zaks void SymExpr::symbol_iterator::expand() {
13525284cc9SRobert Wilhelm const SymExpr *SE = itr.pop_back_val();
136ee1a4353SAnna Zaks
137ecd73008SAnna Zaks switch (SE->getKind()) {
13873f018e3SArtem Dergachev case SymExpr::SymbolRegionValueKind:
13973f018e3SArtem Dergachev case SymExpr::SymbolConjuredKind:
14073f018e3SArtem Dergachev case SymExpr::SymbolDerivedKind:
14173f018e3SArtem Dergachev case SymExpr::SymbolExtentKind:
14273f018e3SArtem Dergachev case SymExpr::SymbolMetadataKind:
143ecd73008SAnna Zaks return;
14473f018e3SArtem Dergachev case SymExpr::SymbolCastKind:
145ecd73008SAnna Zaks itr.push_back(cast<SymbolCast>(SE)->getOperand());
146ecd73008SAnna Zaks return;
147*b5b2aec1SGabor Marton case SymExpr::UnarySymExprKind:
148*b5b2aec1SGabor Marton itr.push_back(cast<UnarySymExpr>(SE)->getOperand());
149*b5b2aec1SGabor Marton return;
15073f018e3SArtem Dergachev case SymExpr::SymIntExprKind:
151ecd73008SAnna Zaks itr.push_back(cast<SymIntExpr>(SE)->getLHS());
152ecd73008SAnna Zaks return;
15373f018e3SArtem Dergachev case SymExpr::IntSymExprKind:
154ecd73008SAnna Zaks itr.push_back(cast<IntSymExpr>(SE)->getRHS());
155ecd73008SAnna Zaks return;
15673f018e3SArtem Dergachev case SymExpr::SymSymExprKind: {
157b8b9af2aSEugene Zelenko const auto *x = cast<SymSymExpr>(SE);
158ecd73008SAnna Zaks itr.push_back(x->getLHS());
159ecd73008SAnna Zaks itr.push_back(x->getRHS());
160ee1a4353SAnna Zaks return;
161ee1a4353SAnna Zaks }
162ee1a4353SAnna Zaks }
163ee1a4353SAnna Zaks llvm_unreachable("unhandled expansion case");
164ee1a4353SAnna Zaks }
165ee1a4353SAnna Zaks
166fa0734ecSArgyrios Kyrtzidis const SymbolRegionValue*
getRegionValueSymbol(const TypedValueRegion * R)1678df44b26STed Kremenek SymbolManager::getRegionValueSymbol(const TypedValueRegion* R) {
168fa0734ecSArgyrios Kyrtzidis llvm::FoldingSetNodeID profile;
169fa0734ecSArgyrios Kyrtzidis SymbolRegionValue::Profile(profile, R);
170fa0734ecSArgyrios Kyrtzidis void *InsertPos;
171fa0734ecSArgyrios Kyrtzidis SymExpr *SD = DataSet.FindNodeOrInsertPos(profile, InsertPos);
172fa0734ecSArgyrios Kyrtzidis if (!SD) {
173fa0734ecSArgyrios Kyrtzidis SD = (SymExpr*) BPAlloc.Allocate<SymbolRegionValue>();
174fa0734ecSArgyrios Kyrtzidis new (SD) SymbolRegionValue(SymbolCounter, R);
175fa0734ecSArgyrios Kyrtzidis DataSet.InsertNode(SD, InsertPos);
176fa0734ecSArgyrios Kyrtzidis ++SymbolCounter;
177fa0734ecSArgyrios Kyrtzidis }
178fa0734ecSArgyrios Kyrtzidis
179fa0734ecSArgyrios Kyrtzidis return cast<SymbolRegionValue>(SD);
180fa0734ecSArgyrios Kyrtzidis }
181fa0734ecSArgyrios Kyrtzidis
conjureSymbol(const Stmt * E,const LocationContext * LCtx,QualType T,unsigned Count,const void * SymbolTag)182d227833cSTed Kremenek const SymbolConjured* SymbolManager::conjureSymbol(const Stmt *E,
183d227833cSTed Kremenek const LocationContext *LCtx,
184d227833cSTed Kremenek QualType T,
185d227833cSTed Kremenek unsigned Count,
186fa0734ecSArgyrios Kyrtzidis const void *SymbolTag) {
187fa0734ecSArgyrios Kyrtzidis llvm::FoldingSetNodeID profile;
188d519cae8STed Kremenek SymbolConjured::Profile(profile, E, T, Count, LCtx, SymbolTag);
189fa0734ecSArgyrios Kyrtzidis void *InsertPos;
190fa0734ecSArgyrios Kyrtzidis SymExpr *SD = DataSet.FindNodeOrInsertPos(profile, InsertPos);
191fa0734ecSArgyrios Kyrtzidis if (!SD) {
192fa0734ecSArgyrios Kyrtzidis SD = (SymExpr*) BPAlloc.Allocate<SymbolConjured>();
193d519cae8STed Kremenek new (SD) SymbolConjured(SymbolCounter, E, LCtx, T, Count, SymbolTag);
194fa0734ecSArgyrios Kyrtzidis DataSet.InsertNode(SD, InsertPos);
195fa0734ecSArgyrios Kyrtzidis ++SymbolCounter;
196fa0734ecSArgyrios Kyrtzidis }
197fa0734ecSArgyrios Kyrtzidis
198fa0734ecSArgyrios Kyrtzidis return cast<SymbolConjured>(SD);
199fa0734ecSArgyrios Kyrtzidis }
200fa0734ecSArgyrios Kyrtzidis
201fa0734ecSArgyrios Kyrtzidis const SymbolDerived*
getDerivedSymbol(SymbolRef parentSymbol,const TypedValueRegion * R)202fa0734ecSArgyrios Kyrtzidis SymbolManager::getDerivedSymbol(SymbolRef parentSymbol,
2038df44b26STed Kremenek const TypedValueRegion *R) {
204fa0734ecSArgyrios Kyrtzidis llvm::FoldingSetNodeID profile;
205fa0734ecSArgyrios Kyrtzidis SymbolDerived::Profile(profile, parentSymbol, R);
206fa0734ecSArgyrios Kyrtzidis void *InsertPos;
207fa0734ecSArgyrios Kyrtzidis SymExpr *SD = DataSet.FindNodeOrInsertPos(profile, InsertPos);
208fa0734ecSArgyrios Kyrtzidis if (!SD) {
209fa0734ecSArgyrios Kyrtzidis SD = (SymExpr*) BPAlloc.Allocate<SymbolDerived>();
210fa0734ecSArgyrios Kyrtzidis new (SD) SymbolDerived(SymbolCounter, parentSymbol, R);
211fa0734ecSArgyrios Kyrtzidis DataSet.InsertNode(SD, InsertPos);
212fa0734ecSArgyrios Kyrtzidis ++SymbolCounter;
213fa0734ecSArgyrios Kyrtzidis }
214fa0734ecSArgyrios Kyrtzidis
215fa0734ecSArgyrios Kyrtzidis return cast<SymbolDerived>(SD);
216fa0734ecSArgyrios Kyrtzidis }
217fa0734ecSArgyrios Kyrtzidis
218fa0734ecSArgyrios Kyrtzidis const SymbolExtent*
getExtentSymbol(const SubRegion * R)219fa0734ecSArgyrios Kyrtzidis SymbolManager::getExtentSymbol(const SubRegion *R) {
220fa0734ecSArgyrios Kyrtzidis llvm::FoldingSetNodeID profile;
221fa0734ecSArgyrios Kyrtzidis SymbolExtent::Profile(profile, R);
222fa0734ecSArgyrios Kyrtzidis void *InsertPos;
223fa0734ecSArgyrios Kyrtzidis SymExpr *SD = DataSet.FindNodeOrInsertPos(profile, InsertPos);
224fa0734ecSArgyrios Kyrtzidis if (!SD) {
225fa0734ecSArgyrios Kyrtzidis SD = (SymExpr*) BPAlloc.Allocate<SymbolExtent>();
226fa0734ecSArgyrios Kyrtzidis new (SD) SymbolExtent(SymbolCounter, R);
227fa0734ecSArgyrios Kyrtzidis DataSet.InsertNode(SD, InsertPos);
228fa0734ecSArgyrios Kyrtzidis ++SymbolCounter;
229fa0734ecSArgyrios Kyrtzidis }
230fa0734ecSArgyrios Kyrtzidis
231fa0734ecSArgyrios Kyrtzidis return cast<SymbolExtent>(SD);
232fa0734ecSArgyrios Kyrtzidis }
233fa0734ecSArgyrios Kyrtzidis
234fa0734ecSArgyrios Kyrtzidis const SymbolMetadata *
getMetadataSymbol(const MemRegion * R,const Stmt * S,QualType T,const LocationContext * LCtx,unsigned Count,const void * SymbolTag)235fa0734ecSArgyrios Kyrtzidis SymbolManager::getMetadataSymbol(const MemRegion* R, const Stmt *S, QualType T,
236cbce96c3SArtem Dergachev const LocationContext *LCtx,
237fa0734ecSArgyrios Kyrtzidis unsigned Count, const void *SymbolTag) {
238fa0734ecSArgyrios Kyrtzidis llvm::FoldingSetNodeID profile;
239cbce96c3SArtem Dergachev SymbolMetadata::Profile(profile, R, S, T, LCtx, Count, SymbolTag);
240fa0734ecSArgyrios Kyrtzidis void *InsertPos;
241fa0734ecSArgyrios Kyrtzidis SymExpr *SD = DataSet.FindNodeOrInsertPos(profile, InsertPos);
242fa0734ecSArgyrios Kyrtzidis if (!SD) {
243fa0734ecSArgyrios Kyrtzidis SD = (SymExpr*) BPAlloc.Allocate<SymbolMetadata>();
244cbce96c3SArtem Dergachev new (SD) SymbolMetadata(SymbolCounter, R, S, T, LCtx, Count, SymbolTag);
245fa0734ecSArgyrios Kyrtzidis DataSet.InsertNode(SD, InsertPos);
246fa0734ecSArgyrios Kyrtzidis ++SymbolCounter;
247fa0734ecSArgyrios Kyrtzidis }
248fa0734ecSArgyrios Kyrtzidis
249fa0734ecSArgyrios Kyrtzidis return cast<SymbolMetadata>(SD);
250fa0734ecSArgyrios Kyrtzidis }
251fa0734ecSArgyrios Kyrtzidis
252c25efcccSAnna Zaks const SymbolCast*
getCastSymbol(const SymExpr * Op,QualType From,QualType To)253c25efcccSAnna Zaks SymbolManager::getCastSymbol(const SymExpr *Op,
254c25efcccSAnna Zaks QualType From, QualType To) {
255c25efcccSAnna Zaks llvm::FoldingSetNodeID ID;
256c25efcccSAnna Zaks SymbolCast::Profile(ID, Op, From, To);
257c25efcccSAnna Zaks void *InsertPos;
258c25efcccSAnna Zaks SymExpr *data = DataSet.FindNodeOrInsertPos(ID, InsertPos);
259c25efcccSAnna Zaks if (!data) {
260c25efcccSAnna Zaks data = (SymbolCast*) BPAlloc.Allocate<SymbolCast>();
261c25efcccSAnna Zaks new (data) SymbolCast(Op, From, To);
262c25efcccSAnna Zaks DataSet.InsertNode(data, InsertPos);
263c25efcccSAnna Zaks }
264c25efcccSAnna Zaks
265c25efcccSAnna Zaks return cast<SymbolCast>(data);
266c25efcccSAnna Zaks }
267c25efcccSAnna Zaks
getSymIntExpr(const SymExpr * lhs,BinaryOperator::Opcode op,const llvm::APSInt & v,QualType t)268fa0734ecSArgyrios Kyrtzidis const SymIntExpr *SymbolManager::getSymIntExpr(const SymExpr *lhs,
269fa0734ecSArgyrios Kyrtzidis BinaryOperator::Opcode op,
270fa0734ecSArgyrios Kyrtzidis const llvm::APSInt& v,
271fa0734ecSArgyrios Kyrtzidis QualType t) {
272fa0734ecSArgyrios Kyrtzidis llvm::FoldingSetNodeID ID;
273fa0734ecSArgyrios Kyrtzidis SymIntExpr::Profile(ID, lhs, op, v, t);
274fa0734ecSArgyrios Kyrtzidis void *InsertPos;
275fa0734ecSArgyrios Kyrtzidis SymExpr *data = DataSet.FindNodeOrInsertPos(ID, InsertPos);
276fa0734ecSArgyrios Kyrtzidis
277fa0734ecSArgyrios Kyrtzidis if (!data) {
278fa0734ecSArgyrios Kyrtzidis data = (SymIntExpr*) BPAlloc.Allocate<SymIntExpr>();
279fa0734ecSArgyrios Kyrtzidis new (data) SymIntExpr(lhs, op, v, t);
280fa0734ecSArgyrios Kyrtzidis DataSet.InsertNode(data, InsertPos);
281fa0734ecSArgyrios Kyrtzidis }
282fa0734ecSArgyrios Kyrtzidis
283fa0734ecSArgyrios Kyrtzidis return cast<SymIntExpr>(data);
284fa0734ecSArgyrios Kyrtzidis }
285fa0734ecSArgyrios Kyrtzidis
getIntSymExpr(const llvm::APSInt & lhs,BinaryOperator::Opcode op,const SymExpr * rhs,QualType t)286ecd73008SAnna Zaks const IntSymExpr *SymbolManager::getIntSymExpr(const llvm::APSInt& lhs,
287ecd73008SAnna Zaks BinaryOperator::Opcode op,
288ecd73008SAnna Zaks const SymExpr *rhs,
289ecd73008SAnna Zaks QualType t) {
290ecd73008SAnna Zaks llvm::FoldingSetNodeID ID;
291ecd73008SAnna Zaks IntSymExpr::Profile(ID, lhs, op, rhs, t);
292ecd73008SAnna Zaks void *InsertPos;
293ecd73008SAnna Zaks SymExpr *data = DataSet.FindNodeOrInsertPos(ID, InsertPos);
294ecd73008SAnna Zaks
295ecd73008SAnna Zaks if (!data) {
296ecd73008SAnna Zaks data = (IntSymExpr*) BPAlloc.Allocate<IntSymExpr>();
297ecd73008SAnna Zaks new (data) IntSymExpr(lhs, op, rhs, t);
298ecd73008SAnna Zaks DataSet.InsertNode(data, InsertPos);
299ecd73008SAnna Zaks }
300ecd73008SAnna Zaks
301ecd73008SAnna Zaks return cast<IntSymExpr>(data);
302ecd73008SAnna Zaks }
303ecd73008SAnna Zaks
getSymSymExpr(const SymExpr * lhs,BinaryOperator::Opcode op,const SymExpr * rhs,QualType t)304fa0734ecSArgyrios Kyrtzidis const SymSymExpr *SymbolManager::getSymSymExpr(const SymExpr *lhs,
305fa0734ecSArgyrios Kyrtzidis BinaryOperator::Opcode op,
306fa0734ecSArgyrios Kyrtzidis const SymExpr *rhs,
307fa0734ecSArgyrios Kyrtzidis QualType t) {
308fa0734ecSArgyrios Kyrtzidis llvm::FoldingSetNodeID ID;
309fa0734ecSArgyrios Kyrtzidis SymSymExpr::Profile(ID, lhs, op, rhs, t);
310fa0734ecSArgyrios Kyrtzidis void *InsertPos;
311fa0734ecSArgyrios Kyrtzidis SymExpr *data = DataSet.FindNodeOrInsertPos(ID, InsertPos);
312fa0734ecSArgyrios Kyrtzidis
313fa0734ecSArgyrios Kyrtzidis if (!data) {
314fa0734ecSArgyrios Kyrtzidis data = (SymSymExpr*) BPAlloc.Allocate<SymSymExpr>();
315fa0734ecSArgyrios Kyrtzidis new (data) SymSymExpr(lhs, op, rhs, t);
316fa0734ecSArgyrios Kyrtzidis DataSet.InsertNode(data, InsertPos);
317fa0734ecSArgyrios Kyrtzidis }
318fa0734ecSArgyrios Kyrtzidis
319fa0734ecSArgyrios Kyrtzidis return cast<SymSymExpr>(data);
320fa0734ecSArgyrios Kyrtzidis }
321fa0734ecSArgyrios Kyrtzidis
getUnarySymExpr(const SymExpr * Operand,UnaryOperator::Opcode Opc,QualType T)322*b5b2aec1SGabor Marton const UnarySymExpr *SymbolManager::getUnarySymExpr(const SymExpr *Operand,
323*b5b2aec1SGabor Marton UnaryOperator::Opcode Opc,
324*b5b2aec1SGabor Marton QualType T) {
325*b5b2aec1SGabor Marton llvm::FoldingSetNodeID ID;
326*b5b2aec1SGabor Marton UnarySymExpr::Profile(ID, Operand, Opc, T);
327*b5b2aec1SGabor Marton void *InsertPos;
328*b5b2aec1SGabor Marton SymExpr *data = DataSet.FindNodeOrInsertPos(ID, InsertPos);
329*b5b2aec1SGabor Marton if (!data) {
330*b5b2aec1SGabor Marton data = (UnarySymExpr *)BPAlloc.Allocate<UnarySymExpr>();
331*b5b2aec1SGabor Marton new (data) UnarySymExpr(Operand, Opc, T);
332*b5b2aec1SGabor Marton DataSet.InsertNode(data, InsertPos);
333*b5b2aec1SGabor Marton }
334*b5b2aec1SGabor Marton
335*b5b2aec1SGabor Marton return cast<UnarySymExpr>(data);
336*b5b2aec1SGabor Marton }
337*b5b2aec1SGabor Marton
getType() const338a808e165STed Kremenek QualType SymbolConjured::getType() const {
339fa0734ecSArgyrios Kyrtzidis return T;
340fa0734ecSArgyrios Kyrtzidis }
341fa0734ecSArgyrios Kyrtzidis
getType() const342a808e165STed Kremenek QualType SymbolDerived::getType() const {
343fa0734ecSArgyrios Kyrtzidis return R->getValueType();
344fa0734ecSArgyrios Kyrtzidis }
345fa0734ecSArgyrios Kyrtzidis
getType() const346a808e165STed Kremenek QualType SymbolExtent::getType() const {
347601687bfSCharusso ASTContext &Ctx = R->getMemRegionManager().getContext();
348fa0734ecSArgyrios Kyrtzidis return Ctx.getSizeType();
349fa0734ecSArgyrios Kyrtzidis }
350fa0734ecSArgyrios Kyrtzidis
getType() const351a808e165STed Kremenek QualType SymbolMetadata::getType() const {
352fa0734ecSArgyrios Kyrtzidis return T;
353fa0734ecSArgyrios Kyrtzidis }
354fa0734ecSArgyrios Kyrtzidis
getType() const355a808e165STed Kremenek QualType SymbolRegionValue::getType() const {
356fa0734ecSArgyrios Kyrtzidis return R->getValueType();
357fa0734ecSArgyrios Kyrtzidis }
358fa0734ecSArgyrios Kyrtzidis
canSymbolicate(QualType T)359fa0734ecSArgyrios Kyrtzidis bool SymbolManager::canSymbolicate(QualType T) {
360fa0734ecSArgyrios Kyrtzidis T = T.getCanonicalType();
361fa0734ecSArgyrios Kyrtzidis
36285a203ebSZhanyong Wan if (Loc::isLocType(T))
363fa0734ecSArgyrios Kyrtzidis return true;
364fa0734ecSArgyrios Kyrtzidis
36561e221f6SJordan Rose if (T->isIntegralOrEnumerationType())
36661e221f6SJordan Rose return true;
367fa0734ecSArgyrios Kyrtzidis
368bc009d44SJordan Rose if (T->isRecordType() && !T->isUnionType())
369bc009d44SJordan Rose return true;
370bc009d44SJordan Rose
371fa0734ecSArgyrios Kyrtzidis return false;
372fa0734ecSArgyrios Kyrtzidis }
373fa0734ecSArgyrios Kyrtzidis
addSymbolDependency(const SymbolRef Primary,const SymbolRef Dependent)37422a9d0f3SAnna Zaks void SymbolManager::addSymbolDependency(const SymbolRef Primary,
37522a9d0f3SAnna Zaks const SymbolRef Dependent) {
37662882925SDavid Blaikie auto &dependencies = SymbolDependencies[Primary];
37762882925SDavid Blaikie if (!dependencies) {
37862882925SDavid Blaikie dependencies = std::make_unique<SymbolRefSmallVectorTy>();
37922a9d0f3SAnna Zaks }
3809b25cee3SAnna Zaks dependencies->push_back(Dependent);
38122a9d0f3SAnna Zaks }
38222a9d0f3SAnna Zaks
getDependentSymbols(const SymbolRef Primary)38322a9d0f3SAnna Zaks const SymbolRefSmallVectorTy *SymbolManager::getDependentSymbols(
38422a9d0f3SAnna Zaks const SymbolRef Primary) {
38522a9d0f3SAnna Zaks SymbolDependTy::const_iterator I = SymbolDependencies.find(Primary);
38622a9d0f3SAnna Zaks if (I == SymbolDependencies.end())
3870dbb783cSCraig Topper return nullptr;
38862882925SDavid Blaikie return I->second.get();
38922a9d0f3SAnna Zaks }
39022a9d0f3SAnna Zaks
markDependentsLive(SymbolRef sym)39122a9d0f3SAnna Zaks void SymbolReaper::markDependentsLive(SymbolRef sym) {
3929b25cee3SAnna Zaks // Do not mark dependents more then once.
3939b25cee3SAnna Zaks SymbolMapTy::iterator LI = TheLiving.find(sym);
3949b25cee3SAnna Zaks assert(LI != TheLiving.end() && "The primary symbol is not live.");
3959b25cee3SAnna Zaks if (LI->second == HaveMarkedDependents)
3969b25cee3SAnna Zaks return;
3979b25cee3SAnna Zaks LI->second = HaveMarkedDependents;
3989b25cee3SAnna Zaks
39922a9d0f3SAnna Zaks if (const SymbolRefSmallVectorTy *Deps = SymMgr.getDependentSymbols(sym)) {
400b8b9af2aSEugene Zelenko for (const auto I : *Deps) {
401b8b9af2aSEugene Zelenko if (TheLiving.find(I) != TheLiving.end())
4029b25cee3SAnna Zaks continue;
403b8b9af2aSEugene Zelenko markLive(I);
40422a9d0f3SAnna Zaks }
40522a9d0f3SAnna Zaks }
40622a9d0f3SAnna Zaks }
40722a9d0f3SAnna Zaks
markLive(SymbolRef sym)408fa0734ecSArgyrios Kyrtzidis void SymbolReaper::markLive(SymbolRef sym) {
4099b25cee3SAnna Zaks TheLiving[sym] = NotProcessed;
41022a9d0f3SAnna Zaks markDependentsLive(sym);
411fa0734ecSArgyrios Kyrtzidis }
412fa0734ecSArgyrios Kyrtzidis
markLive(const MemRegion * region)413c91ca30bSTed Kremenek void SymbolReaper::markLive(const MemRegion *region) {
4142ed0e79bSArtem Dergachev RegionRoots.insert(region->getBaseRegion());
415733e71b7SArtem Dergachev markElementIndicesLive(region);
416733e71b7SArtem Dergachev }
417733e71b7SArtem Dergachev
markElementIndicesLive(const MemRegion * region)418733e71b7SArtem Dergachev void SymbolReaper::markElementIndicesLive(const MemRegion *region) {
419733e71b7SArtem Dergachev for (auto SR = dyn_cast<SubRegion>(region); SR;
420733e71b7SArtem Dergachev SR = dyn_cast<SubRegion>(SR->getSuperRegion())) {
421b8b9af2aSEugene Zelenko if (const auto ER = dyn_cast<ElementRegion>(SR)) {
422733e71b7SArtem Dergachev SVal Idx = ER->getIndex();
423733e71b7SArtem Dergachev for (auto SI = Idx.symbol_begin(), SE = Idx.symbol_end(); SI != SE; ++SI)
424733e71b7SArtem Dergachev markLive(*SI);
425733e71b7SArtem Dergachev }
426733e71b7SArtem Dergachev }
427c91ca30bSTed Kremenek }
428c91ca30bSTed Kremenek
markInUse(SymbolRef sym)429fa0734ecSArgyrios Kyrtzidis void SymbolReaper::markInUse(SymbolRef sym) {
430fa0734ecSArgyrios Kyrtzidis if (isa<SymbolMetadata>(sym))
431fa0734ecSArgyrios Kyrtzidis MetadataInUse.insert(sym);
432fa0734ecSArgyrios Kyrtzidis }
433fa0734ecSArgyrios Kyrtzidis
isLiveRegion(const MemRegion * MR)434c91ca30bSTed Kremenek bool SymbolReaper::isLiveRegion(const MemRegion *MR) {
4352ed0e79bSArtem Dergachev // TODO: For now, liveness of a memory region is equivalent to liveness of its
4362ed0e79bSArtem Dergachev // base region. In fact we can do a bit better: say, if a particular FieldDecl
4372ed0e79bSArtem Dergachev // is not used later in the path, we can diagnose a leak of a value within
4382ed0e79bSArtem Dergachev // that field earlier than, say, the variable that contains the field dies.
4392ed0e79bSArtem Dergachev MR = MR->getBaseRegion();
4402ed0e79bSArtem Dergachev
441c91ca30bSTed Kremenek if (RegionRoots.count(MR))
442c91ca30bSTed Kremenek return true;
443c91ca30bSTed Kremenek
444b8b9af2aSEugene Zelenko if (const auto *SR = dyn_cast<SymbolicRegion>(MR))
445c91ca30bSTed Kremenek return isLive(SR->getSymbol());
446fa0734ecSArgyrios Kyrtzidis
447b8b9af2aSEugene Zelenko if (const auto *VR = dyn_cast<VarRegion>(MR))
448c91ca30bSTed Kremenek return isLive(VR, true);
449fa0734ecSArgyrios Kyrtzidis
450fa0734ecSArgyrios Kyrtzidis // FIXME: This is a gross over-approximation. What we really need is a way to
451fa0734ecSArgyrios Kyrtzidis // tell if anything still refers to this region. Unlike SymbolicRegions,
452fa0734ecSArgyrios Kyrtzidis // AllocaRegions don't have associated symbols, though, so we don't actually
453fa0734ecSArgyrios Kyrtzidis // have a way to track their liveness.
45416be17adSBalazs Benics return isa<AllocaRegion, CXXThisRegion, MemSpaceRegion, CodeTextRegion>(MR);
455fa0734ecSArgyrios Kyrtzidis }
456fa0734ecSArgyrios Kyrtzidis
isLive(SymbolRef sym)457fa0734ecSArgyrios Kyrtzidis bool SymbolReaper::isLive(SymbolRef sym) {
45822a9d0f3SAnna Zaks if (TheLiving.count(sym)) {
45922a9d0f3SAnna Zaks markDependentsLive(sym);
460fa0734ecSArgyrios Kyrtzidis return true;
46122a9d0f3SAnna Zaks }
462fa0734ecSArgyrios Kyrtzidis
46360d704abSJordan Rose bool KnownLive;
464fa0734ecSArgyrios Kyrtzidis
46560d704abSJordan Rose switch (sym->getKind()) {
46673f018e3SArtem Dergachev case SymExpr::SymbolRegionValueKind:
467bda130f0SAnna Zaks KnownLive = isLiveRegion(cast<SymbolRegionValue>(sym)->getRegion());
46860d704abSJordan Rose break;
46973f018e3SArtem Dergachev case SymExpr::SymbolConjuredKind:
47060d704abSJordan Rose KnownLive = false;
47160d704abSJordan Rose break;
47273f018e3SArtem Dergachev case SymExpr::SymbolDerivedKind:
47360d704abSJordan Rose KnownLive = isLive(cast<SymbolDerived>(sym)->getParentSymbol());
47460d704abSJordan Rose break;
47573f018e3SArtem Dergachev case SymExpr::SymbolExtentKind:
47660d704abSJordan Rose KnownLive = isLiveRegion(cast<SymbolExtent>(sym)->getRegion());
47760d704abSJordan Rose break;
47873f018e3SArtem Dergachev case SymExpr::SymbolMetadataKind:
47960d704abSJordan Rose KnownLive = MetadataInUse.count(sym) &&
48060d704abSJordan Rose isLiveRegion(cast<SymbolMetadata>(sym)->getRegion());
48160d704abSJordan Rose if (KnownLive)
482fa0734ecSArgyrios Kyrtzidis MetadataInUse.erase(sym);
48360d704abSJordan Rose break;
48473f018e3SArtem Dergachev case SymExpr::SymIntExprKind:
48560d704abSJordan Rose KnownLive = isLive(cast<SymIntExpr>(sym)->getLHS());
48660d704abSJordan Rose break;
48773f018e3SArtem Dergachev case SymExpr::IntSymExprKind:
48860d704abSJordan Rose KnownLive = isLive(cast<IntSymExpr>(sym)->getRHS());
48960d704abSJordan Rose break;
49073f018e3SArtem Dergachev case SymExpr::SymSymExprKind:
49160d704abSJordan Rose KnownLive = isLive(cast<SymSymExpr>(sym)->getLHS()) &&
49260d704abSJordan Rose isLive(cast<SymSymExpr>(sym)->getRHS());
49360d704abSJordan Rose break;
49473f018e3SArtem Dergachev case SymExpr::SymbolCastKind:
49560d704abSJordan Rose KnownLive = isLive(cast<SymbolCast>(sym)->getOperand());
49660d704abSJordan Rose break;
497*b5b2aec1SGabor Marton case SymExpr::UnarySymExprKind:
498*b5b2aec1SGabor Marton KnownLive = isLive(cast<UnarySymExpr>(sym)->getOperand());
499*b5b2aec1SGabor Marton break;
500fa0734ecSArgyrios Kyrtzidis }
501fa0734ecSArgyrios Kyrtzidis
50260d704abSJordan Rose if (KnownLive)
50360d704abSJordan Rose markLive(sym);
50460d704abSJordan Rose
50560d704abSJordan Rose return KnownLive;
506fa0734ecSArgyrios Kyrtzidis }
507fa0734ecSArgyrios Kyrtzidis
508632e3b7eSTed Kremenek bool
isLive(const Expr * ExprVal,const LocationContext * ELCtx) const509dd1d5488SKristóf Umann SymbolReaper::isLive(const Expr *ExprVal, const LocationContext *ELCtx) const {
5100dbb783cSCraig Topper if (LCtx == nullptr)
5118d1f6ed9SAnna Zaks return false;
5128d1f6ed9SAnna Zaks
513632e3b7eSTed Kremenek if (LCtx != ELCtx) {
514632e3b7eSTed Kremenek // If the reaper's location context is a parent of the expression's
515632e3b7eSTed Kremenek // location context, then the expression value is now "out of scope".
516632e3b7eSTed Kremenek if (LCtx->isParentOf(ELCtx))
517632e3b7eSTed Kremenek return false;
518632e3b7eSTed Kremenek return true;
519632e3b7eSTed Kremenek }
5208d1f6ed9SAnna Zaks
521b9bca883SKristóf Umann // If no statement is provided, everything in this and parent contexts is
522b9bca883SKristóf Umann // live.
5237e53bd6fSAnna Zaks if (!Loc)
5247e53bd6fSAnna Zaks return true;
525632e3b7eSTed Kremenek
526dccc2b22STed Kremenek return LCtx->getAnalysis<RelaxedLiveVariables>()->isLive(Loc, ExprVal);
527fa0734ecSArgyrios Kyrtzidis }
528fa0734ecSArgyrios Kyrtzidis
isLive(const VarRegion * VR,bool includeStoreBindings) const529e9fda1e4STed Kremenek bool SymbolReaper::isLive(const VarRegion *VR, bool includeStoreBindings) const{
530fa0734ecSArgyrios Kyrtzidis const StackFrameContext *VarContext = VR->getStackFrame();
5318d1f6ed9SAnna Zaks
5328d1f6ed9SAnna Zaks if (!VarContext)
5338d1f6ed9SAnna Zaks return true;
5348d1f6ed9SAnna Zaks
5358d1f6ed9SAnna Zaks if (!LCtx)
5368d1f6ed9SAnna Zaks return false;
537dd18b11bSGeorge Karpenkov const StackFrameContext *CurrentContext = LCtx->getStackFrame();
538fa0734ecSArgyrios Kyrtzidis
539e9fda1e4STed Kremenek if (VarContext == CurrentContext) {
540802c4b70SRichard Smith // If no statement is provided, everything is live.
5417e53bd6fSAnna Zaks if (!Loc)
5427e53bd6fSAnna Zaks return true;
5437e53bd6fSAnna Zaks
544a82ffe9dSArtem Dergachev // Anonymous parameters of an inheriting constructor are live for the entire
545a82ffe9dSArtem Dergachev // duration of the constructor.
546a82ffe9dSArtem Dergachev if (isa<CXXInheritedCtorInitExpr>(Loc))
547a82ffe9dSArtem Dergachev return true;
548a82ffe9dSArtem Dergachev
549dccc2b22STed Kremenek if (LCtx->getAnalysis<RelaxedLiveVariables>()->isLive(Loc, VR->getDecl()))
550e9fda1e4STed Kremenek return true;
551e9fda1e4STed Kremenek
552e9fda1e4STed Kremenek if (!includeStoreBindings)
553e9fda1e4STed Kremenek return false;
554e9fda1e4STed Kremenek
555e9fda1e4STed Kremenek unsigned &cachedQuery =
556e9fda1e4STed Kremenek const_cast<SymbolReaper *>(this)->includedRegionCache[VR];
557e9fda1e4STed Kremenek
558e9fda1e4STed Kremenek if (cachedQuery) {
559e9fda1e4STed Kremenek return cachedQuery == 1;
560e9fda1e4STed Kremenek }
561e9fda1e4STed Kremenek
562e9fda1e4STed Kremenek // Query the store to see if the region occurs in any live bindings.
563e9fda1e4STed Kremenek if (Store store = reapedStore.getStore()) {
564e9fda1e4STed Kremenek bool hasRegion =
565e9fda1e4STed Kremenek reapedStore.getStoreManager().includedInBindings(store, VR);
566e9fda1e4STed Kremenek cachedQuery = hasRegion ? 1 : 2;
567e9fda1e4STed Kremenek return hasRegion;
568e9fda1e4STed Kremenek }
569e9fda1e4STed Kremenek
570e9fda1e4STed Kremenek return false;
571e9fda1e4STed Kremenek }
572fa0734ecSArgyrios Kyrtzidis
5738d1f6ed9SAnna Zaks return VarContext->isParentOf(CurrentContext);
574fa0734ecSArgyrios Kyrtzidis }
575