diff options
author | Adrian Prantl <aprantl@apple.com> | 2019-11-08 09:24:31 -0800 |
---|---|---|
committer | Adrian Prantl <aprantl@apple.com> | 2019-11-08 15:14:00 -0800 |
commit | 901cc4a4bc5257d100338e6c318b96b022d554ee (patch) | |
tree | 699a3988455df91d6e9ab9d3ab345b747c6f4fe3 /clang/lib/CodeGen/CGDebugInfo.cpp | |
parent | e1b07aac3d1c92f58e05cb5c37c0707842da5839 (diff) | |
download | bcm5719-llvm-901cc4a4bc5257d100338e6c318b96b022d554ee.tar.gz bcm5719-llvm-901cc4a4bc5257d100338e6c318b96b022d554ee.zip |
Debug Info: Nest Objective-C property function decls inside their container.
This has the nice side-effect of also fixing a crash in Clang.
Starting with DWARF 5 we are emitting ObjC method declarations as
children of their containing entity. This worked for interfaces, but
didn't consider the case of synthessized properties. When a property
of a protocol is synthesized in an interface implementation the
ObjCMethodDecl that was passed to CGF::StartFunction was the property
*declaration* which obviously couldn't have a containing
interface. This patch passes the containing interface all the way
through to CGDebugInfo, so the function declaration can be created
with the correct parent (= the class implementing the protocol).
rdar://problem/53782400
Differential Revision: https://reviews.llvm.org/D66121
Diffstat (limited to 'clang/lib/CodeGen/CGDebugInfo.cpp')
-rw-r--r-- | clang/lib/CodeGen/CGDebugInfo.cpp | 67 |
1 files changed, 42 insertions, 25 deletions
diff --git a/clang/lib/CodeGen/CGDebugInfo.cpp b/clang/lib/CodeGen/CGDebugInfo.cpp index e0bb3fda7ac..75c4b2ae233 100644 --- a/clang/lib/CodeGen/CGDebugInfo.cpp +++ b/clang/lib/CodeGen/CGDebugInfo.cpp @@ -2600,8 +2600,8 @@ llvm::DIType *CGDebugInfo::CreateTypeDefinition(const ObjCInterfaceType *Ty, SourceLocation Loc = PD->getLocation(); llvm::DIFile *PUnit = getOrCreateFile(Loc); unsigned PLine = getLineNumber(Loc); - ObjCMethodDecl *Getter = PD->getGetterMethodDecl(); - ObjCMethodDecl *Setter = PD->getSetterMethodDecl(); + ObjCMethodDecl *Getter = PImpD->getGetterMethodDecl(); + ObjCMethodDecl *Setter = PImpD->getSetterMethodDecl(); PropertyNode = DBuilder.createObjCProperty( PD->getName(), PUnit, PLine, hasDefaultGetterName(PD, Getter) @@ -3490,6 +3490,38 @@ llvm::DISubprogram *CGDebugInfo::getFunctionDeclaration(const Decl *D) { return nullptr; } +llvm::DISubprogram *CGDebugInfo::getObjCMethodDeclaration( + const Decl *D, llvm::DISubroutineType *FnType, unsigned LineNo, + llvm::DINode::DIFlags Flags, llvm::DISubprogram::DISPFlags SPFlags) { + if (!D || DebugKind <= codegenoptions::DebugLineTablesOnly) + return nullptr; + + if (CGM.getCodeGenOpts().DwarfVersion < 5) + return nullptr; + + // Starting with DWARF V5 method declarations are emitted as children of + // the interface type. + const auto *OMD = dyn_cast<ObjCMethodDecl>(D); + if (!OMD) + return nullptr; + auto *ID = dyn_cast_or_null<ObjCInterfaceDecl>(D->getDeclContext()); + if (!ID) + ID = OMD->getClassInterface(); + if (!ID) + return nullptr; + QualType QTy(ID->getTypeForDecl(), 0); + auto It = TypeCache.find(QTy.getAsOpaquePtr()); + if (It == TypeCache.end()) + return nullptr; + auto *InterfaceType = cast<llvm::DICompositeType>(It->second); + llvm::DISubprogram *FD = DBuilder.createFunction( + InterfaceType, getObjCMethodName(OMD), StringRef(), + InterfaceType->getFile(), LineNo, FnType, LineNo, Flags, SPFlags); + DBuilder.finalizeSubprogram(FD); + ObjCMethodCache[ID].push_back(FD); + return FD; +} + // getOrCreateFunctionType - Construct type. If it is a c++ method, include // implicit parameter "this". llvm::DISubroutineType *CGDebugInfo::getOrCreateFunctionType(const Decl *D, @@ -3632,6 +3664,12 @@ void CGDebugInfo::EmitFunctionStart(GlobalDecl GD, SourceLocation Loc, unsigned LineNo = getLineNumber(Loc); unsigned ScopeLine = getLineNumber(ScopeLoc); + llvm::DISubroutineType *DIFnType = getOrCreateFunctionType(D, FnType, Unit); + llvm::DISubprogram *Decl = nullptr; + if (D) + Decl = isa<ObjCMethodDecl>(D) + ? getObjCMethodDeclaration(D, DIFnType, LineNo, Flags, SPFlags) + : getFunctionDeclaration(D); // FIXME: The function declaration we're constructing here is mostly reusing // declarations from CXXMethodDecl and not constructing new ones for arbitrary @@ -3639,9 +3677,8 @@ void CGDebugInfo::EmitFunctionStart(GlobalDecl GD, SourceLocation Loc, // all subprograms instead of the actual context since subprogram definitions // are emitted as CU level entities by the backend. llvm::DISubprogram *SP = DBuilder.createFunction( - FDContext, Name, LinkageName, Unit, LineNo, - getOrCreateFunctionType(D, FnType, Unit), ScopeLine, FlagsForDef, - SPFlagsForDef, TParamsArray.get(), getFunctionDeclaration(D)); + FDContext, Name, LinkageName, Unit, LineNo, DIFnType, ScopeLine, + FlagsForDef, SPFlagsForDef, TParamsArray.get(), Decl); Fn->setSubprogram(SP); // We might get here with a VarDecl in the case we're generating // code for the initialization of globals. Do not record these decls @@ -3658,26 +3695,6 @@ void CGDebugInfo::EmitFunctionStart(GlobalDecl GD, SourceLocation Loc, if (FD->hasBody() && !FD->param_empty()) SPDefCache[FD].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<ObjCMethodDecl>(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<llvm::DICompositeType>(It->second); - llvm::DISubprogram *FD = DBuilder.createFunction( - InterfaceDecl, Name, LinkageName, Unit, LineNo, - getOrCreateFunctionType(D, FnType, Unit), ScopeLine, Flags, SPFlags, - TParamsArray.get()); - DBuilder.finalizeSubprogram(FD); - ObjCMethodCache[ID].push_back(FD); - } - } - } - // Push the function onto the lexical block stack. LexicalBlockStack.emplace_back(SP); |