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