@@ -159,6 +159,79 @@ static bool TagIsRecordType(dw_tag_t tag) {
159159 }
160160}
161161
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+ clang::DeclContext const &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+ if (!subprogram.HasChildren ())
177+ return {};
178+
179+ // FIXME: if subprogram has a explicit DW_AT_object_pointer, use it.
180+
181+ // If no DW_AT_object_pointer was specified, assume the implicit object
182+ // parameter is the first parameter to the function, is called "this" and is
183+ // artificial (which is what most compilers would generate).
184+ auto children = subprogram.children ();
185+ auto it = llvm::find_if (children, [](const DWARFDIE &child) {
186+ return child.Tag () == DW_TAG_formal_parameter;
187+ });
188+
189+ if (it == children.end ())
190+ return {};
191+
192+ DWARFDIE object_pointer = *it;
193+
194+ if (!object_pointer.GetAttributeValueAsUnsigned (DW_AT_artificial, 0 ))
195+ return {};
196+
197+ // Often times compilers omit the "this" name for the
198+ // specification DIEs, so we can't rely upon the name being in
199+ // the formal parameter DIE...
200+ if (char const *name = object_pointer.GetName ();
201+ name && ::strcmp (name, " this" ) == 0 )
202+ return {};
203+
204+ return object_pointer;
205+ }
206+
207+ // / In order to determine the CV-qualifiers for a C++ class
208+ // / method in DWARF, we have to look at the CV-qualifiers of
209+ // / the object parameter's type.
210+ static unsigned GetCXXMethodCVQuals (DWARFDIE const &subprogram,
211+ DWARFDIE const &object_parameter) {
212+ if (!subprogram || !object_parameter)
213+ return 0 ;
214+
215+ Type *this_type = subprogram.ResolveTypeUID (
216+ object_parameter.GetAttributeValueAsReferenceDIE (DW_AT_type));
217+ if (!this_type)
218+ return 0 ;
219+
220+ uint32_t encoding_mask = this_type->GetEncodingMask ();
221+
222+ // FIXME: explicit object parameters need not to be pointers
223+ if (!(encoding_mask & (1u << Type::eEncodingIsPointerUID)))
224+ return 0 ;
225+
226+ unsigned cv_quals = 0 ;
227+ if (encoding_mask & (1u << Type::eEncodingIsConstUID))
228+ cv_quals |= clang::Qualifiers::Const;
229+ if (encoding_mask & (1u << Type::eEncodingIsVolatileUID))
230+ cv_quals |= clang::Qualifiers::Volatile;
231+
232+ return cv_quals;
233+ }
234+
162235TypeSP DWARFASTParserClang::ParseTypeFromClangModule (const SymbolContext &sc,
163236 const DWARFDIE &die,
164237 Log *log) {
@@ -1188,11 +1261,8 @@ DWARFASTParserClang::ParseSubroutine(const DWARFDIE &die,
11881261 const dw_tag_t tag = die.Tag ();
11891262
11901263 bool is_variadic = false ;
1191- bool is_static = false ;
11921264 bool has_template_params = false ;
11931265
1194- unsigned type_quals = 0 ;
1195-
11961266 DEBUG_PRINTF (" 0x%8.8" PRIx64 " : %s (\" %s\" )\n " , die.GetID (),
11971267 DW_TAG_value_to_name (tag), type_name_cstr);
11981268
@@ -1215,23 +1285,15 @@ DWARFASTParserClang::ParseSubroutine(const DWARFDIE &die,
12151285 DWARFDIE decl_ctx_die;
12161286 clang::DeclContext *containing_decl_ctx =
12171287 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- }
1288+ assert (containing_decl_ctx);
12281289
12291290 if (die.HasChildren ()) {
1230- ParseChildParameters (containing_decl_ctx, die, is_static, is_variadic,
1291+ ParseChildParameters (containing_decl_ctx, die, is_variadic,
12311292 has_template_params, function_param_types,
1232- function_param_decls, type_quals );
1293+ function_param_decls);
12331294 }
12341295
1296+ bool is_cxx_method = DeclKindIsCXXClass (containing_decl_ctx->getDeclKind ());
12351297 bool ignore_containing_context = false ;
12361298 // Check for templatized class member functions. If we had any
12371299 // DW_TAG_template_type_parameter or DW_TAG_template_value_parameter
@@ -1251,12 +1313,16 @@ DWARFASTParserClang::ParseSubroutine(const DWARFDIE &die,
12511313 clang::CallingConv calling_convention =
12521314 ConvertDWARFCallingConventionToClang (attrs);
12531315
1316+ const DWARFDIE object_parameter =
1317+ GetCXXObjectParameter (die, *containing_decl_ctx);
1318+
12541319 // clang_type will get the function prototype clang type after this
12551320 // call
12561321 CompilerType clang_type =
12571322 m_ast.CreateFunctionType (return_clang_type, function_param_types.data (),
12581323 function_param_types.size (), is_variadic,
1259- type_quals, calling_convention, attrs.ref_qual );
1324+ GetCXXMethodCVQuals (die, object_parameter),
1325+ calling_convention, attrs.ref_qual );
12601326
12611327 if (attrs.name ) {
12621328 bool type_handled = false ;
@@ -1267,6 +1333,8 @@ DWARFASTParserClang::ParseSubroutine(const DWARFDIE &die,
12671333 type_handled =
12681334 ParseObjCMethod (*objc_method, die, clang_type, attrs, is_variadic);
12691335 } else if (is_cxx_method) {
1336+ // In DWARF, a C++ method is static if it has no object parameter child.
1337+ const bool is_static = !object_parameter.IsValid ();
12701338 auto [handled, type_sp] =
12711339 ParseCXXMethod (die, clang_type, attrs, decl_ctx_die, is_static,
12721340 ignore_containing_context);
@@ -2315,10 +2383,8 @@ size_t DWARFASTParserClang::ParseChildEnumerators(
23152383
23162384ConstString
23172385DWARFASTParserClang::ConstructDemangledNameFromDWARF (const DWARFDIE &die) {
2318- bool is_static = false ;
23192386 bool is_variadic = false ;
23202387 bool has_template_params = false ;
2321- unsigned type_quals = 0 ;
23222388 std::vector<CompilerType> param_types;
23232389 std::vector<clang::ParmVarDecl *> param_decls;
23242390 StreamString sstr;
@@ -2328,9 +2394,13 @@ DWARFASTParserClang::ConstructDemangledNameFromDWARF(const DWARFDIE &die) {
23282394
23292395 clang::DeclContext *containing_decl_ctx =
23302396 GetClangDeclContextContainingDIE (die, nullptr );
2331- ParseChildParameters (containing_decl_ctx, die, is_static, is_variadic,
2332- has_template_params, param_types, param_decls,
2333- type_quals);
2397+ assert (containing_decl_ctx);
2398+
2399+ const unsigned cv_quals = GetCXXMethodCVQuals (
2400+ die, GetCXXObjectParameter (die, *containing_decl_ctx));
2401+
2402+ ParseChildParameters (containing_decl_ctx, die, is_variadic,
2403+ has_template_params, param_types, param_decls);
23342404 sstr << " (" ;
23352405 for (size_t i = 0 ; i < param_types.size (); i++) {
23362406 if (i > 0 )
@@ -2340,7 +2410,7 @@ DWARFASTParserClang::ConstructDemangledNameFromDWARF(const DWARFDIE &die) {
23402410 if (is_variadic)
23412411 sstr << " , ..." ;
23422412 sstr << " )" ;
2343- if (type_quals & clang::Qualifiers::Const)
2413+ if (cv_quals & clang::Qualifiers::Const)
23442414 sstr << " const" ;
23452415
23462416 return ConstString (sstr.GetString ());
@@ -3070,57 +3140,37 @@ bool DWARFASTParserClang::ParseChildMembers(
30703140 return true ;
30713141}
30723142
3073- size_t DWARFASTParserClang::ParseChildParameters (
3143+ void DWARFASTParserClang::ParseChildParameters (
30743144 clang::DeclContext *containing_decl_ctx, const DWARFDIE &parent_die,
3075- bool &is_static, bool & is_variadic, bool &has_template_params,
3145+ bool &is_variadic, bool &has_template_params,
30763146 std::vector<CompilerType> &function_param_types,
3077- std::vector<clang::ParmVarDecl *> &function_param_decls,
3078- unsigned &type_quals) {
3147+ std::vector<clang::ParmVarDecl *> &function_param_decls) {
30793148 if (!parent_die)
3080- return 0 ;
3149+ return ;
30813150
3082- size_t arg_idx = 0 ;
30833151 for (DWARFDIE die : parent_die.children ()) {
30843152 const dw_tag_t tag = die.Tag ();
30853153 switch (tag) {
30863154 case DW_TAG_formal_parameter: {
3155+ if (die.GetAttributeValueAsUnsigned (DW_AT_artificial, 0 ))
3156+ continue ;
3157+
30873158 const char *name = die.GetName ();
30883159 DWARFDIE param_type_die = die.GetAttributeValueAsReferenceDIE (DW_AT_type);
30893160
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 ());
3161+ Type *type = die.ResolveTypeUID (param_type_die);
3162+ if (!type)
3163+ break ;
31133164
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);
3165+ function_param_types.push_back (type->GetForwardCompilerType ());
31193166
3120- m_ast.SetMetadataAsUserID (param_var_decl, die.GetID ());
3121- }
3167+ clang::ParmVarDecl *param_var_decl = m_ast.CreateParameterDeclaration (
3168+ containing_decl_ctx, GetOwningClangModule (die), name,
3169+ type->GetForwardCompilerType (), clang::StorageClass::SC_None);
3170+ assert (param_var_decl);
3171+ function_param_decls.push_back (param_var_decl);
31223172
3123- arg_idx++ ;
3173+ m_ast. SetMetadataAsUserID (param_var_decl, die. GetID ()) ;
31243174 } break ;
31253175
31263176 case DW_TAG_unspecified_parameters:
@@ -3142,7 +3192,6 @@ size_t DWARFASTParserClang::ParseChildParameters(
31423192 break ;
31433193 }
31443194 }
3145- return arg_idx;
31463195}
31473196
31483197clang::Decl *DWARFASTParserClang::GetClangDeclForDIE (const DWARFDIE &die) {
0 commit comments