diff options
author | Eric Fiselier <eric@efcs.ca> | 2019-05-16 21:04:15 +0000 |
---|---|---|
committer | Eric Fiselier <eric@efcs.ca> | 2019-05-16 21:04:15 +0000 |
commit | 708afb56c125ca4f7db7070e836860076c7eafbc (patch) | |
tree | 3dee8820f6b797ab01e7621f7eab44a615fced41 /clang/test/CodeGenCXX/builtin_LINE.cpp | |
parent | e7b680478c8e15e92af6706da0edaeab8708e49e (diff) | |
download | bcm5719-llvm-708afb56c125ca4f7db7070e836860076c7eafbc.tar.gz bcm5719-llvm-708afb56c125ca4f7db7070e836860076c7eafbc.zip |
Implement __builtin_LINE() et. al. to support source location capture.
Summary:
This patch implements the source location builtins `__builtin_LINE(), `__builtin_FUNCTION()`, `__builtin_FILE()` and `__builtin_COLUMN()`. These builtins are needed to implement [`std::experimental::source_location`](https://rawgit.com/cplusplus/fundamentals-ts/v2/main.html#reflection.src_loc.creation).
With the exception of `__builtin_COLUMN`, GCC also implements these builtins, and Clangs behavior is intended to match as closely as possible.
Reviewers: rsmith, joerg, aaron.ballman, bogner, majnemer, shafik, martong
Reviewed By: rsmith
Subscribers: rnkovacs, loskutov, riccibruno, mgorny, kunitoki, alexr, majnemer, hfinkel, cfe-commits
Differential Revision: https://reviews.llvm.org/D37035
llvm-svn: 360937
Diffstat (limited to 'clang/test/CodeGenCXX/builtin_LINE.cpp')
-rw-r--r-- | clang/test/CodeGenCXX/builtin_LINE.cpp | 95 |
1 files changed, 95 insertions, 0 deletions
diff --git a/clang/test/CodeGenCXX/builtin_LINE.cpp b/clang/test/CodeGenCXX/builtin_LINE.cpp new file mode 100644 index 00000000000..806c2111f32 --- /dev/null +++ b/clang/test/CodeGenCXX/builtin_LINE.cpp @@ -0,0 +1,95 @@ +// RUN: %clang_cc1 -std=c++1z -fblocks %s -triple %itanium_abi_triple -emit-llvm -o - | FileCheck %s + +extern "C" int sink; +extern "C" const volatile void* volatile ptr_sink = nullptr; + +struct Tag1 {}; +struct Tag2 {}; +struct Tag3 {}; +struct Tag4 {}; + +constexpr int get_line_constexpr(int l = __builtin_LINE()) { + return l; +} + +int get_line_nonconstexpr(int l = __builtin_LINE()) { + return l; +} + + +int get_line(int l = __builtin_LINE()) { + return l; +} + +int get_line2(int l = get_line()) { return l; } + + +// CHECK: @global_one = global i32 [[@LINE+1]], align 4 +int global_one = __builtin_LINE(); +// CHECK-NEXT: @global_two = global i32 [[@LINE+1]], align 4 +int global_two = get_line_constexpr(); +// CHECK: @_ZL12global_three = internal constant i32 [[@LINE+1]], align 4 +const int global_three(get_line_constexpr()); + +// CHECK-LABEL: define internal void @__cxx_global_var_init +// CHECK: %call = call i32 @_Z21get_line_nonconstexpri(i32 [[@LINE+2]]) +// CHECK-NEXT: store i32 %call, i32* @global_four, align 4 +int global_four = get_line_nonconstexpr(); + +struct InClassInit { + int Init = __builtin_LINE(); + int Init2 = get_line2(); + InClassInit(); + constexpr InClassInit(Tag1, int l = __builtin_LINE()) : Init(l), Init2(l) {} + constexpr InClassInit(Tag2) : Init(__builtin_LINE()), Init2(__builtin_LINE()) {} + InClassInit(Tag3, int l = __builtin_LINE()); + InClassInit(Tag4, int l = get_line2()); + + static void test_class(); +}; +// CHECK-LABEL: define void @_ZN11InClassInit10test_classEv() +void InClassInit::test_class() { + // CHECK: call void @_ZN11InClassInitC1Ev(%struct.InClassInit* %test_one) + InClassInit test_one; + // CHECK-NEXT: call void @_ZN11InClassInitC1E4Tag1i(%struct.InClassInit* %test_two, i32 [[@LINE+1]]) + InClassInit test_two{Tag1{}}; + // CHECK-NEXT: call void @_ZN11InClassInitC1E4Tag2(%struct.InClassInit* %test_three) + InClassInit test_three{Tag2{}}; + // CHECK-NEXT: call void @_ZN11InClassInitC1E4Tag3i(%struct.InClassInit* %test_four, i32 [[@LINE+1]]) + InClassInit test_four(Tag3{}); + // CHECK-NEXT: %[[CALL:.+]] = call i32 @_Z8get_linei(i32 [[@LINE+3]]) + // CHECK-NEXT: %[[CALL2:.+]] = call i32 @_Z9get_line2i(i32 %[[CALL]]) + // CHECK-NEXT: call void @_ZN11InClassInitC1E4Tag4i(%struct.InClassInit* %test_five, i32 %[[CALL2]]) + InClassInit test_five(Tag4{}); + +} +// CHECK-LABEL: define void @_ZN11InClassInitC2Ev +// CHECK: store i32 [[@LINE+4]], i32* %Init, align 4 +// CHECK: %call = call i32 @_Z8get_linei(i32 [[@LINE+3]]) +// CHECK-NEXT: %call2 = call i32 @_Z9get_line2i(i32 %call) +// CHECK-NEXT: store i32 %call2, i32* %Init2, align 4 +InClassInit::InClassInit() = default; + +InClassInit::InClassInit(Tag3, int l) : Init(l) {} + +// CHECK-LABEL: define void @_ZN11InClassInitC2E4Tag4i(%struct.InClassInit* %this, i32 %arg) +// CHECK: %[[TEMP:.+]] = load i32, i32* %arg.addr, align 4 +// CHECK-NEXT: store i32 %[[TEMP]], i32* %Init, align 4 +// CHECK: %[[CALL:.+]] = call i32 @_Z8get_linei(i32 [[@LINE+3]]) +// CHECK-NEXT: %[[CALL2:.+]] = call i32 @_Z9get_line2i(i32 %[[CALL]]) +// CHECK-NEXT: store i32 %[[CALL2]], i32* %Init2, align 4 +InClassInit::InClassInit(Tag4, int arg) : Init(arg) {} + +// CHECK-LABEL: define void @_Z13get_line_testv() +void get_line_test() { + // CHECK: %[[CALL:.+]] = call i32 @_Z8get_linei(i32 [[@LINE+2]]) + // CHECK-NEXT: store i32 %[[CALL]], i32* @sink, align 4 + sink = get_line(); + // CHECK-NEXT: store i32 [[@LINE+1]], i32* @sink, align 4 + sink = __builtin_LINE(); + ptr_sink = &global_three; +} + +void foo() { + const int N[] = {__builtin_LINE(), get_line_constexpr()}; +} |