25
25
#include " toolchain/check/import.h"
26
26
#include " toolchain/check/inst.h"
27
27
#include " toolchain/check/literal.h"
28
+ #include " toolchain/check/name_lookup.h"
28
29
#include " toolchain/check/type.h"
29
30
#include " toolchain/check/type_completion.h"
30
31
#include " toolchain/diagnostics/diagnostic.h"
@@ -321,23 +322,19 @@ static auto MakeIntType(Context& context, IntId size_id) -> TypeExpr {
321
322
return ExprAsType (context, Parse::NodeId::None, type_inst_id);
322
323
}
323
324
324
- // Maps a C++ type to a Carbon type.
325
- // TODO: Support more types.
326
- static auto MapType (Context& context, clang::QualType type) -> TypeExpr {
327
- const auto * builtin_type = dyn_cast<clang::BuiltinType>(type);
328
- if (!builtin_type) {
329
- return {.inst_id = SemIR::ErrorInst::TypeInstId,
330
- .type_id = SemIR::ErrorInst::TypeId};
331
- }
325
+ // Maps a C++ builtin type to a Carbon type.
326
+ // TODO: Support more builtin types.
327
+ static auto MapBuiltinType (Context& context, const clang::BuiltinType& type)
328
+ -> TypeExpr {
332
329
// TODO: Refactor to avoid duplication.
333
- switch (builtin_type-> getKind ()) {
330
+ switch (type. getKind ()) {
334
331
case clang::BuiltinType::Short:
335
- if (context.ast_context ().getTypeSize (type) == 16 ) {
332
+ if (context.ast_context ().getTypeSize (& type) == 16 ) {
336
333
return MakeIntType (context, context.ints ().Add (16 ));
337
334
}
338
335
break ;
339
336
case clang::BuiltinType::Int:
340
- if (context.ast_context ().getTypeSize (type) == 32 ) {
337
+ if (context.ast_context ().getTypeSize (& type) == 32 ) {
341
338
return MakeIntType (context, context.ints ().Add (32 ));
342
339
}
343
340
break ;
@@ -348,11 +345,60 @@ static auto MapType(Context& context, clang::QualType type) -> TypeExpr {
348
345
.type_id = SemIR::ErrorInst::TypeId};
349
346
}
350
347
348
+ // Maps a C++ record type to a Carbon type.
349
+ // TODO: Support more record types.
350
+ static auto MapRecordType (Context& context, SemIR::LocId loc_id,
351
+ SemIR::NameScopeId scope_id,
352
+ const clang::RecordType& type) -> TypeExpr {
353
+ const clang::RecordDecl* record_decl = type.getDecl ();
354
+ if (record_decl && record_decl->isStruct ()) {
355
+ LookupResult result = LookupQualifiedName (
356
+ context, loc_id,
357
+ SemIR::NameId::ForIdentifier (
358
+ context.identifiers ().Add (record_decl->getName ())),
359
+ LookupScope{.name_scope_id = scope_id,
360
+ .specific_id = SemIR::SpecificId::None});
361
+ if (result.scope_result .is_found ()) {
362
+ SemIR::InstId inst_id = result.scope_result .target_inst_id ();
363
+ if (inst_id != SemIR::ErrorInst::InstId) {
364
+ return {.inst_id = context.types ().GetAsTypeInstId (inst_id),
365
+ .type_id = context.classes ()
366
+ .Get (context.insts ()
367
+ .Get (inst_id)
368
+ .As <SemIR::ClassDecl>()
369
+ .class_id )
370
+ .self_type_id };
371
+ }
372
+ }
373
+ }
374
+
375
+ return {.inst_id = SemIR::ErrorInst::TypeInstId,
376
+ .type_id = SemIR::ErrorInst::TypeId};
377
+ }
378
+
379
+ // Maps a C++ type to a Carbon type.
380
+ // TODO: Support more types.
381
+ static auto MapType (Context& context, SemIR::LocId loc_id,
382
+ SemIR::NameScopeId scope_id, clang::QualType type)
383
+ -> TypeExpr {
384
+ if (const auto * builtin_type = dyn_cast<clang::BuiltinType>(type)) {
385
+ return MapBuiltinType (context, *builtin_type);
386
+ }
387
+
388
+ if (const auto * record_type = clang::dyn_cast<clang::RecordType>(type)) {
389
+ return MapRecordType (context, loc_id, scope_id, *record_type);
390
+ }
391
+
392
+ return {.inst_id = SemIR::ErrorInst::TypeInstId,
393
+ .type_id = SemIR::ErrorInst::TypeId};
394
+ }
395
+
351
396
// Returns a block id for the explicit parameters of the given function
352
397
// declaration. If the function declaration has no parameters, it returns
353
398
// `SemIR::InstBlockId::Empty`. In the case of an unsupported parameter type, it
354
399
// returns `SemIR::InstBlockId::None`.
355
400
static auto MakeParamPatternsBlockId (Context& context, SemIR::LocId loc_id,
401
+ SemIR::NameScopeId scope_id,
356
402
const clang::FunctionDecl& clang_decl)
357
403
-> SemIR::InstBlockId {
358
404
if (clang_decl.parameters ().empty ()) {
@@ -363,8 +409,8 @@ static auto MakeParamPatternsBlockId(Context& context, SemIR::LocId loc_id,
363
409
params.reserve (clang_decl.parameters ().size ());
364
410
for (const clang::ParmVarDecl* param : clang_decl.parameters ()) {
365
411
clang::QualType param_type = param->getType ().getCanonicalType ();
366
- SemIR::TypeId type_id =
367
- GetPatternType ( context, MapType (context, param_type).type_id );
412
+ SemIR::TypeId type_id = GetPatternType (
413
+ context, MapType (context, loc_id, scope_id , param_type).type_id );
368
414
if (type_id == SemIR::ErrorInst::TypeId) {
369
415
context.TODO (loc_id, llvm::formatv (" Unsupported: parameter type: {0}" ,
370
416
param_type.getAsString ()));
@@ -401,18 +447,26 @@ static auto MakeParamPatternsBlockId(Context& context, SemIR::LocId loc_id,
401
447
// Currently only void and 32-bit int are supported.
402
448
// TODO: Support more return types.
403
449
static auto GetReturnType (Context& context, SemIR::LocId loc_id,
450
+ SemIR::NameScopeId scope_id,
404
451
const clang::FunctionDecl* clang_decl)
405
452
-> SemIR::InstId {
406
453
clang::QualType ret_type = clang_decl->getReturnType ().getCanonicalType ();
407
454
if (ret_type->isVoidType ()) {
408
455
return SemIR::InstId::None;
409
456
}
410
- auto [type_inst_id, type_id] = MapType (context, ret_type);
457
+ auto [type_inst_id, type_id] = MapType (context, loc_id, scope_id, ret_type);
411
458
if (type_id == SemIR::ErrorInst::TypeId) {
412
459
context.TODO (loc_id, llvm::formatv (" Unsupported: return type: {0}" ,
413
460
ret_type.getAsString ()));
414
461
return SemIR::ErrorInst::InstId;
415
462
}
463
+ if (SemIR::InitRepr::ForType (context.sem_ir (), type_id).kind ==
464
+ SemIR::InitRepr::InPlace) {
465
+ context.TODO (loc_id, llvm::formatv (" Unsupported: in place return type: {0}" ,
466
+ ret_type.getAsString ()));
467
+ return SemIR::ErrorInst::InstId;
468
+ }
469
+
416
470
auto pattern_type_id = GetPatternType (context, type_id);
417
471
SemIR::InstId return_slot_pattern_id = AddInstInNoBlock (
418
472
// TODO: Fill in a location for the return type once available.
@@ -448,11 +502,12 @@ static auto ImportFunctionDecl(Context& context, SemIR::LocId loc_id,
448
502
return SemIR::ErrorInst::InstId;
449
503
}
450
504
auto param_patterns_id =
451
- MakeParamPatternsBlockId (context, loc_id, *clang_decl);
505
+ MakeParamPatternsBlockId (context, loc_id, scope_id, *clang_decl);
452
506
if (!param_patterns_id.has_value ()) {
453
507
return SemIR::ErrorInst::InstId;
454
508
}
455
- auto return_slot_pattern_id = GetReturnType (context, loc_id, clang_decl);
509
+ auto return_slot_pattern_id =
510
+ GetReturnType (context, loc_id, scope_id, clang_decl);
456
511
if (SemIR::ErrorInst::InstId == return_slot_pattern_id) {
457
512
return SemIR::ErrorInst::InstId;
458
513
}
0 commit comments