21 #include "llvm/Support/Casting.h"
22 #include "llvm/Support/raw_ostream.h"
39 clang::ento::DynamicTypeInfo)
45 MR = MR->StripCasts();
48 if (
const DynamicTypeInfo *DTI =
State->get<DynamicTypeMap>(MR))
52 if (
const auto *TR = dyn_cast<TypedRegion>(MR))
53 return DynamicTypeInfo(TR->getLocationType(),
false);
55 if (
const auto *SR = dyn_cast<SymbolicRegion>(MR)) {
57 return DynamicTypeInfo(Sym->getType());
64 const MemRegion *MR) {
65 return State->get<DynamicTypeMap>(MR);
68 static void unbox(QualType &Ty) {
70 while (Ty->isReferenceType() || Ty->isPointerType())
71 Ty = Ty->getPointeeType();
72 Ty = Ty.getCanonicalType().getUnqualifiedType();
79 const auto *Lookup =
State->get<DynamicCastMap>().lookup(MR);
86 for (
const DynamicCastInfo &
Cast : *Lookup)
87 if (
Cast.equals(CastFromTy, CastToTy))
95 const DynamicTypeInfo *DTI =
State->get<DynamicClassObjectMap>(Sym);
96 return DTI ? *DTI : DynamicTypeInfo{};
100 DynamicTypeInfo NewTy) {
101 State =
State->set<DynamicTypeMap>(MR->StripCasts(), NewTy);
107 QualType NewTy,
bool CanBeSubClassed) {
120 assert((CastToTy->isAnyPointerType() || CastToTy->isReferenceType()) &&
121 "DynamicTypeInfo should always be a pointer.");
122 State =
State->set<DynamicTypeMap>(MR, CastToTy);
128 DynamicCastInfo::CastResult ResultKind =
129 CastSucceeds ? DynamicCastInfo::CastResult::Success
130 : DynamicCastInfo::CastResult::Failure;
132 CastSet::Factory &F =
State->get_context<CastSet>();
134 const CastSet *TempSet =
State->get<DynamicCastMap>(MR);
135 CastSet Set = TempSet ? *TempSet : F.getEmptySet();
137 Set = F.add(Set, {CastFromTy, CastToTy, ResultKind});
146 DynamicTypeInfo NewTy) {
147 State =
State->set<DynamicClassObjectMap>(Sym, NewTy);
153 bool CanBeSubClassed) {
155 DynamicTypeInfo(NewTy, CanBeSubClassed));
158 static bool isLive(SymbolReaper &SR,
const MemRegion *MR) {
159 return SR.isLiveRegion(MR);
162 static bool isLive(SymbolReaper &SR,
SymbolRef Sym) {
return SR.isLive(Sym); }
164 template <
typename MapTy>
168 for (
const auto &Elem : Map)
169 if (!isLive(SR, Elem.first))
176 return removeDeadImpl<DynamicTypeMap>(
State, SR);
180 return removeDeadImpl<DynamicCastMap>(
State, SR);
185 return removeDeadImpl<DynamicClassObjectMap>(
State, SR);
192 static raw_ostream &printJson(
const MemRegion *Region, raw_ostream &Out,
193 const char *NL,
unsigned int Space,
bool IsDot) {
194 return Out <<
"\"region\": \"" << Region <<
"\"";
197 static raw_ostream &printJson(
const SymExpr *Symbol, raw_ostream &Out,
198 const char *NL,
unsigned int Space,
bool IsDot) {
199 return Out <<
"\"symbol\": \"" << Symbol <<
"\"";
202 static raw_ostream &printJson(
const DynamicTypeInfo &DTI, raw_ostream &Out,
203 const char *NL,
unsigned int Space,
bool IsDot) {
204 Out <<
"\"dyn_type\": ";
205 if (!DTI.isValid()) {
208 QualType ToPrint = DTI.getType();
209 if (ToPrint->isAnyPointerType())
210 ToPrint = ToPrint->getPointeeType();
212 Out <<
'\"' << ToPrint <<
"\", \"sub_classable\": "
213 << (DTI.canBeASubClass() ?
"true" :
"false");
218 static raw_ostream &printJson(
const DynamicCastInfo &DCI, raw_ostream &Out,
219 const char *NL,
unsigned int Space,
bool IsDot) {
220 return Out <<
"\"from\": \"" << DCI.from() <<
"\", \"to\": \"" << DCI.to()
221 <<
"\", \"kind\": \"" << (DCI.succeeds() ?
"success" :
"fail")
225 template <
class T,
class U>
226 static raw_ostream &printJson(
const std::pair<T, U> &Pair, raw_ostream &Out,
227 const char *NL,
unsigned int Space,
bool IsDot) {
228 printJson(Pair.first, Out, NL, Space, IsDot) <<
", ";
229 return printJson(Pair.second, Out, NL, Space, IsDot);
232 template <
class ContainerTy>
233 static raw_ostream &printJsonContainer(
const ContainerTy &Container,
234 raw_ostream &Out,
const char *NL,
235 unsigned int Space,
bool IsDot) {
236 if (Container.isEmpty()) {
237 return Out <<
"null";
242 for (
auto I = Container.begin(); I != Container.end(); ++I) {
243 const auto &Element = *I;
245 Indent(Out, Space, IsDot) <<
"{ ";
246 printJson(Element, Out, NL, Space, IsDot) <<
" }";
248 if (std::next(I) != Container.end())
254 return Indent(Out, Space, IsDot) <<
"]";
257 static raw_ostream &printJson(
const CastSet &Set, raw_ostream &Out,
258 const char *NL,
unsigned int Space,
bool IsDot) {
259 Out <<
"\"casts\": ";
260 return printJsonContainer(Set, Out, NL, Space, IsDot);
263 template <
class MapTy>
265 const char *Name,
const char *NL,
unsigned int Space,
266 bool IsDot,
bool PrintEvenIfEmpty =
true) {
268 if (Map.isEmpty() && !PrintEvenIfEmpty)
271 Indent(Out, Space, IsDot) <<
"\"" << Name <<
"\": ";
272 printJsonContainer(Map, Out, NL, Space, IsDot) <<
"," << NL;
276 const char *NL,
unsigned int Space,
278 printJsonImpl<DynamicTypeMap>(Out,
State,
"dynamic_types", NL, Space, IsDot);
282 const char *NL,
unsigned int Space,
284 printJsonImpl<DynamicCastMap>(Out,
State,
"dynamic_casts", NL, Space, IsDot);
287 static void printClassObjectDynamicTypesJson(raw_ostream &Out,
289 const char *NL,
unsigned int Space,
293 printJsonImpl<DynamicClassObjectMap>(Out,
State,
"class_object_types", NL,
299 const char *NL,
unsigned int Space,
bool IsDot) {
300 printDynamicTypesJson(Out,
State, NL, Space, IsDot);
301 printDynamicCastsJson(Out,
State, NL, Space, IsDot);
302 printClassObjectDynamicTypesJson(Out,
State, NL, Space, IsDot);
REGISTER_MAP_WITH_PROGRAMSTATE(DynamicTypeMap, const clang::ento::MemRegion *, clang::ento::DynamicTypeInfo) REGISTER_MAP_WITH_PROGRAMSTATE(DynamicCastMap
The GDM component containing the dynamic type info.
Forward-declares and imports various common LLVM datatypes that clang wants to use unqualified.
llvm::DenseMap< Stmt *, Stmt * > MapTy
#define REGISTER_SET_FACTORY_WITH_PROGRAMSTATE(Name, Elem)
Declares an immutable set type Name and registers the factory for such sets in the program state,...
Stores the currently inferred strictest bound on the runtime type of a region in a given state along ...
MemRegion - The root abstract class for all memory regions.
void printDynamicTypeInfoJson(raw_ostream &Out, ProgramStateRef State, const char *NL="\n", unsigned int Space=0, bool IsDot=false)
IntrusiveRefCntPtr< const ProgramState > ProgramStateRef
const DynamicTypeInfo * getRawDynamicTypeInfo(ProgramStateRef State, const MemRegion *MR)
Get raw dynamic type information for the region MR.
const SymExpr * SymbolRef
ProgramStateRef setClassObjectDynamicTypeInfo(ProgramStateRef State, SymbolRef Sym, DynamicTypeInfo NewTy)
Set constraint on a type contained in a class object; return the new state.
ProgramStateRef removeDeadClassObjectTypes(ProgramStateRef State, SymbolReaper &SR)
Removes the dead Class object type informations from State.
DynamicTypeInfo getDynamicTypeInfo(ProgramStateRef State, const MemRegion *MR)
Get dynamic type information for the region MR.
ProgramStateRef removeDeadCasts(ProgramStateRef State, SymbolReaper &SR)
Removes the dead cast informations from State.
const DynamicCastInfo * getDynamicCastInfo(ProgramStateRef State, const MemRegion *MR, QualType CastFromTy, QualType CastToTy)
Get dynamic cast information from CastFromTy to CastToTy of MR.
ProgramStateRef setDynamicTypeInfo(ProgramStateRef State, const MemRegion *MR, DynamicTypeInfo NewTy)
Set dynamic type information of the region; return the new state.
ProgramStateRef removeDeadTypes(ProgramStateRef State, SymbolReaper &SR)
Removes the dead type informations from State.
ProgramStateRef setDynamicTypeAndCastInfo(ProgramStateRef State, const MemRegion *MR, QualType CastFromTy, QualType CastToTy, bool IsCastSucceeds)
Set dynamic type and cast information of the region; return the new state.
DynamicTypeInfo getClassObjectDynamicTypeInfo(ProgramStateRef State, SymbolRef Sym)
Get dynamic type information stored in a class object represented by Sym.
bool Cast(InterpState &S, CodePtr OpPC)
The JSON file list parser is used to communicate input to InstallAPI.