[libc++] RFC: adding a configuration option to enable constexpr constructors in c++1[xy]

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

[libc++] RFC: adding a configuration option to enable constexpr constructors in c++1[xy]

David Chisnall via cfe-dev
Hello,

I'm currently working on migrating a large (100M+ LOC) C++ codebase to libc++. One particular pain point are the absence of constexpr constructors for std::pair, std::array, and std::tuple under C++11. Some older versions of libstdc++ expose constexpr constructors under C++11, while libc++ does not; this causes build failures when using libc++.

I would like to add a configuration variable that enables the constexpr qualifier on these constructors for C++11 or later, with the intent of advancing the C++ version as quickly as possible. Most of the uses can be trivially replaced by removing constexpr or switching to arrays, but this is churn for code which will (hopefully) soon be compliant anyhow.

I suspect this may be useful for other codebases that build in C++11 mode to move to libc++... however, this would be a non-conforming extension. Adding a configuration option in __config_site.in (with the default being conforming behaviour) seems like it may be the most reasonable way to add the option.

Please let me know if there are any strong objections to this plan.

Thanks,
--dlj

_______________________________________________
cfe-dev mailing list
[hidden email]
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-dev
Reply | Threaded
Open this post in threaded view
|

Re: [libc++] RFC: adding a configuration option to enable constexpr constructors in c++1[xy]

David Chisnall via cfe-dev


On Wed, Oct 11, 2017 at 6:30 PM, David Jones via cfe-dev <[hidden email]> wrote:
Hello,

I'm currently working on migrating a large (100M+ LOC) C++ codebase to libc++. One particular pain point are the absence of constexpr constructors for std::pair, std::array, and std::tuple under C++11.

Nit: std::array shouldn't have any constructors. But the other members are conditionally constexpr.
 
Some older versions of libstdc++ expose constexpr constructors under C++11, while libc++ does not; this causes build failures when using libc++.

Hmm, just to clarify, it's not just older versions of libstdc++ that do this, but newer ones as well. It's not like they removed it later.
 

I would like to add a configuration variable that enables the constexpr qualifier on these constructors for C++11 or later, with the intent of advancing the C++ version as quickly as possible. Most of the uses can be trivially replaced by removing constexpr or switching to arrays, but this is churn for code which will (hopefully) soon be compliant anyhow.

I'm actually quite sympathetic to enabling this extension by default, since MSVC and libstdc++ both seem to. We're the odd man out.
If everybody else can safely get away with this, we should be able to as well.

BTW, by "C++11 or later" you mean "C++11" because they're already required to be constexpr in C++14.
 

I suspect this may be useful for other codebases that build in C++11 mode to move to libc++... however, this would be a non-conforming extension. Adding a configuration option in __config_site.in (with the default being conforming behaviour) seems like it may be the most reasonable way to add the option.

The extension is technically slightly worse than non-conforming; it's explicitly forbidden. Implementations are not allowed to apply constexpr where it isn't specified. However I think this rule should be relaxed to allow implementations to backport newly added constexpr specifiers to older dialects as an extension, as is this case.

However my main concern with this as an on-by-default extension is that it has the potential to break code. There are certain constexpr evaluations that might result in a hard compile error that wouldn't before. I think Clang has fixed most of these cases though.


Please let me know if there are any strong objections to this plan.

Thanks,
--dlj

_______________________________________________
cfe-dev mailing list
[hidden email]
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-dev



_______________________________________________
cfe-dev mailing list
[hidden email]
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-dev
Reply | Threaded
Open this post in threaded view
|

Re: [libc++] RFC: adding a configuration option to enable constexpr constructors in c++1[xy]

David Chisnall via cfe-dev
On Wed, Oct 11, 2017 at 6:11 PM, Eric Fiselier <[hidden email]> wrote:


On Wed, Oct 11, 2017 at 6:30 PM, David Jones via cfe-dev <[hidden email]> wrote:
Hello,

