* Re: type punning in gl_list.hh
[not found] ` <79947243-8A13-4BE8-9181-FC284F998F42@lrde.epita.fr>
@ 2020-05-31 10:07 ` Bruno Haible
2020-05-31 10:15 ` iterator and const iterator Bruno Haible
1 sibling, 0 replies; 2+ messages in thread
From: Bruno Haible @ 2020-05-31 10:07 UTC (permalink / raw)
To: Akim Demaille; +Cc: bug-gnulib, Bison Bugs
Akim Demaille wrote in
<https://lists.gnu.org/archive/html/bug-bison/2020-05/msg00102.html>:
> Also, in gnulib, I found this in gl_list.hh:
>
> /* If there is a next element, stores the next element in ELT, advances
> the iterator and returns true.
> Otherwise, returns false. */
> bool next (ELTYPE *& elt)
> { return gl_list_iterator_next (&_state, reinterpret_cast<const void **>(&elt), NULL); }
>
> /* If there is a next element, stores the next element in ELT, stores its
> node in *NODEP if NODEP is non-NULL, advances the iterator and returns true.
> Otherwise, returns false. */
> bool next (ELTYPE *& elt, gl_list_node_t *nodep)
> { return gl_list_iterator_next (&_state, reinterpret_cast<const void **>(&elt), nodep); }
>
>
> It is not my understanding that reinterpret_cast protects from type
> punning issues. Did I miss something? We've had in the past to
> do something alike in Bison
> (https://lists.gnu.org/r/bison-patches/2013-01/msg00131.html).
Agreed. 10 years ago, this reinterpret_cast was probably safe, but
nowadays with the more and more aggressive optimizations of the C++ compilers,
such a reinterpret_cast is dangerous. I'm applying this patch. Let's hope that
the C++ compilers can merge the two tests of the same boolean value into one,
and thus not lose too much performance.
2020-05-31 Bruno Haible <bruno@clisp.org>
list-c++, set-c++, oset-c++, map-c++, omap-c++: Don't fool the compiler.
Reported by Akim Demaille in
<https://lists.gnu.org/archive/html/bug-bison/2020-05/msg00102.html>.
* lib/gl_list.hh (gl_List::iterator::next): Avoid a reinterpret_cast.
* lib/gl_set.hh (gl_Set::iterator::next): Likewise.
* lib/gl_oset.hh (gl_OSet::iterator::next): Likewise.
* lib/gl_map.hh (gl_Map::iterator::next): Likewise.
* lib/gl_omap.hh (gl_OMap::iterator::next): Likewise.
diff --git a/lib/gl_list.hh b/lib/gl_list.hh
index b19bda7..8b0ccad 100644
--- a/lib/gl_list.hh
+++ b/lib/gl_list.hh
@@ -351,13 +351,25 @@ public:
the iterator and returns true.
Otherwise, returns false. */
bool next (ELTYPE *& elt)
- { return gl_list_iterator_next (&_state, reinterpret_cast<const void **>(&elt), NULL); }
+ {
+ const void *next_elt;
+ bool has_next = gl_list_iterator_next (&_state, &next_elt, NULL);
+ if (has_next)
+ elt = static_cast<ELTYPE *>(next_elt);
+ return has_next;
+ }
/* If there is a next element, stores the next element in ELT, stores its
node in *NODEP if NODEP is non-NULL, advances the iterator and returns true.
Otherwise, returns false. */
bool next (ELTYPE *& elt, gl_list_node_t *nodep)
- { return gl_list_iterator_next (&_state, reinterpret_cast<const void **>(&elt), nodep); }
+ {
+ const void *next_elt;
+ bool has_next = gl_list_iterator_next (&_state, &next_elt, nodep);
+ if (has_next)
+ elt = static_cast<ELTYPE *>(next_elt);
+ return has_next;
+ }
~iterator ()
{ gl_list_iterator_free (&_state); }
diff --git a/lib/gl_map.hh b/lib/gl_map.hh
index f3d0a46..082694f 100644
--- a/lib/gl_map.hh
+++ b/lib/gl_map.hh
@@ -143,7 +143,17 @@ public:
/* If there is a next pair, stores the next pair in KEY and VALUE, advance
the iterator, and returns true. Otherwise, returns false. */
bool next (KEYTYPE *& key, VALUETYPE *& value)
- { return gl_map_iterator_next (&_state, reinterpret_cast<const void **>(&key), reinterpret_cast<const void **>(&value)); }
+ {
+ const void *next_key;
+ const void *next_value;
+ bool has_next = gl_map_iterator_next (&_state, &next_key, &next_value);
+ if (has_next)
+ {
+ key = static_cast<KEYTYPE *>(next_key);
+ value = static_cast<VALUETYPE *>(next_value);
+ }
+ return has_next;
+ }
~iterator ()
{ gl_map_iterator_free (&_state); }
diff --git a/lib/gl_omap.hh b/lib/gl_omap.hh
index 15d8104..1f892e4 100644
--- a/lib/gl_omap.hh
+++ b/lib/gl_omap.hh
@@ -150,7 +150,17 @@ public:
/* If there is a next pair, stores the next pair in KEY and VALUE, advances
the iterator, and returns true. Otherwise, returns false. */
bool next (KEYTYPE *& key, VALUETYPE *& value)
- { return gl_omap_iterator_next (&_state, reinterpret_cast<const void **>(&key), reinterpret_cast<const void **>(&value)); }
+ {
+ const void *next_key;
+ const void *next_value;
+ bool has_next = gl_omap_iterator_next (&_state, &next_key, &next_value);
+ if (has_next)
+ {
+ key = static_cast<KEYTYPE *>(next_key);
+ value = static_cast<VALUETYPE *>(next_value);
+ }
+ return has_next;
+ }
~iterator ()
{ gl_omap_iterator_free (&_state); }
diff --git a/lib/gl_oset.hh b/lib/gl_oset.hh
index 16da0dd..b78ef52 100644
--- a/lib/gl_oset.hh
+++ b/lib/gl_oset.hh
@@ -121,7 +121,13 @@ public:
/* If there is a next element, stores the next element in ELT, advances the
iterator and returns true. Otherwise, returns false. */
bool next (ELTYPE *& elt)
- { return gl_oset_iterator_next (&_state, reinterpret_cast<const void **>(&elt)); }
+ {
+ const void *next_elt;
+ bool has_next = gl_oset_iterator_next (&_state, &next_elt);
+ if (has_next)
+ elt = static_cast<ELTYPE *>(next_elt);
+ return has_next;
+ }
~iterator ()
{ gl_oset_iterator_free (&_state); }
diff --git a/lib/gl_set.hh b/lib/gl_set.hh
index 357e141..3b64bc5 100644
--- a/lib/gl_set.hh
+++ b/lib/gl_set.hh
@@ -114,7 +114,13 @@ public:
/* If there is a next element, stores the next element in ELT, advances the
iterator and returns true. Otherwise, returns false. */
bool next (ELTYPE *& elt)
- { return gl_set_iterator_next (&_state, reinterpret_cast<const void **>(&elt)); }
+ {
+ const void *next_elt;
+ bool has_next = gl_set_iterator_next (&_state, &next_elt);
+ if (has_next)
+ elt = static_cast<ELTYPE *>(next_elt);
+ return has_next;
+ }
~iterator ()
{ gl_set_iterator_free (&_state); }
^ permalink raw reply related [flat|nested] 2+ messages in thread
* Re: iterator and const iterator
[not found] ` <79947243-8A13-4BE8-9181-FC284F998F42@lrde.epita.fr>
2020-05-31 10:07 ` type punning in gl_list.hh Bruno Haible
@ 2020-05-31 10:15 ` Bruno Haible
1 sibling, 0 replies; 2+ messages in thread
From: Bruno Haible @ 2020-05-31 10:15 UTC (permalink / raw)
To: Akim Demaille; +Cc: bug-gnulib, bug-bison
Hi Akim,
In <https://lists.gnu.org/archive/html/bug-bison/2020-05/msg00102.html> you
write:
> > Le 3 mai 2020 à 17:17, Bruno Haible <bruno@clisp.org> a écrit :
> >
> > There are a couple of GCC warnings on IRIX (CC="gcc -mabi=n32"):
> >
> > 2)
> > ../src/fixits.c: In function `fixits_run':
> > ../src/fixits.c:129: warning: dereferencing type-punned pointer will break strict-aliasing rules
> >
> > Modern C rules wants f to be a 'const void *'. Inside the loop body,
> > you can cast f to 'fixit const *' without danger.
>
> So I had installed this:
>
> - fixit const *f = NULL;
> + void const *p = NULL;
> gl_list_iterator_t iter = gl_list_iterator (fixits);
> - while (gl_list_iterator_next (&iter, (const void**) &f, NULL))
> + while (gl_list_iterator_next (&iter, &p, NULL))
> {
> + fixit const *f = p;
>
>
>
> Today we have more occurrences of this pattern that we have to fix,
> but some of these items need the pointer to point to a non-const value,
> so we need a const void * pointer, and still a cast.
>
> Would you accept a macro, say gl_list_mutable_iterator_next, where we
> would pass a void** instead of const void**?
No, I don't want this. It's a madness, in C++, to have to write the same
member function definition twice, due to 'const' differences. This madness
should not propagate into our C code. In C, we don't need to have two
functions which produce the exactly same machine code. C has sufficient
means for guaranteeing that one copy of the code will do.
> Of course mutable_iterator
> gives the impression that it's the iterator which is mutable, but an
> iterator must so obviously be mutable that I don't think it would be
> much of an issue, and it's quite symmetrical with const_iterator.
> It might have been less surprising to have the current gl_list_iterator_next
> be about mutable values and use gl_list_const_iterator_next for readonly
> iteration, but it's too late.
Whether you call it mutable_iterator vs. iterator, or iterator vs.
const_iterator, doesn't change the fact that it's a code duplication.
Bruno
^ permalink raw reply [flat|nested] 2+ messages in thread
end of thread, other threads:[~2020-05-31 10:15 UTC | newest]
Thread overview: 2+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
[not found] <4CD189B2-CE25-481F-ACE7-7F8245B91901@lrde.epita.fr>
[not found] ` <4427865.6uD3S8UnPL@omega>
[not found] ` <79947243-8A13-4BE8-9181-FC284F998F42@lrde.epita.fr>
2020-05-31 10:07 ` type punning in gl_list.hh Bruno Haible
2020-05-31 10:15 ` iterator and const iterator Bruno Haible
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).