mirror of
https://github.com/carbon-language/carbon-lang.git
synced 2026-09-24 19:30:12 +01:00
location -> loc abbreviation (#3826)
This commit is contained in:
+24
-26
@@ -26,13 +26,13 @@ namespace Carbon::Check {
|
||||
auto Handle##Name(Context& context, Parse::Name##Id node_id) -> bool;
|
||||
#include "toolchain/parse/node_kind.def"
|
||||
|
||||
// Handles the transformation of a SemIRLocation to a DiagnosticLocation.
|
||||
// Handles the transformation of a SemIRLoc to a DiagnosticLoc.
|
||||
//
|
||||
// TODO: Move this to diagnostic_helpers.cpp.
|
||||
class SemIRDiagnosticConverter : public DiagnosticConverter<SemIRLocation> {
|
||||
class SemIRDiagnosticConverter : public DiagnosticConverter<SemIRLoc> {
|
||||
public:
|
||||
explicit SemIRDiagnosticConverter(
|
||||
const llvm::DenseMap<const SemIR::File*, Parse::NodeLocationConverter*>*
|
||||
const llvm::DenseMap<const SemIR::File*, Parse::NodeLocConverter*>*
|
||||
node_converters,
|
||||
const SemIR::File* sem_ir)
|
||||
: node_converters_(node_converters), sem_ir_(sem_ir) {}
|
||||
@@ -40,8 +40,8 @@ class SemIRDiagnosticConverter : public DiagnosticConverter<SemIRLocation> {
|
||||
// Converts an instruction's location to a diagnostic location, which will be
|
||||
// the underlying line of code. Adds context for any imports used in the
|
||||
// current SemIR to get to the underlying code.
|
||||
auto ConvertLocation(SemIRLocation loc, ContextFnT context_fn) const
|
||||
-> DiagnosticLocation override {
|
||||
auto ConvertLoc(SemIRLoc loc, ContextFnT context_fn) const
|
||||
-> DiagnosticLoc override {
|
||||
// Cursors for the current IR and instruction in that IR.
|
||||
const auto* cursor_ir = sem_ir_;
|
||||
auto cursor_inst_id = SemIR::InstId::Invalid;
|
||||
@@ -51,8 +51,8 @@ class SemIRDiagnosticConverter : public DiagnosticConverter<SemIRLocation> {
|
||||
auto follow_import_ref = [&](SemIR::ImportIRId ir_id,
|
||||
SemIR::InstId inst_id) {
|
||||
const auto& import_ir = cursor_ir->import_irs().Get(ir_id);
|
||||
auto context_loc = ConvertLocationInFile(cursor_ir, import_ir.node_id,
|
||||
loc.token_only, context_fn);
|
||||
auto context_loc = ConvertLocInFile(cursor_ir, import_ir.node_id,
|
||||
loc.token_only, context_fn);
|
||||
CARBON_DIAGNOSTIC(InImport, Note, "In import.");
|
||||
context_fn(context_loc, InImport);
|
||||
cursor_ir = import_ir.sem_ir;
|
||||
@@ -61,8 +61,7 @@ class SemIRDiagnosticConverter : public DiagnosticConverter<SemIRLocation> {
|
||||
|
||||
// If the location is is an import, follows it and returns nullopt.
|
||||
// Otherwise, it's a parse node, so return the final location.
|
||||
auto handle_loc =
|
||||
[&](SemIR::LocationId loc_id) -> std::optional<DiagnosticLocation> {
|
||||
auto handle_loc = [&](SemIR::LocId loc_id) -> std::optional<DiagnosticLoc> {
|
||||
if (loc_id.is_import_ir_inst_id()) {
|
||||
auto import_ir_inst =
|
||||
cursor_ir->import_ir_insts().Get(loc_id.import_ir_inst_id());
|
||||
@@ -70,8 +69,8 @@ class SemIRDiagnosticConverter : public DiagnosticConverter<SemIRLocation> {
|
||||
return std::nullopt;
|
||||
} else {
|
||||
// Parse nodes always refer to the current IR.
|
||||
return ConvertLocationInFile(cursor_ir, loc_id.node_id(),
|
||||
loc.token_only, context_fn);
|
||||
return ConvertLocInFile(cursor_ir, loc_id.node_id(), loc.token_only,
|
||||
context_fn);
|
||||
}
|
||||
};
|
||||
|
||||
@@ -87,7 +86,7 @@ class SemIRDiagnosticConverter : public DiagnosticConverter<SemIRLocation> {
|
||||
|
||||
while (true) {
|
||||
// If the parse node is valid, use it for the location.
|
||||
if (auto loc_id = cursor_ir->insts().GetLocationId(cursor_inst_id);
|
||||
if (auto loc_id = cursor_ir->insts().GetLocId(cursor_inst_id);
|
||||
loc_id.is_valid()) {
|
||||
if (auto diag_loc = handle_loc(loc_id)) {
|
||||
return *diag_loc;
|
||||
@@ -114,8 +113,8 @@ class SemIRDiagnosticConverter : public DiagnosticConverter<SemIRLocation> {
|
||||
}
|
||||
|
||||
// Invalid parse node but not an import; just nothing to point at.
|
||||
return ConvertLocationInFile(cursor_ir, Parse::NodeId::Invalid,
|
||||
loc.token_only, context_fn);
|
||||
return ConvertLocInFile(cursor_ir, Parse::NodeId::Invalid, loc.token_only,
|
||||
context_fn);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -130,20 +129,20 @@ class SemIRDiagnosticConverter : public DiagnosticConverter<SemIRLocation> {
|
||||
return llvm::APSInt(typed_int->value,
|
||||
!sem_ir_->types().IsSignedInt(typed_int->type));
|
||||
}
|
||||
return DiagnosticConverter<SemIRLocation>::ConvertArg(arg);
|
||||
return DiagnosticConverter<SemIRLoc>::ConvertArg(arg);
|
||||
}
|
||||
|
||||
private:
|
||||
auto ConvertLocationInFile(const SemIR::File* sem_ir, Parse::NodeId node_id,
|
||||
bool token_only, ContextFnT context_fn) const
|
||||
-> DiagnosticLocation {
|
||||
auto ConvertLocInFile(const SemIR::File* sem_ir, Parse::NodeId node_id,
|
||||
bool token_only, ContextFnT context_fn) const
|
||||
-> DiagnosticLoc {
|
||||
auto it = node_converters_->find(sem_ir);
|
||||
CARBON_CHECK(it != node_converters_->end());
|
||||
return it->second->ConvertLocation(Parse::NodeLocation(node_id, token_only),
|
||||
context_fn);
|
||||
return it->second->ConvertLoc(Parse::NodeLoc(node_id, token_only),
|
||||
context_fn);
|
||||
}
|
||||
|
||||
const llvm::DenseMap<const SemIR::File*, Parse::NodeLocationConverter*>*
|
||||
const llvm::DenseMap<const SemIR::File*, Parse::NodeLocConverter*>*
|
||||
node_converters_;
|
||||
const SemIR::File* sem_ir_;
|
||||
};
|
||||
@@ -181,9 +180,9 @@ struct UnitInfo {
|
||||
Unit* unit;
|
||||
|
||||
// Emitter information.
|
||||
Parse::NodeLocationConverter converter;
|
||||
Parse::NodeLocConverter converter;
|
||||
ErrorTrackingDiagnosticConsumer err_tracker;
|
||||
DiagnosticEmitter<Parse::NodeLocation> emitter;
|
||||
DiagnosticEmitter<Parse::NodeLoc> emitter;
|
||||
|
||||
// A map of package names to outgoing imports. If the
|
||||
// import's target isn't available, the unit will be nullptr to assist with
|
||||
@@ -300,7 +299,7 @@ static auto ProcessNodeIds(Context& context,
|
||||
|
||||
// Produces and checks the IR for the provided Parse::Tree.
|
||||
static auto CheckParseTree(
|
||||
llvm::DenseMap<const SemIR::File*, Parse::NodeLocationConverter*>*
|
||||
llvm::DenseMap<const SemIR::File*, Parse::NodeLocConverter*>*
|
||||
node_converters,
|
||||
const SemIR::File& builtin_ir, UnitInfo& unit_info,
|
||||
llvm::raw_ostream* vlog_stream) -> void {
|
||||
@@ -626,8 +625,7 @@ auto CheckParseTrees(const SemIR::File& builtin_ir,
|
||||
}
|
||||
}
|
||||
|
||||
llvm::DenseMap<const SemIR::File*, Parse::NodeLocationConverter*>
|
||||
node_converters;
|
||||
llvm::DenseMap<const SemIR::File*, Parse::NodeLocConverter*> node_converters;
|
||||
|
||||
// Check everything with no dependencies. Earlier entries with dependencies
|
||||
// will be checked as soon as all their dependencies have been checked.
|
||||
|
||||
+17
-18
@@ -51,7 +51,7 @@ Context::Context(const Lex::TokenizedBuffer& tokens, DiagnosticEmitter& emitter,
|
||||
SemIR::TypeId::TypeType});
|
||||
}
|
||||
|
||||
auto Context::TODO(SemIRLocation loc, std::string label) -> bool {
|
||||
auto Context::TODO(SemIRLoc loc, std::string label) -> bool {
|
||||
CARBON_DIAGNOSTIC(SemanticsTodo, Error, "Semantics TODO: `{0}`.",
|
||||
std::string);
|
||||
emitter_->Emit(loc, SemanticsTodo, std::move(label));
|
||||
@@ -68,7 +68,7 @@ auto Context::VerifyOnFinish() -> void {
|
||||
param_and_arg_refs_stack_.VerifyOnFinish();
|
||||
}
|
||||
|
||||
auto Context::AddInstInNoBlock(SemIR::LocationIdAndInst loc_id_and_inst)
|
||||
auto Context::AddInstInNoBlock(SemIR::LocIdAndInst loc_id_and_inst)
|
||||
-> SemIR::InstId {
|
||||
auto inst_id = sem_ir().insts().AddInNoBlock(loc_id_and_inst);
|
||||
CARBON_VLOG() << "AddInst: " << loc_id_and_inst.inst << "\n";
|
||||
@@ -83,22 +83,21 @@ auto Context::AddInstInNoBlock(SemIR::LocationIdAndInst loc_id_and_inst)
|
||||
return inst_id;
|
||||
}
|
||||
|
||||
auto Context::AddInst(SemIR::LocationIdAndInst loc_id_and_inst)
|
||||
-> SemIR::InstId {
|
||||
auto Context::AddInst(SemIR::LocIdAndInst loc_id_and_inst) -> SemIR::InstId {
|
||||
auto inst_id = AddInstInNoBlock(loc_id_and_inst);
|
||||
inst_block_stack_.AddInstId(inst_id);
|
||||
return inst_id;
|
||||
}
|
||||
|
||||
auto Context::AddPlaceholderInstInNoBlock(
|
||||
SemIR::LocationIdAndInst loc_id_and_inst) -> SemIR::InstId {
|
||||
auto Context::AddPlaceholderInstInNoBlock(SemIR::LocIdAndInst loc_id_and_inst)
|
||||
-> SemIR::InstId {
|
||||
auto inst_id = sem_ir().insts().AddInNoBlock(loc_id_and_inst);
|
||||
CARBON_VLOG() << "AddPlaceholderInst: " << loc_id_and_inst.inst << "\n";
|
||||
constant_values().Set(inst_id, SemIR::ConstantId::Invalid);
|
||||
return inst_id;
|
||||
}
|
||||
|
||||
auto Context::AddPlaceholderInst(SemIR::LocationIdAndInst loc_id_and_inst)
|
||||
auto Context::AddPlaceholderInst(SemIR::LocIdAndInst loc_id_and_inst)
|
||||
-> SemIR::InstId {
|
||||
auto inst_id = AddPlaceholderInstInNoBlock(loc_id_and_inst);
|
||||
inst_block_stack_.AddInstId(inst_id);
|
||||
@@ -112,14 +111,14 @@ auto Context::AddConstant(SemIR::Inst inst, bool is_symbolic)
|
||||
return const_id;
|
||||
}
|
||||
|
||||
auto Context::AddInstAndPush(SemIR::LocationIdAndInst loc_id_and_inst) -> void {
|
||||
auto Context::AddInstAndPush(SemIR::LocIdAndInst loc_id_and_inst) -> void {
|
||||
auto inst_id = AddInst(loc_id_and_inst);
|
||||
node_stack_.Push(loc_id_and_inst.loc_id.node_id(), inst_id);
|
||||
}
|
||||
|
||||
auto Context::ReplaceLocationIdAndInstBeforeConstantUse(
|
||||
SemIR::InstId inst_id, SemIR::LocationIdAndInst loc_id_and_inst) -> void {
|
||||
sem_ir().insts().SetLocationIdAndInst(inst_id, loc_id_and_inst);
|
||||
auto Context::ReplaceLocIdAndInstBeforeConstantUse(
|
||||
SemIR::InstId inst_id, SemIR::LocIdAndInst loc_id_and_inst) -> void {
|
||||
sem_ir().insts().SetLocIdAndInst(inst_id, loc_id_and_inst);
|
||||
|
||||
CARBON_VLOG() << "ReplaceInst: " << inst_id << " -> " << loc_id_and_inst.inst
|
||||
<< "\n";
|
||||
@@ -169,8 +168,8 @@ auto Context::AddImportRef(SemIR::ImportIRId ir_id, SemIR::InstId inst_id)
|
||||
return import_ref_id;
|
||||
}
|
||||
|
||||
auto Context::DiagnoseDuplicateName(SemIRLocation dup_def,
|
||||
SemIRLocation prev_def) -> void {
|
||||
auto Context::DiagnoseDuplicateName(SemIRLoc dup_def, SemIRLoc prev_def)
|
||||
-> void {
|
||||
CARBON_DIAGNOSTIC(NameDeclDuplicate, Error,
|
||||
"Duplicate name being declared in the same scope.");
|
||||
CARBON_DIAGNOSTIC(NameDeclPrevious, Note,
|
||||
@@ -180,8 +179,8 @@ auto Context::DiagnoseDuplicateName(SemIRLocation dup_def,
|
||||
.Emit();
|
||||
}
|
||||
|
||||
auto Context::DiagnoseNameNotFound(SemIR::LocationId loc_id,
|
||||
SemIR::NameId name_id) -> void {
|
||||
auto Context::DiagnoseNameNotFound(SemIR::LocId loc_id, SemIR::NameId name_id)
|
||||
-> void {
|
||||
CARBON_DIAGNOSTIC(NameNotFound, Error, "Name `{0}` not found.",
|
||||
SemIR::NameId);
|
||||
emitter_->Emit(loc_id, NameNotFound, name_id);
|
||||
@@ -226,7 +225,7 @@ auto Context::AddNameToLookup(SemIR::NameId name_id, SemIR::InstId target_id)
|
||||
}
|
||||
}
|
||||
|
||||
auto Context::LookupNameInDecl(SemIR::LocationId loc_id, SemIR::NameId name_id,
|
||||
auto Context::LookupNameInDecl(SemIR::LocId loc_id, SemIR::NameId name_id,
|
||||
SemIR::NameScopeId scope_id) -> SemIR::InstId {
|
||||
if (!scope_id.is_valid()) {
|
||||
// Look for a name in the current scope only. There are two cases where the
|
||||
@@ -296,7 +295,7 @@ auto Context::LookupUnqualifiedName(Parse::NodeId node_id,
|
||||
}
|
||||
|
||||
// Handles lookup through the import_ir_scopes for LookupNameInExactScope.
|
||||
static auto LookupInImportIRScopes(Context& context, SemIRLocation loc,
|
||||
static auto LookupInImportIRScopes(Context& context, SemIRLoc loc,
|
||||
SemIR::NameId name_id,
|
||||
const SemIR::NameScope& scope)
|
||||
-> SemIR::InstId {
|
||||
@@ -350,7 +349,7 @@ static auto LookupInImportIRScopes(Context& context, SemIRLocation loc,
|
||||
return result_id;
|
||||
}
|
||||
|
||||
auto Context::LookupNameInExactScope(SemIRLocation loc, SemIR::NameId name_id,
|
||||
auto Context::LookupNameInExactScope(SemIRLoc loc, SemIR::NameId name_id,
|
||||
const SemIR::NameScope& scope)
|
||||
-> SemIR::InstId {
|
||||
if (auto it = scope.names.find(name_id); it != scope.names.end()) {
|
||||
|
||||
+16
-19
@@ -26,7 +26,7 @@ namespace Carbon::Check {
|
||||
// Context and shared functionality for semantics handlers.
|
||||
class Context {
|
||||
public:
|
||||
using DiagnosticEmitter = Carbon::DiagnosticEmitter<SemIRLocation>;
|
||||
using DiagnosticEmitter = Carbon::DiagnosticEmitter<SemIRLoc>;
|
||||
using DiagnosticBuilder = DiagnosticEmitter::DiagnosticBuilder;
|
||||
|
||||
// Stores references for work.
|
||||
@@ -35,44 +35,43 @@ class Context {
|
||||
SemIR::File& sem_ir, llvm::raw_ostream* vlog_stream);
|
||||
|
||||
// Marks an implementation TODO. Always returns false.
|
||||
auto TODO(SemIRLocation loc, std::string label) -> bool;
|
||||
auto TODO(SemIRLoc loc, std::string label) -> bool;
|
||||
|
||||
// Runs verification that the processing cleanly finished.
|
||||
auto VerifyOnFinish() -> void;
|
||||
|
||||
// Adds an instruction to the current block, returning the produced ID.
|
||||
auto AddInst(SemIR::LocationIdAndInst loc_id_and_inst) -> SemIR::InstId;
|
||||
auto AddInst(SemIR::LocIdAndInst loc_id_and_inst) -> SemIR::InstId;
|
||||
|
||||
// Adds an instruction in no block, returning the produced ID. Should be used
|
||||
// rarely.
|
||||
auto AddInstInNoBlock(SemIR::LocationIdAndInst loc_id_and_inst)
|
||||
-> SemIR::InstId;
|
||||
auto AddInstInNoBlock(SemIR::LocIdAndInst loc_id_and_inst) -> SemIR::InstId;
|
||||
|
||||
// Adds an instruction to the current block, returning the produced ID. The
|
||||
// instruction is a placeholder that is expected to be replaced by
|
||||
// `ReplaceInstBeforeConstantUse`.
|
||||
auto AddPlaceholderInst(SemIR::LocationIdAndInst loc_id_and_inst)
|
||||
-> SemIR::InstId;
|
||||
auto AddPlaceholderInst(SemIR::LocIdAndInst loc_id_and_inst) -> SemIR::InstId;
|
||||
|
||||
// Adds an instruction in no block, returning the produced ID. Should be used
|
||||
// rarely. The instruction is a placeholder that is expected to be replaced by
|
||||
// `ReplaceInstBeforeConstantUse`.
|
||||
auto AddPlaceholderInstInNoBlock(SemIR::LocationIdAndInst loc_id_and_inst)
|
||||
auto AddPlaceholderInstInNoBlock(SemIR::LocIdAndInst loc_id_and_inst)
|
||||
-> SemIR::InstId;
|
||||
|
||||
// Adds an instruction to the constants block, returning the produced ID.
|
||||
auto AddConstant(SemIR::Inst inst, bool is_symbolic) -> SemIR::ConstantId;
|
||||
|
||||
// Pushes a parse tree node onto the stack, storing the SemIR::Inst as the
|
||||
// result. Only valid if the LocationId is for a NodeId.
|
||||
auto AddInstAndPush(SemIR::LocationIdAndInst loc_id_and_inst) -> void;
|
||||
// result. Only valid if the LocId is for a NodeId.
|
||||
auto AddInstAndPush(SemIR::LocIdAndInst loc_id_and_inst) -> void;
|
||||
|
||||
// Replaces the instruction `inst_id` with `loc_id_and_inst`. The instruction
|
||||
// is required to not have been used in any constant evaluation, either
|
||||
// because it's newly created and entirely unused, or because it's only used
|
||||
// in a position that constant evaluation ignores, such as a return slot.
|
||||
auto ReplaceLocationIdAndInstBeforeConstantUse(
|
||||
SemIR::InstId inst_id, SemIR::LocationIdAndInst loc_id_and_inst) -> void;
|
||||
auto ReplaceLocIdAndInstBeforeConstantUse(SemIR::InstId inst_id,
|
||||
SemIR::LocIdAndInst loc_id_and_inst)
|
||||
-> void;
|
||||
|
||||
// Replaces the instruction `inst_id` with `inst`, not affecting location.
|
||||
// The instruction is required to not have been used in any constant
|
||||
@@ -94,7 +93,7 @@ class Context {
|
||||
// remain const.
|
||||
auto SetNamespaceNodeId(SemIR::InstId inst_id, Parse::NodeId node_id)
|
||||
-> void {
|
||||
sem_ir().insts().SetLocationId(inst_id, SemIR::LocationId(node_id));
|
||||
sem_ir().insts().SetLocId(inst_id, SemIR::LocId(node_id));
|
||||
}
|
||||
|
||||
// Adds a name to name lookup. Prints a diagnostic for name conflicts.
|
||||
@@ -103,7 +102,7 @@ class Context {
|
||||
// Performs name lookup in a specified scope for a name appearing in a
|
||||
// declaration, returning the referenced instruction. If scope_id is invalid,
|
||||
// uses the current contextual scope.
|
||||
auto LookupNameInDecl(SemIR::LocationId loc_id, SemIR::NameId name_id,
|
||||
auto LookupNameInDecl(SemIR::LocId loc_id, SemIR::NameId name_id,
|
||||
SemIR::NameScopeId scope_id) -> SemIR::InstId;
|
||||
|
||||
// Performs an unqualified name lookup, returning the referenced instruction.
|
||||
@@ -113,7 +112,7 @@ class Context {
|
||||
// Performs a name lookup in a specified scope, returning the referenced
|
||||
// instruction. Does not look into extended scopes. Returns an invalid
|
||||
// instruction if the name is not found.
|
||||
auto LookupNameInExactScope(SemIRLocation loc, SemIR::NameId name_id,
|
||||
auto LookupNameInExactScope(SemIRLoc loc, SemIR::NameId name_id,
|
||||
const SemIR::NameScope& scope) -> SemIR::InstId;
|
||||
|
||||
// Performs a qualified name lookup in a specified scope and in scopes that
|
||||
@@ -123,12 +122,10 @@ class Context {
|
||||
-> SemIR::InstId;
|
||||
|
||||
// Prints a diagnostic for a duplicate name.
|
||||
auto DiagnoseDuplicateName(SemIRLocation dup_def, SemIRLocation prev_def)
|
||||
-> void;
|
||||
auto DiagnoseDuplicateName(SemIRLoc dup_def, SemIRLoc prev_def) -> void;
|
||||
|
||||
// Prints a diagnostic for a missing name.
|
||||
auto DiagnoseNameNotFound(SemIR::LocationId loc_id, SemIR::NameId name_id)
|
||||
-> void;
|
||||
auto DiagnoseNameNotFound(SemIR::LocId loc_id, SemIR::NameId name_id) -> void;
|
||||
|
||||
// Adds a note to a diagnostic explaining that a class is incomplete.
|
||||
auto NoteIncompleteClass(SemIR::ClassId class_id, DiagnosticBuilder& builder)
|
||||
|
||||
+27
-28
@@ -96,7 +96,7 @@ static auto FinalizeTemporary(Context& context, SemIR::InstId init_id,
|
||||
<< sem_ir.insts().Get(return_slot_id);
|
||||
auto init = sem_ir.insts().Get(init_id);
|
||||
return context.AddInst(
|
||||
{sem_ir.insts().GetLocationId(init_id),
|
||||
{sem_ir.insts().GetLocId(init_id),
|
||||
SemIR::Temporary{init.type_id(), return_slot_id, init_id}});
|
||||
}
|
||||
|
||||
@@ -111,7 +111,7 @@ static auto FinalizeTemporary(Context& context, SemIR::InstId init_id,
|
||||
// materialize and initialize a temporary, rather than two separate
|
||||
// instructions.
|
||||
auto init = sem_ir.insts().Get(init_id);
|
||||
auto loc_id = sem_ir.insts().GetLocationId(init_id);
|
||||
auto loc_id = sem_ir.insts().GetLocId(init_id);
|
||||
auto temporary_id =
|
||||
context.AddInst({loc_id, SemIR::TemporaryStorage{init.type_id()}});
|
||||
return context.AddInst(
|
||||
@@ -131,7 +131,7 @@ static auto MaterializeIfInitializing(Context& context, SemIR::InstId expr_id)
|
||||
|
||||
// Creates and adds an instruction to perform element access into an aggregate.
|
||||
template <typename AccessInstT, typename InstBlockT>
|
||||
static auto MakeElementAccessInst(Context& context, SemIR::LocationId loc_id,
|
||||
static auto MakeElementAccessInst(Context& context, SemIR::LocId loc_id,
|
||||
SemIR::InstId aggregate_id,
|
||||
SemIR::TypeId elem_type_id, InstBlockT& block,
|
||||
std::size_t i) {
|
||||
@@ -166,7 +166,7 @@ static auto MakeElementAccessInst(Context& context, SemIR::LocationId loc_id,
|
||||
// instruction used to access the destination element.
|
||||
template <typename SourceAccessInstT, typename TargetAccessInstT>
|
||||
static auto ConvertAggregateElement(
|
||||
Context& context, SemIR::LocationId loc_id, SemIR::InstId src_id,
|
||||
Context& context, SemIR::LocId loc_id, SemIR::InstId src_id,
|
||||
SemIR::TypeId src_elem_type,
|
||||
llvm::ArrayRef<SemIR::InstId> src_literal_elems,
|
||||
ConversionTarget::Kind kind, SemIR::InstId target_id,
|
||||
@@ -206,7 +206,7 @@ static auto ConvertTupleToArray(Context& context, SemIR::TupleType tuple_type,
|
||||
auto tuple_elem_types = sem_ir.type_blocks().Get(tuple_type.elements_id);
|
||||
|
||||
auto value = sem_ir.insts().Get(value_id);
|
||||
auto value_loc_id = sem_ir.insts().GetLocationId(value_id);
|
||||
auto value_loc_id = sem_ir.insts().GetLocId(value_id);
|
||||
|
||||
// If we're initializing from a tuple literal, we will use its elements
|
||||
// directly. Otherwise, materialize a temporary if needed and index into the
|
||||
@@ -290,7 +290,7 @@ static auto ConvertTupleToTuple(Context& context, SemIR::TupleType src_type,
|
||||
auto dest_elem_types = sem_ir.type_blocks().Get(dest_type.elements_id);
|
||||
|
||||
auto value = sem_ir.insts().Get(value_id);
|
||||
auto value_loc_id = sem_ir.insts().GetLocationId(value_id);
|
||||
auto value_loc_id = sem_ir.insts().GetLocId(value_id);
|
||||
|
||||
// If we're initializing from a tuple literal, we will use its elements
|
||||
// directly. Otherwise, materialize a temporary if needed and index into the
|
||||
@@ -374,7 +374,7 @@ static auto ConvertStructToStructOrClass(Context& context,
|
||||
auto dest_elem_fields = sem_ir.inst_blocks().Get(dest_type.fields_id);
|
||||
|
||||
auto value = sem_ir.insts().Get(value_id);
|
||||
auto value_loc_id = sem_ir.insts().GetLocationId(value_id);
|
||||
auto value_loc_id = sem_ir.insts().GetLocId(value_id);
|
||||
|
||||
// If we're initializing from a struct literal, we will use its elements
|
||||
// directly. Otherwise, materialize a temporary if needed and index into the
|
||||
@@ -539,7 +539,7 @@ static auto ConvertStructToClass(Context& context, SemIR::StructType src_type,
|
||||
target.kind = ConversionTarget::Initializer;
|
||||
target.init_block = &target_block;
|
||||
target.init_id =
|
||||
target_block.AddInst({context.insts().GetLocationId(value_id),
|
||||
target_block.AddInst({context.insts().GetLocId(value_id),
|
||||
SemIR::TemporaryStorage{target.type_id}});
|
||||
}
|
||||
|
||||
@@ -549,7 +549,7 @@ static auto ConvertStructToClass(Context& context, SemIR::StructType src_type,
|
||||
if (need_temporary) {
|
||||
target_block.InsertHere();
|
||||
result_id = context.AddInst(
|
||||
{context.insts().GetLocationId(value_id),
|
||||
{context.insts().GetLocId(value_id),
|
||||
SemIR::Temporary{target.type_id, target.init_id, result_id}});
|
||||
}
|
||||
return result_id;
|
||||
@@ -596,7 +596,7 @@ static auto ComputeInheritancePath(Context& context, SemIR::TypeId derived_id,
|
||||
|
||||
// Performs a conversion from a derived class value or reference to a base class
|
||||
// value or reference.
|
||||
static auto ConvertDerivedToBase(Context& context, SemIR::LocationId loc_id,
|
||||
static auto ConvertDerivedToBase(Context& context, SemIR::LocId loc_id,
|
||||
SemIR::InstId value_id,
|
||||
const InheritancePath& path) -> SemIR::InstId {
|
||||
// Materialize a temporary if necessary.
|
||||
@@ -614,7 +614,7 @@ static auto ConvertDerivedToBase(Context& context, SemIR::LocationId loc_id,
|
||||
|
||||
// Performs a conversion from a derived class pointer to a base class pointer.
|
||||
static auto ConvertDerivedPointerToBasePointer(
|
||||
Context& context, SemIR::LocationId loc_id, SemIR::PointerType src_ptr_type,
|
||||
Context& context, SemIR::LocId loc_id, SemIR::PointerType src_ptr_type,
|
||||
SemIR::TypeId dest_ptr_type_id, SemIR::InstId ptr_id,
|
||||
const InheritancePath& path) -> SemIR::InstId {
|
||||
// Form `*p`.
|
||||
@@ -651,7 +651,7 @@ static auto IsValidExprCategoryForConversionTarget(
|
||||
}
|
||||
}
|
||||
|
||||
static auto PerformBuiltinConversion(Context& context, SemIR::LocationId loc_id,
|
||||
static auto PerformBuiltinConversion(Context& context, SemIR::LocId loc_id,
|
||||
SemIR::InstId value_id,
|
||||
ConversionTarget target) -> SemIR::InstId {
|
||||
auto& sem_ir = context.sem_ir();
|
||||
@@ -849,7 +849,7 @@ static auto PerformCopy(Context& context, SemIR::InstId expr_id)
|
||||
return SemIR::InstId::BuiltinError;
|
||||
}
|
||||
|
||||
auto Convert(Context& context, SemIR::LocationId loc_id, SemIR::InstId expr_id,
|
||||
auto Convert(Context& context, SemIR::LocId loc_id, SemIR::InstId expr_id,
|
||||
ConversionTarget target) -> SemIR::InstId {
|
||||
auto& sem_ir = context.sem_ir();
|
||||
auto orig_expr_id = expr_id;
|
||||
@@ -923,7 +923,7 @@ auto Convert(Context& context, SemIR::LocationId loc_id, SemIR::InstId expr_id,
|
||||
// Track that we performed a type conversion, if we did so.
|
||||
if (orig_expr_id != expr_id) {
|
||||
expr_id = context.AddInst(
|
||||
{context.insts().GetLocationId(orig_expr_id),
|
||||
{context.insts().GetLocId(orig_expr_id),
|
||||
SemIR::Converted{target.type_id, orig_expr_id, expr_id}});
|
||||
}
|
||||
|
||||
@@ -974,7 +974,7 @@ auto Convert(Context& context, SemIR::LocationId loc_id, SemIR::InstId expr_id,
|
||||
|
||||
// If we have a reference and don't want one, form a value binding.
|
||||
// TODO: Support types with custom value representations.
|
||||
expr_id = context.AddInst({context.insts().GetLocationId(expr_id),
|
||||
expr_id = context.AddInst({context.insts().GetLocId(expr_id),
|
||||
SemIR::BindValue{expr.type_id(), expr_id}});
|
||||
// We now have a value expression.
|
||||
[[fallthrough]];
|
||||
@@ -1001,9 +1001,8 @@ auto Convert(Context& context, SemIR::LocationId loc_id, SemIR::InstId expr_id,
|
||||
return expr_id;
|
||||
}
|
||||
|
||||
auto Initialize(Context& context, SemIR::LocationId loc_id,
|
||||
SemIR::InstId target_id, SemIR::InstId value_id)
|
||||
-> SemIR::InstId {
|
||||
auto Initialize(Context& context, SemIR::LocId loc_id, SemIR::InstId target_id,
|
||||
SemIR::InstId value_id) -> SemIR::InstId {
|
||||
PendingBlock target_block(context);
|
||||
return Convert(context, loc_id, value_id,
|
||||
{.kind = ConversionTarget::Initializer,
|
||||
@@ -1014,33 +1013,33 @@ auto Initialize(Context& context, SemIR::LocationId loc_id,
|
||||
|
||||
auto ConvertToValueExpr(Context& context, SemIR::InstId expr_id)
|
||||
-> SemIR::InstId {
|
||||
return Convert(context, context.insts().GetLocationId(expr_id), expr_id,
|
||||
return Convert(context, context.insts().GetLocId(expr_id), expr_id,
|
||||
{.kind = ConversionTarget::Value,
|
||||
.type_id = context.insts().Get(expr_id).type_id()});
|
||||
}
|
||||
|
||||
auto ConvertToValueOrRefExpr(Context& context, SemIR::InstId expr_id)
|
||||
-> SemIR::InstId {
|
||||
return Convert(context, context.insts().GetLocationId(expr_id), expr_id,
|
||||
return Convert(context, context.insts().GetLocId(expr_id), expr_id,
|
||||
{.kind = ConversionTarget::ValueOrRef,
|
||||
.type_id = context.insts().Get(expr_id).type_id()});
|
||||
}
|
||||
|
||||
auto ConvertToValueOfType(Context& context, SemIR::LocationId loc_id,
|
||||
auto ConvertToValueOfType(Context& context, SemIR::LocId loc_id,
|
||||
SemIR::InstId expr_id, SemIR::TypeId type_id)
|
||||
-> SemIR::InstId {
|
||||
return Convert(context, loc_id, expr_id,
|
||||
{.kind = ConversionTarget::Value, .type_id = type_id});
|
||||
}
|
||||
|
||||
auto ConvertToValueOrRefOfType(Context& context, SemIR::LocationId loc_id,
|
||||
auto ConvertToValueOrRefOfType(Context& context, SemIR::LocId loc_id,
|
||||
SemIR::InstId expr_id, SemIR::TypeId type_id)
|
||||
-> SemIR::InstId {
|
||||
return Convert(context, loc_id, expr_id,
|
||||
{.kind = ConversionTarget::ValueOrRef, .type_id = type_id});
|
||||
}
|
||||
|
||||
auto ConvertToBoolValue(Context& context, SemIR::LocationId loc_id,
|
||||
auto ConvertToBoolValue(Context& context, SemIR::LocId loc_id,
|
||||
SemIR::InstId value_id) -> SemIR::InstId {
|
||||
return ConvertToValueOfType(
|
||||
context, loc_id, value_id,
|
||||
@@ -1057,7 +1056,7 @@ auto ConvertForExplicitAs(Context& context, Parse::NodeId as_node,
|
||||
CARBON_DIAGNOSTIC(InCallToFunction, Note, "Calling function declared here.");
|
||||
|
||||
// Convert the object argument in a method call to match the `self` parameter.
|
||||
static auto ConvertSelf(Context& context, SemIR::LocationId call_loc_id,
|
||||
static auto ConvertSelf(Context& context, SemIR::LocId call_loc_id,
|
||||
SemIR::InstId callee_id,
|
||||
std::optional<SemIR::AddrPattern> addr_pattern,
|
||||
SemIR::InstId self_param_id, SemIR::Param self_param,
|
||||
@@ -1099,7 +1098,7 @@ static auto ConvertSelf(Context& context, SemIR::LocationId call_loc_id,
|
||||
context.emitter().Emit(TokenOnly(call_loc_id), AddrSelfIsNonRef);
|
||||
return SemIR::InstId::BuiltinError;
|
||||
}
|
||||
auto loc_id = context.insts().GetLocationId(self_or_addr_id);
|
||||
auto loc_id = context.insts().GetLocId(self_or_addr_id);
|
||||
self_or_addr_id = context.AddInst(
|
||||
{loc_id, SemIR::AddrOf{context.GetPointerType(self.type_id()),
|
||||
self_or_addr_id}});
|
||||
@@ -1109,7 +1108,7 @@ static auto ConvertSelf(Context& context, SemIR::LocationId call_loc_id,
|
||||
self_param.type_id);
|
||||
}
|
||||
|
||||
auto ConvertCallArgs(Context& context, SemIR::LocationId call_loc_id,
|
||||
auto ConvertCallArgs(Context& context, SemIR::LocId call_loc_id,
|
||||
SemIR::InstId self_id,
|
||||
llvm::ArrayRef<SemIR::InstId> arg_refs,
|
||||
SemIR::InstId return_storage_id, SemIR::InstId callee_id,
|
||||
@@ -1191,8 +1190,8 @@ auto ConvertCallArgs(Context& context, SemIR::LocationId call_loc_id,
|
||||
return context.inst_blocks().Add(args);
|
||||
}
|
||||
|
||||
auto ExprAsType(Context& context, SemIR::LocationId loc_id,
|
||||
SemIR::InstId value_id) -> SemIR::TypeId {
|
||||
auto ExprAsType(Context& context, SemIR::LocId loc_id, SemIR::InstId value_id)
|
||||
-> SemIR::TypeId {
|
||||
auto type_inst_id =
|
||||
ConvertToValueOfType(context, loc_id, value_id, SemIR::TypeId::TypeType);
|
||||
if (type_inst_id == SemIR::InstId::BuiltinError) {
|
||||
|
||||
@@ -50,15 +50,14 @@ struct ConversionTarget {
|
||||
};
|
||||
|
||||
// Convert a value to another type and expression category.
|
||||
auto Convert(Context& context, SemIR::LocationId loc_id, SemIR::InstId expr_id,
|
||||
auto Convert(Context& context, SemIR::LocId loc_id, SemIR::InstId expr_id,
|
||||
ConversionTarget target) -> SemIR::InstId;
|
||||
|
||||
// Performs initialization of `target_id` from `value_id`. Returns the
|
||||
// possibly-converted initializing expression, which should be assigned to the
|
||||
// target using a suitable node for the kind of initialization.
|
||||
auto Initialize(Context& context, SemIR::LocationId loc_id,
|
||||
SemIR::InstId target_id, SemIR::InstId value_id)
|
||||
-> SemIR::InstId;
|
||||
auto Initialize(Context& context, SemIR::LocId loc_id, SemIR::InstId target_id,
|
||||
SemIR::InstId value_id) -> SemIR::InstId;
|
||||
|
||||
// Convert the given expression to a value expression of the same type.
|
||||
auto ConvertToValueExpr(Context& context, SemIR::InstId expr_id)
|
||||
@@ -70,18 +69,18 @@ auto ConvertToValueOrRefExpr(Context& context, SemIR::InstId expr_id)
|
||||
-> SemIR::InstId;
|
||||
|
||||
// Converts `expr_id` to a value expression of type `type_id`.
|
||||
auto ConvertToValueOfType(Context& context, SemIR::LocationId loc_id,
|
||||
auto ConvertToValueOfType(Context& context, SemIR::LocId loc_id,
|
||||
SemIR::InstId expr_id, SemIR::TypeId type_id)
|
||||
-> SemIR::InstId;
|
||||
|
||||
// Convert the given expression to a value or reference expression of the given
|
||||
// type.
|
||||
auto ConvertToValueOrRefOfType(Context& context, SemIR::LocationId loc_id,
|
||||
auto ConvertToValueOrRefOfType(Context& context, SemIR::LocId loc_id,
|
||||
SemIR::InstId expr_id, SemIR::TypeId type_id)
|
||||
-> SemIR::InstId;
|
||||
|
||||
// Converts `value_id` to a value expression of type `bool`.
|
||||
auto ConvertToBoolValue(Context& context, SemIR::LocationId loc_id,
|
||||
auto ConvertToBoolValue(Context& context, SemIR::LocId loc_id,
|
||||
SemIR::InstId value_id) -> SemIR::InstId;
|
||||
|
||||
// Converts `value_id` to type `type_id` for an `as` expression.
|
||||
@@ -92,7 +91,7 @@ auto ConvertForExplicitAs(Context& context, Parse::NodeId as_node,
|
||||
// Implicitly converts a set of arguments to match the parameter types in a
|
||||
// function call. Returns a block containing the converted implicit and explicit
|
||||
// argument values.
|
||||
auto ConvertCallArgs(Context& context, SemIR::LocationId call_loc_id,
|
||||
auto ConvertCallArgs(Context& context, SemIR::LocId call_loc_id,
|
||||
SemIR::InstId self_id,
|
||||
llvm::ArrayRef<SemIR::InstId> arg_refs,
|
||||
SemIR::InstId return_storage_id, SemIR::InstId callee_id,
|
||||
@@ -100,8 +99,8 @@ auto ConvertCallArgs(Context& context, SemIR::LocationId call_loc_id,
|
||||
SemIR::InstBlockId param_refs_id) -> SemIR::InstBlockId;
|
||||
|
||||
// Converts an expression for use as a type.
|
||||
auto ExprAsType(Context& context, SemIR::LocationId loc_id,
|
||||
SemIR::InstId value_id) -> SemIR::TypeId;
|
||||
auto ExprAsType(Context& context, SemIR::LocId loc_id, SemIR::InstId value_id)
|
||||
-> SemIR::TypeId;
|
||||
|
||||
} // namespace Carbon::Check
|
||||
|
||||
|
||||
@@ -15,7 +15,7 @@ auto DeclNameStack::MakeEmptyNameContext() -> NameContext {
|
||||
.target_scope_id = context_->scope_stack().PeekNameScopeId()};
|
||||
}
|
||||
|
||||
auto DeclNameStack::MakeUnqualifiedName(SemIR::LocationId loc_id,
|
||||
auto DeclNameStack::MakeUnqualifiedName(SemIR::LocId loc_id,
|
||||
SemIR::NameId name_id) -> NameContext {
|
||||
NameContext context = MakeEmptyNameContext();
|
||||
ApplyNameQualifierTo(context, loc_id, name_id, /*is_unqualified=*/true);
|
||||
@@ -125,14 +125,14 @@ auto DeclNameStack::AddNameToLookup(NameContext name_context,
|
||||
}
|
||||
}
|
||||
|
||||
auto DeclNameStack::ApplyNameQualifier(SemIR::LocationId loc_id,
|
||||
auto DeclNameStack::ApplyNameQualifier(SemIR::LocId loc_id,
|
||||
SemIR::NameId name_id) -> void {
|
||||
ApplyNameQualifierTo(decl_name_stack_.back(), loc_id, name_id,
|
||||
/*is_unqualified=*/false);
|
||||
}
|
||||
|
||||
auto DeclNameStack::ApplyNameQualifierTo(NameContext& name_context,
|
||||
SemIR::LocationId loc_id,
|
||||
SemIR::LocId loc_id,
|
||||
SemIR::NameId name_id,
|
||||
bool is_unqualified) -> void {
|
||||
if (TryResolveQualifier(name_context, loc_id)) {
|
||||
@@ -241,7 +241,7 @@ auto DeclNameStack::UpdateScopeIfNeeded(NameContext& name_context,
|
||||
}
|
||||
|
||||
auto DeclNameStack::TryResolveQualifier(NameContext& name_context,
|
||||
SemIR::LocationId loc_id) -> bool {
|
||||
SemIR::LocId loc_id) -> bool {
|
||||
// Update has_qualifiers based on the state before any possible changes. If
|
||||
// this is the first qualifier, it may just be the name.
|
||||
name_context.has_qualifiers = name_context.state != NameContext::State::Empty;
|
||||
|
||||
@@ -124,7 +124,7 @@ class DeclNameStack {
|
||||
SemIR::NameScopeId target_scope_id;
|
||||
|
||||
// The last location ID used.
|
||||
SemIR::LocationId loc_id = SemIR::LocationId::Invalid;
|
||||
SemIR::LocId loc_id = SemIR::LocId::Invalid;
|
||||
|
||||
union {
|
||||
// The ID of a resolved qualifier, including both identifiers and
|
||||
@@ -176,14 +176,13 @@ class DeclNameStack {
|
||||
// unqualified name in the current context. This is suitable for adding to
|
||||
// name lookup in situations where a qualified name is not permitted, such as
|
||||
// a pattern binding.
|
||||
auto MakeUnqualifiedName(SemIR::LocationId loc_id, SemIR::NameId name_id)
|
||||
auto MakeUnqualifiedName(SemIR::LocId loc_id, SemIR::NameId name_id)
|
||||
-> NameContext;
|
||||
|
||||
// Applies a Name from the name stack to the top of the declaration name
|
||||
// stack. This will enter the scope corresponding to the name if the name
|
||||
// describes an existing scope, such as a namespace or a defined class.
|
||||
auto ApplyNameQualifier(SemIR::LocationId loc_id, SemIR::NameId name_id)
|
||||
-> void;
|
||||
auto ApplyNameQualifier(SemIR::LocId loc_id, SemIR::NameId name_id) -> void;
|
||||
|
||||
// Adds a name to name lookup. Prints a diagnostic for name conflicts.
|
||||
auto AddNameToLookup(NameContext name_context, SemIR::InstId target_id)
|
||||
@@ -199,12 +198,12 @@ class DeclNameStack {
|
||||
auto MakeEmptyNameContext() -> NameContext;
|
||||
|
||||
// Applies a Name from the name stack to given name context.
|
||||
auto ApplyNameQualifierTo(NameContext& name_context, SemIR::LocationId loc_id,
|
||||
auto ApplyNameQualifierTo(NameContext& name_context, SemIR::LocId loc_id,
|
||||
SemIR::NameId name_id, bool is_unqualified) -> void;
|
||||
|
||||
// Returns true if the context is in a state where it can resolve qualifiers.
|
||||
// Updates name_context as needed.
|
||||
auto TryResolveQualifier(NameContext& name_context, SemIR::LocationId loc_id)
|
||||
auto TryResolveQualifier(NameContext& name_context, SemIR::LocId loc_id)
|
||||
-> bool;
|
||||
|
||||
// Updates the scope on name_context as needed. This is called after
|
||||
|
||||
@@ -14,31 +14,31 @@ namespace Carbon::Check {
|
||||
|
||||
// Diagnostic locations produced by checking may be either a parse node
|
||||
// directly, or an inst ID which is later translated to a parse node.
|
||||
struct SemIRLocation {
|
||||
struct SemIRLoc {
|
||||
// NOLINTNEXTLINE(google-explicit-constructor)
|
||||
SemIRLocation(SemIR::InstId inst_id)
|
||||
SemIRLoc(SemIR::InstId inst_id)
|
||||
: inst_id(inst_id), is_inst_id(true), token_only(false) {}
|
||||
|
||||
// NOLINTNEXTLINE(google-explicit-constructor)
|
||||
SemIRLocation(Parse::NodeId node_id) : SemIRLocation(node_id, false) {}
|
||||
SemIRLoc(Parse::NodeId node_id) : SemIRLoc(node_id, false) {}
|
||||
|
||||
// NOLINTNEXTLINE(google-explicit-constructor)
|
||||
SemIRLocation(SemIR::LocationId loc_id) : SemIRLocation(loc_id, false) {}
|
||||
SemIRLoc(SemIR::LocId loc_id) : SemIRLoc(loc_id, false) {}
|
||||
|
||||
explicit SemIRLocation(SemIR::LocationId loc_id, bool token_only)
|
||||
explicit SemIRLoc(SemIR::LocId loc_id, bool token_only)
|
||||
: loc_id(loc_id), is_inst_id(false), token_only(token_only) {}
|
||||
|
||||
union {
|
||||
SemIR::InstId inst_id;
|
||||
SemIR::LocationId loc_id;
|
||||
SemIR::LocId loc_id;
|
||||
};
|
||||
|
||||
bool is_inst_id;
|
||||
bool token_only;
|
||||
};
|
||||
|
||||
inline auto TokenOnly(SemIR::LocationId loc_id) -> SemIRLocation {
|
||||
return SemIRLocation(loc_id, true);
|
||||
inline auto TokenOnly(SemIR::LocId loc_id) -> SemIRLoc {
|
||||
return SemIRLoc(loc_id, true);
|
||||
}
|
||||
|
||||
// An integer value together with its type. The type is used to determine how to
|
||||
|
||||
@@ -287,14 +287,13 @@ static auto PerformAggregateIndex(Context& context, SemIR::Inst inst)
|
||||
}
|
||||
|
||||
// Issues a diagnostic for a compile-time division by zero.
|
||||
static auto DiagnoseDivisionByZero(Context& context, SemIRLocation loc)
|
||||
-> void {
|
||||
static auto DiagnoseDivisionByZero(Context& context, SemIRLoc loc) -> void {
|
||||
CARBON_DIAGNOSTIC(CompileTimeDivisionByZero, Error, "Division by zero.");
|
||||
context.emitter().Emit(loc, CompileTimeDivisionByZero);
|
||||
}
|
||||
|
||||
// Performs a builtin unary integer -> integer operation.
|
||||
static auto PerformBuiltinUnaryIntOp(Context& context, SemIRLocation loc,
|
||||
static auto PerformBuiltinUnaryIntOp(Context& context, SemIRLoc loc,
|
||||
SemIR::BuiltinFunctionKind builtin_kind,
|
||||
SemIR::InstId arg_id)
|
||||
-> SemIR::ConstantId {
|
||||
@@ -318,7 +317,7 @@ static auto PerformBuiltinUnaryIntOp(Context& context, SemIRLocation loc,
|
||||
}
|
||||
|
||||
// Performs a builtin binary integer -> integer operation.
|
||||
static auto PerformBuiltinBinaryIntOp(Context& context, SemIRLocation loc,
|
||||
static auto PerformBuiltinBinaryIntOp(Context& context, SemIRLoc loc,
|
||||
SemIR::BuiltinFunctionKind builtin_kind,
|
||||
SemIR::InstId lhs_id,
|
||||
SemIR::InstId rhs_id)
|
||||
@@ -416,8 +415,7 @@ static auto PerformBuiltinIntComparison(Context& context,
|
||||
Phase::Template);
|
||||
}
|
||||
|
||||
static auto PerformBuiltinCall(Context& context, SemIRLocation loc,
|
||||
SemIR::Call call,
|
||||
static auto PerformBuiltinCall(Context& context, SemIRLoc loc, SemIR::Call call,
|
||||
SemIR::BuiltinFunctionKind builtin_kind,
|
||||
llvm::ArrayRef<SemIR::InstId> arg_ids,
|
||||
Phase phase) -> SemIR::ConstantId {
|
||||
@@ -463,7 +461,7 @@ static auto PerformBuiltinCall(Context& context, SemIRLocation loc,
|
||||
return SemIR::ConstantId::NotConstant;
|
||||
}
|
||||
|
||||
static auto PerformCall(Context& context, SemIRLocation loc, SemIR::Call call)
|
||||
static auto PerformCall(Context& context, SemIRLoc loc, SemIR::Call call)
|
||||
-> SemIR::ConstantId {
|
||||
Phase phase = Phase::Template;
|
||||
|
||||
|
||||
@@ -193,7 +193,7 @@ auto CheckFunctionTypeMatches(Context& context,
|
||||
|
||||
// Checks to see if a structurally valid redeclaration is allowed in context.
|
||||
// These all still merge.
|
||||
static auto CheckIsAllowedRedecl(Context& context, SemIR::LocationId loc_id,
|
||||
static auto CheckIsAllowedRedecl(Context& context, SemIR::LocId loc_id,
|
||||
SemIR::Function& new_function,
|
||||
bool new_is_definition,
|
||||
SemIR::Function& prev_function,
|
||||
@@ -253,7 +253,7 @@ static auto CheckIsAllowedRedecl(Context& context, SemIR::LocationId loc_id,
|
||||
|
||||
// TODO: Detect conflicting cross-file declarations, as well as uses of imported
|
||||
// declarations followed by a redeclaration.
|
||||
auto MergeFunctionRedecl(Context& context, SemIR::LocationId loc_id,
|
||||
auto MergeFunctionRedecl(Context& context, SemIR::LocId loc_id,
|
||||
SemIR::Function& new_function, bool new_is_definition,
|
||||
SemIR::FunctionId prev_function_id,
|
||||
bool prev_is_import) -> bool {
|
||||
|
||||
@@ -28,7 +28,7 @@ auto CheckFunctionTypeMatches(Context& context,
|
||||
//
|
||||
// If merging is successful, updates the FunctionId on new_function and returns
|
||||
// true. Otherwise, returns false. Prints a diagnostic when appropriate.
|
||||
auto MergeFunctionRedecl(Context& context, SemIR::LocationId loc_id,
|
||||
auto MergeFunctionRedecl(Context& context, SemIR::LocId loc_id,
|
||||
SemIR::Function& new_function, bool new_is_definition,
|
||||
SemIR::FunctionId prev_function_id,
|
||||
bool prev_is_imported) -> bool;
|
||||
|
||||
@@ -19,9 +19,8 @@ auto HandleAnyBindingPattern(Context& context, Parse::NodeId node_id,
|
||||
auto [name_node, name_id] = context.node_stack().PopNameWithNodeId();
|
||||
|
||||
// Create the appropriate kind of binding for this pattern.
|
||||
auto make_bind_name =
|
||||
[&](SemIR::TypeId type_id,
|
||||
SemIR::InstId value_id) -> SemIR::LocationIdAndInst {
|
||||
auto make_bind_name = [&](SemIR::TypeId type_id,
|
||||
SemIR::InstId value_id) -> SemIR::LocIdAndInst {
|
||||
// TODO: Eventually the name will need to support associations with other
|
||||
// scopes, but right now we don't support qualified names here.
|
||||
auto bind_name_id = context.bind_names().Add(
|
||||
|
||||
@@ -15,7 +15,7 @@ static auto HandleDiscardedExpr(Context& context, SemIR::InstId expr_id)
|
||||
// If we discard an initializing expression, convert it to a value or
|
||||
// reference so that it has something to initialize.
|
||||
auto expr = context.insts().Get(expr_id);
|
||||
Convert(context, context.insts().GetLocationId(expr_id), expr_id,
|
||||
Convert(context, context.insts().GetLocId(expr_id), expr_id,
|
||||
{.kind = ConversionTarget::Discarded, .type_id = expr.type_id()});
|
||||
|
||||
// TODO: This will eventually need to do some "do not discard" analysis.
|
||||
|
||||
@@ -45,7 +45,7 @@ auto HandleIndexExpr(Context& context, Parse::IndexExprId node_id) -> bool {
|
||||
switch (operand_type_inst.kind()) {
|
||||
case SemIR::ArrayType::Kind: {
|
||||
auto array_type = operand_type_inst.As<SemIR::ArrayType>();
|
||||
auto index_node_id = context.insts().GetLocationId(index_inst_id);
|
||||
auto index_node_id = context.insts().GetLocId(index_inst_id);
|
||||
auto cast_index_id = ConvertToValueOfType(
|
||||
context, index_node_id, index_inst_id,
|
||||
context.GetBuiltinType(SemIR::BuiltinKind::IntType));
|
||||
@@ -74,7 +74,7 @@ auto HandleIndexExpr(Context& context, Parse::IndexExprId node_id) -> bool {
|
||||
}
|
||||
case SemIR::TupleType::Kind: {
|
||||
SemIR::TypeId element_type_id = SemIR::TypeId::Error;
|
||||
auto index_node_id = context.insts().GetLocationId(index_inst_id);
|
||||
auto index_node_id = context.insts().GetLocId(index_inst_id);
|
||||
index_inst_id = ConvertToValueOfType(
|
||||
context, index_node_id, index_inst_id,
|
||||
context.GetBuiltinType(SemIR::BuiltinKind::IntType));
|
||||
|
||||
@@ -28,7 +28,7 @@ auto HandleLetInitializer(Context& context, Parse::LetInitializerId node_id)
|
||||
|
||||
static auto BuildAssociatedConstantDecl(
|
||||
Context& context, Parse::LetDeclId node_id, SemIR::InstId pattern_id,
|
||||
SemIR::LocationIdAndInst pattern, SemIR::InterfaceId interface_id) -> void {
|
||||
SemIR::LocIdAndInst pattern, SemIR::InterfaceId interface_id) -> void {
|
||||
auto& interface_info = context.interfaces().Get(interface_id);
|
||||
|
||||
auto binding_pattern = pattern.inst.TryAs<SemIR::BindSymbolicName>();
|
||||
@@ -46,7 +46,7 @@ static auto BuildAssociatedConstantDecl(
|
||||
// declaration.
|
||||
auto name_id =
|
||||
context.bind_names().Get(binding_pattern->bind_name_id).name_id;
|
||||
context.ReplaceLocationIdAndInstBeforeConstantUse(
|
||||
context.ReplaceLocIdAndInstBeforeConstantUse(
|
||||
pattern_id, {node_id, SemIR::AssociatedConstantDecl{
|
||||
binding_pattern->type_id, name_id}});
|
||||
auto decl_id = pattern_id;
|
||||
@@ -98,7 +98,7 @@ auto HandleLetDecl(Context& context, Parse::LetDeclId node_id) -> bool {
|
||||
}
|
||||
context.decl_state_stack().Pop(DeclState::Let);
|
||||
|
||||
auto pattern = context.insts().GetWithLocationId(pattern_id);
|
||||
auto pattern = context.insts().GetWithLocId(pattern_id);
|
||||
auto interface_scope = context.GetCurrentScopeAs<SemIR::InterfaceDecl>();
|
||||
|
||||
if (value_id) {
|
||||
|
||||
@@ -40,7 +40,7 @@ auto HandleNamespace(Context& context, Parse::NamespaceId node_id) -> bool {
|
||||
// When the name conflict is an imported namespace, fill the location ID
|
||||
// so that future diagnostics point at this declaration.
|
||||
if (existing->import_id.is_valid() &&
|
||||
!context.insts().GetLocationId(existing_inst_id).is_valid()) {
|
||||
!context.insts().GetLocId(existing_inst_id).is_valid()) {
|
||||
context.SetNamespaceNodeId(existing_inst_id, node_id);
|
||||
}
|
||||
} else {
|
||||
|
||||
@@ -55,7 +55,7 @@ auto HandleVariableDecl(Context& context, Parse::VariableDeclId node_id)
|
||||
// Form a corresponding name in the current context, and bind the name to
|
||||
// the variable.
|
||||
auto name_context = context.decl_name_stack().MakeUnqualifiedName(
|
||||
context.insts().GetLocationId(value_id),
|
||||
context.insts().GetLocId(value_id),
|
||||
context.bind_names().Get(bind_name->bind_name_id).name_id);
|
||||
context.decl_name_stack().AddNameToLookup(name_context, value_id);
|
||||
value_id = bind_name->value_id;
|
||||
@@ -63,7 +63,7 @@ auto HandleVariableDecl(Context& context, Parse::VariableDeclId node_id)
|
||||
context.insts().TryGetAs<SemIR::FieldDecl>(value_id)) {
|
||||
// Introduce the field name into the class.
|
||||
auto name_context = context.decl_name_stack().MakeUnqualifiedName(
|
||||
context.insts().GetLocationId(value_id), field_decl->name_id);
|
||||
context.insts().GetLocId(value_id), field_decl->name_id);
|
||||
context.decl_name_stack().AddNameToLookup(name_context, value_id);
|
||||
}
|
||||
// TODO: Handle other kinds of pattern.
|
||||
|
||||
@@ -158,7 +158,7 @@ class ImportRefResolver {
|
||||
return initial_work < work_stack_.size();
|
||||
}
|
||||
|
||||
auto AddImportIRInst(SemIR::InstId inst_id) -> SemIR::LocationId {
|
||||
auto AddImportIRInst(SemIR::InstId inst_id) -> SemIR::LocId {
|
||||
return context_.import_ir_insts().Add(
|
||||
{.ir_id = import_ir_id_, .inst_id = inst_id});
|
||||
}
|
||||
@@ -274,10 +274,9 @@ class ImportRefResolver {
|
||||
}
|
||||
}
|
||||
if (addr_inst) {
|
||||
new_param_id =
|
||||
context_.AddInstInNoBlock(SemIR::LocationIdAndInst::Untyped(
|
||||
AddImportIRInst(ref_id),
|
||||
SemIR::AddrPattern{type_id, new_param_id}));
|
||||
new_param_id = context_.AddInstInNoBlock(SemIR::LocIdAndInst::Untyped(
|
||||
AddImportIRInst(ref_id),
|
||||
SemIR::AddrPattern{type_id, new_param_id}));
|
||||
}
|
||||
new_param_refs.push_back(new_param_id);
|
||||
}
|
||||
@@ -486,7 +485,7 @@ class ImportRefResolver {
|
||||
}
|
||||
|
||||
// Import the instruction in order to update contained base_type_id.
|
||||
auto inst_id = context_.AddInstInNoBlock(SemIR::LocationIdAndInst::Untyped(
|
||||
auto inst_id = context_.AddInstInNoBlock(SemIR::LocIdAndInst::Untyped(
|
||||
AddImportIRInst(import_inst_id),
|
||||
SemIR::BaseDecl{context_.GetTypeIdForTypeConstant(type_const_id),
|
||||
context_.GetTypeIdForTypeConstant(base_type_const_id),
|
||||
@@ -532,7 +531,7 @@ class ImportRefResolver {
|
||||
SemIR::ClassDecl{SemIR::TypeId::Invalid, SemIR::ClassId::Invalid,
|
||||
SemIR::InstBlockId::Empty};
|
||||
auto class_decl_id =
|
||||
context_.AddPlaceholderInst(SemIR::LocationIdAndInst::Untyped(
|
||||
context_.AddPlaceholderInst(SemIR::LocIdAndInst::Untyped(
|
||||
AddImportIRInst(import_class.decl_id), class_decl));
|
||||
// Regardless of whether ClassDecl is a complete type, we first need an
|
||||
// incomplete type so that any references have something to point at.
|
||||
@@ -664,7 +663,7 @@ class ImportRefResolver {
|
||||
if (HasNewWork(initial_work)) {
|
||||
return ResolveResult::Retry();
|
||||
}
|
||||
auto inst_id = context_.AddInstInNoBlock(SemIR::LocationIdAndInst::Untyped(
|
||||
auto inst_id = context_.AddInstInNoBlock(SemIR::LocIdAndInst::Untyped(
|
||||
AddImportIRInst(import_inst_id),
|
||||
SemIR::FieldDecl{context_.GetTypeIdForTypeConstant(const_id),
|
||||
GetLocalNameId(inst.name_id), inst.index}));
|
||||
@@ -699,7 +698,7 @@ class ImportRefResolver {
|
||||
context_.GetTypeIdForTypeConstant(type_const_id),
|
||||
SemIR::FunctionId::Invalid, SemIR::InstBlockId::Empty};
|
||||
auto function_decl_id =
|
||||
context_.AddPlaceholderInstInNoBlock(SemIR::LocationIdAndInst::Untyped(
|
||||
context_.AddPlaceholderInstInNoBlock(SemIR::LocIdAndInst::Untyped(
|
||||
AddImportIRInst(function.decl_id), function_decl));
|
||||
|
||||
auto new_return_type_id =
|
||||
@@ -737,7 +736,7 @@ class ImportRefResolver {
|
||||
SemIR::InterfaceId::Invalid,
|
||||
SemIR::InstBlockId::Empty};
|
||||
auto interface_decl_id =
|
||||
context_.AddPlaceholderInst(SemIR::LocationIdAndInst::Untyped(
|
||||
context_.AddPlaceholderInst(SemIR::LocIdAndInst::Untyped(
|
||||
AddImportIRInst(import_interface.decl_id), interface_decl));
|
||||
|
||||
// Start with an incomplete interface.
|
||||
|
||||
@@ -29,7 +29,7 @@ auto BuildAssociatedEntity(Context& context, SemIR::InterfaceId interface_id,
|
||||
// not the declaration itself.
|
||||
auto type_id = context.GetAssociatedEntityType(
|
||||
interface_id, context.insts().Get(decl_id).type_id());
|
||||
return context.AddInst({context.insts().GetLocationId(decl_id),
|
||||
return context.AddInst({context.insts().GetLocId(decl_id),
|
||||
SemIR::AssociatedEntity{type_id, index, decl_id}});
|
||||
}
|
||||
|
||||
|
||||
@@ -66,7 +66,7 @@ auto MergeImportRef(Context& context, SemIR::InstId new_inst_id,
|
||||
auto prev_fn_id = prev_inst->As<SemIR::FunctionDecl>().function_id;
|
||||
// TODO: May need to "spoil" the new function to prevent it from being
|
||||
// emitted, since it will already be added.
|
||||
MergeFunctionRedecl(context, context.insts().GetLocationId(new_inst_id),
|
||||
MergeFunctionRedecl(context, context.insts().GetLocId(new_inst_id),
|
||||
new_fn,
|
||||
/*new_is_definition=*/false, prev_fn_id,
|
||||
/*prev_is_imported=*/true);
|
||||
|
||||
@@ -11,7 +11,7 @@ namespace Carbon::Check {
|
||||
static auto ReportNotAllowed(Context& context, Parse::NodeId modifier_node,
|
||||
Lex::TokenKind decl_kind,
|
||||
llvm::StringRef context_string,
|
||||
SemIR::LocationId context_loc_id) -> void {
|
||||
SemIR::LocId context_loc_id) -> void {
|
||||
CARBON_DIAGNOSTIC(ModifierNotAllowedOn, Error,
|
||||
"`{0}` not allowed on `{1}` declaration{2}.",
|
||||
Lex::TokenKind, Lex::TokenKind, std::string);
|
||||
@@ -41,7 +41,7 @@ static auto ModifierOrderAsSet(ModifierOrder order) -> KeywordModifierSet {
|
||||
auto ForbidModifiersOnDecl(Context& context, KeywordModifierSet forbidden,
|
||||
Lex::TokenKind decl_kind,
|
||||
llvm::StringRef context_string,
|
||||
SemIR::LocationId context_loc_id) -> void {
|
||||
SemIR::LocId context_loc_id) -> void {
|
||||
auto& s = context.decl_state_stack().innermost();
|
||||
auto not_allowed = s.modifier_set & forbidden;
|
||||
if (!not_allowed) {
|
||||
@@ -121,12 +121,12 @@ auto CheckMethodModifiersOnFunction(Context& context,
|
||||
if (inheritance_kind == SemIR::Class::Final) {
|
||||
ForbidModifiersOnDecl(context, KeywordModifierSet::Virtual, decl_kind,
|
||||
" in a non-abstract non-base `class` definition",
|
||||
context.insts().GetLocationId(target_id));
|
||||
context.insts().GetLocId(target_id));
|
||||
}
|
||||
if (inheritance_kind != SemIR::Class::Abstract) {
|
||||
ForbidModifiersOnDecl(context, KeywordModifierSet::Abstract, decl_kind,
|
||||
" in a non-abstract `class` definition",
|
||||
context.insts().GetLocationId(target_id));
|
||||
context.insts().GetLocId(target_id));
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -29,10 +29,11 @@ auto CheckMethodModifiersOnFunction(Context& context,
|
||||
// `context_string` (and optional `context_loc_id`) specifying the context in
|
||||
// which those modifiers are forbidden.
|
||||
// TODO: Take another look at diagnostic phrasing for callers.
|
||||
auto ForbidModifiersOnDecl(
|
||||
Context& context, KeywordModifierSet forbidden, Lex::TokenKind decl_kind,
|
||||
llvm::StringRef context_string,
|
||||
SemIR::LocationId context_loc_id = SemIR::LocationId::Invalid) -> void;
|
||||
auto ForbidModifiersOnDecl(Context& context, KeywordModifierSet forbidden,
|
||||
Lex::TokenKind decl_kind,
|
||||
llvm::StringRef context_string,
|
||||
SemIR::LocId context_loc_id = SemIR::LocId::Invalid)
|
||||
-> void;
|
||||
|
||||
// Reports a diagnostic (using `decl_kind`) if modifiers on this declaration are
|
||||
// not in `allowed`. Updates the declaration state in
|
||||
|
||||
@@ -39,7 +39,7 @@ class PendingBlock {
|
||||
size_t size_;
|
||||
};
|
||||
|
||||
auto AddInst(SemIR::LocationIdAndInst loc_id_and_inst) -> SemIR::InstId {
|
||||
auto AddInst(SemIR::LocIdAndInst loc_id_and_inst) -> SemIR::InstId {
|
||||
auto inst_id = context_.AddInstInNoBlock(loc_id_and_inst);
|
||||
insts_.push_back(inst_id);
|
||||
return inst_id;
|
||||
@@ -56,24 +56,24 @@ class PendingBlock {
|
||||
// Replace the instruction at target_id with the instructions in this block.
|
||||
// The new value for target_id should be value_id.
|
||||
auto MergeReplacing(SemIR::InstId target_id, SemIR::InstId value_id) -> void {
|
||||
auto value = context_.insts().GetWithLocationId(value_id);
|
||||
auto value = context_.insts().GetWithLocId(value_id);
|
||||
|
||||
// There are three cases here:
|
||||
|
||||
if (insts_.empty()) {
|
||||
// 1) The block is empty. Replace `target_id` with an empty splice
|
||||
// pointing at `value_id`.
|
||||
context_.ReplaceLocationIdAndInstBeforeConstantUse(
|
||||
context_.ReplaceLocIdAndInstBeforeConstantUse(
|
||||
target_id, {value.loc_id,
|
||||
SemIR::SpliceBlock{value.inst.type_id(),
|
||||
SemIR::InstBlockId::Empty, value_id}});
|
||||
} else if (insts_.size() == 1 && insts_[0] == value_id) {
|
||||
// 2) The block is {value_id}. Replace `target_id` with the instruction
|
||||
// referred to by `value_id`. This is intended to be the common case.
|
||||
context_.ReplaceLocationIdAndInstBeforeConstantUse(target_id, value);
|
||||
context_.ReplaceLocIdAndInstBeforeConstantUse(target_id, value);
|
||||
} else {
|
||||
// 3) Anything else: splice it into the IR, replacing `target_id`.
|
||||
context_.ReplaceLocationIdAndInstBeforeConstantUse(
|
||||
context_.ReplaceLocIdAndInstBeforeConstantUse(
|
||||
target_id,
|
||||
{value.loc_id,
|
||||
SemIR::SpliceBlock{value.inst.type_id(),
|
||||
|
||||
@@ -26,7 +26,7 @@ from typing import Dict, List, NamedTuple, Set
|
||||
IGNORED = set(["MyDiagnostic", "TestDiagnostic", "TestDiagnosticNote"])
|
||||
|
||||
|
||||
class Location(NamedTuple):
|
||||
class Loc(NamedTuple):
|
||||
"""A location for a diagnostic."""
|
||||
|
||||
def __str__(self) -> str:
|
||||
@@ -49,7 +49,7 @@ def load_diagnostic_kind() -> Set[str]:
|
||||
|
||||
def load_diagnostic_uses_in(
|
||||
path: Path,
|
||||
) -> Dict[str, List[Location]]:
|
||||
) -> Dict[str, List[Loc]]:
|
||||
"""Returns the path's CARBON_DIAGNOSTIC uses."""
|
||||
content = path.read_text()
|
||||
|
||||
@@ -57,18 +57,18 @@ def load_diagnostic_uses_in(
|
||||
line = 1
|
||||
line_offset = 0
|
||||
|
||||
found: Dict[str, List[Location]] = collections.defaultdict(lambda: [])
|
||||
found: Dict[str, List[Loc]] = collections.defaultdict(lambda: [])
|
||||
for m in re.finditer(r"CARBON_DIAGNOSTIC\(\s*(\w+),", content):
|
||||
diag = m.group(1)
|
||||
if diag in IGNORED:
|
||||
continue
|
||||
line += content.count("\n", line_offset, m.start())
|
||||
line_offset = m.start()
|
||||
found[diag].append(Location(path, line))
|
||||
found[diag].append(Loc(path, line))
|
||||
return found
|
||||
|
||||
|
||||
def load_diagnostic_uses() -> Dict[str, List[Location]]:
|
||||
def load_diagnostic_uses() -> Dict[str, List[Loc]]:
|
||||
"""Returns all CARBON_DIAGNOSTIC uses."""
|
||||
globs = itertools.chain(
|
||||
*[Path("toolchain").glob(f"**/*.{ext}") for ext in ("h", "cpp")]
|
||||
@@ -76,14 +76,14 @@ def load_diagnostic_uses() -> Dict[str, List[Location]]:
|
||||
with futures.ThreadPoolExecutor() as exec:
|
||||
results = exec.map(load_diagnostic_uses_in, globs)
|
||||
|
||||
found: Dict[str, List[Location]] = collections.defaultdict(lambda: [])
|
||||
found: Dict[str, List[Loc]] = collections.defaultdict(lambda: [])
|
||||
for result in results:
|
||||
for diag, locations in result.items():
|
||||
found[diag].extend(locations)
|
||||
return found
|
||||
|
||||
|
||||
def check_uniqueness(uses: Dict[str, List[Location]]) -> bool:
|
||||
def check_uniqueness(uses: Dict[str, List[Loc]]) -> bool:
|
||||
"""If any diagnostic is non-unique, prints an error and returns true."""
|
||||
has_errors = False
|
||||
for diag in sorted(uses.keys()):
|
||||
@@ -95,7 +95,7 @@ def check_uniqueness(uses: Dict[str, List[Location]]) -> bool:
|
||||
return has_errors
|
||||
|
||||
|
||||
def check_unused(decls: Set[str], uses: Dict[str, List[Location]]) -> bool:
|
||||
def check_unused(decls: Set[str], uses: Dict[str, List[Loc]]) -> bool:
|
||||
"""If any diagnostic is unused, prints an error and returns true."""
|
||||
unused = decls.difference(uses.keys())
|
||||
if not unused:
|
||||
|
||||
@@ -42,10 +42,10 @@ enum class DiagnosticLevel : int8_t {
|
||||
::Carbon::DiagnosticKind::DiagnosticName, \
|
||||
::Carbon::DiagnosticLevel::Level, Format)
|
||||
|
||||
// A location for a diagnostic in a file. The lifetime of a DiagnosticLocation
|
||||
// A location for a diagnostic in a file. The lifetime of a DiagnosticLoc
|
||||
// is required to be less than SourceBuffer that it refers to due to the
|
||||
// contained filename and line references.
|
||||
struct DiagnosticLocation {
|
||||
struct DiagnosticLoc {
|
||||
// Name of the file or buffer that this diagnostic refers to.
|
||||
llvm::StringRef filename;
|
||||
// A reference to the line of the error.
|
||||
@@ -68,7 +68,7 @@ struct DiagnosticMessage {
|
||||
DiagnosticLevel level;
|
||||
|
||||
// The calculated location of the diagnostic.
|
||||
DiagnosticLocation location;
|
||||
DiagnosticLoc loc;
|
||||
|
||||
// The diagnostic's format string. This, along with format_args, will be
|
||||
// passed to format_fn.
|
||||
|
||||
@@ -17,11 +17,11 @@ auto StreamDiagnosticConsumer::HandleDiagnostic(Diagnostic diagnostic) -> void {
|
||||
}
|
||||
|
||||
for (const auto& message : diagnostic.messages) {
|
||||
*stream_ << message.location.filename;
|
||||
if (message.location.line_number > 0) {
|
||||
*stream_ << ":" << message.location.line_number;
|
||||
if (message.location.column_number > 0) {
|
||||
*stream_ << ":" << message.location.column_number;
|
||||
*stream_ << message.loc.filename;
|
||||
if (message.loc.line_number > 0) {
|
||||
*stream_ << ":" << message.loc.line_number;
|
||||
if (message.loc.column_number > 0) {
|
||||
*stream_ << ":" << message.loc.column_number;
|
||||
}
|
||||
}
|
||||
*stream_ << ": ";
|
||||
@@ -29,18 +29,18 @@ auto StreamDiagnosticConsumer::HandleDiagnostic(Diagnostic diagnostic) -> void {
|
||||
*stream_ << "ERROR: ";
|
||||
}
|
||||
*stream_ << message.format_fn(message) << "\n";
|
||||
if (message.location.column_number > 0) {
|
||||
*stream_ << message.location.line << "\n";
|
||||
stream_->indent(message.location.column_number - 1);
|
||||
if (message.loc.column_number > 0) {
|
||||
*stream_ << message.loc.line << "\n";
|
||||
stream_->indent(message.loc.column_number - 1);
|
||||
*stream_ << "^";
|
||||
int underline_length = std::max(0, message.location.length - 1);
|
||||
int underline_length = std::max(0, message.loc.length - 1);
|
||||
// We want to ensure that we don't underline past the end of the line in
|
||||
// case of a multiline token.
|
||||
// TODO: revisit this once we can reference multiple ranges on multiple
|
||||
// lines in a single diagnostic message.
|
||||
underline_length = std::min(
|
||||
underline_length, static_cast<int32_t>(message.location.line.size()) -
|
||||
message.location.column_number);
|
||||
underline_length, static_cast<int32_t>(message.loc.line.size()) -
|
||||
message.loc.column_number);
|
||||
for (int i = 0; i < underline_length; ++i) {
|
||||
*stream_ << "~";
|
||||
}
|
||||
|
||||
@@ -12,21 +12,21 @@ namespace Carbon {
|
||||
|
||||
// An interface that can convert some representation of a location into a
|
||||
// diagnostic location.
|
||||
template <typename LocationT>
|
||||
template <typename LocT>
|
||||
class DiagnosticConverter {
|
||||
public:
|
||||
// Callback type used to report context messages from ConvertLocation.
|
||||
// Note that the first parameter type is DiagnosticLocation rather than
|
||||
// LocationT, because ConvertLocation must not recurse.
|
||||
// Callback type used to report context messages from ConvertLoc.
|
||||
// Note that the first parameter type is DiagnosticLoc rather than
|
||||
// LocT, because ConvertLoc must not recurse.
|
||||
using ContextFnT = llvm::function_ref<void(
|
||||
DiagnosticLocation, const Internal::DiagnosticBase<>&)>;
|
||||
DiagnosticLoc, const Internal::DiagnosticBase<>&)>;
|
||||
|
||||
virtual ~DiagnosticConverter() = default;
|
||||
|
||||
// Converts a LocationT to a DiagnosticLocation. ConvertLocation may invoke
|
||||
// Converts a LocT to a DiagnosticLoc. ConvertLoc may invoke
|
||||
// context_fn to provide context messages.
|
||||
virtual auto ConvertLocation(LocationT loc, ContextFnT context_fn) const
|
||||
-> DiagnosticLocation = 0;
|
||||
virtual auto ConvertLoc(LocT loc, ContextFnT context_fn) const
|
||||
-> DiagnosticLoc = 0;
|
||||
|
||||
// Converts arg types as needed. Not all uses require conversion, so the
|
||||
// default returns the argument unchanged.
|
||||
|
||||
@@ -30,7 +30,7 @@ using NoTypeDeduction = std::type_identity_t<Arg>;
|
||||
|
||||
} // namespace Internal
|
||||
|
||||
template <typename LocationT, typename AnnotateFn>
|
||||
template <typename LocT, typename AnnotateFn>
|
||||
class DiagnosticAnnotationScope;
|
||||
|
||||
// Manages the creation of reports, the testing if diagnostics are enabled, and
|
||||
@@ -41,7 +41,7 @@ class DiagnosticAnnotationScope;
|
||||
// convenient for them, such as a position within a buffer when lexing, a token
|
||||
// when parsing, or a parse tree node when type-checking, and to allow unit
|
||||
// tests to be decoupled from any concrete location representation.
|
||||
template <typename LocationT>
|
||||
template <typename LocT>
|
||||
class DiagnosticEmitter {
|
||||
public:
|
||||
// A builder-pattern type to provide a fluent interface for constructing
|
||||
@@ -60,12 +60,12 @@ class DiagnosticEmitter {
|
||||
// The API mirrors the main emission API: `DiagnosticEmitter::Emit`.
|
||||
// For the expected usage see the builder API: `DiagnosticEmitter::Build`.
|
||||
template <typename... Args>
|
||||
auto Note(LocationT location,
|
||||
auto Note(LocT loc,
|
||||
const Internal::DiagnosticBase<Args...>& diagnostic_base,
|
||||
Internal::NoTypeDeduction<Args>... args) -> DiagnosticBuilder& {
|
||||
CARBON_CHECK(diagnostic_base.Level == DiagnosticLevel::Note)
|
||||
<< static_cast<int>(diagnostic_base.Level);
|
||||
AddMessage(location, diagnostic_base, {emitter_->MakeAny<Args>(args)...});
|
||||
AddMessage(loc, diagnostic_base, {emitter_->MakeAny<Args>(args)...});
|
||||
return *this;
|
||||
}
|
||||
|
||||
@@ -80,47 +80,46 @@ class DiagnosticEmitter {
|
||||
}
|
||||
|
||||
private:
|
||||
friend class DiagnosticEmitter<LocationT>;
|
||||
friend class DiagnosticEmitter<LocT>;
|
||||
|
||||
template <typename... Args>
|
||||
explicit DiagnosticBuilder(
|
||||
DiagnosticEmitter<LocationT>* emitter, LocationT location,
|
||||
DiagnosticEmitter<LocT>* emitter, LocT loc,
|
||||
const Internal::DiagnosticBase<Args...>& diagnostic_base,
|
||||
llvm::SmallVector<llvm::Any> args)
|
||||
: emitter_(emitter), diagnostic_({.level = diagnostic_base.Level}) {
|
||||
AddMessage(location, diagnostic_base, std::move(args));
|
||||
AddMessage(loc, diagnostic_base, std::move(args));
|
||||
CARBON_CHECK(diagnostic_base.Level != DiagnosticLevel::Note);
|
||||
}
|
||||
|
||||
// Adds a message to the diagnostic, handling conversion of the location and
|
||||
// arguments.
|
||||
template <typename... Args>
|
||||
auto AddMessage(LocationT location,
|
||||
auto AddMessage(LocT loc,
|
||||
const Internal::DiagnosticBase<Args...>& diagnostic_base,
|
||||
llvm::SmallVector<llvm::Any> args) -> void {
|
||||
AddMessageWithDiagnosticLocation(
|
||||
emitter_->converter_->ConvertLocation(
|
||||
location,
|
||||
[&](DiagnosticLocation location,
|
||||
AddMessageWithDiagnosticLoc(
|
||||
emitter_->converter_->ConvertLoc(
|
||||
loc,
|
||||
[&](DiagnosticLoc loc,
|
||||
const Internal::DiagnosticBase<>& diagnostic_base) {
|
||||
AddMessageWithDiagnosticLocation(location, diagnostic_base,
|
||||
args);
|
||||
AddMessageWithDiagnosticLoc(loc, diagnostic_base, args);
|
||||
}),
|
||||
diagnostic_base, args);
|
||||
}
|
||||
|
||||
// Adds a message to the diagnostic, handling conversion of the arguments. A
|
||||
// DiagnosticLocation must be provided instead of a LocationT in order to
|
||||
// DiagnosticLoc must be provided instead of a LocT in order to
|
||||
// avoid potential recursion.
|
||||
template <typename... Args>
|
||||
auto AddMessageWithDiagnosticLocation(
|
||||
DiagnosticLocation location,
|
||||
auto AddMessageWithDiagnosticLoc(
|
||||
DiagnosticLoc loc,
|
||||
const Internal::DiagnosticBase<Args...>& diagnostic_base,
|
||||
llvm::SmallVector<llvm::Any> args) {
|
||||
diagnostic_.messages.emplace_back(DiagnosticMessage{
|
||||
.kind = diagnostic_base.Kind,
|
||||
.level = diagnostic_base.Level,
|
||||
.location = location,
|
||||
.loc = loc,
|
||||
.format = diagnostic_base.Format,
|
||||
.format_args = std::move(args),
|
||||
.format_fn = [](const DiagnosticMessage& message) -> std::string {
|
||||
@@ -145,13 +144,13 @@ class DiagnosticEmitter {
|
||||
message.format_args[N])...);
|
||||
}
|
||||
|
||||
DiagnosticEmitter<LocationT>* emitter_;
|
||||
DiagnosticEmitter<LocT>* emitter_;
|
||||
Diagnostic diagnostic_;
|
||||
};
|
||||
|
||||
// The `converter` and `consumer` are required to outlive the diagnostic
|
||||
// emitter.
|
||||
explicit DiagnosticEmitter(DiagnosticConverter<LocationT>& converter,
|
||||
explicit DiagnosticEmitter(DiagnosticConverter<LocT>& converter,
|
||||
DiagnosticConsumer& consumer)
|
||||
: converter_(&converter), consumer_(&consumer) {}
|
||||
~DiagnosticEmitter() = default;
|
||||
@@ -161,24 +160,22 @@ class DiagnosticEmitter {
|
||||
// When passing arguments, they may be buffered. As a consequence, lifetimes
|
||||
// may outlive the `Emit` call.
|
||||
template <typename... Args>
|
||||
auto Emit(LocationT location,
|
||||
const Internal::DiagnosticBase<Args...>& diagnostic_base,
|
||||
auto Emit(LocT loc, const Internal::DiagnosticBase<Args...>& diagnostic_base,
|
||||
Internal::NoTypeDeduction<Args>... args) -> void {
|
||||
DiagnosticBuilder(this, location, diagnostic_base, {MakeAny<Args>(args)...})
|
||||
DiagnosticBuilder(this, loc, diagnostic_base, {MakeAny<Args>(args)...})
|
||||
.Emit();
|
||||
}
|
||||
|
||||
// A fluent interface for building a diagnostic and attaching notes for added
|
||||
// context or information. For example:
|
||||
//
|
||||
// emitter_.Build(location1, MyDiagnostic)
|
||||
// .Note(location2, MyDiagnosticNote)
|
||||
// emitter_.Build(loc1, MyDiagnostic)
|
||||
// .Note(loc2, MyDiagnosticNote)
|
||||
// .Emit();
|
||||
template <typename... Args>
|
||||
auto Build(LocationT location,
|
||||
const Internal::DiagnosticBase<Args...>& diagnostic_base,
|
||||
auto Build(LocT loc, const Internal::DiagnosticBase<Args...>& diagnostic_base,
|
||||
Internal::NoTypeDeduction<Args>... args) -> DiagnosticBuilder {
|
||||
return DiagnosticBuilder(this, location, diagnostic_base,
|
||||
return DiagnosticBuilder(this, loc, diagnostic_base,
|
||||
{MakeAny<Args>(args)...});
|
||||
}
|
||||
|
||||
@@ -195,10 +192,10 @@ class DiagnosticEmitter {
|
||||
return converted;
|
||||
}
|
||||
|
||||
template <typename LocT, typename AnnotateFn>
|
||||
template <typename OtherLocT, typename AnnotateFn>
|
||||
friend class DiagnosticAnnotationScope;
|
||||
|
||||
DiagnosticConverter<LocationT>* converter_;
|
||||
DiagnosticConverter<LocT>* converter_;
|
||||
DiagnosticConsumer* consumer_;
|
||||
llvm::SmallVector<llvm::function_ref<auto(DiagnosticBuilder& builder)->void>>
|
||||
annotate_fns_;
|
||||
@@ -211,10 +208,10 @@ class DiagnosticEmitter {
|
||||
// `DiagnosticBuilder& builder` for any diagnostic that is emitted through the
|
||||
// given emitter. That function can annotate the diagnostic by calling
|
||||
// `builder.Note` to add notes.
|
||||
template <typename LocationT, typename AnnotateFn>
|
||||
template <typename LocT, typename AnnotateFn>
|
||||
class DiagnosticAnnotationScope {
|
||||
public:
|
||||
DiagnosticAnnotationScope(DiagnosticEmitter<LocationT>* emitter,
|
||||
DiagnosticAnnotationScope(DiagnosticEmitter<LocT>* emitter,
|
||||
AnnotateFn annotate)
|
||||
: emitter_(emitter), annotate_(std::move(annotate)) {
|
||||
emitter_->annotate_fns_.push_back(annotate_);
|
||||
@@ -222,15 +219,14 @@ class DiagnosticAnnotationScope {
|
||||
~DiagnosticAnnotationScope() { emitter_->annotate_fns_.pop_back(); }
|
||||
|
||||
private:
|
||||
DiagnosticEmitter<LocationT>* emitter_;
|
||||
DiagnosticEmitter<LocT>* emitter_;
|
||||
// Make a copy of the annotation function to ensure that it lives long enough.
|
||||
AnnotateFn annotate_;
|
||||
};
|
||||
|
||||
template <typename LocationT, typename AnnotateFn>
|
||||
DiagnosticAnnotationScope(DiagnosticEmitter<LocationT>* emitter,
|
||||
AnnotateFn annotate)
|
||||
-> DiagnosticAnnotationScope<LocationT, AnnotateFn>;
|
||||
template <typename LocT, typename AnnotateFn>
|
||||
DiagnosticAnnotationScope(DiagnosticEmitter<LocT>* emitter, AnnotateFn annotate)
|
||||
-> DiagnosticAnnotationScope<LocT, AnnotateFn>;
|
||||
|
||||
} // namespace Carbon
|
||||
|
||||
|
||||
@@ -18,8 +18,8 @@ using ::Carbon::Testing::IsSingleDiagnostic;
|
||||
using testing::ElementsAre;
|
||||
|
||||
struct FakeDiagnosticConverter : DiagnosticConverter<int> {
|
||||
auto ConvertLocation(int n, ContextFnT /*context_fn*/) const
|
||||
-> DiagnosticLocation override {
|
||||
auto ConvertLoc(int n, ContextFnT /*context_fn*/) const
|
||||
-> DiagnosticLoc override {
|
||||
return {.line_number = 1, .column_number = n};
|
||||
}
|
||||
};
|
||||
|
||||
@@ -10,9 +10,9 @@ void PrintTo(const Diagnostic& diagnostic, std::ostream* os) {
|
||||
*os << "Diagnostic{";
|
||||
PrintTo(diagnostic.level, os);
|
||||
for (const auto& message : diagnostic.messages) {
|
||||
*os << ", {" << message.location.filename << ":"
|
||||
<< message.location.line_number << ":" << message.location.column_number
|
||||
<< ", \"" << message.format_fn(message) << "}";
|
||||
*os << ", {" << message.loc.filename << ":" << message.loc.line_number
|
||||
<< ":" << message.loc.column_number << ", \""
|
||||
<< message.format_fn(message) << "}";
|
||||
}
|
||||
*os << "\"}";
|
||||
}
|
||||
|
||||
@@ -31,15 +31,14 @@ inline auto IsDiagnosticMessage(testing::Matcher<DiagnosticKind> kind,
|
||||
-> testing::Matcher<DiagnosticMessage> {
|
||||
using testing::AllOf;
|
||||
using testing::Field;
|
||||
return AllOf(
|
||||
Field("kind", &DiagnosticMessage::kind, kind),
|
||||
Field("level", &DiagnosticMessage::level, level),
|
||||
Field(&DiagnosticMessage::location,
|
||||
AllOf(Field("line_number", &DiagnosticLocation::line_number,
|
||||
line_number),
|
||||
Field("column_number", &DiagnosticLocation::column_number,
|
||||
column_number))),
|
||||
IsDiagnosticMessageString(message));
|
||||
return AllOf(Field("kind", &DiagnosticMessage::kind, kind),
|
||||
Field("level", &DiagnosticMessage::level, level),
|
||||
Field(&DiagnosticMessage::loc,
|
||||
AllOf(Field("line_number", &DiagnosticLoc::line_number,
|
||||
line_number),
|
||||
Field("column_number", &DiagnosticLoc::column_number,
|
||||
column_number))),
|
||||
IsDiagnosticMessageString(message));
|
||||
}
|
||||
|
||||
inline auto IsDiagnostic(
|
||||
|
||||
@@ -9,13 +9,12 @@
|
||||
|
||||
namespace Carbon {
|
||||
|
||||
template <typename LocationT>
|
||||
inline auto NullDiagnosticConverter() -> DiagnosticConverter<LocationT>& {
|
||||
struct Converter : public DiagnosticConverter<LocationT> {
|
||||
auto ConvertLocation(
|
||||
LocationT /*loc*/,
|
||||
DiagnosticConverter<LocationT>::ContextFnT /*context_fn*/) const
|
||||
-> DiagnosticLocation override {
|
||||
template <typename LocT>
|
||||
inline auto NullDiagnosticConverter() -> DiagnosticConverter<LocT>& {
|
||||
struct Converter : public DiagnosticConverter<LocT> {
|
||||
auto ConvertLoc(LocT /*loc*/,
|
||||
DiagnosticConverter<LocT>::ContextFnT /*context_fn*/) const
|
||||
-> DiagnosticLoc override {
|
||||
return {};
|
||||
}
|
||||
};
|
||||
@@ -31,10 +30,10 @@ inline auto NullDiagnosticConsumer() -> DiagnosticConsumer& {
|
||||
return *consumer;
|
||||
}
|
||||
|
||||
template <typename LocationT>
|
||||
inline auto NullDiagnosticEmitter() -> DiagnosticEmitter<LocationT>& {
|
||||
static auto* emitter = new DiagnosticEmitter<LocationT>(
|
||||
NullDiagnosticConverter<LocationT>(), NullDiagnosticConsumer());
|
||||
template <typename LocT>
|
||||
inline auto NullDiagnosticEmitter() -> DiagnosticEmitter<LocT>& {
|
||||
static auto* emitter = new DiagnosticEmitter<LocT>(
|
||||
NullDiagnosticConverter<LocT>(), NullDiagnosticConsumer());
|
||||
return *emitter;
|
||||
}
|
||||
|
||||
|
||||
@@ -35,8 +35,8 @@ class SortingDiagnosticConsumer : public DiagnosticConsumer {
|
||||
void Flush() override {
|
||||
llvm::stable_sort(diagnostics_,
|
||||
[](const Diagnostic& lhs, const Diagnostic& rhs) {
|
||||
const auto& lhs_loc = lhs.messages[0].location;
|
||||
const auto& rhs_loc = rhs.messages[0].location;
|
||||
const auto& lhs_loc = lhs.messages[0].loc;
|
||||
const auto& rhs_loc = rhs.messages[0].loc;
|
||||
return std::tie(lhs_loc.filename, lhs_loc.line_number,
|
||||
lhs_loc.column_number) <
|
||||
std::tie(rhs_loc.filename, rhs_loc.line_number,
|
||||
|
||||
@@ -19,9 +19,9 @@ using ::testing::InSequence;
|
||||
|
||||
CARBON_DIAGNOSTIC(TestDiagnostic, Error, "{0}", llvm::StringLiteral);
|
||||
|
||||
struct FakeDiagnosticConverter : DiagnosticConverter<DiagnosticLocation> {
|
||||
auto ConvertLocation(DiagnosticLocation loc, ContextFnT /*context_fn*/) const
|
||||
-> DiagnosticLocation override {
|
||||
struct FakeDiagnosticConverter : DiagnosticConverter<DiagnosticLoc> {
|
||||
auto ConvertLoc(DiagnosticLoc loc, ContextFnT /*context_fn*/) const
|
||||
-> DiagnosticLoc override {
|
||||
return loc;
|
||||
}
|
||||
};
|
||||
@@ -30,7 +30,7 @@ TEST(SortedDiagnosticEmitterTest, SortErrors) {
|
||||
FakeDiagnosticConverter converter;
|
||||
Testing::MockDiagnosticConsumer consumer;
|
||||
SortingDiagnosticConsumer sorting_consumer(consumer);
|
||||
DiagnosticEmitter<DiagnosticLocation> emitter(converter, sorting_consumer);
|
||||
DiagnosticEmitter<DiagnosticLoc> emitter(converter, sorting_consumer);
|
||||
|
||||
emitter.Emit({"f", "line", 2, 1}, TestDiagnostic, "M1");
|
||||
emitter.Emit({"f", "line", 1, 1}, TestDiagnostic, "M2");
|
||||
|
||||
@@ -1270,8 +1270,7 @@ class Lexer::ErrorRecoveryBuffer {
|
||||
// Find the end of the token before the target token, and add the new token
|
||||
// there. Note that new_token_column is a 1-based column number.
|
||||
auto insert_after = TokenIndex(insert_before.index - 1);
|
||||
auto [new_token_line, new_token_column] =
|
||||
buffer_.GetEndLocation(insert_after);
|
||||
auto [new_token_line, new_token_column] = buffer_.GetEndLoc(insert_after);
|
||||
new_tokens_.push_back(
|
||||
{insert_before,
|
||||
{.kind = kind,
|
||||
|
||||
@@ -24,8 +24,8 @@ class SingleTokenDiagnosticConverter : public DiagnosticConverter<const char*> {
|
||||
explicit SingleTokenDiagnosticConverter(llvm::StringRef token)
|
||||
: token_(token) {}
|
||||
|
||||
auto ConvertLocation(const char* pos, ContextFnT /*context_fn*/) const
|
||||
-> DiagnosticLocation override {
|
||||
auto ConvertLoc(const char* pos, ContextFnT /*context_fn*/) const
|
||||
-> DiagnosticLoc override {
|
||||
CARBON_CHECK(StringRefContainsPointer(token_, pos))
|
||||
<< "invalid diagnostic location";
|
||||
llvm::StringRef prefix = token_.take_front(pos - token_.begin());
|
||||
|
||||
@@ -35,7 +35,7 @@ auto TokenizedBuffer::GetColumnNumber(TokenIndex token) const -> int {
|
||||
return GetTokenInfo(token).column + 1;
|
||||
}
|
||||
|
||||
auto TokenizedBuffer::GetEndLocation(TokenIndex token) const
|
||||
auto TokenizedBuffer::GetEndLoc(TokenIndex token) const
|
||||
-> std::pair<LineIndex, int> {
|
||||
auto line = GetLine(token);
|
||||
int column = GetColumnNumber(token);
|
||||
@@ -345,8 +345,8 @@ auto TokenIterator::Print(llvm::raw_ostream& output) const -> void {
|
||||
output << token_.index;
|
||||
}
|
||||
|
||||
auto TokenizedBuffer::SourceBufferDiagnosticConverter::ConvertLocation(
|
||||
const char* loc, ContextFnT /*context_fn*/) const -> DiagnosticLocation {
|
||||
auto TokenizedBuffer::SourceBufferDiagnosticConverter::ConvertLoc(
|
||||
const char* loc, ContextFnT /*context_fn*/) const -> DiagnosticLoc {
|
||||
CARBON_CHECK(StringRefContainsPointer(buffer_->source_->text(), loc))
|
||||
<< "location not within buffer";
|
||||
int64_t offset = loc - buffer_->source_->text().begin();
|
||||
@@ -390,9 +390,9 @@ auto TokenizedBuffer::SourceBufferDiagnosticConverter::ConvertLocation(
|
||||
.column_number = column_number + 1};
|
||||
}
|
||||
|
||||
auto TokenDiagnosticConverter::ConvertLocation(TokenIndex token,
|
||||
ContextFnT context_fn) const
|
||||
-> DiagnosticLocation {
|
||||
auto TokenDiagnosticConverter::ConvertLoc(TokenIndex token,
|
||||
ContextFnT context_fn) const
|
||||
-> DiagnosticLoc {
|
||||
// Map the token location into a position within the source buffer.
|
||||
const auto& token_info = buffer_->GetTokenInfo(token);
|
||||
const auto& line_info = buffer_->GetLineInfo(token_info.token_line);
|
||||
@@ -402,8 +402,8 @@ auto TokenDiagnosticConverter::ConvertLocation(TokenIndex token,
|
||||
// Find the corresponding file location.
|
||||
// TODO: Should we somehow indicate in the diagnostic location if this token
|
||||
// is a recovery token that doesn't correspond to the original source?
|
||||
DiagnosticLocation loc =
|
||||
TokenizedBuffer::SourceBufferDiagnosticConverter(buffer_).ConvertLocation(
|
||||
DiagnosticLoc loc =
|
||||
TokenizedBuffer::SourceBufferDiagnosticConverter(buffer_).ConvertLoc(
|
||||
token_start, context_fn);
|
||||
loc.length = buffer_->GetTokenText(token).size();
|
||||
return loc;
|
||||
|
||||
@@ -119,8 +119,8 @@ class TokenDiagnosticConverter : public DiagnosticConverter<TokenIndex> {
|
||||
: buffer_(buffer) {}
|
||||
|
||||
// Map the given token into a diagnostic location.
|
||||
auto ConvertLocation(TokenIndex token, ContextFnT context_fn) const
|
||||
-> DiagnosticLocation override;
|
||||
auto ConvertLoc(TokenIndex token, ContextFnT context_fn) const
|
||||
-> DiagnosticLoc override;
|
||||
|
||||
private:
|
||||
const TokenizedBuffer* buffer_;
|
||||
@@ -147,7 +147,7 @@ class TokenizedBuffer : public Printable<TokenizedBuffer> {
|
||||
|
||||
// Returns the line and 1-based column number of the first character after
|
||||
// this token.
|
||||
auto GetEndLocation(TokenIndex token) const -> std::pair<LineIndex, int>;
|
||||
auto GetEndLoc(TokenIndex token) const -> std::pair<LineIndex, int>;
|
||||
|
||||
// Returns the source text lexed into this token.
|
||||
auto GetTokenText(TokenIndex token) const -> llvm::StringRef;
|
||||
@@ -256,8 +256,8 @@ class TokenizedBuffer : public Printable<TokenizedBuffer> {
|
||||
|
||||
// Map the given position within the source buffer into a diagnostic
|
||||
// location.
|
||||
auto ConvertLocation(const char* loc, ContextFnT context_fn) const
|
||||
-> DiagnosticLocation override;
|
||||
auto ConvertLoc(const char* loc, ContextFnT context_fn) const
|
||||
-> DiagnosticLoc override;
|
||||
|
||||
private:
|
||||
const TokenizedBuffer* buffer_;
|
||||
|
||||
+18
-21
@@ -17,7 +17,7 @@
|
||||
namespace Carbon::Parse {
|
||||
|
||||
// A relative location for characters in errors.
|
||||
enum class RelativeLocation : int8_t {
|
||||
enum class RelativeLoc : int8_t {
|
||||
Around,
|
||||
After,
|
||||
Before,
|
||||
@@ -25,20 +25,20 @@ enum class RelativeLocation : int8_t {
|
||||
|
||||
} // namespace Carbon::Parse
|
||||
|
||||
// Adapts RelativeLocation for use with formatv.
|
||||
// Adapts RelativeLoc for use with formatv.
|
||||
template <>
|
||||
struct llvm::format_provider<Carbon::Parse::RelativeLocation> {
|
||||
using RelativeLocation = Carbon::Parse::RelativeLocation;
|
||||
static void format(const RelativeLocation& loc, raw_ostream& out,
|
||||
struct llvm::format_provider<Carbon::Parse::RelativeLoc> {
|
||||
using RelativeLoc = Carbon::Parse::RelativeLoc;
|
||||
static void format(const RelativeLoc& loc, raw_ostream& out,
|
||||
StringRef /*style*/) {
|
||||
switch (loc) {
|
||||
case RelativeLocation::Around:
|
||||
case RelativeLoc::Around:
|
||||
out << "around";
|
||||
break;
|
||||
case RelativeLocation::After:
|
||||
case RelativeLoc::After:
|
||||
out << "after";
|
||||
break;
|
||||
case RelativeLocation::Before:
|
||||
case RelativeLoc::Before:
|
||||
out << "before";
|
||||
break;
|
||||
}
|
||||
@@ -338,14 +338,13 @@ auto Context::DiagnoseOperatorFixity(OperatorFixity fixity) -> void {
|
||||
// Infix operators must satisfy the infix operator rules.
|
||||
if (!IsLexicallyValidInfixOperator()) {
|
||||
CARBON_DIAGNOSTIC(BinaryOperatorRequiresWhitespace, Error,
|
||||
"Whitespace missing {0} binary operator.",
|
||||
RelativeLocation);
|
||||
"Whitespace missing {0} binary operator.", RelativeLoc);
|
||||
emitter_->Emit(*position_, BinaryOperatorRequiresWhitespace,
|
||||
tokens().HasLeadingWhitespace(*position_)
|
||||
? RelativeLocation::After
|
||||
? RelativeLoc::After
|
||||
: (tokens().HasTrailingWhitespace(*position_)
|
||||
? RelativeLocation::Before
|
||||
: RelativeLocation::Around));
|
||||
? RelativeLoc::Before
|
||||
: RelativeLoc::Around));
|
||||
}
|
||||
} else {
|
||||
bool prefix = fixity == OperatorFixity::Prefix;
|
||||
@@ -356,18 +355,16 @@ auto Context::DiagnoseOperatorFixity(OperatorFixity fixity) -> void {
|
||||
: tokens().HasLeadingWhitespace(*position_))) {
|
||||
CARBON_DIAGNOSTIC(UnaryOperatorHasWhitespace, Error,
|
||||
"Whitespace is not allowed {0} this unary operator.",
|
||||
RelativeLocation);
|
||||
emitter_->Emit(
|
||||
*position_, UnaryOperatorHasWhitespace,
|
||||
prefix ? RelativeLocation::After : RelativeLocation::Before);
|
||||
RelativeLoc);
|
||||
emitter_->Emit(*position_, UnaryOperatorHasWhitespace,
|
||||
prefix ? RelativeLoc::After : RelativeLoc::Before);
|
||||
} else if (IsLexicallyValidInfixOperator()) {
|
||||
// Pre/postfix operators must not satisfy the infix operator rules.
|
||||
CARBON_DIAGNOSTIC(UnaryOperatorRequiresWhitespace, Error,
|
||||
"Whitespace is required {0} this unary operator.",
|
||||
RelativeLocation);
|
||||
emitter_->Emit(
|
||||
*position_, UnaryOperatorRequiresWhitespace,
|
||||
prefix ? RelativeLocation::Before : RelativeLocation::After);
|
||||
RelativeLoc);
|
||||
emitter_->Emit(*position_, UnaryOperatorRequiresWhitespace,
|
||||
prefix ? RelativeLoc::Before : RelativeLoc::After);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -25,13 +25,13 @@ static auto HandleDeclNameAndParams(Context& context, State after_name)
|
||||
CARBON_DIAGNOSTIC(ExpectedDeclName, Error,
|
||||
"`{0}` introducer should be followed by a name.",
|
||||
Lex::TokenKind);
|
||||
Lex::TokenIndex location = *context.position();
|
||||
if (context.tokens().GetKind(location) == Lex::TokenKind::FileEnd) {
|
||||
// The end of file is often an especially unhelpful location. If that's
|
||||
// the best we can do here, back up the location to the introducer itself.
|
||||
location = state.token;
|
||||
Lex::TokenIndex token = *context.position();
|
||||
if (context.tokens().GetKind(token) == Lex::TokenKind::FileEnd) {
|
||||
// The end of file is an unhelpful diagnostic location. Instead, use the
|
||||
// introducer token.
|
||||
token = state.token;
|
||||
}
|
||||
context.emitter().Emit(location, ExpectedDeclName,
|
||||
context.emitter().Emit(token, ExpectedDeclName,
|
||||
context.tokens().GetKind(state.token));
|
||||
context.ReturnErrorOnState();
|
||||
context.AddLeafNode(NodeKind::InvalidParse, *context.position(),
|
||||
|
||||
@@ -11,16 +11,16 @@
|
||||
|
||||
namespace Carbon::Parse {
|
||||
|
||||
class NodeLocation {
|
||||
class NodeLoc {
|
||||
public:
|
||||
// NOLINTNEXTLINE(google-explicit-constructor)
|
||||
NodeLocation(NodeId node_id) : NodeLocation(node_id, false) {}
|
||||
NodeLocation(NodeId node_id, bool token_only)
|
||||
NodeLoc(NodeId node_id) : NodeLoc(node_id, false) {}
|
||||
NodeLoc(NodeId node_id, bool token_only)
|
||||
: node_id_(node_id), token_only_(token_only) {}
|
||||
// TODO: Have some other way of representing diagnostic that applies to a file
|
||||
// as a whole.
|
||||
// NOLINTNEXTLINE(google-explicit-constructor)
|
||||
NodeLocation(InvalidNodeId node_id) : NodeLocation(node_id, false) {}
|
||||
NodeLoc(InvalidNodeId node_id) : NodeLoc(node_id, false) {}
|
||||
|
||||
auto node_id() const -> NodeId { return node_id_; }
|
||||
auto token_only() const -> bool { return token_only_; }
|
||||
@@ -30,35 +30,33 @@ class NodeLocation {
|
||||
bool token_only_;
|
||||
};
|
||||
|
||||
class NodeLocationConverter : public DiagnosticConverter<NodeLocation> {
|
||||
class NodeLocConverter : public DiagnosticConverter<NodeLoc> {
|
||||
public:
|
||||
explicit NodeLocationConverter(const Lex::TokenizedBuffer* tokens,
|
||||
llvm::StringRef filename,
|
||||
const Tree* parse_tree)
|
||||
explicit NodeLocConverter(const Lex::TokenizedBuffer* tokens,
|
||||
llvm::StringRef filename, const Tree* parse_tree)
|
||||
: token_converter_(tokens),
|
||||
filename_(filename),
|
||||
parse_tree_(parse_tree) {}
|
||||
|
||||
// Map the given token into a diagnostic location.
|
||||
auto ConvertLocation(NodeLocation node_location, ContextFnT context_fn) const
|
||||
-> DiagnosticLocation override {
|
||||
auto ConvertLoc(NodeLoc node_loc, ContextFnT context_fn) const
|
||||
-> DiagnosticLoc override {
|
||||
// Support the invalid token as a way to emit only the filename, when there
|
||||
// is no line association.
|
||||
if (!node_location.node_id().is_valid()) {
|
||||
if (!node_loc.node_id().is_valid()) {
|
||||
return {.filename = filename_};
|
||||
}
|
||||
|
||||
if (node_location.token_only()) {
|
||||
return token_converter_.ConvertLocation(
|
||||
parse_tree_->node_token(node_location.node_id()), context_fn);
|
||||
if (node_loc.token_only()) {
|
||||
return token_converter_.ConvertLoc(
|
||||
parse_tree_->node_token(node_loc.node_id()), context_fn);
|
||||
}
|
||||
|
||||
// Construct a location that encompasses all tokens that descend from this
|
||||
// node (including the root).
|
||||
Lex::TokenIndex start_token =
|
||||
parse_tree_->node_token(node_location.node_id());
|
||||
Lex::TokenIndex start_token = parse_tree_->node_token(node_loc.node_id());
|
||||
Lex::TokenIndex end_token = start_token;
|
||||
for (NodeId desc : parse_tree_->postorder(node_location.node_id())) {
|
||||
for (NodeId desc : parse_tree_->postorder(node_loc.node_id())) {
|
||||
Lex::TokenIndex desc_token = parse_tree_->node_token(desc);
|
||||
if (!desc_token.is_valid()) {
|
||||
continue;
|
||||
@@ -69,13 +67,12 @@ class NodeLocationConverter : public DiagnosticConverter<NodeLocation> {
|
||||
end_token = desc_token;
|
||||
}
|
||||
}
|
||||
DiagnosticLocation start_loc =
|
||||
token_converter_.ConvertLocation(start_token, context_fn);
|
||||
DiagnosticLoc start_loc =
|
||||
token_converter_.ConvertLoc(start_token, context_fn);
|
||||
if (start_token == end_token) {
|
||||
return start_loc;
|
||||
}
|
||||
DiagnosticLocation end_loc =
|
||||
token_converter_.ConvertLocation(end_token, context_fn);
|
||||
DiagnosticLoc end_loc = token_converter_.ConvertLoc(end_token, context_fn);
|
||||
// For multiline locations we simply return the rest of the line for now
|
||||
// since true multiline locations are not yet supported.
|
||||
if (start_loc.line_number != end_loc.line_number) {
|
||||
|
||||
@@ -26,7 +26,7 @@ auto ConstantStore::GetOrAdd(Inst inst, bool is_symbolic) -> ConstantId {
|
||||
|
||||
// Create the new inst and insert the new node.
|
||||
auto inst_id = constants_.getContext()->insts().AddInNoBlock(
|
||||
LocationIdAndInst::Untyped(Parse::NodeId::Invalid, inst));
|
||||
LocIdAndInst::Untyped(Parse::NodeId::Invalid, inst));
|
||||
auto constant_id = is_symbolic
|
||||
? SemIR::ConstantId::ForSymbolicConstant(inst_id)
|
||||
: SemIR::ConstantId::ForTemplateConstant(inst_id);
|
||||
|
||||
@@ -223,7 +223,7 @@ class File : public Printable<File> {
|
||||
// for references of builtins).
|
||||
ValueStore<ImportIRId> import_irs_;
|
||||
|
||||
// Related IR instructions. These are created for LocationIds for instructions
|
||||
// Related IR instructions. These are created for LocIds for instructions
|
||||
// that are import-related.
|
||||
ValueStore<ImportIRInstId> import_ir_insts_;
|
||||
|
||||
|
||||
@@ -83,8 +83,7 @@ class InstNamer {
|
||||
insts[fn.return_slot_id.index] = {
|
||||
fn_scope,
|
||||
GetScopeInfo(fn_scope).insts.AllocateName(
|
||||
*this, sem_ir.insts().GetLocationId(fn.return_slot_id),
|
||||
"return")};
|
||||
*this, sem_ir.insts().GetLocId(fn.return_slot_id), "return")};
|
||||
}
|
||||
if (!fn.body_block_ids.empty()) {
|
||||
AddBlockLabel(fn_scope, fn.body_block_ids.front(), "entry", fn_loc);
|
||||
@@ -269,7 +268,7 @@ class InstNamer {
|
||||
return Name(allocated.insert({name, NameResult()}).first);
|
||||
}
|
||||
|
||||
auto AllocateName(const InstNamer& namer, SemIR::LocationId loc_id,
|
||||
auto AllocateName(const InstNamer& namer, SemIR::LocId loc_id,
|
||||
std::string name) -> Name {
|
||||
// The best (shortest) name for this instruction so far, and the current
|
||||
// name for it.
|
||||
@@ -346,8 +345,7 @@ class InstNamer {
|
||||
|
||||
auto AddBlockLabel(ScopeId scope_id, InstBlockId block_id,
|
||||
std::string name = "",
|
||||
SemIR::LocationId loc_id = SemIR::LocationId::Invalid)
|
||||
-> void {
|
||||
SemIR::LocId loc_id = SemIR::LocId::Invalid) -> void {
|
||||
if (!block_id.is_valid() || labels[block_id.index].second) {
|
||||
return;
|
||||
}
|
||||
@@ -355,7 +353,7 @@ class InstNamer {
|
||||
if (!loc_id.is_valid()) {
|
||||
if (const auto& block = sem_ir_.inst_blocks().Get(block_id);
|
||||
!block.empty()) {
|
||||
loc_id = sem_ir_.insts().GetLocationId(block.front());
|
||||
loc_id = sem_ir_.insts().GetLocId(block.front());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -366,8 +364,8 @@ class InstNamer {
|
||||
|
||||
// Finds and adds a suitable block label for the given SemIR instruction that
|
||||
// represents some kind of branch.
|
||||
auto AddBlockLabel(ScopeId scope_id, SemIR::LocationId loc_id,
|
||||
AnyBranch branch) -> void {
|
||||
auto AddBlockLabel(ScopeId scope_id, SemIR::LocId loc_id, AnyBranch branch)
|
||||
-> void {
|
||||
llvm::StringRef name;
|
||||
switch (parse_tree_.node_kind(loc_id.node_id())) {
|
||||
case Parse::NodeKind::IfExprIf:
|
||||
@@ -454,7 +452,7 @@ class InstNamer {
|
||||
auto add_inst_name = [&](std::string name) {
|
||||
insts[inst_id.index] = {
|
||||
scope_id, scope.insts.AllocateName(
|
||||
*this, sem_ir_.insts().GetLocationId(inst_id), name)};
|
||||
*this, sem_ir_.insts().GetLocId(inst_id), name)};
|
||||
};
|
||||
auto add_inst_name_id = [&](NameId name_id, llvm::StringRef suffix = "") {
|
||||
add_inst_name(
|
||||
@@ -462,8 +460,7 @@ class InstNamer {
|
||||
};
|
||||
|
||||
if (auto branch = untyped_inst.TryAs<AnyBranch>()) {
|
||||
AddBlockLabel(scope_id, sem_ir_.insts().GetLocationId(inst_id),
|
||||
*branch);
|
||||
AddBlockLabel(scope_id, sem_ir_.insts().GetLocId(inst_id), *branch);
|
||||
}
|
||||
|
||||
CARBON_KIND_SWITCH(untyped_inst) {
|
||||
|
||||
@@ -496,21 +496,20 @@ struct ImportIRInstId : public IdBase, public Printable<InstId> {
|
||||
// - index > Invalid: A Parse::NodeId in the current IR.
|
||||
// - index < Invalid: An ImportIRInstId.
|
||||
// - index == Invalid: Can be used for either.
|
||||
struct LocationId : public IdBase, public Printable<FunctionId> {
|
||||
struct LocId : public IdBase, public Printable<FunctionId> {
|
||||
// An explicitly invalid function ID.
|
||||
static const LocationId Invalid;
|
||||
static const LocId Invalid;
|
||||
|
||||
// NOLINTNEXTLINE(google-explicit-constructor)
|
||||
constexpr LocationId(Parse::InvalidNodeId /*invalid*/)
|
||||
: IdBase(InvalidIndex) {}
|
||||
constexpr LocId(Parse::InvalidNodeId /*invalid*/) : IdBase(InvalidIndex) {}
|
||||
|
||||
// NOLINTNEXTLINE(google-explicit-constructor)
|
||||
constexpr LocationId(Parse::NodeId node_id) : IdBase(node_id.index) {
|
||||
constexpr LocId(Parse::NodeId node_id) : IdBase(node_id.index) {
|
||||
CARBON_CHECK(node_id.is_valid() == is_valid());
|
||||
}
|
||||
|
||||
// NOLINTNEXTLINE(google-explicit-constructor)
|
||||
constexpr LocationId(ImportIRInstId inst_id)
|
||||
constexpr LocId(ImportIRInstId inst_id)
|
||||
: IdBase(InvalidIndex + ImportIRInstId::InvalidIndex - inst_id.index) {
|
||||
CARBON_CHECK(inst_id.is_valid() == is_valid());
|
||||
}
|
||||
@@ -542,7 +541,7 @@ struct LocationId : public IdBase, public Printable<FunctionId> {
|
||||
}
|
||||
};
|
||||
|
||||
constexpr LocationId LocationId::Invalid = LocationId(Parse::NodeId::Invalid);
|
||||
constexpr LocId LocId::Invalid = LocId(Parse::NodeId::Invalid);
|
||||
|
||||
} // namespace Carbon::SemIR
|
||||
|
||||
|
||||
@@ -22,7 +22,7 @@ struct ImportIR : public Printable<ImportIR> {
|
||||
};
|
||||
|
||||
// A reference to an instruction in an imported IR. Used for diagnostics with
|
||||
// LocationId.
|
||||
// LocId.
|
||||
struct ImportIRInst : public Printable<ImportIRInst> {
|
||||
auto Print(llvm::raw_ostream& out) const -> void {
|
||||
out << ir_id << ":" << inst_id;
|
||||
|
||||
+18
-20
@@ -288,15 +288,15 @@ inline auto operator<<(llvm::raw_ostream& out, TypedInst inst)
|
||||
return out;
|
||||
}
|
||||
|
||||
// Associates a LocationId and Inst in order to provide type-checking that the
|
||||
// Associates a LocId and Inst in order to provide type-checking that the
|
||||
// TypedNodeId corresponds to the InstT.
|
||||
struct LocationIdAndInst {
|
||||
struct LocIdAndInst {
|
||||
// In cases where the NodeId is untyped, an inst_id, or the InstT is unknown,
|
||||
// the NodeId check can't be done at compile time.
|
||||
// TODO: Consider runtime validation that InstT::Kind::TypedNodeId
|
||||
// corresponds.
|
||||
static auto Untyped(LocationId loc_id, Inst inst) -> LocationIdAndInst {
|
||||
return LocationIdAndInst(loc_id, inst, /*is_untyped=*/true);
|
||||
static auto Untyped(LocId loc_id, Inst inst) -> LocIdAndInst {
|
||||
return LocIdAndInst(loc_id, inst, /*is_untyped=*/true);
|
||||
}
|
||||
|
||||
// For the common case, support construction as:
|
||||
@@ -304,7 +304,7 @@ struct LocationIdAndInst {
|
||||
template <typename InstT>
|
||||
requires(Internal::HasNodeId<InstT>)
|
||||
// NOLINTNEXTLINE(google-explicit-constructor)
|
||||
LocationIdAndInst(decltype(InstT::Kind)::TypedNodeId node_id, InstT inst)
|
||||
LocIdAndInst(decltype(InstT::Kind)::TypedNodeId node_id, InstT inst)
|
||||
: loc_id(node_id), inst(inst) {}
|
||||
|
||||
// For cases with no parse node, support construction as:
|
||||
@@ -312,23 +312,22 @@ struct LocationIdAndInst {
|
||||
template <typename InstT>
|
||||
requires(!Internal::HasNodeId<InstT>)
|
||||
// NOLINTNEXTLINE(google-explicit-constructor)
|
||||
LocationIdAndInst(InstT inst) : loc_id(Parse::NodeId::Invalid), inst(inst) {}
|
||||
LocIdAndInst(InstT inst) : loc_id(Parse::NodeId::Invalid), inst(inst) {}
|
||||
|
||||
// If TypedNodeId is Parse::NodeId, allow construction with a LocationId
|
||||
// If TypedNodeId is Parse::NodeId, allow construction with a LocId
|
||||
// rather than requiring Untyped.
|
||||
// TODO: This is somewhat historical due to fetching the NodeId from insts()
|
||||
// for things like Temporary; should we require Untyped in these cases?
|
||||
template <typename InstT>
|
||||
requires(std::same_as<typename decltype(InstT::Kind)::TypedNodeId,
|
||||
Parse::NodeId>)
|
||||
LocationIdAndInst(LocationId loc_id, InstT inst)
|
||||
: loc_id(loc_id), inst(inst) {}
|
||||
LocIdAndInst(LocId loc_id, InstT inst) : loc_id(loc_id), inst(inst) {}
|
||||
|
||||
LocationId loc_id;
|
||||
LocId loc_id;
|
||||
Inst inst;
|
||||
|
||||
private:
|
||||
explicit LocationIdAndInst(LocationId loc_id, Inst inst, bool /*is_untyped*/)
|
||||
explicit LocIdAndInst(LocId loc_id, Inst inst, bool /*is_untyped*/)
|
||||
: loc_id(loc_id), inst(inst) {}
|
||||
};
|
||||
|
||||
@@ -340,7 +339,7 @@ class InstStore {
|
||||
// instruction block. Check::Context::AddInst or InstBlockStack::AddInst
|
||||
// should usually be used instead, to add the instruction to the current
|
||||
// block.
|
||||
auto AddInNoBlock(LocationIdAndInst loc_id_and_inst) -> InstId {
|
||||
auto AddInNoBlock(LocIdAndInst loc_id_and_inst) -> InstId {
|
||||
loc_ids_.push_back(loc_id_and_inst.loc_id);
|
||||
return values_.Add(loc_id_and_inst.inst);
|
||||
}
|
||||
@@ -349,8 +348,8 @@ class InstStore {
|
||||
auto Get(InstId inst_id) const -> Inst { return values_.Get(inst_id); }
|
||||
|
||||
// Returns the requested instruction and its location ID.
|
||||
auto GetWithLocationId(InstId inst_id) const -> LocationIdAndInst {
|
||||
return LocationIdAndInst::Untyped(GetLocationId(inst_id), Get(inst_id));
|
||||
auto GetWithLocId(InstId inst_id) const -> LocIdAndInst {
|
||||
return LocIdAndInst::Untyped(GetLocId(inst_id), Get(inst_id));
|
||||
}
|
||||
|
||||
// Returns whether the requested instruction is the specified type.
|
||||
@@ -383,7 +382,7 @@ class InstStore {
|
||||
return TryGetAs<InstT>(inst_id);
|
||||
}
|
||||
|
||||
auto GetLocationId(InstId inst_id) const -> LocationId {
|
||||
auto GetLocId(InstId inst_id) const -> LocId {
|
||||
CARBON_CHECK(inst_id.index >= 0) << inst_id.index;
|
||||
CARBON_CHECK(inst_id.index < (int)loc_ids_.size())
|
||||
<< inst_id.index << " " << loc_ids_.size();
|
||||
@@ -394,15 +393,14 @@ class InstStore {
|
||||
auto Set(InstId inst_id, Inst inst) -> void { values_.Get(inst_id) = inst; }
|
||||
|
||||
// Overwrites a given instruction's location with a new value.
|
||||
auto SetLocationId(InstId inst_id, LocationId loc_id) -> void {
|
||||
auto SetLocId(InstId inst_id, LocId loc_id) -> void {
|
||||
loc_ids_[inst_id.index] = loc_id;
|
||||
}
|
||||
|
||||
// Overwrites a given instruction and location ID with a new value.
|
||||
auto SetLocationIdAndInst(InstId inst_id, LocationIdAndInst loc_id_and_inst)
|
||||
-> void {
|
||||
auto SetLocIdAndInst(InstId inst_id, LocIdAndInst loc_id_and_inst) -> void {
|
||||
Set(inst_id, loc_id_and_inst.inst);
|
||||
SetLocationId(inst_id, loc_id_and_inst.loc_id);
|
||||
SetLocId(inst_id, loc_id_and_inst.loc_id);
|
||||
}
|
||||
|
||||
// Reserves space.
|
||||
@@ -415,7 +413,7 @@ class InstStore {
|
||||
auto size() const -> int { return values_.size(); }
|
||||
|
||||
private:
|
||||
llvm::SmallVector<LocationId> loc_ids_;
|
||||
llvm::SmallVector<LocId> loc_ids_;
|
||||
ValueStore<InstId> values_;
|
||||
};
|
||||
|
||||
|
||||
@@ -12,9 +12,8 @@ namespace Carbon {
|
||||
|
||||
namespace {
|
||||
struct FilenameConverter : DiagnosticConverter<llvm::StringRef> {
|
||||
auto ConvertLocation(llvm::StringRef filename,
|
||||
ContextFnT /*context_fn*/) const
|
||||
-> DiagnosticLocation override {
|
||||
auto ConvertLoc(llvm::StringRef filename, ContextFnT /*context_fn*/) const
|
||||
-> DiagnosticLoc override {
|
||||
return {.filename = filename};
|
||||
}
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user