erichkeane wrote:

> > This is going to need tests on redeclarations, implicit instantiations, and 
> > specializations.
> 
> I'll add those if we agree to move forward with the general concept.
> 
> > Also, I wonder why this is applying to CXXRecordDecl rather than the 
> > primary template.
> 
> I'm not quite sure what you mean here.

See: 
`  let Subjects = SubjectList<[CXXRecord]>;`.  So this can attach to ANY record 
type, not just templates?  Why?

> 
> > I don't see any code to do instantiation, which is a pretty manual process, 
> > so that probably needs attending to.
> 
> I'm not quite sure what you're asking for. I've looked at `PreferredName`, 
> and that also doesn't handle any instantiations AFAICT.
> 

Right, many of our attributes work poorly for templates.  See our 
`instantiateAttrs` functions (IIRC?).  A lot are handled automatically, but 
something like this seems like it would need manual intervention, particularly 
with partial specializations.

> > As far as the value here, I'm on the fence here. I'd like to see much more 
> > justification here for this.
> 
> Do you have some idea of what sort of justification you'd like to see?

At the moment.. any :) 

> > I have to be honest, my initial impression is that we should not need this. 
> > I'd like to understand when you think the diags are insufficient today, and 
> > see if there is something to improve there.
> 
> The main motivation for this attribute isn't insufficient diagnostics, but 
> missing diagnostics due to some functions happening to not actually requiring 
> a complete type currently. The improved diagnostics are just a bonus.
> 
> Though, FWIW the diagnostic for this case:
> 
> ```c++
> #include <vector>
> 
> struct incomplete;
> 
> void func(std::vector<incomplete>& v) {
>   v.emplace_back();
> }
> ```
> 
> before (modified to contain only relative paths):
> 
> ```
> In file included from <source>:1:
> In file included from <vector>:314:
> In file included from <__vector/vector.h>:76:
> <__vector/layout.h>:425:40: error: arithmetic on a pointer to an incomplete 
> type 'incomplete'
>   425 |   return static_cast<size_type>(__end_ - __begin_);
>       |                                 ~~~~~~ ^
> <__vector/vector.h>:395:22: note: in instantiation of member function 
> 'std::__vector_layout<incomplete, std::allocator<incomplete>>::__size' 
> requested here
>   395 |     return __layout_.__size();
>       |                      ^
> <__vector/vector.h>:1081:7: note: in instantiation of member function 
> 'std::vector<incomplete>::size' requested here
>  1081 |       size() != capacity(),
>       |       ^
> <source>:6:5: note: in instantiation of function template specialization 
> 'std::vector<incomplete>::emplace_back<>' requested here
>     6 |   v.emplace_back();
>       |     ^
> <source>:3:8: note: forward declaration of 'incomplete'
>     3 | struct incomplete;
>       |        ^
> In file included from <source>:1:
> In file included from <vector>:314:
> In file included from <__vector/vector.h>:76:
> <__vector/layout.h>:431:45: error: arithmetic on a pointer to an incomplete 
> type 'incomplete'
>   431 |   return static_cast<size_type>(__capacity_ - __begin_);
>       |                                 ~~~~~~~~~~~ ^
> <__vector/vector.h>:398:22: note: in instantiation of member function 
> 'std::__vector_layout<incomplete, std::allocator<incomplete>>::__capacity' 
> requested here
>   398 |     return __layout_.__capacity();
>       |                      ^
> <__vector/vector.h>:1081:17: note: in instantiation of member function 
> 'std::vector<incomplete>::capacity' requested here
>  1081 |       size() != capacity(),
>       |                 ^
> <source>:6:5: note: in instantiation of function template specialization 
> 'std::vector<incomplete>::emplace_back<>' requested here
>     6 |   v.emplace_back();
>       |     ^
> <source>:3:8: note: forward declaration of 'incomplete'
>     3 | struct incomplete;
>       |        ^
> In file included from <source>:1:
> In file included from <vector>:314:
> <__vector/vector.h>:754:75: error: arithmetic on a pointer to an incomplete 
> type 'incomplete'
>   754 |         : __v_(__v), __pos_(__v.__layout_.__end_ptr()), 
> __new_end_(__pos_ + __n) {
>       |                                                                    
> ~~~~~~ ^
> <__vector/vector.h>:475:27: note: in instantiation of member function 
> 'std::vector<incomplete>::_ConstructTransaction::_ConstructTransaction' 
> requested here
>   475 |     _ConstructTransaction __tx(*this, 1);
>       |                           ^
> <__vector/vector.h>:1083:9: note: in instantiation of function template 
> specialization 'std::vector<incomplete>::__emplace_back_assume_capacity<>' 
> requested here
>  1083 |         
> __emplace_back_assume_capacity(std::forward<_Args>(__args)...);
>       |         ^
> <__vector/vector.h>:1082:11: note: while substituting into a lambda 
> expression here
>  1082 |       [&] {
>       |           ^
> <source>:6:5: note: in instantiation of function template specialization 
> 'std::vector<incomplete>::emplace_back<>' requested here
>     6 |   v.emplace_back();
>       |     ^
> <source>:3:8: note: forward declaration of 'incomplete'
>     3 | struct incomplete;
>       |        ^
> In file included from <source>:1:
> In file included from <vector>:314:
> <__vector/vector.h>:733:69: error: arithmetic on a pointer to an incomplete 
> type 'const value_type' (aka 'const incomplete')
>   733 |     std::__annotate_contiguous_container<_Allocator>(data(), data() + 
> capacity(), __old_mid, __new_mid);
>       |                                                              ~~~~~~ ^
> <__vector/vector.h>:745:5: note: in instantiation of member function 
> 'std::vector<incomplete>::__annotate_contiguous_container' requested here
>   745 |     __annotate_contiguous_container(data() + size(), data() + size() 
> + __n);
>       |     ^
> <__vector/vector.h>:755:12: note: in instantiation of member function 
> 'std::vector<incomplete>::__annotate_increase' requested here
>   755 |       __v_.__annotate_increase(__n);
>       |            ^
> <__vector/vector.h>:475:27: note: in instantiation of member function 
> 'std::vector<incomplete>::_ConstructTransaction::_ConstructTransaction' 
> requested here
>   475 |     _ConstructTransaction __tx(*this, 1);
>       |                           ^
> <__vector/vector.h>:1083:9: note: in instantiation of function template 
> specialization 'std::vector<incomplete>::__emplace_back_assume_capacity<>' 
> requested here
>  1083 |         
> __emplace_back_assume_capacity(std::forward<_Args>(__args)...);
>       |         ^
> <__vector/vector.h>:1082:11: note: while substituting into a lambda 
> expression here
>  1082 |       [&] {
>       |           ^
> <source>:6:5: note: in instantiation of function template specialization 
> 'std::vector<incomplete>::emplace_back<>' requested here
>     6 |   v.emplace_back();
>       |     ^
> <source>:3:8: note: forward declaration of 'incomplete'
>     3 | struct incomplete;
>       |        ^
> In file included from <source>:1:
> In file included from <vector>:314:
> <__vector/vector.h>:745:44: error: arithmetic on a pointer to an incomplete 
> type 'const value_type' (aka 'const incomplete')
>   745 |     __annotate_contiguous_container(data() + size(), data() + size() 
> + __n);
>       |                                     ~~~~~~ ^
> <__vector/vector.h>:755:12: note: in instantiation of member function 
> 'std::vector<incomplete>::__annotate_increase' requested here
>   755 |       __v_.__annotate_increase(__n);
>       |            ^
> <__vector/vector.h>:475:27: note: in instantiation of member function 
> 'std::vector<incomplete>::_ConstructTransaction::_ConstructTransaction' 
> requested here
>   475 |     _ConstructTransaction __tx(*this, 1);
>       |                           ^
> <__vector/vector.h>:1083:9: note: in instantiation of function template 
> specialization 'std::vector<incomplete>::__emplace_back_assume_capacity<>' 
> requested here
>  1083 |         
> __emplace_back_assume_capacity(std::forward<_Args>(__args)...);
>       |         ^
> <__vector/vector.h>:1082:11: note: while substituting into a lambda 
> expression here
>  1082 |       [&] {
>       |           ^
> <source>:6:5: note: in instantiation of function template specialization 
> 'std::vector<incomplete>::emplace_back<>' requested here
>     6 |   v.emplace_back();
>       |     ^
> <source>:3:8: note: forward declaration of 'incomplete'
>     3 | struct incomplete;
>       |        ^
> In file included from <source>:1:
> In file included from <vector>:314:
> <__vector/vector.h>:761:43: error: arithmetic on a pointer to an incomplete 
> type 'const incomplete'
>   761 |         __v_.__annotate_shrink(__new_end_ - 
> __v_.__layout_.__begin_ptr());
>       |                                ~~~~~~~~~~ ^
> <__vector/vector.h>:475:27: note: in instantiation of member function 
> 'std::vector<incomplete>::_ConstructTransaction::~_ConstructTransaction' 
> requested here
>   475 |     _ConstructTransaction __tx(*this, 1);
>       |                           ^
> <__vector/vector.h>:1083:9: note: in instantiation of function template 
> specialization 'std::vector<incomplete>::__emplace_back_assume_capacity<>' 
> requested here
>  1083 |         
> __emplace_back_assume_capacity(std::forward<_Args>(__args)...);
>       |         ^
> <__vector/vector.h>:1082:11: note: while substituting into a lambda 
> expression here
>  1082 |       [&] {
>       |           ^
> <source>:6:5: note: in instantiation of function template specialization 
> 'std::vector<incomplete>::emplace_back<>' requested here
>     6 |   v.emplace_back();
>       |     ^
> <source>:3:8: note: forward declaration of 'incomplete'
>     3 | struct incomplete;
>       |        ^
> In file included from <source>:1:
> In file included from <vector>:314:
> In file included from <__vector/vector.h>:35:
> In file included from 
> /home/nikolas/source/llvm-project/libcxx/include/__memory/allocate_at_least.h:14:
> /home/nikolas/source/llvm-project/libcxx/include/__memory/allocator_traits.h:362:5:
>  error: no matching function for call to '__construct_at'
>   362 |     std::__construct_at(__p, std::forward<_Args>(__args)...);
>       |     ^~~~~~~~~~~~~~~~~~~
> <__vector/vector.h>:476:21: note: in instantiation of function template 
> specialization 
> 'std::allocator_traits<std::allocator<incomplete>>::construct<incomplete, 0>' 
> requested here
>   476 |     __alloc_traits::construct(
>       |                     ^
> <__vector/vector.h>:1083:9: note: in instantiation of function template 
> specialization 'std::vector<incomplete>::__emplace_back_assume_capacity<>' 
> requested here
>  1083 |         
> __emplace_back_assume_capacity(std::forward<_Args>(__args)...);
>       |         ^
> <__vector/vector.h>:1082:11: note: while substituting into a lambda 
> expression here
>  1082 |       [&] {
>       |           ^
> <source>:6:5: note: in instantiation of function template specialization 
> 'std::vector<incomplete>::emplace_back<>' requested here
>     6 |   v.emplace_back();
>       |     ^
> /home/nikolas/source/llvm-project/libcxx/include/__memory/construct_at.h:43:58:
>  note: candidate template ignored: substitution failure [with _Tp = 
> incomplete, _Args = <>]: allocation of incomplete type 'incomplete'
>    42 | template <class _Tp, class... _Args, class = 
> decltype(::new(std::declval<void*>()) _Tp(std::declval<_Args>()...))>
>       |                                                                       
>              ~~~
>    43 | _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 _Tp* 
> __construct_at(_Tp* __location, _Args&&... __args) {
>       |                                                          ^
> In file included from <source>:1:
> In file included from <vector>:314:
> <__vector/vector.h>:478:5: error: arithmetic on a pointer to an incomplete 
> type 'incomplete'
>   478 |     ++__tx.__pos_;
>       |     ^ ~~~~~~~~~~~
> <__vector/vector.h>:1083:9: note: in instantiation of function template 
> specialization 'std::vector<incomplete>::__emplace_back_assume_capacity<>' 
> requested here
>  1083 |         
> __emplace_back_assume_capacity(std::forward<_Args>(__args)...);
>       |         ^
> <__vector/vector.h>:1082:11: note: while substituting into a lambda 
> expression here
>  1082 |       [&] {
>       |           ^
> <source>:6:5: note: in instantiation of function template specialization 
> 'std::vector<incomplete>::emplace_back<>' requested here
>     6 |   v.emplace_back();
>       |     ^
> <source>:3:8: note: forward declaration of 'incomplete'
>     3 | struct incomplete;
>       |        ^
> In file included from <source>:1:
> In file included from <vector>:314:
> <__vector/vector.h>:1084:9: error: arithmetic on a pointer to an incomplete 
> type 'incomplete'
>  1084 |         ++__end;
>       |         ^ ~~~~~
> <__vector/vector.h>:1082:11: note: while substituting into a lambda 
> expression here
>  1082 |       [&] {
>       |           ^
> <source>:6:5: note: in instantiation of function template specialization 
> 'std::vector<incomplete>::emplace_back<>' requested here
>     6 |   v.emplace_back();
>       |     ^
> <source>:3:8: note: forward declaration of 'incomplete'
>     3 | struct incomplete;
>       |        ^
> In file included from <source>:1:
> In file included from <vector>:314:
> <__vector/vector.h>:817:62: error: invalid application of 'alignof' to an 
> incomplete type 'incomplete'
>   817 |       return static_cast<_Ptr>(__builtin_assume_aligned(__p, 
> _LIBCPP_ALIGNOF(decltype(*__p))));
>       |                                                              
> ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
> /home/nikolas/source/llvm-project/libcxx/include/__config:111:34: note: 
> expanded from macro '_LIBCPP_ALIGNOF'
>   111 | #    define _LIBCPP_ALIGNOF(...) alignof(__VA_ARGS__)
>       |                                  ^~~~~~~~~~~~~~~~~~~~
> <__vector/vector.h>:357:24: note: in instantiation of function template 
> specialization 
> 'std::vector<incomplete>::__add_alignment_assumption<incomplete *, 0>' 
> requested here
>   357 |     return 
> __make_iter(__add_alignment_assumption(__layout_.__end_ptr()));
>       |                        ^
> <__vector/vector.h>:443:12: note: in instantiation of member function 
> 'std::vector<incomplete>::end' requested here
>   443 |     return end()[-1];
>       |            ^
> <__vector/vector.h>:1090:10: note: in instantiation of member function 
> 'std::vector<incomplete>::back' requested here
>  1090 |   return back();
>       |          ^
> <source>:6:5: note: in instantiation of function template specialization 
> 'std::vector<incomplete>::emplace_back<>' requested here
>     6 |   v.emplace_back();
>       |     ^
> <source>:3:8: note: forward declaration of 'incomplete'
>     3 | struct incomplete;
>       |        ^
> In file included from <source>:1:
> In file included from <vector>:314:
> In file included from <__vector/vector.h>:33:
> /home/nikolas/source/llvm-project/libcxx/include/__iterator/wrap_iter.h:103:12:
>  error: subscript of pointer to incomplete type 'incomplete'
>   103 |     return __i_[__n];
>       |            ^~~~
> <__vector/vector.h>:443:12: note: in instantiation of member function 
> 'std::__wrap_iter<incomplete *>::operator[]' requested here
>   443 |     return end()[-1];
>       |            ^
> <__vector/vector.h>:1090:10: note: in instantiation of member function 
> 'std::vector<incomplete>::back' requested here
>  1090 |   return back();
>       |          ^
> <source>:6:5: note: in instantiation of function template specialization 
> 'std::vector<incomplete>::emplace_back<>' requested here
>     6 |   v.emplace_back();
>       |     ^
> <source>:3:8: note: forward declaration of 'incomplete'
>     3 | struct incomplete;
>       |        ^
> 11 errors generated.
> ```
> 
> and after:
> 
> ```
> <source>:6:5: error: 'incomplete' has to be complete when calling a member 
> function
>     6 |   v.emplace_back();
>       |     ^
> <source>:3:8: note: forward declaration of 'incomplete'
>     3 | struct incomplete;
>       |        ^
> ```
> 
> Looking at this, it would be nice to mention `std::vector<incomplete>`. IDK 
> how difficult that would be.

Is it more reasonable to have the bodies of the functions that matter start 
with a `static_assert` on the completeness of the type? 

https://github.com/llvm/llvm-project/pull/211231
_______________________________________________
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to