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