From 4fb918455800c40cd1b40f8b0a7df4b3790b0465 Mon Sep 17 00:00:00 2001 From: Brock Wyma Date: Tue, 13 Mar 2018 14:14:16 +0000 Subject: [CodeView] Omit forward references for unnamed structs and unions Codeview references to unnamed structs and unions are expected to refer to the complete type definition instead of a forward reference so Visual Studio can resolve the type properly. Differential Revision: https://reviews.llvm.org/D32498 llvm-svn: 327397 --- llvm/lib/CodeGen/AsmPrinter/CodeViewDebug.cpp | 50 +++++++++++++++++++++------ 1 file changed, 40 insertions(+), 10 deletions(-) (limited to 'llvm/lib/CodeGen/AsmPrinter/CodeViewDebug.cpp') diff --git a/llvm/lib/CodeGen/AsmPrinter/CodeViewDebug.cpp b/llvm/lib/CodeGen/AsmPrinter/CodeViewDebug.cpp index 0e8a83cbe18..e397e30b098 100644 --- a/llvm/lib/CodeGen/AsmPrinter/CodeViewDebug.cpp +++ b/llvm/lib/CodeGen/AsmPrinter/CodeViewDebug.cpp @@ -1936,7 +1936,28 @@ ClassInfo CodeViewDebug::collectClassInfo(const DICompositeType *Ty) { return Info; } +static bool shouldAlwaysEmitCompleteClassType(const DICompositeType *Ty) { + // This routine is used by lowerTypeClass and lowerTypeUnion to determine + // if a complete type should be emitted instead of a forward reference. + return Ty->getName().empty() && Ty->getIdentifier().empty() && + !Ty->isForwardDecl(); +} + TypeIndex CodeViewDebug::lowerTypeClass(const DICompositeType *Ty) { + // Emit the complete type for unnamed structs. C++ classes with methods + // which have a circular reference back to the class type are expected to + // be named by the front-end and should not be "unnamed". C unnamed + // structs should not have circular references. + if (shouldAlwaysEmitCompleteClassType(Ty)) { + // If this unnamed complete type is already in the process of being defined + // then the description of the type is malformed and cannot be emitted + // into CodeView correctly so report a fatal error. + auto I = CompleteTypeIndices.find(Ty); + if (I != CompleteTypeIndices.end() && I->second == TypeIndex()) + report_fatal_error("cannot debug circular reference to unnamed type"); + return getCompleteTypeIndex(Ty); + } + // First, construct the forward decl. Don't look into Ty to compute the // forward decl options, since it might not be available in all TUs. TypeRecordKind Kind = getRecordKind(Ty); @@ -1981,6 +2002,10 @@ TypeIndex CodeViewDebug::lowerCompleteTypeClass(const DICompositeType *Ty) { } TypeIndex CodeViewDebug::lowerTypeUnion(const DICompositeType *Ty) { + // Emit the complete type for unnamed unions. + if (shouldAlwaysEmitCompleteClassType(Ty)) + return getCompleteTypeIndex(Ty); + ClassOptions CO = ClassOptions::ForwardReference | getCommonClassOptions(Ty); std::string FullName = getFullyQualifiedName(Ty); @@ -2211,9 +2236,7 @@ TypeIndex CodeViewDebug::getCompleteTypeIndex(DITypeRef TypeRef) { return getTypeIndex(Ty); } - // Check if we've already translated the complete record type. Lowering a - // complete type should never trigger lowering another complete type, so we - // can reuse the hash table lookup result. + // Check if we've already translated the complete record type. const auto *CTy = cast(Ty); auto InsertResult = CompleteTypeIndices.insert({CTy, TypeIndex()}); if (!InsertResult.second) @@ -2224,13 +2247,16 @@ TypeIndex CodeViewDebug::getCompleteTypeIndex(DITypeRef TypeRef) { // Make sure the forward declaration is emitted first. It's unclear if this // is necessary, but MSVC does it, and we should follow suit until we can show // otherwise. - TypeIndex FwdDeclTI = getTypeIndex(CTy); + // We only emit a forward declaration for named types. + if (!CTy->getName().empty() || !CTy->getIdentifier().empty()) { + TypeIndex FwdDeclTI = getTypeIndex(CTy); - // Just use the forward decl if we don't have complete type info. This might - // happen if the frontend is using modules and expects the complete definition - // to be emitted elsewhere. - if (CTy->isForwardDecl()) - return FwdDeclTI; + // Just use the forward decl if we don't have complete type info. This + // might happen if the frontend is using modules and expects the complete + // definition to be emitted elsewhere. + if (CTy->isForwardDecl()) + return FwdDeclTI; + } TypeIndex TI; switch (CTy->getTag()) { @@ -2245,7 +2271,11 @@ TypeIndex CodeViewDebug::getCompleteTypeIndex(DITypeRef TypeRef) { llvm_unreachable("not a record"); } - InsertResult.first->second = TI; + // Update the type index associated with this CompositeType. This cannot + // use the 'InsertResult' iterator above because it is potentially + // invalidated by map insertions which can occur while lowering the class + // type above. + CompleteTypeIndices[CTy] = TI; return TI; } -- cgit v1.2.3