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