@@ -159,6 +159,76 @@ static bool TagIsRecordType(dw_tag_t tag) {
159
159
}
160
160
}
161
161
162
+ // / Get the object parameter DIE if one exists, otherwise returns
163
+ // / a default DWARFDIE. If \c containing_decl_ctx is not a valid
164
+ // / C++ declaration context for class methods, assume no object
165
+ // / parameter exists for the given \c subprogram.
166
+ static DWARFDIE
167
+ GetCXXObjectParameter (const DWARFDIE &subprogram,
168
+ const clang::DeclContext &containing_decl_ctx) {
169
+ assert (subprogram.Tag () == DW_TAG_subprogram ||
170
+ subprogram.Tag () == DW_TAG_inlined_subroutine ||
171
+ subprogram.Tag () == DW_TAG_subroutine_type);
172
+
173
+ if (!DeclKindIsCXXClass (containing_decl_ctx.getDeclKind ()))
174
+ return {};
175
+
176
+ // FIXME: if subprogram has a explicit DW_AT_object_pointer, use it.
177
+
178
+ // If no DW_AT_object_pointer was specified, assume the implicit object
179
+ // parameter is the first parameter to the function, is called "this" and is
180
+ // artificial (which is what most compilers would generate).
181
+ auto children = subprogram.children ();
182
+ auto it = llvm::find_if (children, [](const DWARFDIE &child) {
183
+ return child.Tag () == DW_TAG_formal_parameter;
184
+ });
185
+
186
+ if (it == children.end ())
187
+ return {};
188
+
189
+ DWARFDIE object_pointer = *it;
190
+
191
+ if (!object_pointer.GetAttributeValueAsUnsigned (DW_AT_artificial, 0 ))
192
+ return {};
193
+
194
+ // Often times compilers omit the "this" name for the
195
+ // specification DIEs, so we can't rely upon the name being in
196
+ // the formal parameter DIE...
197
+ if (const char *name = object_pointer.GetName ();
198
+ name && ::strcmp (name, " this" ) != 0 )
199
+ return {};
200
+
201
+ return object_pointer;
202
+ }
203
+
204
+ // / In order to determine the CV-qualifiers for a C++ class
205
+ // / method in DWARF, we have to look at the CV-qualifiers of
206
+ // / the object parameter's type.
207
+ static unsigned GetCXXMethodCVQuals (const DWARFDIE &subprogram,
208
+ const DWARFDIE &object_parameter) {
209
+ if (!subprogram || !object_parameter)
210
+ return 0 ;
211
+
212
+ Type *this_type = subprogram.ResolveTypeUID (
213
+ object_parameter.GetAttributeValueAsReferenceDIE (DW_AT_type));
214
+ if (!this_type)
215
+ return 0 ;
216
+
217
+ uint32_t encoding_mask = this_type->GetEncodingMask ();
218
+
219
+ // FIXME: explicit object parameters need not to be pointers
220
+ if (!(encoding_mask & (1u << Type::eEncodingIsPointerUID)))
221
+ return 0 ;
222
+
223
+ unsigned cv_quals = 0 ;
224
+ if (encoding_mask & (1u << Type::eEncodingIsConstUID))
225
+ cv_quals |= clang::Qualifiers::Const;
226
+ if (encoding_mask & (1u << Type::eEncodingIsVolatileUID))
227
+ cv_quals |= clang::Qualifiers::Volatile;
228
+
229
+ return cv_quals;
230
+ }
231
+
162
232
TypeSP DWARFASTParserClang::ParseTypeFromClangModule (const SymbolContext &sc,
163
233
const DWARFDIE &die,
164
234
Log *log) {
@@ -1188,11 +1258,8 @@ DWARFASTParserClang::ParseSubroutine(const DWARFDIE &die,
1188
1258
const dw_tag_t tag = die.Tag ();
1189
1259
1190
1260
bool is_variadic = false ;
1191
- bool is_static = false ;
1192
1261
bool has_template_params = false ;
1193
1262
1194
- unsigned type_quals = 0 ;
1195
-
1196
1263
DEBUG_PRINTF (" 0x%8.8" PRIx64 " : %s (\" %s\" )\n " , die.GetID (),
1197
1264
DW_TAG_value_to_name (tag), type_name_cstr);
1198
1265
@@ -1215,23 +1282,15 @@ DWARFASTParserClang::ParseSubroutine(const DWARFDIE &die,
1215
1282
DWARFDIE decl_ctx_die;
1216
1283
clang::DeclContext *containing_decl_ctx =
1217
1284
GetClangDeclContextContainingDIE (die, &decl_ctx_die);
1218
- const clang::Decl::Kind containing_decl_kind =
1219
- containing_decl_ctx->getDeclKind ();
1220
-
1221
- bool is_cxx_method = DeclKindIsCXXClass (containing_decl_kind);
1222
- // Start off static. This will be set to false in
1223
- // ParseChildParameters(...) if we find a "this" parameters as the
1224
- // first parameter
1225
- if (is_cxx_method) {
1226
- is_static = true ;
1227
- }
1285
+ assert (containing_decl_ctx);
1228
1286
1229
1287
if (die.HasChildren ()) {
1230
- ParseChildParameters (containing_decl_ctx, die, is_static, is_variadic,
1288
+ ParseChildParameters (containing_decl_ctx, die, is_variadic,
1231
1289
has_template_params, function_param_types,
1232
- function_param_decls, type_quals );
1290
+ function_param_decls);
1233
1291
}
1234
1292
1293
+ bool is_cxx_method = DeclKindIsCXXClass (containing_decl_ctx->getDeclKind ());
1235
1294
bool ignore_containing_context = false ;
1236
1295
// Check for templatized class member functions. If we had any
1237
1296
// DW_TAG_template_type_parameter or DW_TAG_template_value_parameter
@@ -1251,12 +1310,16 @@ DWARFASTParserClang::ParseSubroutine(const DWARFDIE &die,
1251
1310
clang::CallingConv calling_convention =
1252
1311
ConvertDWARFCallingConventionToClang (attrs);
1253
1312
1313
+ const DWARFDIE object_parameter =
1314
+ GetCXXObjectParameter (die, *containing_decl_ctx);
1315
+
1254
1316
// clang_type will get the function prototype clang type after this
1255
1317
// call
1256
1318
CompilerType clang_type =
1257
1319
m_ast.CreateFunctionType (return_clang_type, function_param_types.data (),
1258
1320
function_param_types.size (), is_variadic,
1259
- type_quals, calling_convention, attrs.ref_qual );
1321
+ GetCXXMethodCVQuals (die, object_parameter),
1322
+ calling_convention, attrs.ref_qual );
1260
1323
1261
1324
if (attrs.name ) {
1262
1325
bool type_handled = false ;
@@ -1267,6 +1330,8 @@ DWARFASTParserClang::ParseSubroutine(const DWARFDIE &die,
1267
1330
type_handled =
1268
1331
ParseObjCMethod (*objc_method, die, clang_type, attrs, is_variadic);
1269
1332
} else if (is_cxx_method) {
1333
+ // In DWARF, a C++ method is static if it has no object parameter child.
1334
+ const bool is_static = !object_parameter.IsValid ();
1270
1335
auto [handled, type_sp] =
1271
1336
ParseCXXMethod (die, clang_type, attrs, decl_ctx_die, is_static,
1272
1337
ignore_containing_context);
@@ -2315,10 +2380,8 @@ size_t DWARFASTParserClang::ParseChildEnumerators(
2315
2380
2316
2381
ConstString
2317
2382
DWARFASTParserClang::ConstructDemangledNameFromDWARF (const DWARFDIE &die) {
2318
- bool is_static = false ;
2319
2383
bool is_variadic = false ;
2320
2384
bool has_template_params = false ;
2321
- unsigned type_quals = 0 ;
2322
2385
std::vector<CompilerType> param_types;
2323
2386
std::vector<clang::ParmVarDecl *> param_decls;
2324
2387
StreamString sstr;
@@ -2328,9 +2391,13 @@ DWARFASTParserClang::ConstructDemangledNameFromDWARF(const DWARFDIE &die) {
2328
2391
2329
2392
clang::DeclContext *containing_decl_ctx =
2330
2393
GetClangDeclContextContainingDIE (die, nullptr );
2331
- ParseChildParameters (containing_decl_ctx, die, is_static, is_variadic,
2332
- has_template_params, param_types, param_decls,
2333
- type_quals);
2394
+ assert (containing_decl_ctx);
2395
+
2396
+ const unsigned cv_quals = GetCXXMethodCVQuals (
2397
+ die, GetCXXObjectParameter (die, *containing_decl_ctx));
2398
+
2399
+ ParseChildParameters (containing_decl_ctx, die, is_variadic,
2400
+ has_template_params, param_types, param_decls);
2334
2401
sstr << " (" ;
2335
2402
for (size_t i = 0 ; i < param_types.size (); i++) {
2336
2403
if (i > 0 )
@@ -2340,7 +2407,7 @@ DWARFASTParserClang::ConstructDemangledNameFromDWARF(const DWARFDIE &die) {
2340
2407
if (is_variadic)
2341
2408
sstr << " , ..." ;
2342
2409
sstr << " )" ;
2343
- if (type_quals & clang::Qualifiers::Const)
2410
+ if (cv_quals & clang::Qualifiers::Const)
2344
2411
sstr << " const" ;
2345
2412
2346
2413
return ConstString (sstr.GetString ());
@@ -3070,57 +3137,37 @@ bool DWARFASTParserClang::ParseChildMembers(
3070
3137
return true ;
3071
3138
}
3072
3139
3073
- size_t DWARFASTParserClang::ParseChildParameters (
3140
+ void DWARFASTParserClang::ParseChildParameters (
3074
3141
clang::DeclContext *containing_decl_ctx, const DWARFDIE &parent_die,
3075
- bool &is_static, bool & is_variadic, bool &has_template_params,
3142
+ bool &is_variadic, bool &has_template_params,
3076
3143
std::vector<CompilerType> &function_param_types,
3077
- std::vector<clang::ParmVarDecl *> &function_param_decls,
3078
- unsigned &type_quals) {
3144
+ std::vector<clang::ParmVarDecl *> &function_param_decls) {
3079
3145
if (!parent_die)
3080
- return 0 ;
3146
+ return ;
3081
3147
3082
- size_t arg_idx = 0 ;
3083
3148
for (DWARFDIE die : parent_die.children ()) {
3084
3149
const dw_tag_t tag = die.Tag ();
3085
3150
switch (tag) {
3086
3151
case DW_TAG_formal_parameter: {
3152
+ if (die.GetAttributeValueAsUnsigned (DW_AT_artificial, 0 ))
3153
+ continue ;
3154
+
3087
3155
const char *name = die.GetName ();
3088
3156
DWARFDIE param_type_die = die.GetAttributeValueAsReferenceDIE (DW_AT_type);
3089
3157
3090
- if (die.GetAttributeValueAsUnsigned (DW_AT_artificial, 0 )) {
3091
- // In order to determine if a C++ member function is "const" we
3092
- // have to look at the const-ness of "this"...
3093
- if (arg_idx == 0 &&
3094
- DeclKindIsCXXClass (containing_decl_ctx->getDeclKind ()) &&
3095
- // Often times compilers omit the "this" name for the
3096
- // specification DIEs, so we can't rely upon the name being in
3097
- // the formal parameter DIE...
3098
- (name == nullptr || ::strcmp (name, " this" ) == 0 )) {
3099
- if (Type *this_type = die.ResolveTypeUID (param_type_die)) {
3100
- uint32_t encoding_mask = this_type->GetEncodingMask ();
3101
- if (encoding_mask & Type::eEncodingIsPointerUID) {
3102
- is_static = false ;
3103
-
3104
- if (encoding_mask & (1u << Type::eEncodingIsConstUID))
3105
- type_quals |= clang::Qualifiers::Const;
3106
- if (encoding_mask & (1u << Type::eEncodingIsVolatileUID))
3107
- type_quals |= clang::Qualifiers::Volatile;
3108
- }
3109
- }
3110
- }
3111
- } else if (Type *type = die.ResolveTypeUID (param_type_die)) {
3112
- function_param_types.push_back (type->GetForwardCompilerType ());
3158
+ Type *type = die.ResolveTypeUID (param_type_die);
3159
+ if (!type)
3160
+ break ;
3113
3161
3114
- clang::ParmVarDecl *param_var_decl = m_ast.CreateParameterDeclaration (
3115
- containing_decl_ctx, GetOwningClangModule (die), name,
3116
- type->GetForwardCompilerType (), clang::StorageClass::SC_None);
3117
- assert (param_var_decl);
3118
- function_param_decls.push_back (param_var_decl);
3162
+ function_param_types.push_back (type->GetForwardCompilerType ());
3119
3163
3120
- m_ast.SetMetadataAsUserID (param_var_decl, die.GetID ());
3121
- }
3164
+ clang::ParmVarDecl *param_var_decl = m_ast.CreateParameterDeclaration (
3165
+ containing_decl_ctx, GetOwningClangModule (die), name,
3166
+ type->GetForwardCompilerType (), clang::StorageClass::SC_None);
3167
+ assert (param_var_decl);
3168
+ function_param_decls.push_back (param_var_decl);
3122
3169
3123
- arg_idx++ ;
3170
+ m_ast. SetMetadataAsUserID (param_var_decl, die. GetID ()) ;
3124
3171
} break ;
3125
3172
3126
3173
case DW_TAG_unspecified_parameters:
@@ -3142,7 +3189,6 @@ size_t DWARFASTParserClang::ParseChildParameters(
3142
3189
break ;
3143
3190
}
3144
3191
}
3145
- return arg_idx;
3146
3192
}
3147
3193
3148
3194
clang::Decl *DWARFASTParserClang::GetClangDeclForDIE (const DWARFDIE &die) {
0 commit comments