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.

llvm-svn: 228855
This commit is contained in:
Adrian Prantl 2015-02-11 17:45:15 +00:00
parent 18a25b016e
commit 5f66bae411
2 changed files with 36 additions and 28 deletions

View File

@ -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<llvm::Metadata *>(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<CXXRecordDecl>(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<llvm::Metadata *>(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);

View File

@ -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;