Index: clang/lib/CodeGen/CGDebugInfo.cpp =================================================================== --- clang/lib/CodeGen/CGDebugInfo.cpp +++ clang/lib/CodeGen/CGDebugInfo.cpp @@ -1605,6 +1605,48 @@ ContainingType = RecordTy; } + // DWARF-5 support for, defaulted, deleted member functions + if (const auto *CXXC = dyn_cast(Method)) { + if (CXXC->getCanonicalDecl()->isDeleted()) + SPFlags |= llvm::DISubprogram::SPFlagDeleted; + + if (CXXC->getCanonicalDecl()->isDefaulted()) + SPFlags |= llvm::DISubprogram::SPFlagDefaultedInClass; + else if (const auto Def = CXXC->getDefinition()) { + if (Def->isDefaulted()) + SPFlags |= llvm::DISubprogram::SPFlagDefaultedOutOfClass; + else + SPFlags |= llvm::DISubprogram::SPFlagNotDefaulted; + } + } + if (const auto *DXXC = dyn_cast(Method)) { + if (DXXC->getCanonicalDecl()->isDeleted()) + SPFlags |= llvm::DISubprogram::SPFlagDeleted; + + if (DXXC->getCanonicalDecl()->isDefaulted()) + SPFlags |= llvm::DISubprogram::SPFlagDefaultedInClass; + else if (const auto Def = DXXC->getDefinition()) { + if (Def->isDefaulted()) { + SPFlags |= llvm::DISubprogram::SPFlagDefaultedOutOfClass; + } else { + SPFlags |= llvm::DISubprogram::SPFlagNotDefaulted; + } + } + } + if (Method->isCopyAssignmentOperator() || + Method->isMoveAssignmentOperator()) { + if (Method->getCanonicalDecl()->isDeleted()) + SPFlags |= llvm::DISubprogram::SPFlagDeleted; + + if (Method->getCanonicalDecl()->isDefaulted()) + SPFlags |= llvm::DISubprogram::SPFlagDefaultedInClass; + else if (const auto Def = Method->getDefinition()) { + if (Def->isDefaulted()) + SPFlags |= llvm::DISubprogram::SPFlagDefaultedOutOfClass; + else + SPFlags |= llvm::DISubprogram::SPFlagNotDefaulted; + } + } if (Method->isStatic()) Flags |= llvm::DINode::FlagStaticMember; if (Method->isImplicit()) Index: clang/test/CodeGenCXX/dbg-info-all-calls-described.cpp =================================================================== --- clang/test/CodeGenCXX/dbg-info-all-calls-described.cpp +++ clang/test/CodeGenCXX/dbg-info-all-calls-described.cpp @@ -57,7 +57,7 @@ // NO-ATTR-NOT: FlagAllCallsDescribed // HAS-ATTR-DAG: DISubprogram(name: "declaration2", {{.*}}, flags: DIFlagPrototyped | DIFlagAllCallsDescribed, spFlags: DISPFlagDefinition -// HAS-ATTR-DAG: DISubprogram(name: "struct1", {{.*}}, flags: DIFlagPrototyped, spFlags: DISPFlagOptimized) +// HAS-ATTR-DAG: DISubprogram(name: "struct1", {{.*}}, flags: DIFlagPrototyped, spFlags: DISPFlagOptimized | DISPFlagNotDefaulted) // HAS-ATTR-DAG: DISubprogram(name: "struct1", {{.*}}, flags: DIFlagPrototyped | DIFlagAllCallsDescribed, spFlags: DISPFlagDefinition // HAS-ATTR-DAG: DISubprogram(name: "method1", {{.*}}, flags: DIFlagPrototyped | DIFlagAllCallsDescribed, spFlags: DISPFlagDefinition // HAS-ATTR-DAG: DISubprogram(name: "force_irgen", {{.*}}, flags: DIFlagPrototyped | DIFlagAllCallsDescribed, spFlags: DISPFlagDefinition Index: clang/test/CodeGenCXX/debug-info-defaulted-in-class.cpp =================================================================== --- /dev/null +++ clang/test/CodeGenCXX/debug-info-defaulted-in-class.cpp @@ -0,0 +1,30 @@ +// Test for debug info for C++11 defaulted member functions + +//Supported: DWARF5, -O0, standalone DI +// RUN: %clang_cc1 -emit-llvm -triple x86_64-linux-gnu %s -o - \ +// RUN: -O0 -disable-llvm-passes \ +// RUN: -debug-info-kind=standalone -dwarf-version=5 \ +// RUN: | FileCheck %s -check-prefix=ATTR + +// ATTR: DISubprogram(name: "inclass_defaulted", {{.*}}, flags: DIFlagPublic | DIFlagPrototyped, spFlags: DISPFlagDefaultedInClass +// ATTR: DISubprogram(name: "inclass_defaulted", {{.*}}, flags: DIFlagPublic | DIFlagPrototyped, spFlags: DISPFlagDefaultedInClass +// ATTR: DISubprogram(name: "operator=", linkageName: "_ZN17inclass_defaultedaSERKS_", {{.*}}, flags: DIFlagPublic | DIFlagPrototyped, spFlags: DISPFlagDefaultedInClass +// ATTR: DISubprogram(name: "inclass_defaulted", {{.*}}, flags: DIFlagPublic | DIFlagPrototyped, spFlags: DISPFlagDefaultedInClass +// ATTR: DISubprogram(name: "operator=", linkageName: "_ZN17inclass_defaultedaSEOS_", {{.*}}, flags: DIFlagPublic | DIFlagPrototyped, spFlags: DISPFlagDefaultedInClass +// ATTR: DISubprogram(name: "~inclass_defaulted", {{.*}}, flags: DIFlagPublic | DIFlagPrototyped, spFlags: DISPFlagDefaultedInClass +class inclass_defaulted { +public: + inclass_defaulted() = default; + + inclass_defaulted(const inclass_defaulted &) = default; + inclass_defaulted &operator=(const inclass_defaulted &) = default; + + inclass_defaulted(inclass_defaulted &&) = default; + inclass_defaulted &operator=(inclass_defaulted &&) = default; + + ~inclass_defaulted() = default; +}; + +void foo() { + inclass_defaulted obj1; +} Index: clang/test/CodeGenCXX/debug-info-defaulted-out-of-class.cpp =================================================================== --- /dev/null +++ clang/test/CodeGenCXX/debug-info-defaulted-out-of-class.cpp @@ -0,0 +1,40 @@ +// Test for debug info for C++11 out of defaulted member functions + +//Supported: DWARF5, -O0, standalone DI +// RUN: %clang_cc1 -emit-llvm -triple x86_64-linux-gnu %s -o - \ +// RUN: -O0 -disable-llvm-passes \ +// RUN: -debug-info-kind=standalone -dwarf-version=5 \ +// RUN: | FileCheck %s -check-prefix=ATTR + +// ATTR: DISubprogram(name: "out_of_class_defaulted", {{.*}}, flags: DIFlagPublic | DIFlagPrototyped, spFlags: DISPFlagDefaultedOutOfClass +// ATTR: DISubprogram(name: "out_of_class_defaulted", {{.*}}, flags: DIFlagPublic | DIFlagPrototyped +// ATTR: DISubprogram(name: "operator=", linkageName: "_ZN22out_of_class_defaultedaSERKS_", {{.*}}, flags: DIFlagPublic | DIFlagPrototyped +// ATTR: DISubprogram(name: "out_of_class_defaulted", {{.*}}, flags: DIFlagPublic | DIFlagPrototyped +// ATTR: DISubprogram(name: "operator=", linkageName: "_ZN22out_of_class_defaultedaSEOS_", {{.*}}, flags: DIFlagPublic | DIFlagPrototyped +// ATTR: DISubprogram(name: "~out_of_class_defaulted", {{.*}}, flags: DIFlagPublic | DIFlagPrototyped +class out_of_class_defaulted { +public: + out_of_class_defaulted(); + + out_of_class_defaulted(const out_of_class_defaulted &); + out_of_class_defaulted &operator=(const out_of_class_defaulted &); + + out_of_class_defaulted(out_of_class_defaulted &&); + out_of_class_defaulted &operator=(out_of_class_defaulted &&); + + ~out_of_class_defaulted(); +}; + +out_of_class_defaulted::out_of_class_defaulted() = default; + +out_of_class_defaulted::out_of_class_defaulted(const out_of_class_defaulted &) = default; +out_of_class_defaulted &out_of_class_defaulted::operator=(const out_of_class_defaulted &) = default; + +out_of_class_defaulted::out_of_class_defaulted(out_of_class_defaulted &&) = default; +out_of_class_defaulted &out_of_class_defaulted::operator=(out_of_class_defaulted &&) = default; + +out_of_class_defaulted::~out_of_class_defaulted() = default; + +void foo() { + out_of_class_defaulted obj1; +} Index: clang/test/CodeGenCXX/debug-info-deleted.cpp =================================================================== --- /dev/null +++ clang/test/CodeGenCXX/debug-info-deleted.cpp @@ -0,0 +1,30 @@ +// Test for debug info for C++11 deleted member functions + +//Supported: DWARF5, -O0, standalone DI +// RUN: %clang_cc1 -emit-llvm -triple x86_64-linux-gnu %s -o - \ +// RUN: -O0 -disable-llvm-passes \ +// RUN: -debug-info-kind=standalone -dwarf-version=5 \ +// RUN: | FileCheck %s -check-prefix=ATTR + +// ATTR: DISubprogram(name: "deleted", {{.*}}, flags: DIFlagPublic | DIFlagPrototyped, spFlags: DISPFlagDefaultedInClass +// ATTR: DISubprogram(name: "deleted", {{.*}}, flags: DIFlagPublic | DIFlagPrototyped, spFlags: DISPFlagNotDefaulted | DISPFlagDeleted +// ATTR: DISubprogram(name: "operator=", linkageName: "_ZN7deletedaSERKS_", {{.*}}, flags: DIFlagPublic | DIFlagPrototyped, spFlags: DISPFlagNotDefaulted | DISPFlagDeleted +// ATTR: DISubprogram(name: "deleted", {{.*}}, flags: DIFlagPublic | DIFlagPrototyped, spFlags: DISPFlagNotDefaulted | DISPFlagDeleted +// ATTR: DISubprogram(name: "operator=", linkageName: "_ZN7deletedaSEOS_", {{.*}}, flags: DIFlagPublic | DIFlagPrototyped, spFlags: DISPFlagNotDefaulted | DISPFlagDeleted +// ATTR: DISubprogram(name: "~deleted", {{.*}}, flags: DIFlagPublic | DIFlagPrototyped, spFlags: DISPFlagDefaultedInClass +class deleted { +public: + deleted() = default; // Defaulted on purpose, so as to facilitate object creation + + deleted(const deleted &) = delete; + deleted &operator=(const deleted &) = delete; + + deleted(deleted &&) = delete; + deleted &operator=(deleted &&) = delete; + + ~deleted() = default; +}; + +void foo() { + deleted obj1; +} Index: clang/test/CodeGenCXX/debug-info-not-defaulted.cpp =================================================================== --- /dev/null +++ clang/test/CodeGenCXX/debug-info-not-defaulted.cpp @@ -0,0 +1,30 @@ +// Test for debug info for C++11 Not defaulted member functions + +//Supported: DWARF5, -O0, standalone DI +// RUN: %clang_cc1 -emit-llvm -triple x86_64-linux-gnu %s -o - \ +// RUN: -O0 -disable-llvm-passes \ +// RUN: -debug-info-kind=standalone -dwarf-version=5 \ +// RUN: | FileCheck %s -check-prefix=ATTR + +// ATTR: DISubprogram(name: "not_defaulted", {{.*}}, flags: DIFlagPublic | DIFlagPrototyped, spFlags: DISPFlagNotDefaulted +// ATTR: DISubprogram(name: "not_defaulted", {{.*}}, flags: DIFlagPublic | DIFlagPrototyped, spFlags: DISPFlagNotDefaulted +// ATTR: DISubprogram(name: "operator=", linkageName: "_ZN13not_defaultedaSERS_", {{.*}}, flags: DIFlagPublic | DIFlagPrototyped, spFlags: DISPFlagNotDefaulted +// ATTR: DISubprogram(name: "not_defaulted", {{.*}}, flags: DIFlagPublic | DIFlagPrototyped, spFlags: DISPFlagNotDefaulted +// ATTR: DISubprogram(name: "operator=", linkageName: "_ZN13not_defaultedaSEOS_", {{.*}}, flags: DIFlagPublic | DIFlagPrototyped, spFlags: DISPFlagNotDefaulted +// ATTR: DISubprogram(name: "~not_defaulted", {{.*}}, flags: DIFlagPublic | DIFlagPrototyped, spFlags: DISPFlagNotDefaulted +class not_defaulted { +public: + not_defaulted() {} + + not_defaulted(const not_defaulted &) {} + not_defaulted &operator=(not_defaulted ¶m) { return param; } + + not_defaulted(not_defaulted &¶m) {} + not_defaulted &operator=(not_defaulted &¶m) { return param; } + + ~not_defaulted() {} +}; + +void foo() { + not_defaulted obj1; +} Index: llvm/include/llvm/BinaryFormat/Dwarf.h =================================================================== --- llvm/include/llvm/BinaryFormat/Dwarf.h +++ llvm/include/llvm/BinaryFormat/Dwarf.h @@ -411,6 +411,7 @@ StringRef DecimalSignString(unsigned Sign); StringRef EndianityString(unsigned Endian); StringRef AccessibilityString(unsigned Access); +StringRef DefaultedMemberString(unsigned DefaultedEncodings); StringRef VisibilityString(unsigned Visibility); StringRef VirtualityString(unsigned Virtuality); StringRef LanguageString(unsigned Language); Index: llvm/include/llvm/IR/DebugInfoFlags.def =================================================================== --- llvm/include/llvm/IR/DebugInfoFlags.def +++ llvm/include/llvm/IR/DebugInfoFlags.def @@ -88,11 +88,15 @@ HANDLE_DISP_FLAG((1u << 6), Elemental) HANDLE_DISP_FLAG((1u << 7), Recursive) HANDLE_DISP_FLAG((1u << 8), MainSubprogram) +HANDLE_DISP_FLAG((1u << 9), NotDefaulted) +HANDLE_DISP_FLAG((1u << 10), DefaultedInClass) +HANDLE_DISP_FLAG((1u << 11), DefaultedOutOfClass) +HANDLE_DISP_FLAG((1u << 12), Deleted) #ifdef DISP_FLAG_LARGEST_NEEDED // Intended to be used with ADT/BitmaskEnum.h. // NOTE: Always must be equal to largest flag, check this when adding new flags. -HANDLE_DISP_FLAG((1 << 8), Largest) +HANDLE_DISP_FLAG((1 << 12), Largest) #undef DISP_FLAG_LARGEST_NEEDED #endif Index: llvm/include/llvm/IR/DebugInfoMetadata.h =================================================================== --- llvm/include/llvm/IR/DebugInfoMetadata.h +++ llvm/include/llvm/IR/DebugInfoMetadata.h @@ -1758,6 +1758,14 @@ bool isPure() const { return getSPFlags() & SPFlagPure; } bool isElemental() const { return getSPFlags() & SPFlagElemental; } bool isRecursive() const { return getSPFlags() & SPFlagRecursive; } + bool isDefaultedInClass() const { + return getSPFlags() & SPFlagDefaultedInClass; + } + bool isDefaultedOutOfClass() const { + return getSPFlags() & SPFlagDefaultedOutOfClass; + } + bool isNotDefaulted() const { return getSPFlags() & SPFlagNotDefaulted; } + bool isDeleted() const { return getSPFlags() & SPFlagDeleted; } /// Check if this is reference-qualified. /// Index: llvm/lib/BinaryFormat/Dwarf.cpp =================================================================== --- llvm/lib/BinaryFormat/Dwarf.cpp +++ llvm/lib/BinaryFormat/Dwarf.cpp @@ -271,6 +271,19 @@ return StringRef(); } +StringRef llvm::dwarf::DefaultedMemberString(unsigned DefaultedEncodings) { + switch (DefaultedEncodings) { + // Defaulted Member Encodings codes + case DW_DEFAULTED_no: + return "DW_DEFAULTED_no"; + case DW_DEFAULTED_in_class: + return "DW_DEFAULTED_in_class"; + case DW_DEFAULTED_out_of_class: + return "DW_DEFAULTED_out_of_class"; + } + return StringRef(); +} + StringRef llvm::dwarf::VisibilityString(unsigned Visibility) { switch (Visibility) { case DW_VIS_local: @@ -601,6 +614,8 @@ return ArrayOrderString(Val); case DW_AT_APPLE_runtime_class: return LanguageString(Val); + case DW_AT_defaulted: + return DefaultedMemberString(Val); } return StringRef(); Index: llvm/lib/CodeGen/AsmPrinter/DwarfUnit.cpp =================================================================== --- llvm/lib/CodeGen/AsmPrinter/DwarfUnit.cpp +++ llvm/lib/CodeGen/AsmPrinter/DwarfUnit.cpp @@ -1296,6 +1296,19 @@ addFlag(SPDie, dwarf::DW_AT_elemental); if (SP->isRecursive()) addFlag(SPDie, dwarf::DW_AT_recursive); + if (DD->getDwarfVersion() >= 5) { + if (SP->isDefaultedInClass()) + addUInt(SPDie, dwarf::DW_AT_defaulted, dwarf::DW_FORM_data1, + dwarf::DW_DEFAULTED_in_class); + if (SP->isDefaultedOutOfClass()) + addUInt(SPDie, dwarf::DW_AT_defaulted, dwarf::DW_FORM_data1, + dwarf::DW_DEFAULTED_out_of_class); + if (SP->isNotDefaulted()) + addUInt(SPDie, dwarf::DW_AT_defaulted, dwarf::DW_FORM_data1, + dwarf::DW_DEFAULTED_no); + if (SP->isDeleted()) + addFlag(SPDie, dwarf::DW_AT_deleted); + } } void DwarfUnit::constructSubrangeDIE(DIE &Buffer, const DISubrange *SR,