ilya-biryukov wrote:

In addition to the concerns raised above, I also wanted to highlight that as 
soon as we have the ability to inspect attributes (and I agree with 
@higher-performance that we want it to make this useful for cases like 
`emplace_back`) at compile time, we get into a slippery slope of allowing 
template instantiations based on that, i.e. leaking attributes into ABI, which 
seems to go against the design principles of those attributes.
And since lifetimebound analysis is best-effort and does not provide actual 
safety guarantees (has both false positives and false negatives), it'd be nice 
to ensure the design does not allow it to slip past the `lifetimebound` 
attributes themselves.

Summing up, I would actually propose to have a slightly weird version of the 
"getters" that would only be usable in those `lifetimebound` attrs themselves 
(combining suggestion from @higher-performance and this PR):

```cpp
// Terribly name for the attribute, could be better.
template<class... Args>
reference emplace_back(Args&&... args 
[[clang::lifetimebound_if_lifetimebound(*new 
T(std::forward<Args>(args)...)))]]);
```
if we want more conditions, we could additionally allow some conditional 
expressions:
```cpp
// Slightly confusing syntax, could definitely be better.
template<class... Args>
reference emplace_back(Args&&... args 
[[clang::lifetimebound_if_lifetimebound_and(*new 
T(std::forward<Args>(args)...)), std::is_reference_type_v(args))]]);
```

More generally, my call is to figure out how to not leak the results of this 
analysis to the outside world to avoid the Hyrum's law effect where we cannot 
change it.

I am also unsure about the granularity here. For `emplace_back`, what we 
probably want is to have `lifetimebound` only on parameters that are marked as 
lifetimebound in the constructor. However, in the proposed approach we end up 
marking additional parameters too. Would that result in more false positives?

See https://gcc.godbolt.org/z/boPeheMsK 
```cpp
#include <memory>

struct X {
  X(const int &a, [[clang::lifetimebound]] const int&b);
};

void foo() {
  int a = 1;
  X x(a, 2); // warning.
  X y(1, a); // no warning.

  // make_unique would have both warnings, right?
  // similarly, for emplace_back.
  auto px = std::make_unique<X>(a, 2);
  auto py = std::make_unique<X>(1, a);
}
```

Is there a way to avoid it?

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