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