991110.1 B A J. Merrill C++ Namespace support

This proposal was rewritten by David Anderson.  The original.

=== BACKGROUND

The C++ feature of 'namespace' was invented after the 1993
dwarf2 specification was completed, so currently dwarf2 has
no means of representing C++ namespace information.

This proposes a way of adding namespace support.

This proposal reflects input from the Feb 22, 2000 meeting.

==== OVERVIEW
Use a new tag DW_TAG_namespace to represent
a namespace declaration. DW_TAG_namespace can be nested.

Add to an existing namespace with a
DW_TAG_namespace with a new attribute DW_AT_extension pointing to the
previous extension (the previous
extension might be the base namespace declaration).

Specify a using-directive with a new tag DW_TAG_imported_module,
with a DW_AT_import attribute
referring to DW_TAG_namespace of the previous extension
of this namespace (which might be the base namespace declaration).

Specify a using-declaration with the
existing tag DW_TAG_imported_declaration,
with a DW_AT_import attribute
referring to the declaration being imported
(that imported declaration cannot, by C++ rules, be
a DW_TAG_namespace, ISO C++1998 7.3.3,3.4.1).

Namespace-aliases use the existing tag DW_TAG_imported_declaration
and DW_TAG_imported_declaration has DW_AT_name to
signify this is a namespace alias, not a using-declaration..
The DW_TAG_imported_declaration has a DW_AT_import referring to the
DW_TAG_namespace of the extension
of this namespace (which might be the base namespace declaration)
it refers to.

Namespaces also affect .debug_pubnames, so one paragraph
in the pubnames discussion is altered. See below.

General comment:
Because namespace std is ubiquitous
namespace std is a prime candidate for a comdat approach
so as to avoid the otherwise-natural bloat in
duplicating namespace std information in every compilation unit.
Because namespace std is extended by many headers,
and those headers are not always #included in the same order in
a compilation unit using comdat may be difficult for the
implementation?

There is no mention that duplication/bloat problem below, as
the comdat stuff has not been approved.
But serious bloat could result from this...

===== Document changes, referring to May 5 draft page numbers:

page 6
Figure 1: add
        DW_TAG_namespace
        DW_TAG_imported_module

page 9:
Figure 2: add
        DW_AT_extension      "refers from namespace extension back to
                            previous extension
                            or back to base namespace declaration"

Page 103
Figure 15: add
        DW_TAG_namespace 0x39 (or next available value)
        DW_TAG_imported_module 0x40

Page 106
Figure 17: add
        DW_AT_extension 0x52 (or next available value)

Page 127(approx)
Appendix 1, add
        DW_TAG_namespace DECL
                        DW_AT_name
                        DW_AT_extension
        DW_TAG_imported_module DECL
                        DW_AT_import


For the main discussion, create a new section (5.15 seems
to be the next appropriate number) in the 'type entries'
chapter.

Section 5.15 "Namespaces"

(italics:)
C++ has the notion of a namespace, which
is a way to implement name hiding, so that
names of unrelated things do not accidentally clash in the
global space when an application is linked together.

(normal type:)
Namespace entries may contain declarations
and may also
contain declarations which
are also object or function definitions.

If a type, variable, or function declared
in a namespace is defined outside
of the body of the namespace declaration,
the type, variable, or function has a DW_AT_specification
attribute, whose value is a reference to the debugging information
entry representing the declaration of the type, variable or function.

Types, variables, or functions with a DW_AT_specification
attribute do not need to duplicate information
provided by the declaration entry referenced by the
specification attribute.

The tag DW_TAG_namespace is used to represent
a namespace. A namespace extension is represented
by a DW_TAG_namespace with
a DW_AT_extension attribute referring to the previous
extension (if there is no previous extension, the
DW_AT_extension refers to the base DW_TAG_namespace declaration).
A namespace extension does not need to duplicate
information in a previous extension of the namespace nor
need it duplicate information in the base DW_TAG_namespace
(so a DW_AT_name attribute need only be attached
directly to the base DW_TAG_namespace, for a namespace with a name).


The tag DW_TAG_imported_declaration
is used to represent a namespace-alias.
It contains a DW_AT_name giving the alias name.
It contains a DW_AT_import referring to the applicable
namespace extension
(if there is no namespace extension, the
DW_AT_import refers to the base DW_TAG_namespace declaration).
It contains a DW_AT_name giving the alias name.

A using-declaration is represented with
the tag DW_TAG_imported_declaration.
It contains a DW_AT_import attribute
referring to the declaration being imported
It contains no DW_AT_name attribute, distinguishing this
from a namespace-alias.
(italics)
  That imported declaration cannot, by C++ rules, be
  a DW_TAG_namespace, ISO/IEC 14222:1998 7.3.3,3.4.1.

