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 #include <set> 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 class DiffStatus { 34 public: 35 enum Status { 36 kNoDiff = 0, 37 // The diff has been added to the IRDiffDumper. 38 kIndirectDiff = 1, 39 // The diff has not been added to the IRDiffDumper, and the new ABI is 40 // an extension to the old ABI. 41 kDirectExt = 2, 42 // The diff has not been added to the IRDiffDumper. 43 kDirectDiff = 3, 44 }; 45 46 // Allow implicit conversion. DiffStatus(Status status)47 DiffStatus(Status status) : status_(status) {} 48 HasDiff()49 bool HasDiff() const { return status_ != kNoDiff; } 50 IsDirectDiff()51 bool IsDirectDiff() const { 52 return status_ == kDirectDiff || status_ == kDirectExt; 53 } 54 IsExtension()55 bool IsExtension() const { return status_ == kDirectExt; } 56 CombineWith(DiffStatus other)57 DiffStatus &CombineWith(DiffStatus other) { 58 status_ = std::max(status_, other.status_); 59 return *this; 60 } 61 62 private: 63 Status status_; 64 }; 65 66 struct RecordFieldDiffResult { 67 DiffStatus status = DiffStatus::kNoDiff; 68 std::vector<RecordFieldDiffIR> diffed_fields; 69 std::vector<const RecordFieldIR *> removed_fields; 70 std::vector<const RecordFieldIR *> added_fields; 71 }; 72 73 class TypeStackGuard { 74 public: TypeStackGuard(std::deque<std::string> & type_stack,const std::string & type_name)75 TypeStackGuard(std::deque<std::string> &type_stack, 76 const std::string &type_name) 77 : type_stack_(type_stack) { 78 type_stack_.push_back(type_name); 79 } 80 ~TypeStackGuard()81 ~TypeStackGuard() { type_stack_.pop_back(); } 82 83 private: 84 std::deque<std::string> &type_stack_; 85 }; 86 87 struct DiffPolicyOptions { DiffPolicyOptionsDiffPolicyOptions88 DiffPolicyOptions(bool consider_opaque_types_different) 89 : consider_opaque_types_different_(consider_opaque_types_different) {} 90 91 bool consider_opaque_types_different_; 92 }; 93 94 class AbiDiffHelper { 95 public: 96 AbiDiffHelper( 97 const AbiElementMap<const TypeIR *> &old_types, 98 const AbiElementMap<const TypeIR *> &new_types, 99 const DiffPolicyOptions &diff_policy_options, 100 std::set<std::string> *type_cache, 101 const std::set<std::string> &ignored_linker_set_keys, 102 IRDiffDumper *ir_diff_dumper = nullptr) old_types_(old_types)103 : old_types_(old_types), new_types_(new_types), 104 diff_policy_options_(diff_policy_options), type_cache_(type_cache), 105 ignored_linker_set_keys_(ignored_linker_set_keys), 106 ir_diff_dumper_(ir_diff_dumper) {} 107 108 // Concatenate the strings in type_stack. 109 std::string UnwindTypeStack(); 110 111 bool AreOpaqueTypesEqual(const std::string &old_type_str, 112 const std::string &new_type_str) const; 113 114 DiffStatus CompareAndDumpTypeDiff( 115 const std::string &old_type_str, const std::string &new_type_str, 116 IRDiffDumper::DiffKind diff_kind = DiffMessageIR::Unreferenced); 117 118 DiffStatus CompareAndDumpTypeDiff( 119 const TypeIR *old_type, const TypeIR *new_type, LinkableMessageKind kind, 120 IRDiffDumper::DiffKind diff_kind = DiffMessageIR::Unreferenced); 121 122 DiffStatus CompareRecordTypes(const RecordTypeIR *old_type, 123 const RecordTypeIR *new_type, 124 IRDiffDumper::DiffKind diff_kind); 125 126 DiffStatus CompareEnumTypes(const EnumTypeIR *old_type, 127 const EnumTypeIR *new_type, 128 IRDiffDumper::DiffKind diff_kind); 129 130 DiffStatus CompareFunctionTypes(const CFunctionLikeIR *old_type, 131 const CFunctionLikeIR *new_type, 132 DiffMessageIR::DiffKind diff_kind); 133 134 DiffStatus CompareTemplateInfo( 135 const std::vector<TemplateElementIR> &old_template_elements, 136 const std::vector<TemplateElementIR> &new_template_elements, 137 IRDiffDumper::DiffKind diff_kind); 138 139 private: 140 DiffStatus CompareQualifiedTypes(const QualifiedTypeIR *old_type, 141 const QualifiedTypeIR *new_type, 142 IRDiffDumper::DiffKind diff_kind); 143 144 DiffStatus CompareArrayTypes(const ArrayTypeIR *old_type, 145 const ArrayTypeIR *new_type, 146 IRDiffDumper::DiffKind diff_kind); 147 148 DiffStatus ComparePointerTypes(const PointerTypeIR *old_type, 149 const PointerTypeIR *new_type, 150 IRDiffDumper::DiffKind diff_kind); 151 152 DiffStatus CompareLvalueReferenceTypes(const LvalueReferenceTypeIR *old_type, 153 const LvalueReferenceTypeIR *new_type, 154 IRDiffDumper::DiffKind diff_kind); 155 156 DiffStatus CompareRvalueReferenceTypes(const RvalueReferenceTypeIR *old_type, 157 const RvalueReferenceTypeIR *new_type, 158 IRDiffDumper::DiffKind diff_kind); 159 160 DiffStatus CompareBuiltinTypes(const BuiltinTypeIR *old_type, 161 const BuiltinTypeIR *new_type); 162 163 static void CompareEnumFields( 164 const std::vector<EnumFieldIR> &old_fields, 165 const std::vector<EnumFieldIR> &new_fields, 166 EnumTypeDiffIR *enum_type_diff_ir); 167 168 169 void ReplaceRemovedFieldTypeIdsWithTypeNames( 170 std::vector<RecordFieldIR *> *removed_fields); 171 172 void ReplaceDiffedFieldTypeIdsWithTypeNames( 173 RecordFieldDiffIR *diffed_field); 174 175 std::vector<std::pair<RecordFieldIR, RecordFieldIR>> 176 FixupDiffedFieldTypeIds( 177 const std::vector<RecordFieldDiffIR> &field_diffs); 178 179 DiffStatus CompareAccess(AccessSpecifierIR old_access, 180 AccessSpecifierIR new_access); 181 182 DiffStatus CompareCommonRecordFields(const RecordFieldIR *old_field, 183 const RecordFieldIR *new_field, 184 IRDiffDumper::DiffKind diff_kind); 185 186 DiffStatus FilterOutRenamedRecordFields( 187 DiffMessageIR::DiffKind diff_kind, 188 std::vector<const RecordFieldIR *> &old_fields, 189 std::vector<const RecordFieldIR *> &new_fields); 190 191 RecordFieldDiffResult CompareRecordFields( 192 const std::vector<RecordFieldIR> &old_fields, 193 const std::vector<RecordFieldIR> &new_fields, 194 IRDiffDumper::DiffKind diff_kind); 195 196 bool CompareBaseSpecifiers( 197 const std::vector<CXXBaseSpecifierIR> &old_base_specifiers, 198 const std::vector<CXXBaseSpecifierIR> &new_base_specifiers, 199 IRDiffDumper::DiffKind diff_kind); 200 201 DiffStatus CompareFunctionParameters( 202 const std::vector<ParamIR> &old_parameters, 203 const std::vector<ParamIR> &new_parameters, 204 IRDiffDumper::DiffKind diff_kind); 205 206 DiffStatus CompareParameterTypes(const std::string &old_type_id, 207 const std::string &new_type_id, 208 IRDiffDumper::DiffKind diff_kind); 209 210 DiffStatus CompareReturnTypes(const std::string &old_type_id, 211 const std::string &new_type_id, 212 IRDiffDumper::DiffKind diff_kind); 213 214 protected: 215 const AbiElementMap<const TypeIR *> &old_types_; 216 const AbiElementMap<const TypeIR *> &new_types_; 217 const DiffPolicyOptions &diff_policy_options_; 218 std::set<std::string> *type_cache_; 219 std::deque<std::string> type_stack_; 220 const std::set<std::string> &ignored_linker_set_keys_; 221 IRDiffDumper *ir_diff_dumper_; 222 }; 223 224 void ReplaceTypeIdsWithTypeNames( 225 const AbiElementMap<const TypeIR *> &type_graph, LinkableMessageIR *lm); 226 227 228 } // namespace repr 229 } // namespace header_checker 230 231 232 #endif // ABI_DIFF_HELPERS_H_ 233