aboutsummaryrefslogtreecommitdiff
path: root/libcpp
diff options
context:
space:
mode:
Diffstat (limited to 'libcpp')
-rw-r--r--libcpp/ChangeLog8
-rw-r--r--libcpp/include/cpplib.h3
-rw-r--r--libcpp/init.c1
-rw-r--r--libcpp/lex.c103
4 files changed, 104 insertions, 11 deletions
diff --git a/libcpp/ChangeLog b/libcpp/ChangeLog
index 1f4db49..40bd5cd 100644
--- a/libcpp/ChangeLog
+++ b/libcpp/ChangeLog
@@ -1,3 +1,11 @@
+2016-10-12 Jakub Jelinek <jakub@redhat.com>
+
+ * include/cpplib.h (struct cpp_options): Add
+ cpp_warn_implicit_fallthrough.
+ * init.c (cpp_create_reader): Initialize it to 0.
+ * lex.c (fallthrough_comment_p): Handle different
+ cpp_warn_implicit_fallthrough levels. Whitespace fixes.
+
2016-10-08 Jakub Jelinek <jakub@redhat.com>
* lex.c (fallthrough_comment_p): Accept Else, fallthrough.
diff --git a/libcpp/include/cpplib.h b/libcpp/include/cpplib.h
index 6352ac5..0781c09 100644
--- a/libcpp/include/cpplib.h
+++ b/libcpp/include/cpplib.h
@@ -395,6 +395,9 @@ struct cpp_options
explicitly undefined. */
unsigned char warn_builtin_macro_redefined;
+ /* Different -Wimplicit-fallthrough= levels. */
+ unsigned char cpp_warn_implicit_fallthrough;
+
/* Nonzero means we should look for header.gcc files that remap file
names. */
unsigned char remap;
diff --git a/libcpp/init.c b/libcpp/init.c
index 2df8cfb..5e35280 100644
--- a/libcpp/init.c
+++ b/libcpp/init.c
@@ -189,6 +189,7 @@ cpp_create_reader (enum c_lang lang, cpp_hash_table *table,
CPP_OPTION (pfile, warn_dollars) = 1;
CPP_OPTION (pfile, warn_variadic_macros) = 1;
CPP_OPTION (pfile, warn_builtin_macro_redefined) = 1;
+ CPP_OPTION (pfile, cpp_warn_implicit_fallthrough) = 0;
/* By default, track locations of tokens resulting from macro
expansion. The '2' means, track the locations with the highest
accuracy. Read the comments for struct
diff --git a/libcpp/lex.c b/libcpp/lex.c
index 4d8e5e7..6f65fa1 100644
--- a/libcpp/lex.c
+++ b/libcpp/lex.c
@@ -2040,6 +2040,64 @@ static bool
fallthrough_comment_p (cpp_reader *pfile, const unsigned char *comment_start)
{
const unsigned char *from = comment_start + 1;
+
+ switch (CPP_OPTION (pfile, cpp_warn_implicit_fallthrough))
+ {
+ /* For both -Wimplicit-fallthrough=0 and -Wimplicit-fallthrough=5 we
+ don't recognize any comments. The latter only checks attributes,
+ the former doesn't warn. */
+ case 0:
+ default:
+ return false;
+ /* -Wimplicit-fallthrough=1 considers any comment, no matter what
+ content it has. */
+ case 1:
+ return true;
+ case 2:
+ /* -Wimplicit-fallthrough=2 looks for (case insensitive)
+ .*falls?[ \t-]*thr(u|ough).* regex. */
+ for (; (size_t) (pfile->buffer->cur - from) >= sizeof "fallthru" - 1;
+ from++)
+ {
+ /* Is there anything like strpbrk with upper boundary, or
+ memchr looking for 2 characters rather than just one? */
+ if (from[0] != 'f' && from[0] != 'F')
+ continue;
+ if (from[1] != 'a' && from[1] != 'A')
+ continue;
+ if (from[2] != 'l' && from[2] != 'L')
+ continue;
+ if (from[3] != 'l' && from[3] != 'L')
+ continue;
+ from += sizeof "fall" - 1;
+ if (from[0] == 's' || from[0] == 'S')
+ from++;
+ while (*from == ' ' || *from == '\t' || *from == '-')
+ from++;
+ if (from[0] != 't' && from[0] != 'T')
+ continue;
+ if (from[1] != 'h' && from[1] != 'H')
+ continue;
+ if (from[2] != 'r' && from[2] != 'R')
+ continue;
+ if (from[3] == 'u' || from[3] == 'U')
+ return true;
+ if (from[3] != 'o' && from[3] != 'O')
+ continue;
+ if (from[4] != 'u' && from[4] != 'U')
+ continue;
+ if (from[5] != 'g' && from[5] != 'G')
+ continue;
+ if (from[6] != 'h' && from[6] != 'H')
+ continue;
+ return true;
+ }
+ return false;
+ case 3:
+ case 4:
+ break;
+ }
+
/* Whole comment contents:
-fallthrough
@fallthrough@
@@ -2060,7 +2118,7 @@ fallthrough_comment_p (cpp_reader *pfile, const unsigned char *comment_start)
from += 1 + len;
}
/* Whole comment contents (regex):
- lint -fallthrough ?
+ lint -fallthrough[ \t]*
*/
else if (*from == 'l')
{
@@ -2068,10 +2126,33 @@ fallthrough_comment_p (cpp_reader *pfile, const unsigned char *comment_start)
if ((size_t) (pfile->buffer->cur - from - 1) < len)
return false;
if (memcmp (from + 1, "int -fallthrough", len))
- return false;
+ return false;
from += 1 + len;
- if (*from == ' ')
- from++;
+ while (*from == ' ' || *from == '\t')
+ from++;
+ }
+ /* Whole comment contents (regex):
+ [ \t]*FALLTHR(U|OUGH)[ \t]*
+ */
+ else if (CPP_OPTION (pfile, cpp_warn_implicit_fallthrough) == 4)
+ {
+ while (*from == ' ' || *from == '\t')
+ from++;
+ if ((size_t) (pfile->buffer->cur - from) < sizeof "FALLTHRU" - 1)
+ return false;
+ if (memcmp (from, "FALLTHR", sizeof "FALLTHR" - 1))
+ return false;
+ from += sizeof "FALLTHR" - 1;
+ if (*from == 'U')
+ from++;
+ else if ((size_t) (pfile->buffer->cur - from) < sizeof "OUGH" - 1)
+ return false;
+ else if (memcmp (from, "OUGH", sizeof "OUGH" - 1))
+ return false;
+ else
+ from += sizeof "OUGH" - 1;
+ while (*from == ' ' || *from == '\t')
+ from++;
}
/* Whole comment contents (regex):
[ \t.!]*(ELSE,? |INTENTIONAL(LY)? )?FALL(S | |-)?THR(OUGH|U)[ \t.!]*(-[^\n\r]*)?
@@ -2085,8 +2166,8 @@ fallthrough_comment_p (cpp_reader *pfile, const unsigned char *comment_start)
unsigned char f = *from;
bool all_upper = false;
if (f == 'E' || f == 'e')
- {
- if ((size_t) (pfile->buffer->cur - from)
+ {
+ if ((size_t) (pfile->buffer->cur - from)
< sizeof "else fallthru" - 1)
return false;
if (f == 'E' && memcmp (from + 1, "LSE", sizeof "LSE" - 1) == 0)
@@ -2096,7 +2177,7 @@ fallthrough_comment_p (cpp_reader *pfile, const unsigned char *comment_start)
from += sizeof "else" - 1;
if (*from == ',')
from++;
- if (*from != ' ')
+ if (*from != ' ')
return false;
from++;
if (all_upper && *from == 'f')
@@ -2104,10 +2185,10 @@ fallthrough_comment_p (cpp_reader *pfile, const unsigned char *comment_start)
if (f == 'e' && *from == 'F')
return false;
f = *from;
- }
+ }
else if (f == 'I' || f == 'i')
- {
- if ((size_t) (pfile->buffer->cur - from)
+ {
+ if ((size_t) (pfile->buffer->cur - from)
< sizeof "intentional fallthru" - 1)
return false;
if (f == 'I' && memcmp (from + 1, "NTENTIONAL",
@@ -2138,7 +2219,7 @@ fallthrough_comment_p (cpp_reader *pfile, const unsigned char *comment_start)
if (f == 'i' && *from == 'F')
return false;
f = *from;
- }
+ }
if (f != 'F' && f != 'f')
return false;
if ((size_t) (pfile->buffer->cur - from) < sizeof "fallthru" - 1)