From: Adrian Prantl Date: Wed, 11 Feb 2015 17:45:15 +0000 (+0000) Subject: Fix PR19351. While building up a composite type it is important to use X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=d1c6a9401191aebba6e42975d29cd2b6612106f8;p=clang Fix PR19351. While building up a composite type it is important to use a non-uniqueable temporary node that is only turned into a permanent unique or distinct node after it is finished. Otherwise an intermediate node may get accidentally uniqued with another node as illustrated by the testcase. Paired commit with LLVM. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@228855 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/lib/CodeGen/CGDebugInfo.cpp b/lib/CodeGen/CGDebugInfo.cpp index 530797d15b..19da145dde 100644 --- a/lib/CodeGen/CGDebugInfo.cpp +++ b/lib/CodeGen/CGDebugInfo.cpp @@ -621,6 +621,21 @@ static SmallString<256> getUniqueTagTypeName(const TagType *Ty, return FullName; } +static llvm::dwarf::Tag getTagForRecord(const RecordDecl *RD) { + llvm::dwarf::Tag Tag; + if (RD->isStruct() || RD->isInterface()) + Tag = llvm::dwarf::DW_TAG_structure_type; + else if (RD->isUnion()) + Tag = llvm::dwarf::DW_TAG_union_type; + else { + // FIXME: This could be a struct type giving a default visibility different + // than C++ class type, but needs llvm metadata changes first. + assert(RD->isClass()); + Tag = llvm::dwarf::DW_TAG_class_type; + } + return Tag; +} + // Creates a forward declaration for a RecordDecl in the given context. llvm::DICompositeType CGDebugInfo::getOrCreateRecordFwdDecl(const RecordType *Ty, @@ -632,20 +647,12 @@ CGDebugInfo::getOrCreateRecordFwdDecl(const RecordType *Ty, unsigned Line = getLineNumber(RD->getLocation()); StringRef RDName = getClassName(RD); - llvm::dwarf::Tag Tag; - if (RD->isStruct() || RD->isInterface()) - Tag = llvm::dwarf::DW_TAG_structure_type; - else if (RD->isUnion()) - Tag = llvm::dwarf::DW_TAG_union_type; - else { - assert(RD->isClass()); - Tag = llvm::dwarf::DW_TAG_class_type; - } // Create the type. SmallString<256> FullName = getUniqueTagTypeName(Ty, CGM, TheCU); - llvm::DICompositeType RetTy = DBuilder.createReplaceableForwardDecl( - Tag, RDName, Ctx, DefUnit, Line, 0, 0, 0, FullName); + llvm::DICompositeType RetTy = DBuilder.createReplaceableCompositeType( + getTagForRecord(RD), RDName, Ctx, DefUnit, Line, 0, 0, 0, + llvm::DIDescriptor::FlagFwdDecl, FullName); ReplaceMap.emplace_back( std::piecewise_construct, std::make_tuple(Ty), std::make_tuple(static_cast(RetTy))); @@ -1567,7 +1574,8 @@ llvm::DIType CGDebugInfo::CreateTypeDefinition(const RecordType *Ty) { assert(FwdDecl.isCompositeType() && "The debug type of a RecordType should be a llvm::DICompositeType"); - if (FwdDecl.isForwardDecl()) + const RecordDecl *D = RD->getDefinition(); + if (!D || !D->isCompleteDefinition()) return FwdDecl; if (const CXXRecordDecl *CXXDecl = dyn_cast(RD)) @@ -1602,6 +1610,10 @@ llvm::DIType CGDebugInfo::CreateTypeDefinition(const RecordType *Ty) { llvm::DIArray Elements = DBuilder.getOrCreateArray(EltTys); DBuilder.replaceArrays(FwdDecl, Elements); + if (FwdDecl->isTemporary()) + FwdDecl = llvm::DICompositeType(llvm::MDNode::replaceWithPermanent( + llvm::TempMDNode(FwdDecl.get()))); + RegionMap[Ty->getDecl()].reset(FwdDecl); return FwdDecl; } @@ -1653,7 +1665,7 @@ llvm::DIType CGDebugInfo::CreateType(const ObjCInterfaceType *Ty, // debug type since we won't be able to lay out the entire type. ObjCInterfaceDecl *Def = ID->getDefinition(); if (!Def || !Def->getImplementation()) { - llvm::DIType FwdDecl = DBuilder.createReplaceableForwardDecl( + llvm::DIType FwdDecl = DBuilder.createReplaceableCompositeType( llvm::dwarf::DW_TAG_structure_type, ID->getName(), TheCU, DefUnit, Line, RuntimeLang); ObjCInterfaceCache.push_back(ObjCInterfaceCacheEntry(Ty, FwdDecl, Unit)); @@ -1933,9 +1945,9 @@ llvm::DIType CGDebugInfo::CreateEnumType(const EnumType *Ty) { llvm::DIFile DefUnit = getOrCreateFile(ED->getLocation()); unsigned Line = getLineNumber(ED->getLocation()); StringRef EDName = ED->getName(); - llvm::DIType RetTy = DBuilder.createReplaceableForwardDecl( + llvm::DIType RetTy = DBuilder.createReplaceableCompositeType( llvm::dwarf::DW_TAG_enumeration_type, EDName, EDContext, DefUnit, Line, - 0, Size, Align, FullName); + 0, Size, Align, llvm::DIDescriptor::FlagFwdDecl, FullName); ReplaceMap.emplace_back( std::piecewise_construct, std::make_tuple(Ty), std::make_tuple(static_cast(RetTy))); @@ -2249,19 +2261,8 @@ llvm::DICompositeType CGDebugInfo::CreateLimitedType(const RecordType *Ty) { SmallString<256> FullName = getUniqueTagTypeName(Ty, CGM, TheCU); - if (RD->isUnion()) - RealDecl = DBuilder.createUnionType(RDContext, RDName, DefUnit, Line, Size, - Align, 0, llvm::DIArray(), 0, FullName); - else if (RD->isClass()) { - // FIXME: This could be a struct type giving a default visibility different - // than C++ class type, but needs llvm metadata changes first. - RealDecl = DBuilder.createClassType( - RDContext, RDName, DefUnit, Line, Size, Align, 0, 0, llvm::DIType(), - llvm::DIArray(), llvm::DIType(), llvm::DIArray(), FullName); - } else - RealDecl = DBuilder.createStructType( - RDContext, RDName, DefUnit, Line, Size, Align, 0, llvm::DIType(), - llvm::DIArray(), 0, llvm::DIType(), FullName); + RealDecl = DBuilder.createReplaceableCompositeType(getTagForRecord(RD), + RDName, RDContext, DefUnit, Line, 0, Size, Align, 0, FullName); RegionMap[Ty->getDecl()].reset(RealDecl); TypeCache[QualType(Ty, 0).getAsOpaquePtr()].reset(RealDecl); diff --git a/test/CodeGen/debug-info-same-line.c b/test/CodeGen/debug-info-same-line.c new file mode 100644 index 0000000000..dddabda869 --- /dev/null +++ b/test/CodeGen/debug-info-same-line.c @@ -0,0 +1,7 @@ +// RUN: %clang_cc1 -triple x86_64-apple-darwin -emit-llvm %s -g -o - | FileCheck %s +// Here two temporary nodes are identical (but should not get uniqued) while +// building the full debug type. +typedef struct { long x; } foo; typedef struct { foo *x; } bar; +// CHECK: [ DW_TAG_structure_type ] [line 4, size 64, +// CHECK: [ DW_TAG_structure_type ] [line 4, size 64, +bar b;