Refactor TryEvaluateMacroToConstant to simplify and dedup code (#6820)

For integral and float types, `TryEvaluateMacroToConstant` now calls
`MapAPValueToConstant` to directly convert from an APValue, rather than
converting the `APValue` to an expression and importing it with
`MapConstant`.

`MapConstant` is still used, but only for string literals and nullptrs.
Since it's only used by `TryEvaluateMacroToConstant`, moved it to
`macros.cpp` and removed the code for other types of expressions.
This commit is contained in:
Nicholas Bishop
2026-03-02 21:00:07 +00:00
committed by GitHub
parent 6359e3f550
commit 069c6f4447
5 changed files with 142 additions and 245 deletions
+1 -82
View File
@@ -2079,81 +2079,6 @@ static auto IsIncompleteClass(Context& context, SemIR::NameScopeId scope_id)
context.classes().Get(class_decl->class_id).self_type_id);
}
// Maps a Clang literal expression to a Carbon constant.
// TODO: Add support for all constant types for which a C++ to Carbon type
// mapping exists.
static auto MapConstant(Context& context, SemIR::LocId loc_id,
clang::Expr* expr) -> SemIR::InstId {
CARBON_CHECK(expr, "empty expression");
if (auto* string_literal = dyn_cast<clang::StringLiteral>(expr)) {
if (!string_literal->isOrdinary() && !string_literal->isUTF8()) {
context.TODO(loc_id,
llvm::formatv("Unsupported: string literal type: {0}",
expr->getType()));
return SemIR::ErrorInst::InstId;
}
StringLiteralValueId string_id =
context.string_literal_values().Add(string_literal->getString());
auto inst_id =
MakeStringLiteral(context, Parse::StringLiteralId::None, string_id);
return inst_id;
} else if (isa<clang::CXXNullPtrLiteralExpr>(expr)) {
auto type_id = MapNullptrType(context, loc_id).type_id;
return GetOrAddInst<SemIR::UninitializedValue>(context, SemIR::LocId::None,
{.type_id = type_id});
}
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 if (auto* character_literal =
dyn_cast<clang::CharacterLiteral>(expr)) {
inst_id = AddInstInNoBlock(
context, MakeImportedLocIdAndInst<SemIR::CharLiteralValue>(
context, imported_loc_id,
{.type_id = type_id,
.value = SemIR::CharId(character_literal->getValue())}));
} 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.
@@ -2161,14 +2086,8 @@ static auto ImportMacro(Context& context, SemIR::LocId loc_id,
SemIR::NameScopeId scope_id, SemIR::NameId name_id,
clang::MacroInfo* macro_info)
-> SemIR::ScopeLookupResult {
clang::Expr* macro_expr =
auto inst_id =
TryEvaluateMacroToConstant(context, loc_id, name_id, macro_info);
if (!macro_expr) {
return SemIR::ScopeLookupResult::MakeNotFound();
}
auto inst_id = MapConstant(context, loc_id, macro_expr);
if (inst_id == SemIR::ErrorInst::InstId) {
return SemIR::ScopeLookupResult::MakeNotFound();
}