blob: b312f12d428f5f4a17327d3329b0ce3eb51dc4b4 [file] [log] [blame]
Eric Fiselier708afb52019-05-16 21:04:15 +00001// 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
8template <unsigned>
9struct Printer;
10
11namespace std {
12namespace experimental {
13struct source_location {
14private:
15 unsigned int __m_line = 0;
16 unsigned int __m_col = 0;
17 const char *__m_file = nullptr;
18 const char *__m_func = nullptr;
19public:
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
42using SL = std::experimental::source_location;
43
44#include "Inputs/source-location-file.h"
45namespace SLF = source_location_file;
46
47constexpr 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
57template <class T>
58constexpr T identity(T t) {
59 return t;
60}
61
62template <class T, class U>
63struct Pair {
64 T first;
65 U second;
66};
67
68template <class T, class U>
69constexpr bool is_same = false;
70template <class T>
71constexpr bool is_same<T, T> = true;
72
73// test types
74static_assert(is_same<decltype(__builtin_LINE()), unsigned>);
75static_assert(is_same<decltype(__builtin_COLUMN()), unsigned>);
76static_assert(is_same<decltype(__builtin_FILE()), const char *>);
77static_assert(is_same<decltype(__builtin_FUNCTION()), const char *>);
78
79// test noexcept
80static_assert(noexcept(__builtin_LINE()));
81static_assert(noexcept(__builtin_COLUMN()));
82static_assert(noexcept(__builtin_FILE()));
83static_assert(noexcept(__builtin_FUNCTION()));
84
85//===----------------------------------------------------------------------===//
86// __builtin_LINE()
87//===----------------------------------------------------------------------===//
88
89namespace test_line {
90static_assert(SL::current().line() == __LINE__);
91static_assert(SL::current().line() == CURRENT_FROM_MACRO().line());
92
93static constexpr SL GlobalS = SL::current();
94
95static_assert(GlobalS.line() == __LINE__ - 2);
96
97// clang-format off
98constexpr 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
134static_assert(test_line_fn());
135
136static_assert(__builtin_LINE() == __LINE__, "");
137
138constexpr int baz() { return 101; }
139
140constexpr int test_line_fn_simple(int z = baz(), int x = __builtin_LINE()) {
141 return x;
142}
143void bar() {
144 static_assert(test_line_fn_simple() == __LINE__, "");
145 static_assert(test_line_fn_simple() == __LINE__, "");
146}
147
148struct CallExpr {
149 constexpr int operator()(int x = __builtin_LINE()) const { return x; }
150};
151constexpr CallExpr get_call() { return CallExpr{}; }
152static_assert(get_call()() == __LINE__, "");
153
154template <class T>
155constexpr bool test_line_fn_template(T Expect, int L = __builtin_LINE()) {
156 return Expect == L;
157}
158static_assert(test_line_fn_template(__LINE__));
159
160struct 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};
168static_assert(InMemInit{}.check(__LINE__ - 3), "");
169static_assert(InMemInit{42}.check(__LINE__ - 3), "");
170
171template <class T, class U = SL>
172struct 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};
183void 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
191struct AggInit {
192 int x;
193 int y = __builtin_LINE();
194 constexpr bool check(int expect) const {
195 return y == expect;
196 }
197};
198constexpr AggInit AI{42};
199static_assert(AI.check(__LINE__ - 1), "");
200
201template <class T, class U = SL>
202struct AggInitTemplate {
203 constexpr bool check(int expect) const {
204 return expect == info.line();
205 }
206 T x;
207 U info = U::current();
208};
209
210template <class T, class U = SL>
211constexpr U test_fn_template(T, U u = U::current()) {
212 return u;
213}
214void fn_template_tests() {
215 static_assert(test_fn_template(42).line() == __LINE__, "");
216}
217
218struct 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};
225void method_template_tests() {
226 static_assert(TestMethodTemplate{}.get(42).line() == __LINE__, "");
227}
228
229struct 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};
237const int InStaticInit::x3 = __builtin_LINE();
238static_assert(InStaticInit::x1 == InStaticInit::LINE + 1, "");
239static_assert(InStaticInit::x2 == InStaticInit::LINE + 2, "");
240
241template <class T, int N = __builtin_LINE(), int Expect = -1>
242constexpr void check_fn_template_param(T) {
243 constexpr int RealExpect = Expect == -1 ? __LINE__ - 2 : Expect;
244 static_assert(N == RealExpect);
245}
246template void check_fn_template_param(int);
247template void check_fn_template_param<long, 42, 42>(long);
248
249#line 100
250struct AggBase {
251#line 200
252 int x = __builtin_LINE();
253 int y = __builtin_LINE();
254 int z = __builtin_LINE();
255};
256#line 300
257struct AggDer : AggBase {
258};
259#line 400
260static_assert(AggDer{}.x == 400, "");
261
262struct 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};
272struct 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
279static_assert(ClassDer{}.x == 500, "");
280static_assert(ClassDer{42}.x == 501, "");
281static_assert(ClassDer{42}.z == 601, "");
282static_assert(ClassDer{42, 42}.x == 501, "");
283
284struct ClassAggDer : AggBase {
285#line 800
286 ClassAggDer() = default;
287 constexpr ClassAggDer(int, int x = __builtin_LINE()) : AggBase{x} {}
288};
289static_assert(ClassAggDer{}.x == 100, "");
290
291} // namespace test_line
292
293//===----------------------------------------------------------------------===//
294// __builtin_FILE()
295//===----------------------------------------------------------------------===//
296
297namespace test_file {
298constexpr const char *test_file_simple(const char *__f = __builtin_FILE()) {
299 return __f;
300}
301void 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
314void 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
327void 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
341namespace test_func {
342
343constexpr const char *test_func_simple(const char *__f = __builtin_FUNCTION()) {
344 return __f;
345}
346constexpr const char *get_function() {
347 return __func__;
348}
349constexpr bool test_function() {
350 return is_equal(__func__, test_func_simple()) &&
351 !is_equal(get_function(), test_func_simple());
352}
353static_assert(test_function());
354
355template <class T, class U = SL>
356constexpr 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}
360template <class T>
361void 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}
366template void func_template_tests<int>();
367
368template <class = int, class T = SL>
369struct 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};
376void 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
385constexpr SL global_sl = SL::current();
386static_assert(is_equal(global_sl.function(), ""));
387
388} // namespace test_func
389
390//===----------------------------------------------------------------------===//
391// __builtin_COLUMN()
392//===----------------------------------------------------------------------===//
393
394namespace test_column {
395
396// clang-format off
397constexpr 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
425static_assert(test_column_fn());
426
427// Test that the column matches the start of the call expression 'SL::current()'
428static_assert(SL::current().column() == __builtin_strlen("static_assert(S"));
429struct 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};
434struct TestAggClass {
435 int x = __builtin_COLUMN();
436};
437constexpr 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}
461static_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__.
468namespace test_pragma_line {
469constexpr int StartLine = 42;
470#line 42
471static_assert(__builtin_LINE() == StartLine);
472static_assert(__builtin_LINE() == StartLine + 1);
473static_assert(SL::current().line() == StartLine + 2);
474#line 44 "test_file.c"
475static_assert(is_equal("test_file.c", __FILE__));
476static_assert(is_equal("test_file.c", __builtin_FILE()));
477static_assert(is_equal("test_file.c", SL::current().file()));
478static_assert(is_equal("test_file.c", SLF::test_function().file()));
479static_assert(is_equal(SLF::FILE, SLF::test_function_indirect().file()));
480} // end namespace test_pragma_line
481
482namespace test_out_of_line_init {
483#line 4000 "test_out_of_line_init.cpp"
484constexpr unsigned get_line(unsigned n = __builtin_LINE()) { return n; }
485constexpr const char *get_file(const char *f = __builtin_FILE()) { return f; }
486constexpr const char *get_func(const char *f = __builtin_FUNCTION()) { return f; }
487#line 4100 "A.cpp"
488struct 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"
498struct B {
499 A a = {};
500};
501#line 4300 "test_passed.cpp"
502constexpr B b = {};
503static_assert(b.a.n == 4300, "");
504static_assert(b.a.n2 == 4300, "");
505static_assert(b.a.info.line() == 4300, "");
506static_assert(is_equal(b.a.f, "test_passed.cpp"));
507static_assert(is_equal(b.a.f2, "test_passed.cpp"));
508static_assert(is_equal(b.a.info.file(), "test_passed.cpp"));
509static_assert(is_equal(b.a.func, ""));
510static_assert(is_equal(b.a.func2, ""));
511static_assert(is_equal(b.a.info.function(), ""));
512
513constexpr 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}
527static_assert(test_in_func());
528
529} // end namespace test_out_of_line_init
530
531namespace test_global_scope {
532#line 5000 "test_global_scope.cpp"
533constexpr unsigned get_line(unsigned n = __builtin_LINE()) { return n; }
534constexpr const char *get_file(const char *f = __builtin_FILE()) { return f; }
535constexpr const char *get_func(const char *f = __builtin_FUNCTION()) { return f; }
536#line 5100
537struct 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
546constexpr InInit II;
547
548static_assert(II.l == 5200, "");
549static_assert(is_equal(II.f, "in_init.cpp"));
550static_assert(is_equal(II.func, "InInit"));
551
552#line 5400
553struct 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"
559constexpr AggInit AI = {};
560static_assert(AI.l == 5500);
561static_assert(is_equal(AI.f, "brace_init.cpp"));
562static_assert(is_equal(AI.func, ""));
563
564} // namespace test_global_scope
565
566namespace TestFuncInInit {
567#line 6000 "InitClass.cpp"
568struct Init {
569 SL info;
570#line 6100 "InitCtor.cpp"
571 constexpr Init(SL info = SL::current()) : info(info) {}
572};
573#line 6200 "InitGlobal.cpp"
574constexpr Init I;
575static_assert(I.info.line() == 6200);
576static_assert(is_equal(I.info.file(), "InitGlobal.cpp"));
577
578} // namespace TestFuncInInit
579
580namespace 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}