rjmccall added inline comments.

================
Comment at: docs/LanguageExtensions.rst:1096
+  equivalent to copying the underlying bytes and then dropping the source 
object
+  on the floor.
 * ``__is_destructible`` (MSVC 2013)
----------------
Quuxplusone wrote:
> @rjmccall wrote:
> > trivial_abi permits annotated types to be passed and returned in registers, 
> > which is ABI-breaking. Skimming the blog post, it looks like 
> > trivially_relocatable does not permit this — it merely signifies that 
> > destruction is a no-op after a move construction or assignment.
> 
> Not necessarily a "no-op"; my canonical example is a CopyOnlyCXX03SharedPtr 
> which increments a refcount on construction and decrements on destruction. 
> But move-construction plus destruction should "balance out" and result in no 
> observable side effects.
> 
> > This is usefully different in the design space, since it means you can 
> > safely add the attribute retroactively to e.g. std::unique_ptr, and other 
> > templates can then detect that std::unique_ptr is trivially-relocatable and 
> > optimize themselves to use memcpy or realloc or whatever it is that they 
> > want to do. So in that sense trivial_abi is a *stronger* attribute, not a 
> > *weaker* one: the property it determines ought to imply 
> > trivially_relocatable.
> 
> `trivial_abi` is an "orthogonal" attribute: you can have `trivial_abi` types 
> with non-trivial constructors and destructors, which can have observable side 
> effects. For example,
> ```
> struct [[clang::trivial_abi]] DestructionAnnouncer {
>     ~DestructionAnnouncer() { puts("hello!"); }
> };
> ```
> is `trivial_abi` (because of the annotation) yet not trivially relocatable, 
> because its "move plus destroy" operation has observable side effects.
> 
> > The only interesting question in the language design that I know of is what 
> > happens if you put the attribute on a template that's instantiated to 
> > contain a sub-object that is definitely not trivially relocatable / 
> > trivial-ABI. For trivial_abi, we decided that the attribute is simply 
> > ignored — it implicitly only applies to specializations where the attribute 
> > would be legal. I haven't dug into the design enough to know what 
> > trivially_relocatable decides in this situation, but the three basic 
> > options are:
> >
> > - the attribute always has effect and allows trivial relocation regardless 
> > of the subobject types; this is obviously unsafe, so it limits the safe 
> > applicability of the attribute to templates
> > - the attribute is ignored, like trivial_abi is
> > - the attribute is ill-formed, and you'll need to add a 
> > [[trivially_relocatable(bool)]] version to support templates
> 
> What happens is basically the first thing you said, except that I disagree 
> that it's "obviously unsafe." Right now, conditionally trivial relocation is 
> possible via template metaprogramming; see the libcxx patch at e.g.
> https://github.com/Quuxplusone/libcxx/commit/6524822c009e#diff-38adc80cec663f2f29c22e9ffc0de912
> Since the attribute is an opt-in mechanism, it makes perfect sense to me that 
> if you put it on a class (or class template), then it applies to the class, 
> without any further sanity-checking by the compiler. The compiler has no 
> reason to second-guess the programmer here.
> 
> However, there's one more interesting case. Suppose the programmer puts the 
> attribute on a class that isn't relocatable at all! (For example, the union 
> case @erichkeane mentioned, or a class type with a deleted destructor.) In 
> that case, this patch *does* give an error... *unless* the class was produced 
> by instantiating a template, in which case we *don't* give an error, because 
> it's not the template-writer's fault.
> https://p1144.godbolt.org/z/wSZPba
> trivial_abi is an "orthogonal" attribute: you can have trivial_abi types with 
> non-trivial constructors and destructors, which can have observable side 
> effects. 

Let me cut this conversation short.  `trivial_abi` is not such an old and 
widely-established attribute that we are unable to revise its definition.  I am 
comfortable making the same semantic guarantees for `trivial_abi` that you're 
making for `trivially_relocatable`, because I think it is in the language's 
interest for `trivial_abi` to be strictly stronger than `trivially_relocatable`.

> What happens is basically the first thing you said, except that I disagree 
> that it's "obviously unsafe." 

Under your semantics, the attribute is an unchecked assertion about all of a 
class's subobjects.  A class template which fails to correctly apply the 
template metaprogramming trick to all of its dependently-typed subobjects — 
which can be quite awkward because it creates an extra dimension of partial 
specialization, and which breaks ABI by adding extra template parameters — will 
be silently miscompiled to allow objects to be memcpy'ed when they're 
potentially not legal to memcpy.  That is a footgun, and it is indeed 
"obviously unsafe".

Now, it's fair to say that it's unsafe in a useful way: because the attribute 
isn't checked, you can wrap a type you don't control in a 
`trivially_relocatable` struct and thereby get the advantages of triviality on 
the wrapper.  The model used by `trivial_abi` doesn't allow that.  But I feel 
pretty strongly that that is not the right default behavior for the language.


Repository:
  rC Clang

https://reviews.llvm.org/D50119



_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to