f157c35819e293fcfff568be343eed40434c3180
[platform/upstream/libabigail.git] / src / abg-suppression-priv.h
1 // -*- Mode: C++ -*-
2 //
3 // Copyright (C) 2016-2019 Red Hat, Inc.
4 //
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
10 // later version.
11
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.
16
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/>.
20 //
21 // Author: Dodji Seketeli
22
23 /// @file
24 ///
25 /// This contains the private implementation of the suppression engine
26 /// of libabigail.
27
28 #ifndef __ABG_SUPPRESSION_PRIV_H__
29 #define __ABG_SUPPRESSION_PRIV_H__
30
31 #include "abg-fwd.h"
32 #include "abg-suppression.h"
33 #include "abg-sptr-utils.h"
34
35 namespace abigail
36 {
37
38 namespace suppr
39 {
40
41 // <suppression_base stuff>
42
43 /// The private data of @ref suppression_base.
44 class suppression_base::priv
45 {
46   bool                                  is_artificial_;
47   bool                                  drops_artifact_;
48   string                                label_;
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_;
57
58 public:
59   priv()
60     : is_artificial_(),
61       drops_artifact_()
62   {}
63
64   priv(const string& label)
65     : is_artificial_(),
66       drops_artifact_(),
67       label_(label)
68   {}
69
70   priv(const string& label,
71        const string& file_name_regex_str,
72        const string& file_name_not_regex_str)
73     : is_artificial_(),
74       drops_artifact_(),
75       label_(label),
76       file_name_regex_str_(file_name_regex_str),
77       file_name_not_regex_str_(file_name_not_regex_str)
78   {}
79
80   friend class suppression_base;
81
82   /// Get the regular expression object associated to the 'file_name_regex'
83   /// property of @ref suppression_base.
84   ///
85   /// If the regular expression object is not created, this method
86   /// creates it and returns it.
87   ///
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
92   {
93     if (!file_name_regex_)
94       {
95         if (!file_name_regex_str_.empty())
96           {
97             sptr_utils::regex_t_sptr r = sptr_utils::build_sptr<regex_t>();
98             if (regcomp(r.get(),
99                         file_name_regex_str_.c_str(),
100                         REG_EXTENDED) == 0)
101               file_name_regex_ = r;
102           }
103       }
104     return file_name_regex_;
105   }
106
107   /// Get the regular expression object associated to the
108   /// 'file_name_not_regex' property of @ref suppression_base.
109   ///
110   /// If the regular expression object is not created, this method
111   /// creates it and returns it.
112   ///
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
117   {
118     if (!file_name_not_regex_)
119       {
120         if (!file_name_not_regex_str_.empty())
121           {
122             sptr_utils::regex_t_sptr r = sptr_utils::build_sptr<regex_t>();
123             if (regcomp(r.get(),
124                         file_name_not_regex_str_.c_str(),
125                         REG_EXTENDED) == 0)
126               file_name_not_regex_ = r;
127           }
128       }
129     return file_name_not_regex_;
130   }
131
132   /// Get the regular expression object associated to the
133   /// 'soname_regex' property of @ref suppression_base.
134   ///
135   /// If the regular expression object is not created, this method
136   /// creates it and returns it.
137   ///
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
142   {
143     if (!soname_regex_)
144       {
145         if (!soname_regex_str_.empty())
146           {
147             sptr_utils::regex_t_sptr r = sptr_utils::build_sptr<regex_t>();
148             if (regcomp(r.get(),
149                         soname_regex_str_.c_str(),
150                         REG_EXTENDED) == 0)
151               soname_regex_ = r;
152           }
153       }
154     return soname_regex_;
155   }
156
157   /// Get the regular expression object associated to the
158   /// 'soname_not_regex' property of @ref suppression_base.
159   ///
160   /// If the regular expression object is not created, this method
161   /// creates it and returns it.
162   ///
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
167   {
168     if (!soname_not_regex_)
169       {
170         if (!soname_not_regex_str_.empty())
171           {
172             sptr_utils::regex_t_sptr r = sptr_utils::build_sptr<regex_t>();
173             if (regcomp(r.get(),
174                         soname_not_regex_str_.c_str(),
175                         REG_EXTENDED) == 0)
176               soname_not_regex_ = r;
177           }
178       }
179     return soname_not_regex_;
180   }
181
182   bool
183   matches_soname(const string& soname) const
184   {
185     if (sptr_utils::regex_t_sptr regexp = get_soname_regex())
186       if (regexec(regexp.get(), soname.c_str(), 0, NULL, 0) != 0)
187         return false;
188
189     if (sptr_utils::regex_t_sptr regexp = get_soname_not_regex())
190       if (regexec(regexp.get(), soname.c_str(), 0, NULL, 0) == 0)
191         return false;
192
193     return true;
194   }
195
196   bool
197   matches_binary_name(const string& binary_name) const
198   {
199     if (sptr_utils::regex_t_sptr regexp = get_file_name_regex())
200       if (regexec(regexp.get(), binary_name.c_str(),
201                   0, NULL, 0) != 0)
202         return false;
203
204     if (sptr_utils::regex_t_sptr regexp = get_file_name_not_regex())
205       if (regexec(regexp.get(), binary_name.c_str(),
206                   0, NULL, 0) == 0)
207         return false;
208
209     return true;
210   }
211
212 }; // end clas suppression_base::priv
213
214 // </suppression_base stuff>
215
216 // <function_suppression stuff>
217
218 class function_suppression::parameter_spec::priv
219 {
220   friend class function_suppression::parameter_spec;
221   friend class function_suppression;
222
223   size_t                                index_;
224   string                                type_name_;
225   string                                type_name_regex_str_;
226   mutable sptr_utils::regex_t_sptr      type_name_regex_;
227
228   priv()
229     : index_()
230   {}
231
232   priv(size_t i, const string& tn)
233     : index_(i), type_name_(tn)
234   {}
235
236   priv(size_t i, const string& tn, const string& tn_regex)
237     : index_(i), type_name_(tn), type_name_regex_str_(tn_regex)
238   {}
239
240   const sptr_utils::regex_t_sptr
241   get_type_name_regex() const
242   {
243     if (!type_name_regex_ && !type_name_regex_str_.empty())
244       {
245         sptr_utils::regex_t_sptr r = sptr_utils::build_sptr<regex_t>();
246         if (regcomp(r.get(),
247                     type_name_regex_str_.c_str(),
248                     REG_EXTENDED) == 0)
249           type_name_regex_ = r;
250       }
251     return type_name_regex_;
252   }
253 }; // end class function_suppression::parameter_spec::priv
254
255
256 /// The type of the private data of the @ref function_suppression
257 /// type.
258 struct function_suppression::priv
259 {
260   friend class function_suppression;
261
262   change_kind                           change_kind_;
263   string                                name_;
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_;
272   string                                symbol_name_;
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_;
279
280   priv():
281     change_kind_(ALL_CHANGE_KIND),
282     allow_other_aliases_(true)
283   {}
284
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),
295       name_(name),
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)
305   {}
306
307
308   /// Getter for a pointer to a regular expression object built from
309   /// the regular expression string
310   /// function_suppression::priv::name_regex_str_.
311   ///
312   /// If that string is empty, then an empty regular expression object
313   /// pointer is returned.
314   ///
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
319   {
320     if (!name_regex_ && !name_regex_str_.empty())
321       {
322         sptr_utils::regex_t_sptr r = sptr_utils::build_sptr<regex_t>();
323         if (regcomp(r.get(),
324                     name_regex_str_.c_str(),
325                     REG_EXTENDED) == 0)
326           name_regex_ = r;
327       }
328     return name_regex_;
329   }
330
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_.
334   ///
335   /// If that string is empty, then an empty regular expression object
336   /// pointer is returned.
337   ///
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
342   {
343     if (!name_not_regex_ && !name_not_regex_str_.empty())
344       {
345         sptr_utils::regex_t_sptr r = sptr_utils::build_sptr<regex_t>();
346         if (regcomp(r.get(),
347                     name_not_regex_str_.c_str(),
348                     REG_EXTENDED) == 0)
349           name_not_regex_ = r;
350       }
351     return name_not_regex_;
352   }
353
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_.
357   ///
358   /// If that string is empty, then an empty regular expression object
359   /// pointer is returned.
360   ///
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
365   {
366     if (!return_type_regex_ && !return_type_regex_str_.empty())
367       {
368         sptr_utils::regex_t_sptr r = sptr_utils::build_sptr<regex_t>();
369         if (regcomp(r.get(),
370                     return_type_regex_str_.c_str(),
371                     REG_EXTENDED) == 0)
372           return_type_regex_ = r;
373       }
374     return return_type_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_name_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_name_regex_str_.
386   const sptr_utils::regex_t_sptr
387   get_symbol_name_regex() const
388   {
389     if (!symbol_name_regex_ && !symbol_name_regex_str_.empty())
390       {
391         sptr_utils::regex_t_sptr r = sptr_utils::build_sptr<regex_t>();
392         if (regcomp(r.get(),
393                     symbol_name_regex_str_.c_str(),
394                     REG_EXTENDED) == 0)
395           symbol_name_regex_ = r;
396       }
397     return symbol_name_regex_;
398   }
399
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_.
403   ///
404   /// If that string is empty, then an empty regular expression object
405   /// pointer is returned.
406   ///
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
411   {
412     if (!symbol_version_regex_ && ! symbol_version_regex_str_.empty())
413       {
414         sptr_utils::regex_t_sptr r = sptr_utils::build_sptr<regex_t>();
415         if (regcomp(r.get(),
416                     symbol_version_regex_str_.c_str(),
417                     REG_EXTENDED) == 0)
418           symbol_version_regex_ = r;
419       }
420     return symbol_version_regex_;
421   }
422 }; // end class function_suppression::priv
423
424 bool
425 suppression_matches_function_name(const suppr::function_suppression& s,
426                                   const string& fn_name);
427
428 bool
429 suppression_matches_function_sym_name(const suppr::function_suppression& s,
430                                       const string& fn_linkage_name);
431
432 bool
433 suppression_matches_variable_name(const suppr::variable_suppression& s,
434                                   const string& var_name);
435
436
437 bool
438 suppression_matches_variable_sym_name(const suppr::variable_suppression& s,
439                                       const string& var_linkage_name);
440
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.
445 ///
446 /// @param ctxt the reading context of interest.
447 ///
448 /// @param fn_name the name of the function that a specification can
449 /// match.
450 ///
451 /// @param fn_linkage_name the linkage name of the function that a
452 /// specification can match.
453 ///
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.
458 ///
459 /// @return true iff at least one function specification matches a
460 /// function with name @p fn_name or with linkage name @p
461 /// fn_linkage_name.
462 template <typename ReadContextType>
463 bool
464 function_is_suppressed(const ReadContextType&   ctxt,
465                        const string&            fn_name,
466                        const string&            fn_linkage_name,
467                        bool                     require_drop_property = false)
468 {
469   for (suppr::suppressions_type::const_iterator i =
470          ctxt.get_suppressions().begin();
471        i != ctxt.get_suppressions().end();
472        ++i)
473     if (suppr::function_suppression_sptr suppr = is_function_suppression(*i))
474       {
475         if (require_drop_property && !(*i)->get_drops_artifact_from_ir())
476           continue;
477         if (ctxt.suppression_matches_function_name(*suppr, fn_name))
478           return true;
479         if (ctxt.suppression_matches_function_sym_name(*suppr,
480                                                        fn_linkage_name))
481           return true;
482       }
483   return false;
484 }
485 // </function_suppression stuff>
486
487 // <variable_suppression stuff>
488 /// The type of the private data of the @ref variable_suppression
489 /// type.
490 struct variable_suppression::priv
491 {
492   friend class variable_suppression;
493
494   change_kind                           change_kind_;
495   string                                name_;
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_;
500   string                                symbol_name_;
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_;
506   string                                type_name_;
507   string                                type_name_regex_str_;
508   mutable sptr_utils::regex_t_sptr      type_name_regex_;
509
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),
519       name_(name),
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)
527   {}
528
529   /// Getter for a pointer to a regular expression object built from
530   /// the regular expression string
531   /// variable_suppression::priv::name_regex_str_.
532   ///
533   /// If that string is empty, then an empty regular expression object
534   /// pointer is returned.
535   ///
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
540   {
541     if (!name_regex_ && !name_regex_str_.empty())
542       {
543         sptr_utils::regex_t_sptr r = sptr_utils::build_sptr<regex_t>();
544         if (regcomp(r.get(),
545                     name_regex_str_.c_str(),
546                     REG_EXTENDED) == 0)
547           name_regex_ = r;
548       }
549     return name_regex_;
550   }
551
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_.
555   ///
556   /// If that string is empty, then an empty regular expression object
557   /// pointer is returned.
558   ///
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
563   {
564     if (!name_not_regex_ && !name_not_regex_str_.empty())
565       {
566         sptr_utils::regex_t_sptr r = sptr_utils::build_sptr<regex_t>();
567         if (regcomp(r.get(),
568                     name_not_regex_str_.c_str(),
569                     REG_EXTENDED) == 0)
570           name_not_regex_ = r;
571       }
572     return name_not_regex_;
573   }
574
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_.
578   ///
579   /// If that string is empty, then an empty regular expression object
580   /// pointer is returned.
581   ///
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
586   {
587     if (!symbol_name_regex_ && !symbol_name_regex_str_.empty())
588       {
589         sptr_utils::regex_t_sptr r = sptr_utils::build_sptr<regex_t>();
590         if (regcomp(r.get(),
591                     symbol_name_regex_str_.c_str(),
592                     REG_EXTENDED) == 0)
593           symbol_name_regex_ = r;
594       }
595     return symbol_name_regex_;
596   }
597
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_.
601   ///
602   /// If that string is empty, then an empty regular expression object
603   /// pointer is returned.
604   ///
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
609   {
610     if (!symbol_version_regex_ && !symbol_version_regex_str_.empty())
611       {
612         sptr_utils::regex_t_sptr r = sptr_utils::build_sptr<regex_t>();
613         if (regcomp(r.get(),
614                     symbol_version_regex_str_.c_str(),
615                     REG_EXTENDED) == 0)
616           symbol_version_regex_ = r;
617       }
618     return symbol_version_regex_;
619   }
620
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_.
624   ///
625   /// If that string is empty, then an empty regular expression object
626   /// pointer is returned.
627   ///
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
632   {
633     if (!type_name_regex_ && !type_name_regex_str_.empty())
634       {
635         sptr_utils::regex_t_sptr r = sptr_utils::build_sptr<regex_t>();
636         if (regcomp(r.get(),
637                     type_name_regex_str_.c_str(),
638                     REG_EXTENDED) == 0)
639           type_name_regex_ = r;
640       }
641     return type_name_regex_;
642   }
643 };// end class variable_supppression::priv
644
645 template <typename ReadContextType>
646 bool
647 variable_is_suppressed(const ReadContextType&   ctxt,
648                        const string&            var_name,
649                        const string&            var_linkage_name,
650                        bool                     require_drop_property = false)
651 {
652   for (suppr::suppressions_type::const_iterator i =
653          ctxt.get_suppressions().begin();
654        i != ctxt.get_suppressions().end();
655        ++i)
656     if (suppr::variable_suppression_sptr suppr = is_variable_suppression(*i))
657       {
658         if (require_drop_property && !(*i)->get_drops_artifact_from_ir())
659           continue;
660         if (ctxt.suppression_matches_variable_name(*suppr, var_name))
661           return true;
662         if (ctxt.suppression_matches_variable_sym_name(*suppr,
663                                                        var_linkage_name))
664           return true;
665       }
666   return false;
667 }
668
669 // </variable_suppression stuff>
670
671 // <type_suppression stuff>
672 /// The private data for @ref type_suppression.
673 class type_suppression::priv
674 {
675   string                                type_name_regex_str_;
676   mutable sptr_utils::regex_t_sptr      type_name_regex_;
677   string                                type_name_;
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_;
687
688   priv();
689
690 public:
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)
703   {}
704
705   /// Get the regular expression object associated to the 'type_name_regex'
706   /// property of @ref type_suppression.
707   ///
708   /// If the regular expression object is not created, this method
709   /// creates it and returns it.
710   ///
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
715   {
716     if (!type_name_regex_)
717       {
718         if (!type_name_regex_str_.empty())
719           {
720             sptr_utils::regex_t_sptr r = sptr_utils::build_sptr<regex_t>();
721             if (regcomp(r.get(),
722                         type_name_regex_str_.c_str(),
723                         REG_EXTENDED) == 0)
724               type_name_regex_ = r;
725           }
726       }
727     return type_name_regex_;
728   }
729
730   /// Setter for the type_name_regex object.
731   ///
732   /// @param r the new type_name_regex object.
733   void
734   set_type_name_regex(sptr_utils::regex_t_sptr r)
735   {type_name_regex_ = r;}
736
737   /// Getter for the source_location_to_keep_regex object.
738   ///
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
742   {
743     if (!source_location_to_keep_regex_)
744       {
745         if (!source_location_to_keep_regex_str_.empty())
746           {
747             sptr_utils::regex_t_sptr r = sptr_utils::build_sptr<regex_t>();
748             if (regcomp(r.get(),
749                         source_location_to_keep_regex_str_.c_str(),
750                         REG_EXTENDED) == 0)
751               source_location_to_keep_regex_ = r;
752           }
753       }
754     return source_location_to_keep_regex_;
755   }
756
757   /// Setter for the source_location_to_keep_regex object.
758   ///
759   /// @param r the new regex object.
760   void
761   set_source_location_to_keep_regex(sptr_utils::regex_t_sptr r)
762   {source_location_to_keep_regex_ = r;}
763
764   friend class type_suppression;
765 }; // class type_suppression::priv
766
767 bool
768 suppression_matches_type_name(const suppr::type_suppression&    s,
769                               const string&                     type_name);
770
771 bool
772 suppression_matches_type_name(const suppr::type_suppression&    s,
773                               const scope_decl*         scope,
774                               const type_base_sptr&             type);
775
776 bool
777 suppression_matches_type_location(const type_suppression&       s,
778                                   const location&               loc);
779
780 bool
781 suppression_matches_type_location(const type_suppression&       s,
782                                   const type_base_sptr& type);
783
784 bool
785 suppression_matches_type_name_or_location(const type_suppression& s,
786                                           const string& type_name,
787                                           const location& type_location);
788
789 /// Test if a type (designated by its name and location) is suppressed
790 /// by at least one suppression specification associated with a given
791 /// read context.
792 ///
793 /// @param ctxt the read context to consider.
794 ///
795 /// @param type_name the name of the type to consider.
796 ///
797 /// @param type_location the location of the type to consider.
798 ///
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.
803 ///
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>
807 bool
808 type_is_suppressed(const ReadContextType&       ctxt,
809                    const string&                type_name,
810                    const location&              type_location)
811 {
812   bool type_is_private = false;
813   return type_is_suppressed(ctxt, type_name, type_location, type_is_private);
814 }
815
816 /// Test if a type (designated by its name and location) is suppressed
817 /// by at least one suppression specification associated with a given
818 /// read context.
819 ///
820 /// @param ctxt the read context to consider.
821 ///
822 /// @param type_name the name of the type to consider.
823 ///
824 /// @param type_location the location of the type to consider.
825 ///
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.
828 ///
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.
833 ///
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>
837 bool
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)
843 {
844   for (suppr::suppressions_type::const_iterator i =
845          ctxt.get_suppressions().begin();
846        i != ctxt.get_suppressions().end();
847        ++i)
848     if (suppr::type_suppression_sptr suppr = is_type_suppression(*i))
849       {
850         if (require_drop_property && !(*i)->get_drops_artifact_from_ir())
851           continue;
852         if (ctxt.suppression_matches_type_name_or_location(*suppr, type_name,
853                                                            type_location))
854           {
855             if (is_private_type_suppr_spec(*suppr))
856               type_is_private = true;
857
858             return true;
859           }
860       }
861
862   type_is_private = false;
863   return false;
864 }
865
866 // </type_suppression stuff>
867
868 }// end namespace suppr
869 } // end namespace abigail
870
871 #endif // __ABG_SUPPRESSION_PRIV_H__