On 6/22/21 5:28 PM, David Malcolm wrote:
On Tue, 2021-06-22 at 19:18 -0400, David Malcolm wrote:
On Fri, 2021-06-04 at 15:41 -0600, Martin Sebor wrote:
The attached patch introduces the suppress_warning(),
warning_suppressed(), and copy_no_warning() APIs without making
use of them in the rest of GCC. They are in three files:
diagnostic-spec.{h,c}: Location-centric overloads.
warning-control.cc: Tree- and gimple*-centric overloads.
The location-centric overloads are suitable to use from the
diagnostic
subsystem. The rest can be used from the front ends and the middle
end.
[...snip...]
+/* Return true if warning OPT is suppressed for decl/expression
EXPR.
+ By default tests the disposition for any warning. */
+
+bool
+warning_suppressed_p (const_tree expr, opt_code opt /* =
all_warnings */)
+{
+ const nowarn_spec_t *spec = get_nowarn_spec (expr);
+
+ if (!spec)
+ return get_no_warning_bit (expr);
+
+ const nowarn_spec_t optspec (opt);
+ bool dis = *spec & optspec;
+ gcc_assert (get_no_warning_bit (expr) || !dis);
+ return dis;
Looking through the patch, I don't like the use of "dis" for the "is
suppressed" bool, since...
It's an argument to a a function, unlikely to confuse anyone. But
I also don't think it's important enough to argue about so I changed
it along with the comment below.
[...snip...]
+
+/* Enable, or by default disable, a warning for the statement STMT.
+ The wildcard OPT of -1 controls all warnings. */
...I find the above comment to be confusingly worded due to the double-
negative.
If I'm reading your intent correctly, how about this wording:
/* Change the supression of warnings for statement STMT.
OPT controls which warnings are affected.
The wildcard OPT of -1 controls all warnings.
If SUPP is true (the default), enable the suppression of the
warnings.
If SUPP is false, disable the suppression of the warnings. */
...and rename "dis" to "supp".
Or have I misread the intent of the patch?
+
+void
+suppress_warning (gimple *stmt, opt_code opt /* = all_warnings */,
+ bool dis /* = true */)
+{
+ if (opt == no_warning)
+ return;
+
+ const key_type_t key = convert_to_key (stmt);
+
+ dis = suppress_warning_at (key, opt, dis) || dis;
+ set_no_warning_bit (stmt, dis);
+}
[...snip...]
Also, I think I prefer having a separate entrypoints for the "all
warnings" case; on reading through the various patches I think that in
e.g.:
- TREE_NO_WARNING (*expr_p) = 1;
+ suppress_warning (*expr_p);
I prefer:
suppress_warnings (*expr_p);
(note the plural) since that way we can grep for them, and it seems
like better grammar to me.
Both entrypoints could be implemented by a static suppress_warning_1
internally if that makes it easier.
In that vein, "unsuppress_warning" seems far clearer to me that
"suppress_warning (FOO, false)"; IIRC there are very few uses of this
non-default arg (I couldn't find any in a quick look through the v2
kit).
Does this make sense?
In my experience, names that differ only slightly (such as in just
one letter) tend to easily lead to frustrating mistakes. The new
warning_suppressed_p() added in this patch also handles multiple
warnings (via a wildcard) and uses a singular form, and as do
the gimple_{get,set}no_warning() functions that are being replaced.
So I don't think the suggested change is needed or would be
an improvement.
Similarly, there is no gimple_unset_no_warning() today and I don't
think adding unsuppress_warning() is necessary or would add value,
especially since there are just a handful of callers that re-enable
warnings. For the callers that might need to enable or disable
a warning based on some condition, it's more convenient to do so
in a single call then by having to call different functions based
the value of the condition.
In the attached patch I've changed the comment as you asked and
also renamed the dis argument to supp but kept the function names
the same. I've also moved a few changes to tree.h from a later
patch to this one to let it stand alone and regtested it on its
own on x86_64-linux. I'll plan to go ahead with this version
unless requestsfor substantive changes come up in the review of
the rest of the changes.
Thanks
Martin
Add support for per-location warning groups.
gcc/ChangeLog:
* Makefile.in (OBJS-libcommon): Add diagnostic-spec.o.
* gengtype.c (open_base_files): Add diagnostic-spec.h.
* diagnostic-spec.c: New file.
* diagnostic-spec.h: New file.
* tree.h (no_warning, all_warnings, suppress_warning_at): New
declarations.
* warning-control.cc: New file.
diff --git a/gcc/Makefile.in b/gcc/Makefile.in
index d32de22e4f2..3d8c2b94d70 100644
--- a/gcc/Makefile.in
+++ b/gcc/Makefile.in
@@ -1698,6 +1698,7 @@ OBJS = \
vmsdbgout.o \
vr-values.o \
vtable-verify.o \
+ warning-control.o \
web.o \
wide-int.o \
wide-int-print.o \
@@ -1709,8 +1710,8 @@ OBJS = \
# Objects in libcommon.a, potentially used by all host binaries and with
# no target dependencies.
-OBJS-libcommon = diagnostic.o diagnostic-color.o diagnostic-show-locus.o \
- diagnostic-format-json.o json.o \
+OBJS-libcommon = diagnostic-spec.o diagnostic.o diagnostic-color.o \
+ diagnostic-show-locus.o diagnostic-format-json.o json.o \
edit-context.o \
pretty-print.o intl.o \
sbitmap.o \
@@ -2650,6 +2651,7 @@ GTFILES = $(CPPLIB_H) $(srcdir)/input.h $(srcdir)/coretypes.h \
$(srcdir)/ipa-modref.h $(srcdir)/ipa-modref.c \
$(srcdir)/ipa-modref-tree.h \
$(srcdir)/signop.h \
+ $(srcdir)/diagnostic-spec.h $(srcdir)/diagnostic-spec.c \
$(srcdir)/dwarf2out.h \
$(srcdir)/dwarf2asm.c \
$(srcdir)/dwarf2cfi.c \
diff --git a/gcc/diagnostic-spec.c b/gcc/diagnostic-spec.c
new file mode 100644
index 00000000000..9d1cb0b653b
--- /dev/null
+++ b/gcc/diagnostic-spec.c
@@ -0,0 +1,179 @@
+/* Functions to enable and disable individual warnings on an expression
+ and statement basis.
+ Copyright (C) 2021 Free Software Foundation, Inc.
+ Contributed by Martin Sebor <mse...@redhat.com>
+
+ This file is part of GCC.
+
+ GCC is free software; you can redistribute it and/or modify it under
+ the terms of the GNU General Public License as published by the Free
+ Software Foundation; either version 3, or (at your option) any later
+ version.
+
+ GCC is distributed in the hope that it will be useful, but WITHOUT ANY
+ WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with GCC; see the file COPYING3. If not see
+ <http://www.gnu.org/licenses/>. */
+
+#include "config.h"
+#include "system.h"
+#include "coretypes.h"
+#include "backend.h"
+#include "bitmap.h"
+#include "tree.h"
+#include "cgraph.h"
+#include "hash-map.h"
+#include "diagnostic-spec.h"
+#include "pretty-print.h"
+#include "options.h"
+
+/* Initialize *THIS from warning option OPT. */
+
+nowarn_spec_t::nowarn_spec_t (opt_code opt)
+{
+ /* Create a very simple mapping based on testing and experience.
+ It should become more refined with time. */
+ switch (opt)
+ {
+ case no_warning:
+ bits = 0;
+ break;
+
+ case all_warnings:
+ bits = -1;
+ break;
+
+ /* Flow-sensitive warnings about pointer problems issued by both
+ front ends and the middle end. */
+ case OPT_Waddress:
+ case OPT_Wnonnull:
+ bits = NW_NONNULL;
+ break;
+
+ /* Flow-sensitive warnings about arithmetic overflow issued by both
+ front ends and the middle end. */
+ case OPT_Woverflow:
+ case OPT_Wshift_count_negative:
+ case OPT_Wshift_count_overflow:
+ case OPT_Wstrict_overflow:
+ bits = NW_VFLOW;
+ break;
+
+ /* Lexical warnings issued by front ends. */
+ case OPT_Wabi:
+ case OPT_Wlogical_op:
+ case OPT_Wparentheses:
+ case OPT_Wreturn_type:
+ case OPT_Wsizeof_array_div:
+ case OPT_Wstrict_aliasing:
+ case OPT_Wunused:
+ case OPT_Wunused_function:
+ case OPT_Wunused_but_set_variable:
+ case OPT_Wunused_variable:
+ case OPT_Wunused_but_set_parameter:
+ bits = NW_LEXICAL;
+ break;
+
+ /* Access warning group. */
+ case OPT_Warray_bounds:
+ case OPT_Warray_bounds_:
+ case OPT_Wformat_overflow_:
+ case OPT_Wformat_truncation_:
+ case OPT_Wrestrict:
+ case OPT_Wstrict_aliasing_:
+ case OPT_Wstringop_overflow_:
+ case OPT_Wstringop_overread:
+ case OPT_Wstringop_truncation:
+ bits = NW_ACCESS;
+ break;
+
+ /* Initialization warning group. */
+ case OPT_Winit_self:
+ case OPT_Wuninitialized:
+ case OPT_Wmaybe_uninitialized:
+ bits = NW_UNINIT;
+ break;
+
+ default:
+ /* A catchall group for everything else. */
+ bits = NW_OTHER;
+ }
+}
+
+/* Map from location to its no-warning disposition. */
+
+GTY(()) xint_hash_map_t *nowarn_map;
+
+/* Return the no-warning disposition for location LOC and option OPT
+ or for all/any otions by default. */
+
+bool
+warning_suppressed_at (location_t loc, opt_code opt /* = all_warnings */)
+{
+ if (!nowarn_map)
+ return false;
+
+ if (const nowarn_spec_t* const pspec = nowarn_map->get (loc))
+ {
+ const nowarn_spec_t optspec (opt);
+ return *pspec & optspec;
+ }
+
+ return false;
+}
+
+ /* Change the supression of warnings at location LOC.
+ OPT controls which warnings are affected.
+ The wildcard OPT of -1 controls all warnings.
+ If SUPP is true (the default), enable the suppression of the warnings.
+ If SUPP is false, disable the suppression of the warnings. */
+
+bool
+suppress_warning_at (location_t loc, opt_code opt /* = all_warnings */,
+ bool supp /* = true */)
+{
+ const nowarn_spec_t optspec (supp ? opt : opt_code ());
+
+ if (nowarn_spec_t *pspec = nowarn_map ? nowarn_map->get (loc) : NULL)
+ {
+ if (supp)
+ {
+ *pspec |= optspec;
+ return true;
+ }
+
+ *pspec &= optspec;
+ if (*pspec)
+ return true;
+
+ nowarn_map->remove (loc);
+ return false;
+ }
+
+ if (!supp || opt == no_warning)
+ return false;
+
+ if (!nowarn_map)
+ nowarn_map = xint_hash_map_t::create_ggc (32);
+
+ nowarn_map->put (loc, optspec);
+ return true;
+}
+
+/* Copy the no-warning disposition from one location to another. */
+
+void
+copy_warning (location_t to, location_t from)
+{
+ if (!nowarn_map)
+ return;
+
+ if (nowarn_spec_t *pspec = nowarn_map->get (from))
+ nowarn_map->put (to, *pspec);
+ else
+ nowarn_map->remove (to);
+}
diff --git a/gcc/diagnostic-spec.h b/gcc/diagnostic-spec.h
new file mode 100644
index 00000000000..62d9270ca6d
--- /dev/null
+++ b/gcc/diagnostic-spec.h
@@ -0,0 +1,140 @@
+/* Language-independent APIs to enable/disable per-location warnings.
+
+ Copyright (C) 2021 Free Software Foundation, Inc.
+ Contributed by Martin Sebor <mse...@redhat.com>
+
+ This file is part of GCC.
+
+ GCC is free software; you can redistribute it and/or modify it under
+ the terms of the GNU General Public License as published by the Free
+ Software Foundation; either version 3, or (at your option) any later
+ version.
+
+ GCC is distributed in the hope that it will be useful, but WITHOUT ANY
+ WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with GCC; see the file COPYING3. If not see
+ <http://www.gnu.org/licenses/>. */
+
+#ifndef DIAGNOSTIC_SPEC_H_INCLUDED
+#define DIAGNOSTIC_SPEC_H_INCLUDED
+
+#include "hash-map.h"
+
+/* A "bitset" of warning groups. */
+
+struct nowarn_spec_t
+{
+ enum
+ {
+ /* Middle end warnings about invalid accesses. */
+ NW_ACCESS = 1 << 0,
+ /* Front end/lexical warnings. */
+ NW_LEXICAL = 1 << 1,
+ /* Warnings about null pointers. */
+ NW_NONNULL = 1 << 2,
+ /* Warnings about uninitialized reads. */
+ NW_UNINIT = 1 << 3,
+ /* Warnings about arithmetic overflow. */
+ NW_VFLOW = 1 << 4,
+ /* All other unclassified warnings. */
+ NW_OTHER = 1 << 5,
+ /* All groups of warnings. */
+ NW_ALL = (NW_ACCESS | NW_LEXICAL | NW_NONNULL
+ | NW_UNINIT | NW_VFLOW | NW_OTHER)
+ };
+
+ nowarn_spec_t (): bits () { }
+
+ nowarn_spec_t (opt_code);
+
+ /* Return the raw bitset. */
+ operator unsigned() const
+ {
+ return bits;
+ }
+
+ /* Return true if the bitset is clear. */
+ bool operator!() const
+ {
+ return !bits;
+ }
+
+ /* Return the inverse of the bitset. */
+ nowarn_spec_t operator~() const
+ {
+ nowarn_spec_t res (*this);
+ res.bits &= ~NW_ALL;
+ return res;
+ }
+
+ /* Set *THIS to the bitwise OR of *THIS and RHS. */
+ nowarn_spec_t& operator|= (const nowarn_spec_t &rhs)
+ {
+ bits |= rhs.bits;
+ return *this;
+ }
+
+ /* Set *THIS to the bitwise AND of *THIS and RHS. */
+ nowarn_spec_t& operator&= (const nowarn_spec_t &rhs)
+ {
+ bits &= rhs.bits;
+ return *this;
+ }
+
+ /* Set *THIS to the bitwise exclusive OR of *THIS and RHS. */
+ nowarn_spec_t& operator^= (const nowarn_spec_t &rhs)
+ {
+ bits ^= rhs.bits;
+ return *this;
+ }
+
+private:
+ /* Bitset of warning groups. */
+ unsigned bits;
+};
+
+/* Return the bitwise OR of LHS and RHS. */
+
+inline nowarn_spec_t
+operator| (const nowarn_spec_t &lhs, const nowarn_spec_t &rhs)
+{
+ return nowarn_spec_t (lhs) |= rhs;
+}
+
+/* Return the bitwise AND of LHS and RHS. */
+
+inline nowarn_spec_t
+operator& (const nowarn_spec_t &lhs, const nowarn_spec_t &rhs)
+{
+ return nowarn_spec_t (lhs) &= rhs;
+}
+
+/* Return true if LHS is equal RHS. */
+
+inline bool
+operator== (const nowarn_spec_t &lhs, const nowarn_spec_t &rhs)
+{
+ return static_cast<unsigned>(lhs) == static_cast<unsigned>(rhs);
+}
+
+/* Return true if LHS is not equal RHS. */
+
+inline bool
+operator!= (const nowarn_spec_t &lhs, const nowarn_spec_t &rhs)
+{
+ return !(lhs == rhs);
+}
+
+typedef location_t key_type_t;
+typedef int_hash <key_type_t, 0, UINT_MAX> xint_hash_t;
+typedef hash_map<xint_hash_t, nowarn_spec_t> xint_hash_map_t;
+
+/* A mapping from the location of an expression to the warning spec
+ set for it. */
+extern GTY(()) xint_hash_map_t *nowarn_map;
+
+#endif // DIAGNOSTIC_SPEC_H_INCLUDED
diff --git a/gcc/gengtype.c b/gcc/gengtype.c
index b94e2f126ec..c1fa6d35c87 100644
--- a/gcc/gengtype.c
+++ b/gcc/gengtype.c
@@ -1727,7 +1727,7 @@ open_base_files (void)
"target-globals.h", "ipa-ref.h", "cgraph.h", "symbol-summary.h",
"ipa-prop.h", "ipa-fnsummary.h", "dwarf2out.h", "omp-general.h",
"omp-offload.h", "ipa-modref-tree.h", "ipa-modref.h", "symtab-thunks.h",
- "symtab-clones.h",
+ "symtab-clones.h", "diagnostic-spec.h",
NULL
};
const char *const *ifp;
diff --git a/gcc/tree.h b/gcc/tree.h
index 62b2de46479..973b84be9fc 100644
--- a/gcc/tree.h
+++ b/gcc/tree.h
@@ -21,6 +21,7 @@ along with GCC; see the file COPYING3. If not see
#define GCC_TREE_H
#include "tree-core.h"
+#include "options.h"
/* Convert a target-independent built-in function code to a combined_fn. */
@@ -6440,4 +6441,15 @@ public:
operator location_t () const { return m_combined_loc; }
};
+/* Code that doesn't refer to any warning. Has no effect on suppression
+ functions. */
+constexpr opt_code no_warning = opt_code ();
+/* Wildcard code that refers to all warnings. */
+constexpr opt_code all_warnings = N_OPTS;
+
+/* Set the disposition for a warning (or all warnings by default)
+ at a location to disabled by default. */
+extern bool suppress_warning_at (location_t, opt_code = all_warnings,
+ bool = true);
+
#endif /* GCC_TREE_H */
diff --git a/gcc/warning-control.cc b/gcc/warning-control.cc
new file mode 100644
index 00000000000..ec8ed232763
--- /dev/null
+++ b/gcc/warning-control.cc
@@ -0,0 +1,238 @@
+/* Functions to enable and disable individual warnings on an expression
+ and statement basis.
+
+ Copyright (C) 2021 Free Software Foundation, Inc.
+
+ This file is part of GCC.
+
+ GCC is free software; you can redistribute it and/or modify it under
+ the terms of the GNU General Public License as published by the Free
+ Software Foundation; either version 3, or (at your option) any later
+ version.
+
+ GCC is distributed in the hope that it will be useful, but WITHOUT ANY
+ WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with GCC; see the file COPYING3. If not see
+ <http://www.gnu.org/licenses/>. */
+
+#include "config.h"
+#include "system.h"
+#include "coretypes.h"
+#include "backend.h"
+#include "bitmap.h"
+#include "tree.h"
+#include "gimple.h"
+#include "cgraph.h"
+#include "hash-map.h"
+#include "diagnostic-spec.h"
+
+/* Return the no-warning bit for EXPR. */
+
+static inline bool
+get_no_warning_bit (const_tree expr)
+{
+ return expr->base.nowarning_flag;
+}
+
+/* Return the no-warning bit for statement STMT. */
+
+static inline bool
+get_no_warning_bit (const gimple *stmt)
+{
+ return stmt->no_warning;
+}
+
+/* Set the no-warning bit for EXPR to VALUE. */
+
+static inline void
+set_no_warning_bit (tree expr, bool value)
+{
+ expr->base.nowarning_flag = value;
+}
+
+/* Set the no-warning bit for statement STMT to VALUE. */
+
+static inline void
+set_no_warning_bit (gimple *stmt, bool value)
+{
+ stmt->no_warning = value;
+}
+
+/* Return EXPR location or zero. */
+
+static inline key_type_t
+convert_to_key (const_tree expr)
+{
+ if (DECL_P (expr))
+ return DECL_SOURCE_LOCATION (expr);
+ if (EXPR_P (expr))
+ return EXPR_LOCATION (expr);
+ return 0;
+}
+
+/* Return STMT location (may be zero). */
+
+static inline key_type_t
+convert_to_key (const gimple *stmt)
+{
+ return gimple_location (stmt);
+}
+
+/* Return the no-warning bitmap for decl/expression EXPR. */
+
+static nowarn_spec_t *
+get_nowarn_spec (const_tree expr)
+{
+ const key_type_t key = convert_to_key (expr);
+
+ if (!get_no_warning_bit (expr) || !key)
+ return NULL;
+
+ return nowarn_map ? nowarn_map->get (key) : NULL;
+}
+
+/* Return the no-warning bitmap for stateemt STMT. */
+
+static nowarn_spec_t *
+get_nowarn_spec (const gimple *stmt)
+{
+ const key_type_t key = convert_to_key (stmt);
+
+ if (!get_no_warning_bit (stmt))
+ return NULL;
+
+ return nowarn_map ? nowarn_map->get (key) : NULL;
+}
+
+/* Return true if warning OPT is suppressed for decl/expression EXPR.
+ By default tests the disposition for any warning. */
+
+bool
+warning_suppressed_p (const_tree expr, opt_code opt /* = all_warnings */)
+{
+ const nowarn_spec_t *spec = get_nowarn_spec (expr);
+
+ if (!spec)
+ return get_no_warning_bit (expr);
+
+ const nowarn_spec_t optspec (opt);
+ bool dis = *spec & optspec;
+ gcc_assert (get_no_warning_bit (expr) || !dis);
+ return dis;
+}
+
+/* Return true if warning OPT is suppressed for statement STMT.
+ By default tests the disposition for any warning. */
+
+bool
+warning_suppressed_p (const gimple *stmt, opt_code opt /* = all_warnings */)
+{
+ const nowarn_spec_t *spec = get_nowarn_spec (stmt);
+
+ if (!spec)
+ /* Fall back on the single no-warning bit. */
+ return get_no_warning_bit (stmt);
+
+ const nowarn_spec_t optspec (opt);
+ bool dis = *spec & optspec;
+ gcc_assert (get_no_warning_bit (stmt) || !dis);
+ return dis;
+}
+
+/* Enable, or by default disable, a warning for the expression.
+ The wildcard OPT of -1 controls all warnings. */
+
+void
+suppress_warning (tree expr, opt_code opt /* = all_warnings */,
+ bool supp /* = true */)
+{
+ if (opt == no_warning)
+ return;
+
+ const key_type_t key = convert_to_key (expr);
+
+ supp = suppress_warning_at (key, opt, supp) || supp;
+ set_no_warning_bit (expr, supp);
+}
+
+/* Enable, or by default disable, a warning for the statement STMT.
+ The wildcard OPT of -1 controls all warnings. */
+
+void
+suppress_warning (gimple *stmt, opt_code opt /* = all_warnings */,
+ bool supp /* = true */)
+{
+ if (opt == no_warning)
+ return;
+
+ const key_type_t key = convert_to_key (stmt);
+
+ supp = suppress_warning_at (key, opt, supp) || supp;
+ set_no_warning_bit (stmt, supp);
+}
+
+/* Copy the warning disposition mapping between an expression and/or
+ a statement. */
+
+template <class ToType, class FromType>
+void copy_warning (ToType to, FromType from)
+{
+ const key_type_t to_key = convert_to_key (to);
+
+ if (nowarn_spec_t *from_map = get_nowarn_spec (from))
+ {
+ /* If there's an entry in the map the no-warning bit must be set. */
+ gcc_assert (get_no_warning_bit (from));
+
+ if (!nowarn_map)
+ nowarn_map = xint_hash_map_t::create_ggc (32);
+
+ nowarn_map->put (to_key, *from_map);
+ set_no_warning_bit (to, true);
+ }
+ else
+ {
+ if (nowarn_map)
+ nowarn_map->remove (to_key);
+
+ /* The no-warning bit might be set even if there's no entry
+ in the map. */
+ set_no_warning_bit (to, get_no_warning_bit (from));
+ }
+}
+
+/* Copy the warning disposition mapping from one expression to another. */
+
+void
+copy_warning (tree to, const_tree from)
+{
+ copy_warning<tree, const_tree>(to, from);
+}
+
+/* Copy the warning disposition mapping from a statement to an expression. */
+
+void
+copy_warning (tree to, const gimple *from)
+{
+ copy_warning<tree, const gimple *>(to, from);
+}
+
+/* Copy the warning disposition mapping from an expression to a statement. */
+
+void
+copy_warning (gimple *to, const_tree from)
+{
+ copy_warning<gimple *, const_tree>(to, from);
+}
+
+/* Copy the warning disposition mapping from one statement to another. */
+
+void
+copy_warning (gimple *to, const gimple *from)
+{
+ copy_warning<gimple *, const gimple *>(to, from);
+}