1 // Copyright (C) 2019 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 HEADER_CHECKER_REPR_IR_DIFF_REPRESENTATION_H_ 16 #define HEADER_CHECKER_REPR_IR_DIFF_REPRESENTATION_H_ 17 18 #include "repr/ir_representation.h" 19 20 #include <cstdint> 21 #include <memory> 22 #include <string> 23 #include <utility> 24 #include <vector> 25 26 27 namespace header_checker { 28 namespace repr { 29 30 31 class DiffMessageIR { 32 public: 33 enum DiffKind { 34 Extension, // Applicable for enums. 35 Added, 36 Removed, 37 Referenced, 38 Unreferenced 39 }; 40 41 public: ~DiffMessageIR()42 virtual ~DiffMessageIR() {} 43 44 virtual LinkableMessageKind Kind() const = 0; 45 SetName(const std::string & name)46 void SetName(const std::string &name) { 47 name_ = name; 48 } 49 GetName()50 const std::string &GetName() const { 51 return name_; 52 } 53 54 protected: 55 std::string name_; 56 }; 57 58 class AccessSpecifierDiffIR { 59 public: AccessSpecifierDiffIR(AccessSpecifierIR old_access,AccessSpecifierIR new_access)60 AccessSpecifierDiffIR(AccessSpecifierIR old_access, 61 AccessSpecifierIR new_access) 62 : old_access_(old_access), new_access_(new_access) {} 63 64 protected: 65 AccessSpecifierIR old_access_; 66 AccessSpecifierIR new_access_; 67 }; 68 69 class TypeDiffIR { 70 public: TypeDiffIR(std::pair<uint64_t,uint64_t> && sizes,std::pair<uint32_t,uint32_t> && alignment)71 TypeDiffIR(std::pair<uint64_t, uint64_t> &&sizes, 72 std::pair<uint32_t, uint32_t> &&alignment) 73 : sizes_(std::move(sizes)), alignments_(std::move(alignment)) {} 74 GetSizes()75 const std::pair<uint64_t, uint64_t> &GetSizes() const { 76 return sizes_; 77 } 78 GetAlignments()79 const std::pair<uint32_t, uint32_t> &GetAlignments() const { 80 return alignments_; 81 } 82 83 protected: 84 std::pair<uint64_t, uint64_t> sizes_; 85 std::pair<uint32_t, uint32_t> alignments_; 86 }; 87 88 class VTableLayoutDiffIR { 89 public: VTableLayoutDiffIR(const VTableLayoutIR & old_layout,const VTableLayoutIR & new_layout)90 VTableLayoutDiffIR(const VTableLayoutIR &old_layout, 91 const VTableLayoutIR &new_layout) 92 : old_layout_(old_layout), new_layout_(new_layout) {} 93 GetOldVTable()94 const VTableLayoutIR &GetOldVTable() const { 95 return old_layout_; 96 } 97 GetNewVTable()98 const VTableLayoutIR &GetNewVTable() const { 99 return new_layout_; 100 } 101 102 protected: 103 const VTableLayoutIR &old_layout_; 104 const VTableLayoutIR &new_layout_; 105 }; 106 107 class RecordFieldDiffIR { 108 public: RecordFieldDiffIR(const RecordFieldIR * old_field,const RecordFieldIR * new_field)109 RecordFieldDiffIR(const RecordFieldIR *old_field, 110 const RecordFieldIR *new_field) 111 : old_field_(old_field), new_field_(new_field) {} 112 GetOldField()113 const RecordFieldIR *GetOldField() const { 114 return old_field_; 115 } 116 GetNewField()117 const RecordFieldIR *GetNewField() const { 118 return new_field_; 119 } 120 121 const RecordFieldIR *old_field_; 122 const RecordFieldIR *new_field_; 123 }; 124 125 class CXXBaseSpecifierDiffIR { 126 public: CXXBaseSpecifierDiffIR(const std::vector<CXXBaseSpecifierIR> & old_base_specifiers,const std::vector<CXXBaseSpecifierIR> & new_base_specifiers)127 CXXBaseSpecifierDiffIR( 128 const std::vector<CXXBaseSpecifierIR> &old_base_specifiers, 129 const std::vector<CXXBaseSpecifierIR> &new_base_specifiers) 130 : old_base_specifiers_(old_base_specifiers), 131 new_base_specifiers_(new_base_specifiers) {} 132 GetOldBases()133 const std::vector<CXXBaseSpecifierIR> &GetOldBases() const { 134 return old_base_specifiers_; 135 } 136 GetNewBases()137 const std::vector<CXXBaseSpecifierIR> &GetNewBases() const { 138 return new_base_specifiers_; 139 } 140 141 protected: 142 const std::vector<CXXBaseSpecifierIR> &old_base_specifiers_; 143 const std::vector<CXXBaseSpecifierIR> &new_base_specifiers_; 144 }; 145 146 class RecordTypeDiffIR : public DiffMessageIR { 147 public: Kind()148 LinkableMessageKind Kind() const override { 149 return LinkableMessageKind::RecordTypeKind; 150 } 151 SetFieldDiffs(std::vector<RecordFieldDiffIR> && field_diffs)152 void SetFieldDiffs(std::vector<RecordFieldDiffIR> &&field_diffs) { 153 field_diffs_ = std::move(field_diffs); 154 } 155 GetFieldDiffs()156 const std::vector<RecordFieldDiffIR> &GetFieldDiffs() const { 157 return field_diffs_; 158 } 159 SetFieldsRemoved(std::vector<const RecordFieldIR * > && fields_removed)160 void SetFieldsRemoved(std::vector<const RecordFieldIR *> &&fields_removed) { 161 fields_removed_ = std::move(fields_removed); 162 } 163 SetFieldsAdded(std::vector<const RecordFieldIR * > && fields_added)164 void SetFieldsAdded(std::vector<const RecordFieldIR *> &&fields_added) { 165 fields_added_ = std::move(fields_added); 166 } 167 GetFieldsRemoved()168 const std::vector<const RecordFieldIR *> &GetFieldsRemoved() const { 169 return fields_removed_; 170 } 171 GetFieldsAdded()172 const std::vector<const RecordFieldIR *> &GetFieldsAdded() const { 173 return fields_added_; 174 } 175 SetVTableLayoutDiff(std::unique_ptr<VTableLayoutDiffIR> && vtable_diffs)176 void SetVTableLayoutDiff(std::unique_ptr<VTableLayoutDiffIR> &&vtable_diffs) { 177 vtable_diffs_ = std::move(vtable_diffs); 178 } 179 SetTypeDiff(std::unique_ptr<TypeDiffIR> && type_diff)180 void SetTypeDiff(std::unique_ptr<TypeDiffIR> &&type_diff) { 181 type_diff_ = std::move(type_diff); 182 } 183 SetAccessDiff(std::unique_ptr<AccessSpecifierDiffIR> && access_diff)184 void SetAccessDiff(std::unique_ptr<AccessSpecifierDiffIR> &&access_diff) { 185 access_diff_ = std::move(access_diff); 186 } 187 SetBaseSpecifierDiffs(std::unique_ptr<CXXBaseSpecifierDiffIR> && base_diffs)188 void SetBaseSpecifierDiffs( 189 std::unique_ptr<CXXBaseSpecifierDiffIR> &&base_diffs) { 190 base_specifier_diffs_ = std::move(base_diffs); 191 } 192 DiffExists()193 bool DiffExists() const { 194 return (type_diff_ != nullptr) || (vtable_diffs_ != nullptr) || 195 (fields_removed_.size() != 0) || (field_diffs_.size() != 0) || 196 (access_diff_ != nullptr) || (base_specifier_diffs_ != nullptr); 197 } 198 GetTypeDiff()199 const TypeDiffIR *GetTypeDiff() const { 200 return type_diff_.get(); 201 } 202 GetVTableLayoutDiff()203 const VTableLayoutDiffIR *GetVTableLayoutDiff() const { 204 return vtable_diffs_.get(); 205 } 206 GetBaseSpecifiers()207 const CXXBaseSpecifierDiffIR *GetBaseSpecifiers() const { 208 return base_specifier_diffs_.get(); 209 } 210 211 protected: 212 // optional implemented with vector / std::unique_ptr. 213 std::unique_ptr<TypeDiffIR> type_diff_; 214 std::unique_ptr<VTableLayoutDiffIR> vtable_diffs_; 215 std::vector<RecordFieldDiffIR> field_diffs_; 216 std::vector<const RecordFieldIR *> fields_removed_; 217 std::vector<const RecordFieldIR *> fields_added_; 218 std::unique_ptr<AccessSpecifierDiffIR> access_diff_; 219 std::unique_ptr<CXXBaseSpecifierDiffIR> base_specifier_diffs_; 220 // Template Diffs are not needed since they will show up in the linker set 221 // key. 222 }; 223 224 class EnumFieldDiffIR { 225 public: EnumFieldDiffIR(const EnumFieldIR * old_field,const EnumFieldIR * new_field)226 EnumFieldDiffIR(const EnumFieldIR *old_field, const EnumFieldIR *new_field) 227 : old_field_(old_field), new_field_(new_field) {} 228 GetOldField()229 const EnumFieldIR *GetOldField() const { 230 return old_field_; 231 } 232 GetNewField()233 const EnumFieldIR *GetNewField() const { 234 return new_field_; 235 } 236 237 protected: 238 const EnumFieldIR *old_field_; 239 const EnumFieldIR *new_field_; 240 }; 241 242 class EnumTypeDiffIR : public DiffMessageIR { 243 public: SetFieldsRemoved(std::vector<const EnumFieldIR * > && fields_removed)244 void SetFieldsRemoved(std::vector<const EnumFieldIR *> &&fields_removed) { 245 fields_removed_ = std::move(fields_removed); 246 } 247 GetFieldsRemoved()248 const std::vector<const EnumFieldIR *> &GetFieldsRemoved() const { 249 return fields_removed_; 250 } 251 SetFieldsAdded(std::vector<const EnumFieldIR * > && fields_added)252 void SetFieldsAdded(std::vector<const EnumFieldIR *> &&fields_added) { 253 fields_added_ = std::move(fields_added); 254 } 255 GetFieldsAdded()256 const std::vector<const EnumFieldIR *> &GetFieldsAdded() const { 257 return fields_added_; 258 } 259 SetFieldsDiff(std::vector<EnumFieldDiffIR> && fields_diff)260 void SetFieldsDiff(std::vector<EnumFieldDiffIR> &&fields_diff) { 261 fields_diff_ = std::move(fields_diff); 262 } 263 GetFieldsDiff()264 const std::vector<EnumFieldDiffIR> &GetFieldsDiff() const { 265 return fields_diff_; 266 } 267 SetUnderlyingTypeDiff(std::unique_ptr<std::pair<std::string,std::string>> && utype_diff)268 void SetUnderlyingTypeDiff( 269 std::unique_ptr<std::pair<std::string, std::string>> &&utype_diff) { 270 underlying_type_diff_ = std::move(utype_diff); 271 } 272 GetUnderlyingTypeDiff()273 const std::pair<std::string, std::string> *GetUnderlyingTypeDiff() const { 274 return underlying_type_diff_.get(); 275 } 276 IsExtended()277 bool IsExtended() const { 278 if (fields_removed_.size() == 0 && fields_diff_.size() == 0 && 279 fields_added_.size() != 0) { 280 return true; 281 } 282 return false; 283 } 284 IsIncompatible()285 bool IsIncompatible() const { 286 if (fields_removed_.size() != 0 || fields_diff_.size() != 0) { 287 return true; 288 } 289 return false; 290 } 291 Kind()292 LinkableMessageKind Kind() const override { 293 return LinkableMessageKind::EnumTypeKind; 294 } 295 296 protected: 297 // The underlying type can only be integral, so we just need to check for 298 // referenced type. 299 std::unique_ptr<std::pair<std::string, std::string>> underlying_type_diff_; 300 std::vector<const EnumFieldIR *> fields_removed_; 301 std::vector<const EnumFieldIR *> fields_added_; 302 std::vector<EnumFieldDiffIR> fields_diff_; 303 // Modifiable to allow implicit construction. 304 std::string name_; 305 }; 306 307 class GlobalVarDiffIR : public DiffMessageIR { 308 public: Kind()309 LinkableMessageKind Kind() const override { 310 return LinkableMessageKind::GlobalVarKind; 311 } 312 GlobalVarDiffIR(const GlobalVarIR * old_global_var,const GlobalVarIR * new_global_var)313 GlobalVarDiffIR(const GlobalVarIR *old_global_var, 314 const GlobalVarIR *new_global_var) 315 : old_global_var_(old_global_var), new_global_var_(new_global_var) {} 316 GetOldGlobalVar()317 const GlobalVarIR *GetOldGlobalVar() const { 318 return old_global_var_; 319 } 320 GetNewGlobalVar()321 const GlobalVarIR *GetNewGlobalVar() const { 322 return new_global_var_; 323 } 324 325 protected: 326 const GlobalVarIR *old_global_var_; 327 const GlobalVarIR *new_global_var_; 328 }; 329 330 class FunctionDiffIR : public DiffMessageIR { 331 public: FunctionDiffIR(const FunctionIR * old_function,const FunctionIR * new_function)332 FunctionDiffIR(const FunctionIR *old_function, 333 const FunctionIR *new_function) 334 : old_function_(old_function), new_function_(new_function) {} 335 Kind()336 LinkableMessageKind Kind() const override { 337 return LinkableMessageKind::FunctionKind; 338 } 339 GetOldFunction()340 const FunctionIR *GetOldFunction() const { 341 return old_function_; 342 } 343 GetNewFunction()344 const FunctionIR *GetNewFunction() const { 345 return new_function_; 346 } 347 348 protected: 349 const FunctionIR *old_function_; 350 const FunctionIR *new_function_; 351 }; 352 353 354 } // namespace repr 355 } // namespace header_checker 356 357 358 #endif // HEADER_CHECKER_REPR_IR_DIFF_REPRESENTATION_H_ 359