Index: lib/CodeGen/CGDebugInfo.cpp =================================================================== --- lib/CodeGen/CGDebugInfo.cpp +++ lib/CodeGen/CGDebugInfo.cpp @@ -801,22 +801,46 @@ } } -/// In C++ mode, types have linkage, so we can rely on the ODR and -/// on their mangled names, if they're external. -static SmallString<256> getUniqueTagTypeName(const TagType *Ty, - CodeGenModule &CGM, - llvm::DICompileUnit *TheCU) { - SmallString<256> FullName; +// Determines if the tag declaration will require a type identifier. +static bool needsTypeIdentifier(const TagDecl *TD, + CodeGenModule& CGM, + llvm::DICompileUnit *TheCU) { + // We only add a type identifier for types with C++ name mangling. + if (!hasCXXMangling(TD, TheCU)) + return false; + + // CodeView types with C++ mangling need a type identifier. + if (CGM.getCodeGenOpts().EmitCodeView) + return true; + + // Externally visible types with C++ mangling need a type identifier. + if (TD->isExternallyVisible()) + return true; + + return false; +} + +// When emitting CodeView debug information we need to produce a type +// identifier for all types which have a C++ mangling. Until a GUID is added +// to the identifier (not currently implemented) the result will not be unique +// across compilation units. +// When emitting DWARF debug information, we need to produce a type identifier +// for all externally visible types with C++ name mangling. This identifier +// should be unique across ODR-compliant compilation units. +static SmallString<256> getTypeIdentifier(const TagType *Ty, + CodeGenModule &CGM, + llvm::DICompileUnit *TheCU) { + SmallString<256> Identifier; const TagDecl *TD = Ty->getDecl(); - if (!hasCXXMangling(TD, TheCU) || !TD->isExternallyVisible()) - return FullName; + if (!needsTypeIdentifier(TD, CGM, TheCU)) + return Identifier; // TODO: This is using the RTTI name. Is there a better way to get // a unique string for a type? - llvm::raw_svector_ostream Out(FullName); + llvm::raw_svector_ostream Out(Identifier); CGM.getCXXABI().getMangleContext().mangleCXXRTTIName(QualType(Ty, 0), Out); - return FullName; + return Identifier; } /// \return the appropriate DWARF tag for a composite type. @@ -849,10 +873,10 @@ uint32_t Align = 0; // Create the type. - SmallString<256> FullName = getUniqueTagTypeName(Ty, CGM, TheCU); + SmallString<256> Identifier = getTypeIdentifier(Ty, CGM, TheCU); llvm::DICompositeType *RetTy = DBuilder.createReplaceableCompositeType( getTagForRecord(RD), RDName, Ctx, DefUnit, Line, 0, Size, Align, - llvm::DINode::FlagFwdDecl, FullName); + llvm::DINode::FlagFwdDecl, Identifier); if (CGM.getCodeGenOpts().DebugFwdTemplateParams) if (auto *TSpecial = dyn_cast(RD)) DBuilder.replaceArrays(RetTy, llvm::DINodeArray(), @@ -2477,7 +2501,7 @@ Align = getDeclAlignIfRequired(ED, CGM.getContext()); } - SmallString<256> FullName = getUniqueTagTypeName(Ty, CGM, TheCU); + SmallString<256> Identifier = getTypeIdentifier(Ty, CGM, TheCU); bool isImportedFromModule = DebugTypeExtRefs && ED->isFromASTFile() && ED->getDefinition(); @@ -2500,7 +2524,7 @@ StringRef EDName = ED->getName(); llvm::DIType *RetTy = DBuilder.createReplaceableCompositeType( llvm::dwarf::DW_TAG_enumeration_type, EDName, EDContext, DefUnit, Line, - 0, Size, Align, llvm::DINode::FlagFwdDecl, FullName); + 0, Size, Align, llvm::DINode::FlagFwdDecl, Identifier); ReplaceMap.emplace_back( std::piecewise_construct, std::make_tuple(Ty), @@ -2520,7 +2544,7 @@ Align = getDeclAlignIfRequired(ED, CGM.getContext()); } - SmallString<256> FullName = getUniqueTagTypeName(Ty, CGM, TheCU); + SmallString<256> Identifier = getTypeIdentifier(Ty, CGM, TheCU); // Create elements for each enumerator. SmallVector Enumerators; @@ -2542,7 +2566,7 @@ llvm::DIType *ClassTy = getOrCreateType(ED->getIntegerType(), DefUnit); return DBuilder.createEnumerationType(EnumContext, ED->getName(), DefUnit, Line, Size, Align, EltArray, ClassTy, - FullName, ED->isFixed()); + Identifier, ED->isFixed()); } llvm::DIMacro *CGDebugInfo::CreateMacro(llvm::DIMacroFile *Parent, @@ -2843,7 +2867,7 @@ uint64_t Size = CGM.getContext().getTypeSize(Ty); auto Align = getDeclAlignIfRequired(D, CGM.getContext()); - SmallString<256> FullName = getUniqueTagTypeName(Ty, CGM, TheCU); + SmallString<256> Identifier = getTypeIdentifier(Ty, CGM, TheCU); // Explicitly record the calling convention for C++ records. auto Flags = llvm::DINode::FlagZero; @@ -2856,7 +2880,7 @@ llvm::DICompositeType *RealDecl = DBuilder.createReplaceableCompositeType( getTagForRecord(RD), RDName, RDContext, DefUnit, Line, 0, Size, Align, - Flags, FullName); + Flags, Identifier); // Elements of composite types usually have back to the type, creating // uniquing cycles. Distinct nodes are more efficient. @@ -2870,7 +2894,7 @@ // so they don't tend to be involved in uniquing cycles and there is some // chance of merging them when linking together two modules. Only make // them distinct if they are ODR-uniqued. - if (FullName.empty()) + if (Identifier.empty()) break; LLVM_FALLTHROUGH; Index: test/CodeGen/debug-info-codeview-unnamed.c =================================================================== --- test/CodeGen/debug-info-codeview-unnamed.c +++ test/CodeGen/debug-info-codeview-unnamed.c @@ -0,0 +1,30 @@ +// RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -debug-info-kind=limited -S -emit-llvm -o - %s | FileCheck --check-prefix LINUX %s +// RUN: %clang_cc1 -triple x86_64-windows-msvc -debug-info-kind=limited -gcodeview -S -emit-llvm -o - %s | FileCheck --check-prefix MSVC %s + +int main(int argc, char* argv[], char* arge[]) { + + // In both DWARF and CodeView, an unnamed C structure type will generate a + // DICompositeType without a name or identifier attribute; + // + struct { int bar; } one = {42}; + // + // LINUX: !{{[0-9]+}} = !DILocalVariable(name: "one" + // LINUX-SAME: type: [[TYPE_OF_ONE:![0-9]+]] + // LINUX-SAME: ) + // LINUX: [[TYPE_OF_ONE]] = distinct !DICompositeType( + // LINUX-SAME: tag: DW_TAG_structure_type + // LINUX-NOT: name: + // LINUX-NOT: identifier: + // LINUX-SAME: ) + // + // MSVC: !{{[0-9]+}} = !DILocalVariable(name: "one" + // MSVC-SAME: type: [[TYPE_OF_ONE:![0-9]+]] + // MSVC-SAME: ) + // MSVC: [[TYPE_OF_ONE]] = distinct !DICompositeType + // MSVC-SAME: tag: DW_TAG_structure_type + // MSVC-NOT: name: + // MSVC-NOT: identifier: + // MSVC-SAME: ) + + return 0; +} Index: test/CodeGenCXX/debug-info-codeview-unnamed.cpp =================================================================== --- test/CodeGenCXX/debug-info-codeview-unnamed.cpp +++ test/CodeGenCXX/debug-info-codeview-unnamed.cpp @@ -0,0 +1,108 @@ +// RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -debug-info-kind=limited -S -emit-llvm -std=c++11 -o - %s | FileCheck --check-prefix LINUX %s +// RUN: %clang_cc1 -triple x86_64-windows-msvc -debug-info-kind=limited -gcodeview -S -emit-llvm -std=c++11 -o - %s | FileCheck --check-prefix MSVC %s + +int main(int argc, char* argv[], char* arge[]) { + // + // In CodeView, the LF_MFUNCTION entry for "bar()" refers to the forward + // reference of the unnamed struct. Visual Studio requires a unique + // identifier to match the LF_STRUCTURE forward reference to the definition. + // + struct { void bar() {} } one; + // + // LINUX: !{{[0-9]+}} = !DILocalVariable(name: "one" + // LINUX-SAME: type: [[TYPE_OF_ONE:![0-9]+]] + // LINUX-SAME: ) + // LINUX: [[TYPE_OF_ONE]] = distinct !DICompositeType( + // LINUX-SAME: tag: DW_TAG_structure_type + // LINUX-NOT: name: + // LINUX-NOT: identifier: + // LINUX-SAME: ) + // + // MSVC: !{{[0-9]+}} = !DILocalVariable(name: "one" + // MSVC-SAME: type: [[TYPE_OF_ONE:![0-9]+]] + // MSVC-SAME: ) + // MSVC: [[TYPE_OF_ONE]] = distinct !DICompositeType + // MSVC-SAME: tag: DW_TAG_structure_type + // MSVC-SAME: name: "" + // MSVC-SAME: identifier: ".?AU@?1??main@@9@" + // MSVC-SAME: ) + + + // In CodeView, the LF_POINTER entry for "ptr2unnamed" refers to the forward + // reference of the unnamed struct. Visual Studio requires a unique + // identifier to match the LF_STRUCTURE forward reference to the definition. + // + struct { int bar; } two = { 42 }; + int decltype(two)::*ptr2unnamed = &decltype(two)::bar; + // + // LINUX: !{{[0-9]+}} = !DILocalVariable(name: "two" + // LINUX-SAME: type: [[TYPE_OF_TWO:![0-9]+]] + // LINUX-SAME: ) + // LINUX: [[TYPE_OF_TWO]] = distinct !DICompositeType( + // LINUX-SAME: tag: DW_TAG_structure_type + // LINUX-NOT: name: + // LINUX-NOT: identifier: + // LINUX-SAME: ) + // + // MSVC: !{{[0-9]+}} = !DILocalVariable(name: "two" + // MSVC-SAME: type: [[TYPE_OF_TWO:![0-9]+]] + // MSVC-SAME: ) + // MSVC: [[TYPE_OF_TWO]] = distinct !DICompositeType + // MSVC-SAME: tag: DW_TAG_structure_type + // MSVC-SAME: name: "" + // MSVC-SAME: identifier: ".?AU@?2??main@@9@" + // MSVC-SAME: ) + + + // In DWARF, named structures which are not externally visibile do not + // require an identifier. In CodeView, named structures are given an + // identifier. + // + struct named { int bar; int named::* p2mem; } three = { 42, &named::bar }; + // + // LINUX: !{{[0-9]+}} = !DILocalVariable(name: "three" + // LINUX-SAME: type: [[TYPE_OF_THREE:![0-9]+]] + // LINUX-SAME: ) + // LINUX: [[TYPE_OF_THREE]] = distinct !DICompositeType( + // LINUX-SAME: tag: DW_TAG_structure_type + // LINUX-SAME: name: "named" + // LINUX-NOT: identifier: + // LINUX-SAME: ) + // + // MSVC: !{{[0-9]+}} = !DILocalVariable(name: "three" + // MSVC-SAME: type: [[TYPE_OF_THREE:![0-9]+]] + // MSVC-SAME: ) + // MSVC: [[TYPE_OF_THREE]] = distinct !DICompositeType + // MSVC-SAME: tag: DW_TAG_structure_type + // MSVC-SAME: name: "named" + // MSVC-SAME: identifier: ".?AUnamed@?1??main@@9@" + // MSVC-SAME: ) + + + // In CodeView, the LF_MFUNCTION entry for the lambda "operator()" routine + // refers to the forward reference of the unnamed LF_CLASS for the lambda. + // Visual Studio requires a unique identifier to match the forward reference + // of the LF_CLASS to its definition. + // + auto four = [argc](int i) -> int { return argc == i ? 1 : 0; }; + // + // LINUX: !{{[0-9]+}} = !DILocalVariable(name: "four" + // LINUX-SAME: type: [[TYPE_OF_FOUR:![0-9]+]] + // LINUX-SAME: ) + // LINUX: [[TYPE_OF_FOUR]] = distinct !DICompositeType( + // LINUX-SAME: tag: DW_TAG_class_type + // LINUX-NOT: name: + // LINUX-NOT: identifier: + // LINUX-SAME: ) + // + // MSVC: !{{[0-9]+}} = !DILocalVariable(name: "four" + // MSVC-SAME: type: [[TYPE_OF_FOUR:![0-9]+]] + // MSVC-SAME: ) + // MSVC: [[TYPE_OF_FOUR]] = distinct !DICompositeType + // MSVC-SAME: tag: DW_TAG_class_type + // MSVC-NOT: name: + // MSVC-SAME: identifier: ".?AV@?0??main@@9@" + // MSVC-SAME: ) + + return 0; +}