@@ -435,8 +435,8 @@ impl FunctionSig {
435
435
436
436
// Don't parse operatorxx functions in C++
437
437
let is_operator = |spelling : & str | {
438
- spelling. starts_with ( "operator" ) &&
439
- !clang:: is_valid_identifier ( spelling)
438
+ spelling. starts_with ( "operator" )
439
+ && !clang:: is_valid_identifier ( spelling)
440
440
} ;
441
441
if is_operator ( & spelling) {
442
442
return Err ( ParseError :: Continue ) ;
@@ -445,8 +445,8 @@ impl FunctionSig {
445
445
// Constructors of non-type template parameter classes for some reason
446
446
// include the template parameter in their name. Just skip them, since
447
447
// we don't handle well non-type template parameters anyway.
448
- if ( kind == CXCursor_Constructor || kind == CXCursor_Destructor ) &&
449
- spelling. contains ( '<' )
448
+ if ( kind == CXCursor_Constructor || kind == CXCursor_Destructor )
449
+ && spelling. contains ( '<' )
450
450
{
451
451
return Err ( ParseError :: Continue ) ;
452
452
}
@@ -458,11 +458,11 @@ impl FunctionSig {
458
458
} ;
459
459
460
460
let mut args = match kind {
461
- CXCursor_FunctionDecl |
462
- CXCursor_Constructor |
463
- CXCursor_CXXMethod |
464
- CXCursor_ObjCInstanceMethodDecl |
465
- CXCursor_ObjCClassMethodDecl => {
461
+ CXCursor_FunctionDecl
462
+ | CXCursor_Constructor
463
+ | CXCursor_CXXMethod
464
+ | CXCursor_ObjCInstanceMethodDecl
465
+ | CXCursor_ObjCClassMethodDecl => {
466
466
args_from_ty_and_cursor ( ty, & cursor, ctx)
467
467
}
468
468
_ => {
@@ -505,16 +505,32 @@ impl FunctionSig {
505
505
Default :: default ( )
506
506
} ;
507
507
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
+ . filter ( |& ( 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
+ . next ( )
526
+ . is_some ( ) ;
527
+ is_divergent = is_divergent || has_attribute_noreturn;
512
528
513
529
let is_method = kind == CXCursor_CXXMethod ;
514
530
let is_constructor = kind == CXCursor_Constructor ;
515
531
let is_destructor = kind == CXCursor_Destructor ;
516
- if ( is_constructor || is_destructor || is_method) &&
517
- cursor. lexical_parent ( ) != cursor. semantic_parent ( )
532
+ if ( is_constructor || is_destructor || is_method)
533
+ && cursor. lexical_parent ( ) != cursor. semantic_parent ( )
518
534
{
519
535
// Only parse constructors once.
520
536
return Err ( ParseError :: Continue ) ;
@@ -555,8 +571,8 @@ impl FunctionSig {
555
571
}
556
572
}
557
573
558
- let ty_ret_type = if kind == CXCursor_ObjCInstanceMethodDecl ||
559
- kind == CXCursor_ObjCClassMethodDecl
574
+ let ty_ret_type = if kind == CXCursor_ObjCInstanceMethodDecl
575
+ || kind == CXCursor_ObjCClassMethodDecl
560
576
{
561
577
ty. ret_type ( )
562
578
. or_else ( || cursor. ret_type ( ) )
@@ -734,13 +750,13 @@ impl ClangSubItemParser for Function {
734
750
_ => return Err ( ParseError :: Continue ) ,
735
751
} ;
736
752
737
- if cursor. is_inlined_function ( ) ||
738
- cursor
753
+ if cursor. is_inlined_function ( )
754
+ || cursor
739
755
. definition ( )
740
756
. map_or ( false , |x| x. is_inlined_function ( ) )
741
757
{
742
- if !context. options ( ) . generate_inline_functions &&
743
- !context. options ( ) . wrap_static_fns
758
+ if !context. options ( ) . generate_inline_functions
759
+ && !context. options ( ) . wrap_static_fns
744
760
{
745
761
return Err ( ParseError :: Continue ) ;
746
762
}
@@ -750,9 +766,9 @@ impl ClangSubItemParser for Function {
750
766
}
751
767
752
768
// We cannot handle `inline` functions that are not `static`.
753
- if context. options ( ) . wrap_static_fns &&
754
- cursor. is_inlined_function ( ) &&
755
- matches ! ( linkage, Linkage :: External )
769
+ if context. options ( ) . wrap_static_fns
770
+ && cursor. is_inlined_function ( )
771
+ && matches ! ( linkage, Linkage :: External )
756
772
{
757
773
return Err ( ParseError :: Continue ) ;
758
774
}
0 commit comments