#ifndef ABI_DIFF_HELPERS
#define ABI_DIFF_HELPERS
#include <ir_representation.h>
#include <deque>
// Classes which act as middle-men between clang AST parsing routines and
// message format specific dumpers.
namespace abi_util {
using MergeStatus = TextFormatToIRReader::MergeStatus;
enum DiffStatus {
// There was no diff found while comparing types.
no_diff = 0,
// There was a diff found and it should be added as a part of a diff message.
direct_diff = 1,
// There was a diff found, however it need not be added as a part of a diff
// message, since it would have already been noted elsewhere.
indirect_diff = 2,
};
static inline DiffStatus operator| (DiffStatus f,DiffStatus s) {
return static_cast<DiffStatus>(
static_cast<std::underlying_type<DiffStatus>::type>(f) |
static_cast<std::underlying_type<DiffStatus>::type>(s));
}
static inline DiffStatus operator& (DiffStatus f, DiffStatus s) {
return static_cast<DiffStatus>(
static_cast<std::underlying_type<DiffStatus>::type>(f) &
static_cast<std::underlying_type<DiffStatus>::type>(s));
}
template <typename T>
using DiffStatusPair = std::pair<DiffStatus, T>;
template <typename GenericField, typename GenericFieldDiff>
struct GenericFieldDiffInfo {
DiffStatus diff_status_;
std::vector<GenericFieldDiff> diffed_fields_;
std::vector<const GenericField *> removed_fields_;
std::vector<const GenericField *> added_fields_;
};
std::string Unwind(const std::deque<std::string> *type_queue);
class AbiDiffHelper {
public:
AbiDiffHelper(
const AbiElementMap<const abi_util::TypeIR *> &old_types,
const AbiElementMap<const abi_util::TypeIR *> &new_types,
std::set<std::string> *type_cache,
abi_util::IRDiffDumper *ir_diff_dumper = nullptr,
AbiElementMap<MergeStatus> *local_to_global_type_id_map = nullptr)
: old_types_(old_types), new_types_(new_types),
type_cache_(type_cache), ir_diff_dumper_(ir_diff_dumper),
local_to_global_type_id_map_(local_to_global_type_id_map) { }
DiffStatus CompareAndDumpTypeDiff(
const std::string &old_type_str, const std::string &new_type_str,
std::deque<std::string> *type_queue = nullptr,
abi_util::IRDiffDumper::DiffKind diff_kind = DiffMessageIR::Unreferenced);
DiffStatus CompareAndDumpTypeDiff(
const abi_util::TypeIR *old_type, const abi_util::TypeIR *new_type,
abi_util::LinkableMessageKind kind,
std::deque<std::string> *type_queue = nullptr,
abi_util::IRDiffDumper::DiffKind diff_kind = DiffMessageIR::Unreferenced);
DiffStatus CompareRecordTypes(const abi_util::RecordTypeIR *old_type,
const abi_util::RecordTypeIR *new_type,
std::deque<std::string> *type_queue,
abi_util::IRDiffDumper::DiffKind diff_kind);
DiffStatus CompareQualifiedTypes(const abi_util::QualifiedTypeIR *old_type,
const abi_util::QualifiedTypeIR *new_type,
std::deque<std::string> *type_queue,
abi_util::IRDiffDumper::DiffKind diff_kind);
DiffStatus ComparePointerTypes(const abi_util::PointerTypeIR *old_type,
const abi_util::PointerTypeIR *new_type,
std::deque<std::string> *type_queue,
abi_util::IRDiffDumper::DiffKind diff_kind);
DiffStatus CompareLvalueReferenceTypes(
const abi_util::LvalueReferenceTypeIR *old_type,
const abi_util::LvalueReferenceTypeIR *new_type,
std::deque<std::string> *type_queue,
abi_util::IRDiffDumper::DiffKind diff_kind);
DiffStatus CompareRvalueReferenceTypes(
const abi_util::RvalueReferenceTypeIR *old_type,
const abi_util::RvalueReferenceTypeIR *new_type,
std::deque<std::string> *type_queue,
abi_util::IRDiffDumper::DiffKind diff_kind);
DiffStatus CompareBuiltinTypes(const abi_util::BuiltinTypeIR *old_type,
const abi_util::BuiltinTypeIR *new_type);
static void CompareEnumFields(
const std::vector<abi_util::EnumFieldIR> &old_fields,
const std::vector<abi_util::EnumFieldIR> &new_fields,
abi_util::EnumTypeDiffIR *enum_type_diff_ir);
DiffStatus CompareEnumTypes(const abi_util::EnumTypeIR *old_type,
const abi_util::EnumTypeIR *new_type,
std::deque<std::string> *type_queue,
abi_util::IRDiffDumper::DiffKind diff_kind);
DiffStatus CompareFunctionTypes(const abi_util::FunctionTypeIR *old_type,
const abi_util::FunctionTypeIR *new_type,
std::deque<std::string> *type_queue,
abi_util::DiffMessageIR::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);
DiffStatusPair<std::unique_ptr<abi_util::RecordFieldDiffIR>>
CompareCommonRecordFields(
const abi_util::RecordFieldIR *old_field,
const abi_util::RecordFieldIR *new_field,
std::deque<std::string> *type_queue,
abi_util::IRDiffDumper::DiffKind diff_kind);
GenericFieldDiffInfo<abi_util::RecordFieldIR, abi_util::RecordFieldDiffIR>
CompareRecordFields(
const std::vector<abi_util::RecordFieldIR> &old_fields,
const std::vector<abi_util::RecordFieldIR> &new_fields,
std::deque<std::string> *type_queue,
abi_util::IRDiffDumper::DiffKind diff_kind);
DiffStatus CompareFunctionParameters(
const std::vector<abi_util::ParamIR> &old_parameters,
const std::vector<abi_util::ParamIR> &new_parameters,
std::deque<std::string> *type_queue,
abi_util::IRDiffDumper::DiffKind diff_kind);
bool CompareBaseSpecifiers(
const std::vector<abi_util::CXXBaseSpecifierIR> &old_base_specifiers,
const std::vector<abi_util::CXXBaseSpecifierIR> &new_base_specifiers,
std::deque<std::string> *type_queue,
abi_util::IRDiffDumper::DiffKind diff_kind);
bool CompareVTables(const abi_util::RecordTypeIR *old_record,
const abi_util::RecordTypeIR *new_record);
bool CompareVTableComponents(
const abi_util::VTableComponentIR &old_component,
const abi_util::VTableComponentIR &new_component);
DiffStatus CompareTemplateInfo(
const std::vector<abi_util::TemplateElementIR> &old_template_elements,
const std::vector<abi_util::TemplateElementIR> &new_template_elements,
std::deque<std::string> *type_queue,
abi_util::IRDiffDumper::DiffKind diff_kind);
bool CompareSizeAndAlignment(const abi_util::TypeIR *old_ti,
const abi_util::TypeIR *new_ti);
template <typename DiffType, typename DiffElement>
bool AddToDiff(DiffType *mutable_diff, const DiffElement *oldp,
const DiffElement *newp,
std::deque<std::string> *type_queue = nullptr);
protected:
const AbiElementMap<const abi_util::TypeIR *> &old_types_;
const AbiElementMap<const abi_util::TypeIR *> &new_types_;
std::set<std::string> *type_cache_ = nullptr;
abi_util::IRDiffDumper *ir_diff_dumper_ = nullptr;
AbiElementMap<MergeStatus> *local_to_global_type_id_map_ = nullptr;
};
void ReplaceTypeIdsWithTypeNames(
const AbiElementMap<const TypeIR *> &type_graph, LinkableMessageIR *lm);
} // namespace abi_util
#endif