Skip to content

Commit 5d94f34

Browse files
committed
[DebugInfo] Produce debuginfo for nested types when the outer type is [[clang::standalone_debug]].
Without this, it's impossible to get debuginfo for a nested type that is unused (or that clang mistakenly believes is unused due to e.g. deficiencies in -debug-info-kind=limited), even by marking the "unused" nested type itself with [[clang::standalone_debug]]. This makes writing pretty-printers and similar things difficult. The [[clang::standalone_debug]] attribute is not propagated to the nested type. But after applying [[clang::standalone_debug]] to the outer type to ensure the nested type appears in the debuginfo at all, a developer can also additionally apply the attribute to the nested type if desired.
1 parent ec1c73b commit 5d94f34

File tree

2 files changed

+33
-3
lines changed

2 files changed

+33
-3
lines changed

clang/lib/CodeGen/CGDebugInfo.cpp

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2075,12 +2075,13 @@ void CGDebugInfo::CollectRecordFields(
20752075

20762076
// Bump field number for next field.
20772077
++fieldNo;
2078-
} else if (CGM.getCodeGenOpts().EmitCodeView) {
2078+
} else if (CGM.getCodeGenOpts().EmitCodeView ||
2079+
record->hasAttr<StandaloneDebugAttr>()) {
20792080
// Debug info for nested types is included in the member list only for
2080-
// CodeView.
2081+
// CodeView and types with the standalone_debug attribute.
20812082
if (const auto *nestedType = dyn_cast<TypeDecl>(I)) {
20822083
// MSVC doesn't generate nested type for anonymous struct/union.
2083-
if (isa<RecordDecl>(I) &&
2084+
if (CGM.getCodeGenOpts().EmitCodeView && isa<RecordDecl>(I) &&
20842085
cast<RecordDecl>(I)->isAnonymousStructOrUnion())
20852086
continue;
20862087
if (!nestedType->isImplicit() &&
Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
// RUN: %clang_cc1 -DSETATTR=0 -triple x86_64-unknown-linux-gnu -emit-llvm -debug-info-kind=limited %s -o - | FileCheck %s --check-prefix=DEBUG
2+
// RUN: %clang_cc1 -DSETATTR=1 -triple x86_64-unknown-linux-gnu -emit-llvm -debug-info-kind=limited %s -o - | FileCheck %s --check-prefix=WITHATTR
3+
// Use -debug-info-kind=limited because an unused type will never have a used ctor.
4+
5+
#if SETATTR
6+
#define STANDALONEDEBUGATTR __attribute__((standalone_debug))
7+
#else
8+
#define STANDALONEDEBUGATTR
9+
#endif
10+
11+
struct STANDALONEDEBUGATTR TypeWithNested {
12+
struct Unused1 {
13+
};
14+
struct STANDALONEDEBUGATTR Unused2 {
15+
};
16+
17+
int value = 0;
18+
};
19+
void f(TypeWithNested s) {}
20+
// DEBUG: !DICompositeType(tag: DW_TAG_structure_type, name: "TypeWithNested"
21+
// DEBUG-NOT: !DICompositeType(tag: DW_TAG_structure_type, name: "Unused1"
22+
// DEBUG-NOT: !DICompositeType(tag: DW_TAG_structure_type, name: "Unused2"
23+
// WITHATTR: !DICompositeType(tag: DW_TAG_structure_type, name: "TypeWithNested"
24+
// WITHATTR: !DICompositeType(tag: DW_TAG_structure_type, name: "Unused1"
25+
// The STANDALONEDEBUGATTR isn't propagated to the nested type by default, so
26+
// it should still be a forward declaration.
27+
// WITHATTR-SAME: DIFlagFwdDecl
28+
// WITHATTR: !DICompositeType(tag: DW_TAG_structure_type, name: "Unused2"
29+
// WITHATTR-NOT: DIFlagFwdDecl

0 commit comments

Comments
 (0)