Files
carbon-lang/toolchain/check/handle_call_expression.cpp
T
Richard Smith f389844893 Remove nearly all uses of StubReferences. (#3249)
The speculative insertion of StubReferences after elements in an
argument list turned out to not be necessary, because we decided we want
to insert per-argument initialization steps after all arguments are
evaluated, rather than interleaving them. The StubReferences we insert
are causing some minor code complexity, so remove them.

We still create StubReferences when performing patch-ups of
already-emitted code, but we no longer ever need to look through them
when determining whether an initializer was a literal or when evaluating
a type expression.
2023-09-21 00:00:36 +00:00

78 lines
2.8 KiB
C++

// Part of the Carbon Language project, under the Apache License v2.0 with LLVM
// Exceptions. See /LICENSE for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
#include "toolchain/check/context.h"
#include "toolchain/sem_ir/node.h"
namespace Carbon::Check {
auto HandleCallExpression(Context& context, Parse::Node parse_node) -> bool {
// Process the final explicit call argument, but leave the arguments block on
// the stack until we add the return slot argument.
context.ParamOrArgEndNoPop(Parse::NodeKind::CallExpressionStart);
// TODO: Convert to call expression.
auto [call_expr_parse_node, name_id] =
context.node_stack()
.PopWithParseNode<Parse::NodeKind::CallExpressionStart>();
auto name_node = context.semantics_ir().GetNode(name_id);
if (name_node.kind() != SemIR::NodeKind::FunctionDeclaration) {
// TODO: Work on error.
context.TODO(parse_node, "Not a callable name");
context.node_stack().Push(parse_node, name_id);
context.ParamOrArgPop();
return true;
}
auto function_id = name_node.GetAsFunctionDeclaration();
const auto& callable = context.semantics_ir().GetFunction(function_id);
// For functions with an implicit return type, the return type is the empty
// tuple type.
SemIR::TypeId type_id = callable.return_type_id;
if (!type_id.is_valid()) {
type_id = context.CanonicalizeTupleType(call_expr_parse_node, {});
}
// If there is a return slot, add a corresponding argument.
if (callable.return_slot_id.is_valid()) {
// Tentatively put storage for a temporary in the function's return slot.
// This will be replaced if necessary when we perform initialization.
auto temp_id = context.AddNode(SemIR::Node::TemporaryStorage::Make(
call_expr_parse_node, callable.return_type_id));
context.ParamOrArgSave(temp_id);
}
// Convert the arguments to match the parameters.
auto refs_id = context.ParamOrArgPop();
if (!context.ImplicitAsForArgs(call_expr_parse_node, refs_id,
name_node.parse_node(), callable.param_refs_id,
callable.return_slot_id.is_valid())) {
context.node_stack().Push(parse_node, SemIR::NodeId::BuiltinError);
return true;
}
auto call_node_id = context.AddNode(SemIR::Node::Call::Make(
call_expr_parse_node, type_id, refs_id, function_id));
context.node_stack().Push(parse_node, call_node_id);
return true;
}
auto HandleCallExpressionComma(Context& context, Parse::Node /*parse_node*/)
-> bool {
context.ParamOrArgComma();
return true;
}
auto HandleCallExpressionStart(Context& context, Parse::Node parse_node)
-> bool {
auto name_id = context.node_stack().PopExpression();
context.node_stack().Push(parse_node, name_id);
context.ParamOrArgStart();
return true;
}
} // namespace Carbon::Check