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