This is an archive of the discontinued LLVM Phabricator instance.

[Sema][C++] Adopt DR2171 relaxed triviality requirements
Needs ReviewPublic

Authored by comex on Feb 16 2020, 12:23 AM.

Details

Reviewers
rsmith
Summary

When defining a copy constructor or assignment operator as either explicitly defaulted (= default) or deleted (= delete), it's possible to give it a different parameter list from the normal (const Foo &).

For = default, the only allowed change [1] is to use a non-const reference instead of a const one:

struct X {

X(X &) = default;

};

For = delete, it's also possible to add additional parameters with default values, as well as variadic parameters (...).

(Besides the parameter list, it's also possible to change the exception specification and ref-qualifiers, but those never affected triviality.)

Originally, C++11 (which introduced explicit defaulting) had a rule that any modification of the parameter list would prevent the function from being considered trivial, so e.g. is_trivially_copyable_v<X> would be false. However, Defect Report 2171 [2] (2016) removed that rule entirely. Up until now, that change hasn't been implemented in Clang; this patch implements it.

In addition, Clang currently applies a similar rule to deleted *default* constructors, which AFAICT is not in compliance with any published version of the spec. So this fails when it should pass:

struct X {

X(...) = delete;

};
static_assert(__has_trivial_constructor(X));

This patch also fixes that.

This is an ABI-breaking change, since the existence of trivial constructors affects whether a type is "trivial for the purposes of calls" [3]. I checked other compilers to see whether they implement the DR:

  • GCC has never treated such functions as nontrivial, even before the DR. [4]
  • MSVC currently doesn't treat them as nontrivial [5]; I haven't checked old versions since they're not on Godbolt.

Thus the change would improve Clang's compatibility with those compilers.

Implementation-wise, this patch is simple enough: it just removes the code in Sema::SpecialMemberIsTrivial that checked the parameter list. In terms of tests, there were already a number of tests verifying the old behavior, so the patch merely updates them for the new behavior.

[1] https://eel.is/c++draft/dcl.fct.def.default#2
[2] http://www.open-std.org/Jtc1/sc22/wg21/docs/cwg_defects.html#2171
[3] https://quuxplusone.github.io/blog/2018/05/02/trivial-abi-101/
[4] https://gcc.godbolt.org/z/GU_wyz (note GCC version)
[5] https://gcc.godbolt.org/z/VYiMn3

Diff Detail

Event Timeline

comex created this revision.Feb 16 2020, 12:23 AM
Herald added a project: Restricted Project. · View Herald TranscriptFeb 16 2020, 12:23 AM
Herald added a subscriber: cfe-commits. · View Herald Transcript

This change should be guarded by -fclang-abi-compat= so that users can opt to using the old ABI.

clang/lib/Sema/SemaDeclCXX.cpp
9200–9202

There is corresponding code in lib/AST/DeclCXX.cpp that attempts to determine whether special members are trivial "on the fly" (without performing overload resolution etc). Please check whether that needs to be updated too.

clang/test/CXX/class/class.union/p1.cpp
94–96

Do we still have test coverage for this somewhere? It'd generally be good to keep around the old tests but with updated diagnostic expectations.