ilya-biryukov wrote:

> w.r.t. ABI, I think the end state here would conceptually be most likely be 
> similar to __attribute__((diagnose_if(...))). Does that affect ABI?

I believe it does not as it only produces warnings. However, having an way to 
query the presence of attributes in the code would allow for things like 
overloading or template specializations based on lifetimes. Passing information 
to compiler from code seems fine, it's passing the information from compiler 
back to the code that gives me a pause:
```cpp
template <bool IsLifetimebound>
struct Foo {
  static void call() {
    if (IsLifetimebound)
      std::cerr << "I am being called from a function that passes 
temporaries\n";
  } 

  using type = std::conditional_t<IsLifetimebound, int, double>;
};

template <class T>
struct SomeClass {

  void some_method(const T& a [[clang::lifetimebound]]) {
    // Results of the program below in Clang and GCC are different.
    // Not sure if C++ standard is okay with this.
    using MyFoo = Foo<__is_lifetimebound(a)>;
    MyFoo::call();
    std::vector<MyFoo::type> vec;
    // ...
  } 
};
```

There are other ways to achieve that and there are attributes that may change 
behavior of the program and its meaning, so maybe some folks feel it is 
acceptable. I feel this is probably a bad idea and we should stick to the 
principle that attributes like lifetimebound can be safety removed without 
changing runtime semantics of the program.


> w.r.t. False positives due to annotating the entire pack -- that's a great 
> point. I think it's avoided by the noexcept approach. Any thoughts on that?

Noexcept and lifetimebound are quite orthogonal, so I am a little unsure about 
the particular proposal as is. However, I am also for avoiding duplication if 
possible. And given that the template function bodies have to be available 
anyway, we could maybe even utilize them (for function that don't have 
`noexcept`). I am thinking about some combination of two attributes (this gets 
complex really quickly, as you can see, looking for better ideas):

```cpp

// Can be taken from signature or body, e.g. from noexcept.
template<class ...Args>
void emplace_back(Args &&...args) 
[[clang::infered_fwd_lifetimebound_from_call]] 
noexcept(noexcept([[clang::infer_lifetimebound_from_here]] new 
T(std::forward(args)...))) {}

// Or from the body itself when there isn't noexcept
template<class ...Args>
void emplace_back(Args &&...args) [[clang::infered_lifetimebound_from_call]] {
  [[clang::infer_lifetimebound_from_here]] 
my_vector.push_back(T(std::forward(args)...)));
}

// Presumably we could also have some default inferences rules, e.g.
// - we infer lifetimebound from a single call either in noexcept or inside the 
body mentioning that argument.
// - if there's no such call or more than one mention of an argument, one has 
to mark the call with a special attribute.
// - std::forward/static_cast<T&&> is ignored somehow.
```


https://github.com/llvm/llvm-project/pull/125520
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to