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.