// 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 "common/check.h" #include "toolchain/base/pretty_stack_trace_function.h" #include "toolchain/check/context.h" #include "toolchain/parse/tree_node_location_translator.h" #include "toolchain/sem_ir/file.h" namespace Carbon::Check { auto CheckParseTree(const SemIR::File& builtin_ir, const Lex::TokenizedBuffer& tokens, const Parse::Tree& parse_tree, DiagnosticConsumer& consumer, llvm::raw_ostream* vlog_stream) -> SemIR::File { auto semantics_ir = SemIR::File(&builtin_ir); Parse::NodeLocationTranslator translator(&tokens, &parse_tree); ErrorTrackingDiagnosticConsumer err_tracker(consumer); DiagnosticEmitter emitter(translator, err_tracker); Check::Context context(tokens, emitter, parse_tree, semantics_ir, vlog_stream); PrettyStackTraceFunction context_dumper( [&](llvm::raw_ostream& output) { context.PrintForStackDump(output); }); // Add a block for the Parse::Tree. context.node_block_stack().Push(); context.PushScope(); // Loops over all nodes in the tree. On some errors, this may return early, // for example if an unrecoverable state is encountered. for (auto parse_node : parse_tree.postorder()) { // clang warns on unhandled enum values; clang-tidy is incorrect here. // NOLINTNEXTLINE(bugprone-switch-missing-default-case) switch (auto parse_kind = parse_tree.node_kind(parse_node)) { #define CARBON_PARSE_NODE_KIND(Name) \ case Parse::NodeKind::Name: { \ if (!Check::Handle##Name(context, parse_node)) { \ CARBON_CHECK(err_tracker.seen_error()) \ << "Handle" #Name " returned false without printing a diagnostic"; \ semantics_ir.set_has_errors(true); \ return semantics_ir; \ } \ break; \ } #include "toolchain/parse/node_kind.def" } } // Pop information for the file-level scope. semantics_ir.set_top_node_block_id(context.node_block_stack().Pop()); context.PopScope(); context.VerifyOnFinish(); semantics_ir.set_has_errors(err_tracker.seen_error()); #ifndef NDEBUG if (auto verify = semantics_ir.Verify(); !verify.ok()) { CARBON_FATAL() << semantics_ir << "Built invalid semantics IR: " << verify.error() << "\n"; } #endif return semantics_ir; } } // namespace Carbon::Check