3 // Copyright (C) 2016-2019 Red Hat, Inc.
5 // This file is part of the GNU Application Binary Interface Generic
6 // Analysis and Instrumentation Library (libabigail). This library is
7 // free software; you can redistribute it and/or modify it under the
8 // terms of the GNU Lesser General Public License as published by the
9 // Free Software Foundation; either version 3, or (at your option) any
12 // This library is distributed in the hope that it will be useful, but
13 // WITHOUT ANY WARRANTY; without even the implied warranty of
14 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 // General Lesser Public License for more details.
17 // You should have received a copy of the GNU Lesser General Public
18 // License along with this program; see the file COPYING-LGPLV3. If
19 // not, see <http://www.gnu.org/licenses/>.
21 // Author: Dodji Seketeli
25 /// This contains the private implementation of the suppression engine
28 #ifndef __ABG_SUPPRESSION_PRIV_H__
29 #define __ABG_SUPPRESSION_PRIV_H__
32 #include "abg-suppression.h"
33 #include "abg-sptr-utils.h"
41 // <suppression_base stuff>
43 /// The private data of @ref suppression_base.
44 class suppression_base::priv
49 string file_name_regex_str_;
50 mutable sptr_utils::regex_t_sptr file_name_regex_;
51 string file_name_not_regex_str_;
52 mutable sptr_utils::regex_t_sptr file_name_not_regex_;
53 string soname_regex_str_;
54 mutable sptr_utils::regex_t_sptr soname_regex_;
55 string soname_not_regex_str_;
56 mutable sptr_utils::regex_t_sptr soname_not_regex_;
64 priv(const string& label)
70 priv(const string& label,
71 const string& file_name_regex_str,
72 const string& file_name_not_regex_str)
76 file_name_regex_str_(file_name_regex_str),
77 file_name_not_regex_str_(file_name_not_regex_str)
80 friend class suppression_base;
82 /// Get the regular expression object associated to the 'file_name_regex'
83 /// property of @ref suppression_base.
85 /// If the regular expression object is not created, this method
86 /// creates it and returns it.
88 /// If the 'file_name_regex' property of @ref suppression_base is
89 /// empty then this method returns nil.
90 const sptr_utils::regex_t_sptr&
91 get_file_name_regex() const
93 if (!file_name_regex_)
95 if (!file_name_regex_str_.empty())
97 sptr_utils::regex_t_sptr r = sptr_utils::build_sptr<regex_t>();
99 file_name_regex_str_.c_str(),
101 file_name_regex_ = r;
104 return file_name_regex_;
107 /// Get the regular expression object associated to the
108 /// 'file_name_not_regex' property of @ref suppression_base.
110 /// If the regular expression object is not created, this method
111 /// creates it and returns it.
113 /// If the 'file_name_not_regex' property of @ref suppression_base
114 /// is empty then this method returns nil.
115 const sptr_utils::regex_t_sptr&
116 get_file_name_not_regex() const
118 if (!file_name_not_regex_)
120 if (!file_name_not_regex_str_.empty())
122 sptr_utils::regex_t_sptr r = sptr_utils::build_sptr<regex_t>();
124 file_name_not_regex_str_.c_str(),
126 file_name_not_regex_ = r;
129 return file_name_not_regex_;
132 /// Get the regular expression object associated to the
133 /// 'soname_regex' property of @ref suppression_base.
135 /// If the regular expression object is not created, this method
136 /// creates it and returns it.
138 /// If the 'soname_regex' property of @ref suppression_base is empty
139 /// then this method returns nil.
140 const sptr_utils::regex_t_sptr&
141 get_soname_regex() const
145 if (!soname_regex_str_.empty())
147 sptr_utils::regex_t_sptr r = sptr_utils::build_sptr<regex_t>();
149 soname_regex_str_.c_str(),
154 return soname_regex_;
157 /// Get the regular expression object associated to the
158 /// 'soname_not_regex' property of @ref suppression_base.
160 /// If the regular expression object is not created, this method
161 /// creates it and returns it.
163 /// If the 'soname_not_regex' property of @ref suppression_base is
164 /// empty then this method returns nil.
165 const sptr_utils::regex_t_sptr&
166 get_soname_not_regex() const
168 if (!soname_not_regex_)
170 if (!soname_not_regex_str_.empty())
172 sptr_utils::regex_t_sptr r = sptr_utils::build_sptr<regex_t>();
174 soname_not_regex_str_.c_str(),
176 soname_not_regex_ = r;
179 return soname_not_regex_;
183 matches_soname(const string& soname) const
185 if (sptr_utils::regex_t_sptr regexp = get_soname_regex())
186 if (regexec(regexp.get(), soname.c_str(), 0, NULL, 0) != 0)
189 if (sptr_utils::regex_t_sptr regexp = get_soname_not_regex())
190 if (regexec(regexp.get(), soname.c_str(), 0, NULL, 0) == 0)
197 matches_binary_name(const string& binary_name) const
199 if (sptr_utils::regex_t_sptr regexp = get_file_name_regex())
200 if (regexec(regexp.get(), binary_name.c_str(),
204 if (sptr_utils::regex_t_sptr regexp = get_file_name_not_regex())
205 if (regexec(regexp.get(), binary_name.c_str(),
212 }; // end clas suppression_base::priv
214 // </suppression_base stuff>
216 // <function_suppression stuff>
218 class function_suppression::parameter_spec::priv
220 friend class function_suppression::parameter_spec;
221 friend class function_suppression;
225 string type_name_regex_str_;
226 mutable sptr_utils::regex_t_sptr type_name_regex_;
232 priv(size_t i, const string& tn)
233 : index_(i), type_name_(tn)
236 priv(size_t i, const string& tn, const string& tn_regex)
237 : index_(i), type_name_(tn), type_name_regex_str_(tn_regex)
240 const sptr_utils::regex_t_sptr
241 get_type_name_regex() const
243 if (!type_name_regex_ && !type_name_regex_str_.empty())
245 sptr_utils::regex_t_sptr r = sptr_utils::build_sptr<regex_t>();
247 type_name_regex_str_.c_str(),
249 type_name_regex_ = r;
251 return type_name_regex_;
253 }; // end class function_suppression::parameter_spec::priv
256 /// The type of the private data of the @ref function_suppression
258 struct function_suppression::priv
260 friend class function_suppression;
262 change_kind change_kind_;
264 string name_regex_str_;
265 mutable sptr_utils::regex_t_sptr name_regex_;
266 string name_not_regex_str_;
267 mutable sptr_utils::regex_t_sptr name_not_regex_;
268 string return_type_name_;
269 string return_type_regex_str_;
270 mutable sptr_utils::regex_t_sptr return_type_regex_;
271 parameter_specs_type parm_specs_;
273 string symbol_name_regex_str_;
274 mutable sptr_utils::regex_t_sptr symbol_name_regex_;
275 string symbol_version_;
276 string symbol_version_regex_str_;
277 mutable sptr_utils::regex_t_sptr symbol_version_regex_;
278 bool allow_other_aliases_;
281 change_kind_(ALL_CHANGE_KIND),
282 allow_other_aliases_(true)
285 priv(const string& name,
286 const string& name_regex_str,
287 const string& return_type_name,
288 const string& return_type_regex_str,
289 const parameter_specs_type& parm_specs,
290 const string& symbol_name,
291 const string& symbol_name_regex_str,
292 const string& symbol_version,
293 const string& symbol_version_regex_str)
294 : change_kind_(ALL_CHANGE_KIND),
296 name_regex_str_(name_regex_str),
297 return_type_name_(return_type_name),
298 return_type_regex_str_(return_type_regex_str),
299 parm_specs_(parm_specs),
300 symbol_name_(symbol_name),
301 symbol_name_regex_str_(symbol_name_regex_str),
302 symbol_version_(symbol_version),
303 symbol_version_regex_str_(symbol_version_regex_str),
304 allow_other_aliases_(true)
308 /// Getter for a pointer to a regular expression object built from
309 /// the regular expression string
310 /// function_suppression::priv::name_regex_str_.
312 /// If that string is empty, then an empty regular expression object
313 /// pointer is returned.
315 /// @return a pointer to the regular expression object of
316 /// function_suppression::priv::name_regex_str_..
317 const sptr_utils::regex_t_sptr
318 get_name_regex() const
320 if (!name_regex_ && !name_regex_str_.empty())
322 sptr_utils::regex_t_sptr r = sptr_utils::build_sptr<regex_t>();
324 name_regex_str_.c_str(),
331 /// Getter for a pointer to a regular expression object built from
332 /// the regular expression string
333 /// function_suppression::priv::name_not_regex_str_.
335 /// If that string is empty, then an empty regular expression object
336 /// pointer is returned.
338 /// @return a pointer to the regular expression object of
339 /// function_suppression::priv::name_not_regex_str_..
340 const sptr_utils::regex_t_sptr
341 get_name_not_regex() const
343 if (!name_not_regex_ && !name_not_regex_str_.empty())
345 sptr_utils::regex_t_sptr r = sptr_utils::build_sptr<regex_t>();
347 name_not_regex_str_.c_str(),
351 return name_not_regex_;
354 /// Getter for a pointer to a regular expression object built from
355 /// the regular expression string
356 /// function_suppression::priv::return_type_regex_str_.
358 /// If that string is empty, then an empty regular expression object
359 /// pointer is returned.
361 /// @return a pointer to the regular expression object of
362 /// function_suppression::priv::return_type_regex_str_.
363 const sptr_utils::regex_t_sptr
364 get_return_type_regex() const
366 if (!return_type_regex_ && !return_type_regex_str_.empty())
368 sptr_utils::regex_t_sptr r = sptr_utils::build_sptr<regex_t>();
370 return_type_regex_str_.c_str(),
372 return_type_regex_ = r;
374 return return_type_regex_;
377 /// Getter for a pointer to a regular expression object built from
378 /// the regular expression string
379 /// function_suppression::priv::symbol_name_regex_str_.
381 /// If that string is empty, then an empty regular expression object
382 /// pointer is returned.
384 /// @return a pointer to the regular expression object of
385 /// function_suppression::priv::symbol_name_regex_str_.
386 const sptr_utils::regex_t_sptr
387 get_symbol_name_regex() const
389 if (!symbol_name_regex_ && !symbol_name_regex_str_.empty())
391 sptr_utils::regex_t_sptr r = sptr_utils::build_sptr<regex_t>();
393 symbol_name_regex_str_.c_str(),
395 symbol_name_regex_ = r;
397 return symbol_name_regex_;
400 /// Getter for a pointer to a regular expression object built from
401 /// the regular expression string
402 /// function_suppression::priv::symbol_version_regex_str_.
404 /// If that string is empty, then an empty regular expression object
405 /// pointer is returned.
407 /// @return a pointer to the regular expression object of
408 /// function_suppression::priv::symbol_version_regex_str_.
409 const sptr_utils::regex_t_sptr
410 get_symbol_version_regex() const
412 if (!symbol_version_regex_ && ! symbol_version_regex_str_.empty())
414 sptr_utils::regex_t_sptr r = sptr_utils::build_sptr<regex_t>();
416 symbol_version_regex_str_.c_str(),
418 symbol_version_regex_ = r;
420 return symbol_version_regex_;
422 }; // end class function_suppression::priv
425 suppression_matches_function_name(const suppr::function_suppression& s,
426 const string& fn_name);
429 suppression_matches_function_sym_name(const suppr::function_suppression& s,
430 const string& fn_linkage_name);
433 suppression_matches_variable_name(const suppr::variable_suppression& s,
434 const string& var_name);
438 suppression_matches_variable_sym_name(const suppr::variable_suppression& s,
439 const string& var_linkage_name);
441 /// Test if a given function denoted by its name and linkage name is
442 /// suppressed by any of the suppression specifications associated to
443 /// a given read context used to build the current internal
444 /// representation of ABI corpus.
446 /// @param ctxt the reading context of interest.
448 /// @param fn_name the name of the function that a specification can
451 /// @param fn_linkage_name the linkage name of the function that a
452 /// specification can match.
454 /// @param require_drop_property if set to "true", tests if the
455 /// function is suppressed and if its representation is dropped from
456 /// the ABI corpus being built. Otherwise, if set to "false", only
457 /// test if the function is suppressed.
459 /// @return true iff at least one function specification matches a
460 /// function with name @p fn_name or with linkage name @p
462 template <typename ReadContextType>
464 function_is_suppressed(const ReadContextType& ctxt,
465 const string& fn_name,
466 const string& fn_linkage_name,
467 bool require_drop_property = false)
469 for (suppr::suppressions_type::const_iterator i =
470 ctxt.get_suppressions().begin();
471 i != ctxt.get_suppressions().end();
473 if (suppr::function_suppression_sptr suppr = is_function_suppression(*i))
475 if (require_drop_property && !(*i)->get_drops_artifact_from_ir())
477 if (ctxt.suppression_matches_function_name(*suppr, fn_name))
479 if (ctxt.suppression_matches_function_sym_name(*suppr,
485 // </function_suppression stuff>
487 // <variable_suppression stuff>
488 /// The type of the private data of the @ref variable_suppression
490 struct variable_suppression::priv
492 friend class variable_suppression;
494 change_kind change_kind_;
496 string name_regex_str_;
497 mutable sptr_utils::regex_t_sptr name_regex_;
498 string name_not_regex_str_;
499 mutable sptr_utils::regex_t_sptr name_not_regex_;
501 string symbol_name_regex_str_;
502 mutable sptr_utils::regex_t_sptr symbol_name_regex_;
503 string symbol_version_;
504 string symbol_version_regex_str_;
505 mutable sptr_utils::regex_t_sptr symbol_version_regex_;
507 string type_name_regex_str_;
508 mutable sptr_utils::regex_t_sptr type_name_regex_;
510 priv(const string& name,
511 const string& name_regex_str,
512 const string& symbol_name,
513 const string& symbol_name_regex_str,
514 const string& symbol_version,
515 const string& symbol_version_regex_str,
516 const string& type_name,
517 const string& type_name_regex_str)
518 : change_kind_(ALL_CHANGE_KIND),
520 name_regex_str_(name_regex_str),
521 symbol_name_(symbol_name),
522 symbol_name_regex_str_(symbol_name_regex_str),
523 symbol_version_(symbol_version),
524 symbol_version_regex_str_(symbol_version_regex_str),
525 type_name_(type_name),
526 type_name_regex_str_(type_name_regex_str)
529 /// Getter for a pointer to a regular expression object built from
530 /// the regular expression string
531 /// variable_suppression::priv::name_regex_str_.
533 /// If that string is empty, then an empty regular expression object
534 /// pointer is returned.
536 /// @return a pointer to the regular expression object of
537 /// variable_suppression::priv::name_regex_str_.
538 const sptr_utils::regex_t_sptr
539 get_name_regex() const
541 if (!name_regex_ && !name_regex_str_.empty())
543 sptr_utils::regex_t_sptr r = sptr_utils::build_sptr<regex_t>();
545 name_regex_str_.c_str(),
552 /// Getter for a pointer to a regular expression object built from
553 /// the regular expression string
554 /// variable_suppression::priv::name_not_regex_str_.
556 /// If that string is empty, then an empty regular expression object
557 /// pointer is returned.
559 /// @return a pointer to the regular expression object of
560 /// variable_suppression::priv::name_not_regex_str_..
561 const sptr_utils::regex_t_sptr
562 get_name_not_regex() const
564 if (!name_not_regex_ && !name_not_regex_str_.empty())
566 sptr_utils::regex_t_sptr r = sptr_utils::build_sptr<regex_t>();
568 name_not_regex_str_.c_str(),
572 return name_not_regex_;
575 /// Getter for a pointer to a regular expression object built from
576 /// the regular expression string
577 /// variable_suppression::priv::symbol_name_regex_str_.
579 /// If that string is empty, then an empty regular expression object
580 /// pointer is returned.
582 /// @return a pointer to the regular expression object of
583 /// variable_suppression::priv::symbol_name_regex_str_.
584 const sptr_utils::regex_t_sptr
585 get_symbol_name_regex() const
587 if (!symbol_name_regex_ && !symbol_name_regex_str_.empty())
589 sptr_utils::regex_t_sptr r = sptr_utils::build_sptr<regex_t>();
591 symbol_name_regex_str_.c_str(),
593 symbol_name_regex_ = r;
595 return symbol_name_regex_;
598 /// Getter for a pointer to a regular expression object built from
599 /// the regular expression string
600 /// variable_suppression::priv::symbol_version_regex_str_.
602 /// If that string is empty, then an empty regular expression object
603 /// pointer is returned.
605 /// @return a pointer to the regular expression object of
606 /// variable_suppression::priv::symbol_version_regex_str_.
607 const sptr_utils::regex_t_sptr
608 get_symbol_version_regex() const
610 if (!symbol_version_regex_ && !symbol_version_regex_str_.empty())
612 sptr_utils::regex_t_sptr r = sptr_utils::build_sptr<regex_t>();
614 symbol_version_regex_str_.c_str(),
616 symbol_version_regex_ = r;
618 return symbol_version_regex_;
621 /// Getter for a pointer to a regular expression object built from
622 /// the regular expression string
623 /// variable_suppression::priv::type_name_regex_str_.
625 /// If that string is empty, then an empty regular expression object
626 /// pointer is returned.
628 /// @return a pointer to the regular expression object of
629 /// variable_suppression::priv::type_name_regex_str_.
630 const sptr_utils::regex_t_sptr
631 get_type_name_regex() const
633 if (!type_name_regex_ && !type_name_regex_str_.empty())
635 sptr_utils::regex_t_sptr r = sptr_utils::build_sptr<regex_t>();
637 type_name_regex_str_.c_str(),
639 type_name_regex_ = r;
641 return type_name_regex_;
643 };// end class variable_supppression::priv
645 template <typename ReadContextType>
647 variable_is_suppressed(const ReadContextType& ctxt,
648 const string& var_name,
649 const string& var_linkage_name,
650 bool require_drop_property = false)
652 for (suppr::suppressions_type::const_iterator i =
653 ctxt.get_suppressions().begin();
654 i != ctxt.get_suppressions().end();
656 if (suppr::variable_suppression_sptr suppr = is_variable_suppression(*i))
658 if (require_drop_property && !(*i)->get_drops_artifact_from_ir())
660 if (ctxt.suppression_matches_variable_name(*suppr, var_name))
662 if (ctxt.suppression_matches_variable_sym_name(*suppr,
669 // </variable_suppression stuff>
671 // <type_suppression stuff>
672 /// The private data for @ref type_suppression.
673 class type_suppression::priv
675 string type_name_regex_str_;
676 mutable sptr_utils::regex_t_sptr type_name_regex_;
678 bool consider_type_kind_;
679 type_suppression::type_kind type_kind_;
680 bool consider_reach_kind_;
681 type_suppression::reach_kind reach_kind_;
682 type_suppression::insertion_ranges insertion_ranges_;
683 unordered_set<string> source_locations_to_keep_;
684 string source_location_to_keep_regex_str_;
685 mutable sptr_utils::regex_t_sptr source_location_to_keep_regex_;
686 mutable vector<string> changed_enumerator_names_;
691 priv(const string& type_name_regexp,
692 const string& type_name,
693 bool consider_type_kind,
694 type_suppression::type_kind type_kind,
695 bool consider_reach_kind,
696 type_suppression::reach_kind reach_kind)
697 : type_name_regex_str_(type_name_regexp),
698 type_name_(type_name),
699 consider_type_kind_(consider_type_kind),
700 type_kind_(type_kind),
701 consider_reach_kind_(consider_reach_kind),
702 reach_kind_(reach_kind)
705 /// Get the regular expression object associated to the 'type_name_regex'
706 /// property of @ref type_suppression.
708 /// If the regular expression object is not created, this method
709 /// creates it and returns it.
711 /// If the 'type_name_regex' property of @ref type_suppression is
712 /// empty then this method returns nil.
713 const sptr_utils::regex_t_sptr
714 get_type_name_regex() const
716 if (!type_name_regex_)
718 if (!type_name_regex_str_.empty())
720 sptr_utils::regex_t_sptr r = sptr_utils::build_sptr<regex_t>();
722 type_name_regex_str_.c_str(),
724 type_name_regex_ = r;
727 return type_name_regex_;
730 /// Setter for the type_name_regex object.
732 /// @param r the new type_name_regex object.
734 set_type_name_regex(sptr_utils::regex_t_sptr r)
735 {type_name_regex_ = r;}
737 /// Getter for the source_location_to_keep_regex object.
739 /// This function builds the regex if it's not yet built.
740 const sptr_utils::regex_t_sptr
741 get_source_location_to_keep_regex() const
743 if (!source_location_to_keep_regex_)
745 if (!source_location_to_keep_regex_str_.empty())
747 sptr_utils::regex_t_sptr r = sptr_utils::build_sptr<regex_t>();
749 source_location_to_keep_regex_str_.c_str(),
751 source_location_to_keep_regex_ = r;
754 return source_location_to_keep_regex_;
757 /// Setter for the source_location_to_keep_regex object.
759 /// @param r the new regex object.
761 set_source_location_to_keep_regex(sptr_utils::regex_t_sptr r)
762 {source_location_to_keep_regex_ = r;}
764 friend class type_suppression;
765 }; // class type_suppression::priv
768 suppression_matches_type_name(const suppr::type_suppression& s,
769 const string& type_name);
772 suppression_matches_type_name(const suppr::type_suppression& s,
773 const scope_decl* scope,
774 const type_base_sptr& type);
777 suppression_matches_type_location(const type_suppression& s,
778 const location& loc);
781 suppression_matches_type_location(const type_suppression& s,
782 const type_base_sptr& type);
785 suppression_matches_type_name_or_location(const type_suppression& s,
786 const string& type_name,
787 const location& type_location);
789 /// Test if a type (designated by its name and location) is suppressed
790 /// by at least one suppression specification associated with a given
793 /// @param ctxt the read context to consider.
795 /// @param type_name the name of the type to consider.
797 /// @param type_location the location of the type to consider.
799 /// @param require_drop_property if set to "true", tests if the type
800 /// is suppressed and if its representation is dropped from the ABI
801 /// corpus being built. Otherwise, if set to "false", only test if
802 /// the type is suppressed.
804 /// @return true iff at least one type specification matches a type
805 /// with name @p type_name and with location @p type_location.
806 template <typename ReadContextType>
808 type_is_suppressed(const ReadContextType& ctxt,
809 const string& type_name,
810 const location& type_location)
812 bool type_is_private = false;
813 return type_is_suppressed(ctxt, type_name, type_location, type_is_private);
816 /// Test if a type (designated by its name and location) is suppressed
817 /// by at least one suppression specification associated with a given
820 /// @param ctxt the read context to consider.
822 /// @param type_name the name of the type to consider.
824 /// @param type_location the location of the type to consider.
826 /// @param type_is_private out parameter. If the type is suppressed
827 /// because it's private then this out parameter is set to true.
829 /// @param require_drop_property if set to "true", tests if the type
830 /// is suppressed and if its representation is dropped from the ABI
831 /// corpus being built. Otherwise, if set to "false", only test if
832 /// the type is suppressed.
834 /// @return true iff at least one type specification matches a type
835 /// with name @p type_name and with location @p type_location.
836 template <typename ReadContextType>
838 type_is_suppressed(const ReadContextType& ctxt,
839 const string& type_name,
840 const location& type_location,
841 bool& type_is_private,
842 bool require_drop_property = false)
844 for (suppr::suppressions_type::const_iterator i =
845 ctxt.get_suppressions().begin();
846 i != ctxt.get_suppressions().end();
848 if (suppr::type_suppression_sptr suppr = is_type_suppression(*i))
850 if (require_drop_property && !(*i)->get_drops_artifact_from_ir())
852 if (ctxt.suppression_matches_type_name_or_location(*suppr, type_name,
855 if (is_private_type_suppr_spec(*suppr))
856 type_is_private = true;
862 type_is_private = false;
866 // </type_suppression stuff>
868 }// end namespace suppr
869 } // end namespace abigail
871 #endif // __ABG_SUPPRESSION_PRIV_H__