blob: bc8ef19cb0bd831e8d1b6cde02cb4993b3097c5a [file] [log] [blame]
Shenghou Ma1beb7912013-05-23 04:41:22 +08001#!/usr/bin/env perl
Ian Lance Taylor66b261a2008-09-19 14:39:49 -07002# 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 Sherry802360e2010-12-07 15:28:21 -05006# 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 Taylor66b261a2008-09-19 14:39:49 -070017
Russ Coxd8b461d2009-10-09 00:39:32 -070018use POSIX;
Ian Lance Taylor66b261a2008-09-19 14:39:49 -070019
Russ Cox16cdba82011-08-02 15:19:44 -040020my $exitcode = 1;
21
22if(@ARGV >= 1 && $ARGV[0] eq "-0") {
23 $exitcode = 0;
24 shift;
25}
26
Russ Coxd8b461d2009-10-09 00:39:32 -070027if(@ARGV < 1) {
Eoghan Sherry802360e2010-12-07 15:28:21 -050028 print STDERR "Usage: errchk COMPILER [OPTS] SOURCEFILES\n";
Russ Coxd8b461d2009-10-09 00:39:32 -070029 exit 1;
Russ Cox925454e2008-10-17 07:41:18 -070030}
31
Eoghan Sherry802360e2010-12-07 15:28:21 -050032# Grab SOURCEFILES
33foreach(reverse 0 .. @ARGV-1) {
Russ Coxb5cfbda2013-03-22 15:14:40 -040034 unless($ARGV[$_] =~ /\.(go|s)$/) {
Eoghan Sherry802360e2010-12-07 15:28:21 -050035 @file = @ARGV[$_+1 .. @ARGV-1];
36 last;
37 }
38}
39
Konstantin Shaposhnikov85a4f442016-06-27 17:13:15 +080040# If no files have been specified try to grab SOURCEFILES from the last
41# argument that is an existing directory if any
42unless(@file) {
43 foreach(reverse 0 .. @ARGV-1) {
44 if(-d $ARGV[$_]) {
45 @file = glob($ARGV[$_] . "/*.go");
46 last;
47 }
48 }
49}
50
Eoghan Sherry802360e2010-12-07 15:28:21 -050051foreach $file (@file) {
52 open(SRC, $file) || die "BUG: errchk: open $file: $!";
53 $src{$file} = [<SRC>];
54 close(SRC);
55}
Ian Lance Taylor66b261a2008-09-19 14:39:49 -070056
Russ Coxd8b461d2009-10-09 00:39:32 -070057# Run command
58$cmd = join(' ', @ARGV);
Russ Cox7b5da352009-10-09 16:44:40 -070059open(CMD, "exec $cmd </dev/null 2>&1 |") || die "BUG: errchk: run $cmd: $!";
Russ Cox37c531f2010-06-20 12:05:43 -070060
Aaron Jacobs86286882015-06-24 09:50:12 +100061# gc error messages continue onto additional lines with leading tabs.
Russ Cox37c531f2010-06-20 12:05:43 -070062# 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 Coxd8b461d2009-10-09 00:39:32 -070066close CMD;
Ian Lance Taylor66b261a2008-09-19 14:39:49 -070067
Russ Cox16cdba82011-08-02 15:19:44 -040068if($exitcode != 0 && $? == 0) {
Russ Coxd8b461d2009-10-09 00:39:32 -070069 print STDERR "BUG: errchk: command succeeded unexpectedly\n";
70 print STDERR @out;
71 exit 0;
72}
73
Russ Cox16cdba82011-08-02 15:19:44 -040074if($exitcode == 0 && $? != 0) {
75 print STDERR "BUG: errchk: command failed unexpectedly\n";
76 print STDERR @out;
77 exit 0;
78}
79
Russ Coxd8b461d2009-10-09 00:39:32 -070080if(!WIFEXITED($?)) {
81 print STDERR "BUG: errchk: compiler crashed\n";
Russ Cox7b5da352009-10-09 16:44:40 -070082 print STDERR @out, "\n";
Russ Coxd8b461d2009-10-09 00:39:32 -070083 exit 0;
84}
85
86sub bug() {
87 if(!$bug++) {
88 print STDERR "BUG: ";
89 }
90}
91
Eoghan Sherry802360e2010-12-07 15:28:21 -050092sub 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 Coxf4e76d82011-01-31 18:36:28 -0500100 next if $src =~ m|////|; # double comment disables ERROR
Eoghan Sherry802360e2010-12-07 15:28:21 -0500101 next unless $src =~ m|// (GC_)?ERROR (.*)|;
Russ Coxa5d7c1f2011-08-16 11:14:26 -0400102 my $all = $2;
103 if($all !~ /^"([^"]*)"/) {
Eoghan Sherry802360e2010-12-07 15:28:21 -0500104 print STDERR "$file:$line: malformed regexp\n";
105 next;
106 }
Eoghan Sherry802360e2010-12-07 15:28:21 -0500107 @errmsg = grep { /$file:$line[:[]/ } @out;
108 @out = grep { !/$file:$line[:[]/ } @out;
109 if(@errmsg == 0) {
110 bug();
Russ Coxa5d7c1f2011-08-16 11:14:26 -0400111 print STDERR "errchk: $file:$line: missing expected error: '$all'\n";
Eoghan Sherry802360e2010-12-07 15:28:21 -0500112 next;
113 }
Russ Coxa5d7c1f2011-08-16 11:14:26 -0400114 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 Sherry802360e2010-12-07 15:28:21 -0500137 bug();
Russ Coxa5d7c1f2011-08-16 11:14:26 -0400138 print STDERR "errchk: $file:$line: unmatched error messages:\n";
Russ Coxe0a61742011-06-20 14:06:00 -0400139 foreach my $l (@errmsg) {
140 print STDERR "> $l";
141 }
Eoghan Sherry802360e2010-12-07 15:28:21 -0500142 }
Russ Coxd8b461d2009-10-09 00:39:32 -0700143 }
Eoghan Sherry802360e2010-12-07 15:28:21 -0500144}
145
146foreach $file (@file) {
147 chk($file)
Russ Coxd8b461d2009-10-09 00:39:32 -0700148}
149
150if(@out != 0) {
151 bug();
Eoghan Sherry802360e2010-12-07 15:28:21 -0500152 print STDERR "errchk: unmatched error messages:\n";
Russ Coxd8b461d2009-10-09 00:39:32 -0700153 print STDERR "==================================================\n";
154 print STDERR @out;
155 print STDERR "==================================================\n";
156}
157
158exit 0;