aboutsummaryrefslogtreecommitdiff
path: root/gcc/testsuite/c-c++-common
diff options
context:
space:
mode:
authorMarek Polacek <polacek@redhat.com>2017-06-26 10:02:27 +0000
committerMarek Polacek <mpolacek@gcc.gnu.org>2017-06-26 10:02:27 +0000
commit3e2becc495c2ed8e48b055707430c8204826d7bf (patch)
treeeb5ce085c45fa8f538a1c2ea1da0f6b4aee02485 /gcc/testsuite/c-c++-common
parent945653db613d34683696341759c4b070600b350c (diff)
downloadgcc-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')
-rw-r--r--gcc/testsuite/c-c++-common/Wmultistatement-macros-1.c118
-rw-r--r--gcc/testsuite/c-c++-common/Wmultistatement-macros-10.c82
-rw-r--r--gcc/testsuite/c-c++-common/Wmultistatement-macros-11.c19
-rw-r--r--gcc/testsuite/c-c++-common/Wmultistatement-macros-2.c137
-rw-r--r--gcc/testsuite/c-c++-common/Wmultistatement-macros-3.c12
-rw-r--r--gcc/testsuite/c-c++-common/Wmultistatement-macros-4.c14
-rw-r--r--gcc/testsuite/c-c++-common/Wmultistatement-macros-5.c18
-rw-r--r--gcc/testsuite/c-c++-common/Wmultistatement-macros-6.c22
-rw-r--r--gcc/testsuite/c-c++-common/Wmultistatement-macros-7.c18
-rw-r--r--gcc/testsuite/c-c++-common/Wmultistatement-macros-8.c64
-rw-r--r--gcc/testsuite/c-c++-common/Wmultistatement-macros-9.c62
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++; });
+}