After an evaluation, GNOME has moved from Bugzilla to GitLab. Learn more about GitLab.
No new issues can be reported in GNOME Bugzilla anymore.
To report an issue in a GNOME project, go to GNOME GitLab.
Do not go to GNOME Gitlab for: Bluefish, Doxygen, GnuCash, GStreamer, java-gnome, LDTP, NetworkManager, Tomboy.
Bug 787648 - [2.54] Build failure with clang/libc++ because std::index_sequence is a C++14 feature
[2.54] Build failure with clang/libc++ because std::index_sequence is a C++14...
Status: RESOLVED FIXED
Product: glibmm
Classification: Bindings
Component: build
2.54.x
Other All
: Normal normal
: ---
Assigned To: gtkmm-forge
gtkmm-forge
https://gcc.gnu.org/bugzilla/show_bug...
Depends on:
Blocks:
 
 
Reported: 2017-09-13 22:06 UTC by Armin K.
Modified: 2017-09-19 09:12 UTC
See Also:
GNOME target: ---
GNOME version: ---


Attachments
configure: Require C++14 for std::index_sequence (866 bytes, patch)
2017-09-14 09:16 UTC, Daniel Boles
none Details | Review
examples/thread: Fix a TODO now that we use C++14 (1.20 KB, patch)
2017-09-14 09:20 UTC, Daniel Boles
none Details | Review
configure: Require C++14 for std::index_sequence (788 bytes, patch)
2017-09-14 17:38 UTC, Daniel Boles
none Details | Review
patch: Glib::Variant<std::tuple>: Don't use std::index_sequence from C++14 (4.65 KB, patch)
2017-09-15 17:27 UTC, Kjell Ahlstedt
none Details | Review
patch: Glib::Variant<std::tuple>: Don't use std::index_sequence from C++14 (5.28 KB, patch)
2017-09-17 10:19 UTC, Kjell Ahlstedt
committed Details | Review

Description Armin K. 2017-09-13 22:06:21 UTC
When using clang++, which uses libc++ as its standard library, glibmm-2.54.0 build fails with the following:

../glibmm/variant.h:2012:24: error: no template named 'index_sequence' in namespace 'std'
                  std::index_sequence<Is...>)

Problem happens because glibmm is built using -std=c++11, while on libc++, std::index_sequence is only available if using -std=c++14. Using CXX="clang++ -std=c++14" gets glib to compile.

See also:

