Skip to content

Commit e2966f8

Browse files
committed
[Editorial] Rewrite the section on member pointers
- Break it up into subsections for data and function member pointers - Be much more precise - Use portable concepts - Include the ARM representation for virtual member functions pointers - Add a future-platform recommendation about null data member pointers
1 parent 958b90e commit e2966f8

File tree

1 file changed

+100
-23
lines changed

1 file changed

+100
-23
lines changed

abi.html

Lines changed: 100 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -151,6 +151,13 @@ <h3><a href="#definitions"> 1.1 Definitions </a></h3>
151151
A function that runs the destructors for non-static data members of T and
152152
non-virtual direct base classes of T.
153153

154+
<p>
155+
<dt> <i>basic ABI properties</i> of a type T</dt>
156+
<dd>
157+
The basic representational properties of a type decided by the base C ABI,
158+
including its size, its alignment, its treatment by calling conventions,
159+
and the representation of pointers to it.
160+
154161
<p>
155162
<dt> <i>complete object destructor</i> of a class T</dt>
156163
<dd>
@@ -686,40 +693,110 @@ <h3><a href="#pod"> 2.2 POD Data Types </a></h3>
686693
<a name="member-pointers"></a>
687694
<h3><a href="#member-pointers"> 2.3 Member Pointers </a></h3>
688695

696+
<a name="data-member-pointers"></a>
697+
<h4><a href="#data-member-pointers"> 2.3.1 Data Member Pointers </a></h4>
698+
689699
<p>
690-
A pointer to data member is an offset from the base
691-
address of the class object containing it,
692-
represented as a <code>ptrdiff_t</code>.
693-
It has the size and alignment attributes of a <code>ptrdiff_t</code>.
694-
A NULL pointer is represented as -1.
700+
The basic ABI properties of data member pointer types are those
701+
of <code>ptrdiff_t</code>.
695702

696703
<p>
697-
A pointer to member function is a pair <ptr, adj> as follows:
704+
A data member pointer is represented as the data member's offset in bytes
705+
from the address point of an object of the base type, as a
706+
<code>ptrdiff_t</code>.
698707

699-
<dl>
700708
<p>
701-
<dt> <code>ptr</code>:
702-
<dd> For a non-virtual function, this field is a simple function pointer.
703-
(Under current base Itanium psABI conventions,
704-
that is a pointer to a GP/function address pair.)
705-
For a virtual function,
706-
it is 1 plus the virtual table offset (in bytes) of the function,
707-
represented as a <code>ptrdiff_t</code>.
708-
The value zero represents a NULL pointer,
709-
independent of the adjustment field value below.
709+
A null data member pointer is represented as an offset of <code>-1</code>.
710+
Unfortunately, it is possible to generate an data member pointer with an
711+
offset of <code>-1</code> using explicit derived-to-base conversions.
712+
If this is done, implementations following this ABI may misbehave.
713+
<span class="future-abi">Recommendation for new platforms: consider using
714+
<code>PTRDIFF_MIN</code> as the null data member pointer instead.</span>
710715

711716
<p>
712-
<dt> <code>adj</code>:
713-
<dd> The required adjustment to <i>this</i>,
714-
represented as a <code>ptrdiff_t</code>.
715-
</dl>
717+
Note that by <code>[dcl.init]</code>, "zero initialization" of a data
718+
member pointer object stores a null pointer value into it. Under this
719+
representation, that value has a non-zero bit representation. On most
720+
modern platforms, data member pointers are the only type with this
721+
property.
716722

717723
<p>
718-
It has the size, data size, and alignment
719-
of a class containing those two members, in that order.
720-
(For 64-bit Itanium, that will be 16, 16, and 8 bytes respectively.)
724+
Base-to-derived and derived-to-base conversions of a non-null data member
725+
pointer can be performed by adding or subtracting (respectively) the static
726+
offset of the base within the derived class. The C++ standard does not
727+
permit base-to-derived and derived-to-base conversions of member pointers
728+
to cross a <code>virtual</code> base relationship, and so a static offset
729+
is always known.
721730

731+
<a name="member-function-pointers"></a>
732+
<h4><a href="#member-function-pointers"> 2.3.2 Member Function Pointers </a></h4>
733+
734+
<p>
735+
The basic ABI properties of member function pointer types are those of
736+
the following class:
737+
738+
<pre>
739+
struct {
740+
fnptr_t ptr;
741+
ptrdiff_t adj;
742+
};
743+
</pre>
722744

745+
where <code>fnptr_t</code> is the appropriate function-pointer type
746+
for the member type.
747+
748+
<p>
749+
A member function pointer for a non-virtual function is represented
750+
with <code>ptr</code> set to a function pointer to the function,
751+
using the base ABI's representation of function pointers.
752+
753+
<p>
754+
A member function pointer for a virtual function is represented
755+
with <code>ptr</code> set to 1 plus the virtual table offset of
756+
the function (in bytes), converted to a function pointer as if by <code>reinterpret_cast&lt;fnptr_t&gt;(uintfnptr_t(1 + offset))</code>,
757+
where <code>uintfnptr_t</code> is an unsigned integer of the same
758+
size as <code>fnptr_t</code>.
759+
760+
<p>
761+
In both cases, <code>adj</code> stores the offset (in bytes) which
762+
must be added to a pointer to the base type before the call can be
763+
made. For a virtual member function pointer, the v-table is loaded
764+
from the adjusted address.
765+
766+
<p>
767+
The representation of virtual member function pointers requires the
768+
representation of a function pointer to a non-static member function
769+
to never have its lowest bit set. On most platforms, this is either
770+
always true, or it can be made true at little cost. (For example,
771+
on most platforms a function pointer is just the address of the
772+
first instruction in the function. Many architectures align all
773+
instructions to at least 2 bytes; even on architectures where that's
774+
not true, or where functions aren't byte-addressed, the compiler can
775+
just increase the alignment of non-static member functions until the
776+
low bit of the address is always reliably zero.) However, some platforms
777+
use the low bit of a function pointer for special purposes, such as to
778+
distinguish THUMB functions on ARM. Such platforms must use a slightly
779+
different representation: the virtual/non-virtual bit is instead stored
780+
as the lowest bit of <code>adj</code>, and the adjustment value is
781+
stored left-shifted by 1.
782+
783+
<p>
784+
A null member function pointer is represented by a null value for
785+
<code>ptr</code>. (This assumes that the low bit of a null pointer
786+
is not 1; platforms with non-zero bit representations for null function
787+
pointers may need an adjusted rule.) The value of <code>adj</code>
788+
is not specified unless the alternative virtual-bit representation
789+
is being used, in which case the lowest bit of <code>adj</code> must
790+
also be zero but the remaining bits are still unspecified.
791+
792+
<p>
793+
Base-to-derived and derived-to-base conversions of a member function
794+
pointer can be performed by adding or subtracting (respectively) the
795+
static offset of the base within the derived class to the value of
796+
<code>adj</code>. In the alternative virtual-bit representation,
797+
the addend must be shifted by one. Because the adjustment does not
798+
factor into whether a member function pointer is null, this can be
799+
done unconditionally when performing a conversion.
723800

724801
<p> <hr> <p>
725802
<a name="class-types">

0 commit comments

Comments
 (0)