I'm currently working on migrating a large (100M+ LOC) C++ codebase to libc++. One particular pain point are the absence of constexpr constructors for std::pair, std::array, and std::tuple under C++11.

Nit: std::array shouldn't have any constructors. But the other members are conditionally constexpr.
 
Some older versions of libstdc++ expose constexpr constructors under C++11, while libc++ does not; this causes build failures when using libc++.

Hmm, just to clarify, it's not just older versions of libstdc++ that do this, but newer ones as well. It's not like they removed it later.
 

I would like to add a configuration variable that enables the constexpr qualifier on these constructors for C++11 or later, with the intent of advancing the C++ version as quickly as possible. Most of the uses can be trivially replaced by removing constexpr or switching to arrays, but this is churn for code which will (hopefully) soon be compliant anyhow.

I'm actually quite sympathetic to enabling this extension by default, since MSVC and libstdc++ both seem to. We're the odd man out.
If everybody else can safely get away with this, we should be able to as well.

BTW, by "C++11 or later" you mean "C++11" because they're already required to be constexpr in C++14.

Naturally, yes... although what I really wanted to get at was "not C++03 or earlier."
 
 

I suspect this may be useful for other codebases that build in C++11 mode to move to libc++... however, this would be a non-conforming extension. Adding a configuration option in __config_site.in (with the default being conforming behaviour) seems like it may be the most reasonable way to add the option.

The extension is technically slightly worse than non-conforming; it's explicitly forbidden. Implementations are not allowed to apply constexpr where it isn't specified. However I think this rule should be relaxed to allow implementations to backport newly added constexpr specifiers to older dialects as an extension, as is this case.

However my main concern with this as an on-by-default extension is that it has the potential to break code. There are certain constexpr evaluations that might result in a hard compile error that wouldn't before. I think Clang has fixed most of these cases though.


Right... I think on-by-default might be a bit too much.

_______________________________________________
cfe-dev mailing list
[hidden email]
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-dev
Reply | Threaded
Open this post in threaded view
|

Re: [libc++] RFC: adding a configuration option to enable constexpr constructors in c++1[xy]

David Chisnall via cfe-dev


On Wed, Oct 11, 2017 at 9:18 PM, David Jones <[hidden email]> wrote:
On Wed, Oct 11, 2017 at 6:11 PM, Eric Fiselier <[hidden email]> wrote:


On Wed, Oct 11, 2017 at 6:30 PM, David Jones via cfe-dev <[hidden email]> wrote:
Hello,

I'm currently working on migrating a large (100M+ LOC) C++ codebase to libc++. One particular pain point are the absence of constexpr constructors for std::pair, std::array, and std::tuple under C++11.

Nit: std::array shouldn't have any constructors. But the other members are conditionally constexpr.
 
Some older versions of libstdc++ expose constexpr constructors under C++11, while libc++ does not; this causes build failures when using libc++.

Hmm, just to clarify, it's not just older versions of libstdc++ that do this, but newer ones as well. It's not like they removed it later.
 

I would like to add a configuration variable that enables the constexpr qualifier on these constructors for C++11 or later, with the intent of advancing the C++ version as quickly as possible. Most of the uses can be trivially replaced by removing constexpr or switching to arrays, but this is churn for code which will (hopefully) soon be compliant anyhow.

I'm actually quite sympathetic to enabling this extension by default, since MSVC and libstdc++ both seem to. We're the odd man out.
If everybody else can safely get away with this, we should be able to as well.

BTW, by "C++11 or later" you mean "C++11" because they're already required to be constexpr in C++14.

Naturally, yes... although what I really wanted to get at was "not C++03 or earlier."
 
 

I suspect this may be useful for other codebases that build in C++11 mode to move to libc++... however, this would be a non-conforming extension. Adding a configuration option in __config_site.in (with the default being conforming behaviour) seems like it may be the most reasonable way to add the option.

The extension is technically slightly worse than non-conforming; it's explicitly forbidden. Implementations are not allowed to apply constexpr where it isn't specified. However I think this rule should be relaxed to allow implementations to backport newly added constexpr specifiers to older dialects as an extension, as is this case.

