Bug 58074 - [C++11][DR 1333] __is_trivial intrinsic fails for deleted members and for non-trivial copy-c'tors
Summary: [C++11][DR 1333] __is_trivial intrinsic fails for deleted members and for non...
Status: ASSIGNED
Alias: None
Product: gcc
Classification: Unclassified
Component: c++ (show other bugs)
Version: 4.9.0
: P3 normal
Target Milestone: ---
Assignee: Jason Merrill
URL:
Keywords: ABI, deferred, rejects-valid
Depends on:
Blocks:
 
Reported: 2013-08-03 17:58 UTC by Daniel Krügler
Modified: 2023-02-13 09:30 UTC (History)
4 users (show)

See Also:
Host:
Target:
Build:
Known to work:
Known to fail:
Last reconfirmed: 2013-12-09 00:00:00


Attachments
patch (1.91 KB, patch)
2015-09-22 15:21 UTC, Jason Merrill
Details | Diff
patch for GCC 5 (2.09 KB, patch)
2015-09-22 15:22 UTC, Jason Merrill
Details | Diff

Note You need to log in before you can comment on or make changes to this bug.
Description Daniel Krügler 2013-08-03 17:58:12 UTC
The following observations where originally found by testing the std::is_trivial trait from <type_traits>, but the actual problem seems to result from the __is_trivial intrinsic, therefore I created a non-library issue from this.

gcc 4.9.0 20130616 (experimental) when compiled with the flags

-std=c++11 -Wall -pedantic

rejects the following code:

//-----------------------------
struct Trivial
{
  Trivial() = delete;
};

struct NonTrivial
{
  NonTrivial() = default;
  NonTrivial(NonTrivial&) = default;
  NonTrivial& operator=(NonTrivial&) = default;
};

static_assert(__is_trivial(Trivial), "Ouch");
static_assert(!__is_trivial(NonTrivial), "Ouch");
//-----------------------------

"
main.cpp|13|error: static assertion failed: Ouch|
main.cpp|14|error: static assertion failed: Ouch|
"

The first test should be valid, because 12.1 p4 says 

"A default constructor is trivial if it is **not user-provided** and if [..]" 

and according to 8.4.2 p4 

"A function is user-provided if it is user-declared and **not explicitly defaulted or deleted** on its first declaration.". 

The deleted default constructor should not prevent type Trivial of being trivial (Maybe this part of the problem is related to bug 52707, but I'm not sure).

The second test should succeed, because according to 12.8 p12:

"A copy/move constructor for class X is trivial if it is not user-provided, **its declared parameter type is the same as if it had been implicitly declared**, and if [..]"

and 12.8 p25, respectively:

"A copy/move assignment operator for class X is trivial if it is not user-provided, **its declared parameter type is the same as if it had been implicitly declared**, and if [..]"

The copy-constructor/assignment operator of NonTrivial do both not have the parameter type (according to the definition of function parameter types as of 8.3.5) as if it had been implicitly declared.
Comment 1 Paolo Carlini 2013-08-03 18:12:30 UTC
... and the issue is one more level deeper, because __is_trivial just uses the internal trivial_type_p. I mean, it should be pretty easy to construct testcases not involving __is_trival at all but handled incorrectly: outside the implementation of the intrinsics, the internal pod_type_p itself is, predictably, std_layout_type_p && trivial_type_p and then anything depending on POD-ness is sensitive.
Comment 2 Paolo Carlini 2013-12-09 09:34:30 UTC
In mainline we made some progress, the first static_assert passes.
Comment 3 Richard Smith 2015-06-09 20:51:25 UTC
This bug results in GCC failing to follow the Itanium C++ ABI when passing such types to/from functions; see llvm.org/PR23764 for a user complaint of cross-vendor ABI incompatibility.
Comment 4 Paolo Carlini 2015-07-09 09:12:38 UTC
CC-ing Jason about the ABI issue.
Comment 5 Jason Merrill 2015-09-22 15:20:08 UTC
This comes from DR 1333, which seems to me to be wrongly resolved.  I've raised the question with the committee and will defer this until after the next meeting.
Comment 6 Jason Merrill 2015-09-22 15:21:00 UTC
Created attachment 36369 [details]
patch

But here's the fix if the committee reaffirms the DR.
Comment 7 Jason Merrill 2015-09-22 15:22:11 UTC
Created attachment 36370 [details]
patch for GCC 5

And a patch to add a -Wabi warning to GCC 5.
Comment 8 Eric Gallager 2018-03-22 18:35:05 UTC
(In reply to Jason Merrill from comment #5)
> This comes from DR 1333, which seems to me to be wrongly resolved.  I've
> raised the question with the committee and will defer this until after the
> next meeting.

Have further meetings gotten back to it?
Comment 9 Jonathan Wakely 2019-02-11 20:51:21 UTC
(In reply to Daniel Krügler from comment #0)
> The deleted default constructor should not prevent type Trivial of being
> trivial (Maybe this part of the problem is related to bug 52707, but I'm not
> sure).

I think DR 1363 changed that (and DR 1496 reconfirmed it) so the first test is wrong. But G++ now passes that assertion, so that's also wrong (that is Bug 85723 though).
Comment 10 Daniel Krügler 2019-03-17 16:52:03 UTC
(In reply to Jonathan Wakely from comment #9)
> (In reply to Daniel Krügler from comment #0)
> > The deleted default constructor should not prevent type Trivial of being
> > trivial (Maybe this part of the problem is related to bug 52707, but I'm not
> > sure).
> 
> I think DR 1363 changed that (and DR 1496 reconfirmed it) so the first test
> is wrong. But G++ now passes that assertion, so that's also wrong (that is
> Bug 85723 though).

I agree in regard to DR 1496. The history behind that was that during the Portland 2012 CWG drafting of that issue the following wording suggestion was provided:

"A trivial class is a class that is trivially copyable and has either
a trivial default constructor or no default constructor (12.1 class.ctor)."

That wording had the effect that classes with either deleted or no default constructor could be trivial and made these two cases consistent as pointed out by DR 1496. That P/R was then later rejected and modified to the now accepted wording at the Kona 2015 meeting, which also had the effect of making the two cases consistent in a now a different way, by imposing the requirement that at least one non-deleted default constructor exists. I don't think that DR 1363 changed the situation, because the meaning of the 1363 wording still didn't exclude deleted constructors from being trivial.
Comment 11 Richard Smith 2019-03-18 20:02:39 UTC
The point of trivial (as distinguished from trivially-copyable) is that an instance of type T can be created and "properly" initialized (albeit left with an indeterminate value) without executing any code.

(The notion of a trivial type is not used by the core language, and is used in the library only to constrain things like the template parameters of basic_string and aligned_storage, where it is intentional that objects of type T can be created by allocating suitable storage and performing no further initialization.)

So I think the language rule after the application of the relevant DRs is approximately right: a type with a deleted default constructor should not be considered trivial.

(It's arguable that a type with multiple default constructors should perhaps also not be considered trivial. Or maybe we should decide that the language notion of "trivial" is a useless relic of "POD" and should be removed from the core language, and that the library should be looking for types that are trivially default-constructible and trivially-copyable in the places where it currently looks for "trivial" types.)