; REQUIRES: aarch64

; Here we test that if we defined a protocol MyTestProtocol and also a category MyTestProtocol
; then when merging the category into the base class (and deleting the category), we don't
; delete the 'MyTestProtocol' name

; RUN: llvm-mc -filetype=obj -triple=arm64-apple-macos -o erase-objc-name.o %s
; RUN: %lld -arch arm64 -dylib -o erase-objc-name.dylib erase-objc-name.o -objc_category_merging
; RUN: llvm-objdump --objc-meta-data --macho erase-objc-name.dylib | FileCheck %s --check-prefixes=MERGE_CATS

; === Check merge categories enabled ===
; Check that the original categories are not there
; MERGE_CATS-NOT: __OBJC_$_CATEGORY_MyBaseClass_$_Category01
; MERGE_CATS-NOT: __OBJC_$_CATEGORY_MyBaseClass_$_Category02

; Check that we get the expected output - most importantly that the protocol is named `MyTestProtocol`
; MERGE_CATS:        Contents of (__DATA_CONST,__objc_classlist) section
; MERGE_CATS-NEXT:   _OBJC_CLASS_$_MyBaseClass
; MERGE_CATS-NEXT:            isa {{.*}} _OBJC_METACLASS_$_MyBaseClass
; MERGE_CATS-NEXT:     superclass {{.*}}
; MERGE_CATS-NEXT:          cache {{.*}}
; MERGE_CATS-NEXT:         vtable {{.*}}
; MERGE_CATS-NEXT:           data {{.*}} (struct class_ro_t *)
; MERGE_CATS-NEXT:                     flags {{.*}} RO_ROOT
; MERGE_CATS-NEXT:             instanceStart 0
; MERGE_CATS-NEXT:              instanceSize 0
; MERGE_CATS-NEXT:                  reserved {{.*}}
; MERGE_CATS-NEXT:                ivarLayout {{.*}}
; MERGE_CATS-NEXT:                      name {{.*}} MyBaseClass
; MERGE_CATS-NEXT:               baseMethods {{.*}} (struct method_list_t *)
; MERGE_CATS-NEXT:             entsize 24
; MERGE_CATS-NEXT:               count 2
; MERGE_CATS-NEXT:                name {{.*}} getValue
; MERGE_CATS-NEXT:               types {{.*}} i16@0:8
; MERGE_CATS-NEXT:                 imp -[MyBaseClass(MyTestProtocol) getValue]
; MERGE_CATS-NEXT:                name {{.*}} baseInstanceMethod
; MERGE_CATS-NEXT:               types {{.*}} v16@0:8
; MERGE_CATS-NEXT:                 imp -[MyBaseClass baseInstanceMethod]
; MERGE_CATS-NEXT:             baseProtocols {{.*}}
; MERGE_CATS-NEXT:                       count 1
; MERGE_CATS-NEXT:                list[0] {{.*}} (struct protocol_t *)
; MERGE_CATS-NEXT:                       isa {{.*}}
; MERGE_CATS-NEXT:                      name {{.*}} MyTestProtocol
; MERGE_CATS-NEXT:                 protocols {{.*}}
; MERGE_CATS-NEXT:            instanceMethods {{.*}} (struct method_list_t *)
; MERGE_CATS-NEXT:                    entsize 24
; MERGE_CATS-NEXT:                      count 1
; MERGE_CATS-NEXT:                       name {{.*}} getValue
; MERGE_CATS-NEXT:                      types {{.*}} i16@0:8
; MERGE_CATS-NEXT:                        imp {{.*}}
; MERGE_CATS-NEXT:               classMethods {{.*}} (struct method_list_t *)
; MERGE_CATS-NEXT:     optionalInstanceMethods {{.*}}
; MERGE_CATS-NEXT:        optionalClassMethods {{.*}}
; MERGE_CATS-NEXT:          instanceProperties {{.*}}
; MERGE_CATS-NEXT:                     ivars {{.*}}
; MERGE_CATS-NEXT:            weakIvarLayout {{.*}}
; MERGE_CATS-NEXT:            baseProperties {{.*}}
; MERGE_CATS-NEXT: Meta Class
; MERGE_CATS-NEXT:            isa {{.*}} _OBJC_METACLASS_$_MyBaseClass
; MERGE_CATS-NEXT:     superclass {{.*}} _OBJC_CLASS_$_MyBaseClass
; MERGE_CATS-NEXT:          cache {{.*}}
; MERGE_CATS-NEXT:         vtable {{.*}}
; MERGE_CATS-NEXT:           data {{.*}} (struct class_ro_t *)
; MERGE_CATS-NEXT:                     flags {{.*}} RO_META RO_ROOT
; MERGE_CATS-NEXT:             instanceStart 40
; MERGE_CATS-NEXT:              instanceSize 40
; MERGE_CATS-NEXT:                  reserved {{.*}}
; MERGE_CATS-NEXT:                ivarLayout {{.*}}
; MERGE_CATS-NEXT:                      name {{.*}} MyBaseClass
; MERGE_CATS-NEXT:               baseMethods {{.*}} (struct method_list_t *)
; MERGE_CATS-NEXT:             baseProtocols {{.*}}
; MERGE_CATS-NEXT:                       count 1
; MERGE_CATS-NEXT:                list[0] {{.*}} (struct protocol_t *)
; MERGE_CATS-NEXT:                       isa {{.*}}
; MERGE_CATS-NEXT:                      name {{.*}} MyTestProtocol
; MERGE_CATS-NEXT:                 protocols {{.*}}
; MERGE_CATS-NEXT:            instanceMethods {{.*}} (struct method_list_t *)
; MERGE_CATS-NEXT:                    entsize 24
; MERGE_CATS-NEXT:                      count 1
; MERGE_CATS-NEXT:                       name {{.*}} getValue
; MERGE_CATS-NEXT:                      types {{.*}} i16@0:8
; MERGE_CATS-NEXT:                        imp {{.*}}
; MERGE_CATS-NEXT:               classMethods {{.*}} (struct method_list_t *)
; MERGE_CATS-NEXT:     optionalInstanceMethods {{.*}}
; MERGE_CATS-NEXT:        optionalClassMethods {{.*}}
; MERGE_CATS-NEXT:          instanceProperties {{.*}}
; MERGE_CATS-NEXT:                     ivars {{.*}}
; MERGE_CATS-NEXT:            weakIvarLayout {{.*}}
; MERGE_CATS-NEXT:            baseProperties {{.*}}
; MERGE_CATS-NEXT: Contents of (__DATA_CONST,__objc_protolist) section
; MERGE_CATS-NEXT: {{.*}} {{.*}} __OBJC_PROTOCOL_$_MyTestProtocol
; MERGE_CATS-NEXT: Contents of (__DATA_CONST,__objc_imageinfo) section
; MERGE_CATS-NEXT:   version 0
; MERGE_CATS-NEXT:     flags {{.*}} OBJC_IMAGE_HAS_CATEGORY_CLASS_PROPERTIES