However my main concern with this as an on-by-default extension is that it has the potential to break code. There are certain constexpr evaluations that might result in a hard compile error that wouldn't before. I think Clang has fixed most of these cases though.


Right... I think on-by-default might be a bit too much.

Thankfully, despite my short-lived best efforts so far, I haven't been able to construct a test case that I care about which breaks.
Admittedly, older Clang versions have problematic examples, but I suspect very few people mix very old Clang versions
with brand new STL headers.

For example, the following code has silently different behavior across dialects:

static std::pair<int, int> p(1, 2);

In C++14, the initialization of `p` occurs at compile time, but in C++11, because the constructor is not constexpr,
the initialization happens at run time. This bug also effects types composed using pair, Ex:

struct MyType {
template <class ...Args>
constexpr MyType(Args... args) : p(args...) {}
std::pair<int, int> x;
};

Such a type implicitly depends on `pair`s constructors to be constexpr in order for
for instances of the class with static storage duration to be safely constructed during
constant initialization.

IMHO, It's more important for libc++ to provide consistent and safe semantics for `pair`
and `tuple` across dialects than it is to be pedantically correct. One thing Howard Hinnent
taught me was to act in the best interest of your users; a pedantically correct implementation
without users is of value to no one.

Therefore, I would rather adopt the extension universally, as everybody else does, unless I
can come up with sensible examples of use-cases that break after introducing the extension,

@Marshall, would you be supportive of this?


_______________________________________________
cfe-dev mailing list
[hidden email]
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-dev
Reply | Threaded
Open this post in threaded view
|

Re: [libc++] RFC: adding a configuration option to enable constexpr constructors in c++1[xy]

David Chisnall via cfe-dev
On Oct 12, 2017, at 4:21 AM, Eric Fiselier via cfe-dev <[hidden email]> wrote:

>
>
>
> On Wed, Oct 11, 2017 at 9:18 PM, David Jones <[hidden email]> wrote:
>> On Wed, Oct 11, 2017 at 6:11 PM, Eric Fiselier <[hidden email]> wrote:
>>
>>
>> On Wed, Oct 11, 2017 at 6:30 PM, David Jones via cfe-dev <[hidden email]> wrote:
>>> Hello,
>>>
>>> I'm currently working on migrating a large (100M+ LOC) C++ codebase to libc++. One particular pain point are the absence of constexpr constructors for std::pair, std::array, and std::tuple under C++11.
>>>
>> Nit: std::array shouldn't have any constructors. But the other members are conditionally constexpr.
>>
>>> Some older versions of libstdc++ expose constexpr constructors under C++11, while libc++ does not; this causes build failures when using libc++.
>>>
>> Hmm, just to clarify, it's not just older versions of libstdc++ that do this, but newer ones as well. It's not like they removed it later.
>>
>>
>>> I would like to add a configuration variable that enables the constexpr qualifier on these constructors for C++11 or later, with the intent of advancing the C++ version as quickly as possible. Most of the uses can be trivially replaced by removing constexpr or switching to arrays, but this is churn for code which will (hopefully) soon be compliant anyhow.
>>>
>> I'm actually quite sympathetic to enabling this extension by default, since MSVC and libstdc++ both seem to. We're the odd man out.
>> If everybody else can safely get away with this, we should be able to as well.
>>
>> BTW, by "C++11 or later" you mean "C++11" because they're already required to be constexpr in C++14.
>>
> Naturally, yes... although what I really wanted to get at was "not C++03 or earlier."
>
>
>
>>> I suspect this may be useful for other codebases that build in C++11 mode to move to libc++... however, this would be a non-conforming extension. Adding a configuration option in __config_site.in (with the default being conforming behaviour) seems like it may be the most reasonable way to add the option.
>>>
>> The extension is technically slightly worse than non-conforming; it's explicitly forbidden. Implementations are not allowed to apply constexpr where it isn't specified. However I think this rule should be relaxed to allow implementations to backport newly added constexpr specifiers to older dialects as an extension, as is this case.
>>
>> However my main concern with this as an on-by-default extension is that it has the potential to break code. There are certain constexpr evaluations that might result in a hard compile error that wouldn't before. I think Clang has fixed most of these cases though.
>>
>>
>> Right... I think on-by-default might be a bit too much.
>>
> Thankfully, despite my short-lived best efforts so far, I haven't been able to construct a test case that I care about which breaks.
> Admittedly, older Clang versions have problematic examples, but I suspect very few people mix very old Clang versions
> with brand new STL headers.
>
> For example, the following code has silently different behavior across dialects:
>
> static std::pair<int, int> p(1, 2);
>
> In C++14, the initialization of `p` occurs at compile time, but in C++11, because the constructor is not constexpr,
> the initialization happens at run time. This bug also effects types composed using pair, Ex:
>
> struct MyType {
>   template <class ...Args>
>   constexpr MyType(Args... args) : p(args...) {}
>   std::pair<int, int> x;
> };
>
> Such a type implicitly depends on `pair`s constructors to be constexpr in order for
> for instances of the class with static storage duration to be safely constructed during
> constant initialization.
>
> IMHO, It's more important for libc++ to provide consistent and safe semantics for `pair`
> and `tuple` across dialects than it is to be pedantically correct. One thing Howard Hinnent
> taught me was to act in the best interest of your users; a pedantically correct implementation
> without users is of value to no one.
>
> Therefore, I would rather adopt the extension universally, as everybody else does, unless I
> can come up with sensible examples of use-cases that break after introducing the extension,
>
> @Marshall, would you be supportive of this?
Random, untested thought:

