38 clang::ento::DynamicTypeInfo)
43DynamicTypeInfo getDynamicTypeInfo(ProgramStateRef State,
const MemRegion *MR) {
44 MR = MR->StripCasts();
47 if (
const DynamicTypeInfo *DTI = State->get<DynamicTypeMap>(MR))
51 if (
const auto *TR = dyn_cast<TypedRegion>(MR))
52 return DynamicTypeInfo(TR->getLocationType(),
false);
54 if (
const auto *SR = dyn_cast<SymbolicRegion>(MR)) {
55 SymbolRef Sym = SR->getSymbol();
56 return DynamicTypeInfo(Sym->getType());
62const DynamicTypeInfo *getRawDynamicTypeInfo(ProgramStateRef State,
63 const MemRegion *MR) {
64 return State->get<DynamicTypeMap>(MR);
67static void unbox(QualType &Ty) {
69 while (Ty->isReferenceType() || Ty->isPointerType())
70 Ty = Ty->getPointeeType();
71 Ty = Ty.getCanonicalType().getUnqualifiedType();
74const DynamicCastInfo *getDynamicCastInfo(ProgramStateRef State,
78 const auto *Lookup = State->get<DynamicCastMap>().lookup(MR);
85 for (
const DynamicCastInfo &Cast : *Lookup)
86 if (Cast.equals(CastFromTy, CastToTy))
92DynamicTypeInfo getClassObjectDynamicTypeInfo(ProgramStateRef State,
94 const DynamicTypeInfo *DTI = State->get<DynamicClassObjectMap>(Sym);
95 return DTI ? *DTI : DynamicTypeInfo{};
98ProgramStateRef setDynamicTypeInfo(ProgramStateRef State,
const MemRegion *MR,
99 DynamicTypeInfo NewTy) {
100 State = State->set<DynamicTypeMap>(MR->StripCasts(), NewTy);
105ProgramStateRef setDynamicTypeInfo(ProgramStateRef State,
const MemRegion *MR,
106 QualType NewTy,
bool CanBeSubClassed) {
107 return setDynamicTypeInfo(State, MR, DynamicTypeInfo(NewTy, CanBeSubClassed));
110ProgramStateRef setDynamicTypeAndCastInfo(ProgramStateRef State,
119 assert((CastToTy->isAnyPointerType() || CastToTy->isReferenceType()) &&
120 "DynamicTypeInfo should always be a pointer.");
121 State = State->set<DynamicTypeMap>(MR, CastToTy);
127 DynamicCastInfo::CastResult ResultKind =
128 CastSucceeds ? DynamicCastInfo::CastResult::Success
129 : DynamicCastInfo::CastResult::Failure;
131 CastSet::Factory &F = State->get_context<CastSet>();
133 const CastSet *TempSet = State->get<DynamicCastMap>(MR);
134 CastSet Set = TempSet ? *TempSet : F.getEmptySet();
136 Set = F.add(Set, {CastFromTy, CastToTy, ResultKind});
137 State = State->set<DynamicCastMap>(MR, Set);
143ProgramStateRef setClassObjectDynamicTypeInfo(ProgramStateRef State,
145 DynamicTypeInfo NewTy) {
146 State = State->set<DynamicClassObjectMap>(Sym, NewTy);
150ProgramStateRef setClassObjectDynamicTypeInfo(ProgramStateRef State,
151 SymbolRef Sym, QualType NewTy,
152 bool CanBeSubClassed) {
153 return setClassObjectDynamicTypeInfo(State, Sym,
154 DynamicTypeInfo(NewTy, CanBeSubClassed));
157static bool isLive(SymbolReaper &SR,
const MemRegion *MR) {
158 return SR.isLiveRegion(MR);
161static bool isLive(SymbolReaper &SR, SymbolRef Sym) {
return SR.isLive(Sym); }
163template <
typename MapTy>
164static ProgramStateRef removeDeadImpl(ProgramStateRef State, SymbolReaper &SR) {
165 const auto &Map = State->get<
MapTy>();
167 for (
const auto &Elem : Map)
168 if (!isLive(SR, Elem.first))
169 State = State->remove<
MapTy>(Elem.first);
174ProgramStateRef removeDeadTypes(ProgramStateRef State, SymbolReaper &SR) {
175 return removeDeadImpl<DynamicTypeMap>(State, SR);
178ProgramStateRef removeDeadCasts(ProgramStateRef State, SymbolReaper &SR) {
179 return removeDeadImpl<DynamicCastMap>(State, SR);
182ProgramStateRef removeDeadClassObjectTypes(ProgramStateRef State,
184 return removeDeadImpl<DynamicClassObjectMap>(State, SR);
191static raw_ostream &printJson(
const MemRegion *Region, raw_ostream &Out,
192 const char *NL,
unsigned int Space,
bool IsDot) {
193 return Out <<
"\"region\": \"" << Region <<
"\"";
196static raw_ostream &printJson(
const SymExpr *Symbol, raw_ostream &Out,
197 const char *NL,
unsigned int Space,
bool IsDot) {
198 return Out <<
"\"symbol\": \"" << Symbol <<
"\"";
201static raw_ostream &printJson(
const DynamicTypeInfo &DTI, raw_ostream &Out,
202 const char *NL,
unsigned int Space,
bool IsDot) {
203 Out <<
"\"dyn_type\": ";
204 if (!DTI.isValid()) {
207 QualType ToPrint = DTI.getType();
208 if (ToPrint->isAnyPointerType())
209 ToPrint = ToPrint->getPointeeType();
211 Out <<
'\"' << ToPrint <<
"\", \"sub_classable\": "
212 << (DTI.canBeASubClass() ?
"true" :
"false");
217static raw_ostream &printJson(
const DynamicCastInfo &DCI, raw_ostream &Out,
218 const char *NL,
unsigned int Space,
bool IsDot) {
219 return Out <<
"\"from\": \"" << DCI.from() <<
"\", \"to\": \"" << DCI.to()
220 <<
"\", \"kind\": \"" << (DCI.succeeds() ?
"success" :
"fail")
224template <
class T,
class U>
225static raw_ostream &printJson(
const std::pair<T, U> &Pair, raw_ostream &Out,
226 const char *NL,
unsigned int Space,
bool IsDot) {
227 printJson(Pair.first, Out, NL, Space, IsDot) <<
", ";
228 return printJson(Pair.second, Out, NL, Space, IsDot);
231template <
class ContainerTy>
232static raw_ostream &printJsonContainer(
const ContainerTy &Container,
233 raw_ostream &Out,
const char *NL,
234 unsigned int Space,
bool IsDot) {
235 if (Container.isEmpty()) {
236 return Out <<
"null";
241 for (
auto I = Container.begin(); I != Container.end(); ++I) {
242 const auto &Element = *I;
244 Indent(Out, Space, IsDot) <<
"{ ";
245 printJson(Element, Out, NL, Space, IsDot) <<
" }";
247 if (std::next(I) != Container.end())
253 return Indent(Out, Space, IsDot) <<
"]";
256static raw_ostream &printJson(
const CastSet &Set, raw_ostream &Out,
257 const char *NL,
unsigned int Space,
bool IsDot) {
258 Out <<
"\"casts\": ";
259 return printJsonContainer(Set, Out, NL, Space, IsDot);
262template <
class MapTy>
263static void printJsonImpl(raw_ostream &Out, ProgramStateRef State,
264 const char *Name,
const char *NL,
unsigned int Space,
265 bool IsDot,
bool PrintEvenIfEmpty =
true) {
266 const auto &Map = State->get<
MapTy>();
267 if (Map.isEmpty() && !PrintEvenIfEmpty)
270 Indent(Out, Space, IsDot) <<
"\"" << Name <<
"\": ";
271 printJsonContainer(Map, Out, NL, Space, IsDot) <<
"," << NL;
274static void printDynamicTypesJson(raw_ostream &Out, ProgramStateRef State,
275 const char *NL,
unsigned int Space,
277 printJsonImpl<DynamicTypeMap>(Out, State,
"dynamic_types", NL, Space, IsDot);
280static void printDynamicCastsJson(raw_ostream &Out, ProgramStateRef State,
281 const char *NL,
unsigned int Space,
283 printJsonImpl<DynamicCastMap>(Out, State,
"dynamic_casts", NL, Space, IsDot);
286static void printClassObjectDynamicTypesJson(raw_ostream &Out,
287 ProgramStateRef State,
288 const char *NL,
unsigned int Space,
292 printJsonImpl<DynamicClassObjectMap>(Out, State,
"class_object_types", NL,
297void printDynamicTypeInfoJson(raw_ostream &Out, ProgramStateRef State,
298 const char *NL,
unsigned int Space,
bool IsDot) {
299 printDynamicTypesJson(Out, State, NL, Space, IsDot);
300 printDynamicCastsJson(Out, State, NL, Space, IsDot);
301 printClassObjectDynamicTypesJson(Out, State, NL, Space, IsDot);