From 99dab3b43c3a40a1281ba510e507d94a0ec3d336 Mon Sep 17 00:00:00 2001 From: David Blaikie Date: Wed, 4 Sep 2013 22:03:57 +0000 Subject: [PATCH] Reapply r189013 (reverted in r189906) now that the underlying issue is fixed and tested (in r189996) Debug info emission was tripping over an IRGen bug (fixed in r189996) that was resulting in duplicate emission of static data members of class templates in namespaces. We could add more test coverage to debug info for this issue specifically, but I think the underlying IRGen test is more targeted and sufficient for the issue. llvm-svn: 190001 --- clang/lib/CodeGen/CGDebugInfo.cpp | 64 +++++++++++++------------------ clang/lib/CodeGen/CGDebugInfo.h | 10 ++--- 2 files changed, 32 insertions(+), 42 deletions(-) diff --git a/clang/lib/CodeGen/CGDebugInfo.cpp b/clang/lib/CodeGen/CGDebugInfo.cpp index 4126e208604b..fe503982be3c 100644 --- a/clang/lib/CodeGen/CGDebugInfo.cpp +++ b/clang/lib/CodeGen/CGDebugInfo.cpp @@ -543,8 +543,7 @@ llvm::DIType CGDebugInfo::CreateType(const ComplexType *Ty) { /// CreateCVRType - Get the qualified type from the cache or create /// a new one if necessary. -llvm::DIType CGDebugInfo::CreateQualifiedType(QualType Ty, llvm::DIFile Unit, - bool Declaration) { +llvm::DIType CGDebugInfo::CreateQualifiedType(QualType Ty, llvm::DIFile Unit) { QualifierCollector Qc; const Type *T = Qc.strip(Ty); @@ -570,8 +569,7 @@ llvm::DIType CGDebugInfo::CreateQualifiedType(QualType Ty, llvm::DIFile Unit, return getOrCreateType(QualType(T, 0), Unit); } - llvm::DIType FromTy = - getOrCreateType(Qc.apply(CGM.getContext(), T), Unit, Declaration); + llvm::DIType FromTy = getOrCreateType(Qc.apply(CGM.getContext(), T), Unit); // No need to fill in the Name, Line, Size, Alignment, Offset in case of // CVR derived types. @@ -684,8 +682,7 @@ llvm::DIType CGDebugInfo::CreatePointerLikeType(unsigned Tag, llvm::DIFile Unit) { if (Tag == llvm::dwarf::DW_TAG_reference_type || Tag == llvm::dwarf::DW_TAG_rvalue_reference_type) - return DBuilder.createReferenceType( - Tag, getOrCreateType(PointeeTy, Unit, true)); + return DBuilder.createReferenceType(Tag, getOrCreateType(PointeeTy, Unit)); // Bit size, align and offset of the type. // Size is always the size of a pointer. We can't use getTypeSize here @@ -694,8 +691,8 @@ llvm::DIType CGDebugInfo::CreatePointerLikeType(unsigned Tag, uint64_t Size = CGM.getTarget().getPointerWidth(AS); uint64_t Align = CGM.getContext().getTypeAlign(Ty); - return DBuilder.createPointerType(getOrCreateType(PointeeTy, Unit, true), - Size, Align); + return DBuilder.createPointerType(getOrCreateType(PointeeTy, Unit), Size, + Align); } llvm::DIType CGDebugInfo::getOrCreateStructPtrType(StringRef Name, @@ -771,12 +768,10 @@ llvm::DIType CGDebugInfo::CreateType(const BlockPointerType *Ty, return BlockLiteralGeneric; } -llvm::DIType CGDebugInfo::CreateType(const TypedefType *Ty, llvm::DIFile Unit, - bool Declaration) { +llvm::DIType CGDebugInfo::CreateType(const TypedefType *Ty, llvm::DIFile Unit) { // Typedefs are derived from some other type. If we have a typedef of a // typedef, make sure to emit the whole chain. - llvm::DIType Src = - getOrCreateType(Ty->getDecl()->getUnderlyingType(), Unit, Declaration); + llvm::DIType Src = getOrCreateType(Ty->getDecl()->getUnderlyingType(), Unit); if (!Src) return llvm::DIType(); // We don't set size information, but do specify where the typedef was @@ -796,7 +791,7 @@ llvm::DIType CGDebugInfo::CreateType(const FunctionType *Ty, SmallVector EltTys; // Add the result type at least. - EltTys.push_back(getOrCreateType(Ty->getResultType(), Unit, true)); + EltTys.push_back(getOrCreateType(Ty->getResultType(), Unit)); // Set up remainder of arguments if there is a prototype. // FIXME: IF NOT, HOW IS THIS REPRESENTED? llvm-gcc doesn't represent '...'! @@ -804,7 +799,7 @@ llvm::DIType CGDebugInfo::CreateType(const FunctionType *Ty, EltTys.push_back(DBuilder.createUnspecifiedParameter()); else if (const FunctionProtoType *FPT = dyn_cast(Ty)) { for (unsigned i = 0, e = FPT->getNumArgs(); i != e; ++i) - EltTys.push_back(getOrCreateType(FPT->getArgType(i), Unit, true)); + EltTys.push_back(getOrCreateType(FPT->getArgType(i), Unit)); } llvm::DIArray EltTypeArray = DBuilder.getOrCreateArray(EltTys); @@ -1201,7 +1196,7 @@ CollectCXXFriends(const CXXRecordDecl *RD, llvm::DIFile Unit, continue; if (TypeSourceInfo *TInfo = (*BI)->getFriendType()) EltTys.push_back(DBuilder.createFriend( - RecordTy, getOrCreateType(TInfo->getType(), Unit, true))); + RecordTy, getOrCreateType(TInfo->getType(), Unit))); } } @@ -1503,12 +1498,16 @@ void CGDebugInfo::completeClassData(const RecordDecl *RD) { } /// CreateType - get structure or union type. -llvm::DIType CGDebugInfo::CreateType(const RecordType *Ty, bool Declaration) { +llvm::DIType CGDebugInfo::CreateType(const RecordType *Ty) { RecordDecl *RD = Ty->getDecl(); const CXXRecordDecl *CXXDecl = dyn_cast(RD); - // Limited debug info should only remove struct definitions that can - // safely be replaced by a forward declaration in the source code. - if ((DebugKind <= CodeGenOptions::LimitedDebugInfo && Declaration && + // Always emit declarations for types that aren't required to be complete when + // in limit-debug-info mode. If the type is later found to be required to be + // complete this declaration will be upgraded to a definition by + // `completeRequiredType`. + // If the type is dynamic, only emit the definition in TUs that require class + // data. This is handled by `completeClassData`. + if ((DebugKind <= CodeGenOptions::LimitedDebugInfo && !RD->isCompleteDefinitionRequired() && CGM.getLangOpts().CPlusPlus) || (CXXDecl && CXXDecl->hasDefinition() && CXXDecl->isDynamicClass())) { llvm::DIDescriptor FDContext = @@ -1886,7 +1885,7 @@ llvm::DIType CGDebugInfo::CreateType(const MemberPointerType *Ty, llvm::DIType ClassType = getOrCreateType(QualType(Ty->getClass(), 0), U); if (!Ty->getPointeeType()->isFunctionType()) return DBuilder.createMemberPointerType( - getOrCreateType(Ty->getPointeeType(), U, true), ClassType); + getOrCreateType(Ty->getPointeeType(), U), ClassType); return DBuilder.createMemberPointerType(getOrCreateInstanceMethodType( CGM.getContext().getPointerType( QualType(Ty->getClass(), Ty->getPointeeType().getCVRQualifiers())), @@ -2066,26 +2065,18 @@ llvm::Value *CGDebugInfo::getCachedInterfaceTypeOrNull(QualType Ty) { /// getOrCreateType - Get the type from the cache or create a new /// one if necessary. -llvm::DIType CGDebugInfo::getOrCreateType(QualType Ty, llvm::DIFile Unit, - bool Declaration) { +llvm::DIType CGDebugInfo::getOrCreateType(QualType Ty, llvm::DIFile Unit) { if (Ty.isNull()) return llvm::DIType(); // Unwrap the type as needed for debug information. Ty = UnwrapTypeForDebugInfo(Ty, CGM.getContext()); - if (llvm::DIType T = getCompletedTypeOrNull(Ty)) { - // If we're looking for a definition, make sure we have definitions of any - // underlying types. - if (const TypedefType* TTy = dyn_cast(Ty)) - getOrCreateType(TTy->getDecl()->getUnderlyingType(), Unit, Declaration); - if (Ty.hasLocalQualifiers()) - getOrCreateType(QualType(Ty.getTypePtr(), 0), Unit, Declaration); + if (llvm::DIType T = getCompletedTypeOrNull(Ty)) return T; - } // Otherwise create the type. - llvm::DIType Res = CreateTypeNode(Ty, Unit, Declaration); + llvm::DIType Res = CreateTypeNode(Ty, Unit); void* TyPtr = Ty.getAsOpaquePtr(); // And update the type cache. @@ -2154,11 +2145,10 @@ ObjCInterfaceDecl *CGDebugInfo::getObjCInterfaceDecl(QualType Ty) { } /// CreateTypeNode - Create a new debug type node. -llvm::DIType CGDebugInfo::CreateTypeNode(QualType Ty, llvm::DIFile Unit, - bool Declaration) { +llvm::DIType CGDebugInfo::CreateTypeNode(QualType Ty, llvm::DIFile Unit) { // Handle qualifiers, which recursively handles what they refer to. if (Ty.hasLocalQualifiers()) - return CreateQualifiedType(Ty, Unit, Declaration); + return CreateQualifiedType(Ty, Unit); const char *Diag = 0; @@ -2193,9 +2183,9 @@ llvm::DIType CGDebugInfo::CreateTypeNode(QualType Ty, llvm::DIFile Unit, case Type::BlockPointer: return CreateType(cast(Ty), Unit); case Type::Typedef: - return CreateType(cast(Ty), Unit, Declaration); + return CreateType(cast(Ty), Unit); case Type::Record: - return CreateType(cast(Ty), Declaration); + return CreateType(cast(Ty)); case Type::Enum: return CreateEnumType(cast(Ty)); case Type::FunctionProto: @@ -2381,7 +2371,7 @@ llvm::DIDescriptor CGDebugInfo::getDeclarationOrDefinition(const Decl *D) { // in unlimited debug info) if (const TypeDecl *TD = dyn_cast(D)) return getOrCreateType(CGM.getContext().getTypeDeclType(TD), - getOrCreateFile(TD->getLocation()), true); + getOrCreateFile(TD->getLocation())); // Otherwise fall back to a fairly rudimentary cache of existing declarations. // This doesn't handle providing declarations (for functions or variables) for // entities without definitions in this TU, nor when the definition proceeds diff --git a/clang/lib/CodeGen/CGDebugInfo.h b/clang/lib/CodeGen/CGDebugInfo.h index 3003ce65fd92..a8ba14b8b3fe 100644 --- a/clang/lib/CodeGen/CGDebugInfo.h +++ b/clang/lib/CodeGen/CGDebugInfo.h @@ -107,14 +107,14 @@ class CGDebugInfo { unsigned Checksum(const ObjCInterfaceDecl *InterfaceDecl); llvm::DIType CreateType(const BuiltinType *Ty); llvm::DIType CreateType(const ComplexType *Ty); - llvm::DIType CreateQualifiedType(QualType Ty, llvm::DIFile F, bool Declaration); - llvm::DIType CreateType(const TypedefType *Ty, llvm::DIFile F, bool Declaration); + llvm::DIType CreateQualifiedType(QualType Ty, llvm::DIFile Fg); + llvm::DIType CreateType(const TypedefType *Ty, llvm::DIFile Fg); llvm::DIType CreateType(const ObjCObjectPointerType *Ty, llvm::DIFile F); llvm::DIType CreateType(const PointerType *Ty, llvm::DIFile F); llvm::DIType CreateType(const BlockPointerType *Ty, llvm::DIFile F); llvm::DIType CreateType(const FunctionType *Ty, llvm::DIFile F); - llvm::DIType CreateType(const RecordType *Ty, bool Declaration); + llvm::DIType CreateType(const RecordType *Tyg); llvm::DIType CreateTypeDefinition(const RecordType *Ty); llvm::DICompositeType CreateLimitedType(const RecordType *Ty); void CollectContainingType(const CXXRecordDecl *RD, llvm::DICompositeType CT); @@ -330,14 +330,14 @@ private: /// getOrCreateType - Get the type from the cache or create a new type if /// necessary. - llvm::DIType getOrCreateType(QualType Ty, llvm::DIFile F, bool Declaration = false); + llvm::DIType getOrCreateType(QualType Ty, llvm::DIFile Fg); /// getOrCreateLimitedType - Get the type from the cache or create a new /// partial type if necessary. llvm::DIType getOrCreateLimitedType(const RecordType *Ty, llvm::DIFile F); /// CreateTypeNode - Create type metadata for a source language type. - llvm::DIType CreateTypeNode(QualType Ty, llvm::DIFile F, bool Declaration); + llvm::DIType CreateTypeNode(QualType Ty, llvm::DIFile Fg); /// getObjCInterfaceDecl - return the underlying ObjCInterfaceDecl /// if Ty is an ObjCInterface or a pointer to one. -- GitLab