diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst index 34d2b584274a5..63a65bec74b1a 100644 --- a/clang/docs/ReleaseNotes.rst +++ b/clang/docs/ReleaseNotes.rst @@ -299,6 +299,10 @@ Attribute Changes in Clang - Fix a bug where clang doesn't automatically apply the ``[[gsl::Owner]]`` or ``[[gsl::Pointer]]`` to STL explicit template specialization decls. (#GH109442) +- Introduced a new function attribute ``__attribute__((debug_transparent))`` + which is intended as a hint to debuggers that they should not stop at the annotated + function, but instead step through it when stepping in, and continuing directly to + its caller when stepping out. Improvements to Clang's diagnostics ----------------------------------- diff --git a/clang/include/clang/Basic/Attr.td b/clang/include/clang/Basic/Attr.td index fbcbf0ed41641..3b6c8cb409e8a 100644 --- a/clang/include/clang/Basic/Attr.td +++ b/clang/include/clang/Basic/Attr.td @@ -876,6 +876,13 @@ def Artificial : InheritableAttr { let SimpleHandler = 1; } +def DebugTransparent: InheritableAttr { + let Spellings = [Clang<"debug_transparent">]; + let Subjects = SubjectList<[Function, ObjCMethod]>; + let Documentation = [DebugTransparentDocs]; + let SimpleHandler = 1; +} + def XRayInstrument : InheritableAttr { let Spellings = [Clang<"xray_always_instrument">, Clang<"xray_never_instrument">]; diff --git a/clang/include/clang/Basic/AttrDocs.td b/clang/include/clang/Basic/AttrDocs.td index 53d88482698f0..81a062a5d72a5 100644 --- a/clang/include/clang/Basic/AttrDocs.td +++ b/clang/include/clang/Basic/AttrDocs.td @@ -7866,6 +7866,66 @@ As such, this function attribute is currently only supported on X86 targets. }]; } +def DebugTransparentDocs : Documentation { + let Category = DocCatFunction; + let Content = [{ +The ``debug_transparent`` attribute is intended as a hint for debuggers that this +function itself is not interesting, but it calls a function that might be. So, when +stepping in arrives at a function with this attribute, debuggers should transparently +step-in through it into the functions called by the annotated function (but not by +subsequent calls made by those functions), stopping at the first one its normal rules +for whether to stop says to stop at - or stepping out again if none qualify. Also, when +stepping out arrives at a function with this attribute, the debugger should continue +stepping out to its caller. This attribute is currently only supported by DWARF. + +For example: + +.. code-block:: c + + int bar(void) { + return 42; + } + + __attribute__((debug_transparent)) + int foo(void) { + return bar(); + } + + int caller(void) { + return foo(); + } + +Stepping into ``foo`` should step directly into ``bar`` instead, and stepping out of ``bar`` +should stop in ``caller``. + +Functions with the ``debug_transparent`` attribute can be chained together: + +.. code-block:: c + + int baz(void) { + return 42; + } + + __attribute__((debug_transparent)) + int bar(void) { + return baz(); + } + + __attribute__((debug_transparent)) + int foo(void) { + return bar(); + } + + int caller(void) { + return foo(); + } + +In this example, stepping into ``foo`` should step directly into ``baz``, and stepping out of +``baz`` should stop in ``caller``. + }]; +} + + def ReadOnlyPlacementDocs : Documentation { let Category = DocCatType; let Content = [{This attribute is attached to a structure, class or union declaration. diff --git a/clang/include/clang/Basic/DiagnosticCommonKinds.td b/clang/include/clang/Basic/DiagnosticCommonKinds.td index ae709e45a700a..e9cb8a9aaadfe 100644 --- a/clang/include/clang/Basic/DiagnosticCommonKinds.td +++ b/clang/include/clang/Basic/DiagnosticCommonKinds.td @@ -467,4 +467,6 @@ def warn_try_not_valid_on_target : Warning< "target '%0' does not support exception handling;" " 'catch' block is ignored">, InGroup; +def warn_debug_transparent_ignored : Warning< + "'debug_transparent' attribute is ignored since it is only supported by DWARF">; } diff --git a/clang/lib/CodeGen/CGDebugInfo.cpp b/clang/lib/CodeGen/CGDebugInfo.cpp index 8887c4de7c4c8..396a7b141fa49 100644 --- a/clang/lib/CodeGen/CGDebugInfo.cpp +++ b/clang/lib/CodeGen/CGDebugInfo.cpp @@ -21,6 +21,7 @@ #include "TargetInfo.h" #include "clang/AST/ASTContext.h" #include "clang/AST/Attr.h" +#include "clang/AST/Attrs.inc" #include "clang/AST/DeclCXX.h" #include "clang/AST/DeclFriend.h" #include "clang/AST/DeclObjC.h" @@ -109,6 +110,20 @@ static bool IsArtificial(VarDecl const *VD) { cast(VD->getDeclContext())->isImplicit()); } +static bool usesDebugTransparent(const Decl *D, const CodeGenModule &CGM) { + if (!D) + return false; + + if (auto *attr = D->getAttr()) { + if (CGM.getCodeGenOpts().DwarfVersion == 0) + CGM.getDiags().Report(attr->getLocation(), + diag::warn_debug_transparent_ignored); + return true; + } + + return false; +} + CGDebugInfo::CGDebugInfo(CodeGenModule &CGM) : CGM(CGM), DebugKind(CGM.getCodeGenOpts().getDebugInfo()), DebugTypeExtRefs(CGM.getCodeGenOpts().DebugTypeExtRefs), @@ -4480,6 +4495,8 @@ void CGDebugInfo::emitFunctionStart(GlobalDecl GD, SourceLocation Loc, SPFlags |= llvm::DISubprogram::SPFlagLocalToUnit; if (CGM.getLangOpts().Optimize) SPFlags |= llvm::DISubprogram::SPFlagOptimized; + if (usesDebugTransparent(D, CGM)) + SPFlags |= llvm::DISubprogram::SPFlagIsDebugTransparent; llvm::DINode::DIFlags FlagsForDef = Flags | getCallSiteRelatedAttrs(); llvm::DISubprogram::DISPFlags SPFlagsForDef = diff --git a/clang/test/CodeGen/attr-debug-transparent-cxx.cpp b/clang/test/CodeGen/attr-debug-transparent-cxx.cpp new file mode 100644 index 0000000000000..e8cc7a35312ad --- /dev/null +++ b/clang/test/CodeGen/attr-debug-transparent-cxx.cpp @@ -0,0 +1,37 @@ +// RUN: %clang -gdwarf -emit-llvm -S %s -o - | FileCheck %s + +void foo(void) {} + +struct A { + [[clang::debug_transparent()]] + A() { + foo(); + } + + [[clang::debug_transparent()]] + ~A() { + foo(); + } +[[clang::debug_transparent()]] +void method(void) { + foo(); +} + +[[clang::always_inline()]] +[[clang::debug_transparent()]] +void inline_method(void) { + foo(); +} + +}; + +int main() { + auto a = A(); + a.method(); + a.inline_method(); +} + +// CHECK: DISubprogram(name: "inline_method"{{.*}} DISPFlagIsDebugTransparent +// CHECK: DISubprogram(name: "method"{{.*}} DISPFlagIsDebugTransparent +// CHECK: DISubprogram(name: "A"{{.*}} DISPFlagIsDebugTransparent +// CHECK: DISubprogram(name: "~A"{{.*}} DISPFlagIsDebugTransparent diff --git a/clang/test/CodeGen/attr-debug-transparent-method-warning.cpp b/clang/test/CodeGen/attr-debug-transparent-method-warning.cpp new file mode 100644 index 0000000000000..71b8617d46bd2 --- /dev/null +++ b/clang/test/CodeGen/attr-debug-transparent-method-warning.cpp @@ -0,0 +1,14 @@ +// Pipe stderr to FileCheck since we're checking for a warning +// RUN: %clang -gcodeview -g -emit-llvm -S %s -o - 2>&1 | FileCheck %s + + +struct S { +[[clang::debug_transparent]] +void foo(void) {} +}; + +int main() { + S s; + s.foo(); +} +// CHECK: warning: 'debug_transparent' attribute is ignored since it is only supported by DWARF diff --git a/clang/test/CodeGen/attr-debug-transparent-no-warning.c b/clang/test/CodeGen/attr-debug-transparent-no-warning.c new file mode 100644 index 0000000000000..d49f1ce0bb4a8 --- /dev/null +++ b/clang/test/CodeGen/attr-debug-transparent-no-warning.c @@ -0,0 +1,10 @@ +// Pipe stderr to FileCheck since we're checking for a warning +// RUN: %clang -gcodeview -emit-llvm -S %s -o - 2>&1 | FileCheck %s + + +__attribute__((debug_transparent)) +void foo(void) {} + +// Check that the warning is NOT printed when compiling without debug information. +// CHECK-NOT: warning: 'debug_transparent' attribute is ignored since it is only supported by DWARF + diff --git a/clang/test/CodeGen/attr-debug-transparent-objc-warning.m b/clang/test/CodeGen/attr-debug-transparent-objc-warning.m new file mode 100644 index 0000000000000..ff43bd46c5975 --- /dev/null +++ b/clang/test/CodeGen/attr-debug-transparent-objc-warning.m @@ -0,0 +1,12 @@ +// Pipe stderr to FileCheck since we're checking for a warning +// RUN: %clang -gcodeview -g -emit-llvm -S %s -o - 2>&1 | FileCheck %s + +@interface ObjCClass +- (void)foo __attribute__((debug_transparent)); +@end + +@implementation ObjCClass +- (void)foo {} +@end + +// CHECK: warning: 'debug_transparent' attribute is ignored since it is only supported by DWARF diff --git a/clang/test/CodeGen/attr-debug-transparent-objc.m b/clang/test/CodeGen/attr-debug-transparent-objc.m new file mode 100644 index 0000000000000..4b1450ff4311c --- /dev/null +++ b/clang/test/CodeGen/attr-debug-transparent-objc.m @@ -0,0 +1,13 @@ +// RUN: %clang -gdwarf -emit-llvm -S %s -o - | FileCheck %s + + +@interface ObjCClass +- (void)foo __attribute__((debug_transparent)); +@end + +@implementation ObjCClass +- (void)foo {} +@end + + +// CHECK: DISubprogram(name: "-[ObjCClass foo]"{{.*}} DISPFlagIsDebugTransparent diff --git a/clang/test/CodeGen/attr-debug-transparent-warning.c b/clang/test/CodeGen/attr-debug-transparent-warning.c new file mode 100644 index 0000000000000..ef3e931e3bab8 --- /dev/null +++ b/clang/test/CodeGen/attr-debug-transparent-warning.c @@ -0,0 +1,9 @@ +// Pipe stderr to FileCheck since we're checking for a warning +// RUN: %clang -gcodeview -g -emit-llvm -S %s -o - 2>&1 | FileCheck %s + + +__attribute__((debug_transparent)) +void foo(void) {} + +// CHECK: warning: 'debug_transparent' attribute is ignored since it is only supported by DWARF + diff --git a/clang/test/CodeGen/attr-debug-transparent.c b/clang/test/CodeGen/attr-debug-transparent.c new file mode 100644 index 0000000000000..03af1366723af --- /dev/null +++ b/clang/test/CodeGen/attr-debug-transparent.c @@ -0,0 +1,10 @@ +// RUN: %clang -gdwarf -emit-llvm -S %s -o - | FileCheck %s + +void bar(void) {} + +__attribute__((debug_transparent)) +void foo(void) { + bar(); +} + +// CHECK: DISubprogram(name: "foo"{{.*}} DISPFlagIsDebugTransparent diff --git a/clang/test/Misc/pragma-attribute-supported-attributes-list.test b/clang/test/Misc/pragma-attribute-supported-attributes-list.test index 914f94c08a9fd..d5e8094ec6fe3 100644 --- a/clang/test/Misc/pragma-attribute-supported-attributes-list.test +++ b/clang/test/Misc/pragma-attribute-supported-attributes-list.test @@ -68,6 +68,7 @@ // CHECK-NEXT: CoroWrapper (SubjectMatchRule_function) // CHECK-NEXT: DLLExport (SubjectMatchRule_function, SubjectMatchRule_variable, SubjectMatchRule_record, SubjectMatchRule_objc_interface) // CHECK-NEXT: DLLImport (SubjectMatchRule_function, SubjectMatchRule_variable, SubjectMatchRule_record, SubjectMatchRule_objc_interface) +// CHECK-NEXT: DebugTransparent (SubjectMatchRule_function, SubjectMatchRule_objc_method) // CHECK-NEXT: Destructor (SubjectMatchRule_function) // CHECK-NEXT: DiagnoseAsBuiltin (SubjectMatchRule_function) // CHECK-NEXT: DisableSanitizerInstrumentation (SubjectMatchRule_function, SubjectMatchRule_objc_method, SubjectMatchRule_variable_is_global) diff --git a/clang/test/Sema/attr-debug-transparent.c b/clang/test/Sema/attr-debug-transparent.c new file mode 100644 index 0000000000000..98b2d4357a99e --- /dev/null +++ b/clang/test/Sema/attr-debug-transparent.c @@ -0,0 +1,7 @@ +// RUN: %clang_cc1 %s -verify -fsyntax-only + +__attribute__((debug_transparent)) +void correct(void) {} + +__attribute__((debug_transparent(1))) // expected-error {{'debug_transparent' attribute takes no arguments}} +void wrong_arg(void) {} diff --git a/clang/test/SemaCXX/attr-debug-transparent-method.cpp b/clang/test/SemaCXX/attr-debug-transparent-method.cpp new file mode 100644 index 0000000000000..b19da619742f4 --- /dev/null +++ b/clang/test/SemaCXX/attr-debug-transparent-method.cpp @@ -0,0 +1,11 @@ +// RUN: %clang_cc1 %s -verify -fsyntax-only + + +struct S { +[[clang::debug_transparent]] +void correct(void) {} + +[[clang::debug_transparent(1)]] // expected-error {{'debug_transparent' attribute takes no arguments}} +void one_arg(void) {} +}; + diff --git a/clang/test/SemaObjC/attr-debug-transparent-objc.m b/clang/test/SemaObjC/attr-debug-transparent-objc.m new file mode 100644 index 0000000000000..1fbde59ecb935 --- /dev/null +++ b/clang/test/SemaObjC/attr-debug-transparent-objc.m @@ -0,0 +1,9 @@ +// RUN: %clang_cc1 %s -verify -fsyntax-only + + + +@interface ObjCClass +- (void)correct __attribute__((debug_transparent)); +- (void)one_arg __attribute__((debug_transparent(1))); // expected-error {{'debug_transparent' attribute takes no arguments}} +@end + diff --git a/llvm/include/llvm/IR/DebugInfoFlags.def b/llvm/include/llvm/IR/DebugInfoFlags.def index df375b6c68e81..9903580fb9550 100644 --- a/llvm/include/llvm/IR/DebugInfoFlags.def +++ b/llvm/include/llvm/IR/DebugInfoFlags.def @@ -91,11 +91,12 @@ HANDLE_DISP_FLAG((1u << 8), MainSubprogram) // for defaulted functions HANDLE_DISP_FLAG((1u << 9), Deleted) HANDLE_DISP_FLAG((1u << 11), ObjCDirect) +HANDLE_DISP_FLAG((1u << 12), IsDebugTransparent) #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 << 11), Largest) +HANDLE_DISP_FLAG((1 << 12), Largest) #undef DISP_FLAG_LARGEST_NEEDED #endif diff --git a/llvm/include/llvm/IR/DebugInfoMetadata.h b/llvm/include/llvm/IR/DebugInfoMetadata.h index d2b4e900438d3..80d0c9e57b23d 100644 --- a/llvm/include/llvm/IR/DebugInfoMetadata.h +++ b/llvm/include/llvm/IR/DebugInfoMetadata.h @@ -1830,6 +1830,9 @@ class DISubprogram : public DILocalScope { bool isElemental() const { return getSPFlags() & SPFlagElemental; } bool isRecursive() const { return getSPFlags() & SPFlagRecursive; } bool isObjCDirect() const { return getSPFlags() & SPFlagObjCDirect; } + bool isDebugTransparent() const { + return getSPFlags() & SPFlagIsDebugTransparent; + } /// Check if this is deleted member function. /// diff --git a/llvm/lib/CodeGen/AsmPrinter/DwarfUnit.cpp b/llvm/lib/CodeGen/AsmPrinter/DwarfUnit.cpp index e76b0fe2081c0..bde716c862036 100644 --- a/llvm/lib/CodeGen/AsmPrinter/DwarfUnit.cpp +++ b/llvm/lib/CodeGen/AsmPrinter/DwarfUnit.cpp @@ -1260,6 +1260,9 @@ bool DwarfUnit::applySubprogramDefinitionAttributes(const DISubprogram *SP, (DD->useAllLinkageNames() || DU->getAbstractScopeDIEs().lookup(SP))) addLinkageName(SPDie, LinkageName); + if (SP->isDebugTransparent()) + addFlag(SPDie, dwarf::DW_AT_trampoline); + if (!DeclDie) return false; @@ -1378,6 +1381,8 @@ void DwarfUnit::applySubprogramAttributes(const DISubprogram *SP, DIE &SPDie, if (!SP->getTargetFuncName().empty()) addString(SPDie, dwarf::DW_AT_trampoline, SP->getTargetFuncName()); + else if (SP->isDebugTransparent()) + addFlag(SPDie, dwarf::DW_AT_trampoline); if (DD->getDwarfVersion() >= 5 && SP->isDeleted()) addFlag(SPDie, dwarf::DW_AT_deleted); diff --git a/llvm/test/Assembler/disubprogram-debug-transparent.ll b/llvm/test/Assembler/disubprogram-debug-transparent.ll new file mode 100644 index 0000000000000..316d6d367809c --- /dev/null +++ b/llvm/test/Assembler/disubprogram-debug-transparent.ll @@ -0,0 +1,39 @@ +; This test verifies that the DISPFlagIsDebugTransparent attribute in a DISubprogram +; is assembled/disassembled correctly. +; +; RUN: llvm-as < %s | llvm-dis | llvm-as | llvm-dis | FileCheck %s +; +; CHECK: !DISubprogram(name: "baz",{{.*}} DISPFlagIsDebugTransparent +; +; ModuleID = 't.c' +source_filename = "t.c" +target datalayout = "e-m:o-i64:64-i128:128-n32:64-S128" +target triple = "arm64-apple-macosx13.0.0" + +; Function Attrs: noinline nounwind optnone ssp uwtable(sync) +define void @baz() #0 !dbg !10 { +entry: + ret void, !dbg !14 +} + +attributes #0 = { noinline nounwind optnone ssp uwtable(sync) "frame-pointer"="non-leaf" "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-cpu"="apple-m1" "target-features"="+aes,+crc,+dotprod,+fp-armv8,+fp16fml,+fullfp16,+lse,+neon,+ras,+rcpc,+rdm,+sha2,+sha3,+v8.1a,+v8.2a,+v8.3a,+v8.4a,+v8.5a,+v8a,+zcm,+zcz" } + +!llvm.module.flags = !{!0, !1, !2, !3, !4, !5, !6} +!llvm.dbg.cu = !{!7} +!llvm.ident = !{!9} + +!0 = !{i32 2, !"SDK Version", [2 x i32] [i32 13, i32 2]} +!1 = !{i32 7, !"Dwarf Version", i32 4} +!2 = !{i32 2, !"Debug Info Version", i32 3} +!3 = !{i32 1, !"wchar_size", i32 4} +!4 = !{i32 8, !"PIC Level", i32 2} +!5 = !{i32 7, !"uwtable", i32 1} +!6 = !{i32 7, !"frame-pointer", i32 1} +!7 = distinct !DICompileUnit(language: DW_LANG_C11, file: !8, producer: "clang version 17.0.0", isOptimized: false, runtimeVersion: 0, emissionKind: FullDebug, splitDebugInlining: false, nameTableKind: None) +!8 = !DIFile(filename: "t.c", directory: "/") +!9 = !{!"clang version 17.0.0"} +!10 = distinct !DISubprogram(name: "baz", scope: !8, file: !8, line: 3, type: !11, scopeLine: 3, flags: DIFlagPrototyped, spFlags: DISPFlagDefinition | DISPFlagIsDebugTransparent, unit: !7, retainedNodes: !13) +!11 = !DISubroutineType(types: !12) +!12 = !{null} +!13 = !{} +!14 = !DILocation(line: 4, column: 1, scope: !10) diff --git a/llvm/test/DebugInfo/AArch64/disubprogram-debug-transparent.ll b/llvm/test/DebugInfo/AArch64/disubprogram-debug-transparent.ll new file mode 100644 index 0000000000000..65facbb4a3695 --- /dev/null +++ b/llvm/test/DebugInfo/AArch64/disubprogram-debug-transparent.ll @@ -0,0 +1,42 @@ +; This test verifies that the proper DWARF debug info is emitted +; for a trampoline function with no target. +; +; RUN: llc -filetype=obj %s -o - | llvm-dwarfdump - | FileCheck %s +; +; CHECK: DW_TAG_subprogram +; CHECK: DW_AT_name ("baz") +; CHECK: DW_AT_trampoline (true) +; +; ModuleID = 't.c' +source_filename = "t.c" +target datalayout = "e-m:o-i64:64-i128:128-n32:64-S128" +target triple = "arm64-apple-macosx13.0.0" + +; Function Attrs: noinline nounwind optnone ssp uwtable(sync) +define void @baz() #0 !dbg !10 { +entry: + ret void, !dbg !14 +} + +attributes #0 = { noinline nounwind optnone ssp uwtable(sync) "frame-pointer"="non-leaf" "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-cpu"="apple-m1" "target-features"="+aes,+crc,+dotprod,+fp-armv8,+fp16fml,+fullfp16,+lse,+neon,+ras,+rcpc,+rdm,+sha2,+sha3,+v8.1a,+v8.2a,+v8.3a,+v8.4a,+v8.5a,+v8a,+zcm,+zcz" } + +!llvm.module.flags = !{!0, !1, !2, !3, !4, !5, !6} +!llvm.dbg.cu = !{!7} +!llvm.ident = !{!9} + +!0 = !{i32 2, !"SDK Version", [2 x i32] [i32 13, i32 2]} +!1 = !{i32 7, !"Dwarf Version", i32 4} +!2 = !{i32 2, !"Debug Info Version", i32 3} +!3 = !{i32 1, !"wchar_size", i32 4} +!4 = !{i32 8, !"PIC Level", i32 2} +!5 = !{i32 7, !"uwtable", i32 1} +!6 = !{i32 7, !"frame-pointer", i32 1} +!7 = distinct !DICompileUnit(language: DW_LANG_C11, file: !8, producer: "clang version 17.0.0", isOptimized: false, runtimeVersion: 0, emissionKind: FullDebug, splitDebugInlining: false, nameTableKind: None) +!8 = !DIFile(filename: "t.c", directory: "/") +!9 = !{!"clang version 17.0.0"} +!10 = distinct !DISubprogram(name: "baz", scope: !8, file: !8, line: 3, type: !11, scopeLine: 3, flags: DIFlagPrototyped, spFlags: DISPFlagDefinition | DISPFlagIsDebugTransparent, unit: !7, retainedNodes: !13) +!11 = !DISubroutineType(types: !12) +!12 = !{null} +!13 = !{} +!14 = !DILocation(line: 4, column: 1, scope: !10) + diff --git a/llvm/unittests/IR/MetadataTest.cpp b/llvm/unittests/IR/MetadataTest.cpp index 778fd4d4994f4..dbe38aa323b38 100644 --- a/llvm/unittests/IR/MetadataTest.cpp +++ b/llvm/unittests/IR/MetadataTest.cpp @@ -2553,6 +2553,7 @@ TEST_F(DISubprogramTest, get) { assert(!IsLocalToUnit && IsDefinition && !IsOptimized && "bools and SPFlags have to match"); SPFlags |= DISubprogram::SPFlagDefinition; + SPFlags |= DISubprogram::SPFlagIsDebugTransparent; auto *N = DISubprogram::get( Context, Scope, Name, LinkageName, File, Line, Type, ScopeLine, @@ -2636,6 +2637,12 @@ TEST_F(DISubprogramTest, get) { Flags, SPFlags ^ DISubprogram::SPFlagDefinition, Unit, TemplateParams, Declaration, RetainedNodes, ThrownTypes, Annotations, TargetFuncName)); + EXPECT_NE(N, DISubprogram::get( + Context, Scope, Name, LinkageName, File, Line, Type, + ScopeLine, ContainingType, VirtualIndex, ThisAdjustment, + Flags, SPFlags ^ DISubprogram::SPFlagIsDebugTransparent, + Unit, TemplateParams, Declaration, RetainedNodes, + ThrownTypes, Annotations, TargetFuncName)); EXPECT_NE(N, DISubprogram::get(Context, Scope, Name, LinkageName, File, Line, Type, ScopeLine + 1, ContainingType, VirtualIndex, ThisAdjustment, Flags, SPFlags,