; ================== repro.sh ====================
; # Write the Objective-C code to a file
; cat << EOF > MyClass.m
; @protocol MyTestProtocol
; - (int)getValue;
; @end
;
; __attribute__((objc_root_class))
; @interface MyBaseClass
; - (void)baseInstanceMethod;
; @end
;
; @implementation MyBaseClass
; - (void)baseInstanceMethod {}
; @end
;
; @interface MyBaseClass (MyTestProtocol) <MyTestProtocol>
; @end
;
; @implementation MyBaseClass (MyTestProtocol)
;
; - (int)getValue {
;     return 0x30;
; }
;
; @end
; EOF
;
; # Compile the Objective-C file to assembly
; xcrun clang -S -arch arm64 MyClass.m -o MyClass.s
; ==============================================


       .section      __TEXT,__text,regular,pure_instructions
       .p2align      2                               ; -- Begin function -[MyBaseClass baseInstanceMethod]
"-[MyBaseClass baseInstanceMethod]":    ; @"\01-[MyBaseClass baseInstanceMethod]"
       .cfi_startproc
; %bb.0:
       sub    sp, sp, #16
       .cfi_def_cfa_offset 16
       str    x0, [sp, #8]
       str    x1, [sp]
       add    sp, sp, #16
       ret
       .cfi_endproc
                                        ; -- End function
       .p2align      2                               ; -- Begin function -[MyBaseClass(MyTestProtocol) getValue]
"-[MyBaseClass(MyTestProtocol) getValue]": ; @"\01-[MyBaseClass(MyTestProtocol) getValue]"
       .cfi_startproc
; %bb.0:
       sub    sp, sp, #16
       .cfi_def_cfa_offset 16
       str    x0, [sp, #8]
       str    x1, [sp]
       mov    w0, #48                         ; =0x30
       add    sp, sp, #16
       ret
       .cfi_endproc
                                        ; -- End function
       .section      __DATA,__objc_data
       .globl _OBJC_CLASS_$_MyBaseClass       ; @"OBJC_CLASS_$_MyBaseClass"
       .p2align      3, 0x0
_OBJC_CLASS_$_MyBaseClass:
       .quad  _OBJC_METACLASS_$_MyBaseClass
       .quad  0
       .quad  __objc_empty_cache
       .quad  0
       .quad  __OBJC_CLASS_RO_$_MyBaseClass
       .globl _OBJC_METACLASS_$_MyBaseClass   ; @"OBJC_METACLASS_$_MyBaseClass"
       .p2align      3, 0x0
_OBJC_METACLASS_$_MyBaseClass:
       .quad  _OBJC_METACLASS_$_MyBaseClass
       .quad  _OBJC_CLASS_$_MyBaseClass
       .quad  __objc_empty_cache
       .quad  0
       .quad  __OBJC_METACLASS_RO_$_MyBaseClass
       .section      __TEXT,__objc_classname,cstring_literals
l_OBJC_CLASS_NAME_:                     ; @OBJC_CLASS_NAME_
       .asciz "MyBaseClass"
       .section      __DATA,__objc_const
       .p2align      3, 0x0                          ; @"_OBJC_METACLASS_RO_$_MyBaseClass"
__OBJC_METACLASS_RO_$_MyBaseClass:
       .long  131                             ; 0x83
       .long  40                              ; 0x28
       .long  40                              ; 0x28
       .space 4
       .quad  0
       .quad  l_OBJC_CLASS_NAME_
       .quad  0
       .quad  0
       .quad  0
       .quad  0
       .quad  0
       .section      __TEXT,__objc_methname,cstring_literals
l_OBJC_METH_VAR_NAME_:                  ; @OBJC_METH_VAR_NAME_
       .asciz "baseInstanceMethod"
       .section      __TEXT,__objc_methtype,cstring_literals
l_OBJC_METH_VAR_TYPE_:                  ; @OBJC_METH_VAR_TYPE_
       .asciz "v16@0:8"
       .section      __DATA,__objc_const
       .p2align      3, 0x0                          ; @"_OBJC_$_INSTANCE_METHODS_MyBaseClass"
__OBJC_$_INSTANCE_METHODS_MyBaseClass:
       .long  24                              ; 0x18
       .long  1                               ; 0x1
       .quad  l_OBJC_METH_VAR_NAME_
       .quad  l_OBJC_METH_VAR_TYPE_
       .quad  "-[MyBaseClass baseInstanceMethod]"
       .p2align      3, 0x0                          ; @"_OBJC_CLASS_RO_$_MyBaseClass"
__OBJC_CLASS_RO_$_MyBaseClass:
       .long  130                             ; 0x82
       .long  0                               ; 0x0
       .long  0                               ; 0x0
       .space 4
       .quad  0
       .quad  l_OBJC_CLASS_NAME_
       .quad  __OBJC_$_INSTANCE_METHODS_MyBaseClass
       .quad  0
       .quad  0
       .quad  0
       .quad  0
       .section      __TEXT,__objc_classname,cstring_literals
l_OBJC_CLASS_NAME_.1:                   ; @OBJC_CLASS_NAME_.1
       .asciz "MyTestProtocol"
       .section      __TEXT,__objc_methname,cstring_literals
l_OBJC_METH_VAR_NAME_.2:                ; @OBJC_METH_VAR_NAME_.2
       .asciz "getValue"
       .section      __TEXT,__objc_methtype,cstring_literals
l_OBJC_METH_VAR_TYPE_.3:                ; @OBJC_METH_VAR_TYPE_.3
       .asciz "i16@0:8"
       .section      __DATA,__objc_const
       .p2align      3, 0x0                          ; @"_OBJC_$_CATEGORY_INSTANCE_METHODS_MyBaseClass_$_MyTestProtocol"
__OBJC_$_CATEGORY_INSTANCE_METHODS_MyBaseClass_$_MyTestProtocol:
       .long  24                              ; 0x18
       .long  1                               ; 0x1
       .quad  l_OBJC_METH_VAR_NAME_.2
       .quad  l_OBJC_METH_VAR_TYPE_.3
       .quad  "-[MyBaseClass(MyTestProtocol) getValue]"
       .p2align      3, 0x0                          ; @"_OBJC_$_PROTOCOL_INSTANCE_METHODS_MyTestProtocol"
__OBJC_$_PROTOCOL_INSTANCE_METHODS_MyTestProtocol:
       .long  24                              ; 0x18
       .long  1                               ; 0x1
       .quad  l_OBJC_METH_VAR_NAME_.2
       .quad  l_OBJC_METH_VAR_TYPE_.3
       .quad  0
       .p2align      3, 0x0                          ; @"_OBJC_$_PROTOCOL_METHOD_TYPES_MyTestProtocol"
__OBJC_$_PROTOCOL_METHOD_TYPES_MyTestProtocol:
       .quad  l_OBJC_METH_VAR_TYPE_.3
       .private_extern      __OBJC_PROTOCOL_$_MyTestProtocol ; @"_OBJC_PROTOCOL_$_MyTestProtocol"
       .section      __DATA,__data
       .globl __OBJC_PROTOCOL_$_MyTestProtocol
       .weak_definition     __OBJC_PROTOCOL_$_MyTestProtocol
       .p2align      3, 0x0
__OBJC_PROTOCOL_$_MyTestProtocol:
       .quad  0
       .quad  l_OBJC_CLASS_NAME_.1
       .quad  0
       .quad  __OBJC_$_PROTOCOL_INSTANCE_METHODS_MyTestProtocol
       .quad  0
       .quad  0
       .quad  0
       .quad  0
       .long  96                              ; 0x60
       .long  0                               ; 0x0
       .quad  __OBJC_$_PROTOCOL_METHOD_TYPES_MyTestProtocol
       .quad  0
       .quad  0
       .private_extern      __OBJC_LABEL_PROTOCOL_$_MyTestProtocol ; @"_OBJC_LABEL_PROTOCOL_$_MyTestProtocol"
       .section      __DATA,__objc_protolist,coalesced,no_dead_strip
       .globl __OBJC_LABEL_PROTOCOL_$_MyTestProtocol
       .weak_definition     __OBJC_LABEL_PROTOCOL_$_MyTestProtocol
       .p2align      3, 0x0
__OBJC_LABEL_PROTOCOL_$_MyTestProtocol:
       .quad  __OBJC_PROTOCOL_$_MyTestProtocol
       .section      __DATA,__objc_const
       .p2align      3, 0x0                          ; @"_OBJC_CATEGORY_PROTOCOLS_$_MyBaseClass_$_MyTestProtocol"
__OBJC_CATEGORY_PROTOCOLS_$_MyBaseClass_$_MyTestProtocol:
       .quad  1                               ; 0x1
       .quad  __OBJC_PROTOCOL_$_MyTestProtocol
       .quad  0
       .p2align      3, 0x0                          ; @"_OBJC_$_CATEGORY_MyBaseClass_$_MyTestProtocol"
__OBJC_$_CATEGORY_MyBaseClass_$_MyTestProtocol:
       .quad  l_OBJC_CLASS_NAME_.1
       .quad  _OBJC_CLASS_$_MyBaseClass
       .quad  __OBJC_$_CATEGORY_INSTANCE_METHODS_MyBaseClass_$_MyTestProtocol
       .quad  0
       .quad  __OBJC_CATEGORY_PROTOCOLS_$_MyBaseClass_$_MyTestProtocol
       .quad  0
       .quad  0
       .long  64                              ; 0x40
       .space 4
       .section      __DATA,__objc_classlist,regular,no_dead_strip
       .p2align      3, 0x0                          ; @"OBJC_LABEL_CLASS_$"
l_OBJC_LABEL_CLASS_$:
       .quad  _OBJC_CLASS_$_MyBaseClass
       .section      __DATA,__objc_catlist,regular,no_dead_strip
       .p2align      3, 0x0                          ; @"OBJC_LABEL_CATEGORY_$"
l_OBJC_LABEL_CATEGORY_$:
       .quad  __OBJC_$_CATEGORY_MyBaseClass_$_MyTestProtocol
       .no_dead_strip       __OBJC_PROTOCOL_$_MyTestProtocol
       .no_dead_strip       __OBJC_LABEL_PROTOCOL_$_MyTestProtocol
       .section      __DATA,__objc_imageinfo,regular,no_dead_strip
L_OBJC_IMAGE_INFO:
       .long  0
       .long  64

__objc_empty_cache:
_$sBOWV:
  .quad 0

.subsections_via_symbols
