dlj marked 2 inline comments as done.
dlj added inline comments.

================
Comment at: include/deque:1167-1168
     allocator_type& __a = __alloc();
-    for (iterator __i = begin(), __e = end(); __i != __e; ++__i)
-        __alloc_traits::destroy(__a, _VSTD::addressof(*__i));
+    for (iterator __i = begin(), __e = end(); __i.__ptr_ != __e.__ptr_; 
__i.operator++())
+        __alloc_traits::destroy(__a, _VSTD::addressof(__i.operator*()));
     size() = 0;
----------------
EricWF wrote:
> rsmith wrote:
> > The other changes all look like obvious improvements to me. This one is a 
> > little more subtle, but if we want types like `deque<Holder<Incomplete> *>` 
> > to be destructible, I think we need to do something equivalent to this.
> That's really yucky! I'm OK with this, but I really don't like it.
> 
> Fundamentally this can't work, at least not generically. When the allocator 
> produces a fancy pointer type, the operator lookups need to be performed 
> using ADL.
> 
> In this specific case, we control the iterator type, but this isn't always 
> true. for example like in `__split_buffer`, which uses the allocators pointer 
> type as an iterator.
> 
> @dlj I updated your test case to demonstrate the fancy-pointer problem: 
> https://gist.github.com/EricWF/b465fc475f55561ba972b6dd87e7e7ea
> 
> So I think we have a couple choices:
> 
> (1) Do nothing, since we can't universally support the behavior, so we 
> shouldn't attempt to support any form of this behavior.
> (2) Fix only the non-fancy pointer case (which is what this patch does).
> (3) Attempt to fix *all* cases, including the fancy-pointer ones. This won't 
> be possible, but perhaps certain containers can tolerate incomplete fancy 
> pointers?
> 
> Personally I'm leaning towards (1), since we can't claim to support the use 
> case, at least not universally. If we select (1) we should probably encode 
> the restriction formally in standardese.
> 
> 
So I think there are at least a couple of issues here, but first I want to get 
clarification on this point:

> Do nothing, since we can't universally support the behavior, so we shouldn't 
> attempt to support any form of this behavior.

To me, this sounds like it could be equivalent to the statement "someone might 
do a bad job of implementing type-erasure for fancy pointers, so we should 
never attempt to preserve type erasure of any pointers." Now, that statement 
seems tenuous //at best// (and a straw man on a slippery slope otherwise), so 
I'm guessing that's not quite what you meant. ;-)

That said, it does sort of make sense to ignore deque for now, so I'll drop it 
from the patch; but for other containers, I don't really see the argument.

As for #3: I'm able to make (most of) your gist pass for everything but 
deque... calls to _VSTD::__to_raw_pointer are enough to avoid ADL around 
operators, although a few other changes are needed, too. That probably makes 
sense to do as a follow-up.

As for deque in particular, I think there may just be some missing functions on 
the __deque_iterator, but it probably warrants a closer look before adding to 
the interface.


================
Comment at: include/memory:1349
         is_same<
