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