|| 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 "
--- /dev/null
+/* 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." } */