1 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
2 // -*- Mode: C++ -*-
3 //
4 // Copyright (C) 2013-2020 Red Hat, Inc.
5 //
6 // Author: Dodji Seketeli
7 
8 #ifndef __ABG_REPORTER_PRIV_H__
9 #define __ABG_REPORTER_PRIV_H__
10 
11 #include "abg-comparison.h"
12 #include "abg-reporter.h"
13 
14 /// This is a subroutine of a *::report() function.
15 ///
16 /// If the diff about two subjects S1 and S2 was reported earlier or
17 /// is being reported, emit a diagnostic message about this and return
18 /// from the current diff reporting function.
19 ///
20 /// @param S1 the first diff subject to take in account.
21 ///
22 /// @param S2 the second diff subject to take in account.
23 #define RETURN_IF_BEING_REPORTED_OR_WAS_REPORTED_EARLIER(S1, S2)	\
24   do {									\
25     if (diff_context_sptr ctxt = d.context())				\
26       if (diff_sptr _diff_ = ctxt->get_canonical_diff_for(S1, S2))	\
27 	if (_diff_->currently_reporting() || _diff_->reported_once())	\
28 	  {								\
29 	    if (_diff_->currently_reporting())				\
30 	      out << indent << "details are being reported\n";		\
31 	    else							\
32 	      out << indent << "details were reported earlier\n";	\
33 	    return;							\
34 	  }								\
35   } while (false)
36 
37 /// This is a subroutine of a *::report() function.
38 ///
39 /// If a given diff was reported earlier or is being reported, emit a
40 /// diagnostic message about this and return from the current diff
41 /// reporting function.
42 ///
43 /// @param S1 the first diff subject to take in account.
44 ///
45 /// @param S2 the second diff subject to take in account.
46 ///
47 /// @param INTRO_TEXT the introductory text that precedes the
48 /// diagnostic.
49 #define RETURN_IF_BEING_REPORTED_OR_WAS_REPORTED_EARLIER2(D, INTRO_TEXT) \
50   do {									\
51     if (diff_sptr _diff_ = d.context()->get_canonical_diff_for(D))	\
52       if (_diff_->currently_reporting() || _diff_->reported_once())	\
53 	{								\
54 	  string _name_ = _diff_->first_subject()->get_pretty_representation(); \
55 	  if (_diff_->currently_reporting())				\
56 	    out << indent << INTRO_TEXT << " '" << _name_		\
57 		<< "' changed, as being reported\n";			\
58 	  else								\
59 	    {								\
60 	      out << indent << INTRO_TEXT << " '"			\
61 	      << _name_ << "' changed";					\
62 	      report_loc_info(D->first_subject(), *d.context(), out);	\
63 	      out << ", as reported earlier\n";				\
64 	    }								\
65 	  return ;							\
66 	}								\
67   } while (false)
68 
69 /// This is a subroutine of a *::report() function.
70 ///
71 /// If the diff about two subjects S1 and S2 was reported earlier or
72 /// is being reported, emit a diagnostic message about this and return
73 /// from the current diff reporting function.
74 ///
75 ///
76 /// @param INTRO_TEXT the introductory text that precedes the
77 /// diagnostic.
78 #define RETURN_IF_BEING_REPORTED_OR_WAS_REPORTED_EARLIER3(S1, S2, INTRO_TEXT) \
79     do {								\
80       if (diff_sptr _diff_ = d.context()->get_canonical_diff_for(S1, S2)) \
81 	if (_diff_->currently_reporting() || _diff_->reported_once())	\
82 	  {								\
83 	    string _name_ = _diff_->first_subject()->get_pretty_representation(); \
84 	    if (_diff_->currently_reporting())				\
85 	      out << indent << INTRO_TEXT << " '" << _name_ << "' changed; " \
86 		"details are being reported\n";				\
87 	    else							\
88 	      {								\
89 		out << indent << INTRO_TEXT << " '" << _name_ << "' changed"; \
90 		report_loc_info(S1, *d.context(), out);			\
91 		out << ", as reported earlier\n";			\
92 	      }								\
93 	    return ;							\
94 	  } \
95     } while (false)
96 
97 namespace abigail
98 {
99 
100 namespace comparison
101 {
102 
103 uint64_t
104 convert_bits_to_bytes(size_t bits);
105 
106 uint64_t
107 maybe_convert_bits_to_bytes(uint64_t bits, const diff_context& ctxt);
108 
109 void
110 emit_num_value(uint64_t value, const diff_context& ctxt, ostream& out);
111 
112 void
113 show_offset_or_size(const string&	what,
114 		    uint64_t		value,
115 		    const diff_context& ctxt,
116 		    ostream&		out);
117 
118 void
119 show_offset_or_size(uint64_t		value,
120 		    const diff_context& ctxt,
121 		    ostream&		out);
122 
123 void
124 show_numerical_change(const string&		what,
125 		      uint64_t			old_bits,
126 		      uint64_t			new_bits,
127 		      const diff_context&	ctxt,
128 		      ostream&			out,
129 		      bool show_bits_or_bytes = true);
130 
131 void
132 represent(const diff_context& ctxt,
133 	  method_decl_sptr mem_fn,
134 	  ostream& out);
135 
136 void
137 represent_data_member(var_decl_sptr d,
138 		      const diff_context_sptr& ctxt,
139 		      ostream& out,
140 		      const string& indent);
141 
142 void
143 maybe_show_relative_offset_change(const var_diff_sptr &diff,
144 				  diff_context& ctxt,
145 				  ostream&	out);
146 
147 void
148 maybe_show_relative_size_change(const var_diff_sptr	&diff,
149 				diff_context&		ctxt,
150 				ostream&		out);
151 
152 void
153 represent(const var_diff_sptr	&diff,
154 	  diff_context_sptr	ctxt,
155 	  ostream&		out,
156 	  const string&	indent = "",
157 	  bool			local_only = false);
158 
159 void
160 report_size_and_alignment_changes(type_or_decl_base_sptr	first,
161 				  type_or_decl_base_sptr	second,
162 				  diff_context_sptr		ctxt,
163 				  ostream&			out,
164 				  const string&			indent);
165 
166 bool
167 report_loc_info(const type_or_decl_base_sptr& tod,
168 		const diff_context& ctxt,
169 		ostream &out);
170 
171 void
172 report_name_size_and_alignment_changes(decl_base_sptr		first,
173 				       decl_base_sptr		second,
174 				       diff_context_sptr	ctxt,
175 				       ostream&		out,
176 				       const string&		indent);
177 
178 /// Represent the kind of difference we want report_mem_header() to
179 /// report.
180 enum diff_kind
181 {
182   del_kind,
183   ins_kind,
184   subtype_change_kind,
185   change_kind
186 };
187 
188 void
189 report_mem_header(ostream& out,
190 		  diff_kind k,
191 		  const string& section_name,
192 		  const string& indent);
193 
194 void
195 report_mem_header(ostream& out,
196 		  size_t number,
197 		  size_t num_filtered,
198 		  diff_kind k,
199 		  const string& section_name,
200 		  const string& indent);
201 
202 bool
203 maybe_report_diff_for_member(const decl_base_sptr&	decl1,
204 			     const decl_base_sptr&	decl2,
205 			     const diff_context_sptr&	ctxt,
206 			     ostream&			out,
207 			     const string&		indent);
208 
209 void
210 maybe_report_diff_for_symbol(const elf_symbol_sptr&	symbol1,
211 			     const elf_symbol_sptr&	symbol2,
212 			     const diff_context_sptr&	ctxt,
213 			     ostream&			out,
214 			     const string&		indent);
215 
216 void
217 show_linkage_name_and_aliases(ostream& out,
218 			      const string& indent,
219 			      const elf_symbol& symbol,
220 			      const string_elf_symbols_map_type& sym_map);
221 
222 void
223 maybe_report_unreachable_type_changes(const corpus_diff& d,
224 				      const corpus_diff::diff_stats &s,
225 				      const string& indent,
226 				      ostream& out);
227 
228 void
229 maybe_report_interfaces_impacted_by_diff(const diff		*d,
230 					 ostream		&out,
231 					 const string		&indent);
232 
233 void
234 maybe_report_interfaces_impacted_by_diff(const diff_sptr	&d,
235 					 ostream		&out,
236 					 const string		&indent);
237 
238 void
239 maybe_report_data_members_replaced_by_anon_dm(const class_or_union_diff &d,
240 					      ostream			&out,
241 					      const string		indent);
242 
243 
244 } // end namespace comparison
245 } // end namespace abigail
246 
247 #endif // __ABG_REPORTER_PRIV_H__
248