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

Issue:
_Atomic crashes bindgen even when blocklisted
<!-- Thanks for filing a bindgen issue! We appreciate it :-) -->

### Input C/C++ Header
```C++
_Atomic(int) a;
int b;
```

### Bindgen Invocation
```
$ bindgen --blocklist-item "a" input.h
```

### Actual Results

```
$ RUST_BACKTRACE=1 bindgen --blocklist-item "a" input.h
panicked at /home/kriskras99/.cargo/registry/src/index.crates.io-6f17d22bba15001f/bindgen-0.70.1/ir/var.rs:319:25:
Couldn't resolve constant type, and it wasn't an nondeductible auto type or unexposed type!
panicked at core/src/panicking.rs:221:5:
panic in a function that cannot unwind
thread caused non-unwinding panic. aborting.
[1]    21518 IOT instruction (core dumped)  RUST_BACKTRACE=1 bindgen --blocklist-item "a" input.h
```

### Expected Results
I expect bindgen to ignore the `_Atomic` type as it is on a blocklist:
```rust
/* automatically generated by rust-bindgen 0.70.1 */

extern "C" {
    pub static mut b: ::std::os::raw::c_int;
}
```
In addition, I think the panic message is confusing and should be more like  "_Atomic types are not supported" or something similar.

Pull request:
ir: Dig into atomic types.
Fixes #2920

Patch:
diff --git a/bindgen/Cargo.toml b/bindgen/Cargo.toml
index 9eddd515..1c19cc35 100644
--- a/bindgen/Cargo.toml
+++ b/bindgen/Cargo.toml
@@ -28,7 +28,7 @@ path = "lib.rs"
 annotate-snippets = { version = "0.9.1", features = ["color"], optional = true }
 bitflags = "2.2.1"
 cexpr = "0.6"
-clang-sys = { version = "1", features = ["clang_6_0"] }
+clang-sys = { version = "1", features = ["clang_11_0"] }
 itertools = { version = ">=0.10,<0.14", default-features = false }
 log = { version = "0.4", optional = true }
 prettyplease = { version = "0.2.7", optional = true, features = ["verbatim"] }
diff --git a/bindgen/clang.rs b/bindgen/clang.rs
index 47c7b170..e585fb31 100644
--- a/bindgen/clang.rs
+++ b/bindgen/clang.rs
@@ -1493,6 +1493,15 @@ impl Type {
         }
     }
 
+    /// For atomic types, get the underlying type.
+    pub(crate) fn atomic_value_type(&self) -> Type {
+        unsafe {
+            Type {
+                x: clang_Type_getValueType(self.x),
+            }
+        }
+    }
+
     /// Is this a valid type?
     pub(crate) fn is_valid(&self) -> bool {
         self.kind() != CXType_Invalid
diff --git a/bindgen/ir/ty.rs b/bindgen/ir/ty.rs
index 2a24dd02..6d4c5666 100644
--- a/bindgen/ir/ty.rs
+++ b/bindgen/ir/ty.rs
@@ -1167,6 +1167,18 @@ impl Type {
                     .expect("Not able to resolve array element?");
                     TypeKind::Array(inner, ty.num_elements().unwrap())
                 }
+                CXType_Atomic => {
+                    // TODO(emilio): Maybe we can preserve the "is atomic" bit somehow and generate
+                    // something more useful... But for now this is better than panicking or
+                    // generating nothing.
+                    return Self::from_clang_ty(
+                        potential_id,
+                        &ty.atomic_value_type(),
+                        location,
+                        parent_id,
+                        ctx,
+                    );
+                }
                 CXType_Elaborated => {
                     return Self::from_clang_ty(
                         potential_id,
diff --git a/bindgen/ir/var.rs b/bindgen/ir/var.rs
index 40a061e1..b8fffc7d 100644
--- a/bindgen/ir/var.rs
+++ b/bindgen/ir/var.rs
@@ -320,7 +320,8 @@ impl ClangSubItemParser for Var {
                             matches!(ty.kind(), CXType_Auto | CXType_Unexposed),
                             "Couldn't resolve constant type, and it \
                              wasn't an nondeductible auto type or unexposed \
-                             type!"
+                             type: {:?}",
+                            ty
                         );
                         return Err(e);
                     }


Test patch:
diff --git a/bindgen-tests/tests/expectations/tests/atomic-constant.rs b/bindgen-tests/tests/expectations/tests/atomic-constant.rs
new file mode 100644
index 00000000..bd3c1869
--- /dev/null
+++ b/bindgen-tests/tests/expectations/tests/atomic-constant.rs
@@ -0,0 +1,7 @@
+#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)]
+extern "C" {
+    pub static mut a: ::std::os::raw::c_int;
+}
+extern "C" {
+    pub static mut b: ::std::os::raw::c_int;
+}
diff --git a/bindgen-tests/tests/expectations/tests/libclang-9/atomic-constant.rs b/bindgen-tests/tests/expectations/tests/libclang-9/atomic-constant.rs
new file mode 100644
index 00000000..ce12eaad
--- /dev/null
+++ b/bindgen-tests/tests/expectations/tests/libclang-9/atomic-constant.rs
@@ -0,0 +1,4 @@
+#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)]
+extern "C" {
+    pub static mut b: ::std::os::raw::c_int;
+}
diff --git a/bindgen-tests/tests/headers/atomic-constant.h b/bindgen-tests/tests/headers/atomic-constant.h
new file mode 100644
index 00000000..b28f76f7
--- /dev/null
+++ b/bindgen-tests/tests/headers/atomic-constant.h
@@ -0,0 +1,2 @@
+_Atomic(int) a;
+int b;