|
10 | 10 |
|
11 | 11 | #include "DWARFASTParser.h"
|
12 | 12 | #include "DWARFASTParserClang.h"
|
| 13 | +#include "DWARFCompileUnit.h" |
13 | 14 | #include "DWARFDebugInfo.h"
|
14 | 15 | #include "DWARFDeclContext.h"
|
15 | 16 | #include "DWARFDefines.h"
|
|
26 | 27 | #include "lldb/Core/Value.h"
|
27 | 28 | #include "lldb/Host/Host.h"
|
28 | 29 | #include "lldb/Symbol/CompileUnit.h"
|
| 30 | +#include "lldb/Symbol/CompilerDeclContext.h" |
29 | 31 | #include "lldb/Symbol/Function.h"
|
30 | 32 | #include "lldb/Symbol/ObjectFile.h"
|
31 | 33 | #include "lldb/Symbol/SymbolFile.h"
|
32 | 34 | #include "lldb/Symbol/TypeList.h"
|
33 | 35 | #include "lldb/Symbol/TypeMap.h"
|
| 36 | +#include "lldb/Symbol/VariableList.h" |
34 | 37 | #include "lldb/Target/Language.h"
|
35 | 38 | #include "lldb/Utility/LLDBAssert.h"
|
36 | 39 | #include "lldb/Utility/Log.h"
|
@@ -133,6 +136,52 @@ static lldb::ModuleSP GetContainingClangModule(const DWARFDIE &die) {
|
133 | 136 | return lldb::ModuleSP();
|
134 | 137 | }
|
135 | 138 |
|
| 139 | +std::optional<DWARFFormValue> |
| 140 | +DWARFASTParserClang::FindConstantOnVariableDefinition(DWARFDIE die) { |
| 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 | + |
136 | 185 | TypeSP DWARFASTParserClang::ParseTypeFromClangModule(const SymbolContext &sc,
|
137 | 186 | const DWARFDIE &die,
|
138 | 187 | Log *log) {
|
@@ -2906,9 +2955,21 @@ void DWARFASTParserClang::ParseSingleMember(
|
2906 | 2955 |
|
2907 | 2956 | bool unused;
|
2908 | 2957 | // TODO: Support float/double static members as well.
|
2909 |
| - if (!attrs.const_value_form || !ct.IsIntegerOrEnumerationType(unused)) |
| 2958 | + if (!ct.IsIntegerOrEnumerationType(unused)) |
2910 | 2959 | return;
|
2911 | 2960 |
|
| 2961 | + // Newer versions of Clang don't emit the DW_AT_const_value |
| 2962 | + // on the declaration of a 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 | + |
2912 | 2973 | llvm::Expected<llvm::APInt> const_value_or_err =
|
2913 | 2974 | ExtractIntFromFormValue(ct, *attrs.const_value_form);
|
2914 | 2975 | if (!const_value_or_err) {
|
|
0 commit comments