1 // RUN: %clang_cc1 -std=c++1z -fcxx-exceptions -fexceptions -verify %s
2 // expected-no-diagnostics
4 #define assert(...) ((__VA_ARGS__) ? ((void)0) : throw 42)
5 #define CURRENT_FROM_MACRO() SL::current()
6 #define FORWARD(...) __VA_ARGS__
12 namespace experimental
{
13 struct source_location
{
15 unsigned int __m_line
= 0;
16 unsigned int __m_col
= 0;
17 const char *__m_file
= nullptr;
18 const char *__m_func
= nullptr;
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
;
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
; }
39 } // namespace experimental
42 using SL
= std::experimental::source_location
;
44 #include "Inputs/source-location-file.h"
45 namespace SLF
= source_location_file
;
47 constexpr bool is_equal(const char *LHS
, const char *RHS
) {
48 while (*LHS
!= 0 && *RHS
!= 0) {
54 return *LHS
== 0 && *RHS
== 0;
58 constexpr T
identity(T t
) {
62 template <class T
, class U
>
68 template <class T
, class U
>
69 constexpr bool is_same
= false;
71 constexpr bool is_same
<T
, T
> = true;
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 *>);
80 static_assert(noexcept(__builtin_LINE()));
81 static_assert(noexcept(__builtin_COLUMN()));
82 static_assert(noexcept(__builtin_FILE()));
83 static_assert(noexcept(__builtin_FUNCTION()));
85 //===----------------------------------------------------------------------===//
87 //===----------------------------------------------------------------------===//
90 static_assert(SL::current().line() == __LINE__
);
91 static_assert(SL::current().line() == CURRENT_FROM_MACRO().line());
93 static constexpr SL GlobalS
= SL::current();
95 static_assert(GlobalS
.line() == __LINE__
- 2);
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;
105 SL
// Call expression starts here
112 static_assert(S2
.line() == ExpectLine
, "");
120 == __LINE__
- 1, "");
125 == __LINE__
- 2, "");
129 == __LINE__
- 2, "");
134 static_assert(test_line_fn());
136 static_assert(__builtin_LINE() == __LINE__
, "");
138 constexpr int baz() { return 101; }
140 constexpr int test_line_fn_simple(int z
= baz(), int x
= __builtin_LINE()) {
144 static_assert(test_line_fn_simple() == __LINE__
, "");
145 static_assert(test_line_fn_simple() == __LINE__
, "");
149 constexpr int operator()(int x
= __builtin_LINE()) const { return x
; }
151 constexpr CallExpr
get_call() { return CallExpr
{}; }
152 static_assert(get_call()() == __LINE__
, "");
155 constexpr bool test_line_fn_template(T Expect
, int L
= __builtin_LINE()) {
158 static_assert(test_line_fn_template(__LINE__
));
161 constexpr bool check(int expect
) const {
162 return info
.line() == expect
;
164 SL info
= SL::current();
165 InMemInit() = default;
166 constexpr InMemInit(int) {}
168 static_assert(InMemInit
{}.check(__LINE__
- 3), "");
169 static_assert(InMemInit
{42}.check(__LINE__
- 3), "");
171 template <class T
, class U
= SL
>
172 struct InMemInitTemplate
{
173 constexpr bool check(int expect
) const {
174 return info
.line() == expect
;
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())
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__
), "");
193 int y
= __builtin_LINE();
194 constexpr bool check(int expect
) const {
198 constexpr AggInit AI
{42};
199 static_assert(AI
.check(__LINE__
- 1), "");
201 template <class T
, class U
= SL
>
202 struct AggInitTemplate
{
203 constexpr bool check(int expect
) const {
204 return expect
== info
.line();
207 U info
= U::current();
210 template <class T
, class U
= SL
>
211 constexpr U
test_fn_template(T
, U u
= U::current()) {
214 void fn_template_tests() {
215 static_assert(test_fn_template(42).line() == __LINE__
, "");
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());
225 void method_template_tests() {
226 static_assert(TestMethodTemplate
{}.get(42).line() == __LINE__
, "");
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());
234 const int x4
= __builtin_LINE();
235 int x5
= __builtin_LINE();
237 const int InStaticInit::x3
= __builtin_LINE();
238 static_assert(InStaticInit::x1
== InStaticInit::LINE
+ 1, "");
239 static_assert(InStaticInit::x2
== InStaticInit::LINE
+ 2, "");
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
);
246 template void check_fn_template_param(int);
247 template void check_fn_template_param
<long, 42, 42>(long);
252 int x
= __builtin_LINE();
253 int y
= __builtin_LINE();
254 int z
= __builtin_LINE();
257 struct AggDer
: AggBase
{
260 static_assert(AggDer
{}.x
== 400, "");
264 int x
= __builtin_LINE();
268 ClassBase() = default;
269 constexpr ClassBase(int yy
, int zz
= __builtin_LINE())
272 struct ClassDer
: ClassBase
{
274 ClassDer() = default;
275 constexpr ClassDer(int yy
) : ClassBase(yy
) {}
276 constexpr ClassDer(int yy
, int zz
) : ClassBase(yy
, zz
) {}
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, "");
284 struct ClassAggDer
: AggBase
{
286 ClassAggDer() = default;
287 constexpr ClassAggDer(int, int x
= __builtin_LINE()) : AggBase
{x
} {}
289 static_assert(ClassAggDer
{}.x
== 100, "");
291 } // namespace test_line
293 //===----------------------------------------------------------------------===//
295 //===----------------------------------------------------------------------===//
297 namespace test_file
{
298 constexpr const char *test_file_simple(const char *__f
= __builtin_FILE()) {
301 void test_function() {
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__
), "");
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()), "");
310 static_assert(test_file_simple() != nullptr);
311 static_assert(!is_equal(test_file_simple(), "source_location.cpp"));
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__
), "");
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__
), "");
335 } // namespace test_file
337 //===----------------------------------------------------------------------===//
338 // __builtin_FUNCTION()
339 //===----------------------------------------------------------------------===//
341 namespace test_func
{
343 constexpr const char *test_func_simple(const char *__f
= __builtin_FUNCTION()) {
346 constexpr const char *get_function() {
349 constexpr bool test_function() {
350 return is_equal(__func__
, test_func_simple()) &&
351 !is_equal(get_function(), test_func_simple());
353 static_assert(test_function());
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()};
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__), "");
366 template void func_template_tests
<int>();
368 template <class = int, class T
= SL
>
370 T info
= T::current();
372 TestCtor() = default;
373 template <class U
= SL
>
374 constexpr TestCtor(int, U u
= U::current()) : ctor_info(u
) {}
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__
));
385 constexpr SL global_sl
= SL::current();
386 static_assert(is_equal(global_sl
.function(), ""));
388 } // namespace test_func
390 //===----------------------------------------------------------------------===//
391 // __builtin_COLUMN()
392 //===----------------------------------------------------------------------===//
394 namespace test_column
{
397 constexpr bool test_column_fn() {
398 constexpr SL S
= SL::current();
399 static_assert(S
.line() == (__LINE__
- 1), "");
400 constexpr int Indent
= 4;
402 // The start of the call expression to `current()` begins at the token `SL`
403 constexpr int ExpectCol
= Indent
+ 3;
406 SL
// Call expression starts here
413 static_assert(S2
.column() == ExpectCol
, "");
416 constexpr int ExpectCol
= 2;
418 __builtin_COLUMN
// Expect call expression to start here
420 static_assert(C
== ExpectCol
);
425 static_assert(test_column_fn());
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"));
430 int x
= __builtin_COLUMN();
431 TestClass() = default; /* indented to 3 spaces for testing */
432 constexpr TestClass(int, int o
= __builtin_COLUMN()) : x(o
) {}
434 struct TestAggClass
{
435 int x
= __builtin_COLUMN();
437 constexpr bool test_class() {
439 auto check
= [](int V
, const char* S
, int indent
= 4) {
440 assert(V
== (__builtin_strlen(S
) + indent
));
444 check(t
.x
, " T", 0); // Start of default constructor decl.
449 check(t1
.x
, "TestClass t"); // Start of variable being constructed.
453 check(t
.x
, "TestAggClass t { }");
456 TestAggClass t
= { };
457 check(t
.x
, "TestAggClass t = { }");
461 static_assert(test_class());
463 } // namespace test_column
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;
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
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
; }
489 int n
= __builtin_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();
501 #line 4300 "test_passed.cpp"
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(), ""));
513 constexpr bool test_in_func() {
514 #line 4400 "test_func_passed.cpp"
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"));
527 static_assert(test_in_func());
529 } // end namespace test_out_of_line_init
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
; }
538 unsigned l
= get_line();
539 const char *f
= get_file();
540 const char *func
= get_func();
542 #line 5200 "in_init.cpp"
543 constexpr InInit() {}
548 static_assert(II
.l
== 5200, "");
549 static_assert(is_equal(II
.f
, "in_init.cpp"));
550 static_assert(is_equal(II
.func
, "InInit"));
554 unsigned l
= get_line();
555 const char *f
= get_file();
556 const char *func
= get_func();
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
, ""));
564 } // namespace test_global_scope
566 namespace TestFuncInInit
{
567 #line 6000 "InitClass.cpp"
570 #line 6100 "InitCtor.cpp"
571 constexpr Init(SL info
= SL::current()) : info(info
) {}
573 #line 6200 "InitGlobal.cpp"
575 static_assert(I
.info
.line() == 6200);
576 static_assert(is_equal(I
.info
.file(), "InitGlobal.cpp"));
578 } // namespace TestFuncInInit
580 namespace TestConstexprContext
{
581 #line 7000 "TestConstexprContext.cpp"
582 constexpr const char* foo() { return __builtin_FILE(); }
584 constexpr const char* bar(const char* x
= foo()) { return x
; }
585 constexpr bool test() {
586 static_assert(is_equal(bar(), "TestConstexprContext.cpp"));
589 static_assert(test());