Index: lib/CodeGen/CGDebugInfo.h =================================================================== --- lib/CodeGen/CGDebugInfo.h +++ lib/CodeGen/CGDebugInfo.h @@ -98,6 +98,15 @@ /// Cache of previously constructed interfaces which may change. llvm::SmallVector ObjCInterfaceCache; + struct ObjCMethodCacheEntry { + const ObjCMethodDecl *MD; + llvm::DISubprogram *DIMethodDecl; + }; + + /// Cache of forward declarations for methods belonging to the interface. + llvm::DenseMap> + ObjCMethodCache; + /// Cache of references to clang modules and precompiled headers. llvm::DenseMap ModuleCache; Index: lib/CodeGen/CGDebugInfo.cpp =================================================================== --- lib/CodeGen/CGDebugInfo.cpp +++ lib/CodeGen/CGDebugInfo.cpp @@ -3346,6 +3346,27 @@ if (HasDecl && isa(D)) DeclCache[D->getCanonicalDecl()].reset(SP); + if (CGM.getCodeGenOpts().DwarfVersion >= 5) { + // Starting with DWARF V5 method declarations are emitted as children of + // the interface type. + if (const auto *OMD = dyn_cast_or_null(D)) { + const ObjCInterfaceDecl *ID = OMD->getClassInterface(); + QualType QTy(ID->getTypeForDecl(), 0); + auto it = TypeCache.find(QTy.getAsOpaquePtr()); + if (it != TypeCache.end()) { + llvm::DICompositeType *InterfaceDecl = + cast(it->second); + llvm::DISubprogram *FD = DBuilder.createFunction( + InterfaceDecl, Name, LinkageName, Unit, LineNo, + getOrCreateFunctionType(D, FnType, Unit), Fn->hasLocalLinkage(), + false /*definition*/, ScopeLine, Flags, CGM.getLangOpts().Optimize, + TParamsArray.get()); + DBuilder.finalizeSubprogram(FD); + ObjCMethodCache[ID].push_back({OMD, FD}); + } + } + } + // Push the function onto the lexical block stack. LexicalBlockStack.emplace_back(SP); @@ -4213,6 +4234,30 @@ DBuilder.replaceTemporary(llvm::TempDIType(E.Decl), Ty); } + if (CGM.getCodeGenOpts().DwarfVersion >= 5) { + // Add methods to interface. + for (auto p : ObjCMethodCache) { + if (p.second.empty()) + continue; + + QualType QTy(p.first->getTypeForDecl(), 0); + auto it = TypeCache.find(QTy.getAsOpaquePtr()); + if (it == TypeCache.end()) + continue; + + llvm::DICompositeType *InterfaceDecl = + cast(it->second); + + SmallVector EltTys; + auto CurrenetElts = InterfaceDecl->getElements(); + EltTys.append(CurrenetElts.begin(), CurrenetElts.end()); + for (auto &M : p.second) + EltTys.push_back(M.DIMethodDecl); + llvm::DINodeArray Elements = DBuilder.getOrCreateArray(EltTys); + DBuilder.replaceArrays(InterfaceDecl, Elements); + } + } + for (auto p : ReplaceMap) { assert(p.second); auto *Ty = cast(p.second);