Repository: rust-lang/rust-bindgen (rust)

Issue:
"invalid identifier" when clang targets obj-c
### Input Obj-C Header

```obj-c
//
//  HapticIFace.h
//  rusttest
//
//  Created by user on 4/6/23.
//

#ifndef HapticIFace_h
#define HapticIFace_h

#import <CoreHaptics/CoreHaptics.h>

@interface HapticIFace : NSObject       {
}

@property (nonatomic, strong) CHHapticEngine* engine;

@end

#endif /* HapticIFace_h */
```
This is here as a placeholder since it was the last file I tried. Any file causes this error.

### Bindgen Invocation


```
bindgen ./HapticIFace.h -- -target arm64-apple-ios -x objective-c -isysroot /Users/user/Downloads/Xcode.app/Contents/Developer/Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS.sdk
```


### Actual Results

```
panicked at 'Invalid identifier: Error("expected identifier")', /Users/user/.cargo/registry/src/github.com-x/bindgen-0.64.0/ir/objc.rs:272:30
```

### Expected Results

Unknown

===

This error happens on all files I use w/ objective-c.

I mistakenly [attached](https://github.com/rust-lang/rust-bindgen/issues/2029#issuecomment-1496556695) this onto issue #2029. 
There, I'd used a premade command courtesy of @.simlay: https://simlay.net/posts/rust-bindgen-objc-support/#adding-a-build-rs . I modified it to the correct paths for my usecase and ran that build.rs using `cargo` and had the same issue.

Importantly, if I put a random file in, it goes through that file and obviously detects syntax errors. Perhaps the issue happening here comes after the file is processed? I ran with `RUST_BACKTRACE=1` and there was no difference in the error message, and I also am currently running with `RUST_LOG=bindgen`. It's been going for about fifteen minutes but it's getting slower as more stuff gets printed. It's definitely working with the code given, so I think whatever the issue is is happening after the ir is generated.

Pull request description:
Fix escaping for objective-C identifiers
Fixes #2486


Patch:
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 1317f8fe..46872f6f 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -176,6 +176,9 @@
   the `incorrect_clone_impl_on_copy_type` Clippy lint.
 ## Removed
 ## Fixed
+- Bindgen no longer panics when parsing an objective-C header that includes a
+  Rust keyword that cannot be a raw identifier, such as: `self`, `crate`,
+  `super` or `Self`.
 ## Security
 
 # 0.66.1
diff --git a/bindgen/ir/objc.rs b/bindgen/ir/objc.rs
index eaf3b8a5..2ebf38b8 100644
--- a/bindgen/ir/objc.rs
+++ b/bindgen/ir/objc.rs
@@ -257,15 +257,21 @@ impl ObjCMethod {
                 if name.is_empty() {
                     None
                 } else {
-                    // Try to parse the current name as an identifier. This might fail if the
-                    // name is a keyword so we try to prepend "r#" to it and parse again. If
-                    // this also fails, we panic with the first error.
+                    // Try to parse the current name as an identifier. This might fail if the name
+                    // is a keyword, so we try to  "r#" to it and parse again, this could also fail
+                    // if the name is `crate`, `self`, `super` or `Self`, so we try to add the `_`
+                    // suffix to it and parse again. If this also fails, we panic with the first
+                    // error.
                     Some(
                         syn::parse_str::<Ident>(name)
                             .or_else(|err| {
                                 syn::parse_str::<Ident>(&format!("r#{}", name))
                                     .map_err(|_| err)
                             })
+                            .or_else(|err| {
+                                syn::parse_str::<Ident>(&format!("{}_", name))
+                                    .map_err(|_| err)
+                            })
                             .expect("Invalid identifier"),
                     )
                 }


Test patch:
diff --git a/bindgen-tests/tests/expectations/tests/objc_escape.rs b/bindgen-tests/tests/expectations/tests/objc_escape.rs
index f0ddcc15..abf8df60 100644
--- a/bindgen-tests/tests/expectations/tests/objc_escape.rs
+++ b/bindgen-tests/tests/expectations/tests/objc_escape.rs
@@ -26,4 +26,10 @@ pub trait IA: Sized + std::ops::Deref {
     {
         msg_send!(* self, f : arg1 r#as : arg2)
     }
+    unsafe fn crate_(&self, self_: ::std::os::raw::c_int)
+    where
+        <Self as std::ops::Deref>::Target: objc::Message + Sized,
+    {
+        msg_send!(* self, crate_ : self_)
+    }
 }
diff --git a/bindgen-tests/tests/headers/objc_escape.h b/bindgen-tests/tests/headers/objc_escape.h
index 184d1da8..6b52e745 100644
--- a/bindgen-tests/tests/headers/objc_escape.h
+++ b/bindgen-tests/tests/headers/objc_escape.h
@@ -3,4 +3,5 @@
 
 @interface A
 -(void)f:(int)arg1 as:(int)arg2;
+-(void)crate:(int)self;
 @end