Skip to content

Commit

Permalink
[clang][DebugInfo] Emit DW_AT_deleted on any deleted member function
Browse files Browse the repository at this point in the history
Currently we emit `DW_AT_deleted` for `deleted` special-member
functions (i.e., ctors/dtors). However, in C++ one can mark any
member function as deleted. This patch expands the set of member
functions for which we emit `DW_AT_deleted`.

The DWARFv5 spec section 5.7.8 says:
```
<non-normative>
In C++, a member function may be declared as deleted. This prevents the compiler from
generating a default implementation of a special member function such as a constructor
or destructor, and can affect overload resolution when used on other member functions.
</non-normative>

If the member function entry has been declared as deleted, then that entry has a
DW_AT_deleted attribute.
```

Thus this change is conforming.

Differential Revision: https://reviews.llvm.org/D153282
  • Loading branch information
Michael137 committed Jun 20, 2023
1 parent 189d944 commit c146df9
Show file tree
Hide file tree
Showing 3 changed files with 30 additions and 26 deletions.
23 changes: 2 additions & 21 deletions clang/lib/CodeGen/CGDebugInfo.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1945,27 +1945,8 @@ llvm::DISubprogram *CGDebugInfo::CreateCXXMemberFunction(
ContainingType = RecordTy;
}

// We're checking for deleted C++ special member functions
// [Ctors,Dtors, Copy/Move]
auto checkAttrDeleted = [&](const auto *Method) {
if (Method->getCanonicalDecl()->isDeleted())
SPFlags |= llvm::DISubprogram::SPFlagDeleted;
};

switch (Method->getKind()) {

case Decl::CXXConstructor:
case Decl::CXXDestructor:
checkAttrDeleted(Method);
break;
case Decl::CXXMethod:
if (Method->isCopyAssignmentOperator() ||
Method->isMoveAssignmentOperator())
checkAttrDeleted(Method);
break;
default:
break;
}
if (Method->getCanonicalDecl()->isDeleted())
SPFlags |= llvm::DISubprogram::SPFlagDeleted;

if (Method->isNoReturn())
Flags |= llvm::DINode::FlagNoReturn;
Expand Down
5 changes: 5 additions & 0 deletions clang/test/CodeGenCXX/debug-info-deleted.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,8 @@
// ATTR: DISubprogram(name: "operator=", linkageName: "_ZN7deletedaSERKS_", {{.*}}, flags: DIFlagPublic | DIFlagPrototyped, spFlags: DISPFlagDeleted
// ATTR: DISubprogram(name: "deleted", {{.*}}, flags: DIFlagPublic | DIFlagPrototyped, spFlags: DISPFlagDeleted
// ATTR: DISubprogram(name: "operator=", linkageName: "_ZN7deletedaSEOS_", {{.*}}, flags: DIFlagPublic | DIFlagPrototyped, spFlags: DISPFlagDeleted
// ATTR: DISubprogram(name: "func", {{.*}}, flags: DIFlagPublic | DIFlagPrototyped | DIFlagRValueReference, spFlags: DISPFlagDeleted
// ATTR: DISubprogram(name: "bar", {{.*}}, flags: DIFlagPublic | DIFlagPrototyped | DIFlagStaticMember, spFlags: DISPFlagDeleted
// ATTR: DISubprogram(name: "~deleted", {{.*}}, flags: DIFlagPublic | DIFlagPrototyped,
class deleted {
public:
Expand All @@ -23,6 +25,9 @@ class deleted {
deleted(deleted &&) = delete;
deleted &operator=(deleted &&) = delete;

void func() && = delete;
static int bar() = delete;

~deleted() = default;
};

Expand Down
28 changes: 23 additions & 5 deletions llvm/test/DebugInfo/X86/DW_AT_deleted.ll
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,9 @@
;
; deleted(deleted &&) = delete;
; deleted &operator=(deleted &&) = delete;
;
; void func() && = delete;
; static void bar() = delete;
;
; ~deleted() = default;
; };
Expand Down Expand Up @@ -48,6 +51,16 @@
; CHECK-NEXT: DW_AT_name [DW_FORM_strx1] (indexed (00000008) string = "operator=")
; CHECK: DW_AT_deleted [DW_FORM_flag_present] (true)

