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