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