re PR c/81448 (False positive -Werror=multistatement-macros in openssl)
authorMarek Polacek <polacek@redhat.com>
Wed, 2 Aug 2017 11:56:54 +0000 (11:56 +0000)
committerMarek Polacek <mpolacek@gcc.gnu.org>
Wed, 2 Aug 2017 11:56:54 +0000 (11:56 +0000)
PR c/81448
PR c/81306
* c-warn.c (warn_for_multistatement_macros): Prevent bogus
warnings.  Avoid walking MACRO_MAP_LOCATIONS.

* c-c++-common/Wmultistatement-macros-13.c: New test.

From-SVN: r250822

gcc/c-family/c-warn.c
gcc/c/ChangeLog
gcc/testsuite/ChangeLog
gcc/testsuite/c-c++-common/Wmultistatement-macros-13.c [new file with mode: 0644]

index 505070e5586ab0f888bb595107c92e4a6a62ace4..e970ab2a00d200efaacf50529d93cc418b032bfb 100644 (file)
@@ -2457,34 +2457,44 @@ warn_for_multistatement_macros (location_t body_loc, location_t next_loc,
       || body_loc_exp == next_loc_exp)
     return;
 
-  /* Find the macro map for the macro expansion BODY_LOC.  */
-  const line_map *map = linemap_lookup (line_table, body_loc);
-  const line_map_macro *macro_map = linemap_check_macro (map);
-
-  /* Now see if the following token is coming from the same macro
-     expansion.  If it is, it's a problem, because it should've been
-     parsed at this point.  We only look at odd-numbered indexes
-     within the MACRO_MAP_LOCATIONS array, i.e. the spelling locations
-     of the tokens.  */
-  bool found_guard = false;
-  bool found_next = false;
-  for (unsigned int i = 1;
-       i < 2 * MACRO_MAP_NUM_MACRO_TOKENS (macro_map);
-       i += 2)
-    {
-      if (MACRO_MAP_LOCATIONS (macro_map)[i] == next_loc_exp)
-       found_next = true;
-      if (MACRO_MAP_LOCATIONS (macro_map)[i] == guard_loc_exp)
-       found_guard = true;
-    }
+  /* Find the macro maps for the macro expansions.  */
+  const line_map *body_map = linemap_lookup (line_table, body_loc);
+  const line_map *next_map = linemap_lookup (line_table, next_loc);
+  const line_map *guard_map = linemap_lookup (line_table, guard_loc);
+
+  /* Now see if the following token (after the body) is coming from the
+     same macro expansion.  If it is, it might be a problem.  */
+  if (body_map != next_map)
+    return;
 
   /* The conditional itself must not come from the same expansion, because
      we don't want to warn about
      #define IF if (x) x++; y++
      and similar.  */
-  if (!found_next || found_guard)
+  if (guard_map == body_map)
     return;
 
