Issue 131105.1: C++11 ref-qualifiers on non-static member functions
Section 3, pg
C++11 adds a feature that allows putting ref-qualifiers (&, &&) on
non-static member functions. It's like putting a const qualifier on a
method, except it limits the kinds of value you can call the method on
(&: only on l-values; &&: on either pr-values or x-values).
For example::
struct A {
void foo() &;
void bar() &;
void bar() &&;
};
It is important to encode this in DWARF, because it affects overload
resolution and the name mangling for the functions.
To encode const-volatile qualifiers of non-static member functions,
clang currently uses the type of the artificial "this" argument. This
aligns with the C++11 spec (section 9.3.2):
http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2011/n3242.pdf
"In the body of a non-static (9.3) member function, the keyword this
is a prvalue expression whose value is the address of the object
for which the function is called. The type of this in a member
function of a class X is X*. If the member function is declared
const, the type of this is const X*, if the member function is
declared volatile, the type of this is volatile X*, and if the
member function is declared const volatile, the type of this is
const volatile X*."
In contrast to cv-modifiers it does not make sense to wrap the type of
"this" in a DW_TAG_reference_type (or DW_TAG_rvalue_reference_type)
because a ref-qualifier does not actually change the type of "this"
into a reference.
We suggest to add a DW_AT_reference_qualifier /
DW_AT_rvalue_reference_qualifier attribute to the DW_TAG_subprogram
describing the member function.
Changes
=======
Table 2.2: Attribute names
--------------------------
DW_AT_reference | &-qualified non-static member function
DW_AT_rvalue_reference | &&-qualified non-static member function
5.7.7 Member Function Entries
-----------------------------
[ORIGINAL TEXT]
If the member function entry describes a non-static member function
that has a const-volatile qualification, then the entry describes a
non-static member function whose object formal parameter has a type
that has an equivalent const-volatile qualification.
[REPLACE WITH]
*In C++, non-static member functions can have const-volatile
qualifiers, which affect the type of the first formal parameter (the
"this"-pointer).*
If the member function entry describes a non-static member function
that has a const-volatile qualification, then the entry describes a
non-static member function whose object formal parameter has a type
that has an equivalent const-volatile qualification.
*In C++11, non-static member functions can also have one of the
ref-qualifiers, & and &&. They do not change the type of the
"this"-pointer, but they affect the types of object values the
function can be invoked on.*
The member function entry may have an DW_AT_reference attribute to
indicate a non-static member function that can only be called on
l-value objects, or the attribute DW_AT_rvalue_reference to indicate
that it can only be called on pr-values and x-values.
5.10: Subroutine Type Entries
-----------------------------
*C++ const-volatile qualifiers are encoded as part of the type of the
"this"-pointer. C++11 rvalue-reference qualifiers are stored using
the DW_AT_reference / DW_AT_rvalue_reference attributes. See also
Section 5.7.7.*
A subroutine type entry may have the DW_AT_reference or
DW_AT_rvalue_reference attribute to indicate that it describes the
type of a member function with (rvalue) reference semantics.
Table 7.3: Data representation
------------------------------
DW_AT_reference | 0x77 | flag
DW_AT_rvalue_reference | 0x78 | flag
Table 7.26: Attributes used in type signature computation
---------------------------------------------------------
DW_AT_reference
DW_AT_rvalue_reference
A. Attributes by TAG
---------------------
DW_TAG_subprogram | DW_AT_reference
DW_AT_rvalue_reference
DW_TAG_subroutine_type | DW_AT_reference
DW_AT_rvalue_reference
Section D.4, Member Function Example
-----------------------------------
The following example shows how to encode qualifiers for C++11::
class A {
public:
void f() const &&;
};
void g() {
A a;
// The type of pointer_to_member_function is "void (A::*)() const &&".
auto pointer_to_member_function = &A::f;
}
The DWARF type information for this example looks as follows::
DW_TAG_subprogram
DW_AT_name( "g" )
DW_TAG_variable
DW_AT_name( "a" )
DW_AT_type( {ref to A} )
DW_TAG_variable
DW_AT_name( "pointer_to_member_function" )
DW_AT_type( {ref to mfptr} )
A: DW_TAG_class_type
DW_AT_name( "A" )
DW_TAG_subprogram
DW_AT_name( "f" )
DW_AT_rvalue_reference( 0x01 )
DW_TAG_formal_parameter
DW_AT_type( {ref to const A*} )
DW_AT_artificial( 0x01 )
const A*: DW_TAG_pointer_type
DW_AT_type( {ref to const A} )
const A: DW_TAG_const_type
DW_AT_type( {ref to A} )
mfptr: DW_TAG_ptr_to_member_type
DW_AT_type( {ref to functype} )
DW_AT_containing_type( {ref to A} )
functype: DW_TAG_subroutine_type
DW_AT_rvalue_reference( 0x01 )
DW_TAG_formal_parameter
DW_AT_type( {ref to const A*} )
DW_AT_artificial( 0x01 )
---
Updated - 12/16/2013
Accepted - 12/17/2013
Updated example - 12/19/2013