teak-llvm/clang/test/CodeGenCXX/no-odr-use.cpp
Richard Smith 24cdcadcc5 C++ DR712 and others: handle non-odr-use resulting from an lvalue-to-rvalue conversion applied to a member access or similar not-quite-trivial lvalue expression.
Summary:
When a variable is named in a context where we can't directly emit a
reference to it (because we don't know for sure that it's going to be
defined, or it's from an enclosing function and not captured, or the
reference might not "work" for some reason), we emit a copy of the
variable as a global and use that for the known-to-be-read-only access.

This reinstates r363295, reverted in r363352, with a fix for PR42276:
we now produce a proper name for a non-odr-use reference to a static
constexpr data member. The name <mangled-name>.const is used in that
case; such names are reserved to the implementation for cases such as
this and should demangle nicely.

Reviewers: rjmccall

Subscribers: jdoerfert, cfe-commits

Tags: #clang

Differential Revision: https://reviews.llvm.org/D63157

llvm-svn: 363428
2019-06-14 17:46:37 +00:00

47 lines
2.3 KiB
C++

// RUN: %clang_cc1 -std=c++11 -emit-llvm -o - -triple x86_64-linux-gnu %s | FileCheck %s --check-prefixes=CHECK,CHECK-CXX11
// RUN: %clang_cc1 -std=c++2a -emit-llvm -o - -triple x86_64-linux-gnu %s | FileCheck %s --check-prefixes=CHECK,CHECK-CXX2A
// CHECK-DAG: @__const._Z1fi.a = private unnamed_addr constant {{.*}} { i32 1, [2 x i32] [i32 2, i32 3], [3 x i32] [i32 4, i32 5, i32 6] }
// CHECK-CXX11-DAG: @_ZN7PR422765State1mE.const = private unnamed_addr constant [2 x { i64, i64 }] [{ {{.*}} @_ZN7PR422765State2f1Ev {{.*}}, i64 0 }, { {{.*}} @_ZN7PR422765State2f2Ev {{.*}}, i64 0 }]
// CHECK-CXX2A-DAG: @_ZN7PR422765State1mE = linkonce_odr constant [2 x { i64, i64 }] [{ {{.*}} @_ZN7PR422765State2f1Ev {{.*}}, i64 0 }, { {{.*}} @_ZN7PR422765State2f2Ev {{.*}}, i64 0 }], comdat
struct A { int x, y[2]; int arr[3]; };
// CHECK-LABEL: define i32 @_Z1fi(
int f(int i) {
// CHECK: call void {{.*}}memcpy{{.*}}({{.*}}, {{.*}} @__const._Z1fi.a
constexpr A a = {1, 2, 3, 4, 5, 6};
// CHECK-LABEL: define {{.*}}@"_ZZ1fiENK3$_0clEiM1Ai"(
return [] (int n, int A::*p) {
// CHECK: br i1
return (n >= 0
// CHECK: getelementptr inbounds [3 x i32], [3 x i32]* getelementptr inbounds ({{.*}} @__const._Z1fi.a, i32 0, i32 2), i64 0, i64 %
? a.arr[n]
// CHECK: br i1
: (n == -1
// CHECK: getelementptr inbounds i8, i8* bitcast ({{.*}} @__const._Z1fi.a to i8*), i64 %
// CHECK: bitcast i8* %{{.*}} to i32*
// CHECK: load i32
? a.*p
// CHECK: getelementptr inbounds [2 x i32], [2 x i32]* getelementptr inbounds ({{.*}} @__const._Z1fi.a, i32 0, i32 1), i64 0, i64 %
// CHECK: load i32
: a.y[2 - n]));
}(i, &A::x);
}
namespace PR42276 {
class State {
void syncDirtyObjects();
void f1(), f2();
using l = void (State::*)();
static constexpr l m[]{&State::f1, &State::f2};
};
// CHECK-LABEL: define void @_ZN7PR422765State16syncDirtyObjectsEv(
void State::syncDirtyObjects() {
for (int i = 0; i < sizeof(m) / sizeof(m[0]); ++i)
// CHECK-CXX11: getelementptr inbounds [2 x { i64, i64 }], [2 x { i64, i64 }]* @_ZN7PR422765State1mE.const, i64 0, i64 %
// CHECK-CXX2A: getelementptr inbounds [2 x { i64, i64 }], [2 x { i64, i64 }]* @_ZN7PR422765State1mE, i64 0, i64 %
(this->*m[i])();
}
}