Shenghou Ma | 1beb791 | 2013-05-23 04:41:22 +0800 | [diff] [blame] | 1 | #!/usr/bin/env perl |
Ian Lance Taylor | 66b261a | 2008-09-19 14:39:49 -0700 | [diff] [blame] | 2 | # Copyright 2009 The Go Authors. All rights reserved. |
| 3 | # Use of this source code is governed by a BSD-style |
| 4 | # license that can be found in the LICENSE file. |
| 5 | |
Eoghan Sherry | 802360e | 2010-12-07 15:28:21 -0500 | [diff] [blame] | 6 | # This script checks that the compilers emit the errors which we expect. |
| 7 | # Usage: errchk COMPILER [OPTS] SOURCEFILES. This will run the command |
| 8 | # COMPILER [OPTS] SOURCEFILES. The compilation is expected to fail; if |
| 9 | # it succeeds, this script will report an error. The stderr output of |
| 10 | # the compiler will be matched against comments in SOURCEFILES. For each |
| 11 | # line of the source files which should generate an error, there should |
| 12 | # be a comment of the form // ERROR "regexp". If the compiler generates |
| 13 | # an error for a line which has no such comment, this script will report |
| 14 | # an error. Likewise if the compiler does not generate an error for a |
| 15 | # line which has a comment, or if the error message does not match the |
| 16 | # <regexp>. The <regexp> syntax is Perl but its best to stick to egrep. |
Ian Lance Taylor | 66b261a | 2008-09-19 14:39:49 -0700 | [diff] [blame] | 17 | |
Russ Cox | d8b461d | 2009-10-09 00:39:32 -0700 | [diff] [blame] | 18 | use POSIX; |
Ian Lance Taylor | 66b261a | 2008-09-19 14:39:49 -0700 | [diff] [blame] | 19 | |
Russ Cox | 16cdba8 | 2011-08-02 15:19:44 -0400 | [diff] [blame] | 20 | my $exitcode = 1; |
| 21 | |
| 22 | if(@ARGV >= 1 && $ARGV[0] eq "-0") { |
| 23 | $exitcode = 0; |
| 24 | shift; |
| 25 | } |
| 26 | |
Russ Cox | d8b461d | 2009-10-09 00:39:32 -0700 | [diff] [blame] | 27 | if(@ARGV < 1) { |
Eoghan Sherry | 802360e | 2010-12-07 15:28:21 -0500 | [diff] [blame] | 28 | print STDERR "Usage: errchk COMPILER [OPTS] SOURCEFILES\n"; |
Russ Cox | d8b461d | 2009-10-09 00:39:32 -0700 | [diff] [blame] | 29 | exit 1; |
Russ Cox | 925454e | 2008-10-17 07:41:18 -0700 | [diff] [blame] | 30 | } |
| 31 | |
Eoghan Sherry | 802360e | 2010-12-07 15:28:21 -0500 | [diff] [blame] | 32 | # Grab SOURCEFILES |
| 33 | foreach(reverse 0 .. @ARGV-1) { |
Russ Cox | b5cfbda | 2013-03-22 15:14:40 -0400 | [diff] [blame] | 34 | unless($ARGV[$_] =~ /\.(go|s)$/) { |
Eoghan Sherry | 802360e | 2010-12-07 15:28:21 -0500 | [diff] [blame] | 35 | @file = @ARGV[$_+1 .. @ARGV-1]; |
| 36 | last; |
| 37 | } |
| 38 | } |
| 39 | |
Konstantin Shaposhnikov | 85a4f44 | 2016-06-27 17:13:15 +0800 | [diff] [blame] | 40 | # If no files have been specified try to grab SOURCEFILES from the last |
| 41 | # argument that is an existing directory if any |
| 42 | unless(@file) { |
| 43 | foreach(reverse 0 .. @ARGV-1) { |
| 44 | if(-d $ARGV[$_]) { |
| 45 | @file = glob($ARGV[$_] . "/*.go"); |
| 46 | last; |
| 47 | } |
| 48 | } |
| 49 | } |
| 50 | |
Eoghan Sherry | 802360e | 2010-12-07 15:28:21 -0500 | [diff] [blame] | 51 | foreach $file (@file) { |
| 52 | open(SRC, $file) || die "BUG: errchk: open $file: $!"; |
| 53 | $src{$file} = [<SRC>]; |
| 54 | close(SRC); |
| 55 | } |
Ian Lance Taylor | 66b261a | 2008-09-19 14:39:49 -0700 | [diff] [blame] | 56 | |
Russ Cox | d8b461d | 2009-10-09 00:39:32 -0700 | [diff] [blame] | 57 | # Run command |
| 58 | $cmd = join(' ', @ARGV); |
Russ Cox | 7b5da35 | 2009-10-09 16:44:40 -0700 | [diff] [blame] | 59 | open(CMD, "exec $cmd </dev/null 2>&1 |") || die "BUG: errchk: run $cmd: $!"; |
Russ Cox | 37c531f | 2010-06-20 12:05:43 -0700 | [diff] [blame] | 60 | |
Aaron Jacobs | 8628688 | 2015-06-24 09:50:12 +1000 | [diff] [blame] | 61 | # gc error messages continue onto additional lines with leading tabs. |
Russ Cox | 37c531f | 2010-06-20 12:05:43 -0700 | [diff] [blame] | 62 | # Split the output at the beginning of each line that doesn't begin with a tab. |
| 63 | $out = join('', <CMD>); |
| 64 | @out = split(/^(?!\t)/m, $out); |
| 65 | |
Russ Cox | d8b461d | 2009-10-09 00:39:32 -0700 | [diff] [blame] | 66 | close CMD; |
Ian Lance Taylor | 66b261a | 2008-09-19 14:39:49 -0700 | [diff] [blame] | 67 | |
Russ Cox | 16cdba8 | 2011-08-02 15:19:44 -0400 | [diff] [blame] | 68 | if($exitcode != 0 && $? == 0) { |
Russ Cox | d8b461d | 2009-10-09 00:39:32 -0700 | [diff] [blame] | 69 | print STDERR "BUG: errchk: command succeeded unexpectedly\n"; |
| 70 | print STDERR @out; |
| 71 | exit 0; |
| 72 | } |
| 73 | |
Russ Cox | 16cdba8 | 2011-08-02 15:19:44 -0400 | [diff] [blame] | 74 | if($exitcode == 0 && $? != 0) { |
| 75 | print STDERR "BUG: errchk: command failed unexpectedly\n"; |
| 76 | print STDERR @out; |
| 77 | exit 0; |
| 78 | } |
| 79 | |
Russ Cox | d8b461d | 2009-10-09 00:39:32 -0700 | [diff] [blame] | 80 | if(!WIFEXITED($?)) { |
| 81 | print STDERR "BUG: errchk: compiler crashed\n"; |
Russ Cox | 7b5da35 | 2009-10-09 16:44:40 -0700 | [diff] [blame] | 82 | print STDERR @out, "\n"; |
Russ Cox | d8b461d | 2009-10-09 00:39:32 -0700 | [diff] [blame] | 83 | exit 0; |
| 84 | } |
| 85 | |
| 86 | sub bug() { |
| 87 | if(!$bug++) { |
| 88 | print STDERR "BUG: "; |
| 89 | } |
| 90 | } |
| 91 | |
Eoghan Sherry | 802360e | 2010-12-07 15:28:21 -0500 | [diff] [blame] | 92 | sub chk { |
| 93 | my $file = shift; |
| 94 | my $line = 0; |
| 95 | my $regexp; |
| 96 | my @errmsg; |
| 97 | my @match; |
| 98 | foreach my $src (@{$src{$file}}) { |
| 99 | $line++; |
Russ Cox | f4e76d8 | 2011-01-31 18:36:28 -0500 | [diff] [blame] | 100 | next if $src =~ m|////|; # double comment disables ERROR |
Eoghan Sherry | 802360e | 2010-12-07 15:28:21 -0500 | [diff] [blame] | 101 | next unless $src =~ m|// (GC_)?ERROR (.*)|; |
Russ Cox | a5d7c1f | 2011-08-16 11:14:26 -0400 | [diff] [blame] | 102 | my $all = $2; |
| 103 | if($all !~ /^"([^"]*)"/) { |
Eoghan Sherry | 802360e | 2010-12-07 15:28:21 -0500 | [diff] [blame] | 104 | print STDERR "$file:$line: malformed regexp\n"; |
| 105 | next; |
| 106 | } |
Eoghan Sherry | 802360e | 2010-12-07 15:28:21 -0500 | [diff] [blame] | 107 | @errmsg = grep { /$file:$line[:[]/ } @out; |
| 108 | @out = grep { !/$file:$line[:[]/ } @out; |
| 109 | if(@errmsg == 0) { |
| 110 | bug(); |
Russ Cox | a5d7c1f | 2011-08-16 11:14:26 -0400 | [diff] [blame] | 111 | print STDERR "errchk: $file:$line: missing expected error: '$all'\n"; |
Eoghan Sherry | 802360e | 2010-12-07 15:28:21 -0500 | [diff] [blame] | 112 | next; |
| 113 | } |
Russ Cox | a5d7c1f | 2011-08-16 11:14:26 -0400 | [diff] [blame] | 114 | foreach my $regexp ($all =~ /"([^"]*)"/g) { |
| 115 | # Turn relative line number in message into absolute line number. |
| 116 | if($regexp =~ /LINE(([+-])([0-9]+))?/) { |
| 117 | my $n = $line; |
| 118 | if(defined($1)) { |
| 119 | if($2 eq "+") { |
| 120 | $n += int($3); |
| 121 | } else { |
| 122 | $n -= int($3); |
| 123 | } |
| 124 | } |
| 125 | $regexp = "$`$file:$n$'"; |
| 126 | } |
| 127 | |
| 128 | @match = grep { /$regexp/ } @errmsg; |
| 129 | if(@match == 0) { |
| 130 | bug(); |
| 131 | print STDERR "errchk: $file:$line: error messages do not match '$regexp'\n"; |
| 132 | next; |
| 133 | } |
| 134 | @errmsg = grep { !/$regexp/ } @errmsg; |
| 135 | } |
| 136 | if(@errmsg != 0) { |
Eoghan Sherry | 802360e | 2010-12-07 15:28:21 -0500 | [diff] [blame] | 137 | bug(); |
Russ Cox | a5d7c1f | 2011-08-16 11:14:26 -0400 | [diff] [blame] | 138 | print STDERR "errchk: $file:$line: unmatched error messages:\n"; |
Russ Cox | e0a6174 | 2011-06-20 14:06:00 -0400 | [diff] [blame] | 139 | foreach my $l (@errmsg) { |
| 140 | print STDERR "> $l"; |
| 141 | } |
Eoghan Sherry | 802360e | 2010-12-07 15:28:21 -0500 | [diff] [blame] | 142 | } |
Russ Cox | d8b461d | 2009-10-09 00:39:32 -0700 | [diff] [blame] | 143 | } |
Eoghan Sherry | 802360e | 2010-12-07 15:28:21 -0500 | [diff] [blame] | 144 | } |
| 145 | |
| 146 | foreach $file (@file) { |
| 147 | chk($file) |
Russ Cox | d8b461d | 2009-10-09 00:39:32 -0700 | [diff] [blame] | 148 | } |
| 149 | |
| 150 | if(@out != 0) { |
| 151 | bug(); |
Eoghan Sherry | 802360e | 2010-12-07 15:28:21 -0500 | [diff] [blame] | 152 | print STDERR "errchk: unmatched error messages:\n"; |
Russ Cox | d8b461d | 2009-10-09 00:39:32 -0700 | [diff] [blame] | 153 | print STDERR "==================================================\n"; |
| 154 | print STDERR @out; |
| 155 | print STDERR "==================================================\n"; |
| 156 | } |
| 157 | |
| 158 | exit 0; |