├── README.md └── list_cpp_warning_options.pl /README.md: -------------------------------------------------------------------------------- 1 | # ListCppWarningOptions # 2 | 3 | A simple Perl script that prints GCC warning options you can apply to C++ code. A poor man's equivalent of Clang's `-Weverything` with a couple of extra tricks up its sleeve. 4 | 5 | ## Motivation ## 6 | 7 | GCC online documentation scatters C++ related warning options across two pages and mixes them with options that have no meaning for C++. Furthermore, you have to [find](https://gcc.gnu.org/releases.html) the documentation suitable for your release. 8 | 9 | `list_cpp_warning_options.pl` queries *your* local GCC, filters out options that can not be applied to C++, and prints them on the screen. 10 | 11 | ## Usage ## 12 | 13 | ``` 14 | USAGE: ./list_cpp_warning_options.pl [options] 15 | OPTIONS: 16 | -h, --help Print this message. 17 | -p, --print-descriptions Print option descriptions in the following format: 18 | -Wuseless-cast Warn about useless casts. 19 | -Wunused-label Warn when a label is unused. 20 | ... 21 | -e, --enabled-only Print only currently enabled warning options. 22 | Useful to see what you have so far. 23 | -d, --disabled-only Print only currently disabled warning options. 24 | Useful to see what else can be enabled. 25 | GCC warning options Assorted GCC warning options: -Wall, -Wextra, 26 | -Wno-deprecated, etc. 27 | Use with `--enabled-only` or `--disabled-only`. 28 | 29 | Options `--enabled-only` and `--disabled-only` cannot be used together. 30 | ``` 31 | 32 | ## Caveats ## 33 | 34 | * Ignores `-f` options 35 | * Ignores `-W` options that take arguments 36 | * Ignores `-Wsystem-headers` to avoid noisy output 37 | * Uses whatever `gcc` it finds in `$PATH` 38 | 39 | -------------------------------------------------------------------------------- /list_cpp_warning_options.pl: -------------------------------------------------------------------------------- 1 | #!/usr/bin/perl -w 2 | 3 | use strict; 4 | use warnings; 5 | 6 | use File::Temp qw(tempfile); 7 | 8 | sub get_warning_options 9 | { 10 | my %valid_options; 11 | 12 | my @lines = split("\n", `gcc --help=warnings`); 13 | 14 | my $last_option = ""; 15 | my $last_option_skipped = 0; 16 | 17 | foreach my $line (@lines) 18 | { 19 | my @columns = split(" ", $line); 20 | my $option = shift @columns; 21 | my $description = join(" ", @columns); 22 | 23 | if (defined($option)) 24 | { 25 | if ($option =~ /-W[^=]+[^-=]$/) 26 | { 27 | # Special cases: 28 | # 1) Although it's not specified, all options 29 | # that start with `-Wformat` require a mandatory argument 30 | # and thus should be ignored; 31 | # 2) The `-Wsystem-headers` tells GCC to display warnings 32 | # from systems headers, which is usually not desired. 33 | if ($option !~ /-W(format|system-headers)/) 34 | { 35 | $valid_options{$option} = $description; 36 | 37 | $last_option = $option; 38 | $last_option_skipped = 0; 39 | } 40 | else 41 | { 42 | $last_option_skipped = 1; 43 | } 44 | } 45 | elsif ($option =~ /-W.+=$/) 46 | { 47 | # Sometimes GCC lists options that take arguments twice: 48 | # -Wstrict-overflow Warn about optimizations ... 49 | # -Wstrict-overflow= Warn about optimizations ... 50 | # So if we found `-Wstrict-overflow=` we should ignore it 51 | # and delete `-Wstrict-overflow` as well: 52 | delete($valid_options{$option}); 53 | } 54 | elsif ($option !~ /^-/ && !$last_option_skipped) 55 | { 56 | # Concatenate description if it was split into two lines: 57 | $line =~ s/^\s+//; 58 | $valid_options{$last_option} .= " $line"; 59 | } 60 | } 61 | } 62 | 63 | return %valid_options; 64 | } 65 | 66 | sub get_cpp_options 67 | { 68 | my %options = @_; 69 | my (undef, $filename) = tempfile(); 70 | 71 | # GCC uses the LC_CTYPE environment variable to determine what quotation 72 | # marks to use. If it's *.UTF-8 GCC will use ‘fancy’ quotes that don't 73 | # play well with character classes in regular expressions. Let's force it 74 | # to use ANSI quotes: 75 | my $output = `LC_CTYPE="C" gcc -x c++ -fsyntax-only ${\join(" ", keys(%options))} $filename 2>&1`; 76 | 77 | my @lines = split("\n", $output); 78 | foreach my $line (@lines) 79 | { 80 | if ($line =~ /command line option '(.+)' is valid/) 81 | { 82 | delete($options{$1}); 83 | } 84 | } 85 | 86 | return %options; 87 | } 88 | 89 | sub print_options 90 | { 91 | my $print_descriptions = pop(@_); 92 | my %options = @_; 93 | 94 | foreach my $option (sort(keys(%options))) 95 | { 96 | $print_descriptions 97 | ? printf(" %-35s %s\n", $option, $options{$option}) 98 | : print($option, " "); 99 | } 100 | 101 | print "\n"; 102 | } 103 | 104 | sub print_help 105 | { 106 | print << "END_HELP"; 107 | OVERVIEW: Print GCC warning options applicable to C++ code 108 | USAGE: $0 [options] 109 | OPTIONS: 110 | -h, --help Print this message. 111 | -p, --print-descriptions Print option descriptions in the following format: 112 | -Wuseless-cast Warn about useless casts. 113 | -Wunused-label Warn when a label is unused. 114 | ... 115 | -e, --enabled-only Print only currently enabled warning options. 116 | Useful to see what you have so far. 117 | -d, --disabled-only Print only currently disabled warning options. 118 | Useful to see what else can be enabled. 119 | GCC warning options Assorted GCC warning options: -Wall, -Wextra, 120 | -Wno-deprecated, etc. 121 | Use with `--enabled-only` or `--disabled-only`. 122 | 123 | Options `--enabled-only` and `--disabled-only` cannot be used together. 124 | END_HELP 125 | } 126 | 127 | sub get_cmd_arguments 128 | { 129 | my %arguments; 130 | 131 | foreach my $argument (@ARGV) 132 | { 133 | if ($argument eq "-h" || $argument eq "--help") 134 | { 135 | print_help(); 136 | exit(0); 137 | } 138 | elsif ($argument eq "-p" || $argument eq "--print-descriptions") 139 | { 140 | $arguments{"print_descriptions"} = 1; 141 | } 142 | elsif ($argument eq "-e" || $argument eq "--enabled-only") 143 | { 144 | $arguments{"enabled_only"} = 1; 145 | } 146 | elsif ($argument eq "-d" || $argument eq "--disabled-only") 147 | { 148 | $arguments{"disabled_only"} = 1; 149 | } 150 | elsif ($argument =~ /-W(no-)?/) 151 | { 152 | push(@{$arguments{"gcc_warnings"}}, $argument); 153 | } 154 | else 155 | { 156 | print("Unknown argument: $argument\n"); 157 | print_help(); 158 | exit(1); 159 | } 160 | } 161 | 162 | if ($arguments{"enabled_only"} && $arguments{"disabled_only"}) 163 | { 164 | print_help(); 165 | exit(1); 166 | } 167 | 168 | return %arguments; 169 | } 170 | 171 | sub filter_options 172 | { 173 | my $arguments = shift; 174 | my $cpp_options = shift; 175 | 176 | my $gcc_warnings = $arguments->{"gcc_warnings"} 177 | ? join(" ", @{$arguments->{"gcc_warnings"}}) 178 | : ""; 179 | my $filter = $arguments->{"enabled_only"} ? "enabled" 180 | : $arguments->{"disabled_only"} ? "disabled" 181 | : ""; 182 | 183 | my @lines = split("\n", `gcc $gcc_warnings -Q --help=warnings`); 184 | my @filtered_lines = grep(/$filter/, @lines); 185 | 186 | my %filtered_options; 187 | foreach my $line (@filtered_lines) 188 | { 189 | my $option = (split(" ", $line))[0]; 190 | if ($cpp_options->{$option}) 191 | { 192 | $filtered_options{$option} = $cpp_options->{$option}; 193 | } 194 | } 195 | 196 | return %filtered_options; 197 | } 198 | 199 | sub main 200 | { 201 | my %arguments = get_cmd_arguments(); 202 | 203 | my %options = get_warning_options(); 204 | my %cpp_options = get_cpp_options(%options); 205 | my %filtered_options = filter_options(\%arguments, \%cpp_options); 206 | 207 | print_options(%filtered_options, $arguments{"print_descriptions"}); 208 | } 209 | 210 | main(); 211 | 212 | --------------------------------------------------------------------------------