From 900968f1be1a10c67dd5f4d858f57227d5a09533 Mon Sep 17 00:00:00 2001
From: David Malcolm <dmalcolm@redhat.com>
Date: Tue, 15 Mar 2016 04:56:00 -0400
Subject: [PATCH 09/10] FIXME: add C++ support to -Wunsafe-macro-expansion

---
 gcc/cp/semantics.c                                 |  1 +
 .../c-c++-common/Wunsafe-macro-expansion-2.c       | 46 --------------
 gcc/testsuite/g++.dg/Wunsafe-macro-expansion-2.C   | 73 ++++++++++++++++++++++
 gcc/testsuite/gcc.dg/Wunsafe-macro-expansion-2.c   | 46 ++++++++++++++
 4 files changed, 120 insertions(+), 46 deletions(-)
 delete mode 100644 gcc/testsuite/c-c++-common/Wunsafe-macro-expansion-2.c
 create mode 100644 gcc/testsuite/g++.dg/Wunsafe-macro-expansion-2.C
 create mode 100644 gcc/testsuite/gcc.dg/Wunsafe-macro-expansion-2.c

diff --git a/gcc/cp/semantics.c b/gcc/cp/semantics.c
index a3c0fe9..679b703 100644
--- a/gcc/cp/semantics.c
+++ b/gcc/cp/semantics.c
@@ -382,6 +382,7 @@ add_stmt (tree t)
     STATEMENT_LIST_HAS_LABEL (cur_stmt_list) = 1;
 
   warn_for_macro_side_effects (t);
+  warn_for_unsafe_macro_expansion (t);
 
   /* Add T to the statement-tree.  Non-side-effect statements need to be
      recorded during statement expressions.  */
