Supporting C++17

classic Classic list List threaded Threaded
12 messages Options
Reply | Threaded
Open this post in threaded view
|

Supporting C++17

Murray Cumming-5
Any ideas about how we should support C++17 in gtkmm-3.0 without losing
C++11/14 compatibility and without breaking ABI?

Or should we require C++17 for later gtkmm-3.0 versions?

Noticed here:
https://bugzilla.redhat.com/show_bug.cgi?id=1438766

--
Murray Cumming
[hidden email]
www.murrayc.com

_______________________________________________
gtkmm-list mailing list
[hidden email]
https://mail.gnome.org/mailman/listinfo/gtkmm-list
Reply | Threaded
Open this post in threaded view
|

Re: Supporting C++17

Jonathan Wakely
On 4 April 2017 at 14:52, Murray Cumming wrote:
> Any ideas about how we should support C++17 in gtkmm-3.0 without losing
> C++11/14 compatibility and without breaking ABI?

Replace all dynamic exception specifications with noexcept(false) (or
just no exception specification). That's not an ABI change.


> Or should we require C++17 for later gtkmm-3.0 versions?

I think that would be premature, GCC support for it is still experimental.

> Noticed here:
> https://bugzilla.redhat.com/show_bug.cgi?id=1438766
_______________________________________________
gtkmm-list mailing list
[hidden email]
https://mail.gnome.org/mailman/listinfo/gtkmm-list
Reply | Threaded
Open this post in threaded view
|

Re: Supporting C++17

Jonathan Wakely
On 4 April 2017 at 15:09, Jonathan Wakely wrote:
> On 4 April 2017 at 14:52, Murray Cumming wrote:
>> Noticed here:
>> https://bugzilla.redhat.com/show_bug.cgi?id=1438766

From that bug report:

(In reply to Murray Cumming from comment #6)
> This makes sense: C++17 will remove support for old-style exception
> specifications, so we'd need some cleverness to support both the old and new
> ways in glibmm. I guess this will break lots of C++ code.

Why try to support the old way?

Dynamic exception specifications are not very useful, and have been
recommended against for many many years. Simply removing them (so the
functions are implicitly noexcept(false)) shouldn't break any code.

Even if you have virtual functions using throw(X), user code that
overrides them would still compile if you removed them:

struct X {
  virtual void f() noexcept(false) { }
};

struct Y : X {
  void f() throw(int) { }
};

This is still OK, because the Y::f override has a stricter exception
specification.


The other way around doesn't work. If you have throw(std::bad_cast) on
a virtual function then users who override it are forced to also use a
deprecated dynamic exception specification, they can't use
noexcept(false):

struct X {
  virtual void f() throw(int) { }
};

struct Y : X {
  void f()  noexcept(false) { }
};

v.cc:6:8: error: looser throw specifier for ‘virtual void Y::f()
noexcept (false)’
  void f()  noexcept(false){ }
       ^
v.cc:2:16: error:   overriding ‘virtual void X::f() throw (int)’
  virtual void f() throw(int) { }
               ^

(I don't see any uses on virtual functions in glibmm or gtkmm so this
might not be a problem anyway).

Simply removing them from your headers seems the best solution.
_______________________________________________
gtkmm-list mailing list
[hidden email]
https://mail.gnome.org/mailman/listinfo/gtkmm-list
Reply | Threaded
Open this post in threaded view
|

Re: Supporting C++17

Murray Cumming-5
In reply to this post by Jonathan Wakely
On Tue, 2017-04-04 at 15:09 +0100, Jonathan Wakely wrote:
> On 4 April 2017 at 14:52, Murray Cumming wrote:
> > Any ideas about how we should support C++17 in gtkmm-3.0 without
> > losing
> > C++11/14 compatibility and without breaking ABI?
>
> Replace all dynamic exception specifications with noexcept(false) (or
> just no exception specification). That's not an ABI change.

That's great to know. I'll take care of that then.

--
Murray Cumming
[hidden email]
www.murrayc.com

_______________________________________________
gtkmm-list mailing list
[hidden email]
https://mail.gnome.org/mailman/listinfo/gtkmm-list
Reply | Threaded
Open this post in threaded view
|

Re: Supporting C++17

Chris Vine
On Tue, 04 Apr 2017 18:13:46 +0200
Murray Cumming <[hidden email]> wrote:

> On Tue, 2017-04-04 at 15:09 +0100, Jonathan Wakely wrote:
> > On 4 April 2017 at 14:52, Murray Cumming wrote:  
> > > Any ideas about how we should support C++17 in gtkmm-3.0 without
> > > losing
> > > C++11/14 compatibility and without breaking ABI?  
> >
> > Replace all dynamic exception specifications with noexcept(false)
> > (or just no exception specification). That's not an ABI change.  
>
> That's great to know. I'll take care of that then.

I would check that.  It didn't affect ABI in C++11/14, but I am not so
sure about C++17.  According to
http://en.cppreference.com/w/cpp/language/noexcept_spec,
in C++17 "The noexcept-specification is a part of the function type and
may appear as part of any function declarator."  If it is part of the
type then it might feature in name mangling, so this is worth checking
with the compiler writers.
_______________________________________________
gtkmm-list mailing list
[hidden email]
https://mail.gnome.org/mailman/listinfo/gtkmm-list
Reply | Threaded
Open this post in threaded view
|

Re: Supporting C++17

Chris Vine
On Tue, 4 Apr 2017 22:56:22 +0100
Chris Vine <[hidden email]> wrote:

> On Tue, 04 Apr 2017 18:13:46 +0200
> Murray Cumming <[hidden email]> wrote:
> > On Tue, 2017-04-04 at 15:09 +0100, Jonathan Wakely wrote:  
> > > On 4 April 2017 at 14:52, Murray Cumming wrote:    
> > > > Any ideas about how we should support C++17 in gtkmm-3.0 without
> > > > losing
> > > > C++11/14 compatibility and without breaking ABI?    
> > >
> > > Replace all dynamic exception specifications with noexcept(false)
> > > (or just no exception specification). That's not an ABI
> > > change.    
> >
> > That's great to know. I'll take care of that then.  
>
> I would check that.  It didn't affect ABI in C++11/14, but I am not so
> sure about C++17.  According to
> http://en.cppreference.com/w/cpp/language/noexcept_spec,
> in C++17 "The noexcept-specification is a part of the function type
> and may appear as part of any function declarator."  If it is part of
> the type then it might feature in name mangling, so this is worth
> checking with the compiler writers.

On second thoughts, noexcept(true) might possibly change ABI in C++17,
but it seems inconceivable that noexcept(false) would.  It also seems
weird that merely applying -std=c++17 to your code should break its
ABI.  The more I think about it, the less clear I am what making the
noexcept specification part of the function type in C++17 actually
involves compiler-wise, or what it achieves.
_______________________________________________
gtkmm-list mailing list
[hidden email]
https://mail.gnome.org/mailman/listinfo/gtkmm-list
Reply | Threaded
Open this post in threaded view
|

Re: Supporting C++17

Jonathan Wakely
In reply to this post by Chris Vine
On 4 April 2017 at 22:56, Chris Vine wrote:
> I would check that.  It didn't affect ABI in C++11/14, but I am not so
> sure about C++17.  According to
> http://en.cppreference.com/w/cpp/language/noexcept_spec,
> in C++17 "The noexcept-specification is a part of the function type and
> may appear as part of any function declarator."  If it is part of the
> type then it might feature in name mangling, so this is worth checking
> with the compiler writers.

In C++17 the exception spec is part of the type, so noexcept(true)
functions are mangled differently from functions that are
noexcept(false).

But functions with dynamic exception specification aren't
noexcept(true), so they're not mangled as noexcept(true) functions
would be.

If you replace the throw(std::bad_cast) with neoxcept(false) (or,
equivalently, omit the exception specification entirely) they still
aren't noexcept(true).

Here's the proof:
https://paste.fedoraproject.org/paste/Pwm-rv4LGXKh2EDVJSeOEl5M1UNdIGYhyRLivL9gydE=/

N.B. I didn't say that exception specifications don't affect the type,
I said that removing the deprecated dynamic exception specification,
i.e. throw(std::bad_cast), doesn't affect the type. Because it's still
a noexcept(false) function.
_______________________________________________
gtkmm-list mailing list
[hidden email]
https://mail.gnome.org/mailman/listinfo/gtkmm-list
Reply | Threaded
Open this post in threaded view
|

Re: Supporting C++17

Jonathan Wakely
In reply to this post by Chris Vine
On 4 April 2017 at 23:08, Chris Vine wrote:
> On second thoughts, noexcept(true) might possibly change ABI in C++17,
> but it seems inconceivable that noexcept(false) would.

Right.

You can verify this fairly easily:

https://godbolt.org/g/akduU4

Notice that the type of foo (as used in the type of f1) is the same
for c++98, c++14 and c++17.

The type of bar (as it shown in the type of f2, which godbolt's
demangler doesn't even support!) changes for c++17.

foo is a noexcept(false) function, and is the same whether it uses
throw(bad_cast) or noexcept(false).

bar is a noexcept(true) function, and is the same whether it uses
throw() or noexcept(true), but is not the same for c++17 comapred with
earlier versions.

But what makes a difference is -std=c++17, not whether you use
throw(...) or noexcept(...).

>  It also seems
> weird that merely applying -std=c++17 to your code should break its
> ABI.  The more I think about it, the less clear I am what making the
> noexcept specification part of the function type in C++17 actually
> involves compiler-wise, or what it achieves.

It allows overloading on whether a function can throw, and
specializing templates on it, and deducing it from template arguments.

So if you take the address of a function you don't lose it's
"noexceptiness". Previously this static assertion could never pass:

void f() noexcept;
template<typename F> void g(F f) {
    static_assert( noexcept( f() ), "callback won't throw" );
}

int main() {
    g( &f );
}

In C++17 it compiles.
_______________________________________________
gtkmm-list mailing list
[hidden email]
https://mail.gnome.org/mailman/listinfo/gtkmm-list
Reply | Threaded
Open this post in threaded view
|

Re: Supporting C++17

Chris Vine
In reply to this post by Jonathan Wakely
On Tue, 4 Apr 2017 23:09:33 +0100
Jonathan Wakely <[hidden email]> wrote:

> On 4 April 2017 at 22:56, Chris Vine wrote:
> > I would check that.  It didn't affect ABI in C++11/14, but I am not
> > so sure about C++17.  According to
> > http://en.cppreference.com/w/cpp/language/noexcept_spec,
> > in C++17 "The noexcept-specification is a part of the function type
> > and may appear as part of any function declarator."  If it is part
> > of the type then it might feature in name mangling, so this is
> > worth checking with the compiler writers.  
>
> In C++17 the exception spec is part of the type, so noexcept(true)
> functions are mangled differently from functions that are
> noexcept(false).

As I said in my follow-up email, on reflection I agree with you about
noexcept(false).

But if this is correct about noexcept(true), and I am now beginning to
doubt myself on this, then it seems a recipe for broken libraries.  It
makes any code with a noexcept(true) function specification which has
been compiled with the -std=c++14 option ABI incompatible with the same
code compiled with the -std=c++17 option.

What benefit accrues from making the noexcept specification part of
the type which is worth all that ABI breakage?
_______________________________________________
gtkmm-list mailing list
[hidden email]
https://mail.gnome.org/mailman/listinfo/gtkmm-list
Reply | Threaded
Open this post in threaded view
|

Re: Supporting C++17

Jonathan Wakely
On 4 April 2017 at 23:28, Chris Vine <[hidden email]> wrote:

> On Tue, 4 Apr 2017 23:09:33 +0100
> Jonathan Wakely <[hidden email]> wrote:
>> On 4 April 2017 at 22:56, Chris Vine wrote:
>> > I would check that.  It didn't affect ABI in C++11/14, but I am not
>> > so sure about C++17.  According to
>> > http://en.cppreference.com/w/cpp/language/noexcept_spec,
>> > in C++17 "The noexcept-specification is a part of the function type
>> > and may appear as part of any function declarator."  If it is part
>> > of the type then it might feature in name mangling, so this is
>> > worth checking with the compiler writers.
>>
>> In C++17 the exception spec is part of the type, so noexcept(true)
>> functions are mangled differently from functions that are
>> noexcept(false).
>
> As I said in my follow-up email, on reflection I agree with you about
> noexcept(false).
>
> But if this is correct about noexcept(true), and I am now beginning to
> doubt myself on this, then it seems a recipe for broken libraries.  It
> makes any code with a noexcept(true) function specification which has
> been compiled with the -std=c++14 option ABI incompatible with the same
> code compiled with the -std=c++17 option.

Not any code, only code that depends on the type of function pointers
in mangled names. The mangled names of the functions themselves don't
change, only names that depend on them.

Using https://godbolt.org/g/akduU4 again, foo anr bar do not change
their mangled names. But f2, which depends on decltype(&bar), does
change.

However, it's uncommon to actually use decltype(&bar) like that in a
function signature. Far more common would be something like:

using func_type = void(*)();
void f2(func_type);

And this wouldn't change, because func_type doesn't include the
exception specification (because it wasn't allowed to in C++14).

There's an implicit conversion from R(*)(Args...) noexcept to
R(*)(Args...) so calling f2(&bar) would still work whether it's
declared to take void(*)() or void(*)()noexcept.

Some code may well be affected, and we don't know exactly how much,
but it's not as catastrophic as you suggest. It's a good reason not to
require C++17 for glibmm yet though :-)



> What benefit accrues from making the noexcept specification part of
> the type which is worth all that ABI breakage?

See my previous email.
http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2015/p0012r1.html
also gives some (terse) rationale.
_______________________________________________
gtkmm-list mailing list
[hidden email]
https://mail.gnome.org/mailman/listinfo/gtkmm-list
Reply | Threaded
Open this post in threaded view
|

Re: Supporting C++17

Chris Vine
In reply to this post by Jonathan Wakely
On Tue, 4 Apr 2017 23:28:09 +0100
Jonathan Wakely <[hidden email]> wrote:
> On 4 April 2017 at 23:08, Chris Vine wrote:
[snip]

> >  It also seems
> > weird that merely applying -std=c++17 to your code should break its
> > ABI.  The more I think about it, the less clear I am what making the
> > noexcept specification part of the function type in C++17 actually
> > involves compiler-wise, or what it achieves.  
>
> It allows overloading on whether a function can throw, and
> specializing templates on it, and deducing it from template arguments.
>
> So if you take the address of a function you don't lose it's
> "noexceptiness". Previously this static assertion could never pass:
>
> void f() noexcept;
> template<typename F> void g(F f) {
>     static_assert( noexcept( f() ), "callback won't throw" );
> }
>
> int main() {
>     g( &f );
> }
>
> In C++17 it compiles.

Aha, this may be it.
http://en.cppreference.com/w/cpp/language/noexcept_spec also says:
"Functions differing only in their exception specification cannot be
overloaded (just like the return type, exception specification is part
of function type, but not not part of the function signature) (since
C++17)."

So I suspect that the noexcept specification may still not affect name
mangling.  It might cause a compile error on type mismatch in C++17 when
say assigning a function to a function pointer, and as you say it may
allow the noexcept specification to participate in template type
resolution, but it may not affect linkage. I hope so anyway.
_______________________________________________
gtkmm-list mailing list
[hidden email]
https://mail.gnome.org/mailman/listinfo/gtkmm-list
Reply | Threaded
Open this post in threaded view
|

Re: Supporting C++17

Jonathan Wakely
On 4 April 2017 at 23:37, Chris Vine wrote:
> Aha, this may be it.
> http://en.cppreference.com/w/cpp/language/noexcept_spec also says:
> "Functions differing only in their exception specification cannot be
> overloaded (just like the return type, exception specification is part
> of function type, but not not part of the function signature) (since
> C++17)."
>
> So I suspect that the noexcept specification may still not affect name
> mangling.

Right. See the foo and bar examples.

You can't overload like this:

void f() noexcept;
void f();

But you can overload like this:

void g(void(*)());
void g(void (*)() noexcept);

The mangled name of a function doesn't depend on its exception
specification. It does depend on the parameter types (as it always has
in all versions of C++) and the parameter types can now be affected by
exception specifications.
_______________________________________________
gtkmm-list mailing list
[hidden email]
https://mail.gnome.org/mailman/listinfo/gtkmm-list