Skip to content

Commit 8fffbf8

Browse files
Nathan Ringoemilio
Nathan Ringo
authored andcommitted
Fixes #2715.
1 parent 11aeae4 commit 8fffbf8

File tree

3 files changed

+28
-4
lines changed

3 files changed

+28
-4
lines changed

Diff for: bindgen-tests/tests/expectations/tests/noreturn.rs

+8
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Diff for: bindgen-tests/tests/headers/noreturn.hpp

+2
Original file line numberDiff line numberDiff line change
@@ -2,3 +2,5 @@
22
_Noreturn void f(void);
33
__attribute__((noreturn)) void g(void);
44
[[noreturn]] void h(void);
5+
void i(__attribute__((noreturn)) void (*arg)(void));
6+
__attribute__((noreturn)) void j(__attribute__((noreturn)) void (*arg)(void));

Diff for: bindgen/ir/function.rs

+18-4
Original file line numberDiff line numberDiff line change
@@ -505,10 +505,24 @@ impl FunctionSig {
505505
Default::default()
506506
};
507507

508-
// This looks easy to break but the clang parser keeps the type spelling clean even if
509-
// other attributes are added.
510-
is_divergent =
511-
is_divergent || ty.spelling().contains("__attribute__((noreturn))");
508+
// Check if the type contains __attribute__((noreturn)) outside of parentheses. This is
509+
// somewhat fragile, but it seems to be the only way to get at this information as of
510+
// libclang 9.
511+
let ty_spelling = ty.spelling();
512+
let has_attribute_noreturn = ty_spelling
513+
.match_indices("__attribute__((noreturn))")
514+
.any(|(i, _)| {
515+
let depth = ty_spelling[..i]
516+
.bytes()
517+
.filter_map(|ch| match ch {
518+
b'(' => Some(1),
519+
b')' => Some(-1),
520+
_ => None,
521+
})
522+
.sum::<isize>();
523+
depth == 0
524+
});
525+
is_divergent = is_divergent || has_attribute_noreturn;
512526

513527
let is_method = kind == CXCursor_CXXMethod;
514528
let is_constructor = kind == CXCursor_Constructor;

0 commit comments

Comments
 (0)