This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

RFC: SAFE_MACRO_STMT


Hi,

when writing macros that are intended to be used as if they were single statements, there are a couple of common problems:

1. Ending in semicolon
...
#define foo stmt;
...

This works fine if we use it like:
...
void
bar (void)
{
  foo;
}
...

but we get an "else without a previous if" error when we use it like:
...
void
bar (void)
{
  if (1)
    foo;
  else
    {}
}
...

2. Using if-then-else without wrapping in "do {} while (0)"
...
#define foo if (1) stmt; else {}
...

Again this works fine if we use it like:
...
void
bar (void)
{
  foo;
}
...

but we get an "suggest explicit braces to avoid ambiguous else [-Wparentheses]" warning when we use it like:
...
void
bar (void)
{
  if (1)
    foo;
}
...

3. Multi statement without wrapping it in "do {} while (0)"
...
#define foo stmt; stmt
...

Again this works fine if we use it like:
...
void
bar (void)
{
  foo;
}
...

but we get a "macro expands to multiple statements [-Wmultistatement-macros]" warning when we use it like:
...
void
bar (void)
{
  if (1)
    foo;
}
...


I've written a macro SAFE_MACRO_STMT that triggers these three situations for a macro, but does not change the semantics:
...
#define SAFE_MACRO_STMT(stmt)                   \
  do {                                          \
    stmt;                                       \
    if (0)                                      \
      stmt;                                     \
    else                                        \
      {}                                        \
    if (0)                                      \
      stmt;                                     \
  } while (0)
...

In other words, by wrapping the macro usage in SAFE_MACRO_STMT, we trigger an error or warning if the macro body contains any of the problems:
...
void
bar (void)
{
  SAFE_MACRO_STMT (foo);
}
...

The first demonstrator patch applies this strategy to ASM_OUTPUT_ADDR_VEC_ELT. This smokes out a type 1 error in the ft32 definition of ASM_OUTPUT_ADDR_VEC_ELT, which is fixed by the second patch.

Any comments on this approach?

Thanks,
- Tom
Use SAFE_MACRO_STMT for ASM_OUTPUT_ADDR_VEC_ELT

---
 gcc/final.c | 17 +++++++++++++++--
 1 file changed, 15 insertions(+), 2 deletions(-)

diff --git a/gcc/final.c b/gcc/final.c
index 672c5bb..17c1c12 100644
--- a/gcc/final.c
+++ b/gcc/final.c
@@ -2169,6 +2169,17 @@ asm_show_source (const char *filename, int linenum)
   fputc ('\n', asm_out_file);
 }
 
+#define SAFE_MACRO_STMT(stmt)                   \
+  do {                                          \
+    stmt;					\
+    if (0)                                      \
+      stmt;                                     \
+    else                                        \
+      {}                                        \
+    if (0)                                      \
+      stmt;                                     \
+  } while (0)
+
 /* The final scan for one insn, INSN.
    Args are same as in `final', except that INSN
    is the insn being scanned.
@@ -2562,8 +2573,10 @@ final_scan_insn (rtx_insn *insn, FILE *file, int optimize_p ATTRIBUTE_UNUSED,
 		if (GET_CODE (body) == ADDR_VEC)
 		  {
 #ifdef ASM_OUTPUT_ADDR_VEC_ELT
-		    ASM_OUTPUT_ADDR_VEC_ELT
-		      (file, CODE_LABEL_NUMBER (XEXP (XVECEXP (body, 0, idx), 0)));
+		    SAFE_MACRO_STMT
+		      (ASM_OUTPUT_ADDR_VEC_ELT
+		       (file,
+			CODE_LABEL_NUMBER (XEXP (XVECEXP (body, 0, idx), 0))));
 #else
 		    gcc_unreachable ();
 #endif
[ft32] Remove semicolon after ASM_OUTPUT_ADDR_VEC_ELT

---
 gcc/config/ft32/ft32.h | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/gcc/config/ft32/ft32.h b/gcc/config/ft32/ft32.h
index b276f25..c32db40 100644
--- a/gcc/config/ft32/ft32.h
+++ b/gcc/config/ft32/ft32.h
@@ -205,7 +205,7 @@ enum reg_class
 /* This is how to output an element of a case-vector that is absolute.  */
 
 #define ASM_OUTPUT_ADDR_VEC_ELT(FILE, VALUE)  \
-    fprintf (FILE, "\t.long\t.L%d\n", VALUE);				\
+    fprintf (FILE, "\t.long\t.L%d\n", VALUE)				\
 
 /* Passing Arguments in Registers */
 

Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]