]> git.ipfire.org Git - thirdparty/gcc.git/blob - contrib/check_GNU_style.sh
PR c++/87554 - ICE with extern template and reference member.
[thirdparty/gcc.git] / contrib / check_GNU_style.sh
1 #!/bin/sh
2
3 # Checks some of the GNU style formatting rules in a set of patches.
4 # Copyright (C) 2010, 2012, 2016 Free Software Foundation, Inc.
5 # Contributed by Sebastian Pop <sebastian.pop@amd.com>
6
7 # This program is free software; you can redistribute it and/or modify
8 # it under the terms of the GNU General Public License as published by
9 # the Free Software Foundation; either version 3 of the License, or
10 # (at your option) any later version.
11
12 # This program is distributed in the hope that it will be useful,
13 # but WITHOUT ANY WARRANTY; without even the implied warranty of
14 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 # GNU General Public License for more details.
16
17 # You should have received a copy of the GNU General Public License
18 # along with this program; if not, see the file COPYING3. If not,
19 # see <http://www.gnu.org/licenses/>.
20
21 # Set to empty in the environment to override.
22 : ${color:---color=always}
23
24 usage() {
25 cat <<EOF
26 check_GNU_style.sh [patch]...
27
28 Checks the patches for some of the GNU style formatting problems.
29 When FILE is -, read standard input.
30
31 Please note that these checks are not always accurate, and
32 complete. The reference documentation of the GNU Coding Standards
33 can be found here: http://www.gnu.org/prep/standards_toc.html
34 and there are also some additional coding conventions for GCC:
35 http://gcc.gnu.org/codingconventions.html
36
37 EOF
38 exit 1
39 }
40
41 test $# -eq 0 && usage
42 nfiles=$#
43 files="$*"
44
45 stdin=false
46 stdin_tmp=""
47 if [ $nfiles -eq 1 ] && [ "$files" = "-" ]; then
48 stdin=true
49
50 # By putting stdin into a temp file, we can handle it just like any other
51 # file. F.i., we can cat it twice, which we can't do with stdin.
52 stdin_tmp=check_GNU_style.stdin
53 cat - > $stdin_tmp
54 files=$stdin_tmp
55 else
56 for f in $files; do
57 if [ "$f" = "-" ]; then
58 # Let's keep things simple. Either we read from stdin, or we read
59 # from files specified on the command line, not both.
60 usage
61 fi
62 if [ ! -f "$f" ]; then
63 echo "error: could not read file: $f"
64 exit 1
65 fi
66 done
67 fi
68
69 inp=check_GNU_style.inp
70 tmp=check_GNU_style.tmp
71 tmp2=check_GNU_style.2.tmp
72 tmp3=check_GNU_style.3.tmp
73
74 # Remove $tmp on exit and various signals.
75 trap "rm -f $inp $tmp $tmp2 $tmp3 $stdin_tmp" 0
76 trap "rm -f $inp $tmp $tmp2 $tmp3 $stdin_tmp; exit 1" 1 2 3 5 9 13 15
77
78 if [ $nfiles -eq 1 ]; then
79 # There's no need for the file prefix if we're dealing only with one file.
80 format="-n"
81 else
82 format="-nH"
83 fi
84
85 # Remove the testsuite part of the diff. We don't care about GNU style
86 # in testcases and the dg-* directives give too many false positives.
87 remove_testsuite ()
88 {
89 awk 'BEGIN{testsuite=0} /^(.*:)?([1-9][0-9]*:)?\+\+\+ / && ! /testsuite\//{testsuite=0} \
90 {if (!testsuite) print} /^(.*:)?([1-9][0-9]*:)?\+\+\+ (.*\/)?testsuite\//{testsuite=1}'
91 }
92
93 grep $format '^+' $files \
94 | remove_testsuite \
95 | grep -v ':+++' \
96 > $inp
97
98 cat_with_prefix ()
99 {
100 local f="$1"
101
102 if [ "$prefix" = "" ]; then
103 cat "$f"
104 else
105 awk "{printf \"%s%s\n\", \"$prefix\", \$0}" $f
106 fi
107 }
108
109 # Grep
110 g (){
111 local msg="$1"
112 local arg="$2"
113
114 local found=false
115 cat $inp \
116 | egrep $color -- "$arg" \
117 > "$tmp" && found=true
118
119 if $found; then
120 printf "\n$msg\n"
121 cat "$tmp"
122 fi
123 }
124
125 # And Grep
126 ag (){
127 local msg="$1"
128 local arg1="$2"
129 local arg2="$3"
130
131 local found=false
132 cat $inp \
133 | egrep $color -- "$arg1" \
134 | egrep $color -- "$arg2" \
135 > "$tmp" && found=true
136
137 if $found; then
138 printf "\n$msg\n"
139 cat "$tmp"
140 fi
141 }
142
143 # reVerse Grep
144 vg (){
145 local msg="$1"
146 local varg="$2"
147 local arg="$3"
148
149 local found=false
150 cat $inp \
151 | egrep -v -- "$varg" \
152 | egrep $color -- "$arg" \
153 > "$tmp" && found=true
154
155 if $found; then
156 printf "\n$msg\n"
157 cat "$tmp"
158 fi
159 }
160
161 col (){
162 local msg="$1"
163
164 local first=true
165 local f
166 for f in $files; do
167 prefix=""
168 if [ $nfiles -ne 1 ]; then
169 prefix="$f:"
170 fi
171
172 # Don't reuse $inp, which may be generated using -H and thus contain a
173 # file prefix. Re-remove the testsuite since we're not using $inp.
174 cat $f | remove_testsuite \
175 | grep -n '^+' \
176 | grep -v ':+++' \
177 > $tmp
178
179 # Keep only line number prefix and patch modifier '+'.
180 cat "$tmp" \
181 | sed 's/\(^[0-9][0-9]*:+\).*/\1/' \
182 > "$tmp2"
183
184 # Remove line number prefix and patch modifier '+'.
185 # Expand tabs to spaces according to tab positions.
186 # Keep long lines, make short lines empty. Print the part past 80 chars
187 # in red.
188 cat "$tmp" \
189 | sed 's/^[0-9]*:+//' \
190 | expand \
191 | awk '{ \
192 if (length($0) > 80) \
193 printf "%s\033[1;31m%s\033[0m\n", \
194 substr($0,1,80), \
195 substr($0,81); \
196 else \
197 print "" \
198 }' \
199 > "$tmp3"
200
201 # Combine prefix back with long lines.
202 # Filter out empty lines.
203 local found=false
204 paste -d '\0' "$tmp2" "$tmp3" \
205 | grep -v '^[0-9][0-9]*:+$' \
206 > "$tmp" && found=true
207
208 if $found; then
209 if $first; then
210 printf "\n$msg\n"
211 first=false
212 fi
213 cat_with_prefix "$tmp"
214 fi
215 done
216 }
217
218
219 col 'Lines should not exceed 80 characters.'
220
221 g 'Blocks of 8 spaces should be replaced with tabs.' \
222 ' {8}'
223
224 g 'Trailing whitespace.' \
225 '[[:space:]]$'
226
227 g 'Space before dot.' \
228 '[[:alnum:]][[:blank:]]+\.'
229
230 g 'Dot, space, space, new sentence.' \
231 '[[:alnum:]]\.([[:blank:]]|[[:blank:]]{3,})[A-Z0-9]'
232
233 g 'Dot, space, space, end of comment.' \
234 '[[:alnum:]]\.([[:blank:]]{0,1}|[[:blank:]]{3,})\*/'
235
236 g 'Sentences should end with a dot. Dot, space, space, end of the comment.' \
237 '[[:alnum:]][[:blank:]]*\*/'
238
239 vg 'There should be exactly one space between function name and parenthesis.' \
240 '\#define' \
241 '[[:alnum:]]([[:blank:]]{2,})?\('
242
243 g 'There should be no space before a left square bracket.' \
244 '[[:alnum:]][[:blank:]]+\['
245
246 g 'There should be no space before closing parenthesis.' \
247 '[[:graph:]][[:blank:]]+\)'
248
249 # This will give false positives for C99 compound literals.
250 g 'Braces should be on a separate line.' \
251 '(\)|else)[[:blank:]]*{'
252
253 # Does this apply to definitions of aggregate objects?
254 ag 'Trailing operator.' \
255 '^[1-9][0-9]*:\+[[:space:]]' \
256 '(([^a-zA-Z_]\*)|([-%<=&|^?])|([^*]/)|([^:][+]))$'