@@ -500,16 +500,12 @@ impl<'ctx> BindgenContext<'ctx> {
500
500
wrapping : ItemId ,
501
501
parent_id : ItemId ,
502
502
ty : & clang:: Type ,
503
- location : clang:: Cursor )
503
+ location : clang:: Cursor ,
504
+ declaration : clang:: Cursor )
504
505
-> ItemId {
505
506
use clangll:: * ;
506
507
let mut args = vec ! [ ] ;
507
- let mut found_invalid_template_ref = false ;
508
508
location. visit ( |c| {
509
- if c. kind ( ) == CXCursor_TemplateRef &&
510
- c. cur_type ( ) . kind ( ) == CXType_Invalid {
511
- found_invalid_template_ref = true ;
512
- }
513
509
if c. kind ( ) == CXCursor_TypeRef {
514
510
// The `with_id` id will potentially end up unused if we give up
515
511
// on this type (for example, its a tricky partial template
@@ -528,39 +524,46 @@ impl<'ctx> BindgenContext<'ctx> {
528
524
529
525
let item = {
530
526
let wrapping_type = self . resolve_type ( wrapping) ;
531
- let old_args = match * wrapping_type. kind ( ) {
532
- TypeKind :: Comp ( ref ci) => ci. template_args ( ) ,
533
- _ => panic ! ( "how?" ) ,
534
- } ;
535
- // The following assertion actually fails with partial template
536
- // specialization. But as far as I know there's no way at all to
537
- // grab the specialized types from neither the AST or libclang.
538
- //
539
- // This flaw was already on the old parser, but I now think it has
540
- // no clear solution.
541
- //
542
- // For an easy example in which there's no way at all of getting the
543
- // `int` type, except manually parsing the spelling:
544
- //
545
- // template<typename T, typename U>
546
- // class Incomplete {
547
- // T d;
548
- // U p;
549
- // };
550
- //
551
- // template<typename U>
552
- // class Foo {
553
- // Incomplete<U, int> bar;
554
- // };
555
- //
556
- // debug_assert_eq!(old_args.len(), args.len());
557
- //
558
- // That being said, this is not so common, so just error! and hope
559
- // for the best, returning the previous type, who knows.
560
- if old_args. len ( ) != args. len ( ) {
561
- error ! ( "Found partial template specialization, \
562
- expect dragons!") ;
563
- return wrapping;
527
+ if let TypeKind :: Comp ( ref ci) = * wrapping_type. kind ( ) {
528
+ let old_args = ci. template_args ( ) ;
529
+
530
+ // The following assertion actually fails with partial template
531
+ // specialization. But as far as I know there's no way at all to
532
+ // grab the specialized types from neither the AST or libclang,
533
+ // which sucks. The same happens for specialized type alias
534
+ // template declarations, where we have that ugly hack up there.
535
+ //
536
+ // This flaw was already on the old parser, but I now think it
537
+ // has no clear solution (apart from patching libclang to
538
+ // somehow expose them, of course).
539
+ //
540
+ // For an easy example in which there's no way at all of getting
541
+ // the `int` type, except manually parsing the spelling:
542
+ //
543
+ // template<typename T, typename U>
544
+ // class Incomplete {
545
+ // T d;
546
+ // U p;
547
+ // };
548
+ //
549
+ // template<typename U>
550
+ // class Foo {
551
+ // Incomplete<U, int> bar;
552
+ // };
553
+ //
554
+ // debug_assert_eq!(old_args.len(), args.len());
555
+ //
556
+ // That being said, this is not so common, so just error! and
557
+ // hope for the best, returning the previous type, who knows.
558
+ if old_args. len ( ) != args. len ( ) {
559
+ error ! ( "Found partial template specialization, \
560
+ expect dragons!") ;
561
+ return wrapping;
562
+ }
563
+ } else {
564
+ assert_eq ! ( declaration. kind( ) ,
565
+ :: clangll:: CXCursor_TypeAliasTemplateDecl ,
566
+ "Expected wrappable type" ) ;
564
567
}
565
568
566
569
let type_kind = TypeKind :: TemplateRef ( wrapping, args) ;
@@ -589,7 +592,9 @@ impl<'ctx> BindgenContext<'ctx> {
589
592
location : Option < clang:: Cursor > )
590
593
-> Option < ItemId > {
591
594
use clangll:: { CXCursor_ClassTemplate ,
592
- CXCursor_ClassTemplatePartialSpecialization } ;
595
+ CXCursor_ClassTemplatePartialSpecialization ,
596
+ CXCursor_TypeAliasTemplateDecl ,
597
+ CXCursor_TypeRef } ;
593
598
debug ! ( "builtin_or_resolved_ty: {:?}, {:?}, {:?}" ,
594
599
ty,
595
600
location,
@@ -633,15 +638,33 @@ impl<'ctx> BindgenContext<'ctx> {
633
638
// argument names don't matter in the global context.
634
639
if ( declaration. kind ( ) == CXCursor_ClassTemplate ||
635
640
declaration. kind ( ) ==
636
- CXCursor_ClassTemplatePartialSpecialization ) &&
641
+ CXCursor_ClassTemplatePartialSpecialization ||
642
+ declaration. kind ( ) == CXCursor_TypeAliasTemplateDecl ) &&
637
643
* ty != canonical_declaration. cur_type ( ) &&
638
644
location. is_some ( ) &&
639
645
parent_id. is_some ( ) {
646
+ // For specialized type aliases, there's no way to get the
647
+ // template parameters as of this writing (for a struct
648
+ // specialization we wouldn't be in this branch anyway).
649
+ //
650
+ // Explicitly return `None` if there aren't any
651
+ // unspecialized parameters (contains any `TypeRef`) so we
652
+ // resolve the canonical type if there is one and it's
653
+ // exposed.
654
+ //
655
+ // This is _tricky_, I know :(
656
+ if declaration. kind ( ) == CXCursor_TypeAliasTemplateDecl &&
657
+ !location. unwrap ( ) . contains_cursor ( CXCursor_TypeRef ) &&
658
+ ty. canonical_type ( ) . is_valid_and_exposed ( ) {
659
+ return None ;
660
+ }
661
+
640
662
return Some ( self . build_template_wrapper ( with_id,
641
663
id,
642
664
parent_id. unwrap ( ) ,
643
665
ty,
644
- location. unwrap ( ) ) ) ;
666
+ location. unwrap ( ) ,
667
+ declaration) ) ;
645
668
}
646
669
647
670
return Some ( self . build_ty_wrapper ( with_id, id, parent_id, ty) ) ;
0 commit comments