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 CompareQualifiedTypes(const QualifiedTypeIR *old_type, 111 const QualifiedTypeIR *new_type, 112 std::deque<std::string> *type_queue, 113 IRDiffDumper::DiffKind diff_kind); 114 115 DiffStatus ComparePointerTypes(const PointerTypeIR *old_type, 116 const PointerTypeIR *new_type, 117 std::deque<std::string> *type_queue, 118 IRDiffDumper::DiffKind diff_kind); 119 120 DiffStatus CompareLvalueReferenceTypes( 121 const LvalueReferenceTypeIR *old_type, 122 const LvalueReferenceTypeIR *new_type, 123 std::deque<std::string> *type_queue, 124 IRDiffDumper::DiffKind diff_kind); 125 126 DiffStatus CompareRvalueReferenceTypes( 127 const RvalueReferenceTypeIR *old_type, 128 const RvalueReferenceTypeIR *new_type, 129 std::deque<std::string> *type_queue, 130 IRDiffDumper::DiffKind diff_kind); 131 132 133 DiffStatus CompareBuiltinTypes(const BuiltinTypeIR *old_type, 134 const BuiltinTypeIR *new_type); 135 136 static void CompareEnumFields( 137 const std::vector<EnumFieldIR> &old_fields, 138 const std::vector<EnumFieldIR> &new_fields, 139 EnumTypeDiffIR *enum_type_diff_ir); 140 141 DiffStatus CompareEnumTypes(const EnumTypeIR *old_type, 142 const EnumTypeIR *new_type, 143 std::deque<std::string> *type_queue, 144 IRDiffDumper::DiffKind diff_kind); 145 146 DiffStatus CompareFunctionTypes(const FunctionTypeIR *old_type, 147 const FunctionTypeIR *new_type, 148 std::deque<std::string> *type_queue, 149 DiffMessageIR::DiffKind diff_kind); 150 151 void ReplaceRemovedFieldTypeIdsWithTypeNames( 152 std::vector<RecordFieldIR *> *removed_fields); 153 154 void ReplaceDiffedFieldTypeIdsWithTypeNames( 155 RecordFieldDiffIR *diffed_field); 156 157 std::vector<std::pair<RecordFieldIR, RecordFieldIR>> 158 FixupDiffedFieldTypeIds( 159 const std::vector<RecordFieldDiffIR> &field_diffs); 160 161 DiffStatusPair<std::unique_ptr<RecordFieldDiffIR>> 162 CompareCommonRecordFields( 163 const RecordFieldIR *old_field, 164 const RecordFieldIR *new_field, 165 std::deque<std::string> *type_queue, 166 IRDiffDumper::DiffKind diff_kind); 167 168 GenericFieldDiffInfo<RecordFieldIR, RecordFieldDiffIR> 169 CompareRecordFields( 170 const std::vector<RecordFieldIR> &old_fields, 171 const std::vector<RecordFieldIR> &new_fields, 172 std::deque<std::string> *type_queue, 173 IRDiffDumper::DiffKind diff_kind); 174 175 DiffStatus CompareFunctionParameters( 176 const std::vector<ParamIR> &old_parameters, 177 const std::vector<ParamIR> &new_parameters, 178 std::deque<std::string> *type_queue, 179 IRDiffDumper::DiffKind diff_kind); 180 181 bool CompareBaseSpecifiers( 182 const std::vector<CXXBaseSpecifierIR> &old_base_specifiers, 183 const std::vector<CXXBaseSpecifierIR> &new_base_specifiers, 184 std::deque<std::string> *type_queue, 185 IRDiffDumper::DiffKind diff_kind); 186 187 bool CompareVTables(const RecordTypeIR *old_record, 188 const RecordTypeIR *new_record); 189 190 bool CompareVTableComponents( 191 const VTableComponentIR &old_component, 192 const VTableComponentIR &new_component); 193 194 DiffStatus CompareTemplateInfo( 195 const std::vector<TemplateElementIR> &old_template_elements, 196 const std::vector<TemplateElementIR> &new_template_elements, 197 std::deque<std::string> *type_queue, 198 IRDiffDumper::DiffKind diff_kind); 199 200 201 bool CompareSizeAndAlignment(const TypeIR *old_ti, 202 const TypeIR *new_ti); 203 204 template <typename DiffType, typename DiffElement> 205 bool AddToDiff(DiffType *mutable_diff, const DiffElement *oldp, 206 const DiffElement *newp, 207 std::deque<std::string> *type_queue = nullptr); 208 209 protected: 210 const AbiElementMap<const TypeIR *> &old_types_; 211 const AbiElementMap<const TypeIR *> &new_types_; 212 const DiffPolicyOptions &diff_policy_options_; 213 std::set<std::string> *type_cache_; 214 IRDiffDumper *ir_diff_dumper_; 215 AbiElementMap<MergeStatus> *local_to_global_type_id_map_; 216 }; 217 218 void ReplaceTypeIdsWithTypeNames( 219 const AbiElementMap<const TypeIR *> &type_graph, LinkableMessageIR *lm); 220 221 222 } // namespace repr 223 } // namespace header_checker 224 225 226 #endif // ABI_DIFF_HELPERS_H_ 227