https://gcc.gnu.org/bugzilla/show_bug.cgi?id=120571

            Bug ID: 120571
           Summary: emit DWARF type declarations for incomplete types in
                    headers
           Product: gcc
           Version: unknown
            Status: UNCONFIRMED
          Severity: normal
          Priority: P3
         Component: debug
          Assignee: unassigned at gcc dot gnu.org
          Reporter: woodard at redhat dot com
  Target Milestone: ---

Consider:

impl.h:

struct Point;
int dist(struct Point p1, struct Point p2);
struct Point mid(struct Point p1, struct Point p2);
extern struct Point ORIGIN;

and v1.c:

#include "impl.h"

struct Point {
  int x, y;
};

struct Point ORIGIN = (struct Point){0, 0};
int dist(struct Point p1, struct Point p2) {
  return 0;
}

struct Point mid(struct Point p1, struct Point p2) {
  return ORIGIN; 
}

Currently the DWARF sets the declaration coordinates to the definition rather
than the original declaration found in the header file.

 <1><2e>: Abbrev Number: 4 (DW_TAG_structure_type)
    <2f>   DW_AT_name        : (indirect string, offset: 0x79): Point
    <33>   DW_AT_byte_size   : 8
    <34>   DW_AT_decl_file   : 1
    <35>   DW_AT_decl_line   : 3
    <36>   DW_AT_decl_column : 8

We would also like to have gcc emit DWARF fir the incomplete declaration found
in the header file which we think would look something like this with the
DW_AT_declaration flag set:

 <1><2e>: Abbrev Number: 4 (DW_TAG_structure_type)
    <2f>   DW_AT_name        : (indirect string, offset: 0x79): Point
    <34>   DW_AT_decl_file   : 2
    <35>   DW_AT_decl_line   : 1
    <36>   DW_AT_decl_column : 12
    <XX>   DW_AT_declaration : 1

Of course this would not include the data members because they would not have
been defined yet. I think at some point long ago GCC did emit these but it was
removed as a response to https://gcc.gnu.org/bugzilla/show_bug.cgi?id=54508
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=55059

However, we have a good use case where the information would be necessary:
We would like to be able to do something like:

$ abidiff --header-file1 test/include/public-api.h /usr/lib64/libproject.so
test/lib/libproject.so

When the user specifies a header file with --header-file1 then the types,
variables and functions which are not explicitly declared in the specified
header files are suppressed by default because they are implementation details.
While only the types, varibles and functions originally declared in a public
header are considered for ABI analysis. Currently, this cannot be done because
the DWARF only points to the definition of the type not the original incomplete
declaration of the type. So there is no way to identify from the existing DWARF
if the file was originally declared in the header file.

The problem is, the DWARF currently only points to the definition which is in
the C files, it doesn't enumerate the incomplete declarations in the header
files. If we had both the location of the incomplete declaration in the header
and the definition in the C file then ABI analysis tools such as libabigail
could automatically tell which functions, varibles and types are part of the
library's public API simply by virtue of the header it is in. This would
greatly simplify the process of verifying that the ABI of libraries are not
changing over time.

The current workaround is very cumbersome, a bespoke libabigail suppression
file must be created and maintained for each library which is part of our
collection of software. The mainual effort required to do this makes that
workaround unfeasible at a large scale.

To minimize the volume of additional DWARF being generated It is perfectly
acceptable to have this behavior only happen when requested with something
like: -gincomplete-types or have it rolled up when there extra debug
information is generated with an option like -g3. This should also help
minimize the impact on other tools which might have trouble dealing with the
DWARF having both an incomplete type for the declaration marked with
DW_AT_declaration and a full type definition. 

Tools which only need the full type definition can be taught to ignore
functions, variables, and types which include DW_AT_declaration and to assist
them in finding the full type definition DW_AT_sibling can be emitted in the
incomplete declaration to point them from the incomplete type to the full type
definition.

Reply via email to