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