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