@@ -27,8 +27,8 @@ import cpp_import::clang_c {
2727 clang_EvalResult_getAsStr, clang_EvalResult_getAsUnsigned, clang_EvalResult_getKind
2828 clang_EvalResult_isUnsignedInt, clang_Type_getNamedType, clang_Type_getNumTemplateArguments
2929 clang_Type_getSizeOf, clang_Type_getTemplateArgumentAsType, clang_createIndex, clang_disposeIndex
30- clang_disposeString, clang_disposeTokens, clang_disposeTranslationUnit, clang_equalCursors, clang_getArgType
31- clang_getArrayElementType, clang_getArraySize, clang_getCString, clang_getCanonicalCursor
30+ clang_disposeString, clang_disposeTokens, clang_disposeTranslationUnit, clang_equalCursors, clang_equalTypes
31+ clang_getArgType, clang_getArrayElementType, clang_getArraySize, clang_getCString, clang_getCanonicalCursor
3232 clang_getCanonicalType, clang_getCursorDefinition, clang_getCursorExtent, clang_getCursorKind
3333 clang_getCursorKindSpelling, clang_getCursorLocation, clang_getCursorPrettyPrinted
3434 clang_getCursorPrintingPolicy, clang_getCursorResultType, clang_getCursorSemanticParent, clang_getCursorSpelling
@@ -563,6 +563,104 @@ class CppImportProcessor {
563563 return new_scope_id
564564 }
565565
566+ fn resolve_unexposed_type(
567+ mut this
568+ program: &mut CheckedProgram
569+ scope_id: ScopeId
570+ root_scope_id: ScopeId
571+ module_id: ModuleId
572+ anon t: CXType
573+ ) throws -> TypeId {
574+ // Try to find a decl for the type, to avoid:
575+ // - Unexposed types that are actually elaborated types (e.g. "class Foo" instead of "Foo")
576+ // - Random types that happen to have cv-qualifiers or other decorations that cause clang to give us an unexposed type instead of the actual type.
577+ mut definition_cursor = clang_getTypeDeclaration(t)
578+ if clang_getCursorKind(definition_cursor) is CXCursor_NoDeclFound {
579+ let canonical = clang_getCanonicalType(t)
580+ if not clang_equalTypes(canonical, t) {
581+ definition_cursor = clang_getTypeDeclaration(canonical)
582+ }
583+ }
584+
585+ // If we have a valid declaration, handle like CXType_Elaborated.
586+ if not (clang_getCursorKind(definition_cursor) is CXCursor_NoDeclFound) {
587+ let template_argument_count = clang_Type_getNumTemplateArguments(t)
588+
589+ let base_type: TypeId? = match template_argument_count > 0 {
590+ true => program.find_type_in_scope(
591+ scope_id
592+ name: name_from(definition_cursor)
593+ ignore_mixin_scopes: true
594+ root_scope: root_scope_id
595+ )
596+ false => program.find_type_in_scope(
597+ scope_id
598+ name: name_from(definition_cursor)
599+ ignore_mixin_scopes: true
600+ root_scope: root_scope_id
601+ )
602+ }
603+
604+ return match base_type.has_value() {
605+ false => unknown_type_id()
606+ true => {
607+ mut type_id = base_type!
608+ let base_usr = string_from(clang_getCursorUSR(cursor: definition_cursor))
609+
610+ if base_usr == "c:@N@AK@S@ByteString" {
611+ return program.find_type_in_scope(
612+ scope_id: program.prelude_scope_id()
613+ name: "String"
614+ ) ?? builtin(BuiltinType::JaktString)
615+ }
616+
617+ let is_nnrp_class_type = base_usr.starts_with("c:@N@AK@S@NonnullRefPtr>") or base_usr == "c:@N@AK@ST>1#T@NonnullRefPtr"
618+ let is_ak_function = base_usr.starts_with("c:@N@AK@S@Function>")
619+
620+ if template_argument_count > 0 {
621+ let count = template_argument_count as! u32
622+ mut args: [TypeId] = []
623+ for i in 0..count {
624+ let type = clang_Type_getTemplateArgumentAsType(t, i)
625+ args.push(.type_from(program, scope_id, root_scope_id, module_id, type))
626+ }
627+
628+ if count == 1 and (is_nnrp_class_type or is_ak_function) {
629+ type_id = args[0]
630+ } else {
631+ type_id = program.find_or_add_type_id(
632+ type: match program.get_type(base_type!) {
633+ Struct(id) | GenericInstance(id) => Type::GenericInstance(id, args)
634+ Enum(id) | GenericEnumInstance(id) => Type::GenericEnumInstance(id, args)
635+ else => {
636+ if .debug_print { eprintln("ICE: Unexposed type is not a struct or enum: {}", program.type_name(base_type!, debug_mode: true)) }
637+ yield Type::Unknown
638+ }
639+ }
640+ module_id
641+ only_in_current_module: true
642+ )
643+ }
644+ }
645+
646+ yield type_id
647+ }
648+ }
649+ }
650+
651+ // No declaration found (e.g. type parameters). Fall back to spelling-based lookup.
652+ let name = string_from(clang_getTypeSpelling(t))
653+ if name.is_empty() {
654+ return builtin(BuiltinType::Unknown)
655+ }
656+ return program.find_type_in_scope(
657+ scope_id
658+ name
659+ ignore_mixin_scopes: true
660+ root_scope: root_scope_id
661+ ) ?? builtin(BuiltinType::Unknown)
662+ }
663+
566664 fn type_from(
567665 mut this
568666 program: &mut CheckedProgram
@@ -668,37 +766,44 @@ class CppImportProcessor {
668766 mut type_id = base_type_id
669767 let base_usr = string_from(clang_getCursorUSR(cursor: definition_cursor))
670768
671- // NonnullRefPtr<T> where T is a class -> T
672- let is_nnrp_class_type = base_usr.starts_with("c:@N@AK@S@NonnullRefPtr>") or base_usr == "c:@N@AK@ST>1#T@NonnullRefPtr"
673- // Function<T> -> T
674- let is_ak_function = base_usr.starts_with("c:@N@AK@S@Function>")
675-
676- // Check template params
677- if template_argument_count > 0 {
678- let count = template_argument_count as! u32
679- mut args: [TypeId] = []
680- for i in 0..count {
681- let type = clang_Type_getTemplateArgumentAsType(t, i)
682- args.push(.type_from(program, scope_id, root_scope_id, module_id, type))
683- }
769+ if base_usr == "c:@N@AK@S@ByteString" {
770+ type_id = program.find_type_in_scope(
771+ scope_id: program.prelude_scope_id()
772+ name: "String"
773+ ) ?? builtin(BuiltinType::JaktString)
774+ } else {
775+ // NonnullRefPtr<T> where T is a class -> T
776+ let is_nnrp_class_type = base_usr.starts_with("c:@N@AK@S@NonnullRefPtr>") or base_usr == "c:@N@AK@ST>1#T@NonnullRefPtr"
777+ // Function<T> -> T
778+ let is_ak_function = base_usr.starts_with("c:@N@AK@S@Function>")
779+
780+ // Check template params
781+ if template_argument_count > 0 {
782+ let count = template_argument_count as! u32
783+ mut args: [TypeId] = []
784+ for i in 0..count {
785+ let type = clang_Type_getTemplateArgumentAsType(t, i)
786+ args.push(.type_from(program, scope_id, root_scope_id, module_id, type))
787+ }
684788
685- if count == 1 and (is_nnrp_class_type or is_ak_function) {
686- // Special case: Treat NNRP<T> as T when T is a class type
687- // Special case: Treat Function<Fn> as Fn.
688- type_id = args[0]
689- } else {
690- type_id = program.find_or_add_type_id(
691- type: match program.get_type(base_type!) {
692- Struct(id) | GenericInstance(id) => Type::GenericInstance(id, args)
693- Enum(id) | GenericEnumInstance(id) => Type::GenericEnumInstance(id, args)
694- else => {
695- if .debug_print { eprintln("ICE: Elaborated type is not a struct or enum: {}", program.type_name(base_type!, debug_mode: true)) }
696- yield Type::Unknown
789+ if count == 1 and (is_nnrp_class_type or is_ak_function) {
790+ // Special case: Treat NNRP<T> as T when T is a class type
791+ // Special case: Treat Function<Fn> as Fn.
792+ type_id = args[0]
793+ } else {
794+ type_id = program.find_or_add_type_id(
795+ type: match program.get_type(base_type!) {
796+ Struct(id) | GenericInstance(id) => Type::GenericInstance(id, args)
797+ Enum(id) | GenericEnumInstance(id) => Type::GenericEnumInstance(id, args)
798+ else => {
799+ if .debug_print { eprintln("ICE: Elaborated type is not a struct or enum: {}", program.type_name(base_type!, debug_mode: true)) }
800+ yield Type::Unknown
801+ }
697802 }
698- }
699- module_id
700- only_in_current_module: true
701- )
803+ module_id
804+ only_in_current_module: true
805+ )
806+ }
702807 }
703808 }
704809
@@ -707,16 +812,7 @@ class CppImportProcessor {
707812 }
708813 }
709814 CXType_Unexposed => {
710- let name = string_from(clang_getTypeSpelling(t))
711- yield match name.is_empty() {
712- true => builtin(BuiltinType::Unknown)
713- false => program.find_type_in_scope(
714- scope_id
715- name
716- ignore_mixin_scopes: true
717- root_scope: root_scope_id
718- ) ?? builtin(BuiltinType::Unknown)
719- }
815+ yield .resolve_unexposed_type(program, scope_id, root_scope_id, module_id, t)
720816 }
721817 CXType_LValueReference => program.find_or_add_type_id(
722818 type: Type::Reference(
0 commit comments