2008-02-16 09:12:31 +08:00
|
|
|
//== SymbolManager.h - Management of Symbolic Values ------------*- C++ -*--==//
|
|
|
|
//
|
|
|
|
// The LLVM Compiler Infrastructure
|
|
|
|
//
|
|
|
|
// This file is distributed under the University of Illinois Open Source
|
|
|
|
// License. See LICENSE.TXT for details.
|
|
|
|
//
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
//
|
2008-03-06 18:40:09 +08:00
|
|
|
// This file defines SymbolManager, a class that manages symbolic values
|
2010-12-23 02:53:44 +08:00
|
|
|
// created for use by ExprEngine and related classes.
|
2008-02-16 09:12:31 +08:00
|
|
|
//
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
|
2011-02-10 09:03:03 +08:00
|
|
|
#include "clang/StaticAnalyzer/Core/PathSensitive/SymbolManager.h"
|
2010-03-28 05:19:47 +08:00
|
|
|
#include "clang/Analysis/Analyses/LiveVariables.h"
|
2011-02-10 09:03:03 +08:00
|
|
|
#include "clang/StaticAnalyzer/Core/PathSensitive/MemRegion.h"
|
2011-07-29 07:07:59 +08:00
|
|
|
#include "clang/StaticAnalyzer/Core/PathSensitive/Store.h"
|
2008-12-05 10:45:20 +08:00
|
|
|
#include "llvm/Support/raw_ostream.h"
|
2008-02-16 09:12:31 +08:00
|
|
|
|
|
|
|
using namespace clang;
|
2010-12-23 15:20:52 +08:00
|
|
|
using namespace ento;
|
2008-02-16 09:12:31 +08:00
|
|
|
|
2011-12-20 10:48:34 +08:00
|
|
|
void SymExpr::anchor() { }
|
|
|
|
|
2009-07-14 07:31:04 +08:00
|
|
|
void SymExpr::dump() const {
|
|
|
|
dumpToStream(llvm::errs());
|
|
|
|
}
|
2009-03-26 11:35:11 +08:00
|
|
|
|
2011-08-13 07:37:29 +08:00
|
|
|
void SymIntExpr::dumpToStream(raw_ostream &os) const {
|
2009-03-26 11:35:11 +08:00
|
|
|
os << '(';
|
2009-07-14 07:31:04 +08:00
|
|
|
getLHS()->dumpToStream(os);
|
2013-03-16 05:41:50 +08:00
|
|
|
os << ") "
|
|
|
|
<< BinaryOperator::getOpcodeStr(getOpcode()) << ' '
|
|
|
|
<< getRHS().getZExtValue();
|
|
|
|
if (getRHS().isUnsigned())
|
|
|
|
os << 'U';
|
2009-03-26 11:35:11 +08:00
|
|
|
}
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2011-12-11 07:36:51 +08:00
|
|
|
void IntSymExpr::dumpToStream(raw_ostream &os) const {
|
2013-03-16 05:41:50 +08:00
|
|
|
os << getLHS().getZExtValue();
|
|
|
|
if (getLHS().isUnsigned())
|
|
|
|
os << 'U';
|
|
|
|
os << ' '
|
|
|
|
<< BinaryOperator::getOpcodeStr(getOpcode())
|
|
|
|
<< " (";
|
2011-12-11 07:36:51 +08:00
|
|
|
getRHS()->dumpToStream(os);
|
2013-03-16 05:41:50 +08:00
|
|
|
os << ')';
|
2011-12-11 07:36:51 +08:00
|
|
|
}
|
|
|
|
|
2011-08-13 07:37:29 +08:00
|
|
|
void SymSymExpr::dumpToStream(raw_ostream &os) const {
|
2009-03-26 11:35:11 +08:00
|
|
|
os << '(';
|
2009-07-14 07:31:04 +08:00
|
|
|
getLHS()->dumpToStream(os);
|
2013-03-16 05:41:50 +08:00
|
|
|
os << ") "
|
|
|
|
<< BinaryOperator::getOpcodeStr(getOpcode())
|
|
|
|
<< " (";
|
2009-07-14 07:31:04 +08:00
|
|
|
getRHS()->dumpToStream(os);
|
2009-09-09 23:08:12 +08:00
|
|
|
os << ')';
|
2009-03-26 11:35:11 +08:00
|
|
|
}
|
|
|
|
|
2011-12-07 07:12:27 +08:00
|
|
|
void SymbolCast::dumpToStream(raw_ostream &os) const {
|
|
|
|
os << '(' << ToTy.getAsString() << ") (";
|
|
|
|
Operand->dumpToStream(os);
|
|
|
|
os << ')';
|
|
|
|
}
|
|
|
|
|
2011-08-13 07:37:29 +08:00
|
|
|
void SymbolConjured::dumpToStream(raw_ostream &os) const {
|
2009-08-01 14:17:29 +08:00
|
|
|
os << "conj_$" << getSymbolID() << '{' << T.getAsString() << '}';
|
2009-03-26 11:35:11 +08:00
|
|
|
}
|
|
|
|
|
2011-08-13 07:37:29 +08:00
|
|
|
void SymbolDerived::dumpToStream(raw_ostream &os) const {
|
2009-07-15 10:27:32 +08:00
|
|
|
os << "derived_$" << getSymbolID() << '{'
|
|
|
|
<< getParentSymbol() << ',' << getRegion() << '}';
|
|
|
|
}
|
|
|
|
|
2011-08-13 07:37:29 +08:00
|
|
|
void SymbolExtent::dumpToStream(raw_ostream &os) const {
|
2010-07-04 08:00:41 +08:00
|
|
|
os << "extent_$" << getSymbolID() << '{' << getRegion() << '}';
|
|
|
|
}
|
|
|
|
|
2011-08-13 07:37:29 +08:00
|
|
|
void SymbolMetadata::dumpToStream(raw_ostream &os) const {
|
2010-08-15 04:18:45 +08:00
|
|
|
os << "meta_$" << getSymbolID() << '{'
|
|
|
|
<< getRegion() << ',' << T.getAsString() << '}';
|
|
|
|
}
|
|
|
|
|
2011-12-20 10:48:34 +08:00
|
|
|
void SymbolData::anchor() { }
|
|
|
|
|
2011-08-13 07:37:29 +08:00
|
|
|
void SymbolRegionValue::dumpToStream(raw_ostream &os) const {
|
2009-07-14 07:31:04 +08:00
|
|
|
os << "reg_$" << getSymbolID() << "<" << R << ">";
|
2009-03-04 06:06:47 +08:00
|
|
|
}
|
|
|
|
|
2011-12-07 07:12:33 +08:00
|
|
|
bool SymExpr::symbol_iterator::operator==(const symbol_iterator &X) const {
|
|
|
|
return itr == X.itr;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool SymExpr::symbol_iterator::operator!=(const symbol_iterator &X) const {
|
|
|
|
return itr != X.itr;
|
|
|
|
}
|
|
|
|
|
|
|
|
SymExpr::symbol_iterator::symbol_iterator(const SymExpr *SE) {
|
|
|
|
itr.push_back(SE);
|
|
|
|
}
|
|
|
|
|
|
|
|
SymExpr::symbol_iterator &SymExpr::symbol_iterator::operator++() {
|
|
|
|
assert(!itr.empty() && "attempting to iterate on an 'end' iterator");
|
2012-09-26 03:03:06 +08:00
|
|
|
expand();
|
2011-12-07 07:12:33 +08:00
|
|
|
return *this;
|
|
|
|
}
|
|
|
|
|
|
|
|
SymbolRef SymExpr::symbol_iterator::operator*() {
|
|
|
|
assert(!itr.empty() && "attempting to dereference an 'end' iterator");
|
2012-09-26 03:03:06 +08:00
|
|
|
return itr.back();
|
2011-12-07 07:12:33 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
void SymExpr::symbol_iterator::expand() {
|
2013-08-24 00:11:15 +08:00
|
|
|
const SymExpr *SE = itr.pop_back_val();
|
2011-12-07 07:12:33 +08:00
|
|
|
|
2011-12-11 07:36:51 +08:00
|
|
|
switch (SE->getKind()) {
|
|
|
|
case SymExpr::RegionValueKind:
|
|
|
|
case SymExpr::ConjuredKind:
|
|
|
|
case SymExpr::DerivedKind:
|
|
|
|
case SymExpr::ExtentKind:
|
|
|
|
case SymExpr::MetadataKind:
|
|
|
|
return;
|
|
|
|
case SymExpr::CastSymbolKind:
|
|
|
|
itr.push_back(cast<SymbolCast>(SE)->getOperand());
|
|
|
|
return;
|
|
|
|
case SymExpr::SymIntKind:
|
|
|
|
itr.push_back(cast<SymIntExpr>(SE)->getLHS());
|
|
|
|
return;
|
|
|
|
case SymExpr::IntSymKind:
|
|
|
|
itr.push_back(cast<IntSymExpr>(SE)->getRHS());
|
|
|
|
return;
|
|
|
|
case SymExpr::SymSymKind: {
|
|
|
|
const SymSymExpr *x = cast<SymSymExpr>(SE);
|
|
|
|
itr.push_back(x->getLHS());
|
|
|
|
itr.push_back(x->getRHS());
|
|
|
|
return;
|
|
|
|
}
|
2011-12-07 07:12:33 +08:00
|
|
|
}
|
|
|
|
llvm_unreachable("unhandled expansion case");
|
|
|
|
}
|
|
|
|
|
2012-05-03 10:13:50 +08:00
|
|
|
unsigned SymExpr::computeComplexity() const {
|
|
|
|
unsigned R = 0;
|
|
|
|
for (symbol_iterator I = symbol_begin(), E = symbol_end(); I != E; ++I)
|
|
|
|
R++;
|
|
|
|
return R;
|
|
|
|
}
|
|
|
|
|
2009-09-09 23:08:12 +08:00
|
|
|
const SymbolRegionValue*
|
2011-08-13 04:02:48 +08:00
|
|
|
SymbolManager::getRegionValueSymbol(const TypedValueRegion* R) {
|
2008-03-12 09:21:45 +08:00
|
|
|
llvm::FoldingSetNodeID profile;
|
2010-03-01 14:56:52 +08:00
|
|
|
SymbolRegionValue::Profile(profile, R);
|
2011-08-13 07:37:29 +08:00
|
|
|
void *InsertPos;
|
2009-09-09 23:08:12 +08:00
|
|
|
SymExpr *SD = DataSet.FindNodeOrInsertPos(profile, InsertPos);
|
|
|
|
if (!SD) {
|
2009-05-09 12:08:27 +08:00
|
|
|
SD = (SymExpr*) BPAlloc.Allocate<SymbolRegionValue>();
|
2010-03-01 14:56:52 +08:00
|
|
|
new (SD) SymbolRegionValue(SymbolCounter, R);
|
2009-03-26 11:35:11 +08:00
|
|
|
DataSet.InsertNode(SD, InsertPos);
|
|
|
|
++SymbolCounter;
|
|
|
|
}
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2009-05-09 12:08:27 +08:00
|
|
|
return cast<SymbolRegionValue>(SD);
|
2008-11-19 19:03:17 +08:00
|
|
|
}
|
2008-03-12 09:21:45 +08:00
|
|
|
|
2012-08-22 14:26:06 +08:00
|
|
|
const SymbolConjured* SymbolManager::conjureSymbol(const Stmt *E,
|
|
|
|
const LocationContext *LCtx,
|
|
|
|
QualType T,
|
|
|
|
unsigned Count,
|
|
|
|
const void *SymbolTag) {
|
2008-03-12 09:21:45 +08:00
|
|
|
llvm::FoldingSetNodeID profile;
|
2012-02-18 07:13:45 +08:00
|
|
|
SymbolConjured::Profile(profile, E, T, Count, LCtx, SymbolTag);
|
2011-08-13 07:37:29 +08:00
|
|
|
void *InsertPos;
|
2009-09-09 23:08:12 +08:00
|
|
|
SymExpr *SD = DataSet.FindNodeOrInsertPos(profile, InsertPos);
|
|
|
|
if (!SD) {
|
2009-03-26 11:35:11 +08:00
|
|
|
SD = (SymExpr*) BPAlloc.Allocate<SymbolConjured>();
|
2012-02-18 07:13:45 +08:00
|
|
|
new (SD) SymbolConjured(SymbolCounter, E, LCtx, T, Count, SymbolTag);
|
2009-09-09 23:08:12 +08:00
|
|
|
DataSet.InsertNode(SD, InsertPos);
|
2009-03-26 11:35:11 +08:00
|
|
|
++SymbolCounter;
|
|
|
|
}
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2009-03-26 11:35:11 +08:00
|
|
|
return cast<SymbolConjured>(SD);
|
2008-03-12 09:21:45 +08:00
|
|
|
}
|
|
|
|
|
2009-07-15 10:27:32 +08:00
|
|
|
const SymbolDerived*
|
|
|
|
SymbolManager::getDerivedSymbol(SymbolRef parentSymbol,
|
2011-08-13 04:02:48 +08:00
|
|
|
const TypedValueRegion *R) {
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2009-07-15 10:27:32 +08:00
|
|
|
llvm::FoldingSetNodeID profile;
|
|
|
|
SymbolDerived::Profile(profile, parentSymbol, R);
|
2011-08-13 07:37:29 +08:00
|
|
|
void *InsertPos;
|
2009-09-09 23:08:12 +08:00
|
|
|
SymExpr *SD = DataSet.FindNodeOrInsertPos(profile, InsertPos);
|
|
|
|
if (!SD) {
|
2009-07-15 10:27:32 +08:00
|
|
|
SD = (SymExpr*) BPAlloc.Allocate<SymbolDerived>();
|
|
|
|
new (SD) SymbolDerived(SymbolCounter, parentSymbol, R);
|
2009-09-09 23:08:12 +08:00
|
|
|
DataSet.InsertNode(SD, InsertPos);
|
2009-07-15 10:27:32 +08:00
|
|
|
++SymbolCounter;
|
|
|
|
}
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2009-07-15 10:27:32 +08:00
|
|
|
return cast<SymbolDerived>(SD);
|
|
|
|
}
|
|
|
|
|
2010-07-04 08:00:41 +08:00
|
|
|
const SymbolExtent*
|
|
|
|
SymbolManager::getExtentSymbol(const SubRegion *R) {
|
|
|
|
llvm::FoldingSetNodeID profile;
|
|
|
|
SymbolExtent::Profile(profile, R);
|
2011-08-13 07:37:29 +08:00
|
|
|
void *InsertPos;
|
2010-07-04 08:00:41 +08:00
|
|
|
SymExpr *SD = DataSet.FindNodeOrInsertPos(profile, InsertPos);
|
|
|
|
if (!SD) {
|
|
|
|
SD = (SymExpr*) BPAlloc.Allocate<SymbolExtent>();
|
|
|
|
new (SD) SymbolExtent(SymbolCounter, R);
|
|
|
|
DataSet.InsertNode(SD, InsertPos);
|
|
|
|
++SymbolCounter;
|
|
|
|
}
|
|
|
|
|
|
|
|
return cast<SymbolExtent>(SD);
|
|
|
|
}
|
|
|
|
|
2010-08-15 04:18:45 +08:00
|
|
|
const SymbolMetadata*
|
2011-08-13 07:37:29 +08:00
|
|
|
SymbolManager::getMetadataSymbol(const MemRegion* R, const Stmt *S, QualType T,
|
|
|
|
unsigned Count, const void *SymbolTag) {
|
2010-08-15 04:18:45 +08:00
|
|
|
|
|
|
|
llvm::FoldingSetNodeID profile;
|
|
|
|
SymbolMetadata::Profile(profile, R, S, T, Count, SymbolTag);
|
2011-08-13 07:37:29 +08:00
|
|
|
void *InsertPos;
|
2010-08-15 04:18:45 +08:00
|
|
|
SymExpr *SD = DataSet.FindNodeOrInsertPos(profile, InsertPos);
|
|
|
|
if (!SD) {
|
|
|
|
SD = (SymExpr*) BPAlloc.Allocate<SymbolMetadata>();
|
|
|
|
new (SD) SymbolMetadata(SymbolCounter, R, S, T, Count, SymbolTag);
|
|
|
|
DataSet.InsertNode(SD, InsertPos);
|
|
|
|
++SymbolCounter;
|
|
|
|
}
|
|
|
|
|
|
|
|
return cast<SymbolMetadata>(SD);
|
|
|
|
}
|
|
|
|
|
2011-12-07 07:12:27 +08:00
|
|
|
const SymbolCast*
|
|
|
|
SymbolManager::getCastSymbol(const SymExpr *Op,
|
|
|
|
QualType From, QualType To) {
|
|
|
|
llvm::FoldingSetNodeID ID;
|
|
|
|
SymbolCast::Profile(ID, Op, From, To);
|
|
|
|
void *InsertPos;
|
|
|
|
SymExpr *data = DataSet.FindNodeOrInsertPos(ID, InsertPos);
|
|
|
|
if (!data) {
|
|
|
|
data = (SymbolCast*) BPAlloc.Allocate<SymbolCast>();
|
|
|
|
new (data) SymbolCast(Op, From, To);
|
|
|
|
DataSet.InsertNode(data, InsertPos);
|
|
|
|
}
|
|
|
|
|
|
|
|
return cast<SymbolCast>(data);
|
|
|
|
}
|
|
|
|
|
2009-03-26 11:35:11 +08:00
|
|
|
const SymIntExpr *SymbolManager::getSymIntExpr(const SymExpr *lhs,
|
2009-09-09 23:08:12 +08:00
|
|
|
BinaryOperator::Opcode op,
|
2009-03-26 11:35:11 +08:00
|
|
|
const llvm::APSInt& v,
|
|
|
|
QualType t) {
|
2009-03-25 13:58:37 +08:00
|
|
|
llvm::FoldingSetNodeID ID;
|
|
|
|
SymIntExpr::Profile(ID, lhs, op, v, t);
|
2009-03-26 11:35:11 +08:00
|
|
|
void *InsertPos;
|
|
|
|
SymExpr *data = DataSet.FindNodeOrInsertPos(ID, InsertPos);
|
|
|
|
|
|
|
|
if (!data) {
|
|
|
|
data = (SymIntExpr*) BPAlloc.Allocate<SymIntExpr>();
|
|
|
|
new (data) SymIntExpr(lhs, op, v, t);
|
|
|
|
DataSet.InsertNode(data, InsertPos);
|
|
|
|
}
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2009-03-26 11:35:11 +08:00
|
|
|
return cast<SymIntExpr>(data);
|
2009-03-25 13:58:37 +08:00
|
|
|
}
|
|
|
|
|
2011-12-11 07:36:51 +08:00
|
|
|
const IntSymExpr *SymbolManager::getIntSymExpr(const llvm::APSInt& lhs,
|
|
|
|
BinaryOperator::Opcode op,
|
|
|
|
const SymExpr *rhs,
|
|
|
|
QualType t) {
|
|
|
|
llvm::FoldingSetNodeID ID;
|
|
|
|
IntSymExpr::Profile(ID, lhs, op, rhs, t);
|
|
|
|
void *InsertPos;
|
|
|
|
SymExpr *data = DataSet.FindNodeOrInsertPos(ID, InsertPos);
|
|
|
|
|
|
|
|
if (!data) {
|
|
|
|
data = (IntSymExpr*) BPAlloc.Allocate<IntSymExpr>();
|
|
|
|
new (data) IntSymExpr(lhs, op, rhs, t);
|
|
|
|
DataSet.InsertNode(data, InsertPos);
|
|
|
|
}
|
|
|
|
|
|
|
|
return cast<IntSymExpr>(data);
|
|
|
|
}
|
|
|
|
|
2009-03-26 11:35:11 +08:00
|
|
|
const SymSymExpr *SymbolManager::getSymSymExpr(const SymExpr *lhs,
|
|
|
|
BinaryOperator::Opcode op,
|
|
|
|
const SymExpr *rhs,
|
|
|
|
QualType t) {
|
2009-03-25 13:58:37 +08:00
|
|
|
llvm::FoldingSetNodeID ID;
|
|
|
|
SymSymExpr::Profile(ID, lhs, op, rhs, t);
|
2009-03-26 11:35:11 +08:00
|
|
|
void *InsertPos;
|
|
|
|
SymExpr *data = DataSet.FindNodeOrInsertPos(ID, InsertPos);
|
|
|
|
|
|
|
|
if (!data) {
|
|
|
|
data = (SymSymExpr*) BPAlloc.Allocate<SymSymExpr>();
|
|
|
|
new (data) SymSymExpr(lhs, op, rhs, t);
|
|
|
|
DataSet.InsertNode(data, InsertPos);
|
|
|
|
}
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2009-03-26 11:35:11 +08:00
|
|
|
return cast<SymSymExpr>(data);
|
2008-03-12 09:21:45 +08:00
|
|
|
}
|
|
|
|
|
2012-09-26 14:00:14 +08:00
|
|
|
QualType SymbolConjured::getType() const {
|
Static analyzer: Remove a bunch of outdated SymbolData objects and
their associated APIs. We no longer need separate SymbolData objects
for fields, variables, etc. Instead, we now associated symbols with
the "rvalue" of a MemRegion (i.e., the value stored at that region).
Now we only have two kinds of SymbolData objects: SymbolRegionRValue
and SymbolConjured.
This cleanup also makes the distinction between a SymbolicRegion and a
symbolic value that is a location much clearer. A SymbolicRegion
represents a chunk of symbolic memory, while a symbolic location is
just a "pointer" with different possible values. Without any specific
knowledge, a symbolic location resolves (i.e., via a dereference) to a
SymbolicRegion. In the future, when we do better alias reasoning, a
symbolic location can become an alias for another location, thus
merging the constraints on the referred SymbolicRegion with the other
region.
llvm-svn: 62769
2009-01-23 02:23:34 +08:00
|
|
|
return T;
|
|
|
|
}
|
2008-12-05 09:31:31 +08:00
|
|
|
|
2012-09-26 14:00:14 +08:00
|
|
|
QualType SymbolDerived::getType() const {
|
2010-08-11 14:10:55 +08:00
|
|
|
return R->getValueType();
|
2009-07-15 10:27:32 +08:00
|
|
|
}
|
|
|
|
|
2012-09-26 14:00:14 +08:00
|
|
|
QualType SymbolExtent::getType() const {
|
|
|
|
ASTContext &Ctx = R->getMemRegionManager()->getContext();
|
2010-07-04 08:00:41 +08:00
|
|
|
return Ctx.getSizeType();
|
|
|
|
}
|
|
|
|
|
2012-09-26 14:00:14 +08:00
|
|
|
QualType SymbolMetadata::getType() const {
|
2010-08-15 04:18:45 +08:00
|
|
|
return T;
|
|
|
|
}
|
|
|
|
|
2012-09-26 14:00:14 +08:00
|
|
|
QualType SymbolRegionValue::getType() const {
|
2010-08-11 14:10:55 +08:00
|
|
|
return R->getValueType();
|
2008-02-16 09:12:31 +08:00
|
|
|
}
|
|
|
|
|
2011-08-12 08:34:56 +08:00
|
|
|
SymbolManager::~SymbolManager() {
|
2014-02-20 07:44:52 +08:00
|
|
|
llvm::DeleteContainerSeconds(SymbolDependencies);
|
2011-08-12 08:34:56 +08:00
|
|
|
}
|
2009-01-22 06:26:05 +08:00
|
|
|
|
2009-03-23 23:42:58 +08:00
|
|
|
bool SymbolManager::canSymbolicate(QualType T) {
|
2011-01-26 05:08:47 +08:00
|
|
|
T = T.getCanonicalType();
|
|
|
|
|
2011-02-17 05:13:32 +08:00
|
|
|
if (Loc::isLocType(T))
|
2010-07-29 08:28:43 +08:00
|
|
|
return true;
|
|
|
|
|
2013-04-09 10:30:33 +08:00
|
|
|
if (T->isIntegralOrEnumerationType())
|
|
|
|
return true;
|
2010-07-29 08:28:43 +08:00
|
|
|
|
2012-09-06 01:11:15 +08:00
|
|
|
if (T->isRecordType() && !T->isUnionType())
|
|
|
|
return true;
|
|
|
|
|
2010-07-29 08:28:43 +08:00
|
|
|
return false;
|
2009-03-23 23:42:58 +08:00
|
|
|
}
|
|
|
|
|
2011-08-12 00:43:28 +08:00
|
|
|
void SymbolManager::addSymbolDependency(const SymbolRef Primary,
|
|
|
|
const SymbolRef Dependent) {
|
2011-08-12 08:34:56 +08:00
|
|
|
SymbolDependTy::iterator I = SymbolDependencies.find(Primary);
|
2014-05-27 10:45:47 +08:00
|
|
|
SymbolRefSmallVectorTy *dependencies = nullptr;
|
2011-08-12 08:34:56 +08:00
|
|
|
if (I == SymbolDependencies.end()) {
|
|
|
|
dependencies = new SymbolRefSmallVectorTy();
|
|
|
|
SymbolDependencies[Primary] = dependencies;
|
|
|
|
} else {
|
|
|
|
dependencies = I->second;
|
|
|
|
}
|
|
|
|
dependencies->push_back(Dependent);
|
2011-08-12 00:43:28 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
const SymbolRefSmallVectorTy *SymbolManager::getDependentSymbols(
|
|
|
|
const SymbolRef Primary) {
|
|
|
|
SymbolDependTy::const_iterator I = SymbolDependencies.find(Primary);
|
|
|
|
if (I == SymbolDependencies.end())
|
2014-05-27 10:45:47 +08:00
|
|
|
return nullptr;
|
2011-08-12 08:34:56 +08:00
|
|
|
return I->second;
|
2011-08-12 00:43:28 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
void SymbolReaper::markDependentsLive(SymbolRef sym) {
|
2011-08-12 08:34:56 +08:00
|
|
|
// Do not mark dependents more then once.
|
|
|
|
SymbolMapTy::iterator LI = TheLiving.find(sym);
|
|
|
|
assert(LI != TheLiving.end() && "The primary symbol is not live.");
|
|
|
|
if (LI->second == HaveMarkedDependents)
|
|
|
|
return;
|
|
|
|
LI->second = HaveMarkedDependents;
|
|
|
|
|
2011-08-12 00:43:28 +08:00
|
|
|
if (const SymbolRefSmallVectorTy *Deps = SymMgr.getDependentSymbols(sym)) {
|
|
|
|
for (SymbolRefSmallVectorTy::const_iterator I = Deps->begin(),
|
|
|
|
E = Deps->end(); I != E; ++I) {
|
2011-08-12 08:34:56 +08:00
|
|
|
if (TheLiving.find(*I) != TheLiving.end())
|
|
|
|
continue;
|
2011-08-12 00:43:28 +08:00
|
|
|
markLive(*I);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2009-01-22 06:26:05 +08:00
|
|
|
void SymbolReaper::markLive(SymbolRef sym) {
|
2011-08-12 08:34:56 +08:00
|
|
|
TheLiving[sym] = NotProcessed;
|
2009-09-02 14:03:18 +08:00
|
|
|
TheDead.erase(sym);
|
2011-08-12 00:43:28 +08:00
|
|
|
markDependentsLive(sym);
|
2009-01-22 06:26:05 +08:00
|
|
|
}
|
|
|
|
|
2011-08-06 08:29:57 +08:00
|
|
|
void SymbolReaper::markLive(const MemRegion *region) {
|
|
|
|
RegionRoots.insert(region);
|
|
|
|
}
|
|
|
|
|
2010-08-15 04:18:45 +08:00
|
|
|
void SymbolReaper::markInUse(SymbolRef sym) {
|
|
|
|
if (isa<SymbolMetadata>(sym))
|
|
|
|
MetadataInUse.insert(sym);
|
|
|
|
}
|
|
|
|
|
2009-01-22 06:26:05 +08:00
|
|
|
bool SymbolReaper::maybeDead(SymbolRef sym) {
|
|
|
|
if (isLive(sym))
|
|
|
|
return false;
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2009-09-02 14:03:18 +08:00
|
|
|
TheDead.insert(sym);
|
2009-01-22 06:26:05 +08:00
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2011-08-06 08:29:57 +08:00
|
|
|
bool SymbolReaper::isLiveRegion(const MemRegion *MR) {
|
|
|
|
if (RegionRoots.count(MR))
|
|
|
|
return true;
|
2015-09-08 11:50:52 +08:00
|
|
|
|
2010-08-15 04:18:45 +08:00
|
|
|
MR = MR->getBaseRegion();
|
|
|
|
|
|
|
|
if (const SymbolicRegion *SR = dyn_cast<SymbolicRegion>(MR))
|
2011-08-06 08:29:57 +08:00
|
|
|
return isLive(SR->getSymbol());
|
2010-08-15 04:18:45 +08:00
|
|
|
|
|
|
|
if (const VarRegion *VR = dyn_cast<VarRegion>(MR))
|
2011-08-06 08:29:57 +08:00
|
|
|
return isLive(VR, true);
|
2010-08-15 04:18:45 +08:00
|
|
|
|
|
|
|
// FIXME: This is a gross over-approximation. What we really need is a way to
|
|
|
|
// tell if anything still refers to this region. Unlike SymbolicRegions,
|
|
|
|
// AllocaRegions don't have associated symbols, though, so we don't actually
|
|
|
|
// have a way to track their liveness.
|
|
|
|
if (isa<AllocaRegion>(MR))
|
|
|
|
return true;
|
|
|
|
|
|
|
|
if (isa<CXXThisRegion>(MR))
|
|
|
|
return true;
|
|
|
|
|
|
|
|
if (isa<MemSpaceRegion>(MR))
|
|
|
|
return true;
|
|
|
|
|
[analyzer] Add support for testing the presence of weak functions.
When casting the address of a FunctionTextRegion to bool, or when adding
constraints to such an address, use a stand-in symbol to represent the
presence or absence of the function if the function is weakly linked.
This is groundwork for possible simple availability testing checks, and
can already catch mistakes involving inverted null checks for
weakly-linked functions.
Currently, the implementation reuses the "extent" symbols, originally created
for tracking the size of a malloc region. Since FunctionTextRegions cannot
be dereferenced, the extent symbol will never be used for anything else.
Still, this probably deserves a refactoring in the future.
This patch does not attempt to support testing the presence of weak
/variables/ (global variables), which would likely require much more of
a change and a generalization of "region structure metadata", like the
current "extents", vs. "region contents metadata", like CStringChecker's
"string length".
Patch by Richard <tarka.t.otter@googlemail.com>!
llvm-svn: 189492
2013-08-29 01:07:04 +08:00
|
|
|
if (isa<CodeTextRegion>(MR))
|
|
|
|
return true;
|
|
|
|
|
2010-08-15 04:18:45 +08:00
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
Static analyzer: Remove a bunch of outdated SymbolData objects and
their associated APIs. We no longer need separate SymbolData objects
for fields, variables, etc. Instead, we now associated symbols with
the "rvalue" of a MemRegion (i.e., the value stored at that region).
Now we only have two kinds of SymbolData objects: SymbolRegionRValue
and SymbolConjured.
This cleanup also makes the distinction between a SymbolicRegion and a
symbolic value that is a location much clearer. A SymbolicRegion
represents a chunk of symbolic memory, while a symbolic location is
just a "pointer" with different possible values. Without any specific
knowledge, a symbolic location resolves (i.e., via a dereference) to a
SymbolicRegion. In the future, when we do better alias reasoning, a
symbolic location can become an alias for another location, thus
merging the constraints on the referred SymbolicRegion with the other
region.
llvm-svn: 62769
2009-01-23 02:23:34 +08:00
|
|
|
bool SymbolReaper::isLive(SymbolRef sym) {
|
2011-08-12 00:43:28 +08:00
|
|
|
if (TheLiving.count(sym)) {
|
|
|
|
markDependentsLive(sym);
|
2009-01-23 02:51:33 +08:00
|
|
|
return true;
|
2011-08-12 00:43:28 +08:00
|
|
|
}
|
2015-09-08 11:50:52 +08:00
|
|
|
|
2012-09-26 03:03:01 +08:00
|
|
|
bool KnownLive;
|
2015-09-08 11:50:52 +08:00
|
|
|
|
2012-09-26 03:03:01 +08:00
|
|
|
switch (sym->getKind()) {
|
|
|
|
case SymExpr::RegionValueKind:
|
2013-03-16 07:34:29 +08:00
|
|
|
KnownLive = isLiveRegion(cast<SymbolRegionValue>(sym)->getRegion());
|
2012-09-26 03:03:01 +08:00
|
|
|
break;
|
|
|
|
case SymExpr::ConjuredKind:
|
|
|
|
KnownLive = false;
|
|
|
|
break;
|
|
|
|
case SymExpr::DerivedKind:
|
|
|
|
KnownLive = isLive(cast<SymbolDerived>(sym)->getParentSymbol());
|
|
|
|
break;
|
|
|
|
case SymExpr::ExtentKind:
|
|
|
|
KnownLive = isLiveRegion(cast<SymbolExtent>(sym)->getRegion());
|
|
|
|
break;
|
|
|
|
case SymExpr::MetadataKind:
|
|
|
|
KnownLive = MetadataInUse.count(sym) &&
|
|
|
|
isLiveRegion(cast<SymbolMetadata>(sym)->getRegion());
|
|
|
|
if (KnownLive)
|
|
|
|
MetadataInUse.erase(sym);
|
|
|
|
break;
|
|
|
|
case SymExpr::SymIntKind:
|
|
|
|
KnownLive = isLive(cast<SymIntExpr>(sym)->getLHS());
|
|
|
|
break;
|
|
|
|
case SymExpr::IntSymKind:
|
|
|
|
KnownLive = isLive(cast<IntSymExpr>(sym)->getRHS());
|
|
|
|
break;
|
|
|
|
case SymExpr::SymSymKind:
|
|
|
|
KnownLive = isLive(cast<SymSymExpr>(sym)->getLHS()) &&
|
|
|
|
isLive(cast<SymSymExpr>(sym)->getRHS());
|
|
|
|
break;
|
|
|
|
case SymExpr::CastSymbolKind:
|
|
|
|
KnownLive = isLive(cast<SymbolCast>(sym)->getOperand());
|
|
|
|
break;
|
2010-08-15 04:18:45 +08:00
|
|
|
}
|
|
|
|
|
2012-09-26 03:03:01 +08:00
|
|
|
if (KnownLive)
|
|
|
|
markLive(sym);
|
2010-07-04 08:00:41 +08:00
|
|
|
|
2012-09-26 03:03:01 +08:00
|
|
|
return KnownLive;
|
2009-01-22 06:26:05 +08:00
|
|
|
}
|
2009-02-14 11:16:10 +08:00
|
|
|
|
2012-01-07 06:09:28 +08:00
|
|
|
bool
|
|
|
|
SymbolReaper::isLive(const Stmt *ExprVal, const LocationContext *ELCtx) const {
|
2014-05-27 10:45:47 +08:00
|
|
|
if (LCtx == nullptr)
|
2012-11-03 10:54:20 +08:00
|
|
|
return false;
|
|
|
|
|
2012-01-07 06:09:28 +08:00
|
|
|
if (LCtx != ELCtx) {
|
|
|
|
// If the reaper's location context is a parent of the expression's
|
|
|
|
// location context, then the expression value is now "out of scope".
|
|
|
|
if (LCtx->isParentOf(ELCtx))
|
|
|
|
return false;
|
|
|
|
return true;
|
|
|
|
}
|
2012-11-03 10:54:20 +08:00
|
|
|
|
2012-04-21 05:59:08 +08:00
|
|
|
// If no statement is provided, everything is this and parent contexts is live.
|
|
|
|
if (!Loc)
|
|
|
|
return true;
|
2012-01-07 06:09:28 +08:00
|
|
|
|
2011-10-08 06:21:02 +08:00
|
|
|
return LCtx->getAnalysis<RelaxedLiveVariables>()->isLive(Loc, ExprVal);
|
2010-03-05 12:45:36 +08:00
|
|
|
}
|
|
|
|
|
2011-07-29 07:07:59 +08:00
|
|
|
bool SymbolReaper::isLive(const VarRegion *VR, bool includeStoreBindings) const{
|
2010-08-15 04:18:45 +08:00
|
|
|
const StackFrameContext *VarContext = VR->getStackFrame();
|
2012-11-03 10:54:20 +08:00
|
|
|
|
|
|
|
if (!VarContext)
|
|
|
|
return true;
|
|
|
|
|
|
|
|
if (!LCtx)
|
|
|
|
return false;
|
2010-08-15 04:18:45 +08:00
|
|
|
const StackFrameContext *CurrentContext = LCtx->getCurrentStackFrame();
|
2010-02-17 16:50:05 +08:00
|
|
|
|
2011-07-29 07:07:59 +08:00
|
|
|
if (VarContext == CurrentContext) {
|
2012-08-23 14:16:52 +08:00
|
|
|
// If no statement is provided, everything is live.
|
2012-04-21 05:59:08 +08:00
|
|
|
if (!Loc)
|
|
|
|
return true;
|
|
|
|
|
2011-10-08 06:21:02 +08:00
|
|
|
if (LCtx->getAnalysis<RelaxedLiveVariables>()->isLive(Loc, VR->getDecl()))
|
2011-07-29 07:07:59 +08:00
|
|
|
return true;
|
|
|
|
|
|
|
|
if (!includeStoreBindings)
|
|
|
|
return false;
|
2015-09-08 11:50:52 +08:00
|
|
|
|
2011-07-29 07:07:59 +08:00
|
|
|
unsigned &cachedQuery =
|
|
|
|
const_cast<SymbolReaper*>(this)->includedRegionCache[VR];
|
|
|
|
|
|
|
|
if (cachedQuery) {
|
|
|
|
return cachedQuery == 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Query the store to see if the region occurs in any live bindings.
|
|
|
|
if (Store store = reapedStore.getStore()) {
|
2015-09-08 11:50:52 +08:00
|
|
|
bool hasRegion =
|
2011-07-29 07:07:59 +08:00
|
|
|
reapedStore.getStoreManager().includedInBindings(store, VR);
|
|
|
|
cachedQuery = hasRegion ? 1 : 2;
|
|
|
|
return hasRegion;
|
|
|
|
}
|
2015-09-08 11:50:52 +08:00
|
|
|
|
2011-07-29 07:07:59 +08:00
|
|
|
return false;
|
|
|
|
}
|
2010-08-15 04:18:45 +08:00
|
|
|
|
2012-11-03 10:54:20 +08:00
|
|
|
return VarContext->isParentOf(CurrentContext);
|
2009-12-05 04:32:20 +08:00
|
|
|
}
|