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