| #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, |
| |
| opaque_diff = 3, |
| }; |
| |
| 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); |
| |
| struct DiffPolicyOptions { |
| DiffPolicyOptions(bool consider_opaque_types_different) : |
| consider_opaque_types_different_(consider_opaque_types_different) { } |
| bool consider_opaque_types_different_ = false; |
| }; |
| |
| class AbiDiffHelper { |
| public: |
| AbiDiffHelper( |
| const AbiElementMap<const abi_util::TypeIR *> &old_types, |
| const AbiElementMap<const abi_util::TypeIR *> &new_types, |
| const DiffPolicyOptions &diff_policy_options, |
| 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), |
| diff_policy_options_(diff_policy_options), 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_; |
| const DiffPolicyOptions &diff_policy_options_; |
| 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 |