1 // Copyright (C) 2016 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 #include "diff/abi_diff_wrappers.h"
16 
17 #include "utils/header_abi_util.h"
18 
19 #include <llvm/Support/raw_ostream.h>
20 
21 
22 namespace header_checker {
23 namespace diff {
24 
25 
26 using repr::AbiElementMap;
27 using repr::DiffStatus;
28 using repr::Unwind;
29 
30 
31 template <>
DumpDiff(repr::DiffMessageIR::DiffKind diff_kind)32 bool DiffWrapper<repr::RecordTypeIR>::DumpDiff(
33     repr::DiffMessageIR::DiffKind diff_kind) {
34   std::deque<std::string> type_queue;
35   if (oldp_->GetLinkerSetKey() != newp_->GetLinkerSetKey()) {
36     llvm::errs() << "Comparing two different unreferenced records\n";
37     return false;
38   }
39   if (!type_cache_->insert(
40           oldp_->GetSelfType() + newp_->GetSelfType()).second) {
41     return true;
42   }
43   CompareRecordTypes(oldp_, newp_, &type_queue, diff_kind);
44   return true;
45 }
46 
47 template <>
DumpDiff(repr::DiffMessageIR::DiffKind diff_kind)48 bool DiffWrapper<repr::EnumTypeIR>::DumpDiff(
49     repr::DiffMessageIR::DiffKind diff_kind) {
50   std::deque<std::string> type_queue;
51   if (oldp_->GetLinkerSetKey() != newp_->GetLinkerSetKey()) {
52     llvm::errs() << "Comparing two different unreferenced enums\n";
53     return false;
54   }
55   if (!type_cache_->insert(
56       oldp_->GetSelfType() + newp_->GetSelfType()).second) {
57     return true;
58   }
59   CompareEnumTypes(oldp_, newp_, &type_queue, diff_kind);
60   return true;
61 }
62 
63 template <>
DumpDiff(repr::DiffMessageIR::DiffKind diff_kind)64 bool DiffWrapper<repr::GlobalVarIR>::DumpDiff(
65     repr::DiffMessageIR::DiffKind diff_kind) {
66   std::deque<std::string> type_queue;
67   type_queue.push_back(oldp_->GetName());
68   DiffStatus type_diff = CompareAndDumpTypeDiff(oldp_->GetReferencedType(),
69                                                 newp_->GetReferencedType(),
70                                                 &type_queue, diff_kind);
71   DiffStatus access_diff = (oldp_->GetAccess() == newp_->GetAccess()) ?
72       DiffStatus::no_diff : DiffStatus::direct_diff;
73   if ((type_diff | access_diff) & DiffStatus::direct_diff) {
74     repr::GlobalVarIR old_global_var = *oldp_;
75     repr::GlobalVarIR new_global_var = *newp_;
76     ReplaceTypeIdsWithTypeNames(old_types_, &old_global_var);
77     ReplaceTypeIdsWithTypeNames(new_types_, &new_global_var);
78     repr::GlobalVarDiffIR global_var_diff_ir(&old_global_var,
79                                                  &new_global_var);
80     global_var_diff_ir.SetName(oldp_->GetName());
81     return ir_diff_dumper_->AddDiffMessageIR(&global_var_diff_ir,
82                                              Unwind(&type_queue), diff_kind);
83   }
84   return true;
85 }
86 
87 template <>
DumpDiff(repr::DiffMessageIR::DiffKind diff_kind)88 bool DiffWrapper<repr::FunctionIR>::DumpDiff(
89     repr::DiffMessageIR::DiffKind diff_kind) {
90   std::deque<std::string> type_queue;
91   type_queue.push_back(oldp_->GetName());
92 
93   DiffStatus param_diffs = CompareFunctionParameters(
94       oldp_->GetParameters(), newp_->GetParameters(), &type_queue, diff_kind);
95 
96   DiffStatus return_type_diff = CompareAndDumpTypeDiff(
97       oldp_->GetReturnType(), newp_->GetReturnType(), &type_queue, diff_kind);
98 
99   CompareTemplateInfo(oldp_->GetTemplateElements(),
100                       newp_->GetTemplateElements(),
101                       &type_queue, diff_kind);
102 
103   if ((param_diffs == DiffStatus::direct_diff ||
104        return_type_diff == DiffStatus::direct_diff) ||
105       (oldp_->GetAccess() != newp_->GetAccess())) {
106     repr::FunctionIR old_function = *oldp_;
107     repr::FunctionIR new_function = *newp_;
108     ReplaceTypeIdsWithTypeNames(old_types_, &old_function);
109     ReplaceTypeIdsWithTypeNames(new_types_, &new_function);
110     repr::FunctionDiffIR function_diff_ir(&old_function, &new_function);
111     function_diff_ir.SetName(oldp_->GetName());
112     return ir_diff_dumper_->AddDiffMessageIR(&function_diff_ir,
113                                              Unwind(&type_queue), diff_kind);
114   }
115   return true;
116 }
117 
118 
119 }  // namespace diff
120 }  // namespace header_checker
121