53 lines
2.3 KiB
C++
53 lines
2.3 KiB
C++
// Tests that lifetime-extended temporaries whose backing storage is a
|
|
// subobject (member or base) are always emitted as `internal global`, never
|
|
// 'internal constant', regardless of the cv-qualification on the reference.
|
|
//
|
|
// In C++98, skipRValueSubobjectAdjustments is used for rvalue subobject
|
|
// adjustments. The MaterializeTemporaryExpr ends up with the type of the
|
|
// reference (e.g. `const int`), not the type of the backing store (e.g. `S`).
|
|
// hasSameUnqualifiedType detects this mismatch and correctly falls back to
|
|
// Init->getType(), preventing the backing store from being marked constant.
|
|
//
|
|
// RUN: %clang_cc1 -std=c++98 -triple x86_64-linux-gnu -emit-llvm -o - %s | FileCheck %s
|
|
// RUN: %clang_cc1 -std=c++11 -triple x86_64-linux-gnu -emit-llvm -o - %s | FileCheck %s
|
|
// RUN: %clang_cc1 -std=c++98 -triple x86_64-linux-gnu -emit-llvm -o - %s -fexperimental-new-constant-interpreter | FileCheck %s
|
|
// RUN: %clang_cc1 -std=c++11 -triple x86_64-linux-gnu -emit-llvm -o - %s -fexperimental-new-constant-interpreter | FileCheck %s
|
|
|
|
// `const int &` bound to a member of an S temporary.
|
|
// The backing store is the whole S object, which can't be stored const.
|
|
|
|
struct MemberS { int x, y; };
|
|
const int &member_ref = MemberS().x;
|
|
|
|
// CHECK: @_ZGR10member_ref_ = internal global %struct.MemberS
|
|
|
|
// Binding a `const int &` to a mutable member.
|
|
// The backing store is the whole object (with a mutable member), so it
|
|
// must remain writable.
|
|
|
|
struct MutableS {
|
|
mutable int m;
|
|
MutableS() : m(1) {}
|
|
};
|
|
const int &mutable_member_ref = MutableS().m;
|
|
void write_mutable() { const_cast<int &>(mutable_member_ref) = 5; }
|
|
|
|
// CHECK: @_ZGR18mutable_member_ref_ = internal global %struct.MutableS
|
|
|
|
// `const Base &` bound to a Derived temporary.
|
|
// Non-constexpr constructors mean no constant initializer is possible, and
|
|
// the backing store is the full Derived object.
|
|
|
|
struct Base { int b; Base() : b(11) {} };
|
|
struct Derived : Base { int d; Derived() : Base(), d(22) {} };
|
|
const Base &base_ref = Derived();
|
|
|
|
// CHECK: @_ZGR8base_ref_ = internal global %struct.Derived
|
|
|
|
// Same as above but using a plain member instead of a base class.
|
|
|
|
struct Pair { int a, c; Pair() : a(33), c(44) {} };
|
|
const int &pair_member_ref = Pair().a;
|
|
|
|
// CHECK: @_ZGR15pair_member_ref_ = internal global %struct.Pair
|