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

Code before:
  const auto& var_storage =
      context.insts().TryGetAs<SemIR::VarStorage>(inst.value_id);
  if (!var_storage) {
    return ConstantEvalResult::NotConstant;
  }

  // Try to map from var storage to a C++ global.
  auto var_name_id = SemIR::GetFirstBindingNameFromPatternId(
      context.sem_ir(), var_storage->pattern_id);
  if (auto cpp_global_var_id = context.sem_ir().cpp_global_vars().Lookup(
          {.entity_name_id = var_name_id});
      cpp_global_var_id.has_value()) {
    SemIR::ClangDeclId clang_decl_id =
        context.sem_ir().cpp_global_vars().Get(cpp_global_var_id).clang_decl_id;
    const auto* var_decl =
        cast<clang::VarDecl>(context.clang_decls().Get(clang_decl_id).key.decl);

    // If the C++ global is constant, map it to a Carbon constant.
    if (var_decl->isUsableInConstantExpressions(context.ast_context())) {
      if (const auto* ap_value = var_decl->getEvaluatedValue()) {
        auto const_inst_id = MapAPValueToConstant(
            context, SemIR::LocId(inst_id), *ap_value, var_decl->getType());
        if (const_inst_id != SemIR::ErrorInst::InstId) {
          return ConstantEvalResult::NewSamePhase(
              context.insts().Get(const_inst_id));
        }
      }
    }

    return ConstantEvalResult::NotConstant;
  }

  return ConstantEvalResult::TODO;
}

auto EvalConstantInst(Context& context, SemIR::ClassElementAccess inst)
    -> ConstantEvalResult {
  return PerformAggregateAccess(context, inst);
}

auto EvalConstantInst(Context& context, SemIR::ClassDecl inst)
    -> ConstantEvalResult {
  const auto& class_info = context.classes().Get(inst.class_id);

  // If the class has generic parameters, we don't produce a class type, but a
  // callable whose return value is a class type.
  if (class_info.has_parameters()) {
    return ConstantEvalResult::NewSamePhase(SemIR::StructValue{
        .type_id = inst.type_id, .elements_id = SemIR::InstBlockId::Empty});
  }


Review comment (suggestion):
I think it'd make sense to have `MapAPValueToConstant` return a `ConstantId` instead of an `InstId`, and use `ConstantEvalResult::Existing` here instead.

Code after:
                      SemIR::AcquireValue inst) -> ConstantEvalResult {
  const auto& var_storage =
      context.insts().TryGetAs<SemIR::VarStorage>(inst.value_id);
  if (!var_storage) {
    return ConstantEvalResult::NotConstant;
  }

  // Try to map from var storage to a C++ global.
  auto var_name_id = SemIR::GetFirstBindingNameFromPatternId(
      context.sem_ir(), var_storage->pattern_id);
  if (auto cpp_global_var_id = context.sem_ir().cpp_global_vars().Lookup(
          {.entity_name_id = var_name_id});
      cpp_global_var_id.has_value()) {
    SemIR::ClangDeclId clang_decl_id =
        context.sem_ir().cpp_global_vars().Get(cpp_global_var_id).clang_decl_id;
    const auto* var_decl =
        cast<clang::VarDecl>(context.clang_decls().Get(clang_decl_id).key.decl);

    // If the C++ global is constant, map it to a Carbon constant.
    if (var_decl->isUsableInConstantExpressions(context.ast_context())) {
      if (const auto* ap_value = var_decl->getEvaluatedValue()) {
        auto clang_type = MapToCppType(context, inst.type_id);
        if (clang_type.isNull()) {
          return ConstantEvalResult::TODO;
        }

        auto const_id = MapAPValueToConstant(context, SemIR::LocId(inst_id),
                                             *ap_value, clang_type);
        if (const_id.has_value() && const_id.is_constant()) {
          return ConstantEvalResult::Existing(const_id);
        }
      }
    }

    return ConstantEvalResult::NotConstant;
  }

  return ConstantEvalResult::TODO;
}

auto EvalConstantInst(Context& context, SemIR::ClassElementAccess inst)
    -> ConstantEvalResult {
  return PerformAggregateAccess(context, inst);
}

auto EvalConstantInst(Context& context, SemIR::ClassDecl inst)
    -> ConstantEvalResult {
  const auto& class_info = context.classes().Get(inst.class_id);

  // If the class has generic parameters, we don't produce a class type, but a
  // callable whose return value is a class type.