// 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(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