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

Code before:
  }

  SemIR::TypeId type_id = MapType(context, loc_id, expr->getType()).type_id;
  if (!type_id.has_value()) {
    context.TODO(loc_id, llvm::formatv("Unsupported: C++ literal's type `{0}` "
                                       "could not be mapped to a Carbon type",
                                       expr->getType().getAsString()));
    return SemIR::ErrorInst::InstId;
  }

  SemIR::InstId inst_id = SemIR::InstId::None;
  SemIR::ImportIRInstId imported_loc_id =
      AddImportIRInst(context.sem_ir(), expr->getExprLoc());

  if (auto* integer_literal = dyn_cast<clang::IntegerLiteral>(expr)) {
    IntId int_id =
        context.ints().Add(integer_literal->getValue().getSExtValue());
    inst_id = AddInstInNoBlock(
        context,
        MakeImportedLocIdAndInst<SemIR::IntValue>(
            context, imported_loc_id, {.type_id = type_id, .int_id = int_id}));
  } else if (auto* bool_literal = dyn_cast<clang::CXXBoolLiteralExpr>(expr)) {
    inst_id = AddInstInNoBlock(
        context, MakeImportedLocIdAndInst(
                     context, imported_loc_id,
                     SemIR::BoolLiteral{.type_id = type_id,
                                        .value = SemIR::BoolValue::From(
                                            bool_literal->getValue())}));
  } else if (auto* float_literal = dyn_cast<clang::FloatingLiteral>(expr)) {
    FloatId float_id = context.floats().Add(float_literal->getValue());
    inst_id = AddInstInNoBlock(context,
                               MakeImportedLocIdAndInst<SemIR::FloatValue>(
                                   context, imported_loc_id,
                                   {.type_id = type_id, .float_id = float_id}));
  } else {
    context.TODO(loc_id, llvm::formatv(
                             "Unsupported: C++ constant expression type: '{0}'",
                             expr->getType().getAsString()));
    return SemIR::ErrorInst::InstId;
  }

  context.imports().push_back(inst_id);
  return inst_id;
}

// Imports a macro definition into the scope. Currently supports only simple
// object-like macros that expand to a constant integer value.
// TODO: Add support for other macro types and non-integer literal values.
static auto ImportMacro(Context& context, SemIR::LocId loc_id,
                        SemIR::NameScopeId scope_id, SemIR::NameId name_id,
                        clang::MacroInfo* macro_info)

Review comment (suggestion):
nit: We usually write the instruction type in the instruction-creating functions as an explicit template parameter. Why? Idk, I always have to move it to the `{}` when I have an error and need to see what it actually is. But I think clang-format does a nicer job with things that way, and by being consistent you can grep for `<SemIR::SomeInstName` to find where it's created.

```suggestion
        context, MakeImportedLocIdAndInst<SemIR::BoolLiteral>(
                     context, imported_loc_id,
                     {.type_id = type_id,
```

Will probably need to reformat after

Code after:
  }

  SemIR::TypeId type_id = MapType(context, loc_id, expr->getType()).type_id;
  if (!type_id.has_value()) {
    context.TODO(loc_id, llvm::formatv("Unsupported: C++ literal's type `{0}` "
                                       "could not be mapped to a Carbon type",
                                       expr->getType().getAsString()));
    return SemIR::ErrorInst::InstId;
  }

  SemIR::InstId inst_id = SemIR::InstId::None;
  SemIR::ImportIRInstId imported_loc_id =
      AddImportIRInst(context.sem_ir(), expr->getExprLoc());

  if (auto* integer_literal = dyn_cast<clang::IntegerLiteral>(expr)) {
    IntId int_id =
        context.ints().Add(integer_literal->getValue().getSExtValue());
    inst_id = AddInstInNoBlock(
        context,
        MakeImportedLocIdAndInst<SemIR::IntValue>(
            context, imported_loc_id, {.type_id = type_id, .int_id = int_id}));
  } else if (auto* bool_literal = dyn_cast<clang::CXXBoolLiteralExpr>(expr)) {
    inst_id = AddInstInNoBlock(
        context,
        MakeImportedLocIdAndInst<SemIR::BoolLiteral>(
            context, imported_loc_id,
            {.type_id = type_id,
             .value = SemIR::BoolValue::From(bool_literal->getValue())}));
  } else if (auto* float_literal = dyn_cast<clang::FloatingLiteral>(expr)) {
    FloatId float_id = context.floats().Add(float_literal->getValue());
    inst_id = AddInstInNoBlock(context,
                               MakeImportedLocIdAndInst<SemIR::FloatValue>(
                                   context, imported_loc_id,
                                   {.type_id = type_id, .float_id = float_id}));
  } else {
    context.TODO(loc_id, llvm::formatv(
                             "Unsupported: C++ constant expression type: '{0}'",
                             expr->getType().getAsString()));
    return SemIR::ErrorInst::InstId;
  }

  context.imports().push_back(inst_id);
  return inst_id;
}

// Imports a macro definition into the scope. Currently supports only simple
// object-like macros that expand to a constant integer value.
// TODO: Add support for other macro types and non-integer literal values.
static auto ImportMacro(Context& context, SemIR::LocId loc_id,
                        SemIR::NameScopeId scope_id, SemIR::NameId name_id,
                        clang::MacroInfo* macro_info)