+  /* Handle the case where NEXT and BODY come from the same expansion while
+     GUARD doesn't, yet we shouldn't warn.  E.g.
+
+       #define GUARD if (...)
+       #define GUARD2 GUARD
+
+     and in the definition of another macro:
+
+       GUARD2
+       foo ();
+       return 1;
+   */
+  while (linemap_macro_expansion_map_p (guard_map))
+    {
+      const line_map_macro *mm = linemap_check_macro (guard_map);
+      guard_loc_exp = MACRO_MAP_EXPANSION_POINT_LOCATION (mm);
+      guard_map = linemap_lookup (line_table, guard_loc_exp);
+      if (guard_map == body_map)
+       return;
+    }
+
   if (warning_at (body_loc, OPT_Wmultistatement_macros,
                  "macro expands to multiple statements"))
     inform (guard_loc, "some parts of macro expansion are not guarded by "
index c89af1d57762bc411c1f22355839c038028c0e28..6c7b585fb83032c1308c43fbb87c149d781209fd 100644 (file)
@@ -3,6 +3,11 @@
        PR c/81289
        * c-parser.c (c_parser_unary_expression): Use set_error.
 
+       PR c/81448
+       PR c/81306
+       * c-warn.c (warn_for_multistatement_macros): Prevent bogus
+       warnings.  Avoid walking MACRO_MAP_LOCATIONS.
+
 2017-07-31  Jan Hubicka <hubicka@ucw.cz>
            Martin Liska  <mliska@suse.cz>
 
index a6d97e861f15e62a752fd97680cfd7940510c85e..9730b0cafa6d0bbc40f54a554744b43cf2d384f3 100644 (file)
@@ -3,6 +3,10 @@
        PR c/81289
        * gcc.dg/noncompile/pr81289.c: New test.
 
+       PR c/81448
+       PR c/81306
+       * c-c++-common/Wmultistatement-macros-13.c: New test.
+
 2017-08-02  Jakub Jelinek  <jakub@redhat.com>
 
        PR c++/81640
diff --git a/gcc/testsuite/c-c++-common/Wmultistatement-macros-13.c b/gcc/testsuite/c-c++-common/Wmultistatement-macros-13.c
new file mode 100644 (file)
index 0000000..9f42e26
--- /dev/null
@@ -0,0 +1,104 @@
+/* PR c/81448 */
+/* { dg-do compile } */
+/* { dg-options "-Wmultistatement-macros" } */
+
+extern int i;
+
+#define BAD4 i++; i++ /* { dg-warning "macro expands to multiple statements" } */
+#define BAD5 i++; i++ /* { dg-warning "macro expands to multiple statements" } */
+#define BAD6 i++; i++ /* { dg-warning "macro expands to multiple statements" } */
+#define BAD7 i++; i++ /* { dg-warning "macro expands to multiple statements" } */
+#define BAD8 i++; i++ /* { dg-warning "macro expands to multiple statements" } */
+#define BAD9 i++; i++ /* { dg-warning "macro expands to multiple statements" } */
+#define IF if (1) /* { dg-message "not guarded by this 'if' clause" } */
+#define IF2 IF /* { dg-message "in expansion of macro .IF." } */
+#define BADB7 BAD7 /* { dg-message "in expansion of macro .BAD7." } */
+#define BADB8 BAD8 /* { dg-message "in expansion of macro .BAD8." } */
+#define BADB9 BAD9 /* { dg-message "in expansion of macro .BAD9." } */
+
+#define FN0                            \
+void fn0 (void)                                \
+{                                      \
+  IF                                   \
+    i++;                               \
+  return;                              \
+}
+
+#define FN1                            \
+void fn1 (void)                                \
+{                                      \
+  IF2                                  \
+    i++;                               \
+  return;                              \
+}
+
+#define FN2                            \
+void fn2 (void)                                \
+{                                      \
+  if (1)                               \
+    i++;                               \
+  return;                              \
+}
+
+#define TOP FN3
+#define FN3                            \
+void fn3 (void)                                \
+{                                      \
+  IF                                   \
+    i++;                               \
+  return;                              \
+}
+
+#define TOP2 FN4 /* { dg-message "in expansion of macro .FN4." } */
+#define FN4                            \
+void fn4 (void)                                \
+{                                      \
+  IF2 /* { dg-message "in expansion of macro .IF2." } */ \
+    BAD4; /* { dg-message "in expansion of macro .BAD4." } */ \
+}
+
+#define FN5                            \
+void fn5 (void)                                \
+{                                      \
+  IF /* { dg-message "in expansion of macro .IF." } */ \
+    BAD5; /* { dg-message "in expansion of macro .BAD5." } */ \
+}
+
+#define FN6                            \
+void fn6 (void)                                \
+{                                      \
+  if (1) /* { dg-message "not guarded by this 'if' clause" } */ \
+    BAD6; /* { dg-message "in expansion of macro .BAD6." } */ \
+}
+
+#define FN7                            \
+void fn7 (void)                                \
+{                                      \
+  if (1) /* { dg-message "not guarded by this 'if' clause" } */        \
+    BADB7; /* { dg-message "in expansion of macro .BADB7." } */ \
+}
+
+#define FN8                            \
+void fn8 (void)                                \
+{                                      \
+  IF2 /* { dg-message "in expansion of macro .IF2." } */ \
+    BADB8; /* { dg-message "in expansion of macro .BADB8." } */ \
+}
+
+#define FN9                            \
+void fn9 (void)                                \
+{                                      \
+  IF /* { dg-message "in expansion of macro .IF." } */ \
+    BADB9; /* { dg-message "in expansion of macro .BADB9." } */        \
+}
+
+FN0
+FN1
+FN2
+TOP
+TOP2 /* { dg-message "in expansion of macro .TOP2." } */
+FN5 /* { dg-message "in expansion of macro .FN5." } */
+FN6 /* { dg-message "in expansion of macro .FN6." } */
+FN7 /* { dg-message "in expansion of macro .FN7." } */
+FN8 /* { dg-message "in expansion of macro .FN8." } */
+FN9 /* { dg-message "in expansion of macro .FN9." } */