-            decltype(__has_construct_test(declval<_Alloc>(),
-                                          declval<_Pointer>(),
-                                          declval<_Args>()...)),
+            decltype(_VSTD::__has_construct_test(declval<_Alloc>(),
+                                                 declval<_Pointer>(),
----------------
EricWF wrote:
> Quuxplusone wrote:
> > EricWF wrote:
> > > Wouldn't the `declval` calls also need qualification?
> > (Sorry I'm jumping in before I know the full backstory here.) I would 
> > expect that the "declval" call doesn't need qualification because its 
> > argument-list is empty. ADL doesn't apply to template arguments AFAIK.
> > (Test case proving it to myself: 
> > https://wandbox.org/permlink/i0YarAfjOYKOhLFP )
> > 
> > Now, IMHO, `__has_construct_test` also doesn't need guarding against ADL, 
> > because it contains a double underscore and is thus firmly in the library's 
> > namespace. If the user has declared an ADL-findable entity 
> > `my::__has_construct_test`, they're already in undefined behavior land and 
> > you don't need to uglify libc++'s code just to coddle such users.
> > 
> > And, IMO, to the extent that ADL *does* work on the old code here, that's a 
> > feature, not a bug. As the implementor of some weird fancy pointer or 
> > iterator type, I might *like* having the power to hook into libc++'s 
> > customization points here. Of course I wouldn't try to hook into 
> > `__has_construct_test`, but `__to_raw_pointer` feels more likely. (At my 
> > current low level of understanding, that is.)
> >  If the user has declared an ADL-findable entity my::__has_construct_test, 
> > they're already in undefined behavior land 
> 
> The problem isn't that it will find a `my::__has_construct_test`, but that 
> the simple act of looking requires completed types, otherwise an error is 
> generated. [Example](https://wandbox.org/permlink/KAgGXkGSjXTETKKw)
> 
>  
Hmm, no I don't think so... declval<_Alloc> is a "declaration of a function at 
block scope" (because it's a template specialization), so it does not 
participate in ADL.

I believe the difference with e.g. __has_construct_test is that the other calls 
name a function template, which is not specialized (and so isn't a function 
declaration) until it wins the ADL.

I'm a little bit hazy on exactly the semantics, though, so Richard can correct 
me if I've gotten it substantially wrong. :-)


================
Comment at: include/memory:1349
         is_same<
-            decltype(__has_construct_test(declval<_Alloc>(),
-                                          declval<_Pointer>(),
-                                          declval<_Args>()...)),
+            decltype(_VSTD::__has_construct_test(declval<_Alloc>(),
+                                                 declval<_Pointer>(),
----------------
dlj wrote:
> EricWF wrote:
> > Quuxplusone wrote:
> > > EricWF wrote:
> > > > Wouldn't the `declval` calls also need qualification?
> > > (Sorry I'm jumping in before I know the full backstory here.) I would 
> > > expect that the "declval" call doesn't need qualification because its 
> > > argument-list is empty. ADL doesn't apply to template arguments AFAIK.
> > > (Test case proving it to myself: 
> > > https://wandbox.org/permlink/i0YarAfjOYKOhLFP )
> > > 
> > > Now, IMHO, `__has_construct_test` also doesn't need guarding against ADL, 
> > > because it contains a double underscore and is thus firmly in the 
> > > library's namespace. If the user has declared an ADL-findable entity 
> > > `my::__has_construct_test`, they're already in undefined behavior land 
> > > and you don't need to uglify libc++'s code just to coddle such users.
> > > 
> > > And, IMO, to the extent that ADL *does* work on the old code here, that's 
> > > a feature, not a bug. As the implementor of some weird fancy pointer or 
> > > iterator type, I might *like* having the power to hook into libc++'s 
> > > customization points here. Of course I wouldn't try to hook into 
> > > `__has_construct_test`, but `__to_raw_pointer` feels more likely. (At my 
> > > current low level of understanding, that is.)
> > >  If the user has declared an ADL-findable entity 
> > > my::__has_construct_test, they're already in undefined behavior land 
> > 
> > The problem isn't that it will find a `my::__has_construct_test`, but that 
> > the simple act of looking requires completed types, otherwise an error is 
> > generated. [Example](https://wandbox.org/permlink/KAgGXkGSjXTETKKw)
> > 
> >  
> Hmm, no I don't think so... declval<_Alloc> is a "declaration of a function 
> at block scope" (because it's a template specialization), so it does not 
> participate in ADL.
> 
> I believe the difference with e.g. __has_construct_test is that the other 
> calls name a function template, which is not specialized (and so isn't a 
> function declaration) until it wins the ADL.
> 
> I'm a little bit hazy on exactly the semantics, though, so Richard can 
> correct me if I've gotten it substantially wrong. :-)
Double-underscore names don't actually change the lookup rules, so (as Eric 
points out) isn't really related to the issue I'm addressing here.

As for extension points... __to_raw_pointer is essentially a selector for the 
correct expression syntax to get the pointed-to node, somewhat analogous to how 
std::pointer_traits selects an "unwrapped" pointee type. (In this case, an 
"extension point" already exists: you can use a custom allocator with fancy 
pointers... have a look at Eric's comments in include/deque for a good example 
of how you might write one.)


https://reviews.llvm.org/D37538



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

Reply via email to