Bug 59426 - __has_trivial_{copy/assign} behavior differs from documentation
Summary: __has_trivial_{copy/assign} behavior differs from documentation
Status: RESOLVED FIXED
Alias: None
Product: gcc
Classification: Unclassified
Component: c++ (show other bugs)
Version: 4.8.1
: P3 normal
Target Milestone: 12.0
Assignee: Not yet assigned to anyone
URL:
Keywords: documentation
Depends on:
Blocks:
 
Reported: 2013-12-09 08:46 UTC by Kenton Varda
Modified: 2022-03-28 19:37 UTC (History)
5 users (show)

See Also:
Host:
Target:
Build:
Known to work:
Known to fail:
Last reconfirmed:


Attachments

Note You need to log in before you can comment on or make changes to this bug.
Description Kenton Varda 2013-12-09 08:46:15 UTC
Consider this struct with deleted copy/assignment:

struct S {
  S(const S&) = delete;
  S& operator=(const S&) = delete;
};

GCC's __has_trivial_{copy,assign}() intrinsics return false for this type.  This is a useful answer, but appears to disagree with the documentation:

http://gcc.gnu.org/onlinedocs/gcc/Type-Traits.html

"__has_trivial_copy(type): If __is_pod (type) is true or type is a reference type then the trait is true, else if type is a cv class or union type with a trivial copy constructor ([class.copy]) then the trait is true, else it is false. Requires: type shall be a complete type, (possibly cv-qualified) void, or an array of unknown bound."

Technically, according to [class.copy], a deleted copy constructor is "trivial" (because it is not user-provided, and none of the other exceptions apply).  A similar argument applies to assignment.  Clang has chosen to implement these intrinsics according to the docs rather than according to GCC's actual behavior, and thus both return true for S.  To avoid confusion, GCC should update either its documentation or its implementation so that the two match.

Apparently, other compilers (Embarcadero, MSVC) implement these intrinsics as well.  I do not have access to them to test their behavior in this case.

(I originally filed a bug against Clang:  http://llvm.org/bugs/show_bug.cgi?id=18185 )
Comment 1 Paolo Carlini 2013-12-09 12:13:17 UTC
The documentation definitely needs updating. The builtins track the C++11 semantics.
Comment 2 Richard Smith 2013-12-09 21:05:48 UTC
Which C++11 semantics? Is __has_trivial_copy(T) intended to determine:
 1) if T has a trivial copy constructor, or
 2) whether T has a trivial copy constructor and no non-trivial copy constructor, or
 3) whether the constructor selected to perform a copy from a 'const T' lvalue would be trivial, or 
 4) the value of std::is_trivially_copyable<T>::value?
Comment 3 Paolo Carlini 2013-12-09 23:35:32 UTC
Sorry, I spent too little time on my message. I meant to say that, *in general*, our intrinsics (modulo bugs, of course) try to track the c++11 semantics of the corresponding C++11 type trait with the same name. In general - maybe that's already clear, I don't know - we don't try to provide a separate C++98 semantics when -std=c++98 is in effect. In the specific area at issue, the various is_trivially_* would be the reference, but those are still unimplemented. In my opinion we should simply deprecate the various __has_trivial*, which by now are just legacy, too bad that internally they are implemented in terms of functions which in turn changed over time, but frankly I'm not sure there is much interest in "fixing" that, implementing correctly the various is_trivially_* has a much higher priority. You may want to ask other people, of course.
Comment 4 GCC Commits 2022-03-28 19:36:51 UTC
The master branch has been updated by Jason Merrill <jason@gcc.gnu.org>:

https://gcc.gnu.org/g:83a21c993449a32b98916814ed8ca237b3276912

commit r12-7863-g83a21c993449a32b98916814ed8ca237b3276912
Author: Jason Merrill <jason@redhat.com>
Date:   Mon Mar 28 15:32:30 2022 -0400

    c++: Fix __has_trivial_* docs [PR59426]
    
    These have been misdocumented since C++98 POD was split into C++11 trivial
    and standard-layout in r149721.
    
            PR c++/59426
    
    gcc/ChangeLog:
    
            * doc/extend.texi: Refer to __is_trivial instead of __is_pod.
Comment 5 Jason Merrill 2022-03-28 19:37:07 UTC
Fixed.