415e74f5b9f3774007e6d0c8e1b8b50edddc8ff7
[platform/upstream/libabigail.git] / include / abg-suppression.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 #ifndef __ABG_SUPPRESSION_H__
24 #define __ABG_SUPPRESSION_H__
25
26 #include "abg-cxx-compat.h"
27 #include "abg-ini.h"
28 #include "abg-comparison.h"
29
30 namespace abigail
31 {
32
33 /// @brief an engine to suppress the parts of the result of comparing
34 /// two sets of ABI artifacts.
35 ///
36 /// The user specifies the kind of changes between ABI artefact she
37 /// wants to see suppressed.  That suppression specification is done
38 /// in an INI format.
39 ///
40 /// That INI file is parsed and represented internally using the types
41 /// that are defined in this namespace.
42 namespace suppr
43 {
44
45 using namespace abigail::comparison;
46 using abg_compat::unordered_set;
47
48 /// Base type of the suppression specifications types.
49 ///
50 /// This abstracts a suppression specification.  It's a way to specify
51 /// how to drop reports about a particular diff node on the floor, if
52 /// it matches the supppression specification.
53 class suppression_base
54 {
55   class priv;
56   typedef shared_ptr<priv> priv_sptr;
57
58   // Forbid default constructor
59   suppression_base();
60
61 public:
62   priv_sptr priv_;
63
64   suppression_base(const string& label);
65
66   suppression_base(const string& label,
67                    const string& file_name_regex_str,
68                    const string& file_name_not_regex_str);
69
70   bool
71   get_drops_artifact_from_ir() const;
72
73   void
74   set_drops_artifact_from_ir(bool) const;
75
76   bool
77   get_is_artificial() const;
78
79   void
80   set_is_artificial(bool);
81
82   const string
83   get_label() const;
84
85   void
86   set_label(const string&);
87
88   void
89   set_file_name_regex_str(const string& regexp);
90
91   const string&
92   get_file_name_regex_str() const;
93
94   void
95   set_file_name_not_regex_str(const string& regexp);
96
97   const string&
98   get_file_name_not_regex_str() const;
99
100   void
101   set_soname_regex_str(const string& regexp);
102
103   const string&
104   get_soname_regex_str() const;
105
106   void
107   set_soname_not_regex_str(const string& regexp);
108
109   const string&
110   get_soname_not_regex_str() const;
111
112   virtual bool
113   suppresses_diff(const diff*) const = 0;
114
115   virtual ~suppression_base();
116 }; // end class suppression_base
117
118 void
119 read_suppressions(std::istream& input,
120                   suppressions_type& suppressions);
121
122 void
123 read_suppressions(const string& file_path,
124                   suppressions_type& suppressions);
125
126 class type_suppression;
127
128 /// Convenience typedef for a shared pointer to type_suppression.
129 typedef shared_ptr<type_suppression> type_suppression_sptr;
130
131 /// Convenience typedef for vector of @ref type_suppression_sptr.
132 typedef vector<type_suppression_sptr> type_suppressions_type;
133
134 /// Abstraction of a type suppression specification.
135 ///
136 /// Specifies under which condition reports about a type diff node
137 /// should be dropped on the floor.
138 class type_suppression : public suppression_base
139 {
140   class priv;
141   typedef shared_ptr<priv> priv_sptr;
142
143   // Forbid this;
144   type_suppression();
145
146 public:
147
148   priv_sptr priv_;
149
150   /// The kind of the type the current type suppression is supposed to
151   /// be about.
152   enum type_kind
153   {
154     UNKNOWN_TYPE_KIND,
155     CLASS_TYPE_KIND,
156     STRUCT_TYPE_KIND,
157     UNION_TYPE_KIND,
158     ENUM_TYPE_KIND,
159     ARRAY_TYPE_KIND,
160     TYPEDEF_TYPE_KIND,
161     BUILTIN_TYPE_KIND
162   }; // end enum type_kind
163
164   /// The different ways through which the type diff has been reached.
165   enum reach_kind
166   {
167     /// The type diff has been reached (from a function or variable
168     /// change) directly.
169     DIRECT_REACH_KIND = 0,
170
171     /// The type diff has been reached (from a function or variable
172     /// change) through a pointer.
173     POINTER_REACH_KIND,
174
175     /// The type diff has been reached (from a function or variable
176     /// change) through a reference; you know, like a c++ reference..
177     REFERENCE_REACH_KIND,
178
179     /// The type diff has been reached (from a function or variable
180     /// change) through either a reference or a pointer.
181     REFERENCE_OR_POINTER_REACH_KIND
182   }; // end enum reach_kind
183
184   class insertion_range;
185   /// A convenience typedef for a shared pointer to @ref
186   /// insertion_range.
187   typedef shared_ptr<insertion_range> insertion_range_sptr;
188   /// A convenience typedef for a vector of @ref insertion_range_sptr.
189   typedef vector<insertion_range_sptr> insertion_ranges;
190
191   type_suppression(const string& label,
192                    const string& type_name_regexp,
193                    const string& type_name);
194
195   virtual ~type_suppression();
196
197   void
198   set_type_name_regex_str(const string& name_regex_str);
199
200   const string&
201   get_type_name_regex_str() const;
202
203   void
204   set_type_name(const string& name);
205
206   const string&
207   get_type_name() const;
208
209   bool
210   get_consider_type_kind() const;
211
212   void
213   set_consider_type_kind(bool f);
214
215   void
216   set_type_kind(type_kind k);
217
218   type_kind
219   get_type_kind() const;
220
221   bool
222   get_consider_reach_kind() const;
223
224   void
225   set_consider_reach_kind(bool f);
226
227   reach_kind
228   get_reach_kind() const;
229
230   void
231   set_reach_kind(reach_kind k);
232
233   void
234   set_data_member_insertion_ranges(const insertion_ranges& r);
235
236   const insertion_ranges&
237   get_data_member_insertion_ranges() const;
238
239   insertion_ranges&
240   get_data_member_insertion_ranges();
241
242   const unordered_set<string>&
243   get_source_locations_to_keep() const;
244
245   unordered_set<string>&
246   get_source_locations_to_keep();
247
248   void
249   set_source_locations_to_keep(const unordered_set<string>&);
250
251   const string&
252   get_source_location_to_keep_regex_str() const;
253
254   void
255   set_source_location_to_keep_regex_str(const string&);
256
257   const vector<string>&
258   get_changed_enumerator_names() const;
259
260   void
261   set_changed_enumerator_names(const vector<string>&);
262
263   virtual bool
264   suppresses_diff(const diff* diff) const;
265
266   bool
267   suppresses_type(const type_base_sptr& type,
268                   const diff_context_sptr& ctxt) const;
269
270   bool
271   suppresses_type(const type_base_sptr& type) const;
272
273   bool
274   suppresses_type(const type_base_sptr& type,
275                   const scope_decl* type_scope) const;
276 }; // end type_suppression
277
278 type_suppression_sptr
279 is_type_suppression(const suppression_sptr);
280
281 /// The abstraction of a range of offsets in which a member of a type
282 /// might get inserted.
283 class type_suppression::insertion_range
284 {
285 public:
286
287   class boundary;
288   class integer_boundary;
289   class fn_call_expr_boundary;
290
291   /// Convenience typedef for a shared_ptr to @ref boundary
292   typedef shared_ptr<boundary> boundary_sptr;
293
294   /// Convenience typedef for a shared_ptr to a @ref integer_boundary
295   typedef shared_ptr<integer_boundary> integer_boundary_sptr;
296
297   /// Convenience typedef for a shared_ptr to a @ref
298   /// fn_call_expr_boundary
299   typedef shared_ptr<fn_call_expr_boundary> fn_call_expr_boundary_sptr;
300
301 private:
302   struct priv;
303   typedef shared_ptr<priv> priv_sptr;
304
305   priv_sptr priv_;
306
307 public:
308   insertion_range();
309
310   insertion_range(boundary_sptr begin, boundary_sptr end);
311
312   boundary_sptr
313   begin() const;
314
315  boundary_sptr
316   end() const;
317
318   static insertion_range::integer_boundary_sptr
319   create_integer_boundary(int value);
320
321   static insertion_range::fn_call_expr_boundary_sptr
322   create_fn_call_expr_boundary(ini::function_call_expr_sptr);
323
324   static insertion_range::fn_call_expr_boundary_sptr
325   create_fn_call_expr_boundary(const string&);
326
327   static bool
328   eval_boundary(boundary_sptr   boundary,
329                 class_decl_sptr context,
330                 ssize_t&        value);
331 }; // end class insertion_range
332
333 type_suppression::insertion_range::integer_boundary_sptr
334 is_integer_boundary(type_suppression::insertion_range::boundary_sptr);
335
336 type_suppression::insertion_range::fn_call_expr_boundary_sptr
337 is_fn_call_expr_boundary(type_suppression::insertion_range::boundary_sptr);
338
339 /// The abstraction of the boundary of an @ref insertion_range, in the
340 /// context of a @ref type_suppression
341 class type_suppression::insertion_range::boundary
342 {
343   struct priv;
344   typedef shared_ptr<priv> priv_sptr;
345
346   priv_sptr priv_;
347
348 public:
349   boundary();
350   virtual ~boundary();
351 };// end class type_suppression::insertion_range::boundary
352
353 /// An @ref insertion_range boundary that is expressed as an integer
354 /// value.  That integer value is usually a bit offset.
355 class type_suppression::insertion_range::integer_boundary
356   : public type_suppression::insertion_range::boundary
357 {
358   struct priv;
359   typedef shared_ptr<priv> priv_sptr;
360
361   priv_sptr priv_;
362
363   integer_boundary();
364
365 public:
366   integer_boundary(int value);
367   int as_integer() const;
368   operator int() const;
369   ~integer_boundary();
370 }; //end class type_suppression::insertion_range::integer_boundary
371
372 /// An @ref insertion_range boundary that is expressed as function
373 /// call expression.  The (integer) value of that expression is
374 /// usually a bit offset.
375 class type_suppression::insertion_range::fn_call_expr_boundary
376   : public type_suppression::insertion_range::boundary
377 {
378   struct priv;
379   typedef shared_ptr<priv> priv_sptr;
380
381   priv_sptr priv_;
382
383   fn_call_expr_boundary();
384
385 public:
386   fn_call_expr_boundary(ini::function_call_expr_sptr expr);
387   ini::function_call_expr_sptr as_function_call_expr() const;
388   operator ini::function_call_expr_sptr () const;
389   ~fn_call_expr_boundary();
390 }; //end class type_suppression::insertion_range::fn_call_expr_boundary
391
392 class function_suppression;
393
394 /// Convenience typedef for a shared pointer to function_suppression.
395 typedef shared_ptr<function_suppression> function_suppression_sptr;
396
397 /// Convenience typedef for a vector of @ref function_suppression_sptr.
398 typedef vector<function_suppression_sptr> function_suppressions_type;
399
400 /// Abstraction of a function suppression specification.
401 ///
402 /// Specifies under which condition reports about a @ref
403 /// function_decl_diff diff node should be dropped on the floor for
404 /// the purpose of reporting.
405 class function_suppression : public suppression_base
406 {
407   struct priv;
408   typedef shared_ptr<priv> priv_sptr;
409
410 public:
411
412   priv_sptr priv_;
413   class parameter_spec;
414
415   /// Convenience typedef for shared_ptr of @ref parameter_spec.
416   typedef shared_ptr<parameter_spec> parameter_spec_sptr;
417
418   /// Convenience typedef for vector of @ref parameter_spec_sptr.
419   typedef vector<parameter_spec_sptr> parameter_specs_type;
420
421   /// The kind of change the current function suppression should apply
422   /// to.
423   enum change_kind
424   {
425     UNDEFINED_CHANGE_KIND,
426     /// A change in a sub-type of the function.
427     FUNCTION_SUBTYPE_CHANGE_KIND = 1,
428     /// The function was added to the second subject of the diff.
429     ADDED_FUNCTION_CHANGE_KIND = 1 << 1,
430     /// The function was deleted from the second subject of the diff.
431     DELETED_FUNCTION_CHANGE_KIND = 1 << 2,
432     /// This represents all the changes possibly described by this
433     /// enum.  It's a logical 'OR' of all the change enumerators
434     /// above.
435     ALL_CHANGE_KIND = (FUNCTION_SUBTYPE_CHANGE_KIND
436                        | ADDED_FUNCTION_CHANGE_KIND
437                        | DELETED_FUNCTION_CHANGE_KIND)
438   };
439
440   function_suppression();
441
442   function_suppression(const string&            label,
443                        const string&            name,
444                        const string&            name_regex,
445                        const string&            return_type_name,
446                        const string&            return_type_regex,
447                        parameter_specs_type&    parm_specs,
448                        const string&            symbol_name,
449                        const string&            symbol_name_regex,
450                        const string&            symbol_version,
451                        const string&            symbol_version_regex_str);
452
453   virtual ~function_suppression();
454
455   static change_kind
456   parse_change_kind(const string&);
457
458   change_kind
459   get_change_kind() const;
460
461   void
462   set_change_kind(change_kind k);
463
464   const string&
465   get_name() const;
466
467   void
468   set_name(const string&);
469
470   const string&
471   get_name_regex_str() const;
472
473   void
474   set_name_regex_str(const string&);
475
476   const string&
477   get_name_not_regex_str() const;
478
479   void
480   set_name_not_regex_str(const string&);
481
482   const string&
483   get_return_type_name() const;
484
485   void
486   set_return_type_name(const string&);
487
488   const string&
489   get_return_type_regex_str() const;
490
491   void
492   set_return_type_regex_str(const string& r);
493
494   const parameter_specs_type&
495   get_parameter_specs() const;
496
497   void
498   set_parameter_specs(parameter_specs_type&);
499
500   void
501   append_parameter_specs(const parameter_spec_sptr);
502
503   const string&
504   get_symbol_name() const;
505
506   void
507   set_symbol_name(const string& n);
508
509   const string&
510   get_symbol_name_regex_str() const;
511
512   void
513   set_symbol_name_regex_str(const string&);
514
515   const string&
516   get_symbol_version() const;
517
518   void
519   set_symbol_version(const string&);
520
521   const string&
522   get_symbol_version_regex_str() const;
523
524   void
525   set_symbol_version_regex_str(const string&);
526
527   bool
528   get_allow_other_aliases() const;
529
530   void
531   set_allow_other_aliases(bool f);
532
533   virtual bool
534   suppresses_diff(const diff* diff) const;
535
536   bool
537   suppresses_function(const function_decl* fn,
538                       change_kind k,
539                       const diff_context_sptr ctxt) const;
540
541   bool
542   suppresses_function(const function_decl_sptr fn,
543                       change_kind k,
544                       const diff_context_sptr ctxt) const;
545
546   bool
547   suppresses_function_symbol(const elf_symbol* sym,
548                              change_kind k,
549                              const diff_context_sptr ctxt);
550
551   bool
552   suppresses_function_symbol(const elf_symbol_sptr sym,
553                              change_kind k,
554                              const diff_context_sptr ctxt);
555 }; // end class function_suppression.
556
557 function_suppression_sptr
558 is_function_suppression(const suppression_sptr);
559
560 function_suppression::change_kind
561 operator&(function_suppression::change_kind l,
562           function_suppression::change_kind r);
563
564 function_suppression::change_kind
565 operator|(function_suppression::change_kind l,
566           function_suppression::change_kind r);
567
568 /// Abstraction of the specification of a function parameter in a
569 /// function suppression specification.
570 class function_suppression::parameter_spec
571 {
572   class priv;
573   typedef shared_ptr<priv> priv_sptr;
574
575   friend class function_suppression;
576
577   priv_sptr priv_;
578
579   // Forbid this.
580   parameter_spec();
581
582 public:
583   parameter_spec(size_t index,
584                  const string& type_name,
585                  const string& type_name_regex);
586
587   size_t
588   get_index() const;
589
590   void
591   set_index(size_t);
592
593   const string&
594   get_parameter_type_name() const;
595
596   void
597   set_parameter_type_name(const string&);
598
599   const string&
600   get_parameter_type_name_regex_str() const;
601
602   void
603   set_parameter_type_name_regex_str(const string&);
604 };// end class function_suppression::parameter_spec
605
606 class variable_suppression;
607
608 /// A convenience typedef for a shared pointer to @ref
609 /// variable_suppression.
610 typedef shared_ptr<variable_suppression> variable_suppression_sptr;
611
612 /// A convenience typedef for a vector of @ref
613 /// variable_suppression_sptr.
614 typedef vector<variable_suppression_sptr> variable_suppressions_type;
615
616 /// The abstraction of a variable suppression specification.
617 ///
618 /// It specifies under which condition reports about a @ref var_diff
619 /// diff node should be dropped on the floor for the purpose of
620 /// reporting.
621 class variable_suppression : public suppression_base
622 {
623 public:
624
625   /// The kind of change the current variable suppression should apply
626   /// to.
627   enum change_kind
628   {
629     UNDEFINED_CHANGE_KIND,
630     /// A change in a sub-type of the variable.
631     VARIABLE_SUBTYPE_CHANGE_KIND = 1,
632     /// The variable was added to the second second subject of the
633     /// diff.
634     ADDED_VARIABLE_CHANGE_KIND = 1 << 1,
635     /// The variable was deleted from the second subject of the diff.
636     DELETED_VARIABLE_CHANGE_KIND = 1 << 2,
637     /// This represents all the changes possibly described by this
638     /// enum.  It's a logical 'OR' of all the change enumerators
639     /// above.
640     ALL_CHANGE_KIND = (VARIABLE_SUBTYPE_CHANGE_KIND
641                        | ADDED_VARIABLE_CHANGE_KIND
642                        | DELETED_VARIABLE_CHANGE_KIND)
643   };
644
645 private:
646   struct priv;
647   typedef shared_ptr<priv> priv_sptr;
648
649 public:
650
651   priv_sptr priv_;
652
653   variable_suppression(const string& label = "",
654                        const string& name = "",
655                        const string& name_regex_str = "",
656                        const string& symbol_name = "",
657                        const string& symbol_name_regex_str = "",
658                        const string& symbol_version = "",
659                        const string& symbol_version_regex_str = "",
660                        const string& type_name = "",
661                        const string& type_name_regex_str = "");
662
663   virtual ~variable_suppression();
664
665   static change_kind
666   parse_change_kind(const string&);
667
668   change_kind
669   get_change_kind() const;
670
671   void
672   set_change_kind(change_kind k);
673
674   const string&
675   get_name() const;
676
677   void
678   set_name(const string&);
679
680   const string&
681   get_name_regex_str() const;
682
683   void
684   set_name_regex_str(const string&);
685
686   const string&
687   get_name_not_regex_str() const;
688
689   void
690   set_name_not_regex_str(const string&);
691
692   const string&
693   get_symbol_name() const;
694
695   void
696   set_symbol_name(const string&);
697
698   const string&
699   get_symbol_name_regex_str() const;
700
701   void
702   set_symbol_name_regex_str(const string&);
703
704   const string&
705   get_symbol_version() const;
706
707   void
708   set_symbol_version(const string&);
709
710   const string&
711   get_symbol_version_regex_str() const;
712
713   void
714   set_symbol_version_regex_str(const string&);
715
716   const string&
717   get_type_name() const;
718
719   void
720   set_type_name(const string&);
721
722   const string&
723   get_type_name_regex_str() const;
724
725   void
726   set_type_name_regex_str(const string&);
727
728   bool
729   suppresses_diff(const diff* d) const;
730
731   bool
732   suppresses_variable(const var_decl* var,
733                       change_kind k,
734                       const diff_context_sptr cxt) const;
735
736   bool
737   suppresses_variable(const var_decl_sptr var,
738                       change_kind k,
739                       const diff_context_sptr cxt) const;
740
741   bool
742   suppresses_variable_symbol(const elf_symbol* sym,
743                              change_kind k,
744                              const diff_context_sptr cxt) const;
745
746   bool
747   suppresses_variable_symbol(const elf_symbol_sptr fn,
748                              change_kind k,
749                              const diff_context_sptr cxt) const;
750 }; // end class variable_suppression
751
752 variable_suppression_sptr
753 is_variable_suppression(const suppression_sptr);
754
755 variable_suppression::change_kind
756 operator&(variable_suppression::change_kind l,
757           variable_suppression::change_kind r);
758
759 variable_suppression::change_kind
760 operator|(variable_suppression::change_kind l,
761           variable_suppression::change_kind r);
762
763 class file_suppression;
764
765 /// A convenience typedef for a shared_ptr to @ref file_suppression
766 typedef shared_ptr<file_suppression> file_suppression_sptr;
767
768 /// Abstraction of a suppression specification to avoid loading a
769 /// file.
770 ///
771 /// This can be used by a tool that loads (binary) files, to know
772 /// which file it has to avoid loading.
773 class file_suppression: public suppression_base
774 {
775   class priv;
776   typedef shared_ptr<priv> priv_sptr;
777
778   priv_sptr priv_;
779
780   // Forbid this
781   file_suppression();
782
783 public:
784
785   file_suppression(const string& label,
786                    const string& file_name_regex,
787                    const string& file_name_not_regex);
788
789   virtual bool
790   suppresses_diff(const diff* diff) const;
791
792   bool
793   suppresses_file(const string& file_path);
794
795   virtual ~file_suppression();
796 }; // end file_suppression
797
798 file_suppression_sptr
799 is_file_suppression(const suppression_sptr);
800
801 file_suppression_sptr
802 file_is_suppressed(const string& file_path,
803                    const suppressions_type& suppressions);
804
805 const char*
806 get_private_types_suppr_spec_label();
807
808 bool
809 is_private_type_suppr_spec(const type_suppression&);
810
811 bool
812 is_private_type_suppr_spec(const suppression_sptr& s);
813 } // end namespace suppr
814
815 } // end namespace abigail
816
817 #endif //__ABG_SUPPRESSION_H__