15#define DEBUG_TYPE "dataflow"
22 assert(Field.getType()->isReferenceType() ||
23 (SrcFieldLoc !=
nullptr && DstFieldLoc !=
nullptr));
25 if (Field.getType()->isRecordType()) {
26 copyRecord(cast<RecordStorageLocation>(*SrcFieldLoc),
27 cast<RecordStorageLocation>(*DstFieldLoc),
Env);
28 }
else if (Field.getType()->isReferenceType()) {
41 copyRecord(cast<RecordStorageLocation>(SrcFieldLoc),
42 cast<RecordStorageLocation>(DstFieldLoc),
Env);
57 auto DstDecl = DstType->getAsCXXRecordDecl();
59 [[maybe_unused]]
bool compatibleTypes =
61 (SrcDecl !=
nullptr && DstDecl !=
nullptr &&
62 (SrcDecl->isDerivedFrom(DstDecl) || DstDecl->isDerivedFrom(SrcDecl)));
65 if (!compatibleTypes) {
66 llvm::dbgs() <<
"Source type " << Src.
getType() <<
"\n";
67 llvm::dbgs() <<
"Destination type " << Dst.
getType() <<
"\n";
70 assert(compatibleTypes);
72 if (SrcType == DstType || (SrcDecl !=
nullptr && DstDecl !=
nullptr &&
73 SrcDecl->isDerivedFrom(DstDecl))) {
74 for (
auto [Field, DstFieldLoc] : Dst.
children())
80 for (
auto [Field, SrcFieldLoc] : Src.
children())
93 llvm::dbgs() <<
"Loc1 type " << Loc1.getType() <<
"\n";
94 llvm::dbgs() <<
"Loc2 type " << Loc2.getType() <<
"\n";
100 for (
auto [Field, FieldLoc1] : Loc1.
children()) {
103 assert(Field->getType()->isReferenceType() ||
104 (FieldLoc1 !=
nullptr && FieldLoc2 !=
nullptr));
106 if (Field->getType()->isRecordType()) {
107 if (!
recordsEqual(cast<RecordStorageLocation>(*FieldLoc1), Env1,
108 cast<RecordStorageLocation>(*FieldLoc2), Env2))
110 }
else if (Field->getType()->isReferenceType()) {
111 if (FieldLoc1 != FieldLoc2)
119 if (SynthFieldLoc1->getType()->isRecordType()) {
121 *cast<RecordStorageLocation>(SynthFieldLoc1), Env1,
124 }
else if (Env1.
getValue(*SynthFieldLoc1) !=
A (possibly-)qualified type.
QualType getCanonicalType() const
QualType getUnqualifiedType() const
Retrieve the unqualified variant of the given type, removing as little sugar as possible.
CXXRecordDecl * getAsCXXRecordDecl() const
Retrieves the CXXRecordDecl that this type refers to, either because the type is a RecordType or beca...
bool isRecordType() const
Represent the declaration of a variable (in which case it is an lvalue) a function (in which case it ...
Holds the state of the program (store and heap) at a given program point.
void clearValue(const StorageLocation &Loc)
Clears any association between Loc and a value in the environment.
Value * getValue(const StorageLocation &Loc) const
Returns the value assigned to Loc in the environment or null if Loc isn't assigned a value in the env...
void setValue(const StorageLocation &Loc, Value &Val)
Assigns Val as the value of Loc in the environment.
A storage location for a record (struct, class, or union).
llvm::iterator_range< SyntheticFieldMap::const_iterator > synthetic_fields() const
StorageLocation * getChild(const ValueDecl &D) const
Returns the child storage location for D.
void setChild(const ValueDecl &D, StorageLocation *Loc)
Changes the child storage location for a field D of reference type.
StorageLocation & getSyntheticField(llvm::StringRef Name) const
Returns the storage location for the synthetic field Name.
llvm::iterator_range< FieldToLoc::const_iterator > children() const
Base class for elements of the local variable store and of the heap.
Base class for all values computed by abstract interpretation.
Dataflow Directional Tag Classes.
bool recordsEqual(const RecordStorageLocation &Loc1, const Environment &Env1, const RecordStorageLocation &Loc2, const Environment &Env2)
Returns whether the records Loc1 and Loc2 are equal.
void copyRecord(RecordStorageLocation &Src, RecordStorageLocation &Dst, Environment &Env)
Copies a record (struct, class, or union) from Src to Dst.
static void copyField(const ValueDecl &Field, StorageLocation *SrcFieldLoc, StorageLocation *DstFieldLoc, RecordStorageLocation &Dst, Environment &Env)
static void copySyntheticField(QualType FieldType, StorageLocation &SrcFieldLoc, StorageLocation &DstFieldLoc, Environment &Env)