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_representation.h" 21 22 #include <deque> 23 24 25 namespace header_checker { 26 namespace repr { 27 28 29 // Classes which act as middle-men between clang AST parsing routines and 30 // message format specific dumpers. 31 32 enum DiffStatus { 33 // There was no diff found while comparing types. 34 no_diff = 0, 35 // There was a diff found and it should be added as a part of a diff message. 36 direct_diff = 1, 37 // There was a diff found, however it need not be added as a part of a diff 38 // message, since it would have already been noted elsewhere. 39 indirect_diff = 2, 40 41 opaque_diff = 3, 42 }; 43 44 static inline DiffStatus operator|(DiffStatus f, DiffStatus s) { 45 return static_cast<DiffStatus>( 46 static_cast<std::underlying_type<DiffStatus>::type>(f) | 47 static_cast<std::underlying_type<DiffStatus>::type>(s)); 48 } 49 50 static inline DiffStatus operator&(DiffStatus f, DiffStatus s) { 51 return static_cast<DiffStatus>( 52 static_cast<std::underlying_type<DiffStatus>::type>(f) & 53 static_cast<std::underlying_type<DiffStatus>::type>(s)); 54 } 55 56 template <typename T> 57 using DiffStatusPair = std::pair<DiffStatus, T>; 58 59 template <typename GenericField, typename GenericFieldDiff> 60 struct GenericFieldDiffInfo { 61 DiffStatus diff_status_; 62 std::vector<GenericFieldDiff> diffed_fields_; 63 std::vector<const GenericField *> removed_fields_; 64 std::vector<const GenericField *> added_fields_; 65 }; 66 67 std::string Unwind(const std::deque<std::string> *type_queue); 68 69 struct DiffPolicyOptions { DiffPolicyOptionsDiffPolicyOptions70 DiffPolicyOptions(bool consider_opaque_types_different) 71 : consider_opaque_types_different_(consider_opaque_types_different) {} 72 73 bool consider_opaque_types_different_; 74 }; 75 76 class AbiDiffHelper { 77 public: 78 AbiDiffHelper( 79 const AbiElementMap<const TypeIR *> &old_types, 80 const AbiElementMap<const TypeIR *> &new_types, 81 const DiffPolicyOptions &diff_policy_options, 82 std::set<std::string> *type_cache, 83 IRDiffDumper *ir_diff_dumper = nullptr) old_types_(old_types)84 : old_types_(old_types), new_types_(new_types), 85 diff_policy_options_(diff_policy_options), type_cache_(type_cache), 86 ir_diff_dumper_(ir_diff_dumper) {} 87 88 DiffStatus CompareAndDumpTypeDiff( 89 const std::string &old_type_str, const std::string &new_type_str, 90 std::deque<std::string> *type_queue = nullptr, 91 IRDiffDumper::DiffKind diff_kind = DiffMessageIR::Unreferenced); 92 93 DiffStatus CompareAndDumpTypeDiff( 94 const TypeIR *old_type, const TypeIR *new_type, 95 LinkableMessageKind kind, 96 std::deque<std::string> *type_queue = nullptr, 97 IRDiffDumper::DiffKind diff_kind = DiffMessageIR::Unreferenced); 98 99 100 DiffStatus CompareRecordTypes(const RecordTypeIR *old_type, 101 const RecordTypeIR *new_type, 102 std::deque<std::string> *type_queue, 103 IRDiffDumper::DiffKind diff_kind); 104 105 DiffStatus CompareEnumTypes(const EnumTypeIR *old_type, 106 const EnumTypeIR *new_type, 107 std::deque<std::string> *type_queue, 108 IRDiffDumper::DiffKind diff_kind); 109 110 DiffStatus CompareFunctionTypes(const FunctionTypeIR *old_type, 111 const FunctionTypeIR *new_type, 112 std::deque<std::string> *type_queue, 113 DiffMessageIR::DiffKind diff_kind); 114 115 DiffStatus CompareFunctionParameters( 116 const std::vector<ParamIR> &old_parameters, 117 const std::vector<ParamIR> &new_parameters, 118 std::deque<std::string> *type_queue, 119 IRDiffDumper::DiffKind diff_kind); 120 121 DiffStatus CompareTemplateInfo( 122 const std::vector<TemplateElementIR> &old_template_elements, 123 const std::vector<TemplateElementIR> &new_template_elements, 124 std::deque<std::string> *type_queue, 125 IRDiffDumper::DiffKind diff_kind); 126 127 128 private: 129 DiffStatus CompareQualifiedTypes(const QualifiedTypeIR *old_type, 130 const QualifiedTypeIR *new_type, 131 std::deque<std::string> *type_queue, 132 IRDiffDumper::DiffKind diff_kind); 133 134 DiffStatus ComparePointerTypes(const PointerTypeIR *old_type, 135 const PointerTypeIR *new_type, 136 std::deque<std::string> *type_queue, 137 IRDiffDumper::DiffKind diff_kind); 138 139 DiffStatus CompareLvalueReferenceTypes( 140 const LvalueReferenceTypeIR *old_type, 141 const LvalueReferenceTypeIR *new_type, 142 std::deque<std::string> *type_queue, 143 IRDiffDumper::DiffKind diff_kind); 144 145 DiffStatus CompareRvalueReferenceTypes( 146 const RvalueReferenceTypeIR *old_type, 147 const RvalueReferenceTypeIR *new_type, 148 std::deque<std::string> *type_queue, 149 IRDiffDumper::DiffKind diff_kind); 150 151 152 DiffStatus CompareBuiltinTypes(const BuiltinTypeIR *old_type, 153 const BuiltinTypeIR *new_type); 154 155 static void CompareEnumFields( 156 const std::vector<EnumFieldIR> &old_fields, 157 const std::vector<EnumFieldIR> &new_fields, 158 EnumTypeDiffIR *enum_type_diff_ir); 159 160 161 void ReplaceRemovedFieldTypeIdsWithTypeNames( 162 std::vector<RecordFieldIR *> *removed_fields); 163 164 void ReplaceDiffedFieldTypeIdsWithTypeNames( 165 RecordFieldDiffIR *diffed_field); 166 167 std::vector<std::pair<RecordFieldIR, RecordFieldIR>> 168 FixupDiffedFieldTypeIds( 169 const std::vector<RecordFieldDiffIR> &field_diffs); 170 171 DiffStatusPair<std::unique_ptr<RecordFieldDiffIR>> 172 CompareCommonRecordFields( 173 const RecordFieldIR *old_field, 174 const RecordFieldIR *new_field, 175 std::deque<std::string> *type_queue, 176 IRDiffDumper::DiffKind diff_kind); 177 178 GenericFieldDiffInfo<RecordFieldIR, RecordFieldDiffIR> 179 CompareRecordFields( 180 const std::vector<RecordFieldIR> &old_fields, 181 const std::vector<RecordFieldIR> &new_fields, 182 std::deque<std::string> *type_queue, 183 IRDiffDumper::DiffKind diff_kind); 184 185 bool CompareBaseSpecifiers( 186 const std::vector<CXXBaseSpecifierIR> &old_base_specifiers, 187 const std::vector<CXXBaseSpecifierIR> &new_base_specifiers, 188 std::deque<std::string> *type_queue, 189 IRDiffDumper::DiffKind diff_kind); 190 191 bool CompareVTables(const RecordTypeIR *old_record, 192 const RecordTypeIR *new_record); 193 194 bool CompareVTableComponents( 195 const VTableComponentIR &old_component, 196 const VTableComponentIR &new_component); 197 198 bool CompareSizeAndAlignment(const TypeIR *old_ti, 199 const TypeIR *new_ti); 200 201 template <typename DiffType, typename DiffElement> 202 bool AddToDiff(DiffType *mutable_diff, const DiffElement *oldp, 203 const DiffElement *newp, 204 std::deque<std::string> *type_queue = nullptr); 205 206 protected: 207 const AbiElementMap<const TypeIR *> &old_types_; 208 const AbiElementMap<const TypeIR *> &new_types_; 209 const DiffPolicyOptions &diff_policy_options_; 210 std::set<std::string> *type_cache_; 211 IRDiffDumper *ir_diff_dumper_; 212 }; 213 214 void ReplaceTypeIdsWithTypeNames( 215 const AbiElementMap<const TypeIR *> &type_graph, LinkableMessageIR *lm); 216 217 218 } // namespace repr 219 } // namespace header_checker 220 221 222 #endif // ABI_DIFF_HELPERS_H_ 223