Repository: carbon-language/carbon-lang
File: toolchain/check/import_cpp.cpp (C++)

Code before:

  if (quals.hasConst()) {
    auto type_id = GetConstType(context, type_expr.inst_id);
    type_expr = {.inst_id = context.types().GetInstId(type_id),
                 .type_id = type_id};
    quals.removeConst();
  }

  // TODO: Support other qualifiers.
  if (!quals.empty()) {
    return {.inst_id = SemIR::TypeInstId::None, .type_id = SemIR::TypeId::None};
  }

  return type_expr;
}

// Maps a C++ pointer type to a Carbon pointer type.
static auto MapPointerType(Context& context, clang::QualType type,
                           TypeExpr pointee_type_expr) -> TypeExpr {
  CARBON_CHECK(type->isPointerType());

  if (auto nullability = type->getNullability();
      !nullability.has_value() ||
      *nullability != clang::NullabilityKind::NonNull) {
    return {.inst_id = SemIR::TypeInstId::None, .type_id = SemIR::TypeId::None};
  }

  SemIR::TypeId pointer_type_id =
      GetPointerType(context, pointee_type_expr.inst_id);
  return {.inst_id = context.types().GetInstId(pointer_type_id),
          .type_id = pointer_type_id};
}

// Maps a C++ type to a Carbon type. `type` should not be canonicalized because
// we check for pointer nullability and nullability will be lost by
// canonicalization.
static auto MapType(Context& context, SemIR::LocId loc_id, clang::QualType type)
    -> TypeExpr {
  // Unwrap any type modifiers and wrappers.
  llvm::SmallVector<clang::QualType> wrapper_types;
  while (true) {
    clang::QualType orig_type = type;
    if (type.hasQualifiers()) {
      type = type.getUnqualifiedType();
    } else if (type->isPointerType()) {
      type = type->getPointeeType();
    } else {
      break;
    }
    wrapper_types.push_back(orig_type);
  }

Review comment (suggestion):
Maybe keep an explicit todo?

```suggestion
    // TODO: Support nullable pointers.
    return {.inst_id = SemIR::TypeInstId::None, .type_id = SemIR::TypeId::None};
```

Code after:

  if (quals.hasConst()) {
    auto type_id = GetConstType(context, type_expr.inst_id);
    type_expr = {.inst_id = context.types().GetInstId(type_id),
                 .type_id = type_id};
    quals.removeConst();
  }

  // TODO: Support other qualifiers.
  if (!quals.empty()) {
    return {.inst_id = SemIR::TypeInstId::None, .type_id = SemIR::TypeId::None};
  }

  return type_expr;
}

// Maps a C++ pointer type to a Carbon pointer type.
static auto MapPointerType(Context& context, clang::QualType type,
                           TypeExpr pointee_type_expr) -> TypeExpr {
  CARBON_CHECK(type->isPointerType());

  if (auto nullability = type->getNullability();
      !nullability.has_value() ||
      *nullability != clang::NullabilityKind::NonNull) {
    // TODO: Support nullable pointers.
    return {.inst_id = SemIR::TypeInstId::None, .type_id = SemIR::TypeId::None};
  }

  SemIR::TypeId pointer_type_id =
      GetPointerType(context, pointee_type_expr.inst_id);
  return {.inst_id = context.types().GetInstId(pointer_type_id),
          .type_id = pointer_type_id};
}

// Maps a C++ type to a Carbon type. `type` should not be canonicalized because
// we check for pointer nullability and nullability will be lost by
// canonicalization.
static auto MapType(Context& context, SemIR::LocId loc_id, clang::QualType type)
    -> TypeExpr {
  // Unwrap any type modifiers and wrappers.
  llvm::SmallVector<clang::QualType> wrapper_types;
  while (true) {
    clang::QualType orig_type = type;
    if (type.hasQualifiers()) {
      type = type.getUnqualifiedType();
    } else if (type->isPointerType()) {
      type = type->getPointeeType();
    } else {
      break;
    }
    wrapper_types.push_back(orig_type);