Index: llvm/trunk/include/llvm/IR/DIBuilder.h =================================================================== --- llvm/trunk/include/llvm/IR/DIBuilder.h +++ llvm/trunk/include/llvm/IR/DIBuilder.h @@ -560,6 +560,9 @@ /// virtual function. /// \param VTableIndex Index no of this method in virtual table, or -1u if /// unrepresentable. + /// \param ThisAdjustment + /// MS ABI-specific adjustment of 'this' that occurs + /// in the prologue. /// \param VTableHolder Type that holds vtable. /// \param Flags e.g. is this function prototyped or not. /// This flags are used to emit dwarf attributes. @@ -569,8 +572,9 @@ createMethod(DIScope *Scope, StringRef Name, StringRef LinkageName, DIFile *File, unsigned LineNo, DISubroutineType *Ty, bool isLocalToUnit, bool isDefinition, unsigned Virtuality = 0, - unsigned VTableIndex = 0, DIType *VTableHolder = nullptr, - unsigned Flags = 0, bool isOptimized = false, + unsigned VTableIndex = 0, int ThisAdjustment = 0, + DIType *VTableHolder = nullptr, unsigned Flags = 0, + bool isOptimized = false, DITemplateParameterArray TParams = nullptr); /// This creates new descriptor for a namespace with the specified Index: llvm/trunk/include/llvm/IR/DebugInfoMetadata.h =================================================================== --- llvm/trunk/include/llvm/IR/DebugInfoMetadata.h +++ llvm/trunk/include/llvm/IR/DebugInfoMetadata.h @@ -1280,6 +1280,11 @@ unsigned ScopeLine; unsigned VirtualIndex; + /// In the MS ABI, the implicit 'this' parameter is adjusted in the prologue + /// of method overrides from secondary bases by this amount. It may be + /// negative. + int ThisAdjustment; + // Virtuality can only assume three values, so we can pack // in 2 bits (none/pure/pure_virtual). unsigned Virtuality : 2; @@ -1296,13 +1301,14 @@ DISubprogram(LLVMContext &C, StorageType Storage, unsigned Line, unsigned ScopeLine, unsigned Virtuality, unsigned VirtualIndex, - unsigned Flags, bool IsLocalToUnit, bool IsDefinition, - bool IsOptimized, ArrayRef Ops) + int ThisAdjustment, unsigned Flags, bool IsLocalToUnit, + bool IsDefinition, bool IsOptimized, ArrayRef Ops) : DILocalScope(C, DISubprogramKind, Storage, dwarf::DW_TAG_subprogram, Ops), Line(Line), ScopeLine(ScopeLine), VirtualIndex(VirtualIndex), - Virtuality(Virtuality), Flags(Flags), IsLocalToUnit(IsLocalToUnit), - IsDefinition(IsDefinition), IsOptimized(IsOptimized) { + ThisAdjustment(ThisAdjustment), Virtuality(Virtuality), Flags(Flags), + IsLocalToUnit(IsLocalToUnit), IsDefinition(IsDefinition), + IsOptimized(IsOptimized) { static_assert(dwarf::DW_VIRTUALITY_max < 4, "Virtuality out of range"); assert(Virtuality < 4 && "Virtuality out of range"); assert((Flags < (1 << 27)) && "Flags out of range"); @@ -1314,33 +1320,34 @@ StringRef LinkageName, DIFile *File, unsigned Line, DISubroutineType *Type, bool IsLocalToUnit, bool IsDefinition, unsigned ScopeLine, DITypeRef ContainingType, unsigned Virtuality, - unsigned VirtualIndex, unsigned Flags, bool IsOptimized, - DICompileUnit *Unit, DITemplateParameterArray TemplateParams, - DISubprogram *Declaration, DILocalVariableArray Variables, - StorageType Storage, bool ShouldCreate = true) { + unsigned VirtualIndex, int ThisAdjustment, unsigned Flags, + bool IsOptimized, DICompileUnit *Unit, + DITemplateParameterArray TemplateParams, DISubprogram *Declaration, + DILocalVariableArray Variables, StorageType Storage, + bool ShouldCreate = true) { return getImpl(Context, Scope, getCanonicalMDString(Context, Name), getCanonicalMDString(Context, LinkageName), File, Line, Type, IsLocalToUnit, IsDefinition, ScopeLine, ContainingType, - Virtuality, VirtualIndex, Flags, IsOptimized, Unit, - TemplateParams.get(), Declaration, Variables.get(), Storage, - ShouldCreate); + Virtuality, VirtualIndex, ThisAdjustment, Flags, IsOptimized, + Unit, TemplateParams.get(), Declaration, Variables.get(), + Storage, ShouldCreate); } static DISubprogram * getImpl(LLVMContext &Context, Metadata *Scope, MDString *Name, MDString *LinkageName, Metadata *File, unsigned Line, Metadata *Type, bool IsLocalToUnit, bool IsDefinition, unsigned ScopeLine, Metadata *ContainingType, unsigned Virtuality, unsigned VirtualIndex, - unsigned Flags, bool IsOptimized, Metadata *Unit, + int ThisAdjustment, unsigned Flags, bool IsOptimized, Metadata *Unit, Metadata *TemplateParams, Metadata *Declaration, Metadata *Variables, StorageType Storage, bool ShouldCreate = true); TempDISubprogram cloneImpl() const { - return getTemporary(getContext(), getScope(), getName(), getLinkageName(), - getFile(), getLine(), getType(), isLocalToUnit(), - isDefinition(), getScopeLine(), getContainingType(), - getVirtuality(), getVirtualIndex(), getFlags(), - isOptimized(), getUnit(), getTemplateParams(), - getDeclaration(), getVariables()); + return getTemporary( + getContext(), getScope(), getName(), getLinkageName(), getFile(), + getLine(), getType(), isLocalToUnit(), isDefinition(), getScopeLine(), + getContainingType(), getVirtuality(), getVirtualIndex(), + getThisAdjustment(), getFlags(), isOptimized(), getUnit(), + getTemplateParams(), getDeclaration(), getVariables()); } public: @@ -1349,26 +1356,26 @@ DIFile *File, unsigned Line, DISubroutineType *Type, bool IsLocalToUnit, bool IsDefinition, unsigned ScopeLine, DITypeRef ContainingType, unsigned Virtuality, - unsigned VirtualIndex, unsigned Flags, bool IsOptimized, - DICompileUnit *Unit, + unsigned VirtualIndex, int ThisAdjustment, unsigned Flags, + bool IsOptimized, DICompileUnit *Unit, DITemplateParameterArray TemplateParams = nullptr, DISubprogram *Declaration = nullptr, DILocalVariableArray Variables = nullptr), (Scope, Name, LinkageName, File, Line, Type, IsLocalToUnit, IsDefinition, ScopeLine, ContainingType, Virtuality, - VirtualIndex, Flags, IsOptimized, Unit, TemplateParams, - Declaration, Variables)) + VirtualIndex, ThisAdjustment, Flags, IsOptimized, Unit, + TemplateParams, Declaration, Variables)) DEFINE_MDNODE_GET( DISubprogram, (Metadata * Scope, MDString *Name, MDString *LinkageName, Metadata *File, unsigned Line, Metadata *Type, bool IsLocalToUnit, bool IsDefinition, unsigned ScopeLine, Metadata *ContainingType, unsigned Virtuality, - unsigned VirtualIndex, unsigned Flags, bool IsOptimized, - Metadata *Unit, Metadata *TemplateParams = nullptr, + unsigned VirtualIndex, int ThisAdjustment, unsigned Flags, + bool IsOptimized, Metadata *Unit, Metadata *TemplateParams = nullptr, Metadata *Declaration = nullptr, Metadata *Variables = nullptr), (Scope, Name, LinkageName, File, Line, Type, IsLocalToUnit, IsDefinition, - ScopeLine, ContainingType, Virtuality, VirtualIndex, Flags, IsOptimized, - Unit, TemplateParams, Declaration, Variables)) + ScopeLine, ContainingType, Virtuality, VirtualIndex, ThisAdjustment, + Flags, IsOptimized, Unit, TemplateParams, Declaration, Variables)) TempDISubprogram clone() const { return cloneImpl(); } @@ -1376,6 +1383,7 @@ unsigned getLine() const { return Line; } unsigned getVirtuality() const { return Virtuality; } unsigned getVirtualIndex() const { return VirtualIndex; } + int getThisAdjustment() const { return ThisAdjustment; } unsigned getScopeLine() const { return ScopeLine; } unsigned getFlags() const { return Flags; } bool isLocalToUnit() const { return IsLocalToUnit; } Index: llvm/trunk/lib/AsmParser/LLParser.cpp =================================================================== --- llvm/trunk/lib/AsmParser/LLParser.cpp +++ llvm/trunk/lib/AsmParser/LLParser.cpp @@ -3983,7 +3983,7 @@ /// file: !1, line: 7, type: !2, isLocal: false, /// isDefinition: true, scopeLine: 8, containingType: !3, /// virtuality: DW_VIRTUALTIY_pure_virtual, -/// virtualIndex: 10, flags: 11, +/// virtualIndex: 10, thisAdjustment: 4, flags: 11, /// isOptimized: false, templateParams: !4, declaration: !5, /// variables: !6) bool LLParser::ParseDISubprogram(MDNode *&Result, bool IsDistinct) { @@ -4001,6 +4001,7 @@ OPTIONAL(containingType, MDField, ); \ OPTIONAL(virtuality, DwarfVirtualityField, ); \ OPTIONAL(virtualIndex, MDUnsignedField, (0, UINT32_MAX)); \ + OPTIONAL(thisAdjustment, MDSignedField, (0, INT32_MIN, INT32_MAX)); \ OPTIONAL(flags, DIFlagField, ); \ OPTIONAL(isOptimized, MDBoolField, ); \ OPTIONAL(unit, MDField, ); \ @@ -4019,8 +4020,9 @@ DISubprogram, (Context, scope.Val, name.Val, linkageName.Val, file.Val, line.Val, type.Val, isLocal.Val, isDefinition.Val, scopeLine.Val, containingType.Val, virtuality.Val, - virtualIndex.Val, flags.Val, isOptimized.Val, unit.Val, - templateParams.Val, declaration.Val, variables.Val)); + virtualIndex.Val, thisAdjustment.Val, flags.Val, + isOptimized.Val, unit.Val, templateParams.Val, + declaration.Val, variables.Val)); return false; } Index: llvm/trunk/lib/Bitcode/Reader/BitcodeReader.cpp =================================================================== --- llvm/trunk/lib/Bitcode/Reader/BitcodeReader.cpp +++ llvm/trunk/lib/Bitcode/Reader/BitcodeReader.cpp @@ -2466,7 +2466,7 @@ break; } case bitc::METADATA_SUBPROGRAM: { - if (Record.size() != 18 && Record.size() != 19) + if (Record.size() < 18 || Record.size() > 20) return error("Invalid record"); IsDistinct = @@ -2474,21 +2474,36 @@ // Version 1 has a Function as Record[15]. // Version 2 has removed Record[15]. // Version 3 has the Unit as Record[15]. + // Version 4 added thisAdjustment. bool HasUnit = Record[0] >= 2; - if (HasUnit && Record.size() != 19) + if (HasUnit && Record.size() < 19) return error("Invalid record"); Metadata *CUorFn = getMDOrNull(Record[15]); - unsigned Offset = Record.size() == 19 ? 1 : 0; + unsigned Offset = Record.size() >= 19 ? 1 : 0; bool HasFn = Offset && !HasUnit; + bool HasThisAdj = Record.size() >= 20; DISubprogram *SP = GET_OR_DISTINCT( - DISubprogram, - (Context, getDITypeRefOrNull(Record[1]), getMDString(Record[2]), - getMDString(Record[3]), getMDOrNull(Record[4]), Record[5], - getMDOrNull(Record[6]), Record[7], Record[8], Record[9], - getDITypeRefOrNull(Record[10]), Record[11], Record[12], Record[13], - Record[14], HasUnit ? CUorFn : nullptr, - getMDOrNull(Record[15 + Offset]), getMDOrNull(Record[16 + Offset]), - getMDOrNull(Record[17 + Offset]))); + DISubprogram, (Context, + getDITypeRefOrNull(Record[1]), // scope + getMDString(Record[2]), // name + getMDString(Record[3]), // linkageName + getMDOrNull(Record[4]), // file + Record[5], // line + getMDOrNull(Record[6]), // type + Record[7], // isLocal + Record[8], // isDefinition + Record[9], // scopeLine + getDITypeRefOrNull(Record[10]), // containingType + Record[11], // virtuality + Record[12], // virtualIndex + HasThisAdj ? Record[19] : 0, // thisAdjustment + Record[13], // flags + Record[14], // isOptimized + HasUnit ? CUorFn : nullptr, // unit + getMDOrNull(Record[15 + Offset]), // templateParams + getMDOrNull(Record[16 + Offset]), // declaration + getMDOrNull(Record[17 + Offset]) // variables + )); MetadataList.assignValue(SP, NextMetadataNo++); // Upgrade sp->function mapping to function->sp mapping. Index: llvm/trunk/lib/Bitcode/Writer/BitcodeWriter.cpp =================================================================== --- llvm/trunk/lib/Bitcode/Writer/BitcodeWriter.cpp +++ llvm/trunk/lib/Bitcode/Writer/BitcodeWriter.cpp @@ -1543,6 +1543,7 @@ Record.push_back(VE.getMetadataOrNullID(N->getTemplateParams().get())); Record.push_back(VE.getMetadataOrNullID(N->getDeclaration())); Record.push_back(VE.getMetadataOrNullID(N->getVariables().get())); + Record.push_back(N->getThisAdjustment()); Stream.EmitRecord(bitc::METADATA_SUBPROGRAM, Record, Abbrev); Record.clear(); Index: llvm/trunk/lib/CodeGen/AsmPrinter/CodeViewDebug.cpp =================================================================== --- llvm/trunk/lib/CodeGen/AsmPrinter/CodeViewDebug.cpp +++ llvm/trunk/lib/CodeGen/AsmPrinter/CodeViewDebug.cpp @@ -156,6 +156,18 @@ return getQualifiedName(QualifiedNameComponents, Name); } +struct CodeViewDebug::TypeLoweringScope { + TypeLoweringScope(CodeViewDebug &CVD) : CVD(CVD) { ++CVD.TypeEmissionLevel; } + ~TypeLoweringScope() { + // Don't decrement TypeEmissionLevel until after emitting deferred types, so + // inner TypeLoweringScopes don't attempt to emit deferred types. + if (CVD.TypeEmissionLevel == 1) + CVD.emitDeferredCompleteTypes(); + --CVD.TypeEmissionLevel; + } + CodeViewDebug &CVD; +}; + TypeIndex CodeViewDebug::getScopeIndex(const DIScope *Scope) { // No scope means global scope and that uses the zero index. if (!Scope || isa(Scope)) @@ -213,16 +225,24 @@ TypeIndex CodeViewDebug::getMemberFunctionType(const DISubprogram *SP, const DICompositeType *Class) { + // Always use the method declaration as the key for the function type. The + // method declaration contains the this adjustment. + if (SP->getDeclaration()) + SP = SP->getDeclaration(); + assert(!SP->getDeclaration() && "should use declaration as key"); + // Key the MemberFunctionRecord into the map as {SP, Class}. It won't collide // with the MemberFuncIdRecord, which is keyed in as {SP, nullptr}. - auto I = TypeIndices.find({SP, nullptr}); + auto I = TypeIndices.find({SP, Class}); if (I != TypeIndices.end()) return I->second; - // FIXME: Get the ThisAdjustment off of SP when it is available. + // Make sure complete type info for the class is emitted *after* the member + // function type, as the complete class type is likely to reference this + // member function type. + TypeLoweringScope S(*this); TypeIndex TI = - lowerTypeMemberFunction(SP->getType(), Class, /*ThisAdjustment=*/0); - + lowerTypeMemberFunction(SP->getType(), Class, SP->getThisAdjustment()); return recordTypeIndexForDINode(SP, TI, Class); } @@ -1582,18 +1602,6 @@ return VBPType; } -struct CodeViewDebug::TypeLoweringScope { - TypeLoweringScope(CodeViewDebug &CVD) : CVD(CVD) { ++CVD.TypeEmissionLevel; } - ~TypeLoweringScope() { - // Don't decrement TypeEmissionLevel until after emitting deferred types, so - // inner TypeLoweringScopes don't attempt to emit deferred types. - if (CVD.TypeEmissionLevel == 1) - CVD.emitDeferredCompleteTypes(); - --CVD.TypeEmissionLevel; - } - CodeViewDebug &CVD; -}; - TypeIndex CodeViewDebug::getTypeIndex(DITypeRef TypeRef, DITypeRef ClassTyRef) { const DIType *Ty = TypeRef.resolve(); const DIType *ClassTy = ClassTyRef.resolve(); @@ -1609,14 +1617,9 @@ if (I != TypeIndices.end()) return I->second; - TypeIndex TI; - { - TypeLoweringScope S(*this); - TI = lowerType(Ty, ClassTy); - recordTypeIndexForDINode(Ty, TI, ClassTy); - } - - return TI; + TypeLoweringScope S(*this); + TypeIndex TI = lowerType(Ty, ClassTy); + return recordTypeIndexForDINode(Ty, TI, ClassTy); } TypeIndex CodeViewDebug::getCompleteTypeIndex(DITypeRef TypeRef) { Index: llvm/trunk/lib/IR/AsmWriter.cpp =================================================================== --- llvm/trunk/lib/IR/AsmWriter.cpp +++ llvm/trunk/lib/IR/AsmWriter.cpp @@ -1720,6 +1720,7 @@ if (N->getVirtuality() != dwarf::DW_VIRTUALITY_none || N->getVirtualIndex() != 0) Printer.printInt("virtualIndex", N->getVirtualIndex(), false); + Printer.printInt("thisAdjustment", N->getThisAdjustment()); Printer.printDIFlags("flags", N->getFlags()); Printer.printBool("isOptimized", N->isOptimized()); Printer.printMetadata("unit", N->getRawUnit()); Index: llvm/trunk/lib/IR/DIBuilder.cpp =================================================================== --- llvm/trunk/lib/IR/DIBuilder.cpp +++ llvm/trunk/lib/IR/DIBuilder.cpp @@ -667,8 +667,8 @@ auto *Node = getSubprogram( /* IsDistinct = */ isDefinition, VMContext, getNonCompileUnitScope(Context), Name, LinkageName, File, LineNo, Ty, - isLocalToUnit, isDefinition, ScopeLine, nullptr, 0, 0, Flags, isOptimized, - isDefinition ? CUNode : nullptr, TParams, Decl, + isLocalToUnit, isDefinition, ScopeLine, nullptr, 0, 0, 0, Flags, + isOptimized, isDefinition ? CUNode : nullptr, TParams, Decl, MDTuple::getTemporary(VMContext, None).release()); if (isDefinition) @@ -685,8 +685,8 @@ return DISubprogram::getTemporary( VMContext, getNonCompileUnitScope(Context), Name, LinkageName, File, LineNo, Ty, isLocalToUnit, isDefinition, ScopeLine, nullptr, - 0, 0, Flags, isOptimized, isDefinition ? CUNode : nullptr, TParams, - Decl, nullptr) + 0, 0, 0, Flags, isOptimized, isDefinition ? CUNode : nullptr, + TParams, Decl, nullptr) .release(); } @@ -694,8 +694,9 @@ DIBuilder::createMethod(DIScope *Context, StringRef Name, StringRef LinkageName, DIFile *F, unsigned LineNo, DISubroutineType *Ty, bool isLocalToUnit, bool isDefinition, unsigned VK, - unsigned VIndex, DIType *VTableHolder, unsigned Flags, - bool isOptimized, DITemplateParameterArray TParams) { + unsigned VIndex, int ThisAdjustment, + DIType *VTableHolder, unsigned Flags, bool isOptimized, + DITemplateParameterArray TParams) { assert(getNonCompileUnitScope(Context) && "Methods should have both a Context and a context that isn't " "the compile unit."); @@ -703,7 +704,7 @@ auto *SP = getSubprogram( /* IsDistinct = */ isDefinition, VMContext, cast(Context), Name, LinkageName, F, LineNo, Ty, isLocalToUnit, isDefinition, LineNo, - VTableHolder, VK, VIndex, Flags, isOptimized, + VTableHolder, VK, VIndex, ThisAdjustment, Flags, isOptimized, isDefinition ? CUNode : nullptr, TParams, nullptr, nullptr); if (isDefinition) Index: llvm/trunk/lib/IR/DebugInfoMetadata.cpp =================================================================== --- llvm/trunk/lib/IR/DebugInfoMetadata.cpp +++ llvm/trunk/lib/IR/DebugInfoMetadata.cpp @@ -412,22 +412,22 @@ MDString *LinkageName, Metadata *File, unsigned Line, Metadata *Type, bool IsLocalToUnit, bool IsDefinition, unsigned ScopeLine, Metadata *ContainingType, unsigned Virtuality, unsigned VirtualIndex, - unsigned Flags, bool IsOptimized, Metadata *Unit, Metadata *TemplateParams, - Metadata *Declaration, Metadata *Variables, StorageType Storage, - bool ShouldCreate) { + int ThisAdjustment, unsigned Flags, bool IsOptimized, Metadata *Unit, + Metadata *TemplateParams, Metadata *Declaration, Metadata *Variables, + StorageType Storage, bool ShouldCreate) { assert(isCanonical(Name) && "Expected canonical MDString"); assert(isCanonical(LinkageName) && "Expected canonical MDString"); - DEFINE_GETIMPL_LOOKUP(DISubprogram, - (Scope, Name, LinkageName, File, Line, Type, - IsLocalToUnit, IsDefinition, ScopeLine, ContainingType, - Virtuality, VirtualIndex, Flags, IsOptimized, Unit, - TemplateParams, Declaration, Variables)); + DEFINE_GETIMPL_LOOKUP( + DISubprogram, + (Scope, Name, LinkageName, File, Line, Type, IsLocalToUnit, IsDefinition, + ScopeLine, ContainingType, Virtuality, VirtualIndex, ThisAdjustment, + Flags, IsOptimized, Unit, TemplateParams, Declaration, Variables)); Metadata *Ops[] = {File, Scope, Name, Name, LinkageName, Type, ContainingType, Unit, TemplateParams, Declaration, Variables}; - DEFINE_GETIMPL_STORE(DISubprogram, - (Line, ScopeLine, Virtuality, VirtualIndex, Flags, - IsLocalToUnit, IsDefinition, IsOptimized), + DEFINE_GETIMPL_STORE(DISubprogram, (Line, ScopeLine, Virtuality, VirtualIndex, + ThisAdjustment, Flags, IsLocalToUnit, + IsDefinition, IsOptimized), Ops); } Index: llvm/trunk/lib/IR/LLVMContextImpl.h =================================================================== --- llvm/trunk/lib/IR/LLVMContextImpl.h +++ llvm/trunk/lib/IR/LLVMContextImpl.h @@ -528,6 +528,7 @@ Metadata *ContainingType; unsigned Virtuality; unsigned VirtualIndex; + int ThisAdjustment; unsigned Flags; bool IsOptimized; Metadata *Unit; @@ -539,15 +540,16 @@ Metadata *File, unsigned Line, Metadata *Type, bool IsLocalToUnit, bool IsDefinition, unsigned ScopeLine, Metadata *ContainingType, unsigned Virtuality, - unsigned VirtualIndex, unsigned Flags, bool IsOptimized, - Metadata *Unit, Metadata *TemplateParams, Metadata *Declaration, - Metadata *Variables) + unsigned VirtualIndex, int ThisAdjustment, unsigned Flags, + bool IsOptimized, Metadata *Unit, Metadata *TemplateParams, + Metadata *Declaration, Metadata *Variables) : Scope(Scope), Name(Name), LinkageName(LinkageName), File(File), Line(Line), Type(Type), IsLocalToUnit(IsLocalToUnit), IsDefinition(IsDefinition), ScopeLine(ScopeLine), ContainingType(ContainingType), Virtuality(Virtuality), - VirtualIndex(VirtualIndex), Flags(Flags), IsOptimized(IsOptimized), - Unit(Unit), TemplateParams(TemplateParams), Declaration(Declaration), + VirtualIndex(VirtualIndex), ThisAdjustment(ThisAdjustment), + Flags(Flags), IsOptimized(IsOptimized), Unit(Unit), + TemplateParams(TemplateParams), Declaration(Declaration), Variables(Variables) {} MDNodeKeyImpl(const DISubprogram *N) : Scope(N->getRawScope()), Name(N->getRawName()), @@ -556,8 +558,9 @@ IsLocalToUnit(N->isLocalToUnit()), IsDefinition(N->isDefinition()), ScopeLine(N->getScopeLine()), ContainingType(N->getRawContainingType()), Virtuality(N->getVirtuality()), VirtualIndex(N->getVirtualIndex()), - Flags(N->getFlags()), IsOptimized(N->isOptimized()), - Unit(N->getRawUnit()), TemplateParams(N->getRawTemplateParams()), + ThisAdjustment(N->getThisAdjustment()), Flags(N->getFlags()), + IsOptimized(N->isOptimized()), Unit(N->getRawUnit()), + TemplateParams(N->getRawTemplateParams()), Declaration(N->getRawDeclaration()), Variables(N->getRawVariables()) {} bool isKeyOf(const DISubprogram *RHS) const { @@ -569,8 +572,10 @@ ScopeLine == RHS->getScopeLine() && ContainingType == RHS->getRawContainingType() && Virtuality == RHS->getVirtuality() && - VirtualIndex == RHS->getVirtualIndex() && Flags == RHS->getFlags() && - IsOptimized == RHS->isOptimized() && Unit == RHS->getUnit() && + VirtualIndex == RHS->getVirtualIndex() && + ThisAdjustment == RHS->getThisAdjustment() && + Flags == RHS->getFlags() && IsOptimized == RHS->isOptimized() && + Unit == RHS->getUnit() && TemplateParams == RHS->getRawTemplateParams() && Declaration == RHS->getRawDeclaration() && Variables == RHS->getRawVariables(); Index: llvm/trunk/test/Assembler/disubprogram.ll =================================================================== --- llvm/trunk/test/Assembler/disubprogram.ll +++ llvm/trunk/test/Assembler/disubprogram.ll @@ -28,13 +28,13 @@ ; CHECK: !9 = !DISubprogram(scope: null, isLocal: false, isDefinition: false, isOptimized: false) !9 = !DISubprogram(isDefinition: false) -; CHECK: !10 = distinct !DISubprogram(name: "foo", linkageName: "_Zfoov", scope: !1, file: !2, line: 7, type: !3, isLocal: true, isDefinition: true, scopeLine: 8, containingType: !4, virtuality: DW_VIRTUALITY_pure_virtual, virtualIndex: 10, flags: DIFlagPrototyped, isOptimized: true, unit: !8, templateParams: !5, declaration: !9, variables: !6) +; CHECK: !10 = distinct !DISubprogram(name: "foo", linkageName: "_Zfoov", scope: !1, file: !2, line: 7, type: !3, isLocal: true, isDefinition: true, scopeLine: 8, containingType: !4, virtuality: DW_VIRTUALITY_pure_virtual, virtualIndex: 10, thisAdjustment: 3, flags: DIFlagPrototyped, isOptimized: true, unit: !8, templateParams: !5, declaration: !9, variables: !6) !10 = distinct !DISubprogram(name: "foo", linkageName: "_Zfoov", scope: !1, file: !2, line: 7, type: !3, isLocal: true, isDefinition: true, scopeLine: 8, containingType: !4, virtuality: DW_VIRTUALITY_pure_virtual, - virtualIndex: 10, flags: DIFlagPrototyped, + virtualIndex: 10, thisAdjustment: 3, flags: DIFlagPrototyped, isOptimized: true, unit: !8, templateParams: !5, declaration: !9, variables: !6) Index: llvm/trunk/test/Bitcode/upgrade-subprogram-this.ll =================================================================== --- llvm/trunk/test/Bitcode/upgrade-subprogram-this.ll +++ llvm/trunk/test/Bitcode/upgrade-subprogram-this.ll @@ -0,0 +1,30 @@ +; RUN: llvm-dis < %s.bc | FileCheck %s +; RUN: verify-uselistorder < %s.bc + +; Test upgrading from bitcode without a this adjustment record. It will fill in +; an implicit zero thisAdjustment, so it will not be present in the output. + +; CHECK: DISubprogram(name: "f", +; CHECK-NOT: thisAdjustment +; CHECK-SAME: ){{$}} + +target datalayout = "e-m:w-i64:64-f80:128-n8:16:32:64-S128" +target triple = "x86_64-pc-windows-msvc19.0.23918" + +; Function Attrs: nounwind uwtable +define void @f() !dbg !7 { +entry: + ret void, !dbg !10 +} + +!llvm.dbg.cu = !{!0} +!llvm.module.flags = !{!4} + +!0 = distinct !DICompileUnit(language: DW_LANG_C_plus_plus, file: !1, emissionKind: FullDebug) +!1 = !DIFile(filename: "t.cpp", directory: "D:\5Csrc\5Cllvm\5Cbuild") +!2 = !{} +!4 = !{i32 2, !"Debug Info Version", i32 3} +!7 = distinct !DISubprogram(name: "f", linkageName: "\01?f@@YAXXZ", scope: !1, file: !1, line: 1, type: !8, isLocal: false, isDefinition: true, scopeLine: 1, flags: DIFlagPrototyped, isOptimized: false, unit: !0, variables: !2) +!8 = !DISubroutineType(types: !9) +!9 = !{null} +!10 = !DILocation(line: 1, column: 11, scope: !7) Index: llvm/trunk/test/DebugInfo/COFF/virtual-methods.ll =================================================================== --- llvm/trunk/test/DebugInfo/COFF/virtual-methods.ll +++ llvm/trunk/test/DebugInfo/COFF/virtual-methods.ll @@ -0,0 +1,441 @@ +; RUN: llc < %s -filetype=obj | llvm-readobj - -codeview | FileCheck %s + +; C++ source used to generate IR: +; $ cat t.cpp +; struct A { +; virtual int f(); +; }; +; struct B { +; virtual int g() = 0; +; }; +; struct C : A, B { +; int c = 42; +; virtual int g(); +; }; +; int C::g() { return c; } +; struct D : virtual B { +; int d = 13; +; virtual int g(); +; }; +; int D::g() { return d; } +; $ clang t.cpp -S -emit-llvm -fstandalone-debug -g -gcodeview -o t.ll + +; A::f +; CHECK: MemberFunction ({{.*}}) { +; CHECK-NEXT: TypeLeafKind: LF_MFUNCTION (0x1009) +; CHECK-NEXT: ReturnType: int (0x74) +; CHECK-NEXT: ClassType: A ({{.*}}) +; CHECK-NEXT: ThisType: A* ({{.*}}) +; CHECK-NEXT: CallingConvention: NearC (0x0) +; CHECK-NEXT: FunctionOptions [ (0x0) +; CHECK-NEXT: ] +; CHECK-NEXT: NumParameters: 0 +; CHECK-NEXT: ArgListType: () ({{.*}}) +; CHECK-NEXT: ThisAdjustment: 0 +; CHECK-NEXT: } + +; A::g +; CHECK: MemberFunction ({{.*}}) { +; CHECK-NEXT: TypeLeafKind: LF_MFUNCTION (0x1009) +; CHECK-NEXT: ReturnType: int (0x74) +; CHECK-NEXT: ClassType: B ({{.*}}) +; CHECK-NEXT: ThisType: B* ({{.*}}) +; CHECK-NEXT: CallingConvention: NearC (0x0) +; CHECK-NEXT: FunctionOptions [ (0x0) +; CHECK-NEXT: ] +; CHECK-NEXT: NumParameters: 0 +; CHECK-NEXT: ArgListType: () ({{.*}}) +; CHECK-NEXT: ThisAdjustment: 0 +; CHECK-NEXT: } + +; C::g +; CHECK: MemberFunction ([[C_g:.*]]) { +; CHECK-NEXT: TypeLeafKind: LF_MFUNCTION (0x1009) +; CHECK-NEXT: ReturnType: int (0x74) +; CHECK-NEXT: ClassType: C ({{.*}}) +; CHECK-NEXT: ThisType: C* ({{.*}}) +; CHECK-NEXT: CallingConvention: NearC (0x0) +; CHECK-NEXT: FunctionOptions [ (0x0) +; CHECK-NEXT: ] +; CHECK-NEXT: NumParameters: 0 +; CHECK-NEXT: ArgListType: () ({{.*}}) +; CHECK-NEXT: ThisAdjustment: 8 +; CHECK-NEXT: } + +; CHECK: FieldList ({{.*}}) { +; CHECK: OneMethod { +; CHECK-NEXT: AccessSpecifier: Public (0x3) +; CHECK-NEXT: MethodKind: Virtual (0x1) +; CHECK-NEXT: Type: int C::() ([[C_g]]) +; CHECK-NEXT: Name: g +; CHECK-NEXT: } +; CHECK-NEXT: } + +; D::g +; CHECK: MemberFunction ([[D_g:.*]]) { +; CHECK-NEXT: TypeLeafKind: LF_MFUNCTION (0x1009) +; CHECK-NEXT: ReturnType: int (0x74) +; CHECK-NEXT: ClassType: D ({{.*}}) +; CHECK-NEXT: ThisType: D* ({{.*}}) +; CHECK-NEXT: CallingConvention: NearC (0x0) +; CHECK-NEXT: FunctionOptions [ (0x0) +; CHECK-NEXT: ] +; CHECK-NEXT: NumParameters: 0 +; CHECK-NEXT: ArgListType: () ({{.*}}) +; CHECK-NEXT: ThisAdjustment: 16 +; CHECK-NEXT: } + +; CHECK: FieldList ({{.*}}) { +; CHECK: OneMethod { +; CHECK-NEXT: AccessSpecifier: Public (0x3) +; CHECK-NEXT: MethodKind: Virtual (0x1) +; CHECK-NEXT: Type: int D::() ([[D_g]]) +; CHECK-NEXT: Name: g +; CHECK-NEXT: } +; CHECK-NEXT: } + +; Need to skip constructor IDs... +; CHECK: MemberFuncId ({{.*}}) { +; CHECK: TypeLeafKind: LF_MFUNC_ID (0x1602) +; CHECK: ClassType: A +; CHECK: FunctionType: void A::() +; CHECK: Name: A +; CHECK: } +; CHECK: MemberFuncId ({{.*}}) { +; CHECK: TypeLeafKind: LF_MFUNC_ID (0x1602) +; CHECK: ClassType: B +; CHECK: FunctionType: void B::() +; CHECK: Name: B +; CHECK: } +; CHECK: MemberFuncId ({{.*}}) { +; CHECK: TypeLeafKind: LF_MFUNC_ID (0x1602) +; CHECK: ClassType: C +; CHECK: FunctionType: void C::() +; CHECK: Name: C +; CHECK: } +; CHECK: MemberFuncId ({{.*}}) { +; CHECK: TypeLeafKind: LF_MFUNC_ID (0x1602) +; CHECK: ClassType: D +; CHECK: FunctionType: void D::() +; CHECK: Name: D +; CHECK: } + +; CHECK: MemberFuncId ({{.*}}) { +; CHECK-NEXT: TypeLeafKind: LF_MFUNC_ID (0x1602) +; CHECK-NEXT: ClassType: C ({{.*}}) +; CHECK-NEXT: FunctionType: int C::() ([[C_g]]) +; CHECK-NEXT: Name: g +; CHECK-NEXT: } + +; CHECK: MemberFuncId ({{.*}}) { +; CHECK-NEXT: TypeLeafKind: LF_MFUNC_ID (0x1602) +; CHECK-NEXT: ClassType: D ({{.*}}) +; CHECK-NEXT: FunctionType: int D::() ([[D_g]]) +; CHECK-NEXT: Name: g +; CHECK-NEXT: } + +; ModuleID = 't.cpp' +source_filename = "t.cpp" +target datalayout = "e-m:w-i64:64-f80:128-n8:16:32:64-S128" +target triple = "x86_64-pc-windows-msvc19.0.23918" + +%struct.A = type { i32 (...)** } +%struct.B = type { i32 (...)** } +%struct.C = type { %struct.A, %struct.B, i32 } +%struct.D = type { i32*, i32, %struct.B } + +$"\01??0A@@QEAA@XZ" = comdat any + +$"\01??0B@@QEAA@XZ" = comdat any + +$"\01??0C@@QEAA@XZ" = comdat any + +$"\01??0D@@QEAA@XZ" = comdat any + +$"\01?g@C@@UEAAHXZ" = comdat any + +$"\01?g@D@@UEAAHXZ" = comdat any + +$"\01??_7A@@6B@" = comdat any + +$"\01??_7B@@6B@" = comdat any + +$"\01??_7C@@6BA@@@" = comdat any + +$"\01??_7C@@6BB@@@" = comdat any + +$"\01??_8D@@7B@" = comdat any + +$"\01??_7D@@6B@" = comdat any + +@"\01??_7A@@6B@" = linkonce_odr unnamed_addr constant [1 x i8*] [i8* bitcast (i32 (%struct.A*)* @"\01?f@A@@UEAAHXZ" to i8*)], comdat +@"\01??_7B@@6B@" = linkonce_odr unnamed_addr constant [1 x i8*] [i8* bitcast (i32 (%struct.B*)* @"\01?g@B@@UEAAHXZ" to i8*)], comdat +@"\01??_7C@@6BA@@@" = linkonce_odr unnamed_addr constant [1 x i8*] [i8* bitcast (i32 (%struct.A*)* @"\01?f@A@@UEAAHXZ" to i8*)], comdat +@"\01??_7C@@6BB@@@" = linkonce_odr unnamed_addr constant [1 x i8*] [i8* bitcast (i32 (i8*)* @"\01?g@C@@UEAAHXZ" to i8*)], comdat +@"\01??_8D@@7B@" = linkonce_odr unnamed_addr constant [2 x i32] [i32 0, i32 16], comdat +@"\01??_7D@@6B@" = linkonce_odr unnamed_addr constant [1 x i8*] [i8* bitcast (i32 (i8*)* @"\01?g@D@@UEAAHXZ" to i8*)], comdat + +; Function Attrs: uwtable +define void @"\01?usetypes@@YAXXZ"() #0 !dbg !7 { +entry: + %a = alloca %struct.A, align 8 + %b = alloca %struct.B, align 8 + %c = alloca %struct.C, align 8 + %d = alloca %struct.D, align 8 + call void @llvm.dbg.declare(metadata %struct.A* %a, metadata !10, metadata !23), !dbg !24 + %call = call %struct.A* @"\01??0A@@QEAA@XZ"(%struct.A* %a) #5, !dbg !24 + call void @llvm.dbg.declare(metadata %struct.B* %b, metadata !25, metadata !23), !dbg !33 + %call1 = call %struct.B* @"\01??0B@@QEAA@XZ"(%struct.B* %b) #5, !dbg !33 + call void @llvm.dbg.declare(metadata %struct.C* %c, metadata !34, metadata !23), !dbg !44 + %call2 = call %struct.C* @"\01??0C@@QEAA@XZ"(%struct.C* %c) #5, !dbg !44 + call void @llvm.dbg.declare(metadata %struct.D* %d, metadata !45, metadata !23), !dbg !55 + %call3 = call %struct.D* @"\01??0D@@QEAA@XZ"(%struct.D* %d, i32 1) #5, !dbg !55 + %0 = bitcast %struct.C* %c to i8*, !dbg !56 + %1 = getelementptr i8, i8* %0, i64 8, !dbg !56 + %call4 = call i32 @"\01?g@C@@UEAAHXZ"(i8* %1), !dbg !56 + ret void, !dbg !57 +} + +; Function Attrs: nounwind readnone +declare void @llvm.dbg.declare(metadata, metadata, metadata) #1 + +; Function Attrs: inlinehint nounwind uwtable +define linkonce_odr %struct.A* @"\01??0A@@QEAA@XZ"(%struct.A* returned %this) unnamed_addr #2 comdat align 2 !dbg !58 { +entry: + %this.addr = alloca %struct.A*, align 8 + store %struct.A* %this, %struct.A** %this.addr, align 8 + call void @llvm.dbg.declare(metadata %struct.A** %this.addr, metadata !62, metadata !23), !dbg !64 + %this1 = load %struct.A*, %struct.A** %this.addr, align 8 + %0 = bitcast %struct.A* %this1 to i32 (...)***, !dbg !65 + store i32 (...)** bitcast ([1 x i8*]* @"\01??_7A@@6B@" to i32 (...)**), i32 (...)*** %0, align 8, !dbg !65 + ret %struct.A* %this1, !dbg !65 +} + +; Function Attrs: inlinehint nounwind uwtable +define linkonce_odr %struct.B* @"\01??0B@@QEAA@XZ"(%struct.B* returned %this) unnamed_addr #2 comdat align 2 !dbg !66 { +entry: + %this.addr = alloca %struct.B*, align 8 + store %struct.B* %this, %struct.B** %this.addr, align 8 + call void @llvm.dbg.declare(metadata %struct.B** %this.addr, metadata !70, metadata !23), !dbg !72 + %this1 = load %struct.B*, %struct.B** %this.addr, align 8 + %0 = bitcast %struct.B* %this1 to i32 (...)***, !dbg !73 + store i32 (...)** bitcast ([1 x i8*]* @"\01??_7B@@6B@" to i32 (...)**), i32 (...)*** %0, align 8, !dbg !73 + ret %struct.B* %this1, !dbg !73 +} + +; Function Attrs: inlinehint nounwind uwtable +define linkonce_odr %struct.C* @"\01??0C@@QEAA@XZ"(%struct.C* returned %this) unnamed_addr #2 comdat align 2 !dbg !74 { +entry: + %this.addr = alloca %struct.C*, align 8 + store %struct.C* %this, %struct.C** %this.addr, align 8 + call void @llvm.dbg.declare(metadata %struct.C** %this.addr, metadata !78, metadata !23), !dbg !80 + %this1 = load %struct.C*, %struct.C** %this.addr, align 8 + %0 = bitcast %struct.C* %this1 to %struct.A*, !dbg !81 + %call = call %struct.A* @"\01??0A@@QEAA@XZ"(%struct.A* %0) #5, !dbg !81 + %1 = bitcast %struct.C* %this1 to i8*, !dbg !81 + %2 = getelementptr inbounds i8, i8* %1, i64 8, !dbg !81 + %3 = bitcast i8* %2 to %struct.B*, !dbg !81 + %call2 = call %struct.B* @"\01??0B@@QEAA@XZ"(%struct.B* %3) #5, !dbg !81 + %4 = bitcast %struct.C* %this1 to i32 (...)***, !dbg !81 + store i32 (...)** bitcast ([1 x i8*]* @"\01??_7C@@6BA@@@" to i32 (...)**), i32 (...)*** %4, align 8, !dbg !81 + %5 = bitcast %struct.C* %this1 to i8*, !dbg !81 + %add.ptr = getelementptr inbounds i8, i8* %5, i64 8, !dbg !81 + %6 = bitcast i8* %add.ptr to i32 (...)***, !dbg !81 + store i32 (...)** bitcast ([1 x i8*]* @"\01??_7C@@6BB@@@" to i32 (...)**), i32 (...)*** %6, align 8, !dbg !81 + %c = getelementptr inbounds %struct.C, %struct.C* %this1, i32 0, i32 2, !dbg !82 + store i32 42, i32* %c, align 8, !dbg !82 + ret %struct.C* %this1, !dbg !81 +} + +; Function Attrs: inlinehint nounwind uwtable +define linkonce_odr %struct.D* @"\01??0D@@QEAA@XZ"(%struct.D* returned %this, i32 %is_most_derived) unnamed_addr #2 comdat align 2 !dbg !83 { +entry: + %retval = alloca %struct.D*, align 8 + %is_most_derived.addr = alloca i32, align 4 + %this.addr = alloca %struct.D*, align 8 + store i32 %is_most_derived, i32* %is_most_derived.addr, align 4 + call void @llvm.dbg.declare(metadata i32* %is_most_derived.addr, metadata !87, metadata !23), !dbg !88 + store %struct.D* %this, %struct.D** %this.addr, align 8 + call void @llvm.dbg.declare(metadata %struct.D** %this.addr, metadata !89, metadata !23), !dbg !88 + %this1 = load %struct.D*, %struct.D** %this.addr, align 8 + store %struct.D* %this1, %struct.D** %retval, align 8 + %is_most_derived2 = load i32, i32* %is_most_derived.addr, align 4 + %is_complete_object = icmp ne i32 %is_most_derived2, 0, !dbg !91 + br i1 %is_complete_object, label %ctor.init_vbases, label %ctor.skip_vbases, !dbg !91 + +ctor.init_vbases: ; preds = %entry + %this.int8 = bitcast %struct.D* %this1 to i8*, !dbg !91 + %0 = getelementptr inbounds i8, i8* %this.int8, i64 0, !dbg !91 + %vbptr.D = bitcast i8* %0 to i32**, !dbg !91 + store i32* getelementptr inbounds ([2 x i32], [2 x i32]* @"\01??_8D@@7B@", i32 0, i32 0), i32** %vbptr.D, align 8, !dbg !91 + %1 = bitcast %struct.D* %this1 to i8*, !dbg !91 + %2 = getelementptr inbounds i8, i8* %1, i64 16, !dbg !91 + %3 = bitcast i8* %2 to %struct.B*, !dbg !91 + %call = call %struct.B* @"\01??0B@@QEAA@XZ"(%struct.B* %3) #5, !dbg !91 + br label %ctor.skip_vbases, !dbg !91 + +ctor.skip_vbases: ; preds = %ctor.init_vbases, %entry + %4 = bitcast %struct.D* %this1 to i8*, !dbg !91 + %vbptr = getelementptr inbounds i8, i8* %4, i64 0, !dbg !91 + %5 = bitcast i8* %vbptr to i32**, !dbg !91 + %vbtable = load i32*, i32** %5, align 8, !dbg !91 + %6 = getelementptr inbounds i32, i32* %vbtable, i32 1, !dbg !91 + %vbase_offs = load i32, i32* %6, align 4, !dbg !91 + %7 = sext i32 %vbase_offs to i64, !dbg !91 + %8 = add nsw i64 0, %7, !dbg !91 + %9 = bitcast %struct.D* %this1 to i8*, !dbg !91 + %add.ptr = getelementptr inbounds i8, i8* %9, i64 %8, !dbg !91 + %10 = bitcast i8* %add.ptr to i32 (...)***, !dbg !91 + store i32 (...)** bitcast ([1 x i8*]* @"\01??_7D@@6B@" to i32 (...)**), i32 (...)*** %10, align 8, !dbg !91 + %d = getelementptr inbounds %struct.D, %struct.D* %this1, i32 0, i32 1, !dbg !92 + store i32 13, i32* %d, align 8, !dbg !92 + %11 = load %struct.D*, %struct.D** %retval, align 8, !dbg !91 + ret %struct.D* %11, !dbg !91 +} + +; Function Attrs: nounwind uwtable +define linkonce_odr i32 @"\01?g@C@@UEAAHXZ"(i8*) unnamed_addr #3 comdat align 2 !dbg !93 { +entry: + %this.addr = alloca %struct.C*, align 8 + %1 = getelementptr inbounds i8, i8* %0, i32 -8 + %this = bitcast i8* %1 to %struct.C* + store %struct.C* %this, %struct.C** %this.addr, align 8 + call void @llvm.dbg.declare(metadata %struct.C** %this.addr, metadata !94, metadata !23), !dbg !95 + %this1 = load %struct.C*, %struct.C** %this.addr, align 8 + %c = getelementptr inbounds %struct.C, %struct.C* %this1, i32 0, i32 2, !dbg !96 + %2 = load i32, i32* %c, align 8, !dbg !96 + ret i32 %2, !dbg !97 +} + +declare i32 @"\01?f@A@@UEAAHXZ"(%struct.A*) unnamed_addr #4 + +declare i32 @"\01?g@B@@UEAAHXZ"(%struct.B*) unnamed_addr #4 + +; Function Attrs: nounwind uwtable +define linkonce_odr i32 @"\01?g@D@@UEAAHXZ"(i8*) unnamed_addr #3 comdat align 2 !dbg !98 { +entry: + %this.addr = alloca %struct.D*, align 8 + %1 = getelementptr inbounds i8, i8* %0, i32 -16 + %this = bitcast i8* %1 to %struct.D* + store %struct.D* %this, %struct.D** %this.addr, align 8 + call void @llvm.dbg.declare(metadata %struct.D** %this.addr, metadata !99, metadata !23), !dbg !100 + %this1 = load %struct.D*, %struct.D** %this.addr, align 8 + %d = getelementptr inbounds %struct.D, %struct.D* %this1, i32 0, i32 1, !dbg !101 + %2 = load i32, i32* %d, align 8, !dbg !101 + ret i32 %2, !dbg !102 +} + +attributes #0 = { uwtable "disable-tail-calls"="false" "less-precise-fpmad"="false" "no-frame-pointer-elim"="false" "no-infs-fp-math"="false" "no-jump-tables"="false" "no-nans-fp-math"="false" "stack-protector-buffer-size"="8" "target-cpu"="x86-64" "target-features"="+fxsr,+mmx,+sse,+sse2,+x87" "unsafe-fp-math"="false" "use-soft-float"="false" } +attributes #1 = { nounwind readnone } +attributes #2 = { inlinehint nounwind uwtable "disable-tail-calls"="false" "less-precise-fpmad"="false" "no-frame-pointer-elim"="false" "no-infs-fp-math"="false" "no-jump-tables"="false" "no-nans-fp-math"="false" "stack-protector-buffer-size"="8" "target-cpu"="x86-64" "target-features"="+fxsr,+mmx,+sse,+sse2,+x87" "unsafe-fp-math"="false" "use-soft-float"="false" } +attributes #3 = { nounwind uwtable "disable-tail-calls"="false" "less-precise-fpmad"="false" "no-frame-pointer-elim"="false" "no-infs-fp-math"="false" "no-jump-tables"="false" "no-nans-fp-math"="false" "stack-protector-buffer-size"="8" "target-cpu"="x86-64" "target-features"="+fxsr,+mmx,+sse,+sse2,+x87" "unsafe-fp-math"="false" "use-soft-float"="false" } +attributes #4 = { "disable-tail-calls"="false" "less-precise-fpmad"="false" "no-frame-pointer-elim"="false" "no-infs-fp-math"="false" "no-nans-fp-math"="false" "stack-protector-buffer-size"="8" "target-cpu"="x86-64" "target-features"="+fxsr,+mmx,+sse,+sse2,+x87" "unsafe-fp-math"="false" "use-soft-float"="false" } +attributes #5 = { nounwind } + +!llvm.dbg.cu = !{!0} +!llvm.module.flags = !{!3, !4, !5} +!llvm.ident = !{!6} + +!0 = distinct !DICompileUnit(language: DW_LANG_C_plus_plus, file: !1, producer: "clang version 3.9.0 ", isOptimized: false, runtimeVersion: 0, emissionKind: FullDebug, enums: !2) +!1 = !DIFile(filename: "t.cpp", directory: "D:\5Csrc\5Cllvm\5Cbuild") +!2 = !{} +!3 = !{i32 2, !"CodeView", i32 1} +!4 = !{i32 2, !"Debug Info Version", i32 3} +!5 = !{i32 1, !"PIC Level", i32 2} +!6 = !{!"clang version 3.9.0 "} +!7 = distinct !DISubprogram(name: "usetypes", linkageName: "\01?usetypes@@YAXXZ", scope: !1, file: !1, line: 15, type: !8, isLocal: false, isDefinition: true, scopeLine: 15, flags: DIFlagPrototyped, isOptimized: false, unit: !0, variables: !2) +!8 = !DISubroutineType(types: !9) +!9 = !{null} +!10 = !DILocalVariable(name: "a", scope: !7, file: !1, line: 16, type: !11) +!11 = distinct !DICompositeType(tag: DW_TAG_structure_type, name: "A", file: !1, line: 1, size: 64, align: 64, elements: !12, vtableHolder: !11, identifier: ".?AUA@@") +!12 = !{!13, !19} +!13 = !DIDerivedType(tag: DW_TAG_member, name: "_vptr$A", scope: !1, file: !1, baseType: !14, size: 64, flags: DIFlagArtificial) +!14 = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: !15, size: 64) +!15 = !DIDerivedType(tag: DW_TAG_pointer_type, name: "__vtbl_ptr_type", baseType: !16, size: 64) +!16 = !DISubroutineType(types: !17) +!17 = !{!18} +!18 = !DIBasicType(name: "int", size: 32, align: 32, encoding: DW_ATE_signed) +!19 = !DISubprogram(name: "f", linkageName: "\01?f@A@@UEAAHXZ", scope: !11, file: !1, line: 2, type: !20, isLocal: false, isDefinition: false, scopeLine: 2, containingType: !11, virtuality: DW_VIRTUALITY_virtual, virtualIndex: 0, flags: DIFlagPrototyped | DIFlagIntroducedVirtual, isOptimized: false) +!20 = !DISubroutineType(types: !21) +!21 = !{!18, !22} +!22 = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: !11, size: 64, align: 64, flags: DIFlagArtificial | DIFlagObjectPointer) +!23 = !DIExpression() +!24 = !DILocation(line: 16, column: 5, scope: !7) +!25 = !DILocalVariable(name: "b", scope: !7, file: !1, line: 17, type: !26) +!26 = distinct !DICompositeType(tag: DW_TAG_structure_type, name: "B", file: !1, line: 4, size: 64, align: 64, elements: !27, vtableHolder: !26, identifier: ".?AUB@@") +!27 = !{!28, !29} +!28 = !DIDerivedType(tag: DW_TAG_member, name: "_vptr$B", scope: !1, file: !1, baseType: !14, size: 64, flags: DIFlagArtificial) +!29 = !DISubprogram(name: "g", linkageName: "\01?g@B@@UEAAHXZ", scope: !26, file: !1, line: 5, type: !30, isLocal: false, isDefinition: false, scopeLine: 5, containingType: !26, virtuality: DW_VIRTUALITY_pure_virtual, virtualIndex: 0, flags: DIFlagPrototyped | DIFlagIntroducedVirtual, isOptimized: false) +!30 = !DISubroutineType(types: !31) +!31 = !{!18, !32} +!32 = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: !26, size: 64, align: 64, flags: DIFlagArtificial | DIFlagObjectPointer) +!33 = !DILocation(line: 17, column: 5, scope: !7) +!34 = !DILocalVariable(name: "c", scope: !7, file: !1, line: 18, type: !35) +!35 = distinct !DICompositeType(tag: DW_TAG_structure_type, name: "C", file: !1, line: 7, size: 192, align: 64, elements: !36, vtableHolder: !11, identifier: ".?AUC@@") +!36 = !{!37, !38, !39, !40} +!37 = !DIDerivedType(tag: DW_TAG_inheritance, scope: !35, baseType: !11) +!38 = !DIDerivedType(tag: DW_TAG_inheritance, scope: !35, baseType: !26, offset: 64) +!39 = !DIDerivedType(tag: DW_TAG_member, name: "c", scope: !35, file: !1, line: 8, baseType: !18, size: 32, align: 32, offset: 128) +!40 = !DISubprogram(name: "g", linkageName: "\01?g@C@@UEAAHXZ", scope: !35, file: !1, line: 9, type: !41, isLocal: false, isDefinition: false, scopeLine: 9, containingType: !35, virtuality: DW_VIRTUALITY_virtual, virtualIndex: 0, thisAdjustment: 8, flags: DIFlagPrototyped, isOptimized: false) +!41 = !DISubroutineType(types: !42) +!42 = !{!18, !43} +!43 = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: !35, size: 64, align: 64, flags: DIFlagArtificial | DIFlagObjectPointer) +!44 = !DILocation(line: 18, column: 5, scope: !7) +!45 = !DILocalVariable(name: "d", scope: !7, file: !1, line: 19, type: !46) +!46 = distinct !DICompositeType(tag: DW_TAG_structure_type, name: "D", file: !1, line: 11, size: 192, align: 64, elements: !47, vtableHolder: !46, identifier: ".?AUD@@") +!47 = !{!48, !49, !50, !51} +!48 = !DIDerivedType(tag: DW_TAG_inheritance, scope: !46, baseType: !26, offset: 4, flags: DIFlagVirtual) +!49 = !DIDerivedType(tag: DW_TAG_member, name: "_vptr$D", scope: !1, file: !1, baseType: !14, size: 64, flags: DIFlagArtificial) +!50 = !DIDerivedType(tag: DW_TAG_member, name: "d", scope: !46, file: !1, line: 12, baseType: !18, size: 32, align: 32, offset: 64) +!51 = !DISubprogram(name: "g", linkageName: "\01?g@D@@UEAAHXZ", scope: !46, file: !1, line: 13, type: !52, isLocal: false, isDefinition: false, scopeLine: 13, containingType: !46, virtuality: DW_VIRTUALITY_virtual, virtualIndex: 0, thisAdjustment: 16, flags: DIFlagPrototyped, isOptimized: false) +!52 = !DISubroutineType(types: !53) +!53 = !{!18, !54} +!54 = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: !46, size: 64, align: 64, flags: DIFlagArtificial | DIFlagObjectPointer) +!55 = !DILocation(line: 19, column: 5, scope: !7) +!56 = !DILocation(line: 20, column: 5, scope: !7) +!57 = !DILocation(line: 21, column: 1, scope: !7) +!58 = distinct !DISubprogram(name: "A", linkageName: "\01??0A@@QEAA@XZ", scope: !11, file: !1, line: 1, type: !59, isLocal: false, isDefinition: true, scopeLine: 1, flags: DIFlagArtificial | DIFlagPrototyped, isOptimized: false, unit: !0, declaration: !61, variables: !2) +!59 = !DISubroutineType(types: !60) +!60 = !{null, !22} +!61 = !DISubprogram(name: "A", scope: !11, type: !59, isLocal: false, isDefinition: false, flags: DIFlagArtificial | DIFlagPrototyped, isOptimized: false) +!62 = !DILocalVariable(name: "this", arg: 1, scope: !58, type: !63, flags: DIFlagArtificial | DIFlagObjectPointer) +!63 = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: !11, size: 64, align: 64) +!64 = !DILocation(line: 0, scope: !58) +!65 = !DILocation(line: 1, column: 8, scope: !58) +!66 = distinct !DISubprogram(name: "B", linkageName: "\01??0B@@QEAA@XZ", scope: !26, file: !1, line: 4, type: !67, isLocal: false, isDefinition: true, scopeLine: 4, flags: DIFlagArtificial | DIFlagPrototyped, isOptimized: false, unit: !0, declaration: !69, variables: !2) +!67 = !DISubroutineType(types: !68) +!68 = !{null, !32} +!69 = !DISubprogram(name: "B", scope: !26, type: !67, isLocal: false, isDefinition: false, flags: DIFlagArtificial | DIFlagPrototyped, isOptimized: false) +!70 = !DILocalVariable(name: "this", arg: 1, scope: !66, type: !71, flags: DIFlagArtificial | DIFlagObjectPointer) +!71 = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: !26, size: 64, align: 64) +!72 = !DILocation(line: 0, scope: !66) +!73 = !DILocation(line: 4, column: 8, scope: !66) +!74 = distinct !DISubprogram(name: "C", linkageName: "\01??0C@@QEAA@XZ", scope: !35, file: !1, line: 7, type: !75, isLocal: false, isDefinition: true, scopeLine: 7, flags: DIFlagArtificial | DIFlagPrototyped, isOptimized: false, unit: !0, declaration: !77, variables: !2) +!75 = !DISubroutineType(types: !76) +!76 = !{null, !43} +!77 = !DISubprogram(name: "C", scope: !35, type: !75, isLocal: false, isDefinition: false, flags: DIFlagArtificial | DIFlagPrototyped, isOptimized: false) +!78 = !DILocalVariable(name: "this", arg: 1, scope: !74, type: !79, flags: DIFlagArtificial | DIFlagObjectPointer) +!79 = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: !35, size: 64, align: 64) +!80 = !DILocation(line: 0, scope: !74) +!81 = !DILocation(line: 7, column: 8, scope: !74) +!82 = !DILocation(line: 8, column: 7, scope: !74) +!83 = distinct !DISubprogram(name: "D", linkageName: "\01??0D@@QEAA@XZ", scope: !46, file: !1, line: 11, type: !84, isLocal: false, isDefinition: true, scopeLine: 11, flags: DIFlagArtificial | DIFlagPrototyped, isOptimized: false, unit: !0, declaration: !86, variables: !2) +!84 = !DISubroutineType(types: !85) +!85 = !{null, !54} +!86 = !DISubprogram(name: "D", scope: !46, type: !84, isLocal: false, isDefinition: false, flags: DIFlagArtificial | DIFlagPrototyped, isOptimized: false) +!87 = !DILocalVariable(name: "is_most_derived", arg: 2, scope: !83, type: !18, flags: DIFlagArtificial) +!88 = !DILocation(line: 0, scope: !83) +!89 = !DILocalVariable(name: "this", arg: 1, scope: !83, type: !90, flags: DIFlagArtificial | DIFlagObjectPointer) +!90 = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: !46, size: 64, align: 64) +!91 = !DILocation(line: 11, column: 8, scope: !83) +!92 = !DILocation(line: 12, column: 7, scope: !83) +!93 = distinct !DISubprogram(name: "g", linkageName: "\01?g@C@@UEAAHXZ", scope: !35, file: !1, line: 9, type: !41, isLocal: false, isDefinition: true, scopeLine: 9, flags: DIFlagPrototyped, isOptimized: false, unit: !0, declaration: !40, variables: !2) +!94 = !DILocalVariable(name: "this", arg: 1, scope: !93, type: !79, flags: DIFlagArtificial | DIFlagObjectPointer) +!95 = !DILocation(line: 0, scope: !93) +!96 = !DILocation(line: 9, column: 28, scope: !93) +!97 = !DILocation(line: 9, column: 21, scope: !93) +!98 = distinct !DISubprogram(name: "g", linkageName: "\01?g@D@@UEAAHXZ", scope: !46, file: !1, line: 13, type: !52, isLocal: false, isDefinition: true, scopeLine: 13, flags: DIFlagPrototyped, isOptimized: false, unit: !0, declaration: !51, variables: !2) +!99 = !DILocalVariable(name: "this", arg: 1, scope: !98, type: !90, flags: DIFlagArtificial | DIFlagObjectPointer) +!100 = !DILocation(line: 0, scope: !98) +!101 = !DILocation(line: 13, column: 28, scope: !98) +!102 = !DILocation(line: 13, column: 21, scope: !98) Index: llvm/trunk/unittests/IR/MetadataTest.cpp =================================================================== --- llvm/trunk/unittests/IR/MetadataTest.cpp +++ llvm/trunk/unittests/IR/MetadataTest.cpp @@ -85,7 +85,7 @@ DISubprogram *getSubprogram() { return DISubprogram::getDistinct(Context, nullptr, "", "", nullptr, 0, nullptr, false, false, 0, nullptr, - 0, 0, 0, false, nullptr); + 0, 0, 0, 0, false, nullptr); } DIFile *getFile() { return DIFile::getDistinct(Context, "file.c", "/path/to/dir"); @@ -1422,6 +1422,7 @@ DIType *ContainingType = getCompositeType(); unsigned Virtuality = 2; unsigned VirtualIndex = 5; + int ThisAdjustment = -3; unsigned Flags = 6; unsigned NotFlags = (~Flags) & ((1 << 27) - 1); bool IsOptimized = false; @@ -1430,10 +1431,11 @@ MDTuple *Variables = getTuple(); DICompileUnit *Unit = getUnit(); - auto *N = DISubprogram::get( - Context, Scope, Name, LinkageName, File, Line, Type, IsLocalToUnit, - IsDefinition, ScopeLine, ContainingType, Virtuality, VirtualIndex, Flags, - IsOptimized, Unit, TemplateParams, Declaration, Variables); + auto *N = DISubprogram::get(Context, Scope, Name, LinkageName, File, Line, + Type, IsLocalToUnit, IsDefinition, ScopeLine, + ContainingType, Virtuality, VirtualIndex, + ThisAdjustment, Flags, IsOptimized, Unit, + TemplateParams, Declaration, Variables); EXPECT_EQ(dwarf::DW_TAG_subprogram, N->getTag()); EXPECT_EQ(Scope, N->getScope()); @@ -1448,6 +1450,7 @@ EXPECT_EQ(ContainingType, N->getContainingType()); EXPECT_EQ(Virtuality, N->getVirtuality()); EXPECT_EQ(VirtualIndex, N->getVirtualIndex()); + EXPECT_EQ(ThisAdjustment, N->getThisAdjustment()); EXPECT_EQ(Flags, N->getFlags()); EXPECT_EQ(IsOptimized, N->isOptimized()); EXPECT_EQ(Unit, N->getUnit()); @@ -1457,99 +1460,100 @@ EXPECT_EQ(N, DISubprogram::get(Context, Scope, Name, LinkageName, File, Line, Type, IsLocalToUnit, IsDefinition, ScopeLine, ContainingType, Virtuality, VirtualIndex, - Flags, IsOptimized, Unit, TemplateParams, - Declaration, Variables)); - - EXPECT_NE(N, DISubprogram::get(Context, getCompositeType(), Name, LinkageName, - File, Line, Type, IsLocalToUnit, IsDefinition, - ScopeLine, ContainingType, Virtuality, - VirtualIndex, Flags, IsOptimized, Unit, - TemplateParams, Declaration, Variables)); - EXPECT_NE(N, DISubprogram::get(Context, Scope, "other", LinkageName, File, - Line, Type, IsLocalToUnit, IsDefinition, - ScopeLine, ContainingType, Virtuality, - VirtualIndex, Flags, IsOptimized, Unit, + ThisAdjustment, Flags, IsOptimized, Unit, TemplateParams, Declaration, Variables)); + + EXPECT_NE(N, DISubprogram::get( + Context, getCompositeType(), Name, LinkageName, File, Line, + Type, IsLocalToUnit, IsDefinition, ScopeLine, ContainingType, + Virtuality, VirtualIndex, ThisAdjustment, Flags, IsOptimized, + Unit, TemplateParams, Declaration, Variables)); + EXPECT_NE(N, DISubprogram::get( + Context, Scope, "other", LinkageName, File, Line, Type, + IsLocalToUnit, IsDefinition, ScopeLine, ContainingType, + Virtuality, VirtualIndex, ThisAdjustment, Flags, IsOptimized, + Unit, TemplateParams, Declaration, Variables)); EXPECT_NE(N, DISubprogram::get(Context, Scope, Name, "other", File, Line, Type, IsLocalToUnit, IsDefinition, ScopeLine, ContainingType, Virtuality, VirtualIndex, - Flags, IsOptimized, Unit, TemplateParams, - Declaration, Variables)); - EXPECT_NE(N, DISubprogram::get(Context, Scope, Name, LinkageName, getFile(), - Line, Type, IsLocalToUnit, IsDefinition, - ScopeLine, ContainingType, Virtuality, - VirtualIndex, Flags, IsOptimized, Unit, - TemplateParams, Declaration, Variables)); - EXPECT_NE(N, DISubprogram::get(Context, Scope, Name, LinkageName, File, - Line + 1, Type, IsLocalToUnit, IsDefinition, - ScopeLine, ContainingType, Virtuality, - VirtualIndex, Flags, IsOptimized, Unit, + ThisAdjustment, Flags, IsOptimized, Unit, TemplateParams, Declaration, Variables)); - EXPECT_NE(N, DISubprogram::get(Context, Scope, Name, LinkageName, File, Line, - getSubroutineType(), IsLocalToUnit, - IsDefinition, ScopeLine, ContainingType, - Virtuality, VirtualIndex, Flags, IsOptimized, - Unit, TemplateParams, Declaration, Variables)); + EXPECT_NE(N, DISubprogram::get( + Context, Scope, Name, LinkageName, getFile(), Line, Type, + IsLocalToUnit, IsDefinition, ScopeLine, ContainingType, + Virtuality, VirtualIndex, ThisAdjustment, Flags, IsOptimized, + Unit, TemplateParams, Declaration, Variables)); + EXPECT_NE(N, DISubprogram::get( + Context, Scope, Name, LinkageName, File, Line + 1, Type, + IsLocalToUnit, IsDefinition, ScopeLine, ContainingType, + Virtuality, VirtualIndex, ThisAdjustment, Flags, IsOptimized, + Unit, TemplateParams, Declaration, Variables)); + EXPECT_NE(N, + DISubprogram::get(Context, Scope, Name, LinkageName, File, Line, + getSubroutineType(), IsLocalToUnit, IsDefinition, + ScopeLine, ContainingType, Virtuality, + VirtualIndex, ThisAdjustment, Flags, IsOptimized, + Unit, TemplateParams, Declaration, Variables)); EXPECT_NE(N, DISubprogram::get(Context, Scope, Name, LinkageName, File, Line, Type, !IsLocalToUnit, IsDefinition, ScopeLine, ContainingType, Virtuality, VirtualIndex, - Flags, IsOptimized, Unit, TemplateParams, - Declaration, Variables)); + ThisAdjustment, Flags, IsOptimized, Unit, + TemplateParams, Declaration, Variables)); EXPECT_NE(N, DISubprogram::get(Context, Scope, Name, LinkageName, File, Line, Type, IsLocalToUnit, !IsDefinition, ScopeLine, ContainingType, Virtuality, VirtualIndex, - Flags, IsOptimized, Unit, TemplateParams, - Declaration, Variables)); - EXPECT_NE(N, DISubprogram::get(Context, Scope, Name, LinkageName, File, Line, - Type, IsLocalToUnit, IsDefinition, - ScopeLine + 1, ContainingType, Virtuality, - VirtualIndex, Flags, IsOptimized, Unit, + ThisAdjustment, Flags, IsOptimized, Unit, TemplateParams, Declaration, Variables)); + EXPECT_NE(N, DISubprogram::get( + Context, Scope, Name, LinkageName, File, Line, Type, + IsLocalToUnit, IsDefinition, ScopeLine + 1, ContainingType, + Virtuality, VirtualIndex, ThisAdjustment, Flags, IsOptimized, + Unit, TemplateParams, Declaration, Variables)); EXPECT_NE(N, DISubprogram::get(Context, Scope, Name, LinkageName, File, Line, Type, IsLocalToUnit, IsDefinition, ScopeLine, getCompositeType(), Virtuality, VirtualIndex, - Flags, IsOptimized, Unit, TemplateParams, - Declaration, Variables)); + ThisAdjustment, Flags, IsOptimized, Unit, + TemplateParams, Declaration, Variables)); EXPECT_NE(N, DISubprogram::get(Context, Scope, Name, LinkageName, File, Line, Type, IsLocalToUnit, IsDefinition, ScopeLine, ContainingType, Virtuality + 1, VirtualIndex, - Flags, IsOptimized, Unit, TemplateParams, - Declaration, Variables)); + ThisAdjustment, Flags, IsOptimized, Unit, + TemplateParams, Declaration, Variables)); EXPECT_NE(N, DISubprogram::get(Context, Scope, Name, LinkageName, File, Line, Type, IsLocalToUnit, IsDefinition, ScopeLine, ContainingType, Virtuality, VirtualIndex + 1, - Flags, IsOptimized, Unit, TemplateParams, - Declaration, Variables)); + ThisAdjustment, Flags, IsOptimized, Unit, + TemplateParams, Declaration, Variables)); EXPECT_NE(N, DISubprogram::get(Context, Scope, Name, LinkageName, File, Line, Type, IsLocalToUnit, IsDefinition, ScopeLine, ContainingType, Virtuality, VirtualIndex, - NotFlags, IsOptimized, Unit, TemplateParams, - Declaration, Variables)); + ThisAdjustment, NotFlags, IsOptimized, Unit, + TemplateParams, Declaration, Variables)); EXPECT_NE(N, DISubprogram::get(Context, Scope, Name, LinkageName, File, Line, Type, IsLocalToUnit, IsDefinition, ScopeLine, ContainingType, Virtuality, VirtualIndex, - Flags, !IsOptimized, Unit, TemplateParams, - Declaration, Variables)); + ThisAdjustment, Flags, !IsOptimized, Unit, + TemplateParams, Declaration, Variables)); EXPECT_NE(N, DISubprogram::get(Context, Scope, Name, LinkageName, File, Line, Type, IsLocalToUnit, IsDefinition, ScopeLine, ContainingType, Virtuality, VirtualIndex, - Flags, IsOptimized, nullptr, TemplateParams, - Declaration, Variables)); + ThisAdjustment, Flags, IsOptimized, nullptr, + TemplateParams, Declaration, Variables)); EXPECT_NE(N, DISubprogram::get(Context, Scope, Name, LinkageName, File, Line, Type, IsLocalToUnit, IsDefinition, ScopeLine, ContainingType, Virtuality, VirtualIndex, - Flags, IsOptimized, Unit, getTuple(), - Declaration, Variables)); + ThisAdjustment, Flags, IsOptimized, Unit, + getTuple(), Declaration, Variables)); EXPECT_NE(N, DISubprogram::get(Context, Scope, Name, LinkageName, File, Line, Type, IsLocalToUnit, IsDefinition, ScopeLine, ContainingType, Virtuality, VirtualIndex, - Flags, IsOptimized, Unit, TemplateParams, - getSubprogram(), Variables)); + ThisAdjustment, Flags, IsOptimized, Unit, + TemplateParams, getSubprogram(), Variables)); EXPECT_NE(N, DISubprogram::get(Context, Scope, Name, LinkageName, File, Line, Type, IsLocalToUnit, IsDefinition, ScopeLine, ContainingType, Virtuality, VirtualIndex, - Flags, IsOptimized, Unit, TemplateParams, - Declaration, getTuple())); + ThisAdjustment, Flags, IsOptimized, Unit, + TemplateParams, Declaration, getTuple())); TempDISubprogram Temp = N->clone(); EXPECT_EQ(N, MDNode::replaceWithUniqued(std::move(Temp)));