mirror of
https://github.com/carbon-language/carbon-lang.git
synced 2026-09-24 19:00:11 +01:00
Move default value inst ids to a dedicated value store. (#7810)
Per #7737 we move the default value `InstId` storage from a block in the `SemIR::Function` data structure to a `SemIR::File` scoped `ValueStore`. Moves the default value consistency checking to the general merge argument pattern matching logic, which changes the error message issued to the generic one.
This commit is contained in:
@@ -86,6 +86,7 @@ Example usage:
|
||||
"constant": "SemIR::MakeConstantId",
|
||||
"constraint": "SemIR::MakeNamedConstraintId",
|
||||
"declared_facet_type": "SemIR::MakeDeclaredFacetTypeId",
|
||||
"default_value": "SemIR::MakeDefaultValueId",
|
||||
"entity_name": "SemIR::MakeEntityNameId",
|
||||
"function": "SemIR::MakeFunctionId",
|
||||
"generated_function": "SemIR::MakeGeneratedFunctionId",
|
||||
|
||||
@@ -401,6 +401,9 @@ class Context {
|
||||
auto declared_facet_types() -> SemIR::DeclaredFacetTypeStore& {
|
||||
return sem_ir().declared_facet_types();
|
||||
}
|
||||
auto default_values() -> SemIR::DefaultValueStore& {
|
||||
return sem_ir().default_values();
|
||||
}
|
||||
auto identified_facet_types() -> SemIR::IdentifiedFacetTypeStore& {
|
||||
return sem_ir().identified_facet_types();
|
||||
}
|
||||
|
||||
@@ -1967,7 +1967,6 @@ static auto ImportFunction(Context& context, SemIR::LocId loc_id,
|
||||
.call_param_patterns_id =
|
||||
function_params_insts->call_param_patterns_id,
|
||||
.call_params_id = function_params_insts->call_params_id,
|
||||
.call_param_default_values_id = SemIR::InstBlockId::Empty,
|
||||
.call_param_ranges = function_params_insts->param_ranges,
|
||||
.return_type_inst_id = function_params_insts->return_type_inst_id,
|
||||
.return_form_inst_id = function_params_insts->return_form_inst_id,
|
||||
|
||||
@@ -64,18 +64,24 @@ LLVM_DUMP_METHOD static auto Dump(const Context& context,
|
||||
return SemIR::Dump(context.sem_ir(), const_id);
|
||||
}
|
||||
|
||||
LLVM_DUMP_METHOD static auto Dump(const Context& context,
|
||||
SemIR::EntityNameId entity_name_id)
|
||||
-> std::string {
|
||||
return SemIR::Dump(context.sem_ir(), entity_name_id);
|
||||
}
|
||||
|
||||
LLVM_DUMP_METHOD static auto Dump(
|
||||
const Context& context, SemIR::DeclaredFacetTypeId declared_facet_type_id)
|
||||
-> std::string {
|
||||
return SemIR::Dump(context.sem_ir(), declared_facet_type_id);
|
||||
}
|
||||
|
||||
LLVM_DUMP_METHOD static auto Dump(const Context& context,
|
||||
SemIR::DefaultValueId value_id)
|
||||
-> std::string {
|
||||
return SemIR::Dump(context.sem_ir(), value_id);
|
||||
}
|
||||
|
||||
LLVM_DUMP_METHOD static auto Dump(const Context& context,
|
||||
SemIR::EntityNameId entity_name_id)
|
||||
-> std::string {
|
||||
return SemIR::Dump(context.sem_ir(), entity_name_id);
|
||||
}
|
||||
|
||||
LLVM_DUMP_METHOD static auto Dump(const Context& context,
|
||||
SemIR::FunctionId function_id)
|
||||
-> std::string {
|
||||
|
||||
@@ -81,6 +81,7 @@ class FullPatternStack {
|
||||
bind_name_stack_.PushArray();
|
||||
var_pattern_stack_.PushArray();
|
||||
next_var_index_stack_.push_back(-1);
|
||||
unspecified_default_values_stack_.PushArray();
|
||||
}
|
||||
|
||||
// Marks the start of a new full-pattern for a name binding declaration.
|
||||
@@ -89,6 +90,7 @@ class FullPatternStack {
|
||||
bind_name_stack_.PushArray();
|
||||
var_pattern_stack_.PushArray();
|
||||
next_var_index_stack_.push_back(-1);
|
||||
unspecified_default_values_stack_.PushArray();
|
||||
}
|
||||
|
||||
// Marks the start of a new full-pattern for a class `var` declaration.
|
||||
@@ -97,6 +99,7 @@ class FullPatternStack {
|
||||
bind_name_stack_.PushArray();
|
||||
var_pattern_stack_.PushArray();
|
||||
next_var_index_stack_.push_back(-1);
|
||||
unspecified_default_values_stack_.PushArray();
|
||||
}
|
||||
|
||||
// Marks the start of the current parameterized entity's implicit parameter
|
||||
@@ -121,8 +124,6 @@ class FullPatternStack {
|
||||
CARBON_CHECK(kind_stack_.back() == Kind::NotInEitherParamList, "{0}",
|
||||
kind_stack_.back());
|
||||
kind_stack_.back() = Kind::ExplicitParamList;
|
||||
raw_default_values_stack_.PushArray();
|
||||
converted_default_values_stack_.PushArray();
|
||||
}
|
||||
|
||||
// Marks the end of the current parameterized entity's explicit parameter
|
||||
@@ -142,17 +143,14 @@ class FullPatternStack {
|
||||
// Marks the end of checking and pattern matching for the current
|
||||
// full-pattern.
|
||||
auto PopFullPattern() -> void {
|
||||
auto kind = kind_stack_.pop_back_val();
|
||||
kind_stack_.pop_back();
|
||||
bind_name_stack_.PopArray();
|
||||
int index = next_var_index_stack_.pop_back_val();
|
||||
CARBON_CHECK(index < 0 || static_cast<size_t>(index) ==
|
||||
var_pattern_stack_.PeekArray().size(),
|
||||
"`GetLocalVarStorage` not called for all var patterns");
|
||||
var_pattern_stack_.PopArray();
|
||||
if (kind == Kind::ExplicitParamList) {
|
||||
raw_default_values_stack_.PopArray();
|
||||
converted_default_values_stack_.PopArray();
|
||||
}
|
||||
unspecified_default_values_stack_.PopArray();
|
||||
}
|
||||
|
||||
// Records that `name_id` was introduced by the current full-pattern.
|
||||
@@ -207,51 +205,18 @@ class FullPatternStack {
|
||||
kind_stack_.size());
|
||||
}
|
||||
|
||||
// Adds the inst id for a default value for any subpattern in the
|
||||
// full-pattern. We store these before the type of the pattern with this
|
||||
// default value is known. Returns the index of the added instruction
|
||||
// as a `DefaultValueId`. Note default values are only supported for
|
||||
// explicit parameter lists.
|
||||
auto AddRawDefaultValue(SemIR::InstId inst_id) -> SemIR::DefaultValueId {
|
||||
CARBON_CHECK(kind_stack_.back() == Kind::ExplicitParamList);
|
||||
return AddDefaultValue(inst_id, raw_default_values_stack_);
|
||||
// Adds an unspecified pattern default value to the array at the top of the
|
||||
// full pattern stack. We track these for possible later use in diagnostics.
|
||||
auto AddUnspecifiedDefaultValue(SemIR::InstId inst_id) -> void {
|
||||
unspecified_default_values_stack_.AppendToTop(inst_id);
|
||||
}
|
||||
|
||||
// Adds the inst id for a default value after conversion to the pattern type.
|
||||
// Returns the index of the added instruction as a `DefaultValueId`.
|
||||
auto AddConvertedDefaultValue(SemIR::InstId inst_id)
|
||||
-> SemIR::DefaultValueId {
|
||||
return AddDefaultValue(inst_id, converted_default_values_stack_);
|
||||
}
|
||||
|
||||
// Returns a reference to the array of raw default value inst ids at the top
|
||||
// of the stack. Note default values are only supported for explicit parameter
|
||||
// lists.
|
||||
auto GetRawDefaultValues() -> llvm::ArrayRef<SemIR::InstId> {
|
||||
return raw_default_values_stack_.empty()
|
||||
? llvm::ArrayRef<SemIR::InstId>()
|
||||
: raw_default_values_stack_.PeekArray();
|
||||
}
|
||||
|
||||
// Returns a reference to the array of type-converted default value inst ids
|
||||
// at the top of the stack.
|
||||
auto GetConvertedDefaultValues() -> llvm::ArrayRef<SemIR::InstId> {
|
||||
return converted_default_values_stack_.empty()
|
||||
? llvm::ArrayRef<SemIR::InstId>()
|
||||
: converted_default_values_stack_.PeekArray();
|
||||
// Returns the unspecified default values array at the top of the stack.
|
||||
auto GetUnspecifiedDefaultValues() -> llvm::ArrayRef<SemIR::InstId> {
|
||||
return unspecified_default_values_stack_.PeekArray();
|
||||
}
|
||||
|
||||
private:
|
||||
// TODO: move default value InstIds to a value store and remove them from the
|
||||
// pattern stack.
|
||||
auto AddDefaultValue(SemIR::InstId inst_id, ArrayStack<SemIR::InstId>& stack)
|
||||
-> SemIR::DefaultValueId {
|
||||
auto index =
|
||||
SemIR::DefaultValueId(static_cast<int32_t>(stack.PeekArray().size()));
|
||||
stack.AppendToTop(inst_id);
|
||||
return index;
|
||||
}
|
||||
|
||||
LexicalLookup* lookup_;
|
||||
|
||||
// The stack of pending full-patterns is organized as a struct of arrays, with
|
||||
@@ -283,16 +248,9 @@ class FullPatternStack {
|
||||
// of that frame are not ready for consumption.
|
||||
llvm::SmallVector<int> next_var_index_stack_;
|
||||
|
||||
// The stack of instructions specifying default values for subpatterns
|
||||
// within this full-pattern. These instructions are as they are written by
|
||||
// the developer, with no type conversions applied. They are indexed by
|
||||
// `DefaultValueId` values.
|
||||
ArrayStack<SemIR::InstId> raw_default_values_stack_;
|
||||
|
||||
// The stack of instructions for default values after the conversions to the
|
||||
// type of the pattern have been applied. They are indexed by `DefaultValueId`
|
||||
// values.
|
||||
ArrayStack<SemIR::InstId> converted_default_values_stack_;
|
||||
// For each full pattern we maintain a list of the InstIds of any
|
||||
// unspecified default values, for use in diagnostics.
|
||||
ArrayStack<SemIR::InstId> unspecified_default_values_stack_;
|
||||
};
|
||||
|
||||
} // namespace Carbon::Check
|
||||
|
||||
@@ -91,7 +91,6 @@ struct FunctionSignatureInsts {
|
||||
SemIR::InstBlockId param_patterns_id = SemIR::InstBlockId::None;
|
||||
SemIR::InstBlockId call_param_patterns_id = SemIR::InstBlockId::None;
|
||||
SemIR::InstBlockId call_params_id = SemIR::InstBlockId::None;
|
||||
SemIR::InstBlockId call_param_default_values_id = SemIR::InstBlockId::Empty;
|
||||
SemIR::Function::CallParamIndexRanges call_param_ranges =
|
||||
SemIR::Function::CallParamIndexRanges::Empty;
|
||||
SemIR::TypeInstId return_type_inst_id = SemIR::TypeInstId::None;
|
||||
@@ -191,8 +190,6 @@ auto MakeGeneratedFunctionDecl(Context& context, SemIR::LocId loc_id,
|
||||
{
|
||||
.call_param_patterns_id = insts.call_param_patterns_id,
|
||||
.call_params_id = insts.call_params_id,
|
||||
.call_param_default_values_id =
|
||||
insts.call_param_default_values_id,
|
||||
.call_param_ranges = insts.call_param_ranges,
|
||||
.return_type_inst_id = insts.return_type_inst_id,
|
||||
.return_form_inst_id = insts.return_form_inst_id,
|
||||
@@ -305,62 +302,6 @@ static auto CheckFunctionEvaluationModeMatches(
|
||||
return false;
|
||||
}
|
||||
|
||||
// Checks that if `new_id` has a specified value, it has the same value as
|
||||
// specified by `prev_id`. If `diagnose` is true this will issue a diagnostic
|
||||
// if it detects a difference. Returns true if the values are the same or
|
||||
// `new_id` is unspecified.
|
||||
//
|
||||
// Note: this function is only called on the function's first owning
|
||||
// declaration, as that is the declaration with this requirement.
|
||||
static auto CheckDefaultValueIsSame(Context& context, SemIR::InstId new_id,
|
||||
SemIR::InstId prev_id, bool diagnose)
|
||||
-> bool {
|
||||
CARBON_CHECK(!context.insts().Is<SemIR::UnspecifiedValue>(prev_id));
|
||||
if (!context.insts().Is<SemIR::UnspecifiedValue>(new_id)) {
|
||||
auto new_constant_id = context.constant_values().Get(new_id);
|
||||
auto prev_constant_id = context.constant_values().Get(prev_id);
|
||||
if (new_constant_id != prev_constant_id) {
|
||||
if (diagnose) {
|
||||
CARBON_DIAGNOSTIC(
|
||||
PatternDefaultValueDiffers, Error,
|
||||
"default value of {0} differs from the previously declared default "
|
||||
"value of {1}",
|
||||
InstIdAsConstant, InstIdAsConstant);
|
||||
CARBON_DIAGNOSTIC(PatternDefaultValueDiffersNote, Note,
|
||||
"different previous declaration here");
|
||||
context.emitter()
|
||||
.Build(new_id, PatternDefaultValueDiffers, new_id, prev_id)
|
||||
.Note(prev_id, PatternDefaultValueDiffersNote)
|
||||
.Emit();
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
// Checks every parameter in `prev_function` and `new_function`, that if they
|
||||
// both specify a default value those values are identical. If `diagnose` is
|
||||
// true, issues diagnostics when that condition is violated. Returns true if
|
||||
// every parameter met the condition.
|
||||
static auto CheckDefaultValueConsistency(Context& context,
|
||||
const SemIR::Function& new_function,
|
||||
const SemIR::Function& prev_function,
|
||||
bool diagnose) -> bool {
|
||||
auto new_default_value_ids = context.inst_blocks().GetOrEmpty(
|
||||
new_function.call_param_default_values_id);
|
||||
auto prev_default_value_ids = context.inst_blocks().GetOrEmpty(
|
||||
prev_function.call_param_default_values_id);
|
||||
|
||||
return llvm::all_of(
|
||||
llvm::zip_equal(new_default_value_ids, prev_default_value_ids),
|
||||
[&context, diagnose](auto id_pair) -> bool {
|
||||
auto [new_id, prev_id] = id_pair;
|
||||
return CheckDefaultValueIsSame(context, new_id, prev_id, diagnose);
|
||||
});
|
||||
}
|
||||
|
||||
auto CheckFunctionTypeMatches(Context& context,
|
||||
const SemIR::Function& new_function,
|
||||
const SemIR::Function& prev_function,
|
||||
@@ -379,10 +320,6 @@ auto CheckFunctionTypeMatches(Context& context,
|
||||
diagnose)) {
|
||||
return false;
|
||||
}
|
||||
if (!CheckDefaultValueConsistency(context, new_function, prev_function,
|
||||
diagnose)) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
@@ -51,7 +51,6 @@ auto GlobalInit::Finalize() -> void {
|
||||
.first_owning_decl_id = SemIR::InstId::None},
|
||||
{.call_param_patterns_id = SemIR::InstBlockId::Empty,
|
||||
.call_params_id = SemIR::InstBlockId::Empty,
|
||||
.call_param_default_values_id = SemIR::InstBlockId::Empty,
|
||||
.call_param_ranges = SemIR::Function::CallParamIndexRanges::Empty,
|
||||
.return_type_inst_id = SemIR::TypeInstId::None,
|
||||
.return_form_inst_id = SemIR::InstId::None,
|
||||
|
||||
@@ -373,18 +373,13 @@ static auto DiagnosePositionalParams(Context& context,
|
||||
function_info.param_patterns_id = SemIR::InstBlockId::Empty;
|
||||
}
|
||||
|
||||
// Diagnoses that the default values for function parameters have been
|
||||
// Diagnoses any default values for function parameters that have not been
|
||||
// completely specified, which is a requirement on the first owning declaration
|
||||
// of a function.
|
||||
static auto CheckDefaultValuesCompletelySpecified(
|
||||
Context& context, SemIR::Function& function_info) -> void {
|
||||
auto unspecified_value_ids = llvm::make_filter_range(
|
||||
context.inst_blocks().GetOrEmpty(
|
||||
function_info.call_param_default_values_id),
|
||||
[&context](auto inst_id) {
|
||||
return context.insts().Is<SemIR::UnspecifiedValue>(inst_id);
|
||||
});
|
||||
for (auto inst_id : unspecified_value_ids) {
|
||||
static auto DiagnoseDefaultValuesNotSpecified(
|
||||
Context& context, llvm::ArrayRef<SemIR::InstId> unspecified_inst_ids)
|
||||
-> void {
|
||||
for (auto inst_id : unspecified_inst_ids) {
|
||||
CARBON_DIAGNOSTIC(PatternDefaultValueNotSpecified, Error,
|
||||
"found unspecified default parameter value in the "
|
||||
"function's first owning declaration");
|
||||
@@ -455,22 +450,21 @@ static auto BuildFunctionDecl(Context& context,
|
||||
|
||||
// Build the function entity. This will be merged into an existing function if
|
||||
// there is one, or otherwise added to the function store.
|
||||
auto function_info = SemIR::Function{
|
||||
name_context.MakeEntityWithParamsBase(name, decl_id, is_extern,
|
||||
introducer.extern_library),
|
||||
{
|
||||
.call_param_patterns_id = name.call_param_patterns_id,
|
||||
.call_params_id = name.call_params_id,
|
||||
.call_param_default_values_id = name.call_param_default_values_id,
|
||||
.call_param_ranges = name.param_ranges,
|
||||
.return_type_inst_id = return_type_inst_id,
|
||||
.return_form_inst_id = return_form_inst_id,
|
||||
.return_pattern_id = return_pattern_id,
|
||||
.virtual_modifier = virtual_modifier,
|
||||
.evaluation_mode = evaluation_mode,
|
||||
.interface_modifier = interface_modifier,
|
||||
.self_param_id = self_param_id,
|
||||
}};
|
||||
auto function_info =
|
||||
SemIR::Function{name_context.MakeEntityWithParamsBase(
|
||||
name, decl_id, is_extern, introducer.extern_library),
|
||||
{
|
||||
.call_param_patterns_id = name.call_param_patterns_id,
|
||||
.call_params_id = name.call_params_id,
|
||||
.call_param_ranges = name.param_ranges,
|
||||
.return_type_inst_id = return_type_inst_id,
|
||||
.return_form_inst_id = return_form_inst_id,
|
||||
.return_pattern_id = return_pattern_id,
|
||||
.virtual_modifier = virtual_modifier,
|
||||
.evaluation_mode = evaluation_mode,
|
||||
.interface_modifier = interface_modifier,
|
||||
.self_param_id = self_param_id,
|
||||
}};
|
||||
if (is_definition) {
|
||||
function_info.definition_id = decl_id;
|
||||
}
|
||||
@@ -478,7 +472,8 @@ static auto BuildFunctionDecl(Context& context,
|
||||
DiagnosePositionalParams(context, function_info);
|
||||
if (name_context.state != DeclNameStack::NameContext::State::Poisoned &&
|
||||
!name_context.prev_inst_id().has_value()) {
|
||||
CheckDefaultValuesCompletelySpecified(context, function_info);
|
||||
DiagnoseDefaultValuesNotSpecified(
|
||||
context, context.inst_blocks().Get(name.unspecified_values_block_id));
|
||||
}
|
||||
|
||||
TryMergeRedecl(
|
||||
|
||||
@@ -200,9 +200,9 @@ static auto PopImplIntroducerAndParamsAsNameComponent(
|
||||
.param_patterns_id = SemIR::InstBlockId::None,
|
||||
.call_param_patterns_id = SemIR::InstBlockId::None,
|
||||
.call_params_id = SemIR::InstBlockId::None,
|
||||
.call_param_default_values_id = SemIR::InstBlockId::Empty,
|
||||
.param_ranges = SemIR::Function::CallParamIndexRanges::Empty,
|
||||
.pattern_block_id = pattern_block_id};
|
||||
.pattern_block_id = pattern_block_id,
|
||||
.unspecified_values_block_id = SemIR::InstBlockId::Empty};
|
||||
}
|
||||
|
||||
// Build an ImplDecl describing the signature of an impl. This handles the
|
||||
|
||||
@@ -154,11 +154,15 @@ auto HandleParseNode(Context& context, Parse::PatternListCommaId /*node_id*/)
|
||||
|
||||
auto HandleParseNode(Context& context, Parse::DefaultValueUnspecifiedId node_id)
|
||||
-> bool {
|
||||
context.node_stack().Push(
|
||||
node_id, AddInst<SemIR::UnspecifiedValue>(
|
||||
context, node_id,
|
||||
{.type_id = GetSingletonType(
|
||||
context, SemIR::UnspecifiedValueType::TypeInstId)}));
|
||||
auto inst_id = AddInst<SemIR::UnspecifiedValue>(
|
||||
context, node_id,
|
||||
{.type_id =
|
||||
GetSingletonType(context, SemIR::UnspecifiedValueType::TypeInstId)});
|
||||
|
||||
// Add the unspecified default value for later diagnostics checks.
|
||||
context.full_pattern_stack().AddUnspecifiedDefaultValue(inst_id);
|
||||
|
||||
context.node_stack().Push(node_id, inst_id);
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -194,11 +198,13 @@ auto HandleParseNode(Context& context, Parse::DefaultValuePatternId node_id)
|
||||
return false;
|
||||
}
|
||||
|
||||
// Add the value to the default values array in the full pattern stack, for
|
||||
// recovery later in the NameComponent. We store the raw value here for
|
||||
// Add the value to the default values store. We store the raw value here for
|
||||
// conversion during pattern matching once the type of the pattern is known.
|
||||
auto default_value_id =
|
||||
context.full_pattern_stack().AddRawDefaultValue(expr_inst_id);
|
||||
auto default_value_id = context.default_values().Add(
|
||||
{.raw_id = expr_inst_id,
|
||||
.value_id = SemIR::InstId::None,
|
||||
.is_unspecified =
|
||||
context.insts().Is<SemIR::UnspecifiedValue>(expr_inst_id)});
|
||||
|
||||
// Next on the node stack should be the pattern for which this default was
|
||||
// specified. We pop that so we can issue the DefaultValuePattern in its
|
||||
|
||||
@@ -179,6 +179,9 @@ class ImportContext {
|
||||
auto import_constant_values() -> const SemIR::ConstantValueStore& {
|
||||
return import_ir().constant_values();
|
||||
}
|
||||
auto import_default_values() -> const SemIR::DefaultValueStore& {
|
||||
return import_ir().default_values();
|
||||
}
|
||||
auto import_entity_names() -> const SemIR::EntityNameStore& {
|
||||
return import_ir().entity_names();
|
||||
}
|
||||
@@ -267,6 +270,9 @@ class ImportContext {
|
||||
auto local_constant_values() -> SemIR::ConstantValueStore& {
|
||||
return local_ir().constant_values();
|
||||
}
|
||||
auto local_default_values() -> SemIR::DefaultValueStore& {
|
||||
return local_ir().default_values();
|
||||
}
|
||||
auto local_entity_names() -> SemIR::EntityNameStore& {
|
||||
return local_ir().entity_names();
|
||||
}
|
||||
@@ -2306,6 +2312,12 @@ static auto TryResolveTypedInst(ImportRefResolver& resolver,
|
||||
SemIR::DefaultValuePattern inst)
|
||||
-> ResolveResult {
|
||||
auto subpattern = GetLocalImportRefInfo(resolver, inst.subpattern_id);
|
||||
const auto& import_default_value =
|
||||
resolver.import_default_values().Get(inst.default_value_id);
|
||||
// We import the first owning declaration of a function, which must always
|
||||
// have default values completely specified.
|
||||
CARBON_CHECK(!import_default_value.is_unspecified);
|
||||
auto value = GetLocalImportRefInfo(resolver, import_default_value.value_id);
|
||||
if (resolver.HasNewWork()) {
|
||||
return ResolveResult::Retry();
|
||||
}
|
||||
@@ -2316,7 +2328,10 @@ static auto TryResolveTypedInst(ImportRefResolver& resolver,
|
||||
.type_id = resolver.local_types().GetTypeIdForTypeConstantId(
|
||||
subpattern.local_type_const_id),
|
||||
.subpattern_id = AddLoadedImportRef(resolver, subpattern),
|
||||
.default_value_id = inst.default_value_id,
|
||||
.default_value_id = resolver.local_default_values().Add(
|
||||
{.raw_id = SemIR::InstId::None,
|
||||
.value_id = AddLoadedImportRef(resolver, value),
|
||||
.is_unspecified = false}),
|
||||
});
|
||||
}
|
||||
|
||||
@@ -2425,7 +2440,6 @@ static auto ImportFunctionDecl(
|
||||
{GetIncompleteLocalEntityBase(context, function_decl_id, import_function),
|
||||
{.call_param_patterns_id = SemIR::InstBlockId::None,
|
||||
.call_params_id = SemIR::InstBlockId::None,
|
||||
.call_param_default_values_id = SemIR::InstBlockId::Empty,
|
||||
.call_param_ranges = import_function.call_param_ranges,
|
||||
.return_type_inst_id = SemIR::TypeInstId::None,
|
||||
.return_form_inst_id = SemIR::InstId::None,
|
||||
@@ -2571,8 +2585,6 @@ static auto TryResolveTypedInst(ImportRefResolver& resolver,
|
||||
|
||||
auto call_param_patterns = GetLocalBlockImportRefInfo(
|
||||
resolver, import_function.call_param_patterns_id);
|
||||
auto call_param_default_values = GetLocalBlockImportRefInfo(
|
||||
resolver, import_function.call_param_default_values_id);
|
||||
auto return_type_const_id = SemIR::ConstantId::None;
|
||||
if (import_function.return_type_inst_id.has_value()) {
|
||||
return_type_const_id =
|
||||
@@ -2627,10 +2639,6 @@ static auto TryResolveTypedInst(ImportRefResolver& resolver,
|
||||
// Add the function declaration.
|
||||
new_function.call_param_patterns_id =
|
||||
AddLoadedImportRefBlock(resolver, call_param_patterns);
|
||||
if (call_param_default_values.has_value()) {
|
||||
new_function.call_param_default_values_id =
|
||||
AddLoadedImportRefBlock(resolver, *call_param_default_values);
|
||||
}
|
||||
new_function.parent_scope_id = parent_scope_id;
|
||||
new_function.implicit_param_patterns_id =
|
||||
AddLoadedImportRefBlock(resolver, implicit_param_patterns);
|
||||
|
||||
@@ -339,14 +339,30 @@ static auto CheckRedeclParam(Context& context, bool is_implicit_param,
|
||||
auto prev_default_value_pattern =
|
||||
prev_param_pattern.As<SemIR::DefaultValuePattern>();
|
||||
|
||||
// If the new pattern specified a default value, it must match the
|
||||
// previously declared default value.
|
||||
const auto& new_default_value = context.default_values().Get(
|
||||
new_default_value_pattern.default_value_id);
|
||||
|
||||
if (!new_default_value.is_unspecified) {
|
||||
const auto& prev_default_value = context.default_values().Get(
|
||||
prev_default_value_pattern.default_value_id);
|
||||
// We require first owning declaration to always specify a default
|
||||
// value.
|
||||
CARBON_CHECK(!prev_default_value.is_unspecified);
|
||||
auto new_constant_id =
|
||||
context.constant_values().Get(new_default_value.value_id);
|
||||
auto prev_constant_id =
|
||||
context.constant_values().Get(prev_default_value.value_id);
|
||||
if (new_constant_id != prev_constant_id) {
|
||||
emit_general_diagnostic();
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
pattern_stack.push_back(
|
||||
{.prev_id = prev_default_value_pattern.subpattern_id,
|
||||
.new_id = new_default_value_pattern.subpattern_id});
|
||||
|
||||
// The node kind comparison should catch this on the mismatched patterns
|
||||
// prior to this, so the indices should never mismatch.
|
||||
CARBON_CHECK(prev_default_value_pattern.default_value_id.index ==
|
||||
new_default_value_pattern.default_value_id.index);
|
||||
break;
|
||||
}
|
||||
default: {
|
||||
|
||||
@@ -45,10 +45,10 @@ auto PopNameComponent(Context& context, SemIR::InstId return_pattern_id)
|
||||
}
|
||||
|
||||
auto call_param_patterns_id = SemIR::InstBlockId::None;
|
||||
auto call_param_default_values_id = SemIR::InstBlockId::Empty;
|
||||
auto call_params_id = SemIR::InstBlockId::None;
|
||||
auto param_ranges = SemIR::Function::CallParamIndexRanges::Empty;
|
||||
auto pattern_block_id = SemIR::InstBlockId::None;
|
||||
auto unspecified_values_block_id = SemIR::InstBlockId::Empty;
|
||||
if (param_patterns_id->has_value() ||
|
||||
implicit_param_patterns_id->has_value() ||
|
||||
return_pattern_id.has_value()) {
|
||||
@@ -57,11 +57,8 @@ auto PopNameComponent(Context& context, SemIR::InstId return_pattern_id)
|
||||
call_param_patterns_id = results.call_param_patterns_id;
|
||||
call_params_id = results.call_params_id;
|
||||
param_ranges = results.param_ranges;
|
||||
CARBON_CHECK(
|
||||
context.full_pattern_stack().GetRawDefaultValues().size() ==
|
||||
context.full_pattern_stack().GetConvertedDefaultValues().size());
|
||||
call_param_default_values_id = context.inst_blocks().Add(
|
||||
context.full_pattern_stack().GetConvertedDefaultValues());
|
||||
unspecified_values_block_id = context.inst_blocks().Add(
|
||||
context.full_pattern_stack().GetUnspecifiedDefaultValues());
|
||||
pattern_block_id = context.pattern_block_stack().Pop();
|
||||
context.full_pattern_stack().PopFullPattern();
|
||||
}
|
||||
@@ -69,21 +66,19 @@ auto PopNameComponent(Context& context, SemIR::InstId return_pattern_id)
|
||||
auto [name_loc_id, name_id] =
|
||||
context.node_stack().PopWithNodeId<Parse::NodeCategory::NonExprName>();
|
||||
|
||||
return {
|
||||
.name_loc_id = name_loc_id,
|
||||
.name_id = name_id,
|
||||
.first_param_node_id = first_param_node_id,
|
||||
.last_param_node_id = last_param_node_id,
|
||||
.implicit_params_loc_id = implicit_params_node_id,
|
||||
.implicit_param_patterns_id = *implicit_param_patterns_id,
|
||||
.params_loc_id = params_node_id,
|
||||
.param_patterns_id = *param_patterns_id,
|
||||
.call_param_patterns_id = call_param_patterns_id,
|
||||
.call_params_id = call_params_id,
|
||||
.call_param_default_values_id = call_param_default_values_id,
|
||||
.param_ranges = param_ranges,
|
||||
.pattern_block_id = pattern_block_id,
|
||||
};
|
||||
return {.name_loc_id = name_loc_id,
|
||||
.name_id = name_id,
|
||||
.first_param_node_id = first_param_node_id,
|
||||
.last_param_node_id = last_param_node_id,
|
||||
.implicit_params_loc_id = implicit_params_node_id,
|
||||
.implicit_param_patterns_id = *implicit_param_patterns_id,
|
||||
.params_loc_id = params_node_id,
|
||||
.param_patterns_id = *param_patterns_id,
|
||||
.call_param_patterns_id = call_param_patterns_id,
|
||||
.call_params_id = call_params_id,
|
||||
.param_ranges = param_ranges,
|
||||
.pattern_block_id = pattern_block_id,
|
||||
.unspecified_values_block_id = unspecified_values_block_id};
|
||||
}
|
||||
|
||||
// Pop the name of a declaration from the node stack, and diagnose if it has
|
||||
|
||||
@@ -40,12 +40,13 @@ struct NameComponent {
|
||||
// SemIR::EntityWithParamsBase).
|
||||
SemIR::InstBlockId call_param_patterns_id;
|
||||
SemIR::InstBlockId call_params_id;
|
||||
// The pattern default values as extracted from the parameter list.
|
||||
SemIR::InstBlockId call_param_default_values_id;
|
||||
SemIR::Function::CallParamIndexRanges param_ranges;
|
||||
|
||||
// The pattern block.
|
||||
SemIR::InstBlockId pattern_block_id;
|
||||
|
||||
// The `UnspecifiedValue` insts from the parameter default values, if any.
|
||||
SemIR::InstBlockId unspecified_values_block_id;
|
||||
};
|
||||
|
||||
// Pops a name component from the node stack (and pattern block stack, if it has
|
||||
|
||||
@@ -962,21 +962,13 @@ auto MatchContext::DoPostWork(State state,
|
||||
|
||||
// If a constant was specified, we should be able to convert it into the
|
||||
// type of the parameter.
|
||||
auto raw_default_value_inst_id =
|
||||
context_.full_pattern_stack()
|
||||
.GetRawDefaultValues()[default_value_pattern.default_value_id.index];
|
||||
auto converted_inst_id =
|
||||
context_.insts().Is<SemIR::UnspecifiedValue>(raw_default_value_inst_id)
|
||||
? raw_default_value_inst_id
|
||||
: ConvertToValueOfType(context_,
|
||||
SemIR::LocId(raw_default_value_inst_id),
|
||||
raw_default_value_inst_id, param_type_id);
|
||||
|
||||
// The index of the converted value should be the same as the raw value.
|
||||
auto converted_default_id =
|
||||
context_.full_pattern_stack().AddConvertedDefaultValue(converted_inst_id);
|
||||
CARBON_CHECK(converted_default_id.index ==
|
||||
default_value_pattern.default_value_id.index);
|
||||
auto& default_value =
|
||||
context_.default_values().Get(default_value_pattern.default_value_id);
|
||||
if (!default_value.is_unspecified) {
|
||||
default_value.value_id =
|
||||
ConvertToValueOfType(context_, SemIR::LocId(default_value.raw_id),
|
||||
default_value.raw_id, param_type_id);
|
||||
}
|
||||
|
||||
results_stack_.PopArray();
|
||||
|
||||
|
||||
@@ -21,6 +21,7 @@
|
||||
// CHECK:STDOUT: import_ir_insts: {}
|
||||
// CHECK:STDOUT: clang_decls: {}
|
||||
// CHECK:STDOUT: clang_decl_signatures: {}
|
||||
// CHECK:STDOUT: default_values: {}
|
||||
// CHECK:STDOUT: name_scopes:
|
||||
// CHECK:STDOUT: name_scope0: {inst: inst10, parent_scope: name_scope<none>, has_error: false, extended_scopes: [], names: {}}
|
||||
// CHECK:STDOUT: entity_names: {}
|
||||
|
||||
@@ -30,6 +30,7 @@ fn F(generic Form: Core.Form) ->? Form;
|
||||
// CHECK:STDOUT: import_ir_inst0: {ir_id: import_ir70000003, inst_id: inst50000023}
|
||||
// CHECK:STDOUT: clang_decls: {}
|
||||
// CHECK:STDOUT: clang_decl_signatures: {}
|
||||
// CHECK:STDOUT: default_values: {}
|
||||
// CHECK:STDOUT: name_scopes:
|
||||
// CHECK:STDOUT: name_scope0: {inst: inst10, parent_scope: name_scope<none>, has_error: false, extended_scopes: [], names: {name(Core): inst70000012, name0: inst70000033}}
|
||||
// CHECK:STDOUT: name_scope70000001: {inst: inst70000012, parent_scope: name_scope0, has_error: false, extended_scopes: [], names: {name1: inst70000017}}
|
||||
|
||||
@@ -65,6 +65,7 @@ fn G(x: Cpp.X) {
|
||||
// CHECK:STDOUT: clang_decl_signatures:
|
||||
// CHECK:STDOUT: clang_decl_signature_id50000000: {kind: normal, num_params: 0}
|
||||
// CHECK:STDOUT: clang_decl_signature_id50000001: {kind: normal, num_params: 1, modes: [value]}
|
||||
// CHECK:STDOUT: default_values: {}
|
||||
// CHECK:STDOUT: name_scopes:
|
||||
// CHECK:STDOUT: name_scope0: {inst: inst10, parent_scope: name_scope<none>, has_error: false, extended_scopes: [], names: {name(Cpp): inst50000012, name0: inst5000001F}}
|
||||
// CHECK:STDOUT: name_scope50000001: {inst: inst50000012, parent_scope: name_scope0, has_error: false, extended_scopes: [], names: {name2: inst50000014, name3: inst5000002D, name4: inst50000055}}
|
||||
|
||||
@@ -38,6 +38,7 @@ fn B() {
|
||||
// CHECK:STDOUT: import_ir_insts: {}
|
||||
// CHECK:STDOUT: clang_decls: {}
|
||||
// CHECK:STDOUT: clang_decl_signatures: {}
|
||||
// CHECK:STDOUT: default_values: {}
|
||||
// CHECK:STDOUT: name_scopes:
|
||||
// CHECK:STDOUT: name_scope0: {inst: inst10, parent_scope: name_scope<none>, has_error: false, extended_scopes: [], names: {name0: inst50000011}}
|
||||
// CHECK:STDOUT: entity_names: {}
|
||||
@@ -142,6 +143,7 @@ fn B() {
|
||||
// CHECK:STDOUT: import_ir_inst1: {ir_id: import_ir70000002, inst_id: inst50000011}
|
||||
// CHECK:STDOUT: clang_decls: {}
|
||||
// CHECK:STDOUT: clang_decl_signatures: {}
|
||||
// CHECK:STDOUT: default_values: {}
|
||||
// CHECK:STDOUT: name_scopes:
|
||||
// CHECK:STDOUT: name_scope0: {inst: inst10, parent_scope: name_scope<none>, has_error: false, extended_scopes: [], names: {name1: inst70000012, name0: inst70000013}}
|
||||
// CHECK:STDOUT: name_scope70000001: {inst: inst70000012, parent_scope: name_scope0, has_error: false, extended_scopes: [], names: {name1: inst70000018}}
|
||||
|
||||
@@ -38,6 +38,7 @@ fn B() {
|
||||
// CHECK:STDOUT: import_ir_insts: {}
|
||||
// CHECK:STDOUT: clang_decls: {}
|
||||
// CHECK:STDOUT: clang_decl_signatures: {}
|
||||
// CHECK:STDOUT: default_values: {}
|
||||
// CHECK:STDOUT: name_scopes:
|
||||
// CHECK:STDOUT: name_scope0: {inst: inst10, parent_scope: name_scope<none>, has_error: false, extended_scopes: [], names: {name0: inst50000011}}
|
||||
// CHECK:STDOUT: entity_names: {}
|
||||
@@ -161,6 +162,7 @@ fn B() {
|
||||
// CHECK:STDOUT: import_ir_inst1: {ir_id: import_ir70000002, inst_id: inst50000011}
|
||||
// CHECK:STDOUT: clang_decls: {}
|
||||
// CHECK:STDOUT: clang_decl_signatures: {}
|
||||
// CHECK:STDOUT: default_values: {}
|
||||
// CHECK:STDOUT: name_scopes:
|
||||
// CHECK:STDOUT: name_scope0: {inst: inst10, parent_scope: name_scope<none>, has_error: false, extended_scopes: [], names: {name1: inst70000012, name0: inst70000013}}
|
||||
// CHECK:STDOUT: name_scope70000001: {inst: inst70000012, parent_scope: name_scope0, has_error: false, extended_scopes: [], names: {name1: inst70000018}}
|
||||
|
||||
@@ -47,6 +47,7 @@ fn UseLocalCopy[T: Copy](_: T.T1, _: T.T2) {}
|
||||
// CHECK:STDOUT: import_ir_insts: {}
|
||||
// CHECK:STDOUT: clang_decls: {}
|
||||
// CHECK:STDOUT: clang_decl_signatures: {}
|
||||
// CHECK:STDOUT: default_values: {}
|
||||
// CHECK:STDOUT: name_scopes:
|
||||
// CHECK:STDOUT: name_scope0: {inst: inst10, parent_scope: name_scope<none>, has_error: false, extended_scopes: [], names: {name1: inst60000011}}
|
||||
// CHECK:STDOUT: name_scope60000001: {inst: inst60000011, parent_scope: name_scope0, has_error: false, extended_scopes: [], names: {name(SelfType): inst60000013}}
|
||||
@@ -211,6 +212,7 @@ fn UseLocalCopy[T: Copy](_: T.T1, _: T.T2) {}
|
||||
// CHECK:STDOUT: import_ir_instC: {ir_id: import_ir50000002, inst_id: inst6000001D}
|
||||
// CHECK:STDOUT: clang_decls: {}
|
||||
// CHECK:STDOUT: clang_decl_signatures: {}
|
||||
// CHECK:STDOUT: default_values: {}
|
||||
// CHECK:STDOUT: name_scopes:
|
||||
// CHECK:STDOUT: name_scope0: {inst: inst10, parent_scope: name_scope<none>, has_error: false, extended_scopes: [], names: {name0: inst50000012, name1: inst50000013, name4: inst5000006B, name7: inst500000AA}}
|
||||
// CHECK:STDOUT: name_scope50000001: {inst: inst50000012, parent_scope: name_scope0, has_error: false, extended_scopes: [], names: {name6: inst50000026}}
|
||||
|
||||
@@ -339,6 +339,7 @@ fn Foo[T: type](p: T*) -> (T*, ()) {
|
||||
// CHECK:STDOUT: import_ir_inst129: {ir_id: import_ir78000004, inst_id: inst700002D4}
|
||||
// CHECK:STDOUT: clang_decls: {}
|
||||
// CHECK:STDOUT: clang_decl_signatures: {}
|
||||
// CHECK:STDOUT: default_values: {}
|
||||
// CHECK:STDOUT: name_scopes:
|
||||
// CHECK:STDOUT: name_scope0: {inst: inst10, parent_scope: name_scope<none>, has_error: false, extended_scopes: [], names: {name(Core): inst78000012, name0: inst78000049}}
|
||||
// CHECK:STDOUT: name_scope78000001: {inst: inst78000012, parent_scope: name_scope0, has_error: false, extended_scopes: [], names: {name3: inst78000059}}
|
||||
|
||||
@@ -29,6 +29,7 @@ fn Foo(n: ()) -> ((), ()) {
|
||||
// CHECK:STDOUT: import_ir_insts: {}
|
||||
// CHECK:STDOUT: clang_decls: {}
|
||||
// CHECK:STDOUT: clang_decl_signatures: {}
|
||||
// CHECK:STDOUT: default_values: {}
|
||||
// CHECK:STDOUT: name_scopes:
|
||||
// CHECK:STDOUT: name_scope0: {inst: inst10, parent_scope: name_scope<none>, has_error: false, extended_scopes: [], names: {name0: inst5000002F}}
|
||||
// CHECK:STDOUT: entity_names:
|
||||
|
||||
@@ -170,7 +170,7 @@ fn F(x: C = {});
|
||||
// CHECK:STDOUT: %a.patt: %pattern_type.d8d = wrapper_binding_pattern a, %a.param_patt [concrete]
|
||||
// CHECK:STDOUT: %empty_struct: %empty_struct_type = struct_value () [concrete]
|
||||
// CHECK:STDOUT: %C.val: %C = struct_value () [concrete]
|
||||
// CHECK:STDOUT: %.68d: %pattern_type.d8d = default_value_pattern %a.patt, index: 0 [concrete]
|
||||
// CHECK:STDOUT: %.e44: %pattern_type.d8d = default_value_pattern %a.patt, @F.%.loc10_16.7 [concrete]
|
||||
// CHECK:STDOUT: %C.as.ImplicitAs.impl.Convert.bound: <bound method> = bound_method %C.val, %C.as.ImplicitAs.impl.Convert [concrete]
|
||||
// CHECK:STDOUT: %.115: ref %C = temporary invalid, %C.val [concrete]
|
||||
// CHECK:STDOUT: %F.type: type = fn_type @F [concrete]
|
||||
@@ -181,7 +181,7 @@ fn F(x: C = {});
|
||||
// CHECK:STDOUT: %F.decl: %F.type = fn_decl @F [concrete = constants.%F] {
|
||||
// CHECK:STDOUT: %a.param_patt: %pattern_type.d8d = value_param_pattern [concrete = constants.%a.param_patt]
|
||||
// CHECK:STDOUT: %a.patt: %pattern_type.d8d = wrapper_binding_pattern a, %a.param_patt [concrete = constants.%a.patt]
|
||||
// CHECK:STDOUT: %.loc10_11: %pattern_type.d8d = default_value_pattern %a.patt, index: 0 [concrete = constants.%.68d]
|
||||
// CHECK:STDOUT: %.loc10_11: %pattern_type.d8d = default_value_pattern %a.patt, %.loc10_16.7 [concrete = constants.%.e44]
|
||||
// CHECK:STDOUT: } {
|
||||
// CHECK:STDOUT: %.loc10_14.1: %empty_struct_type = struct_literal () [concrete = constants.%empty_struct]
|
||||
// CHECK:STDOUT: %C.ref: type = name_ref C, file.%C.decl [concrete = constants.%C]
|
||||
@@ -203,10 +203,7 @@ fn F(x: C = {});
|
||||
// CHECK:STDOUT: }
|
||||
// CHECK:STDOUT: }
|
||||
// CHECK:STDOUT:
|
||||
// CHECK:STDOUT: fn @F(%a.param: %D) {
|
||||
// CHECK:STDOUT: !default_values:
|
||||
// CHECK:STDOUT: %.loc10_16.7: %D = acquire_value %.loc10_16.6
|
||||
// CHECK:STDOUT: }
|
||||
// CHECK:STDOUT: fn @F(%a.param: %D);
|
||||
// CHECK:STDOUT:
|
||||
// CHECK:STDOUT: --- nested.carbon
|
||||
// CHECK:STDOUT:
|
||||
@@ -240,7 +237,7 @@ fn F(x: C = {});
|
||||
// CHECK:STDOUT: %tuple.56c: %tuple.type.6ca = tuple_value (%empty_struct, %tuple.9a3) [concrete]
|
||||
// CHECK:STDOUT: %tuple.type.bcdf: type = tuple_type (%empty_struct_type, %tuple.type.6ca) [concrete]
|
||||
// CHECK:STDOUT: %tuple.4f4: %tuple.type.bcdf = tuple_value (%empty_struct, %tuple.56c) [concrete]
|
||||
// CHECK:STDOUT: %.b6d: %pattern_type.f5f = default_value_pattern %.341, index: 0 [concrete]
|
||||
// CHECK:STDOUT: %.391: %pattern_type.f5f = default_value_pattern %.341, @F.%.loc6_62.6 [concrete]
|
||||
// CHECK:STDOUT: %C.val: %C = struct_value () [concrete]
|
||||
// CHECK:STDOUT: %.115: ref %C = temporary invalid, %C.val [concrete]
|
||||
// CHECK:STDOUT: %tuple.d3e: %tuple.type.748 = tuple_value (%C.val, %C.val) [concrete]
|
||||
@@ -265,7 +262,7 @@ fn F(x: C = {});
|
||||
// CHECK:STDOUT: %.loc6_37: %pattern_type.8b4 = tuple_pattern (%d.patt, %e.patt) [concrete = constants.%.fe8]
|
||||
// CHECK:STDOUT: %.loc6_38: %pattern_type.4fa = tuple_pattern (%c.patt, %.loc6_37) [concrete = constants.%.972]
|
||||
// CHECK:STDOUT: %.loc6_39: %pattern_type.f5f = tuple_pattern (%b.patt, %.loc6_38) [concrete = constants.%.341]
|
||||
// CHECK:STDOUT: %.loc6_41: %pattern_type.f5f = default_value_pattern %.loc6_39, index: 0 [concrete = constants.%.b6d]
|
||||
// CHECK:STDOUT: %.loc6_41: %pattern_type.f5f = default_value_pattern %.loc6_39, %.loc6_62.6 [concrete = constants.%.391]
|
||||
// CHECK:STDOUT: } {
|
||||
// CHECK:STDOUT: %.loc6_45.1: %empty_struct_type = struct_literal () [concrete = constants.%empty_struct]
|
||||
// CHECK:STDOUT: %.loc6_50.1: %empty_struct_type = struct_literal () [concrete = constants.%empty_struct]
|
||||
@@ -321,10 +318,7 @@ fn F(x: C = {});
|
||||
// CHECK:STDOUT: }
|
||||
// CHECK:STDOUT: }
|
||||
// CHECK:STDOUT:
|
||||
// CHECK:STDOUT: fn @F(%a.param: %C, %b.param: %C, %c.param: %C, %d.param: %C, %e.param: %C) {
|
||||
// CHECK:STDOUT: !default_values:
|
||||
// CHECK:STDOUT: %.loc6_62.6: %tuple.type.a40 = converted %.loc6_62.1, %tuple.loc6_62 [concrete = constants.%tuple.800]
|
||||
// CHECK:STDOUT: }
|
||||
// CHECK:STDOUT: fn @F(%a.param: %C, %b.param: %C, %c.param: %C, %d.param: %C, %e.param: %C);
|
||||
// CHECK:STDOUT:
|
||||
// CHECK:STDOUT: --- basic.carbon
|
||||
// CHECK:STDOUT:
|
||||
@@ -335,7 +329,7 @@ fn F(x: C = {});
|
||||
// CHECK:STDOUT: %x.param_patt: %pattern_type = value_param_pattern [concrete]
|
||||
// CHECK:STDOUT: %x.patt: %pattern_type = wrapper_binding_pattern x, %x.param_patt [concrete]
|
||||
// CHECK:STDOUT: %empty_struct: %empty_struct_type = struct_value () [concrete]
|
||||
// CHECK:STDOUT: %.015: %pattern_type = default_value_pattern %x.patt, index: 0 [concrete]
|
||||
// CHECK:STDOUT: %.ff4: %pattern_type = default_value_pattern %x.patt, @F.%.loc6_14.6 [concrete]
|
||||
// CHECK:STDOUT: %C.val: %C = struct_value () [concrete]
|
||||
// CHECK:STDOUT: %.115: ref %C = temporary invalid, %C.val [concrete]
|
||||
// CHECK:STDOUT: %F.type: type = fn_type @F [concrete]
|
||||
@@ -346,7 +340,7 @@ fn F(x: C = {});
|
||||
// CHECK:STDOUT: %F.decl: %F.type = fn_decl @F [concrete = constants.%F] {
|
||||
// CHECK:STDOUT: %x.param_patt: %pattern_type = value_param_pattern [concrete = constants.%x.param_patt]
|
||||
// CHECK:STDOUT: %x.patt: %pattern_type = wrapper_binding_pattern x, %x.param_patt [concrete = constants.%x.patt]
|
||||
// CHECK:STDOUT: %.loc6_11: %pattern_type = default_value_pattern %x.patt, index: 0 [concrete = constants.%.015]
|
||||
// CHECK:STDOUT: %.loc6_11: %pattern_type = default_value_pattern %x.patt, %.loc6_14.6 [concrete = constants.%.ff4]
|
||||
// CHECK:STDOUT: } {
|
||||
// CHECK:STDOUT: %.loc6_14.1: %empty_struct_type = struct_literal () [concrete = constants.%empty_struct]
|
||||
// CHECK:STDOUT: %x.param: %C = value_param call_param0
|
||||
@@ -360,8 +354,5 @@ fn F(x: C = {});
|
||||
// CHECK:STDOUT: }
|
||||
// CHECK:STDOUT: }
|
||||
// CHECK:STDOUT:
|
||||
// CHECK:STDOUT: fn @F(%x.param: %C) {
|
||||
// CHECK:STDOUT: !default_values:
|
||||
// CHECK:STDOUT: %.loc6_14.6: %C = acquire_value %.loc6_14.5 [concrete = constants.%C.val]
|
||||
// CHECK:STDOUT: }
|
||||
// CHECK:STDOUT: fn @F(%x.param: %C);
|
||||
// CHECK:STDOUT:
|
||||
|
||||
@@ -14,12 +14,12 @@
|
||||
library "[[@TEST_NAME]]";
|
||||
|
||||
fn F(x: i32 = 0, y: i32 = 10);
|
||||
// CHECK:STDERR: fail_defaults_different_values_redecl.carbon:[[@LINE+7]]:41: error: redeclaration syntax differs here [RedeclParamSyntaxDiffers]
|
||||
// CHECK:STDERR: fail_defaults_different_values_redecl.carbon:[[@LINE+7]]:25: error: redeclaration differs at parameter 2 [RedeclParamDiffers]
|
||||
// CHECK:STDERR: fn F(unused x: i32 = 0, unused y: i32 = 22) { }
|
||||
// CHECK:STDERR: ^~
|
||||
// CHECK:STDERR: fail_defaults_different_values_redecl.carbon:[[@LINE-4]]:27: note: comparing with previous declaration here [RedeclParamSyntaxPrevious]
|
||||
// CHECK:STDERR: ^~~~~~~~~~~~~~~~~~
|
||||
// CHECK:STDERR: fail_defaults_different_values_redecl.carbon:[[@LINE-4]]:18: note: previous declaration's corresponding parameter here [RedeclParamPrevious]
|
||||
// CHECK:STDERR: fn F(x: i32 = 0, y: i32 = 10);
|
||||
// CHECK:STDERR: ^~
|
||||
// CHECK:STDERR: ^~~~~~~~~~~
|
||||
// CHECK:STDERR:
|
||||
fn F(unused x: i32 = 0, unused y: i32 = 22) { }
|
||||
|
||||
@@ -49,13 +49,13 @@ fn F(x: i32 = 0, y: i32 = 10);
|
||||
// --- fail_imported_defaults_different_values.impl.carbon
|
||||
impl library "[[@TEST_NAME]]";
|
||||
|
||||
// CHECK:STDERR: fail_imported_defaults_different_values.impl.carbon:[[@LINE+8]]:41: error: default value of `22` differs from the previously declared default value of `10` [PatternDefaultValueDiffers]
|
||||
// CHECK:STDERR: fail_imported_defaults_different_values.impl.carbon:[[@LINE+8]]:25: error: redeclaration differs at parameter 2 [RedeclParamDiffers]
|
||||
// CHECK:STDERR: fn F(unused x: i32 = 0, unused y: i32 = 22) { }
|
||||
// CHECK:STDERR: ^~
|
||||
// CHECK:STDERR: ^~~~~~~~~~~~~~~~~~
|
||||
// CHECK:STDERR: fail_imported_defaults_different_values.impl.carbon:[[@LINE-5]]:1: in import [InImport]
|
||||
// CHECK:STDERR: imported_defaults_different_values.carbon:3:27: note: different previous declaration here [PatternDefaultValueDiffersNote]
|
||||
// CHECK:STDERR: imported_defaults_different_values.carbon:3:18: note: previous declaration's corresponding parameter here [RedeclParamPrevious]
|
||||
// CHECK:STDERR: fn F(x: i32 = 0, y: i32 = 10);
|
||||
// CHECK:STDERR: ^~
|
||||
// CHECK:STDERR: ^~~~~~~~~~~
|
||||
// CHECK:STDERR:
|
||||
fn F(unused x: i32 = 0, unused y: i32 = 22) { }
|
||||
|
||||
@@ -104,7 +104,6 @@ fn F(x: i32 = _) -> i32 { return x; }
|
||||
// CHECK:STDOUT: %x.param_patt: %pattern_type.6b6 = value_param_pattern [concrete]
|
||||
// CHECK:STDOUT: %x.patt: %pattern_type.6b6 = wrapper_binding_pattern x, %x.param_patt [concrete]
|
||||
// CHECK:STDOUT: %int_0.5c6: Core.IntLiteral = int_value 0 [concrete]
|
||||
// CHECK:STDOUT: %.e53: %pattern_type.6b6 = default_value_pattern %x.patt, index: 0 [concrete]
|
||||
// CHECK:STDOUT: %.795f: Core.Form = init_form %i32 [concrete]
|
||||
// CHECK:STDOUT: %return.param_patt.a9a: %pattern_type.6b6 = out_param_pattern [concrete]
|
||||
// CHECK:STDOUT: %return.patt.e1b: %pattern_type.6b6 = return_slot_pattern %return.param_patt.a9a, %i32 [concrete]
|
||||
@@ -126,6 +125,7 @@ fn F(x: i32 = _) -> i32 { return x; }
|
||||
// CHECK:STDOUT: %F: %F.type = struct_value () [concrete]
|
||||
// CHECK:STDOUT: %G.type: type = fn_type @G [concrete]
|
||||
// CHECK:STDOUT: %G: %G.type = struct_value () [concrete]
|
||||
// CHECK:STDOUT: %.d3f: %pattern_type.6b6 = default_value_pattern %x.patt, @F.%.loc7_15.2 [concrete]
|
||||
// CHECK:STDOUT: %Copy.type: type = facet_type <@Copy> [concrete]
|
||||
// CHECK:STDOUT: %Int.as.Copy.impl.Op.type.ac8: type = fn_type @Int.as.Copy.impl.Op, @Int.as.Copy.impl(%N) [symbolic]
|
||||
// CHECK:STDOUT: %Int.as.Copy.impl.Op.5e0: %Int.as.Copy.impl.Op.type.ac8 = struct_value () [symbolic]
|
||||
@@ -137,6 +137,7 @@ fn F(x: i32 = _) -> i32 { return x; }
|
||||
// CHECK:STDOUT: %.737: type = fn_type_with_self_type %Copy.WithSelf.Op.type.381, %Copy.facet [concrete]
|
||||
// CHECK:STDOUT: %Int.as.Copy.impl.Op.specific_fn: <specific function> = specific_function %Int.as.Copy.impl.Op.4f6, @Int.as.Copy.impl.Op(%int_32) [concrete]
|
||||
// CHECK:STDOUT: %.d49: <unspecified_value> = unspecified_value [concrete]
|
||||
// CHECK:STDOUT: %.5aa: %pattern_type.6b6 = default_value_pattern %x.patt, <unspecified> [concrete]
|
||||
// CHECK:STDOUT: }
|
||||
// CHECK:STDOUT:
|
||||
// CHECK:STDOUT: imports {
|
||||
@@ -150,7 +151,7 @@ fn F(x: i32 = _) -> i32 { return x; }
|
||||
// CHECK:STDOUT: %F.decl.loc7: %F.type = fn_decl @F [concrete = constants.%F] {
|
||||
// CHECK:STDOUT: %x.param_patt: %pattern_type.6b6 = value_param_pattern [concrete = constants.%x.param_patt]
|
||||
// CHECK:STDOUT: %x.patt: %pattern_type.6b6 = wrapper_binding_pattern x, %x.param_patt [concrete = constants.%x.patt]
|
||||
// CHECK:STDOUT: %.loc7_13: %pattern_type.6b6 = default_value_pattern %x.patt, index: 0 [concrete = constants.%.e53]
|
||||
// CHECK:STDOUT: %.loc7_13: %pattern_type.6b6 = default_value_pattern %x.patt, %.loc7_15.2 [concrete = constants.%.d3f]
|
||||
// CHECK:STDOUT: %return.param_patt: %pattern_type.6b6 = out_param_pattern [concrete = constants.%return.param_patt.a9a]
|
||||
// CHECK:STDOUT: %return.patt: %pattern_type.6b6 = return_slot_pattern %return.param_patt, %i32.loc7_21 [concrete = constants.%return.patt.e1b]
|
||||
// CHECK:STDOUT: } {
|
||||
@@ -173,7 +174,7 @@ fn F(x: i32 = _) -> i32 { return x; }
|
||||
// CHECK:STDOUT: %G.decl.loc8: %G.type = fn_decl @G [concrete = constants.%G] {
|
||||
// CHECK:STDOUT: %x.param_patt: %pattern_type.6b6 = value_param_pattern [concrete = constants.%x.param_patt]
|
||||
// CHECK:STDOUT: %x.patt: %pattern_type.6b6 = wrapper_binding_pattern x, %x.param_patt [concrete = constants.%x.patt]
|
||||
// CHECK:STDOUT: %.loc8_13: %pattern_type.6b6 = default_value_pattern %x.patt, index: 0 [concrete = constants.%.e53]
|
||||
// CHECK:STDOUT: %.loc8_13: %pattern_type.6b6 = default_value_pattern %x.patt, <unspecified> [concrete = constants.%.5aa]
|
||||
// CHECK:STDOUT: %return.param_patt: %pattern_type.6b6 = out_param_pattern [concrete = constants.%return.param_patt.a9a]
|
||||
// CHECK:STDOUT: %return.patt: %pattern_type.6b6 = return_slot_pattern %return.param_patt, %i32.loc8_21 [concrete = constants.%return.patt.e1b]
|
||||
// CHECK:STDOUT: } {
|
||||
@@ -189,9 +190,6 @@ fn F(x: i32 = _) -> i32 { return x; }
|
||||
// CHECK:STDOUT: }
|
||||
// CHECK:STDOUT:
|
||||
// CHECK:STDOUT: fn @F(%x.param.loc7: %i32) -> out %return.param.loc7: %i32 {
|
||||
// CHECK:STDOUT: !default_values:
|
||||
// CHECK:STDOUT: <elided>
|
||||
// CHECK:STDOUT:
|
||||
// CHECK:STDOUT: !entry:
|
||||
// CHECK:STDOUT: %x.ref: %i32 = name_ref x, %x.loc7
|
||||
// CHECK:STDOUT: %impl.elem0.loc7_34: %.737 = impl_witness_access constants.%Copy.impl_witness.b51, element0 [concrete = constants.%Int.as.Copy.impl.Op.4f6]
|
||||
@@ -203,9 +201,6 @@ fn F(x: i32 = _) -> i32 { return x; }
|
||||
// CHECK:STDOUT: }
|
||||
// CHECK:STDOUT:
|
||||
// CHECK:STDOUT: fn @G(%x.param.loc8: %i32) -> out %return.param.loc8: %i32 {
|
||||
// CHECK:STDOUT: !default_values:
|
||||
// CHECK:STDOUT: <elided>
|
||||
// CHECK:STDOUT:
|
||||
// CHECK:STDOUT: !entry:
|
||||
// CHECK:STDOUT: %x.ref: %i32 = name_ref x, %x.loc8
|
||||
// CHECK:STDOUT: %impl.elem0.loc8: %.737 = impl_witness_access constants.%Copy.impl_witness.b51, element0 [concrete = constants.%Int.as.Copy.impl.Op.4f6]
|
||||
@@ -229,7 +224,7 @@ fn F(x: i32 = _) -> i32 { return x; }
|
||||
// CHECK:STDOUT: %x.param_patt: %pattern_type.6b6 = value_param_pattern [concrete]
|
||||
// CHECK:STDOUT: %x.patt: %pattern_type.6b6 = wrapper_binding_pattern x, %x.param_patt [concrete]
|
||||
// CHECK:STDOUT: %int_0.5c6: Core.IntLiteral = int_value 0 [concrete]
|
||||
// CHECK:STDOUT: %.e53: %pattern_type.6b6 = default_value_pattern %x.patt, index: 0 [concrete]
|
||||
// CHECK:STDOUT: %.3d1: %pattern_type.6b6 = default_value_pattern %x.patt, @F.%.loc4_15.2 [concrete]
|
||||
// CHECK:STDOUT: %.795f: Core.Form = init_form %i32 [concrete]
|
||||
// CHECK:STDOUT: %return.param_patt.a9a: %pattern_type.6b6 = out_param_pattern [concrete]
|
||||
// CHECK:STDOUT: %return.patt.e1b: %pattern_type.6b6 = return_slot_pattern %return.param_patt.a9a, %i32 [concrete]
|
||||
@@ -269,7 +264,7 @@ fn F(x: i32 = _) -> i32 { return x; }
|
||||
// CHECK:STDOUT: %F.decl: %F.type = fn_decl @F [concrete = constants.%F] {
|
||||
// CHECK:STDOUT: %x.param_patt: %pattern_type.6b6 = value_param_pattern [concrete = constants.%x.param_patt]
|
||||
// CHECK:STDOUT: %x.patt: %pattern_type.6b6 = wrapper_binding_pattern x, %x.param_patt [concrete = constants.%x.patt]
|
||||
// CHECK:STDOUT: %.loc4_13: %pattern_type.6b6 = default_value_pattern %x.patt, index: 0 [concrete = constants.%.e53]
|
||||
// CHECK:STDOUT: %.loc4_13: %pattern_type.6b6 = default_value_pattern %x.patt, %.loc4_15.2 [concrete = constants.%.3d1]
|
||||
// CHECK:STDOUT: %return.param_patt: %pattern_type.6b6 = out_param_pattern [concrete = constants.%return.param_patt.a9a]
|
||||
// CHECK:STDOUT: %return.patt: %pattern_type.6b6 = return_slot_pattern %return.param_patt, %i32.loc4_21 [concrete = constants.%return.patt.e1b]
|
||||
// CHECK:STDOUT: } {
|
||||
@@ -292,9 +287,6 @@ fn F(x: i32 = _) -> i32 { return x; }
|
||||
// CHECK:STDOUT: }
|
||||
// CHECK:STDOUT:
|
||||
// CHECK:STDOUT: fn @F(%x.param: %i32) -> out %return.param: %i32 [from "imported_repeated_defaults.carbon"] {
|
||||
// CHECK:STDOUT: !default_values:
|
||||
// CHECK:STDOUT: <elided>
|
||||
// CHECK:STDOUT:
|
||||
// CHECK:STDOUT: !entry:
|
||||
// CHECK:STDOUT: %x.ref: %i32 = name_ref x, %x
|
||||
// CHECK:STDOUT: %impl.elem0.loc4_34: %.737 = impl_witness_access constants.%Copy.impl_witness.b51, element0 [concrete = constants.%Int.as.Copy.impl.Op.4f6]
|
||||
@@ -315,7 +307,7 @@ fn F(x: i32 = _) -> i32 { return x; }
|
||||
// CHECK:STDOUT: %x.param_patt: %pattern_type.6b6 = value_param_pattern [concrete]
|
||||
// CHECK:STDOUT: %x.patt: %pattern_type.6b6 = wrapper_binding_pattern x, %x.param_patt [concrete]
|
||||
// CHECK:STDOUT: %.d49: <unspecified_value> = unspecified_value [concrete]
|
||||
// CHECK:STDOUT: %.e53: %pattern_type.6b6 = default_value_pattern %x.patt, index: 0 [concrete]
|
||||
// CHECK:STDOUT: %.c5e: %pattern_type.6b6 = default_value_pattern %x.patt, <unspecified> [concrete]
|
||||
// CHECK:STDOUT: %.795f: Core.Form = init_form %i32 [concrete]
|
||||
// CHECK:STDOUT: %return.param_patt.a9a: %pattern_type.6b6 = out_param_pattern [concrete]
|
||||
// CHECK:STDOUT: %return.patt.e1b: %pattern_type.6b6 = return_slot_pattern %return.param_patt.a9a, %i32 [concrete]
|
||||
@@ -342,7 +334,7 @@ fn F(x: i32 = _) -> i32 { return x; }
|
||||
// CHECK:STDOUT: %F.decl: %F.type = fn_decl @F [concrete = constants.%F] {
|
||||
// CHECK:STDOUT: %x.param_patt: %pattern_type.6b6 = value_param_pattern [concrete = constants.%x.param_patt]
|
||||
// CHECK:STDOUT: %x.patt: %pattern_type.6b6 = wrapper_binding_pattern x, %x.param_patt [concrete = constants.%x.patt]
|
||||
// CHECK:STDOUT: %.loc4_13: %pattern_type.6b6 = default_value_pattern %x.patt, index: 0 [concrete = constants.%.e53]
|
||||
// CHECK:STDOUT: %.loc4_13: %pattern_type.6b6 = default_value_pattern %x.patt, <unspecified> [concrete = constants.%.c5e]
|
||||
// CHECK:STDOUT: %return.param_patt: %pattern_type.6b6 = out_param_pattern [concrete = constants.%return.param_patt.a9a]
|
||||
// CHECK:STDOUT: %return.patt: %pattern_type.6b6 = return_slot_pattern %return.param_patt, %i32.loc4_21 [concrete = constants.%return.patt.e1b]
|
||||
// CHECK:STDOUT: } {
|
||||
@@ -358,9 +350,6 @@ fn F(x: i32 = _) -> i32 { return x; }
|
||||
// CHECK:STDOUT: }
|
||||
// CHECK:STDOUT:
|
||||
// CHECK:STDOUT: fn @F(%x.param: %i32) -> out %return.param: %i32 [from "imported_elided_defaults_in_def.carbon"] {
|
||||
// CHECK:STDOUT: !default_values:
|
||||
// CHECK:STDOUT: <elided>
|
||||
// CHECK:STDOUT:
|
||||
// CHECK:STDOUT: !entry:
|
||||
// CHECK:STDOUT: %x.ref: %i32 = name_ref x, %x
|
||||
// CHECK:STDOUT: %impl.elem0: %.737 = impl_witness_access constants.%Copy.impl_witness.b51, element0 [concrete = constants.%Int.as.Copy.impl.Op.4f6]
|
||||
|
||||
@@ -249,7 +249,6 @@ static auto CloneFunctionDecl(Context& context, SemIR::LocId loc_id,
|
||||
{
|
||||
.call_param_patterns_id = match_results.call_param_patterns_id,
|
||||
.call_params_id = match_results.call_params_id,
|
||||
.call_param_default_values_id = SemIR::InstBlockId::Empty,
|
||||
.call_param_ranges = match_results.param_ranges,
|
||||
.return_type_inst_id = return_type_inst_id,
|
||||
.return_form_inst_id = return_form_inst_id,
|
||||
|
||||
@@ -620,8 +620,6 @@ CARBON_DIAGNOSTIC_KIND(GenericMissingExplicitParameters)
|
||||
CARBON_DIAGNOSTIC_KIND(RequiredPatternDefaultValueMissing)
|
||||
CARBON_DIAGNOSTIC_KIND(RequiredPatternDefaultValueFirstDefault)
|
||||
CARBON_DIAGNOSTIC_KIND(RequiredPatternDefaultValueMissingAdditional)
|
||||
CARBON_DIAGNOSTIC_KIND(PatternDefaultValueDiffers)
|
||||
CARBON_DIAGNOSTIC_KIND(PatternDefaultValueDiffersNote)
|
||||
CARBON_DIAGNOSTIC_KIND(PatternDefaultValueNotConstant)
|
||||
CARBON_DIAGNOSTIC_KIND(PatternDefaultValueNotInParameterList)
|
||||
CARBON_DIAGNOSTIC_KIND(PatternDefaultValueNotSpecified)
|
||||
|
||||
+1
@@ -33,6 +33,7 @@
|
||||
// CHECK:STDOUT: import_ir_insts: {}
|
||||
// CHECK:STDOUT: clang_decls: {}
|
||||
// CHECK:STDOUT: clang_decl_signatures: {}
|
||||
// CHECK:STDOUT: default_values: {}
|
||||
// CHECK:STDOUT: name_scopes:
|
||||
// CHECK:STDOUT: name_scope0: {inst: inst10, parent_scope: name_scope<none>, has_error: false, extended_scopes: [], names: {}}
|
||||
// CHECK:STDOUT: entity_names: {}
|
||||
|
||||
@@ -100,6 +100,7 @@ cc_library(
|
||||
"cpp_initializer_list.cpp",
|
||||
"cpp_overload_set.cpp",
|
||||
"declared_facet_type.cpp",
|
||||
"default_value.cpp",
|
||||
"entity_name.cpp",
|
||||
"field.cpp",
|
||||
"file.cpp",
|
||||
@@ -135,6 +136,7 @@ cc_library(
|
||||
"cpp_initializer_list.h",
|
||||
"cpp_overload_set.h",
|
||||
"declared_facet_type.h",
|
||||
"default_value.h",
|
||||
"entity_name.h",
|
||||
"entity_with_params_base.h",
|
||||
"field.h",
|
||||
|
||||
@@ -0,0 +1,12 @@
|
||||
// Part of the Carbon Language project, under the Apache License v2.0 with LLVM
|
||||
// Exceptions. See /LICENSE for license information.
|
||||
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
|
||||
#include "toolchain/sem_ir/default_value.h"
|
||||
|
||||
#include "toolchain/base/value_store_impl.h"
|
||||
|
||||
namespace Carbon {
|
||||
template class ValueStore<SemIR::DefaultValueId, SemIR::DefaultValue,
|
||||
Tag<SemIR::CheckIRId>>;
|
||||
} // namespace Carbon
|
||||
@@ -0,0 +1,45 @@
|
||||
// Part of the Carbon Language project, under the Apache License v2.0 with LLVM
|
||||
// Exceptions. See /LICENSE for license information.
|
||||
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
|
||||
#ifndef CARBON_TOOLCHAIN_SEM_IR_DEFAULT_VALUE_H_
|
||||
#define CARBON_TOOLCHAIN_SEM_IR_DEFAULT_VALUE_H_
|
||||
|
||||
#include "toolchain/base/value_store.h"
|
||||
#include "toolchain/sem_ir/ids.h"
|
||||
|
||||
namespace Carbon::SemIR {
|
||||
|
||||
// Information about a default value for a pattern, such as default values for
|
||||
// function parameters.
|
||||
struct DefaultValue : public Printable<DefaultValue> {
|
||||
auto Print(llvm::raw_ostream& out) const -> void {
|
||||
out << "{raw_id: " << raw_id << ", value_id: " << value_id
|
||||
<< ", is_unspecified: " << is_unspecified << "}";
|
||||
}
|
||||
|
||||
// The instruction specifying the default value as specified by the developer,
|
||||
// before conversion to the pattern scrutinee type is applied.
|
||||
InstId raw_id;
|
||||
|
||||
// The instruction specifying the default value in the same type as the
|
||||
// scrutinee type.
|
||||
InstId value_id;
|
||||
|
||||
// Whether the user left this default value unspecified. The `value_id` will
|
||||
// be `None` but the `raw_id` will contain the `UnspecifiedValue` instruction
|
||||
// for use in diagnostics if needed.
|
||||
bool is_unspecified;
|
||||
};
|
||||
|
||||
using DefaultValueStore =
|
||||
ValueStore<DefaultValueId, DefaultValue, Tag<SemIR::CheckIRId>>;
|
||||
|
||||
} // namespace Carbon::SemIR
|
||||
|
||||
namespace Carbon {
|
||||
extern template class ValueStore<SemIR::DefaultValueId, SemIR::DefaultValue,
|
||||
Tag<SemIR::CheckIRId>>;
|
||||
}
|
||||
|
||||
#endif // CARBON_TOOLCHAIN_SEM_IR_DEFAULT_VALUE_H_
|
||||
+27
-11
@@ -255,17 +255,6 @@ LLVM_DUMP_METHOD auto Dump(const File& file, CppOverloadSetId overload_set_id)
|
||||
return out.TakeStr();
|
||||
}
|
||||
|
||||
LLVM_DUMP_METHOD auto Dump(const File& file, EntityNameId entity_name_id)
|
||||
-> std::string {
|
||||
RawStringOstream out;
|
||||
out << entity_name_id;
|
||||
if (entity_name_id.has_value()) {
|
||||
auto entity_name = file.entity_names().Get(entity_name_id);
|
||||
out << ": " << entity_name << DumpNameOfEntityName(file, entity_name);
|
||||
}
|
||||
return out.TakeStr();
|
||||
}
|
||||
|
||||
LLVM_DUMP_METHOD auto Dump(const File& file,
|
||||
DeclaredFacetTypeId declared_facet_type_id)
|
||||
-> std::string {
|
||||
@@ -314,6 +303,30 @@ LLVM_DUMP_METHOD auto Dump(const File& file,
|
||||
return out.TakeStr();
|
||||
}
|
||||
|
||||
LLVM_DUMP_METHOD auto Dump(const File& file, DefaultValueId value_id)
|
||||
-> std::string {
|
||||
RawStringOstream out;
|
||||
out << value_id;
|
||||
if (value_id.has_value()) {
|
||||
const auto& default_value = file.default_values().Get(value_id);
|
||||
out << ": " << default_value
|
||||
<< "\n - raw: " << DumpInstSummary(file, default_value.raw_id)
|
||||
<< "\n - value: " << DumpInstSummary(file, default_value.value_id);
|
||||
}
|
||||
return out.TakeStr();
|
||||
}
|
||||
|
||||
LLVM_DUMP_METHOD auto Dump(const File& file, EntityNameId entity_name_id)
|
||||
-> std::string {
|
||||
RawStringOstream out;
|
||||
out << entity_name_id;
|
||||
if (entity_name_id.has_value()) {
|
||||
auto entity_name = file.entity_names().Get(entity_name_id);
|
||||
out << ": " << entity_name << DumpNameOfEntityName(file, entity_name);
|
||||
}
|
||||
return out.TakeStr();
|
||||
}
|
||||
|
||||
LLVM_DUMP_METHOD auto Dump(const File& file, FieldId field_id) -> std::string {
|
||||
RawStringOstream out;
|
||||
out << field_id;
|
||||
@@ -655,6 +668,9 @@ LLVM_DUMP_METHOD static auto MakeConstantId(int id) -> ConstantId {
|
||||
LLVM_DUMP_METHOD auto MakeSymbolicConstantId(int id) -> ConstantId {
|
||||
return ConstantId::ForSymbolicConstantId(ConstantId::SymbolicId(id));
|
||||
}
|
||||
LLVM_DUMP_METHOD static auto MakeDefaultValueId(int id) -> DefaultValueId {
|
||||
return DefaultValueId(id);
|
||||
}
|
||||
LLVM_DUMP_METHOD static auto MakeEntityNameId(int id) -> EntityNameId {
|
||||
return EntityNameId(id);
|
||||
}
|
||||
|
||||
@@ -28,9 +28,10 @@ auto Dump(const File& file, GeneratedFunctionId generated_function_id)
|
||||
auto Dump(const File& file, ClassId class_id) -> std::string;
|
||||
auto Dump(const File& file, ConstantId const_id) -> std::string;
|
||||
auto Dump(const File& file, CppOverloadSetId overload_set_id) -> std::string;
|
||||
auto Dump(const File& file, EntityNameId entity_name_id) -> std::string;
|
||||
auto Dump(const File& file, DeclaredFacetTypeId declared_facet_type_id)
|
||||
-> std::string;
|
||||
auto Dump(const File& file, DefaultValueId default_value_id) -> std::string;
|
||||
auto Dump(const File& file, EntityNameId entity_name_id) -> std::string;
|
||||
auto Dump(const File& file, FieldId field_id) -> std::string;
|
||||
auto Dump(const File& file, FunctionId function_id) -> std::string;
|
||||
auto Dump(const File& file, GenericId generic_id) -> std::string;
|
||||
|
||||
@@ -40,6 +40,7 @@ File::File(const Parse::Tree* parse_tree, CheckIRId check_ir_id,
|
||||
value_stores_(&value_stores),
|
||||
filename_(std::move(filename)),
|
||||
entity_names_(check_ir_id),
|
||||
default_values_(check_ir_id),
|
||||
functions_(check_ir_id),
|
||||
generated_functions_(check_ir_id),
|
||||
cpp_overload_sets_(check_ir_id),
|
||||
@@ -160,6 +161,7 @@ auto File::OutputYaml(bool include_singletons) const -> Yaml::OutputMapping {
|
||||
map.Add("import_ir_insts", import_ir_insts_.OutputYaml());
|
||||
map.Add("clang_decls", clang_decls_.OutputYaml());
|
||||
map.Add("clang_decl_signatures", clang_decl_signatures_.OutputYaml());
|
||||
map.Add("default_values", default_values_.OutputYaml());
|
||||
map.Add("name_scopes", name_scopes_.OutputYaml());
|
||||
map.Add("entity_names", entity_names_.OutputYaml());
|
||||
map.Add("functions", functions_.OutputYaml());
|
||||
@@ -200,6 +202,8 @@ auto File::CollectMemUsage(MemUsage& mem_usage, llvm::StringRef label) const
|
||||
mem_usage.Collect(MemUsage::ConcatLabel(label, "functions_"), functions_);
|
||||
mem_usage.Collect(MemUsage::ConcatLabel(label, "thunks_"), thunks_);
|
||||
mem_usage.Collect(MemUsage::ConcatLabel(label, "classes_"), classes_);
|
||||
mem_usage.Collect(MemUsage::ConcatLabel(label, "default_values_"),
|
||||
default_values_);
|
||||
mem_usage.Collect(MemUsage::ConcatLabel(label, "interfaces_"), interfaces_);
|
||||
mem_usage.Collect(MemUsage::ConcatLabel(label, "impls_"), impls_);
|
||||
mem_usage.Collect(MemUsage::ConcatLabel(label, "generics_"), generics_);
|
||||
|
||||
@@ -25,6 +25,7 @@
|
||||
#include "toolchain/sem_ir/cpp_file.h"
|
||||
#include "toolchain/sem_ir/cpp_overload_set.h"
|
||||
#include "toolchain/sem_ir/declared_facet_type.h"
|
||||
#include "toolchain/sem_ir/default_value.h"
|
||||
#include "toolchain/sem_ir/entity_name.h"
|
||||
#include "toolchain/sem_ir/field.h"
|
||||
#include "toolchain/sem_ir/function.h"
|
||||
@@ -222,6 +223,10 @@ class File : public Printable<File> {
|
||||
auto declared_facet_types() const -> const DeclaredFacetTypeStore& {
|
||||
return declared_facet_types_;
|
||||
}
|
||||
auto default_values() const -> const DefaultValueStore& {
|
||||
return default_values_;
|
||||
}
|
||||
auto default_values() -> DefaultValueStore& { return default_values_; }
|
||||
|
||||
// If `class_id` is an imported C++ class, appends the Clang mangled name of
|
||||
// its type to `out` and returns true. Otherwise returns false and leaves
|
||||
@@ -365,6 +370,9 @@ class File : public Printable<File> {
|
||||
// Storage for EntityNames.
|
||||
EntityNameStore entity_names_;
|
||||
|
||||
// Storage for DefaultValues.
|
||||
DefaultValueStore default_values_;
|
||||
|
||||
// Storage for callable objects.
|
||||
FunctionStore functions_;
|
||||
|
||||
|
||||
@@ -598,17 +598,10 @@ auto Formatter::FormatFunction(FunctionId id, const Function& fn) -> void {
|
||||
out() << "]";
|
||||
}
|
||||
|
||||
if (!fn.body_block_ids.empty() ||
|
||||
fn.call_param_default_values_id != SemIR::InstBlockId::Empty) {
|
||||
if (!fn.body_block_ids.empty()) {
|
||||
out() << ' ';
|
||||
OpenBrace();
|
||||
|
||||
if (fn.call_param_default_values_id != SemIR::InstBlockId::Empty) {
|
||||
IndentLabel();
|
||||
out() << "!default_values:\n";
|
||||
FormatCodeBlock(fn.call_param_default_values_id);
|
||||
}
|
||||
|
||||
for (auto block_id : fn.body_block_ids) {
|
||||
IndentLabel();
|
||||
FormatLabel(block_id);
|
||||
@@ -1646,7 +1639,12 @@ auto Formatter::FormatArg(DeclaredFacetTypeId id) -> void {
|
||||
}
|
||||
|
||||
auto Formatter::FormatArg(DefaultValueId id) -> void {
|
||||
out() << "index: " << id.index;
|
||||
const auto& default_value = sem_ir_->default_values().Get(id);
|
||||
if (default_value.is_unspecified) {
|
||||
out() << "<unspecified>";
|
||||
} else {
|
||||
FormatArg(default_value.value_id);
|
||||
}
|
||||
}
|
||||
|
||||
auto Formatter::FormatArg(FieldId id) -> void {
|
||||
|
||||
@@ -82,9 +82,6 @@ struct FunctionFields {
|
||||
// because it is relevant only for a function definition.
|
||||
InstBlockId call_params_id;
|
||||
|
||||
// Instructions representing the default values for parameters.
|
||||
InstBlockId call_param_default_values_id;
|
||||
|
||||
// The index ranges within the `Call` parameters that correspond to the
|
||||
// implicit parameters, explicit parameters, and return.
|
||||
//
|
||||
@@ -234,9 +231,6 @@ struct Function : public EntityWithParamsBase,
|
||||
if (call_params_id.has_value()) {
|
||||
out << ", call_params_id: " << call_params_id;
|
||||
}
|
||||
if (call_param_default_values_id != SemIR::InstBlockId::Empty) {
|
||||
out << ", call_param_default_values_id: " << call_param_default_values_id;
|
||||
}
|
||||
if (return_type_inst_id.has_value()) {
|
||||
out << ", return_type_inst_id: " << return_type_inst_id;
|
||||
}
|
||||
|
||||
@@ -116,11 +116,11 @@ class AbsoluteInstId : public InstId {
|
||||
using InstId::InstId;
|
||||
};
|
||||
|
||||
// An id representing the index of the default value constant instruction in
|
||||
// a default values instruction block.
|
||||
// The ID of a default value.
|
||||
class DefaultValueId : public IdBase<DefaultValueId> {
|
||||
public:
|
||||
static constexpr llvm::StringLiteral Label = "default_value_id";
|
||||
static constexpr llvm::StringLiteral Label = "default_value";
|
||||
|
||||
using IdBase::IdBase;
|
||||
};
|
||||
|
||||
|
||||
@@ -62,6 +62,7 @@ TEST(SemIRTest, Yaml) {
|
||||
Pair("import_ir_insts", Yaml::Mapping(SizeIs(0))),
|
||||
Pair("clang_decls", Yaml::Mapping(SizeIs(0))),
|
||||
Pair("clang_decl_signatures", Yaml::Mapping(SizeIs(0))),
|
||||
Pair("default_values", Yaml::Mapping(SizeIs(0))),
|
||||
Pair("name_scopes", Yaml::Mapping(SizeIs(1))),
|
||||
Pair("entity_names", Yaml::Mapping(SizeIs(1))),
|
||||
Pair("functions", Yaml::Mapping(SizeIs(1))),
|
||||
|
||||
Reference in New Issue
Block a user