Here is the latest revision:

- Removed Pascal-specific wording from text in 5.19 (field -> data member)
- added updates for Appendix A
- updated Section 7.32 for type signature computation.

-- adrian

# Add support for "properties"

## Background

Pascal has a property construct, that allows a "variable like"
identifier, which can either point to a field (member variable) or a
getter/setter function.

    TFoo = class
      FField: integer;
      function GetProp: integer;
      procedure SetProp(AVal: Integer);
      property MyProp: integer read GetProp write SetProp;
      property MyOtherProp: integer read FField;
    end;

* Properties can exist in a structure, interface, or on a global level.

* Properties can be read/write, read only, write only.

* Properties can have one or more array like indexes (of any type).

        function GetProp(AIdx:word; AIdx2: boolean): integer;
        procedure SetProp(AIdx:word; AIdx2: boolean; AVal: Integer);
        property MyProp[AIdx:word; AIdx2: boolean]: integer read GetProp write SetProp;

* Properties can share a method, and provide an index (constant) to
  identify which property called the method.

        function GetProp(AIndex: Integer): integer;
        procedure SetProp(AIndex: Integer; AValue: integer);
        property MyProp1: integer index 1 read GetProp write SetProp;
        property MyProp2: integer index 2 read GetProp write SetProp;

* Properties can have a "default" flag, indicating that the array []
  access can omit the property name. I.e. accessing "Object[n]" is a
  shortcut for the default property. (default for non-array properties is
  being considered for future addition)

* Properties can have "default" and "stored" values for streaming
  (constant or via function).

* Properties can be elevated to a higher visibility (private/public) in
  inherited classes.

There may be partial overlaps with properties in Objective-C and C#.

Update: This proposal has been updated in a way to make to also useful
for properties in Objective-C and Swift.


### References

- [FreePascal property doc][freepascal]
- [Oxygene][oxygene]
- [Apple extension for Objective-C][objc]

[freepascal]: https://www.freepascal.org/docs-html/ref/refse27.html
[oxygene]: https://docs.elementscompiler.com/Oxygene/Members/Properties/
[objc]: https://github.com/llvm/llvm-project/blob/main/llvm/docs/SourceLevelDebugging.rst#debugging-information-format-1

## Proposed Changes

### Section 2.1: The Debugging Information Entry

In Table 2.1, add `DW_TAG_property`, `DW_TAG_property_getter`,
`DW_TAG_property_setter`, and `DW_TAG_property_stored`.

### New Section 5.7.11 Property Entries

A property member is represented by a debugging information entry with
the tag `DW_TAG_property` as specified in Section 5.19.

### New Section 5.19(?): Property Entries

Add the following new subsection to Chapter 5:

> 5.19(?) Property Entries
>
> [Non-normative] Many object-oriented languages like Pascal and
> Objective-C have properties, which are member functions that
> syntactically behave like data members of an object. In Pascal
> properties can also be global and behave like data members of a
> unit.
>
> A property is represented by a debugging information entry with the
> tag `DW_TAG_property`. A property entry may have a `DW_AT_name` string
> attribute, whose value is the property name. A property entry may have
> a `DW_AT_type` attribute to denote the type of that property.
>
> A property may have `DW_AT_external`, `DW_AT_virtuality`,
> `DW_AT_start_scope`, `DW_AT_decl_column`, `DW_AT_decl_file` and
> `DW_AT_decl_line` attributes with the respective semantics described
> for these attributes for `DW_TAG_member` (see Section 5.7.6).
>
> A property may have one or several of `DW_TAG_property_getter`,
> `DW_TAG_property_setter`, or `DW_TAG_property_stored` children to
> represent the getter and setter (member) functions, or underlying
> storage. A `DW_TAG_property_stored` child describes the Pascal-style
> `stored` accessor for a property. Each of these tags have a
> `DW_AT_property_forward` attribute to point to a (member) function
> declaration or a data member. If they point to a function, they may
> also have `DW_TAG_formal_parameter` children (matching the ones in
> the function) that can have `DW_AT_default_value` attributes to
> declare additional default arguments for when these functions are
> used as property accessors.
>
> Some languages can automatically derive property derive accessors
> from a data member in property's parent entity. In such cases the
> `DW_AT_property_forward` attribute of the accessor entry points to
> the `DW_TAG_property`'s sibling `DW_TAG_member` entry that holds the
> properties underlying storage. In the case of a global property it
> may point to a `DW_TAG_variable` or `DW_TAG_constant`.
>
> Property accessors may also have any other attributes allowed in a
> `DW_TAG_subprogram` subroutine entry. If the value of a property can
> be derived by evaluating a DWARF expression, the
> `DW_TAG_property_getter` may have a `DW_AT_location` holding a DWARF
> expression that may use `DW_OP_push_object_address` to inquire the
> address of the property's parent entity.
>
> To change the accessibility of a property in an inherited class, a
> access declaration [link to 5.7.4: Access Declarations] can be
> specified with the property name and accessibility.  For example if
> in a subclass property `a` becomes private it is sufficient to add the
> following to the subclass entry:
>
>     DW_TAG_class
>       DW_AT_name            "subclass"
>       DW_TAG_inheritance
>         ...
>
>       DW_TAG_access_declaration
>         DW_AT_name            "a"
>         DW_AT_accessibility   DW_ACCESS_private

