diff options
Diffstat (limited to 'libcpp')
-rw-r--r-- | libcpp/include/cpplib.h | 7 | ||||
-rw-r--r-- | libcpp/init.cc | 1 | ||||
-rw-r--r-- | libcpp/internal.h | 3 | ||||
-rw-r--r-- | libcpp/lex.cc | 109 |
4 files changed, 118 insertions, 2 deletions
diff --git a/libcpp/include/cpplib.h b/libcpp/include/cpplib.h index 5441229..b4ff6a9 100644 --- a/libcpp/include/cpplib.h +++ b/libcpp/include/cpplib.h @@ -609,9 +609,15 @@ struct cpp_options /* True if -finput-charset= option has been used explicitly. */ bool cpp_input_charset_explicit; + /* -Wleading-whitespace= value. */ + unsigned char cpp_warn_leading_whitespace; + /* -Wtrailing-whitespace= value. */ unsigned char cpp_warn_trailing_whitespace; + /* -ftabstop= value. */ + unsigned int cpp_tabstop; + /* Dependency generation. */ struct { @@ -738,6 +744,7 @@ enum cpp_warning_reason { CPP_W_UNICODE, CPP_W_HEADER_GUARD, CPP_W_PRAGMA_ONCE_OUTSIDE_HEADER, + CPP_W_LEADING_WHITESPACE, CPP_W_TRAILING_WHITESPACE }; diff --git a/libcpp/init.cc b/libcpp/init.cc index 4789274..fff0eb8 100644 --- a/libcpp/init.cc +++ b/libcpp/init.cc @@ -261,6 +261,7 @@ cpp_create_reader (enum c_lang lang, cpp_hash_table *table, CPP_OPTION (pfile, cpp_warn_invalid_utf8) = 0; CPP_OPTION (pfile, cpp_warn_unicode) = 1; CPP_OPTION (pfile, cpp_input_charset_explicit) = 0; + CPP_OPTION (pfile, cpp_tabstop) = 8; /* Default CPP arithmetic to something sensible for the host for the benefit of dumb users like fix-header. */ diff --git a/libcpp/internal.h b/libcpp/internal.h index 13186c5..066652b 100644 --- a/libcpp/internal.h +++ b/libcpp/internal.h @@ -318,7 +318,8 @@ struct _cpp_line_note /* Type of note. The 9 'from' trigraph characters represent those trigraphs, '\\' an escaped newline, ' ' an escaped newline with - intervening space, 'W' trailing whitespace, 0 represents a note that + intervening space, 'W' trailing whitespace, 'L', 'S' and 'T' for + leading whitespace issues, 0 represents a note that has already been handled, and anything else is invalid. */ unsigned int type; }; diff --git a/libcpp/lex.cc b/libcpp/lex.cc index bb5cd39..8406c10 100644 --- a/libcpp/lex.cc +++ b/libcpp/lex.cc @@ -818,6 +818,59 @@ _cpp_init_lexer (void) #endif } +/* Look for leading whitespace style issues on lines which don't contain + just whitespace. + For -Wleading-whitespace=spaces report if such lines contain leading + whitespace other than spaces. + For -Wleading-whitespace=tabs report if such lines contain leading + whitespace other than tabs. + For -Wleading-whitespace=blanks report if such lines contain leading + whitespace other than spaces+tabs, or contain in it tab after space, + or -ftabstop= or more consecutive spaces. */ + +static void +find_leading_whitespace_issues (cpp_reader *pfile, const uchar *s) +{ + const unsigned char *p = NULL; + uchar type = 'L'; + switch (CPP_OPTION (pfile, cpp_warn_leading_whitespace)) + { + case 1: /* spaces */ + while (*s == ' ') + ++s; + break; + case 2: /* tabs */ + while (*s == '\t') + ++s; + break; + case 3: /* blanks */ + while (*s == '\t') + ++s; + int n; + n = CPP_OPTION (pfile, cpp_tabstop); + while (*s == ' ') + { + if (--n == 0) + break; + ++s; + } + if (*s == '\t') + type = 'T'; /* Tab after space. */ + else if (*s == ' ') + type = 'S'; /* Too many spaces. */ + break; + default: + abort (); + } + if (!IS_NVSPACE (*s)) + return; + p = s++; + while (IS_NVSPACE (*s)) + ++s; + if (*s != '\n' && *s != '\r') + add_line_note (pfile->buffer, p, type); +} + /* Returns with a logical line that contains no escaped newlines or trigraphs. This is a time-critical inner loop. */ void @@ -836,6 +889,10 @@ _cpp_clean_line (cpp_reader *pfile) if (!buffer->from_stage3) { const uchar *pbackslash = NULL; + bool leading_ws_done = true; + + if (CPP_OPTION (pfile, cpp_warn_leading_whitespace)) + find_leading_whitespace_issues (pfile, s); /* Fast path. This is the common case of an un-escaped line with no trigraphs. The primary win here is by not writing any @@ -906,6 +963,7 @@ _cpp_clean_line (cpp_reader *pfile) add_line_note (buffer, p - 1, p != d ? ' ' : '\\'); d = p - 2; buffer->next_line = p - 1; + leading_ws_done = false; slow_path: while (1) @@ -915,6 +973,10 @@ _cpp_clean_line (cpp_reader *pfile) if (c == '\n' || c == '\r') { + if (CPP_OPTION (pfile, cpp_warn_leading_whitespace) + && !leading_ws_done) + find_leading_whitespace_issues (pfile, buffer->next_line); + /* Handle DOS line endings. */ if (c == '\r' && s != buffer->rlimit && s[1] == '\n') s++; @@ -931,9 +993,17 @@ _cpp_clean_line (cpp_reader *pfile) add_line_note (buffer, p - 1, p != d ? ' ' : '\\'); d = p - 2; buffer->next_line = p - 1; + leading_ws_done = false; } else if (c == '?' && s[1] == '?' && _cpp_trigraph_map[s[2]]) { + if (CPP_OPTION (pfile, cpp_warn_leading_whitespace) + && !leading_ws_done) + { + find_leading_whitespace_issues (pfile, buffer->next_line); + leading_ws_done = true; + } + /* Add a note regardless, for the benefit of -Wtrigraphs. */ add_line_note (buffer, d, s[2]); if (CPP_OPTION (pfile, trigraphs)) @@ -1073,6 +1143,39 @@ _cpp_process_line_notes (cpp_reader *pfile, int in_comment) cpp_warning_with_line (pfile, CPP_W_TRAILING_WHITESPACE, pfile->line_table->highest_line, col, "trailing whitespace"); + else if (note->type == 'S') + cpp_warning_with_line (pfile, CPP_W_LEADING_WHITESPACE, + pfile->line_table->highest_line, col, + "too many consecutive spaces in leading " + "whitespace"); + else if (note->type == 'T') + cpp_warning_with_line (pfile, CPP_W_LEADING_WHITESPACE, + pfile->line_table->highest_line, col, + "tab after space in leading whitespace"); + else if (note->type == 'L') + switch (CPP_OPTION (pfile, cpp_warn_leading_whitespace)) + { + case 1: + cpp_warning_with_line (pfile, CPP_W_LEADING_WHITESPACE, + pfile->line_table->highest_line, col, + "whitespace other than spaces in leading " + "whitespace"); + break; + case 2: + cpp_warning_with_line (pfile, CPP_W_LEADING_WHITESPACE, + pfile->line_table->highest_line, col, + "whitespace other than tabs in leading " + "whitespace"); + break; + case 3: + cpp_warning_with_line (pfile, CPP_W_LEADING_WHITESPACE, + pfile->line_table->highest_line, col, + "whitespace other than spaces and tabs in " + "leading whitespace"); + break; + default: + abort (); + } else if (note->type == 0) /* Already processed in lex_raw_string. */; else @@ -2532,7 +2635,11 @@ lex_raw_string (cpp_reader *pfile, cpp_token *token, const uchar *base) break; case 'W': - /* Don't warn about trailing whitespace in raw string literals. */ + case 'L': + case 'S': + case 'T': + /* Don't warn about leading or trailing whitespace in raw string + literals. */ note->type = 0; note++; break; |