Eric Fiselier | 708afb5 | 2019-05-16 21:04:15 +0000 | [diff] [blame] | 1 | // RUN: %clang_cc1 -std=c++1z -fcxx-exceptions -fexceptions -verify %s |
| 2 | // expected-no-diagnostics |
| 3 | |
| 4 | #define assert(...) ((__VA_ARGS__) ? ((void)0) : throw 42) |
| 5 | #define CURRENT_FROM_MACRO() SL::current() |
| 6 | #define FORWARD(...) __VA_ARGS__ |
| 7 | |
| 8 | template <unsigned> |
| 9 | struct Printer; |
| 10 | |
| 11 | namespace std { |
| 12 | namespace experimental { |
| 13 | struct source_location { |
| 14 | private: |
| 15 | unsigned int __m_line = 0; |
| 16 | unsigned int __m_col = 0; |
| 17 | const char *__m_file = nullptr; |
| 18 | const char *__m_func = nullptr; |
| 19 | public: |
| 20 | static constexpr source_location current( |
| 21 | const char *__file = __builtin_FILE(), |
| 22 | const char *__func = __builtin_FUNCTION(), |
| 23 | unsigned int __line = __builtin_LINE(), |
| 24 | unsigned int __col = __builtin_COLUMN()) noexcept { |
| 25 | source_location __loc; |
| 26 | __loc.__m_line = __line; |
| 27 | __loc.__m_col = __col; |
| 28 | __loc.__m_file = __file; |
| 29 | __loc.__m_func = __func; |
| 30 | return __loc; |
| 31 | } |
| 32 | constexpr source_location() = default; |
| 33 | constexpr source_location(source_location const &) = default; |
| 34 | constexpr unsigned int line() const noexcept { return __m_line; } |
| 35 | constexpr unsigned int column() const noexcept { return __m_col; } |
| 36 | constexpr const char *file() const noexcept { return __m_file; } |
| 37 | constexpr const char *function() const noexcept { return __m_func; } |
| 38 | }; |
| 39 | } // namespace experimental |
| 40 | } // namespace std |
| 41 | |
| 42 | using SL = std::experimental::source_location; |
| 43 | |
| 44 | #include "Inputs/source-location-file.h" |
| 45 | namespace SLF = source_location_file; |
| 46 | |
| 47 | constexpr bool is_equal(const char *LHS, const char *RHS) { |
| 48 | while (*LHS != 0 && *RHS != 0) { |
| 49 | if (*LHS != *RHS) |
| 50 | return false; |
| 51 | ++LHS; |
| 52 | ++RHS; |
| 53 | } |
| 54 | return *LHS == 0 && *RHS == 0; |
| 55 | } |
| 56 | |
| 57 | template <class T> |
| 58 | constexpr T identity(T t) { |
| 59 | return t; |
| 60 | } |
| 61 | |
| 62 | template <class T, class U> |
| 63 | struct Pair { |
| 64 | T first; |
| 65 | U second; |
| 66 | }; |
| 67 | |
| 68 | template <class T, class U> |
| 69 | constexpr bool is_same = false; |
| 70 | template <class T> |
| 71 | constexpr bool is_same<T, T> = true; |
| 72 | |
| 73 | // test types |
| 74 | static_assert(is_same<decltype(__builtin_LINE()), unsigned>); |
| 75 | static_assert(is_same<decltype(__builtin_COLUMN()), unsigned>); |
| 76 | static_assert(is_same<decltype(__builtin_FILE()), const char *>); |
| 77 | static_assert(is_same<decltype(__builtin_FUNCTION()), const char *>); |
| 78 | |
| 79 | // test noexcept |
| 80 | static_assert(noexcept(__builtin_LINE())); |
| 81 | static_assert(noexcept(__builtin_COLUMN())); |
| 82 | static_assert(noexcept(__builtin_FILE())); |
| 83 | static_assert(noexcept(__builtin_FUNCTION())); |
| 84 | |
| 85 | //===----------------------------------------------------------------------===// |
| 86 | // __builtin_LINE() |
| 87 | //===----------------------------------------------------------------------===// |
| 88 | |
| 89 | namespace test_line { |
| 90 | static_assert(SL::current().line() == __LINE__); |
| 91 | static_assert(SL::current().line() == CURRENT_FROM_MACRO().line()); |
| 92 | |
| 93 | static constexpr SL GlobalS = SL::current(); |
| 94 | |
| 95 | static_assert(GlobalS.line() == __LINE__ - 2); |
| 96 | |
| 97 | // clang-format off |
| 98 | constexpr bool test_line_fn() { |
| 99 | constexpr SL S = SL::current(); |
| 100 | static_assert(S.line() == (__LINE__ - 1), ""); |
| 101 | // The start of the call expression to `current()` begins at the token `SL` |
| 102 | constexpr int ExpectLine = __LINE__ + 3; |
| 103 | constexpr SL S2 |
| 104 | = |
| 105 | SL // Call expression starts here |
| 106 | :: |
| 107 | current |
| 108 | ( |
| 109 | |
| 110 | ) |
| 111 | ; |
| 112 | static_assert(S2.line() == ExpectLine, ""); |
| 113 | |
| 114 | static_assert( |
| 115 | FORWARD( |
| 116 | __builtin_LINE |
| 117 | ( |
| 118 | ) |
| 119 | ) |
| 120 | == __LINE__ - 1, ""); |
| 121 | static_assert(\ |
| 122 | \ |
| 123 | __builtin_LINE()\ |
| 124 | \ |
| 125 | == __LINE__ - 2, ""); |
| 126 | static_assert(\ |
| 127 | _\ |
| 128 | _builtin_LINE() |
| 129 | == __LINE__ - 2, ""); |
| 130 | |
| 131 | return true; |
| 132 | } |
| 133 | // clang-format on |
| 134 | static_assert(test_line_fn()); |
| 135 | |
| 136 | static_assert(__builtin_LINE() == __LINE__, ""); |
| 137 | |
| 138 | constexpr int baz() { return 101; } |
| 139 | |
| 140 | constexpr int test_line_fn_simple(int z = baz(), int x = __builtin_LINE()) { |
| 141 | return x; |
| 142 | } |
| 143 | void bar() { |
| 144 | static_assert(test_line_fn_simple() == __LINE__, ""); |
| 145 | static_assert(test_line_fn_simple() == __LINE__, ""); |
| 146 | } |
| 147 | |
| 148 | struct CallExpr { |
| 149 | constexpr int operator()(int x = __builtin_LINE()) const { return x; } |
| 150 | }; |
| 151 | constexpr CallExpr get_call() { return CallExpr{}; } |
| 152 | static_assert(get_call()() == __LINE__, ""); |
| 153 | |
| 154 | template <class T> |
| 155 | constexpr bool test_line_fn_template(T Expect, int L = __builtin_LINE()) { |
| 156 | return Expect == L; |
| 157 | } |
| 158 | static_assert(test_line_fn_template(__LINE__)); |
| 159 | |
| 160 | struct InMemInit { |
| 161 | constexpr bool check(int expect) const { |
| 162 | return info.line() == expect; |
| 163 | } |
| 164 | SL info = SL::current(); |
| 165 | InMemInit() = default; |
| 166 | constexpr InMemInit(int) {} |
| 167 | }; |
| 168 | static_assert(InMemInit{}.check(__LINE__ - 3), ""); |
| 169 | static_assert(InMemInit{42}.check(__LINE__ - 3), ""); |
| 170 | |
| 171 | template <class T, class U = SL> |
| 172 | struct InMemInitTemplate { |
| 173 | constexpr bool check(int expect) const { |
| 174 | return info.line() == expect; |
| 175 | } |
| 176 | U info = U::current(); |
| 177 | InMemInitTemplate() = default; |
| 178 | constexpr InMemInitTemplate(T) {} |
| 179 | constexpr InMemInitTemplate(T, T) : info(U::current()) {} |
| 180 | template <class V = U> constexpr InMemInitTemplate(T, T, T, V info = U::current()) |
| 181 | : info(info) {} |
| 182 | }; |
| 183 | void test_mem_init_template() { |
| 184 | constexpr int line_offset = 8; |
| 185 | static_assert(InMemInitTemplate<int>{}.check(__LINE__ - line_offset), ""); |
| 186 | static_assert(InMemInitTemplate<unsigned>{42}.check(__LINE__ - line_offset), ""); |
| 187 | static_assert(InMemInitTemplate<unsigned>{42, 42}.check(__LINE__ - line_offset), ""); |
| 188 | static_assert(InMemInitTemplate<unsigned>{42, 42, 42}.check(__LINE__), ""); |
| 189 | } |
| 190 | |
| 191 | struct AggInit { |
| 192 | int x; |
| 193 | int y = __builtin_LINE(); |
| 194 | constexpr bool check(int expect) const { |
| 195 | return y == expect; |
| 196 | } |
| 197 | }; |
| 198 | constexpr AggInit AI{42}; |
| 199 | static_assert(AI.check(__LINE__ - 1), ""); |
| 200 | |
| 201 | template <class T, class U = SL> |
| 202 | struct AggInitTemplate { |
| 203 | constexpr bool check(int expect) const { |
| 204 | return expect == info.line(); |
| 205 | } |
| 206 | T x; |
| 207 | U info = U::current(); |
| 208 | }; |
| 209 | |
| 210 | template <class T, class U = SL> |
| 211 | constexpr U test_fn_template(T, U u = U::current()) { |
| 212 | return u; |
| 213 | } |
| 214 | void fn_template_tests() { |
| 215 | static_assert(test_fn_template(42).line() == __LINE__, ""); |
| 216 | } |
| 217 | |
| 218 | struct TestMethodTemplate { |
| 219 | template <class T, class U = SL, class U2 = SL> |
| 220 | constexpr U get(T, U u = U::current(), U2 u2 = identity(U2::current())) const { |
| 221 | assert(u.line() == u2.line()); |
| 222 | return u; |
| 223 | } |
| 224 | }; |
| 225 | void method_template_tests() { |
| 226 | static_assert(TestMethodTemplate{}.get(42).line() == __LINE__, ""); |
| 227 | } |
| 228 | |
| 229 | struct InStaticInit { |
| 230 | static constexpr int LINE = __LINE__; |
| 231 | static constexpr const int x1 = __builtin_LINE(); |
| 232 | static constexpr const int x2 = identity(__builtin_LINE()); |
| 233 | static const int x3; |
| 234 | const int x4 = __builtin_LINE(); |
| 235 | int x5 = __builtin_LINE(); |
| 236 | }; |
| 237 | const int InStaticInit::x3 = __builtin_LINE(); |
| 238 | static_assert(InStaticInit::x1 == InStaticInit::LINE + 1, ""); |
| 239 | static_assert(InStaticInit::x2 == InStaticInit::LINE + 2, ""); |
| 240 | |
| 241 | template <class T, int N = __builtin_LINE(), int Expect = -1> |
| 242 | constexpr void check_fn_template_param(T) { |
| 243 | constexpr int RealExpect = Expect == -1 ? __LINE__ - 2 : Expect; |
| 244 | static_assert(N == RealExpect); |
| 245 | } |
| 246 | template void check_fn_template_param(int); |
| 247 | template void check_fn_template_param<long, 42, 42>(long); |
| 248 | |
| 249 | #line 100 |
| 250 | struct AggBase { |
| 251 | #line 200 |
| 252 | int x = __builtin_LINE(); |
| 253 | int y = __builtin_LINE(); |
| 254 | int z = __builtin_LINE(); |
| 255 | }; |
| 256 | #line 300 |
| 257 | struct AggDer : AggBase { |
| 258 | }; |
| 259 | #line 400 |
| 260 | static_assert(AggDer{}.x == 400, ""); |
| 261 | |
| 262 | struct ClassBase { |
| 263 | #line 400 |
| 264 | int x = __builtin_LINE(); |
| 265 | int y = 0; |
| 266 | int z = 0; |
| 267 | #line 500 |
| 268 | ClassBase() = default; |
| 269 | constexpr ClassBase(int yy, int zz = __builtin_LINE()) |
| 270 | : y(yy), z(zz) {} |
| 271 | }; |
| 272 | struct ClassDer : ClassBase { |
| 273 | #line 600 |
| 274 | ClassDer() = default; |
| 275 | constexpr ClassDer(int yy) : ClassBase(yy) {} |
| 276 | constexpr ClassDer(int yy, int zz) : ClassBase(yy, zz) {} |
| 277 | }; |
| 278 | #line 700 |
| 279 | static_assert(ClassDer{}.x == 500, ""); |
| 280 | static_assert(ClassDer{42}.x == 501, ""); |
| 281 | static_assert(ClassDer{42}.z == 601, ""); |
| 282 | static_assert(ClassDer{42, 42}.x == 501, ""); |
| 283 | |
| 284 | struct ClassAggDer : AggBase { |
| 285 | #line 800 |
| 286 | ClassAggDer() = default; |
| 287 | constexpr ClassAggDer(int, int x = __builtin_LINE()) : AggBase{x} {} |
| 288 | }; |
| 289 | static_assert(ClassAggDer{}.x == 100, ""); |
| 290 | |
| 291 | } // namespace test_line |
| 292 | |
| 293 | //===----------------------------------------------------------------------===// |
| 294 | // __builtin_FILE() |
| 295 | //===----------------------------------------------------------------------===// |
| 296 | |
| 297 | namespace test_file { |
| 298 | constexpr const char *test_file_simple(const char *__f = __builtin_FILE()) { |
| 299 | return __f; |
| 300 | } |
| 301 | void test_function() { |
| 302 | #line 900 |
| 303 | static_assert(is_equal(test_file_simple(), __FILE__)); |
| 304 | static_assert(is_equal(SLF::test_function().file(), __FILE__), ""); |
| 305 | static_assert(is_equal(SLF::test_function_template(42).file(), __FILE__), ""); |
| 306 | |
| 307 | static_assert(is_equal(SLF::test_function_indirect().file(), SLF::global_info.file()), ""); |
| 308 | static_assert(is_equal(SLF::test_function_template_indirect(42).file(), SLF::global_info.file()), ""); |
| 309 | |
| 310 | static_assert(test_file_simple() != nullptr); |
| 311 | static_assert(!is_equal(test_file_simple(), "source_location.cpp")); |
| 312 | } |
| 313 | |
| 314 | void test_class() { |
| 315 | #line 315 |
| 316 | using SLF::TestClass; |
| 317 | constexpr TestClass Default; |
| 318 | constexpr TestClass InParam{42}; |
| 319 | constexpr TestClass Template{42, 42}; |
| 320 | constexpr auto *F = Default.info.file(); |
| 321 | constexpr auto Char = F[0]; |
| 322 | static_assert(is_equal(Default.info.file(), SLF::FILE), ""); |
| 323 | static_assert(is_equal(InParam.info.file(), SLF::FILE), ""); |
| 324 | static_assert(is_equal(InParam.ctor_info.file(), __FILE__), ""); |
| 325 | } |
| 326 | |
| 327 | void test_aggr_class() { |
| 328 | using Agg = SLF::AggrClass<>; |
| 329 | constexpr Agg Default{}; |
| 330 | constexpr Agg InitOne{42}; |
| 331 | static_assert(is_equal(Default.init_info.file(), __FILE__), ""); |
| 332 | static_assert(is_equal(InitOne.init_info.file(), __FILE__), ""); |
| 333 | } |
| 334 | |
| 335 | } // namespace test_file |
| 336 | |
| 337 | //===----------------------------------------------------------------------===// |
| 338 | // __builtin_FUNCTION() |
| 339 | //===----------------------------------------------------------------------===// |
| 340 | |
| 341 | namespace test_func { |
| 342 | |
| 343 | constexpr const char *test_func_simple(const char *__f = __builtin_FUNCTION()) { |
| 344 | return __f; |
| 345 | } |
| 346 | constexpr const char *get_function() { |
| 347 | return __func__; |
| 348 | } |
| 349 | constexpr bool test_function() { |
| 350 | return is_equal(__func__, test_func_simple()) && |
| 351 | !is_equal(get_function(), test_func_simple()); |
| 352 | } |
| 353 | static_assert(test_function()); |
| 354 | |
| 355 | template <class T, class U = SL> |
| 356 | constexpr Pair<U, U> test_func_template(T, U u = U::current()) { |
| 357 | static_assert(is_equal(__func__, U::current().function())); |
| 358 | return {u, U::current()}; |
| 359 | } |
| 360 | template <class T> |
| 361 | void func_template_tests() { |
| 362 | constexpr auto P = test_func_template(42); |
| 363 | //static_assert(is_equal(P.first.function(), __func__), ""); |
| 364 | //static_assert(!is_equal(P.second.function(), __func__), ""); |
| 365 | } |
| 366 | template void func_template_tests<int>(); |
| 367 | |
| 368 | template <class = int, class T = SL> |
| 369 | struct TestCtor { |
| 370 | T info = T::current(); |
| 371 | T ctor_info; |
| 372 | TestCtor() = default; |
| 373 | template <class U = SL> |
| 374 | constexpr TestCtor(int, U u = U::current()) : ctor_info(u) {} |
| 375 | }; |
| 376 | void ctor_tests() { |
| 377 | constexpr TestCtor<> Default; |
| 378 | constexpr TestCtor<> Template{42}; |
| 379 | static_assert(!is_equal(Default.info.function(), __func__)); |
| 380 | static_assert(is_equal(Default.info.function(), "TestCtor")); |
| 381 | static_assert(is_equal(Template.info.function(), "TestCtor")); |
| 382 | static_assert(is_equal(Template.ctor_info.function(), __func__)); |
| 383 | } |
| 384 | |
| 385 | constexpr SL global_sl = SL::current(); |
| 386 | static_assert(is_equal(global_sl.function(), "")); |
| 387 | |
| 388 | } // namespace test_func |
| 389 | |
| 390 | //===----------------------------------------------------------------------===// |
| 391 | // __builtin_COLUMN() |
| 392 | //===----------------------------------------------------------------------===// |
| 393 | |
| 394 | namespace test_column { |
| 395 | |
| 396 | // clang-format off |
| 397 | constexpr bool test_column_fn() { |
| 398 | constexpr SL S = SL::current(); |
| 399 | static_assert(S.line() == (__LINE__ - 1), ""); |
| 400 | constexpr int Indent = 4; |
| 401 | { |
| 402 | // The start of the call expression to `current()` begins at the token `SL` |
| 403 | constexpr int ExpectCol = Indent + 3; |
| 404 | constexpr SL S2 |
| 405 | = |
| 406 | SL // Call expression starts here |
| 407 | :: |
| 408 | current |
| 409 | ( |
| 410 | |
| 411 | ) |
| 412 | ; |
| 413 | static_assert(S2.column() == ExpectCol, ""); |
| 414 | } |
| 415 | { |
| 416 | constexpr int ExpectCol = 2; |
| 417 | constexpr int C = |
| 418 | __builtin_COLUMN // Expect call expression to start here |
| 419 | (); |
| 420 | static_assert(C == ExpectCol); |
| 421 | } |
| 422 | return true; |
| 423 | } |
| 424 | #line 420 |
| 425 | static_assert(test_column_fn()); |
| 426 | |
| 427 | // Test that the column matches the start of the call expression 'SL::current()' |
| 428 | static_assert(SL::current().column() == __builtin_strlen("static_assert(S")); |
| 429 | struct TestClass { |
| 430 | int x = __builtin_COLUMN(); |
| 431 | TestClass() = default; /* indented to 3 spaces for testing */ |
| 432 | constexpr TestClass(int, int o = __builtin_COLUMN()) : x(o) {} |
| 433 | }; |
| 434 | struct TestAggClass { |
| 435 | int x = __builtin_COLUMN(); |
| 436 | }; |
| 437 | constexpr bool test_class() { |
| 438 | |
| 439 | auto check = [](int V, const char* S, int indent = 4) { |
| 440 | assert(V == (__builtin_strlen(S) + indent)); |
| 441 | }; |
| 442 | { |
| 443 | TestClass t{}; |
| 444 | check(t.x, " T", 0); // Start of default constructor decl. |
| 445 | } |
| 446 | { |
| 447 | TestClass t1 |
| 448 | {42}; |
| 449 | check(t1.x, "TestClass t"); // Start of variable being constructed. |
| 450 | } |
| 451 | { |
| 452 | TestAggClass t { }; |
| 453 | check(t.x, "TestAggClass t { }"); |
| 454 | } |
| 455 | { |
| 456 | TestAggClass t = { }; |
| 457 | check(t.x, "TestAggClass t = { }"); |
| 458 | } |
| 459 | return true; |
| 460 | } |
| 461 | static_assert(test_class()); |
| 462 | // clang-format on |
| 463 | } // namespace test_column |
| 464 | |
| 465 | // Test [reflection.src_loc.creation]p2 |
| 466 | // > The value should be affected by #line (C++14 16.4) in the same manner as |
| 467 | // > for __LINE__ and __FILE__. |
| 468 | namespace test_pragma_line { |
| 469 | constexpr int StartLine = 42; |
| 470 | #line 42 |
| 471 | static_assert(__builtin_LINE() == StartLine); |
| 472 | static_assert(__builtin_LINE() == StartLine + 1); |
| 473 | static_assert(SL::current().line() == StartLine + 2); |
| 474 | #line 44 "test_file.c" |
| 475 | static_assert(is_equal("test_file.c", __FILE__)); |
| 476 | static_assert(is_equal("test_file.c", __builtin_FILE())); |
| 477 | static_assert(is_equal("test_file.c", SL::current().file())); |
| 478 | static_assert(is_equal("test_file.c", SLF::test_function().file())); |
| 479 | static_assert(is_equal(SLF::FILE, SLF::test_function_indirect().file())); |
| 480 | } // end namespace test_pragma_line |
| 481 | |
| 482 | namespace test_out_of_line_init { |
| 483 | #line 4000 "test_out_of_line_init.cpp" |
| 484 | constexpr unsigned get_line(unsigned n = __builtin_LINE()) { return n; } |
| 485 | constexpr const char *get_file(const char *f = __builtin_FILE()) { return f; } |
| 486 | constexpr const char *get_func(const char *f = __builtin_FUNCTION()) { return f; } |
| 487 | #line 4100 "A.cpp" |
| 488 | struct A { |
| 489 | int n = __builtin_LINE(); |
| 490 | int n2 = get_line(); |
| 491 | const char *f = __builtin_FILE(); |
| 492 | const char *f2 = get_file(); |
| 493 | const char *func = __builtin_FUNCTION(); |
| 494 | const char *func2 = get_func(); |
| 495 | SL info = SL::current(); |
| 496 | }; |
| 497 | #line 4200 "B.cpp" |
| 498 | struct B { |
| 499 | A a = {}; |
| 500 | }; |
| 501 | #line 4300 "test_passed.cpp" |
| 502 | constexpr B b = {}; |
| 503 | static_assert(b.a.n == 4300, ""); |
| 504 | static_assert(b.a.n2 == 4300, ""); |
| 505 | static_assert(b.a.info.line() == 4300, ""); |
| 506 | static_assert(is_equal(b.a.f, "test_passed.cpp")); |
| 507 | static_assert(is_equal(b.a.f2, "test_passed.cpp")); |
| 508 | static_assert(is_equal(b.a.info.file(), "test_passed.cpp")); |
| 509 | static_assert(is_equal(b.a.func, "")); |
| 510 | static_assert(is_equal(b.a.func2, "")); |
| 511 | static_assert(is_equal(b.a.info.function(), "")); |
| 512 | |
| 513 | constexpr bool test_in_func() { |
| 514 | #line 4400 "test_func_passed.cpp" |
| 515 | constexpr B b = {}; |
| 516 | static_assert(b.a.n == 4400, ""); |
| 517 | static_assert(b.a.n2 == 4400, ""); |
| 518 | static_assert(b.a.info.line() == 4400, ""); |
| 519 | static_assert(is_equal(b.a.f, "test_func_passed.cpp")); |
| 520 | static_assert(is_equal(b.a.f2, "test_func_passed.cpp")); |
| 521 | static_assert(is_equal(b.a.info.file(), "test_func_passed.cpp")); |
| 522 | static_assert(is_equal(b.a.func, "test_in_func")); |
| 523 | static_assert(is_equal(b.a.func2, "test_in_func")); |
| 524 | static_assert(is_equal(b.a.info.function(), "test_in_func")); |
| 525 | return true; |
| 526 | } |
| 527 | static_assert(test_in_func()); |
| 528 | |
| 529 | } // end namespace test_out_of_line_init |
| 530 | |
| 531 | namespace test_global_scope { |
| 532 | #line 5000 "test_global_scope.cpp" |
| 533 | constexpr unsigned get_line(unsigned n = __builtin_LINE()) { return n; } |
| 534 | constexpr const char *get_file(const char *f = __builtin_FILE()) { return f; } |
| 535 | constexpr const char *get_func(const char *f = __builtin_FUNCTION()) { return f; } |
| 536 | #line 5100 |
| 537 | struct InInit { |
| 538 | unsigned l = get_line(); |
| 539 | const char *f = get_file(); |
| 540 | const char *func = get_func(); |
| 541 | |
| 542 | #line 5200 "in_init.cpp" |
| 543 | constexpr InInit() {} |
| 544 | }; |
| 545 | #line 5300 |
| 546 | constexpr InInit II; |
| 547 | |
| 548 | static_assert(II.l == 5200, ""); |
| 549 | static_assert(is_equal(II.f, "in_init.cpp")); |
| 550 | static_assert(is_equal(II.func, "InInit")); |
| 551 | |
| 552 | #line 5400 |
| 553 | struct AggInit { |
| 554 | unsigned l = get_line(); |
| 555 | const char *f = get_file(); |
| 556 | const char *func = get_func(); |
| 557 | }; |
| 558 | #line 5500 "brace_init.cpp" |
| 559 | constexpr AggInit AI = {}; |
| 560 | static_assert(AI.l == 5500); |
| 561 | static_assert(is_equal(AI.f, "brace_init.cpp")); |
| 562 | static_assert(is_equal(AI.func, "")); |
| 563 | |
| 564 | } // namespace test_global_scope |
| 565 | |
| 566 | namespace TestFuncInInit { |
| 567 | #line 6000 "InitClass.cpp" |
| 568 | struct Init { |
| 569 | SL info; |
| 570 | #line 6100 "InitCtor.cpp" |
| 571 | constexpr Init(SL info = SL::current()) : info(info) {} |
| 572 | }; |
| 573 | #line 6200 "InitGlobal.cpp" |
| 574 | constexpr Init I; |
| 575 | static_assert(I.info.line() == 6200); |
| 576 | static_assert(is_equal(I.info.file(), "InitGlobal.cpp")); |
| 577 | |
| 578 | } // namespace TestFuncInInit |
| 579 | |
| 580 | namespace TestConstexprContext { |
| 581 | #line 7000 "TestConstexprContext.cpp" |
| 582 | constexpr const char* foo() { return __builtin_FILE(); } |
| 583 | #line 7100 "Bar.cpp" |
| 584 | constexpr const char* bar(const char* x = foo()) { return x; } |
| 585 | constexpr bool test() { |
| 586 | static_assert(is_equal(bar(), "TestConstexprContext.cpp")); |
| 587 | return true; |
| 588 | } |
| 589 | static_assert(test()); |
| 590 | } |