#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