A using-directive is represented with the
tag DW_TAG_imported_module,
with a DW_AT_import attribute
referring to DW_TAG_namespace of the previous extension
of this namespace (which might be the base namespace declaration).

The global namespace (the namespace referred to by "::f",
for example) is not explicitly represented in dwarf with
a DW_TAG_namespace (thus mirroring the situation in C++ source).
Global items are simply declared
with no reference to a namespace, and that is how they should appear
in dwarf.

The compilation-unit-specific "unnamed namespace"
(ISO/IEC 14222:1998 7.3.1.1)
is represented by a DW_TAG_namespace with no DW_AT_name
attribute in the base namespace declaration (and therefore
no DW_AT_name in any namespace extension of this namespace either).


(italics:)
A compiler emitting namespace
information may choose to explicitly show namespace
extensions, or to simply show the final namespace
declaration of a compilation unit:
this is a quality-of-implementation issue
and no specific requirements are imposed.
If only the final namespace is shown it is impossible
to interpret using-declaration references in
exactly the manner defined by the C++ standard: see
ISO/IEC 14222:1998, 7.3.2, paragraph number 9.

(italics:)
A simple emission of all namespace declaration information
in all compilation units could result in a significant
increase in the size of the debug information and
significant duplication of information
across compilation units.
C++ namespace std, for example, is large
and will probably be referred to in
every C++ compilation unit.

(normal text:)


C++ example:
namespace {
  int i;
}

namespace A {
  namespace B {
    int j;
    int myfunc(int a);
    int myfunc2(int a) { return a +2;}
  }
}

namespace Y {
    using A::B::j; // using declaration
    int foo;
}

using A::B::j; // using-declaration

namespace Foo = A::B; // namespace-alias

using namespace Foo; // using-directive


namespace A {
  namespace B {
    using namespace Y; // using-directive
    int k;
  }
}

int Foo::myfunc(int a)
{
    i = 3;
    j = 4;
    return myfunc2(3) + j +i + a + 2;
}



A representation of the above, offsets represented
only where necessary:

0x0     DW_TAG_basetype
            DW_AT_name "int"
            ...
0x6     DW_TAG_namespace
            <no AT_name>
        DW_TAG_variable
            DW_AT_name "i"
            DW_AT_type 0x0
            DW_AT_location ...
            ...


0x10:   DW_TAG_namespace
            DW_AT_name "A"
0x20:   DW_TAG_namespace
            DW_AT_name "B"
0x30:   DW_TAG_variable
            DW_AT_name "j"
            DW_AT_type 0x0
            DW_AT_location ...
            ...
0x34:  DW_TAG_subprogram
            DW_AT_name "myfunc"
            DW_AT_type 0x0
            ...
       DW_TAG_subprogram
            DW_AT_name "myfunc2"
            DW_AT_low_pc ...
            DW_AT_high_pc ...
            DW_AT_type 0x0
            ...


0x40:  DW_TAG_namespace
            DW_AT_name "Y"
               DW_TAG_imported_declaration // using-declaration
                    DW_AT_import 0x30
               DW_TAG_variable
                    DW_AT_name "foo";
                    DW_AT_type 0x0
                    DW_AT_location ...
                    ...

       DW_TAG_imported_declaration // using-declaration
            DW_AT_import 0x30

       DW_TAG_imported_declaration // namespace alias
            DW_AT_name "Foo"
            DW_AT_import 0x20

       DW_TAG_imported_module // using-directive
            DW_AT_import 0x20

       DW_TAG_namespace
            DW_AT_extension 0x10
            DW_TAG_namespace
                DW_AT_extension 0x20
                DW_TAG_imported_module // using-directive
                    DW_AT_import 0x40
                DW_TAG_variable
                    DW_AT_name "k"
                    DW_AT_type 0x0
                    DW_AT_location ...
                    ...

0x60   DW_TAG_subprogram
            DW_AT_name "myfunc"
            DW_AT_specification 0x34
            DW_AT_low_pc ...
            DW_AT_high_pc ...
            ...

==========section 6.1.1, Lookup By Name

Change the last paragraph to:

In the case of the name of a function member or static data
member of a C++ structure, class, or union, or
of the name of a member of a namespace, the name
represented in the .debug_pubnames section is not the
simple name given by the DW_AT_name attribute of the referenced
debugging entry, but rather the fully namespace-and-class qualified
name of the debugging entry.
Names in an unnamed-namespace declaration never appear
in the .debug_pubnames section as such names are effectively
private to a compilation unit.