Skip to content

Commit 066eea7

Browse files
committed
Revert "Reland "clang][DebugInfo] Emit global variable definitions for static data members with constant initializers (#70639)""
This casued asserts: llvm/lib/IR/Metadata.cpp:689: void llvm::MDNode::resolve(): Assertion `isUniqued() && "Expected this to be uniqued"' failed. See comments on the PR. This also reverts the dependent follow-up commits, see below. > When an LLDB user asks for the value of a static data member, LLDB > starts by searching the Names accelerator table for the corresponding > variable definition DIE. For static data members with out-of-class > definitions that works fine, because those get represented as global > variables with a location and making them eligible to be added to the > Names table. However, in-class definitions won<E2><80><99>t get indexed because > we usually don't emit global variables for them. So in DWARF we end > up with a single `DW_TAG_member` that usually holds the constant > initializer. But we don't get a corresponding CU-level > `DW_TAG_variable` like we do for out-of-class definitions. > > To make it more convenient for debuggers to get to the value of > inline static data members, this patch makes sure we emit definitions > for static variables with constant initializers the same way we do > for other static variables. This also aligns Clang closer to GCC, > which produces CU-level definitions for inline statics and also > emits these into `.debug_pubnames`. > > The implementation keeps track of newly created static data members. > Then in `CGDebugInfo::finalize`, we emit a global `DW_TAG_variable` > with a `DW_AT_const_value` for any of those declarations that didn't > end up with a definition in the `DeclCache`. > > The newly emitted `DW_TAG_variable` will look as follows: > ``` > 0x0000007b: DW_TAG_structure_type > DW_AT_calling_convention (DW_CC_pass_by_value) > DW_AT_name ("Foo") > ... > > 0x0000008d: DW_TAG_member > DW_AT_name ("i") > DW_AT_type (0x00000062 "const int") > DW_AT_external (true) > DW_AT_declaration (true) > DW_AT_const_value (4) > > Newly added > vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv > > 0x0000009a: DW_TAG_variable > DW_AT_specification (0x0000008d "i") > DW_AT_const_value (4) > DW_AT_linkage_name ("_ZN2t2IiE1iIfEE") > ``` > > This patch also drops the `DW_AT_const_value` off of the declaration > since we now always have it on the definition. This ensures that the > `DWARFParallelLinker` can type-merge class with static members where > we couldn't attach the constant on the declaration in some CUs. This reverts commit 7c3707a. This reverts commit cab0a19. This reverts commit 317481b. This reverts commit 15fc809. This reverts commit 470de2b.
1 parent a737a33 commit 066eea7

File tree

13 files changed

+48
-361
lines changed

13 files changed

+48
-361
lines changed

clang/lib/CodeGen/CGDebugInfo.cpp

Lines changed: 11 additions & 47 deletions
Original file line numberDiff line numberDiff line change
@@ -1677,13 +1677,22 @@ CGDebugInfo::CreateRecordStaticField(const VarDecl *Var, llvm::DIType *RecordTy,
16771677

16781678
unsigned LineNumber = getLineNumber(Var->getLocation());
16791679
StringRef VName = Var->getName();
1680+
llvm::Constant *C = nullptr;
1681+
if (Var->getInit()) {
1682+
const APValue *Value = Var->evaluateValue();
1683+
if (Value) {
1684+
if (Value->isInt())
1685+
C = llvm::ConstantInt::get(CGM.getLLVMContext(), Value->getInt());
1686+
if (Value->isFloat())
1687+
C = llvm::ConstantFP::get(CGM.getLLVMContext(), Value->getFloat());
1688+
}
1689+
}
16801690

16811691
llvm::DINode::DIFlags Flags = getAccessFlag(Var->getAccess(), RD);
16821692
auto Align = getDeclAlignIfRequired(Var, CGM.getContext());
16831693
llvm::DIDerivedType *GV = DBuilder.createStaticMemberType(
1684-
RecordTy, VName, VUnit, LineNumber, VTy, Flags, /* Val */ nullptr, Align);
1694+
RecordTy, VName, VUnit, LineNumber, VTy, Flags, C, Align);
16851695
StaticDataMemberCache[Var->getCanonicalDecl()].reset(GV);
1686-
StaticDataMemberDefinitionsToEmit.push_back(Var->getCanonicalDecl());
16871696
return GV;
16881697
}
16891698

@@ -5587,39 +5596,6 @@ void CGDebugInfo::EmitGlobalVariable(const ValueDecl *VD, const APValue &Init) {
55875596
TemplateParameters, Align));
55885597
}
55895598

5590-
void CGDebugInfo::EmitGlobalVariable(const VarDecl *VD) {
5591-
assert(VD->hasInit());
5592-
assert(CGM.getCodeGenOpts().hasReducedDebugInfo());
5593-
if (VD->hasAttr<NoDebugAttr>())
5594-
return;
5595-
5596-
auto &GV = DeclCache[VD];
5597-
if (GV)
5598-
return;
5599-
5600-
auto const *InitVal = VD->evaluateValue();
5601-
if (!InitVal)
5602-
return;
5603-
5604-
llvm::DIFile *Unit = nullptr;
5605-
llvm::DIScope *DContext = nullptr;
5606-
unsigned LineNo;
5607-
StringRef DeclName, LinkageName;
5608-
QualType T;
5609-
llvm::MDTuple *TemplateParameters = nullptr;
5610-
collectVarDeclProps(VD, Unit, LineNo, T, DeclName, LinkageName,
5611-
TemplateParameters, DContext);
5612-
5613-
auto Align = getDeclAlignIfRequired(VD, CGM.getContext());
5614-
llvm::DINodeArray Annotations = CollectBTFDeclTagAnnotations(VD);
5615-
llvm::DIExpression *InitExpr = createConstantValueExpression(VD, *InitVal);
5616-
5617-
GV.reset(DBuilder.createGlobalVariableExpression(
5618-
TheCU, DeclName, LinkageName, Unit, LineNo, getOrCreateType(T, Unit),
5619-
true, true, InitExpr, getOrCreateStaticDataMemberDeclarationOrNull(VD),
5620-
TemplateParameters, Align, Annotations));
5621-
}
5622-
56235599
void CGDebugInfo::EmitExternalVariable(llvm::GlobalVariable *Var,
56245600
const VarDecl *D) {
56255601
assert(CGM.getCodeGenOpts().hasReducedDebugInfo());
@@ -5890,18 +5866,6 @@ void CGDebugInfo::finalize() {
58905866
DBuilder.replaceTemporary(std::move(FwdDecl), cast<llvm::MDNode>(Repl));
58915867
}
58925868

5893-
for (auto const *VD : StaticDataMemberDefinitionsToEmit) {
5894-
assert(VD->isStaticDataMember());
5895-
5896-
if (DeclCache.contains(VD))
5897-
continue;
5898-
5899-
if (!VD->hasInit())
5900-
continue;
5901-
5902-
EmitGlobalVariable(VD);
5903-
}
5904-
59055869
// We keep our own list of retained types, because we need to look
59065870
// up the final type in the type cache.
59075871
for (auto &RT : RetainedTypes)

clang/lib/CodeGen/CGDebugInfo.h

Lines changed: 0 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -161,9 +161,6 @@ class CGDebugInfo {
161161
llvm::DenseMap<const Decl *, llvm::TypedTrackingMDRef<llvm::DIDerivedType>>
162162
StaticDataMemberCache;
163163

164-
/// Keeps track of static data members for which we should emit a definition.
165-
std::vector<const VarDecl *> StaticDataMemberDefinitionsToEmit;
166-
167164
using ParamDecl2StmtTy = llvm::DenseMap<const ParmVarDecl *, const Stmt *>;
168165
using Param2DILocTy =
169166
llvm::DenseMap<const ParmVarDecl *, llvm::DILocalVariable *>;
@@ -529,9 +526,6 @@ class CGDebugInfo {
529526
/// Emit a constant global variable's debug info.
530527
void EmitGlobalVariable(const ValueDecl *VD, const APValue &Init);
531528

532-
/// Emit debug-info for a variable with a constant initializer.
533-
void EmitGlobalVariable(const VarDecl *VD);
534-
535529
/// Emit information about an external variable.
536530
void EmitExternalVariable(llvm::GlobalVariable *GV, const VarDecl *Decl);
537531

clang/test/CodeGenCXX/debug-info-class.cpp

Lines changed: 4 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -116,19 +116,11 @@ int main(int argc, char **argv) {
116116
// CHECK-SAME: DIFlagFwdDecl
117117
// CHECK-NOT: identifier:
118118
// CHECK-SAME: ){{$}}
119-
120-
// CHECK: !DIGlobalVariableExpression(var: ![[HDR_VAR:[0-9]+]], expr: !DIExpression(DW_OP_constu, 52, DW_OP_stack_value))
121-
// CHECK: ![[HDR_VAR]] = distinct !DIGlobalVariable(name: "HdrSize",
122-
// CHECK-SAME: isLocal: true, isDefinition: true, declaration: ![[HDR_VAR_DECL:[0-9]+]])
123-
// CHECK: ![[INT:[0-9]+]] = !DIBasicType(name: "int"
124-
// CHECK: ![[HDR_VAR_DECL]] = !DIDerivedType(tag: DW_TAG_member, name: "HdrSize"
125-
126-
// CHECK: !DICompositeType(tag: DW_TAG_structure_type, name: "A"
127-
128119
// CHECK: !DICompositeType(tag: DW_TAG_structure_type, name: "I"
129120
// CHECK-NOT: DIFlagFwdDecl
130121
// CHECK-SAME: ){{$}}
131122

123+
// CHECK: ![[INT:[0-9]+]] = !DIBasicType(name: "int"
132124
// CHECK: !DICompositeType(tag: DW_TAG_structure_type, name: "foo"
133125
// CHECK: !DICompositeType(tag: DW_TAG_class_type, name: "bar"
134126
// CHECK: !DICompositeType(tag: DW_TAG_union_type, name: "baz"
@@ -194,5 +186,8 @@ int main(int argc, char **argv) {
194186
// CHECK: [[G_INNER_I]] = !DIDerivedType(tag: DW_TAG_member, name: "j"
195187
// CHECK-SAME: baseType: ![[INT]]
196188

189+
// CHECK: !DICompositeType(tag: DW_TAG_structure_type, name: "A"
190+
// CHECK: !DIDerivedType(tag: DW_TAG_member, name: "HdrSize"
191+
//
197192
// CHECK: ![[EXCEPTLOC]] = !DILocation(line: 100,
198193
// CHECK: ![[RETLOC]] = !DILocation(line: 99,

clang/test/CodeGenCXX/debug-info-static-inline-member.cpp

Lines changed: 0 additions & 94 deletions
This file was deleted.

clang/test/CodeGenCXX/debug-info-static-member.cpp

Lines changed: 20 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -63,32 +63,32 @@ int C::a = 4;
6363
// CHECK-NOT: offset:
6464
// CHECK-SAME: flags: DIFlagStaticMember)
6565
//
66-
// CHECK: ![[CONST_A_DECL:[0-9]+]] = !DIDerivedType(tag: DW_TAG_member, name: "const_a"
67-
// CHECK-NOT: size:
68-
// CHECK-NOT: align:
69-
// CHECK-NOT: offset:
70-
// CHECK-SAME: flags: DIFlagStaticMember
71-
// CHECK-NOT: extraData:
72-
73-
// CHECK: ![[CONST_B_DECL:[0-9]+]] = !DIDerivedType(tag: DW_TAG_member, name: "const_b"
74-
// CHECK-NOT: size:
75-
// CHECK-NOT: align:
76-
// CHECK-NOT: offset:
77-
// CHECK-SAME: flags: DIFlagProtected | DIFlagStaticMember
78-
// CHECK-NOT: extraData:
66+
// CHECK: !DIDerivedType(tag: DW_TAG_member, name: "const_a"
67+
// CHECK-NOT: size:
68+
// CHECK-NOT: align:
69+
// CHECK-NOT: offset:
70+
// CHECK-SAME: flags: DIFlagStaticMember,
71+
// CHECK-SAME: extraData: i1 true)
72+
73+
// CHECK: !DIDerivedType(tag: DW_TAG_member, name: "const_b"
74+
// CHECK-NOT: size:
75+
// CHECK-NOT: align:
76+
// CHECK-NOT: offset:
77+
// CHECK-SAME: flags: DIFlagProtected | DIFlagStaticMember,
78+
// CHECK-SAME: extraData: float 0x{{.*}})
7979

8080
// CHECK: ![[DECL_C:[0-9]+]] = !DIDerivedType(tag: DW_TAG_member, name: "c"
8181
// CHECK-NOT: size:
8282
// CHECK-NOT: align:
8383
// CHECK-NOT: offset:
8484
// CHECK-SAME: flags: DIFlagPublic | DIFlagStaticMember)
8585
//
86-
// CHECK: ![[CONST_C_DECL:[0-9]+]] = !DIDerivedType(tag: DW_TAG_member, name: "const_c"
87-
// CHECK-NOT: size:
88-
// CHECK-NOT: align:
89-
// CHECK-NOT: offset:
90-
// CHECK-SAME: flags: DIFlagPublic | DIFlagStaticMember
91-
// CHECK-NOT: extraData:
86+
// CHECK: !DIDerivedType(tag: DW_TAG_member, name: "const_c"
87+
// CHECK-NOT: size:
88+
// CHECK-NOT: align:
89+
// CHECK-NOT: offset:
90+
// CHECK-SAME: flags: DIFlagPublic | DIFlagStaticMember,
91+
// CHECK-SAME: extraData: i32 18)
9292
//
9393
// CHECK: !DIDerivedType(tag: DW_TAG_member, name: "x_a"
9494
// CHECK-SAME: flags: DIFlagPublic | DIFlagStaticMember)
@@ -144,7 +144,7 @@ struct V {
144144
// const_va is not emitted for MS targets.
145145
// NOT-MS: !DIDerivedType(tag: DW_TAG_member, name: "const_va",
146146
// NOT-MS-SAME: line: [[@LINE-5]]
147-
// NOT-MS-NOT: extraData:
147+
// NOT-MS-SAME: extraData: i32 42
148148
const int V::const_va;
149149

150150
namespace x {
@@ -156,15 +156,3 @@ struct y {
156156
};
157157
int y::z;
158158
}
159-
160-
// CHECK: !DIGlobalVariableExpression(var: ![[CONST_A_VAR:[0-9]+]], expr: !DIExpression(DW_OP_constu, 1, DW_OP_stack_value))
161-
// CHECK: ![[CONST_A_VAR]] = distinct !DIGlobalVariable(name: "const_a"
162-
// CHECK-SAME: isLocal: true, isDefinition: true, declaration: ![[CONST_A_DECL]])
163-
164-
// CHECK: !DIGlobalVariableExpression(var: ![[CONST_B_VAR:[0-9]+]], expr: !DIExpression(DW_OP_constu, {{.*}}, DW_OP_stack_value))
165-
// CHECK: ![[CONST_B_VAR]] = distinct !DIGlobalVariable(name: "const_b"
166-
// CHECK-SAME: isLocal: true, isDefinition: true, declaration: ![[CONST_B_DECL]])
167-
168-
// CHECK: !DIGlobalVariableExpression(var: ![[CONST_C_VAR:[0-9]+]], expr: !DIExpression(DW_OP_constu, 18, DW_OP_stack_value))
169-
// CHECK: ![[CONST_C_VAR]] = distinct !DIGlobalVariable(name: "const_c"
170-
// CHECK-SAME: isLocal: true, isDefinition: true, declaration: ![[CONST_C_DECL]])

lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.cpp

Lines changed: 1 addition & 62 deletions
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,6 @@
3131
#include "lldb/Symbol/SymbolFile.h"
3232
#include "lldb/Symbol/TypeList.h"
3333
#include "lldb/Symbol/TypeMap.h"
34-
#include "lldb/Symbol/VariableList.h"
3534
#include "lldb/Target/Language.h"
3635
#include "lldb/Utility/LLDBAssert.h"
3736
#include "lldb/Utility/Log.h"
@@ -134,54 +133,6 @@ static lldb::ModuleSP GetContainingClangModule(const DWARFDIE &die) {
134133
return lldb::ModuleSP();
135134
}
136135

137-
std::optional<DWARFFormValue>
138-
DWARFASTParserClang::FindConstantOnVariableDefinition(DWARFDIE die) {
139-
assert(die.Tag() == llvm::dwarf::DW_TAG_member);
140-
141-
auto *dwarf = die.GetDWARF();
142-
if (!dwarf)
143-
return {};
144-
145-
ConstString name{die.GetName()};
146-
if (!name)
147-
return {};
148-
149-
auto *CU = die.GetCU();
150-
if (!CU)
151-
return {};
152-
153-
DWARFASTParser *dwarf_ast = dwarf->GetDWARFParser(*CU);
154-
auto parent_decl_ctx = dwarf_ast->GetDeclContextContainingUIDFromDWARF(die);
155-
156-
// Make sure we populate the GetDieToVariable cache.
157-
VariableList variables;
158-
dwarf->FindGlobalVariables(name, parent_decl_ctx, UINT_MAX, variables);
159-
160-
// The cache contains the variable definition whose DW_AT_specification
161-
// points to our declaration DIE. Look up that definition using our
162-
// declaration.
163-
auto const &die_to_var = dwarf->GetDIEToVariable();
164-
auto it = die_to_var.find(die.GetDIE());
165-
if (it == die_to_var.end())
166-
return {};
167-
168-
auto var_sp = it->getSecond();
169-
assert(var_sp != nullptr);
170-
171-
if (!var_sp->GetLocationIsConstantValueData())
172-
return {};
173-
174-
auto def = dwarf->GetDIE(var_sp->GetID());
175-
auto def_attrs = def.GetAttributes();
176-
DWARFFormValue form_value;
177-
if (!def_attrs.ExtractFormValueAtIndex(
178-
def_attrs.FindAttributeIndex(llvm::dwarf::DW_AT_const_value),
179-
form_value))
180-
return {};
181-
182-
return form_value;
183-
}
184-
185136
TypeSP DWARFASTParserClang::ParseTypeFromClangModule(const SymbolContext &sc,
186137
const DWARFDIE &die,
187138
Log *log) {
@@ -2955,21 +2906,9 @@ void DWARFASTParserClang::ParseSingleMember(
29552906

29562907
bool unused;
29572908
// TODO: Support float/double static members as well.
2958-
if (!ct.IsIntegerOrEnumerationType(unused))
2909+
if (!attrs.const_value_form || !ct.IsIntegerOrEnumerationType(unused))
29592910
return;
29602911

2961-
// Newer versions of Clang don't emit the DW_AT_const_value
2962-
// on the declaration of an inline static data member. Instead
2963-
// it's attached to the definition DIE. If that's the case,
2964-
// try and fetch it.
2965-
if (!attrs.const_value_form) {
2966-
auto maybe_form_value = FindConstantOnVariableDefinition(die);
2967-
if (!maybe_form_value)
2968-
return;
2969-
2970-
attrs.const_value_form = *maybe_form_value;
2971-
}
2972-
29732912
llvm::Expected<llvm::APInt> const_value_or_err =
29742913
ExtractIntFromFormValue(ct, *attrs.const_value_form);
29752914
if (!const_value_or_err) {

0 commit comments

Comments
 (0)