1 // Copyright (C) 2018 The Android Open Source Project 2 // 3 // Licensed under the Apache License, Version 2.0 (the "License"); 4 // you may not use this file except in compliance with the License. 5 // You may obtain a copy of the License at 6 // 7 // http://www.apache.org/licenses/LICENSE-2.0 8 // 9 // Unless required by applicable law or agreed to in writing, software 10 // distributed under the License is distributed on an "AS IS" BASIS, 11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 // See the License for the specific language governing permissions and 13 // limitations under the License. 14 15 #ifndef ABI_DIFF_HELPERS_H_ 16 #define ABI_DIFF_HELPERS_H_ 17 18 #include "repr/ir_diff_dumper.h" 19 #include "repr/ir_diff_representation.h" 20 #include "repr/ir_reader.h" 21 #include "repr/ir_representation.h" 22 23 #include <deque> 24 25 26 namespace header_checker { 27 namespace repr { 28 29 30 // Classes which act as middle-men between clang AST parsing routines and 31 // message format specific dumpers. 32 33 using MergeStatus = IRReader::MergeStatus; 34 35 enum DiffStatus { 36 // There was no diff found while comparing types. 37 no_diff = 0, 38 // There was a diff found and it should be added as a part of a diff message. 39 direct_diff = 1, 40 // There was a diff found, however it need not be added as a part of a diff 41 // message, since it would have already been noted elsewhere. 42 indirect_diff = 2, 43 44 opaque_diff = 3, 45 }; 46 47 static inline DiffStatus operator|(DiffStatus f, DiffStatus s) { 48 return static_cast<DiffStatus>( 49 static_cast<std::underlying_type<DiffStatus>::type>(f) | 50 static_cast<std::underlying_type<DiffStatus>::type>(s)); 51 } 52 53 static inline DiffStatus operator&(DiffStatus f, DiffStatus s) { 54 return static_cast<DiffStatus>( 55 static_cast<std::underlying_type<DiffStatus>::type>(f) & 56 static_cast<std::underlying_type<DiffStatus>::type>(s)); 57 } 58 59 template <typename T> 60 using DiffStatusPair = std::pair<DiffStatus, T>; 61 62 template <typename GenericField, typename GenericFieldDiff> 63 struct GenericFieldDiffInfo { 64 DiffStatus diff_status_; 65 std::vector<GenericFieldDiff> diffed_fields_; 66 std::vector<const GenericField *> removed_fields_; 67 std::vector<const GenericField *> added_fields_; 68 }; 69 70 std::string Unwind(const std::deque<std::string> *type_queue); 71 72 struct DiffPolicyOptions { DiffPolicyOptionsDiffPolicyOptions73 DiffPolicyOptions(bool consider_opaque_types_different) 74 : consider_opaque_types_different_(consider_opaque_types_different) {} 75 76 bool consider_opaque_types_different_; 77 }; 78 79 class AbiDiffHelper { 80 public: 81 AbiDiffHelper( 82 const AbiElementMap<const TypeIR *> &old_types, 83 const AbiElementMap<const TypeIR *> &new_types, 84 const DiffPolicyOptions &diff_policy_options, 85 std::set<std::string> *type_cache, 86 IRDiffDumper *ir_diff_dumper = nullptr, 87 AbiElementMap<MergeStatus> *local_to_global_type_id_map = nullptr) old_types_(old_types)88 : old_types_(old_types), new_types_(new_types), 89 diff_policy_options_(diff_policy_options), type_cache_(type_cache), 90 ir_diff_dumper_(ir_diff_dumper), 91 local_to_global_type_id_map_(local_to_global_type_id_map) {} 92 93 DiffStatus CompareAndDumpTypeDiff( 94 const std::string &old_type_str, const std::string &new_type_str, 95 std::deque<std::string> *type_queue = nullptr, 96 IRDiffDumper::DiffKind diff_kind = DiffMessageIR::Unreferenced); 97 98 DiffStatus CompareAndDumpTypeDiff( 99 const TypeIR *old_type, const TypeIR *new_type, 100 LinkableMessageKind kind, 101 std::deque<std::string> *type_queue = nullptr, 102 IRDiffDumper::DiffKind diff_kind = DiffMessageIR::Unreferenced); 103 104 105 DiffStatus CompareRecordTypes(const RecordTypeIR *old_type, 106 const RecordTypeIR *new_type, 107 std::deque<std::string> *type_queue, 108 IRDiffDumper::DiffKind diff_kind); 109 110 DiffStatus CompareEnumTypes(const EnumTypeIR *old_type, 111 const EnumTypeIR *new_type, 112 std::deque<std::string> *type_queue, 113 IRDiffDumper::DiffKind diff_kind); 114 115 DiffStatus CompareFunctionTypes(const FunctionTypeIR *old_type, 116 const FunctionTypeIR *new_type, 117 std::deque<std::string> *type_queue, 118 DiffMessageIR::DiffKind diff_kind); 119 120 DiffStatus CompareFunctionParameters( 121 const std::vector<ParamIR> &old_parameters, 122 const std::vector<ParamIR> &new_parameters, 123 std::deque<std::string> *type_queue, 124 IRDiffDumper::DiffKind diff_kind); 125 126 DiffStatus CompareTemplateInfo( 127 const std::vector<TemplateElementIR> &old_template_elements, 128 const std::vector<TemplateElementIR> &new_template_elements, 129 std::deque<std::string> *type_queue, 130 IRDiffDumper::DiffKind diff_kind); 131 132 133 private: 134 DiffStatus CompareQualifiedTypes(const QualifiedTypeIR *old_type, 135 const QualifiedTypeIR *new_type, 136 std::deque<std::string> *type_queue, 137 IRDiffDumper::DiffKind diff_kind); 138 139 DiffStatus ComparePointerTypes(const PointerTypeIR *old_type, 140 const PointerTypeIR *new_type, 141 std::deque<std::string> *type_queue, 142 IRDiffDumper::DiffKind diff_kind); 143 144 DiffStatus CompareLvalueReferenceTypes( 145 const LvalueReferenceTypeIR *old_type, 146 const LvalueReferenceTypeIR *new_type, 147 std::deque<std::string> *type_queue, 148 IRDiffDumper::DiffKind diff_kind); 149 150 DiffStatus CompareRvalueReferenceTypes( 151 const RvalueReferenceTypeIR *old_type, 152 const RvalueReferenceTypeIR *new_type, 153 std::deque<std::string> *type_queue, 154 IRDiffDumper::DiffKind diff_kind); 155 156 157 DiffStatus CompareBuiltinTypes(const BuiltinTypeIR *old_type, 158 const BuiltinTypeIR *new_type); 159 160 static void CompareEnumFields( 161 const std::vector<EnumFieldIR> &old_fields, 162 const std::vector<EnumFieldIR> &new_fields, 163 EnumTypeDiffIR *enum_type_diff_ir); 164 165 166 void ReplaceRemovedFieldTypeIdsWithTypeNames( 167 std::vector<RecordFieldIR *> *removed_fields); 168 169 void ReplaceDiffedFieldTypeIdsWithTypeNames( 170 RecordFieldDiffIR *diffed_field); 171 172 std::vector<std::pair<RecordFieldIR, RecordFieldIR>> 173 FixupDiffedFieldTypeIds( 174 const std::vector<RecordFieldDiffIR> &field_diffs); 175 176 DiffStatusPair<std::unique_ptr<RecordFieldDiffIR>> 177 CompareCommonRecordFields( 178 const RecordFieldIR *old_field, 179 const RecordFieldIR *new_field, 180 std::deque<std::string> *type_queue, 181 IRDiffDumper::DiffKind diff_kind); 182 183 GenericFieldDiffInfo<RecordFieldIR, RecordFieldDiffIR> 184 CompareRecordFields( 185 const std::vector<RecordFieldIR> &old_fields, 186 const std::vector<RecordFieldIR> &new_fields, 187 std::deque<std::string> *type_queue, 188 IRDiffDumper::DiffKind diff_kind); 189 190 bool CompareBaseSpecifiers( 191 const std::vector<CXXBaseSpecifierIR> &old_base_specifiers, 192 const std::vector<CXXBaseSpecifierIR> &new_base_specifiers, 193 std::deque<std::string> *type_queue, 194 IRDiffDumper::DiffKind diff_kind); 195 196 bool CompareVTables(const RecordTypeIR *old_record, 197 const RecordTypeIR *new_record); 198 199 bool CompareVTableComponents( 200 const VTableComponentIR &old_component, 201 const VTableComponentIR &new_component); 202 203 bool CompareSizeAndAlignment(const TypeIR *old_ti, 204 const TypeIR *new_ti); 205 206 template <typename DiffType, typename DiffElement> 207 bool AddToDiff(DiffType *mutable_diff, const DiffElement *oldp, 208 const DiffElement *newp, 209 std::deque<std::string> *type_queue = nullptr); 210 211 protected: 212 const AbiElementMap<const TypeIR *> &old_types_; 213 const AbiElementMap<const TypeIR *> &new_types_; 214 const DiffPolicyOptions &diff_policy_options_; 215 std::set<std::string> *type_cache_; 216 IRDiffDumper *ir_diff_dumper_; 217 AbiElementMap<MergeStatus> *local_to_global_type_id_map_; 218 }; 219 220 void ReplaceTypeIdsWithTypeNames( 221 const AbiElementMap<const TypeIR *> &type_graph, LinkableMessageIR *lm); 222 223 224 } // namespace repr 225 } // namespace header_checker 226 227 228 #endif // ABI_DIFF_HELPERS_H_ 229