diff options
author | Marek Polacek <polacek@redhat.com> | 2017-06-26 10:02:27 +0000 |
---|---|---|
committer | Marek Polacek <mpolacek@gcc.gnu.org> | 2017-06-26 10:02:27 +0000 |
commit | 3e2becc495c2ed8e48b055707430c8204826d7bf (patch) | |
tree | eb5ce085c45fa8f538a1c2ea1da0f6b4aee02485 /gcc/testsuite/c-c++-common | |
parent | 945653db613d34683696341759c4b070600b350c (diff) | |
download | gcc-3e2becc495c2ed8e48b055707430c8204826d7bf.zip gcc-3e2becc495c2ed8e48b055707430c8204826d7bf.tar.gz gcc-3e2becc495c2ed8e48b055707430c8204826d7bf.tar.bz2 |
re PR c/80116 (Warn about macros expanding to multiple statements)
PR c/80116
* c-common.h (warn_for_multistatement_macros): Declare.
* c-warn.c: Include "c-family/c-indentation.h".
(warn_for_multistatement_macros): New function.
* c.opt (Wmultistatement-macros): New option.
* c-indentation.c (guard_tinfo_to_string): No longer static.
Change the parameter type to "enum rid". Handle RID_SWITCH.
* c-indentation.h (guard_tinfo_to_string): Declare.
* c-parser.c (c_parser_if_body): Set the location of the
body of the conditional after parsing all the labels. Call
warn_for_multistatement_macros.
(c_parser_else_body): Likewise.
(c_parser_switch_statement): Likewise.
(c_parser_while_statement): Likewise.
(c_parser_for_statement): Likewise.
(c_parser_statement): Add a default argument. Save the location
after labels have been parsed.
(c_parser_c99_block_statement): Likewise.
* parser.c (cp_parser_statement): Add a default argument. Save the
location of the expression-statement after labels have been parsed.
(cp_parser_implicitly_scoped_statement): Set the location of the
body of the conditional after parsing all the labels. Call
warn_for_multistatement_macros.
(cp_parser_already_scoped_statement): Likewise.
* doc/invoke.texi: Document -Wmultistatement-macros.
* c-c++-common/Wmultistatement-macros-1.c: New test.
* c-c++-common/Wmultistatement-macros-2.c: New test.
* c-c++-common/Wmultistatement-macros-3.c: New test.
* c-c++-common/Wmultistatement-macros-4.c: New test.
* c-c++-common/Wmultistatement-macros-5.c: New test.
* c-c++-common/Wmultistatement-macros-6.c: New test.
* c-c++-common/Wmultistatement-macros-7.c: New test.
* c-c++-common/Wmultistatement-macros-8.c: New test.
* c-c++-common/Wmultistatement-macros-9.c: New test.
* c-c++-common/Wmultistatement-macros-10.c: New test.
* c-c++-common/Wmultistatement-macros-11.c: New test.
From-SVN: r249643
Diffstat (limited to 'gcc/testsuite/c-c++-common')
11 files changed, 566 insertions, 0 deletions
diff --git a/gcc/testsuite/c-c++-common/Wmultistatement-macros-1.c b/gcc/testsuite/c-c++-common/Wmultistatement-macros-1.c new file mode 100644 index 0000000..cdecbb4 --- /dev/null +++ b/gcc/testsuite/c-c++-common/Wmultistatement-macros-1.c @@ -0,0 +1,118 @@ +/* PR c/80116 */ +/* { dg-options "-Wmultistatement-macros" } */ +/* { dg-do compile } */ + +#define SWAP(X, Y) \ + tmp = X; /* { dg-warning "macro expands to multiple statements" } */ \ + X = Y; \ + Y = tmp + +#define STUFF \ + if (0) x = y + +#define STUFF2 \ + if (0) x = y; x++ + +#define STUFF3 \ + if (x) /* { dg-message "not guarded by this 'if' clause" } */ \ + SWAP(x, y) /* { dg-message "in expansion of macro .SWAP." } */ + +#define SET(X, Y) \ + (X) = (Y) + +#define STUFF4 \ + if (x) \ + SET(x, y); \ + SET(x, y) + +#define STUFF5 \ + { tmp = x; x = y; } + +#define STUFF6 \ + x++;; + +int x, y, tmp; + +void +fn1 (void) +{ + if (x) /* { dg-message "not guarded by this 'if' clause" } */ + SWAP(x, y); /* { dg-message "in expansion of macro .SWAP." } */ +} + +void +fn2 (void) +{ + SWAP(x, y); +} + +void +fn3 (void) +{ + if (x) + { + SWAP(x, y); + } +} + +void +fn4 (void) +{ + if (x) + ({ x = 10; x++; }); +} + +void +fn5 (void) +{ + if (x) /* { dg-message "not guarded by this 'if' clause" } */ +L1: + SWAP (x, y); /* { dg-message "in expansion of macro .SWAP." } */ + goto L1; +} + +void +fn6 (void) +{ + if (x) + SET (x, y); + SET (tmp, x); +} + +void +fn7 (void) +{ + STUFF; +} + +void +fn8 (void) +{ + STUFF2; +} + +void +fn9 (void) +{ + STUFF3; /* { dg-message "in expansion of macro .STUFF3." } */ +} + +void +fn10 (void) +{ + STUFF4; +} + +void +fn11 (void) +{ + if (x) + STUFF5; +} + +void +fn12 (void) +{ + if (x) + STUFF6; +} diff --git a/gcc/testsuite/c-c++-common/Wmultistatement-macros-10.c b/gcc/testsuite/c-c++-common/Wmultistatement-macros-10.c new file mode 100644 index 0000000..766ed25 --- /dev/null +++ b/gcc/testsuite/c-c++-common/Wmultistatement-macros-10.c @@ -0,0 +1,82 @@ +/* PR c/80116 */ +/* { dg-options "-Wmultistatement-macros" } */ +/* { dg-do compile } */ + +#define SWAP(x, y) \ + tmp = x; /* { dg-warning "macro expands to multiple statements" } */ \ + x = y; \ + y = tmp + +#define M1 \ + switch (x) /* { dg-message "not guarded by this 'switch' clause" } */ \ + case 1: \ + SWAP (x, y) /* { dg-message "in expansion of macro .SWAP." } */ + +#define M2 \ + switch (x) \ + case 1: \ + x++ + +#define M3 \ + switch (x) \ + case 1: \ + x++;; + +#define M4 \ + switch (x) /* { dg-message "not guarded by this 'switch' clause" } */ \ +L1: \ + case 1: \ + SWAP (x, y) /* { dg-message "in expansion of macro .SWAP." } */ + +#define INC \ + x++;; + +int x, y, tmp; + +void +fn0 (void) +{ + switch (x) /* { dg-message "not guarded by this 'switch' clause" } */ + case 1: + SWAP (x, y); /* { dg-message "in expansion of macro .SWAP." } */ + + switch (x) /* { dg-message "not guarded by this 'switch' clause" } */ + case 1: + case 2: + case 3: + case 4: + case 5: + SWAP (x, y); /* { dg-message "in expansion of macro .SWAP." } */ +} + +void +fn1 (void) +{ + M1; /* { dg-message "in expansion of macro .M1." } */ + M2; + M3; + M4; /* { dg-message "in expansion of macro .M4." } */ + goto L1; +} + +void +fn2 (void) +{ + switch (x) + case 1: + INC + + switch (x) + case 1: + ({ x = 10; x++; }); +} + +void +fn3 (void) +{ + switch (x) + { + case 1: + SWAP (x, y); + } +} diff --git a/gcc/testsuite/c-c++-common/Wmultistatement-macros-11.c b/gcc/testsuite/c-c++-common/Wmultistatement-macros-11.c new file mode 100644 index 0000000..4f4a123 --- /dev/null +++ b/gcc/testsuite/c-c++-common/Wmultistatement-macros-11.c @@ -0,0 +1,19 @@ +/* PR c/80116 */ +/* { dg-options "-Wmultistatement-macros" } */ +/* { dg-do compile } */ + +enum E { A, B }; + +const char * +foo (enum E e) +{ +#define CASE(X) case X: return #X + switch (e) + { + CASE (A); + CASE (B); + default: + return "<unknown>"; + } +#undef CASE +}; diff --git a/gcc/testsuite/c-c++-common/Wmultistatement-macros-2.c b/gcc/testsuite/c-c++-common/Wmultistatement-macros-2.c new file mode 100644 index 0000000..9fef901 --- /dev/null +++ b/gcc/testsuite/c-c++-common/Wmultistatement-macros-2.c @@ -0,0 +1,137 @@ +/* PR c/80116 */ +/* { dg-options "-Wmultistatement-macros" } */ +/* { dg-do compile } */ + +#define SWAP(X, Y) \ + tmp = X; /* { dg-warning "macro expands to multiple statements" } */ \ + X = Y; \ + Y = tmp + +#define STUFF \ + if (0) {} else x = y + +#define STUFF2 \ + if (0) {} else x = y; x++ + +#define STUFF3 \ + if (x) \ + {} \ + else /* { dg-message "not guarded by this 'else' clause" } */ \ + SWAP(x, y) /* { dg-message "in expansion of macro .SWAP." } */ + +#define SET(X, Y) \ + (X) = (Y) + +#define STUFF4 \ + if (x) \ + {} \ + else \ + SET(x, y); \ + SET(x, y) + +#define STUFF5 \ + { tmp = x; x = y; } + +#define STUFF6 \ + x++;; + +int x, y, tmp; + +void +fn1 (void) +{ + if (x) + { + } + else /* { dg-message "not guarded by this 'else' clause" } */ + SWAP(x, y); /* { dg-message "in expansion of macro .SWAP." } */ +} + +void +fn2 (void) +{ + SWAP(x, y); +} + +void +fn3 (void) +{ + if (x) + { + } + else + { + SWAP(x, y); + } +} + +void +fn4 (void) +{ + if (x) + { + } + else + ({ x = 10; x++; }); +} + +void +fn5 (void) +{ + if (x) + { + } + else /* { dg-message "not guarded by this 'else' clause" } */ +L1: + SWAP (x, y); /* { dg-message "in expansion of macro .SWAP." } */ + goto L1; +} + +void +fn6 (void) +{ + if (x) + { + } + else + SET (x, y); + SET (tmp, x); +} + +void +fn7 (void) +{ + STUFF; +} + +void +fn8 (void) +{ + STUFF2; +} + +void +fn9 (void) +{ + STUFF3; /* { dg-message "in expansion of macro .STUFF3." } */ +} + +void +fn10 (void) +{ + STUFF4; +} + +void +fn11 (void) +{ + if (x) + STUFF5; +} + +void +fn12 (void) +{ + if (x) + STUFF6; +} diff --git a/gcc/testsuite/c-c++-common/Wmultistatement-macros-3.c b/gcc/testsuite/c-c++-common/Wmultistatement-macros-3.c new file mode 100644 index 0000000..d130a35 --- /dev/null +++ b/gcc/testsuite/c-c++-common/Wmultistatement-macros-3.c @@ -0,0 +1,12 @@ +/* PR c/80116 */ +/* { dg-options "-Wmultistatement-macros" } */ +/* { dg-do compile } */ + +#define CHECK(X) if (!(X)) __builtin_abort () + +void +fn (int i) +{ + CHECK (i == 1); + CHECK (i == 2); +} diff --git a/gcc/testsuite/c-c++-common/Wmultistatement-macros-4.c b/gcc/testsuite/c-c++-common/Wmultistatement-macros-4.c new file mode 100644 index 0000000..e5cc9c3 --- /dev/null +++ b/gcc/testsuite/c-c++-common/Wmultistatement-macros-4.c @@ -0,0 +1,14 @@ +/* PR c/80116 */ +/* { dg-options "-Wmultistatement-macros" } */ +/* { dg-do compile } */ + +#define FN(C) \ + void \ + fn (void) \ + { \ + C; \ + } + +int i; + +FN (if (i) ++i) diff --git a/gcc/testsuite/c-c++-common/Wmultistatement-macros-5.c b/gcc/testsuite/c-c++-common/Wmultistatement-macros-5.c new file mode 100644 index 0000000..0ac84f5 --- /dev/null +++ b/gcc/testsuite/c-c++-common/Wmultistatement-macros-5.c @@ -0,0 +1,18 @@ +/* PR c/80116 */ +/* { dg-options "-Wmultistatement-macros" } */ +/* { dg-do compile } */ + +#define M(N) \ +L ## N: \ + x++; x++ /* { dg-warning "macro expands to multiple statements" } */ + +int x, y, tmp; + +void +fn1 (void) +{ + if (x) /* { dg-message "not guarded by this 'if' clause" } */ + M (0); /* { dg-message "in expansion of macro .M." } */ + if (x) /* { dg-message "not guarded by this 'if' clause" } */ + M (1); /* { dg-message "in expansion of macro .M." } */ +} diff --git a/gcc/testsuite/c-c++-common/Wmultistatement-macros-6.c b/gcc/testsuite/c-c++-common/Wmultistatement-macros-6.c new file mode 100644 index 0000000..5ec9cd9 --- /dev/null +++ b/gcc/testsuite/c-c++-common/Wmultistatement-macros-6.c @@ -0,0 +1,22 @@ +/* PR c/80116 */ +/* { dg-options "-Wmultistatement-macros" } */ +/* { dg-do compile } */ + +#define M \ + if (x) x++; x++ + +void +f (int x) +{ + M; + M; + M; + M; + M; + M; + M; + M; + M; + M; + M; +} diff --git a/gcc/testsuite/c-c++-common/Wmultistatement-macros-7.c b/gcc/testsuite/c-c++-common/Wmultistatement-macros-7.c new file mode 100644 index 0000000..d661f14 --- /dev/null +++ b/gcc/testsuite/c-c++-common/Wmultistatement-macros-7.c @@ -0,0 +1,18 @@ +/* PR c/80116 */ +/* { dg-options "-Wmultistatement-macros" } */ +/* { dg-do compile } */ + +#define SWAP(X, Y) \ + tmp = X; /* { dg-warning "macro expands to multiple statements" } */ \ + X = Y; \ + Y = tmp + +#define BODY_AND_IF(COND, X, Y) \ + if (COND) SWAP (X, Y) /* { dg-message "in expansion of macro .SWAP." } */ + +void +fn (int x, int y) +{ + int tmp; + BODY_AND_IF (1, x, y); /* { dg-message "in expansion of macro .BODY_AND_IF." } */ +} diff --git a/gcc/testsuite/c-c++-common/Wmultistatement-macros-8.c b/gcc/testsuite/c-c++-common/Wmultistatement-macros-8.c new file mode 100644 index 0000000..06522a7 --- /dev/null +++ b/gcc/testsuite/c-c++-common/Wmultistatement-macros-8.c @@ -0,0 +1,64 @@ +/* PR c/80116 */ +/* { dg-options "-Wmultistatement-macros" } */ +/* { dg-do compile } */ + +#define SWAP(x, y) \ + tmp = x; /* { dg-warning "macro expands to multiple statements" } */ \ + x = y; \ + y = tmp + +#define M1 \ + for (i = 0; i < 1; ++i) /* { dg-message "not guarded by this 'for' clause" } */ \ + SWAP (x, y) /* { dg-message "in expansion of macro .SWAP." } */ + +#define M2 \ + for (i = 0; i < 1; ++i) \ + x++ + +#define M3 \ + for (i = 0; i < 1; ++i) \ + x++;; + +#define M4 \ + for (i = 0; i < 1; ++i) /* { dg-message "not guarded by this 'for' clause" } */ \ +L1: \ + SWAP (x, y) /* { dg-message "in expansion of macro .SWAP." } */ + +#define INC \ + x++;; + +int x, y, tmp; + +void +fn0 (void) +{ + int i; + for (i = 0; i < 1; ++i) /* { dg-message "not guarded by this 'for' clause" } */ + SWAP (x, y); /* { dg-message "in expansion of macro .SWAP." } */ + + for (i = 0; i < 1; ++i) /* { dg-message "not guarded by this 'for' clause" } */ +L: + SWAP (x, y); /* { dg-message "in expansion of macro .SWAP." } */ + goto L; +} + +void +fn1 (void) +{ + int i; + M1; /* { dg-message "in expansion of macro .M1." } */ + M2; + M3; + M4; /* { dg-message "in expansion of macro .M4." } */ + goto L1; +} + +void +fn2 (void) +{ + for (int i = 0; i < 1; ++i) + INC + + for (int i = 0; i < 1; ++i) + ({ x = 10; x++; }); +} diff --git a/gcc/testsuite/c-c++-common/Wmultistatement-macros-9.c b/gcc/testsuite/c-c++-common/Wmultistatement-macros-9.c new file mode 100644 index 0000000..350c4f9f --- /dev/null +++ b/gcc/testsuite/c-c++-common/Wmultistatement-macros-9.c @@ -0,0 +1,62 @@ +/* PR c/80116 */ +/* { dg-options "-Wmultistatement-macros" } */ +/* { dg-do compile } */ + +#define SWAP(x, y) \ + tmp = x; /* { dg-warning "macro expands to multiple statements" } */ \ + x = y; \ + y = tmp + +#define M1 \ + while (x) /* { dg-message "not guarded by this 'while' claus" } */ \ + SWAP (x, y) /* { dg-message "in expansion of macro .SWAP." } */ + +#define M2 \ + while (x) \ + x++ + +#define M3 \ + while (x) \ + x++;; + +#define M4 \ + while (x) /* { dg-message "not guarded by this 'while' claus" } */ \ +L1: \ + SWAP (x, y) /* { dg-message "in expansion of macro .SWAP." } */ + +#define INC \ + x++;; + +int x, y, tmp; + +void +fn0 (void) +{ + while (x) /* { dg-message "not guarded by this 'while' claus" } */ + SWAP (x, y); /* { dg-message "in expansion of macro .SWAP." } */ + + while (x) /* { dg-message "not guarded by this 'while' claus" } */ +L: + SWAP (x, y); /* { dg-message "in expansion of macro .SWAP." } */ + goto L; +} + +void +fn1 (void) +{ + M1; /* { dg-message "in expansion of macro .M1." } */ + M2; + M3; + M4; /* { dg-message "in expansion of macro .M4." } */ + goto L1; +} + +void +fn2 (void) +{ + while (x) + INC + + while (x) + ({ x = 10; x++; }); +} |