What if in <__config> every _LIBCPP_CONFIG_MACRO was defined like this:

#ifndef _LIBCPP_CONFIG_MACRO

// Current configuration goes here

#endif

And then clients could compile like this if desired:

clang++ -D_LIBCPP_CONSTEXPR_AFTER_CXX11=constexpr …

libc++ stays conformant, but becomes far more configurable.

Testing might be a problem...

Howard


_______________________________________________
cfe-dev mailing list
[hidden email]
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-dev

signature.asc (849 bytes) Download Attachment
Reply | Threaded
Open this post in threaded view
|

Re: [libc++] RFC: adding a configuration option to enable constexpr constructors in c++1[xy]

David Chisnall via cfe-dev
> -----Original Message-----
> From: cfe-dev [mailto:[hidden email]] On Behalf Of Howard
> Hinnant via cfe-dev
...

> Random, untested thought:
>
> What if in <__config> every _LIBCPP_CONFIG_MACRO was defined like this:
>
> #ifndef _LIBCPP_CONFIG_MACRO
>
> // Current configuration goes here
>
> #endif
>
> And then clients could compile like this if desired:
>
> clang++ -D_LIBCPP_CONSTEXPR_AFTER_CXX11=constexpr …
>
> libc++ stays conformant, but becomes far more configurable.

That seems a little awkward.  What if we added a "-std=clang++11" mode (like "gnu++11" ) that would specify that definition when stdlib=libc++?  If we came up with other good-for-users deviations from the standard, we could enable them in this mode.

-Brian

_______________________________________________
cfe-dev mailing list
[hidden email]
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-dev
Reply | Threaded
Open this post in threaded view
|

Re: [libc++] RFC: adding a configuration option to enable constexpr constructors in c++1[xy]

David Chisnall via cfe-dev
In reply to this post by David Chisnall via cfe-dev
On 12 Oct 2017 01:22, "Eric Fiselier via cfe-dev" <[hidden email]> wrote:


On Wed, Oct 11, 2017 at 9:18 PM, David Jones <[hidden email]> wrote:
On Wed, Oct 11, 2017 at 6:11 PM, Eric Fiselier <[hidden email]> wrote:


On Wed, Oct 11, 2017 at 6:30 PM, David Jones via cfe-dev <[hidden email]> wrote:
Hello,

I'm currently working on migrating a large (100M+ LOC) C++ codebase to libc++. One particular pain point are the absence of constexpr constructors for std::pair, std::array, and std::tuple under C++11.

Nit: std::array shouldn't have any constructors. But the other members are conditionally constexpr.
 
Some older versions of libstdc++ expose constexpr constructors under C++11, while libc++ does not; this causes build failures when using libc++.

Hmm, just to clarify, it's not just older versions of libstdc++ that do this, but newer ones as well. It's not like they removed it later.
 

I would like to add a configuration variable that enables the constexpr qualifier on these constructors for C++11 or later, with the intent of advancing the C++ version as quickly as possible. Most of the uses can be trivially replaced by removing constexpr or switching to arrays, but this is churn for code which will (hopefully) soon be compliant anyhow.

I'm actually quite sympathetic to enabling this extension by default, since MSVC and libstdc++ both seem to. We're the odd man out.
If everybody else can safely get away with this, we should be able to as well.

BTW, by "C++11 or later" you mean "C++11" because they're already required to be constexpr in C++14.

Naturally, yes... although what I really wanted to get at was "not C++03 or earlier."
 
 

I suspect this may be useful for other codebases that build in C++11 mode to move to libc++... however, this would be a non-conforming extension. Adding a configuration option in __config_site.in (with the default being conforming behaviour) seems like it may be the most reasonable way to add the option.

The extension is technically slightly worse than non-conforming; it's explicitly forbidden. Implementations are not allowed to apply constexpr where it isn't specified. However I think this rule should be relaxed to allow implementations to backport newly added constexpr specifiers to older dialects as an extension, as is this case.

However my main concern with this as an on-by-default extension is that it has the potential to break code. There are certain constexpr evaluations that might result in a hard compile error that wouldn't before. I think Clang has fixed most of these cases though.


Right... I think on-by-default might be a bit too much.

Thankfully, despite my short-lived best efforts so far, I haven't been able to construct a test case that I care about which breaks.
Admittedly, older Clang versions have problematic examples, but I suspect very few people mix very old Clang versions
with brand new STL headers.

For example, the following code has silently different behavior across dialects:

static std::pair<int, int> p(1, 2);

In C++14, the initialization of `p` occurs at compile time, but in C++11, because the constructor is not constexpr,
the initialization happens at run time.

The initialization might happen at compile time, even in C++11 or C++98. See http://eel.is/c++draft/basic.start.static#3

This bug also effects types composed using pair, Ex:

struct MyType {
template <class ...Args>
constexpr MyType(Args... args) : p(args...) {}
std::pair<int, int> x;
};

Such a type implicitly depends on `pair`s constructors to be constexpr in order for
for instances of the class with static storage duration to be safely constructed during
constant initialization.

IMHO, It's more important for libc++ to provide consistent and safe semantics for `pair`
and `tuple` across dialects than it is to be pedantically correct. One thing Howard Hinnent
taught me was to act in the best interest of your users; a pedantically correct implementation
without users is of value to no one.

Therefore, I would rather adopt the extension universally, as everybody else does, unless I
can come up with sensible examples of use-cases that break after introducing the extension,

@Marshall, would you be supportive of this?


_______________________________________________
cfe-dev mailing list
[hidden email]
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-dev



_______________________________________________
cfe-dev mailing list
[hidden email]
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-dev
Reply | Threaded
Open this post in threaded view
|

Re: [libc++] RFC: adding a configuration option to enable constexpr constructors in c++1[xy]

David Chisnall via cfe-dev
In reply to this post by David Chisnall via cfe-dev

