| Issue |
165182
|
| Summary |
[Clang] Lifetime extension of temporaries in for-range-initializers is not applied in templates
|
| Labels |
clang:frontend,
c++23
|
| Assignees |
|
| Reporter |
Sirraide
|
This is based on the example in [[stmt.ranged]](https://eel.is/c++draft/stmt.ranged#example-2):
```c++
const char* s = "1";
struct Foo {
int& x;
Foo(int& x) noexcept : x{x} {}
~Foo() noexcept { x = 42; }
const char* begin() const noexcept { return s; }
const char* end() const noexcept { return s + 1; }
};
const Foo& f1(const Foo& t) noexcept { return t; }
Foo g(int& x) noexcept { return Foo(x); }
// Lifetime extension is missing!
template <typename T>
int test1() {
int x = 5;
int sum = 0;
for (int _ : f1(g(x))) sum += x; // 'x' should still be 5 here
sum += x; // 'x' set to 42 by the destructor of 'g(x)'
return sum; // should be 47
}
```
According to my understanding of this, we should be applying lifetime extension to `g(x)` here in `test1()`, but we don't. GCC seems to agree with me, because this function returns `47` when compiled with GCC, but `84` when compiled with Clang (yes, I did make sure to enable lifetime extension by passing `-std=c++23`). MSVC w/ `/std:c++latest` also returns `84`.
If we remove the template-head from `test1()`, then we suddenly get `47` again: https://clang.godbolt.org/z/jEYsE6fbb.
It seems that we’re forgetting about the lifetime extension at some point during template instantiation; compare the AST node before
```console
MaterializeTemporaryExpr 0x29052c50 <col:21, col:24> 'const Foo' lvalue extended by Var 0x29052d98 '__range1' 'const Foo &'
```
and after instantiation:
```console
MaterializeTemporaryExpr 0x29057b90 <col:21, col:24> 'const Foo' lvalue
```
_______________________________________________
llvm-bugs mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-bugs