Skip to content

Commit

Permalink
Fixes #2715.
Browse files Browse the repository at this point in the history
  • Loading branch information
remexre committed Jan 12, 2024
1 parent d0c2b1e commit fb72abf
Show file tree
Hide file tree
Showing 3 changed files with 50 additions and 24 deletions.
8 changes: 8 additions & 0 deletions bindgen-tests/tests/expectations/tests/noreturn.rs

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 2 additions & 0 deletions bindgen-tests/tests/headers/noreturn.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -2,3 +2,5 @@
_Noreturn void f(void);
__attribute__((noreturn)) void g(void);
[[noreturn]] void h(void);
void i(__attribute__((noreturn)) void (*arg)(void));
__attribute__((noreturn)) void j(__attribute__((noreturn)) void (*arg)(void));
64 changes: 40 additions & 24 deletions bindgen/ir/function.rs
Original file line number Diff line number Diff line change
Expand Up @@ -435,8 +435,8 @@ impl FunctionSig {

// Don't parse operatorxx functions in C++
let is_operator = |spelling: &str| {
spelling.starts_with("operator") &&
!clang::is_valid_identifier(spelling)
spelling.starts_with("operator")
&& !clang::is_valid_identifier(spelling)
};
if is_operator(&spelling) {
return Err(ParseError::Continue);
Expand All @@ -445,8 +445,8 @@ impl FunctionSig {
// Constructors of non-type template parameter classes for some reason
// include the template parameter in their name. Just skip them, since
// we don't handle well non-type template parameters anyway.
if (kind == CXCursor_Constructor || kind == CXCursor_Destructor) &&
spelling.contains('<')
if (kind == CXCursor_Constructor || kind == CXCursor_Destructor)
&& spelling.contains('<')
{
return Err(ParseError::Continue);
}
Expand All @@ -458,11 +458,11 @@ impl FunctionSig {
};

let mut args = match kind {
CXCursor_FunctionDecl |
CXCursor_Constructor |
CXCursor_CXXMethod |
CXCursor_ObjCInstanceMethodDecl |
CXCursor_ObjCClassMethodDecl => {
CXCursor_FunctionDecl
| CXCursor_Constructor
| CXCursor_CXXMethod
| CXCursor_ObjCInstanceMethodDecl
| CXCursor_ObjCClassMethodDecl => {
args_from_ty_and_cursor(ty, &cursor, ctx)
}
_ => {
Expand Down Expand Up @@ -505,16 +505,32 @@ impl FunctionSig {
Default::default()
};

// This looks easy to break but the clang parser keeps the type spelling clean even if
// other attributes are added.
is_divergent =
is_divergent || ty.spelling().contains("__attribute__((noreturn))");
// Check if the type contains __attribute__((noreturn)) outside of parentheses. This is
// somewhat fragile, but it seems to be the only way to get at this information as of
// libclang 9.
let ty_spelling = ty.spelling();
let has_attribute_noreturn = ty_spelling
.match_indices("__attribute__((noreturn))")
.filter(|&(i, _)| {
let depth = ty_spelling[..i]
.bytes()
.filter_map(|ch| match ch {
b'(' => Some(1),
b')' => Some(-1),
_ => None,
})
.sum::<isize>();
depth == 0
})
.next()
.is_some();
is_divergent = is_divergent || has_attribute_noreturn;

let is_method = kind == CXCursor_CXXMethod;
let is_constructor = kind == CXCursor_Constructor;
let is_destructor = kind == CXCursor_Destructor;
if (is_constructor || is_destructor || is_method) &&
cursor.lexical_parent() != cursor.semantic_parent()
if (is_constructor || is_destructor || is_method)
&& cursor.lexical_parent() != cursor.semantic_parent()
{
// Only parse constructors once.
return Err(ParseError::Continue);
Expand Down Expand Up @@ -555,8 +571,8 @@ impl FunctionSig {
}
}

let ty_ret_type = if kind == CXCursor_ObjCInstanceMethodDecl ||
kind == CXCursor_ObjCClassMethodDecl
let ty_ret_type = if kind == CXCursor_ObjCInstanceMethodDecl
|| kind == CXCursor_ObjCClassMethodDecl
{
ty.ret_type()
.or_else(|| cursor.ret_type())
Expand Down Expand Up @@ -734,13 +750,13 @@ impl ClangSubItemParser for Function {
_ => return Err(ParseError::Continue),
};

if cursor.is_inlined_function() ||
cursor
if cursor.is_inlined_function()
|| cursor
.definition()
.map_or(false, |x| x.is_inlined_function())
{
if !context.options().generate_inline_functions &&
!context.options().wrap_static_fns
if !context.options().generate_inline_functions
&& !context.options().wrap_static_fns
{
return Err(ParseError::Continue);
}
Expand All @@ -750,9 +766,9 @@ impl ClangSubItemParser for Function {
}

// We cannot handle `inline` functions that are not `static`.
if context.options().wrap_static_fns &&
cursor.is_inlined_function() &&
matches!(linkage, Linkage::External)
if context.options().wrap_static_fns
&& cursor.is_inlined_function()
&& matches!(linkage, Linkage::External)
{
return Err(ParseError::Continue);
}
Expand Down

0 comments on commit fb72abf

Please sign in to comment.