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