### Section 7

Add to Table 7.3

>     DW_TAG_property         0x4c
>     DW_TAG_property_getter  0x4d
>     DW_TAG_property_setter  0x4e
>     DW_TAG_property_stored  0x4f

Add to Table 7.5

>     DW_AT_property_forward  0x61  reference

Add to 7.32

Change bullet point 5 to:

>  If the tag in Step 3 is one of DW_TAG_pointer_type,
>  DW_TAG_reference_type, DW_TAG_rvalue_reference_type,
>  DW_TAG_ptr_to_member_type, DW_TAG_property_getter,
>  DW_TAG_property_setter, DW_TAG_property_stored, or DW_TAG_friend,
>  and the referenced type (via the DW_AT_type,
>  DW_AT_property_forward, or DW_AT_friend attribute) has a DW_AT_name
>  attribute, append to S the letter ’N’, the DWARF attribute code
>  (DW_AT_type or DW_AT_friend), the context of the type (according to
>  the method in Step 2), the letter ’E’, and the name of the type.
>  For DW_AT_propery_forward and DW_AT_friend, if the referenced entry
>  is a DW_TAG_subprogram, the context is omitted and the name to be
>  used is the ABI-specific name of the subprogram (for example, the
>  nangled linker name).

### Appendix A:

Add to Table A.1:

> DW_TAG_property | DECL, DW_AT_type, DW_AT_external, DW_AT_virtuality, DW_AT_start_scope
> DW_TAG_property_getter | DECL, DW_AT_property_forward
> DW_TAG_property_setter | DECL, DW_AT_property_forward
> DW_TAG_property_stored | DECL, DW_AT_property_forward

### Appendix D: Examples

Add a new subsection:

> D.x Properties
>
> The properties in the Pascal object in this example are represented by
> the following DWARF.
>
>     TClass = class
>       private
>          PrivateField: integer;
>          function shouldStore : boolean;
>       public
>          function GetProp: integer;
>          procedure SetProp(AVal: Integer);
>          property PropFromMethods: integer read GetProp write SetProp;
>          property PropFromField: integer read PrivateField;
>          function GetValue(x: word; AIndex: Integer): char;
>          property Indexed[x: word]: char index 1 read GetValue;
>          property MaybeStored: integer stored shouldStore;
>     end;
>
>
>     DW_TAG_class_type
>       DW_AT_name "TClass"
>       DW_TAG_member
>         DW_AT_accessibility DW_AT_private
>         DW_AT_name "PrivateField"
>         DW_AT_type <ref to integer>
>       DW_TAG_subprogram
>         DW_AT_name "GetProp"
>         ...
>       DW_TAG_subprogram
>         DW_AT_name "SetProp"
>         ...
>
>       DW_TAG_property
>         DW_AT_name "PropFromMethods"
>         DW_TAG_property_getter
>           DW_AT_property_forward <ref to GetProp>
>         DW_TAG_property_setter
>           DW_AT_property_forward <ref to SetProp>
>
>       DW_TAG_property
>         DW_AT_name "PropFromField"
>         DW_TAG_property_getter
>           DW_AT_property_forward <ref to PrivateField>
>
>       DW_TAG_subprogram
>         DW_AT_name "GetValue"
>         ...
>
>       DW_TAG_property
>         DW_AT_name "Indexed"
>
>         DW_TAG_property_getter
>           DW_AT_property_forward <ref to GetValue>
>
>           DW_TAG_formal_parameter  ; _this (no default specified, details inherited from GetValue
>           DW_TAG_formal_parameter  ; x (no default specified)
>           DW_TAG_formal_parameter
>             DW_AT_default_value <DW_OP_lit 1> ; property index
>
>       DW_TAG_property
>         DW_AT_name "MaybeStored"
>
>         DW_TAG_property_stored
>           DW_AT_property_forward <ref to shouldStore>
>

---

2024-05-07: [Original proposal][orig].

2024-10-12: [Revised][diff1] after online discussion.

2025-01-03: [Revised][diff2] with updated examples and Chapter 7 changes.

2025-02-17: [Revised][diff3] with updated examples and Chapter 7 changes, and a fix to accessibility.

2025-03-03: Discussed in meeting. Change "field" (Pascal term) to "data member"
(DWARF term); add updates for App. A; update Table 7.32 for type signature
computation.
-- 
Dwarf-discuss mailing list
Dwarf-discuss@lists.dwarfstd.org
https://lists.dwarfstd.org/mailman/listinfo/dwarf-discuss

Reply via email to