Is this the right alias for discussion of Clang implementation specifics? Or would that be better over on cfe-commits?<div><br></div><div>Assuming this is an appropriate alias (or that I can simply forward this on if not), I am fixing some missing compiler intrinsics that Clang doesn't provide but the VS 2012 STL headers require for some of their type traits implementations.</div>

<div><br></div><div>In doing this I have found a couple of things in Clang's current type trait support that seem incorrect by my reading of the standards, but I wanted to run this by other people before I changed anything.</div>

<div><br></div><div>The first issue is this code:</div><div><br></div><div>struct NotTrivial {</div><div>  NotTrivial() = delete;</div><div>};</div><div><br></div><div>int main(int,char**)<br>{</div><div>    static_assert(!__is_trivial(NotTrivial), "A class with no default constructor doesn't meet the definition of a trivial class");</div>

<div>    return 0;</div><div>}</div><div><br></div><div>This fires today in Clang trunk.</div><div><br></div><div>Looking at the standard I see this:</div><div><br></div><div><div>The definition of a trivial type is n3376 3.9 [basic.types]/9</div>

<div><br></div><div>Arithmetic types (3.9.1), enumeration types, pointer types, pointer to member types (3.9.2), std::nullptr_t, and cv-qualified </div><div>versions of these types (3.9.3) are collectively called scalar types. Scalar types, POD classes (Clause 9), arrays of such types and cv-qualified versions of these types (3.9.3) are collectively called POD types. Scalar types, trivially copyable class types (Clause 9), arrays of such types, and cv-qualified versions of these types (3.9.3) are collectively called trivially copyable types. Scalar types, trivial class types (Clause 9), arrays of such types and cv-qualified versions of these types (3.9.3) are collectively called trivial types. Scalar types, standard-layout class types (Clause 9), arrays of such types and cv-qualified </div>

<div>versions of these types (3.9.3) are collectively called standard layout types.</div></div><div><br></div><div>The referenced Clause 9 says (n3376 9 [class]/6):</div><div><br></div><div><div>A trivial class is a class that has a trivial default constructor (12.1) and is trivially copyable.</div>

<div>[ Note: In particular, a trivially copyable or trivial class does not have virtual functions or virtual base</div></div><div><br></div><div>Since NotTrivial has no default constructor it seems it can't meet this definition.</div>

<div><br></div><div>I believe the issue lies in clang\lib\AST\DeclCXX.cpp (line 579):</div><div><br></div><div><div>bool UserProvided = Constructor->isUserProvided();</div></div><div><br></div><div><div>if (Constructor->isDefaultConstructor()) {</div>

</div><div>  data().DeclaredDefaultConstructor = true;</div><div><div>  if (UserProvided) {</div></div><div><div>    // C++0x [class.ctor]p5:</div><div>    //   A default constructor is trivial if it is not user-provided [...]</div>

<div>    data().HasTrivialDefaultConstructor = false;</div><div>    data().UserProvidedDefaultConstructor = true;</div><div>  }</div></div><div><br></div><div>In this case isUserProvided is defined as:</div><div><br></div>

<div><div>/// isUserProvided - True if this method is user-declared and was not</div><div>/// deleted or defaulted on its first declaration.</div><div>bool isUserProvided() const {</div><div>  return !(isDeleted() || getCanonicalDecl()->isDefaulted());</div>

<div>}</div></div><div><br></div><div>so we never fall into the block that would set HasTrivialDefaultConstructor to false, since UserProvided ends up as false. We also set DeclaredDefaultConstructor to true even though Constructor->isDeleted() would return true here.</div>

<div><br></div><div><br></div><div><br></div><div>The second issue (this one I am less sure about) is in this code (this also fires in Clang trunk):</div><div><br></div><div><div>struct NotTriviallyCopyable {</div><div>  NotTriviallyCopyable(const NotTriviallyCopyable&) = delete;</div>

<div>  NotTriviallyCopyable& operator=(const NotTriviallyCopyable&) = delete;</div><div>};</div><div><br></div><div>int main(int,char**)<br>{</div><div>    static_assert(!__is_trivially_copyable(NotTriviallyCopyable), "A class with no copy constructor or copy assignment operator is not trivially copyable");</div>

<div>    return 0;</div><div>}</div></div><div><br></div><div>This one hinges on the definition of trivially-copyable, which seems like it can be read two ways:</div><div><br></div><div><div><div>n3376 9 [class]/6:</div>
</div>
<div><br></div><div>A trivially copyable class is a class that:</div><div>  — has no non-trivial copy constructors (12.8),</div><div>  — has no non-trivial move constructors (12.8),</div><div>  — has no non-trivial copy assignment operators (13.5.3, 12.8),</div>

<div>  — has no non-trivial move assignment operators (13.5.3, 12.8), and</div><div>  — has a trivial destructor (12.4).</div></div><div><br></div><div>It seems since this class has NO copy constructors or copy assignment operators that it shouldn't be considered trivially copyable. </div>

<div><br></div><div>That said, you could also read this as the fact there are no such operators means, implicitly, that there are no non-trivial versions of said operators and thus this class IS trivially copyable. That reading doesn't really seem to yield interesting type information since you can't actually copy a type such as this (short of just doing a memcpy). Or is the intention of code dealing with trivial types WOULD just copy say via std::memcpy?</div>

<div><br></div><div>Thoughts? Am I misreading the standard? Misunderstanding the Clang code here?</div><div><br></div><div>Ryan</div>