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