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