https://github.com/llvm-mirror/libcxx/blob/master/include/utility#L151
Comment 1 Daniel Boles 2017-09-14 09:08:08 UTC
(In reply to Armin K. from comment #0)
> Problem happens because glibmm is built using -std=c++11, while on libc++,
> std::index_sequence is only available if using -std=c++14. Using
> CXX="clang++ -std=c++14" gets glib[mm] to compile.

libc++ is more correct here; index_sequence was only formally added in C++14.
Comment 2 Daniel Boles 2017-09-14 09:14:23 UTC
This was presumably missed because libstdc++ is conditional on C++11 for defining index_sequence. That's clearly wrong IMO, especially if you compile with noext like we do, but oh well.

https://github.com/gcc-mirror/gcc/blob/master/libstdc%2B%2B-v3/include/std/utility#L298
Comment 3 Daniel Boles 2017-09-14 09:16:47 UTC
Created attachment 359768 [details] [review]
configure: Require C++14 for std::index_sequence

    We now use std::index_sequence in variant.h, which debuted in C++14.

    This was presumably missed because libstdc++ defines it in C++11 mode.
Comment 4 Daniel Boles 2017-09-14 09:20:38 UTC
Created attachment 359769 [details] [review]
examples/thread: Fix a TODO now that we use C++14

    make_unique<T>(…) is more concise/efficient than unique_ptr<T>(new T{…})
Comment 5 Armin K. 2017-09-14 09:32:54 UTC
Note that requiring c++14 in glibmm requires forcing c++14 on all other mm components, such as atkmm, pangomm, gtkmm (2 and 3) and all the packages that use any of these (I had to do it for gparted (using gtkmm2) and gnome-system-monitor (using gtkmm3)).
Comment 6 Daniel Boles 2017-09-14 09:36:37 UTC
Right. To be clear, I don't know if we want to make that change yet. The alternative appears to be replacing the uses of std::index_sequence with a local implementation.

Your warnings are completely correct, and ideally would have been noticed when Bug 777791 was adding this. However, I can't really blame that too much when libstdc++ behaves in a non-standard way and thus made this *seem* to be allowed in C++11.
Comment 7 Daniel Boles 2017-09-14 09:47:20 UTC
Since this apppears to be one, I filed it as a bug with libstdc++: https://gcc.gnu.org/bugzilla/show_bug.cgi?id=82212
Comment 8 Jonathan Wakely 2017-09-14 12:08:49 UTC
(In reply to Daniel Boles from comment #2)
> This was presumably missed because libstdc++ is conditional on C++11 for
> defining index_sequence. That's clearly wrong IMO, especially if you compile
> with noext like we do, but oh well.
> 
> https://github.com/gcc-mirror/gcc/blob/master/libstdc%2B%2B-v3/include/std/
> utility#L298

Try reading the code again, or try compiling an example using -std=c++11.

This is not a bug in libstdc++.
Comment 9 Daniel Boles 2017-09-14 12:37:02 UTC
It seems you're right. Sorry for the noise.

This patch originated in master, which already requires C++14, but then got picked to 2.54, which does not - and somehow no one noticed until now.

It's not clear from the OP whether g++ still works here, but since a simple test fails as it should, if g++ was working for 2.54, then something else must be up.
Comment 10 Jonathan Wakely 2017-09-14 12:44:42 UTC
GCC defaults to -std=gnu++14 so unless you add an explicit -std=c++11 or -std=gnu++11 you'll get access to C++14 features.

If you do add an explicit -std=c++11 and are still getting C++14 then you must be adding another -std later in the command line to override it (or doing something *really* bad like redefining __cplusplus!)
Comment 11 Daniel Boles 2017-09-14 12:46:48 UTC
We call this in configure.ac for 2.54:

  MM_AX_CXX_COMPILE_STDCXX([11], [noext], [mandatory])

which I would've expected to suffice, but yep, maybe something else is going wrong

Thanks for the info!
Comment 12 Murray Cumming 2017-09-14 15:51:58 UTC
Sorry for not noticing this before releasing a tarball.

(In reply to Armin K. from comment #5)
> Note that requiring c++14 in glibmm requires forcing c++14 on all other mm
> components, such as atkmm, pangomm, gtkmm (2 and 3) and all the packages
> that use any of these (I had to do it for gparted (using gtkmm2) and
> gnome-system-monitor (using gtkmm3)).

Let's require C++14, instead of C++11, for glibmm 2.54.x. That doesn't seem like a big change. Any practical objections?
Comment 13 Daniel Boles 2017-09-14 17:15:20 UTC
Not sure about practical - I'm all for encouraging C++14 - but theoretically, isn't that a bit excessive for a minor release?

It would probably be better to roll our own implementation of index_sequence and move to that, and keep the current (previous) compiler flags.
Comment 14 Daniel Boles 2017-09-14 17:17:42 UTC
Here's a page about doing that in C++11, including examples that are specifically about unpacking tuples, like the new feature that introduced this:

https://blog.galowicz.de/2016/06/24/integer_sequences_at_compile_time/
Comment 15 Daniel Boles 2017-09-14 17:38:52 UTC
Created attachment 359806 [details] [review]
configure: Require C++14 for std::index_sequence

We now use std::index_sequence in variant.h, which debuted in C++14.


--

Remove the bit blaming libstdc++, since it seems something else happened.
Comment 16 Murray Cumming 2017-09-14 19:22:48 UTC
> isn't that a bit excessive for a minor release?

Well, we already require it for the .0 release, so now we are just making that more obvious for a .1 release.

I'd generally like to not have too many branches on too many different C++ versions, and I'd like us to generally push forwards as long as it's no great disadvantage to anyone.
Comment 17 Daniel Boles 2017-09-14 19:28:51 UTC
(In reply to Murray Cumming from comment #16)
> > isn't that a bit excessive for a minor release?
> 
> Well, we already require it for the .0 release, so now we are just making
> that more obvious for a .1 release.

Sure, though what I really meant was that maybe we should consider .0 requiring it as an accident, replace the offending class with a small local implementation, and not impose that all users must now bump their own build systems. Maybe no one will mind... but I'm not so certain.

But yeah, if you view it as too late now, that makes sense in its own way too.
Comment 18 Murray Cumming 2017-09-14 21:09:02 UTC
I also think it's OK to require it in the change between glibmm 2.52 and 2.54. But I'm open to a practical objection.
Comment 19 Kjell Ahlstedt 2017-09-15 17:27:32 UTC
Created attachment 359869 [details] [review]
patch: Glib::Variant<std::tuple>: Don't use std::index_sequence from C++14

This patch copies index_sequence from the utility file in libstdc++ to
variant.hg. I don't know if this is legal.

index_sequence is not used in public API. It's only used in templates.
AFAICT the patch does not break API or ABI.
Comment 20 Daniel Boles 2017-09-15 17:36:19 UTC
Review of attachment 359869 [details] [review]:

Seems like a good solution. I don't see why there would be any issue of legality, since you're defining these in our own namespace.

It may be nicer to keep this in its own header file, though? Especially if we end up wanting to use it for anything else in this version (however likely that may be).

::: glib/src/variant.hg
@@ +1513,3 @@
+  // Stores a tuple of indices.  Used by tuple and pair, and by bind() to
+  // extract the elements in a tuple.
+  template<size_t... Indexes> struct Index_tuple { };

I think technically we need to #include <cstddef> and use std::size_t everywhere. Plain size_t is not guaranteed to be defined in the global namespace, especially if we don't include any header defining it. It probably will be in most situations, but we should be explicit/correct.
Comment 21 houz 2017-09-15 19:40:04 UTC
Just as a small remark, this release made it to Debian/sid already. Since Inkscape requires C++11 it's no longer possible to build that. I would be happy if the 2.54 branch could stick with C++11.
Comment 22 Daniel Boles 2017-09-15 19:53:12 UTC
Having thought about it more, and despite having written patches to make it happen... my opinion is this.

Suddenly, unexpectedly - and ultimately unintentionally - requiring all users to start using a different C++ revision - which will happen, even if they don't try to use the new Variant features - may be seen as highly inconvenient and not a source of goodwill.

Plus, as if that's not reason enough - which it should be - it's possible, however rare in practice, that they will have to do more than update one number somewhere, since in theory changes in C++14 can break code that was valid in C++11. So, there might be more than the immediate effect on projects using this. See https://www.infoq.com/news/2014/06/cpp14-changes-breaking-compat and the SO thread linked from it.

IMO, given how this dependency on C++14 was inadvertent, and how simple it is to include a little local implementation of index_sequence, there's no reason not to fix the accident and put out a .1 asap, clarifying that C++11 is still OK.


(Then we still have to figure out why apparently everyone except the OP was able to compile this in C++11 mode!)
Comment 23 Kjell Ahlstedt 2017-09-16 08:47:57 UTC
> I don't see why there would be any issue of legality, since you're defining
> these in our own namespace.

What I meant: According to the copyright notices in the files, libstdc++ is
released under the GNU General Public License, version 3. glibmm is released
under the GNU Lesser General Public License, version 2.1.
Is it allowed to copy some code from libstdc++ to glibmm? If it's at all
allowed, do we have to include some extra copyright notice? E.g. saying that
this code is copyright Free Software Foundation, Inc?

> It may be nicer to keep this in its own header file, though? Especially if we
> end up wanting to use it for anything else in this version.

Let's move it to its own header file only if and when we really find a second
use for it. It's improbable that it will ever be needed.

> I think technically we need to #include <cstddef> and use std::size_t
> everywhere.

Correct. I should have added std:: when I moved the code from namespace std.
Comment 24 Jonathan Wakely 2017-09-16 09:29:38 UTC
(In reply to Kjell Ahlstedt from comment #23)
> > I don't see why there would be any issue of legality, since you're defining
> > these in our own namespace.
> 
> What I meant: According to the copyright notices in the files, libstdc++ is
> released under the GNU General Public License, version 3. glibmm is released
> under the GNU Lesser General Public License, version 2.1.
> Is it allowed to copy some code from libstdc++ to glibmm? If it's at all
> allowed, do we have to include some extra copyright notice? E.g. saying that
> this code is copyright Free Software Foundation, Inc?


No, you cannot relicense GPLv3+exception code as LGPL v2.1 without permission from the copyright holder.
Comment 25 Jonathan Wakely 2017-09-16 09:38:42 UTC
Since I'm the original author of that code, I could give permission to use it in glibmm under the LGPL terms, but I refuse, because it's a *really* weird implementation to copy! It's unnecessarily complicated in order to share the implementation with the _Index_tuple type that we already had in libstdc++ before I standardized std::integer_sequence. You have no need for that.

Let me give you a much simpler form ...
Comment 26 Jonathan Wakely 2017-09-16 09:46:01 UTC
Here's one I made earlier:
https://gitlab.com/redistd/integer_seq/blob/master/integer_seq.h

I started simplifying the libstdc++ version and realised I was reimplementing exactly this. You have my permission to use that code under the terms of the LGPL v2.1 or later.
Comment 27 Jonathan Wakely 2017-09-16 10:29:53 UTC
Or here's the simplified form of the libstdc++ code, without the extra libstdc++-specific stuff you don't need:

#include <cstddef>

  /// Class template integer_sequence
  template<typename T, T... Idx>
    struct integer_sequence
    {
      typedef T value_type;
      static constexpr size_t size() { return sizeof...(Idx); }
    };

  // Concatenates two integer_sequences.
  template<typename Iseq1, typename Iseq2> struct iseq_cat;

  template<typename T, size_t... Ind1, size_t... Ind2>
    struct iseq_cat<integer_sequence<T, Ind1...>, integer_sequence<T, Ind2...>>
    {
      using type = integer_sequence<T, Ind1..., (Ind2 + sizeof...(Ind1))...>;
    };

  // Builds an integer_sequence<T, 0, 1, 2, ..., Num-1>.
  template<typename T, size_t Num>
    struct make_intseq
    : iseq_cat<typename make_intseq<T, Num / 2>::type,
		typename make_intseq<T, Num - Num / 2>::type>
    { };

  template<typename T>
    struct make_intseq<T, 1>
    {
      typedef integer_sequence<T, 0> type;
    };

  template<typename T>
    struct make_intseq<T, 0>
    {
      typedef integer_sequence<T> type;
    };

  /// Alias template make_integer_sequence
  template<typename T, T Num>
    using make_integer_sequence = typename make_intseq<T, Num>::type;

  /// Alias template index_sequence
  template<size_t... Idx>
    using index_sequence = integer_sequence<size_t, Idx...>;

  /// Alias template make_index_sequence
  template<size_t Num>
    using make_index_sequence = make_integer_sequence<size_t, Num>;

  /// Alias template index_sequence_for
  template<typename... Types>
    using index_sequence_for = make_index_sequence<sizeof...(Types)>;
Comment 28 Bryce Harrington 2017-09-16 17:26:33 UTC
This has been breaking Inkscape's automated nightly PPA builds this week:

Build Log: https://launchpad.net/~inkscape.dev/+archive/ubuntu/trunk/+build/13381797/+files/buildlog_ubuntu-artful-i386.inkscape-trunk_1%3A0.92.0+devel+16029+91~ubuntu17.10.1_BUILDING.txt.gz

If the fix won't be available soonish (within a few days), is there a recommended workaround?
Comment 29 Kjell Ahlstedt 2017-09-17 10:19:49 UTC
Created attachment 359924 [details] [review]
patch: Glib::Variant<std::tuple>: Don't use std::index_sequence from C++14

Hopefully a legal patch this time. This patch uses Jonathan's code from
comment 27. Thanks a lot for that code!

All this trouble with index_sequence is my fault, I'm afraid. I copied a patch
from the master branch without realizing that the patch required C++14 support.
That's no problem in the master branch, but it is in the glibmm-2-54 branch.

MM_AX_CXX_COMPILE_STDCXX([11], [noext], [mandatory]) in configure.ac prefers a
configuration with the default value of the -std parameter in g++. The default
of g++ version 6 is to support C++14. Therefore the compiler did not report the
problematic use of std::index_sequence when I built glibmm.
The MM_AX_CXX_COMPILE_STDCXX() macro seems to generate configuration code that
gives you support for *at least* what you require, not *exactly* what you
require.
Comment 30 Kjell Ahlstedt 2017-09-18 08:44:57 UTC
Jonathan, can you please confirm that it's OK with you that I push the patch in
comment 29 to glibmm. Or, if it's not OK, tell which modifications you want.
Comment 31 Jonathan Wakely 2017-09-18 09:21:24 UTC
Yes that's fine, just don't use the overly complicated one straight from libstdc++, as that solves a different problem.
Comment 32 Murray Cumming 2017-09-18 09:23:35 UTC
This is the commit that used std::index_sequence:
https://git.gnome.org/browse/glibmm/commit/?h=glibmm-2-54&id=cca6a67aeef42a79c9b7896ab092e513a779a8b3

Wouldn't it be simpler to just revert it?
Comment 33 Kjell Ahlstedt 2017-09-18 13:38:27 UTC
> Wouldn't it be simpler to just revert it?

Then the Glib::Variant<std::tuple> specialization that was added in
glibmm 2.54.0 would be removed in 2.54.1. If that's acceptable, reverting the
commit is of course an alternative.

Thanks to Jonathan, we now have a patch that fixes the bug without removing
Glib::Variant<std::tuple>. A few days ago it would have been simpler to revert
the problematic commit. Now it's just as simple to commit the new patch.
Comment 34 Kjell Ahlstedt 2017-09-18 15:07:55 UTC
I have pushed the patch.
https://git.gnome.org/browse/glibmm/commit/?h=glibmm-2-54&id=7f825b98c6ba261ffe1117ec80e3b150de424bcd

I suppose that we must also very soon release glibmm 2.54.1 with this fix.
Murray, will you do that, or do you want me to do it?
Comment 35 Murray Cumming 2017-09-18 15:41:32 UTC
OK. Thanks. Please go ahead.
Comment 36 Kjell Ahlstedt 2017-09-18 18:31:10 UTC
glibmm 2.54.1 with the fix of this bug has been released.
Comment 37 Armin K. 2017-09-18 18:54:59 UTC
While I'm able to build glibmm and friends without using -std=c++14 now, there's still one minor warning:

In file included from pollableoutputstream.cc:4:
In file included from ../../glib/glibmm.h:92:
In file included from ../../glib/glibmm/arrayhandle.h:21:
In file included from ../../glib/glibmm/containerhandle_shared.h:23:
../../glib/glibmm/variant.h:2132:3: warning: use of this statement in a constexpr function is a C++14 extension [-Wc++14-extensions]
  (void)arg;
  ^
Comment 38 Kjell Ahlstedt 2017-09-19 08:09:07 UTC
clang++ issues more warnings than g++. I should have tested with clang++
earlier. Now I've pushed a patch that fixes the (void)arg warning and another
warning from clang++.

variant.cc:267:40: error: implicit conversion of nullptr constant to 'bool'
      [-Werror,-Wnull-conversion]
  return gobj() ? GINT_TO_POINTER(1) : nullptr;

https://git.gnome.org/browse/glibmm/commit/?h=glibmm-2-54&id=7f5065a7de446563f303fbbdb5d28a710403c23f

How urgent is this fix? Do you need a glibmm 2.54.2 release right away?
If it's not that urgent, I'd prefer to wait for a while. There might be other
fixes that could go into 2.54.2. ("A while" in this case could means several
weeks.)
Comment 39 Armin K. 2017-09-19 09:12:32 UTC
It's not a big deal, it's just a warning. Take your time for .2 release.