xref: /freebsd-src/contrib/llvm-project/clang/lib/StaticAnalyzer/Core/SymbolManager.cpp (revision 06c3fb2749bda94cb5201f81ffdb8fa6c3161b2e)
10b57cec5SDimitry Andric //===- SymbolManager.h - Management of Symbolic Values --------------------===//
20b57cec5SDimitry Andric //
30b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
40b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
50b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
60b57cec5SDimitry Andric //
70b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
80b57cec5SDimitry Andric //
90b57cec5SDimitry Andric //  This file defines SymbolManager, a class that manages symbolic values
100b57cec5SDimitry Andric //  created for use by ExprEngine and related classes.
110b57cec5SDimitry Andric //
120b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
130b57cec5SDimitry Andric 
140b57cec5SDimitry Andric #include "clang/StaticAnalyzer/Core/PathSensitive/SymbolManager.h"
150b57cec5SDimitry Andric #include "clang/AST/ASTContext.h"
160b57cec5SDimitry Andric #include "clang/AST/Expr.h"
17e8d8bef9SDimitry Andric #include "clang/AST/StmtObjC.h"
180b57cec5SDimitry Andric #include "clang/Analysis/Analyses/LiveVariables.h"
190b57cec5SDimitry Andric #include "clang/Analysis/AnalysisDeclContext.h"
200b57cec5SDimitry Andric #include "clang/Basic/LLVM.h"
210b57cec5SDimitry Andric #include "clang/StaticAnalyzer/Core/PathSensitive/MemRegion.h"
220b57cec5SDimitry Andric #include "clang/StaticAnalyzer/Core/PathSensitive/SVals.h"
230b57cec5SDimitry Andric #include "clang/StaticAnalyzer/Core/PathSensitive/Store.h"
240b57cec5SDimitry Andric #include "clang/StaticAnalyzer/Core/PathSensitive/SymExpr.h"
250b57cec5SDimitry Andric #include "llvm/ADT/FoldingSet.h"
260b57cec5SDimitry Andric #include "llvm/ADT/STLExtras.h"
270b57cec5SDimitry Andric #include "llvm/Support/Casting.h"
280b57cec5SDimitry Andric #include "llvm/Support/Compiler.h"
290b57cec5SDimitry Andric #include "llvm/Support/ErrorHandling.h"
300b57cec5SDimitry Andric #include "llvm/Support/raw_ostream.h"
310b57cec5SDimitry Andric #include <cassert>
320b57cec5SDimitry Andric 
330b57cec5SDimitry Andric using namespace clang;
340b57cec5SDimitry Andric using namespace ento;
350b57cec5SDimitry Andric 
anchor()360b57cec5SDimitry Andric void SymExpr::anchor() {}
370b57cec5SDimitry Andric 
getKindStr() const38e8d8bef9SDimitry Andric StringRef SymbolConjured::getKindStr() const { return "conj_$"; }
getKindStr() const39e8d8bef9SDimitry Andric StringRef SymbolDerived::getKindStr() const { return "derived_$"; }
getKindStr() const40e8d8bef9SDimitry Andric StringRef SymbolExtent::getKindStr() const { return "extent_$"; }
getKindStr() const41e8d8bef9SDimitry Andric StringRef SymbolMetadata::getKindStr() const { return "meta_$"; }
getKindStr() const42e8d8bef9SDimitry Andric StringRef SymbolRegionValue::getKindStr() const { return "reg_$"; }
43e8d8bef9SDimitry Andric 
dump() const445ffd83dbSDimitry Andric LLVM_DUMP_METHOD void SymExpr::dump() const { dumpToStream(llvm::errs()); }
455ffd83dbSDimitry Andric 
dumpToStreamImpl(raw_ostream & OS,const SymExpr * Sym)465ffd83dbSDimitry Andric void BinarySymExpr::dumpToStreamImpl(raw_ostream &OS, const SymExpr *Sym) {
475ffd83dbSDimitry Andric   OS << '(';
485ffd83dbSDimitry Andric   Sym->dumpToStream(OS);
495ffd83dbSDimitry Andric   OS << ')';
500b57cec5SDimitry Andric }
510b57cec5SDimitry Andric 
dumpToStreamImpl(raw_ostream & OS,const llvm::APSInt & Value)525ffd83dbSDimitry Andric void BinarySymExpr::dumpToStreamImpl(raw_ostream &OS,
535ffd83dbSDimitry Andric                                      const llvm::APSInt &Value) {
545ffd83dbSDimitry Andric   if (Value.isUnsigned())
555ffd83dbSDimitry Andric     OS << Value.getZExtValue();
560b57cec5SDimitry Andric   else
575ffd83dbSDimitry Andric     OS << Value.getSExtValue();
585ffd83dbSDimitry Andric   if (Value.isUnsigned())
595ffd83dbSDimitry Andric     OS << 'U';
600b57cec5SDimitry Andric }
610b57cec5SDimitry Andric 
dumpToStreamImpl(raw_ostream & OS,BinaryOperator::Opcode Op)625ffd83dbSDimitry Andric void BinarySymExpr::dumpToStreamImpl(raw_ostream &OS,
635ffd83dbSDimitry Andric                                      BinaryOperator::Opcode Op) {
645ffd83dbSDimitry Andric   OS << ' ' << BinaryOperator::getOpcodeStr(Op) << ' ';
650b57cec5SDimitry Andric }
660b57cec5SDimitry Andric 
dumpToStream(raw_ostream & os) const670b57cec5SDimitry Andric void SymbolCast::dumpToStream(raw_ostream &os) const {
6881ad6265SDimitry Andric   os << '(' << ToTy << ") (";
690b57cec5SDimitry Andric   Operand->dumpToStream(os);
700b57cec5SDimitry Andric   os << ')';
710b57cec5SDimitry Andric }
720b57cec5SDimitry Andric 
dumpToStream(raw_ostream & os) const7381ad6265SDimitry Andric void UnarySymExpr::dumpToStream(raw_ostream &os) const {
7481ad6265SDimitry Andric   os << UnaryOperator::getOpcodeStr(Op);
7581ad6265SDimitry Andric   bool Binary = isa<BinarySymExpr>(Operand);
7681ad6265SDimitry Andric   if (Binary)
7781ad6265SDimitry Andric     os << '(';
7881ad6265SDimitry Andric   Operand->dumpToStream(os);
7981ad6265SDimitry Andric   if (Binary)
8081ad6265SDimitry Andric     os << ')';
8181ad6265SDimitry Andric }
8281ad6265SDimitry Andric 
dumpToStream(raw_ostream & os) const830b57cec5SDimitry Andric void SymbolConjured::dumpToStream(raw_ostream &os) const {
8481ad6265SDimitry Andric   os << getKindStr() << getSymbolID() << '{' << T << ", LC" << LCtx->getID();
850b57cec5SDimitry Andric   if (S)
860b57cec5SDimitry Andric     os << ", S" << S->getID(LCtx->getDecl()->getASTContext());
870b57cec5SDimitry Andric   else
880b57cec5SDimitry Andric     os << ", no stmt";
890b57cec5SDimitry Andric   os << ", #" << Count << '}';
900b57cec5SDimitry Andric }
910b57cec5SDimitry Andric 
dumpToStream(raw_ostream & os) const920b57cec5SDimitry Andric void SymbolDerived::dumpToStream(raw_ostream &os) const {
93e8d8bef9SDimitry Andric   os << getKindStr() << getSymbolID() << '{' << getParentSymbol() << ','
94e8d8bef9SDimitry Andric      << getRegion() << '}';
950b57cec5SDimitry Andric }
960b57cec5SDimitry Andric 
dumpToStream(raw_ostream & os) const970b57cec5SDimitry Andric void SymbolExtent::dumpToStream(raw_ostream &os) const {
98e8d8bef9SDimitry Andric   os << getKindStr() << getSymbolID() << '{' << getRegion() << '}';
990b57cec5SDimitry Andric }
1000b57cec5SDimitry Andric 
dumpToStream(raw_ostream & os) const1010b57cec5SDimitry Andric void SymbolMetadata::dumpToStream(raw_ostream &os) const {
10281ad6265SDimitry Andric   os << getKindStr() << getSymbolID() << '{' << getRegion() << ',' << T << '}';
1030b57cec5SDimitry Andric }
1040b57cec5SDimitry Andric 
anchor()1050b57cec5SDimitry Andric void SymbolData::anchor() {}
1060b57cec5SDimitry Andric 
dumpToStream(raw_ostream & os) const1070b57cec5SDimitry Andric void SymbolRegionValue::dumpToStream(raw_ostream &os) const {
10881ad6265SDimitry Andric   os << getKindStr() << getSymbolID() << '<' << getType() << ' ' << R << '>';
1090b57cec5SDimitry Andric }
1100b57cec5SDimitry Andric 
operator ==(const symbol_iterator & X) const1110b57cec5SDimitry Andric bool SymExpr::symbol_iterator::operator==(const symbol_iterator &X) const {
1120b57cec5SDimitry Andric   return itr == X.itr;
1130b57cec5SDimitry Andric }
1140b57cec5SDimitry Andric 
operator !=(const symbol_iterator & X) const1150b57cec5SDimitry Andric bool SymExpr::symbol_iterator::operator!=(const symbol_iterator &X) const {
1160b57cec5SDimitry Andric   return itr != X.itr;
1170b57cec5SDimitry Andric }
1180b57cec5SDimitry Andric 
symbol_iterator(const SymExpr * SE)1190b57cec5SDimitry Andric SymExpr::symbol_iterator::symbol_iterator(const SymExpr *SE) {
1200b57cec5SDimitry Andric   itr.push_back(SE);
1210b57cec5SDimitry Andric }
1220b57cec5SDimitry Andric 
operator ++()1230b57cec5SDimitry Andric SymExpr::symbol_iterator &SymExpr::symbol_iterator::operator++() {
1240b57cec5SDimitry Andric   assert(!itr.empty() && "attempting to iterate on an 'end' iterator");
1250b57cec5SDimitry Andric   expand();
1260b57cec5SDimitry Andric   return *this;
1270b57cec5SDimitry Andric }
1280b57cec5SDimitry Andric 
operator *()1290b57cec5SDimitry Andric SymbolRef SymExpr::symbol_iterator::operator*() {
1300b57cec5SDimitry Andric   assert(!itr.empty() && "attempting to dereference an 'end' iterator");
1310b57cec5SDimitry Andric   return itr.back();
1320b57cec5SDimitry Andric }
1330b57cec5SDimitry Andric 
expand()1340b57cec5SDimitry Andric void SymExpr::symbol_iterator::expand() {
1350b57cec5SDimitry Andric   const SymExpr *SE = itr.pop_back_val();
1360b57cec5SDimitry Andric 
1370b57cec5SDimitry Andric   switch (SE->getKind()) {
1380b57cec5SDimitry Andric     case SymExpr::SymbolRegionValueKind:
1390b57cec5SDimitry Andric     case SymExpr::SymbolConjuredKind:
1400b57cec5SDimitry Andric     case SymExpr::SymbolDerivedKind:
1410b57cec5SDimitry Andric     case SymExpr::SymbolExtentKind:
1420b57cec5SDimitry Andric     case SymExpr::SymbolMetadataKind:
1430b57cec5SDimitry Andric       return;
1440b57cec5SDimitry Andric     case SymExpr::SymbolCastKind:
1450b57cec5SDimitry Andric       itr.push_back(cast<SymbolCast>(SE)->getOperand());
1460b57cec5SDimitry Andric       return;
14781ad6265SDimitry Andric     case SymExpr::UnarySymExprKind:
14881ad6265SDimitry Andric       itr.push_back(cast<UnarySymExpr>(SE)->getOperand());
14981ad6265SDimitry Andric       return;
1500b57cec5SDimitry Andric     case SymExpr::SymIntExprKind:
1510b57cec5SDimitry Andric       itr.push_back(cast<SymIntExpr>(SE)->getLHS());
1520b57cec5SDimitry Andric       return;
1530b57cec5SDimitry Andric     case SymExpr::IntSymExprKind:
1540b57cec5SDimitry Andric       itr.push_back(cast<IntSymExpr>(SE)->getRHS());
1550b57cec5SDimitry Andric       return;
1560b57cec5SDimitry Andric     case SymExpr::SymSymExprKind: {
1570b57cec5SDimitry Andric       const auto *x = cast<SymSymExpr>(SE);
1580b57cec5SDimitry Andric       itr.push_back(x->getLHS());
1590b57cec5SDimitry Andric       itr.push_back(x->getRHS());
1600b57cec5SDimitry Andric       return;
1610b57cec5SDimitry Andric     }
1620b57cec5SDimitry Andric   }
1630b57cec5SDimitry Andric   llvm_unreachable("unhandled expansion case");
1640b57cec5SDimitry Andric }
1650b57cec5SDimitry Andric 
1660b57cec5SDimitry Andric const SymbolRegionValue*
getRegionValueSymbol(const TypedValueRegion * R)1670b57cec5SDimitry Andric SymbolManager::getRegionValueSymbol(const TypedValueRegion* R) {
1680b57cec5SDimitry Andric   llvm::FoldingSetNodeID profile;
1690b57cec5SDimitry Andric   SymbolRegionValue::Profile(profile, R);
1700b57cec5SDimitry Andric   void *InsertPos;
1710b57cec5SDimitry Andric   SymExpr *SD = DataSet.FindNodeOrInsertPos(profile, InsertPos);
1720b57cec5SDimitry Andric   if (!SD) {
173*06c3fb27SDimitry Andric     SD = new (BPAlloc) SymbolRegionValue(SymbolCounter, R);
1740b57cec5SDimitry Andric     DataSet.InsertNode(SD, InsertPos);
1750b57cec5SDimitry Andric     ++SymbolCounter;
1760b57cec5SDimitry Andric   }
1770b57cec5SDimitry Andric 
1780b57cec5SDimitry Andric   return cast<SymbolRegionValue>(SD);
1790b57cec5SDimitry Andric }
1800b57cec5SDimitry Andric 
conjureSymbol(const Stmt * E,const LocationContext * LCtx,QualType T,unsigned Count,const void * SymbolTag)1810b57cec5SDimitry Andric const SymbolConjured* SymbolManager::conjureSymbol(const Stmt *E,
1820b57cec5SDimitry Andric                                                    const LocationContext *LCtx,
1830b57cec5SDimitry Andric                                                    QualType T,
1840b57cec5SDimitry Andric                                                    unsigned Count,
1850b57cec5SDimitry Andric                                                    const void *SymbolTag) {
1860b57cec5SDimitry Andric   llvm::FoldingSetNodeID profile;
1870b57cec5SDimitry Andric   SymbolConjured::Profile(profile, E, T, Count, LCtx, SymbolTag);
1880b57cec5SDimitry Andric   void *InsertPos;
1890b57cec5SDimitry Andric   SymExpr *SD = DataSet.FindNodeOrInsertPos(profile, InsertPos);
1900b57cec5SDimitry Andric   if (!SD) {
191*06c3fb27SDimitry Andric     SD = new (BPAlloc) SymbolConjured(SymbolCounter, E, LCtx, T, Count, SymbolTag);
1920b57cec5SDimitry Andric     DataSet.InsertNode(SD, InsertPos);
1930b57cec5SDimitry Andric     ++SymbolCounter;
1940b57cec5SDimitry Andric   }
1950b57cec5SDimitry Andric 
1960b57cec5SDimitry Andric   return cast<SymbolConjured>(SD);
1970b57cec5SDimitry Andric }
1980b57cec5SDimitry Andric 
1990b57cec5SDimitry Andric const SymbolDerived*
getDerivedSymbol(SymbolRef parentSymbol,const TypedValueRegion * R)2000b57cec5SDimitry Andric SymbolManager::getDerivedSymbol(SymbolRef parentSymbol,
2010b57cec5SDimitry Andric                                 const TypedValueRegion *R) {
2020b57cec5SDimitry Andric   llvm::FoldingSetNodeID profile;
2030b57cec5SDimitry Andric   SymbolDerived::Profile(profile, parentSymbol, R);
2040b57cec5SDimitry Andric   void *InsertPos;
2050b57cec5SDimitry Andric   SymExpr *SD = DataSet.FindNodeOrInsertPos(profile, InsertPos);
2060b57cec5SDimitry Andric   if (!SD) {
207*06c3fb27SDimitry Andric     SD = new (BPAlloc) SymbolDerived(SymbolCounter, parentSymbol, R);
2080b57cec5SDimitry Andric     DataSet.InsertNode(SD, InsertPos);
2090b57cec5SDimitry Andric     ++SymbolCounter;
2100b57cec5SDimitry Andric   }
2110b57cec5SDimitry Andric 
2120b57cec5SDimitry Andric   return cast<SymbolDerived>(SD);
2130b57cec5SDimitry Andric }
2140b57cec5SDimitry Andric 
2150b57cec5SDimitry Andric const SymbolExtent*
getExtentSymbol(const SubRegion * R)2160b57cec5SDimitry Andric SymbolManager::getExtentSymbol(const SubRegion *R) {
2170b57cec5SDimitry Andric   llvm::FoldingSetNodeID profile;
2180b57cec5SDimitry Andric   SymbolExtent::Profile(profile, R);
2190b57cec5SDimitry Andric   void *InsertPos;
2200b57cec5SDimitry Andric   SymExpr *SD = DataSet.FindNodeOrInsertPos(profile, InsertPos);
2210b57cec5SDimitry Andric   if (!SD) {
222*06c3fb27SDimitry Andric     SD = new (BPAlloc) SymbolExtent(SymbolCounter, R);
2230b57cec5SDimitry Andric     DataSet.InsertNode(SD, InsertPos);
2240b57cec5SDimitry Andric     ++SymbolCounter;
2250b57cec5SDimitry Andric   }
2260b57cec5SDimitry Andric 
2270b57cec5SDimitry Andric   return cast<SymbolExtent>(SD);
2280b57cec5SDimitry Andric }
2290b57cec5SDimitry Andric 
2300b57cec5SDimitry Andric const SymbolMetadata *
getMetadataSymbol(const MemRegion * R,const Stmt * S,QualType T,const LocationContext * LCtx,unsigned Count,const void * SymbolTag)2310b57cec5SDimitry Andric SymbolManager::getMetadataSymbol(const MemRegion* R, const Stmt *S, QualType T,
2320b57cec5SDimitry Andric                                  const LocationContext *LCtx,
2330b57cec5SDimitry Andric                                  unsigned Count, const void *SymbolTag) {
2340b57cec5SDimitry Andric   llvm::FoldingSetNodeID profile;
2350b57cec5SDimitry Andric   SymbolMetadata::Profile(profile, R, S, T, LCtx, Count, SymbolTag);
2360b57cec5SDimitry Andric   void *InsertPos;
2370b57cec5SDimitry Andric   SymExpr *SD = DataSet.FindNodeOrInsertPos(profile, InsertPos);
2380b57cec5SDimitry Andric   if (!SD) {
239*06c3fb27SDimitry Andric     SD = new (BPAlloc) SymbolMetadata(SymbolCounter, R, S, T, LCtx, Count, SymbolTag);
2400b57cec5SDimitry Andric     DataSet.InsertNode(SD, InsertPos);
2410b57cec5SDimitry Andric     ++SymbolCounter;
2420b57cec5SDimitry Andric   }
2430b57cec5SDimitry Andric 
2440b57cec5SDimitry Andric   return cast<SymbolMetadata>(SD);
2450b57cec5SDimitry Andric }
2460b57cec5SDimitry Andric 
2470b57cec5SDimitry Andric const SymbolCast*
getCastSymbol(const SymExpr * Op,QualType From,QualType To)2480b57cec5SDimitry Andric SymbolManager::getCastSymbol(const SymExpr *Op,
2490b57cec5SDimitry Andric                              QualType From, QualType To) {
2500b57cec5SDimitry Andric   llvm::FoldingSetNodeID ID;
2510b57cec5SDimitry Andric   SymbolCast::Profile(ID, Op, From, To);
2520b57cec5SDimitry Andric   void *InsertPos;
2530b57cec5SDimitry Andric   SymExpr *data = DataSet.FindNodeOrInsertPos(ID, InsertPos);
2540b57cec5SDimitry Andric   if (!data) {
255*06c3fb27SDimitry Andric     data = new (BPAlloc) SymbolCast(Op, From, To);
2560b57cec5SDimitry Andric     DataSet.InsertNode(data, InsertPos);
2570b57cec5SDimitry Andric   }
2580b57cec5SDimitry Andric 
2590b57cec5SDimitry Andric   return cast<SymbolCast>(data);
2600b57cec5SDimitry Andric }
2610b57cec5SDimitry Andric 
getSymIntExpr(const SymExpr * lhs,BinaryOperator::Opcode op,const llvm::APSInt & v,QualType t)2620b57cec5SDimitry Andric const SymIntExpr *SymbolManager::getSymIntExpr(const SymExpr *lhs,
2630b57cec5SDimitry Andric                                                BinaryOperator::Opcode op,
2640b57cec5SDimitry Andric                                                const llvm::APSInt& v,
2650b57cec5SDimitry Andric                                                QualType t) {
2660b57cec5SDimitry Andric   llvm::FoldingSetNodeID ID;
2670b57cec5SDimitry Andric   SymIntExpr::Profile(ID, lhs, op, v, t);
2680b57cec5SDimitry Andric   void *InsertPos;
2690b57cec5SDimitry Andric   SymExpr *data = DataSet.FindNodeOrInsertPos(ID, InsertPos);
2700b57cec5SDimitry Andric 
2710b57cec5SDimitry Andric   if (!data) {
272*06c3fb27SDimitry Andric     data = new (BPAlloc) SymIntExpr(lhs, op, v, t);
2730b57cec5SDimitry Andric     DataSet.InsertNode(data, InsertPos);
2740b57cec5SDimitry Andric   }
2750b57cec5SDimitry Andric 
2760b57cec5SDimitry Andric   return cast<SymIntExpr>(data);
2770b57cec5SDimitry Andric }
2780b57cec5SDimitry Andric 
getIntSymExpr(const llvm::APSInt & lhs,BinaryOperator::Opcode op,const SymExpr * rhs,QualType t)2790b57cec5SDimitry Andric const IntSymExpr *SymbolManager::getIntSymExpr(const llvm::APSInt& lhs,
2800b57cec5SDimitry Andric                                                BinaryOperator::Opcode op,
2810b57cec5SDimitry Andric                                                const SymExpr *rhs,
2820b57cec5SDimitry Andric                                                QualType t) {
2830b57cec5SDimitry Andric   llvm::FoldingSetNodeID ID;
2840b57cec5SDimitry Andric   IntSymExpr::Profile(ID, lhs, op, rhs, t);
2850b57cec5SDimitry Andric   void *InsertPos;
2860b57cec5SDimitry Andric   SymExpr *data = DataSet.FindNodeOrInsertPos(ID, InsertPos);
2870b57cec5SDimitry Andric 
2880b57cec5SDimitry Andric   if (!data) {
289*06c3fb27SDimitry Andric     data = new (BPAlloc) IntSymExpr(lhs, op, rhs, t);
2900b57cec5SDimitry Andric     DataSet.InsertNode(data, InsertPos);
2910b57cec5SDimitry Andric   }
2920b57cec5SDimitry Andric 
2930b57cec5SDimitry Andric   return cast<IntSymExpr>(data);
2940b57cec5SDimitry Andric }
2950b57cec5SDimitry Andric 
getSymSymExpr(const SymExpr * lhs,BinaryOperator::Opcode op,const SymExpr * rhs,QualType t)2960b57cec5SDimitry Andric const SymSymExpr *SymbolManager::getSymSymExpr(const SymExpr *lhs,
2970b57cec5SDimitry Andric                                                BinaryOperator::Opcode op,
2980b57cec5SDimitry Andric                                                const SymExpr *rhs,
2990b57cec5SDimitry Andric                                                QualType t) {
3000b57cec5SDimitry Andric   llvm::FoldingSetNodeID ID;
3010b57cec5SDimitry Andric   SymSymExpr::Profile(ID, lhs, op, rhs, t);
3020b57cec5SDimitry Andric   void *InsertPos;
3030b57cec5SDimitry Andric   SymExpr *data = DataSet.FindNodeOrInsertPos(ID, InsertPos);
3040b57cec5SDimitry Andric 
3050b57cec5SDimitry Andric   if (!data) {
306*06c3fb27SDimitry Andric     data = new (BPAlloc) SymSymExpr(lhs, op, rhs, t);
3070b57cec5SDimitry Andric     DataSet.InsertNode(data, InsertPos);
3080b57cec5SDimitry Andric   }
3090b57cec5SDimitry Andric 
3100b57cec5SDimitry Andric   return cast<SymSymExpr>(data);
3110b57cec5SDimitry Andric }
3120b57cec5SDimitry Andric 
getUnarySymExpr(const SymExpr * Operand,UnaryOperator::Opcode Opc,QualType T)31381ad6265SDimitry Andric const UnarySymExpr *SymbolManager::getUnarySymExpr(const SymExpr *Operand,
31481ad6265SDimitry Andric                                                    UnaryOperator::Opcode Opc,
31581ad6265SDimitry Andric                                                    QualType T) {
31681ad6265SDimitry Andric   llvm::FoldingSetNodeID ID;
31781ad6265SDimitry Andric   UnarySymExpr::Profile(ID, Operand, Opc, T);
31881ad6265SDimitry Andric   void *InsertPos;
31981ad6265SDimitry Andric   SymExpr *data = DataSet.FindNodeOrInsertPos(ID, InsertPos);
32081ad6265SDimitry Andric   if (!data) {
321*06c3fb27SDimitry Andric     data = new (BPAlloc) UnarySymExpr(Operand, Opc, T);
32281ad6265SDimitry Andric     DataSet.InsertNode(data, InsertPos);
32381ad6265SDimitry Andric   }
32481ad6265SDimitry Andric 
32581ad6265SDimitry Andric   return cast<UnarySymExpr>(data);
32681ad6265SDimitry Andric }
32781ad6265SDimitry Andric 
getType() const3280b57cec5SDimitry Andric QualType SymbolConjured::getType() const {
3290b57cec5SDimitry Andric   return T;
3300b57cec5SDimitry Andric }
3310b57cec5SDimitry Andric 
getType() const3320b57cec5SDimitry Andric QualType SymbolDerived::getType() const {
3330b57cec5SDimitry Andric   return R->getValueType();
3340b57cec5SDimitry Andric }
3350b57cec5SDimitry Andric 
getType() const3360b57cec5SDimitry Andric QualType SymbolExtent::getType() const {
3375ffd83dbSDimitry Andric   ASTContext &Ctx = R->getMemRegionManager().getContext();
3380b57cec5SDimitry Andric   return Ctx.getSizeType();
3390b57cec5SDimitry Andric }
3400b57cec5SDimitry Andric 
getType() const3410b57cec5SDimitry Andric QualType SymbolMetadata::getType() const {
3420b57cec5SDimitry Andric   return T;
3430b57cec5SDimitry Andric }
3440b57cec5SDimitry Andric 
getType() const3450b57cec5SDimitry Andric QualType SymbolRegionValue::getType() const {
3460b57cec5SDimitry Andric   return R->getValueType();
3470b57cec5SDimitry Andric }
3480b57cec5SDimitry Andric 
canSymbolicate(QualType T)3490b57cec5SDimitry Andric bool SymbolManager::canSymbolicate(QualType T) {
3500b57cec5SDimitry Andric   T = T.getCanonicalType();
3510b57cec5SDimitry Andric 
3520b57cec5SDimitry Andric   if (Loc::isLocType(T))
3530b57cec5SDimitry Andric     return true;
3540b57cec5SDimitry Andric 
3550b57cec5SDimitry Andric   if (T->isIntegralOrEnumerationType())
3560b57cec5SDimitry Andric     return true;
3570b57cec5SDimitry Andric 
3580b57cec5SDimitry Andric   if (T->isRecordType() && !T->isUnionType())
3590b57cec5SDimitry Andric     return true;
3600b57cec5SDimitry Andric 
3610b57cec5SDimitry Andric   return false;
3620b57cec5SDimitry Andric }
3630b57cec5SDimitry Andric 
addSymbolDependency(const SymbolRef Primary,const SymbolRef Dependent)3640b57cec5SDimitry Andric void SymbolManager::addSymbolDependency(const SymbolRef Primary,
3650b57cec5SDimitry Andric                                         const SymbolRef Dependent) {
3665ffd83dbSDimitry Andric   auto &dependencies = SymbolDependencies[Primary];
3675ffd83dbSDimitry Andric   if (!dependencies) {
3685ffd83dbSDimitry Andric     dependencies = std::make_unique<SymbolRefSmallVectorTy>();
3690b57cec5SDimitry Andric   }
3700b57cec5SDimitry Andric   dependencies->push_back(Dependent);
3710b57cec5SDimitry Andric }
3720b57cec5SDimitry Andric 
getDependentSymbols(const SymbolRef Primary)3730b57cec5SDimitry Andric const SymbolRefSmallVectorTy *SymbolManager::getDependentSymbols(
3740b57cec5SDimitry Andric                                                      const SymbolRef Primary) {
3750b57cec5SDimitry Andric   SymbolDependTy::const_iterator I = SymbolDependencies.find(Primary);
3760b57cec5SDimitry Andric   if (I == SymbolDependencies.end())
3770b57cec5SDimitry Andric     return nullptr;
3785ffd83dbSDimitry Andric   return I->second.get();
3790b57cec5SDimitry Andric }
3800b57cec5SDimitry Andric 
markDependentsLive(SymbolRef sym)3810b57cec5SDimitry Andric void SymbolReaper::markDependentsLive(SymbolRef sym) {
3820b57cec5SDimitry Andric   // Do not mark dependents more then once.
3830b57cec5SDimitry Andric   SymbolMapTy::iterator LI = TheLiving.find(sym);
3840b57cec5SDimitry Andric   assert(LI != TheLiving.end() && "The primary symbol is not live.");
3850b57cec5SDimitry Andric   if (LI->second == HaveMarkedDependents)
3860b57cec5SDimitry Andric     return;
3870b57cec5SDimitry Andric   LI->second = HaveMarkedDependents;
3880b57cec5SDimitry Andric 
3890b57cec5SDimitry Andric   if (const SymbolRefSmallVectorTy *Deps = SymMgr.getDependentSymbols(sym)) {
3900b57cec5SDimitry Andric     for (const auto I : *Deps) {
391*06c3fb27SDimitry Andric       if (TheLiving.contains(I))
3920b57cec5SDimitry Andric         continue;
3930b57cec5SDimitry Andric       markLive(I);
3940b57cec5SDimitry Andric     }
3950b57cec5SDimitry Andric   }
3960b57cec5SDimitry Andric }
3970b57cec5SDimitry Andric 
markLive(SymbolRef sym)3980b57cec5SDimitry Andric void SymbolReaper::markLive(SymbolRef sym) {
3990b57cec5SDimitry Andric   TheLiving[sym] = NotProcessed;
4000b57cec5SDimitry Andric   markDependentsLive(sym);
4010b57cec5SDimitry Andric }
4020b57cec5SDimitry Andric 
markLive(const MemRegion * region)4030b57cec5SDimitry Andric void SymbolReaper::markLive(const MemRegion *region) {
404bdd1243dSDimitry Andric   LiveRegionRoots.insert(region->getBaseRegion());
4050b57cec5SDimitry Andric   markElementIndicesLive(region);
4060b57cec5SDimitry Andric }
4070b57cec5SDimitry Andric 
markLazilyCopied(const clang::ento::MemRegion * region)408bdd1243dSDimitry Andric void SymbolReaper::markLazilyCopied(const clang::ento::MemRegion *region) {
409bdd1243dSDimitry Andric   LazilyCopiedRegionRoots.insert(region->getBaseRegion());
410bdd1243dSDimitry Andric }
411bdd1243dSDimitry Andric 
markElementIndicesLive(const MemRegion * region)4120b57cec5SDimitry Andric void SymbolReaper::markElementIndicesLive(const MemRegion *region) {
4130b57cec5SDimitry Andric   for (auto SR = dyn_cast<SubRegion>(region); SR;
4140b57cec5SDimitry Andric        SR = dyn_cast<SubRegion>(SR->getSuperRegion())) {
4150b57cec5SDimitry Andric     if (const auto ER = dyn_cast<ElementRegion>(SR)) {
4160b57cec5SDimitry Andric       SVal Idx = ER->getIndex();
417*06c3fb27SDimitry Andric       for (SymbolRef Sym : Idx.symbols())
418*06c3fb27SDimitry Andric         markLive(Sym);
4190b57cec5SDimitry Andric     }
4200b57cec5SDimitry Andric   }
4210b57cec5SDimitry Andric }
4220b57cec5SDimitry Andric 
markInUse(SymbolRef sym)4230b57cec5SDimitry Andric void SymbolReaper::markInUse(SymbolRef sym) {
4240b57cec5SDimitry Andric   if (isa<SymbolMetadata>(sym))
4250b57cec5SDimitry Andric     MetadataInUse.insert(sym);
4260b57cec5SDimitry Andric }
4270b57cec5SDimitry Andric 
isLiveRegion(const MemRegion * MR)4280b57cec5SDimitry Andric bool SymbolReaper::isLiveRegion(const MemRegion *MR) {
4290b57cec5SDimitry Andric   // TODO: For now, liveness of a memory region is equivalent to liveness of its
4300b57cec5SDimitry Andric   // base region. In fact we can do a bit better: say, if a particular FieldDecl
4310b57cec5SDimitry Andric   // is not used later in the path, we can diagnose a leak of a value within
4320b57cec5SDimitry Andric   // that field earlier than, say, the variable that contains the field dies.
4330b57cec5SDimitry Andric   MR = MR->getBaseRegion();
434bdd1243dSDimitry Andric   if (LiveRegionRoots.count(MR))
4350b57cec5SDimitry Andric     return true;
4360b57cec5SDimitry Andric 
4370b57cec5SDimitry Andric   if (const auto *SR = dyn_cast<SymbolicRegion>(MR))
4380b57cec5SDimitry Andric     return isLive(SR->getSymbol());
4390b57cec5SDimitry Andric 
4400b57cec5SDimitry Andric   if (const auto *VR = dyn_cast<VarRegion>(MR))
4410b57cec5SDimitry Andric     return isLive(VR, true);
4420b57cec5SDimitry Andric 
4430b57cec5SDimitry Andric   // FIXME: This is a gross over-approximation. What we really need is a way to
4440b57cec5SDimitry Andric   // tell if anything still refers to this region. Unlike SymbolicRegions,
4450b57cec5SDimitry Andric   // AllocaRegions don't have associated symbols, though, so we don't actually
4460b57cec5SDimitry Andric   // have a way to track their liveness.
447349cc55cSDimitry Andric   return isa<AllocaRegion, CXXThisRegion, MemSpaceRegion, CodeTextRegion>(MR);
4480b57cec5SDimitry Andric }
4490b57cec5SDimitry Andric 
isLazilyCopiedRegion(const MemRegion * MR) const450bdd1243dSDimitry Andric bool SymbolReaper::isLazilyCopiedRegion(const MemRegion *MR) const {
451bdd1243dSDimitry Andric   // TODO: See comment in isLiveRegion.
452bdd1243dSDimitry Andric   return LazilyCopiedRegionRoots.count(MR->getBaseRegion());
453bdd1243dSDimitry Andric }
454bdd1243dSDimitry Andric 
isReadableRegion(const MemRegion * MR)455bdd1243dSDimitry Andric bool SymbolReaper::isReadableRegion(const MemRegion *MR) {
456bdd1243dSDimitry Andric   return isLiveRegion(MR) || isLazilyCopiedRegion(MR);
457bdd1243dSDimitry Andric }
458bdd1243dSDimitry Andric 
isLive(SymbolRef sym)4590b57cec5SDimitry Andric bool SymbolReaper::isLive(SymbolRef sym) {
4600b57cec5SDimitry Andric   if (TheLiving.count(sym)) {
4610b57cec5SDimitry Andric     markDependentsLive(sym);
4620b57cec5SDimitry Andric     return true;
4630b57cec5SDimitry Andric   }
4640b57cec5SDimitry Andric 
4650b57cec5SDimitry Andric   bool KnownLive;
4660b57cec5SDimitry Andric 
4670b57cec5SDimitry Andric   switch (sym->getKind()) {
4680b57cec5SDimitry Andric   case SymExpr::SymbolRegionValueKind:
469bdd1243dSDimitry Andric     KnownLive = isReadableRegion(cast<SymbolRegionValue>(sym)->getRegion());
4700b57cec5SDimitry Andric     break;
4710b57cec5SDimitry Andric   case SymExpr::SymbolConjuredKind:
4720b57cec5SDimitry Andric     KnownLive = false;
4730b57cec5SDimitry Andric     break;
4740b57cec5SDimitry Andric   case SymExpr::SymbolDerivedKind:
4750b57cec5SDimitry Andric     KnownLive = isLive(cast<SymbolDerived>(sym)->getParentSymbol());
4760b57cec5SDimitry Andric     break;
4770b57cec5SDimitry Andric   case SymExpr::SymbolExtentKind:
4780b57cec5SDimitry Andric     KnownLive = isLiveRegion(cast<SymbolExtent>(sym)->getRegion());
4790b57cec5SDimitry Andric     break;
4800b57cec5SDimitry Andric   case SymExpr::SymbolMetadataKind:
4810b57cec5SDimitry Andric     KnownLive = MetadataInUse.count(sym) &&
4820b57cec5SDimitry Andric                 isLiveRegion(cast<SymbolMetadata>(sym)->getRegion());
4830b57cec5SDimitry Andric     if (KnownLive)
4840b57cec5SDimitry Andric       MetadataInUse.erase(sym);
4850b57cec5SDimitry Andric     break;
4860b57cec5SDimitry Andric   case SymExpr::SymIntExprKind:
4870b57cec5SDimitry Andric     KnownLive = isLive(cast<SymIntExpr>(sym)->getLHS());
4880b57cec5SDimitry Andric     break;
4890b57cec5SDimitry Andric   case SymExpr::IntSymExprKind:
4900b57cec5SDimitry Andric     KnownLive = isLive(cast<IntSymExpr>(sym)->getRHS());
4910b57cec5SDimitry Andric     break;
4920b57cec5SDimitry Andric   case SymExpr::SymSymExprKind:
4930b57cec5SDimitry Andric     KnownLive = isLive(cast<SymSymExpr>(sym)->getLHS()) &&
4940b57cec5SDimitry Andric                 isLive(cast<SymSymExpr>(sym)->getRHS());
4950b57cec5SDimitry Andric     break;
4960b57cec5SDimitry Andric   case SymExpr::SymbolCastKind:
4970b57cec5SDimitry Andric     KnownLive = isLive(cast<SymbolCast>(sym)->getOperand());
4980b57cec5SDimitry Andric     break;
49981ad6265SDimitry Andric   case SymExpr::UnarySymExprKind:
50081ad6265SDimitry Andric     KnownLive = isLive(cast<UnarySymExpr>(sym)->getOperand());
50181ad6265SDimitry Andric     break;
5020b57cec5SDimitry Andric   }
5030b57cec5SDimitry Andric 
5040b57cec5SDimitry Andric   if (KnownLive)
5050b57cec5SDimitry Andric     markLive(sym);
5060b57cec5SDimitry Andric 
5070b57cec5SDimitry Andric   return KnownLive;
5080b57cec5SDimitry Andric }
5090b57cec5SDimitry Andric 
5100b57cec5SDimitry Andric bool
isLive(const Expr * ExprVal,const LocationContext * ELCtx) const511e8d8bef9SDimitry Andric SymbolReaper::isLive(const Expr *ExprVal, const LocationContext *ELCtx) const {
5120b57cec5SDimitry Andric   if (LCtx == nullptr)
5130b57cec5SDimitry Andric     return false;
5140b57cec5SDimitry Andric 
5150b57cec5SDimitry Andric   if (LCtx != ELCtx) {
5160b57cec5SDimitry Andric     // If the reaper's location context is a parent of the expression's
5170b57cec5SDimitry Andric     // location context, then the expression value is now "out of scope".
5180b57cec5SDimitry Andric     if (LCtx->isParentOf(ELCtx))
5190b57cec5SDimitry Andric       return false;
5200b57cec5SDimitry Andric     return true;
5210b57cec5SDimitry Andric   }
5220b57cec5SDimitry Andric 
523e8d8bef9SDimitry Andric   // If no statement is provided, everything in this and parent contexts is
524e8d8bef9SDimitry Andric   // live.
5250b57cec5SDimitry Andric   if (!Loc)
5260b57cec5SDimitry Andric     return true;
5270b57cec5SDimitry Andric 
5280b57cec5SDimitry Andric   return LCtx->getAnalysis<RelaxedLiveVariables>()->isLive(Loc, ExprVal);
5290b57cec5SDimitry Andric }
5300b57cec5SDimitry Andric 
isLive(const VarRegion * VR,bool includeStoreBindings) const5310b57cec5SDimitry Andric bool SymbolReaper::isLive(const VarRegion *VR, bool includeStoreBindings) const{
5320b57cec5SDimitry Andric   const StackFrameContext *VarContext = VR->getStackFrame();
5330b57cec5SDimitry Andric 
5340b57cec5SDimitry Andric   if (!VarContext)
5350b57cec5SDimitry Andric     return true;
5360b57cec5SDimitry Andric 
5370b57cec5SDimitry Andric   if (!LCtx)
5380b57cec5SDimitry Andric     return false;
5390b57cec5SDimitry Andric   const StackFrameContext *CurrentContext = LCtx->getStackFrame();
5400b57cec5SDimitry Andric 
5410b57cec5SDimitry Andric   if (VarContext == CurrentContext) {
5420b57cec5SDimitry Andric     // If no statement is provided, everything is live.
5430b57cec5SDimitry Andric     if (!Loc)
5440b57cec5SDimitry Andric       return true;
5450b57cec5SDimitry Andric 
5465ffd83dbSDimitry Andric     // Anonymous parameters of an inheriting constructor are live for the entire
5475ffd83dbSDimitry Andric     // duration of the constructor.
5485ffd83dbSDimitry Andric     if (isa<CXXInheritedCtorInitExpr>(Loc))
5495ffd83dbSDimitry Andric       return true;
5505ffd83dbSDimitry Andric 
5510b57cec5SDimitry Andric     if (LCtx->getAnalysis<RelaxedLiveVariables>()->isLive(Loc, VR->getDecl()))
5520b57cec5SDimitry Andric       return true;
5530b57cec5SDimitry Andric 
5540b57cec5SDimitry Andric     if (!includeStoreBindings)
5550b57cec5SDimitry Andric       return false;
5560b57cec5SDimitry Andric 
5570b57cec5SDimitry Andric     unsigned &cachedQuery =
5580b57cec5SDimitry Andric       const_cast<SymbolReaper *>(this)->includedRegionCache[VR];
5590b57cec5SDimitry Andric 
5600b57cec5SDimitry Andric     if (cachedQuery) {
5610b57cec5SDimitry Andric       return cachedQuery == 1;
5620b57cec5SDimitry Andric     }
5630b57cec5SDimitry Andric 
5640b57cec5SDimitry Andric     // Query the store to see if the region occurs in any live bindings.
5650b57cec5SDimitry Andric     if (Store store = reapedStore.getStore()) {
5660b57cec5SDimitry Andric       bool hasRegion =
5670b57cec5SDimitry Andric         reapedStore.getStoreManager().includedInBindings(store, VR);
5680b57cec5SDimitry Andric       cachedQuery = hasRegion ? 1 : 2;
5690b57cec5SDimitry Andric       return hasRegion;
5700b57cec5SDimitry Andric     }
5710b57cec5SDimitry Andric 
5720b57cec5SDimitry Andric     return false;
5730b57cec5SDimitry Andric   }
5740b57cec5SDimitry Andric 
5750b57cec5SDimitry Andric   return VarContext->isParentOf(CurrentContext);
5760b57cec5SDimitry Andric }
577