Fix abi diffing to incporporate changes in type graphs.
We now need to convert from type ids to type names while adding a diff
message, since types don't have type names as references anymore.
Bug: 71486971
Test: tests/test.py test updation CL; all tests pass.
Test: tests/gen_all.py; manually diff between libcpp_gold.so.lsdump and
libcpp_gold_member_diff.so.lsdump, diff is visually the same as
before.
Test: build android source tree for aosp_arm64_ab; create reference
dumps; rebuild; confirm no errors or warnings.
Change-Id: I17a3a1a02c5c2312e543a930ae3a1d9037e683b8
This commit is contained in:
@@ -46,34 +46,16 @@ abi_util::CompatibilityStatusIR HeaderAbiDiff::GenerateCompatibilityReport() {
|
||||
return status;
|
||||
}
|
||||
|
||||
template <typename KeyGetter, typename ValueGetter>
|
||||
static void AddTypesToMap(AbiElementMap<const abi_util::TypeIR *> *dst,
|
||||
const abi_util::TextFormatToIRReader *tu,
|
||||
KeyGetter get_key, ValueGetter get_value) {
|
||||
AddToMap(dst, tu->GetRecordTypes(), get_key, get_value);
|
||||
AddToMap(dst, tu->GetEnumTypes(), get_key, get_value);
|
||||
AddToMap(dst, tu->GetPointerTypes(), get_key, get_value);
|
||||
AddToMap(dst, tu->GetBuiltinTypes(), get_key, get_value);
|
||||
AddToMap(dst, tu->GetArrayTypes(), get_key, get_value);
|
||||
AddToMap(dst, tu->GetLvalueReferenceTypes(), get_key, get_value);
|
||||
AddToMap(dst, tu->GetRvalueReferenceTypes(), get_key, get_value);
|
||||
AddToMap(dst, tu->GetQualifiedTypes(), get_key, get_value);
|
||||
}
|
||||
|
||||
abi_util::CompatibilityStatusIR HeaderAbiDiff::CompareTUs(
|
||||
const abi_util::TextFormatToIRReader *old_tu,
|
||||
const abi_util::TextFormatToIRReader *new_tu,
|
||||
abi_util::IRDiffDumper *ir_diff_dumper) {
|
||||
// Collect all old and new types in maps, so that we can refer to them by
|
||||
// type name / linker_set_key later.
|
||||
AbiElementMap<const abi_util::TypeIR *> old_types;
|
||||
AbiElementMap<const abi_util::TypeIR *> new_types;
|
||||
AddTypesToMap(&old_types, old_tu,
|
||||
[](auto e) {return e->first;},
|
||||
[](auto e) {return &(e->second);});
|
||||
AddTypesToMap(&new_types, new_tu,
|
||||
[](auto e) {return e->first;},
|
||||
[](auto e) {return &(e->second);});
|
||||
const AbiElementMap<const abi_util::TypeIR *> old_types =
|
||||
old_tu->GetTypeGraph();
|
||||
const AbiElementMap<const abi_util::TypeIR *> new_types =
|
||||
new_tu->GetTypeGraph();
|
||||
|
||||
// Collect fills in added, removed ,unsafe and safe function diffs.
|
||||
if (!CollectDynsymExportables(old_tu->GetFunctions(), new_tu->GetFunctions(),
|
||||
@@ -108,42 +90,68 @@ abi_util::CompatibilityStatusIR HeaderAbiDiff::CompareTUs(
|
||||
return combined_status;
|
||||
}
|
||||
|
||||
std::pair<AbiElementMap<const abi_util::EnumTypeIR *>,
|
||||
AbiElementMap<const abi_util::RecordTypeIR *>>
|
||||
HeaderAbiDiff::ExtractUserDefinedTypes(
|
||||
const abi_util::TextFormatToIRReader *tu) {
|
||||
AbiElementMap<const abi_util::EnumTypeIR *> enum_types;
|
||||
AbiElementMap<const abi_util::RecordTypeIR *> record_types;
|
||||
// Iterate through the ODRListMap, if there is more than 1 element in the
|
||||
// list, we cannot really unique the type by name, so skip it. If not, add a
|
||||
// map entry ODRListMapKey -> const Record(Enum)TypeIR *.
|
||||
for (auto &it : tu->GetODRListMap()) {
|
||||
auto &odr_list = it.second;
|
||||
if (odr_list.size() != 1) {
|
||||
continue;
|
||||
}
|
||||
const abi_util::TypeIR *type = *(odr_list.begin());
|
||||
switch (type->GetKind()) {
|
||||
case abi_util::RecordTypeKind:
|
||||
record_types.emplace(type->GetLinkerSetKey(),
|
||||
static_cast<const abi_util::RecordTypeIR *>(type));
|
||||
break;
|
||||
case abi_util::EnumTypeKind:
|
||||
enum_types.emplace(type->GetLinkerSetKey(),
|
||||
static_cast<const abi_util::EnumTypeIR *>(type));
|
||||
break;
|
||||
default:
|
||||
// Only user defined types should have ODR list entries.
|
||||
assert(0);
|
||||
}
|
||||
}
|
||||
return std::make_pair(std::move(enum_types), std::move(record_types));
|
||||
}
|
||||
|
||||
bool HeaderAbiDiff::CollectUserDefinedTypes(
|
||||
const abi_util::TextFormatToIRReader *old_tu,
|
||||
const abi_util::TextFormatToIRReader *new_tu,
|
||||
const AbiElementMap<const abi_util::TypeIR *> &old_types_map,
|
||||
const AbiElementMap<const abi_util::TypeIR *> &new_types_map,
|
||||
abi_util::IRDiffDumper *ir_diff_dumper) {
|
||||
|
||||
auto old_enums_and_records_extracted = ExtractUserDefinedTypes(old_tu);
|
||||
auto new_enums_and_records_extracted = ExtractUserDefinedTypes(new_tu);
|
||||
|
||||
return CollectUserDefinedTypesInternal(
|
||||
old_tu->GetRecordTypes(), new_tu->GetRecordTypes(), old_types_map,
|
||||
old_enums_and_records_extracted.second,
|
||||
new_enums_and_records_extracted.second, old_types_map,
|
||||
new_types_map, ir_diff_dumper) &&
|
||||
CollectUserDefinedTypesInternal(old_tu->GetEnumTypes(),
|
||||
new_tu->GetEnumTypes(), old_types_map,
|
||||
new_types_map, ir_diff_dumper);
|
||||
CollectUserDefinedTypesInternal(old_enums_and_records_extracted.first,
|
||||
new_enums_and_records_extracted.first,
|
||||
old_types_map, new_types_map,
|
||||
ir_diff_dumper);
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
bool HeaderAbiDiff::CollectUserDefinedTypesInternal(
|
||||
const AbiElementMap<T> &old_ud_types,
|
||||
const AbiElementMap<T> &new_ud_types,
|
||||
const AbiElementMap<const T*> &old_ud_types_map,
|
||||
const AbiElementMap<const T*> &new_ud_types_map,
|
||||
const AbiElementMap<const abi_util::TypeIR *> &old_types_map,
|
||||
const AbiElementMap<const abi_util::TypeIR *> &new_types_map,
|
||||
abi_util::IRDiffDumper *ir_diff_dumper) {
|
||||
|
||||
// No elf information for records and enums.
|
||||
AbiElementMap<const T *> old_ud_types_map;
|
||||
AbiElementMap<const T *> new_ud_types_map;
|
||||
|
||||
abi_util::AddToMap(&old_ud_types_map, old_ud_types,
|
||||
[](auto e) { return e->first;},
|
||||
[](auto e) {return &(e->second);});
|
||||
|
||||
abi_util::AddToMap(&new_ud_types_map, new_ud_types,
|
||||
[](auto e) { return e->first;},
|
||||
[](auto e) {return &(e->second);});
|
||||
|
||||
return Collect(old_ud_types_map, new_ud_types_map, nullptr, nullptr,
|
||||
ir_diff_dumper) &&
|
||||
ir_diff_dumper, old_types_map, new_types_map) &&
|
||||
PopulateCommonElements(old_ud_types_map, new_ud_types_map, old_types_map,
|
||||
new_types_map, ir_diff_dumper,
|
||||
abi_util::DiffMessageIR::Unreferenced);
|
||||
@@ -182,7 +190,7 @@ bool HeaderAbiDiff::CollectDynsymExportables(
|
||||
|
||||
if (!Collect(old_exportables_map,
|
||||
new_exportables_map, &old_elf_symbol_map, &new_elf_symbol_map,
|
||||
ir_diff_dumper) ||
|
||||
ir_diff_dumper, old_types_map, new_types_map) ||
|
||||
!CollectElfSymbols(old_elf_symbol_map, new_elf_symbol_map,
|
||||
ir_diff_dumper) ||
|
||||
!PopulateCommonElements(old_exportables_map, new_exportables_map,
|
||||
@@ -206,13 +214,16 @@ bool HeaderAbiDiff::Collect(
|
||||
const AbiElementMap<const T*> &new_elements_map,
|
||||
const AbiElementMap<const abi_util::ElfSymbolIR *> *old_elf_map,
|
||||
const AbiElementMap<const abi_util::ElfSymbolIR *> *new_elf_map,
|
||||
abi_util::IRDiffDumper *ir_diff_dumper) {
|
||||
abi_util::IRDiffDumper *ir_diff_dumper,
|
||||
const AbiElementMap<const abi_util::TypeIR *> &old_types_map,
|
||||
const AbiElementMap<const abi_util::TypeIR *> &new_types_map) {
|
||||
if (!PopulateRemovedElements(
|
||||
old_elements_map, new_elements_map, new_elf_map, ir_diff_dumper,
|
||||
abi_util::DiffMessageIR::Removed) ||
|
||||
abi_util::DiffMessageIR::Removed, old_types_map) ||
|
||||
!PopulateRemovedElements(new_elements_map, old_elements_map, old_elf_map,
|
||||
ir_diff_dumper,
|
||||
abi_util::IRDiffDumper::DiffKind::Added)) {
|
||||
abi_util::IRDiffDumper::DiffKind::Added,
|
||||
new_types_map)) {
|
||||
llvm::errs() << "Populating functions in report failed\n";
|
||||
return false;
|
||||
}
|
||||
@@ -253,10 +264,12 @@ bool HeaderAbiDiff::PopulateRemovedElements(
|
||||
const AbiElementMap<const T*> &new_elements_map,
|
||||
const AbiElementMap<const abi_util::ElfSymbolIR *> *elf_map,
|
||||
abi_util::IRDiffDumper *ir_diff_dumper,
|
||||
abi_util::IRDiffDumper::DiffKind diff_kind) {
|
||||
abi_util::IRDiffDumper::DiffKind diff_kind,
|
||||
const AbiElementMap<const abi_util::TypeIR *> &removed_types_map) {
|
||||
std::vector<const T *> removed_elements =
|
||||
abi_util::FindRemovedElements(old_elements_map, new_elements_map);
|
||||
if (!DumpLoneElements(removed_elements, elf_map, ir_diff_dumper, diff_kind)) {
|
||||
if (!DumpLoneElements(removed_elements, elf_map, ir_diff_dumper, diff_kind,
|
||||
removed_types_map)) {
|
||||
llvm::errs() << "Dumping added / removed element to report failed\n";
|
||||
return false;
|
||||
}
|
||||
@@ -289,7 +302,8 @@ bool HeaderAbiDiff::DumpLoneElements(
|
||||
std::vector<const T *> &elements,
|
||||
const AbiElementMap<const abi_util::ElfSymbolIR *> *elf_map,
|
||||
abi_util::IRDiffDumper *ir_diff_dumper,
|
||||
abi_util::IRDiffDumper::DiffKind diff_kind) {
|
||||
abi_util::IRDiffDumper::DiffKind diff_kind,
|
||||
const AbiElementMap<const abi_util::TypeIR *> &types_map) {
|
||||
// If the record / enum has source file information, skip it.
|
||||
std::smatch source_file_match;
|
||||
std::regex source_file_regex(" at ");
|
||||
@@ -310,7 +324,9 @@ bool HeaderAbiDiff::DumpLoneElements(
|
||||
source_file_regex)) {
|
||||
continue;
|
||||
}
|
||||
if (!ir_diff_dumper->AddLinkableMessageIR(element, diff_kind)) {
|
||||
auto element_copy = *element;
|
||||
ReplaceTypeIdsWithTypeNames(types_map, &element_copy);
|
||||
if (!ir_diff_dumper->AddLinkableMessageIR(&element_copy, diff_kind)) {
|
||||
llvm::errs() << "Couldn't dump added /removed element\n";
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -60,7 +60,9 @@ class HeaderAbiDiff {
|
||||
const AbiElementMap<const T *> &new_elements_map,
|
||||
const AbiElementMap<const abi_util::ElfSymbolIR *> *old_elf_map,
|
||||
const AbiElementMap<const abi_util::ElfSymbolIR *> *new_elf_map,
|
||||
abi_util::IRDiffDumper *ir_diff_dumper);
|
||||
abi_util::IRDiffDumper *ir_diff_dumper,
|
||||
const AbiElementMap<const abi_util::TypeIR *> &old_types_map,
|
||||
const AbiElementMap<const abi_util::TypeIR *> &new_types_map);
|
||||
|
||||
bool CollectElfSymbols(
|
||||
const AbiElementMap<const abi_util::ElfSymbolIR *> &old_symbols,
|
||||
@@ -78,7 +80,8 @@ class HeaderAbiDiff {
|
||||
const AbiElementMap<const T *> &new_elements_map,
|
||||
const AbiElementMap<const abi_util::ElfSymbolIR *> *elf_map,
|
||||
abi_util::IRDiffDumper *ir_diff_dumper,
|
||||
abi_util::IRDiffDumper::DiffKind diff_kind);
|
||||
abi_util::IRDiffDumper::DiffKind diff_kind,
|
||||
const AbiElementMap<const abi_util::TypeIR *> &types_map);
|
||||
|
||||
template <typename T>
|
||||
bool PopulateCommonElements(
|
||||
@@ -102,7 +105,12 @@ class HeaderAbiDiff {
|
||||
std::vector<const T *> &elements,
|
||||
const AbiElementMap<const abi_util::ElfSymbolIR *> *elf_map,
|
||||
abi_util::IRDiffDumper *ir_diff_dumper,
|
||||
abi_util::IRDiffDumper::DiffKind diff_kind);
|
||||
abi_util::IRDiffDumper::DiffKind diff_kind,
|
||||
const AbiElementMap<const abi_util::TypeIR *> &old_types_map);
|
||||
|
||||
std::pair<AbiElementMap<const abi_util::EnumTypeIR *>,
|
||||
AbiElementMap<const abi_util::RecordTypeIR *>>
|
||||
ExtractUserDefinedTypes(const abi_util::TextFormatToIRReader *tu);
|
||||
|
||||
bool CollectUserDefinedTypes(
|
||||
const abi_util::TextFormatToIRReader *old_tu,
|
||||
@@ -113,8 +121,8 @@ class HeaderAbiDiff {
|
||||
|
||||
template <typename T>
|
||||
bool CollectUserDefinedTypesInternal(
|
||||
const AbiElementMap<T> &old_ud_types,
|
||||
const AbiElementMap<T> &new_ud_types,
|
||||
const AbiElementMap<const T*> &old_ud_types_map,
|
||||
const AbiElementMap<const T*> &new_ud_types_map,
|
||||
const AbiElementMap<const abi_util::TypeIR *> &old_types_map,
|
||||
const AbiElementMap<const abi_util::TypeIR *> &new_types_map,
|
||||
abi_util::IRDiffDumper *ir_diff_dumper);
|
||||
|
||||
@@ -65,7 +65,12 @@ bool DiffWrapper<abi_util::GlobalVarIR>::DumpDiff(
|
||||
DiffStatus access_diff = (oldp_->GetAccess() == newp_->GetAccess()) ?
|
||||
DiffStatus::no_diff : DiffStatus::direct_diff;
|
||||
if ((type_diff | access_diff) & DiffStatus::direct_diff) {
|
||||
abi_util::GlobalVarDiffIR global_var_diff_ir(oldp_, newp_);
|
||||
abi_util::GlobalVarIR old_global_var = *oldp_;
|
||||
abi_util::GlobalVarIR new_global_var = *newp_;
|
||||
ReplaceTypeIdsWithTypeNames(old_types_, &old_global_var);
|
||||
ReplaceTypeIdsWithTypeNames(new_types_, &new_global_var);
|
||||
abi_util::GlobalVarDiffIR global_var_diff_ir(&old_global_var,
|
||||
&new_global_var);
|
||||
global_var_diff_ir.SetName(oldp_->GetName());
|
||||
return ir_diff_dumper_->AddDiffMessageIR(&global_var_diff_ir,
|
||||
Unwind(&type_queue), diff_kind);
|
||||
@@ -92,7 +97,11 @@ bool DiffWrapper<abi_util::FunctionIR>::DumpDiff(
|
||||
if ((param_diffs == DiffStatus::direct_diff ||
|
||||
return_type_diff == DiffStatus::direct_diff) ||
|
||||
(oldp_->GetAccess() != newp_->GetAccess())) {
|
||||
abi_util::FunctionDiffIR function_diff_ir(oldp_, newp_);
|
||||
abi_util::FunctionIR old_function = *oldp_;
|
||||
abi_util::FunctionIR new_function = *newp_;
|
||||
ReplaceTypeIdsWithTypeNames(old_types_, &old_function);
|
||||
ReplaceTypeIdsWithTypeNames(new_types_, &new_function);
|
||||
abi_util::FunctionDiffIR function_diff_ir(&old_function, &new_function);
|
||||
function_diff_ir.SetName(oldp_->GetName());
|
||||
return ir_diff_dumper_->AddDiffMessageIR(&function_diff_ir,
|
||||
Unwind(&type_queue), diff_kind);
|
||||
|
||||
@@ -36,6 +36,7 @@ static bool IgnoreSymbol(const T *element,
|
||||
|
||||
template <typename T>
|
||||
class DiffWrapper : public AbiDiffHelper {
|
||||
|
||||
public:
|
||||
DiffWrapper(const T *oldp, const T *newp,
|
||||
abi_util::IRDiffDumper *ir_diff_dumper,
|
||||
@@ -44,7 +45,9 @@ class DiffWrapper : public AbiDiffHelper {
|
||||
std::set<std::string> *type_cache)
|
||||
: AbiDiffHelper(old_types, new_types, type_cache, ir_diff_dumper),
|
||||
oldp_(oldp), newp_(newp) { }
|
||||
|
||||
bool DumpDiff(abi_util::IRDiffDumper::DiffKind diff_kind);
|
||||
|
||||
private:
|
||||
const T *oldp_;
|
||||
const T *newp_;
|
||||
|
||||
@@ -102,6 +102,19 @@ class AbiDiffHelper {
|
||||
std::deque<std::string> *type_queue,
|
||||
abi_util::IRDiffDumper::DiffKind diff_kind);
|
||||
|
||||
void ReplaceRemovedFieldTypeIdsWithTypeNames(
|
||||
std::vector<abi_util::RecordFieldIR *> *removed_fields);
|
||||
|
||||
void ReplaceDiffedFieldTypeIdsWithTypeNames(
|
||||
abi_util::RecordFieldDiffIR *diffed_field);
|
||||
|
||||
std::vector<std::pair<abi_util::RecordFieldIR, abi_util::RecordFieldIR>>
|
||||
FixupDiffedFieldTypeIds(
|
||||
const std::vector<abi_util::RecordFieldDiffIR> &field_diffs);
|
||||
|
||||
std::vector<abi_util::RecordFieldIR>FixupRemovedFieldTypeIds(
|
||||
const std::vector<const abi_util::RecordFieldIR *> &fields_removed);
|
||||
|
||||
DiffStatusPair<std::unique_ptr<abi_util::RecordFieldDiffIR>>
|
||||
CompareCommonRecordFields(
|
||||
const abi_util::RecordFieldIR *old_field,
|
||||
@@ -158,5 +171,8 @@ class AbiDiffHelper {
|
||||
AbiElementMap<MergeStatus> *local_to_global_type_id_map_ = nullptr;
|
||||
};
|
||||
|
||||
void ReplaceTypeIdsWithTypeNames(
|
||||
const AbiElementMap<const TypeIR *> &type_graph, LinkableMessageIR *lm);
|
||||
|
||||
} // namespace abi_util
|
||||
#endif
|
||||
|
||||
@@ -1104,7 +1104,6 @@ class RecordFieldDiffIR {
|
||||
return new_field_;
|
||||
}
|
||||
|
||||
protected:
|
||||
const RecordFieldIR *old_field_;
|
||||
const RecordFieldIR *new_field_;
|
||||
};
|
||||
|
||||
@@ -51,6 +51,96 @@ static bool IsAccessDownGraded(abi_util::AccessSpecifierIR old_access,
|
||||
return access_downgraded;
|
||||
}
|
||||
|
||||
static std::string ConvertTypeIdToString(
|
||||
const AbiElementMap<const TypeIR *> &type_graph,
|
||||
const std::string &type_id) {
|
||||
auto it = type_graph.find(type_id);
|
||||
if (it != type_graph.end()) {
|
||||
return it->second->GetName();
|
||||
}
|
||||
return "type-unexported";
|
||||
}
|
||||
|
||||
template <typename Container>
|
||||
static void ReplaceReferencesOtherTypeIdWithName(
|
||||
const AbiElementMap<const TypeIR *> &type_graph,
|
||||
Container &to_fix_elements) {
|
||||
for (auto &element : to_fix_elements) {
|
||||
element.SetReferencedType(
|
||||
ConvertTypeIdToString(type_graph, element.GetReferencedType()));
|
||||
}
|
||||
}
|
||||
|
||||
static void ReplaceEnumTypeIRTypeIdsWithTypeNames(
|
||||
const AbiElementMap<const TypeIR *> &type_graph,
|
||||
EnumTypeIR *enum_type_ir) {
|
||||
// Replace underlying type.
|
||||
enum_type_ir->SetUnderlyingType(
|
||||
ConvertTypeIdToString(type_graph, enum_type_ir->GetUnderlyingType()));
|
||||
}
|
||||
|
||||
static void ReplaceRecordTypeIRTypeIdsWithTypeNames(
|
||||
const AbiElementMap<const TypeIR *> &type_graph,
|
||||
RecordTypeIR *record_type_ir) {
|
||||
// Replace Fields
|
||||
ReplaceReferencesOtherTypeIdWithName(type_graph,
|
||||
record_type_ir->GetFields());
|
||||
// Replace template parameters
|
||||
ReplaceReferencesOtherTypeIdWithName(type_graph,
|
||||
record_type_ir->GetTemplateElements());
|
||||
// Replace bases
|
||||
ReplaceReferencesOtherTypeIdWithName(type_graph,
|
||||
record_type_ir->GetBases());
|
||||
}
|
||||
|
||||
static void ReplaceGlobalVarTypeIdsWithTypeNames(
|
||||
const AbiElementMap<const TypeIR *> &type_graph,
|
||||
GlobalVarIR *global_var_ir) {
|
||||
// Replace referenced type id.
|
||||
global_var_ir->SetReferencedType(
|
||||
ConvertTypeIdToString(type_graph, global_var_ir->GetReferencedType()));
|
||||
}
|
||||
|
||||
static void ReplaceFunctionTypeIdsWithTypeNames(
|
||||
const AbiElementMap<const TypeIR *> &type_graph, FunctionIR *function_ir) {
|
||||
// Replace return type
|
||||
function_ir->SetReturnType(
|
||||
ConvertTypeIdToString(type_graph, function_ir->GetReturnType()));
|
||||
// Replace function parameters
|
||||
ReplaceReferencesOtherTypeIdWithName(type_graph,
|
||||
function_ir->GetParameters());
|
||||
// Replace function template parameters
|
||||
ReplaceReferencesOtherTypeIdWithName(type_graph,
|
||||
function_ir->GetTemplateElements());
|
||||
}
|
||||
|
||||
void ReplaceTypeIdsWithTypeNames(
|
||||
const AbiElementMap<const TypeIR *> &type_graph,
|
||||
LinkableMessageIR *lm) {
|
||||
switch (lm->GetKind()) {
|
||||
case FunctionKind:
|
||||
ReplaceFunctionTypeIdsWithTypeNames(type_graph,
|
||||
static_cast<FunctionIR *>(lm));
|
||||
break;
|
||||
case GlobalVarKind:
|
||||
ReplaceGlobalVarTypeIdsWithTypeNames(type_graph,
|
||||
static_cast<GlobalVarIR *>(lm));
|
||||
break;
|
||||
case RecordTypeKind:
|
||||
ReplaceRecordTypeIRTypeIdsWithTypeNames(type_graph,
|
||||
static_cast<RecordTypeIR *>(lm));
|
||||
|
||||
break;
|
||||
case EnumTypeKind:
|
||||
ReplaceEnumTypeIRTypeIdsWithTypeNames(type_graph,
|
||||
static_cast<EnumTypeIR *>(lm));
|
||||
break;
|
||||
default:
|
||||
// This method should not be called on any other LinkableMessage
|
||||
assert(0);
|
||||
}
|
||||
}
|
||||
|
||||
void AbiDiffHelper::CompareEnumFields(
|
||||
const std::vector<abi_util::EnumFieldIR> &old_fields,
|
||||
const std::vector<abi_util::EnumFieldIR> &new_fields,
|
||||
@@ -98,8 +188,10 @@ DiffStatus AbiDiffHelper::CompareEnumTypes(
|
||||
}
|
||||
auto enum_type_diff_ir = std::make_unique<abi_util::EnumTypeDiffIR>();
|
||||
enum_type_diff_ir->SetName(old_type->GetName());
|
||||
const std::string &old_underlying_type = old_type->GetUnderlyingType();
|
||||
const std::string &new_underlying_type = new_type->GetUnderlyingType();
|
||||
const std::string &old_underlying_type =
|
||||
ConvertTypeIdToString(old_types_, old_type->GetUnderlyingType());
|
||||
const std::string &new_underlying_type =
|
||||
ConvertTypeIdToString(new_types_, new_type->GetUnderlyingType());
|
||||
if (old_underlying_type != new_underlying_type) {
|
||||
enum_type_diff_ir->SetUnderlyingTypeDiff(
|
||||
std::make_unique<std::pair<std::string, std::string>>(
|
||||
@@ -235,6 +327,7 @@ AbiDiffHelper::CompareRecordFields(
|
||||
removed_fields.erase(
|
||||
std::remove_if(removed_fields.begin(), removed_fields.end(), predicate),
|
||||
removed_fields.end());
|
||||
|
||||
diffed_and_removed_fields.second = std::move(removed_fields);
|
||||
std::vector<std::pair<
|
||||
const abi_util::RecordFieldIR *, const abi_util::RecordFieldIR *>> cf =
|
||||
@@ -292,7 +385,6 @@ void AbiDiffHelper::CompareTemplateInfo(
|
||||
std::deque<std::string> *type_queue,
|
||||
abi_util::DiffMessageIR::DiffKind diff_kind) {
|
||||
uint32_t old_template_size = old_template_elements.size();
|
||||
assert(old_template_size == new_template_elements.size());
|
||||
uint32_t i = 0;
|
||||
while (i < old_template_size) {
|
||||
const abi_util::TemplateElementIR &old_template_element =
|
||||
@@ -306,6 +398,57 @@ void AbiDiffHelper::CompareTemplateInfo(
|
||||
}
|
||||
}
|
||||
|
||||
template <typename DiffContainer, typename T>
|
||||
static std::vector<DiffContainer> ConvertToDiffContainerVector(
|
||||
std::vector<std::pair<T, T>> &nc_vector) {
|
||||
std::vector<DiffContainer> cptr_vec;
|
||||
for (auto &e : nc_vector) {
|
||||
cptr_vec.emplace_back(&e.first, &e.second);
|
||||
}
|
||||
return cptr_vec;
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
static std::vector<const T*> ConvertToConstPtrVector(
|
||||
std::vector<T> &nc_vector) {
|
||||
std::vector<const T*> cptr_vec;
|
||||
for (auto &e : nc_vector) {
|
||||
cptr_vec.emplace_back(&e);
|
||||
}
|
||||
return cptr_vec;
|
||||
}
|
||||
|
||||
std::vector<abi_util::RecordFieldIR> AbiDiffHelper::FixupRemovedFieldTypeIds(
|
||||
const std::vector<const abi_util::RecordFieldIR *> &removed_fields) {
|
||||
std::vector<abi_util::RecordFieldIR> removed_fields_dup;
|
||||
for (auto &removed_field : removed_fields) {
|
||||
removed_fields_dup.emplace_back(*removed_field);
|
||||
RecordFieldIR &it = removed_fields_dup[removed_fields_dup.size() -1];
|
||||
it.SetReferencedType(
|
||||
ConvertTypeIdToString(old_types_, it.GetReferencedType()));
|
||||
}
|
||||
return removed_fields_dup;
|
||||
}
|
||||
|
||||
std::vector<std::pair<abi_util::RecordFieldIR, abi_util::RecordFieldIR>>
|
||||
AbiDiffHelper::FixupDiffedFieldTypeIds(
|
||||
const std::vector<abi_util::RecordFieldDiffIR> &field_diffs) {
|
||||
std::vector<std::pair<abi_util::RecordFieldIR, abi_util::RecordFieldIR>>
|
||||
diffed_fields_dup;
|
||||
for (auto &field_diff : field_diffs) {
|
||||
diffed_fields_dup.emplace_back(*(field_diff.old_field_),
|
||||
*(field_diff.new_field_));
|
||||
auto it = diffed_fields_dup[diffed_fields_dup.size() - 1];
|
||||
abi_util::RecordFieldIR &old_field = it.first;
|
||||
abi_util::RecordFieldIR &new_field = it.second;
|
||||
old_field.SetReferencedType(
|
||||
ConvertTypeIdToString(old_types_, old_field.GetReferencedType()));
|
||||
new_field.SetReferencedType(
|
||||
ConvertTypeIdToString(new_types_, new_field.GetReferencedType()));
|
||||
}
|
||||
return diffed_fields_dup;
|
||||
}
|
||||
|
||||
DiffStatus AbiDiffHelper::CompareRecordTypes(
|
||||
const abi_util::RecordTypeIR *old_type,
|
||||
const abi_util::RecordTypeIR *new_type,
|
||||
@@ -342,32 +485,50 @@ DiffStatus AbiDiffHelper::CompareRecordTypes(
|
||||
std::make_unique<abi_util::VTableLayoutDiffIR>(
|
||||
old_type->GetVTableLayout(), new_type->GetVTableLayout()));
|
||||
}
|
||||
auto &old_fields_dup = old_type->GetFields();
|
||||
auto &new_fields_dup = new_type->GetFields();
|
||||
|
||||
auto field_status_and_diffs =
|
||||
CompareRecordFields(old_type->GetFields(), new_type->GetFields(),
|
||||
CompareRecordFields(old_fields_dup, new_fields_dup,
|
||||
type_queue, diff_kind);
|
||||
// TODO: combine this with base class diffs as well.
|
||||
final_diff_status = final_diff_status | field_status_and_diffs.first;
|
||||
auto field_diffs = field_status_and_diffs.second;
|
||||
record_type_diff_ir->SetFieldDiffs(std::move(field_diffs.first));
|
||||
record_type_diff_ir->SetFieldsRemoved(std::move(field_diffs.second));
|
||||
const std::vector<abi_util::CXXBaseSpecifierIR> &old_bases =
|
||||
old_type->GetBases();
|
||||
const std::vector<abi_util::CXXBaseSpecifierIR> &new_bases =
|
||||
new_type->GetBases();
|
||||
|
||||
if (!CompareBaseSpecifiers(old_bases, new_bases, type_queue, diff_kind)) {
|
||||
std::vector<abi_util::CXXBaseSpecifierIR> old_bases = old_type->GetBases();
|
||||
std::vector<abi_util::CXXBaseSpecifierIR> new_bases = new_type->GetBases();
|
||||
|
||||
if (!CompareBaseSpecifiers(old_bases, new_bases, type_queue, diff_kind) &&
|
||||
ir_diff_dumper_) {
|
||||
ReplaceReferencesOtherTypeIdWithName(old_types_, old_bases);
|
||||
ReplaceReferencesOtherTypeIdWithName(new_types_, new_bases);
|
||||
record_type_diff_ir->SetBaseSpecifierDiffs (
|
||||
std::make_unique<abi_util::CXXBaseSpecifierDiffIR>(old_bases,
|
||||
new_bases));
|
||||
}
|
||||
if (ir_diff_dumper_) {
|
||||
// Make copies of the fields removed and diffed, since we have to change
|
||||
// type ids -> type strings.
|
||||
std::vector<std::pair<RecordFieldIR, RecordFieldIR>> field_diff_dups =
|
||||
FixupDiffedFieldTypeIds(field_diffs.first);
|
||||
std::vector<abi_util::RecordFieldDiffIR> field_diffs_fixed =
|
||||
ConvertToDiffContainerVector<abi_util::RecordFieldDiffIR,
|
||||
abi_util::RecordFieldIR>(field_diff_dups);
|
||||
|
||||
std::vector<abi_util::RecordFieldIR> field_removed_dups =
|
||||
FixupRemovedFieldTypeIds(field_diffs.second);
|
||||
std::vector<const abi_util::RecordFieldIR *> fields_removed_fixed =
|
||||
ConvertToConstPtrVector(field_removed_dups);
|
||||
|
||||
record_type_diff_ir->SetFieldDiffs(std::move(field_diffs_fixed));
|
||||
record_type_diff_ir->SetFieldsRemoved(std::move(fields_removed_fixed));
|
||||
if (record_type_diff_ir->DiffExists() &&
|
||||
ir_diff_dumper_ &&
|
||||
!ir_diff_dumper_->AddDiffMessageIR(record_type_diff_ir.get(),
|
||||
Unwind(type_queue), diff_kind)) {
|
||||
llvm::errs() << "AddDiffMessage on record type failed\n";
|
||||
::exit(1);
|
||||
} // No need to add a dump for an extension since records can't be "extended".
|
||||
|
||||
}
|
||||
CompareTemplateInfo(old_type->GetTemplateElements(),
|
||||
new_type->GetTemplateElements(),
|
||||
type_queue, diff_kind);
|
||||
@@ -545,7 +706,8 @@ DiffStatus AbiDiffHelper::CompareAndDumpTypeDiff(
|
||||
if (!type_cache_->insert(old_type_id + new_type_id).second) {
|
||||
return DiffStatus::no_diff;
|
||||
} else {
|
||||
TypeQueueCheckAndPushBack(type_queue, old_type_id);
|
||||
TypeQueueCheckAndPushBack(type_queue,
|
||||
ConvertTypeIdToString(old_types_,old_type_id));
|
||||
}
|
||||
AbiElementMap<const abi_util::TypeIR *>::const_iterator old_it =
|
||||
old_types_.find(old_type_id);
|
||||
|
||||
Reference in New Issue
Block a user