; CHECK: DW_TAG_subprogram [10]
; CHECK-NEXT: DW_AT_linkage_name [DW_FORM_strx1] (indexed (0000000b) string = "_ZNO7deleted4funcEv")
; CHECK-NEXT: DW_AT_name [DW_FORM_strx1] (indexed (0000000c) string = "func")
; CHECK: DW_AT_deleted [DW_FORM_flag_present] (true)

; CHECK: DW_TAG_subprogram [11]
; CHECK-NEXT: DW_AT_linkage_name [DW_FORM_strx1] (indexed (0000000d) string = "_ZN7deleted3barEv")
; CHECK-NEXT: DW_AT_name [DW_FORM_strx1] (indexed (0000000e) string = "bar")
; CHECK: DW_AT_deleted [DW_FORM_flag_present] (true)

; ModuleID = 'debug-info-deleted.cpp'
source_filename = "debug-info-deleted.cpp"
target datalayout = "e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-f80:128-n8:16:32:64-S128"
Expand All @@ -58,8 +71,8 @@ target triple = "x86_64-unknown-linux-gnu"
; Function Attrs: noinline nounwind optnone uwtable
define dso_local void @_Z3foov() #0 !dbg !7 {
%1 = alloca %class.deleted, align 1
call void @llvm.dbg.declare(metadata ptr %1, metadata !10, metadata !DIExpression()), !dbg !34
ret void, !dbg !35
call void @llvm.dbg.declare(metadata ptr %1, metadata !10, metadata !DIExpression()), !dbg !39
ret void, !dbg !40
}

; Function Attrs: nounwind readnone speculatable willreturn
Expand All @@ -84,7 +97,7 @@ attributes #1 = { nounwind readnone speculatable willreturn }
!9 = !{null}
!10 = !DILocalVariable(name: "obj1", scope: !7, file: !1, line: 15, type: !11)
!11 = distinct !DICompositeType(tag: DW_TAG_class_type, name: "deleted", file: !1, line: 1, size: 8, flags: DIFlagTypePassByReference, elements: !12, identifier: "_ZTS7deleted")
!12 = !{!13, !17, !22, !26, !30, !33}
!12 = !{!13, !17, !22, !26, !30, !33, !34, !36}
!13 = !DISubprogram(name: "deleted", scope: !11, file: !1, line: 3, type: !14, scopeLine: 3, flags: DIFlagPublic | DIFlagPrototyped, spFlags: 0)
!14 = !DISubroutineType(types: !15)
!15 = !{null, !16}
Expand All @@ -106,5 +119,10 @@ attributes #1 = { nounwind readnone speculatable willreturn }
!31 = !DISubroutineType(types: !32)
!32 = !{!25, !16, !29}
!33 = !DISubprogram(name: "~deleted", scope: !11, file: !1, line: 11, type: !14, scopeLine: 11, flags: DIFlagPublic | DIFlagPrototyped, spFlags: 0)
!34 = !DILocation(line: 15, column: 13, scope: !7)
!35 = !DILocation(line: 16, column: 3, scope: !7)
!34 = !DISubprogram(name: "func", linkageName: "_ZNO7deleted4funcEv", scope: !11, file: !1, line: 13, type: !35, scopeLine: 13, flags: DIFlagPublic | DIFlagPrototyped | DIFlagRValueReference, spFlags: DISPFlagDeleted)
!35 = !DISubroutineType(flags: DIFlagRValueReference, types: !15)
!36 = !DISubprogram(name: "bar", linkageName: "_ZN7deleted3barEv", scope: !11, file: !1, line: 15, type: !37, scopeLine: 15, flags: DIFlagPublic | DIFlagPrototyped | DIFlagStaticMember, spFlags: DISPFlagDeleted)
!37 = !DISubroutineType(types: !38)
!38 = !{null}
!39 = !DILocation(line: 15, column: 13, scope: !7)
!40 = !DILocation(line: 16, column: 3, scope: !7)

0 comments on commit c146df9

Please sign in to comment.