libabigail
abg-suppression.cc
Go to the documentation of this file.
1 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
2 // -*- Mode: C++ -*-
3 //
4 // Copyright (C) 2016-2025 Red Hat, Inc.
5 //
6 // Author: Dodji Seketeli
7 
8 /// @file
9 ///
10 /// This contains the implementation of the suppression engine of
11 /// libabigail.
12 
13 #include <algorithm>
14 
15 #include "abg-internal.h"
16 #include <memory>
17 #include <limits>
18 
19 // <headers defining libabigail's API go under here>
20 ABG_BEGIN_EXPORT_DECLARATIONS
21 
22 #include "abg-ini.h"
23 #include "abg-comp-filter.h"
24 #include "abg-suppression.h"
25 #include "abg-tools-utils.h"
26 #include "abg-fe-iface.h"
27 #include "abg-comparison.h"
28 
30 // </headers defining libabigail's API>
31 
32 #include "abg-suppression-priv.h"
33 
34 namespace abigail
35 {
36 
37 namespace suppr
38 {
39 
40 // Inject the abigail::comparison namespace in here.
41 using namespace comparison;
42 
43 using std::dynamic_pointer_cast;
45 
46 /// @return the string constant "offset_of_flexible_array_data_member".
47 static const string&
48 OFFSET_OF_FLEXIBLE_ARRAY_DATA_MEMBER_STRING()
49 {
50  static string s = "offset_of_flexible_array_data_member";
51  return s;
52 }
53 
54 /// @return the string constant "end";
55 static const string&
56 END_STRING()
57 {
58  static string s = "end";
59  return s;
60 }
61 
62 // <parsing stuff>
63 
64 // section parsing
65 
66 /// Check if a section has at least one of the given properties.
67 ///
68 /// @param names pointer to the start of an array of names.
69 ///
70 /// @param count number of names in the array.
71 ///
72 /// @return whether at least of one the properties was found.
73 bool
74 check_sufficient_props(const char *const * names, size_t count,
75  const ini::config::section& section)
76 {
77  for (const char *const * name = names; name < names + count; ++name)
78  if (section.find_property(*name))
79  return true;
80  // TODO: Possibly give reason for failure in a message here.
81  return false;
82 }
83 
84 // </parsing stuff>
85 
86 // <suppression_base stuff>
87 
88 /// Constructor for @ref suppression_base
89 ///
90 /// @param a label for the suppression. This represents just a
91 /// comment.
92 suppression_base::suppression_base(const string& label)
93  : priv_(new priv(label))
94 {}
95 
96 /// Constructor for @ref suppression_base
97 ///
98 /// @param a label for the suppression. This represents just a
99 /// comment.
100 ///
101 /// @param file_name_regex_str the regular expression that denotes the
102 /// file name to match.
103 ///
104 /// @param file_name_not_regex_str the regular expression that denotes
105 /// the file name to *NOT* match.
106 suppression_base::suppression_base(const string& label,
107  const string& file_name_regex_str,
108  const string& file_name_not_regex_str)
109  : priv_(new priv(label,
110  file_name_regex_str,
111  file_name_not_regex_str))
112 {
113 }
114 
115 /// Tests if the current suppression specification is to avoid adding
116 /// the matched ABI artifact to the internal representation or not.
117 ///
118 /// @return true iff the current suppression specification is to avoid
119 /// adding the matched ABI artifact to the internal representation.
120 bool
122 {return priv_->drops_artifact_;}
123 
124 /// Set the flag that says whether the current suppression
125 /// specification is to avoid adding the matched ABI artifact to the
126 /// internal representation or not.
127 ///
128 /// @param f the flag to set to true iff the current suppression
129 /// specification is to avoid adding the matched ABI artifact to the
130 /// internal representation.
131 void
133 {priv_->drops_artifact_ = f;}
134 
135 /// Test is the suppression specification is artificial.
136 ///
137 /// Artificial means that the suppression was automatically generated
138 /// by libabigail, rather than being constructed from a suppression
139 /// file provided by the user.
140 ///
141 /// @return TRUE iff the suppression specification is artificial.
142 bool
144 {return priv_->is_artificial_;}
145 
146 /// Set a flag saying if the suppression specification is artificial
147 /// or not.
148 ///
149 /// Artificial means that the suppression was automatically generated
150 /// by libabigail, rather than being constructed from a suppression
151 /// file provided by the user.
152 void
154 {priv_->is_artificial_ = f;}
155 
156 /// Getter for the label associated to this suppression specification.
157 ///
158 /// @return the label.
159 const string
161 {return priv_->label_;}
162 
163 /// Setter for the label associated to this suppression specification.
164 ///
165 /// @param label the new label.
166 void
167 suppression_base::set_label(const string& label)
168 {priv_->label_ = label;}
169 
170 /// Setter for the "file_name_regex" property of the current instance
171 /// of @ref suppression_base.
172 ///
173 /// The "file_name_regex" property is a regular expression string that
174 /// designates the file name that contains the ABI artifact this
175 /// suppression should apply to.
176 ///
177 /// @param regexp the new regular expression string.
178 void
180 {priv_->file_name_regex_str_ = regexp;}
181 
182 /// Getter for the "file_name_regex" property of the current instance
183 /// of @ref suppression_base.
184 ///
185 /// The "file_name_regex" property is a regular expression string that
186 /// designates the file name that contains the ABI artifacts this
187 /// suppression should apply to.
188 ///
189 /// @return the regular expression string.
190 const string&
192 {return priv_->file_name_regex_str_;}
193 
194 /// Setter for the "file_name_not_regex" property of the current
195 /// instance of @ref suppression_base.
196 ///
197 /// The current suppression specification should apply to ABI
198 /// artifacts of a file which name does *NOT* match the regular
199 /// expression string designated by the "file_name_not_regex"
200 /// property.
201 ///
202 /// @param regexp the new regular expression string.
203 void
205 {priv_->file_name_not_regex_str_ = regexp;}
206 
207 /// Getter for the "file_name_not_regex" property of the current
208 /// instance of @ref suppression_base.
209 ///
210 /// The current suppression specification should apply to ABI
211 /// artifacts of a file which name does *NOT* match the regular
212 /// expression string designated by the "file_name_not_regex"
213 /// property.
214 ///
215 /// @return the regular expression string.
216 const string&
218 {return priv_->file_name_not_regex_str_;}
219 
220 /// Test if the current suppression has a property related to file
221 /// name.
222 ///
223 /// @return true iff the current suppression has either a
224 /// file_name_regex or a file_name_not_regex property.
225 bool
227 {
228  return (!(get_file_name_regex_str().empty()
229  && get_file_name_not_regex_str().empty()));
230 }
231 
232 /// Setter of the "soname_regex_str property of the current instance
233 /// of @ref suppression_base.
234 ///
235 /// The "soname_regex_str" is a regular expression string that
236 /// designates the soname of the shared library that contains the ABI
237 /// artifacts this suppression should apply to.
238 ///
239 /// @param regexp the new regular expression string.
240 void
242 {priv_->soname_regex_str_ = regexp;}
243 
244 /// Getter of the "soname_regex_str property of the current instance
245 /// of @ref suppression_base.
246 ///
247 /// The "soname_regex_str" is a regular expression string that
248 /// designates the soname of the shared library that contains the ABI
249 /// artifacts this suppression should apply to.
250 ///
251 /// @return the regular expression string.
252 const string&
254 {return priv_->soname_regex_str_;}
255 
256 /// Setter of the "soname_not_regex_str property of the current
257 /// instance of @ref suppression_base.
258 ///
259 /// The current suppression specification should apply to ABI
260 /// artifacts of a shared library which SONAME does *NOT* match the
261 /// regular expression string designated by the "soname_not_regex"
262 /// property.
263 ///
264 /// @param regexp the new regular expression string.
265 void
267 {priv_->soname_not_regex_str_ = regexp;}
268 
269 /// Getter of the "soname_not_regex_str property of the current
270 /// instance of @ref suppression_base.
271 ///
272 /// The current suppression specification should apply to ABI
273 /// artifacts of a shared library which SONAME does *NOT* match the
274 /// regular expression string designated by the "soname_not_regex"
275 /// property.
276 ///
277 /// @return the regular expression string.
278 const string&
280 {return priv_->soname_not_regex_str_;}
281 
282 /// Test if the current suppression has a property related to SONAMEs.
283 ///
284 /// @return true iff the current suppression has either a soname_regex
285 /// or a soname_not_regex property.
286 bool
288 {
289  return (!(get_soname_regex_str().empty()
290  && get_soname_not_regex_str().empty()));
291 }
292 
293 /// Constructor of the @ref negated_suppression_base.
295 {
296 }
297 
298 /// Destructor of the @ref negated_suppression_base.
300 {
301 }
302 
303 /// Test if a suppression specification is a negated suppression.
304 ///
305 /// @param s the suppression to consider.
306 ///
307 /// @return true iff @p s is an instance of @ref
308 /// negated_suppression_base.
309 bool
311 {
312  bool result = true;
313  try
314  {
315  if (const negated_suppression_base* s_prime =
316  &dynamic_cast<const negated_suppression_base&>(s))
317  return !!s_prime;
318  }
319  catch (...)
320  {
321  result = false;
322  }
323  return result;
324 }
325 
326 /// Test if a suppression specification is a negated suppression.
327 ///
328 /// @param s the suppression to consider.
329 ///
330 /// @return true a pointer to the @ref negated_suppression_base which
331 /// @p s, or nil if it's not a negated suppression.
332 /// negated_suppression_base.
335 {
336  const negated_suppression_base* result = nullptr;
337  result = dynamic_cast<const negated_suppression_base*>(s);
338  return result;
339 }
340 
341 /// Test if a suppression specification is a negated suppression.
342 ///
343 /// @param s the suppression to consider.
344 ///
345 /// @return true a pointer to the @ref negated_suppression_base which
346 /// @p s, or nil if it's not a negated suppression.
347 /// negated_suppression_base.
350 {
352  result = dynamic_pointer_cast<negated_suppression_base>(s);
353  return result;
354 }
355 
356 /// Check if the SONAMEs of the two binaries being compared match the
357 /// content of the properties "soname_regexp" and "soname_not_regexp"
358 /// of the current suppression specification.
359 ///
360 /// @param suppr the suppression specification
361 ///
362 /// @param ctxt the context of the comparison.
363 ///
364 /// @return false if the regular expression contained in the property
365 /// soname_regexp or in the property "soname_not_regexp" does *NOT*
366 /// match at least one of the SONAMEs of the two binaries being
367 /// compared. Return true otherwise.
368 static bool
369 sonames_of_binaries_match(const suppression_base& suppr,
370  const diff_context& ctxt)
371 {
372  // Check if the sonames of the binaries match
373  string first_soname = ctxt.get_corpus_diff()->first_corpus()->get_soname(),
374  second_soname = ctxt.get_corpus_diff()->second_corpus()->get_soname();
375 
376  if (!suppr.has_soname_related_property())
377  return false;
378 
379  if (!suppr.priv_->matches_soname(first_soname)
380  && !suppr.priv_->matches_soname(second_soname))
381  return false;
382 
383  return true;
384 }
385 
386 /// Check if the names of the two binaries being compared match the
387 /// content of the properties "file_name_regexp" and
388 /// "file_name_not_regexp".
389 ///
390 /// @param suppr the current suppression specification.
391 ///
392 /// @param ctxt the context of the comparison.
393 ///
394 /// @return false if the regular expression contained in the property
395 /// file_name_regexp or in the property "file_name_not_regexp" does
396 /// *NOT* match at least one of the names of the two binaries being
397 /// compared. Return true otherwise.
398 static bool
399 names_of_binaries_match(const suppression_base& suppr,
400  const diff_context &ctxt)
401 {
402  // Check if the file names of the binaries match
403  string first_binary_path = ctxt.get_corpus_diff()->first_corpus()->get_path(),
404  second_binary_path = ctxt.get_corpus_diff()->second_corpus()->get_path();
405 
406  if (!suppr.has_file_name_related_property())
407  return false;
408 
409  if (!suppr.priv_->matches_binary_name(first_binary_path)
410  && !suppr.priv_->matches_binary_name(second_binary_path))
411  return false;
412 
413  return true;
414 }
415 
416 suppression_base::~suppression_base()
417 {}
418 
420 read_type_suppression(const ini::config::section& section);
421 
423 read_function_suppression(const ini::config::section& section);
424 
426 read_variable_suppression(const ini::config::section& section);
427 
429 read_file_suppression(const ini::config::section& section);
430 
431 /// Read a vector of suppression specifications from the sections of
432 /// an ini::config.
433 ///
434 /// Note that this function needs to be updated each time a new kind
435 /// of suppression specification is added.
436 ///
437 /// @param config the config to read from.
438 ///
439 /// @param suppressions out parameter. The vector of suppressions to
440 /// append the newly read suppressions to.
441 static void
442 read_suppressions(const ini::config& config,
443  suppressions_type& suppressions)
444 {
446  for (ini::config::sections_type::const_iterator i =
447  config.get_sections().begin();
448  i != config.get_sections().end();
449  ++i)
450  if ((s = read_type_suppression(**i))
451  || (s = read_function_suppression(**i))
452  || (s = read_variable_suppression(**i))
453  || (s = read_file_suppression(**i)))
454  suppressions.push_back(s);
455 
456 }
457 
458 /// Read suppressions specifications from an input stream.
459 ///
460 /// @param input the input stream to read from.
461 ///
462 /// @param suppressions the vector of suppressions to append the newly
463 /// read suppressions to.
464 void
465 read_suppressions(std::istream& input,
466  suppressions_type& suppressions)
467 {
468  if (ini::config_sptr config = ini::read_config(input))
469  read_suppressions(*config, suppressions);
470 }
471 
472 /// Read suppressions specifications from an input file on disk.
473 ///
474 /// @param input the path to the input file to read from.
475 ///
476 /// @param suppressions the vector of suppressions to append the newly
477 /// read suppressions to.
478 void
479 read_suppressions(const string& file_path,
480  suppressions_type& suppressions)
481 {
482  if (ini::config_sptr config = ini::read_config(file_path))
483  read_suppressions(*config, suppressions);
484 }
485 // </suppression_base stuff>
486 
487 // <type_suppression stuff>
488 
489 /// Constructor for @ref type_suppression.
490 ///
491 /// @param label the label of the suppression. This is just a free
492 /// form comment explaining what the suppression is about.
493 ///
494 /// @param type_name_regexp the regular expression describing the
495 /// types about which diff reports should be suppressed. If it's an
496 /// empty string, the parameter is ignored.
497 ///
498 /// @param type_name the name of the type about which diff reports
499 /// should be suppressed. If it's an empty string, the parameter is
500 /// ignored.
501 ///
502 /// Note that parameter @p type_name_regexp and @p type_name_regexp
503 /// should not necessarily be populated. It usually is either one or
504 /// the other that the user wants.
505 type_suppression::type_suppression(const string& label,
506  const string& type_name_regexp,
507  const string& type_name)
508  : suppression_base(label),
509  priv_(new priv(type_name_regexp,
510  type_name,
511  /*consider_type_kind=*/false,
512  /*type_kind=*/CLASS_TYPE_KIND,
513  /*consider_reach_kind=*/false,
514  /*reach_kind=*/DIRECT_REACH_KIND))
515 {}
516 
517 type_suppression::~type_suppression()
518 {}
519 
520 /// Setter for the "type_name_regex" property of the type suppression
521 /// specification.
522 ///
523 /// This sets a regular expression that specifies the family of types
524 /// about which diff reports should be suppressed.
525 ///
526 /// @param name_regex_str the new regular expression to set.
527 void
528 type_suppression::set_type_name_regex_str(const string& name_regex_str)
529 {priv_->type_name_regex_str_ = name_regex_str;}
530 
531 /// Getter for the "type_name_regex" property of the type suppression
532 /// specification.
533 ///
534 /// This returns a regular expression string that specifies the family
535 /// of types about which diff reports should be suppressed.
536 ///
537 /// @return the regular expression string.
538 const string&
540 {return priv_->type_name_regex_str_;}
541 
542 /// Setter for the "type_name_not_regex_str" property of the type
543 /// suppression specification.
544 ///
545 /// This returns a regular expression string that specifies the family
546 /// of types that should be kept after suppression.
547 ///
548 /// @param r the new regexp string.
549 void
551 {priv_->set_type_name_not_regex_str(r);}
552 
553 /// Getter for the "type_name_not_regex_str" property of the type
554 /// suppression specification.
555 ///
556 /// This returns a regular expression string that specifies the family
557 /// of types that should be kept after suppression.
558 ///
559 /// @return the new regexp string.
560 const string&
562 {return priv_->get_type_name_not_regex_str();}
563 
564 /// Setter for the name of the type about which diff reports should be
565 /// suppressed.
566 ///
567 /// @param name the new type name.
568 void
570 {priv_->type_name_ = name;}
571 
572 /// Getter for the name of the type about which diff reports should be
573 /// suppressed.
574 ///
575 /// @param return the type name.
576 const string&
578 {return priv_->type_name_;}
579 
580 /// Getter of the property that says whether to consider the kind of
581 /// type this suppression is about.
582 ///
583 /// @return the boolean value of the property.
584 bool
586 {return priv_->consider_type_kind_;}
587 
588 /// Setter of the property that says whether to consider the kind of
589 /// type this suppression is about.
590 ///
591 /// @param f the new boolean value of the property.
592 void
594 {priv_->consider_type_kind_ = f;}
595 
596 /// Setter of the kind of type this suppression is about.
597 ///
598 /// Note that this will be considered during evaluation of the
599 /// suppression only if type_suppression::get_consider_type_kind()
600 /// returns true.
601 ///
602 /// @param k the new kind of type this suppression is about.
603 void
605 {priv_->type_kind_ = k;}
606 
607 /// Getter of the kind of type this suppression is about.
608 ///
609 /// Note that this will be considered during evaluation of the
610 /// suppression only if type_suppression::get_consider_type_kind()
611 /// returns true.
612 ///
613 /// @return the kind of type this suppression is about.
616 {return priv_->type_kind_;}
617 
618 /// Test if the current type suppression specification
619 /// suggests to consider how the matching diff node is reached.
620 ///
621 /// @return true if the current type suppression specification
622 /// suggests to consider how the matching diff node is reached.
623 bool
625 {return priv_->consider_reach_kind_;}
626 
627 /// Set a flag saying if the current type suppression specification
628 /// suggests to consider how the matching diff node is reached.
629 ///
630 /// @param f the new value of the flag. It's true iff the current
631 /// type suppression specification suggests to consider how the
632 /// matching diff node is reached.
633 void
635 {priv_->consider_reach_kind_ = f;}
636 
637 /// Getter of the way the diff node matching the current suppression
638 /// specification is to be reached.
639 ///
640 /// @return the way the diff node matching the current suppression
641 /// specification is to be reached.
644 {return priv_->reach_kind_;}
645 
646 /// Setter of the way the diff node matching the current suppression
647 /// specification is to be reached.
648 ///
649 /// @param p the way the diff node matching the current suppression
650 /// specification is to be reached.
651 void
653 {priv_->reach_kind_ = k;}
654 
655 /// Getter of the "has_size_change" property.
656 ///
657 /// @return the value of the "has_size_change" property.
658 bool
660 {return priv_->has_size_change_;}
661 
662 /// Setter of the "has_size_change" property.
663 ///
664 /// @param flag the new value of the "has_size_change" property.
665 void
667 {priv_->has_size_change_ = flag;}
668 
669 /// Getter of the "potential_data_member_names" property.
670 ///
671 /// @return the set of potential data member names of this
672 /// suppression.
673 const unordered_set<string>&
675 {return priv_->potential_data_members_;}
676 
677 /// Setter of the "potential_data_member_names" property.
678 ///
679 /// @param s the new set of potential data member names of this
680 /// suppression.
681 void
683 (const string_set_type& s) const
684 {priv_->potential_data_members_ = s;}
685 
686 /// Getter of the "potential_data_member_names_regex" string.
687 ///
688 /// @return the "potential_data_member_names_regex" string.
689 const string&
691 {return priv_->potential_data_members_regex_str_;}
692 
693 /// Setter of the "potential_data_member_names_regex" string.
694 ///
695 /// @param d the new "potential_data_member_names_regex" string.
696 void
698 (const string& d) const
699 {priv_->potential_data_members_regex_str_ = d;}
700 
701 /// Setter for the vector of data member insertion ranges that
702 /// specifies where a data member is inserted as far as this
703 /// suppression specification is concerned.
704 ///
705 /// @param r the new insertion range vector.
706 void
708 {priv_->insertion_ranges_ = r;}
709 
710 /// Getter for the vector of data member insertion range that
711 /// specifiers where a data member is inserted as far as this
712 /// suppression specification is concerned.
713 ///
714 /// @return the vector of insertion ranges.
717 {return priv_->insertion_ranges_;}
718 
719 /// Getter for the vector of data member insertion range that
720 /// specifiers where a data member is inserted as far as this
721 /// suppression specification is concerned.
722 ///
723 /// @return the vector of insertion ranges.
726 {return priv_->insertion_ranges_;}
727 
728 /// Getter for the array of source location paths of types that should
729 /// *NOT* be suppressed.
730 ///
731 /// @return the set of source locations of types that should *NOT* be
732 /// supressed.
733 const unordered_set<string>&
735 {return priv_->source_locations_to_keep_;}
736 
737 /// Getter for the array of source location paths of types that should
738 /// *NOT* be suppressed.
739 ///
740 /// @return the array of source locations of types that should *NOT*
741 /// be supressed.
742 unordered_set<string>&
744 {return priv_->source_locations_to_keep_;}
745 
746 /// Setter for the array of source location paths of types that should
747 /// *NOT* be suppressed.
748 ///
749 /// @param l the new array.
750 void
752 (const unordered_set<string>& l)
753 {priv_->source_locations_to_keep_ = l;}
754 
755 /// Getter of the regular expression string that designates the source
756 /// location paths of types that should not be suppressed.
757 ///
758 /// @return the regular expression string.
759 const string&
761 {return priv_->source_location_to_keep_regex_str_;}
762 
763 /// Setter of the regular expression string that designates the source
764 /// location paths of types that should not be suppressed.
765 ///
766 /// @param r the new regular expression.
767 void
769 {priv_->source_location_to_keep_regex_str_ = r;}
770 
771 /// Getter of the vector of the changed enumerators that are supposed
772 /// to be suppressed. Note that this will be "valid" only if the type
773 /// suppression has the 'type_kind = enum' property.
774 ///
775 /// @return the vector of the changed enumerators that are supposed to
776 /// be suppressed.
777 const vector<string>&
779 {return priv_->changed_enumerator_names_;}
780 
781 /// Setter of the vector of changed enumerators that are supposed to
782 /// be suppressed. Note that this will be "valid" only if the type
783 /// suppression has the 'type_kind = enum' property.
784 ///
785 /// @param n the vector of the changed enumerators that are supposed
786 /// to be suppressed.
787 void
789 {priv_->changed_enumerator_names_ = n;}
790 
791 /// Getter of the vector of the regular expression strings for changed
792 /// enumerators that are supposed to be suppressed. Note that this
793 /// will be "valid" only if the type suppression has the
794 /// 'type_kind = enum' property.
795 ///
796 /// @return the vector of the regular expression strings that are
797 /// supposed to match enumertor names to be suppressed.
798 const vector<regex::regex_t_sptr>&
800 {return priv_->changed_enumerators_regexp_;}
801 
802 /// Setter of the vector of the regular expression strings for changed
803 /// enumerators that are supposed to be suppressed. Note that this
804 /// will be "valid" only if the type suppression has the
805 /// 'type_kind = enum' property.
806 ///
807 /// @param n the vector of the regular expression strings that are
808 /// supposed to match enumertor names to be suppressed.
809 void
810 type_suppression::set_changed_enumerators_regexp(const vector<regex::regex_t_sptr>& n)
811 {priv_->changed_enumerators_regexp_ = n;}
812 
813 /// Getter of the "has_string_fam_conversion" property.
814 ///
815 /// @return the value of the "has_string_fam_conversion" property.
816 bool
818 {return priv_->has_strict_fam_conv_;}
819 
820 /// Setter of the "has_string_fam_conversion" property.
821 ///
822 /// @param f the new value of the "has_string_fam_conversion"
823 /// property.
824 void
826 {priv_->has_strict_fam_conv_ = f;}
827 
828 /// Evaluate this suppression specification on a given diff node and
829 /// say if the diff node should be suppressed or not.
830 ///
831 /// @param diff the diff node to evaluate this suppression
832 /// specification against.
833 ///
834 /// @return true if @p diff should be suppressed.
835 bool
837 {
838  const type_diff_base* d = is_type_diff(diff);
839  if (!d)
840  {
841  // So the diff we are looking at is not a type diff. However,
842  // there are cases where a type suppression can suppress changes
843  // on functions.
844 
845  // Typically, if a virtual member function's virtual index (its
846  // index in the vtable of a class) changes and if the current
847  // type suppression is meant to suppress change reports about
848  // the enclosing class of the virtual member function, then this
849  // type suppression should suppress reports about that function
850  // change.
851  const function_decl_diff* d = is_function_decl_diff(diff);
852  if (d)
853  {
854  // Let's see if 'd' carries a virtual member function
855  // change.
856  if (comparison::filtering::has_virtual_mem_fn_change(d))
857  {
859  class_decl_sptr fc =
860  is_class_type(is_method_type(f->get_type())->get_class_type());
861  ABG_ASSERT(fc);
862  if (suppresses_type(fc, diff->context()))
863  return true;
864  }
865  }
866  return false;
867  }
868 
869  // If the suppression should consider the way the diff node has been
870  // reached, then do it now.
872  {
874  {
875  if (const pointer_diff* ptr_diff = is_pointer_diff(diff))
876  {
877  d = is_type_diff(ptr_diff->underlying_type_diff().get());
878  if (!d)
879  // This might be of, e.g, distinct_diff type.
880  return false;
882  }
883  else
884  return false;
885  }
886  else if (get_reach_kind() == REFERENCE_REACH_KIND)
887  {
888  if (const reference_diff* ref_diff = is_reference_diff(diff))
889  {
890  d = is_type_diff(ref_diff->underlying_type_diff().get());
891  if (!d)
892  // This might be of, e.g, distinct_diff type.
893  return false;
895  }
896  else
897  return false;
898  }
900  {
901  if (const pointer_diff* ptr_diff = is_pointer_diff(diff))
902  {
903  d = is_type_diff(ptr_diff->underlying_type_diff().get());
904  ABG_ASSERT(d);
906  }
907  else if (const reference_diff* ref_diff = is_reference_diff(diff))
908  {
909  d = is_type_diff(ref_diff->underlying_type_diff().get());
910  ABG_ASSERT(d);
912  }
913  else
914  return false;
915  }
916  }
917 
918  type_base_sptr ft, st;
919  ft = is_type(d->first_subject());
920  st = is_type(d->second_subject());
921  ABG_ASSERT(ft && st);
922 
923  if (!suppresses_type(ft, d->context())
924  && !suppresses_type(st, d->context()))
925  {
926  // A private type suppression specification considers that a
927  // type can be private and yet some typedefs of that type can be
928  // public -- depending on, e.g, if the typedef is defined in a
929  // public header or not. So if we are in the context of a
930  // private type suppression let's *NOT* peel typedefs away.
931  if (!is_opaque_type_suppr_spec(*this))
932  {
933  ft = peel_typedef_type(ft);
934  st = peel_typedef_type(st);
935  }
936 
937  if (!suppresses_type(ft, d->context())
938  && !suppresses_type(st, d->context()))
939  return false;
940 
942  }
943 
944  // Now let's consider class diffs in the context of a suppr spec
945  // that contains properties like "has_data_member_inserted_*".
946 
947  const class_or_union_diff* cou_diff = is_class_or_union_diff(d);
948  if (cou_diff)
949  {
950  class_or_union_sptr f = cou_diff->first_class_or_union();
951  // We are looking at the a class or union diff ...
952  if (!get_potential_data_member_names().empty())
953  {
954  // ... and the suppr spec has a:
955  //
956  // "has_data_member = {foo, bar}" property
957  //
958  for (string var_name : get_potential_data_member_names())
959  if (!f->find_data_member(var_name))
960  return false;
961  }
962 
964  {
965  if (const regex_t_sptr& data_member_name_regex =
966  priv_->get_potential_data_member_names_regex())
967  {
968  bool data_member_matched = false;
969  for (var_decl_sptr dm : f->get_data_members())
970  {
971  if (regex::match(data_member_name_regex, dm->get_name()))
972  {
973  data_member_matched = true;
974  break;
975  }
976  }
977  if (!data_member_matched)
978  return false;
979  }
980  }
981  }
982 
983  // Evaluate has_data_member_inserted_*" clauses.
984  const class_diff* klass_diff = dynamic_cast<const class_diff*>(d);
985  if (klass_diff)
986  {
987  const class_decl_sptr& first_class =
988  klass_diff->first_class_decl();
989  const class_decl_sptr& second_class =
990  klass_diff->second_class_decl();
991 
992  // We are looking at a class diff ...
993  if (!get_data_member_insertion_ranges().empty())
994  {
995  // ... and the suppr spec contains a
996  // "has_data_member_inserted_*" clause ...
997  if ((klass_diff->first_class_decl()->get_size_in_bits()
998  == klass_diff->second_class_decl()->get_size_in_bits())
999  || get_has_size_change())
1000  {
1001  // That "has_data_member_inserted_*" clause doesn't hold
1002  // if the class changed size, unless the user specified
1003  // that suppression applies to types that have size
1004  // change.
1005 
1006  if (klass_diff->inserted_data_members().empty()
1007  && klass_diff->changed_data_members().empty())
1008  // So there is a has_data_member_inserted_* clause,
1009  // but no data member was inserted. That means the
1010  // clause is falsified.
1011  return false;
1012 
1013  // All inserted data members must be in an allowed
1014  // insertion range.
1015  for (const auto& m : klass_diff->inserted_data_members())
1016  {
1017  decl_base_sptr member = m.second;
1018  bool matched = false;
1019 
1020  for (const auto& range : get_data_member_insertion_ranges())
1022  range,
1023  first_class.get()))
1024  matched = true;
1025 
1026  if (!matched)
1027  return false;
1028  }
1029 
1030  // Similarly, each data member that replaced another one
1031  // must be in an allowed insertion range.
1032  for (const auto& m : klass_diff->changed_data_members())
1033  {
1034  var_decl_sptr member = m.second->second_var();
1035  bool matched = false;
1036 
1037  for (const auto& range : get_data_member_insertion_ranges())
1038  if (is_data_member_offset_in_range(member, range,
1039  first_class.get()))
1040  matched = true;
1041 
1042  if (!matched)
1043  return false;
1044  }
1045  }
1046  else
1047  return false;
1048  }
1049 
1050  // Support for the
1051  // "has_strict_flexible_array_data_member_conversion = true"
1052  // clause.
1054  {
1055  // Let's detect if the first class of the diff has a fake
1056  // flexible array data member that got turned into a real
1057  // flexible array data member.
1058  if (!((get_has_size_change() || ((first_class->get_size_in_bits()
1059  == second_class->get_size_in_bits())))
1060  && filtering::has_strict_fam_conversion(klass_diff)))
1061  return false;
1062  }
1063  }
1064 
1065  const enum_diff* enum_dif = dynamic_cast<const enum_diff*>(d);
1066  if (// We are looking at an enum diff node which ...
1067  enum_dif
1068  //... carries no deleted enumerator ... "
1069  && enum_dif->deleted_enumerators().empty()
1070  // ... carries no size change ...
1071  && (enum_dif->first_enum()->get_size_in_bits()
1072  == enum_dif->second_enum()->get_size_in_bits())
1073  // ... and yet carries some changed enumerators!
1074  && !enum_dif->changed_enumerators().empty())
1075  {
1076 
1077  // Make sure that all changed enumerators are either:
1078  // 1. listed in the vector of enumerator names returned
1079  // by the get_changed_enumerator_names() member function
1080  // 2. match a regular expression returned by the
1081  // get_changed_enumerators_regexp() member function
1082  bool matched = true;
1083  for (string_changed_enumerator_map::const_iterator i =
1084  enum_dif->changed_enumerators().begin();
1085  i != enum_dif->changed_enumerators().end();
1086  ++i)
1087  {
1088  matched &= true;
1089  if ((std::find(get_changed_enumerator_names().begin(),
1091  i->first) == get_changed_enumerator_names().end())
1092  &&
1093  (std::find_if(get_changed_enumerators_regexp().begin(),
1095  [&] (const regex_t_sptr& enum_regexp)
1096  {
1097  return regex::match(enum_regexp, i->first);
1098  }) == get_changed_enumerators_regexp().end()))
1099  {
1100  matched &= false;
1101  break;
1102  }
1103  }
1104  if (!matched)
1105  return false;
1106  }
1107 
1108  return true;
1109 }
1110 
1111 /// Test if the current instance of @ref type_suppression suppresses a
1112 /// change reports about a given type.
1113 ///
1114 /// @param type the type to consider.
1115 ///
1116 /// @param ctxt the context of comparison we are involved with.
1117 ///
1118 /// @return true iff the suppression specification suppresses type @p
1119 /// type.
1120 bool
1121 type_suppression::suppresses_type(const type_base_sptr& type,
1122  const diff_context_sptr& ctxt) const
1123 {
1124  if (ctxt)
1125  {
1126  // Check if the names of the binaries match the suppression
1127  if (!names_of_binaries_match(*this, *ctxt))
1129  return false;
1130 
1131  // Check if the sonames of the binaries match the suppression
1132  if (!sonames_of_binaries_match(*this, *ctxt))
1134  return false;
1135  }
1136 
1137  return suppresses_type(type);
1138 }
1139 
1140 /// Test if an instance of @ref type_suppression matches a given type.
1141 ///
1142 /// This function does not take the name of the type into account
1143 /// while testing if the type matches the type_suppression.
1144 ///
1145 /// @param s the suppression to evaluate.
1146 ///
1147 /// @param type the type to consider.
1148 ///
1149 /// @return true iff the suppression specification matches type @p
1150 /// type without taking its name into account.
1151 static bool
1152 suppression_matches_type_no_name(const type_suppression& s,
1153  const type_base_sptr &type)
1154 {
1155  // If the suppression should consider type kind then, well, check
1156  // for that.
1157  if (s.get_consider_type_kind())
1158  {
1160  bool matches = true;
1161  switch (tk)
1162  {
1163  case type_suppression::UNKNOWN_TYPE_KIND:
1164  case type_suppression::CLASS_TYPE_KIND:
1165  if (!is_class_type(type))
1166  matches = false;
1167  break;
1168  case type_suppression::STRUCT_TYPE_KIND:
1169  {
1170  class_decl_sptr klass = is_class_type(type);
1171  if (!klass || !klass->is_struct())
1172  matches = false;
1173  }
1174  break;
1175  case type_suppression::UNION_TYPE_KIND:
1176  if (!is_union_type(type))
1177  matches = false;
1178  break;
1179  case type_suppression::ENUM_TYPE_KIND:
1180  if (!is_enum_type(type))
1181  matches = false;
1182  break;
1183  case type_suppression::ARRAY_TYPE_KIND:
1184  if (!is_array_type(type))
1185  matches = false;
1186  break;
1187  case type_suppression::TYPEDEF_TYPE_KIND:
1188  if (!is_typedef(type))
1189  matches = false;
1190  break;
1191  case type_suppression::BUILTIN_TYPE_KIND:
1192  if (!is_type_decl(type))
1193  matches = false;
1194  break;
1195  }
1196 
1197  if (!matches)
1198  return false;
1199  }
1200 
1201  // Check if there is a source location related match.
1202  if (!suppression_matches_type_location(s, type))
1203  return false;
1204 
1205  return true;
1206 }
1207 
1208 /// Test if a type suppression specification matches a type name.
1209 ///
1210 /// @param s the type suppression to consider.
1211 ///
1212 /// @param type_name the type name to consider.
1213 ///
1214 /// @return true iff the type designated by its name @p type_name is
1215 /// matched by the type suppression specification @p s.
1216 bool
1218  const string& type_name)
1219 {
1220  if (!s.get_type_name().empty()
1221  || s.priv_->get_type_name_regex()
1222  || s.priv_->get_type_name_not_regex())
1223  {
1224  // Check if there is an exact type name match.
1225  if (!s.get_type_name().empty())
1226  {
1227  if (s.get_type_name() != type_name)
1228  return false;
1229  }
1230  else
1231  {
1232  // Now check if there is a regular expression match.
1233  //
1234  // If the qualified name of the considered type doesn't match
1235  // the regular expression of the type name, then this
1236  // suppression doesn't apply.
1237  if (const regex_t_sptr& type_name_regex =
1238  s.priv_->get_type_name_regex())
1239  {
1240  if (!regex::match(type_name_regex, type_name))
1241  return false;
1242  }
1243 
1244  if (const regex_t_sptr type_name_not_regex =
1245  s.priv_->get_type_name_not_regex())
1246  {
1247  if (regex::match(type_name_not_regex, type_name))
1248  return false;
1249  }
1250  }
1251  }
1252 
1253  return true;
1254 }
1255 
1256 /// Test if a type suppression matches a type in a particular scope.
1257 ///
1258 /// @param s the type suppression to consider.
1259 ///
1260 /// @param type_scope the scope of the type to consider.
1261 ///
1262 /// @param type the type to consider.
1263 ///
1264 /// @return true iff the supression @p s matches type @p type in scope
1265 /// @p type_scope.
1266 bool
1268  const scope_decl* type_scope,
1269  const type_base_sptr& type)
1270 {
1271  string type_name = build_qualified_name(type_scope, type);
1272  return suppression_matches_type_name(s, type_name);
1273 }
1274 
1275 /// Test if a type suppression matches a source location.
1276 ///
1277 /// @param s the type suppression to consider.
1278 ///
1279 /// @param loc the location to consider.
1280 ///
1281 /// @return true iff the suppression @p s matches location @p loc.
1282 bool
1284  const location& loc)
1285 {
1286  if (loc)
1287  {
1288  // Check if there is a source location related match.
1289  string loc_path, loc_path_base;
1290  unsigned loc_line = 0, loc_column = 0;
1291  loc.expand(loc_path, loc_line, loc_column);
1292 
1293  if (regex_t_sptr regexp = s.priv_->get_source_location_to_keep_regex())
1294  if (regex::match(regexp, loc_path))
1295  return false;
1296 
1297  tools_utils::base_name(loc_path, loc_path_base);
1298  if (s.get_source_locations_to_keep().find(loc_path_base)
1299  != s.get_source_locations_to_keep().end())
1300  return false;
1301  if (s.get_source_locations_to_keep().find(loc_path)
1302  != s.get_source_locations_to_keep().end())
1303  return false;
1304  }
1305  else
1306  {
1307  if (!s.get_source_locations_to_keep().empty()
1308  || s.priv_->get_source_location_to_keep_regex())
1309  // The user provided a "source_location_not_regexp" or
1310  // a "source_location_not_in" property that was not
1311  // triggered. This means the current type suppression
1312  // doesn't suppress the type given.
1313  return false;
1314  }
1315 
1316  return true;
1317 }
1318 
1319 /// Test if a type suppression matches a type.
1320 ///
1321 /// @param s the type suppression to consider.
1322 ///
1323 /// @param type the type to consider.
1324 ///
1325 /// @return true iff the suppression @p s matches type @p type.
1326 bool
1328  const type_base_sptr& type)
1329 {
1330  location loc = get_location(type);
1331  if (loc)
1332  return suppression_matches_type_location(s, loc);
1333  else
1334  {
1335  // The type had no source location.
1336  //
1337  // In the case where this type suppression was automatically
1338  // generated to suppress types not defined in public
1339  // headers, then this might mean that the type is not
1340  // defined in the public headers. Otherwise, why does it
1341  // not have a source location?
1342  if (s.get_is_artificial())
1343  {
1344  if (class_decl_sptr cl = is_class_type(type))
1345  {
1346  if (cl->get_is_declaration_only())
1347  // We tried hard above to get the definition of
1348  // the declaration. If we reach this place, it
1349  // means the class has no definition at this point.
1350  ABG_ASSERT(!cl->get_definition_of_declaration());
1352  // So this looks like what really amounts to an
1353  // opaque type. So it's not defined in the public
1354  // headers. So we want to filter it out.
1355  return true;
1356  }
1357  }
1358  if (!s.get_source_locations_to_keep().empty()
1359  || s.priv_->get_source_location_to_keep_regex())
1360  // The user provided a "source_location_not_regexp" or
1361  // a "source_location_not_in" property that was not
1362  // triggered. This means the current type suppression
1363  // doesn't suppress the type given.
1364  return false;
1365  }
1366 
1367  return true;
1368 }
1369 
1370 /// Test if a type suppression matches a type name and location.
1371 ///
1372 /// @param s the type suppression to consider.
1373 ///
1374 /// @param type_name the name of the type to consider.
1375 ///
1376 /// @param type_location the location of the type to consider.
1377 ///
1378 /// @return true iff suppression @p s matches a type named @p
1379 /// type_name with a location @p type_location.
1380 bool
1382  const string& type_name,
1383  const location& type_location)
1384 {
1385  if (!suppression_matches_type_name(s, type_name))
1386  return false;
1387  if (!suppression_matches_type_location(s, type_location))
1388  return false;
1389  return true;
1390 }
1391 
1392 /// Test if the current instance of @ref type_suppression matches a
1393 /// given type.
1394 ///
1395 /// @param type the type to consider.
1396 ///
1397 /// @return true iff the suppression specification suppresses type @p
1398 /// type.
1399 bool
1400 type_suppression::suppresses_type(const type_base_sptr& type) const
1401 {
1402  if (!suppression_matches_type_no_name(*this, type))
1403  return false;
1404 
1405  if (!suppression_matches_type_name(*this, get_name(type)))
1406  return false;
1407 
1408  return true;
1409 }
1410 
1411 /// Test if the current instance of @ref type_suppression matches a
1412 /// given type in a given scope.
1413 ///
1414 /// @param type the type to consider.
1415 ///
1416 /// @param type_scope the scope of type @p type.
1417 ///
1418 /// @return true iff the suppression specification suppresses type @p
1419 /// type from scope @p type_scope.
1420 bool
1421 type_suppression::suppresses_type(const type_base_sptr& type,
1422  const scope_decl* type_scope) const
1423 {
1424  if (!suppression_matches_type_no_name(*this, type))
1425  return false;
1426 
1427  if (!suppression_matches_type_name(*this, type_scope, type))
1428  return false;
1429 
1430  return true;
1431 }
1432 
1433 /// The private data of type_suppression::insertion_range
1434 struct type_suppression::insertion_range::priv
1435 {
1436  boundary_sptr begin_;
1437  boundary_sptr end_;
1438 
1439  priv()
1440  {}
1441 
1443  : begin_(begin), end_(end)
1444  {}
1445 }; // end struct type_suppression::insertion_range::priv
1446 
1447 /// Default Constructor of @ref type_suppression::insertion_range.
1449  : priv_(new priv)
1450 {}
1451 
1452 /// Constructor of @ref type_suppression::insertion_range.
1453 ///
1454 /// @param begin the start of the range. A range boundary that is an
1455 /// instance of @ref interger_boundary with a negative value means the
1456 /// maximum possible value.
1457 ///
1458 /// @param end the end of the range. A range boundary that is an
1459 /// instance of @ref interger_boundary with a negative value means the
1460 /// maximum possible value.
1462  boundary_sptr end)
1463  : priv_(new priv(begin, end))
1464 {}
1465 
1466 /// Getter for the beginning of the range.
1467 ///
1468 /// @return the beginning of the range. A range boundary that is an
1469 /// instance of @ref interger_boundary with a negative value means the
1470 /// maximum possible value.
1473 {return priv_->begin_;}
1474 
1475 /// Getter for the end of the range.
1476 ///
1477 /// @return the end of the range. A range boundary that is an
1478 /// instance of @ref interger_boundary with a negative value means the
1479 /// maximum possible value.
1482 {return priv_->end_;}
1483 
1484 /// Create an integer boundary.
1485 ///
1486 /// The return value of this function is to be used as a boundary for
1487 /// an instance of @ref type_suppression::insertion_range. That
1488 /// boundary evaluates to an integer value.
1489 ///
1490 /// @param value the value of the integer boundary.
1491 ///
1492 /// @return the resulting integer boundary.
1495 {return integer_boundary_sptr(new integer_boundary(value));}
1496 
1497 /// Create a function call expression boundary.
1498 ///
1499 /// The return value of this function is to be used as a boundary for
1500 /// an instance of @ref type_suppression::insertion_range. The value
1501 /// of that boundary is actually a function call expression that
1502 /// itself evalutates to an integer value, in the context of a @ref
1503 /// class_decl.
1504 ///
1505 /// @param expr the function call expression to create the boundary from.
1506 ///
1507 /// @return the resulting function call expression boundary.
1511 
1512 /// Create a function call expression boundary.
1513 ///
1514 /// The return value of this function is to be used as a boundary for
1515 /// an instance of @ref type_suppression::insertion_range. The value
1516 /// of that boundary is actually a function call expression that
1517 /// itself evalutates to an integer value, in the context of a @ref
1518 /// class_decl.
1519 ///
1520 /// @param s a string representing the expression the function call
1521 /// expression to create the boundary from.
1522 ///
1523 /// @return the resulting function call expression boundary.
1526 {
1527  fn_call_expr_boundary_sptr result, nil;
1529  if (ini::read_function_call_expr(s, expr) && expr)
1530  result.reset(new fn_call_expr_boundary(expr));
1531  return result;
1532 }
1533 
1534 /// Create a named boundary.
1535 ///
1536 /// The return value is to be used as a boundary for an instance of
1537 /// @ref type_suppression::insertion_range. The value of that
1538 /// boundary is a named constant that is to be evaluated to an integer
1539 /// value, in the context of a @ref class_decl. That evaluate is
1540 /// performed by the function
1541 /// type_suppression::insertion_range::eval_boundary().
1542 ///
1543 /// @param name the name of the boundary.
1544 ///
1545 /// @return the newly created named boundary.
1548 {
1549  named_boundary_sptr result(new named_boundary(name));
1550  return result;
1551 }
1552 
1553 /// Evaluate an insertion range boundary to get a resulting integer
1554 /// value.
1555 ///
1556 /// @param boundary the boundary to evaluate.
1557 ///
1558 /// @param context the context of evualuation. It's a @ref class_decl
1559 /// to take into account during the evaluation, if there is a need for
1560 /// it.
1561 ///
1562 /// @return true iff the evaluation was successful and @p value
1563 /// contains the resulting value.
1564 bool
1566  const class_or_union* context,
1567  uint64_t& value)
1568 {
1569  if (integer_boundary_sptr b = is_integer_boundary(boundary))
1570  {
1571  value = b->as_integer();
1572  return true;
1573  }
1575  {
1576  ini::function_call_expr_sptr fn_call = b->as_function_call_expr();
1577  if (fn_call
1578  && (fn_call->get_name() == "offset_of"
1579  || fn_call->get_name() == "offset_after"
1580  || fn_call->get_name() == "offset_of_first_data_member_regexp"
1581  || fn_call->get_name() == "offset_of_last_data_member_regexp")
1582  && fn_call->get_arguments().size() == 1)
1583  {
1584  if (fn_call->get_name() == "offset_of"
1585  || fn_call->get_name() == "offset_after")
1586  {
1587  string member_name = fn_call->get_arguments()[0];
1588  for (class_decl::data_members::const_iterator it =
1589  context->get_data_members().begin();
1590  it != context->get_data_members().end();
1591  ++it)
1592  {
1593  if (!get_data_member_is_laid_out(**it))
1594  continue;
1595  if ((*it)->get_name() == member_name)
1596  {
1597  if (fn_call->get_name() == "offset_of")
1598  value = get_data_member_offset(*it);
1599  else if (fn_call->get_name() == "offset_after")
1600  {
1601  if (!get_next_data_member_offset(context, *it, value))
1602  {
1603  value = get_data_member_offset(*it) +
1604  (*it)->get_type()->get_size_in_bits();
1605  }
1606  }
1607  else
1608  // We should not reach this point.
1609  abort();
1610  return true;
1611  }
1612  }
1613  }
1614  else if (fn_call->get_name() == "offset_of_first_data_member_regexp"
1615  || fn_call->get_name() == "offset_of_last_data_member_regexp")
1616  {
1617  string name_regexp = fn_call->get_arguments()[0];
1618  auto r = regex::compile(name_regexp);
1619  var_decl_sptr dm;
1620 
1621  if (fn_call->get_name() == "offset_of_first_data_member_regexp")
1622  dm = find_first_data_member_matching_regexp(*context, r);
1623  else if (fn_call->get_name() == "offset_of_last_data_member_regexp")
1624  dm = find_last_data_member_matching_regexp(*context, r);
1625 
1626  if (dm)
1627  {
1628  value = get_data_member_offset(dm);
1629  return true;
1630  }
1631  }
1632  }
1633  }
1634  else if (named_boundary_sptr b = is_named_boundary(boundary))
1635  {
1636  if (b->get_name() == OFFSET_OF_FLEXIBLE_ARRAY_DATA_MEMBER_STRING())
1637  {
1638  // Look at the last data member of 'context' and make sure
1639  // its type is an array with non-finite size.
1641  {
1642  value = get_data_member_offset(dm);
1643  return true;
1644  }
1645  }
1646  else if (b->get_name() == END_STRING())
1647  {
1648  // The 'end' of a struct is represented by the value
1649  // std::numeric_limits<uint64_t>::max(), recognized by
1650  // type_suppression::insertion_range::boundary_value_is_end.
1651  value = std::numeric_limits<uint64_t>::max();
1652  return true;
1653  }
1654  }
1655  return false;
1656 }
1657 
1658 /// Test if a given value supposed to be inside an insertion range
1659 /// represents the end of the range.
1660 ///
1661 /// @param value the value to test for.
1662 ///
1663 /// @return true iff @p value represents the end of the insertion
1664 /// range.
1665 bool
1667 {
1668  return value == std::numeric_limits<uint64_t>::max();
1669 }
1670 
1671 /// Tests if a given instance of @ref
1672 /// type_suppression::insertion_range::boundary is actually an integer boundary.
1673 ///
1674 /// @param b the boundary to test.
1675 ///
1676 /// @return a pointer to the instance of
1677 /// type_suppression::insertion_range::integer_boundary if @p b is
1678 /// actually an integer boundary. Otherwise, return a null pointer.
1681 {return dynamic_pointer_cast<type_suppression::insertion_range::integer_boundary>(b);}
1682 
1683 /// Tests if a given instance of @ref
1684 /// type_suppression::insertion_range::boundary is actually a
1685 /// function call expression boundary.
1686 ///
1687 /// @param b the boundary to test.
1688 ///
1689 /// @return a pointer to the instance of
1690 /// type_suppression::insertion_range::fn_call_expr_boundary if @p b
1691 /// is actually an function call expression boundary. Otherwise,
1692 /// return a null pointer.
1695 {return dynamic_pointer_cast<type_suppression::insertion_range::fn_call_expr_boundary>(b);}
1696 
1697 /// Test if a given instance of @ref
1698 /// type_suppression::insertion_range::boundary is actually a named boundary.
1699 ///
1700 /// @param b the boundary to consider.
1701 ///
1702 /// @return the instance of @ref
1703 /// type_suppression::insertion_range::named_boundary if @p b is a
1704 /// named boundary, or nil.
1707 {return dynamic_pointer_cast<type_suppression::insertion_range::named_boundary>(b);}
1708 
1709 /// The private data type of @ref
1710 /// type_suppression::insertion_range::boundary.
1711 struct type_suppression::insertion_range::boundary::priv
1712 {
1713  priv()
1714  {}
1715 }; // end struct type_suppression::insertion_range::boundary::priv
1716 
1717 /// Default constructor of @ref
1718 /// type_suppression::insertion_range::boundary
1720  : priv_(new priv())
1721 {}
1722 
1723 /// Destructor of @ref type_suppression::insertion_range::boundary.
1725 {}
1726 
1727 /// Private data type for @ref
1728 /// type_suppression::insertion_range::integer_boundary.
1729 struct type_suppression::insertion_range::integer_boundary::priv
1730 {
1731  uint64_t value_;
1732 
1733  priv()
1734  : value_()
1735  {}
1736 
1737  priv(uint64_t value)
1738  : value_(value)
1739  {}
1740 }; // end type_suppression::insertion_range::integer_boundary::priv
1741 
1742 /// Converting constructor of
1743 /// type_suppression::insertion_range::integer_boundary.
1744 ///
1745 /// @param value the integer value of the newly created integer boundary.
1746 type_suppression::insertion_range::integer_boundary::integer_boundary(uint64_t value)
1747  : priv_(new priv(value))
1748 {}
1749 
1750 /// Return the integer value of the current instance of @ref
1751 /// type_suppression::insertion_range::integer_boundary.
1752 ///
1753 /// @return the integer value of the current boundary.
1754 uint64_t
1756 {return priv_->value_;}
1757 
1758 /// Converts the current boundary into an integer value.
1759 ///
1760 /// @return the integer value of the current boundary.
1761 type_suppression::insertion_range::integer_boundary::operator uint64_t() const
1762 {return as_integer();}
1763 
1764 /// Destructor of @ref type_suppression::insertion_range::integer_boundary.
1766 {}
1767 
1768 /// Private data type of type @ref
1769 /// type_suppression::insertion_range::fn_call_expr_boundary.
1770 struct type_suppression::insertion_range::fn_call_expr_boundary::priv
1771 {
1773 
1774  priv()
1775  {}
1776 
1778  : expr_(expr)
1779  {}
1780 }; // end struct type_suppression::insertion_range::fn_call_expr_boundary::priv
1781 
1782 /// Converting constructor for @ref
1783 /// type_suppression::insertion_range::fn_call_expr_boundary.
1784 ///
1785 /// @param expr the function call expression to build this boundary
1786 /// from.
1787 type_suppression::insertion_range::fn_call_expr_boundary::
1788 fn_call_expr_boundary(ini::function_call_expr_sptr expr)
1789  : priv_(new priv(expr))
1790 {}
1791 
1792 /// Returns the function call expression value of the current boundary.
1793 ///
1794 /// @return the function call expression value of the current boundary;
1797 {return priv_->expr_;}
1798 
1799 /// Converts the current boundary to its function call expression value.
1800 ///
1801 /// @return the function call expression value of the current boundary.
1802 type_suppression::insertion_range::fn_call_expr_boundary::operator ini::function_call_expr_sptr () const
1803 {return as_function_call_expr();}
1804 
1805 /// Destructor of @ref
1806 /// type_suppression::insertion_range::fn_call_expr_boundary.
1808 {}
1809 
1810 /// The private data type for the @ref
1811 /// type_suppression::insertion_range::named_boundary.
1812 struct type_suppression::insertion_range::named_boundary::priv
1813 {
1814  string name_;
1815 
1816  priv()
1817  {}
1818 
1819  priv(const string& name)
1820  : name_(name)
1821  {}
1822 }; // end struct type_suppression::insertion_range::named_boundary::priv
1823 
1824 /// Constructor for @ref
1825 /// type_suppression::insertion_range::named_boundary
1826 ///
1827 /// @param name the name of the @ref named_boundary type.
1828 type_suppression::insertion_range::named_boundary::named_boundary(const string& name)
1829  : priv_(new priv(name))
1830 {}
1831 
1832 /// Getter for the name of the named boundary.
1833 ///
1834 /// @return the name of the named boundary.
1835 const string&
1837 {return priv_->name_;}
1838 
1839 /// Test if an instance of @ref suppression is an instance of @ref
1840 /// type_suppression.
1841 ///
1842 /// @param suppr the instance of @ref suppression to test for.
1843 ///
1844 /// @return if @p suppr is an instance of @ref type_suppression, then
1845 /// return the sub-object of the @p suppr of type @ref
1846 /// type_suppression, otherwise return a nil pointer.
1849 {return dynamic_pointer_cast<type_suppression>(suppr);}
1850 
1851 // </type_suppression stuff>
1852 
1853 // <negated_type_suppression stuff>
1854 
1855 /// Constructor for @ref negated_type_suppression.
1856 ///
1857 /// @param label the label of the suppression. This is just a free
1858 /// form comment explaining what the suppression is about.
1859 ///
1860 /// @param type_name_regexp the regular expression describing the
1861 /// types about which diff reports should be suppressed. If it's an
1862 /// empty string, the parameter is ignored.
1863 ///
1864 /// @param type_name the name of the type about which diff reports
1865 /// should be suppressed. If it's an empty string, the parameter is
1866 /// ignored.
1867 ///
1868 /// Note that parameter @p type_name_regexp and @p type_name_regexp
1869 /// should not necessarily be populated. It usually is either one or
1870 /// the other that the user wants.
1872  const string& type_name_regexp,
1873  const string& type_name)
1874  : type_suppression(label, type_name_regexp, type_name),
1876 {
1877 }
1878 
1879 /// Evaluate this suppression specification on a given diff node and
1880 /// say if the diff node should be suppressed or not.
1881 ///
1882 /// @param diff the diff node to evaluate this suppression
1883 /// specification against.
1884 ///
1885 /// @return true if @p diff should be suppressed.
1886 bool
1888 {
1889  return !type_suppression::suppresses_diff(diff);
1890 }
1891 
1892 /// Destructor of the @ref negated_type_suppression type.
1894 {
1895 }
1896 
1897 // </negated_type_suppression stuff>
1898 
1899 /// Parse the value of the "type_kind" property in the "suppress_type"
1900 /// section.
1901 ///
1902 /// @param input the input string representing the value of the
1903 /// "type_kind" property.
1904 ///
1905 /// @return the @ref type_kind enumerator parsed.
1907 read_type_kind_string(const string& input)
1908 {
1909  if (input == "class")
1910  return type_suppression::CLASS_TYPE_KIND;
1911  else if (input == "struct")
1912  return type_suppression::STRUCT_TYPE_KIND;
1913  else if (input == "union")
1914  return type_suppression::UNION_TYPE_KIND;
1915  else if (input == "enum")
1916  return type_suppression::ENUM_TYPE_KIND;
1917  else if (input == "array")
1918  return type_suppression::ARRAY_TYPE_KIND;
1919  else if (input == "typedef")
1920  return type_suppression::TYPEDEF_TYPE_KIND;
1921  else if (input == "builtin")
1922  return type_suppression::BUILTIN_TYPE_KIND;
1923  else
1924  return type_suppression::UNKNOWN_TYPE_KIND;
1925 }
1926 
1927 /// Parse the value of the "accessed_through" property in the
1928 /// "suppress_type" section.
1929 ///
1930 /// @param input the input string representing the value of the
1931 /// "accessed_through" property.
1932 ///
1933 /// @return the @ref type_suppression::reach_kind enumerator parsed.
1935 read_suppression_reach_kind(const string& input)
1936 {
1937  if (input == "direct")
1939  else if (input == "pointer")
1941  else if (input == "reference")
1943  else if (input == "reference-or-pointer")
1945  else
1947 }
1948 
1949 /// Read a type suppression from an instance of ini::config::section
1950 /// and build a @ref type_suppression as a result.
1951 ///
1952 /// @param section the section of the ini config to read.
1953 ///
1954 /// @return the resulting @ref type_suppression upon successful
1955 /// parsing, or nil.
1956 static type_suppression_sptr
1957 read_type_suppression(const ini::config::section& section)
1958 {
1959  type_suppression_sptr result;
1960 
1961  if (section.get_name() != "suppress_type"
1962  && section.get_name() != "allow_type")
1963  return result;
1964 
1965  static const char *const sufficient_props[] = {
1966  "file_name_regexp",
1967  "file_name_not_regexp",
1968  "soname_regexp",
1969  "soname_not_regexp",
1970  "name",
1971  "name_regexp",
1972  "name_not_regexp",
1973  "type_kind",
1974  "source_location_not_in",
1975  "source_location_not_regexp",
1976  };
1977  if (!check_sufficient_props(sufficient_props,
1978  sizeof(sufficient_props)/sizeof(char*),
1979  section))
1980  return result;
1981 
1982  ini::simple_property_sptr drop_artifact =
1983  is_simple_property(section.find_property("drop_artifact"));
1984  if (!drop_artifact)
1985  drop_artifact = is_simple_property(section.find_property("drop"));
1986 
1987  string drop_artifact_str = drop_artifact
1988  ? drop_artifact->get_value()->as_string()
1989  : "";
1990 
1991  ini::simple_property_sptr has_size_change =
1992  is_simple_property(section.find_property("has_size_change"));
1993 
1994  string has_size_change_str = has_size_change
1995  ? has_size_change->get_value()->as_string()
1996  : "";
1997 
1999  is_simple_property(section.find_property("label"));
2000  string label_str = label ? label->get_value()->as_string() : "";
2001 
2002  ini::simple_property_sptr file_name_regex_prop =
2003  is_simple_property(section.find_property("file_name_regexp"));
2004  string file_name_regex_str =
2005  file_name_regex_prop ? file_name_regex_prop->get_value()->as_string() : "";
2006 
2007  ini::simple_property_sptr file_name_not_regex_prop =
2008  is_simple_property(section.find_property("file_name_not_regexp"));
2009  string file_name_not_regex_str =
2010  file_name_not_regex_prop
2011  ? file_name_not_regex_prop->get_value()->as_string()
2012  : "";
2013 
2014  ini::simple_property_sptr soname_regex_prop =
2015  is_simple_property(section.find_property("soname_regexp"));
2016  string soname_regex_str =
2017  soname_regex_prop ? soname_regex_prop->get_value()->as_string() : "";
2018 
2019  ini::simple_property_sptr soname_not_regex_prop =
2020  is_simple_property(section.find_property("soname_not_regexp"));
2021  string soname_not_regex_str =
2022  soname_not_regex_prop
2023  ? soname_not_regex_prop->get_value()->as_string()
2024  : "";
2025 
2026  ini::simple_property_sptr name_regex_prop =
2027  is_simple_property(section.find_property("name_regexp"));
2028  string name_regex_str = name_regex_prop
2029  ? name_regex_prop->get_value()->as_string()
2030  : "";
2031 
2032  ini::simple_property_sptr name_not_regex_prop =
2033  is_simple_property(section.find_property("name_not_regexp"));
2034  string name_not_regex_str = name_not_regex_prop
2035  ? name_not_regex_prop->get_value()->as_string()
2036  : "";
2037 
2038  ini::simple_property_sptr name_prop =
2039  is_simple_property(section.find_property("name"));
2040  string name_str = name_prop
2041  ? name_prop->get_value()->as_string()
2042  : "";
2043 
2044  ini::property_sptr srcloc_not_in_prop =
2045  section.find_property("source_location_not_in");
2046  unordered_set<string> srcloc_not_in;
2047  if (srcloc_not_in_prop)
2048  {
2049  if (ini::simple_property_sptr p = is_simple_property(srcloc_not_in_prop))
2050  srcloc_not_in.insert(p->get_value()->as_string());
2051  else
2052  {
2053  ini::list_property_sptr list_property =
2054  is_list_property(srcloc_not_in_prop);
2055  if (list_property)
2056  {
2057  vector<string>::const_iterator i;
2058  for (i = list_property->get_value()->get_content().begin();
2059  i != list_property->get_value()->get_content().end();
2060  ++i)
2061  srcloc_not_in.insert(*i);
2062  }
2063  }
2064  }
2065 
2066  ini::simple_property_sptr srcloc_not_regexp_prop =
2067  is_simple_property(section.find_property("source_location_not_regexp"));
2068  string srcloc_not_regexp_str;
2069  if (srcloc_not_regexp_prop)
2070  srcloc_not_regexp_str = srcloc_not_regexp_prop->get_value()->as_string();
2071 
2072  bool consider_type_kind = false;
2073  type_suppression::type_kind type_kind = type_suppression::UNKNOWN_TYPE_KIND;
2074  if (ini::simple_property_sptr type_kind_prop =
2075  is_simple_property(section.find_property("type_kind")))
2076  {
2077  consider_type_kind = true;
2078  type_kind =
2079  read_type_kind_string(type_kind_prop->get_value()->as_string());
2080  }
2081 
2082  bool consider_reach_kind = false;
2084  if (ini::simple_property_sptr reach_kind_prop =
2085  is_simple_property(section.find_property("accessed_through")))
2086  {
2087  consider_reach_kind = true;
2088  reach_kind =
2089  read_suppression_reach_kind(reach_kind_prop->get_value()->as_string());
2090  }
2091 
2092  // Support has_data_member = {}
2093  string_set_type potential_data_member_names;
2094  if (ini::property_sptr propertee = section.find_property("has_data_member"))
2095  {
2096  // This is either has_data_member = {foo, blah} or
2097  // has_data_member = foo.
2100  if (ini::tuple_property_sptr prop = is_tuple_property(propertee))
2101  // Value is of the form {foo,blah}
2102  tv = prop->get_value();
2103  else if (ini::simple_property_sptr prop = is_simple_property(propertee))
2104  // Value is of the form foo.
2105  sv = prop->get_value();
2106 
2107  // Ensure that the property value has the form {"foo", "blah", ...};
2108  // Meaning it's a tuple of one element which is a list or a string.
2109  if (tv
2110  && tv->get_value_items().size() == 1
2111  && (is_list_property_value(tv->get_value_items().front())
2112  || is_string_property_value(tv->get_value_items().front())))
2113  {
2115  is_list_property_value(tv->get_value_items().front());
2116  if (!val)
2117  {
2118  // We have just one potential data member name,as a
2119  // string_property_value.
2120  string name =
2121  is_string_property_value(tv->get_value_items().front())
2122  ->as_string();
2123  potential_data_member_names.insert(name);
2124  }
2125  else
2126  for (const string& name : val->get_content())
2127  potential_data_member_names.insert(name);
2128  }
2129  else if (sv)
2130  {
2131  string name = sv->as_string();
2132  potential_data_member_names.insert(name);
2133  }
2134  }
2135 
2136  // Support has_data_member_regexp = str
2137  string potential_data_member_names_regexp_str;
2138  if (ini::simple_property_sptr prop =
2139  is_simple_property(section.find_property("has_data_member_regexp")))
2140  potential_data_member_names_regexp_str = prop->get_value()->as_string();
2141 
2142  // Support has_data_member_inserted_at
2143  vector<type_suppression::insertion_range_sptr> insert_ranges;
2144  bool consider_data_member_insertion = false;
2145  if (ini::simple_property_sptr prop =
2146  is_simple_property(section.find_property("has_data_member_inserted_at")))
2147  {
2148  // So this property has the form:
2149  // has_data_member_inserted_at = <one-string-property-value>
2150  string ins_point = prop->get_value()->as_string();
2152  if (ins_point == END_STRING())
2154  else if (ins_point == OFFSET_OF_FLEXIBLE_ARRAY_DATA_MEMBER_STRING())
2156  else if (isdigit(ins_point[0]))
2158  (atoi(ins_point.c_str()));
2161  begin = expr;
2162  else
2163  return result;
2164 
2167  (new type_suppression::insertion_range(begin, end));
2168  insert_ranges.push_back(insert_range);
2169  consider_data_member_insertion = true;
2170  }
2171 
2172  // Support has_data_member_inserted_between
2173  if (ini::tuple_property_sptr prop =
2174  is_tuple_property(section.find_property
2175  ("has_data_member_inserted_between")))
2176  {
2177  // ensures that this has the form:
2178  // has_data_member_inserted_between = {0 , end};
2179  // and not (for instance):
2180  // has_data_member_inserted_between = {{0 , end}, {1, foo}}
2181  //
2182  // This means that the tuple_property_value contains just one
2183  // value, which is a list_property that itself contains 2
2184  // values.
2186  ini::tuple_property_value_sptr v = prop->get_value();
2187  if (v
2188  && v->get_value_items().size() == 1
2189  && is_list_property_value(v->get_value_items()[0])
2190  && is_list_property_value(v->get_value_items()[0])->get_content().size() == 2)
2191  {
2193  is_list_property_value(v->get_value_items()[0]);
2194  ABG_ASSERT(val);
2195  string str = val->get_content()[0];
2196  if (str == "end")
2197  begin =
2199  else if (isdigit(str[0]))
2201  (atoi(str.c_str()));
2204  begin = expr;
2205  else
2206  return result;
2207 
2208  str = val->get_content()[1];
2209  if (str == "end")
2210  end =
2212  else if (isdigit(str[0]))
2214  (atoi(str.c_str()));
2217  end = expr;
2218  else
2219  return result;
2220 
2222  (new type_suppression::insertion_range(begin, end));
2223  insert_ranges.push_back(insert_range);
2224  consider_data_member_insertion = true;
2225  }
2226  else
2227  // the 'has_data_member_inserted_between' property has a wrong
2228  // value type, so let's discard the endire [suppress_type]
2229  // section.
2230  return result;
2231  }
2232 
2233  // Support has_data_members_inserted_between
2234  // The syntax looks like:
2235  //
2236  // has_data_members_inserted_between = {{8, 24}, {32, 64}, {128, end}}
2237  //
2238  // So we expect a tuple property, with potentially several pairs (as
2239  // part of the value); each pair designating a range. Note that
2240  // each pair (range) is a list property value.
2241  if (ini::tuple_property_sptr prop =
2242  is_tuple_property(section.find_property
2243  ("has_data_members_inserted_between")))
2244  {
2245  bool is_well_formed = true;
2246  for (vector<ini::property_value_sptr>::const_iterator i =
2247  prop->get_value()->get_value_items().begin();
2248  is_well_formed && i != prop->get_value()->get_value_items().end();
2249  ++i)
2250  {
2251  ini::tuple_property_value_sptr tuple_value =
2253  if (!tuple_value
2254  || tuple_value->get_value_items().size() != 1
2255  || !is_list_property_value(tuple_value->get_value_items()[0]))
2256  {
2257  is_well_formed = false;
2258  break;
2259  }
2260  ini::list_property_value_sptr list_value =
2261  is_list_property_value(tuple_value->get_value_items()[0]);
2262  if (list_value->get_content().size() != 2)
2263  {
2264  is_well_formed = false;
2265  break;
2266  }
2267 
2269  string str = list_value->get_content()[0];
2270  if (str == "end")
2271  begin =
2273  else if (isdigit(str[0]))
2274  begin =
2276  (atoi(str.c_str()));
2279  begin = expr;
2280  else
2281  return result;
2282 
2283  str = list_value->get_content()[1];
2284  if (str == "end")
2285  end =
2287  else if (isdigit(str[0]))
2289  (atoi(str.c_str()));
2292  end = expr;
2293  else
2294  return result;
2295 
2297  (new type_suppression::insertion_range(begin, end));
2298  insert_ranges.push_back(insert_range);
2299  consider_data_member_insertion = true;
2300  }
2301  if (!is_well_formed)
2302  return result;
2303  }
2304 
2305  /// Support 'changed_enumerators = foo, bar, baz'
2306  ///
2307  /// Note that this constraint is valid only if we have:
2308  /// 'type_kind = enum'.
2309  ///
2310  /// If the current type is an enum and if it carries changed
2311  /// enumerators listed in the changed_enumerators property value
2312  /// then it should be suppressed.
2313 
2314  ini::property_sptr changed_enumerators_prop =
2315  section.find_property("changed_enumerators");
2316 
2317  vector<string> changed_enumerator_names;
2318  if (changed_enumerators_prop)
2319  {
2320  if (ini::list_property_sptr p =
2321  is_list_property(changed_enumerators_prop))
2322  changed_enumerator_names =
2323  p->get_value()->get_content();
2324  else if (ini::simple_property_sptr p =
2325  is_simple_property(changed_enumerators_prop))
2326  changed_enumerator_names.push_back(p->get_value()->as_string());
2327  }
2328 
2329  /// Support 'changed_enumerators_regexp = .*_foo, bar_[0-9]+, baz'
2330  ///
2331  /// If the current type is an enum and if it carries changed
2332  /// enumerators that match regular expressions listed in the
2333  /// changed_enumerators_regexp property value then it should be
2334  /// suppressed.
2335 
2336  ini::property_sptr changed_enumerators_regexp_prop =
2337  section.find_property("changed_enumerators_regexp");
2338 
2339  vector<regex_t_sptr> changed_enumerators_regexp;
2340  if (changed_enumerators_regexp_prop)
2341  {
2342  if (ini::list_property_sptr p =
2343  is_list_property(changed_enumerators_regexp_prop))
2344  {
2345  for (string e : p->get_value()->get_content())
2346  changed_enumerators_regexp.push_back(regex::compile(e));
2347  }
2348  else if (ini::simple_property_sptr p =
2349  is_simple_property(changed_enumerators_regexp_prop))
2350  {
2351  changed_enumerators_regexp.push_back(
2352  regex::compile(p->get_value()->as_string())
2353  );
2354  }
2355  }
2356 
2357  // Support "has_strict_flexible_array_data_member_conversion"
2358  ini::simple_property_sptr has_strict_fam_conv =
2360  (section.find_property("has_strict_flexible_array_data_member_conversion"));
2361  string has_strict_fam_conv_str = has_strict_fam_conv
2362  ? has_strict_fam_conv->get_value()->as_string()
2363  : "";
2364 
2365  if (section.get_name() == "suppress_type")
2366  result.reset(new type_suppression(label_str, name_regex_str, name_str));
2367  else if (section.get_name() == "allow_type")
2368  result.reset(new negated_type_suppression(label_str, name_regex_str,
2369  name_str));
2370 
2371  if (consider_type_kind)
2372  {
2373  result->set_consider_type_kind(true);
2374  result->set_type_kind(type_kind);
2375  }
2376 
2377  if (consider_reach_kind)
2378  {
2379  result->set_consider_reach_kind(true);
2380  result->set_reach_kind(reach_kind);
2381  }
2382 
2383  if (!potential_data_member_names.empty())
2384  result->set_potential_data_member_names(potential_data_member_names);
2385 
2386  if (!potential_data_member_names_regexp_str.empty())
2387  result->set_potential_data_member_names_regex_str
2388  (potential_data_member_names_regexp_str);
2389 
2390  if (consider_data_member_insertion)
2391  result->set_data_member_insertion_ranges(insert_ranges);
2392 
2393  if (!name_not_regex_str.empty())
2394  result->set_type_name_not_regex_str(name_not_regex_str);
2395 
2396  if (!file_name_regex_str.empty())
2397  result->set_file_name_regex_str(file_name_regex_str);
2398 
2399  if (!file_name_not_regex_str.empty())
2400  result->set_file_name_not_regex_str(file_name_not_regex_str);
2401 
2402  if (!soname_regex_str.empty())
2403  result->set_soname_regex_str(soname_regex_str);
2404 
2405  if (!soname_not_regex_str.empty())
2406  result->set_soname_not_regex_str(soname_not_regex_str);
2407 
2408  if (!srcloc_not_in.empty())
2409  result->set_source_locations_to_keep(srcloc_not_in);
2410 
2411  if (!srcloc_not_regexp_str.empty())
2412  result->set_source_location_to_keep_regex_str(srcloc_not_regexp_str);
2413 
2414  if ((drop_artifact_str == "yes" || drop_artifact_str == "true")
2415  && ((!name_regex_str.empty()
2416  || !name_str.empty()
2417  || !srcloc_not_regexp_str.empty()
2418  || !srcloc_not_in.empty())))
2419  result->set_drops_artifact_from_ir(true);
2420 
2421  if (has_size_change_str == "yes" || has_size_change_str == "true")
2422  result->set_has_size_change(true);
2423 
2424  if (result->get_type_kind() == type_suppression::ENUM_TYPE_KIND
2425  && !changed_enumerator_names.empty())
2426  result->set_changed_enumerator_names(changed_enumerator_names);
2427 
2428  if (result->get_type_kind() == type_suppression::ENUM_TYPE_KIND
2429  && !changed_enumerators_regexp.empty())
2430  result->set_changed_enumerators_regexp(changed_enumerators_regexp);
2431 
2432  if (has_strict_fam_conv_str == "yes" || has_strict_fam_conv_str == "true")
2433  result->set_has_strict_fam_conversion(true);
2434 
2435  return result;
2436 }
2437 
2438 // <function_suppression stuff>
2439 
2440 /// Constructor for the @ref the function_suppression::parameter_spec
2441 /// type.
2442 ///
2443 /// @param i the index of the parameter designated by this specification.
2444 ///
2445 /// @param tn the type name of the parameter designated by this specification.
2446 ///
2447 /// @param tn_regex a regular expression that defines a set of type
2448 /// names for the parameter designated by this specification. Note
2449 /// that at evaluation time, this regular expression is taken in
2450 /// account only if the parameter @p tn is empty.
2451 function_suppression::parameter_spec::parameter_spec(size_t i,
2452  const string& tn,
2453  const string& tn_regex)
2454  : priv_(new priv(i, tn, tn_regex))
2455 {}
2456 
2457 /// Getter for the index of the parameter designated by this
2458 /// specification.
2459 ///
2460 /// @return the index of the parameter designated by this
2461 /// specification.
2462 size_t
2464 {return priv_->index_;}
2465 
2466 /// Setter for the index of the parameter designated by this
2467 /// specification.
2468 ///
2469 /// @param i the new index to set.
2470 void
2472 {priv_->index_ = i;}
2473 
2474 /// Getter for the type name of the parameter designated by this specification.
2475 ///
2476 /// @return the type name of the parameter.
2477 const string&
2479 {return priv_->type_name_;}
2480 
2481 /// Setter for the type name of the parameter designated by this
2482 /// specification.
2483 ///
2484 /// @param tn new parameter type name to set.
2485 void
2487 {priv_->type_name_ = tn;}
2488 
2489 /// Getter for the regular expression that defines a set of type names
2490 /// for the parameter designated by this specification.
2491 ///
2492 /// Note that at evaluation time, this regular expression is taken in
2493 /// account only if the name of the parameter as returned by
2494 /// function_suppression::parameter_spec::get_parameter_type_name() is
2495 /// empty.
2496 ///
2497 /// @return the regular expression or the parameter type name.
2498 const string&
2500 {return priv_->type_name_regex_str_;}
2501 
2502 /// Setter for the regular expression that defines a set of type names
2503 /// for the parameter designated by this specification.
2504 ///
2505 /// Note that at evaluation time, this regular expression is taken in
2506 /// account only if the name of the parameter as returned by
2507 /// function_suppression::parameter_spec::get_parameter_type_name() is
2508 /// empty.
2509 ///
2510 /// @param type_name_regex_str the new type name regular expression to
2511 /// set.
2512 void
2514 (const string& type_name_regex_str)
2515 {priv_->type_name_regex_str_ = type_name_regex_str;}
2516 
2517 /// Default constructor for the @ref function_suppression type.
2518 ///
2519 /// It defines no suppression for now. Suppressions have to be
2520 /// specified by using the various accessors of the @ref
2521 /// function_suppression type.
2523  : suppression_base(/*label=*/""), priv_(new priv)
2524 {}
2525 
2526 /// Constructor for the @ref function_suppression type.
2527 ///
2528 /// @param label an informative text string that the evalution code
2529 /// might use to designate this function suppression specification in
2530 /// error messages. This parameter might be empty, in which case it's
2531 /// ignored at evaluation time.
2532 ///
2533 /// @param the name of the function the user wants the current
2534 /// specification to designate. This parameter might be empty, in
2535 /// which case it's ignored at evaluation time.
2536 ///
2537 /// @param nr if @p name is empty this parameter is a regular
2538 /// expression for a family of names of functions the user wants the
2539 /// current specification to designate. If @p name is not empty, this
2540 /// parameter is ignored at specification evaluation time. This
2541 /// parameter might be empty, in which case it's ignored at evaluation
2542 /// time.
2543 ///
2544 /// @param ret_tn the name of the return type of the function the user
2545 /// wants this specification to designate. This parameter might be
2546 /// empty, in which case it's ignored at evaluation time.
2547 ///
2548 /// @param ret_tr if @p ret_tn is empty, then this is a regular
2549 /// expression for a family of return type names for functions the
2550 /// user wants the current specification to designate. If @p ret_tn
2551 /// is not empty, then this parameter is ignored at specification
2552 /// evaluation time. This parameter might be empty, in which case
2553 /// it's ignored at evaluation time.
2554 ///
2555 /// @param ps a vector of parameter specifications to specify
2556 /// properties of the parameters of the functions the user wants this
2557 /// specification to designate. This parameter might be empty, in
2558 /// which case it's ignored at evaluation time.
2559 ///
2560 /// @param sym_n the name of symbol of the function the user wants
2561 /// this specification to designate. This parameter might be empty,
2562 /// in which case it's ignored at evaluation time.
2563 ///
2564 /// @param sym_nr if the parameter @p sym_n is empty, then this
2565 /// parameter is a regular expression for a family of names of symbols
2566 /// of functions the user wants this specification to designate. If
2567 /// the parameter @p sym_n is not empty, then this parameter is
2568 /// ignored at specification evaluation time. This parameter might be
2569 /// empty, in which case it's ignored at evaluation time.
2570 ///
2571 /// @param sym_v the name of the version of the symbol of the function
2572 /// the user wants this specification to designate. This parameter
2573 /// might be empty, in which case it's ignored at evaluation time.
2574 ///
2575 /// @param sym_vr if the parameter @p sym_v is empty, then this
2576 /// parameter is a regular expression for a family of versions of
2577 /// symbols of functions the user wants the current specification to
2578 /// designate. If the parameter @p sym_v is non empty, then this
2579 /// parameter is ignored. This parameter might be empty, in which
2580 /// case it's ignored at evaluation time.
2582  const string& name,
2583  const string& nr,
2584  const string& ret_tn,
2585  const string& ret_tr,
2587  const string& sym_n,
2588  const string& sym_nr,
2589  const string& sym_v,
2590  const string& sym_vr)
2591  : suppression_base(label),
2592  priv_(new priv(name, nr, ret_tn, ret_tr, ps,
2593  sym_n, sym_nr, sym_v, sym_vr))
2594 {}
2595 
2596 function_suppression::~function_suppression()
2597 {}
2598 
2599 /// Parses a string containing the content of the "change-kind"
2600 /// property and returns the an instance of @ref
2601 /// function_suppression::change_kind as a result.
2602 ///
2603 /// @param s the string to parse.
2604 ///
2605 /// @return the resulting @ref function_suppression::change_kind.
2608 {
2609  if (s == "function-subtype-change")
2611  else if (s == "added-function")
2613  else if (s == "deleted-function")
2615  else if (s == "all")
2616  return ALL_CHANGE_KIND;
2617  else
2618  return UNDEFINED_CHANGE_KIND;
2619 }
2620 
2621 /// Getter of the "change-kind" property.
2622 ///
2623 /// @param returnthe "change-kind" property.
2626 {return priv_->change_kind_;}
2627 
2628 /// Setter of the "change-kind" property.
2629 ///
2630 /// @param k the new value of the change_kind property.
2631 void
2633 {priv_->change_kind_ = k;}
2634 
2635 /// Getter for the name of the function the user wants the current
2636 /// specification to designate. This might be empty, in which case
2637 /// it's ignored at evaluation time.
2638 ///
2639 /// @return the name of the function.
2640 const string&
2642 {return priv_->name_;}
2643 
2644 /// Setter for the name of the function the user wants the current
2645 /// specification to designate. This might be empty, in which case
2646 /// it's ignored at evaluation time.
2647 ///
2648 /// @param n the new function name to set.
2649 void
2651 {priv_->name_ = n;}
2652 
2653 /// Getter for a regular expression for a family of names of functions
2654 /// the user wants the current specification to designate.
2655 ///
2656 /// @return the regular expression for the possible names of the
2657 /// function(s).
2658 const string&
2660 {return priv_->name_regex_str_;}
2661 
2662 /// Setter for a regular expression for a family of names of functions
2663 /// the user wants the current specification to designate.
2664 ///
2665 /// @param r the new the regular expression for the possible names of
2666 /// the function(s).
2667 void
2669 {priv_->name_regex_str_ = r;}
2670 
2671 /// Getter for a regular expression of a family of names of functions
2672 /// the user wants the current specification to designate the negation
2673 /// of.
2674 ///
2675 /// @return the regular expression for the possible names of the
2676 /// function(s).
2677 const string&
2679 {return priv_->name_not_regex_str_;}
2680 
2681 /// Setter for a regular expression for a family of names of functions
2682 /// the user wants the current specification to designate the negation
2683 /// of.
2684 ///
2685 /// @param r the new the regular expression for the possible names of
2686 /// the function(s).
2687 void
2689 {priv_->name_not_regex_str_ = r;}
2690 
2691 /// Getter for the name of the return type of the function the user
2692 /// wants this specification to designate. This property might be
2693 /// empty, in which case it's ignored at evaluation time.
2694 ///
2695 /// @return the name of the return type of the function.
2696 const string&
2698 {return priv_->return_type_name_;}
2699 
2700 /// Setter for the name of the return type of the function the user
2701 /// wants this specification to designate. This property might be
2702 /// empty, in which case it's ignored at evaluation time.
2703 ///
2704 /// @param tr the new name of the return type of the function to set.
2705 void
2707 {priv_->return_type_name_ = tr;}
2708 
2709 /// Getter for a regular expression for a family of return type names
2710 /// for functions the user wants the current specification to
2711 /// designate.
2712 ///
2713 /// If the name of the return type of the function as returned by
2714 /// function_suppression::get_return_type_name() is not empty, then
2715 /// this property is ignored at specification evaluation time. This
2716 /// property might be empty, in which case it's ignored at evaluation
2717 /// time.
2718 ///
2719 /// @return the regular expression for the possible names of the
2720 /// return types of the function(s).
2721 const string&
2723 {return priv_->return_type_regex_str_;}
2724 
2725 /// Setter for a regular expression for a family of return type names
2726 /// for functions the user wants the current specification to
2727 /// designate.
2728 ///
2729 /// If the name of the return type of the function as returned by
2730 /// function_suppression::get_return_type_name() is not empty, then
2731 /// this property is ignored at specification evaluation time. This
2732 /// property might be empty, in which case it's ignored at evaluation
2733 /// time.
2734 ///
2735 /// @param r the new regular expression for the possible names of the
2736 /// return types of the function(s) to set.
2737 void
2739 {priv_->return_type_regex_str_ = r;}
2740 
2741 /// Getter for a vector of parameter specifications to specify
2742 /// properties of the parameters of the functions the user wants this
2743 /// specification to designate.
2744 ///
2745 /// This property might be empty, in which case it's ignored at
2746 /// evaluation time.
2747 ///
2748 /// @return the specifications of the parameters of the function(s).
2751 {return priv_->parm_specs_;}
2752 
2753 /// Setter for a vector of parameter specifications to specify
2754 /// properties of the parameters of the functions the user wants this
2755 /// specification to designate.
2756 ///
2757 /// This property might be empty, in which case it's ignored at
2758 /// evaluation time.
2759 ///
2760 /// @param p the new specifications of the parameters of the
2761 /// function(s) to set.
2762 void
2764 {priv_->parm_specs_ = p;}
2765 
2766 /// Append a specification of a parameter of the function specification.
2767 ///
2768 /// @param p the parameter specification to add.
2769 void
2771 {priv_->parm_specs_.push_back(p);}
2772 
2773 /// Getter for the name of symbol of the function the user wants this
2774 /// specification to designate.
2775 ///
2776 /// This property might be empty, in which case it's ignored at
2777 /// evaluation time.
2778 ///
2779 /// @return name of the symbol of the function.
2780 const string&
2782 {return priv_->symbol_name_;}
2783 
2784 /// Setter for the name of symbol of the function the user wants this
2785 /// specification to designate.
2786 ///
2787 /// This property might be empty, in which case it's ignored at
2788 /// evaluation time.
2789 ///
2790 /// @return name of the symbol of the function.
2791 void
2793 {priv_->symbol_name_ = n;}
2794 
2795 /// Getter for a regular expression for a family of names of symbols
2796 /// of functions the user wants this specification to designate.
2797 ///
2798 /// If the symbol name as returned by
2799 /// function_suppression::get_symbol_name() is not empty, then this
2800 /// property is ignored at specification evaluation time.
2801 ///
2802 /// This property might be empty, in which case it's ignored at
2803 /// evaluation time.
2804 ///
2805 /// @return the regular expression for a family of names of symbols of
2806 /// functions to designate.
2807 const string&
2809 {return priv_->symbol_name_regex_str_;}
2810 
2811 /// Setter for a regular expression for a family of names of symbols
2812 /// of functions the user wants this specification to designate.
2813 ///
2814 /// If the symbol name as returned by
2815 /// function_suppression::get_symbol_name() is not empty, then this
2816 /// property is ignored at specification evaluation time.
2817 ///
2818 /// This property might be empty, in which case it's ignored at
2819 /// evaluation time.
2820 ///
2821 /// @param r the new regular expression for a family of names of
2822 /// symbols of functions to set.
2823 void
2825 {priv_->symbol_name_regex_str_ = r;}
2826 
2827 /// Getter for a regular expression for a family of names of symbols
2828 /// of functions the user wants this specification to designate.
2829 ///
2830 /// If a symbol name is matched by this regular expression, then the
2831 /// suppression specification will *NOT* suppress the symbol.
2832 ///
2833 /// If the symbol name as returned by
2834 /// function_suppression::get_symbol_name() is not empty, then this
2835 /// property is ignored at specification evaluation time.
2836 ///
2837 /// This property might be empty, in which case it's ignored at
2838 /// evaluation time.
2839 ///
2840 /// @return the regular expression string for a family of names of
2841 /// symbols that is to be *NOT* suppressed by this suppression specification.
2842 const string&
2844 {return priv_->symbol_name_not_regex_str_;}
2845 
2846 /// Setter for a regular expression for a family of names of symbols
2847 /// of functions the user wants this specification to designate.
2848 ///
2849 /// If a symbol name is matched by this regular expression, then the
2850 /// suppression specification will *NOT* suppress the symbol.
2851 ///
2852 /// If the symbol name as returned by
2853 /// function_suppression::get_symbol_name() is not empty, then this
2854 /// property is ignored at specification evaluation time.
2855 ///
2856 /// This property might be empty, in which case it's ignored at
2857 /// evaluation time.
2858 ///
2859 /// @param the new regular expression string for a family of names of
2860 /// symbols that is to be *NOT* suppressed by this suppression
2861 /// specification.
2862 void
2864 {priv_->symbol_name_not_regex_str_ = r;}
2865 
2866 /// Getter for the name of the version of the symbol of the function
2867 /// the user wants this specification to designate.
2868 ///
2869 /// This property might be empty, in which case it's ignored at
2870 /// evaluation time.
2871 ///
2872 /// @return the symbol version of the function.
2873 const string&
2875 {return priv_->symbol_version_;}
2876 
2877 /// Setter for the name of the version of the symbol of the function
2878 /// the user wants this specification to designate.
2879 ///
2880 /// This property might be empty, in which case it's ignored at
2881 /// evaluation time.
2882 ///
2883 /// @param v the new symbol version of the function.
2884 void
2886 {priv_->symbol_version_ = v;}
2887 
2888 /// Getter for a regular expression for a family of versions of
2889 /// symbols of functions the user wants the current specification to
2890 /// designate.
2891 ///
2892 /// If the symbol version as returned by
2893 /// function_suppression::get_symbol_version() is non empty, then this
2894 /// property is ignored. This property might be empty, in which case
2895 /// it's ignored at evaluation time.
2896 ///
2897 /// @return the regular expression for the versions of symbols of
2898 /// functions to designate.
2899 const string&
2901 {return priv_->symbol_version_regex_str_;}
2902 
2903 /// Setter for a regular expression for a family of versions of
2904 /// symbols of functions the user wants the current specification to
2905 /// designate.
2906 ///
2907 /// If the symbol version as returned by
2908 /// function_suppression::get_symbol_version() is non empty, then this
2909 /// property is ignored. This property might be empty, in which case
2910 /// it's ignored at evaluation time.
2911 ///
2912 /// @param the new regular expression for the versions of symbols of
2913 /// functions to designate.
2914 void
2916 {priv_->symbol_version_regex_str_ = r;}
2917 
2918 /// Getter for the "allow_other_aliases" property of the function
2919 /// suppression specification.
2920 ///
2921 /// @return the value of the "allow_other_aliases" property.
2922 bool
2924 {return priv_->allow_other_aliases_;}
2925 
2926 /// Setter for the "allow_other_aliases" property of the function
2927 /// suppression specification.
2928 ///
2929 /// @param f the new value of the property.
2930 void
2932 {priv_->allow_other_aliases_ = f;}
2933 
2934 /// Evaluate this suppression specification on a given diff node and
2935 /// say if the diff node should be suppressed or not.
2936 ///
2937 /// @param diff the diff node to evaluate this suppression
2938 /// specification against.
2939 ///
2940 /// @return true if @p diff should be suppressed.
2941 bool
2943 {
2944  const function_decl_diff* d = is_function_decl_diff(diff);
2945  if (!d)
2946  return false;
2947 
2950  ABG_ASSERT(ff && sf);
2951 
2952  return (suppresses_function(ff,
2954  diff->context())
2955  || suppresses_function(sf,
2957  diff->context()));
2958 }
2959 
2960 /// Evaluate the current function suppression specification on a given
2961 /// @ref function_decl and say if a report about a change involving this
2962 /// @ref function_decl should be suppressed or not.
2963 ///
2964 /// @param fn the @ref function_decl to evaluate this suppression
2965 /// specification against.
2966 ///
2967 /// @param k the kind of function change @p fn is supposed to have.
2968 ///
2969 /// @param ctxt the context of the current diff.
2970 ///
2971 /// @return true iff a report about a change involving the function @p
2972 /// fn should be suppressed.
2973 bool
2975  change_kind k,
2976  const diff_context_sptr ctxt) const
2977 {
2978  if (!(get_change_kind() & k))
2979  return false;
2980 
2981  // Check if the name and soname of the binaries match the current
2982  // suppr spec
2983  if (ctxt)
2984  {
2985  // Check if the name of the binaries match the current suppr spec
2986  if (!names_of_binaries_match(*this, *ctxt))
2988  return false;
2989 
2990  // Check if the soname of the binaries match the current suppr spec
2991  if (!sonames_of_binaries_match(*this, *ctxt))
2993  return false;
2994  }
2995 
2996  string fname = fn->get_qualified_name();
2997 
2998  // Check if the "name" property matches.
2999  if (!get_name().empty())
3000  {
3001  if (get_name() != fn->get_qualified_name())
3002  return false;
3003 
3005  && fn->get_symbol()
3006  && fn->get_symbol()->get_alias_from_name(fname))
3007  {
3008  // So we are in a case of a languages in which the symbol
3009  // name is the same as the function name and we want to
3010  // allow the removal of change reports on an aliased
3011  // function only if the suppression condition matches the
3012  // names of all aliases.
3013  string symbol_name;
3014  elf_symbol_sptr sym = fn->get_symbol();
3015  ABG_ASSERT(sym);
3016  symbol_name = sym->get_name();
3017  if (sym->has_aliases() && sym->get_alias_from_name(fname))
3018  {
3019  for (elf_symbol_sptr a = sym->get_next_alias();
3020  a && !a->is_main_symbol();
3021  a = a->get_next_alias())
3022  if (a->get_name() != symbol_name)
3023  // There is an alias which name is different from
3024  // the function (symbol) name given in the
3025  // suppression condition.
3026  return false;
3027  }
3028  }
3029  }
3030 
3031  // check if the "name_regexp" property matches.
3032  const regex_t_sptr name_regex = priv_->get_name_regex();
3033  if (name_regex)
3034  {
3035  if (!regex::match(name_regex, fname))
3036  return false;
3037 
3039  && fn->get_symbol()
3040  && fn->get_symbol()->get_alias_from_name(fname))
3041  {
3042  // So we are in a case of a languages in which the symbol
3043  // name is the same as the function name and we want to
3044  // allow the removal of change reports on an aliased
3045  // function only if the suppression condition matches *all*
3046  // the aliases.
3047  string symbol_name;
3048  elf_symbol_sptr sym = fn->get_symbol();
3049  ABG_ASSERT(sym);
3050  symbol_name = sym->get_name();
3051  if (sym->has_aliases())
3052  {
3053  for (elf_symbol_sptr a = sym->get_next_alias();
3054  a && !a->is_main_symbol();
3055  a = a->get_next_alias())
3056  if (!regex::match(name_regex, a->get_name()))
3057  return false;
3058  }
3059  }
3060  }
3061 
3062  // check if the "name_not_regexp" property matches.
3063  const regex_t_sptr name_not_regex = priv_->get_name_not_regex();
3064  if (name_not_regex)
3065  {
3066  if (regex::match(name_not_regex, fname))
3067  return false;
3068 
3070  && fn->get_symbol()
3071  && fn->get_symbol()->get_alias_from_name(fname))
3072  {
3073  // So we are in a case of a languages in which the symbol
3074  // name is the same as the function name and we want to
3075  // allow the removal of change reports on an aliased
3076  // function only if the suppression condition matches *all*
3077  // the aliases.
3078  string symbol_name;
3079  elf_symbol_sptr sym = fn->get_symbol();
3080  ABG_ASSERT(sym);
3081  symbol_name = sym->get_name();
3082  if (sym->has_aliases())
3083  {
3084  for (elf_symbol_sptr a = sym->get_next_alias();
3085  a && !a->is_main_symbol();
3086  a = a->get_next_alias())
3087  if (regex::match(name_regex, a->get_name()))
3088  return false;
3089  }
3090  }
3091  }
3092 
3093  // Check if the "return_type_name" or "return_type_regexp"
3094  // properties matches.
3095 
3096  string fn_return_type_name = fn->get_type()->get_return_type()
3097  ? static_cast<string>
3098  ((get_type_declaration(fn->get_type()->get_return_type())
3099  ->get_qualified_name()))
3100  : "";
3101 
3102  if (!get_return_type_name().empty())
3103  {
3104  if (fn_return_type_name != get_return_type_name())
3105  return false;
3106  }
3107  else
3108  {
3109  const regex_t_sptr return_type_regex = priv_->get_return_type_regex();
3110  if (return_type_regex
3111  && !regex::match(return_type_regex, fn_return_type_name))
3112  return false;
3113  }
3114 
3115  // Check if the "symbol_name", "symbol_name_regexp", and
3116  // "symbol_name_not_regexp" properties match.
3117  string fn_sym_name, fn_sym_version;
3118  elf_symbol_sptr sym = fn->get_symbol();
3119  if (sym)
3120  {
3121  fn_sym_name = sym->get_name();
3122  fn_sym_version = sym->get_version().str();
3123  }
3124 
3125  if (sym && !get_symbol_name().empty())
3126  {
3127  if (fn_sym_name != get_symbol_name())
3128  return false;
3129 
3130  if (sym && get_allow_other_aliases())
3131  {
3132  // In this case, we want to allow the suppression of change
3133  // reports about an aliased symbol only if the suppression
3134  // condition matches the name of all aliases.
3135  if (sym->has_aliases())
3136  {
3137  for (elf_symbol_sptr a = sym->get_next_alias();
3138  a && !a->is_main_symbol();
3139  a = a->get_next_alias())
3140  if (a->get_name() != fn_sym_name)
3141  return false;
3142  }
3143  }
3144  }
3145  else if (sym)
3146  {
3147  const regex_t_sptr symbol_name_regex = priv_->get_symbol_name_regex();
3148  if (symbol_name_regex && !regex::match(symbol_name_regex, fn_sym_name))
3149  return false;
3150 
3151  const regex_t_sptr symbol_name_not_regex =
3152  priv_->get_symbol_name_not_regex();
3153  if (symbol_name_not_regex
3154  && regex::match(symbol_name_not_regex, fn_sym_name))
3155  return false;
3156 
3158  {
3159  // In this case, we want to allow the suppression of change
3160  // reports about an aliased symbol only if the suppression
3161  // condition matches the name of all aliases.
3162  if (sym->has_aliases())
3163  {
3164  for (elf_symbol_sptr a = sym->get_next_alias();
3165  a && !a->is_main_symbol();
3166  a = a->get_next_alias())
3167  {
3168  if (symbol_name_regex
3169  && !regex::match(symbol_name_regex, a->get_name()))
3170  return false;
3171 
3172  if (symbol_name_not_regex
3173  && regex::match(symbol_name_not_regex, a->get_name()))
3174  return false;
3175  }
3176  }
3177  }
3178  }
3179 
3180  // Check if the "symbol_version" and "symbol_version_regexp"
3181  // properties match.
3182  if (sym && !get_symbol_version().empty())
3183  {
3184  if (fn_sym_version != get_symbol_version())
3185  return false;
3186  }
3187  else if (sym)
3188  {
3189  const regex_t_sptr symbol_version_regex =
3190  priv_->get_symbol_version_regex();
3191  if (symbol_version_regex
3192  && !regex::match(symbol_version_regex, fn_sym_version))
3193  return false;
3194  }
3195 
3196  // Check the 'parameter' property.
3197  if (!get_parameter_specs().empty())
3198  {
3199  function_type_sptr fn_type = fn->get_type();
3200  type_base_sptr parm_type;
3201 
3202  for (parameter_specs_type::const_iterator p =
3203  get_parameter_specs().begin();
3204  p != get_parameter_specs().end();
3205  ++p)
3206  {
3207  size_t index = (*p)->get_index();
3209  fn_type->get_parm_at_index_from_first_non_implicit_parm(index);
3210  if (!fn_parm)
3211  return false;
3212 
3213  string fn_parm_type_qualified_name;
3214  if (fn_parm)
3215  {
3216  parm_type = fn_parm->get_type();
3217  fn_parm_type_qualified_name =
3219  }
3220 
3221  const string& tn = (*p)->get_parameter_type_name();
3222  if (!tn.empty())
3223  {
3224  if (tn != fn_parm_type_qualified_name)
3225  return false;
3226  }
3227  else
3228  {
3229  const regex_t_sptr parm_type_name_regex =
3230  (*p)->priv_->get_type_name_regex();
3231  if (parm_type_name_regex)
3232  {
3233  if (!regex::match(parm_type_name_regex,
3234  fn_parm_type_qualified_name))
3235  return false;
3236  }
3237  }
3238  }
3239  }
3240 
3241  return true;
3242 }
3243 
3244 /// Evaluate the current function suppression specification on a given
3245 /// @ref function_decl and say if a report about a change involving this
3246 /// @ref function_decl should be suppressed or not.
3247 ///
3248 /// @param fn the @ref function_decl to evaluate this suppression
3249 /// specification against.
3250 ///
3251 /// @param k the kind of function change @p fn is supposed to have.
3252 ///
3253 /// @param ctxt the context of the current diff.
3254 ///
3255 /// @return true iff a report about a change involving the function @p
3256 /// fn should be suppressed.
3257 bool
3259  change_kind k,
3260  const diff_context_sptr ctxt) const
3261 {return suppresses_function(fn.get(), k, ctxt);}
3262 
3263 /// Evaluate the current function suppression specification on a given
3264 /// @ref elf_symbol and say if a report about a change involving this
3265 /// @ref elf_symbol should be suppressed or not.
3266 ///
3267 /// @param sym the @ref elf_symbol to evaluate this suppression
3268 /// specification against.
3269 ///
3270 /// @param k the kind of function change @p sym is supposed to have.
3271 ///
3272 /// @param ctxt the context of the current diff.
3273 ///
3274 /// @return true iff a report about a change involving the symbol @p
3275 /// sym should be suppressed.
3276 bool
3278  change_kind k,
3279  const diff_context_sptr ctxt)
3280 {
3281  if (!sym)
3282  return false;
3283 
3284  if (!(get_change_kind() & k))
3285  return false;
3286 
3287  if (!sym->is_function())
3288  return false;
3289 
3292 
3293  // Check if the name and soname of the binaries match the current
3294  // suppr spect
3295  if (ctxt)
3296  {
3297  // Check if the name of the binaries match the current
3298  // suppr spect
3299  if (!names_of_binaries_match(*this, *ctxt))
3301  return false;
3302 
3303  // Check if the soname of the binaries match the current
3304  // suppr spect
3305  if (!sonames_of_binaries_match(*this, *ctxt))
3307  return false;
3308  }
3309 
3310  string sym_name = sym->get_name(), sym_version = sym->get_version().str();
3311  bool no_symbol_name = false, no_symbol_version = false;
3312 
3313  // Consider the symbol name.
3314  if (!get_symbol_name().empty())
3315  {
3316  if (sym_name != get_symbol_name())
3317  return false;
3318  }
3319  else if (!get_symbol_name_regex_str().empty())
3320  {
3321  const regex_t_sptr symbol_name_regex = priv_->get_symbol_name_regex();
3322  if (symbol_name_regex && !regex::match(symbol_name_regex, sym_name))
3323  return false;
3324  }
3325  else
3326  no_symbol_name = true;
3327 
3328  // Consider the symbol version
3329  if (!get_symbol_version().empty())
3330  {
3331  if (sym_version != get_symbol_version())
3332  return false;
3333  }
3334  else if (!get_symbol_version_regex_str().empty())
3335  {
3336  const regex_t_sptr symbol_version_regex =
3337  priv_->get_symbol_version_regex();
3338  if (symbol_version_regex
3339  && !regex::match(symbol_version_regex, sym_version))
3340  return false;
3341  }
3342  else
3343  no_symbol_version = true;
3344 
3345  if (no_symbol_name && no_symbol_version)
3346  return false;
3347 
3348  return true;
3349 }
3350 
3351 /// Evaluate the current function suppression specification on a given
3352 /// @ref elf_symbol and say if a report about a change involving this
3353 /// @ref elf_symbol should be suppressed or not.
3354 ///
3355 /// @param sym the @ref elf_symbol to evaluate this suppression
3356 /// specification against.
3357 ///
3358 /// @param k the kind of function change @p sym is supposed to have.
3359 ///
3360 /// @param ctxt the context of the current diff.
3361 ///
3362 /// @return true iff a report about a change involving the symbol @p
3363 /// sym should be suppressed.
3364 bool
3366  change_kind k,
3367  const diff_context_sptr ctxt)
3368 {return suppresses_function_symbol(sym.get(), k, ctxt);}
3369 
3370 /// Test if an instance of @ref suppression is an instance of @ref
3371 /// function_suppression.
3372 ///
3373 /// @param suppr the instance of @ref suppression to test for.
3374 ///
3375 /// @return if @p suppr is an instance of @ref function_suppression, then
3376 /// return the sub-object of the @p suppr of type @ref
3377 /// function_suppression, otherwise return a nil pointer.
3380 {return dynamic_pointer_cast<function_suppression>(suppr);}
3381 
3382 /// The bitwise 'and' operator for the enum @ref
3383 /// function_suppression::change_kind.
3384 ///
3385 /// @param l the first operand of the 'and' operator.
3386 ///
3387 /// @param r the second operand of the 'and' operator.
3388 ///
3389 /// @return the result of 'and' operation on @p l and @p r.
3393 {
3394  return static_cast<function_suppression::change_kind>
3395  (static_cast<unsigned>(l) & static_cast<unsigned>(r));
3396 }
3397 
3398 /// The bitwise 'or' operator for the enum @ref
3399 /// function_suppression::change_kind.
3400 ///
3401 /// @param l the first operand of the 'or' operator.
3402 ///
3403 /// @param r the second operand of the 'or' operator.
3404 ///
3405 /// @return the result of 'or' operation on @p l and @p r.
3409 {
3410  return static_cast<function_suppression::change_kind>
3411  (static_cast<unsigned>(l) | static_cast<unsigned>(r));
3412 }
3413 
3414 /// Test if a variable suppression matches a variable denoted by its name.
3415 ///
3416 /// @param s the variable suppression to consider.
3417 ///
3418 /// @param var_name the name of the variable to consider.
3419 ///
3420 /// @return true if the variable is matches by the suppression
3421 /// specification.
3422 bool
3424  const string& var_name)
3425 {
3426  if (regex_t_sptr regexp = s.priv_->get_name_regex())
3427  {
3428  if (!regex::match(regexp, var_name))
3429  return false;
3430  }
3431  else if (regex_t_sptr regexp = s.priv_->get_name_not_regex())
3432  {
3433  if (regex::match(regexp, var_name))
3434  return false;
3435  }
3436  else if (s.priv_->name_.empty())
3437  return false;
3438  else // if (!s.priv_->name_.empty())
3439  {
3440  if (s.priv_->name_ != var_name)
3441  return false;
3442  }
3443 
3444  return true;
3445 }
3446 
3447 /// Test if a variable suppression matches a variable denoted by its
3448 /// symbol name.
3449 ///
3450 /// @param s the variable suppression to consider.
3451 ///
3452 /// @param var_linkage_name the name of the variable to consider.
3453 ///
3454 /// @return true if the variable is matches by the suppression
3455 /// specification.
3456 bool
3458  const string& var_linkage_name)
3459 {
3460  if (regex_t_sptr regexp = s.priv_->get_symbol_name_regex())
3461  {
3462  if (!regex::match(regexp, var_linkage_name))
3463  return false;
3464  }
3465  else if (regex_t_sptr regexp =
3466  s.priv_->get_symbol_name_not_regex())
3467  {
3468  if (regex::match(regexp, var_linkage_name))
3469  return false;
3470  }
3471  else if (s.priv_->symbol_name_.empty())
3472  return false;
3473  else // if (!s.priv_->symbol_name_.empty())
3474  {
3475  if (s.priv_->symbol_name_ != var_linkage_name)
3476  return false;
3477  }
3478 
3479  return true;
3480 }
3481 
3482 /// Test if a type suppression matches a type designated by its fully
3483 /// qualified name.
3484 ///
3485 /// @param s the type suppression to consider.
3486 ///
3487 /// @param type_name the name of the type to consider.
3488 ///
3489 /// @return true iff the suppression s matches the type denoted by
3490 /// name @p type_name.
3491 bool
3493  const string& type_name)
3494 {
3495  if (regex_t_sptr regexp = s.priv_->get_type_name_regex())
3496  {
3497  if (!regex::match(regexp, type_name))
3498  return false;
3499  }
3500  else if (!s.get_type_name().empty())
3501  {
3502  if (s.get_type_name() != type_name)
3503  return false;
3504  }
3505  else
3506  return false;
3507 
3508  return true;
3509 }
3510 
3511 /// Parse a string containing a parameter spec, build an instance of
3512 /// function_suppression::parameter_spec from it and return a pointer
3513 /// to that object.
3514 ///
3515 /// @return a shared pointer pointer to the newly built instance of
3516 /// function_suppression::parameter_spec. If the parameter
3517 /// specification could not be parsed, return a nil object.
3519 read_parameter_spec_from_string(const string& str)
3520 {
3521  string::size_type cur = 0;
3523 
3524  // skip leading white spaces.
3525  for (; cur < str.size(); ++cur)
3526  if (!isspace(str[cur]))
3527  break;
3528 
3529  // look for the parameter index
3530  string index_str;
3531  if (str[cur] == '\'')
3532  {
3533  ++cur;
3534  for (; cur < str.size(); ++cur)
3535  if (!isdigit(str[cur]))
3536  break;
3537  else
3538  index_str += str[cur];
3539  }
3540 
3541  // skip white spaces.
3542  for (; cur < str.size(); ++cur)
3543  if (!isspace(str[cur]))
3544  break;
3545 
3546  bool is_regex = false;
3547  if (str[cur] == '/')
3548  {
3549  is_regex = true;
3550  ++cur;
3551  }
3552 
3553  // look for the type name (regex)
3554  string type_name;
3555  for (; cur < str.size(); ++cur)
3556  if (!isspace(str[cur]))
3557  {
3558  if (is_regex && str[cur] == '/')
3559  break;
3560  type_name += str[cur];
3561  }
3562 
3563  if (is_regex && str[cur] == '/')
3564  ++cur;
3565 
3566  if (!index_str.empty() || !type_name.empty())
3567  {
3568  std::string type_name_regex;
3569  if (is_regex)
3570  {
3571  type_name_regex = type_name;
3572  type_name.clear();
3573  }
3574  function_suppression::parameter_spec* p =
3575  new function_suppression::parameter_spec(atoi(index_str.c_str()),
3576  type_name, type_name_regex);
3577  result.reset(p);
3578  }
3579 
3580  return result;
3581 }
3582 
3583 /// Parse function suppression specification, build a resulting @ref
3584 /// function_suppression type and return a shared pointer to that
3585 /// object.
3586 ///
3587 /// @return a shared pointer to the newly built @ref
3588 /// function_suppression. If the function suppression specification
3589 /// could not be parsed then a nil shared pointer is returned.
3591 read_function_suppression(const ini::config::section& section)
3592 {
3594 
3595  if (section.get_name() != "suppress_function")
3596  return result;
3597 
3598  static const char *const sufficient_props[] = {
3599  "label",
3600  "file_name_regexp",
3601  "file_name_not_regexp",
3602  "soname_regexp",
3603  "soname_not_regexp",
3604  "name",
3605  "name_regexp",
3606  "name_not_regexp",
3607  "parameter",
3608  "return_type_name",
3609  "return_type_regexp",
3610  "symbol_name",
3611  "symbol_name_regexp",
3612  "symbol_name_not_regexp",
3613  "symbol_version",
3614  "symbol_version_regexp",
3615  };
3616  if (!check_sufficient_props(sufficient_props,
3617  sizeof(sufficient_props)/sizeof(char*),
3618  section))
3619  return result;
3620 
3621  ini::simple_property_sptr drop_artifact =
3622  is_simple_property(section.find_property("drop_artifact"));
3623  if (!drop_artifact)
3624  drop_artifact = is_simple_property(section.find_property("drop"));
3625 
3626  string drop_artifact_str = drop_artifact
3627  ? drop_artifact->get_value()->as_string()
3628  : "";
3629 
3630  ini::simple_property_sptr change_kind_prop =
3631  is_simple_property(section.find_property("change_kind"));
3632  string change_kind_str = change_kind_prop
3633  ? change_kind_prop->get_value()->as_string()
3634  : "";
3635 
3636  ini::simple_property_sptr label_prop =
3637  is_simple_property(section.find_property("label"));
3638  string label_str = label_prop
3639  ? label_prop->get_value()->as_string()
3640  : "";
3641 
3642  ini::simple_property_sptr file_name_regex_prop =
3643  is_simple_property(section.find_property("file_name_regexp"));
3644  string file_name_regex_str =
3645  file_name_regex_prop ? file_name_regex_prop->get_value()->as_string() : "";
3646 
3647  ini::simple_property_sptr file_name_not_regex_prop =
3648  is_simple_property(section.find_property("file_name_not_regexp"));
3649  string file_name_not_regex_str =
3650  file_name_not_regex_prop
3651  ? file_name_not_regex_prop->get_value()->as_string()
3652  : "";
3653 
3654  ini::simple_property_sptr soname_regex_prop =
3655  is_simple_property(section.find_property("soname_regexp"));
3656  string soname_regex_str =
3657  soname_regex_prop ? soname_regex_prop->get_value()->as_string() : "";
3658 
3659  ini::simple_property_sptr soname_not_regex_prop =
3660  is_simple_property(section.find_property("soname_not_regexp"));
3661  string soname_not_regex_str =
3662  soname_not_regex_prop
3663  ? soname_not_regex_prop->get_value()->as_string()
3664  : "";
3665 
3666  ini::simple_property_sptr name_prop =
3667  is_simple_property(section.find_property("name"));
3668  string name = name_prop
3669  ? name_prop->get_value()->as_string()
3670  : "";
3671 
3672  ini::simple_property_sptr name_regex_prop =
3673  is_simple_property(section.find_property("name_regexp"));
3674  string name_regex_str = name_regex_prop
3675  ? name_regex_prop->get_value()->as_string()
3676  : "";
3677 
3678  ini::simple_property_sptr name_not_regex_prop =
3679  is_simple_property(section.find_property("name_not_regexp"));
3680  string name_not_regex_str = name_not_regex_prop
3681  ? name_not_regex_prop->get_value()->as_string()
3682  : "";
3683 
3684  ini::simple_property_sptr return_type_name_prop =
3685  is_simple_property(section.find_property("return_type_name"));
3686  string return_type_name = return_type_name_prop
3687  ? return_type_name_prop->get_value()->as_string()
3688  : "";
3689 
3690  ini::simple_property_sptr return_type_regex_prop =
3691  is_simple_property(section.find_property("return_type_regexp"));
3692  string return_type_regex_str = return_type_regex_prop
3693  ? return_type_regex_prop->get_value()->as_string()
3694  : "";
3695 
3696  ini::simple_property_sptr sym_name_prop =
3697  is_simple_property(section.find_property("symbol_name"));
3698  string sym_name = sym_name_prop
3699  ? sym_name_prop->get_value()->as_string()
3700  : "";
3701 
3702  ini::simple_property_sptr sym_name_regex_prop =
3703  is_simple_property(section.find_property("symbol_name_regexp"));
3704  string sym_name_regex_str = sym_name_regex_prop
3705  ? sym_name_regex_prop->get_value()->as_string()
3706  : "";
3707 
3708  ini::simple_property_sptr sym_name_not_regex_prop =
3709  is_simple_property(section.find_property("symbol_name_not_regexp"));
3710  string sym_name_not_regex_str = sym_name_not_regex_prop
3711  ? sym_name_not_regex_prop->get_value()->as_string()
3712  : "";
3713 
3714  ini::simple_property_sptr sym_ver_prop =
3715  is_simple_property(section.find_property("symbol_version"));
3716  string sym_version = sym_ver_prop
3717  ? sym_ver_prop->get_value()->as_string()
3718  : "";
3719 
3720  ini::simple_property_sptr sym_ver_regex_prop =
3721  is_simple_property(section.find_property("symbol_version_regexp"));
3722  string sym_ver_regex_str = sym_ver_regex_prop
3723  ? sym_ver_regex_prop->get_value()->as_string()
3724  : "";
3725 
3726  ini::simple_property_sptr allow_other_aliases_prop =
3727  is_simple_property(section.find_property("allow_other_aliases"));
3728  string allow_other_aliases = allow_other_aliases_prop
3729  ? allow_other_aliases_prop->get_value()->as_string()
3730  : "";
3731 
3734  for (ini::config::properties_type::const_iterator p =
3735  section.get_properties().begin();
3736  p != section.get_properties().end();
3737  ++p)
3738  if ((*p)->get_name() == "parameter")
3739  {
3741  ABG_ASSERT(prop);
3742  if ((parm = read_parameter_spec_from_string
3743  (prop->get_value()->as_string())))
3744  parms.push_back(parm);
3745  }
3746 
3747  result.reset(new function_suppression(label_str,
3748  name,
3749  name_regex_str,
3750  return_type_name,
3751  return_type_regex_str,
3752  parms,
3753  sym_name,
3754  sym_name_regex_str,
3755  sym_version,
3756  sym_ver_regex_str));
3757 
3758  if ((drop_artifact_str == "yes" || drop_artifact_str == "true")
3759  && (!name.empty()
3760  || !name_regex_str.empty()
3761  || !name_not_regex_str.empty()
3762  || !sym_name.empty()
3763  || !sym_name_regex_str.empty()
3764  || !sym_name_not_regex_str.empty()))
3765  result->set_drops_artifact_from_ir(true);
3766 
3767  if (!change_kind_str.empty())
3768  result->set_change_kind
3769  (function_suppression::parse_change_kind(change_kind_str));
3770 
3771  if (!allow_other_aliases.empty())
3772  result->set_allow_other_aliases(allow_other_aliases == "yes"
3773  || allow_other_aliases == "true");
3774 
3775  if (!name_not_regex_str.empty())
3776  result->set_name_not_regex_str(name_not_regex_str);
3777 
3778  if (!sym_name_not_regex_str.empty())
3779  result->set_symbol_name_not_regex_str(sym_name_not_regex_str);
3780 
3781  if (!file_name_regex_str.empty())
3782  result->set_file_name_regex_str(file_name_regex_str);
3783 
3784  if (!file_name_not_regex_str.empty())
3785  result->set_file_name_not_regex_str(file_name_not_regex_str);
3786 
3787  if (!soname_regex_str.empty())
3788  result->set_soname_regex_str(soname_regex_str);
3789 
3790  if (!soname_not_regex_str.empty())
3791  result->set_soname_not_regex_str(soname_not_regex_str);
3792 
3793  return result;
3794 }
3795 
3796 // </function_suppression stuff>
3797 
3798 // <variable_suppression stuff>
3799 
3800 /// Constructor for the @ref variable_suppression type.
3801 ///
3802 /// @param label an informative text string that the evalution code
3803 /// might use to designate this variable suppression specification in
3804 /// error messages. This parameter might be empty, in which case it's
3805 /// ignored at evaluation time.
3806 ///
3807 /// @param name the name of the variable the user wants the current
3808 /// specification to designate. This parameter might be empty, in
3809 /// which case it's ignored at evaluation time.
3810 ///
3811 /// @param name_regex_str if @p name is empty, this parameter is a
3812 /// regular expression for a family of names of variables the user
3813 /// wants the current specification to designate. If @p name is not
3814 /// empty, then this parameter is ignored at evaluation time. This
3815 /// parameter might be empty, in which case it's ignored at evaluation
3816 /// time.
3817 ///
3818 /// @param symbol_name the name of the symbol of the variable the user
3819 /// wants the current specification to designate. This parameter
3820 /// might be empty, in which case it's ignored at evaluation time.
3821 ///
3822 /// @param symbol_name_str if @p symbol_name is empty, this parameter
3823 /// is a regular expression for a family of names of symbols of
3824 /// variables the user wants the current specification to designate.
3825 /// If @p symbol_name is not empty, then this parameter is ignored at
3826 /// evaluation time. This parameter might be empty, in which case
3827 /// it's ignored at evaluation time.
3828 ///
3829 /// @param symbol_version the version of the symbol of the variable
3830 /// the user wants the current specification to designate. This
3831 /// parameter might be empty, in which case it's ignored at evaluation
3832 /// time.
3833 ///
3834 /// @param symbol_version_regex if @p symbol_version is empty, then
3835 /// this parameter is a regular expression for a family of versions of
3836 /// symbol for the variables the user wants the current specification
3837 /// to designate. If @p symbol_version is not empty, then this
3838 /// parameter is ignored at evaluation time. This parameter might be
3839 /// empty, in which case it's ignored at evaluation time.
3840 ///
3841 /// @param type_name the name of the type of the variable the user
3842 /// wants the current specification to designate. This parameter
3843 /// might be empty, in which case it's ignored at evaluation time.
3844 ///
3845 /// @param type_name_regex_str if @p type_name is empty, then this
3846 /// parameter is a regular expression for a family of type names of
3847 /// variables the user wants the current specification to designate.
3848 /// If @p type_name is not empty, then this parameter is ignored at
3849 /// evluation time. This parameter might be empty, in which case it's
3850 /// ignored at evaluation time.
3852  const string& name,
3853  const string& name_regex_str,
3854  const string& symbol_name,
3855  const string& symbol_name_regex_str,
3856  const string& symbol_version,
3857  const string& symbol_version_regex,
3858  const string& type_name,
3859  const string& type_name_regex_str)
3860  : suppression_base(label),
3861  priv_(new priv(name, name_regex_str,
3862  symbol_name, symbol_name_regex_str,
3863  symbol_version, symbol_version_regex,
3864  type_name, type_name_regex_str))
3865 {}
3866 
3867 /// Virtual destructor for the @erf variable_suppression type.
3868 /// variable_suppression type.
3870 {}
3871 
3872 /// Parses a string containing the content of the "change-kind"
3873 /// property and returns the an instance of @ref
3874 /// variable_suppression::change_kind as a result.
3875 ///
3876 /// @param s the string to parse.
3877 ///
3878 /// @return the resulting @ref variable_suppression::change_kind.
3881 {
3882  if (s == "variable-subtype-change")
3884  else if (s == "added-variable")
3886  else if (s == "deleted-variable")
3888  else if (s == "all")
3889  return ALL_CHANGE_KIND;
3890  else
3891  return UNDEFINED_CHANGE_KIND;
3892 }
3893 
3894 /// Getter of the "change_king" property.
3895 ///
3896 /// @return the value of the "change_kind" property.
3899 {return priv_->change_kind_;}
3900 
3901 /// Setter of the "change_kind" property.
3902 ///
3903 /// @param k the new value of of the change_kind.
3904 void
3906 {priv_->change_kind_ = k;}
3907 
3908 /// Getter for the name of the variable the user wants the current
3909 /// specification to designate. This property might be empty, in
3910 /// which case it's ignored at evaluation time.
3911 ///
3912 /// @return the name of the variable.
3913 const string&
3915 {return priv_->name_;}
3916 
3917 /// Setter for the name of the variable the user wants the current
3918 /// specification to designate. This property might be empty, in
3919 /// which case it's ignored at evaluation time.
3920 ///
3921 /// @param n the new name of the variable to set.
3922 void
3924 {priv_->name_ = n;}
3925 
3926 /// Getter for the regular expression for a family of names of
3927 /// variables the user wants the current specification to designate.
3928 /// If the variable name as returned by
3929 /// variable_suppression::get_name() is not empty, then this property
3930 /// is ignored at evaluation time. This property might be empty, in
3931 /// which case it's ignored at evaluation time.
3932 ///
3933 /// @return the regular expression for the variable name.
3934 const string&
3936 {return priv_->name_regex_str_;}
3937 
3938 /// Setter for the regular expression for a family of names of
3939 /// variables the user wants the current specification to designate.
3940 /// If the variable name as returned by
3941 /// variable_suppression::get_name() is not empty, then this property
3942 /// is ignored at evaluation time. This property might be empty, in
3943 /// which case it's ignored at evaluation time.
3944 ///
3945 /// @param r the new regular expression for the variable name.
3946 void
3948 {priv_->name_regex_str_ = r;}
3949 
3950 /// Getter for the "name_not_regexp" property of the specification.
3951 ///
3952 /// @return the value of the "name_not_regexp" property.
3953 const string&
3955 {return priv_->name_not_regex_str_;}
3956 
3957 /// Setter for the "name_not_regexp" property of the specification.
3958 ///
3959 /// @param r the new value of the "name_not_regexp" property.
3960 void
3962 {priv_->name_not_regex_str_ = r;}
3963 
3964 /// Getter for the name of the symbol of the variable the user wants
3965 /// the current specification to designate.
3966 ///
3967 /// This property might be empty, in which case it is ignored at
3968 /// evaluation time.
3969 ///
3970 /// @return the name of the symbol of the variable.
3971 const string&
3973 {return priv_->symbol_name_;}
3974 
3975 /// Setter for the name of the symbol of the variable the user wants
3976 /// the current specification to designate.
3977 ///
3978 /// This property might be empty, in which case it is ignored at
3979 /// evaluation time.
3980 ///
3981 /// @param n the new name of the symbol of the variable.
3982 void
3984 {priv_->symbol_name_ = n;}
3985 
3986 /// Getter of the regular expression for a family of symbol names of
3987 /// the variables this specification is about to designate.
3988 ///
3989 /// This property might be empty, in which case it's ignored at
3990 /// evaluation time. Otherwise, it is taken in account iff the
3991 /// property returned by variable_suppression::get_symbol_name() is
3992 /// empty.
3993 ///
3994 /// @return the regular expression for a symbol name of the variable.
3995 const string&
3997 {return priv_->symbol_name_regex_str_;}
3998 
3999 /// Setter of the regular expression for a family of symbol names of
4000 /// the variables this specification is about to designate.
4001 ///
4002 /// This property might be empty, in which case it's ignored at
4003 /// evaluation time. Otherwise, it is taken in account iff the
4004 /// property returned by variable_suppression::get_symbol_name() is
4005 /// empty.
4006 ///
4007 /// @param r the regular expression for a symbol name of the variable.
4008 void
4010 {priv_->symbol_name_regex_str_ = r;}
4011 
4012 /// Getter for a regular expression for a family of names of symbols
4013 /// of variables the user wants this specification to designate.
4014 ///
4015 /// If a symbol name is matched by this regular expression, then the
4016 /// suppression specification will *NOT* suppress the symbol.
4017 ///
4018 /// If the symbol name as returned by
4019 /// variable_suppression::get_symbol_name() is not empty, then this
4020 /// property is ignored at specification evaluation time.
4021 ///
4022 /// This property might be empty, in which case it's ignored at
4023 /// evaluation time.
4024 ///
4025 /// @return the regular expression string for a family of names of
4026 /// symbols that is to be *NOT* suppressed by this suppression specification.
4027 const string&
4029 {return priv_->symbol_name_not_regex_str_;}
4030 
4031 /// Setter for a regular expression for a family of names of symbols
4032 /// of variables the user wants this specification to designate.
4033 ///
4034 /// If a symbol name is matched by this regular expression, then the
4035 /// suppression specification will *NOT* suppress the symbol.
4036 ///
4037 /// If the symbol name as returned by
4038 /// variable_suppression::get_symbol_name() is not empty, then this
4039 /// property is ignored at specification evaluation time.
4040 ///
4041 /// This property might be empty, in which case it's ignored at
4042 /// evaluation time.
4043 ///
4044 /// @param the new regular expression string for a family of names of
4045 /// symbols that is to be *NOT* suppressed by this suppression
4046 /// specification.
4047 void
4049 {priv_->symbol_name_not_regex_str_ = r;}
4050 
4051 /// Getter for the version of the symbol of the variable the user
4052 /// wants the current specification to designate. This property might
4053 /// be empty, in which case it's ignored at evaluation time.
4054 ///
4055 /// @return the symbol version of the variable.
4056 const string&
4058 {return priv_->symbol_version_;}
4059 
4060 /// Setter for the version of the symbol of the variable the user
4061 /// wants the current specification to designate. This property might
4062 /// be empty, in which case it's ignored at evaluation time.
4063 ///
4064 /// @return the new symbol version of the variable.
4065 void
4067 {priv_->symbol_version_ = v;}
4068 
4069 /// Getter of the regular expression for a family of versions of
4070 /// symbol for the variables the user wants the current specification
4071 /// to designate. If @p symbol_version is not empty, then this
4072 /// property is ignored at evaluation time. This property might be
4073 /// empty, in which case it's ignored at evaluation time.
4074 ///
4075 /// @return the regular expression of the symbol version of the
4076 /// variable.
4077 const string&
4079 {return priv_->symbol_version_regex_str_;}
4080 
4081 /// Setter of the regular expression for a family of versions of
4082 /// symbol for the variables the user wants the current specification
4083 /// to designate. If @p symbol_version is not empty, then this
4084 /// property is ignored at evaluation time. This property might be
4085 /// empty, in which case it's ignored at evaluation time.
4086 ///
4087 /// @param v the new regular expression of the symbol version of the
4088 /// variable.
4089 void
4091 {priv_->symbol_version_regex_str_ = r;}
4092 
4093 /// Getter for the name of the type of the variable the user wants the
4094 /// current specification to designate.
4095 ///
4096 /// This property might be empty, in which case it's ignored at
4097 /// evaluation time.
4098 ///
4099 /// @return the name of the variable type.
4100 const string&
4102 {return priv_->type_name_;}
4103 
4104 /// Setter for the name of the type of the variable the user wants the
4105 /// current specification to designate.
4106 ///
4107 /// This property might be empty, in which case it's ignored at
4108 /// evaluation time.
4109 ///
4110 /// @param n the new name of the variable type.
4111 void
4113 {priv_->type_name_ = n;}
4114 
4115 /// Getter for the regular expression for a family of type names of
4116 /// variables the user wants the current specification to designate.
4117 ///
4118 /// If the type name as returned by
4119 /// variable_suppression::get_type_name() is not empty, then this
4120 /// property is ignored at evaluation time. This property might be
4121 /// empty, in which case it's ignored at evaluation time.
4122 ///
4123 /// @return the regular expression of the variable type name.
4124 const string&
4126 {return priv_->type_name_regex_str_;}
4127 
4128 /// Setter for the regular expression for a family of type names of
4129 /// variables the user wants the current specification to designate.
4130 ///
4131 /// If the type name as returned by
4132 /// variable_suppression::get_type_name() is not empty, then this
4133 /// property is ignored at evaluation time. This property might be
4134 /// empty, in which case it's ignored at evaluation time.
4135 ///
4136 /// @param r the regular expression of the variable type name.
4137 void
4139 {priv_->type_name_regex_str_ = r;}
4140 
4141 /// Evaluate this suppression specification on a given diff node and
4142 /// say if the diff node should be suppressed or not.
4143 ///
4144 /// @param diff the diff node to evaluate this suppression
4145 /// specification against.
4146 ///
4147 /// @return true if @p diff should be suppressed.
4148 bool
4150 {
4151  const var_diff* d = is_var_diff(diff);
4152  if (!d)
4153  return false;
4154 
4156  sv = is_var_decl(is_decl(d->second_subject()));
4157 
4158  ABG_ASSERT(fv && sv);
4159 
4160  return (suppresses_variable(fv,
4162  diff->context())
4163  || suppresses_variable(sv,
4165  diff->context()));
4166 }
4167 
4168 /// Evaluate the current variable suppression specification on a given
4169 /// @ref var_decl and say if a report about a change involving this
4170 /// @ref var_decl should be suppressed or not.
4171 ///
4172 /// @param var the @ref var_decl to evaluate this suppression
4173 /// specification against.
4174 ///
4175 /// @param k the kind of variable change @p var is supposed to have.
4176 ///
4177 /// @param ctxt the context of the current diff.
4178 ///
4179 /// @return true iff a report about a change involving the variable @p
4180 /// var should be suppressed.
4181 bool
4183  change_kind k,
4184  const diff_context_sptr ctxt) const
4185 {
4186  if (!(get_change_kind() & k))
4187  return false;
4188 
4189  // Check if the name and soname of the binaries match
4190  if (ctxt)
4191  {
4192  // Check if the name of the binaries match the current
4193  // suppr spec
4194  if (!names_of_binaries_match(*this, *ctxt))
4196  return false;
4197 
4198  // Check if the soname of the binaries match the current suppr
4199  // spec
4200  if (!sonames_of_binaries_match(*this, *ctxt))
4202  return false;
4203  }
4204 
4205  string var_name = var->get_qualified_name();
4206 
4207  // Check for "name" property match.
4208  if (!get_name().empty())
4209  {
4210  if (get_name() != var_name)
4211  return false;
4212  }
4213  else
4214  {
4215  // If the "name" property is empty, then consider checking for the
4216  // "name_regex" and "name_not_regex" properties match
4217  if (get_name().empty())
4218  {
4219  const regex_t_sptr name_regex = priv_->get_name_regex();
4220  if (name_regex && !regex::match(name_regex, var_name))
4221  return false;
4222 
4223  const regex_t_sptr name_not_regex = priv_->get_name_not_regex();
4224  if (name_not_regex && regex::match(name_not_regex, var_name))
4225  return false;
4226  }
4227  }
4228 
4229  // Check for the symbol_name, symbol_name_regex and
4230  // symbol_name_not_regex property match.
4231  string var_sym_name = var->get_symbol() ? var->get_symbol()->get_name() : "";
4232  if (!get_symbol_name().empty())
4233  {
4234  if (get_symbol_name() != var_sym_name)
4235  return false;
4236  }
4237  else
4238  {
4239  const regex_t_sptr sym_name_regex = priv_->get_symbol_name_regex();
4240  if (sym_name_regex && !regex::match(sym_name_regex, var_sym_name))
4241  return false;
4242 
4243  const regex_t_sptr sym_name_not_regex =
4244  priv_->get_symbol_name_not_regex();
4245  if (sym_name_not_regex && regex::match(sym_name_not_regex, var_sym_name))
4246  return false;
4247  }
4248 
4249  // Check for symbol_version and symbol_version_regexp property match
4250  string var_sym_version =
4251  var->get_symbol() ? var->get_symbol()->get_version().str() : "";
4252  if (!get_symbol_version().empty())
4253  {
4254  if (get_symbol_version() != var_sym_version)
4255  return false;
4256  }
4257  else
4258  {
4259  const regex_t_sptr symbol_version_regex =
4260  priv_->get_symbol_version_regex();
4261  if (symbol_version_regex
4262  && !regex::match(symbol_version_regex, var_sym_version))
4263  return false;
4264  }
4265 
4266  // Check for the "type_name" and type_name_regex properties match.
4267  string var_type_name =
4268  get_type_declaration(var->get_type())->get_qualified_name();
4269 
4270  if (!get_type_name().empty())
4271  {
4272  if (get_type_name() != var_type_name)
4273  return false;
4274  }
4275  else
4276  {
4277  if (get_type_name().empty())
4278  {
4279  const regex_t_sptr type_name_regex = priv_->get_type_name_regex();
4280  if (type_name_regex && !regex::match(type_name_regex, var_type_name))
4281  return false;
4282  }
4283  }
4284 
4285  return true;
4286 }
4287 
4288 /// Evaluate the current variable suppression specification on a given
4289 /// @ref var_decl and say if a report about a change involving this
4290 /// @ref var_decl should be suppressed or not.
4291 ///
4292 /// @param var the @ref var_decl to evaluate this suppression
4293 /// specification against.
4294 ///
4295 /// @param k the kind of variable change @p var is supposed to have.
4296 ///
4297 /// @param ctxt the context of the current diff.
4298 ///
4299 /// @return true iff a report about a change involving the variable @p
4300 /// var should be suppressed.
4301 bool
4303  change_kind k,
4304  const diff_context_sptr ctxt) const
4305 {return suppresses_variable(var.get(), k, ctxt);}
4306 
4307 /// Evaluate the current variable suppression specification on a given
4308 /// @ref elf_symbol and say if a report about a change involving this
4309 /// @ref elf_symbol should be suppressed or not.
4310 ///
4311 /// @param sym the @ref elf_symbol to evaluate this suppression
4312 /// specification against.
4313 ///
4314 /// @param k the kind of variable change @p sym is supposed to have.
4315 ///
4316 /// @param ctxt the context of the current diff.
4317 ///
4318 /// @return true iff a report about a change involving the symbol @p
4319 /// sym should be suppressed.
4320 bool
4322  change_kind k,
4323  const diff_context_sptr ctxt) const
4324 {
4325  if (!sym)
4326  return false;
4327 
4328  if (!(get_change_kind() & k))
4329  return false;
4330 
4331  if (!sym->is_variable())
4332  return false;
4333 
4336 
4337  // Check if the name and soname of the binaries match the current
4338  // suppr spec.
4339  if (ctxt)
4340  {
4341  // Check if the name of the binaries match the current suppr
4342  // spec
4343  if (!names_of_binaries_match(*this, *ctxt))
4345  return false;
4346 
4347  // Check if the soname of the binaries match the current suppr spec
4348  if (!sonames_of_binaries_match(*this, *ctxt))
4350  return false;
4351  }
4352 
4353  string sym_name = sym->get_name(), sym_version = sym->get_version().str();
4354 
4355  bool no_symbol_name = false, no_symbol_version = false;
4356 
4357  // Consider the symbol name
4358  if (!get_name().empty())
4359  {
4360  if (get_name() != sym_name)
4361  return false;
4362  }
4363  else if (!get_symbol_name().empty())
4364  {
4365  if (get_symbol_name() != sym_name)
4366  return false;
4367  }
4368  else if (!get_symbol_name_regex_str().empty())
4369  {
4370  const regex_t_sptr sym_name_regex = priv_->get_symbol_name_regex();
4371  if (sym_name_regex && !regex::match(sym_name_regex, sym_name))
4372  return false;
4373  }
4374  else
4375  no_symbol_name = true;
4376 
4377  // Consider the symbol version.
4378  if (!get_symbol_version().empty())
4379  {
4380  if (get_symbol_version() != sym_version)
4381  return false;
4382  }
4383  else if (!get_symbol_version_regex_str().empty())
4384  {
4385  const regex_t_sptr symbol_version_regex =
4386  priv_->get_symbol_version_regex();
4387  if (symbol_version_regex
4388  && !regex::match(symbol_version_regex, sym_version))
4389  return false;
4390  }
4391  else
4392  no_symbol_version = true;
4393 
4394  if (no_symbol_name && no_symbol_version)
4395  return false;
4396 
4397  return true;
4398 }
4399 
4400 /// Evaluate the current variable suppression specification on a given
4401 /// @ref elf_symbol and say if a report about a change involving this
4402 /// @ref elf_symbol should be suppressed or not.
4403 ///
4404 /// @param sym the @ref elf_symbol to evaluate this suppression
4405 /// specification against.
4406 ///
4407 /// @param k the kind of variable change @p sym is supposed to have.
4408 ///
4409 /// @param ctxt the context of the current diff.
4410 ///
4411 /// @return true iff a report about a change involving the symbol @p
4412 /// sym should be suppressed.
4413 bool
4415  change_kind k,
4416  const diff_context_sptr ctxt) const
4417 {return suppresses_variable_symbol(sym.get(), k, ctxt);}
4418 
4419 /// Test if an instance of @ref suppression is an instance of @ref
4420 /// variable_suppression.
4421 ///
4422 /// @param suppr the instance of @ref suppression to test for.
4423 ///
4424 /// @return if @p suppr is an instance of @ref variable_suppression, then
4425 /// return the sub-object of the @p suppr of type @ref
4426 /// variable_suppression, otherwise return a nil pointer.
4429 {return dynamic_pointer_cast<variable_suppression>(s);}
4430 
4431 /// The bitwise 'and' operator for the enum @ref
4432 /// variable_suppression::change_kind.
4433 ///
4434 /// @param l the first operand of the 'and' operator.
4435 ///
4436 /// @param r the second operand of the 'and' operator.
4437 ///
4438 /// @return the result of 'and' operation on @p l and @p r.
4442 {
4443  return static_cast<variable_suppression::change_kind>
4444  (static_cast<unsigned>(l) & static_cast<unsigned>(r));
4445 }
4446 
4447 /// The bitwise 'or' operator for the enum @ref
4448 /// variable_suppression::change_kind.
4449 ///
4450 /// @param l the first operand of the 'or' operator.
4451 ///
4452 /// @param r the second operand of the 'or' operator.
4453 ///
4454 /// @return the result of 'or' operation on @p l and @p r.
4458 {
4459  return static_cast<variable_suppression::change_kind>
4460  (static_cast<unsigned>(l) | static_cast<unsigned>(r));
4461 }
4462 
4463 /// Parse variable suppression specification, build a resulting @ref
4464 /// variable_suppression type and return a shared pointer to that
4465 /// object.
4466 ///
4467 /// @return a shared pointer to the newly built @ref
4468 /// variable_suppression. If the variable suppression specification
4469 /// could not be parsed then a nil shared pointer is returned.
4471 read_variable_suppression(const ini::config::section& section)
4472 {
4474 
4475  if (section.get_name() != "suppress_variable")
4476  return result;
4477 
4478  static const char *const sufficient_props[] = {
4479  "label",
4480  "file_name_regexp",
4481  "file_name_not_regexp",
4482  "soname_regexp",
4483  "soname_not_regexp",
4484  "name",
4485  "name_regexp",
4486  "name_not_regexp",
4487  "symbol_name",
4488  "symbol_name_regexp",
4489  "symbol_name_not_regexp",
4490  "symbol_version",
4491  "symbol_version_regexp",
4492  "type_name",
4493  "type_name_regexp",
4494  };
4495  if (!check_sufficient_props(sufficient_props,
4496  sizeof(sufficient_props)/sizeof(char*),
4497  section))
4498  return result;
4499 
4500  ini::simple_property_sptr drop_artifact =
4501  is_simple_property(section.find_property("drop_artifact"));
4502  if (!drop_artifact)
4503  drop_artifact = is_simple_property(section.find_property("drop"));
4504 
4505  string drop_artifact_str = drop_artifact
4506  ? drop_artifact->get_value()->as_string()
4507  : "";
4508 
4509  ini::simple_property_sptr change_kind_prop =
4510  is_simple_property(section.find_property("change_kind"));
4511  string change_kind_str = change_kind_prop
4512  ? change_kind_prop->get_value()->as_string()
4513  : "";
4514 
4515  ini::simple_property_sptr label_prop =
4516  is_simple_property(section.find_property("label"));
4517  string label_str = (label_prop
4518  ? label_prop->get_value()->as_string()
4519  : "");
4520 
4521  ini::simple_property_sptr file_name_regex_prop =
4522  is_simple_property(section.find_property("file_name_regexp"));
4523  string file_name_regex_str =
4524  file_name_regex_prop ? file_name_regex_prop->get_value()->as_string() : "";
4525 
4526  ini::simple_property_sptr file_name_not_regex_prop =
4527  is_simple_property(section.find_property("file_name_not_regexp"));
4528  string file_name_not_regex_str =
4529  file_name_not_regex_prop
4530  ? file_name_not_regex_prop->get_value()->as_string()
4531  : "";
4532 
4533  ini::simple_property_sptr soname_regex_prop =
4534  is_simple_property(section.find_property("soname_regexp"));
4535  string soname_regex_str =
4536  soname_regex_prop ? soname_regex_prop->get_value()->as_string() : "";
4537 
4538  ini::simple_property_sptr soname_not_regex_prop =
4539  is_simple_property(section.find_property("soname_not_regexp"));
4540  string soname_not_regex_str =
4541  soname_not_regex_prop
4542  ? soname_not_regex_prop->get_value()->as_string()
4543  : "";
4544 
4545  ini::simple_property_sptr name_prop =
4546  is_simple_property(section.find_property("name"));
4547  string name_str = (name_prop
4548  ? name_prop->get_value()->as_string()
4549  : "");
4550 
4551  ini::simple_property_sptr name_regex_prop =
4552  is_simple_property(section.find_property("name_regexp"));
4553  string name_regex_str = (name_regex_prop
4554  ? name_regex_prop->get_value()->as_string()
4555  : "");
4556 
4557  ini::simple_property_sptr name_not_regex_prop =
4558  is_simple_property(section.find_property("name_not_regexp"));
4559  string name_not_regex_str = name_not_regex_prop
4560  ? name_not_regex_prop->get_value()->as_string()
4561  : "";
4562 
4563  ini::simple_property_sptr sym_name_prop =
4564  is_simple_property(section.find_property("symbol_name"));
4565  string symbol_name = (sym_name_prop
4566  ? sym_name_prop->get_value()->as_string()
4567  : "");
4568 
4569  ini::simple_property_sptr sym_name_regex_prop =
4570  is_simple_property(section.find_property("symbol_name_regexp"));
4571  string symbol_name_regex_str = sym_name_regex_prop
4572  ? sym_name_regex_prop->get_value()->as_string()
4573  : "";
4574 
4575  ini::simple_property_sptr sym_name_not_regex_prop =
4576  is_simple_property(section.find_property("symbol_name_not_regexp"));
4577  string symbol_name_not_regex_str = sym_name_not_regex_prop
4578  ? sym_name_not_regex_prop->get_value()->as_string()
4579  : "";
4580 
4581  ini::simple_property_sptr sym_version_prop =
4582  is_simple_property(section.find_property("symbol_version"));
4583  string symbol_version = sym_version_prop
4584  ? sym_version_prop->get_value()->as_string()
4585  : "";
4586 
4587  ini::simple_property_sptr sym_version_regex_prop =
4588  is_simple_property(section.find_property("symbol_version_regexp"));
4589  string symbol_version_regex_str = sym_version_regex_prop
4590  ? sym_version_regex_prop->get_value()->as_string()
4591  : "";
4592 
4593  ini::simple_property_sptr type_name_prop =
4594  is_simple_property(section.find_property("type_name"));
4595  string type_name_str = type_name_prop
4596  ? type_name_prop->get_value()->as_string()
4597  : "";
4598 
4599  ini::simple_property_sptr type_name_regex_prop =
4600  is_simple_property(section.find_property("type_name_regexp"));
4601  string type_name_regex_str = type_name_regex_prop
4602  ? type_name_regex_prop->get_value()->as_string()
4603  : "";
4604 
4605  result.reset(new variable_suppression(label_str,
4606  name_str,
4607  name_regex_str,
4608  symbol_name,
4609  symbol_name_regex_str,
4610  symbol_version,
4611  symbol_version_regex_str,
4612  type_name_str,
4613  type_name_regex_str));
4614 
4615  if ((drop_artifact_str == "yes" || drop_artifact_str == "true")
4616  && (!name_str.empty()
4617  || !name_regex_str.empty()
4618  || !name_not_regex_str.empty()
4619  || !symbol_name.empty()
4620  || !symbol_name_regex_str.empty()
4621  || !symbol_name_not_regex_str.empty()))
4622  result->set_drops_artifact_from_ir(true);
4623 
4624  if (!name_not_regex_str.empty())
4625  result->set_name_not_regex_str(name_not_regex_str);
4626 
4627  if (!symbol_name_not_regex_str.empty())
4628  result->set_symbol_name_not_regex_str(symbol_name_not_regex_str);
4629 
4630  if (!change_kind_str.empty())
4631  result->set_change_kind
4632  (variable_suppression::parse_change_kind(change_kind_str));
4633 
4634  if (!file_name_regex_str.empty())
4635  result->set_file_name_regex_str(file_name_regex_str);
4636 
4637  if (!file_name_not_regex_str.empty())
4638  result->set_file_name_not_regex_str(file_name_not_regex_str);
4639 
4640  if (!soname_regex_str.empty())
4641  result->set_soname_regex_str(soname_regex_str);
4642 
4643  if (!soname_not_regex_str.empty())
4644  result->set_soname_not_regex_str(soname_not_regex_str);
4645 
4646  return result;
4647 }
4648 
4649 /// Test if a given variable is suppressed by at least one suppression
4650 /// specification among a vector of suppression specifications.
4651 ///
4652 /// @param supprs the vector of suppression specifications to consider.
4653 ///
4654 /// @param var_name the name of the variable to consider.
4655 ///
4656 /// @param var_linkage_name the linkage name of the variable to consider.
4657 ///
4658 /// @param require_drop_property if yes, then only suppression
4659 /// specifications that require that the variable be dropped from the
4660 /// internal representation are taking into account.
4661 ///
4662 /// @return true if there is at least one suppression specification in
4663 /// @p supprs which matches a variable named @p var_name, OR a
4664 /// variable which linkage name is @p var_linkage_name.
4665 bool
4667  const string& var_name,
4668  const string& var_linkage_name,
4669  bool require_drop_property)
4670 {
4671  for (auto i : supprs)
4673  {
4674  if (require_drop_property && !i->get_drops_artifact_from_ir())
4675  continue;
4676  if (!var_name.empty()
4677  && suppression_matches_variable_name(*suppr, var_name))
4678  return true;
4679  if (!var_linkage_name.empty()
4681  var_linkage_name))
4682  return true;
4683  }
4684  return false;
4685 }
4686 // </variable_suppression stuff>
4687 
4688 // <file_suppression stuff>
4689 
4690 /// Constructor for the the @ref file_suppression type.
4691 ///
4692 /// @param label the label of the suppression directive.
4693 ///
4694 /// @param fname_regex_str the regular expression string that
4695 /// designates the file name that instances of @ref file_suppression
4696 /// should match.
4697 ///
4698 /// @param fname_not_regex_str the regular expression string that
4699 /// designates the file name that instances of @ref file_suppression
4700 /// shoult *NOT* match. In other words, this file_suppression should
4701 /// be activated if its file name does not match the regular
4702 /// expression @p fname_not_regex_str.
4703 file_suppression::file_suppression(const string& label,
4704  const string& fname_regex_str,
4705  const string& fname_not_regex_str)
4706  : suppression_base(label,
4707  fname_regex_str,
4708  fname_not_regex_str)
4709 {}
4710 
4711 /// Test if instances of this @ref file_suppression suppresses a
4712 /// certain instance of @ref diff.
4713 ///
4714 /// This function always returns false because, obviously, a
4715 /// file_suppression is meants to prevents Abigail tools from loading
4716 /// some files. It is not meant to act on instance of @ref diff.
4717 /// @return false.
4718 bool
4720 {return false;}
4721 
4722 /// Test if a instances of this @ref file_suppression suppresses a
4723 /// given file.
4724 ///
4725 /// @param file_path the file path to test against.
4726 ///
4727 /// @return true iff this file_suppression matches the file path @p
4728 /// file_path.
4729 bool
4730 file_suppression::suppresses_file(const string& file_path)
4731 {
4732  if (file_path.empty())
4733  return false;
4734 
4735  string fname;
4736  tools_utils::base_name(file_path, fname);
4737 
4738  bool has_regexp = false;
4739 
4740  if (regex_t_sptr regexp = suppression_base::priv_->get_file_name_regex())
4741  {
4742  has_regexp = true;
4743  if (!regex::match(regexp, fname))
4744  return false;
4745  }
4746 
4747  if (regex_t_sptr regexp = suppression_base::priv_->get_file_name_not_regex())
4748  {
4749  has_regexp = true;
4750  if (regex::match(regexp, fname))
4751  return false;
4752  }
4753 
4754  if (!has_regexp)
4755  return false;
4756 
4757  return true;
4758 }
4759 
4760 /// Destructor of @ref file_suppression.
4762 {
4763 }
4764 
4765 /// Read a file suppression from an instance of ini::config::section
4766 /// and build a @ref type_suppression as a result.
4767 ///
4768 /// @param section the section (from an ini file) to read the file
4769 /// suppression from.
4770 ///
4771 /// @return file_suppression_sptr.
4772 static file_suppression_sptr
4773 read_file_suppression(const ini::config::section& section)
4774 {
4775  file_suppression_sptr result;
4776 
4777  if (section.get_name() != "suppress_file")
4778  return result;
4779 
4780  static const char *const sufficient_props[] = {
4781  "file_name_regexp",
4782  "file_name_not_regexp",
4783  "soname_regexp",
4784  "soname_not_regexp",
4785  };
4786  if (!check_sufficient_props(sufficient_props,
4787  sizeof(sufficient_props)/sizeof(char*),
4788  section))
4789  return result;
4790 
4791  ini::simple_property_sptr label_prop =
4792  is_simple_property(section.find_property("label"));
4793  string label_str = (label_prop
4794  ? label_prop->get_value()->as_string()
4795  : "");
4796 
4797  ini::simple_property_sptr file_name_regex_prop =
4798  is_simple_property(section.find_property("file_name_regexp"));
4799  string file_name_regex_str =
4800  file_name_regex_prop ? file_name_regex_prop->get_value()->as_string() : "";
4801 
4802  ini::simple_property_sptr file_name_not_regex_prop =
4803  is_simple_property(section.find_property("file_name_not_regexp"));
4804  string file_name_not_regex_str =
4805  file_name_not_regex_prop
4806  ? file_name_not_regex_prop->get_value()->as_string()
4807  : "";
4808 
4809  ini::simple_property_sptr soname_regex_prop =
4810  is_simple_property(section.find_property("soname_regexp"));
4811  string soname_regex_str =
4812  soname_regex_prop ? soname_regex_prop->get_value()->as_string() : "";
4813 
4814  ini::simple_property_sptr soname_not_regex_prop =
4815  is_simple_property(section.find_property("soname_not_regexp"));
4816  string soname_not_regex_str =
4817  soname_not_regex_prop
4818  ? soname_not_regex_prop->get_value()->as_string()
4819  : "";
4820 
4821  result.reset(new file_suppression(label_str,
4822  file_name_regex_str,
4823  file_name_not_regex_str));
4824 
4825  if (!soname_regex_str.empty())
4826  {
4827  result->set_soname_regex_str(soname_regex_str);
4828  result->set_drops_artifact_from_ir(true);
4829  }
4830 
4831  if (!soname_not_regex_str.empty())
4832  {
4833  result->set_soname_not_regex_str(soname_not_regex_str);
4834  result->set_drops_artifact_from_ir(true);
4835  }
4836 
4837  return result;
4838 }
4839 
4840 /// Test if a given suppression specification is a file suppression
4841 /// specification.
4842 ///
4843 /// @param s the instance of @ref suppression_base to test.
4844 ///
4845 /// @return the instance of @ref file_suppression that @p s points to,
4846 /// iff s is an instance of @ref file_suppression. Otherwise, returns
4847 /// nil.
4850 {return dynamic_pointer_cast<file_suppression>(s);}
4851 
4852 /// Test if a given file path is "suppressed" by at least one file
4853 /// suppression specification among a vector of suppression
4854 /// specifications.
4855 ///
4856 /// @param file_path the file path to test.
4857 ///
4858 /// @param sprs the vector of suppressions to use to test if one of
4859 /// them at lease matches the file path @p file_path.
4860 ///
4861 /// @return a pointer to the first instance of @ref file_suppression
4862 /// that matches @p file_path, or nil if no file suppression matches.
4864 file_is_suppressed(const string& file_path,
4865  const suppressions_type& sprs)
4866 {
4867  for (suppressions_type::const_iterator i = sprs.begin(); i != sprs.end(); ++i)
4869  if (s->suppresses_file(file_path))
4870  return s;
4871 
4872  return file_suppression_sptr();
4873 }
4874 
4875 /// Test if a given SONAME is matched by a given suppression
4876 /// specification.
4877 ///
4878 /// @param soname the SONAME to consider.
4879 ///
4880 /// @param suppr the suppression specification to consider.
4881 ///
4882 /// @return true iff a given SONAME is matched by a given suppression
4883 /// specification.
4884 bool
4885 suppression_matches_soname(const string& soname,
4886  const suppression_base& suppr)
4887 {
4888  return suppr.priv_->matches_soname(soname);
4889 }
4890 
4891 /// Test if a given SONAME or file name is matched by a given
4892 /// suppression specification.
4893 ///
4894 /// @param soname the SONAME to consider.
4895 ///
4896 /// @param filename the file name to consider.
4897 ///
4898 /// @param suppr the suppression specification to consider.
4899 ///
4900 /// @return true iff either @p soname or @p filename is matched by the
4901 /// suppression specification @p suppr.
4902 bool
4904  const string& filename,
4905  const suppression_base& suppr)
4906 {
4907  return (suppression_matches_soname(soname, suppr)
4908  || suppr.priv_->matches_binary_name(filename));
4909 }
4910 
4911 /// @return the name of the artificial private type suppression
4912 /// specification that is auto-generated by libabigail to suppress
4913 /// change reports about types that are not defined in public headers.
4914 const char*
4916 {
4917  static const char *OPAQUE_TYPES_SUPPR_SPEC_NAME =
4918  "libabigail::OPAQUE_TYPE_LABEL";
4919 
4920  return OPAQUE_TYPES_SUPPR_SPEC_NAME;
4921 }
4922 
4923 /// Test if a type suppression specification represents a private type
4924 /// suppression automatically generated by libabigail from the user
4925 /// telling us where public headers are.
4926 ///
4927 /// @param s the suppression specification we are looking at.
4928 ///
4929 /// @return true iff @p s is a private type suppr spec.
4930 bool
4933 
4934 /// Test if a type suppression specification represents a private type
4935 /// suppression automatically generated by libabigail from the user
4936 /// telling us where public headers are.
4937 ///
4938 /// @param s the suppression specification we are looking at.
4939 ///
4940 /// @return true iff @p s is a private type suppr spec.
4941 bool
4943 {
4945  return (type_suppr
4946  && type_suppr->get_label() == get_opaque_types_suppr_spec_label());
4947 }
4948 // </file_suppression stuff>
4949 
4950 /// Test if a given suppression specification can match an ABI
4951 /// artifact coming from the corpus being analyzed by a given
4952 /// front-end interface.
4953 ///
4954 /// @param fe the front-end to consider.
4955 ///
4956 /// @param s the suppression speficication to consider.
4957 ///
4958 /// @return true if the suppression specification @p s CAN patch ABI
4959 /// artifacts coming from the ABI corpus being analyzed by the
4960 /// front-end @p fe.
4961 bool
4963  const suppression_base& s)
4964 {
4965  if (!s.priv_->matches_soname(fe.dt_soname()))
4967  // The suppression has some SONAME related properties, but
4968  // none of them match the SONAME of the current binary. So
4969  // the suppression cannot match the current binary.
4970  return false;
4971 
4972  if (!s.priv_->matches_binary_name(fe.corpus_path()))
4974  // The suppression has some file_name related properties, but
4975  // none of them match the file name of the current binary. So
4976  // the suppression cannot match the current binary.
4977  return false;
4978 
4979  return true;
4980 }
4981 
4982 /// Test if a given function is suppressed by a suppression
4983 /// specification.
4984 ///
4985 /// @param fe the front-end to consider.
4986 ///
4987 /// @param s the suppression specification to consider.
4988 ///
4989 /// @param fn_name the name of the function to consider.
4990 ///
4991 /// @return true iff the suppression specification @p s matches the
4992 /// function which name is @p fn_name.
4993 bool
4994 suppression_matches_function_name(const fe_iface& fe,
4995  const suppr::function_suppression& s,
4996  const string& fn_name)
4997 {
4998  if (!suppression_can_match(fe, s))
4999  return false;
5000 
5001  if (regex::regex_t_sptr regexp = s.priv_->get_name_regex())
5002  {
5003  if (!regex::match(regexp, fn_name))
5004  return false;
5005  }
5006  else if (regex::regex_t_sptr regexp = s.priv_->get_name_not_regex())
5007  {
5008  if (regex::match(regexp, fn_name))
5009  return false;
5010  }
5011  else if (s.priv_->name_.empty())
5012  return false;
5013  else // if (!s.priv_->name_.empty())
5014  {
5015  if (s.priv_->name_ != fn_name)
5016  return false;
5017  }
5018 
5019  return true;
5020 }
5021 
5022 /// Test if a given function is suppressed by a suppression
5023 /// specification.
5024 ///
5025 /// @param fe the front-end to consider.
5026 ///
5027 /// @param s the suppression specification to consider.
5028 ///
5029 /// @param fn_linkage_name the linkage name of the function to
5030 /// consider.
5031 ///
5032 /// @return true iff the suppression specification @p s matches the
5033 /// function which linkage name is @p fn_linkage_name.
5034 bool
5035 suppression_matches_function_sym_name(const fe_iface& fe,
5036  const suppr::function_suppression& s,
5037  const string& fn_linkage_name)
5038 {
5039  if (!suppression_can_match(fe, s))
5040  return false;
5041 
5042  if (regex::regex_t_sptr regexp = s.priv_->get_symbol_name_regex())
5043  {
5044  if (!regex::match(regexp, fn_linkage_name))
5045  return false;
5046  }
5047  else if (regex::regex_t_sptr regexp = s.priv_->get_symbol_name_not_regex())
5048  {
5049  if (regex::match(regexp, fn_linkage_name))
5050  return false;
5051  }
5052  else if (s.priv_->symbol_name_.empty())
5053  return false;
5054  else // if (!s.priv_->symbol_name_.empty())
5055  {
5056  if (s.priv_->symbol_name_ != fn_linkage_name)
5057  return false;
5058  }
5059 
5060  return true;
5061 }
5062 
5063 /// Test if a suppression specification matches a variable of a given
5064 /// name, in the context of a given front-end.
5065 ///
5066 /// @param fe the front-end to consider.
5067 ///
5068 /// @param s the variable suppression specification to consider.
5069 ///
5070 /// @param var_name the name of the variable to consider.
5071 ///
5072 /// @return true iff the suppression specification @p s matches the
5073 /// variable which name is @p var_name.
5074 bool
5076  const suppr::variable_suppression& s,
5077  const string& var_name)
5078 {
5079  if (!suppression_can_match(fe, s))
5080  return false;
5081 
5082  return suppression_matches_variable_name(s, var_name);
5083 }
5084 
5085 /// Test if a suppression specification matches a variable which ELF
5086 /// symbol has a given name, in the context of a given front-end.
5087 ///
5088 /// @param fe the front-end to consider.
5089 ///
5090 /// @param s the variable suppression specification to consider.
5091 ///
5092 /// @param var_linkage_name the name of the ELF symbol of the variable
5093 /// to consider.
5094 ///
5095 /// @return true iff the suppression specification @p s matches the
5096 /// variable which ELF symbol name is @p var_linkage_name.
5097 bool
5099  const suppr::variable_suppression& s,
5100  const string& var_linkage_name)
5101 {
5102  if (!suppression_can_match(fe, s))
5103  return false;
5104 
5105  return suppression_matches_variable_sym_name(s, var_linkage_name);
5106 }
5107 
5108 /// Test if a suppression specification matches a type designated by
5109 /// its name and source location, in the context of a given front-end.
5110 ///
5111 /// @param fe the front-end to consider.
5112 ///
5113 /// @param s the suppression specification to consider.
5114 ///
5115 /// @param type_name the name of the type to consider.
5116 ///
5117 /// @param type_location the source location of the type designated by
5118 /// @p type_name.
5119 ///
5120 /// @return true iff the suppression @p s matches the type designated
5121 /// by @p type_name at source location @type_location.
5122 bool
5124  const suppr::type_suppression& s,
5125  const string& type_name,
5126  const location& type_location)
5127 {
5128  if (!suppression_can_match(fe, s))
5129  return false;
5130 
5131  return suppression_matches_type_name_or_location(s, type_name,
5132  type_location);
5133 }
5134 
5135 /// Test if an ELF symbol is suppressed by at least one of the
5136 /// suppression specifications associated with a given front-end.
5137 ///
5138 /// The function looks for each suppression specification provided to
5139 /// a given libabigail front-end and analyzes them to see if they
5140 /// match a given ELF symbol.
5141 ///
5142 /// @param fe the front-end to consider.
5143 ///
5144 /// @param symbol the ELF symbol to consider.
5145 ///
5146 /// @return true iff the symbol @p symbol is matched by at least a
5147 /// suppression specification associated with the front-end @p fe.
5148 bool
5150  const elf_symbol_sptr& symbol)
5151 {
5152  if (elf_symbol_is_function(symbol->get_type()))
5153  return is_function_suppressed(fe, /*fn_name=*/"",
5154  /*symbol_name=*/symbol->get_name());
5155  else if (elf_symbol_is_variable(symbol->get_type()))
5156  return is_variable_suppressed(fe, /*var_name=*/"",
5157  /*symbol_name=*/symbol->get_name());
5158  return false;
5159 }
5160 
5161 /// Test if an ELF symbol is suppressed by at least one of the
5162 /// suppression specifications associated with a given front-end.
5163 ///
5164 /// The function looks for each suppression specification provided to
5165 /// a given libabigail front-end and analyzes them to see if they
5166 /// match a given ELF symbol, designated by its name and kind.
5167 ///
5168 /// @param fe the front-end to consider.
5169 ///
5170 /// @param sym_name the name of the symbol to consider.
5171 ///
5172 /// @return true iff the symbol denoted by @p sym_name, of kind @p
5173 /// sym_type, is matched by at least a suppression specification
5174 /// associated with the front-end @p fe.
5175 bool
5177  const string& sym_name,
5178  elf_symbol::type sym_type)
5179 {
5180  if (elf_symbol_is_function(sym_type))
5181  return is_function_suppressed(fe, /*fn_name=*/"",
5182  /*symbol_name=*/sym_name);
5183  else if (elf_symbol_is_variable(sym_type))
5184  return is_variable_suppressed(fe, /*var_name=*/"",
5185  /*symbol_name=*/sym_name);
5186  return false;
5187 }
5188 
5189 /// Test if a function is matched by at least one suppression
5190 /// specification associated with a given front-end.
5191 ///
5192 /// The function is designated by its name and its linkage_name.
5193 ///
5194 /// @param fe the front-end to consider.
5195 ///
5196 /// @param fn_name the name of the function to consider.
5197 ///
5198 /// @param fn_linkage_name the linkage name of the function to
5199 /// consider.
5200 ///
5201 /// @param require_drop_property if true, this function requires the
5202 /// suppression specification to contain the "drop" property to match
5203 /// the function.
5204 ///
5205 /// @return true iff the function is matched by at least one
5206 /// suppression specification coming from the front-end.
5207 bool
5209  const string& fn_name,
5210  const string& fn_linkage_name,
5211  bool require_drop_property)
5212 {
5213  for (auto i : fe.suppressions())
5215  {
5216  if (require_drop_property && !i->get_drops_artifact_from_ir())
5217  continue;
5218  if (!fn_name.empty()
5219  && suppression_matches_function_name(fe, *suppr, fn_name))
5220  return true;
5221  if (!fn_linkage_name.empty()
5222  && suppression_matches_function_sym_name(fe, *suppr,
5223  fn_linkage_name))
5224  return true;
5225  }
5226  return false;
5227 }
5228 
5229 /// Test if a variable is matched by at least one suppression
5230 /// specification associated with a given front-end.
5231 ///
5232 /// The variable is designated by its name and its linkage_name.
5233 ///
5234 /// @param fe the front-end to consider.
5235 ///
5236 /// @param var_name the name of the variable to consider.
5237 ///
5238 /// @param var_linkage_name the linkage name of the variable to
5239 /// consider.
5240 ///
5241 /// @param require_drop_property if true, this variable requires the
5242 /// suppression specification to contain the "drop" property to match
5243 /// the function.
5244 ///
5245 /// @return true iff the variable is matched by at least one
5246 /// suppression specification coming from the front-end.
5247 bool
5249  const string& var_name,
5250  const string& var_linkage_name,
5251  bool require_drop_property)
5252 {
5253  for (auto i : fe.suppressions())
5255  {
5256  if (require_drop_property && !i->get_drops_artifact_from_ir())
5257  continue;
5258  if (!var_name.empty()
5259  && suppression_matches_variable_name(fe, *suppr, var_name))
5260  return true;
5261  if (!var_linkage_name.empty()
5263  var_linkage_name))
5264  return true;
5265  }
5266  return false;
5267 }
5268 
5269 /// Test if a type is matched by at least one suppression
5270 /// specification associated with a given front-end.
5271 ///
5272 /// The type is designated by its name and its source location.
5273 ///
5274 /// @param fe the front-end to consider.
5275 ///
5276 /// @param type_name the name of the type to consider.
5277 ///
5278 /// @param type_location the source location of the type.
5279 ///
5280 /// @param type_is_opaque output parameter. This is set to true if
5281 /// the type was matched by one suppression specification, and if the
5282 /// suppression was for opaque types.
5283 ///
5284 /// @param require_drop_property if true, this type requires the
5285 /// suppression specification to contain the "drop" property to match
5286 /// the type.
5287 ///
5288 /// @return true iff the type is matched by at least one suppression
5289 /// specification coming from the front-end.
5290 bool
5292  const string& type_name,
5293  const location& type_location,
5294  bool& type_is_opaque,
5295  bool require_drop_property)
5296 {
5297  for (auto i : fe.suppressions())
5299  {
5300  if (require_drop_property && !i->get_drops_artifact_from_ir())
5301  continue;
5303  type_name,
5304  type_location))
5305  {
5306  if (is_opaque_type_suppr_spec(*suppr))
5307  type_is_opaque = true;
5308 
5309  return true;
5310  }
5311  }
5312 
5313  type_is_opaque = false;
5314  return false;
5315 }
5316 
5317 /// Test if a data memer offset is in a given insertion range.
5318 ///
5319 /// @param dm the data member to consider.
5320 ///
5321 /// @param range the insertion range to consider.
5322 ///
5323 /// @param the class (or union) type to consider as the context in
5324 /// which to evaluate the insertion range denoted by @p range.
5325 ///
5326 /// @return true iff the offset of the data member @p dm is in the
5327 /// insertion range @p range in the context of the type denoted by @p
5328 /// context.
5329 bool
5332  const class_or_union* context)
5333 {
5334  ABG_ASSERT(dm && range && context);
5335 
5336  uint64_t range_begin = 0, range_end = 0;
5338  context,
5339  range_begin))
5340  return false;
5341 
5343  context,
5344  range_end))
5345  return false;
5346 
5347  if (range_begin > range_end)
5348  // wrong range, ignore it.
5349  return false;
5350 
5351  uint64_t dm_offset = get_data_member_offset(dm);
5354  {
5355  // This idiom represents the predicate
5356  // "has_data_member_inserted_at = end"
5357  if (dm_offset > get_data_member_offset(get_last_data_member(context)))
5358  return true;
5359  return false;
5360  }
5361 
5362  if (dm_offset < range_begin || dm_offset > range_end)
5363  // The offset of the data member is outside the range.
5364  return false;
5365 
5366  return true;
5367 }
5368 
5369 }// end namespace suppr
5370 } // end namespace abigail
bool is_elf_symbol_suppressed(const fe_iface &fe, const elf_symbol_sptr &symbol)
Test if an ELF symbol is suppressed by at least one of the suppression specifications associated with...
shared_ptr< negated_suppression_base > negated_suppression_sptr
A convenience typedef for a shared pointer to negated_suppression_base.
void set_type_kind(type_kind k)
Setter of the kind of type this suppression is about.
const string_decl_base_sptr_map & inserted_data_members() const
Getter for the data members that got inserted.
const string & get_name_not_regex_str() const
Getter for the "name_not_regexp" property of the specification.
bool is_type(const type_or_decl_base &tod)
Test whether a declaration is a type.
Definition: abg-ir.cc:10807
type_kind
The kind of the type the current type suppression is supposed to be about.
const string & get_name_not_regex_str() const
Getter for a regular expression of a family of names of functions the user wants the current specific...
const vector< string > & get_changed_enumerator_names() const
Getter of the vector of the changed enumerators that are supposed to be suppressed. Note that this will be "valid" only if the type suppression has the 'type_kind = enum' property.
suppr::suppressions_type & suppressions()
Getter of the vector of suppression specifications associated with the current front-end.
const string & get_parameter_type_name_regex_str() const
Getter for the regular expression that defines a set of type names for the parameter designated by th...
void set_name_not_regex_str(const string &)
Setter for a regular expression for a family of names of functions the user wants the current specifi...
const string_property_value_sptr & get_value() const
Getter for the string value of the property.
Definition: abg-ini.cc:586
void set_consider_type_kind(bool f)
Setter of the property that says whether to consider the kind of type this suppression is about...
type_suppression_sptr is_type_suppression(suppression_sptr suppr)
Test if an instance of suppression is an instance of type_suppression.
bool suppression_can_match(const fe_iface &fe, const suppression_base &s)
Test if a given suppression specification can match an ABI artifact coming from the corpus being anal...
function_suppression_sptr is_function_suppression(const suppression_sptr suppr)
Test if an instance of suppression is an instance of function_suppression.
An insertion_range boundary that is expressed as function call expression. The (integer) value of tha...
const string & get_type_name_not_regex_str() const
Getter for the "type_name_not_regex_str" property of the type suppression specification.
This header declares filters for the diff trees resulting from comparing ABI Corpora.
The abstraction of a change between two ABI artifacts, a.k.a an artifact change.
const pointer_diff * is_pointer_diff(const diff *diff)
Test if a diff node is about differences between two pointers.
void set_name(const string &)
Setter for the name of the function the user wants the current specification to designate. This might be empty, in which case it's ignored at evaluation time.
bool suppresses_variable_symbol(const elf_symbol *sym, change_kind k, const diff_context_sptr cxt) const
Evaluate the current variable suppression specification on a given elf_symbol and say if a report abo...
const string & get_file_name_regex_str() const
Getter for the "file_name_regex" property of the current instance of suppression_base.
static insertion_range::fn_call_expr_boundary_sptr create_fn_call_expr_boundary(ini::function_call_expr_sptr)
Create a function call expression boundary.
void set_return_type_regex_str(const string &r)
Setter for a regular expression for a family of return type names for functions the user wants the cu...
class_decl_sptr second_class_decl() const
Getter of the second class involved in the diff.
bool variable_is_suppressed(const suppr::suppressions_type &supprs, const string &var_name, const string &var_linkage_name, bool require_drop_property)
Test if a given variable is suppressed by at least one suppression specification among a vector of su...
const function_decl_sptr first_function_decl() const
const string & str() const
Getter for the version name.
Definition: abg-ir.cc:3205
insertion_range()
Default Constructor of type_suppression::insertion_range.
const type_decl * is_type_decl(const type_or_decl_base *t)
Test whether a type is a type_decl (a builtin type).
Definition: abg-ir.cc:10909
bool read_config(istream &input, config &conf)
Parse an ini config file from an input stream.
Definition: abg-ini.cc:1747
An insertion_range boundary that is expressed as a named constant that is to be evaluated later in th...
string build_qualified_name(const scope_decl *scope, const string &name)
Build and return a qualified name from a name and its scope.
Definition: abg-ir.cc:8732
bool suppression_matches_type_location(const type_suppression &s, const location &loc)
Test if a type suppression matches a source location.
bool is_variable() const
Test if the current instance of elf_symbol is a variable symbol or not.
Definition: abg-ir.cc:2299
The type diff has been reached (from a function or variable change) through a reference; you know...
shared_ptr< string_property_value > string_property_value_sptr
A convenience typedef for a shared_ptr to string_property_value.
Definition: abg-ini.h:94
This file contains the declarations for the fe_iface a.k.a "Front End Interface". ...
shared_ptr< list_property_value > list_property_value_sptr
A convenience typedef for a shared_ptr to list_property_value.
Definition: abg-ini.h:126
The base class of all libabigail front-ends: The Front End Interface.
Definition: abg-fe-iface.h:28
void set_consider_reach_kind(bool f)
Set a flag saying if the current type suppression specification suggests to consider how the matching...
shared_ptr< suppression_base > suppression_sptr
Convenience typedef for a shared pointer to a suppression.
Definition: abg-fwd.h:1681
static insertion_range::named_boundary_sptr create_named_boundary(const string &)
Create a named boundary.
bool is_class_type(const type_or_decl_base &t)
Test whether a type is a class.
Definition: abg-ir.cc:11165
Abstraction of a suppression specification to avoid loading a file.
The type diff has been reached (from a function or variable change) through a pointer.
shared_ptr< function_type > function_type_sptr
Convenience typedef for a shared pointer on a function_type.
Definition: abg-fwd.h:208
change_kind get_change_kind() const
Getter of the "change_king" property.
regex_t_sptr compile(const std::string &str)
Compile a regex from a string.
Definition: abg-regex.cc:111
The type of the private data of the function_suppression type.
bool suppression_matches_type_name(const suppr::type_suppression &s, const string &type_name)
Test if a type suppression specification matches a type name.
This file contains the declarations for the ini file reader used in the libabigail library...
size_t get_index() const
Getter for the index of the parameter designated by this specification.
void set_name(const string &)
Setter for the name of the variable the user wants the current specification to designate. This property might be empty, in which case it's ignored at evaluation time.
virtual ~file_suppression()
Destructor of file_suppression.
void set_symbol_name(const string &)
Setter for the name of the symbol of the variable the user wants the current specification to designa...
type_suppression::insertion_range::fn_call_expr_boundary_sptr is_fn_call_expr_boundary(type_suppression::insertion_range::boundary_sptr b)
Tests if a given instance of type_suppression::insertion_range::boundary is actually a function call ...
const function_type_sptr get_type() const
Return the type of the current instance of function_decl.
Definition: abg-ir.cc:22974
A declaration that introduces a scope.
Definition: abg-ir.h:1852
bool is_negated_suppression(const suppression_base &s)
Test if a suppression specification is a negated suppression.
void set_has_strict_fam_conversion(bool)
Setter of the "has_string_fam_conversion" property.
This type abstracts changes for a class_decl.
The type diff has been reached (from a function or variable change) through either a reference or a p...
const string & get_name_regex_str() const
Getter for the regular expression for a family of names of variables the user wants the current speci...
static change_kind parse_change_kind(const string &)
Parses a string containing the content of the "change-kind" property and returns the an instance of v...
type_or_decl_base_sptr first_subject() const
Getter of the first subject of the diff.
negated_type_suppression(const string &label, const string &type_name_regexp, const string &type_name)
Constructor for negated_type_suppression.
const elf_symbol_sptr & get_symbol() const
Gets the the underlying ELF symbol for the current variable, that was set using function_decl::set_sy...
Definition: abg-ir.cc:23027
shared_ptr< function_call_expr > function_call_expr_sptr
Convenience typedef for a shared pointer to function_call_expr.
Definition: abg-ini.h:427
bool has_file_name_related_property() const
Test if the current suppression has a property related to file name.
void set_is_artificial(bool)
Set a flag saying if the suppression specification is artificial or not.
const string & get_soname_not_regex_str() const
Getter of the "soname_not_regex_str property of the current instance of suppression_base.
shared_ptr< diff_context > diff_context_sptr
Convenience typedef for a shared pointer of diff_context.
Definition: abg-fwd.h:67
const corpus_diff_sptr & get_corpus_diff() const
Get the corpus diff for the current context.
bool get_drops_artifact_from_ir() const
Tests if the current suppression specification is to avoid adding the matched ABI artifact to the int...
static bool eval_boundary(const boundary_sptr boundary, const class_or_union *context, uint64_t &value)
Evaluate an insertion range boundary to get a resulting integer value.
const var_diff * is_var_diff(const diff *diff)
Test if a diff node is about differences between variables.
void set_source_location_to_keep_regex_str(const string &)
Setter of the regular expression string that designates the source location paths of types that shoul...
bool suppression_matches_type(const suppr::type_suppression &s, const string &type_name)
Test if a type suppression matches a type designated by its fully qualified name. ...
const string & get_symbol_name() const
Getter for the name of symbol of the function the user wants this specification to designate...
The variable was deleted from the second subject of the diff.
shared_ptr< var_decl > var_decl_sptr
Convenience typedef for a shared pointer on a var_decl.
Definition: abg-fwd.h:253
class_or_union_sptr first_class_or_union() const
The private data for type_suppression.
const string_enumerator_map & deleted_enumerators() const
const vector< regex::regex_t_sptr > & get_changed_enumerators_regexp() const
Getter of the vector of the regular expression strings for changed enumerators that are supposed to b...
void set_soname_not_regex_str(const string &regexp)
Setter of the "soname_not_regex_str property of the current instance of suppression_base.
shared_ptr< property > property_sptr
Convenience typefef for shared_ptr to property.
Definition: abg-ini.h:34
shared_ptr< file_suppression > file_suppression_sptr
A convenience typedef for a shared_ptr to file_suppression.
simple_property * is_simple_property(const property *p)
Tests if a property is a simple property.
Definition: abg-ini.cc:619
bool get_is_artificial() const
Test is the suppression specification is artificial.
file_suppression_sptr is_file_suppression(const suppression_sptr s)
Test if a given suppression specification is a file suppression specification.
bool get_allow_other_aliases() const
Getter for the "allow_other_aliases" property of the function suppression specification.
const string & get_name_regex_str() const
Getter for a regular expression for a family of names of functions the user wants the current specifi...
virtual ~boundary()
Destructor of type_suppression::insertion_range::boundary.
tuple_property * is_tuple_property(const property *p)
Test if an instance of property is an instance of tuple_property.
Definition: abg-ini.cc:757
Abstraction of a diff between two function_decl.
const string & get_type_name_regex_str() const
Getter for the "type_name_regex" property of the type suppression specification.
const string & get_name() const
Getter for the name of the elf_symbol.
Definition: abg-ir.cc:2159
bool suppression_matches_type_name_or_location(const type_suppression &s, const string &type_name, const location &type_location)
Test if a type suppression matches a type name and location.
void set_change_kind(change_kind k)
Setter of the "change_kind" property.
The abstraction of the boundary of an insertion_range, in the context of a type_suppression.
const enum_type_decl_sptr first_enum() const
void set_type_name(const string &name)
Setter for the name of the type about which diff reports should be suppressed.
const elf_symbol_sptr & get_symbol() const
Gets the the underlying ELF symbol for the current variable, that was set using var_decl::set_symbol(...
Definition: abg-ir.cc:21482
static insertion_range::integer_boundary_sptr create_integer_boundary(int value)
Create an integer boundary.
const string & get_symbol_version_regex_str() const
Getter of the regular expression for a family of versions of symbol for the variables the user wants ...
virtual bool suppresses_diff(const diff *diff) const
Evaluate this suppression specification on a given diff node and say if the diff node should be suppr...
void set_symbol_version(const string &)
Setter for the name of the version of the symbol of the function the user wants this specification to...
shared_ptr< type_suppression > type_suppression_sptr
Convenience typedef for a shared pointer to type_suppression.
void set_index(size_t)
Setter for the index of the parameter designated by this specification.
Abstraction of a diff between two enums.
bool suppression_matches_variable_name(const suppr::variable_suppression &s, const string &var_name)
Test if a variable suppression matches a variable denoted by its name.
Abstracts a variable declaration.
Definition: abg-ir.h:3067
bool is_data_member_offset_in_range(const var_decl_sptr &dm, const type_suppression::insertion_range_sptr &range, const class_or_union *context)
Test if a data memer offset is in a given insertion range.
virtual bool suppresses_diff(const diff *diff) const
Evaluate this suppression specification on a given diff node and say if the diff node should be suppr...
void set_symbol_version(const string &)
Setter for the version of the symbol of the variable the user wants the current specification to desi...
void set_return_type_name(const string &)
Setter for the name of the return type of the function the user wants this specification to designate...
The base class of diff between types.
bool is_variable_suppressed(const fe_iface &fe, const string &var_name, const string &var_linkage_name, bool require_drop_property)
Test if a variable is matched by at least one suppression specification associated with a given front...
static bool boundary_value_is_end(uint64_t value)
Test if a given value supposed to be inside an insertion range represents the end of the range...
const function_decl_sptr second_function_decl() const
bool suppresses_function_symbol(const elf_symbol *sym, change_kind k, const diff_context_sptr ctxt)
Evaluate the current function suppression specification on a given elf_symbol and say if a report abo...
bool elf_symbol_is_function(elf_symbol::type t)
Test if the type of an ELF symbol denotes a function symbol.
Definition: abg-ir.cc:3145
var_decl * is_var_decl(const type_or_decl_base *tod)
Tests if a declaration is a variable declaration.
Definition: abg-ir.cc:12059
This is the base class of class_diff and union_diff.
ini::function_call_expr_sptr as_function_call_expr() const
Returns the function call expression value of the current boundary.
const string & get_potential_data_member_names_regex_str() const
Getter of the "potential_data_member_names_regex" string.
void set_potential_data_member_names_regex_str(const string &) const
Setter of the "potential_data_member_names_regex" string.
bool suppresses_function(const function_decl *fn, change_kind k, const diff_context_sptr ctxt) const
Evaluate the current function suppression specification on a given function_decl and say if a report ...
const string & get_symbol_version() const
Getter for the name of the version of the symbol of the function the user wants this specification to...
void set_type_name_regex_str(const string &name_regex_str)
Setter for the "type_name_regex" property of the type suppression specification.
void expand(std::string &path, unsigned &line, unsigned &column) const
Expand the current location into a tripplet file path, line and column number.
Definition: abg-ir.cc:452
const string & get_symbol_name() const
Getter for the name of the symbol of the variable the user wants the current specification to designa...
typedef_decl_sptr is_typedef(const type_or_decl_base_sptr t)
Test whether a type is a typedef.
Definition: abg-ir.cc:11011
shared_ptr< insertion_range > insertion_range_sptr
A convenience typedef for a shared pointer to insertion_range.
uint64_t get_data_member_offset(const var_decl &m)
Get the offset of a data member.
Definition: abg-ir.cc:6184
bool has_strict_fam_conversion(const class_decl_sptr &first, const class_decl_sptr &second)
Test if a class with a fake flexible data member got changed into a class with a real fexible data me...
Toplevel namespace for libabigail.
The variable was added to the second second subject of the diff.
bool get_consider_reach_kind() const
Test if the current type suppression specification suggests to consider how the matching diff node is...
bool is_type_suppressed(const fe_iface &fe, const string &type_name, const location &type_location, bool &type_is_opaque, bool require_drop_property)
Test if a type is matched by at least one suppression specification associated with a given front-end...
const unordered_set< string > & get_source_locations_to_keep() const
Getter for the array of source location paths of types that should *NOT* be suppressed.
change_kind get_change_kind() const
Getter of the "change-kind" property.
const string & get_type_name_regex_str() const
Getter for the regular expression for a family of type names of variables the user wants the current ...
shared_ptr< function_decl > function_decl_sptr
Convenience typedef for a shared pointer on a function_decl.
Definition: abg-fwd.h:266
decl_base * is_decl(const type_or_decl_base *d)
Test if an ABI artifact is a declaration.
Definition: abg-ir.cc:10747
The type of the private data of the variable_suppression type.
bool elf_symbol_is_variable(elf_symbol::type t)
Test if the type of an ELF symbol denotes a function symbol.
Definition: abg-ir.cc:3155
const enum_type_decl * is_enum_type(const type_or_decl_base *d)
Test if a decl is an enum_type_decl.
Definition: abg-ir.cc:11100
boundary_sptr begin() const
Getter for the beginning of the range.
reach_kind
The different ways through which the type diff has been reached.
virtual const interned_string & get_qualified_name(bool internal=false) const
Get the qualified name of a given variable or data member.
Definition: abg-ir.cc:21740
shared_ptr< config > config_sptr
A convenience typedef for a shared pointer to config.
Definition: abg-ini.h:313
const string & get_symbol_name_not_regex_str() const
Getter for a regular expression for a family of names of symbols of functions the user wants this spe...
type_suppression::insertion_range::named_boundary_sptr is_named_boundary(type_suppression::insertion_range::boundary_sptr b)
Test if a given instance of type_suppression::insertion_range::boundary is actually a named boundary...
bool suppression_matches_variable_sym_name(const suppr::variable_suppression &s, const string &var_linkage_name)
Test if a variable suppression matches a variable denoted by its symbol name.
void set_symbol_version_regex_str(const string &)
Setter for a regular expression for a family of versions of symbols of functions the user wants the c...
shared_ptr< parameter > parameter_sptr
Convenience typedef for a shared pointer on a function_decl::parameter.
Definition: abg-ir.h:3183
const string & get_symbol_name_not_regex_str() const
Getter for a regular expression for a family of names of symbols of variables the user wants this spe...
The type diff has been reached (from a function or variable change) directly.
tuple_property_value * is_tuple_property_value(const property_value *v)
Test if a given instance of property_value is an instance of tuple_property_value too...
Definition: abg-ini.cc:525
void set_source_locations_to_keep(const unordered_set< string > &)
Setter for the array of source location paths of types that should *NOT* be suppressed.
shared_ptr< simple_property > simple_property_sptr
Convenience typedef for a shared_ptr to an simple_property.
Definition: abg-ini.h:204
void set_changed_enumerator_names(const vector< string > &)
Setter of the vector of changed enumerators that are supposed to be suppressed. Note that this will b...
Abstraction for a function declaration.
Definition: abg-ir.h:3164
list_property * is_list_property(const property *p)
Test if an instance of a property is actually an instance of list_property.
Definition: abg-ini.cc:686
type_kind get_type_kind() const
Getter of the kind of type this suppression is about.
const string & get_return_type_name() const
Getter for the name of the return type of the function the user wants this specification to designate...
vector< insertion_range_sptr > insertion_ranges
A convenience typedef for a vector of insertion_range_sptr.
bool suppresses_type(const type_base_sptr &type, const diff_context_sptr &ctxt) const
Test if the current instance of type_suppression suppresses a change reports about a given type...
class_decl_sptr first_class_decl() const
The context of the diff. This type holds various bits of information that is going to be used through...
The base type of class_decl and union_decl.
Definition: abg-ir.h:3976
The abstraction of a diff between two references.
type
The type of a symbol.
Definition: abg-ir.h:964
const decl_base * get_type_declaration(const type_base *t)
Get the declaration for a given type.
Definition: abg-ir.cc:10229
The source location of a token.
Definition: abg-ir.h:306
void set_symbol_version_regex_str(const string &)
Setter of the regular expression for a family of versions of symbol for the variables the user wants ...
string_property_value * is_string_property_value(const property_value *v)
Test if a given property value is a string property value.
Definition: abg-ini.cc:341
location get_location(const type_base_sptr &type)
Get the location of the declaration of a given type.
Definition: abg-ir.cc:8766
const string & get_soname_regex_str() const
Getter of the "soname_regex_str property of the current instance of suppression_base.
~integer_boundary()
Destructor of type_suppression::insertion_range::integer_boundary.
boundary_sptr end() const
Getter for the end of the range.
The abstraction of a diff between two pointers.
Abstraction of an elf symbol.
Definition: abg-ir.h:960
bool get_next_data_member_offset(const class_or_union *klass, const var_decl_sptr &dm, uint64_t &offset)
Get the offset of the non-static data member that comes after a given one.
Definition: abg-ir.cc:6229
void set_symbol_name_not_regex_str(const string &)
Setter for a regular expression for a family of names of symbols of functions the user wants this spe...
void set_parameter_type_name(const string &)
Setter for the type name of the parameter designated by this specification.
The function was deleted from the second subject of the diff.
const function_decl_diff * is_function_decl_diff(const diff *diff)
Test if a diff node is about differences between functions.
shared_ptr< named_boundary > named_boundary_sptr
Convenience typedef for a shared_ptr to a named_boundary.
This contains the private implementation of the suppression engine of libabigail. ...
function_suppression::change_kind operator|(function_suppression::change_kind l, function_suppression::change_kind r)
The bitwise 'or' operator for the enum function_suppression::change_kind.
bool suppresses_diff(const diff *d) const
Evaluate this suppression specification on a given diff node and say if the diff node should be suppr...
boundary()
Default constructor of type_suppression::insertion_range::boundary.
void set_type_name(const string &)
Setter for the name of the type of the variable the user wants the current specification to designate...
shared_ptr< elf_symbol > elf_symbol_sptr
A convenience typedef for a shared pointer to elf_symbol.
Definition: abg-ir.h:924
std::shared_ptr< regex_t > regex_t_sptr
A convenience typedef for a shared pointer of regex_t.
Definition: abg-fwd.h:87
#define ABG_ASSERT(cond)
This is a wrapper around the 'assert' glibc call. It allows for its argument to have side effects...
Definition: abg-fwd.h:1743
function_suppression()
Default constructor for the function_suppression type.
virtual ~negated_type_suppression()
Destructor of the negated_type_suppression type.
bool is_opaque_type_suppr_spec(const type_suppression &s)
Test if a type suppression specification represents a private type suppression automatically generate...
Base type of a direct suppression specifications types.
virtual ~negated_suppression_base()
Destructor of the negated_suppression_base.
type_suppression::insertion_range::integer_boundary_sptr is_integer_boundary(type_suppression::insertion_range::boundary_sptr b)
Tests if a given instance of type_suppression::insertion_range::boundary is actually an integer bound...
bool get_data_member_is_laid_out(const var_decl &m)
Test whether a data member is laid out.
Definition: abg-ir.cc:6344
const diff * peel_qualified_diff(const diff *dif)
If a diff node is about changes between two qualified types, get the diff node about changes between ...
change_kind
The kind of change the current function suppression should apply to.
void set_allow_other_aliases(bool f)
Setter for the "allow_other_aliases" property of the function suppression specification.
const string & get_symbol_version() const
Getter for the version of the symbol of the variable the user wants the current specification to desi...
var_decl_sptr find_first_data_member_matching_regexp(const class_or_union &t, const regex::regex_t_sptr &r)
Find the first data member of a class or union which name matches a regular expression.
Definition: abg-ir.cc:29190
vector< suppression_sptr > suppressions_type
Convenience typedef for a vector of suppression_sptr.
Definition: abg-fwd.h:1687
variable_suppression_sptr is_variable_suppression(const suppression_sptr s)
Test if an instance of suppression is an instance of variable_suppression.
bool is_union_type(const type_or_decl_base &t)
Test if a type is a union_decl.
Definition: abg-ir.cc:11445
shared_ptr< parameter_spec > parameter_spec_sptr
Convenience typedef for shared_ptr of parameter_spec.
array_type_def * is_array_type(const type_or_decl_base *type, bool look_through_qualifiers)
Test if a type is an array_type_def.
Definition: abg-ir.cc:12123
const string & get_symbol_name_regex_str() const
Getter of the regular expression for a family of symbol names of the variables this specification is ...
void append_parameter_specs(const parameter_spec_sptr)
Append a specification of a parameter of the function specification.
var_decl_sptr find_last_data_member_matching_regexp(const class_or_union &t, const regex::regex_t_sptr &regex)
Find the last data member of a class or union which name matches a regular expression.
Definition: abg-ir.cc:29211
function_decl * is_function_decl(const type_or_decl_base *d)
Test whether a declaration is a function_decl.
Definition: abg-ir.cc:10695
const type_base_sptr get_type() const
Getter of the type of the variable.
Definition: abg-ir.cc:21419
void set_data_member_insertion_ranges(const insertion_ranges &r)
Setter for the vector of data member insertion ranges that specifies where a data member is inserted ...
void set_potential_data_member_names(const string_set_type &) const
Setter of the "potential_data_member_names" property.
bool suppression_matches_soname_or_filename(const string &soname, const string &filename, const suppression_base &suppr)
Test if a given SONAME or file name is matched by a given suppression specification.
virtual bool suppresses_diff(const diff *diff) const
Test if instances of this file_suppression suppresses a certain instance of diff. ...
bool read_function_call_expr(std::istream &input, function_call_expr_sptr &expr)
Read a function call expression and build its representation.
Definition: abg-ini.cc:2017
const string & get_file_name_not_regex_str() const
Getter for the "file_name_not_regex" property of the current instance of suppression_base.
static change_kind parse_change_kind(const string &)
Parses a string containing the content of the "change-kind" property and returns the an instance of f...
change_kind
The kind of change the current variable suppression should apply to.
shared_ptr< tuple_property_value > tuple_property_value_sptr
Convenience typedef for a shared_ptr to a tuple_property_value.
Definition: abg-ini.h:166
const string & get_name() const
Get the name of the section.
Definition: abg-ini.cc:812
virtual bool suppresses_diff(const diff *diff) const
Evaluate this suppression specification on a given diff node and say if the diff node should be suppr...
shared_ptr< tuple_property > tuple_property_sptr
Convenience typedef for a shared_ptr of tuple_property.
Definition: abg-ini.h:280
const string & get_type_name() const
Getter for the name of the type of the variable the user wants the current specification to designate...
vector< parameter_spec_sptr > parameter_specs_type
Convenience typedef for vector of parameter_spec_sptr.
bool suppresses_variable(const var_decl *var, change_kind k, const diff_context_sptr cxt) const
Evaluate the current variable suppression specification on a given var_decl and say if a report about...
The function was added to the second subject of the diff.
Abstraction of a type suppression specification.
shared_ptr< list_property > list_property_sptr
A convenience typedef for a shared_ptr to a list_property.
Definition: abg-ini.h:241
shared_ptr< fn_call_expr_boundary > fn_call_expr_boundary_sptr
Convenience typedef for a shared_ptr to a fn_call_expr_boundary.
void set_name_not_regex_str(const string &)
Setter for the "name_not_regexp" property of the specification.
file_suppression_sptr file_is_suppressed(const string &file_path, const suppressions_type &sprs)
Test if a given file path is "suppressed" by at least one file suppression specification among a vect...
void set_reach_kind(reach_kind k)
Setter of the way the diff node matching the current suppression specification is to be reached...
bool is_function() const
Test if the current instance of elf_symbol is a function symbol or not.
Definition: abg-ir.cc:2290
const string & get_type_name() const
Getter for the name of the type about which diff reports should be suppressed.
const string & get_name() const
Getter for the name of the named boundary.
virtual ~variable_suppression()
Virtual destructor for the variable_suppression type. variable_suppression type. ...
bool check_sufficient_props(const char *const *names, size_t count, const ini::config::section &section)
Check if a section has at least one of the given properties.
void set_symbol_name(const string &n)
Setter for the name of symbol of the function the user wants this specification to designate...
const parameter_specs_type & get_parameter_specs() const
Getter for a vector of parameter specifications to specify properties of the parameters of the functi...
void set_change_kind(change_kind k)
Setter of the "change-kind" property.
shared_ptr< class_decl > class_decl_sptr
Convenience typedef for a shared pointer on a class_decl.
Definition: abg-fwd.h:190
virtual void get_qualified_name(interned_string &qualified_name, bool internal=false) const
Compute the qualified name of the decl.
Definition: abg-ir.cc:4823
const string_changed_enumerator_map & changed_enumerators() const
const insertion_ranges & get_data_member_insertion_ranges() const
Getter for the vector of data member insertion range that specifiers where a data member is inserted ...
bool get_has_size_change() const
Getter of the "has_size_change" property.
bool suppression_matches_soname(const string &soname, const suppression_base &suppr)
Test if a given SONAME is matched by a given suppression specification.
const string get_label() const
Getter for the label associated to this suppression specification.
version & get_version() const
Getter for the version of the current instanc of elf_symbol.
Definition: abg-ir.cc:2218
void set_has_size_change(bool flag)
Setter of the "has_size_change" property.
string get_name(const type_or_decl_base *tod, bool qualified)
Build and return a copy of the name of an ABI artifact that is either a type or a decl...
Definition: abg-ir.cc:8686
void set_parameter_specs(parameter_specs_type &)
Setter for a vector of parameter specifications to specify properties of the parameters of the functi...
bool match(const regex_t_sptr &r, const std::string &str)
See if a string matches a regex.
Definition: abg-regex.cc:127
bool suppresses_file(const string &file_path)
Test if a instances of this file_suppression suppresses a given file.
bool has_strict_fam_conversion() const
Getter of the "has_string_fam_conversion" property.
This represents all the changes possibly described by this enum. It's a logical 'OR' of all the chang...
The private data of suppression_base.
void set_label(const string &)
Setter for the label associated to this suppression specification.
Abstraction of a function suppression specification.
Abstracts a diff between two instances of var_decl.
const std::string & corpus_path() const
Getter of the path to the file which an ABI corpus is to be created for.
shared_ptr< boundary > boundary_sptr
Convenience typedef for a shared_ptr to boundary.
list_property_value * is_list_property_value(const property_value *v)
Test if an instance of is a list_property_value.
Definition: abg-ini.cc:437
void set_drops_artifact_from_ir(bool)
Set the flag that says whether the current suppression specification is to avoid adding the matched A...
The abstraction of a variable suppression specification.
const string & get_source_location_to_keep_regex_str() const
Getter of the regular expression string that designates the source location paths of types that shoul...
property_sptr find_property(const string &prop_name) const
Find a property that has a given name.
Definition: abg-ini.cc:845
const class_or_union_diff * is_class_or_union_diff(const diff *d)
Test if a diff node is a class_or_union_diff node.
const string & get_return_type_regex_str() const
Getter for a regular expression for a family of return type names for functions the user wants the cu...
An insertion_range boundary that is expressed as an integer value. That integer value is usually a bi...
The abstraction of one section of the .ini config.
Definition: abg-ini.h:358
const reference_diff * is_reference_diff(const diff *diff)
Test if a diff node is about differences between two references.
void set_parameter_type_name_regex_str(const string &)
Setter for the regular expression that defines a set of type names for the parameter designated by th...
~fn_call_expr_boundary()
Destructor of type_suppression::insertion_range::fn_call_expr_boundary.
uint64_t as_integer() const
Return the integer value of the current instance of type_suppression::insertion_range::integer_bounda...
void set_type_name_regex_str(const string &)
Setter for the regular expression for a family of type names of variables the user wants the current ...
const diff * get_typedef_diff_underlying_type_diff(const diff *diff)
Return the leaf underlying diff node of a typedef_diff node.
const string & dt_soname() const
Getter for the SONAME of the analyzed binary.
variable_suppression(const string &label="", const string &name="", const string &name_regex_str="", const string &symbol_name="", const string &symbol_name_regex_str="", const string &symbol_version="", const string &symbol_version_regex_str="", const string &type_name="", const string &type_name_regex_str="")
Constructor for the variable_suppression type.
const type_diff_base * is_type_diff(const diff *diff)
Test if a diff node is about differences between types.
The base class of suppression specifications that are defined by the negation of matching clauses...
const data_members & get_data_members() const
Get the data members of this class_or_union.
Definition: abg-ir.cc:24233
shared_ptr< variable_suppression > variable_suppression_sptr
A convenience typedef for a shared pointer to variable_suppression.
const string & get_name() const
Getter for the name of the variable the user wants the current specification to designate. This property might be empty, in which case it's ignored at evaluation time.
void set_soname_regex_str(const string &regexp)
Setter of the "soname_regex_str property of the current instance of suppression_base.
shared_ptr< integer_boundary > integer_boundary_sptr
Convenience typedef for a shared_ptr to a integer_boundary.
void set_file_name_regex_str(const string &regexp)
Setter for the "file_name_regex" property of the current instance of suppression_base.
void set_symbol_name_regex_str(const string &)
Setter of the regular expression for a family of symbol names of the variables this specification is ...
shared_ptr< function_suppression > function_suppression_sptr
Convenience typedef for a shared pointer to function_suppression.
var_decl_sptr get_last_data_member(const class_or_union &klass)
Get the last data member of a class type.
Definition: abg-ir.cc:5781
void set_file_name_not_regex_str(const string &regexp)
Setter for the "file_name_not_regex" property of the current instance of suppression_base.
const string & get_symbol_name_regex_str() const
Getter for a regular expression for a family of names of symbols of functions the user wants this spe...
type_or_decl_base_sptr second_subject() const
Getter of the second subject of the diff.
void set_type_name_not_regex_str(const string &name_regex_str)
Setter for the "type_name_not_regex_str" property of the type suppression specification.
const string & get_symbol_version_regex_str() const
Getter for a regular expression for a family of versions of symbols of functions the user wants the c...
reach_kind get_reach_kind() const
Getter of the way the diff node matching the current suppression specification is to be reached...
void set_name_regex_str(const string &)
Setter for a regular expression for a family of names of functions the user wants the current specifi...
var_decl_sptr has_flexible_array_data_member(const class_decl &klass)
Test if the last data member of a class is an array with non-finite data member.
Definition: abg-ir.cc:11206
const string & get_name() const
Getter for the name of the function the user wants the current specification to designate. This might be empty, in which case it's ignored at evaluation time.
void set_changed_enumerators_regexp(const vector< regex::regex_t_sptr > &)
Setter of the vector of the regular expression strings for changed enumerators that are supposed to b...
void set_symbol_name_regex_str(const string &)
Setter for a regular expression for a family of names of symbols of functions the user wants this spe...
method_type_sptr is_method_type(const type_or_decl_base_sptr &t)
Test whether a type is a method_type.
Definition: abg-ir.cc:11888
const string_set_type & get_potential_data_member_names() const
Getter of the "potential_data_member_names" property.
bool base_name(string const &path, string &file_name)
Return the file name part of a file part.
bool get_consider_type_kind() const
Getter of the property that says whether to consider the kind of type this suppression is about...
type_base_sptr peel_typedef_type(const type_base_sptr &type)
Return the leaf underlying type node of a typedef_decl node.
Definition: abg-ir.cc:7063
void set_symbol_name_not_regex_str(const string &)
Setter for a regular expression for a family of names of symbols of variables the user wants this spe...
const diff_context_sptr context() const
Getter of the context of the current diff.
function_suppression::change_kind operator&(function_suppression::change_kind l, function_suppression::change_kind r)
The bitwise 'and' operator for the enum function_suppression::change_kind.
bool has_soname_related_property() const
Test if the current suppression has a property related to SONAMEs.
This represents all the changes possibly described by this enum. It's a logical 'OR' of all the chang...
const enum_type_decl_sptr second_enum() const
const string & get_parameter_type_name() const
Getter for the type name of the parameter designated by this specification.
const char * get_opaque_types_suppr_spec_label()
negated_suppression_base()
Constructor of the negated_suppression_base.
const unsigned_var_diff_sptr_map & changed_data_members() const
Getter of the map of data members that got replaced by another data member. The key of the map is the...
bool is_function_suppressed(const fe_iface &fe, const string &fn_name, const string &fn_linkage_name, bool require_drop_property)
Test if a function is matched by at least one suppression specification associated with a given front...
void set_name_regex_str(const string &)
Setter for the regular expression for a family of names of variables the user wants the current speci...