diff --git a/gcc/testsuite/c-c++-common/Wunsafe-macro-expansion-2.c b/gcc/testsuite/c-c++-common/Wunsafe-macro-expansion-2.c
deleted file mode 100644
index 6d95b62..0000000
--- a/gcc/testsuite/c-c++-common/Wunsafe-macro-expansion-2.c
+++ /dev/null
@@ -1,46 +0,0 @@
-/* Reduced reproducer for the issue described in
-   https://dmalcolm.fedorapeople.org/presentations/PyCon-US-2013/PyCon-US-2013-dmalcolm-StaticAnalysis.html#(38)
-*/
-
-/* { dg-options "-Wunsafe-macro-expansion -fdiagnostics-show-caret" } */
-
-#define NULL ((void *)0)
-typedef struct _object { int ob_refcnt; } PyObject;
-#define Py_DECREF(op)                                   \
-    do {                                                \
-        if (--((PyObject*)(op))->ob_refcnt == 0)        \
-          _Py_Dealloc((PyObject *)(op));                \
-    } while (0)
-#define Py_XDECREF(op) do { if ((op) == NULL) ; else Py_DECREF(op); } while (0)
-/* { dg-message "parameter 1 ..op.. is expanded 2 times by macro .Py_XDECREF." "" { target *-*-* } 14 } */
-#define _Py_Dealloc(op) /* no-op for simplicity */
-
-extern PyObject *
-PyObject_CallObject (PyObject *callable_object, PyObject *args);
-
-void
-test_1 (PyObject *callable, PyObject *args)
-{
-  Py_XDECREF(PyObject_CallObject(callable, args)); /* { dg-warning "repeated side-effects within expansion of unsafe macro .Py_XDECREF." } */
-
-  /* { dg-begin-multiline-output "" }
-   Py_XDECREF(PyObject_CallObject(callable, args));
-              ^
-     { dg-end-multiline-output "" } */
-  /* { dg-begin-multiline-output "" }
- #define Py_XDECREF(op) do { if ((op) == NULL) ; else Py_DECREF(op); } while (0)
-                                  ^~
-     { dg-end-multiline-output "" } */
-  /* { dg-begin-multiline-output "" }
- #define Py_XDECREF(op) do { if ((op) == NULL) ; else Py_DECREF(op); } while (0)
-                                  ^~                            ^~
-     { dg-end-multiline-output "" } */
-}
-
-/* This invocation doesn't have side-effects; we shouldn't warn.  */
-
-void
-test_2 (PyObject *obj)
-{
-  Py_XDECREF (obj);
-}
diff --git a/gcc/testsuite/g++.dg/Wunsafe-macro-expansion-2.C b/gcc/testsuite/g++.dg/Wunsafe-macro-expansion-2.C
new file mode 100644
index 0000000..785e62b
--- /dev/null
+++ b/gcc/testsuite/g++.dg/Wunsafe-macro-expansion-2.C
@@ -0,0 +1,73 @@
+/* Reduced reproducer for the issue described in
+   https://dmalcolm.fedorapeople.org/presentations/PyCon-US-2013/PyCon-US-2013-dmalcolm-StaticAnalysis.html#(38)
+*/
+
+/* { dg-options "-Wunsafe-macro-expansion -fdiagnostics-show-caret" } */
+
+#define NULL ((void *)0)
+typedef struct _object { int ob_refcnt; } PyObject;
+#define Py_DECREF(op)                                   \
+    do {                                                \
+        if (--((PyObject*)(op))->ob_refcnt == 0)        \
+          _Py_Dealloc((PyObject *)(op));                \
+    } while (0)
+#define Py_XDECREF(op) do { if ((op) == NULL) ; else Py_DECREF(op); } while (0)
+/* { dg-message "parameter 1 ..op.. is expanded 2 times by macro .Py_XDECREF." "" { target *-*-* } 14 } */
+#define _Py_Dealloc(op) /* no-op for simplicity */
+
+extern PyObject *
+PyObject_CallObject (PyObject *callable_object, PyObject *args);
+
+void
+test_1 (PyObject *callable, PyObject *args)
+{
+  Py_XDECREF(PyObject_CallObject(callable, args)); /* { dg-warning "repeated side-effects within expansion of unsafe macro .Py_XDECREF." } */
+  /* { dg-warning "repeated side-effects within expansion of unsafe macro .Py_DECREF." "" { target *-*-* } 24 } */
+
+  /* { dg-begin-multiline-output "" }
+   Py_XDECREF(PyObject_CallObject(callable, args));
+                                 ^
+     { dg-end-multiline-output "" } */
+  /* { dg-begin-multiline-output "" }
+ #define Py_XDECREF(op) do { if ((op) == NULL) ; else Py_DECREF(op); } while (0)
+                                  ^~
+     { dg-end-multiline-output "" } */
+  /* { dg-begin-multiline-output "" }
+ #define Py_XDECREF(op) do { if ((op) == NULL) ; else Py_DECREF(op); } while (0)
+                                  ^~                            ^~
+     { dg-end-multiline-output "" } */
+
+
+  /* { dg-begin-multiline-output "" }
+   Py_XDECREF(PyObject_CallObject(callable, args));
+                                 ^
+     { dg-end-multiline-output "" } */
+  /* { dg-begin-multiline-output "" }
+         if (--((PyObject*)(op))->ob_refcnt == 0)        \
+                            ^~
+     { dg-end-multiline-output "" } */
+  /* { dg-begin-multiline-output "" }
+   Py_XDECREF(PyObject_CallObject(callable, args));
+   ^~~~~~~~~~
+     { dg-end-multiline-output "" } */
+
+  /* { dg-begin-multiline-output "" }
+ #define Py_DECREF(op)                                   \
+     { dg-end-multiline-output "" } */
+  /* { dg-locus "28" "" { target *-*-* } "11" } */
+  /* { dg-begin-multiline-output "" }
+         if (--((PyObject*)(op))->ob_refcnt == 0)        \
+                            ^~
+           _Py_Dealloc((PyObject *)(op));                \
+                                    ^~
+     { dg-end-multiline-output "" } */
+
+}
+
+/* This invocation doesn't have side-effects; we shouldn't warn.  */
+
+void
+test_2 (PyObject *obj)
+{
+  Py_XDECREF (obj);
+}
diff --git a/gcc/testsuite/gcc.dg/Wunsafe-macro-expansion-2.c b/gcc/testsuite/gcc.dg/Wunsafe-macro-expansion-2.c
new file mode 100644
index 0000000..6d95b62
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/Wunsafe-macro-expansion-2.c
@@ -0,0 +1,46 @@
+/* Reduced reproducer for the issue described in
+   https://dmalcolm.fedorapeople.org/presentations/PyCon-US-2013/PyCon-US-2013-dmalcolm-StaticAnalysis.html#(38)
+*/
+
+/* { dg-options "-Wunsafe-macro-expansion -fdiagnostics-show-caret" } */
+
+#define NULL ((void *)0)
+typedef struct _object { int ob_refcnt; } PyObject;
+#define Py_DECREF(op)                                   \
+    do {                                                \
+        if (--((PyObject*)(op))->ob_refcnt == 0)        \
+          _Py_Dealloc((PyObject *)(op));                \
+    } while (0)
+#define Py_XDECREF(op) do { if ((op) == NULL) ; else Py_DECREF(op); } while (0)
+/* { dg-message "parameter 1 ..op.. is expanded 2 times by macro .Py_XDECREF." "" { target *-*-* } 14 } */
+#define _Py_Dealloc(op) /* no-op for simplicity */
+
+extern PyObject *
+PyObject_CallObject (PyObject *callable_object, PyObject *args);
+
+void
+test_1 (PyObject *callable, PyObject *args)
+{
+  Py_XDECREF(PyObject_CallObject(callable, args)); /* { dg-warning "repeated side-effects within expansion of unsafe macro .Py_XDECREF." } */
+
+  /* { dg-begin-multiline-output "" }
+   Py_XDECREF(PyObject_CallObject(callable, args));
+              ^
+     { dg-end-multiline-output "" } */
+  /* { dg-begin-multiline-output "" }
+ #define Py_XDECREF(op) do { if ((op) == NULL) ; else Py_DECREF(op); } while (0)
+                                  ^~
+     { dg-end-multiline-output "" } */
+  /* { dg-begin-multiline-output "" }
+ #define Py_XDECREF(op) do { if ((op) == NULL) ; else Py_DECREF(op); } while (0)
+                                  ^~                            ^~
+     { dg-end-multiline-output "" } */
+}
+
+/* This invocation doesn't have side-effects; we shouldn't warn.  */
+
+void
+test_2 (PyObject *obj)
+{
+  Py_XDECREF (obj);
+}
-- 
1.8.5.3

