https://gcc.gnu.org/bugzilla/show_bug.cgi?id=126233
Bug ID: 126233
Summary: source_location::current() in default template
argument produces garbage
Product: gcc
Version: 17.0
Status: UNCONFIRMED
Severity: normal
Priority: P3
Component: c++
Assignee: unassigned at gcc dot gnu.org
Reporter: ivan.lazaric.gcc at gmail dot com
Target Milestone: ---
```cpp
#include <format>
#include <source_location>
consteval bool check(std::source_location loc) {
__builtin_constexpr_diag(0, "", std::format("line: {}", loc.line()));
__builtin_constexpr_diag(0, "", std::format("function name: {}",
loc.function_name()));
return true;
}
template<auto S = check(std::source_location::current())>
void fn() {}
int main() { fn(); }
```
Flags: "-std=c++26 -O3"
Compiler output:
```
<source>: In substitution of 'template<auto S> void fn() [with auto S =
<missing>]':
<source>:13:16: required from here
13 | int main() { fn(); }
| ~~^~
<source>:10:24: in 'constexpr' expansion of
'check(std::source_location::current(__builtin_source_location()))'
10 | template<auto S = check(std::source_location::current())>
| ~~~~~^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
<source>:5:27: note: constexpr message: line: 10
5 | __builtin_constexpr_diag(0, "", std::format("line: {}", loc.line()));
| ~~~~~~~~~~~~~~~~~~~~~~~~^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
<source>:10:24: in 'constexpr' expansion of
'check(std::source_location::current(__builtin_source_location()))'
10 | template<auto S = check(std::source_location::current())>
| ~~~~~^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
<source>:6:27: note: constexpr message: function name: int main()
6 | __builtin_constexpr_diag(0, "", std::format("function name: {}",
loc.function_name()));
|
~~~~~~~~~~~~~~~~~~~~~~~~^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
```
Of note are the following two lines:
```
<source>:5:27: note: constexpr message: line: 10
<source>:6:27: note: constexpr message: function name: int main()
```
This makes no sense because `main()` does not cross line 10, it is fully in
line 13.
It seems `source_location::current()` created a mixed object,
with `line()` for the location of the default template argument,
and with `function_name()` for the location where we use the function template.
Noting this is unrelated to `__builtin_constexpr_diag()`, example without it:
```
#include <source_location>
#include <cassert>
#include <string_view>
consteval bool check(std::source_location loc) {
assert(loc.line() == 11); // outside of main
assert(std::string_view(loc.function_name()) == "int main()");
return true;
}
template<auto S = check(std::source_location::current())>
void fn() {}
int main() { fn(); }
```
Godbolt of first example: https://godbolt.org/z/65cYM4q1G
Godbolt of second example: https://godbolt.org/z/YWzaa4aoY