Issue 040511.1: Static Member Function

Author: David Anderson
Champion: Matthew Gretton-Dann
Date submitted: 2004-05-11
Date revised:
Date closed:
Type: Clarification
Status: Accepted with modifications
DWARF Version: 3
Ron Brender

|What is intended and/or good practice regarding the DWARF
|description of member functions; specifically, how is it intended
|to distinguish a static vs non-static member function?
|
|Consider:
|
|ABC.HXX
|-------
|
|struct X
|    {
|    int a;
|    void b();
|    static void c( X* );
|    int f() { return a; };
|    }
|
|
|A.CXX
|-----
|
|#include "abc.hxx"
|
|int main()
|    {
|    X x;
|
|    x.b();
|    x.c( &x );
|    return 0;
|    }
|
|
|B.CXX
|-----
|
|#include "abc.hxx"
|
|void X::b(){ f(); }
|
|
|C.CXX
|-----
|
|#include "abc.hxx"
|
|void X::c( X* that ){ that->f(); }
|
|
|It appears that about the only way for a DWARF description to
|identify a non-static member function is for the implicit 'this'
|parameter to be included in the description of member function.
|In particular, in parameter needs to include the name attribute
|'this'. Without that name, it seems b will "look" exactly like
|member function c (based on formal parameter(s) and associated
|type(s)).
|
|An alternative might be to mark the implicit parameter to b with
|the artificial attribute. This seems less satisfactory and less
|definitive because in general there can be many reasons for
|marking an entity as artificial; in particular, any implementation
|may have other kinds of implicit/hidden parameters that just the
|'this' parameter.
|
|Using artificial in combination with the name 'this' does seem
|like it has much to recommend it.
|
|Any thought or recommendation regarding what is considered good/
|recommended practice is appreciated.

Daniel Jacobowitz

|On Tue, May 11, 2004 at 01:09:07PM -0400, Ron 603-884-2088 wrote:
|> An alternative might be to mark the implicit parameter to b with
|> the artificial attribute. This seems less satisfactory and less
|> definitive because in general there can be many reasons for
|> marking an entity as artificial; in particular, any implementation
|> may have other kinds of implicit/hidden parameters that just the
|> 'this' parameter.
|>
|> Using artificial in combination with the name 'this' does seem
|> like it has much to recommend it.
|>
|> Any thought or recommendation regarding what is considered good/
|> recommended practice is appreciated.
|
|I don't know what good practice may be, but GDB has been just using the
|artificial flag of the leading parameter for some time.  I think it
|would be nice to specify this in some more clear way.

David Anderson

There is the syntactic C++ element here for a member function like
    static void c( X* );
and whether the debugger can report it correctly.
Plus the debugger ability to call it correctly.
(these issues are closely tied together).


Kendrick Wong, Dec 2002:

|What is the expected dwarf 3 representation for const member functions?
|
|i.e.
|
|class K {
|  int foo const();
|};
|
|I'm not sure how to qualify a member function.  (It doesn't seem to make
|sense to use DW_TAG_const_type for member function)
|
|<1> DW_TAG_class_type
|      DW_AT_name  K
|<2> DW_TAG_subprogram
|      DW_AT_name  foo

"Brian Nettleton"
|I would expect that the "this" parameter is of type pointer to constant
|type.  But perhaps it would be worthwhile to have a specific attribute to
|identify a const member function?


The following is in the nature of a straw proposal in hopes
someone has a better proposal or modification of this one.

Adding two new attributes would be more 'regular', probably superior
than what follows.  Are there other ideas?


PROPOSAL:

Use an existing TAG and a new Attribute.
This is irregular and so not pleasing.

That two new paragraphs be added to section 5.6.7, Member Function entries.

"If a C++ member function is declared const, the function may
own a DW_TAG_const_type type modifier, signifying that the
function may not modify the object.
This type modifier would refer to nothing (reference to 0).
Normally in this case
the "this" parameter of the function (which would be marked
DW_AT_artificial as it is  the invisible "this " paramenter)
would also me marked with DW_TAG_const_type as  const pointer."


"If a C++ member function is declared static, the function
may have a DW_AT_static attribute, whose value is a flag
indicating whether this is a static member function."

=============================================

Revised proposal:
In Section 5.6.7 add the following text before the paragraph that
begins "If a subroutine entry represents the defining declaration...":

    "If the member function entry describes a non-static member
    function then that entry owns at least one formal parameter
    entry. The first such formal parameter entry
    corresponds to the object for which the function is called.
    The name attribute of that first formal parameter is defined by
    the current language (for example <code>this</code> for C++ or
    <code>self</code> for Objective-C++ and some other languages).
    The parameter also has a DW_AT_artificial attribute whose value
    is true. Conversely, if any of these properies does not apply
    then the member function entry describes a static member function.

    "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 first formal parameter has a type
    that has an equivalentl const-volatile qualification."

    *For simplicity, the type of the first formal parameter
    of a non-static member function need not be checked by a
    consumer to confirm that it is a pointer to the parent
    class or a const qualified variant thereof.

    See the example in Appendix D.4.*

After Example D.3 add a new section D.4 (moving the current D.4 and
following up a number):

    D.3 Member Functions Example:

    The C++ example in Figure #1 is used to illustrate the representation of
    member functions:

    Figure #1:
    class A
    {
     void func1(int x1);
     void func2() const;
     static void func3(int x3);
    };

    The DWARF representation in Figure #2 is appropriate:

    #2:

    1$:    DW_TAG_unspecified_type
           DW_AT_name("void")
           ...
    2$     DW_TAG_base_type
           DW_AT_name("int")
           ...
    3$:    DW_TAG_class_type
           DW_AT_name("A")
           ...
    4$:        DW_TAG_pointer_type
           DW_AT_type(reference to 3$)
           ...
    5$:        DW_TAG_const_type
           DW_AT_type(reference to 3$)
           ...
    6$:        DW_TAG_pointer_type
           DW_AT_type(reference to 5$)
           ...
    7$:        DW_TAG_subprogram
           DW_AT_name("func1")
           DW_AT_type(reference to 1$)
           ...
    8$:            DW_TAG_formal_parameter
               DW_AT_artificial(true)
               DW_AT_name("this")
               DW_AT_type(reference to 4$)
               ! Makes type of 'this' as 'A*' =>
               ! func1 has not been marked const or volatile
               DW_AT_location ...
               ...
    9$:            DW_TAG_formal_parameter
               DW_AT_name(x1)
               DW_AT_type(reference to 2$)
               ...
    10$:       DW_TAG_subprogram
           DW_AT_name("func2")
           DW_AT_type(reference to 1$)
           ...
    11$:           DW_TAG_formal_parameter
               DW_AT_artificial(true)
               DW_AT_name("this")
               DW_AT_type(reference to 6$)
               ! Makes type of 'this' as 'A const*' =>
               ! func2 marked as const
               DW_AT_location ...
               ...
    12$:       DW_TAG_subprogram
           DW_AT_name("func3")
           DW_AT_type(reference to 1$)
           ...
               ! No 'this' formal_parameter => func3 is static
    13$:           DW_TAG_formal_parameter
               DW_AT_name(x3)
               DW_AT_type(reference to 2$)
               ...