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