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