On Thu, Oct 12, 2017 at 7:39 AM Brian Cain via cfe-dev <[hidden email]> wrote:
> -----Original Message-----
> From: cfe-dev [mailto:[hidden email]] On Behalf Of Howard
> Hinnant via cfe-dev
...
> Random, untested thought:
>
> What if in <__config> every _LIBCPP_CONFIG_MACRO was defined like this:
>
> #ifndef _LIBCPP_CONFIG_MACRO
>
> // Current configuration goes here
>
> #endif
>
> And then clients could compile like this if desired:
>
> clang++ -D_LIBCPP_CONSTEXPR_AFTER_CXX11=constexpr …
>
> libc++ stays conformant, but becomes far more configurable.

That seems a little awkward.  What if we added a "-std=clang++11" mode (like "gnu++11" ) that would specify that definition when stdlib=libc++?  If we came up with other good-for-users deviations from the standard, we could enable them in this mode.

+1

Please do not deliberately break standard conformance when apparently standard-enforcing flags are used.

Jeff
--

_______________________________________________
cfe-dev mailing list
[hidden email]
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-dev
Reply | Threaded
Open this post in threaded view
|

Re: [libc++] RFC: adding a configuration option to enable constexpr constructors in c++1[xy]

David Chisnall via cfe-dev

The initialization might happen at compile time, even in C++11 or C++98. See http://eel.is/c++draft/basic.start.static#3

*might happen*. Even worse...
 
I think we're jumping the gun. First, we're the only standard library to not backport these extensions.
In this sense of strict conformance, we're the odd man out: We're the only one to exhibit the bad behavior.

Before we concern ourselves too much with standards conformance, we need to establish that making
the suggested changes would actually break reasonable user code. (Which I haven't been able to do in a meaningful way).

Can somebody provide an example of such code?

Otherwise, we should do as the Romans do, and change libc++ to do the *right* thing.

/Eric


On Thu, Oct 12, 2017 at 10:18 AM, Jeff Hammond <[hidden email]> wrote:

On Thu, Oct 12, 2017 at 7:39 AM Brian Cain via cfe-dev <[hidden email]> wrote:
> -----Original Message-----
> From: cfe-dev [mailto:[hidden email]] On Behalf Of Howard
> Hinnant via cfe-dev
...
> Random, untested thought:
>
> What if in <__config> every _LIBCPP_CONFIG_MACRO was defined like this:
>
> #ifndef _LIBCPP_CONFIG_MACRO
>
> // Current configuration goes here
>
> #endif
>
> And then clients could compile like this if desired:
>
> clang++ -D_LIBCPP_CONSTEXPR_AFTER_CXX11=constexpr …
>
> libc++ stays conformant, but becomes far more configurable.

That seems a little awkward.  What if we added a "-std=clang++11" mode (like "gnu++11" ) that would specify that definition when stdlib=libc++?  If we came up with other good-for-users deviations from the standard, we could enable them in this mode.

+1

Please do not deliberately break standard conformance when apparently standard-enforcing flags are used.

Jeff
--


On Thu, Oct 12, 2017 at 10:18 AM, Jeff Hammond <[hidden email]> wrote:

On Thu, Oct 12, 2017 at 7:39 AM Brian Cain via cfe-dev <[hidden email]> wrote:
> -----Original Message-----
> From: cfe-dev [mailto:[hidden email]] On Behalf Of Howard
> Hinnant via cfe-dev
...
> Random, untested thought:
>
> What if in <__config> every _LIBCPP_CONFIG_MACRO was defined like this:
>
> #ifndef _LIBCPP_CONFIG_MACRO
>
> // Current configuration goes here
>
> #endif
>
> And then clients could compile like this if desired:
>
> clang++ -D_LIBCPP_CONSTEXPR_AFTER_CXX11=constexpr …
>
> libc++ stays conformant, but becomes far more configurable.

That seems a little awkward.  What if we added a "-std=clang++11" mode (like "gnu++11" ) that would specify that definition when stdlib=libc++?  If we came up with other good-for-users deviations from the standard, we could enable them in this mode.

+1

Please do not deliberately break standard conformance when apparently standard-enforcing flags are used.

Jeff
--


_______________________________________________
cfe-dev mailing list
[hidden email]
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-dev