1 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
2 // -*- Mode: C++ -*-
3 //
4 // Copyright (C) 2016-2020 Red Hat, Inc.
5 //
6 // Author: Dodji Seketeli
7 
8 /// @file
9 ///
10 /// This contains the private implementation of the suppression engine
11 /// of libabigail.
12 
13 #ifndef __ABG_SUPPRESSION_PRIV_H__
14 #define __ABG_SUPPRESSION_PRIV_H__
15 
16 #include "abg-fwd.h"
17 #include "abg-regex.h"
18 #include "abg-sptr-utils.h"
19 #include "abg-suppression.h"
20 
21 namespace abigail
22 {
23 
24 namespace suppr
25 {
26 
27 // <suppression_base stuff>
28 
29 /// The private data of @ref suppression_base.
30 class suppression_base::priv
31 {
32   bool					is_artificial_;
33   bool					drops_artifact_;
34   string				label_;
35   string				file_name_regex_str_;
36   mutable regex::regex_t_sptr		file_name_regex_;
37   string				file_name_not_regex_str_;
38   mutable regex::regex_t_sptr		file_name_not_regex_;
39   string				soname_regex_str_;
40   mutable regex::regex_t_sptr		soname_regex_;
41   string				soname_not_regex_str_;
42   mutable regex::regex_t_sptr		soname_not_regex_;
43 
44 public:
priv()45   priv()
46     : is_artificial_(),
47       drops_artifact_()
48   {}
49 
priv(const string & label)50   priv(const string& label)
51     : is_artificial_(),
52       drops_artifact_(),
53       label_(label)
54   {}
55 
priv(const string & label,const string & file_name_regex_str,const string & file_name_not_regex_str)56   priv(const string& label,
57        const string& file_name_regex_str,
58        const string& file_name_not_regex_str)
59     : is_artificial_(),
60       drops_artifact_(),
61       label_(label),
62       file_name_regex_str_(file_name_regex_str),
63       file_name_not_regex_str_(file_name_not_regex_str)
64   {}
65 
66   friend class suppression_base;
67 
68   /// Get the regular expression object associated to the 'file_name_regex'
69   /// property of @ref suppression_base.
70   ///
71   /// If the regular expression object is not created, this method
72   /// creates it and returns it.
73   ///
74   /// If the 'file_name_regex' property of @ref suppression_base is
75   /// empty then this method returns nil.
76   const regex::regex_t_sptr&
get_file_name_regex()77   get_file_name_regex() const
78   {
79     if (!file_name_regex_ && !file_name_regex_str_.empty())
80       file_name_regex_ = regex::compile(file_name_regex_str_);
81     return file_name_regex_;
82   }
83 
84   /// Get the regular expression object associated to the
85   /// 'file_name_not_regex' property of @ref suppression_base.
86   ///
87   /// If the regular expression object is not created, this method
88   /// creates it and returns it.
89   ///
90   /// If the 'file_name_not_regex' property of @ref suppression_base
91   /// is empty then this method returns nil.
92   const regex::regex_t_sptr&
get_file_name_not_regex()93   get_file_name_not_regex() const
94   {
95     if (!file_name_not_regex_ && !file_name_not_regex_str_.empty())
96       file_name_not_regex_ = regex::compile(file_name_not_regex_str_);
97     return file_name_not_regex_;
98   }
99 
100   /// Get the regular expression object associated to the
101   /// 'soname_regex' property of @ref suppression_base.
102   ///
103   /// If the regular expression object is not created, this method
104   /// creates it and returns it.
105   ///
106   /// If the 'soname_regex' property of @ref suppression_base is empty
107   /// then this method returns nil.
108   const regex::regex_t_sptr&
get_soname_regex()109   get_soname_regex() const
110   {
111     if (!soname_regex_ && !soname_regex_str_.empty())
112       soname_regex_ = regex::compile(soname_regex_str_);
113     return soname_regex_;
114   }
115 
116   /// Get the regular expression object associated to the
117   /// 'soname_not_regex' property of @ref suppression_base.
118   ///
119   /// If the regular expression object is not created, this method
120   /// creates it and returns it.
121   ///
122   /// If the 'soname_not_regex' property of @ref suppression_base is
123   /// empty then this method returns nil.
124   const regex::regex_t_sptr&
get_soname_not_regex()125   get_soname_not_regex() const
126   {
127     if (!soname_not_regex_ && !soname_not_regex_str_.empty())
128       soname_not_regex_ = regex::compile(soname_not_regex_str_);
129     return soname_not_regex_;
130   }
131 
132   /// Test if the current suppression matches a given SONAME.
133   ///
134   /// @param soname the SONAME to consider.
135   ///
136   /// @return true iff the suppression matches the SONAME denoted by
137   /// @p soname.
138   ///
139   /// Note that if the suppression contains no property that is
140   /// related to SONAMEs, the function returns false.
141   bool
matches_soname(const string & soname)142   matches_soname(const string& soname) const
143   {
144     bool has_regexp = false;
145     if (regex::regex_t_sptr regexp = get_soname_regex())
146       {
147 	has_regexp = true;
148 	if (!regex::match(regexp, soname))
149 	  return false;
150       }
151 
152     if (regex::regex_t_sptr regexp = get_soname_not_regex())
153       {
154 	has_regexp = true;
155 	if (regex::match(regexp, soname))
156 	  return false;
157       }
158 
159       if (!has_regexp)
160 	return false;
161 
162     return true;
163   }
164 
165   /// Test if the current suppression matches the full file path to a
166   /// given binary.
167   ///
168   /// @param binary_name the full path to the binary.
169   ///
170   /// @return true iff the suppression matches the path denoted by @p
171   /// binary_name.
172   ///
173   /// Note that if the suppression contains no property that is
174   /// related to file name, the function returns false.
175   bool
matches_binary_name(const string & binary_name)176   matches_binary_name(const string& binary_name) const
177   {
178     bool has_regexp = false;
179 
180     if (regex::regex_t_sptr regexp = get_file_name_regex())
181       {
182 	has_regexp = true;
183 	if (!regex::match(regexp, binary_name))
184 	  return false;
185       }
186 
187     if (regex::regex_t_sptr regexp = get_file_name_not_regex())
188       {
189 	has_regexp = true;
190 	if (regex::match(regexp, binary_name))
191 	  return false;
192       }
193 
194     if (!has_regexp)
195       return false;
196 
197     return true;
198   }
199 
200 }; // end clas suppression_base::priv
201 
202 // </suppression_base stuff>
203 
204 // <function_suppression stuff>
205 
206 class function_suppression::parameter_spec::priv
207 {
208   friend class function_suppression::parameter_spec;
209   friend class function_suppression;
210 
211   size_t				index_;
212   string				type_name_;
213   string				type_name_regex_str_;
214   mutable regex::regex_t_sptr		type_name_regex_;
215 
priv()216   priv()
217     : index_()
218   {}
219 
priv(size_t i,const string & tn)220   priv(size_t i, const string& tn)
221     : index_(i), type_name_(tn)
222   {}
223 
priv(size_t i,const string & tn,const string & tn_regex)224   priv(size_t i, const string& tn, const string& tn_regex)
225     : index_(i), type_name_(tn), type_name_regex_str_(tn_regex)
226   {}
227 
228   const regex::regex_t_sptr
get_type_name_regex()229   get_type_name_regex() const
230   {
231     if (!type_name_regex_ && !type_name_regex_str_.empty())
232       type_name_regex_ = regex::compile(type_name_regex_str_);
233     return type_name_regex_;
234   }
235 }; // end class function_suppression::parameter_spec::priv
236 
237 
238 /// The type of the private data of the @ref function_suppression
239 /// type.
240 struct function_suppression::priv
241 {
242   friend class function_suppression;
243 
244   change_kind				change_kind_;
245   string				name_;
246   string				name_regex_str_;
247   mutable regex::regex_t_sptr		name_regex_;
248   string				name_not_regex_str_;
249   mutable regex::regex_t_sptr		name_not_regex_;
250   string				return_type_name_;
251   string				return_type_regex_str_;
252   mutable regex::regex_t_sptr		return_type_regex_;
253   parameter_specs_type			parm_specs_;
254   string				symbol_name_;
255   string				symbol_name_regex_str_;
256   mutable regex::regex_t_sptr		symbol_name_regex_;
257   string				symbol_name_not_regex_str_;
258   mutable regex::regex_t_sptr		symbol_name_not_regex_;
259   string				symbol_version_;
260   string				symbol_version_regex_str_;
261   mutable regex::regex_t_sptr		symbol_version_regex_;
262   bool					allow_other_aliases_;
263 
privpriv264   priv():
265     change_kind_(ALL_CHANGE_KIND),
266     allow_other_aliases_(true)
267   {}
268 
privpriv269   priv(const string&			name,
270        const string&			name_regex_str,
271        const string&			return_type_name,
272        const string&			return_type_regex_str,
273        const parameter_specs_type&	parm_specs,
274        const string&			symbol_name,
275        const string&			symbol_name_regex_str,
276        const string&			symbol_version,
277        const string&			symbol_version_regex_str)
278     : change_kind_(ALL_CHANGE_KIND),
279       name_(name),
280       name_regex_str_(name_regex_str),
281       return_type_name_(return_type_name),
282       return_type_regex_str_(return_type_regex_str),
283       parm_specs_(parm_specs),
284       symbol_name_(symbol_name),
285       symbol_name_regex_str_(symbol_name_regex_str),
286       symbol_version_(symbol_version),
287       symbol_version_regex_str_(symbol_version_regex_str),
288       allow_other_aliases_(true)
289   {}
290 
291 
292   /// Getter for a pointer to a regular expression object built from
293   /// the regular expression string
294   /// function_suppression::priv::name_regex_str_.
295   ///
296   /// If that string is empty, then an empty regular expression object
297   /// pointer is returned.
298   ///
299   /// @return a pointer to the regular expression object of
300   /// function_suppression::priv::name_regex_str_..
301   const regex::regex_t_sptr
get_name_regexpriv302   get_name_regex() const
303   {
304     if (!name_regex_ && !name_regex_str_.empty())
305       name_regex_ = regex::compile(name_regex_str_);
306     return name_regex_;
307   }
308 
309   /// Getter for a pointer to a regular expression object built from
310   /// the regular expression string
311   /// function_suppression::priv::name_not_regex_str_.
312   ///
313   /// If that string is empty, then an empty regular expression object
314   /// pointer is returned.
315   ///
316   /// @return a pointer to the regular expression object of
317   /// function_suppression::priv::name_not_regex_str_..
318   const regex::regex_t_sptr
get_name_not_regexpriv319   get_name_not_regex() const
320   {
321     if (!name_not_regex_ && !name_not_regex_str_.empty())
322       name_not_regex_ = regex::compile(name_not_regex_str_);
323     return name_not_regex_;
324   }
325 
326   /// Getter for a pointer to a regular expression object built from
327   /// the regular expression string
328   /// function_suppression::priv::return_type_regex_str_.
329   ///
330   /// If that string is empty, then an empty regular expression object
331   /// pointer is returned.
332   ///
333   /// @return a pointer to the regular expression object of
334   /// function_suppression::priv::return_type_regex_str_.
335   const regex::regex_t_sptr
get_return_type_regexpriv336   get_return_type_regex() const
337   {
338     if (!return_type_regex_ && !return_type_regex_str_.empty())
339       return_type_regex_ = regex::compile(return_type_regex_str_);
340     return return_type_regex_;
341   }
342 
343   /// Getter for a pointer to a regular expression object built from
344   /// the regular expression string
345   /// function_suppression::priv::symbol_name_regex_str_.
346   ///
347   /// If that string is empty, then an empty regular expression object
348   /// pointer is returned.
349   ///
350   /// @return a pointer to the regular expression object of
351   /// function_suppression::priv::symbol_name_regex_str_.
352   const regex::regex_t_sptr
get_symbol_name_regexpriv353   get_symbol_name_regex() const
354   {
355     if (!symbol_name_regex_ && !symbol_name_regex_str_.empty())
356       symbol_name_regex_ = regex::compile(symbol_name_regex_str_);
357     return symbol_name_regex_;
358   }
359 
360   /// Getter for a pointer to a regular expression object built from
361   /// the regular expression string
362   /// function_suppression::priv::symbol_name_not_regex_str_.
363   ///
364   /// If that string is empty, then an empty regular expression object
365   /// pointer is returned.
366   ///
367   /// @return a pointer to the regular expression object of
368   /// function_suppression::priv::symbol_name_not_regex_str_.
369   const regex::regex_t_sptr
get_symbol_name_not_regexpriv370   get_symbol_name_not_regex() const
371   {
372     if (!symbol_name_not_regex_ && !symbol_name_not_regex_str_.empty())
373       symbol_name_not_regex_ = regex::compile(symbol_name_not_regex_str_);
374     return symbol_name_not_regex_;
375   }
376 
377   /// Getter for a pointer to a regular expression object built from
378   /// the regular expression string
379   /// function_suppression::priv::symbol_version_regex_str_.
380   ///
381   /// If that string is empty, then an empty regular expression object
382   /// pointer is returned.
383   ///
384   /// @return a pointer to the regular expression object of
385   /// function_suppression::priv::symbol_version_regex_str_.
386   const regex::regex_t_sptr
get_symbol_version_regexpriv387   get_symbol_version_regex() const
388   {
389     if (!symbol_version_regex_ && !symbol_version_regex_str_.empty())
390       symbol_version_regex_ = regex::compile(symbol_version_regex_str_);
391     return symbol_version_regex_;
392   }
393 }; // end class function_suppression::priv
394 
395 bool
396 suppression_matches_function_name(const suppr::function_suppression& s,
397 				  const string& fn_name);
398 
399 bool
400 suppression_matches_function_sym_name(const suppr::function_suppression& s,
401 				      const string& fn_linkage_name);
402 
403 bool
404 suppression_matches_variable_name(const suppr::variable_suppression& s,
405 				  const string& var_name);
406 
407 
408 bool
409 suppression_matches_variable_sym_name(const suppr::variable_suppression& s,
410 				      const string& var_linkage_name);
411 
412 /// Test if a given function denoted by its name and linkage name is
413 /// suppressed by any of the suppression specifications associated to
414 /// a given read context used to build the current internal
415 /// representation of ABI corpus.
416 ///
417 /// @param ctxt the reading context of interest.
418 ///
419 /// @param fn_name the name of the function that a specification can
420 /// match.
421 ///
422 /// @param fn_linkage_name the linkage name of the function that a
423 /// specification can match.
424 ///
425 /// @param require_drop_property if set to "true", tests if the
426 /// function is suppressed and if its representation is dropped from
427 /// the ABI corpus being built.  Otherwise, if set to "false", only
428 /// test if the function is suppressed.
429 ///
430 /// @return true iff at least one function specification matches a
431 /// function with name @p fn_name or with linkage name @p
432 /// fn_linkage_name.
433 template <typename ReadContextType>
434 bool
435 function_is_suppressed(const ReadContextType&	ctxt,
436 		       const string&		fn_name,
437 		       const string&		fn_linkage_name,
438 		       bool			require_drop_property = false)
439 {
440   for (suppr::suppressions_type::const_iterator i =
441 	 ctxt.get_suppressions().begin();
442        i != ctxt.get_suppressions().end();
443        ++i)
444     if (suppr::function_suppression_sptr suppr = is_function_suppression(*i))
445       {
446 	if (require_drop_property && !(*i)->get_drops_artifact_from_ir())
447 	  continue;
448 	if (!fn_name.empty()
449 	    && ctxt.suppression_matches_function_name(*suppr, fn_name))
450 	  return true;
451 	if (!fn_linkage_name.empty()
452 	    && ctxt.suppression_matches_function_sym_name(*suppr,
453 							  fn_linkage_name))
454 	  return true;
455       }
456   return false;
457 }
458 // </function_suppression stuff>
459 
460 // <variable_suppression stuff>
461 /// The type of the private data of the @ref variable_suppression
462 /// type.
463 struct variable_suppression::priv
464 {
465   friend class variable_suppression;
466 
467   change_kind				change_kind_;
468   string				name_;
469   string				name_regex_str_;
470   mutable regex::regex_t_sptr		name_regex_;
471   string				name_not_regex_str_;
472   mutable regex::regex_t_sptr		name_not_regex_;
473   string				symbol_name_;
474   string				symbol_name_regex_str_;
475   mutable regex::regex_t_sptr		symbol_name_regex_;
476   string				symbol_name_not_regex_str_;
477   mutable regex::regex_t_sptr		symbol_name_not_regex_;
478   string				symbol_version_;
479   string				symbol_version_regex_str_;
480   mutable regex::regex_t_sptr		symbol_version_regex_;
481   string				type_name_;
482   string				type_name_regex_str_;
483   mutable regex::regex_t_sptr		type_name_regex_;
484 
privpriv485   priv(const string& name,
486        const string& name_regex_str,
487        const string& symbol_name,
488        const string& symbol_name_regex_str,
489        const string& symbol_version,
490        const string& symbol_version_regex_str,
491        const string& type_name,
492        const string& type_name_regex_str)
493     : change_kind_(ALL_CHANGE_KIND),
494       name_(name),
495       name_regex_str_(name_regex_str),
496       symbol_name_(symbol_name),
497       symbol_name_regex_str_(symbol_name_regex_str),
498       symbol_version_(symbol_version),
499       symbol_version_regex_str_(symbol_version_regex_str),
500       type_name_(type_name),
501       type_name_regex_str_(type_name_regex_str)
502   {}
503 
504   /// Getter for a pointer to a regular expression object built from
505   /// the regular expression string
506   /// variable_suppression::priv::name_regex_str_.
507   ///
508   /// If that string is empty, then an empty regular expression object
509   /// pointer is returned.
510   ///
511   /// @return a pointer to the regular expression object of
512   /// variable_suppression::priv::name_regex_str_.
513   const regex::regex_t_sptr
get_name_regexpriv514   get_name_regex() const
515   {
516     if (!name_regex_ && !name_regex_str_.empty())
517       name_regex_ = regex::compile(name_regex_str_);
518     return name_regex_;
519   }
520 
521   /// Getter for a pointer to a regular expression object built from
522   /// the regular expression string
523   /// variable_suppression::priv::name_not_regex_str_.
524   ///
525   /// If that string is empty, then an empty regular expression object
526   /// pointer is returned.
527   ///
528   /// @return a pointer to the regular expression object of
529   /// variable_suppression::priv::name_not_regex_str_..
530   const regex::regex_t_sptr
get_name_not_regexpriv531   get_name_not_regex() const
532   {
533     if (!name_not_regex_ && !name_not_regex_str_.empty())
534       name_not_regex_ = regex::compile(name_not_regex_str_);
535     return name_not_regex_;
536   }
537 
538   /// Getter for a pointer to a regular expression object built from
539   /// the regular expression string
540   /// variable_suppression::priv::symbol_name_regex_str_.
541   ///
542   /// If that string is empty, then an empty regular expression object
543   /// pointer is returned.
544   ///
545   /// @return a pointer to the regular expression object of
546   /// variable_suppression::priv::symbol_name_regex_str_.
547   const regex::regex_t_sptr
get_symbol_name_regexpriv548   get_symbol_name_regex() const
549   {
550     if (!symbol_name_regex_ && !symbol_name_regex_str_.empty())
551       symbol_name_regex_ = regex::compile(symbol_name_regex_str_);
552     return symbol_name_regex_;
553   }
554 
555   /// Getter for a pointer to a regular expression object built from
556   /// the regular expression string
557   /// variable_suppression::priv::symbol_name_not_regex_str_.
558   ///
559   /// If that string is empty, then an empty regular expression object
560   /// pointer is returned.
561   ///
562   /// @return a pointer to the regular expression object of
563   /// variable_suppression::priv::symbol_name_not_regex_str_.
564   const regex::regex_t_sptr
get_symbol_name_not_regexpriv565   get_symbol_name_not_regex() const
566   {
567     if (!symbol_name_not_regex_ && !symbol_name_not_regex_str_.empty())
568       symbol_name_not_regex_ = regex::compile(symbol_name_not_regex_str_);
569     return symbol_name_not_regex_;
570   }
571 
572   /// Getter for a pointer to a regular expression object built from
573   /// the regular expression string
574   /// variable_suppression::priv::symbol_version_regex_str_.
575   ///
576   /// If that string is empty, then an empty regular expression object
577   /// pointer is returned.
578   ///
579   /// @return a pointer to the regular expression object of
580   /// variable_suppression::priv::symbol_version_regex_str_.
581   const regex::regex_t_sptr
get_symbol_version_regexpriv582   get_symbol_version_regex()  const
583   {
584     if (!symbol_version_regex_ && !symbol_version_regex_str_.empty())
585       symbol_version_regex_ = regex::compile(symbol_version_regex_str_);
586     return symbol_version_regex_;
587   }
588 
589   /// Getter for a pointer to a regular expression object built from
590   /// the regular expression string
591   /// variable_suppression::priv::type_name_regex_str_.
592   ///
593   /// If that string is empty, then an empty regular expression object
594   /// pointer is returned.
595   ///
596   /// @return a pointer to the regular expression object of
597   /// variable_suppression::priv::type_name_regex_str_.
598   const regex::regex_t_sptr
get_type_name_regexpriv599   get_type_name_regex() const
600   {
601     if (!type_name_regex_ && !type_name_regex_str_.empty())
602       type_name_regex_ = regex::compile(type_name_regex_str_);
603     return type_name_regex_;
604   }
605 };// end class variable_supppression::priv
606 
607 template <typename ReadContextType>
608 bool
609 variable_is_suppressed(const ReadContextType&	ctxt,
610 		       const string&		var_name,
611 		       const string&		var_linkage_name,
612 		       bool			require_drop_property = false)
613 {
614   for (suppr::suppressions_type::const_iterator i =
615 	 ctxt.get_suppressions().begin();
616        i != ctxt.get_suppressions().end();
617        ++i)
618     if (suppr::variable_suppression_sptr suppr = is_variable_suppression(*i))
619       {
620 	if (require_drop_property && !(*i)->get_drops_artifact_from_ir())
621 	  continue;
622 	if (!var_name.empty()
623 	    && ctxt.suppression_matches_variable_name(*suppr, var_name))
624 	  return true;
625 	if (!var_linkage_name.empty()
626 	    && ctxt.suppression_matches_variable_sym_name(*suppr,
627 							  var_linkage_name))
628 	  return true;
629       }
630   return false;
631 }
632 
633 // </variable_suppression stuff>
634 
635 // <type_suppression stuff>
636 /// The private data for @ref type_suppression.
637 class type_suppression::priv
638 {
639   string				type_name_regex_str_;
640   mutable regex::regex_t_sptr		type_name_regex_;
641   string				type_name_;
642   string				type_name_not_regex_str_;
643   mutable regex::regex_t_sptr		type_name_not_regex_;
644   bool					consider_type_kind_;
645   type_suppression::type_kind		type_kind_;
646   bool					consider_reach_kind_;
647   type_suppression::reach_kind		reach_kind_;
648   type_suppression::insertion_ranges	insertion_ranges_;
649   unordered_set<string>			source_locations_to_keep_;
650   string				source_location_to_keep_regex_str_;
651   mutable regex::regex_t_sptr		source_location_to_keep_regex_;
652   mutable vector<string>		changed_enumerator_names_;
653 
654   priv();
655 
656 public:
priv(const string & type_name_regexp,const string & type_name,bool consider_type_kind,type_suppression::type_kind type_kind,bool consider_reach_kind,type_suppression::reach_kind reach_kind)657   priv(const string&			type_name_regexp,
658        const string&			type_name,
659        bool				consider_type_kind,
660        type_suppression::type_kind	type_kind,
661        bool				consider_reach_kind,
662        type_suppression::reach_kind	reach_kind)
663     : type_name_regex_str_(type_name_regexp),
664       type_name_(type_name),
665       consider_type_kind_(consider_type_kind),
666       type_kind_(type_kind),
667       consider_reach_kind_(consider_reach_kind),
668       reach_kind_(reach_kind)
669   {}
670 
671   /// Get the regular expression object associated to the 'type_name_regex'
672   /// property of @ref type_suppression.
673   ///
674   /// If the regular expression object is not created, this method
675   /// creates it and returns it.
676   ///
677   /// If the 'type_name_regex' property of @ref type_suppression is
678   /// empty then this method returns nil.
679   const regex::regex_t_sptr
get_type_name_regex()680   get_type_name_regex() const
681   {
682     if (!type_name_regex_ && !type_name_regex_str_.empty())
683       type_name_regex_ = regex::compile(type_name_regex_str_);
684     return type_name_regex_;
685   }
686 
687   /// Setter for the type_name_regex object.
688   ///
689   /// @param r the new type_name_regex object.
690   void
set_type_name_regex(regex::regex_t_sptr r)691   set_type_name_regex(regex::regex_t_sptr r)
692   {type_name_regex_ = r;}
693 
694   /// Get the regular expression object associated to the
695   /// 'type_name_not_regex' property of @ref type_suppression.
696   ///
697   /// If the regular expression object is not created, this method
698   /// creates it and returns it.
699   ///
700   /// If the 'type_name_not_regex' property of @ref type_suppression is
701   /// empty then this method returns nil.
702   const regex::regex_t_sptr
get_type_name_not_regex()703   get_type_name_not_regex() const
704   {
705     if (!type_name_not_regex_ && !type_name_not_regex_str_.empty())
706       type_name_not_regex_ = regex::compile(type_name_not_regex_str_);
707     return type_name_not_regex_;
708   }
709 
710   /// Setter for the type_name_not_regex object.
711   ///
712   /// @param r the new type_name_not_regex object.
713   void
set_type_name_not_regex(regex::regex_t_sptr r)714   set_type_name_not_regex(regex::regex_t_sptr r)
715   {type_name_not_regex_ = r;}
716 
717   /// Getter for the string that denotes the 'type_name_not_regex'
718   /// property.
719   ///
720   /// @return the value of the string value of the
721   /// 'type_name_not_regex' property.
722   const string&
get_type_name_not_regex_str()723   get_type_name_not_regex_str() const
724   {return type_name_not_regex_str_;}
725 
726   /// Setter for the string that denotes the 'type_name_not_regex'
727   /// property.
728   ///
729   /// @return the value of the string value of the
730   /// 'type_name_not_regex' property.
731   void
set_type_name_not_regex_str(const string regex_str)732   set_type_name_not_regex_str(const string regex_str)
733   {type_name_not_regex_str_ = regex_str;}
734 
735   /// Getter for the source_location_to_keep_regex object.
736   ///
737   /// This function builds the regex if it's not yet built.
738   const regex::regex_t_sptr
get_source_location_to_keep_regex()739   get_source_location_to_keep_regex() const
740   {
741     if (!source_location_to_keep_regex_
742 	&& !source_location_to_keep_regex_str_.empty())
743       source_location_to_keep_regex_ =
744 	  regex::compile(source_location_to_keep_regex_str_);
745     return source_location_to_keep_regex_;
746   }
747 
748   /// Setter for the source_location_to_keep_regex object.
749   ///
750   /// @param r the new regex object.
751   void
set_source_location_to_keep_regex(regex::regex_t_sptr r)752   set_source_location_to_keep_regex(regex::regex_t_sptr r)
753   {source_location_to_keep_regex_ = r;}
754 
755   friend class type_suppression;
756 }; // class type_suppression::priv
757 
758 bool
759 suppression_matches_type_name(const suppr::type_suppression&	s,
760 			      const string&			type_name);
761 
762 bool
763 suppression_matches_type_name(const suppr::type_suppression&	s,
764 			      const scope_decl*		scope,
765 			      const type_base_sptr&		type);
766 
767 bool
768 suppression_matches_type_location(const type_suppression&	s,
769 				  const location&		loc);
770 
771 bool
772 suppression_matches_type_location(const type_suppression&	s,
773 				  const type_base_sptr&	type);
774 
775 bool
776 suppression_matches_type_name_or_location(const type_suppression& s,
777 					  const string& type_name,
778 					  const location& type_location);
779 
780 /// Test if a type (designated by its name and location) is suppressed
781 /// by at least one suppression specification associated with a given
782 /// read context.
783 ///
784 /// @param ctxt the read context to consider.
785 ///
786 /// @param type_name the name of the type to consider.
787 ///
788 /// @param type_location the location of the type to consider.
789 ///
790 /// @param require_drop_property if set to "true", tests if the type
791 /// is suppressed and if its representation is dropped from the ABI
792 /// corpus being built.  Otherwise, if set to "false", only test if
793 /// the type is suppressed.
794 ///
795 /// @return true iff at least one type specification matches a type
796 /// with name @p type_name and with location @p type_location.
797 template <typename ReadContextType>
798 bool
type_is_suppressed(const ReadContextType & ctxt,const string & type_name,const location & type_location)799 type_is_suppressed(const ReadContextType&	ctxt,
800 		   const string&		type_name,
801 		   const location&		type_location)
802 {
803   bool type_is_private = false;
804   return type_is_suppressed(ctxt, type_name, type_location, type_is_private);
805 }
806 
807 /// Test if a type (designated by its name and location) is suppressed
808 /// by at least one suppression specification associated with a given
809 /// read context.
810 ///
811 /// @param ctxt the read context to consider.
812 ///
813 /// @param type_name the name of the type to consider.
814 ///
815 /// @param type_location the location of the type to consider.
816 ///
817 /// @param type_is_private out parameter. If the type is suppressed
818 /// because it's private then this out parameter is set to true.
819 ///
820 /// @param require_drop_property if set to "true", tests if the type
821 /// is suppressed and if its representation is dropped from the ABI
822 /// corpus being built.  Otherwise, if set to "false", only test if
823 /// the type is suppressed.
824 ///
825 /// @return true iff at least one type specification matches a type
826 /// with name @p type_name and with location @p type_location.
827 template <typename ReadContextType>
828 bool
829 type_is_suppressed(const ReadContextType&	ctxt,
830 		   const string&		type_name,
831 		   const location&		type_location,
832 		   bool&			type_is_private,
833 		   bool require_drop_property = false)
834 {
835   for (suppr::suppressions_type::const_iterator i =
836 	 ctxt.get_suppressions().begin();
837        i != ctxt.get_suppressions().end();
838        ++i)
839     if (suppr::type_suppression_sptr suppr = is_type_suppression(*i))
840       {
841 	if (require_drop_property && !(*i)->get_drops_artifact_from_ir())
842 	  continue;
843 	if (ctxt.suppression_matches_type_name_or_location(*suppr, type_name,
844 							   type_location))
845 	  {
846 	    if (is_private_type_suppr_spec(*suppr))
847 	      type_is_private = true;
848 
849 	    return true;
850 	  }
851       }
852 
853   type_is_private = false;
854   return false;
855 }
856 
857 /// Test if a given ELF symbol is suppressed by a suppression
858 /// specification.
859 ///
860 /// @param ctxt the read context to use.
861 ///
862 /// @param sym_name the name of the symbol to consider.
863 ///
864 /// @param sym_type the type of the symbol to consider.
865 ///
866 /// @return true iff the elf symbol denoted by @p sym_name and @p
867 /// sym_type is suppressed.
868 template<typename ReadContextType>
869 bool
is_elf_symbol_suppressed(const ReadContextType & ctxt,const string & sym_name,elf_symbol::type sym_type)870 is_elf_symbol_suppressed(const ReadContextType& ctxt,
871 			 const string& sym_name,
872 			 elf_symbol::type sym_type)
873 {
874   if (elf_symbol_is_function(sym_type))
875     return suppr::function_is_suppressed(ctxt, /*fn_name=*/"",
876 					 /*symbol_name=*/sym_name);
877   else if (elf_symbol_is_variable(sym_type))
878     return suppr::variable_is_suppressed(ctxt, /*var_name=*/"",
879 					 /*symbol_name=*/sym_name);
880 
881   return false;
882 }
883 
884 // </type_suppression stuff>
885 
886 }// end namespace suppr
887 } // end namespace abigail
888 
889 #endif // __ABG_SUPPRESSION_PRIV_H__
890