source: tags/svn.1.5.4/SOURCE_TOOLS/postcompile.pl

Last change on this file was 8098, checked in by westram, 14 years ago

merge from ptpan_back [8023] [8030] [8052] [8058] [8062]

  • suppress several boost-warnings
  • store old SIGSEGV-handler in AISC-servers
  • removed chroot (unused and name conflicts with libc)
  • fixed abuse of GB_export_errorf
  • accept if sighandler is already installed (happens when opening 2 DB-clients from same binary)
  • Property svn:eol-style set to native
  • Property svn:executable set to *
  • Property svn:keywords set to Author Date Id Revision
File size: 11.3 KB
Line 
1#!/usr/bin/perl
2# ================================================================= #
3#                                                                   #
4#   File      : postcompile.pl                                      #
5#   Purpose   : filter gcc shadow spam                              #
6#                                                                   #
7#   Coded by Ralf Westram (coder@reallysoft.de) in September 2007   #
8#   Institute of Microbiology (Technical University Munich)         #
9#   http://www.arb-home.de/                                         #
10#                                                                   #
11# ================================================================= #
12
13use strict;
14use warnings;
15
16# Note: g++ must be called with -fmessage-length=0
17
18my $show_supressed_lines = 0;
19my $show_filtered_lines  = 0;
20
21# regexps for whole line:
22my $reg_file = qr/^([^:]+):([0-9]+):(([0-9]+):)?\s/; # finds all messages
23my $reg_file_noline = qr/^([^:]+):\s/; # finds all messages w/o linenumber (if not matched $reg_file)
24my $reg_included = qr/^In\sfile\sincluded\sfrom\s(.*)[,:]/;
25my $reg_included2 = qr/^\s+from\s(.*)[,:]/;
26my $reg_location = qr/^[^:]+:\sIn\sfunction\s/;
27my $reg_location2 = qr/^[^:]+:\sAt\stop\slevel:/;
28
29# regexps for messages:
30my $reg_is_error = qr/^error:\s/i;
31my $reg_is_warning = qr/^warning:\s/i;
32my $reg_is_note = qr/^note:\s/i;
33my $reg_is_instantiated = qr/^\s\sinstantiated\sfrom\s/;
34
35# regexps for warning messages (for part behind 'warning: ')
36my $reg_shadow_warning = qr/^declaration\sof\s.*\sshadows\s/;
37my $reg_shadow_location = qr/^shadowed\s/;
38
39my $filter_Weffpp = 1;
40my @reg_Weffpp = (
41                  qr/^base\sclass\s.*has\sa\snon-virtual\sdestructor/,
42                  qr/\sshould\sbe\sinitialized\sin\sthe\smember\sinitialization\slist/,
43                  qr/boost::icl::(insert|add)_iterator<ContainerT>.*should\sreturn/, # filter boost-iterator postfix operators warnings
44                  qr/^\s\sbut\sdoes\snot\soverride/, # belongs to reg_Weffpp_copyable
45                  qr/^\s\sor\s'operator=/, # belongs to reg_Weffpp_copyable
46                 );
47
48my $filter_Weffpp_copyable = 0; # 1 = filter copy-ctor/op=-warning, 0 = check for Noncopyable and warn
49my $reg_Weffpp_copyable = qr/'(class|struct)\s([A-Za-z_0-9:]+).*'\shas\spointer\sdata\smembers/; # occurs also if derived from 'Noncopyable'
50
51# regexps for files:
52my $reg_user_include       = qr/^\/usr\/include\//;
53my $reg_HEADERLIBS_include = qr/\/HEADERLIBS\//;
54
55my $stop_after_first_error = 0;
56my $hide_warnings          = 0;
57
58# ----------------------------------------
59
60sub getModtime($) {
61  my ($fileOrDir) = @_;
62  my $modtime = (stat($fileOrDir))[9];
63  return $modtime;
64}
65
66my %derived_from_NC = (); # key=classname, value=1/0
67my $NC_save_name = $ENV{ARBHOME}.'/SOURCE_TOOLS/postcompile.sav';
68my $NC_loaded    = 0;
69my $NC_loaded_timestamp;
70my $NC_need_save = 0;
71
72sub load_from_NC() {
73  if (-f $NC_save_name) {
74    $NC_loaded_timestamp = getModtime($NC_save_name);
75    my $age = $NC_loaded_timestamp - time;
76    if ($age<3*60) { # never load data older than 3 min
77      open(NC,'<'.$NC_save_name);
78      foreach (<NC>) {
79        chomp;
80        if (/^([01]),/o) {
81          $derived_from_NC{$'} = $1;
82        }
83      }
84      close(NC);
85    }
86    else {
87      $NC_loaded_timestamp = 0; # epoch
88    }
89  }
90  else {
91    $NC_loaded_timestamp = 0; # epoch
92  }
93  $NC_loaded = 1;
94}
95
96sub save_from_NC() {
97  if ($NC_need_save==1) {
98    my $mt = 0;
99    if (-f $NC_save_name) { $mt = getModtime($NC_save_name); }
100    if ($mt>$NC_loaded_timestamp) { # changed on disk
101      load_from_NC(); # does simple merge
102    }
103    my $NC_save_name_private = $NC_save_name.'.'.$$;
104    open(NC,'>'.$NC_save_name_private);
105    foreach (sort keys %derived_from_NC) {
106      print NC $derived_from_NC{$_}.','.$_."\n";
107    }
108    close(NC);
109
110    rename($NC_save_name_private,$NC_save_name) || die "can't rename '$NC_save_name_private' to '$NC_save_name' (Reason: $!)";
111  }
112}
113
114sub advice_derived_from_Noncopyable($$$) {
115  # Note: you can silence the Noncopyable-warning by
116  # adding a comment containing 'Noncopyable' behind the 'class'-line
117  my ($classname,$file,$linenr) = @_;
118
119  if ($NC_loaded==0) { load_from_NC(); }
120  my $is_a_NC = $derived_from_NC{$classname};
121  if (defined $is_a_NC) {
122    return 0; # do not warn twice
123  }
124
125  if (not -f $file) {
126    die "no such file '$file'";
127  }
128
129  my $uq_classname = $classname;
130  while ($uq_classname =~ /::/o) { $uq_classname = $'; } # skip namespace prefixes
131
132  open(FILE,'<'.$file) || die "can't read '$file' (Reason: $!)";
133  my $line;
134  my $line_count = 0;
135 LINE: while (defined($line=<FILE>)) {
136    $line_count++;
137    if ($line_count==$linenr) {
138      if ($line =~ /(class|struct)\s+$uq_classname(.*)Noncopyable/) {
139        my $prefix = $2;
140        if (not $prefix =~ /\/\//) { # if we have a comment, assume it mentions that the class is derived from a Noncopyable
141          if (not $prefix =~ /virtual/) {
142            print $file.':'.$linenr.': inheritance from Noncopyable should be virtual'."\n";
143          }
144        }
145        $is_a_NC = 1;
146      }
147      else { $is_a_NC = 0; }
148      last LINE;
149    }
150  }
151  close(FILE);
152  $derived_from_NC{$classname} = $is_a_NC;
153  $NC_need_save = 1;
154
155  return 1-$is_a_NC;
156}
157
158# results for Weffpp_warning_wanted():
159my $WANTED            = 0;
160my $WANTED_NO_RELATED = 1;
161my $UNWANTED          = 2;
162
163sub Weffpp_warning_wanted($$\$) {
164  my ($file,$line,$warning_text_r) = @_;
165
166  if ($filter_Weffpp==1) {
167    foreach my $reg (@reg_Weffpp) {
168      return $UNWANTED if ($$warning_text_r =~ $reg);
169    }
170    if ($$warning_text_r =~ $reg_Weffpp_copyable) {
171      my $classname = $2;
172      return $UNWANTED if ($filter_Weffpp_copyable==1);
173      return $UNWANTED if (advice_derived_from_Noncopyable($classname,$file,$line)==0);
174      $$warning_text_r = $$warning_text_r.' (and is neighter derived from Noncopyable nor defines copy-ctor and op=)';
175      return $WANTED_NO_RELATED;
176    }
177  }
178  return $WANTED;
179}
180
181sub warning($\@) {
182  my ($msg,$out_r) = @_;
183  push @$out_r, '[postcompile]: '.$msg;
184}
185
186my $shadow_warning = undef;
187
188sub store_shadow($\@) {
189  my ($warn,$out_r) = @_;
190  if (defined $shadow_warning) {
191    warning('unprocessed shadow_warning:', @$out_r);
192    push @$out_r, $shadow_warning;
193  }
194  $shadow_warning = $warn;
195}
196
197sub push_loc_and_related($$\@\@) {
198  my ($location_info,$message,$related_r,$out_r) = @_;
199  if (defined $location_info) {
200    push @$out_r, $location_info;
201    $location_info = undef;
202  }
203  push @$out_r, $message;
204  foreach (@$related_r) { push @$out_r, $_; }
205}
206
207sub included_from_here($) {
208  my ($loc) = @_;
209  return $loc.': included from here';
210}
211
212sub suppress($\@) {
213  my ($curr,$out_r) = @_;
214  if ($show_supressed_lines==1) {
215    warning('suppressed: '.$curr,@$out_r);
216  }
217  return undef;
218}
219
220sub is_system_or_builtin($) {
221  my ($file) = @_;
222  return (($file =~ $reg_user_include) or ($file eq '<built-in>') or ($file =~ $reg_HEADERLIBS_include));
223}
224
225sub suppress_shadow_warning_for($) {
226  my ($file) = @_;
227  return is_system_or_builtin($file);
228}
229
230sub parse_input(\@) {
231  my ($out_r) = @_;
232  my @related = ();
233  my $location_info = undef;
234
235  my @warnout = ();
236  my @errout = ();
237
238  my $did_show_previous = 0;
239  my $is_error          = 0;
240  my $curr_out_r = \@warnout;
241
242 LINE: while (defined($_=<>)) {
243    chomp;
244    my $filter_current = 0;
245
246    if ($_ =~ $reg_file) {
247      my ($file,$line,$msg) = ($1,$2,$');
248
249      if ($msg =~ $reg_is_warning) {
250        my $warn_text = $';
251        if ($warn_text =~ $reg_shadow_warning) {
252          if (not $' =~ /this/) { # don't store this warnings (no location follows)
253            store_shadow($_,@warnout);
254            $_ = suppress($_,@warnout);
255          }
256          elsif (suppress_shadow_warning_for($file)) {
257            $_ = suppress($_,@warnout);
258            # $location_info = undef;
259          }
260        }
261        elsif ($warn_text =~ $reg_shadow_location) {
262          if (not defined $shadow_warning) { warning('no shadow_warning seen',@warnout); }
263          else {
264            if (suppress_shadow_warning_for($file)) {
265              # don't warn about /usr/include or <built-in> shadowing
266              $_ = suppress($_,@warnout);
267              @related = ();
268              $location_info = undef;
269            }
270            else {
271              if (defined $location_info) {
272                push @warnout, $location_info;
273                $location_info = undef;
274              }
275              push @warnout, $shadow_warning;
276            }
277            $shadow_warning = undef;
278          }
279        }
280        else {
281          my $warn_is = Weffpp_warning_wanted($file,$line,$warn_text);
282          if ($warn_is == $UNWANTED) {
283            $filter_current = 1; # ignore this warning
284          }
285          elsif ($warn_is == $WANTED_NO_RELATED) {
286            @related = (); # drop related messages
287          }
288          # rebuild warning (Weffpp_warning_wanted might modify the message)
289          $_ = $file.':'.$line.': warning: '.$warn_text;
290        }
291        $is_error = 0;
292        $curr_out_r = \@warnout;
293      }
294      elsif ($msg =~ $reg_is_error) {
295        $is_error = 1;
296        $curr_out_r = \@errout;
297      }
298      elsif ($msg =~ $reg_is_instantiated) {
299        push @related, $_;
300        $_ = suppress($_,@warnout);
301      }
302      elsif ($msg =~ $reg_is_note) {
303        if ($did_show_previous==0) {
304          $_ = suppress($_,@warnout);
305        }
306        #else display normally
307      }
308    }
309    elsif ($_ =~ $reg_location or $_ =~ $reg_location2) {
310      $location_info = $_;
311      $_ = suppress($_,@warnout);
312    }
313    elsif ($_ =~ $reg_included) {
314      push @related, included_from_here($1);
315      $_ = suppress($_,@warnout);
316    }
317    elsif ($_ =~ $reg_file_noline) {
318      if (/^cc1plus:.*error/) {
319        ; # display normally
320      }
321      else {
322        push @related, included_from_here($1);
323        $_ = suppress($_,@warnout);
324      }
325    }
326    elsif (@related) {
327      if ($_ =~ $reg_included2) {
328        push @related, included_from_here($1);
329        $_ = suppress($_,@warnout);
330      }
331    }
332
333    if (defined $_) {
334      if ($filter_current==0) {
335        push_loc_and_related($location_info,$_,@related,@$curr_out_r);
336        $did_show_previous = 1;
337
338        if (($is_error==1) and ($stop_after_first_error==1)) {
339          @warnout = (); # drop warnings
340          last LINE;
341        }
342      }
343      else {
344        die "can't filter errors (Error=$_)" if ($is_error==1);
345        if ($show_filtered_lines==1) { warning('filtered: '.$_, @$curr_out_r); }
346        $did_show_previous = 0;
347      }
348      @related = ();
349    }
350  }
351
352  @$out_r = @errout;
353  if ($hide_warnings==0) { push @$out_r, @warnout; }
354}
355
356sub main() {
357  my $args = scalar(@ARGV);
358  my $pass_through = 0;
359  while ($args>0) {
360    my $arg = shift(@ARGV);
361    if ($arg eq '--no-warnings') { $hide_warnings = 1; }
362    elsif ($arg eq '--only-first-error') { $stop_after_first_error = 1; }
363    elsif ($arg eq '--original') { $pass_through = 1; }
364    elsif ($arg eq '--show-useless-Weff++') { $filter_Weffpp = 0; }
365    elsif ($arg eq '--hide-Noncopyable-advices') { $filter_Weffpp_copyable = 1; }
366    else {
367      die "Usage: postcompile.pl [--no-warnings] [--only-first-error] [--filter-Weff++] [--hide-Noncopyable-advices] [--original]\n";
368    }
369    $args--;
370  }
371
372  eval {
373    if ($pass_through==1) {
374      while (defined($_=<>)) { print $_; }
375    }
376    else {
377      my @out = ();
378      parse_input(@out);
379      store_shadow(undef,@out);
380      foreach (@out) { print "$_\n"; }
381    }
382  };
383  my $err = $@;
384  save_from_NC();
385  if ($err) { die $err; }
386}
387main();
Note: See TracBrowser for help on using the repository browser.