// Part of the Carbon Language project, under the Apache License v2.0 with LLVM // Exceptions. See /LICENSE for license information. // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception #ifndef CARBON_TOOLCHAIN_CHECK_MERGE_H_ #define CARBON_TOOLCHAIN_CHECK_MERGE_H_ #include "toolchain/check/context.h" #include "toolchain/check/subst.h" #include "toolchain/sem_ir/ids.h" namespace Carbon::Check { // Diagnoses an `extern` declaration that was not preceded by a declaration in // the API file. auto DiagnoseExternRequiresDeclInApiFile(Context& context, SemIR::LocId loc_id) -> void; // Information on new and previous declarations for DiagnoseIfInvalidRedecl. struct RedeclInfo { explicit RedeclInfo(const SemIR::EntityWithParamsBase& params, SemIR::LocId loc_id, bool is_definition) : loc_id(loc_id), is_definition(is_definition), is_extern(params.is_extern), extern_library_id(params.extern_library_id) {} // The associated diagnostic location. SemIR::LocId loc_id; // True if a definition. bool is_definition; // True if an `extern` declaration. bool is_extern; // The library name in `extern library`, or `None` if not present. SemIR::LibraryNameId extern_library_id; }; // Checks for various invalid redeclarations. This can emit diagnostics. // However, merging is still often appropriate for error recovery, so this // doesn't return whether a diagnostic occurred. // // The kinds of things this verifies are: // - A declaration is not redundant. // - A definition doesn't redefine a prior definition. // - The use of `extern` is consistent within a library. // - Multiple libraries do not declare non-`extern`. auto DiagnoseIfInvalidRedecl(Context& context, Lex::TokenKind decl_kind, SemIR::NameId name_id, RedeclInfo new_decl, RedeclInfo prev_decl, SemIR::ImportIRId prev_import_ir_id) -> void; // When the prior name lookup result is an import and we are successfully // merging, replace the name lookup result with the reference in the current // file. auto ReplacePrevInstForMerge(Context& context, SemIR::NameScopeId scope_id, SemIR::NameId name_id, SemIR::InstId new_inst_id) -> void; // Information about the parameters of a declaration, which is common across // different kinds of entity such as classes and functions. struct DeclParams { explicit DeclParams(const SemIR::EntityWithParamsBase& base) : loc_id(base.latest_decl_id()), first_param_node_id(base.first_param_node_id), last_param_node_id(base.last_param_node_id), implicit_param_patterns_id(base.implicit_param_patterns_id), param_patterns_id(base.param_patterns_id) {} DeclParams(SemIR::LocId loc_id, Parse::NodeId first_param_node_id, Parse::NodeId last_param_node_id, SemIR::InstBlockId implicit_param_patterns_id, SemIR::InstBlockId param_patterns_id) : loc_id(loc_id), first_param_node_id(first_param_node_id), last_param_node_id(last_param_node_id), implicit_param_patterns_id(implicit_param_patterns_id), param_patterns_id(param_patterns_id) {} // The location of the declaration of the entity. SemIR::LocId loc_id; // Parse tree bounds for the parameters, including both implicit and explicit // parameters. These will be compared to match between declaration and // definition. Parse::NodeId first_param_node_id; Parse::NodeId last_param_node_id; // The implicit parameters of the entity. Can be `None` if there is no // implicit parameter list. SemIR::InstBlockId implicit_param_patterns_id; // The explicit parameters of the entity. Can be `None` if there is no // explicit parameter list. SemIR::InstBlockId param_patterns_id; }; // Checks that the parameters in a redeclaration of an entity match the // parameters in the prior declaration. If not, produces a diagnostic if // `diagnose` is true, and returns false. If `check_self` is false, // type and name mismatches will not be diagnosed for the `self` parameter // (if any), but form mismatches will still be diagnosed. auto CheckRedeclParamsMatch(Context& context, const DeclParams& new_entity, const DeclParams& prev_entity, SemIR::SpecificId prev_specific_id, bool diagnose, bool check_syntax, bool check_self) -> bool; inline auto CheckRedeclParamsMatch(Context& context, const DeclParams& new_entity, const DeclParams& prev_entity) -> bool { return CheckRedeclParamsMatch(context, new_entity, prev_entity, SemIR::SpecificId::None, /*diagnose=*/true, /*check_syntax=*/true, /*check_self=*/true); } } // namespace Carbon::Check #endif // CARBON_TOOLCHAIN_CHECK_MERGE_H_