Index: clang/include/clang/AST/DeclBase.h =================================================================== --- clang/include/clang/AST/DeclBase.h +++ clang/include/clang/AST/DeclBase.h @@ -1797,6 +1797,11 @@ return const_cast(this)->getParent(); } + // Get the first declaration. + Decl *getFirstDeclaration() const { + return FirstDecl; + } + /// getLexicalParent - Returns the containing lexical DeclContext. May be /// different from getParent, e.g.: /// Index: clang/lib/CodeGen/CGDebugInfo.cpp =================================================================== --- clang/lib/CodeGen/CGDebugInfo.cpp +++ clang/lib/CodeGen/CGDebugInfo.cpp @@ -3659,6 +3659,7 @@ StringRef Name; StringRef LinkageName; + StringRef LambdaName; FnBeginRegionCount.push_back(LexicalBlockStack.size()); @@ -3723,6 +3724,23 @@ llvm::DISubprogram::DISPFlags SPFlagsForDef = SPFlags | llvm::DISubprogram::SPFlagDefinition; + // Check if it is the operator() of a lambda. + // TODO: This should be done clearer. + if (Name == "operator()") { + if (D) { + auto CXXMethod = dyn_cast(D); + if (CXXMethod) { + auto ParentDecl = CXXMethod->getParent(); + if (ParentDecl->isLambda()) { + auto LamdaVarDecl = ParentDecl->getParent()->getFirstDeclaration(); + if (LamdaVarDecl) { + LambdaName = cast(LamdaVarDecl)->getName(); + } + } + } + } + } + unsigned LineNo = getLineNumber(Loc); unsigned ScopeLine = getLineNumber(ScopeLoc); llvm::DISubroutineType *DIFnType = getOrCreateFunctionType(D, FnType, Unit); @@ -3739,7 +3757,7 @@ // are emitted as CU level entities by the backend. llvm::DISubprogram *SP = DBuilder.createFunction( FDContext, Name, LinkageName, Unit, LineNo, DIFnType, ScopeLine, - FlagsForDef, SPFlagsForDef, TParamsArray.get(), Decl); + FlagsForDef, SPFlagsForDef, TParamsArray.get(), Decl, nullptr, LambdaName); Fn->setSubprogram(SP); // We might get here with a VarDecl in the case we're generating // code for the initialization of globals. Do not record these decls Index: clang/test/CodeGenCXX/dbg-info-lambda-name.cpp =================================================================== --- /dev/null +++ clang/test/CodeGenCXX/dbg-info-lambda-name.cpp @@ -0,0 +1,19 @@ +// Test the DW_AT_LLVM_lambda_name. + +// RUN: %clangxx -S -emit-llvm -g -O2 %s -o - \ +// RUN: | FileCheck %s + +extern void fn(int); + +int fn2() { + auto doSomething = [](int num) { + fn(num); + }; + + for (int i = 0; i < 5; ++i) + doSomething(i); + + return 0; +} + +// CHECK: DISubprogram(name: "operator()", {{.*}}, lambda: "doSomething") Index: llvm/include/llvm/IR/DIBuilder.h =================================================================== --- llvm/include/llvm/IR/DIBuilder.h +++ llvm/include/llvm/IR/DIBuilder.h @@ -674,7 +674,8 @@ DISubprogram::DISPFlags SPFlags = DISubprogram::SPFlagZero, DITemplateParameterArray TParams = nullptr, DISubprogram *Decl = nullptr, - DITypeArray ThrownTypes = nullptr); + DITypeArray ThrownTypes = nullptr, + StringRef Lamda = ""); /// Identical to createFunction, /// except that the resulting DbgNode is meant to be RAUWed. Index: llvm/include/llvm/IR/DebugInfoMetadata.h =================================================================== --- llvm/include/llvm/IR/DebugInfoMetadata.h +++ llvm/include/llvm/IR/DebugInfoMetadata.h @@ -1670,14 +1670,14 @@ unsigned VirtualIndex, int ThisAdjustment, DIFlags Flags, DISPFlags SPFlags, DICompileUnit *Unit, DITemplateParameterArray TemplateParams, DISubprogram *Declaration, - DINodeArray RetainedNodes, DITypeArray ThrownTypes, + DINodeArray RetainedNodes, DITypeArray ThrownTypes, StringRef Lambda, StorageType Storage, bool ShouldCreate = true) { return getImpl(Context, Scope, getCanonicalMDString(Context, Name), getCanonicalMDString(Context, LinkageName), File, Line, Type, ScopeLine, ContainingType, VirtualIndex, ThisAdjustment, Flags, SPFlags, Unit, TemplateParams.get(), Declaration, - RetainedNodes.get(), ThrownTypes.get(), Storage, - ShouldCreate); + RetainedNodes.get(), ThrownTypes.get(), + getCanonicalMDString(Context, Lambda), Storage, ShouldCreate); } static DISubprogram *getImpl(LLVMContext &Context, Metadata *Scope, MDString *Name, MDString *LinkageName, @@ -1687,6 +1687,7 @@ DIFlags Flags, DISPFlags SPFlags, Metadata *Unit, Metadata *TemplateParams, Metadata *Declaration, Metadata *RetainedNodes, Metadata *ThrownTypes, + MDString *Lambda, StorageType Storage, bool ShouldCreate = true); TempDISubprogram cloneImpl() const { @@ -1695,7 +1696,7 @@ getContainingType(), getVirtualIndex(), getThisAdjustment(), getFlags(), getSPFlags(), getUnit(), getTemplateParams(), getDeclaration(), - getRetainedNodes(), getThrownTypes()); + getRetainedNodes(), getThrownTypes(), getLambda()); } public: @@ -1707,10 +1708,10 @@ DIFlags Flags, DISPFlags SPFlags, DICompileUnit *Unit, DITemplateParameterArray TemplateParams = nullptr, DISubprogram *Declaration = nullptr, DINodeArray RetainedNodes = nullptr, - DITypeArray ThrownTypes = nullptr), + DITypeArray ThrownTypes = nullptr, StringRef Lambda = ""), (Scope, Name, LinkageName, File, Line, Type, ScopeLine, ContainingType, VirtualIndex, ThisAdjustment, Flags, SPFlags, Unit, TemplateParams, - Declaration, RetainedNodes, ThrownTypes)) + Declaration, RetainedNodes, ThrownTypes, Lambda)) DEFINE_MDNODE_GET( DISubprogram, @@ -1719,10 +1720,11 @@ Metadata *ContainingType, unsigned VirtualIndex, int ThisAdjustment, DIFlags Flags, DISPFlags SPFlags, Metadata *Unit, Metadata *TemplateParams = nullptr, Metadata *Declaration = nullptr, - Metadata *RetainedNodes = nullptr, Metadata *ThrownTypes = nullptr), + Metadata *RetainedNodes = nullptr, Metadata *ThrownTypes = nullptr, + MDString *Lambda = nullptr), (Scope, Name, LinkageName, File, Line, Type, ScopeLine, ContainingType, VirtualIndex, ThisAdjustment, Flags, SPFlags, Unit, TemplateParams, - Declaration, RetainedNodes, ThrownTypes)) + Declaration, RetainedNodes, ThrownTypes, Lambda)) TempDISubprogram clone() const { return cloneImpl(); } @@ -1823,6 +1825,13 @@ return cast_or_null(getRawThrownTypes()); } + StringRef getLambda() const { + if (auto *s = getRawLambda()) { + return s->getString(); + } + return StringRef(); + } + Metadata *getRawScope() const { return getOperand(1); } MDString *getRawName() const { return getOperandAs(2); } MDString *getRawLinkageName() const { return getOperandAs(3); } @@ -1840,6 +1849,10 @@ return getNumOperands() > 10 ? getOperandAs(10) : nullptr; } + MDString *getRawLambda() const { + return getNumOperands() > 11 ? getOperandAs(11) : nullptr; + } + /// Check if this subprogram describes the given function. /// /// FIXME: Should this be looking through bitcasts? Index: llvm/lib/AsmParser/LLParser.cpp =================================================================== --- llvm/lib/AsmParser/LLParser.cpp +++ llvm/lib/AsmParser/LLParser.cpp @@ -4682,7 +4682,8 @@ /// virtuality: DW_VIRTUALTIY_pure_virtual, /// virtualIndex: 10, thisAdjustment: 4, flags: 11, /// spFlags: 10, isOptimized: false, templateParams: !4, -/// declaration: !5, retainedNodes: !6, thrownTypes: !7) +/// declaration: !5, retainedNodes: !6, thrownTypes: !7, +/// lambda: "doSomething") bool LLParser::ParseDISubprogram(MDNode *&Result, bool IsDistinct) { auto Loc = Lex.getLoc(); #define VISIT_MD_FIELDS(OPTIONAL, REQUIRED) \ @@ -4706,7 +4707,8 @@ OPTIONAL(templateParams, MDField, ); \ OPTIONAL(declaration, MDField, ); \ OPTIONAL(retainedNodes, MDField, ); \ - OPTIONAL(thrownTypes, MDField, ); + OPTIONAL(thrownTypes, MDField, ); \ + OPTIONAL(lambda, MDStringField, ); PARSE_MD_FIELDS(); #undef VISIT_MD_FIELDS @@ -4725,7 +4727,7 @@ (Context, scope.Val, name.Val, linkageName.Val, file.Val, line.Val, type.Val, scopeLine.Val, containingType.Val, virtualIndex.Val, thisAdjustment.Val, flags.Val, SPFlags, unit.Val, templateParams.Val, - declaration.Val, retainedNodes.Val, thrownTypes.Val)); + declaration.Val, retainedNodes.Val, thrownTypes.Val, lambda.Val)); return false; } Index: llvm/lib/Bitcode/Reader/MetadataLoader.cpp =================================================================== --- llvm/lib/Bitcode/Reader/MetadataLoader.cpp +++ llvm/lib/Bitcode/Reader/MetadataLoader.cpp @@ -1535,6 +1535,7 @@ bool HasFn = false; bool HasThisAdj = true; bool HasThrownTypes = true; + bool HasLambda = true; unsigned OffsetA = 0; unsigned OffsetB = 0; if (!HasSPFlags) { @@ -1546,6 +1547,7 @@ } HasThisAdj = Record.size() >= 20; HasThrownTypes = Record.size() >= 21; + HasLambda = Record.size() >= 22; } Metadata *CUorFn = getMDOrNull(Record[12 + OffsetB]); DISubprogram *SP = GET_OR_DISTINCT( @@ -1568,7 +1570,9 @@ getMDOrNull(Record[14 + OffsetB]), // declaration getMDOrNull(Record[15 + OffsetB]), // retainedNodes HasThrownTypes ? getMDOrNull(Record[17 + OffsetB]) - : nullptr // thrownTypes + : nullptr, // thrownTypes + HasLambda ? getMDString(Record[18 + OffsetB]) + : nullptr // lambda )); MetadataList.assignValue(SP, NextMetadataNo); NextMetadataNo++; Index: llvm/lib/Bitcode/Writer/BitcodeWriter.cpp =================================================================== --- llvm/lib/Bitcode/Writer/BitcodeWriter.cpp +++ llvm/lib/Bitcode/Writer/BitcodeWriter.cpp @@ -1698,6 +1698,7 @@ Record.push_back(VE.getMetadataOrNullID(N->getRetainedNodes().get())); Record.push_back(N->getThisAdjustment()); Record.push_back(VE.getMetadataOrNullID(N->getThrownTypes().get())); + Record.push_back(VE.getMetadataOrNullID(N->getRawLambda())); Stream.EmitRecord(bitc::METADATA_SUBPROGRAM, Record, Abbrev); Record.clear(); Index: llvm/lib/IR/AsmWriter.cpp =================================================================== --- llvm/lib/IR/AsmWriter.cpp +++ llvm/lib/IR/AsmWriter.cpp @@ -1976,6 +1976,7 @@ Printer.printMetadata("declaration", N->getRawDeclaration()); Printer.printMetadata("retainedNodes", N->getRawRetainedNodes()); Printer.printMetadata("thrownTypes", N->getRawThrownTypes()); + Printer.printString("lambda", N->getLambda()); Out << ")"; } Index: llvm/lib/IR/DIBuilder.cpp =================================================================== --- llvm/lib/IR/DIBuilder.cpp +++ llvm/lib/IR/DIBuilder.cpp @@ -758,13 +758,14 @@ unsigned LineNo, DISubroutineType *Ty, unsigned ScopeLine, DINode::DIFlags Flags, DISubprogram::DISPFlags SPFlags, DITemplateParameterArray TParams, DISubprogram *Decl, - DITypeArray ThrownTypes) { + DITypeArray ThrownTypes, StringRef Lambda) { bool IsDefinition = SPFlags & DISubprogram::SPFlagDefinition; + auto *Node = getSubprogram( /*IsDistinct=*/IsDefinition, VMContext, getNonCompileUnitScope(Context), Name, LinkageName, File, LineNo, Ty, ScopeLine, nullptr, 0, 0, Flags, SPFlags, IsDefinition ? CUNode : nullptr, TParams, Decl, - MDTuple::getTemporary(VMContext, None).release(), ThrownTypes); + MDTuple::getTemporary(VMContext, None).release(), ThrownTypes, Lambda); if (IsDefinition) AllSubprograms.push_back(Node); Index: llvm/lib/IR/DebugInfoMetadata.cpp =================================================================== --- llvm/lib/IR/DebugInfoMetadata.cpp +++ llvm/lib/IR/DebugInfoMetadata.cpp @@ -642,23 +642,27 @@ unsigned ScopeLine, Metadata *ContainingType, unsigned VirtualIndex, int ThisAdjustment, DIFlags Flags, DISPFlags SPFlags, Metadata *Unit, Metadata *TemplateParams, Metadata *Declaration, Metadata *RetainedNodes, - Metadata *ThrownTypes, StorageType Storage, bool ShouldCreate) { + Metadata *ThrownTypes, MDString *Lambda, + 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, ScopeLine, ContainingType, VirtualIndex, ThisAdjustment, Flags, SPFlags, Unit, TemplateParams, Declaration, - RetainedNodes, ThrownTypes)); - SmallVector Ops = { + RetainedNodes, ThrownTypes, Lambda)); + SmallVector Ops = { File, Scope, Name, LinkageName, Type, Unit, - Declaration, RetainedNodes, ContainingType, TemplateParams, ThrownTypes}; - if (!ThrownTypes) { + Declaration, RetainedNodes, ContainingType, TemplateParams, ThrownTypes, Lambda}; + if (!Lambda) { Ops.pop_back(); - if (!TemplateParams) { + if (!ThrownTypes) { Ops.pop_back(); - if (!ContainingType) + if (!TemplateParams) { Ops.pop_back(); + if (!ContainingType) + Ops.pop_back(); + } } } DEFINE_GETIMPL_STORE_N( Index: llvm/lib/IR/LLVMContextImpl.h =================================================================== --- llvm/lib/IR/LLVMContextImpl.h +++ llvm/lib/IR/LLVMContextImpl.h @@ -623,6 +623,7 @@ Metadata *Declaration; Metadata *RetainedNodes; Metadata *ThrownTypes; + MDString *Lambda; MDNodeKeyImpl(Metadata *Scope, MDString *Name, MDString *LinkageName, Metadata *File, unsigned Line, Metadata *Type, @@ -630,13 +631,13 @@ unsigned VirtualIndex, int ThisAdjustment, unsigned Flags, unsigned SPFlags, Metadata *Unit, Metadata *TemplateParams, Metadata *Declaration, Metadata *RetainedNodes, - Metadata *ThrownTypes) + Metadata *ThrownTypes, MDString *Lambda) : Scope(Scope), Name(Name), LinkageName(LinkageName), File(File), Line(Line), Type(Type), ScopeLine(ScopeLine), ContainingType(ContainingType), VirtualIndex(VirtualIndex), ThisAdjustment(ThisAdjustment), Flags(Flags), SPFlags(SPFlags), Unit(Unit), TemplateParams(TemplateParams), Declaration(Declaration), - RetainedNodes(RetainedNodes), ThrownTypes(ThrownTypes) {} + RetainedNodes(RetainedNodes), ThrownTypes(ThrownTypes), Lambda(Lambda) {} MDNodeKeyImpl(const DISubprogram *N) : Scope(N->getRawScope()), Name(N->getRawName()), LinkageName(N->getRawLinkageName()), File(N->getRawFile()), @@ -648,7 +649,8 @@ TemplateParams(N->getRawTemplateParams()), Declaration(N->getRawDeclaration()), RetainedNodes(N->getRawRetainedNodes()), - ThrownTypes(N->getRawThrownTypes()) {} + ThrownTypes(N->getRawThrownTypes()), + Lambda(N->getRawLambda()) {} bool isKeyOf(const DISubprogram *RHS) const { return Scope == RHS->getRawScope() && Name == RHS->getRawName() && @@ -663,7 +665,8 @@ TemplateParams == RHS->getRawTemplateParams() && Declaration == RHS->getRawDeclaration() && RetainedNodes == RHS->getRawRetainedNodes() && - ThrownTypes == RHS->getRawThrownTypes(); + ThrownTypes == RHS->getRawThrownTypes() && + Lambda == RHS->getRawLambda(); } bool isDefinition() const { return SPFlags & DISubprogram::SPFlagDefinition; } Index: llvm/lib/IR/Verifier.cpp =================================================================== --- llvm/lib/IR/Verifier.cpp +++ llvm/lib/IR/Verifier.cpp @@ -1149,6 +1149,8 @@ Op); } + // TODO: Verify lambdas. + if (N.areAllCallsDescribed()) AssertDI(N.isDefinition(), "DIFlagAllCallsDescribed must be attached to a definition");