diff --git a/toolchain/check/cpp/import.cpp b/toolchain/check/cpp/import.cpp index 9582e9fccb19..6e8a2bf1eb07 100644 --- a/toolchain/check/cpp/import.cpp +++ b/toolchain/check/cpp/import.cpp @@ -480,7 +480,8 @@ auto ImportCppFiles(Context& context, SemIR::NameScope& name_scope = context.name_scopes().Get(name_scope_id); name_scope.set_is_closed_import(true); name_scope.set_clang_decl_context_id(context.clang_decls().Add( - {.decl = generated_ast->getASTContext().getTranslationUnitDecl(), + {.key = SemIR::ClangDeclKey( + generated_ast->getASTContext().getTranslationUnitDecl()), .inst_id = name_scope.inst_id()})); if (ast_has_error) { @@ -500,7 +501,7 @@ static auto GetDeclContext(Context& context, SemIR::NameScopeId scope_id) auto scope_clang_decl_context_id = context.name_scopes().Get(scope_id).clang_decl_context_id(); return dyn_cast( - context.clang_decls().Get(scope_clang_decl_context_id).decl); + context.clang_decls().Get(scope_clang_decl_context_id).key.decl); } // Looks up for constructors in the class scope and returns the lookup result. @@ -511,7 +512,7 @@ static auto ClangConstructorLookup(Context& context, clang::Sema& sema = context.clang_sema(); clang::Decl* decl = - context.clang_decls().Get(scope.clang_decl_context_id()).decl; + context.clang_decls().Get(scope.clang_decl_context_id()).key.decl; return sema.LookupConstructors(cast(decl)); } @@ -533,7 +534,8 @@ static auto IsDeclInjectedClassName(Context& context, const SemIR::ClangDecl& clang_decl = context.clang_decls().Get( context.name_scopes().Get(scope_id).clang_decl_context_id()); - const auto* scope_record_decl = cast(clang_decl.decl); + const auto* scope_record_decl = + cast(clang_decl.key.decl); const clang::ASTContext& ast_context = context.ast_context(); CARBON_CHECK(ast_context.getCanonicalTagType(scope_record_decl) == @@ -596,16 +598,17 @@ static auto ClangLookupName(Context& context, SemIR::NameScopeId scope_id, } // Returns whether `decl` already mapped to an instruction. -static auto IsClangDeclImported(Context& context, clang::Decl* decl) -> bool { - return context.clang_decls().Lookup(decl->getCanonicalDecl()).has_value(); +static auto IsClangDeclImported(Context& context, SemIR::ClangDeclKey key) + -> bool { + return context.clang_decls().Lookup(key).has_value(); } // If `decl` already mapped to an instruction, returns that instruction. // Otherwise returns `None`. -static auto LookupClangDeclInstId(Context& context, clang::Decl* decl) +static auto LookupClangDeclInstId(Context& context, SemIR::ClangDeclKey key) -> SemIR::InstId { const auto& clang_decls = context.clang_decls(); - if (auto context_clang_decl_id = clang_decls.Lookup(decl->getCanonicalDecl()); + if (auto context_clang_decl_id = clang_decls.Lookup(key); context_clang_decl_id.has_value()) { return clang_decls.Get(context_clang_decl_id).inst_id; } @@ -626,24 +629,27 @@ static auto GetParentDecl(clang::Decl* clang_decl) -> clang::Decl* { // was already imported. static auto GetParentNameScopeId(Context& context, clang::Decl* clang_decl) -> SemIR::NameScopeId { - SemIR::InstId parent_inst_id = - LookupClangDeclInstId(context, GetParentDecl(clang_decl)); - CARBON_CHECK(parent_inst_id.has_value()); + auto* parent_decl = GetParentDecl(clang_decl); - CARBON_KIND_SWITCH(context.insts().Get(parent_inst_id)) { - case CARBON_KIND(SemIR::ClassDecl class_decl): { - return context.classes().Get(class_decl.class_id).scope_id; - } - case CARBON_KIND(SemIR::InterfaceDecl interface_decl): { - return context.interfaces().Get(interface_decl.interface_id).scope_id; - } - case CARBON_KIND(SemIR::Namespace namespace_inst): { - return namespace_inst.name_scope_id; - } - default: { - CARBON_FATAL("Unexpected parent instruction kind"); - } + if (auto* tag_decl = dyn_cast(parent_decl)) { + auto class_inst_id = + LookupClangDeclInstId(context, SemIR::ClangDeclKey(tag_decl)); + CARBON_CHECK(class_inst_id.has_value()); + return context.classes() + .Get(context.insts().GetAs(class_inst_id).class_id) + .scope_id; } + + if (isa(parent_decl)) { + auto namespace_inst_id = LookupClangDeclInstId( + context, SemIR::ClangDeclKey::ForNonFunctionDecl(parent_decl)); + CARBON_CHECK(namespace_inst_id.has_value()); + return context.insts() + .GetAs(namespace_inst_id) + .name_scope_id; + } + + CARBON_FATAL("Unexpected kind of parent {0}", parent_decl->getDeclKindName()); } // Imports a namespace declaration from Clang to Carbon. If successful, returns @@ -652,9 +658,9 @@ static auto GetParentNameScopeId(Context& context, clang::Decl* clang_decl) static auto ImportNamespaceDecl(Context& context, clang::NamespaceDecl* clang_decl) -> SemIR::InstId { + auto key = SemIR::ClangDeclKey(clang_decl); // Check if the declaration is already mapped. - if (SemIR::InstId existing_inst_id = - LookupClangDeclInstId(context, clang_decl); + if (SemIR::InstId existing_inst_id = LookupClangDeclInstId(context, key); existing_inst_id.has_value()) { return existing_inst_id; } @@ -665,8 +671,8 @@ static auto ImportNamespaceDecl(Context& context, /*import_id=*/SemIR::InstId::None); context.name_scopes() .Get(result.name_scope_id) - .set_clang_decl_context_id(context.clang_decls().Add( - {.decl = clang_decl->getCanonicalDecl(), .inst_id = result.inst_id})); + .set_clang_decl_context_id( + context.clang_decls().Add({.key = key, .inst_id = result.inst_id})); return result.inst_id; } @@ -731,8 +737,9 @@ static auto ImportTagDecl(Context& context, clang::TagDecl* clang_decl) AddIdentifierName(context, clang_decl->getName())); // TODO: The caller does the same lookup. Avoid doing it twice. - auto clang_decl_id = context.clang_decls().Add( - {.decl = clang_decl->getCanonicalDecl(), .inst_id = class_inst_id}); + auto key = SemIR::ClangDeclKey(clang_decl); + auto clang_decl_id = + context.clang_decls().Add({.key = key, .inst_id = class_inst_id}); // Name lookup into the Carbon class looks in the C++ class definition. auto& class_info = context.classes().Get(class_id); @@ -909,8 +916,10 @@ static auto ImportClassObjectRepr(Context& context, SemIR::ClassId class_id, context, class_type_inst_id, field_type_inst_id), .name_id = field_name_id, .index = SemIR::ElementIndex(fields.size())})); - context.clang_decls().Add( - {.decl = decl->getCanonicalDecl(), .inst_id = field_decl_id}); + // The imported SemIR::FieldDecl represents the original declaration `decl`, + // which is either the field or the indirect field declaration. + auto key = SemIR::ClangDeclKey::ForNonFunctionDecl(decl); + context.clang_decls().Add({.key = key, .inst_id = field_decl_id}); // Compute the offset to the field that appears directly in the class. uint64_t offset = clang_layout.getFieldOffset( @@ -1026,11 +1035,13 @@ static auto BuildEnumDefinition(Context& context, static auto ImportEnumConstantDecl(Context& context, clang::EnumConstantDecl* enumerator_decl) -> SemIR::InstId { - CARBON_CHECK(!IsClangDeclImported(context, enumerator_decl)); + auto key = SemIR::ClangDeclKey(enumerator_decl); + CARBON_CHECK(!IsClangDeclImported(context, key)); // Find the enclosing enum type. - auto type_inst_id = LookupClangDeclInstId( - context, cast(enumerator_decl->getDeclContext())); + auto enum_key = SemIR::ClangDeclKey( + cast(enumerator_decl->getDeclContext())); + auto type_inst_id = LookupClangDeclInstId(context, enum_key); auto type_id = context.types().GetTypeIdForTypeInstId(type_inst_id); // Build a corresponding IntValue. @@ -1040,15 +1051,13 @@ static auto ImportEnumConstantDecl(Context& context, auto inst_id = AddInstInNoBlock( context, loc_id, {.type_id = type_id, .int_id = int_id}); context.imports().push_back(inst_id); - context.clang_decls().Add( - {.decl = enumerator_decl->getCanonicalDecl(), .inst_id = inst_id}); + context.clang_decls().Add({.key = key, .inst_id = inst_id}); return inst_id; } -// Mark the given `Decl` as failed in `clang_decls`. -static auto MarkFailedDecl(Context& context, clang::Decl* clang_decl) { - context.clang_decls().Add({.decl = clang_decl->getCanonicalDecl(), - .inst_id = SemIR::ErrorInst::InstId}); +// Mark the given `key` as failed in `clang_decls`. +static auto MarkFailedDecl(Context& context, SemIR::ClangDeclKey key) { + context.clang_decls().Add({.key = key, .inst_id = SemIR::ErrorInst::InstId}); } // Creates an integer type of the given size. @@ -1143,13 +1152,13 @@ static auto MapTagType(Context& context, const clang::TagType& type) CARBON_CHECK(tag_decl); // Check if the declaration is already mapped. - SemIR::InstId tag_inst_id = LookupClangDeclInstId(context, tag_decl); + auto key = SemIR::ClangDeclKey(tag_decl); + SemIR::InstId tag_inst_id = LookupClangDeclInstId(context, key); if (!tag_inst_id.has_value()) { if (auto* record_decl = dyn_cast(tag_decl)) { auto custom_type = LookupCustomRecordType(context, record_decl); if (custom_type.inst_id.has_value()) { - context.clang_decls().Add( - {.decl = record_decl, .inst_id = custom_type.inst_id}); + context.clang_decls().Add({.key = key, .inst_id = custom_type.inst_id}); return custom_type; } } @@ -1332,21 +1341,28 @@ static auto MakeImplicitParamPatternsBlockId( // TODO: Consider refactoring to extract and reuse more logic from // `HandleAnyBindingPattern()`. static auto MakeParamPatternsBlockId(Context& context, SemIR::LocId loc_id, - const clang::FunctionDecl& clang_decl) - -> SemIR::InstBlockId { - if (clang_decl.parameters().empty()) { + const clang::FunctionDecl& clang_decl, + int num_params) -> SemIR::InstBlockId { + if (clang_decl.parameters().empty() || num_params == 0) { return SemIR::InstBlockId::Empty; } llvm::SmallVector params; - params.reserve(clang_decl.getNumNonObjectParams()); - for (unsigned i : llvm::seq(clang_decl.getNumNonObjectParams())) { + params.reserve(num_params); + CARBON_CHECK( + static_cast(clang_decl.getNumNonObjectParams()) >= num_params, + "varargs functions are not supported"); + const auto* function_type = + clang_decl.getType()->castAs(); + for (int i : llvm::seq(num_params)) { const auto* param = clang_decl.getNonObjectParameter(i); - // TODO: Get the parameter type from the function, not from the - // `ParmVarDecl`. The type of the `ParmVarDecl` is the type within the - // function, and isn't in general the same as the type that's exposed to - // callers. In particular, the parameter type exposed to callers will never - // be cv-qualified. - clang::QualType param_type = param->getType(); + // The parameter type is decayed but hasn't necessarily had its qualifiers + // removed. + // TODO: The presence of qualifiers here is probably a Clang bug. + clang::QualType param_type = + function_type + ->getParamType(clang_decl.hasCXXExplicitFunctionObjectParameter() + + i) + .getUnqualifiedType(); // We map `T&` parameters to `addr param: T*`, and `T&&` parameters to // `param: T`. @@ -1365,8 +1381,9 @@ static auto MakeParamPatternsBlockId(Context& context, SemIR::LocId loc_id, EndSubpatternAsExpr(context, orig_type_inst_id); if (!type_id.has_value()) { - context.TODO(loc_id, llvm::formatv("Unsupported: parameter type: {0}", - param->getType().getAsString())); + context.TODO(loc_id, + llvm::formatv("Unsupported: parameter type: {0}", + function_type->getParamType(i).getAsString())); return SemIR::InstBlockId::None; } @@ -1431,17 +1448,15 @@ static auto GetReturnTypeExpr(Context& context, SemIR::LocId loc_id, return mapped_type; } - if (!isa(clang_decl)) { + auto* ctor = dyn_cast(clang_decl); + if (!ctor) { // void. return TypeExpr::None; } // TODO: Make this a `PartialType`. SemIR::TypeInstId record_type_inst_id = context.types().GetAsTypeInstId( - context.clang_decls() - .Get(context.clang_decls().Lookup( - cast(clang_decl->getParent()))) - .inst_id); + LookupClangDeclInstId(context, SemIR::ClangDeclKey(ctor->getParent()))); return { .inst_id = record_type_inst_id, .type_id = context.types().GetTypeIdForTypeInstId(record_type_inst_id)}; @@ -1494,7 +1509,8 @@ struct FunctionParamsInsts { // Produces a diagnostic and returns `std::nullopt` if the function declaration // has an unsupported parameter type. static auto CreateFunctionParamsInsts(Context& context, SemIR::LocId loc_id, - clang::FunctionDecl* clang_decl) + clang::FunctionDecl* clang_decl, + int num_params) -> std::optional { if (isa(clang_decl)) { context.TODO(loc_id, "Unsupported: Destructor"); @@ -1507,7 +1523,7 @@ static auto CreateFunctionParamsInsts(Context& context, SemIR::LocId loc_id, return std::nullopt; } auto param_patterns_id = - MakeParamPatternsBlockId(context, loc_id, *clang_decl); + MakeParamPatternsBlockId(context, loc_id, *clang_decl, num_params); if (!param_patterns_id.has_value()) { return std::nullopt; } @@ -1531,10 +1547,11 @@ static auto GetFunctionName(Context& context, clang::FunctionDecl* clang_decl) -> SemIR::NameId { switch (clang_decl->getDeclName().getNameKind()) { case clang::DeclarationName::CXXConstructorName: { + auto key = SemIR::ClangDeclKey( + cast(clang_decl)->getParent()); return context.classes() .Get(context.insts() - .GetAs(LookupClangDeclInstId( - context, cast(clang_decl->getParent()))) + .GetAs(LookupClangDeclInstId(context, key)) .class_id) .name_id; } @@ -1554,14 +1571,14 @@ static auto GetFunctionName(Context& context, clang::FunctionDecl* clang_decl) // * Have not been imported before. // * Be of supported type (ignoring parameters). static auto ImportFunction(Context& context, SemIR::LocId loc_id, - clang::FunctionDecl* clang_decl) + clang::FunctionDecl* clang_decl, int num_params) -> std::optional { context.scope_stack().PushForDeclName(); context.inst_block_stack().Push(); context.pattern_block_stack().Push(); auto function_params_insts = - CreateFunctionParamsInsts(context, loc_id, clang_decl); + CreateFunctionParamsInsts(context, loc_id, clang_decl, num_params); auto pattern_block_id = context.pattern_block_stack().Pop(); auto decl_block_id = context.inst_block_stack().Pop(); @@ -1614,7 +1631,8 @@ static auto ImportFunction(Context& context, SemIR::LocId loc_id, .self_param_id = FindSelfPattern( context, function_params_insts->implicit_param_patterns_id), .clang_decl_id = context.clang_decls().Add( - {.decl = clang_decl, .inst_id = decl_id})}}; + {.key = SemIR::ClangDeclKey::ForFunctionDecl(clang_decl, num_params), + .inst_id = decl_id})}}; function_decl.function_id = context.functions().Add(function_info); function_decl.type_id = GetFunctionType(context, function_decl.function_id, @@ -1623,34 +1641,40 @@ static auto ImportFunction(Context& context, SemIR::LocId loc_id, return function_decl.function_id; } -auto ImportCppFunctionDecl(Context& context, SemIR::LocId loc_id, - clang::FunctionDecl* clang_decl) -> SemIR::InstId { +// Imports a C++ function, returning a corresponding Carbon function. +// `num_params` specifies how many parameters the corresponding Carbon function +// should have, which may be fewer than the number of parameters that the C++ +// function has if default arguments are available for the trailing parameters. +static auto ImportFunctionDecl(Context& context, SemIR::LocId loc_id, + clang::FunctionDecl* clang_decl, int num_params) + -> SemIR::InstId { + auto key = SemIR::ClangDeclKey::ForFunctionDecl(clang_decl, num_params); + // Check if the declaration is already mapped. - if (SemIR::InstId existing_inst_id = - LookupClangDeclInstId(context, clang_decl); + if (SemIR::InstId existing_inst_id = LookupClangDeclInstId(context, key); existing_inst_id.has_value()) { return existing_inst_id; } if (clang_decl->isVariadic()) { context.TODO(loc_id, "Unsupported: Variadic function"); - MarkFailedDecl(context, clang_decl); + MarkFailedDecl(context, key); return SemIR::ErrorInst::InstId; } if (clang_decl->getTemplatedKind() == clang::FunctionDecl::TK_FunctionTemplate) { context.TODO(loc_id, "Unsupported: Template function"); - MarkFailedDecl(context, clang_decl); + MarkFailedDecl(context, key); return SemIR::ErrorInst::InstId; } CARBON_CHECK(clang_decl->getFunctionType()->isFunctionProtoType(), "Not Prototype function (non-C++ code)"); - auto function_id = ImportFunction(context, loc_id, clang_decl); + auto function_id = ImportFunction(context, loc_id, clang_decl, num_params); if (!function_id) { - MarkFailedDecl(context, clang_decl); + MarkFailedDecl(context, key); return SemIR::ErrorInst::InstId; } @@ -1666,8 +1690,8 @@ auto ImportCppFunctionDecl(Context& context, SemIR::LocId loc_id, clang::FunctionDecl* thunk_clang_decl = BuildCppThunk(context, function_info); if (thunk_clang_decl) { - SemIR::FunctionId thunk_function_id = - *ImportFunction(context, loc_id, thunk_clang_decl); + SemIR::FunctionId thunk_function_id = *ImportFunction( + context, loc_id, thunk_clang_decl, thunk_clang_decl->getNumParams()); SemIR::InstId thunk_function_decl_id = context.functions().Get(thunk_function_id).first_owning_decl_id; function_info.SetHasCppThunk(thunk_function_decl_id); @@ -1683,7 +1707,7 @@ namespace { // to use a `PointerIntPair`. struct ImportItem { // A declaration that we want to import. - clang::Decl* decl; + SemIR::ClangDeclKey decl_key; // Whether we have added `decl`'s dependencies to the worklist. bool added_dependencies; }; @@ -1692,10 +1716,10 @@ using ImportWorklist = llvm::SmallVector; } // namespace // Adds the given declaration to our list of declarations to import. -static auto AddDependentDecl(Context& context, clang::Decl* decl, +static auto AddDependentDecl(Context& context, SemIR::ClangDeclKey decl, ImportWorklist& worklist) -> void { if (!IsClangDeclImported(context, decl)) { - worklist.push_back({.decl = decl, .added_dependencies = false}); + worklist.push_back({.decl_key = decl, .added_dependencies = false}); } } @@ -1716,17 +1740,22 @@ static auto AddDependentUnimportedTypeDecls(Context& context, } if (const auto* tag_type = type->getAs()) { - AddDependentDecl(context, tag_type->getOriginalDecl(), worklist); + AddDependentDecl(context, SemIR::ClangDeclKey(tag_type->getOriginalDecl()), + worklist); } } // Finds all decls that need to be imported before importing the given function // and adds them to the given set. static auto AddDependentUnimportedFunctionDecls( - Context& context, const clang::FunctionDecl& clang_decl, + Context& context, const clang::FunctionDecl& clang_decl, int num_params, ImportWorklist& worklist) -> void { - for (const auto* param : clang_decl.parameters()) { - AddDependentUnimportedTypeDecls(context, param->getType(), worklist); + const auto* function_type = + clang_decl.getType()->castAs(); + for (int i : llvm::seq(clang_decl.hasCXXExplicitFunctionObjectParameter() + + num_params)) { + AddDependentUnimportedTypeDecls(context, function_type->getParamType(i), + worklist); } AddDependentUnimportedTypeDecls(context, clang_decl.getReturnType(), worklist); @@ -1735,11 +1764,12 @@ static auto AddDependentUnimportedFunctionDecls( // Finds all decls that need to be imported before importing the given // declaration and adds them to the given set. static auto AddDependentUnimportedDecls(Context& context, - clang::Decl* clang_decl, + SemIR::ClangDeclKey key, ImportWorklist& worklist) -> void { + clang::Decl* clang_decl = key.decl; if (auto* clang_function_decl = clang_decl->getAsFunction()) { AddDependentUnimportedFunctionDecls(context, *clang_function_decl, - worklist); + key.num_params, worklist); } else if (auto* type_decl = dyn_cast(clang_decl)) { if (!isa(clang_decl)) { AddDependentUnimportedTypeDecls( @@ -1747,14 +1777,18 @@ static auto AddDependentUnimportedDecls(Context& context, worklist); } } - if (!isa(clang_decl)) { - AddDependentDecl(context, GetParentDecl(clang_decl), worklist); + auto* parent = GetParentDecl(clang_decl); + if (llvm::isa_and_nonnull(parent)) { + AddDependentDecl(context, SemIR::ClangDeclKey::ForNonFunctionDecl(parent), + worklist); } } static auto ImportVarDecl(Context& context, SemIR::LocId loc_id, clang::VarDecl* var_decl) -> SemIR::InstId { - if (SemIR::InstId existing_inst_id = LookupClangDeclInstId(context, var_decl); + if (SemIR::InstId existing_inst_id = + LookupClangDeclInstId(context, SemIR::ClangDeclKey(var_decl)); existing_inst_id.has_value()) { return existing_inst_id; } @@ -1777,7 +1811,7 @@ static auto ImportVarDecl(Context& context, SemIR::LocId loc_id, AddPlaceholderInstInNoBlock(context, {loc_id, var_storage}); auto clang_decl_id = context.clang_decls().Add( - {.decl = var_decl, .inst_id = var_storage_inst_id}); + {.key = SemIR::ClangDeclKey(var_decl), .inst_id = var_storage_inst_id}); // Entity name referring to a Clang decl for mangling. SemIR::EntityNameId entity_name_id = @@ -1809,10 +1843,12 @@ static auto ImportVarDecl(Context& context, SemIR::LocId loc_id, // new Carbon declaration, which will be an ErrorInst on failure. Assumes all // dependencies have already been imported. static auto ImportDeclAfterDependencies(Context& context, SemIR::LocId loc_id, - clang::Decl* clang_decl) + SemIR::ClangDeclKey key) -> SemIR::InstId { + clang::Decl* clang_decl = key.decl; if (auto* clang_function_decl = clang_decl->getAsFunction()) { - return ImportCppFunctionDecl(context, loc_id, clang_function_decl); + return ImportFunctionDecl(context, loc_id, clang_function_decl, + key.num_params); } if (auto* clang_namespace_decl = dyn_cast(clang_decl)) { return ImportNamespaceDecl(context, clang_namespace_decl); @@ -1826,13 +1862,12 @@ static auto ImportDeclAfterDependencies(Context& context, SemIR::LocId loc_id, type.getAsString())); return SemIR::ErrorInst::InstId; } - context.clang_decls().Add({.decl = clang_decl, .inst_id = type_inst_id}); + context.clang_decls().Add({.key = key, .inst_id = type_inst_id}); return type_inst_id; } if (isa(clang_decl)) { // Usable fields get imported as a side effect of importing the class. - if (SemIR::InstId existing_inst_id = - LookupClangDeclInstId(context, clang_decl); + if (SemIR::InstId existing_inst_id = LookupClangDeclInstId(context, key); existing_inst_id.has_value()) { return existing_inst_id; } @@ -1866,7 +1901,7 @@ static auto ImportDeclSet(Context& context, SemIR::LocId loc_id, // adding the item to the worklist, but it might have been added to the // worklist twice before the first time we visited it. For example, this // happens for `fn F(a: Cpp.T, b: Cpp.T)`. - if (IsClangDeclImported(context, item.decl)) { + if (IsClangDeclImported(context, item.decl_key)) { worklist.pop_back(); continue; } @@ -1874,23 +1909,17 @@ static auto ImportDeclSet(Context& context, SemIR::LocId loc_id, // First time visiting this declaration (preorder): add its dependencies // to the work list. item.added_dependencies = true; - AddDependentUnimportedDecls(context, item.decl, worklist); + AddDependentUnimportedDecls(context, item.decl_key, worklist); } else { // Second time visiting this declaration (postorder): its dependencies are // already imported, so we can import it now. - auto* decl = worklist.pop_back_val().decl; - // Functions that are part of the overload set are imported at a later - // point, once the overload resolution has selected the suitable function - // for the call. - if (decl->getAsFunction()) { - continue; - } - auto inst_id = ImportDeclAfterDependencies(context, loc_id, decl); + auto decl_key = worklist.pop_back_val().decl_key; + auto inst_id = ImportDeclAfterDependencies(context, loc_id, decl_key); CARBON_CHECK(inst_id.has_value()); if (inst_id == SemIR::ErrorInst::InstId) { return false; } - CARBON_CHECK(IsClangDeclImported(context, decl)); + CARBON_CHECK(IsClangDeclImported(context, decl_key)); } } @@ -1901,15 +1930,15 @@ static auto ImportDeclSet(Context& context, SemIR::LocId loc_id, // instruction for the new Carbon declaration. All unimported dependencies are // imported first. static auto ImportDeclAndDependencies(Context& context, SemIR::LocId loc_id, - clang::Decl* clang_decl) + SemIR::ClangDeclKey key) -> SemIR::InstId { // Collect dependencies by walking the dependency graph in depth-first order. ImportWorklist worklist; - AddDependentDecl(context, clang_decl, worklist); + AddDependentDecl(context, key, worklist); if (!ImportDeclSet(context, loc_id, worklist)) { return SemIR::ErrorInst::InstId; } - return LookupClangDeclInstId(context, clang_decl); + return LookupClangDeclInstId(context, key); } // Imports a type from Clang to Carbon. If successful, returns the imported @@ -1926,6 +1955,14 @@ static auto ImportTypeAndDependencies(Context& context, SemIR::LocId loc_id, return MapType(context, loc_id, type); } +auto ImportCppFunctionDecl(Context& context, SemIR::LocId loc_id, + clang::FunctionDecl* clang_decl, int num_params) + -> SemIR::InstId { + return ImportDeclAndDependencies( + context, loc_id, + SemIR::ClangDeclKey::ForFunctionDecl(clang_decl, num_params)); +} + // Maps `clang::AccessSpecifier` to `SemIR::AccessKind`. static auto MapAccess(clang::AccessSpecifier access_specifier) -> SemIR::AccessKind { @@ -1940,16 +1977,15 @@ static auto MapAccess(clang::AccessSpecifier access_specifier) } } -// Imports a `clang::NamedDecl` into Carbon and adds that name into the +// Imports a Clang declaration into Carbon and adds that name into the // `NameScope`. static auto ImportNameDeclIntoScope(Context& context, SemIR::LocId loc_id, SemIR::NameScopeId scope_id, SemIR::NameId name_id, - clang::NamedDecl* clang_decl, + SemIR::ClangDeclKey key, clang::AccessSpecifier access) -> SemIR::ScopeLookupResult { - SemIR::InstId inst_id = - ImportDeclAndDependencies(context, loc_id, clang_decl); + SemIR::InstId inst_id = ImportDeclAndDependencies(context, loc_id, key); if (!inst_id.has_value()) { return SemIR::ScopeLookupResult::MakeNotFound(); } @@ -2051,22 +2087,8 @@ static auto GetOverloadSetAccess(Context& context, SemIR::LocId loc_id, return MapAccess(access); } -static auto ImportOverloadSetAndDependencies( - Context& context, SemIR::LocId loc_id, SemIR::NameScopeId scope_id, - SemIR::NameId name_id, const clang::UnresolvedSet<4>& overloaded_set) - -> SemIR::InstId { - ImportWorklist worklist; - for (clang::NamedDecl* fn_decl : overloaded_set) { - AddDependentDecl(context, fn_decl, worklist); - } - if (!ImportDeclSet(context, loc_id, worklist)) { - return SemIR::ErrorInst::InstId; - } - return ImportCppOverloadSet(context, scope_id, name_id, overloaded_set); -} - -// Imports an overloaded function set from Clang to Carbon and adds the -// name into the `NameScope`. +// Imports an overload set from Clang to Carbon and adds the name into the +// `NameScope`. static auto ImportOverloadSetIntoScope( Context& context, SemIR::LocId loc_id, SemIR::NameScopeId scope_id, SemIR::NameId name_id, const clang::UnresolvedSet<4>& overload_set) @@ -2077,8 +2099,8 @@ static auto ImportOverloadSetIntoScope( return SemIR::ScopeLookupResult::MakeError(); } - SemIR::InstId inst_id = ImportOverloadSetAndDependencies( - context, loc_id, scope_id, name_id, overload_set); + SemIR::InstId inst_id = + ImportCppOverloadSet(context, scope_id, name_id, overload_set); AddNameToScope(context, scope_id, name_id, access_kind.value(), inst_id); return SemIR::ScopeLookupResult::MakeWrappedLookupResult(inst_id, access_kind.value()); @@ -2182,8 +2204,8 @@ auto ImportNameFromCpp(Context& context, SemIR::LocId loc_id, lookup->getFoundDecl())) { return ImportConstructorsIntoScope(context, loc_id, scope_id, name_id); } - return ImportNameDeclIntoScope(context, loc_id, scope_id, name_id, - lookup->getFoundDecl(), + auto key = SemIR::ClangDeclKey::ForNonFunctionDecl(lookup->getFoundDecl()); + return ImportNameDeclIntoScope(context, loc_id, scope_id, name_id, key, lookup->begin().getAccess()); } @@ -2195,7 +2217,7 @@ auto ImportClassDefinitionForClangDecl(Context& context, SemIR::LocId loc_id, CARBON_CHECK(ast); auto* clang_decl = - cast(context.clang_decls().Get(clang_decl_id).decl); + cast(context.clang_decls().Get(clang_decl_id).key.decl); auto class_inst_id = context.types().GetAsTypeInstId( context.classes().Get(class_id).first_owning_decl_id); diff --git a/toolchain/check/cpp/import.h b/toolchain/check/cpp/import.h index eb96d82212f7..805f8b4b49ac 100644 --- a/toolchain/check/cpp/import.h +++ b/toolchain/check/cpp/import.h @@ -28,7 +28,8 @@ auto ImportCppFiles(Context& context, // the new Carbon function declaration `InstId`. If the declaration was already // imported, returns the mapped instruction. auto ImportCppFunctionDecl(Context& context, SemIR::LocId loc_id, - clang::FunctionDecl* clang_decl) -> SemIR::InstId; + clang::FunctionDecl* clang_decl, int num_params) + -> SemIR::InstId; // Imports an overloaded function set from Clang to Carbon. auto ImportCppOverloadSet(Context& context, SemIR::NameScopeId scope_id, diff --git a/toolchain/check/cpp/overload_resolution.cpp b/toolchain/check/cpp/overload_resolution.cpp index dba901bd455d..a3ebd59e8381 100644 --- a/toolchain/check/cpp/overload_resolution.cpp +++ b/toolchain/check/cpp/overload_resolution.cpp @@ -10,6 +10,7 @@ #include "toolchain/check/cpp/import.h" #include "toolchain/check/cpp/location.h" #include "toolchain/check/cpp/type_mapping.h" +#include "toolchain/diagnostics/diagnostic_emitter.h" #include "toolchain/sem_ir/ids.h" #include "toolchain/sem_ir/typed_insts.h" @@ -79,6 +80,12 @@ auto PerformCppOverloadResolution(Context& context, SemIR::LocId loc_id, SemIR::InstId self_id, llvm::ArrayRef arg_ids) -> SemIR::InstId { + // Register an annotation scope to flush any Clang diagnostics when we return. + // This is important to ensure that Clang diagnostics are properly interleaved + // with Carbon diagnostics. + Diagnostics::AnnotationScope annotate_diagnostics(&context.emitter(), + [](auto& /*builder*/) {}); + // Map Carbon call argument types to C++ types. clang::Expr* self_expr = nullptr; if (self_id.has_value()) { @@ -117,8 +124,8 @@ auto PerformCppOverloadResolution(Context& context, SemIR::LocId loc_id, // TODO: Handle the cases when Function is null. CARBON_CHECK(best_viable_fn->Function); sema.MarkFunctionReferenced(loc, best_viable_fn->Function); - SemIR::InstId result = - ImportCppFunctionDecl(context, loc_id, best_viable_fn->Function); + SemIR::InstId result = ImportCppFunctionDecl( + context, loc_id, best_viable_fn->Function, arg_exprs.size()); return result; } case clang::OverloadingResult::OR_No_Viable_Function: { diff --git a/toolchain/check/cpp/thunk.cpp b/toolchain/check/cpp/thunk.cpp index ac0b4d2f919a..d54f25b20226 100644 --- a/toolchain/check/cpp/thunk.cpp +++ b/toolchain/check/cpp/thunk.cpp @@ -35,11 +35,16 @@ static auto GetGlobalDecl(const clang::FunctionDecl* decl) // Returns the C++ thunk mangled name given the callee function. static auto GenerateThunkMangledName( clang::MangleContext& mangle_context, - const clang::FunctionDecl& callee_function_decl) -> std::string { + const clang::FunctionDecl& callee_function_decl, int num_params) + -> std::string { RawStringOstream mangled_name_stream; mangle_context.mangleName(GetGlobalDecl(&callee_function_decl), mangled_name_stream); mangled_name_stream << ".carbon_thunk"; + if (num_params != + static_cast(callee_function_decl.getNumNonObjectParams())) { + mangled_name_stream << num_params; + } return mangled_name_stream.TakeStr(); } @@ -90,14 +95,22 @@ auto IsCppThunkRequired(Context& context, const SemIR::Function& function) // we don't generate a thunk if any relevant type is erroneous. bool thunk_required = false; - // We require a thunk if any parameter is of reference type, even if the - // corresponding SemIR function has an acceptable parameter type. - // TODO: We should be able to avoid thunks for reference parameters. - const auto* decl = cast( - context.clang_decls().Get(function.clang_decl_id).decl); - for (auto* param : decl->parameters()) { - if (param->getType()->isReferenceType()) { - thunk_required = true; + const auto& decl_info = context.clang_decls().Get(function.clang_decl_id); + const auto* decl = cast(decl_info.key.decl); + if (decl_info.key.num_params != + static_cast(decl->getNumNonObjectParams())) { + // We require a thunk if the number of parameters we want isn't all of them. + // This happens if default arguments are in use, or (eventually) when + // calling a varargs function. + thunk_required = true; + } else { + // We require a thunk if any parameter is of reference type, even if the + // corresponding SemIR function has an acceptable parameter type. + // TODO: We should be able to avoid thunks for reference parameters. + for (auto* param : decl->parameters()) { + if (param->getType()->isReferenceType()) { + thunk_required = true; + } } } @@ -147,7 +160,9 @@ static auto IsSimpleAbiType(clang::ASTContext& ast_context, namespace { // Information about the callee of a thunk. struct CalleeFunctionInfo { - explicit CalleeFunctionInfo(clang::FunctionDecl* decl) : decl(decl) { + explicit CalleeFunctionInfo(clang::FunctionDecl* decl, int num_params) + : decl(decl), + num_params(num_params + decl->hasCXXExplicitFunctionObjectParameter()) { auto& ast_context = decl->getASTContext(); const auto* method_decl = dyn_cast(decl); bool is_ctor = isa(decl); @@ -174,7 +189,7 @@ struct CalleeFunctionInfo { // Returns the number of parameters the thunk should have. auto num_thunk_params() const -> unsigned { - return has_implicit_object_parameter() + decl->getNumParams() + + return has_implicit_object_parameter() + num_params + !has_simple_return_type; } @@ -188,12 +203,17 @@ struct CalleeFunctionInfo { // the address of the return value. auto GetThunkReturnParamIndex() const -> unsigned { CARBON_CHECK(!has_simple_return_type); - return has_implicit_object_parameter() + decl->getNumParams(); + return has_implicit_object_parameter() + num_params; } // The callee function. clang::FunctionDecl* decl; + // The number of explicit parameters to import. This may be less than the + // number of parameters that the function has if default arguments are being + // used. + int num_params; + // Whether the callee has an object parameter, which might be explicit or // implicit. bool has_object_parameter; @@ -244,12 +264,11 @@ static auto BuildThunkParameterTypes(clang::ASTContext& ast_context, GetNonnullType(ast_context, callee_info.implicit_this_type)); } - for (const clang::ParmVarDecl* callee_param : - callee_info.decl->parameters()) { - // TODO: We should use the type from the function signature, not the type of - // the parameter here. + const auto* function_type = + callee_info.decl->getType()->castAs(); + for (int i : llvm::seq(callee_info.num_params)) { thunk_param_types.push_back( - GetThunkParameterType(ast_context, callee_param->getType())); + GetThunkParameterType(ast_context, function_type->getParamType(i))); } if (!callee_info.has_simple_return_type) { @@ -270,7 +289,7 @@ static auto BuildThunkParameters(clang::ASTContext& ast_context, clang::SourceLocation clang_loc = callee_info.decl->getLocation(); const auto* thunk_function_proto_type = - thunk_function_decl->getFunctionType()->getAs(); + thunk_function_decl->getType()->castAs(); llvm::SmallVector thunk_params; unsigned num_thunk_params = thunk_function_decl->getNumParams(); @@ -285,7 +304,7 @@ static auto BuildThunkParameters(clang::ASTContext& ast_context, thunk_params.push_back(thunk_param); } - for (unsigned i : llvm::seq(callee_info.decl->getNumParams())) { + for (int i : llvm::seq(callee_info.num_params)) { clang::ParmVarDecl* thunk_param = clang::ParmVarDecl::Create( ast_context, thunk_function_decl, clang_loc, clang_loc, callee_info.decl->getParamDecl(i)->getIdentifier(), @@ -344,8 +363,9 @@ static auto CreateThunkFunctionDecl( // Set asm(".carbon_thunk"). thunk_function_decl->addAttr(clang::AsmLabelAttr::CreateImplicit( ast_context, - GenerateThunkMangledName(*context.sem_ir().clang_mangle_context(), - *callee_info.decl), + GenerateThunkMangledName( + *context.sem_ir().clang_mangle_context(), *callee_info.decl, + callee_info.num_params - callee_info.has_explicit_object_parameter()), clang_loc)); // Set function declaration type source info. @@ -416,10 +436,9 @@ static auto BuildCalleeArgs(clang::Sema& sema, // The object parameter is always passed as `self`, not in the callee argument // list, so the first argument corresponds to the second parameter if there is // an explicit object parameter and the first parameter otherwise. - unsigned first_param = callee_info.has_explicit_object_parameter(); - unsigned num_params = callee_info.decl->getNumParams(); - call_args.reserve(num_params - first_param); - for (unsigned callee_index : llvm::seq(first_param, num_params)) { + int first_param = callee_info.has_explicit_object_parameter(); + call_args.reserve(callee_info.num_params - first_param); + for (unsigned callee_index : llvm::seq(first_param, callee_info.num_params)) { call_args.push_back(BuildParamRefForCalleeArg(sema, thunk_function_decl, callee_info, callee_index)); } @@ -520,10 +539,12 @@ auto BuildCppThunk(Context& context, const SemIR::Function& callee_function) clang::FunctionDecl* callee_function_decl = context.clang_decls() .Get(callee_function.clang_decl_id) - .decl->getAsFunction(); + .key.decl->getAsFunction(); CARBON_CHECK(callee_function_decl); - CalleeFunctionInfo callee_info(callee_function_decl); + CalleeFunctionInfo callee_info( + callee_function_decl, + context.inst_blocks().Get(callee_function.param_patterns_id).size()); // Build the thunk function declaration. auto thunk_param_types = @@ -591,7 +612,8 @@ auto PerformCppThunkCall(Context& context, SemIR::LocId loc_id, // We assume that the call parameters exactly match the parameter patterns for // both the thunk and the callee. This is currently guaranteed because we only // create trivial *ParamPatterns when importing a C++ function. - CARBON_CHECK(num_callee_args == callee_function_params.size()); + CARBON_CHECK(num_callee_args == callee_function_params.size(), "{0} != {1}", + num_callee_args, callee_function_params.size()); CARBON_CHECK(num_callee_args == callee_arg_ids.size()); CARBON_CHECK(num_thunk_args == thunk_function_params.size()); diff --git a/toolchain/check/cpp/type_mapping.cpp b/toolchain/check/cpp/type_mapping.cpp index dd0840ca89f4..71235f5aaf67 100644 --- a/toolchain/check/cpp/type_mapping.cpp +++ b/toolchain/check/cpp/type_mapping.cpp @@ -95,7 +95,7 @@ static auto TryMapClassType(Context& context, SemIR::ClassType class_type) .Get(context.classes().Get(class_type.class_id).scope_id) .clang_decl_context_id(); if (clang_decl_id.has_value()) { - clang::Decl* clang_decl = context.clang_decls().Get(clang_decl_id).decl; + clang::Decl* clang_decl = context.clang_decls().Get(clang_decl_id).key.decl; auto* tag_type_decl = clang::cast(clang_decl); return context.ast_context().getCanonicalTagType(tag_type_decl); } @@ -230,9 +230,6 @@ static auto MapToCppType(Context& context, SemIR::InstId inst_id) auto InventClangArg(Context& context, SemIR::InstId arg_id) -> clang::Expr* { clang::ExprValueKind value_kind; switch (SemIR::GetExprCategory(context.sem_ir(), arg_id)) { - case SemIR::ExprCategory::NotExpr: - CARBON_FATAL("Should not see these here"); - case SemIR::ExprCategory::Error: return nullptr; @@ -244,6 +241,13 @@ auto InventClangArg(Context& context, SemIR::InstId arg_id) -> clang::Expr* { value_kind = clang::ExprValueKind::VK_XValue; break; + case SemIR::ExprCategory::NotExpr: + // A call using this expression as an argument won't be valid, but we + // don't diagnose that until we convert the expression to the parameter + // type. + value_kind = clang::ExprValueKind::VK_PRValue; + break; + case SemIR::ExprCategory::Value: case SemIR::ExprCategory::Initializing: value_kind = clang::ExprValueKind::VK_PRValue; diff --git a/toolchain/check/testdata/basics/raw_sem_ir/builtins.carbon b/toolchain/check/testdata/basics/raw_sem_ir/builtins.carbon index cef8cd71d297..83404615e486 100644 --- a/toolchain/check/testdata/basics/raw_sem_ir/builtins.carbon +++ b/toolchain/check/testdata/basics/raw_sem_ir/builtins.carbon @@ -18,6 +18,7 @@ // CHECK:STDOUT: ir0: {decl_id: inst, is_export: false} // CHECK:STDOUT: ir1: {decl_id: inst, is_export: false} // CHECK:STDOUT: import_ir_insts: {} +// CHECK:STDOUT: clang_decls: {} // CHECK:STDOUT: name_scopes: // CHECK:STDOUT: name_scope0: {inst: inst14, parent_scope: name_scope, has_error: false, extended_scopes: [], names: {}} // CHECK:STDOUT: entity_names: {} diff --git a/toolchain/check/testdata/basics/raw_sem_ir/cpp_interop.carbon b/toolchain/check/testdata/basics/raw_sem_ir/cpp_interop.carbon new file mode 100644 index 000000000000..960e74eadc84 --- /dev/null +++ b/toolchain/check/testdata/basics/raw_sem_ir/cpp_interop.carbon @@ -0,0 +1,302 @@ +// 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-FILE: toolchain/testing/testdata/min_prelude/none.carbon +// EXTRA-ARGS: --dump-raw-sem-ir --builtin-sem-ir +// +// AUTOUPDATE +// TIP: To test this file alone, run: +// TIP: bazel test //toolchain/testing:file_test --test_arg=--file_tests=toolchain/check/testdata/basics/raw_sem_ir/cpp_interop.carbon +// TIP: To dump output, run: +// TIP: bazel run //toolchain/testing:file_test -- --dump_output --file_tests=toolchain/check/testdata/basics/raw_sem_ir/cpp_interop.carbon + +// --- header.h + +struct X { + X *p; +}; + +void f(X x = {}) { +} + +// --- import.carbon + +import Cpp library "header.h"; + +fn G(x: Cpp.X) { + Cpp.f(); + Cpp.f(x); +} + +// CHECK:STDOUT: --- +// CHECK:STDOUT: filename: import.carbon +// CHECK:STDOUT: sem_ir: +// CHECK:STDOUT: import_irs: +// CHECK:STDOUT: ir0: {decl_id: inst, is_export: false} +// CHECK:STDOUT: ir1: {decl_id: inst, is_export: false} +// CHECK:STDOUT: import_ir_insts: +// CHECK:STDOUT: import_ir_inst0: {ir_id: ir1, clang_source_loc_id: clang_source_loc0} +// CHECK:STDOUT: clang_decls: +// CHECK:STDOUT: clang_decl_id0: {key: "", inst_id: inst16} +// CHECK:STDOUT: clang_decl_id1: {key: "struct X {}", inst_id: inst18} +// CHECK:STDOUT: clang_decl_id2: {key: {decl: "void f(X x = {})", num_params: 0}, inst_id: inst41} +// CHECK:STDOUT: clang_decl_id3: {key: {decl: "extern void f__carbon_thunk()", num_params: 0}, inst_id: inst44} +// CHECK:STDOUT: clang_decl_id4: {key: {decl: "void f(X x = {})", num_params: 1}, inst_id: inst55} +// CHECK:STDOUT: clang_decl_id5: {key: {decl: "extern void f__carbon_thunk(X * _Nonnull x)", num_params: 1}, inst_id: inst64} +// CHECK:STDOUT: name_scopes: +// CHECK:STDOUT: name_scope0: {inst: inst14, parent_scope: name_scope, has_error: false, extended_scopes: [], names: {name0: inst16, name1: inst27}} +// CHECK:STDOUT: name_scope1: {inst: inst16, parent_scope: name_scope0, has_error: false, extended_scopes: [], names: {name3: inst18, name4: inst38}} +// CHECK:STDOUT: name_scope2: {inst: inst18, parent_scope: name_scope1, has_error: false, extended_scopes: [], names: {}} +// CHECK:STDOUT: entity_names: +// CHECK:STDOUT: entity_name0: {name: name2, parent_scope: name_scope, index: -1, is_template: 0, clang_decl_id: clang_decl_id} +// CHECK:STDOUT: entity_name1: {name: name2, parent_scope: name_scope, index: -1, is_template: 0, clang_decl_id: clang_decl_id} +// CHECK:STDOUT: entity_name2: {name: name2, parent_scope: name_scope, index: -1, is_template: 0, clang_decl_id: clang_decl_id} +// CHECK:STDOUT: functions: +// CHECK:STDOUT: function0: {name: name1, parent_scope: name_scope0, call_params_id: inst_block6, body: [inst_block9]} +// CHECK:STDOUT: function1: {name: name4, parent_scope: name_scope1, call_params_id: inst_block_empty} +// CHECK:STDOUT: function2: {name: name6, parent_scope: name_scope1, call_params_id: inst_block_empty} +// CHECK:STDOUT: function3: {name: name4, parent_scope: name_scope1, call_params_id: inst_block13} +// CHECK:STDOUT: function4: {name: name6, parent_scope: name_scope1, call_params_id: inst_block18} +// CHECK:STDOUT: classes: +// CHECK:STDOUT: class0: {name: name3, parent_scope: name_scope1, self_type_id: type(inst19), inheritance_kind: Base, is_dynamic: 0, scope_id: name_scope2, body_block_id: inst_block10, adapt_id: inst, base_id: inst, complete_type_witness_id: inst33, vtable_decl_id: inst}} +// CHECK:STDOUT: generics: {} +// CHECK:STDOUT: specifics: {} +// CHECK:STDOUT: struct_type_fields: +// CHECK:STDOUT: struct_type_fields0: {} +// CHECK:STDOUT: types: +// CHECK:STDOUT: 'type(TypeType)': +// CHECK:STDOUT: value_repr: {kind: copy, type: type(TypeType)} +// CHECK:STDOUT: 'type(Error)': +// CHECK:STDOUT: value_repr: {kind: copy, type: type(Error)} +// CHECK:STDOUT: 'type(inst(NamespaceType))': +// CHECK:STDOUT: value_repr: {kind: copy, type: type(inst(NamespaceType))} +// CHECK:STDOUT: 'type(inst28)': +// CHECK:STDOUT: value_repr: {kind: none, type: type(inst29)} +// CHECK:STDOUT: 'type(inst29)': +// CHECK:STDOUT: value_repr: {kind: none, type: type(inst29)} +// CHECK:STDOUT: 'type(inst(WitnessType))': +// CHECK:STDOUT: value_repr: {kind: copy, type: type(inst(WitnessType))} +// CHECK:STDOUT: 'type(inst32)': +// CHECK:STDOUT: value_repr: {kind: pointer, type: type(inst35)} +// CHECK:STDOUT: 'type(inst35)': +// CHECK:STDOUT: value_repr: {kind: copy, type: type(inst35)} +// CHECK:STDOUT: 'type(inst19)': +// CHECK:STDOUT: value_repr: {kind: pointer, type: type(inst35)} +// CHECK:STDOUT: 'type(inst37)': +// CHECK:STDOUT: value_repr: {kind: none, type: type(inst29)} +// CHECK:STDOUT: 'type(inst42)': +// CHECK:STDOUT: value_repr: {kind: none, type: type(inst29)} +// CHECK:STDOUT: 'type(inst45)': +// CHECK:STDOUT: value_repr: {kind: none, type: type(inst29)} +// CHECK:STDOUT: 'type(inst56)': +// CHECK:STDOUT: value_repr: {kind: none, type: type(inst29)} +// CHECK:STDOUT: 'type(inst65)': +// CHECK:STDOUT: value_repr: {kind: none, type: type(inst29)} +// CHECK:STDOUT: 'type(inst58)': +// CHECK:STDOUT: value_repr: {kind: copy, type: type(inst58)} +// CHECK:STDOUT: insts: +// CHECK:STDOUT: 'inst(TypeType)': {kind: TypeType, type: type(TypeType)} +// CHECK:STDOUT: 'inst(AutoType)': {kind: AutoType, type: type(TypeType)} +// CHECK:STDOUT: 'inst(BoolType)': {kind: BoolType, type: type(TypeType)} +// CHECK:STDOUT: 'inst(BoundMethodType)': {kind: BoundMethodType, type: type(TypeType)} +// CHECK:STDOUT: 'inst(CharLiteralType)': {kind: CharLiteralType, type: type(TypeType)} +// CHECK:STDOUT: 'inst(ErrorInst)': {kind: ErrorInst, type: type(Error)} +// CHECK:STDOUT: 'inst(FloatLiteralType)': {kind: FloatLiteralType, type: type(TypeType)} +// CHECK:STDOUT: 'inst(ImplWitnessTablePlaceholder)': {kind: ImplWitnessTablePlaceholder, type: type(TypeType)} +// CHECK:STDOUT: 'inst(InstType)': {kind: InstType, type: type(TypeType)} +// CHECK:STDOUT: 'inst(IntLiteralType)': {kind: IntLiteralType, type: type(TypeType)} +// CHECK:STDOUT: 'inst(NamespaceType)': {kind: NamespaceType, type: type(TypeType)} +// CHECK:STDOUT: 'inst(SpecificFunctionType)': {kind: SpecificFunctionType, type: type(TypeType)} +// CHECK:STDOUT: 'inst(VtableType)': {kind: VtableType, type: type(TypeType)} +// CHECK:STDOUT: 'inst(WitnessType)': {kind: WitnessType, type: type(TypeType)} +// CHECK:STDOUT: inst14: {kind: Namespace, arg0: name_scope0, arg1: inst, type: type(inst(NamespaceType))} +// CHECK:STDOUT: inst15: {kind: ImportCppDecl} +// CHECK:STDOUT: inst16: {kind: Namespace, arg0: name_scope1, arg1: inst15, type: type(inst(NamespaceType))} +// CHECK:STDOUT: inst17: {kind: NameRef, arg0: name0, arg1: inst16, type: type(inst(NamespaceType))} +// CHECK:STDOUT: inst18: {kind: ClassDecl, arg0: class0, arg1: inst_block, type: type(TypeType)} +// CHECK:STDOUT: inst19: {kind: ClassType, arg0: class0, arg1: specific, type: type(TypeType)} +// CHECK:STDOUT: inst20: {kind: NameRef, arg0: name3, arg1: inst18, type: type(TypeType)} +// CHECK:STDOUT: inst21: {kind: BindName, arg0: entity_name0, arg1: inst25, type: type(inst19)} +// CHECK:STDOUT: inst22: {kind: PatternType, arg0: inst19, type: type(TypeType)} +// CHECK:STDOUT: inst23: {kind: BindingPattern, arg0: entity_name0, type: type(inst22)} +// CHECK:STDOUT: inst24: {kind: ValueParamPattern, arg0: inst23, arg1: call_param0, type: type(inst22)} +// CHECK:STDOUT: inst25: {kind: ValueParam, arg0: call_param0, arg1: name2, type: type(inst19)} +// CHECK:STDOUT: inst26: {kind: SpliceBlock, arg0: inst_block4, arg1: inst20, type: type(TypeType)} +// CHECK:STDOUT: inst27: {kind: FunctionDecl, arg0: function0, arg1: inst_block8, type: type(inst28)} +// CHECK:STDOUT: inst28: {kind: FunctionType, arg0: function0, arg1: specific, type: type(TypeType)} +// CHECK:STDOUT: inst29: {kind: TupleType, arg0: inst_block_empty, type: type(TypeType)} +// CHECK:STDOUT: inst30: {kind: StructValue, arg0: inst_block_empty, type: type(inst28)} +// CHECK:STDOUT: inst31: {kind: CustomLayoutType, arg0: struct_type_fields0, arg1: custom_layout1, type: type(TypeType)} +// CHECK:STDOUT: inst32: {kind: CustomLayoutType, arg0: struct_type_fields0, arg1: custom_layout1, type: type(TypeType)} +// CHECK:STDOUT: inst33: {kind: CompleteTypeWitness, arg0: inst31, type: type(inst(WitnessType))} +// CHECK:STDOUT: inst34: {kind: CompleteTypeWitness, arg0: inst32, type: type(inst(WitnessType))} +// CHECK:STDOUT: inst35: {kind: PointerType, arg0: inst32, type: type(TypeType)} +// CHECK:STDOUT: inst36: {kind: NameRef, arg0: name0, arg1: inst16, type: type(inst(NamespaceType))} +// CHECK:STDOUT: inst37: {kind: CppOverloadSetType, arg0: cpp_overload_set0, arg1: specific, type: type(TypeType)} +// CHECK:STDOUT: inst38: {kind: CppOverloadSetValue, arg0: cpp_overload_set0, type: type(inst37)} +// CHECK:STDOUT: inst39: {kind: StructValue, arg0: inst_block_empty, type: type(inst37)} +// CHECK:STDOUT: inst40: {kind: NameRef, arg0: name4, arg1: inst38, type: type(inst37)} +// CHECK:STDOUT: inst41: {kind: FunctionDecl, arg0: function1, arg1: inst_block_empty, type: type(inst42)} +// CHECK:STDOUT: inst42: {kind: FunctionType, arg0: function1, arg1: specific, type: type(TypeType)} +// CHECK:STDOUT: inst43: {kind: StructValue, arg0: inst_block_empty, type: type(inst42)} +// CHECK:STDOUT: inst44: {kind: FunctionDecl, arg0: function2, arg1: inst_block_empty, type: type(inst45)} +// CHECK:STDOUT: inst45: {kind: FunctionType, arg0: function2, arg1: specific, type: type(TypeType)} +// CHECK:STDOUT: inst46: {kind: StructValue, arg0: inst_block_empty, type: type(inst45)} +// CHECK:STDOUT: inst47: {kind: Call, arg0: inst44, arg1: inst_block_empty, type: type(inst29)} +// CHECK:STDOUT: inst48: {kind: NameRef, arg0: name0, arg1: inst16, type: type(inst(NamespaceType))} +// CHECK:STDOUT: inst49: {kind: NameRef, arg0: name4, arg1: inst38, type: type(inst37)} +// CHECK:STDOUT: inst50: {kind: NameRef, arg0: name2, arg1: inst21, type: type(inst19)} +// CHECK:STDOUT: inst51: {kind: BindName, arg0: entity_name1, arg1: inst54, type: type(inst19)} +// CHECK:STDOUT: inst52: {kind: BindingPattern, arg0: entity_name1, type: type(inst22)} +// CHECK:STDOUT: inst53: {kind: ValueParamPattern, arg0: inst52, arg1: call_param0, type: type(inst22)} +// CHECK:STDOUT: inst54: {kind: ValueParam, arg0: call_param0, arg1: name2, type: type(inst19)} +// CHECK:STDOUT: inst55: {kind: FunctionDecl, arg0: function3, arg1: inst_block15, type: type(inst56)} +// CHECK:STDOUT: inst56: {kind: FunctionType, arg0: function3, arg1: specific, type: type(TypeType)} +// CHECK:STDOUT: inst57: {kind: StructValue, arg0: inst_block_empty, type: type(inst56)} +// CHECK:STDOUT: inst58: {kind: PointerType, arg0: inst19, type: type(TypeType)} +// CHECK:STDOUT: inst59: {kind: BindName, arg0: entity_name2, arg1: inst63, type: type(inst58)} +// CHECK:STDOUT: inst60: {kind: PatternType, arg0: inst58, type: type(TypeType)} +// CHECK:STDOUT: inst61: {kind: BindingPattern, arg0: entity_name2, type: type(inst60)} +// CHECK:STDOUT: inst62: {kind: ValueParamPattern, arg0: inst61, arg1: call_param0, type: type(inst60)} +// CHECK:STDOUT: inst63: {kind: ValueParam, arg0: call_param0, arg1: name2, type: type(inst58)} +// CHECK:STDOUT: inst64: {kind: FunctionDecl, arg0: function4, arg1: inst_block20, type: type(inst65)} +// CHECK:STDOUT: inst65: {kind: FunctionType, arg0: function4, arg1: specific, type: type(TypeType)} +// CHECK:STDOUT: inst66: {kind: StructValue, arg0: inst_block_empty, type: type(inst65)} +// CHECK:STDOUT: inst67: {kind: ValueAsRef, arg0: inst50, type: type(inst19)} +// CHECK:STDOUT: inst68: {kind: AddrOf, arg0: inst67, type: type(inst58)} +// CHECK:STDOUT: inst69: {kind: Call, arg0: inst64, arg1: inst_block22, type: type(inst29)} +// CHECK:STDOUT: inst70: {kind: Return} +// CHECK:STDOUT: constant_values: +// CHECK:STDOUT: values: +// CHECK:STDOUT: 'inst(TypeType)': concrete_constant(inst(TypeType)) +// CHECK:STDOUT: 'inst(AutoType)': concrete_constant(inst(AutoType)) +// CHECK:STDOUT: 'inst(BoolType)': concrete_constant(inst(BoolType)) +// CHECK:STDOUT: 'inst(BoundMethodType)': concrete_constant(inst(BoundMethodType)) +// CHECK:STDOUT: 'inst(CharLiteralType)': concrete_constant(inst(CharLiteralType)) +// CHECK:STDOUT: 'inst(ErrorInst)': concrete_constant(inst(ErrorInst)) +// CHECK:STDOUT: 'inst(FloatLiteralType)': concrete_constant(inst(FloatLiteralType)) +// CHECK:STDOUT: 'inst(ImplWitnessTablePlaceholder)': concrete_constant(inst(ImplWitnessTablePlaceholder)) +// CHECK:STDOUT: 'inst(InstType)': concrete_constant(inst(InstType)) +// CHECK:STDOUT: 'inst(IntLiteralType)': concrete_constant(inst(IntLiteralType)) +// CHECK:STDOUT: 'inst(NamespaceType)': concrete_constant(inst(NamespaceType)) +// CHECK:STDOUT: 'inst(SpecificFunctionType)': concrete_constant(inst(SpecificFunctionType)) +// CHECK:STDOUT: 'inst(VtableType)': concrete_constant(inst(VtableType)) +// CHECK:STDOUT: 'inst(WitnessType)': concrete_constant(inst(WitnessType)) +// CHECK:STDOUT: inst14: concrete_constant(inst14) +// CHECK:STDOUT: inst16: concrete_constant(inst16) +// CHECK:STDOUT: inst17: concrete_constant(inst16) +// CHECK:STDOUT: inst18: concrete_constant(inst19) +// CHECK:STDOUT: inst19: concrete_constant(inst19) +// CHECK:STDOUT: inst20: concrete_constant(inst19) +// CHECK:STDOUT: inst22: concrete_constant(inst22) +// CHECK:STDOUT: inst23: concrete_constant(inst23) +// CHECK:STDOUT: inst24: concrete_constant(inst24) +// CHECK:STDOUT: inst26: concrete_constant(inst19) +// CHECK:STDOUT: inst27: concrete_constant(inst30) +// CHECK:STDOUT: inst28: concrete_constant(inst28) +// CHECK:STDOUT: inst29: concrete_constant(inst29) +// CHECK:STDOUT: inst30: concrete_constant(inst30) +// CHECK:STDOUT: inst31: concrete_constant(inst32) +// CHECK:STDOUT: inst32: concrete_constant(inst32) +// CHECK:STDOUT: inst33: concrete_constant(inst34) +// CHECK:STDOUT: inst34: concrete_constant(inst34) +// CHECK:STDOUT: inst35: concrete_constant(inst35) +// CHECK:STDOUT: inst36: concrete_constant(inst16) +// CHECK:STDOUT: inst37: concrete_constant(inst37) +// CHECK:STDOUT: inst38: concrete_constant(inst39) +// CHECK:STDOUT: inst39: concrete_constant(inst39) +// CHECK:STDOUT: inst40: concrete_constant(inst39) +// CHECK:STDOUT: inst41: concrete_constant(inst43) +// CHECK:STDOUT: inst42: concrete_constant(inst42) +// CHECK:STDOUT: inst43: concrete_constant(inst43) +// CHECK:STDOUT: inst44: concrete_constant(inst46) +// CHECK:STDOUT: inst45: concrete_constant(inst45) +// CHECK:STDOUT: inst46: concrete_constant(inst46) +// CHECK:STDOUT: inst48: concrete_constant(inst16) +// CHECK:STDOUT: inst49: concrete_constant(inst39) +// CHECK:STDOUT: inst52: concrete_constant(inst52) +// CHECK:STDOUT: inst53: concrete_constant(inst53) +// CHECK:STDOUT: inst55: concrete_constant(inst57) +// CHECK:STDOUT: inst56: concrete_constant(inst56) +// CHECK:STDOUT: inst57: concrete_constant(inst57) +// CHECK:STDOUT: inst58: concrete_constant(inst58) +// CHECK:STDOUT: inst60: concrete_constant(inst60) +// CHECK:STDOUT: inst61: concrete_constant(inst61) +// CHECK:STDOUT: inst62: concrete_constant(inst62) +// CHECK:STDOUT: inst64: concrete_constant(inst66) +// CHECK:STDOUT: inst65: concrete_constant(inst65) +// CHECK:STDOUT: inst66: concrete_constant(inst66) +// CHECK:STDOUT: symbolic_constants: {} +// CHECK:STDOUT: inst_blocks: +// CHECK:STDOUT: inst_block_empty: {} +// CHECK:STDOUT: exports: +// CHECK:STDOUT: 0: inst27 +// CHECK:STDOUT: imports: +// CHECK:STDOUT: 0: inst16 +// CHECK:STDOUT: 1: inst18 +// CHECK:STDOUT: 2: inst38 +// CHECK:STDOUT: 3: inst41 +// CHECK:STDOUT: 4: inst44 +// CHECK:STDOUT: 5: inst55 +// CHECK:STDOUT: 6: inst64 +// CHECK:STDOUT: global_init: {} +// CHECK:STDOUT: inst_block4: +// CHECK:STDOUT: 0: inst17 +// CHECK:STDOUT: 1: inst20 +// CHECK:STDOUT: inst_block5: +// CHECK:STDOUT: 0: inst24 +// CHECK:STDOUT: inst_block6: +// CHECK:STDOUT: 0: inst25 +// CHECK:STDOUT: inst_block7: +// CHECK:STDOUT: 0: inst23 +// CHECK:STDOUT: 1: inst24 +// CHECK:STDOUT: inst_block8: +// CHECK:STDOUT: 0: inst25 +// CHECK:STDOUT: 1: inst26 +// CHECK:STDOUT: 2: inst21 +// CHECK:STDOUT: inst_block9: +// CHECK:STDOUT: 0: inst36 +// CHECK:STDOUT: 1: inst40 +// CHECK:STDOUT: 2: inst47 +// CHECK:STDOUT: 3: inst48 +// CHECK:STDOUT: 4: inst49 +// CHECK:STDOUT: 5: inst50 +// CHECK:STDOUT: 6: inst67 +// CHECK:STDOUT: 7: inst68 +// CHECK:STDOUT: 8: inst69 +// CHECK:STDOUT: 9: inst70 +// CHECK:STDOUT: inst_block10: +// CHECK:STDOUT: 0: inst31 +// CHECK:STDOUT: 1: inst33 +// CHECK:STDOUT: inst_block11: {} +// CHECK:STDOUT: inst_block12: +// CHECK:STDOUT: 0: inst53 +// CHECK:STDOUT: inst_block13: +// CHECK:STDOUT: 0: inst54 +// CHECK:STDOUT: inst_block14: +// CHECK:STDOUT: 0: inst52 +// CHECK:STDOUT: 1: inst53 +// CHECK:STDOUT: inst_block15: +// CHECK:STDOUT: 0: inst54 +// CHECK:STDOUT: 1: inst51 +// CHECK:STDOUT: inst_block16: {} +// CHECK:STDOUT: inst_block17: +// CHECK:STDOUT: 0: inst62 +// CHECK:STDOUT: inst_block18: +// CHECK:STDOUT: 0: inst63 +// CHECK:STDOUT: inst_block19: +// CHECK:STDOUT: 0: inst61 +// CHECK:STDOUT: 1: inst62 +// CHECK:STDOUT: inst_block20: +// CHECK:STDOUT: 0: inst63 +// CHECK:STDOUT: 1: inst59 +// CHECK:STDOUT: inst_block21: +// CHECK:STDOUT: 0: inst50 +// CHECK:STDOUT: inst_block22: +// CHECK:STDOUT: 0: inst68 +// CHECK:STDOUT: inst_block23: +// CHECK:STDOUT: 0: inst14 +// CHECK:STDOUT: 1: inst15 +// CHECK:STDOUT: 2: inst27 +// CHECK:STDOUT: ... diff --git a/toolchain/check/testdata/basics/raw_sem_ir/multifile.carbon b/toolchain/check/testdata/basics/raw_sem_ir/multifile.carbon index 45c1bfe036dd..9dc8ed41c66d 100644 --- a/toolchain/check/testdata/basics/raw_sem_ir/multifile.carbon +++ b/toolchain/check/testdata/basics/raw_sem_ir/multifile.carbon @@ -34,6 +34,7 @@ fn B() { // CHECK:STDOUT: ir0: {decl_id: inst, is_export: false} // CHECK:STDOUT: ir1: {decl_id: inst, is_export: false} // CHECK:STDOUT: import_ir_insts: {} +// CHECK:STDOUT: clang_decls: {} // CHECK:STDOUT: name_scopes: // CHECK:STDOUT: name_scope0: {inst: inst14, parent_scope: name_scope, has_error: false, extended_scopes: [], names: {name0: inst15}} // CHECK:STDOUT: entity_names: {} @@ -93,6 +94,7 @@ fn B() { // CHECK:STDOUT: import_ir_insts: // CHECK:STDOUT: import_ir_inst0: {ir_id: ir2, inst_id: inst15} // CHECK:STDOUT: import_ir_inst1: {ir_id: ir2, inst_id: inst15} +// CHECK:STDOUT: clang_decls: {} // CHECK:STDOUT: name_scopes: // CHECK:STDOUT: name_scope0: {inst: inst14, parent_scope: name_scope, has_error: false, extended_scopes: [], names: {name1: inst16, name0: inst17}} // CHECK:STDOUT: name_scope1: {inst: inst16, parent_scope: name_scope0, has_error: false, extended_scopes: [], names: {name1: inst22}} diff --git a/toolchain/check/testdata/basics/raw_sem_ir/multifile_with_textual_ir.carbon b/toolchain/check/testdata/basics/raw_sem_ir/multifile_with_textual_ir.carbon index 1994b772b72e..68d7d05d64cb 100644 --- a/toolchain/check/testdata/basics/raw_sem_ir/multifile_with_textual_ir.carbon +++ b/toolchain/check/testdata/basics/raw_sem_ir/multifile_with_textual_ir.carbon @@ -34,6 +34,7 @@ fn B() { // CHECK:STDOUT: ir0: {decl_id: inst, is_export: false} // CHECK:STDOUT: ir1: {decl_id: inst, is_export: false} // CHECK:STDOUT: import_ir_insts: {} +// CHECK:STDOUT: clang_decls: {} // CHECK:STDOUT: name_scopes: // CHECK:STDOUT: name_scope0: {inst: inst14, parent_scope: name_scope, has_error: false, extended_scopes: [], names: {name0: inst15}} // CHECK:STDOUT: entity_names: {} @@ -112,6 +113,7 @@ fn B() { // CHECK:STDOUT: import_ir_insts: // CHECK:STDOUT: import_ir_inst0: {ir_id: ir2, inst_id: inst15} // CHECK:STDOUT: import_ir_inst1: {ir_id: ir2, inst_id: inst15} +// CHECK:STDOUT: clang_decls: {} // CHECK:STDOUT: name_scopes: // CHECK:STDOUT: name_scope0: {inst: inst14, parent_scope: name_scope, has_error: false, extended_scopes: [], names: {name1: inst16, name0: inst17}} // CHECK:STDOUT: name_scope1: {inst: inst16, parent_scope: name_scope0, has_error: false, extended_scopes: [], names: {name1: inst22}} diff --git a/toolchain/check/testdata/basics/raw_sem_ir/one_file.carbon b/toolchain/check/testdata/basics/raw_sem_ir/one_file.carbon index 82e0a1fdaf36..ed92b329037e 100644 --- a/toolchain/check/testdata/basics/raw_sem_ir/one_file.carbon +++ b/toolchain/check/testdata/basics/raw_sem_ir/one_file.carbon @@ -216,6 +216,7 @@ fn Foo[T:! type](p: T*) -> (T*, ()) { // CHECK:STDOUT: import_ir_inst185: {ir_id: ir4, inst_id: inst605} // CHECK:STDOUT: import_ir_inst186: {ir_id: ir4, inst_id: inst606} // CHECK:STDOUT: import_ir_inst187: {ir_id: ir4, inst_id: inst611} +// CHECK:STDOUT: clang_decls: {} // CHECK:STDOUT: name_scopes: // CHECK:STDOUT: name_scope0: {inst: inst14, parent_scope: name_scope, has_error: false, extended_scopes: [], names: {name(Core): inst16, name0: inst53}} // CHECK:STDOUT: name_scope1: {inst: inst16, parent_scope: name_scope0, has_error: false, extended_scopes: [], names: {name3: inst69}} diff --git a/toolchain/check/testdata/basics/raw_sem_ir/one_file_with_textual_ir.carbon b/toolchain/check/testdata/basics/raw_sem_ir/one_file_with_textual_ir.carbon index c07a30318bf0..7bcdfb3655fe 100644 --- a/toolchain/check/testdata/basics/raw_sem_ir/one_file_with_textual_ir.carbon +++ b/toolchain/check/testdata/basics/raw_sem_ir/one_file_with_textual_ir.carbon @@ -24,6 +24,7 @@ fn Foo(n: ()) -> ((), ()) { // CHECK:STDOUT: ir0: {decl_id: inst, is_export: false} // CHECK:STDOUT: ir1: {decl_id: inst, is_export: false} // CHECK:STDOUT: import_ir_insts: {} +// CHECK:STDOUT: clang_decls: {} // CHECK:STDOUT: name_scopes: // CHECK:STDOUT: name_scope0: {inst: inst14, parent_scope: name_scope, has_error: false, extended_scopes: [], names: {name0: inst37}} // CHECK:STDOUT: entity_names: diff --git a/toolchain/check/testdata/interop/cpp/class/constructor.carbon b/toolchain/check/testdata/interop/cpp/class/constructor.carbon index b6052acd495e..6a14e24933b7 100644 --- a/toolchain/check/testdata/interop/cpp/class/constructor.carbon +++ b/toolchain/check/testdata/interop/cpp/class/constructor.carbon @@ -82,30 +82,25 @@ fn F() { } // ============================================================================ -// Constructor with default values +// Constructor with default arguments // ============================================================================ -// --- default_values.h +// --- default_arguments.h class C { public: C(int x, int y = 8); }; -// --- fail_todo_import_default_values.carbon +// --- import_default_arguments.carbon library "[[@TEST_NAME]]"; -import Cpp library "default_values.h"; +import Cpp library "default_arguments.h"; fn F() { //@dump-sem-ir-begin let c1: Cpp.C = Cpp.C.C(8, 9); - // CHECK:STDERR: fail_todo_import_default_values.carbon:[[@LINE+5]]:19: error: 1 argument passed to function expecting 2 arguments [CallArgCountMismatch] - // CHECK:STDERR: let c2: Cpp.C = Cpp.C.C(8); - // CHECK:STDERR: ^~~~~~~~~~ - // CHECK:STDERR: fail_todo_import_default_values.carbon: note: calling function declared here [InCallToEntity] - // CHECK:STDERR: let c2: Cpp.C = Cpp.C.C(8); //@dump-sem-ir-end } @@ -186,11 +181,6 @@ import Cpp library "implicit_multi_arguments.h"; fn F() { //@dump-sem-ir-begin let c1: Cpp.C = Cpp.C.C(8, 9); - // CHECK:STDERR: fail_todo_import_implicit_multi_arguments.carbon:[[@LINE+5]]:19: error: 1 argument passed to function expecting 2 arguments [CallArgCountMismatch] - // CHECK:STDERR: let c2: Cpp.C = Cpp.C.C(8); - // CHECK:STDERR: ^~~~~~~~~~ - // CHECK:STDERR: fail_todo_import_implicit_multi_arguments.carbon: note: calling function declared here [InCallToEntity] - // CHECK:STDERR: let c2: Cpp.C = Cpp.C.C(8); // CHECK:STDERR: fail_todo_import_implicit_multi_arguments.carbon:[[@LINE+7]]:19: error: cannot implicitly convert expression of type `i32` to `Cpp.C` [ConversionFailure] // CHECK:STDERR: let c3: Cpp.C = 8 as i32; @@ -518,21 +508,21 @@ fn F() { // CHECK:STDOUT: // CHECK:STDOUT: } // CHECK:STDOUT: -// CHECK:STDOUT: --- fail_todo_import_default_values.carbon +// CHECK:STDOUT: --- import_default_arguments.carbon // CHECK:STDOUT: // CHECK:STDOUT: constants { // CHECK:STDOUT: %empty_tuple.type: type = tuple_type () [concrete] // CHECK:STDOUT: %C: type = class_type @C [concrete] // CHECK:STDOUT: %pattern_type.217: type = pattern_type %C [concrete] -// CHECK:STDOUT: %.d40: type = cpp_overload_set_type @C.C [concrete] +// CHECK:STDOUT: %.d40: type = cpp_overload_set_type @C.C.1 [concrete] // CHECK:STDOUT: %empty_struct: %.d40 = struct_value () [concrete] // CHECK:STDOUT: %int_8.b85: Core.IntLiteral = int_value 8 [concrete] // CHECK:STDOUT: %int_9.988: Core.IntLiteral = int_value 9 [concrete] // CHECK:STDOUT: %int_32: Core.IntLiteral = int_value 32 [concrete] // CHECK:STDOUT: %i32: type = class_type @Int, @Int(%int_32) [concrete] // CHECK:STDOUT: %ptr.d9e: type = ptr_type %C [concrete] -// CHECK:STDOUT: %C__carbon_thunk.type: type = fn_type @C__carbon_thunk [concrete] -// CHECK:STDOUT: %C__carbon_thunk: %C__carbon_thunk.type = struct_value () [concrete] +// CHECK:STDOUT: %C__carbon_thunk.type.65f120.1: type = fn_type @C__carbon_thunk.1 [concrete] +// CHECK:STDOUT: %C__carbon_thunk.d98342.1: %C__carbon_thunk.type.65f120.1 = struct_value () [concrete] // CHECK:STDOUT: %ImplicitAs.type.d14: type = facet_type <@ImplicitAs, @ImplicitAs(%i32)> [concrete] // CHECK:STDOUT: %ImplicitAs.Convert.type.1b6: type = fn_type @ImplicitAs.Convert, @ImplicitAs(%i32) [concrete] // CHECK:STDOUT: %To: Core.IntLiteral = bind_symbolic_name To, 0 [symbolic] @@ -550,6 +540,8 @@ fn F() { // CHECK:STDOUT: %Core.IntLiteral.as.ImplicitAs.impl.Convert.bound.36a: = bound_method %int_9.988, %Core.IntLiteral.as.ImplicitAs.impl.Convert.0f0 [concrete] // CHECK:STDOUT: %bound_method.942: = bound_method %int_9.988, %Core.IntLiteral.as.ImplicitAs.impl.Convert.specific_fn [concrete] // CHECK:STDOUT: %int_9.f88: %i32 = int_value 9 [concrete] +// CHECK:STDOUT: %C__carbon_thunk.type.65f120.2: type = fn_type @C__carbon_thunk.2 [concrete] +// CHECK:STDOUT: %C__carbon_thunk.d98342.2: %C__carbon_thunk.type.65f120.2 = struct_value () [concrete] // CHECK:STDOUT: %type_where: type = facet_type > [concrete] // CHECK:STDOUT: %facet_value: %type_where = facet_value %C, () [concrete] // CHECK:STDOUT: %AggregateT.as_type.as.Destroy.impl.Op.type.fc1: type = fn_type @AggregateT.as_type.as.Destroy.impl.Op, @AggregateT.as_type.as.Destroy.impl(%facet_value) [concrete] @@ -562,14 +554,19 @@ fn F() { // CHECK:STDOUT: import Cpp//... // CHECK:STDOUT: } // CHECK:STDOUT: %C.decl: type = class_decl @C [concrete = constants.%C] {} {} -// CHECK:STDOUT: %.40b: %.d40 = cpp_overload_set_value @C.C [concrete = constants.%empty_struct] -// CHECK:STDOUT: %C__carbon_thunk.decl: %C__carbon_thunk.type = fn_decl @C__carbon_thunk [concrete = constants.%C__carbon_thunk] { +// CHECK:STDOUT: %.40b: %.d40 = cpp_overload_set_value @C.C.1 [concrete = constants.%empty_struct] +// CHECK:STDOUT: %C__carbon_thunk.decl.8acdfe.1: %C__carbon_thunk.type.65f120.1 = fn_decl @C__carbon_thunk.1 [concrete = constants.%C__carbon_thunk.d98342.1] { // CHECK:STDOUT: // CHECK:STDOUT: } { // CHECK:STDOUT: // CHECK:STDOUT: } // CHECK:STDOUT: %Core.import_ref.ee7: @Core.IntLiteral.as.ImplicitAs.impl.%Core.IntLiteral.as.ImplicitAs.impl.Convert.type (%Core.IntLiteral.as.ImplicitAs.impl.Convert.type.340) = import_ref Core//prelude/parts/int, loc23_39, loaded [symbolic = @Core.IntLiteral.as.ImplicitAs.impl.%Core.IntLiteral.as.ImplicitAs.impl.Convert (constants.%Core.IntLiteral.as.ImplicitAs.impl.Convert.1c0)] // CHECK:STDOUT: %ImplicitAs.impl_witness_table.9e9 = impl_witness_table (%Core.import_ref.ee7), @Core.IntLiteral.as.ImplicitAs.impl [concrete] +// CHECK:STDOUT: %C__carbon_thunk.decl.8acdfe.2: %C__carbon_thunk.type.65f120.2 = fn_decl @C__carbon_thunk.2 [concrete = constants.%C__carbon_thunk.d98342.2] { +// CHECK:STDOUT: +// CHECK:STDOUT: } { +// CHECK:STDOUT: +// CHECK:STDOUT: } // CHECK:STDOUT: } // CHECK:STDOUT: // CHECK:STDOUT: fn @F() { @@ -598,8 +595,8 @@ fn F() { // CHECK:STDOUT: %.loc8_30.1: %i32 = value_of_initializer %Core.IntLiteral.as.ImplicitAs.impl.Convert.call.loc8_30 [concrete = constants.%int_9.f88] // CHECK:STDOUT: %.loc8_30.2: %i32 = converted %int_9, %.loc8_30.1 [concrete = constants.%int_9.f88] // CHECK:STDOUT: %addr.loc8_31.1: %ptr.d9e = addr_of %.loc8_31.1 -// CHECK:STDOUT: %C__carbon_thunk.call: init %empty_tuple.type = call imports.%C__carbon_thunk.decl(%.loc8_27.2, %.loc8_30.2, %addr.loc8_31.1) -// CHECK:STDOUT: %.loc8_31.2: init %C = in_place_init %C__carbon_thunk.call, %.loc8_31.1 +// CHECK:STDOUT: %C__carbon_thunk.call.loc8: init %empty_tuple.type = call imports.%C__carbon_thunk.decl.8acdfe.1(%.loc8_27.2, %.loc8_30.2, %addr.loc8_31.1) +// CHECK:STDOUT: %.loc8_31.2: init %C = in_place_init %C__carbon_thunk.call.loc8, %.loc8_31.1 // CHECK:STDOUT: %.loc8_14: type = splice_block %C.ref.loc8_14 [concrete = constants.%C] { // CHECK:STDOUT: %Cpp.ref.loc8_11: = name_ref Cpp, imports.%Cpp [concrete = imports.%Cpp] // CHECK:STDOUT: %C.ref.loc8_14: type = name_ref C, imports.%C.decl [concrete = constants.%C] @@ -610,22 +607,42 @@ fn F() { // CHECK:STDOUT: name_binding_decl { // CHECK:STDOUT: %c2.patt: %pattern_type.217 = binding_pattern c2 [concrete] // CHECK:STDOUT: } -// CHECK:STDOUT: %Cpp.ref.loc14_19: = name_ref Cpp, imports.%Cpp [concrete = imports.%Cpp] -// CHECK:STDOUT: %C.ref.loc14_22: type = name_ref C, imports.%C.decl [concrete = constants.%C] -// CHECK:STDOUT: %C.ref.loc14_24: %.d40 = name_ref C, imports.%.40b [concrete = constants.%empty_struct] -// CHECK:STDOUT: %int_8.loc14: Core.IntLiteral = int_value 8 [concrete = constants.%int_8.b85] -// CHECK:STDOUT: %.loc14: type = splice_block %C.ref.loc14_14 [concrete = constants.%C] { -// CHECK:STDOUT: %Cpp.ref.loc14_11: = name_ref Cpp, imports.%Cpp [concrete = imports.%Cpp] -// CHECK:STDOUT: %C.ref.loc14_14: type = name_ref C, imports.%C.decl [concrete = constants.%C] +// CHECK:STDOUT: %Cpp.ref.loc9_19: = name_ref Cpp, imports.%Cpp [concrete = imports.%Cpp] +// CHECK:STDOUT: %C.ref.loc9_22: type = name_ref C, imports.%C.decl [concrete = constants.%C] +// CHECK:STDOUT: %C.ref.loc9_24: %.d40 = name_ref C, imports.%.40b [concrete = constants.%empty_struct] +// CHECK:STDOUT: %int_8.loc9: Core.IntLiteral = int_value 8 [concrete = constants.%int_8.b85] +// CHECK:STDOUT: %.loc9_28.1: ref %C = temporary_storage +// CHECK:STDOUT: %impl.elem0.loc9: %.1df = impl_witness_access constants.%ImplicitAs.impl_witness.204, element0 [concrete = constants.%Core.IntLiteral.as.ImplicitAs.impl.Convert.0f0] +// CHECK:STDOUT: %bound_method.loc9_27.1: = bound_method %int_8.loc9, %impl.elem0.loc9 [concrete = constants.%Core.IntLiteral.as.ImplicitAs.impl.Convert.bound.0ab] +// CHECK:STDOUT: %specific_fn.loc9: = specific_function %impl.elem0.loc9, @Core.IntLiteral.as.ImplicitAs.impl.Convert(constants.%int_32) [concrete = constants.%Core.IntLiteral.as.ImplicitAs.impl.Convert.specific_fn] +// CHECK:STDOUT: %bound_method.loc9_27.2: = bound_method %int_8.loc9, %specific_fn.loc9 [concrete = constants.%bound_method.b23] +// CHECK:STDOUT: %Core.IntLiteral.as.ImplicitAs.impl.Convert.call.loc9: init %i32 = call %bound_method.loc9_27.2(%int_8.loc9) [concrete = constants.%int_8.98c] +// CHECK:STDOUT: %.loc9_27.1: %i32 = value_of_initializer %Core.IntLiteral.as.ImplicitAs.impl.Convert.call.loc9 [concrete = constants.%int_8.98c] +// CHECK:STDOUT: %.loc9_27.2: %i32 = converted %int_8.loc9, %.loc9_27.1 [concrete = constants.%int_8.98c] +// CHECK:STDOUT: %addr.loc9_28.1: %ptr.d9e = addr_of %.loc9_28.1 +// CHECK:STDOUT: %C__carbon_thunk.call.loc9: init %empty_tuple.type = call imports.%C__carbon_thunk.decl.8acdfe.2(%.loc9_27.2, %addr.loc9_28.1) +// CHECK:STDOUT: %.loc9_28.2: init %C = in_place_init %C__carbon_thunk.call.loc9, %.loc9_28.1 +// CHECK:STDOUT: %.loc9_14: type = splice_block %C.ref.loc9_14 [concrete = constants.%C] { +// CHECK:STDOUT: %Cpp.ref.loc9_11: = name_ref Cpp, imports.%Cpp [concrete = imports.%Cpp] +// CHECK:STDOUT: %C.ref.loc9_14: type = name_ref C, imports.%C.decl [concrete = constants.%C] // CHECK:STDOUT: } -// CHECK:STDOUT: %c2: %C = bind_name c2, [concrete = ] -// CHECK:STDOUT: %facet_value: %type_where = facet_value constants.%C, () [concrete = constants.%facet_value] -// CHECK:STDOUT: %.loc8_31.5: %type_where = converted constants.%C, %facet_value [concrete = constants.%facet_value] -// CHECK:STDOUT: %AggregateT.as_type.as.Destroy.impl.Op.bound: = bound_method %.loc8_31.3, constants.%AggregateT.as_type.as.Destroy.impl.Op.6b9 +// CHECK:STDOUT: %.loc9_28.3: ref %C = temporary %.loc9_28.1, %.loc9_28.2 +// CHECK:STDOUT: %.loc9_28.4: %C = bind_value %.loc9_28.3 +// CHECK:STDOUT: %c2: %C = bind_name c2, %.loc9_28.4 +// CHECK:STDOUT: %facet_value.loc9: %type_where = facet_value constants.%C, () [concrete = constants.%facet_value] +// CHECK:STDOUT: %.loc9_28.5: %type_where = converted constants.%C, %facet_value.loc9 [concrete = constants.%facet_value] +// CHECK:STDOUT: %AggregateT.as_type.as.Destroy.impl.Op.bound.loc9: = bound_method %.loc9_28.3, constants.%AggregateT.as_type.as.Destroy.impl.Op.6b9 // CHECK:STDOUT: -// CHECK:STDOUT: %bound_method.loc8_31: = bound_method %.loc8_31.3, %AggregateT.as_type.as.Destroy.impl.Op.specific_fn +// CHECK:STDOUT: %bound_method.loc9_28: = bound_method %.loc9_28.3, %AggregateT.as_type.as.Destroy.impl.Op.specific_fn.1 +// CHECK:STDOUT: %addr.loc9_28.2: %ptr.d9e = addr_of %.loc9_28.3 +// CHECK:STDOUT: %AggregateT.as_type.as.Destroy.impl.Op.call.loc9: init %empty_tuple.type = call %bound_method.loc9_28(%addr.loc9_28.2) +// CHECK:STDOUT: %facet_value.loc8: %type_where = facet_value constants.%C, () [concrete = constants.%facet_value] +// CHECK:STDOUT: %.loc8_31.5: %type_where = converted constants.%C, %facet_value.loc8 [concrete = constants.%facet_value] +// CHECK:STDOUT: %AggregateT.as_type.as.Destroy.impl.Op.bound.loc8: = bound_method %.loc8_31.3, constants.%AggregateT.as_type.as.Destroy.impl.Op.6b9 +// CHECK:STDOUT: +// CHECK:STDOUT: %bound_method.loc8_31: = bound_method %.loc8_31.3, %AggregateT.as_type.as.Destroy.impl.Op.specific_fn.2 // CHECK:STDOUT: %addr.loc8_31.2: %ptr.d9e = addr_of %.loc8_31.3 -// CHECK:STDOUT: %AggregateT.as_type.as.Destroy.impl.Op.call: init %empty_tuple.type = call %bound_method.loc8_31(%addr.loc8_31.2) +// CHECK:STDOUT: %AggregateT.as_type.as.Destroy.impl.Op.call.loc8: init %empty_tuple.type = call %bound_method.loc8_31(%addr.loc8_31.2) // CHECK:STDOUT: // CHECK:STDOUT: } // CHECK:STDOUT: @@ -755,15 +772,15 @@ fn F() { // CHECK:STDOUT: %empty_tuple.type: type = tuple_type () [concrete] // CHECK:STDOUT: %C: type = class_type @C [concrete] // CHECK:STDOUT: %pattern_type.217: type = pattern_type %C [concrete] -// CHECK:STDOUT: %.d40: type = cpp_overload_set_type @C.C [concrete] +// CHECK:STDOUT: %.d40: type = cpp_overload_set_type @C.C.1 [concrete] // CHECK:STDOUT: %empty_struct: %.d40 = struct_value () [concrete] // CHECK:STDOUT: %int_8.b85: Core.IntLiteral = int_value 8 [concrete] // CHECK:STDOUT: %int_9.988: Core.IntLiteral = int_value 9 [concrete] // CHECK:STDOUT: %int_32: Core.IntLiteral = int_value 32 [concrete] // CHECK:STDOUT: %i32: type = class_type @Int, @Int(%int_32) [concrete] // CHECK:STDOUT: %ptr.d9e: type = ptr_type %C [concrete] -// CHECK:STDOUT: %C__carbon_thunk.type: type = fn_type @C__carbon_thunk [concrete] -// CHECK:STDOUT: %C__carbon_thunk: %C__carbon_thunk.type = struct_value () [concrete] +// CHECK:STDOUT: %C__carbon_thunk.type.65f120.1: type = fn_type @C__carbon_thunk.1 [concrete] +// CHECK:STDOUT: %C__carbon_thunk.d98342.1: %C__carbon_thunk.type.65f120.1 = struct_value () [concrete] // CHECK:STDOUT: %ImplicitAs.type.d14: type = facet_type <@ImplicitAs, @ImplicitAs(%i32)> [concrete] // CHECK:STDOUT: %ImplicitAs.Convert.type.1b6: type = fn_type @ImplicitAs.Convert, @ImplicitAs(%i32) [concrete] // CHECK:STDOUT: %To: Core.IntLiteral = bind_symbolic_name To, 0 [symbolic] @@ -781,6 +798,8 @@ fn F() { // CHECK:STDOUT: %Core.IntLiteral.as.ImplicitAs.impl.Convert.bound.36a: = bound_method %int_9.988, %Core.IntLiteral.as.ImplicitAs.impl.Convert.0f0 [concrete] // CHECK:STDOUT: %bound_method.942: = bound_method %int_9.988, %Core.IntLiteral.as.ImplicitAs.impl.Convert.specific_fn [concrete] // CHECK:STDOUT: %int_9.f88: %i32 = int_value 9 [concrete] +// CHECK:STDOUT: %C__carbon_thunk.type.65f120.2: type = fn_type @C__carbon_thunk.2 [concrete] +// CHECK:STDOUT: %C__carbon_thunk.d98342.2: %C__carbon_thunk.type.65f120.2 = struct_value () [concrete] // CHECK:STDOUT: %As.type.dbd: type = facet_type <@As, @As(%i32)> [concrete] // CHECK:STDOUT: %As.Convert.type.99b: type = fn_type @As.Convert, @As(%i32) [concrete] // CHECK:STDOUT: %Core.IntLiteral.as.As.impl.Convert.type.565: type = fn_type @Core.IntLiteral.as.As.impl.Convert, @Core.IntLiteral.as.As.impl(%To) [symbolic] @@ -805,14 +824,19 @@ fn F() { // CHECK:STDOUT: import Cpp//... // CHECK:STDOUT: } // CHECK:STDOUT: %C.decl: type = class_decl @C [concrete = constants.%C] {} {} -// CHECK:STDOUT: %.40b: %.d40 = cpp_overload_set_value @C.C [concrete = constants.%empty_struct] -// CHECK:STDOUT: %C__carbon_thunk.decl: %C__carbon_thunk.type = fn_decl @C__carbon_thunk [concrete = constants.%C__carbon_thunk] { +// CHECK:STDOUT: %.40b: %.d40 = cpp_overload_set_value @C.C.1 [concrete = constants.%empty_struct] +// CHECK:STDOUT: %C__carbon_thunk.decl.8acdfe.1: %C__carbon_thunk.type.65f120.1 = fn_decl @C__carbon_thunk.1 [concrete = constants.%C__carbon_thunk.d98342.1] { // CHECK:STDOUT: // CHECK:STDOUT: } { // CHECK:STDOUT: // CHECK:STDOUT: } // CHECK:STDOUT: %Core.import_ref.ee7: @Core.IntLiteral.as.ImplicitAs.impl.%Core.IntLiteral.as.ImplicitAs.impl.Convert.type (%Core.IntLiteral.as.ImplicitAs.impl.Convert.type.340) = import_ref Core//prelude/parts/int, loc23_39, loaded [symbolic = @Core.IntLiteral.as.ImplicitAs.impl.%Core.IntLiteral.as.ImplicitAs.impl.Convert (constants.%Core.IntLiteral.as.ImplicitAs.impl.Convert.1c0)] // CHECK:STDOUT: %ImplicitAs.impl_witness_table.9e9 = impl_witness_table (%Core.import_ref.ee7), @Core.IntLiteral.as.ImplicitAs.impl [concrete] +// CHECK:STDOUT: %C__carbon_thunk.decl.8acdfe.2: %C__carbon_thunk.type.65f120.2 = fn_decl @C__carbon_thunk.2 [concrete = constants.%C__carbon_thunk.d98342.2] { +// CHECK:STDOUT: +// CHECK:STDOUT: } { +// CHECK:STDOUT: +// CHECK:STDOUT: } // CHECK:STDOUT: %Core.import_ref.99c: @Core.IntLiteral.as.As.impl.%Core.IntLiteral.as.As.impl.Convert.type (%Core.IntLiteral.as.As.impl.Convert.type.565) = import_ref Core//prelude/parts/int, loc32_39, loaded [symbolic = @Core.IntLiteral.as.As.impl.%Core.IntLiteral.as.As.impl.Convert (constants.%Core.IntLiteral.as.As.impl.Convert.d2c)] // CHECK:STDOUT: %As.impl_witness_table.5ad = impl_witness_table (%Core.import_ref.99c), @Core.IntLiteral.as.As.impl [concrete] // CHECK:STDOUT: } @@ -843,8 +867,8 @@ fn F() { // CHECK:STDOUT: %.loc8_30.1: %i32 = value_of_initializer %Core.IntLiteral.as.ImplicitAs.impl.Convert.call.loc8_30 [concrete = constants.%int_9.f88] // CHECK:STDOUT: %.loc8_30.2: %i32 = converted %int_9, %.loc8_30.1 [concrete = constants.%int_9.f88] // CHECK:STDOUT: %addr.loc8_31.1: %ptr.d9e = addr_of %.loc8_31.1 -// CHECK:STDOUT: %C__carbon_thunk.call: init %empty_tuple.type = call imports.%C__carbon_thunk.decl(%.loc8_27.2, %.loc8_30.2, %addr.loc8_31.1) -// CHECK:STDOUT: %.loc8_31.2: init %C = in_place_init %C__carbon_thunk.call, %.loc8_31.1 +// CHECK:STDOUT: %C__carbon_thunk.call.loc8: init %empty_tuple.type = call imports.%C__carbon_thunk.decl.8acdfe.1(%.loc8_27.2, %.loc8_30.2, %addr.loc8_31.1) +// CHECK:STDOUT: %.loc8_31.2: init %C = in_place_init %C__carbon_thunk.call.loc8, %.loc8_31.1 // CHECK:STDOUT: %.loc8_14: type = splice_block %C.ref.loc8_14 [concrete = constants.%C] { // CHECK:STDOUT: %Cpp.ref.loc8_11: = name_ref Cpp, imports.%Cpp [concrete = imports.%Cpp] // CHECK:STDOUT: %C.ref.loc8_14: type = name_ref C, imports.%C.decl [concrete = constants.%C] @@ -855,41 +879,61 @@ fn F() { // CHECK:STDOUT: name_binding_decl { // CHECK:STDOUT: %c2.patt: %pattern_type.217 = binding_pattern c2 [concrete] // CHECK:STDOUT: } -// CHECK:STDOUT: %Cpp.ref.loc14_19: = name_ref Cpp, imports.%Cpp [concrete = imports.%Cpp] -// CHECK:STDOUT: %C.ref.loc14_22: type = name_ref C, imports.%C.decl [concrete = constants.%C] -// CHECK:STDOUT: %C.ref.loc14_24: %.d40 = name_ref C, imports.%.40b [concrete = constants.%empty_struct] -// CHECK:STDOUT: %int_8.loc14: Core.IntLiteral = int_value 8 [concrete = constants.%int_8.b85] -// CHECK:STDOUT: %.loc14: type = splice_block %C.ref.loc14_14 [concrete = constants.%C] { -// CHECK:STDOUT: %Cpp.ref.loc14_11: = name_ref Cpp, imports.%Cpp [concrete = imports.%Cpp] -// CHECK:STDOUT: %C.ref.loc14_14: type = name_ref C, imports.%C.decl [concrete = constants.%C] +// CHECK:STDOUT: %Cpp.ref.loc9_19: = name_ref Cpp, imports.%Cpp [concrete = imports.%Cpp] +// CHECK:STDOUT: %C.ref.loc9_22: type = name_ref C, imports.%C.decl [concrete = constants.%C] +// CHECK:STDOUT: %C.ref.loc9_24: %.d40 = name_ref C, imports.%.40b [concrete = constants.%empty_struct] +// CHECK:STDOUT: %int_8.loc9: Core.IntLiteral = int_value 8 [concrete = constants.%int_8.b85] +// CHECK:STDOUT: %.loc9_28.1: ref %C = temporary_storage +// CHECK:STDOUT: %impl.elem0.loc9: %.1df = impl_witness_access constants.%ImplicitAs.impl_witness.204, element0 [concrete = constants.%Core.IntLiteral.as.ImplicitAs.impl.Convert.0f0] +// CHECK:STDOUT: %bound_method.loc9_27.1: = bound_method %int_8.loc9, %impl.elem0.loc9 [concrete = constants.%Core.IntLiteral.as.ImplicitAs.impl.Convert.bound.0ab] +// CHECK:STDOUT: %specific_fn.loc9: = specific_function %impl.elem0.loc9, @Core.IntLiteral.as.ImplicitAs.impl.Convert(constants.%int_32) [concrete = constants.%Core.IntLiteral.as.ImplicitAs.impl.Convert.specific_fn] +// CHECK:STDOUT: %bound_method.loc9_27.2: = bound_method %int_8.loc9, %specific_fn.loc9 [concrete = constants.%bound_method.b23] +// CHECK:STDOUT: %Core.IntLiteral.as.ImplicitAs.impl.Convert.call.loc9: init %i32 = call %bound_method.loc9_27.2(%int_8.loc9) [concrete = constants.%int_8.98c] +// CHECK:STDOUT: %.loc9_27.1: %i32 = value_of_initializer %Core.IntLiteral.as.ImplicitAs.impl.Convert.call.loc9 [concrete = constants.%int_8.98c] +// CHECK:STDOUT: %.loc9_27.2: %i32 = converted %int_8.loc9, %.loc9_27.1 [concrete = constants.%int_8.98c] +// CHECK:STDOUT: %addr.loc9_28.1: %ptr.d9e = addr_of %.loc9_28.1 +// CHECK:STDOUT: %C__carbon_thunk.call.loc9: init %empty_tuple.type = call imports.%C__carbon_thunk.decl.8acdfe.2(%.loc9_27.2, %addr.loc9_28.1) +// CHECK:STDOUT: %.loc9_28.2: init %C = in_place_init %C__carbon_thunk.call.loc9, %.loc9_28.1 +// CHECK:STDOUT: %.loc9_14: type = splice_block %C.ref.loc9_14 [concrete = constants.%C] { +// CHECK:STDOUT: %Cpp.ref.loc9_11: = name_ref Cpp, imports.%Cpp [concrete = imports.%Cpp] +// CHECK:STDOUT: %C.ref.loc9_14: type = name_ref C, imports.%C.decl [concrete = constants.%C] // CHECK:STDOUT: } -// CHECK:STDOUT: %c2: %C = bind_name c2, [concrete = ] +// CHECK:STDOUT: %.loc9_28.3: ref %C = temporary %.loc9_28.1, %.loc9_28.2 +// CHECK:STDOUT: %.loc9_28.4: %C = bind_value %.loc9_28.3 +// CHECK:STDOUT: %c2: %C = bind_name c2, %.loc9_28.4 // CHECK:STDOUT: name_binding_decl { // CHECK:STDOUT: %c3.patt: %pattern_type.217 = binding_pattern c3 [concrete] // CHECK:STDOUT: } -// CHECK:STDOUT: %int_8.loc22: Core.IntLiteral = int_value 8 [concrete = constants.%int_8.b85] +// CHECK:STDOUT: %int_8.loc17: Core.IntLiteral = int_value 8 [concrete = constants.%int_8.b85] // CHECK:STDOUT: %int_32: Core.IntLiteral = int_value 32 [concrete = constants.%int_32] // CHECK:STDOUT: %i32: type = class_type @Int, @Int(constants.%int_32) [concrete = constants.%i32] -// CHECK:STDOUT: %impl.elem0.loc22: %.351 = impl_witness_access constants.%As.impl_witness.080, element0 [concrete = constants.%Core.IntLiteral.as.As.impl.Convert.414] -// CHECK:STDOUT: %bound_method.loc22_21.1: = bound_method %int_8.loc22, %impl.elem0.loc22 [concrete = constants.%Core.IntLiteral.as.As.impl.Convert.bound] -// CHECK:STDOUT: %specific_fn.loc22: = specific_function %impl.elem0.loc22, @Core.IntLiteral.as.As.impl.Convert(constants.%int_32) [concrete = constants.%Core.IntLiteral.as.As.impl.Convert.specific_fn] -// CHECK:STDOUT: %bound_method.loc22_21.2: = bound_method %int_8.loc22, %specific_fn.loc22 [concrete = constants.%bound_method.80c] -// CHECK:STDOUT: %Core.IntLiteral.as.As.impl.Convert.call: init %i32 = call %bound_method.loc22_21.2(%int_8.loc22) [concrete = constants.%int_8.98c] -// CHECK:STDOUT: %.loc22_21.1: %i32 = value_of_initializer %Core.IntLiteral.as.As.impl.Convert.call [concrete = constants.%int_8.98c] -// CHECK:STDOUT: %.loc22_21.2: %i32 = converted %int_8.loc22, %.loc22_21.1 [concrete = constants.%int_8.98c] -// CHECK:STDOUT: %.loc22_14: type = splice_block %C.ref.loc22 [concrete = constants.%C] { -// CHECK:STDOUT: %Cpp.ref.loc22: = name_ref Cpp, imports.%Cpp [concrete = imports.%Cpp] -// CHECK:STDOUT: %C.ref.loc22: type = name_ref C, imports.%C.decl [concrete = constants.%C] +// CHECK:STDOUT: %impl.elem0.loc17: %.351 = impl_witness_access constants.%As.impl_witness.080, element0 [concrete = constants.%Core.IntLiteral.as.As.impl.Convert.414] +// CHECK:STDOUT: %bound_method.loc17_21.1: = bound_method %int_8.loc17, %impl.elem0.loc17 [concrete = constants.%Core.IntLiteral.as.As.impl.Convert.bound] +// CHECK:STDOUT: %specific_fn.loc17: = specific_function %impl.elem0.loc17, @Core.IntLiteral.as.As.impl.Convert(constants.%int_32) [concrete = constants.%Core.IntLiteral.as.As.impl.Convert.specific_fn] +// CHECK:STDOUT: %bound_method.loc17_21.2: = bound_method %int_8.loc17, %specific_fn.loc17 [concrete = constants.%bound_method.80c] +// CHECK:STDOUT: %Core.IntLiteral.as.As.impl.Convert.call: init %i32 = call %bound_method.loc17_21.2(%int_8.loc17) [concrete = constants.%int_8.98c] +// CHECK:STDOUT: %.loc17_21.1: %i32 = value_of_initializer %Core.IntLiteral.as.As.impl.Convert.call [concrete = constants.%int_8.98c] +// CHECK:STDOUT: %.loc17_21.2: %i32 = converted %int_8.loc17, %.loc17_21.1 [concrete = constants.%int_8.98c] +// CHECK:STDOUT: %.loc17_14: type = splice_block %C.ref.loc17 [concrete = constants.%C] { +// CHECK:STDOUT: %Cpp.ref.loc17: = name_ref Cpp, imports.%Cpp [concrete = imports.%Cpp] +// CHECK:STDOUT: %C.ref.loc17: type = name_ref C, imports.%C.decl [concrete = constants.%C] // CHECK:STDOUT: } -// CHECK:STDOUT: %.loc22_21.3: %C = converted %.loc22_21.2, [concrete = ] +// CHECK:STDOUT: %.loc17_21.3: %C = converted %.loc17_21.2, [concrete = ] // CHECK:STDOUT: %c3: %C = bind_name c3, [concrete = ] -// CHECK:STDOUT: %facet_value: %type_where = facet_value constants.%C, () [concrete = constants.%facet_value] -// CHECK:STDOUT: %.loc8_31.5: %type_where = converted constants.%C, %facet_value [concrete = constants.%facet_value] -// CHECK:STDOUT: %AggregateT.as_type.as.Destroy.impl.Op.bound: = bound_method %.loc8_31.3, constants.%AggregateT.as_type.as.Destroy.impl.Op.6b9 +// CHECK:STDOUT: %facet_value.loc9: %type_where = facet_value constants.%C, () [concrete = constants.%facet_value] +// CHECK:STDOUT: %.loc9_28.5: %type_where = converted constants.%C, %facet_value.loc9 [concrete = constants.%facet_value] +// CHECK:STDOUT: %AggregateT.as_type.as.Destroy.impl.Op.bound.loc9: = bound_method %.loc9_28.3, constants.%AggregateT.as_type.as.Destroy.impl.Op.6b9 // CHECK:STDOUT: -// CHECK:STDOUT: %bound_method.loc8_31: = bound_method %.loc8_31.3, %AggregateT.as_type.as.Destroy.impl.Op.specific_fn +// CHECK:STDOUT: %bound_method.loc9_28: = bound_method %.loc9_28.3, %AggregateT.as_type.as.Destroy.impl.Op.specific_fn.1 +// CHECK:STDOUT: %addr.loc9_28.2: %ptr.d9e = addr_of %.loc9_28.3 +// CHECK:STDOUT: %AggregateT.as_type.as.Destroy.impl.Op.call.loc9: init %empty_tuple.type = call %bound_method.loc9_28(%addr.loc9_28.2) +// CHECK:STDOUT: %facet_value.loc8: %type_where = facet_value constants.%C, () [concrete = constants.%facet_value] +// CHECK:STDOUT: %.loc8_31.5: %type_where = converted constants.%C, %facet_value.loc8 [concrete = constants.%facet_value] +// CHECK:STDOUT: %AggregateT.as_type.as.Destroy.impl.Op.bound.loc8: = bound_method %.loc8_31.3, constants.%AggregateT.as_type.as.Destroy.impl.Op.6b9 +// CHECK:STDOUT: +// CHECK:STDOUT: %bound_method.loc8_31: = bound_method %.loc8_31.3, %AggregateT.as_type.as.Destroy.impl.Op.specific_fn.2 // CHECK:STDOUT: %addr.loc8_31.2: %ptr.d9e = addr_of %.loc8_31.3 -// CHECK:STDOUT: %AggregateT.as_type.as.Destroy.impl.Op.call: init %empty_tuple.type = call %bound_method.loc8_31(%addr.loc8_31.2) +// CHECK:STDOUT: %AggregateT.as_type.as.Destroy.impl.Op.call.loc8: init %empty_tuple.type = call %bound_method.loc8_31(%addr.loc8_31.2) // CHECK:STDOUT: // CHECK:STDOUT: } // CHECK:STDOUT: diff --git a/toolchain/check/testdata/interop/cpp/enum/anonymous.carbon b/toolchain/check/testdata/interop/cpp/enum/anonymous.carbon index 95c47e816b6e..e86243865bd9 100644 --- a/toolchain/check/testdata/interop/cpp/enum/anonymous.carbon +++ b/toolchain/check/testdata/interop/cpp/enum/anonymous.carbon @@ -43,9 +43,9 @@ fn G() { // CHECK:STDOUT: %G.type: type = fn_type @G [concrete] // CHECK:STDOUT: %empty_tuple.type: type = tuple_type () [concrete] // CHECK:STDOUT: %G: %G.type = struct_value () [concrete] -// CHECK:STDOUT: %.4f0: type = class_type @.1 [concrete] // CHECK:STDOUT: %.557: type = cpp_overload_set_type @C.C [concrete] // CHECK:STDOUT: %empty_struct.56a: %.557 = struct_value () [concrete] +// CHECK:STDOUT: %.4f0: type = class_type @.1 [concrete] // CHECK:STDOUT: %int_1.81a: %.4f0 = int_value 1 [concrete] // CHECK:STDOUT: %ptr.793: type = ptr_type %.4f0 [concrete] // CHECK:STDOUT: %F__carbon_thunk.type.eda1ac.1: type = fn_type @F__carbon_thunk.1 [concrete] @@ -56,9 +56,9 @@ fn G() { // CHECK:STDOUT: %ptr.d9e: type = ptr_type %C [concrete] // CHECK:STDOUT: %C__carbon_thunk.type: type = fn_type @C__carbon_thunk [concrete] // CHECK:STDOUT: %C__carbon_thunk: %C__carbon_thunk.type = struct_value () [concrete] -// CHECK:STDOUT: %.bb7: type = class_type @.2 [concrete] // CHECK:STDOUT: %.9a3: type = cpp_overload_set_type @C.F [concrete] // CHECK:STDOUT: %empty_struct.acc: %.9a3 = struct_value () [concrete] +// CHECK:STDOUT: %.bb7: type = class_type @.2 [concrete] // CHECK:STDOUT: %int_1.1d6: %.bb7 = int_value 1 [concrete] // CHECK:STDOUT: %ptr.73d: type = ptr_type %.bb7 [concrete] // CHECK:STDOUT: %F__carbon_thunk.type.eda1ac.2: type = fn_type @F__carbon_thunk.2 [concrete] diff --git a/toolchain/check/testdata/interop/cpp/function/arithmetic_types_bridged.carbon b/toolchain/check/testdata/interop/cpp/function/arithmetic_types_bridged.carbon index 56f2fee70ca1..46684408f357 100644 --- a/toolchain/check/testdata/interop/cpp/function/arithmetic_types_bridged.carbon +++ b/toolchain/check/testdata/interop/cpp/function/arithmetic_types_bridged.carbon @@ -386,34 +386,6 @@ fn F() { //@dump-sem-ir-end } -// ============================================================================ -// const short param -// ============================================================================ - -// --- const_short_param.h - -auto foo(const short a) -> void; - -// --- fail_todo_import_const_short_param.carbon - -library "[[@TEST_NAME]]"; - -import Cpp library "const_short_param.h"; - -fn F() { - //@dump-sem-ir-begin - // CHECK:STDERR: fail_todo_import_const_short_param.carbon:[[@LINE+8]]:11: error: cannot implicitly convert expression of type `i16` to `const i16` [ConversionFailure] - // CHECK:STDERR: Cpp.foo(1 as i16); - // CHECK:STDERR: ^~~~~~~~ - // CHECK:STDERR: fail_todo_import_const_short_param.carbon:[[@LINE+5]]:11: note: type `i16` does not implement interface `Core.ImplicitAs(const i16)` [MissingImplInMemberAccessNote] - // CHECK:STDERR: Cpp.foo(1 as i16); - // CHECK:STDERR: ^~~~~~~~ - // CHECK:STDERR: fail_todo_import_const_short_param.carbon: note: initializing function parameter [InCallToFunctionParam] - // CHECK:STDERR: - Cpp.foo(1 as i16); - //@dump-sem-ir-end -} - // ============================================================================ // _Float16 param // ============================================================================ @@ -1738,85 +1710,6 @@ fn F() { // CHECK:STDOUT: // CHECK:STDOUT: } // CHECK:STDOUT: -// CHECK:STDOUT: --- fail_todo_import_const_short_param.carbon -// CHECK:STDOUT: -// CHECK:STDOUT: constants { -// CHECK:STDOUT: %empty_tuple.type: type = tuple_type () [concrete] -// CHECK:STDOUT: %.c5d: type = cpp_overload_set_type @As.Convert [concrete] -// CHECK:STDOUT: %empty_struct: %.c5d = struct_value () [concrete] -// CHECK:STDOUT: %int_1.5b8: Core.IntLiteral = int_value 1 [concrete] -// CHECK:STDOUT: %int_16: Core.IntLiteral = int_value 16 [concrete] -// CHECK:STDOUT: %i16: type = class_type @Int, @Int(%int_16) [concrete] -// CHECK:STDOUT: %As.type.771: type = facet_type <@As, @As(%i16)> [concrete] -// CHECK:STDOUT: %As.Convert.type.be5: type = fn_type @As.Convert, @As(%i16) [concrete] -// CHECK:STDOUT: %To.c80: Core.IntLiteral = bind_symbolic_name To, 0 [symbolic] -// CHECK:STDOUT: %Core.IntLiteral.as.As.impl.Convert.type.565: type = fn_type @Core.IntLiteral.as.As.impl.Convert, @Core.IntLiteral.as.As.impl(%To.c80) [symbolic] -// CHECK:STDOUT: %Core.IntLiteral.as.As.impl.Convert.d2c: %Core.IntLiteral.as.As.impl.Convert.type.565 = struct_value () [symbolic] -// CHECK:STDOUT: %As.impl_witness.2d2: = impl_witness imports.%As.impl_witness_table.5ad, @Core.IntLiteral.as.As.impl(%int_16) [concrete] -// CHECK:STDOUT: %Core.IntLiteral.as.As.impl.Convert.type.38a: type = fn_type @Core.IntLiteral.as.As.impl.Convert, @Core.IntLiteral.as.As.impl(%int_16) [concrete] -// CHECK:STDOUT: %Core.IntLiteral.as.As.impl.Convert.97a: %Core.IntLiteral.as.As.impl.Convert.type.38a = struct_value () [concrete] -// CHECK:STDOUT: %As.facet: %As.type.771 = facet_value Core.IntLiteral, (%As.impl_witness.2d2) [concrete] -// CHECK:STDOUT: %.026: type = fn_type_with_self_type %As.Convert.type.be5, %As.facet [concrete] -// CHECK:STDOUT: %Core.IntLiteral.as.As.impl.Convert.bound: = bound_method %int_1.5b8, %Core.IntLiteral.as.As.impl.Convert.97a [concrete] -// CHECK:STDOUT: %Core.IntLiteral.as.As.impl.Convert.specific_fn: = specific_function %Core.IntLiteral.as.As.impl.Convert.97a, @Core.IntLiteral.as.As.impl.Convert(%int_16) [concrete] -// CHECK:STDOUT: %bound_method: = bound_method %int_1.5b8, %Core.IntLiteral.as.As.impl.Convert.specific_fn [concrete] -// CHECK:STDOUT: %int_1.f90: %i16 = int_value 1 [concrete] -// CHECK:STDOUT: %const.660: type = const_type %i16 [concrete] -// CHECK:STDOUT: %ptr.758: type = ptr_type %const.660 [concrete] -// CHECK:STDOUT: %foo__carbon_thunk.type: type = fn_type @foo__carbon_thunk [concrete] -// CHECK:STDOUT: %foo__carbon_thunk: %foo__carbon_thunk.type = struct_value () [concrete] -// CHECK:STDOUT: %Copy.type: type = facet_type <@Copy> [concrete] -// CHECK:STDOUT: %Copy.impl_witness.51d: = impl_witness imports.%Copy.impl_witness_table.965, @Int.as.Copy.impl(%int_16) [concrete] -// CHECK:STDOUT: %Copy.facet.b88: %Copy.type = facet_value %i16, (%Copy.impl_witness.51d) [concrete] -// CHECK:STDOUT: %Copy.impl_witness.184: = impl_witness imports.%Copy.impl_witness_table.df8, @const.as.Copy.impl(%Copy.facet.b88) [concrete] -// CHECK:STDOUT: %Copy.facet.61b: %Copy.type = facet_value %const.660, (%Copy.impl_witness.184) [concrete] -// CHECK:STDOUT: } -// CHECK:STDOUT: -// CHECK:STDOUT: imports { -// CHECK:STDOUT: %Cpp: = namespace file.%Cpp.import_cpp, [concrete] { -// CHECK:STDOUT: .foo = %.a21 -// CHECK:STDOUT: import Cpp//... -// CHECK:STDOUT: } -// CHECK:STDOUT: %.a21: %.c5d = cpp_overload_set_value @As.Convert [concrete = constants.%empty_struct] -// CHECK:STDOUT: %Core.import_ref.99c: @Core.IntLiteral.as.As.impl.%Core.IntLiteral.as.As.impl.Convert.type (%Core.IntLiteral.as.As.impl.Convert.type.565) = import_ref Core//prelude/types/int, loc36_39, loaded [symbolic = @Core.IntLiteral.as.As.impl.%Core.IntLiteral.as.As.impl.Convert (constants.%Core.IntLiteral.as.As.impl.Convert.d2c)] -// CHECK:STDOUT: %As.impl_witness_table.5ad = impl_witness_table (%Core.import_ref.99c), @Core.IntLiteral.as.As.impl [concrete] -// CHECK:STDOUT: %foo__carbon_thunk.decl: %foo__carbon_thunk.type = fn_decl @foo__carbon_thunk [concrete = constants.%foo__carbon_thunk] { -// CHECK:STDOUT: -// CHECK:STDOUT: } { -// CHECK:STDOUT: -// CHECK:STDOUT: } -// CHECK:STDOUT: %Core.import_ref.71e = import_ref Core//prelude/copy, loc19_31, unloaded -// CHECK:STDOUT: %Copy.impl_witness_table.df8 = impl_witness_table (%Core.import_ref.71e), @const.as.Copy.impl [concrete] -// CHECK:STDOUT: %Core.import_ref.2eb = import_ref Core//prelude/types/int, loc21_31, unloaded -// CHECK:STDOUT: %Copy.impl_witness_table.965 = impl_witness_table (%Core.import_ref.2eb), @Int.as.Copy.impl [concrete] -// CHECK:STDOUT: } -// CHECK:STDOUT: -// CHECK:STDOUT: fn @F() { -// CHECK:STDOUT: !entry: -// CHECK:STDOUT: %Cpp.ref: = name_ref Cpp, imports.%Cpp [concrete = imports.%Cpp] -// CHECK:STDOUT: %foo.ref: %.c5d = name_ref foo, imports.%.a21 [concrete = constants.%empty_struct] -// CHECK:STDOUT: %int_1: Core.IntLiteral = int_value 1 [concrete = constants.%int_1.5b8] -// CHECK:STDOUT: %int_16: Core.IntLiteral = int_value 16 [concrete = constants.%int_16] -// CHECK:STDOUT: %i16: type = class_type @Int, @Int(constants.%int_16) [concrete = constants.%i16] -// CHECK:STDOUT: %impl.elem0: %.026 = impl_witness_access constants.%As.impl_witness.2d2, element0 [concrete = constants.%Core.IntLiteral.as.As.impl.Convert.97a] -// CHECK:STDOUT: %bound_method.loc16_13.1: = bound_method %int_1, %impl.elem0 [concrete = constants.%Core.IntLiteral.as.As.impl.Convert.bound] -// CHECK:STDOUT: %specific_fn: = specific_function %impl.elem0, @Core.IntLiteral.as.As.impl.Convert(constants.%int_16) [concrete = constants.%Core.IntLiteral.as.As.impl.Convert.specific_fn] -// CHECK:STDOUT: %bound_method.loc16_13.2: = bound_method %int_1, %specific_fn [concrete = constants.%bound_method] -// CHECK:STDOUT: %Core.IntLiteral.as.As.impl.Convert.call: init %i16 = call %bound_method.loc16_13.2(%int_1) [concrete = constants.%int_1.f90] -// CHECK:STDOUT: %.loc16_13.1: %i16 = value_of_initializer %Core.IntLiteral.as.As.impl.Convert.call [concrete = constants.%int_1.f90] -// CHECK:STDOUT: %.loc16_13.2: %i16 = converted %int_1, %.loc16_13.1 [concrete = constants.%int_1.f90] -// CHECK:STDOUT: %Copy.facet.loc16_13.1: %Copy.type = facet_value constants.%i16, (constants.%Copy.impl_witness.51d) [concrete = constants.%Copy.facet.b88] -// CHECK:STDOUT: %.loc16_13.3: %Copy.type = converted constants.%i16, %Copy.facet.loc16_13.1 [concrete = constants.%Copy.facet.b88] -// CHECK:STDOUT: %Copy.facet.loc16_13.2: %Copy.type = facet_value constants.%const.660, (constants.%Copy.impl_witness.184) [concrete = constants.%Copy.facet.61b] -// CHECK:STDOUT: %.loc16_13.4: %Copy.type = converted constants.%const.660, %Copy.facet.loc16_13.2 [concrete = constants.%Copy.facet.61b] -// CHECK:STDOUT: %Copy.facet.loc16_13.3: %Copy.type = facet_value constants.%i16, (constants.%Copy.impl_witness.51d) [concrete = constants.%Copy.facet.b88] -// CHECK:STDOUT: %.loc16_13.5: %Copy.type = converted constants.%i16, %Copy.facet.loc16_13.3 [concrete = constants.%Copy.facet.b88] -// CHECK:STDOUT: %.loc16_13.6: %const.660 = converted %.loc16_13.2, [concrete = ] -// CHECK:STDOUT: %addr: %ptr.758 = addr_of [concrete = ] -// CHECK:STDOUT: %foo__carbon_thunk.call: init %empty_tuple.type = call imports.%foo__carbon_thunk.decl(%addr) -// CHECK:STDOUT: -// CHECK:STDOUT: } -// CHECK:STDOUT: // CHECK:STDOUT: --- import_float16_param.carbon // CHECK:STDOUT: // CHECK:STDOUT: constants { diff --git a/toolchain/check/testdata/interop/cpp/function/arithmetic_types_direct.carbon b/toolchain/check/testdata/interop/cpp/function/arithmetic_types_direct.carbon index f60fd1cd15c7..96295be3710e 100644 --- a/toolchain/check/testdata/interop/cpp/function/arithmetic_types_direct.carbon +++ b/toolchain/check/testdata/interop/cpp/function/arithmetic_types_direct.carbon @@ -262,71 +262,6 @@ fn F() { //@dump-sem-ir-end } -// ============================================================================ -// int default param -// ============================================================================ - -// --- int_default_param.h - -auto foo(int a = 0) -> void; - -// --- fail_todo_import_int_default_parameterless_call.carbon - -library "[[@TEST_NAME]]"; - -import Cpp library "int_default_param.h"; - -fn F() { - //@dump-sem-ir-begin - // CHECK:STDERR: fail_todo_import_int_default_parameterless_call.carbon:[[@LINE+5]]:3: error: 0 arguments passed to function expecting 1 argument [CallArgCountMismatch] - // CHECK:STDERR: Cpp.foo(); - // CHECK:STDERR: ^~~~~~~~~ - // CHECK:STDERR: fail_todo_import_int_default_parameterless_call.carbon: note: calling function declared here [InCallToEntity] - // CHECK:STDERR: - Cpp.foo(); - //@dump-sem-ir-end -} - -// --- import_int_default_param_sucessful_call.carbon - -library "[[@TEST_NAME]]"; - -import Cpp library "int_default_param.h"; - -fn F() { - //@dump-sem-ir-begin - Cpp.foo(1); - //@dump-sem-ir-end -} - -// ============================================================================ -// const int param -// ============================================================================ - -// --- const_int_param.h - -auto foo(const int a) -> void; - -// --- fail_todo_import_const_int_param.carbon - -library "[[@TEST_NAME]]"; - -import Cpp library "const_int_param.h"; - -fn F() { - //@dump-sem-ir-begin - // CHECK:STDERR: fail_todo_import_const_int_param.carbon:[[@LINE+8]]:11: error: cannot implicitly convert expression of type `Core.IntLiteral` to `const i32` [ConversionFailure] - // CHECK:STDERR: Cpp.foo(1); - // CHECK:STDERR: ^ - // CHECK:STDERR: fail_todo_import_const_int_param.carbon:[[@LINE+5]]:11: note: type `Core.IntLiteral` does not implement interface `Core.ImplicitAs(const i32)` [MissingImplInMemberAccessNote] - // CHECK:STDERR: Cpp.foo(1); - // CHECK:STDERR: ^ - // CHECK:STDERR: fail_todo_import_const_int_param.carbon: note: initializing function parameter [InCallToFunctionParam] - // CHECK:STDERR: - Cpp.foo(1); - //@dump-sem-ir-end -} - // ============================================================================ // int return // ============================================================================ @@ -1028,123 +963,6 @@ fn F() { // CHECK:STDOUT: // CHECK:STDOUT: } // CHECK:STDOUT: -// CHECK:STDOUT: --- fail_todo_import_int_default_parameterless_call.carbon -// CHECK:STDOUT: -// CHECK:STDOUT: constants { -// CHECK:STDOUT: %.c5d: type = cpp_overload_set_type @foo [concrete] -// CHECK:STDOUT: %empty_struct: %.c5d = struct_value () [concrete] -// CHECK:STDOUT: } -// CHECK:STDOUT: -// CHECK:STDOUT: imports { -// CHECK:STDOUT: %Cpp: = namespace file.%Cpp.import_cpp, [concrete] { -// CHECK:STDOUT: .foo = %.a21 -// CHECK:STDOUT: import Cpp//... -// CHECK:STDOUT: } -// CHECK:STDOUT: %.a21: %.c5d = cpp_overload_set_value @foo [concrete = constants.%empty_struct] -// CHECK:STDOUT: } -// CHECK:STDOUT: -// CHECK:STDOUT: fn @F() { -// CHECK:STDOUT: !entry: -// CHECK:STDOUT: %Cpp.ref: = name_ref Cpp, imports.%Cpp [concrete = imports.%Cpp] -// CHECK:STDOUT: %foo.ref: %.c5d = name_ref foo, imports.%.a21 [concrete = constants.%empty_struct] -// CHECK:STDOUT: -// CHECK:STDOUT: } -// CHECK:STDOUT: -// CHECK:STDOUT: --- import_int_default_param_sucessful_call.carbon -// CHECK:STDOUT: -// CHECK:STDOUT: constants { -// CHECK:STDOUT: %empty_tuple.type: type = tuple_type () [concrete] -// CHECK:STDOUT: %.c5d: type = cpp_overload_set_type @foo [concrete] -// CHECK:STDOUT: %empty_struct: %.c5d = struct_value () [concrete] -// CHECK:STDOUT: %int_1.5b8: Core.IntLiteral = int_value 1 [concrete] -// CHECK:STDOUT: %int_32: Core.IntLiteral = int_value 32 [concrete] -// CHECK:STDOUT: %i32: type = class_type @Int, @Int(%int_32) [concrete] -// CHECK:STDOUT: %foo.type: type = fn_type @foo [concrete] -// CHECK:STDOUT: %foo: %foo.type = struct_value () [concrete] -// CHECK:STDOUT: %ImplicitAs.type.d14: type = facet_type <@ImplicitAs, @ImplicitAs(%i32)> [concrete] -// CHECK:STDOUT: %ImplicitAs.Convert.type.1b6: type = fn_type @ImplicitAs.Convert, @ImplicitAs(%i32) [concrete] -// CHECK:STDOUT: %To: Core.IntLiteral = bind_symbolic_name To, 0 [symbolic] -// CHECK:STDOUT: %Core.IntLiteral.as.ImplicitAs.impl.Convert.type.340: type = fn_type @Core.IntLiteral.as.ImplicitAs.impl.Convert, @Core.IntLiteral.as.ImplicitAs.impl(%To) [symbolic] -// CHECK:STDOUT: %Core.IntLiteral.as.ImplicitAs.impl.Convert.1c0: %Core.IntLiteral.as.ImplicitAs.impl.Convert.type.340 = struct_value () [symbolic] -// CHECK:STDOUT: %ImplicitAs.impl_witness.204: = impl_witness imports.%ImplicitAs.impl_witness_table.9e9, @Core.IntLiteral.as.ImplicitAs.impl(%int_32) [concrete] -// CHECK:STDOUT: %Core.IntLiteral.as.ImplicitAs.impl.Convert.type.584: type = fn_type @Core.IntLiteral.as.ImplicitAs.impl.Convert, @Core.IntLiteral.as.ImplicitAs.impl(%int_32) [concrete] -// CHECK:STDOUT: %Core.IntLiteral.as.ImplicitAs.impl.Convert.0f0: %Core.IntLiteral.as.ImplicitAs.impl.Convert.type.584 = struct_value () [concrete] -// CHECK:STDOUT: %ImplicitAs.facet: %ImplicitAs.type.d14 = facet_value Core.IntLiteral, (%ImplicitAs.impl_witness.204) [concrete] -// CHECK:STDOUT: %.1df: type = fn_type_with_self_type %ImplicitAs.Convert.type.1b6, %ImplicitAs.facet [concrete] -// CHECK:STDOUT: %Core.IntLiteral.as.ImplicitAs.impl.Convert.bound: = bound_method %int_1.5b8, %Core.IntLiteral.as.ImplicitAs.impl.Convert.0f0 [concrete] -// CHECK:STDOUT: %Core.IntLiteral.as.ImplicitAs.impl.Convert.specific_fn: = specific_function %Core.IntLiteral.as.ImplicitAs.impl.Convert.0f0, @Core.IntLiteral.as.ImplicitAs.impl.Convert(%int_32) [concrete] -// CHECK:STDOUT: %bound_method: = bound_method %int_1.5b8, %Core.IntLiteral.as.ImplicitAs.impl.Convert.specific_fn [concrete] -// CHECK:STDOUT: %int_1.5d2: %i32 = int_value 1 [concrete] -// CHECK:STDOUT: } -// CHECK:STDOUT: -// CHECK:STDOUT: imports { -// CHECK:STDOUT: %Cpp: = namespace file.%Cpp.import_cpp, [concrete] { -// CHECK:STDOUT: .foo = %.a21 -// CHECK:STDOUT: import Cpp//... -// CHECK:STDOUT: } -// CHECK:STDOUT: %.a21: %.c5d = cpp_overload_set_value @foo [concrete = constants.%empty_struct] -// CHECK:STDOUT: %foo.decl: %foo.type = fn_decl @foo [concrete = constants.%foo] { -// CHECK:STDOUT: -// CHECK:STDOUT: } { -// CHECK:STDOUT: -// CHECK:STDOUT: } -// CHECK:STDOUT: %Core.import_ref.ee7: @Core.IntLiteral.as.ImplicitAs.impl.%Core.IntLiteral.as.ImplicitAs.impl.Convert.type (%Core.IntLiteral.as.ImplicitAs.impl.Convert.type.340) = import_ref Core//prelude/parts/int, loc23_39, loaded [symbolic = @Core.IntLiteral.as.ImplicitAs.impl.%Core.IntLiteral.as.ImplicitAs.impl.Convert (constants.%Core.IntLiteral.as.ImplicitAs.impl.Convert.1c0)] -// CHECK:STDOUT: %ImplicitAs.impl_witness_table.9e9 = impl_witness_table (%Core.import_ref.ee7), @Core.IntLiteral.as.ImplicitAs.impl [concrete] -// CHECK:STDOUT: } -// CHECK:STDOUT: -// CHECK:STDOUT: fn @F() { -// CHECK:STDOUT: !entry: -// CHECK:STDOUT: %Cpp.ref: = name_ref Cpp, imports.%Cpp [concrete = imports.%Cpp] -// CHECK:STDOUT: %foo.ref: %.c5d = name_ref foo, imports.%.a21 [concrete = constants.%empty_struct] -// CHECK:STDOUT: %int_1: Core.IntLiteral = int_value 1 [concrete = constants.%int_1.5b8] -// CHECK:STDOUT: %impl.elem0: %.1df = impl_witness_access constants.%ImplicitAs.impl_witness.204, element0 [concrete = constants.%Core.IntLiteral.as.ImplicitAs.impl.Convert.0f0] -// CHECK:STDOUT: %bound_method.loc8_11.1: = bound_method %int_1, %impl.elem0 [concrete = constants.%Core.IntLiteral.as.ImplicitAs.impl.Convert.bound] -// CHECK:STDOUT: %specific_fn: = specific_function %impl.elem0, @Core.IntLiteral.as.ImplicitAs.impl.Convert(constants.%int_32) [concrete = constants.%Core.IntLiteral.as.ImplicitAs.impl.Convert.specific_fn] -// CHECK:STDOUT: %bound_method.loc8_11.2: = bound_method %int_1, %specific_fn [concrete = constants.%bound_method] -// CHECK:STDOUT: %Core.IntLiteral.as.ImplicitAs.impl.Convert.call: init %i32 = call %bound_method.loc8_11.2(%int_1) [concrete = constants.%int_1.5d2] -// CHECK:STDOUT: %.loc8_11.1: %i32 = value_of_initializer %Core.IntLiteral.as.ImplicitAs.impl.Convert.call [concrete = constants.%int_1.5d2] -// CHECK:STDOUT: %.loc8_11.2: %i32 = converted %int_1, %.loc8_11.1 [concrete = constants.%int_1.5d2] -// CHECK:STDOUT: %foo.call: init %empty_tuple.type = call imports.%foo.decl(%.loc8_11.2) -// CHECK:STDOUT: -// CHECK:STDOUT: } -// CHECK:STDOUT: -// CHECK:STDOUT: --- fail_todo_import_const_int_param.carbon -// CHECK:STDOUT: -// CHECK:STDOUT: constants { -// CHECK:STDOUT: %empty_tuple.type: type = tuple_type () [concrete] -// CHECK:STDOUT: %.c5d: type = cpp_overload_set_type @foo [concrete] -// CHECK:STDOUT: %empty_struct: %.c5d = struct_value () [concrete] -// CHECK:STDOUT: %int_1: Core.IntLiteral = int_value 1 [concrete] -// CHECK:STDOUT: %int_32: Core.IntLiteral = int_value 32 [concrete] -// CHECK:STDOUT: %i32: type = class_type @Int, @Int(%int_32) [concrete] -// CHECK:STDOUT: %const: type = const_type %i32 [concrete] -// CHECK:STDOUT: %foo.type: type = fn_type @foo [concrete] -// CHECK:STDOUT: %foo: %foo.type = struct_value () [concrete] -// CHECK:STDOUT: } -// CHECK:STDOUT: -// CHECK:STDOUT: imports { -// CHECK:STDOUT: %Cpp: = namespace file.%Cpp.import_cpp, [concrete] { -// CHECK:STDOUT: .foo = %.a21 -// CHECK:STDOUT: import Cpp//... -// CHECK:STDOUT: } -// CHECK:STDOUT: %.a21: %.c5d = cpp_overload_set_value @foo [concrete = constants.%empty_struct] -// CHECK:STDOUT: %foo.decl: %foo.type = fn_decl @foo [concrete = constants.%foo] { -// CHECK:STDOUT: -// CHECK:STDOUT: } { -// CHECK:STDOUT: -// CHECK:STDOUT: } -// CHECK:STDOUT: } -// CHECK:STDOUT: -// CHECK:STDOUT: fn @F() { -// CHECK:STDOUT: !entry: -// CHECK:STDOUT: %Cpp.ref: = name_ref Cpp, imports.%Cpp [concrete = imports.%Cpp] -// CHECK:STDOUT: %foo.ref: %.c5d = name_ref foo, imports.%.a21 [concrete = constants.%empty_struct] -// CHECK:STDOUT: %int_1: Core.IntLiteral = int_value 1 [concrete = constants.%int_1] -// CHECK:STDOUT: %.loc16: %const = converted %int_1, [concrete = ] -// CHECK:STDOUT: %foo.call: init %empty_tuple.type = call imports.%foo.decl() -// CHECK:STDOUT: -// CHECK:STDOUT: } -// CHECK:STDOUT: // CHECK:STDOUT: --- import_int_return.carbon // CHECK:STDOUT: // CHECK:STDOUT: constants { diff --git a/toolchain/check/testdata/interop/cpp/function/class.carbon b/toolchain/check/testdata/interop/cpp/function/class.carbon index c70d90c3c3de..364526c7d169 100644 --- a/toolchain/check/testdata/interop/cpp/function/class.carbon +++ b/toolchain/check/testdata/interop/cpp/function/class.carbon @@ -526,10 +526,10 @@ fn F() { // CHECK:STDOUT: // CHECK:STDOUT: constants { // CHECK:STDOUT: %empty_tuple.type: type = tuple_type () [concrete] -// CHECK:STDOUT: %C: type = class_type @C [concrete] // CHECK:STDOUT: %.c5d: type = cpp_overload_set_type @foo [concrete] // CHECK:STDOUT: %empty_struct: %.c5d = struct_value () [concrete] // CHECK:STDOUT: %empty_struct_type: type = struct_type {} [concrete] +// CHECK:STDOUT: %C: type = class_type @C [concrete] // CHECK:STDOUT: %C.val: %C = struct_value () [concrete] // CHECK:STDOUT: %ptr.d9e: type = ptr_type %C [concrete] // CHECK:STDOUT: %foo__carbon_thunk.type: type = fn_type @foo__carbon_thunk [concrete] @@ -546,8 +546,8 @@ fn F() { // CHECK:STDOUT: .C = %C.decl // CHECK:STDOUT: import Cpp//... // CHECK:STDOUT: } -// CHECK:STDOUT: %C.decl: type = class_decl @C [concrete = constants.%C] {} {} // CHECK:STDOUT: %.a21: %.c5d = cpp_overload_set_value @foo [concrete = constants.%empty_struct] +// CHECK:STDOUT: %C.decl: type = class_decl @C [concrete = constants.%C] {} {} // CHECK:STDOUT: %foo__carbon_thunk.decl: %foo__carbon_thunk.type = fn_decl @foo__carbon_thunk [concrete = constants.%foo__carbon_thunk] { // CHECK:STDOUT: // CHECK:STDOUT: } { @@ -584,10 +584,10 @@ fn F() { // CHECK:STDOUT: // CHECK:STDOUT: constants { // CHECK:STDOUT: %empty_tuple.type: type = tuple_type () [concrete] -// CHECK:STDOUT: %C: type = class_type @C [concrete] // CHECK:STDOUT: %.c5d: type = cpp_overload_set_type @foo [concrete] // CHECK:STDOUT: %empty_struct: %.c5d = struct_value () [concrete] // CHECK:STDOUT: %empty_struct_type: type = struct_type {} [concrete] +// CHECK:STDOUT: %C: type = class_type @C [concrete] // CHECK:STDOUT: %C.val: %C = struct_value () [concrete] // CHECK:STDOUT: %foo.type: type = fn_type @foo [concrete] // CHECK:STDOUT: %foo: %foo.type = struct_value () [concrete] @@ -604,8 +604,8 @@ fn F() { // CHECK:STDOUT: .C = %C.decl // CHECK:STDOUT: import Cpp//... // CHECK:STDOUT: } -// CHECK:STDOUT: %C.decl: type = class_decl @C [concrete = constants.%C] {} {} // CHECK:STDOUT: %.a21: %.c5d = cpp_overload_set_value @foo [concrete = constants.%empty_struct] +// CHECK:STDOUT: %C.decl: type = class_decl @C [concrete = constants.%C] {} {} // CHECK:STDOUT: %foo.decl: %foo.type = fn_decl @foo [concrete = constants.%foo] { // CHECK:STDOUT: // CHECK:STDOUT: } { @@ -639,10 +639,10 @@ fn F() { // CHECK:STDOUT: --- fail_todo_import_definition_single_data_member_value_param_type.carbon // CHECK:STDOUT: // CHECK:STDOUT: constants { -// CHECK:STDOUT: %C: type = class_type @C [concrete] // CHECK:STDOUT: %.c5d: type = cpp_overload_set_type @As.Convert [concrete] // CHECK:STDOUT: %empty_struct: %.c5d = struct_value () [concrete] // CHECK:STDOUT: %empty_struct_type: type = struct_type {} [concrete] +// CHECK:STDOUT: %C: type = class_type @C [concrete] // CHECK:STDOUT: } // CHECK:STDOUT: // CHECK:STDOUT: imports { @@ -651,8 +651,8 @@ fn F() { // CHECK:STDOUT: .C = %C.decl // CHECK:STDOUT: import Cpp//... // CHECK:STDOUT: } -// CHECK:STDOUT: %C.decl: type = class_decl @C [concrete = constants.%C] {} {} // CHECK:STDOUT: %.a21: %.c5d = cpp_overload_set_value @As.Convert [concrete = constants.%empty_struct] +// CHECK:STDOUT: %C.decl: type = class_decl @C [concrete = constants.%C] {} {} // CHECK:STDOUT: } // CHECK:STDOUT: // CHECK:STDOUT: fn @F() { @@ -669,10 +669,10 @@ fn F() { // CHECK:STDOUT: --- fail_todo_import_definition_multiple_data_members_value_param_type.carbon // CHECK:STDOUT: // CHECK:STDOUT: constants { -// CHECK:STDOUT: %C: type = class_type @C [concrete] // CHECK:STDOUT: %.c5d: type = cpp_overload_set_type @As.Convert [concrete] // CHECK:STDOUT: %empty_struct: %.c5d = struct_value () [concrete] // CHECK:STDOUT: %empty_struct_type: type = struct_type {} [concrete] +// CHECK:STDOUT: %C: type = class_type @C [concrete] // CHECK:STDOUT: } // CHECK:STDOUT: // CHECK:STDOUT: imports { @@ -681,8 +681,8 @@ fn F() { // CHECK:STDOUT: .C = %C.decl // CHECK:STDOUT: import Cpp//... // CHECK:STDOUT: } -// CHECK:STDOUT: %C.decl: type = class_decl @C [concrete = constants.%C] {} {} // CHECK:STDOUT: %.a21: %.c5d = cpp_overload_set_value @As.Convert [concrete = constants.%empty_struct] +// CHECK:STDOUT: %C.decl: type = class_decl @C [concrete = constants.%C] {} {} // CHECK:STDOUT: } // CHECK:STDOUT: // CHECK:STDOUT: fn @F() { @@ -700,10 +700,10 @@ fn F() { // CHECK:STDOUT: // CHECK:STDOUT: constants { // CHECK:STDOUT: %empty_tuple.type: type = tuple_type () [concrete] -// CHECK:STDOUT: %C: type = class_type @C [concrete] // CHECK:STDOUT: %.c5d: type = cpp_overload_set_type @foo [concrete] // CHECK:STDOUT: %empty_struct: %.c5d = struct_value () [concrete] // CHECK:STDOUT: %empty_struct_type: type = struct_type {} [concrete] +// CHECK:STDOUT: %C: type = class_type @C [concrete] // CHECK:STDOUT: %C.val: %C = struct_value () [concrete] // CHECK:STDOUT: %pattern_type.69f: type = pattern_type %C [concrete] // CHECK:STDOUT: %ptr.838: type = ptr_type %C [concrete] @@ -721,12 +721,12 @@ fn F() { // CHECK:STDOUT: .N = %N // CHECK:STDOUT: import Cpp//... // CHECK:STDOUT: } +// CHECK:STDOUT: %.a21: %.c5d = cpp_overload_set_value @foo [concrete = constants.%empty_struct] // CHECK:STDOUT: %N: = namespace [concrete] { // CHECK:STDOUT: .C = %C.decl // CHECK:STDOUT: import Cpp//... // CHECK:STDOUT: } // CHECK:STDOUT: %C.decl: type = class_decl @C [concrete = constants.%C] {} {} -// CHECK:STDOUT: %.a21: %.c5d = cpp_overload_set_value @foo [concrete = constants.%empty_struct] // CHECK:STDOUT: %foo__carbon_thunk.decl: %foo__carbon_thunk.type = fn_decl @foo__carbon_thunk [concrete = constants.%foo__carbon_thunk] { // CHECK:STDOUT: // CHECK:STDOUT: } { @@ -782,10 +782,10 @@ fn F() { // CHECK:STDOUT: // CHECK:STDOUT: constants { // CHECK:STDOUT: %empty_tuple.type: type = tuple_type () [concrete] -// CHECK:STDOUT: %C: type = class_type @C [concrete] // CHECK:STDOUT: %.92e: type = cpp_overload_set_type @foo [concrete] // CHECK:STDOUT: %empty_struct: %.92e = struct_value () [concrete] // CHECK:STDOUT: %empty_struct_type: type = struct_type {} [concrete] +// CHECK:STDOUT: %C: type = class_type @C [concrete] // CHECK:STDOUT: %C.val: %C = struct_value () [concrete] // CHECK:STDOUT: %ptr.c0c: type = ptr_type %C [concrete] // CHECK:STDOUT: %foo__carbon_thunk.type: type = fn_type @foo__carbon_thunk [concrete] @@ -806,12 +806,12 @@ fn F() { // CHECK:STDOUT: .N2 = %N2 // CHECK:STDOUT: import Cpp//... // CHECK:STDOUT: } +// CHECK:STDOUT: %.218: %.92e = cpp_overload_set_value @foo [concrete = constants.%empty_struct] // CHECK:STDOUT: %N2: = namespace [concrete] { // CHECK:STDOUT: .C = %C.decl // CHECK:STDOUT: import Cpp//... // CHECK:STDOUT: } // CHECK:STDOUT: %C.decl: type = class_decl @C [concrete = constants.%C] {} {} -// CHECK:STDOUT: %.218: %.92e = cpp_overload_set_value @foo [concrete = constants.%empty_struct] // CHECK:STDOUT: %foo__carbon_thunk.decl: %foo__carbon_thunk.type = fn_decl @foo__carbon_thunk [concrete = constants.%foo__carbon_thunk] { // CHECK:STDOUT: // CHECK:STDOUT: } { @@ -851,11 +851,11 @@ fn F() { // CHECK:STDOUT: // CHECK:STDOUT: constants { // CHECK:STDOUT: %empty_tuple.type: type = tuple_type () [concrete] -// CHECK:STDOUT: %O: type = class_type @O [concrete] -// CHECK:STDOUT: %C: type = class_type @C [concrete] // CHECK:STDOUT: %.c5d: type = cpp_overload_set_type @foo [concrete] // CHECK:STDOUT: %empty_struct: %.c5d = struct_value () [concrete] // CHECK:STDOUT: %empty_struct_type: type = struct_type {} [concrete] +// CHECK:STDOUT: %O: type = class_type @O [concrete] +// CHECK:STDOUT: %C: type = class_type @C [concrete] // CHECK:STDOUT: %C.val: %C = struct_value () [concrete] // CHECK:STDOUT: %ptr.de2: type = ptr_type %C [concrete] // CHECK:STDOUT: %foo__carbon_thunk.type: type = fn_type @foo__carbon_thunk [concrete] @@ -877,9 +877,9 @@ fn F() { // CHECK:STDOUT: .O = %O.decl // CHECK:STDOUT: import Cpp//... // CHECK:STDOUT: } +// CHECK:STDOUT: %.a21: %.c5d = cpp_overload_set_value @foo [concrete = constants.%empty_struct] // CHECK:STDOUT: %O.decl: type = class_decl @O [concrete = constants.%O] {} {} // CHECK:STDOUT: %C.decl: type = class_decl @C [concrete = constants.%C] {} {} -// CHECK:STDOUT: %.a21: %.c5d = cpp_overload_set_value @foo [concrete = constants.%empty_struct] // CHECK:STDOUT: %foo__carbon_thunk.decl: %foo__carbon_thunk.type = fn_decl @foo__carbon_thunk [concrete = constants.%foo__carbon_thunk] { // CHECK:STDOUT: // CHECK:STDOUT: } { @@ -1002,10 +1002,10 @@ fn F() { // CHECK:STDOUT: // CHECK:STDOUT: constants { // CHECK:STDOUT: %empty_tuple.type: type = tuple_type () [concrete] -// CHECK:STDOUT: %C: type = class_type @C [concrete] // CHECK:STDOUT: %.c5d: type = cpp_overload_set_type @foo__carbon_thunk [concrete] // CHECK:STDOUT: %empty_struct.109: %.c5d = struct_value () [concrete] // CHECK:STDOUT: %empty_struct_type: type = struct_type {} [concrete] +// CHECK:STDOUT: %C: type = class_type @C [concrete] // CHECK:STDOUT: %C.val: %C = struct_value () [concrete] // CHECK:STDOUT: %ptr.d9e: type = ptr_type %C [concrete] // CHECK:STDOUT: %foo__carbon_thunk.type: type = fn_type @foo__carbon_thunk [concrete] @@ -1026,8 +1026,8 @@ fn F() { // CHECK:STDOUT: .C = %C.decl // CHECK:STDOUT: import Cpp//... // CHECK:STDOUT: } -// CHECK:STDOUT: %C.decl: type = class_decl @C [concrete = constants.%C] {} {} // CHECK:STDOUT: %.a21: %.c5d = cpp_overload_set_value @foo__carbon_thunk [concrete = constants.%empty_struct.109] +// CHECK:STDOUT: %C.decl: type = class_decl @C [concrete = constants.%C] {} {} // CHECK:STDOUT: %foo__carbon_thunk.decl: %foo__carbon_thunk.type = fn_decl @foo__carbon_thunk [concrete = constants.%foo__carbon_thunk] { // CHECK:STDOUT: // CHECK:STDOUT: } { @@ -1142,9 +1142,9 @@ fn F() { // CHECK:STDOUT: // CHECK:STDOUT: constants { // CHECK:STDOUT: %empty_tuple.type: type = tuple_type () [concrete] -// CHECK:STDOUT: %C: type = class_type @C [concrete] // CHECK:STDOUT: %.c5d: type = cpp_overload_set_type @foo [concrete] // CHECK:STDOUT: %empty_struct: %.c5d = struct_value () [concrete] +// CHECK:STDOUT: %C: type = class_type @C [concrete] // CHECK:STDOUT: %ptr.d9e: type = ptr_type %C [concrete] // CHECK:STDOUT: %foo__carbon_thunk.type: type = fn_type @foo__carbon_thunk [concrete] // CHECK:STDOUT: %foo__carbon_thunk: %foo__carbon_thunk.type = struct_value () [concrete] @@ -1189,9 +1189,9 @@ fn F() { // CHECK:STDOUT: --- import_decl_pointer_return_type.carbon // CHECK:STDOUT: // CHECK:STDOUT: constants { -// CHECK:STDOUT: %C: type = class_type @C [concrete] // CHECK:STDOUT: %.c5d: type = cpp_overload_set_type @foo [concrete] // CHECK:STDOUT: %empty_struct: %.c5d = struct_value () [concrete] +// CHECK:STDOUT: %C: type = class_type @C [concrete] // CHECK:STDOUT: %ptr: type = ptr_type %C [concrete] // CHECK:STDOUT: %foo.type: type = fn_type @foo [concrete] // CHECK:STDOUT: %foo: %foo.type = struct_value () [concrete] @@ -1221,9 +1221,9 @@ fn F() { // CHECK:STDOUT: --- import_definition_pointer_return_type.carbon // CHECK:STDOUT: // CHECK:STDOUT: constants { -// CHECK:STDOUT: %C: type = class_type @C [concrete] // CHECK:STDOUT: %.c5d: type = cpp_overload_set_type @foo [concrete] // CHECK:STDOUT: %empty_struct: %.c5d = struct_value () [concrete] +// CHECK:STDOUT: %C: type = class_type @C [concrete] // CHECK:STDOUT: %ptr: type = ptr_type %C [concrete] // CHECK:STDOUT: %foo.type: type = fn_type @foo [concrete] // CHECK:STDOUT: %foo: %foo.type = struct_value () [concrete] diff --git a/toolchain/check/testdata/interop/cpp/function/decayed_param.carbon b/toolchain/check/testdata/interop/cpp/function/decayed_param.carbon new file mode 100644 index 000000000000..79310600ff97 --- /dev/null +++ b/toolchain/check/testdata/interop/cpp/function/decayed_param.carbon @@ -0,0 +1,196 @@ +// 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-FILE: toolchain/testing/testdata/min_prelude/int.carbon +// +// AUTOUPDATE +// TIP: To test this file alone, run: +// TIP: bazel test //toolchain/testing:file_test --test_arg=--file_tests=toolchain/check/testdata/interop/cpp/function/decayed_param.carbon +// TIP: To dump output, run: +// TIP: bazel run //toolchain/testing:file_test -- --dump_output --file_tests=toolchain/check/testdata/interop/cpp/function/decayed_param.carbon + +// --- params.h + +void TakesArray(int arr[42]); +void TakesFunction(int f(int)); + +int Function(int); + +// --- fail_todo_call_params.carbon + +library "[[@TEST_NAME]]"; + +import Cpp library "params.h"; + +fn G(n: i32) -> i32; + +fn F() { + //@dump-sem-ir-begin + var n: array(i32, 42); + // CHECK:STDERR: fail_todo_call_params.carbon:[[@LINE+4]]:3: error: semantics TODO: `Unsupported: parameter type: int *` [SemanticsTodo] + // CHECK:STDERR: Cpp.TakesArray(&n[0]); + // CHECK:STDERR: ^~~~~~~~~~~~~~~~~~~~~ + // CHECK:STDERR: + Cpp.TakesArray(&n[0]); + + // CHECK:STDERR: fail_todo_call_params.carbon:[[@LINE+4]]:18: error: member name `nullptr` not found in `Cpp` [MemberNameNotFoundInInstScope] + // CHECK:STDERR: Cpp.TakesArray(Cpp.nullptr); + // CHECK:STDERR: ^~~~~~~~~~~ + // CHECK:STDERR: + Cpp.TakesArray(Cpp.nullptr); + + // CHECK:STDERR: fail_todo_call_params.carbon:[[@LINE+4]]:21: error: call argument of type `` is not supported [CppCallArgTypeNotSupported] + // CHECK:STDERR: Cpp.TakesFunction(G); + // CHECK:STDERR: ^ + // CHECK:STDERR: + Cpp.TakesFunction(G); + + // CHECK:STDERR: fail_todo_call_params.carbon:[[@LINE+4]]:21: error: call argument of type `` is not supported [CppCallArgTypeNotSupported] + // CHECK:STDERR: Cpp.TakesFunction(Cpp.Function); + // CHECK:STDERR: ^~~~~~~~~~~~ + // CHECK:STDERR: + Cpp.TakesFunction(Cpp.Function); + + // CHECK:STDERR: fail_todo_call_params.carbon:[[@LINE+8]]:26: error: no matching function for call to 'TakesFunction' [CppInteropParseError] + // CHECK:STDERR: 43 | Cpp.TakesFunction(&n[0]); + // CHECK:STDERR: | ^ + // CHECK:STDERR: fail_todo_call_params.carbon:[[@LINE-34]]:10: in file included here [InCppInclude] + // CHECK:STDERR: ./params.h:3:6: note: candidate function not viable: no known conversion from 'int * _Nonnull' to 'int (*)(int)' for 1st argument [CppInteropParseNote] + // CHECK:STDERR: 3 | void TakesFunction(int f(int)); + // CHECK:STDERR: | ^ ~~~~~~~~~~ + // CHECK:STDERR: + Cpp.TakesFunction(&n[0]); + + // CHECK:STDERR: fail_todo_call_params.carbon:[[@LINE+4]]:21: error: member name `nullptr` not found in `Cpp` [MemberNameNotFoundInInstScope] + // CHECK:STDERR: Cpp.TakesFunction(Cpp.nullptr); + // CHECK:STDERR: ^~~~~~~~~~~ + // CHECK:STDERR: + Cpp.TakesFunction(Cpp.nullptr); + //@dump-sem-ir-end +} + +// CHECK:STDOUT: --- fail_todo_call_params.carbon +// CHECK:STDOUT: +// CHECK:STDOUT: constants { +// CHECK:STDOUT: %int_32: Core.IntLiteral = int_value 32 [concrete] +// CHECK:STDOUT: %empty_tuple.type: type = tuple_type () [concrete] +// CHECK:STDOUT: %i32: type = class_type @Int, @Int(%int_32) [concrete] +// CHECK:STDOUT: %G.type: type = fn_type @G [concrete] +// CHECK:STDOUT: %G: %G.type = struct_value () [concrete] +// CHECK:STDOUT: %int_42: Core.IntLiteral = int_value 42 [concrete] +// CHECK:STDOUT: %array_type: type = array_type %int_42, %i32 [concrete] +// CHECK:STDOUT: %ptr.830: type = ptr_type %array_type [concrete] +// CHECK:STDOUT: %pattern_type.b6e: type = pattern_type %array_type [concrete] +// CHECK:STDOUT: %.cdf: type = cpp_overload_set_type @Core.IntLiteral.as.ImplicitAs.impl.Convert [concrete] +// CHECK:STDOUT: %empty_struct.5c5: %.cdf = struct_value () [concrete] +// CHECK:STDOUT: %int_0.5c6: Core.IntLiteral = int_value 0 [concrete] +// CHECK:STDOUT: %ImplicitAs.type.d14: type = facet_type <@ImplicitAs, @ImplicitAs(%i32)> [concrete] +// CHECK:STDOUT: %ImplicitAs.Convert.type.1b6: type = fn_type @ImplicitAs.Convert, @ImplicitAs(%i32) [concrete] +// CHECK:STDOUT: %To: Core.IntLiteral = bind_symbolic_name To, 0 [symbolic] +// CHECK:STDOUT: %Core.IntLiteral.as.ImplicitAs.impl.Convert.type.340: type = fn_type @Core.IntLiteral.as.ImplicitAs.impl.Convert, @Core.IntLiteral.as.ImplicitAs.impl(%To) [symbolic] +// CHECK:STDOUT: %Core.IntLiteral.as.ImplicitAs.impl.Convert.1c0: %Core.IntLiteral.as.ImplicitAs.impl.Convert.type.340 = struct_value () [symbolic] +// CHECK:STDOUT: %ImplicitAs.impl_witness.204: = impl_witness imports.%ImplicitAs.impl_witness_table.9e9, @Core.IntLiteral.as.ImplicitAs.impl(%int_32) [concrete] +// CHECK:STDOUT: %Core.IntLiteral.as.ImplicitAs.impl.Convert.type.584: type = fn_type @Core.IntLiteral.as.ImplicitAs.impl.Convert, @Core.IntLiteral.as.ImplicitAs.impl(%int_32) [concrete] +// CHECK:STDOUT: %Core.IntLiteral.as.ImplicitAs.impl.Convert.0f0: %Core.IntLiteral.as.ImplicitAs.impl.Convert.type.584 = struct_value () [concrete] +// CHECK:STDOUT: %ImplicitAs.facet: %ImplicitAs.type.d14 = facet_value Core.IntLiteral, (%ImplicitAs.impl_witness.204) [concrete] +// CHECK:STDOUT: %.1df: type = fn_type_with_self_type %ImplicitAs.Convert.type.1b6, %ImplicitAs.facet [concrete] +// CHECK:STDOUT: %Core.IntLiteral.as.ImplicitAs.impl.Convert.bound: = bound_method %int_0.5c6, %Core.IntLiteral.as.ImplicitAs.impl.Convert.0f0 [concrete] +// CHECK:STDOUT: %Core.IntLiteral.as.ImplicitAs.impl.Convert.specific_fn: = specific_function %Core.IntLiteral.as.ImplicitAs.impl.Convert.0f0, @Core.IntLiteral.as.ImplicitAs.impl.Convert(%int_32) [concrete] +// CHECK:STDOUT: %bound_method: = bound_method %int_0.5c6, %Core.IntLiteral.as.ImplicitAs.impl.Convert.specific_fn [concrete] +// CHECK:STDOUT: %int_0.6a9: %i32 = int_value 0 [concrete] +// CHECK:STDOUT: %ptr.235: type = ptr_type %i32 [concrete] +// CHECK:STDOUT: %.319: type = cpp_overload_set_type @Int.as.ImplicitAs.impl.Convert [concrete] +// CHECK:STDOUT: %empty_struct.45a: %.319 = struct_value () [concrete] +// CHECK:STDOUT: %.001: type = cpp_overload_set_type @Destroy.Op [concrete] +// CHECK:STDOUT: %empty_struct.89b: %.001 = struct_value () [concrete] +// CHECK:STDOUT: %type_where: type = facet_type > [concrete] +// CHECK:STDOUT: %facet_value: %type_where = facet_value %array_type, () [concrete] +// CHECK:STDOUT: %AggregateT.as_type.as.Destroy.impl.Op.type.b6e: type = fn_type @AggregateT.as_type.as.Destroy.impl.Op, @AggregateT.as_type.as.Destroy.impl(%facet_value) [concrete] +// CHECK:STDOUT: %AggregateT.as_type.as.Destroy.impl.Op.91f: %AggregateT.as_type.as.Destroy.impl.Op.type.b6e = struct_value () [concrete] +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: imports { +// CHECK:STDOUT: %Cpp: = namespace file.%Cpp.import_cpp, [concrete] { +// CHECK:STDOUT: .TakesArray = %.782 +// CHECK:STDOUT: .nullptr = +// CHECK:STDOUT: .TakesFunction = %.a02 +// CHECK:STDOUT: .Function = %.5ec +// CHECK:STDOUT: import Cpp//... +// CHECK:STDOUT: } +// CHECK:STDOUT: %.782: %.cdf = cpp_overload_set_value @Core.IntLiteral.as.ImplicitAs.impl.Convert [concrete = constants.%empty_struct.5c5] +// CHECK:STDOUT: %Core.import_ref.ee7: @Core.IntLiteral.as.ImplicitAs.impl.%Core.IntLiteral.as.ImplicitAs.impl.Convert.type (%Core.IntLiteral.as.ImplicitAs.impl.Convert.type.340) = import_ref Core//prelude/parts/int, loc23_39, loaded [symbolic = @Core.IntLiteral.as.ImplicitAs.impl.%Core.IntLiteral.as.ImplicitAs.impl.Convert (constants.%Core.IntLiteral.as.ImplicitAs.impl.Convert.1c0)] +// CHECK:STDOUT: %ImplicitAs.impl_witness_table.9e9 = impl_witness_table (%Core.import_ref.ee7), @Core.IntLiteral.as.ImplicitAs.impl [concrete] +// CHECK:STDOUT: %.a02: %.319 = cpp_overload_set_value @Int.as.ImplicitAs.impl.Convert [concrete = constants.%empty_struct.45a] +// CHECK:STDOUT: %.5ec: %.001 = cpp_overload_set_value @Destroy.Op [concrete = constants.%empty_struct.89b] +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: fn @F() { +// CHECK:STDOUT: !entry: +// CHECK:STDOUT: name_binding_decl { +// CHECK:STDOUT: %n.patt: %pattern_type.b6e = binding_pattern n [concrete] +// CHECK:STDOUT: %n.var_patt: %pattern_type.b6e = var_pattern %n.patt [concrete] +// CHECK:STDOUT: } +// CHECK:STDOUT: %n.var: ref %array_type = var %n.var_patt +// CHECK:STDOUT: %.loc10_23: type = splice_block %array_type [concrete = constants.%array_type] { +// CHECK:STDOUT: %int_32.loc10: Core.IntLiteral = int_value 32 [concrete = constants.%int_32] +// CHECK:STDOUT: %i32.loc10: type = class_type @Int, @Int(constants.%int_32) [concrete = constants.%i32] +// CHECK:STDOUT: %int_42: Core.IntLiteral = int_value 42 [concrete = constants.%int_42] +// CHECK:STDOUT: %array_type: type = array_type %int_42, %i32.loc10 [concrete = constants.%array_type] +// CHECK:STDOUT: } +// CHECK:STDOUT: %n: ref %array_type = bind_name n, %n.var +// CHECK:STDOUT: %Cpp.ref.loc15: = name_ref Cpp, imports.%Cpp [concrete = imports.%Cpp] +// CHECK:STDOUT: %TakesArray.ref.loc15: %.cdf = name_ref TakesArray, imports.%.782 [concrete = constants.%empty_struct.5c5] +// CHECK:STDOUT: %n.ref.loc15: ref %array_type = name_ref n, %n +// CHECK:STDOUT: %int_0.loc15: Core.IntLiteral = int_value 0 [concrete = constants.%int_0.5c6] +// CHECK:STDOUT: %int_32.loc15: Core.IntLiteral = int_value 32 [concrete = constants.%int_32] +// CHECK:STDOUT: %i32.loc15: type = class_type @Int, @Int(constants.%int_32) [concrete = constants.%i32] +// CHECK:STDOUT: %impl.elem0.loc15: %.1df = impl_witness_access constants.%ImplicitAs.impl_witness.204, element0 [concrete = constants.%Core.IntLiteral.as.ImplicitAs.impl.Convert.0f0] +// CHECK:STDOUT: %bound_method.loc15_21.1: = bound_method %int_0.loc15, %impl.elem0.loc15 [concrete = constants.%Core.IntLiteral.as.ImplicitAs.impl.Convert.bound] +// CHECK:STDOUT: %specific_fn.loc15: = specific_function %impl.elem0.loc15, @Core.IntLiteral.as.ImplicitAs.impl.Convert(constants.%int_32) [concrete = constants.%Core.IntLiteral.as.ImplicitAs.impl.Convert.specific_fn] +// CHECK:STDOUT: %bound_method.loc15_21.2: = bound_method %int_0.loc15, %specific_fn.loc15 [concrete = constants.%bound_method] +// CHECK:STDOUT: %Core.IntLiteral.as.ImplicitAs.impl.Convert.call.loc15: init %i32 = call %bound_method.loc15_21.2(%int_0.loc15) [concrete = constants.%int_0.6a9] +// CHECK:STDOUT: %.loc15_21.1: %i32 = value_of_initializer %Core.IntLiteral.as.ImplicitAs.impl.Convert.call.loc15 [concrete = constants.%int_0.6a9] +// CHECK:STDOUT: %.loc15_21.2: %i32 = converted %int_0.loc15, %.loc15_21.1 [concrete = constants.%int_0.6a9] +// CHECK:STDOUT: %.loc15_22: ref %i32 = array_index %n.ref.loc15, %.loc15_21.2 +// CHECK:STDOUT: %addr.loc15: %ptr.235 = addr_of %.loc15_22 +// CHECK:STDOUT: %Cpp.ref.loc21_3: = name_ref Cpp, imports.%Cpp [concrete = imports.%Cpp] +// CHECK:STDOUT: %TakesArray.ref.loc21: %.cdf = name_ref TakesArray, imports.%.782 [concrete = constants.%empty_struct.5c5] +// CHECK:STDOUT: %Cpp.ref.loc21_18: = name_ref Cpp, imports.%Cpp [concrete = imports.%Cpp] +// CHECK:STDOUT: %nullptr.ref.loc21: = name_ref nullptr, [concrete = ] +// CHECK:STDOUT: %Cpp.ref.loc27: = name_ref Cpp, imports.%Cpp [concrete = imports.%Cpp] +// CHECK:STDOUT: %TakesFunction.ref.loc27: %.319 = name_ref TakesFunction, imports.%.a02 [concrete = constants.%empty_struct.45a] +// CHECK:STDOUT: %G.ref: %G.type = name_ref G, file.%G.decl [concrete = constants.%G] +// CHECK:STDOUT: %Cpp.ref.loc33_3: = name_ref Cpp, imports.%Cpp [concrete = imports.%Cpp] +// CHECK:STDOUT: %TakesFunction.ref.loc33: %.319 = name_ref TakesFunction, imports.%.a02 [concrete = constants.%empty_struct.45a] +// CHECK:STDOUT: %Cpp.ref.loc33_21: = name_ref Cpp, imports.%Cpp [concrete = imports.%Cpp] +// CHECK:STDOUT: %Function.ref: %.001 = name_ref Function, imports.%.5ec [concrete = constants.%empty_struct.89b] +// CHECK:STDOUT: %Cpp.ref.loc43: = name_ref Cpp, imports.%Cpp [concrete = imports.%Cpp] +// CHECK:STDOUT: %TakesFunction.ref.loc43: %.319 = name_ref TakesFunction, imports.%.a02 [concrete = constants.%empty_struct.45a] +// CHECK:STDOUT: %n.ref.loc43: ref %array_type = name_ref n, %n +// CHECK:STDOUT: %int_0.loc43: Core.IntLiteral = int_value 0 [concrete = constants.%int_0.5c6] +// CHECK:STDOUT: %int_32.loc43: Core.IntLiteral = int_value 32 [concrete = constants.%int_32] +// CHECK:STDOUT: %i32.loc43: type = class_type @Int, @Int(constants.%int_32) [concrete = constants.%i32] +// CHECK:STDOUT: %impl.elem0.loc43: %.1df = impl_witness_access constants.%ImplicitAs.impl_witness.204, element0 [concrete = constants.%Core.IntLiteral.as.ImplicitAs.impl.Convert.0f0] +// CHECK:STDOUT: %bound_method.loc43_24.1: = bound_method %int_0.loc43, %impl.elem0.loc43 [concrete = constants.%Core.IntLiteral.as.ImplicitAs.impl.Convert.bound] +// CHECK:STDOUT: %specific_fn.loc43: = specific_function %impl.elem0.loc43, @Core.IntLiteral.as.ImplicitAs.impl.Convert(constants.%int_32) [concrete = constants.%Core.IntLiteral.as.ImplicitAs.impl.Convert.specific_fn] +// CHECK:STDOUT: %bound_method.loc43_24.2: = bound_method %int_0.loc43, %specific_fn.loc43 [concrete = constants.%bound_method] +// CHECK:STDOUT: %Core.IntLiteral.as.ImplicitAs.impl.Convert.call.loc43: init %i32 = call %bound_method.loc43_24.2(%int_0.loc43) [concrete = constants.%int_0.6a9] +// CHECK:STDOUT: %.loc43_24.1: %i32 = value_of_initializer %Core.IntLiteral.as.ImplicitAs.impl.Convert.call.loc43 [concrete = constants.%int_0.6a9] +// CHECK:STDOUT: %.loc43_24.2: %i32 = converted %int_0.loc43, %.loc43_24.1 [concrete = constants.%int_0.6a9] +// CHECK:STDOUT: %.loc43_25: ref %i32 = array_index %n.ref.loc43, %.loc43_24.2 +// CHECK:STDOUT: %addr.loc43: %ptr.235 = addr_of %.loc43_25 +// CHECK:STDOUT: %Cpp.ref.loc49_3: = name_ref Cpp, imports.%Cpp [concrete = imports.%Cpp] +// CHECK:STDOUT: %TakesFunction.ref.loc49: %.319 = name_ref TakesFunction, imports.%.a02 [concrete = constants.%empty_struct.45a] +// CHECK:STDOUT: %Cpp.ref.loc49_21: = name_ref Cpp, imports.%Cpp [concrete = imports.%Cpp] +// CHECK:STDOUT: %nullptr.ref.loc49: = name_ref nullptr, [concrete = ] +// CHECK:STDOUT: %facet_value: %type_where = facet_value constants.%array_type, () [concrete = constants.%facet_value] +// CHECK:STDOUT: %.loc10_3: %type_where = converted constants.%array_type, %facet_value [concrete = constants.%facet_value] +// CHECK:STDOUT: %AggregateT.as_type.as.Destroy.impl.Op.bound: = bound_method %n.var, constants.%AggregateT.as_type.as.Destroy.impl.Op.91f +// CHECK:STDOUT: +// CHECK:STDOUT: %bound_method.loc10: = bound_method %n.var, %AggregateT.as_type.as.Destroy.impl.Op.specific_fn +// CHECK:STDOUT: %addr.loc10: %ptr.830 = addr_of %n.var +// CHECK:STDOUT: %AggregateT.as_type.as.Destroy.impl.Op.call: init %empty_tuple.type = call %bound_method.loc10(%addr.loc10) +// CHECK:STDOUT: +// CHECK:STDOUT: } +// CHECK:STDOUT: diff --git a/toolchain/check/testdata/interop/cpp/function/default_arg.carbon b/toolchain/check/testdata/interop/cpp/function/default_arg.carbon new file mode 100644 index 000000000000..d6bf9cd47adf --- /dev/null +++ b/toolchain/check/testdata/interop/cpp/function/default_arg.carbon @@ -0,0 +1,761 @@ +// 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-FILE: toolchain/testing/testdata/min_prelude/int.carbon +// EXTRA-ARGS: --clang-arg=--std=c++23 +// +// AUTOUPDATE +// TIP: To test this file alone, run: +// TIP: bazel test //toolchain/testing:file_test --test_arg=--file_tests=toolchain/check/testdata/interop/cpp/function/default_arg.carbon +// TIP: To dump output, run: +// TIP: bazel run //toolchain/testing:file_test -- --dump_output --file_tests=toolchain/check/testdata/interop/cpp/function/default_arg.carbon + +// --- functions.h + +void A(int a, int b, int c = 1, int d = 2); + +struct X { + void B(int a, int b = 1); + static void C(int a, int b = 1); + void D(this X, int a, int b = 1); +}; + +// --- call_without_default.carbon + +library "[[@TEST_NAME]]"; + +import Cpp library "functions.h"; + +fn Call() { + //@dump-sem-ir-begin + Cpp.A(1, 2, 3, 4); + ({} as Cpp.X).B(1, 2); + Cpp.X.C(1, 2); + ({} as Cpp.X).D(1, 2); + //@dump-sem-ir-end +} + +// --- call_with_default.carbon +//@include-in-dumps +library "[[@TEST_NAME]]"; + +import Cpp library "functions.h"; + +fn Call() { + // //@dump-sem-ir-begin + Cpp.A(1, 2); + Cpp.A(1, 2, 3); + ({} as Cpp.X).B(1); + Cpp.X.C(1); + ({} as Cpp.X).D(1); + // //@dump-sem-ir-end +} + +// --- fail_call_too_few_args.carbon + +library "[[@TEST_NAME]]"; + +import Cpp library "functions.h"; + +fn Call() { + //@dump-sem-ir-begin + // CHECK:STDERR: fail_call_too_few_args.carbon:[[@LINE+8]]:10: error: no matching function for call to 'A' [CppInteropParseError] + // CHECK:STDERR: 16 | Cpp.A(1); + // CHECK:STDERR: | ^ + // CHECK:STDERR: fail_call_too_few_args.carbon:[[@LINE-7]]:10: in file included here [InCppInclude] + // CHECK:STDERR: ./functions.h:2:6: note: candidate function not viable: requires at least 2 arguments, but 1 was provided [CppInteropParseNote] + // CHECK:STDERR: 2 | void A(int a, int b, int c = 1, int d = 2); + // CHECK:STDERR: | ^ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // CHECK:STDERR: + Cpp.A(1); + + // CHECK:STDERR: fail_call_too_few_args.carbon:[[@LINE+8]]:9: error: no matching function for call to 'A' [CppInteropParseError] + // CHECK:STDERR: 26 | Cpp.A(); + // CHECK:STDERR: | ^ + // CHECK:STDERR: fail_call_too_few_args.carbon:[[@LINE-17]]:10: in file included here [InCppInclude] + // CHECK:STDERR: ./functions.h:2:6: note: candidate function not viable: requires at least 2 arguments, but 0 were provided [CppInteropParseNote] + // CHECK:STDERR: 2 | void A(int a, int b, int c = 1, int d = 2); + // CHECK:STDERR: | ^ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // CHECK:STDERR: + Cpp.A(); + + // CHECK:STDERR: fail_call_too_few_args.carbon:[[@LINE+8]]:19: error: no matching function for call to 'B' [CppInteropParseError] + // CHECK:STDERR: 36 | ({} as Cpp.X).B(); + // CHECK:STDERR: | ^ + // CHECK:STDERR: fail_call_too_few_args.carbon:[[@LINE-27]]:10: in file included here [InCppInclude] + // CHECK:STDERR: ./functions.h:5:8: note: candidate function not viable: requires at least argument 'a', but no arguments were provided [CppInteropParseNote] + // CHECK:STDERR: 5 | void B(int a, int b = 1); + // CHECK:STDERR: | ^ ~~~~~~~~~~~~~~~~ + // CHECK:STDERR: + ({} as Cpp.X).B(); + + // CHECK:STDERR: fail_call_too_few_args.carbon:[[@LINE+8]]:11: error: no matching function for call to 'C' [CppInteropParseError] + // CHECK:STDERR: 46 | Cpp.X.C(); + // CHECK:STDERR: | ^ + // CHECK:STDERR: fail_call_too_few_args.carbon:[[@LINE-37]]:10: in file included here [InCppInclude] + // CHECK:STDERR: ./functions.h:6:15: note: candidate function not viable: requires at least argument 'a', but no arguments were provided [CppInteropParseNote] + // CHECK:STDERR: 6 | static void C(int a, int b = 1); + // CHECK:STDERR: | ^ ~~~~~~~~~~~~~~~~ + // CHECK:STDERR: + Cpp.X.C(); + + // CHECK:STDERR: fail_call_too_few_args.carbon:[[@LINE+8]]:19: error: no matching function for call to 'D' [CppInteropParseError] + // CHECK:STDERR: 56 | ({} as Cpp.X).D(); + // CHECK:STDERR: | ^ + // CHECK:STDERR: fail_call_too_few_args.carbon:[[@LINE-47]]:10: in file included here [InCppInclude] + // CHECK:STDERR: ./functions.h:7:8: note: candidate function not viable: requires at least non-object argument 'a', but no arguments were provided [CppInteropParseNote] + // CHECK:STDERR: 7 | void D(this X, int a, int b = 1); + // CHECK:STDERR: | ^ ~~~~~~~~~~~~~~~~~~~~~~~~ + // CHECK:STDERR: + ({} as Cpp.X).D(); + //@dump-sem-ir-end +} + +// CHECK:STDOUT: --- call_without_default.carbon +// CHECK:STDOUT: +// CHECK:STDOUT: constants { +// CHECK:STDOUT: %empty_tuple.type: type = tuple_type () [concrete] +// CHECK:STDOUT: %.490: type = cpp_overload_set_type @Int.as.ImplicitAs.impl.Convert [concrete] +// CHECK:STDOUT: %empty_struct.a89: %.490 = struct_value () [concrete] +// CHECK:STDOUT: %int_1.5b8: Core.IntLiteral = int_value 1 [concrete] +// CHECK:STDOUT: %int_2.ecc: Core.IntLiteral = int_value 2 [concrete] +// CHECK:STDOUT: %int_3.1ba: Core.IntLiteral = int_value 3 [concrete] +// CHECK:STDOUT: %int_4.0c1: Core.IntLiteral = int_value 4 [concrete] +// CHECK:STDOUT: %int_32: Core.IntLiteral = int_value 32 [concrete] +// CHECK:STDOUT: %i32: type = class_type @Int, @Int(%int_32) [concrete] +// CHECK:STDOUT: %A.type: type = fn_type @A [concrete] +// CHECK:STDOUT: %A: %A.type = struct_value () [concrete] +// CHECK:STDOUT: %ImplicitAs.type.d14: type = facet_type <@ImplicitAs, @ImplicitAs(%i32)> [concrete] +// CHECK:STDOUT: %ImplicitAs.Convert.type.1b6: type = fn_type @ImplicitAs.Convert, @ImplicitAs(%i32) [concrete] +// CHECK:STDOUT: %To: Core.IntLiteral = bind_symbolic_name To, 0 [symbolic] +// CHECK:STDOUT: %Core.IntLiteral.as.ImplicitAs.impl.Convert.type.340: type = fn_type @Core.IntLiteral.as.ImplicitAs.impl.Convert, @Core.IntLiteral.as.ImplicitAs.impl(%To) [symbolic] +// CHECK:STDOUT: %Core.IntLiteral.as.ImplicitAs.impl.Convert.1c0: %Core.IntLiteral.as.ImplicitAs.impl.Convert.type.340 = struct_value () [symbolic] +// CHECK:STDOUT: %ImplicitAs.impl_witness.204: = impl_witness imports.%ImplicitAs.impl_witness_table.9e9, @Core.IntLiteral.as.ImplicitAs.impl(%int_32) [concrete] +// CHECK:STDOUT: %Core.IntLiteral.as.ImplicitAs.impl.Convert.type.584: type = fn_type @Core.IntLiteral.as.ImplicitAs.impl.Convert, @Core.IntLiteral.as.ImplicitAs.impl(%int_32) [concrete] +// CHECK:STDOUT: %Core.IntLiteral.as.ImplicitAs.impl.Convert.0f0: %Core.IntLiteral.as.ImplicitAs.impl.Convert.type.584 = struct_value () [concrete] +// CHECK:STDOUT: %ImplicitAs.facet: %ImplicitAs.type.d14 = facet_value Core.IntLiteral, (%ImplicitAs.impl_witness.204) [concrete] +// CHECK:STDOUT: %.1df: type = fn_type_with_self_type %ImplicitAs.Convert.type.1b6, %ImplicitAs.facet [concrete] +// CHECK:STDOUT: %Core.IntLiteral.as.ImplicitAs.impl.Convert.bound.abf: = bound_method %int_1.5b8, %Core.IntLiteral.as.ImplicitAs.impl.Convert.0f0 [concrete] +// CHECK:STDOUT: %Core.IntLiteral.as.ImplicitAs.impl.Convert.specific_fn: = specific_function %Core.IntLiteral.as.ImplicitAs.impl.Convert.0f0, @Core.IntLiteral.as.ImplicitAs.impl.Convert(%int_32) [concrete] +// CHECK:STDOUT: %bound_method.c11: = bound_method %int_1.5b8, %Core.IntLiteral.as.ImplicitAs.impl.Convert.specific_fn [concrete] +// CHECK:STDOUT: %int_1.5d2: %i32 = int_value 1 [concrete] +// CHECK:STDOUT: %Core.IntLiteral.as.ImplicitAs.impl.Convert.bound.b82: = bound_method %int_2.ecc, %Core.IntLiteral.as.ImplicitAs.impl.Convert.0f0 [concrete] +// CHECK:STDOUT: %bound_method.8bd: = bound_method %int_2.ecc, %Core.IntLiteral.as.ImplicitAs.impl.Convert.specific_fn [concrete] +// CHECK:STDOUT: %int_2.ef8: %i32 = int_value 2 [concrete] +// CHECK:STDOUT: %Core.IntLiteral.as.ImplicitAs.impl.Convert.bound.595: = bound_method %int_3.1ba, %Core.IntLiteral.as.ImplicitAs.impl.Convert.0f0 [concrete] +// CHECK:STDOUT: %bound_method.f36: = bound_method %int_3.1ba, %Core.IntLiteral.as.ImplicitAs.impl.Convert.specific_fn [concrete] +// CHECK:STDOUT: %int_3.822: %i32 = int_value 3 [concrete] +// CHECK:STDOUT: %Core.IntLiteral.as.ImplicitAs.impl.Convert.bound.5bb: = bound_method %int_4.0c1, %Core.IntLiteral.as.ImplicitAs.impl.Convert.0f0 [concrete] +// CHECK:STDOUT: %bound_method.9cd: = bound_method %int_4.0c1, %Core.IntLiteral.as.ImplicitAs.impl.Convert.specific_fn [concrete] +// CHECK:STDOUT: %int_4.940: %i32 = int_value 4 [concrete] +// CHECK:STDOUT: %empty_struct_type: type = struct_type {} [concrete] +// CHECK:STDOUT: %X: type = class_type @X [concrete] +// CHECK:STDOUT: %X.val: %X = struct_value () [concrete] +// CHECK:STDOUT: %.ed9: type = cpp_overload_set_type @X.B [concrete] +// CHECK:STDOUT: %empty_struct.61d: %.ed9 = struct_value () [concrete] +// CHECK:STDOUT: %ptr.1f9: type = ptr_type %X [concrete] +// CHECK:STDOUT: %X.B.type: type = fn_type @X.B [concrete] +// CHECK:STDOUT: %X.B: %X.B.type = struct_value () [concrete] +// CHECK:STDOUT: %.ce5: type = cpp_overload_set_type @X.C [concrete] +// CHECK:STDOUT: %empty_struct.a7d: %.ce5 = struct_value () [concrete] +// CHECK:STDOUT: %X.C.type: type = fn_type @X.C [concrete] +// CHECK:STDOUT: %X.C: %X.C.type = struct_value () [concrete] +// CHECK:STDOUT: %.c13: type = cpp_overload_set_type @X.D [concrete] +// CHECK:STDOUT: %empty_struct.576: %.c13 = struct_value () [concrete] +// CHECK:STDOUT: %D__carbon_thunk.type: type = fn_type @D__carbon_thunk [concrete] +// CHECK:STDOUT: %D__carbon_thunk: %D__carbon_thunk.type = struct_value () [concrete] +// CHECK:STDOUT: %type_where: type = facet_type > [concrete] +// CHECK:STDOUT: %facet_value: %type_where = facet_value %X, () [concrete] +// CHECK:STDOUT: %AggregateT.as_type.as.Destroy.impl.Op.type.d91: type = fn_type @AggregateT.as_type.as.Destroy.impl.Op, @AggregateT.as_type.as.Destroy.impl(%facet_value) [concrete] +// CHECK:STDOUT: %AggregateT.as_type.as.Destroy.impl.Op.55b: %AggregateT.as_type.as.Destroy.impl.Op.type.d91 = struct_value () [concrete] +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: imports { +// CHECK:STDOUT: %Cpp: = namespace file.%Cpp.import_cpp, [concrete] { +// CHECK:STDOUT: .A = %.7c0 +// CHECK:STDOUT: .X = %X.decl +// CHECK:STDOUT: import Cpp//... +// CHECK:STDOUT: } +// CHECK:STDOUT: %.7c0: %.490 = cpp_overload_set_value @Int.as.ImplicitAs.impl.Convert [concrete = constants.%empty_struct.a89] +// CHECK:STDOUT: %A.decl: %A.type = fn_decl @A [concrete = constants.%A] { +// CHECK:STDOUT: +// CHECK:STDOUT: } { +// CHECK:STDOUT: +// CHECK:STDOUT: } +// CHECK:STDOUT: %Core.import_ref.ee7: @Core.IntLiteral.as.ImplicitAs.impl.%Core.IntLiteral.as.ImplicitAs.impl.Convert.type (%Core.IntLiteral.as.ImplicitAs.impl.Convert.type.340) = import_ref Core//prelude/parts/int, loc23_39, loaded [symbolic = @Core.IntLiteral.as.ImplicitAs.impl.%Core.IntLiteral.as.ImplicitAs.impl.Convert (constants.%Core.IntLiteral.as.ImplicitAs.impl.Convert.1c0)] +// CHECK:STDOUT: %ImplicitAs.impl_witness_table.9e9 = impl_witness_table (%Core.import_ref.ee7), @Core.IntLiteral.as.ImplicitAs.impl [concrete] +// CHECK:STDOUT: %X.decl: type = class_decl @X [concrete = constants.%X] {} {} +// CHECK:STDOUT: %.8ab: %.ed9 = cpp_overload_set_value @X.B [concrete = constants.%empty_struct.61d] +// CHECK:STDOUT: %X.B.decl: %X.B.type = fn_decl @X.B [concrete = constants.%X.B] { +// CHECK:STDOUT: +// CHECK:STDOUT: } { +// CHECK:STDOUT: +// CHECK:STDOUT: } +// CHECK:STDOUT: %.7af: %.ce5 = cpp_overload_set_value @X.C [concrete = constants.%empty_struct.a7d] +// CHECK:STDOUT: %X.C.decl: %X.C.type = fn_decl @X.C [concrete = constants.%X.C] { +// CHECK:STDOUT: +// CHECK:STDOUT: } { +// CHECK:STDOUT: +// CHECK:STDOUT: } +// CHECK:STDOUT: %.7b7: %.c13 = cpp_overload_set_value @X.D [concrete = constants.%empty_struct.576] +// CHECK:STDOUT: %D__carbon_thunk.decl: %D__carbon_thunk.type = fn_decl @D__carbon_thunk [concrete = constants.%D__carbon_thunk] { +// CHECK:STDOUT: +// CHECK:STDOUT: } { +// CHECK:STDOUT: +// CHECK:STDOUT: } +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: fn @Call() { +// CHECK:STDOUT: !entry: +// CHECK:STDOUT: %Cpp.ref.loc8: = name_ref Cpp, imports.%Cpp [concrete = imports.%Cpp] +// CHECK:STDOUT: %A.ref: %.490 = name_ref A, imports.%.7c0 [concrete = constants.%empty_struct.a89] +// CHECK:STDOUT: %int_1.loc8: Core.IntLiteral = int_value 1 [concrete = constants.%int_1.5b8] +// CHECK:STDOUT: %int_2.loc8: Core.IntLiteral = int_value 2 [concrete = constants.%int_2.ecc] +// CHECK:STDOUT: %int_3: Core.IntLiteral = int_value 3 [concrete = constants.%int_3.1ba] +// CHECK:STDOUT: %int_4: Core.IntLiteral = int_value 4 [concrete = constants.%int_4.0c1] +// CHECK:STDOUT: %impl.elem0.loc8_9: %.1df = impl_witness_access constants.%ImplicitAs.impl_witness.204, element0 [concrete = constants.%Core.IntLiteral.as.ImplicitAs.impl.Convert.0f0] +// CHECK:STDOUT: %bound_method.loc8_9.1: = bound_method %int_1.loc8, %impl.elem0.loc8_9 [concrete = constants.%Core.IntLiteral.as.ImplicitAs.impl.Convert.bound.abf] +// CHECK:STDOUT: %specific_fn.loc8_9: = specific_function %impl.elem0.loc8_9, @Core.IntLiteral.as.ImplicitAs.impl.Convert(constants.%int_32) [concrete = constants.%Core.IntLiteral.as.ImplicitAs.impl.Convert.specific_fn] +// CHECK:STDOUT: %bound_method.loc8_9.2: = bound_method %int_1.loc8, %specific_fn.loc8_9 [concrete = constants.%bound_method.c11] +// CHECK:STDOUT: %Core.IntLiteral.as.ImplicitAs.impl.Convert.call.loc8_9: init %i32 = call %bound_method.loc8_9.2(%int_1.loc8) [concrete = constants.%int_1.5d2] +// CHECK:STDOUT: %.loc8_9.1: %i32 = value_of_initializer %Core.IntLiteral.as.ImplicitAs.impl.Convert.call.loc8_9 [concrete = constants.%int_1.5d2] +// CHECK:STDOUT: %.loc8_9.2: %i32 = converted %int_1.loc8, %.loc8_9.1 [concrete = constants.%int_1.5d2] +// CHECK:STDOUT: %impl.elem0.loc8_12: %.1df = impl_witness_access constants.%ImplicitAs.impl_witness.204, element0 [concrete = constants.%Core.IntLiteral.as.ImplicitAs.impl.Convert.0f0] +// CHECK:STDOUT: %bound_method.loc8_12.1: = bound_method %int_2.loc8, %impl.elem0.loc8_12 [concrete = constants.%Core.IntLiteral.as.ImplicitAs.impl.Convert.bound.b82] +// CHECK:STDOUT: %specific_fn.loc8_12: = specific_function %impl.elem0.loc8_12, @Core.IntLiteral.as.ImplicitAs.impl.Convert(constants.%int_32) [concrete = constants.%Core.IntLiteral.as.ImplicitAs.impl.Convert.specific_fn] +// CHECK:STDOUT: %bound_method.loc8_12.2: = bound_method %int_2.loc8, %specific_fn.loc8_12 [concrete = constants.%bound_method.8bd] +// CHECK:STDOUT: %Core.IntLiteral.as.ImplicitAs.impl.Convert.call.loc8_12: init %i32 = call %bound_method.loc8_12.2(%int_2.loc8) [concrete = constants.%int_2.ef8] +// CHECK:STDOUT: %.loc8_12.1: %i32 = value_of_initializer %Core.IntLiteral.as.ImplicitAs.impl.Convert.call.loc8_12 [concrete = constants.%int_2.ef8] +// CHECK:STDOUT: %.loc8_12.2: %i32 = converted %int_2.loc8, %.loc8_12.1 [concrete = constants.%int_2.ef8] +// CHECK:STDOUT: %impl.elem0.loc8_15: %.1df = impl_witness_access constants.%ImplicitAs.impl_witness.204, element0 [concrete = constants.%Core.IntLiteral.as.ImplicitAs.impl.Convert.0f0] +// CHECK:STDOUT: %bound_method.loc8_15.1: = bound_method %int_3, %impl.elem0.loc8_15 [concrete = constants.%Core.IntLiteral.as.ImplicitAs.impl.Convert.bound.595] +// CHECK:STDOUT: %specific_fn.loc8_15: = specific_function %impl.elem0.loc8_15, @Core.IntLiteral.as.ImplicitAs.impl.Convert(constants.%int_32) [concrete = constants.%Core.IntLiteral.as.ImplicitAs.impl.Convert.specific_fn] +// CHECK:STDOUT: %bound_method.loc8_15.2: = bound_method %int_3, %specific_fn.loc8_15 [concrete = constants.%bound_method.f36] +// CHECK:STDOUT: %Core.IntLiteral.as.ImplicitAs.impl.Convert.call.loc8_15: init %i32 = call %bound_method.loc8_15.2(%int_3) [concrete = constants.%int_3.822] +// CHECK:STDOUT: %.loc8_15.1: %i32 = value_of_initializer %Core.IntLiteral.as.ImplicitAs.impl.Convert.call.loc8_15 [concrete = constants.%int_3.822] +// CHECK:STDOUT: %.loc8_15.2: %i32 = converted %int_3, %.loc8_15.1 [concrete = constants.%int_3.822] +// CHECK:STDOUT: %impl.elem0.loc8_18: %.1df = impl_witness_access constants.%ImplicitAs.impl_witness.204, element0 [concrete = constants.%Core.IntLiteral.as.ImplicitAs.impl.Convert.0f0] +// CHECK:STDOUT: %bound_method.loc8_18.1: = bound_method %int_4, %impl.elem0.loc8_18 [concrete = constants.%Core.IntLiteral.as.ImplicitAs.impl.Convert.bound.5bb] +// CHECK:STDOUT: %specific_fn.loc8_18: = specific_function %impl.elem0.loc8_18, @Core.IntLiteral.as.ImplicitAs.impl.Convert(constants.%int_32) [concrete = constants.%Core.IntLiteral.as.ImplicitAs.impl.Convert.specific_fn] +// CHECK:STDOUT: %bound_method.loc8_18.2: = bound_method %int_4, %specific_fn.loc8_18 [concrete = constants.%bound_method.9cd] +// CHECK:STDOUT: %Core.IntLiteral.as.ImplicitAs.impl.Convert.call.loc8_18: init %i32 = call %bound_method.loc8_18.2(%int_4) [concrete = constants.%int_4.940] +// CHECK:STDOUT: %.loc8_18.1: %i32 = value_of_initializer %Core.IntLiteral.as.ImplicitAs.impl.Convert.call.loc8_18 [concrete = constants.%int_4.940] +// CHECK:STDOUT: %.loc8_18.2: %i32 = converted %int_4, %.loc8_18.1 [concrete = constants.%int_4.940] +// CHECK:STDOUT: %A.call: init %empty_tuple.type = call imports.%A.decl(%.loc8_9.2, %.loc8_12.2, %.loc8_15.2, %.loc8_18.2) +// CHECK:STDOUT: %.loc9_5.1: %empty_struct_type = struct_literal () +// CHECK:STDOUT: %Cpp.ref.loc9: = name_ref Cpp, imports.%Cpp [concrete = imports.%Cpp] +// CHECK:STDOUT: %X.ref.loc9: type = name_ref X, imports.%X.decl [concrete = constants.%X] +// CHECK:STDOUT: %.loc9_5.2: ref %X = temporary_storage +// CHECK:STDOUT: %.loc9_5.3: init %X = class_init (), %.loc9_5.2 [concrete = constants.%X.val] +// CHECK:STDOUT: %.loc9_5.4: ref %X = temporary %.loc9_5.2, %.loc9_5.3 +// CHECK:STDOUT: %.loc9_7: ref %X = converted %.loc9_5.1, %.loc9_5.4 +// CHECK:STDOUT: %B.ref: %.ed9 = name_ref B, imports.%.8ab [concrete = constants.%empty_struct.61d] +// CHECK:STDOUT: %bound_method.loc9_16: = bound_method %.loc9_7, %B.ref +// CHECK:STDOUT: %int_1.loc9: Core.IntLiteral = int_value 1 [concrete = constants.%int_1.5b8] +// CHECK:STDOUT: %int_2.loc9: Core.IntLiteral = int_value 2 [concrete = constants.%int_2.ecc] +// CHECK:STDOUT: %addr.loc9_7: %ptr.1f9 = addr_of %.loc9_7 +// CHECK:STDOUT: %impl.elem0.loc9_19: %.1df = impl_witness_access constants.%ImplicitAs.impl_witness.204, element0 [concrete = constants.%Core.IntLiteral.as.ImplicitAs.impl.Convert.0f0] +// CHECK:STDOUT: %bound_method.loc9_19.1: = bound_method %int_1.loc9, %impl.elem0.loc9_19 [concrete = constants.%Core.IntLiteral.as.ImplicitAs.impl.Convert.bound.abf] +// CHECK:STDOUT: %specific_fn.loc9_19: = specific_function %impl.elem0.loc9_19, @Core.IntLiteral.as.ImplicitAs.impl.Convert(constants.%int_32) [concrete = constants.%Core.IntLiteral.as.ImplicitAs.impl.Convert.specific_fn] +// CHECK:STDOUT: %bound_method.loc9_19.2: = bound_method %int_1.loc9, %specific_fn.loc9_19 [concrete = constants.%bound_method.c11] +// CHECK:STDOUT: %Core.IntLiteral.as.ImplicitAs.impl.Convert.call.loc9_19: init %i32 = call %bound_method.loc9_19.2(%int_1.loc9) [concrete = constants.%int_1.5d2] +// CHECK:STDOUT: %.loc9_19.1: %i32 = value_of_initializer %Core.IntLiteral.as.ImplicitAs.impl.Convert.call.loc9_19 [concrete = constants.%int_1.5d2] +// CHECK:STDOUT: %.loc9_19.2: %i32 = converted %int_1.loc9, %.loc9_19.1 [concrete = constants.%int_1.5d2] +// CHECK:STDOUT: %impl.elem0.loc9_22: %.1df = impl_witness_access constants.%ImplicitAs.impl_witness.204, element0 [concrete = constants.%Core.IntLiteral.as.ImplicitAs.impl.Convert.0f0] +// CHECK:STDOUT: %bound_method.loc9_22.1: = bound_method %int_2.loc9, %impl.elem0.loc9_22 [concrete = constants.%Core.IntLiteral.as.ImplicitAs.impl.Convert.bound.b82] +// CHECK:STDOUT: %specific_fn.loc9_22: = specific_function %impl.elem0.loc9_22, @Core.IntLiteral.as.ImplicitAs.impl.Convert(constants.%int_32) [concrete = constants.%Core.IntLiteral.as.ImplicitAs.impl.Convert.specific_fn] +// CHECK:STDOUT: %bound_method.loc9_22.2: = bound_method %int_2.loc9, %specific_fn.loc9_22 [concrete = constants.%bound_method.8bd] +// CHECK:STDOUT: %Core.IntLiteral.as.ImplicitAs.impl.Convert.call.loc9_22: init %i32 = call %bound_method.loc9_22.2(%int_2.loc9) [concrete = constants.%int_2.ef8] +// CHECK:STDOUT: %.loc9_22.1: %i32 = value_of_initializer %Core.IntLiteral.as.ImplicitAs.impl.Convert.call.loc9_22 [concrete = constants.%int_2.ef8] +// CHECK:STDOUT: %.loc9_22.2: %i32 = converted %int_2.loc9, %.loc9_22.1 [concrete = constants.%int_2.ef8] +// CHECK:STDOUT: %X.B.call: init %empty_tuple.type = call imports.%X.B.decl(%addr.loc9_7, %.loc9_19.2, %.loc9_22.2) +// CHECK:STDOUT: %Cpp.ref.loc10: = name_ref Cpp, imports.%Cpp [concrete = imports.%Cpp] +// CHECK:STDOUT: %X.ref.loc10: type = name_ref X, imports.%X.decl [concrete = constants.%X] +// CHECK:STDOUT: %C.ref: %.ce5 = name_ref C, imports.%.7af [concrete = constants.%empty_struct.a7d] +// CHECK:STDOUT: %int_1.loc10: Core.IntLiteral = int_value 1 [concrete = constants.%int_1.5b8] +// CHECK:STDOUT: %int_2.loc10: Core.IntLiteral = int_value 2 [concrete = constants.%int_2.ecc] +// CHECK:STDOUT: %impl.elem0.loc10_11: %.1df = impl_witness_access constants.%ImplicitAs.impl_witness.204, element0 [concrete = constants.%Core.IntLiteral.as.ImplicitAs.impl.Convert.0f0] +// CHECK:STDOUT: %bound_method.loc10_11.1: = bound_method %int_1.loc10, %impl.elem0.loc10_11 [concrete = constants.%Core.IntLiteral.as.ImplicitAs.impl.Convert.bound.abf] +// CHECK:STDOUT: %specific_fn.loc10_11: = specific_function %impl.elem0.loc10_11, @Core.IntLiteral.as.ImplicitAs.impl.Convert(constants.%int_32) [concrete = constants.%Core.IntLiteral.as.ImplicitAs.impl.Convert.specific_fn] +// CHECK:STDOUT: %bound_method.loc10_11.2: = bound_method %int_1.loc10, %specific_fn.loc10_11 [concrete = constants.%bound_method.c11] +// CHECK:STDOUT: %Core.IntLiteral.as.ImplicitAs.impl.Convert.call.loc10_11: init %i32 = call %bound_method.loc10_11.2(%int_1.loc10) [concrete = constants.%int_1.5d2] +// CHECK:STDOUT: %.loc10_11.1: %i32 = value_of_initializer %Core.IntLiteral.as.ImplicitAs.impl.Convert.call.loc10_11 [concrete = constants.%int_1.5d2] +// CHECK:STDOUT: %.loc10_11.2: %i32 = converted %int_1.loc10, %.loc10_11.1 [concrete = constants.%int_1.5d2] +// CHECK:STDOUT: %impl.elem0.loc10_14: %.1df = impl_witness_access constants.%ImplicitAs.impl_witness.204, element0 [concrete = constants.%Core.IntLiteral.as.ImplicitAs.impl.Convert.0f0] +// CHECK:STDOUT: %bound_method.loc10_14.1: = bound_method %int_2.loc10, %impl.elem0.loc10_14 [concrete = constants.%Core.IntLiteral.as.ImplicitAs.impl.Convert.bound.b82] +// CHECK:STDOUT: %specific_fn.loc10_14: = specific_function %impl.elem0.loc10_14, @Core.IntLiteral.as.ImplicitAs.impl.Convert(constants.%int_32) [concrete = constants.%Core.IntLiteral.as.ImplicitAs.impl.Convert.specific_fn] +// CHECK:STDOUT: %bound_method.loc10_14.2: = bound_method %int_2.loc10, %specific_fn.loc10_14 [concrete = constants.%bound_method.8bd] +// CHECK:STDOUT: %Core.IntLiteral.as.ImplicitAs.impl.Convert.call.loc10_14: init %i32 = call %bound_method.loc10_14.2(%int_2.loc10) [concrete = constants.%int_2.ef8] +// CHECK:STDOUT: %.loc10_14.1: %i32 = value_of_initializer %Core.IntLiteral.as.ImplicitAs.impl.Convert.call.loc10_14 [concrete = constants.%int_2.ef8] +// CHECK:STDOUT: %.loc10_14.2: %i32 = converted %int_2.loc10, %.loc10_14.1 [concrete = constants.%int_2.ef8] +// CHECK:STDOUT: %X.C.call: init %empty_tuple.type = call imports.%X.C.decl(%.loc10_11.2, %.loc10_14.2) +// CHECK:STDOUT: %.loc11_5.1: %empty_struct_type = struct_literal () +// CHECK:STDOUT: %Cpp.ref.loc11: = name_ref Cpp, imports.%Cpp [concrete = imports.%Cpp] +// CHECK:STDOUT: %X.ref.loc11: type = name_ref X, imports.%X.decl [concrete = constants.%X] +// CHECK:STDOUT: %.loc11_5.2: ref %X = temporary_storage +// CHECK:STDOUT: %.loc11_5.3: init %X = class_init (), %.loc11_5.2 [concrete = constants.%X.val] +// CHECK:STDOUT: %.loc11_5.4: ref %X = temporary %.loc11_5.2, %.loc11_5.3 +// CHECK:STDOUT: %.loc11_7.1: ref %X = converted %.loc11_5.1, %.loc11_5.4 +// CHECK:STDOUT: %D.ref: %.c13 = name_ref D, imports.%.7b7 [concrete = constants.%empty_struct.576] +// CHECK:STDOUT: %bound_method.loc11_16: = bound_method %.loc11_7.1, %D.ref +// CHECK:STDOUT: %int_1.loc11: Core.IntLiteral = int_value 1 [concrete = constants.%int_1.5b8] +// CHECK:STDOUT: %int_2.loc11: Core.IntLiteral = int_value 2 [concrete = constants.%int_2.ecc] +// CHECK:STDOUT: %.loc11_7.2: %X = bind_value %.loc11_7.1 +// CHECK:STDOUT: %impl.elem0.loc11_19: %.1df = impl_witness_access constants.%ImplicitAs.impl_witness.204, element0 [concrete = constants.%Core.IntLiteral.as.ImplicitAs.impl.Convert.0f0] +// CHECK:STDOUT: %bound_method.loc11_19.1: = bound_method %int_1.loc11, %impl.elem0.loc11_19 [concrete = constants.%Core.IntLiteral.as.ImplicitAs.impl.Convert.bound.abf] +// CHECK:STDOUT: %specific_fn.loc11_19: = specific_function %impl.elem0.loc11_19, @Core.IntLiteral.as.ImplicitAs.impl.Convert(constants.%int_32) [concrete = constants.%Core.IntLiteral.as.ImplicitAs.impl.Convert.specific_fn] +// CHECK:STDOUT: %bound_method.loc11_19.2: = bound_method %int_1.loc11, %specific_fn.loc11_19 [concrete = constants.%bound_method.c11] +// CHECK:STDOUT: %Core.IntLiteral.as.ImplicitAs.impl.Convert.call.loc11_19: init %i32 = call %bound_method.loc11_19.2(%int_1.loc11) [concrete = constants.%int_1.5d2] +// CHECK:STDOUT: %.loc11_19.1: %i32 = value_of_initializer %Core.IntLiteral.as.ImplicitAs.impl.Convert.call.loc11_19 [concrete = constants.%int_1.5d2] +// CHECK:STDOUT: %.loc11_19.2: %i32 = converted %int_1.loc11, %.loc11_19.1 [concrete = constants.%int_1.5d2] +// CHECK:STDOUT: %impl.elem0.loc11_22: %.1df = impl_witness_access constants.%ImplicitAs.impl_witness.204, element0 [concrete = constants.%Core.IntLiteral.as.ImplicitAs.impl.Convert.0f0] +// CHECK:STDOUT: %bound_method.loc11_22.1: = bound_method %int_2.loc11, %impl.elem0.loc11_22 [concrete = constants.%Core.IntLiteral.as.ImplicitAs.impl.Convert.bound.b82] +// CHECK:STDOUT: %specific_fn.loc11_22: = specific_function %impl.elem0.loc11_22, @Core.IntLiteral.as.ImplicitAs.impl.Convert(constants.%int_32) [concrete = constants.%Core.IntLiteral.as.ImplicitAs.impl.Convert.specific_fn] +// CHECK:STDOUT: %bound_method.loc11_22.2: = bound_method %int_2.loc11, %specific_fn.loc11_22 [concrete = constants.%bound_method.8bd] +// CHECK:STDOUT: %Core.IntLiteral.as.ImplicitAs.impl.Convert.call.loc11_22: init %i32 = call %bound_method.loc11_22.2(%int_2.loc11) [concrete = constants.%int_2.ef8] +// CHECK:STDOUT: %.loc11_22.1: %i32 = value_of_initializer %Core.IntLiteral.as.ImplicitAs.impl.Convert.call.loc11_22 [concrete = constants.%int_2.ef8] +// CHECK:STDOUT: %.loc11_22.2: %i32 = converted %int_2.loc11, %.loc11_22.1 [concrete = constants.%int_2.ef8] +// CHECK:STDOUT: %.loc11_7.3: ref %X = value_as_ref %.loc11_7.2 +// CHECK:STDOUT: %addr.loc11_23: %ptr.1f9 = addr_of %.loc11_7.3 +// CHECK:STDOUT: %D__carbon_thunk.call: init %empty_tuple.type = call imports.%D__carbon_thunk.decl(%addr.loc11_23, %.loc11_19.2, %.loc11_22.2) +// CHECK:STDOUT: %facet_value.loc11: %type_where = facet_value constants.%X, () [concrete = constants.%facet_value] +// CHECK:STDOUT: %.loc11_5.5: %type_where = converted constants.%X, %facet_value.loc11 [concrete = constants.%facet_value] +// CHECK:STDOUT: %AggregateT.as_type.as.Destroy.impl.Op.bound.loc11: = bound_method %.loc11_5.4, constants.%AggregateT.as_type.as.Destroy.impl.Op.55b +// CHECK:STDOUT: +// CHECK:STDOUT: %bound_method.loc11_5: = bound_method %.loc11_5.4, %AggregateT.as_type.as.Destroy.impl.Op.specific_fn.1 +// CHECK:STDOUT: %addr.loc11_5: %ptr.1f9 = addr_of %.loc11_5.4 +// CHECK:STDOUT: %AggregateT.as_type.as.Destroy.impl.Op.call.loc11: init %empty_tuple.type = call %bound_method.loc11_5(%addr.loc11_5) +// CHECK:STDOUT: %facet_value.loc9: %type_where = facet_value constants.%X, () [concrete = constants.%facet_value] +// CHECK:STDOUT: %.loc9_5.5: %type_where = converted constants.%X, %facet_value.loc9 [concrete = constants.%facet_value] +// CHECK:STDOUT: %AggregateT.as_type.as.Destroy.impl.Op.bound.loc9: = bound_method %.loc9_5.4, constants.%AggregateT.as_type.as.Destroy.impl.Op.55b +// CHECK:STDOUT: +// CHECK:STDOUT: %bound_method.loc9_5: = bound_method %.loc9_5.4, %AggregateT.as_type.as.Destroy.impl.Op.specific_fn.2 +// CHECK:STDOUT: %addr.loc9_5: %ptr.1f9 = addr_of %.loc9_5.4 +// CHECK:STDOUT: %AggregateT.as_type.as.Destroy.impl.Op.call.loc9: init %empty_tuple.type = call %bound_method.loc9_5(%addr.loc9_5) +// CHECK:STDOUT: +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: --- call_with_default.carbon +// CHECK:STDOUT: +// CHECK:STDOUT: constants { +// CHECK:STDOUT: %Call.type: type = fn_type @Call [concrete] +// CHECK:STDOUT: %empty_tuple.type: type = tuple_type () [concrete] +// CHECK:STDOUT: %Call: %Call.type = struct_value () [concrete] +// CHECK:STDOUT: %.490: type = cpp_overload_set_type @Core.IntLiteral.as.ImplicitAs.impl.Convert [concrete] +// CHECK:STDOUT: %empty_struct.a89: %.490 = struct_value () [concrete] +// CHECK:STDOUT: %int_1.5b8: Core.IntLiteral = int_value 1 [concrete] +// CHECK:STDOUT: %int_2.ecc: Core.IntLiteral = int_value 2 [concrete] +// CHECK:STDOUT: %int_32: Core.IntLiteral = int_value 32 [concrete] +// CHECK:STDOUT: %Int.type: type = generic_class_type @Int [concrete] +// CHECK:STDOUT: %Int.generic: %Int.type = struct_value () [concrete] +// CHECK:STDOUT: %i32: type = class_type @Int, @Int(%int_32) [concrete] +// CHECK:STDOUT: %pattern_type.7ce: type = pattern_type %i32 [concrete] +// CHECK:STDOUT: %A__carbon_thunk.type.f1e093.1: type = fn_type @A__carbon_thunk.1 [concrete] +// CHECK:STDOUT: %A__carbon_thunk.8f654e.1: %A__carbon_thunk.type.f1e093.1 = struct_value () [concrete] +// CHECK:STDOUT: %ImplicitAs.type.cc7: type = generic_interface_type @ImplicitAs [concrete] +// CHECK:STDOUT: %ImplicitAs.generic: %ImplicitAs.type.cc7 = struct_value () [concrete] +// CHECK:STDOUT: %ImplicitAs.type.d14: type = facet_type <@ImplicitAs, @ImplicitAs(%i32)> [concrete] +// CHECK:STDOUT: %ImplicitAs.Convert.type.1b6: type = fn_type @ImplicitAs.Convert, @ImplicitAs(%i32) [concrete] +// CHECK:STDOUT: %To: Core.IntLiteral = bind_symbolic_name To, 0 [symbolic] +// CHECK:STDOUT: %Core.IntLiteral.as.ImplicitAs.impl.Convert.type.340: type = fn_type @Core.IntLiteral.as.ImplicitAs.impl.Convert, @Core.IntLiteral.as.ImplicitAs.impl(%To) [symbolic] +// CHECK:STDOUT: %Core.IntLiteral.as.ImplicitAs.impl.Convert.1c0: %Core.IntLiteral.as.ImplicitAs.impl.Convert.type.340 = struct_value () [symbolic] +// CHECK:STDOUT: %ImplicitAs.impl_witness.204: = impl_witness imports.%ImplicitAs.impl_witness_table.9e9, @Core.IntLiteral.as.ImplicitAs.impl(%int_32) [concrete] +// CHECK:STDOUT: %Core.IntLiteral.as.ImplicitAs.impl.Convert.type.584: type = fn_type @Core.IntLiteral.as.ImplicitAs.impl.Convert, @Core.IntLiteral.as.ImplicitAs.impl(%int_32) [concrete] +// CHECK:STDOUT: %Core.IntLiteral.as.ImplicitAs.impl.Convert.0f0: %Core.IntLiteral.as.ImplicitAs.impl.Convert.type.584 = struct_value () [concrete] +// CHECK:STDOUT: %ImplicitAs.facet: %ImplicitAs.type.d14 = facet_value Core.IntLiteral, (%ImplicitAs.impl_witness.204) [concrete] +// CHECK:STDOUT: %.1df: type = fn_type_with_self_type %ImplicitAs.Convert.type.1b6, %ImplicitAs.facet [concrete] +// CHECK:STDOUT: %Core.IntLiteral.as.ImplicitAs.impl.Convert.bound.abf: = bound_method %int_1.5b8, %Core.IntLiteral.as.ImplicitAs.impl.Convert.0f0 [concrete] +// CHECK:STDOUT: %Core.IntLiteral.as.ImplicitAs.impl.Convert.specific_fn: = specific_function %Core.IntLiteral.as.ImplicitAs.impl.Convert.0f0, @Core.IntLiteral.as.ImplicitAs.impl.Convert(%int_32) [concrete] +// CHECK:STDOUT: %bound_method.c11: = bound_method %int_1.5b8, %Core.IntLiteral.as.ImplicitAs.impl.Convert.specific_fn [concrete] +// CHECK:STDOUT: %int_1.5d2: %i32 = int_value 1 [concrete] +// CHECK:STDOUT: %Core.IntLiteral.as.ImplicitAs.impl.Convert.bound.b82: = bound_method %int_2.ecc, %Core.IntLiteral.as.ImplicitAs.impl.Convert.0f0 [concrete] +// CHECK:STDOUT: %bound_method.8bd: = bound_method %int_2.ecc, %Core.IntLiteral.as.ImplicitAs.impl.Convert.specific_fn [concrete] +// CHECK:STDOUT: %int_2.ef8: %i32 = int_value 2 [concrete] +// CHECK:STDOUT: %int_3.1ba: Core.IntLiteral = int_value 3 [concrete] +// CHECK:STDOUT: %A__carbon_thunk.type.f1e093.2: type = fn_type @A__carbon_thunk.2 [concrete] +// CHECK:STDOUT: %A__carbon_thunk.8f654e.2: %A__carbon_thunk.type.f1e093.2 = struct_value () [concrete] +// CHECK:STDOUT: %Core.IntLiteral.as.ImplicitAs.impl.Convert.bound.595: = bound_method %int_3.1ba, %Core.IntLiteral.as.ImplicitAs.impl.Convert.0f0 [concrete] +// CHECK:STDOUT: %bound_method.f36: = bound_method %int_3.1ba, %Core.IntLiteral.as.ImplicitAs.impl.Convert.specific_fn [concrete] +// CHECK:STDOUT: %int_3.822: %i32 = int_value 3 [concrete] +// CHECK:STDOUT: %empty_struct_type: type = struct_type {} [concrete] +// CHECK:STDOUT: %X: type = class_type @X [concrete] +// CHECK:STDOUT: %complete_type.357: = complete_type_witness %empty_struct_type [concrete] +// CHECK:STDOUT: %X.val: %X = struct_value () [concrete] +// CHECK:STDOUT: %.ed9: type = cpp_overload_set_type @Int.as.ImplicitAs.impl.Convert [concrete] +// CHECK:STDOUT: %empty_struct.61d: %.ed9 = struct_value () [concrete] +// CHECK:STDOUT: %ptr.1f9: type = ptr_type %X [concrete] +// CHECK:STDOUT: %pattern_type.45c: type = pattern_type %ptr.1f9 [concrete] +// CHECK:STDOUT: %B__carbon_thunk.type: type = fn_type @B__carbon_thunk [concrete] +// CHECK:STDOUT: %B__carbon_thunk: %B__carbon_thunk.type = struct_value () [concrete] +// CHECK:STDOUT: %.ce5: type = cpp_overload_set_type @A.2 [concrete] +// CHECK:STDOUT: %empty_struct.a7d: %.ce5 = struct_value () [concrete] +// CHECK:STDOUT: %C__carbon_thunk.type: type = fn_type @C__carbon_thunk [concrete] +// CHECK:STDOUT: %C__carbon_thunk: %C__carbon_thunk.type = struct_value () [concrete] +// CHECK:STDOUT: %.c13: type = cpp_overload_set_type @A__carbon_thunk.2 [concrete] +// CHECK:STDOUT: %empty_struct.576: %.c13 = struct_value () [concrete] +// CHECK:STDOUT: %D__carbon_thunk.type: type = fn_type @D__carbon_thunk [concrete] +// CHECK:STDOUT: %D__carbon_thunk: %D__carbon_thunk.type = struct_value () [concrete] +// CHECK:STDOUT: %Destroy.type: type = facet_type <@Destroy> [concrete] +// CHECK:STDOUT: %type_where: type = facet_type > [concrete] +// CHECK:STDOUT: %facet_value: %type_where = facet_value %X, () [concrete] +// CHECK:STDOUT: %AggregateT.as_type.as.Destroy.impl.Op.type.d91: type = fn_type @AggregateT.as_type.as.Destroy.impl.Op, @AggregateT.as_type.as.Destroy.impl(%facet_value) [concrete] +// CHECK:STDOUT: %AggregateT.as_type.as.Destroy.impl.Op.55b: %AggregateT.as_type.as.Destroy.impl.Op.type.d91 = struct_value () [concrete] +// CHECK:STDOUT: %AggregateT.as_type.as.Destroy.impl.Op.specific_fn: = specific_function %AggregateT.as_type.as.Destroy.impl.Op.55b, @AggregateT.as_type.as.Destroy.impl.Op(%facet_value) [concrete] +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: imports { +// CHECK:STDOUT: %Core: = namespace file.%Core.import, [concrete] { +// CHECK:STDOUT: .Int = %Core.Int +// CHECK:STDOUT: .ImplicitAs = %Core.ImplicitAs +// CHECK:STDOUT: .Destroy = %Core.Destroy +// CHECK:STDOUT: import Core//prelude +// CHECK:STDOUT: import Core//prelude/... +// CHECK:STDOUT: } +// CHECK:STDOUT: %Cpp: = namespace file.%Cpp.import_cpp, [concrete] { +// CHECK:STDOUT: .A = %.7c0 +// CHECK:STDOUT: .X = %X.decl +// CHECK:STDOUT: import Cpp//... +// CHECK:STDOUT: } +// CHECK:STDOUT: %.7c0: %.490 = cpp_overload_set_value @Core.IntLiteral.as.ImplicitAs.impl.Convert [concrete = constants.%empty_struct.a89] +// CHECK:STDOUT: %Core.Int: %Int.type = import_ref Core//prelude/parts/int, Int, loaded [concrete = constants.%Int.generic] +// CHECK:STDOUT: %A__carbon_thunk.decl.713db8.1: %A__carbon_thunk.type.f1e093.1 = fn_decl @A__carbon_thunk.1 [concrete = constants.%A__carbon_thunk.8f654e.1] { +// CHECK:STDOUT: %a.patt: %pattern_type.7ce = binding_pattern a [concrete] +// CHECK:STDOUT: %a.param_patt: %pattern_type.7ce = value_param_pattern %a.patt, call_param0 [concrete] +// CHECK:STDOUT: %b.patt: %pattern_type.7ce = binding_pattern b [concrete] +// CHECK:STDOUT: %b.param_patt: %pattern_type.7ce = value_param_pattern %b.patt, call_param1 [concrete] +// CHECK:STDOUT: } { +// CHECK:STDOUT: %a.param: %i32 = value_param call_param0 +// CHECK:STDOUT: %.1: type = splice_block %i32.2 [concrete = constants.%i32] { +// CHECK:STDOUT: %int_32.2: Core.IntLiteral = int_value 32 [concrete = constants.%int_32] +// CHECK:STDOUT: %i32.2: type = class_type @Int, @Int(constants.%int_32) [concrete = constants.%i32] +// CHECK:STDOUT: } +// CHECK:STDOUT: %a: %i32 = bind_name a, %a.param +// CHECK:STDOUT: %b.param: %i32 = value_param call_param1 +// CHECK:STDOUT: %.2: type = splice_block %i32.1 [concrete = constants.%i32] { +// CHECK:STDOUT: %int_32.1: Core.IntLiteral = int_value 32 [concrete = constants.%int_32] +// CHECK:STDOUT: %i32.1: type = class_type @Int, @Int(constants.%int_32) [concrete = constants.%i32] +// CHECK:STDOUT: } +// CHECK:STDOUT: %b: %i32 = bind_name b, %b.param +// CHECK:STDOUT: } +// CHECK:STDOUT: %Core.ImplicitAs: %ImplicitAs.type.cc7 = import_ref Core//prelude/parts/as, ImplicitAs, loaded [concrete = constants.%ImplicitAs.generic] +// CHECK:STDOUT: %Core.import_ref.ee7: @Core.IntLiteral.as.ImplicitAs.impl.%Core.IntLiteral.as.ImplicitAs.impl.Convert.type (%Core.IntLiteral.as.ImplicitAs.impl.Convert.type.340) = import_ref Core//prelude/parts/int, loc23_39, loaded [symbolic = @Core.IntLiteral.as.ImplicitAs.impl.%Core.IntLiteral.as.ImplicitAs.impl.Convert (constants.%Core.IntLiteral.as.ImplicitAs.impl.Convert.1c0)] +// CHECK:STDOUT: %ImplicitAs.impl_witness_table.9e9 = impl_witness_table (%Core.import_ref.ee7), @Core.IntLiteral.as.ImplicitAs.impl [concrete] +// CHECK:STDOUT: %A__carbon_thunk.decl.713db8.2: %A__carbon_thunk.type.f1e093.2 = fn_decl @A__carbon_thunk.2 [concrete = constants.%A__carbon_thunk.8f654e.2] { +// CHECK:STDOUT: %a.patt: %pattern_type.7ce = binding_pattern a [concrete] +// CHECK:STDOUT: %a.param_patt: %pattern_type.7ce = value_param_pattern %a.patt, call_param0 [concrete] +// CHECK:STDOUT: %b.patt: %pattern_type.7ce = binding_pattern b [concrete] +// CHECK:STDOUT: %b.param_patt: %pattern_type.7ce = value_param_pattern %b.patt, call_param1 [concrete] +// CHECK:STDOUT: %c.patt: %pattern_type.7ce = binding_pattern c [concrete] +// CHECK:STDOUT: %c.param_patt: %pattern_type.7ce = value_param_pattern %c.patt, call_param2 [concrete] +// CHECK:STDOUT: } { +// CHECK:STDOUT: %a.param: %i32 = value_param call_param0 +// CHECK:STDOUT: %.1: type = splice_block %i32.3 [concrete = constants.%i32] { +// CHECK:STDOUT: %int_32.3: Core.IntLiteral = int_value 32 [concrete = constants.%int_32] +// CHECK:STDOUT: %i32.3: type = class_type @Int, @Int(constants.%int_32) [concrete = constants.%i32] +// CHECK:STDOUT: } +// CHECK:STDOUT: %a: %i32 = bind_name a, %a.param +// CHECK:STDOUT: %b.param: %i32 = value_param call_param1 +// CHECK:STDOUT: %.2: type = splice_block %i32.2 [concrete = constants.%i32] { +// CHECK:STDOUT: %int_32.2: Core.IntLiteral = int_value 32 [concrete = constants.%int_32] +// CHECK:STDOUT: %i32.2: type = class_type @Int, @Int(constants.%int_32) [concrete = constants.%i32] +// CHECK:STDOUT: } +// CHECK:STDOUT: %b: %i32 = bind_name b, %b.param +// CHECK:STDOUT: %c.param: %i32 = value_param call_param2 +// CHECK:STDOUT: %.3: type = splice_block %i32.1 [concrete = constants.%i32] { +// CHECK:STDOUT: %int_32.1: Core.IntLiteral = int_value 32 [concrete = constants.%int_32] +// CHECK:STDOUT: %i32.1: type = class_type @Int, @Int(constants.%int_32) [concrete = constants.%i32] +// CHECK:STDOUT: } +// CHECK:STDOUT: %c: %i32 = bind_name c, %c.param +// CHECK:STDOUT: } +// CHECK:STDOUT: %X.decl: type = class_decl @X [concrete = constants.%X] {} {} +// CHECK:STDOUT: %.8ab: %.ed9 = cpp_overload_set_value @Int.as.ImplicitAs.impl.Convert [concrete = constants.%empty_struct.61d] +// CHECK:STDOUT: %B__carbon_thunk.decl: %B__carbon_thunk.type = fn_decl @B__carbon_thunk [concrete = constants.%B__carbon_thunk] { +// CHECK:STDOUT: %this.patt: %pattern_type.45c = binding_pattern this [concrete] +// CHECK:STDOUT: %this.param_patt: %pattern_type.45c = value_param_pattern %this.patt, call_param0 [concrete] +// CHECK:STDOUT: %a.patt: %pattern_type.7ce = binding_pattern a [concrete] +// CHECK:STDOUT: %a.param_patt: %pattern_type.7ce = value_param_pattern %a.patt, call_param1 [concrete] +// CHECK:STDOUT: } { +// CHECK:STDOUT: %this.param: %ptr.1f9 = value_param call_param0 +// CHECK:STDOUT: %this: %ptr.1f9 = bind_name this, %this.param +// CHECK:STDOUT: %a.param: %i32 = value_param call_param1 +// CHECK:STDOUT: %.1: type = splice_block %i32 [concrete = constants.%i32] { +// CHECK:STDOUT: %int_32: Core.IntLiteral = int_value 32 [concrete = constants.%int_32] +// CHECK:STDOUT: %i32: type = class_type @Int, @Int(constants.%int_32) [concrete = constants.%i32] +// CHECK:STDOUT: } +// CHECK:STDOUT: %a: %i32 = bind_name a, %a.param +// CHECK:STDOUT: } +// CHECK:STDOUT: %.7af: %.ce5 = cpp_overload_set_value @A.2 [concrete = constants.%empty_struct.a7d] +// CHECK:STDOUT: %C__carbon_thunk.decl: %C__carbon_thunk.type = fn_decl @C__carbon_thunk [concrete = constants.%C__carbon_thunk] { +// CHECK:STDOUT: %a.patt: %pattern_type.7ce = binding_pattern a [concrete] +// CHECK:STDOUT: %a.param_patt: %pattern_type.7ce = value_param_pattern %a.patt, call_param0 [concrete] +// CHECK:STDOUT: } { +// CHECK:STDOUT: %a.param: %i32 = value_param call_param0 +// CHECK:STDOUT: %.1: type = splice_block %i32 [concrete = constants.%i32] { +// CHECK:STDOUT: %int_32: Core.IntLiteral = int_value 32 [concrete = constants.%int_32] +// CHECK:STDOUT: %i32: type = class_type @Int, @Int(constants.%int_32) [concrete = constants.%i32] +// CHECK:STDOUT: } +// CHECK:STDOUT: %a: %i32 = bind_name a, %a.param +// CHECK:STDOUT: } +// CHECK:STDOUT: %.7b7: %.c13 = cpp_overload_set_value @A__carbon_thunk.2 [concrete = constants.%empty_struct.576] +// CHECK:STDOUT: %D__carbon_thunk.decl: %D__carbon_thunk.type = fn_decl @D__carbon_thunk [concrete = constants.%D__carbon_thunk] { +// CHECK:STDOUT: %_.patt: %pattern_type.45c = binding_pattern _ [concrete] +// CHECK:STDOUT: %_.param_patt: %pattern_type.45c = value_param_pattern %_.patt, call_param0 [concrete] +// CHECK:STDOUT: %a.patt: %pattern_type.7ce = binding_pattern a [concrete] +// CHECK:STDOUT: %a.param_patt: %pattern_type.7ce = value_param_pattern %a.patt, call_param1 [concrete] +// CHECK:STDOUT: } { +// CHECK:STDOUT: %_.param: %ptr.1f9 = value_param call_param0 +// CHECK:STDOUT: %_: %ptr.1f9 = bind_name _, %_.param +// CHECK:STDOUT: %a.param: %i32 = value_param call_param1 +// CHECK:STDOUT: %.1: type = splice_block %i32 [concrete = constants.%i32] { +// CHECK:STDOUT: %int_32: Core.IntLiteral = int_value 32 [concrete = constants.%int_32] +// CHECK:STDOUT: %i32: type = class_type @Int, @Int(constants.%int_32) [concrete = constants.%i32] +// CHECK:STDOUT: } +// CHECK:STDOUT: %a: %i32 = bind_name a, %a.param +// CHECK:STDOUT: } +// CHECK:STDOUT: %Core.Destroy: type = import_ref Core//prelude/parts/destroy, Destroy, loaded [concrete = constants.%Destroy.type] +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: file { +// CHECK:STDOUT: package: = namespace [concrete] { +// CHECK:STDOUT: .Core = imports.%Core +// CHECK:STDOUT: .Cpp = imports.%Cpp +// CHECK:STDOUT: .Call = %Call.decl +// CHECK:STDOUT: } +// CHECK:STDOUT: %Core.import = import Core +// CHECK:STDOUT: %Cpp.import_cpp = import_cpp { +// CHECK:STDOUT: import Cpp "functions.h" +// CHECK:STDOUT: } +// CHECK:STDOUT: %Call.decl: %Call.type = fn_decl @Call [concrete = constants.%Call] {} {} +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: class @X { +// CHECK:STDOUT: %empty_struct_type: type = struct_type {} [concrete = constants.%empty_struct_type] +// CHECK:STDOUT: %complete_type: = complete_type_witness %empty_struct_type [concrete = constants.%complete_type.357] +// CHECK:STDOUT: complete_type_witness = %complete_type +// CHECK:STDOUT: +// CHECK:STDOUT: !members: +// CHECK:STDOUT: .B = imports.%.8ab +// CHECK:STDOUT: .C = imports.%.7af +// CHECK:STDOUT: .D = imports.%.7b7 +// CHECK:STDOUT: import Cpp//... +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: fn @Call() { +// CHECK:STDOUT: !entry: +// CHECK:STDOUT: %Cpp.ref.loc8: = name_ref Cpp, imports.%Cpp [concrete = imports.%Cpp] +// CHECK:STDOUT: %A.ref.loc8: %.490 = name_ref A, imports.%.7c0 [concrete = constants.%empty_struct.a89] +// CHECK:STDOUT: %int_1.loc8: Core.IntLiteral = int_value 1 [concrete = constants.%int_1.5b8] +// CHECK:STDOUT: %int_2.loc8: Core.IntLiteral = int_value 2 [concrete = constants.%int_2.ecc] +// CHECK:STDOUT: %impl.elem0.loc8_9: %.1df = impl_witness_access constants.%ImplicitAs.impl_witness.204, element0 [concrete = constants.%Core.IntLiteral.as.ImplicitAs.impl.Convert.0f0] +// CHECK:STDOUT: %bound_method.loc8_9.1: = bound_method %int_1.loc8, %impl.elem0.loc8_9 [concrete = constants.%Core.IntLiteral.as.ImplicitAs.impl.Convert.bound.abf] +// CHECK:STDOUT: %specific_fn.loc8_9: = specific_function %impl.elem0.loc8_9, @Core.IntLiteral.as.ImplicitAs.impl.Convert(constants.%int_32) [concrete = constants.%Core.IntLiteral.as.ImplicitAs.impl.Convert.specific_fn] +// CHECK:STDOUT: %bound_method.loc8_9.2: = bound_method %int_1.loc8, %specific_fn.loc8_9 [concrete = constants.%bound_method.c11] +// CHECK:STDOUT: %Core.IntLiteral.as.ImplicitAs.impl.Convert.call.loc8_9: init %i32 = call %bound_method.loc8_9.2(%int_1.loc8) [concrete = constants.%int_1.5d2] +// CHECK:STDOUT: %.loc8_9.1: %i32 = value_of_initializer %Core.IntLiteral.as.ImplicitAs.impl.Convert.call.loc8_9 [concrete = constants.%int_1.5d2] +// CHECK:STDOUT: %.loc8_9.2: %i32 = converted %int_1.loc8, %.loc8_9.1 [concrete = constants.%int_1.5d2] +// CHECK:STDOUT: %impl.elem0.loc8_12: %.1df = impl_witness_access constants.%ImplicitAs.impl_witness.204, element0 [concrete = constants.%Core.IntLiteral.as.ImplicitAs.impl.Convert.0f0] +// CHECK:STDOUT: %bound_method.loc8_12.1: = bound_method %int_2.loc8, %impl.elem0.loc8_12 [concrete = constants.%Core.IntLiteral.as.ImplicitAs.impl.Convert.bound.b82] +// CHECK:STDOUT: %specific_fn.loc8_12: = specific_function %impl.elem0.loc8_12, @Core.IntLiteral.as.ImplicitAs.impl.Convert(constants.%int_32) [concrete = constants.%Core.IntLiteral.as.ImplicitAs.impl.Convert.specific_fn] +// CHECK:STDOUT: %bound_method.loc8_12.2: = bound_method %int_2.loc8, %specific_fn.loc8_12 [concrete = constants.%bound_method.8bd] +// CHECK:STDOUT: %Core.IntLiteral.as.ImplicitAs.impl.Convert.call.loc8_12: init %i32 = call %bound_method.loc8_12.2(%int_2.loc8) [concrete = constants.%int_2.ef8] +// CHECK:STDOUT: %.loc8_12.1: %i32 = value_of_initializer %Core.IntLiteral.as.ImplicitAs.impl.Convert.call.loc8_12 [concrete = constants.%int_2.ef8] +// CHECK:STDOUT: %.loc8_12.2: %i32 = converted %int_2.loc8, %.loc8_12.1 [concrete = constants.%int_2.ef8] +// CHECK:STDOUT: %A__carbon_thunk.call.loc8: init %empty_tuple.type = call imports.%A__carbon_thunk.decl.713db8.1(%.loc8_9.2, %.loc8_12.2) +// CHECK:STDOUT: %Cpp.ref.loc9: = name_ref Cpp, imports.%Cpp [concrete = imports.%Cpp] +// CHECK:STDOUT: %A.ref.loc9: %.490 = name_ref A, imports.%.7c0 [concrete = constants.%empty_struct.a89] +// CHECK:STDOUT: %int_1.loc9: Core.IntLiteral = int_value 1 [concrete = constants.%int_1.5b8] +// CHECK:STDOUT: %int_2.loc9: Core.IntLiteral = int_value 2 [concrete = constants.%int_2.ecc] +// CHECK:STDOUT: %int_3: Core.IntLiteral = int_value 3 [concrete = constants.%int_3.1ba] +// CHECK:STDOUT: %impl.elem0.loc9_9: %.1df = impl_witness_access constants.%ImplicitAs.impl_witness.204, element0 [concrete = constants.%Core.IntLiteral.as.ImplicitAs.impl.Convert.0f0] +// CHECK:STDOUT: %bound_method.loc9_9.1: = bound_method %int_1.loc9, %impl.elem0.loc9_9 [concrete = constants.%Core.IntLiteral.as.ImplicitAs.impl.Convert.bound.abf] +// CHECK:STDOUT: %specific_fn.loc9_9: = specific_function %impl.elem0.loc9_9, @Core.IntLiteral.as.ImplicitAs.impl.Convert(constants.%int_32) [concrete = constants.%Core.IntLiteral.as.ImplicitAs.impl.Convert.specific_fn] +// CHECK:STDOUT: %bound_method.loc9_9.2: = bound_method %int_1.loc9, %specific_fn.loc9_9 [concrete = constants.%bound_method.c11] +// CHECK:STDOUT: %Core.IntLiteral.as.ImplicitAs.impl.Convert.call.loc9_9: init %i32 = call %bound_method.loc9_9.2(%int_1.loc9) [concrete = constants.%int_1.5d2] +// CHECK:STDOUT: %.loc9_9.1: %i32 = value_of_initializer %Core.IntLiteral.as.ImplicitAs.impl.Convert.call.loc9_9 [concrete = constants.%int_1.5d2] +// CHECK:STDOUT: %.loc9_9.2: %i32 = converted %int_1.loc9, %.loc9_9.1 [concrete = constants.%int_1.5d2] +// CHECK:STDOUT: %impl.elem0.loc9_12: %.1df = impl_witness_access constants.%ImplicitAs.impl_witness.204, element0 [concrete = constants.%Core.IntLiteral.as.ImplicitAs.impl.Convert.0f0] +// CHECK:STDOUT: %bound_method.loc9_12.1: = bound_method %int_2.loc9, %impl.elem0.loc9_12 [concrete = constants.%Core.IntLiteral.as.ImplicitAs.impl.Convert.bound.b82] +// CHECK:STDOUT: %specific_fn.loc9_12: = specific_function %impl.elem0.loc9_12, @Core.IntLiteral.as.ImplicitAs.impl.Convert(constants.%int_32) [concrete = constants.%Core.IntLiteral.as.ImplicitAs.impl.Convert.specific_fn] +// CHECK:STDOUT: %bound_method.loc9_12.2: = bound_method %int_2.loc9, %specific_fn.loc9_12 [concrete = constants.%bound_method.8bd] +// CHECK:STDOUT: %Core.IntLiteral.as.ImplicitAs.impl.Convert.call.loc9_12: init %i32 = call %bound_method.loc9_12.2(%int_2.loc9) [concrete = constants.%int_2.ef8] +// CHECK:STDOUT: %.loc9_12.1: %i32 = value_of_initializer %Core.IntLiteral.as.ImplicitAs.impl.Convert.call.loc9_12 [concrete = constants.%int_2.ef8] +// CHECK:STDOUT: %.loc9_12.2: %i32 = converted %int_2.loc9, %.loc9_12.1 [concrete = constants.%int_2.ef8] +// CHECK:STDOUT: %impl.elem0.loc9_15: %.1df = impl_witness_access constants.%ImplicitAs.impl_witness.204, element0 [concrete = constants.%Core.IntLiteral.as.ImplicitAs.impl.Convert.0f0] +// CHECK:STDOUT: %bound_method.loc9_15.1: = bound_method %int_3, %impl.elem0.loc9_15 [concrete = constants.%Core.IntLiteral.as.ImplicitAs.impl.Convert.bound.595] +// CHECK:STDOUT: %specific_fn.loc9_15: = specific_function %impl.elem0.loc9_15, @Core.IntLiteral.as.ImplicitAs.impl.Convert(constants.%int_32) [concrete = constants.%Core.IntLiteral.as.ImplicitAs.impl.Convert.specific_fn] +// CHECK:STDOUT: %bound_method.loc9_15.2: = bound_method %int_3, %specific_fn.loc9_15 [concrete = constants.%bound_method.f36] +// CHECK:STDOUT: %Core.IntLiteral.as.ImplicitAs.impl.Convert.call.loc9_15: init %i32 = call %bound_method.loc9_15.2(%int_3) [concrete = constants.%int_3.822] +// CHECK:STDOUT: %.loc9_15.1: %i32 = value_of_initializer %Core.IntLiteral.as.ImplicitAs.impl.Convert.call.loc9_15 [concrete = constants.%int_3.822] +// CHECK:STDOUT: %.loc9_15.2: %i32 = converted %int_3, %.loc9_15.1 [concrete = constants.%int_3.822] +// CHECK:STDOUT: %A__carbon_thunk.call.loc9: init %empty_tuple.type = call imports.%A__carbon_thunk.decl.713db8.2(%.loc9_9.2, %.loc9_12.2, %.loc9_15.2) +// CHECK:STDOUT: %.loc10_5.1: %empty_struct_type = struct_literal () +// CHECK:STDOUT: %Cpp.ref.loc10: = name_ref Cpp, imports.%Cpp [concrete = imports.%Cpp] +// CHECK:STDOUT: %X.ref.loc10: type = name_ref X, imports.%X.decl [concrete = constants.%X] +// CHECK:STDOUT: %.loc10_5.2: ref %X = temporary_storage +// CHECK:STDOUT: %.loc10_5.3: init %X = class_init (), %.loc10_5.2 [concrete = constants.%X.val] +// CHECK:STDOUT: %.loc10_5.4: ref %X = temporary %.loc10_5.2, %.loc10_5.3 +// CHECK:STDOUT: %.loc10_7: ref %X = converted %.loc10_5.1, %.loc10_5.4 +// CHECK:STDOUT: %B.ref: %.ed9 = name_ref B, imports.%.8ab [concrete = constants.%empty_struct.61d] +// CHECK:STDOUT: %bound_method.loc10_16: = bound_method %.loc10_7, %B.ref +// CHECK:STDOUT: %int_1.loc10: Core.IntLiteral = int_value 1 [concrete = constants.%int_1.5b8] +// CHECK:STDOUT: %addr.loc10_7: %ptr.1f9 = addr_of %.loc10_7 +// CHECK:STDOUT: %impl.elem0.loc10: %.1df = impl_witness_access constants.%ImplicitAs.impl_witness.204, element0 [concrete = constants.%Core.IntLiteral.as.ImplicitAs.impl.Convert.0f0] +// CHECK:STDOUT: %bound_method.loc10_19.1: = bound_method %int_1.loc10, %impl.elem0.loc10 [concrete = constants.%Core.IntLiteral.as.ImplicitAs.impl.Convert.bound.abf] +// CHECK:STDOUT: %specific_fn.loc10: = specific_function %impl.elem0.loc10, @Core.IntLiteral.as.ImplicitAs.impl.Convert(constants.%int_32) [concrete = constants.%Core.IntLiteral.as.ImplicitAs.impl.Convert.specific_fn] +// CHECK:STDOUT: %bound_method.loc10_19.2: = bound_method %int_1.loc10, %specific_fn.loc10 [concrete = constants.%bound_method.c11] +// CHECK:STDOUT: %Core.IntLiteral.as.ImplicitAs.impl.Convert.call.loc10: init %i32 = call %bound_method.loc10_19.2(%int_1.loc10) [concrete = constants.%int_1.5d2] +// CHECK:STDOUT: %.loc10_19.1: %i32 = value_of_initializer %Core.IntLiteral.as.ImplicitAs.impl.Convert.call.loc10 [concrete = constants.%int_1.5d2] +// CHECK:STDOUT: %.loc10_19.2: %i32 = converted %int_1.loc10, %.loc10_19.1 [concrete = constants.%int_1.5d2] +// CHECK:STDOUT: %B__carbon_thunk.call: init %empty_tuple.type = call imports.%B__carbon_thunk.decl(%addr.loc10_7, %.loc10_19.2) +// CHECK:STDOUT: %Cpp.ref.loc11: = name_ref Cpp, imports.%Cpp [concrete = imports.%Cpp] +// CHECK:STDOUT: %X.ref.loc11: type = name_ref X, imports.%X.decl [concrete = constants.%X] +// CHECK:STDOUT: %C.ref: %.ce5 = name_ref C, imports.%.7af [concrete = constants.%empty_struct.a7d] +// CHECK:STDOUT: %int_1.loc11: Core.IntLiteral = int_value 1 [concrete = constants.%int_1.5b8] +// CHECK:STDOUT: %impl.elem0.loc11: %.1df = impl_witness_access constants.%ImplicitAs.impl_witness.204, element0 [concrete = constants.%Core.IntLiteral.as.ImplicitAs.impl.Convert.0f0] +// CHECK:STDOUT: %bound_method.loc11_11.1: = bound_method %int_1.loc11, %impl.elem0.loc11 [concrete = constants.%Core.IntLiteral.as.ImplicitAs.impl.Convert.bound.abf] +// CHECK:STDOUT: %specific_fn.loc11: = specific_function %impl.elem0.loc11, @Core.IntLiteral.as.ImplicitAs.impl.Convert(constants.%int_32) [concrete = constants.%Core.IntLiteral.as.ImplicitAs.impl.Convert.specific_fn] +// CHECK:STDOUT: %bound_method.loc11_11.2: = bound_method %int_1.loc11, %specific_fn.loc11 [concrete = constants.%bound_method.c11] +// CHECK:STDOUT: %Core.IntLiteral.as.ImplicitAs.impl.Convert.call.loc11: init %i32 = call %bound_method.loc11_11.2(%int_1.loc11) [concrete = constants.%int_1.5d2] +// CHECK:STDOUT: %.loc11_11.1: %i32 = value_of_initializer %Core.IntLiteral.as.ImplicitAs.impl.Convert.call.loc11 [concrete = constants.%int_1.5d2] +// CHECK:STDOUT: %.loc11_11.2: %i32 = converted %int_1.loc11, %.loc11_11.1 [concrete = constants.%int_1.5d2] +// CHECK:STDOUT: %C__carbon_thunk.call: init %empty_tuple.type = call imports.%C__carbon_thunk.decl(%.loc11_11.2) +// CHECK:STDOUT: %.loc12_5.1: %empty_struct_type = struct_literal () +// CHECK:STDOUT: %Cpp.ref.loc12: = name_ref Cpp, imports.%Cpp [concrete = imports.%Cpp] +// CHECK:STDOUT: %X.ref.loc12: type = name_ref X, imports.%X.decl [concrete = constants.%X] +// CHECK:STDOUT: %.loc12_5.2: ref %X = temporary_storage +// CHECK:STDOUT: %.loc12_5.3: init %X = class_init (), %.loc12_5.2 [concrete = constants.%X.val] +// CHECK:STDOUT: %.loc12_5.4: ref %X = temporary %.loc12_5.2, %.loc12_5.3 +// CHECK:STDOUT: %.loc12_7.1: ref %X = converted %.loc12_5.1, %.loc12_5.4 +// CHECK:STDOUT: %D.ref: %.c13 = name_ref D, imports.%.7b7 [concrete = constants.%empty_struct.576] +// CHECK:STDOUT: %bound_method.loc12_16: = bound_method %.loc12_7.1, %D.ref +// CHECK:STDOUT: %int_1.loc12: Core.IntLiteral = int_value 1 [concrete = constants.%int_1.5b8] +// CHECK:STDOUT: %.loc12_7.2: %X = bind_value %.loc12_7.1 +// CHECK:STDOUT: %impl.elem0.loc12: %.1df = impl_witness_access constants.%ImplicitAs.impl_witness.204, element0 [concrete = constants.%Core.IntLiteral.as.ImplicitAs.impl.Convert.0f0] +// CHECK:STDOUT: %bound_method.loc12_19.1: = bound_method %int_1.loc12, %impl.elem0.loc12 [concrete = constants.%Core.IntLiteral.as.ImplicitAs.impl.Convert.bound.abf] +// CHECK:STDOUT: %specific_fn.loc12: = specific_function %impl.elem0.loc12, @Core.IntLiteral.as.ImplicitAs.impl.Convert(constants.%int_32) [concrete = constants.%Core.IntLiteral.as.ImplicitAs.impl.Convert.specific_fn] +// CHECK:STDOUT: %bound_method.loc12_19.2: = bound_method %int_1.loc12, %specific_fn.loc12 [concrete = constants.%bound_method.c11] +// CHECK:STDOUT: %Core.IntLiteral.as.ImplicitAs.impl.Convert.call.loc12: init %i32 = call %bound_method.loc12_19.2(%int_1.loc12) [concrete = constants.%int_1.5d2] +// CHECK:STDOUT: %.loc12_19.1: %i32 = value_of_initializer %Core.IntLiteral.as.ImplicitAs.impl.Convert.call.loc12 [concrete = constants.%int_1.5d2] +// CHECK:STDOUT: %.loc12_19.2: %i32 = converted %int_1.loc12, %.loc12_19.1 [concrete = constants.%int_1.5d2] +// CHECK:STDOUT: %.loc12_7.3: ref %X = value_as_ref %.loc12_7.2 +// CHECK:STDOUT: %addr.loc12_20: %ptr.1f9 = addr_of %.loc12_7.3 +// CHECK:STDOUT: %D__carbon_thunk.call: init %empty_tuple.type = call imports.%D__carbon_thunk.decl(%addr.loc12_20, %.loc12_19.2) +// CHECK:STDOUT: %facet_value.loc12: %type_where = facet_value constants.%X, () [concrete = constants.%facet_value] +// CHECK:STDOUT: %.loc12_5.5: %type_where = converted constants.%X, %facet_value.loc12 [concrete = constants.%facet_value] +// CHECK:STDOUT: %AggregateT.as_type.as.Destroy.impl.Op.bound.loc12: = bound_method %.loc12_5.4, constants.%AggregateT.as_type.as.Destroy.impl.Op.55b +// CHECK:STDOUT: %AggregateT.as_type.as.Destroy.impl.Op.specific_fn.1: = specific_function constants.%AggregateT.as_type.as.Destroy.impl.Op.55b, @AggregateT.as_type.as.Destroy.impl.Op(constants.%facet_value) [concrete = constants.%AggregateT.as_type.as.Destroy.impl.Op.specific_fn] +// CHECK:STDOUT: %bound_method.loc12_5: = bound_method %.loc12_5.4, %AggregateT.as_type.as.Destroy.impl.Op.specific_fn.1 +// CHECK:STDOUT: %addr.loc12_5: %ptr.1f9 = addr_of %.loc12_5.4 +// CHECK:STDOUT: %AggregateT.as_type.as.Destroy.impl.Op.call.loc12: init %empty_tuple.type = call %bound_method.loc12_5(%addr.loc12_5) +// CHECK:STDOUT: %facet_value.loc10: %type_where = facet_value constants.%X, () [concrete = constants.%facet_value] +// CHECK:STDOUT: %.loc10_5.5: %type_where = converted constants.%X, %facet_value.loc10 [concrete = constants.%facet_value] +// CHECK:STDOUT: %AggregateT.as_type.as.Destroy.impl.Op.bound.loc10: = bound_method %.loc10_5.4, constants.%AggregateT.as_type.as.Destroy.impl.Op.55b +// CHECK:STDOUT: %AggregateT.as_type.as.Destroy.impl.Op.specific_fn.2: = specific_function constants.%AggregateT.as_type.as.Destroy.impl.Op.55b, @AggregateT.as_type.as.Destroy.impl.Op(constants.%facet_value) [concrete = constants.%AggregateT.as_type.as.Destroy.impl.Op.specific_fn] +// CHECK:STDOUT: %bound_method.loc10_5: = bound_method %.loc10_5.4, %AggregateT.as_type.as.Destroy.impl.Op.specific_fn.2 +// CHECK:STDOUT: %addr.loc10_5: %ptr.1f9 = addr_of %.loc10_5.4 +// CHECK:STDOUT: %AggregateT.as_type.as.Destroy.impl.Op.call.loc10: init %empty_tuple.type = call %bound_method.loc10_5(%addr.loc10_5) +// CHECK:STDOUT: return +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: fn @A.1(%a.param: %i32, %b.param: %i32); +// CHECK:STDOUT: +// CHECK:STDOUT: fn @A__carbon_thunk.1(%a.param: %i32, %b.param: %i32); +// CHECK:STDOUT: +// CHECK:STDOUT: fn @A.2(%a.param: %i32, %b.param: %i32, %c.param: %i32); +// CHECK:STDOUT: +// CHECK:STDOUT: fn @A__carbon_thunk.2(%a.param: %i32, %b.param: %i32, %c.param: %i32); +// CHECK:STDOUT: +// CHECK:STDOUT: fn @X.B(%self.param: %ptr.1f9, %a.param: %i32); +// CHECK:STDOUT: +// CHECK:STDOUT: fn @B__carbon_thunk(%this.param: %ptr.1f9, %a.param: %i32); +// CHECK:STDOUT: +// CHECK:STDOUT: fn @X.C(%a.param: %i32); +// CHECK:STDOUT: +// CHECK:STDOUT: fn @C__carbon_thunk(%a.param: %i32); +// CHECK:STDOUT: +// CHECK:STDOUT: fn @X.D(%self.param: %X, %a.param: %i32); +// CHECK:STDOUT: +// CHECK:STDOUT: fn @D__carbon_thunk(%_.param: %ptr.1f9, %a.param: %i32); +// CHECK:STDOUT: +// CHECK:STDOUT: --- fail_call_too_few_args.carbon +// CHECK:STDOUT: +// CHECK:STDOUT: constants { +// CHECK:STDOUT: %empty_tuple.type: type = tuple_type () [concrete] +// CHECK:STDOUT: %.490: type = cpp_overload_set_type @const.as.Destroy.impl.Op [concrete] +// CHECK:STDOUT: %empty_struct.a89: %.490 = struct_value () [concrete] +// CHECK:STDOUT: %int_1: Core.IntLiteral = int_value 1 [concrete] +// CHECK:STDOUT: %empty_struct_type: type = struct_type {} [concrete] +// CHECK:STDOUT: %X: type = class_type @X [concrete] +// CHECK:STDOUT: %X.val: %X = struct_value () [concrete] +// CHECK:STDOUT: %.ed9: type = cpp_overload_set_type @ [concrete] +// CHECK:STDOUT: %empty_struct.61d: %.ed9 = struct_value () [concrete] +// CHECK:STDOUT: %.ce5: type = cpp_overload_set_type @ [concrete] +// CHECK:STDOUT: %empty_struct.a7d: %.ce5 = struct_value () [concrete] +// CHECK:STDOUT: %.c13: type = cpp_overload_set_type @ [concrete] +// CHECK:STDOUT: %empty_struct.576: %.c13 = struct_value () [concrete] +// CHECK:STDOUT: %type_where: type = facet_type > [concrete] +// CHECK:STDOUT: %facet_value: %type_where = facet_value %X, () [concrete] +// CHECK:STDOUT: %AggregateT.as_type.as.Destroy.impl.Op.type.d91: type = fn_type @AggregateT.as_type.as.Destroy.impl.Op, @AggregateT.as_type.as.Destroy.impl(%facet_value) [concrete] +// CHECK:STDOUT: %AggregateT.as_type.as.Destroy.impl.Op.55b: %AggregateT.as_type.as.Destroy.impl.Op.type.d91 = struct_value () [concrete] +// CHECK:STDOUT: %ptr.1f9: type = ptr_type %X [concrete] +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: imports { +// CHECK:STDOUT: %Cpp: = namespace file.%Cpp.import_cpp, [concrete] { +// CHECK:STDOUT: .A = %.7c0 +// CHECK:STDOUT: .X = %X.decl +// CHECK:STDOUT: import Cpp//... +// CHECK:STDOUT: } +// CHECK:STDOUT: %.7c0: %.490 = cpp_overload_set_value @const.as.Destroy.impl.Op [concrete = constants.%empty_struct.a89] +// CHECK:STDOUT: %X.decl: type = class_decl @X [concrete = constants.%X] {} {} +// CHECK:STDOUT: %.8ab: %.ed9 = cpp_overload_set_value @ [concrete = constants.%empty_struct.61d] +// CHECK:STDOUT: %.7af: %.ce5 = cpp_overload_set_value @ [concrete = constants.%empty_struct.a7d] +// CHECK:STDOUT: %.7b7: %.c13 = cpp_overload_set_value @ [concrete = constants.%empty_struct.576] +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: fn @Call() { +// CHECK:STDOUT: !entry: +// CHECK:STDOUT: %Cpp.ref.loc16: = name_ref Cpp, imports.%Cpp [concrete = imports.%Cpp] +// CHECK:STDOUT: %A.ref.loc16: %.490 = name_ref A, imports.%.7c0 [concrete = constants.%empty_struct.a89] +// CHECK:STDOUT: %int_1: Core.IntLiteral = int_value 1 [concrete = constants.%int_1] +// CHECK:STDOUT: %Cpp.ref.loc26: = name_ref Cpp, imports.%Cpp [concrete = imports.%Cpp] +// CHECK:STDOUT: %A.ref.loc26: %.490 = name_ref A, imports.%.7c0 [concrete = constants.%empty_struct.a89] +// CHECK:STDOUT: %.loc36_5.1: %empty_struct_type = struct_literal () +// CHECK:STDOUT: %Cpp.ref.loc36: = name_ref Cpp, imports.%Cpp [concrete = imports.%Cpp] +// CHECK:STDOUT: %X.ref.loc36: type = name_ref X, imports.%X.decl [concrete = constants.%X] +// CHECK:STDOUT: %.loc36_5.2: ref %X = temporary_storage +// CHECK:STDOUT: %.loc36_5.3: init %X = class_init (), %.loc36_5.2 [concrete = constants.%X.val] +// CHECK:STDOUT: %.loc36_5.4: ref %X = temporary %.loc36_5.2, %.loc36_5.3 +// CHECK:STDOUT: %.loc36_7: ref %X = converted %.loc36_5.1, %.loc36_5.4 +// CHECK:STDOUT: %B.ref: %.ed9 = name_ref B, imports.%.8ab [concrete = constants.%empty_struct.61d] +// CHECK:STDOUT: %bound_method.loc36_16: = bound_method %.loc36_7, %B.ref +// CHECK:STDOUT: %Cpp.ref.loc46: = name_ref Cpp, imports.%Cpp [concrete = imports.%Cpp] +// CHECK:STDOUT: %X.ref.loc46: type = name_ref X, imports.%X.decl [concrete = constants.%X] +// CHECK:STDOUT: %C.ref: %.ce5 = name_ref C, imports.%.7af [concrete = constants.%empty_struct.a7d] +// CHECK:STDOUT: %.loc56_5.1: %empty_struct_type = struct_literal () +// CHECK:STDOUT: %Cpp.ref.loc56: = name_ref Cpp, imports.%Cpp [concrete = imports.%Cpp] +// CHECK:STDOUT: %X.ref.loc56: type = name_ref X, imports.%X.decl [concrete = constants.%X] +// CHECK:STDOUT: %.loc56_5.2: ref %X = temporary_storage +// CHECK:STDOUT: %.loc56_5.3: init %X = class_init (), %.loc56_5.2 [concrete = constants.%X.val] +// CHECK:STDOUT: %.loc56_5.4: ref %X = temporary %.loc56_5.2, %.loc56_5.3 +// CHECK:STDOUT: %.loc56_7: ref %X = converted %.loc56_5.1, %.loc56_5.4 +// CHECK:STDOUT: %D.ref: %.c13 = name_ref D, imports.%.7b7 [concrete = constants.%empty_struct.576] +// CHECK:STDOUT: %bound_method.loc56_16: = bound_method %.loc56_7, %D.ref +// CHECK:STDOUT: %facet_value.loc56: %type_where = facet_value constants.%X, () [concrete = constants.%facet_value] +// CHECK:STDOUT: %.loc56_5.5: %type_where = converted constants.%X, %facet_value.loc56 [concrete = constants.%facet_value] +// CHECK:STDOUT: %AggregateT.as_type.as.Destroy.impl.Op.bound.loc56: = bound_method %.loc56_5.4, constants.%AggregateT.as_type.as.Destroy.impl.Op.55b +// CHECK:STDOUT: +// CHECK:STDOUT: %bound_method.loc56_5: = bound_method %.loc56_5.4, %AggregateT.as_type.as.Destroy.impl.Op.specific_fn.1 +// CHECK:STDOUT: %addr.loc56: %ptr.1f9 = addr_of %.loc56_5.4 +// CHECK:STDOUT: %AggregateT.as_type.as.Destroy.impl.Op.call.loc56: init %empty_tuple.type = call %bound_method.loc56_5(%addr.loc56) +// CHECK:STDOUT: %facet_value.loc36: %type_where = facet_value constants.%X, () [concrete = constants.%facet_value] +// CHECK:STDOUT: %.loc36_5.5: %type_where = converted constants.%X, %facet_value.loc36 [concrete = constants.%facet_value] +// CHECK:STDOUT: %AggregateT.as_type.as.Destroy.impl.Op.bound.loc36: = bound_method %.loc36_5.4, constants.%AggregateT.as_type.as.Destroy.impl.Op.55b +// CHECK:STDOUT: +// CHECK:STDOUT: %bound_method.loc36_5: = bound_method %.loc36_5.4, %AggregateT.as_type.as.Destroy.impl.Op.specific_fn.2 +// CHECK:STDOUT: %addr.loc36: %ptr.1f9 = addr_of %.loc36_5.4 +// CHECK:STDOUT: %AggregateT.as_type.as.Destroy.impl.Op.call.loc36: init %empty_tuple.type = call %bound_method.loc36_5(%addr.loc36) +// CHECK:STDOUT: +// CHECK:STDOUT: } +// CHECK:STDOUT: diff --git a/toolchain/check/testdata/interop/cpp/function/overloads.carbon b/toolchain/check/testdata/interop/cpp/function/overloads.carbon index 7fc8af5c668c..af546f357554 100644 --- a/toolchain/check/testdata/interop/cpp/function/overloads.carbon +++ b/toolchain/check/testdata/interop/cpp/function/overloads.carbon @@ -1453,13 +1453,6 @@ fn F() { // CHECK:STDOUT: %F.decl: %F.type = fn_decl @F [concrete = constants.%F] {} {} // CHECK:STDOUT: } // CHECK:STDOUT: -// CHECK:STDOUT: class @S { -// CHECK:STDOUT: complete_type_witness = invalid -// CHECK:STDOUT: -// CHECK:STDOUT: !members: -// CHECK:STDOUT: import Cpp//... -// CHECK:STDOUT: } -// CHECK:STDOUT: // CHECK:STDOUT: fn @F() { // CHECK:STDOUT: !entry: // CHECK:STDOUT: %Cpp.ref: = name_ref Cpp, imports.%Cpp [concrete = imports.%Cpp] diff --git a/toolchain/check/testdata/interop/cpp/function/qualified_param.carbon b/toolchain/check/testdata/interop/cpp/function/qualified_param.carbon new file mode 100644 index 000000000000..a824f0fc3d46 --- /dev/null +++ b/toolchain/check/testdata/interop/cpp/function/qualified_param.carbon @@ -0,0 +1,147 @@ +// 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-FILE: toolchain/testing/testdata/min_prelude/int.carbon +// +// AUTOUPDATE +// TIP: To test this file alone, run: +// TIP: bazel test //toolchain/testing:file_test --test_arg=--file_tests=toolchain/check/testdata/interop/cpp/function/qualified_param.carbon +// TIP: To dump output, run: +// TIP: bazel run //toolchain/testing:file_test -- --dump_output --file_tests=toolchain/check/testdata/interop/cpp/function/qualified_param.carbon + +// --- qualifiers.h + +void TakesConstInt(const int); + +struct S {}; + +void TakesConstS(const S); + +// --- call_qualifiers.carbon + +library "[[@TEST_NAME]]"; + +import Cpp library "qualifiers.h"; + +fn F() { + //@dump-sem-ir-begin + Cpp.TakesConstInt(42); + + var s: Cpp.S = {}; + Cpp.TakesConstS(s); + //@dump-sem-ir-end +} + +// CHECK:STDOUT: --- call_qualifiers.carbon +// CHECK:STDOUT: +// CHECK:STDOUT: constants { +// CHECK:STDOUT: %empty_tuple.type: type = tuple_type () [concrete] +// CHECK:STDOUT: %.fc4: type = cpp_overload_set_type @ImplicitAs.Convert [concrete] +// CHECK:STDOUT: %empty_struct.cca: %.fc4 = struct_value () [concrete] +// CHECK:STDOUT: %int_42.20e: Core.IntLiteral = int_value 42 [concrete] +// CHECK:STDOUT: %int_32: Core.IntLiteral = int_value 32 [concrete] +// CHECK:STDOUT: %i32: type = class_type @Int, @Int(%int_32) [concrete] +// CHECK:STDOUT: %TakesConstInt.type: type = fn_type @TakesConstInt [concrete] +// CHECK:STDOUT: %TakesConstInt: %TakesConstInt.type = struct_value () [concrete] +// CHECK:STDOUT: %ImplicitAs.type.d14: type = facet_type <@ImplicitAs, @ImplicitAs(%i32)> [concrete] +// CHECK:STDOUT: %ImplicitAs.Convert.type.1b6: type = fn_type @ImplicitAs.Convert, @ImplicitAs(%i32) [concrete] +// CHECK:STDOUT: %To: Core.IntLiteral = bind_symbolic_name To, 0 [symbolic] +// CHECK:STDOUT: %Core.IntLiteral.as.ImplicitAs.impl.Convert.type.340: type = fn_type @Core.IntLiteral.as.ImplicitAs.impl.Convert, @Core.IntLiteral.as.ImplicitAs.impl(%To) [symbolic] +// CHECK:STDOUT: %Core.IntLiteral.as.ImplicitAs.impl.Convert.1c0: %Core.IntLiteral.as.ImplicitAs.impl.Convert.type.340 = struct_value () [symbolic] +// CHECK:STDOUT: %ImplicitAs.impl_witness.204: = impl_witness imports.%ImplicitAs.impl_witness_table.9e9, @Core.IntLiteral.as.ImplicitAs.impl(%int_32) [concrete] +// CHECK:STDOUT: %Core.IntLiteral.as.ImplicitAs.impl.Convert.type.584: type = fn_type @Core.IntLiteral.as.ImplicitAs.impl.Convert, @Core.IntLiteral.as.ImplicitAs.impl(%int_32) [concrete] +// CHECK:STDOUT: %Core.IntLiteral.as.ImplicitAs.impl.Convert.0f0: %Core.IntLiteral.as.ImplicitAs.impl.Convert.type.584 = struct_value () [concrete] +// CHECK:STDOUT: %ImplicitAs.facet: %ImplicitAs.type.d14 = facet_value Core.IntLiteral, (%ImplicitAs.impl_witness.204) [concrete] +// CHECK:STDOUT: %.1df: type = fn_type_with_self_type %ImplicitAs.Convert.type.1b6, %ImplicitAs.facet [concrete] +// CHECK:STDOUT: %Core.IntLiteral.as.ImplicitAs.impl.Convert.bound: = bound_method %int_42.20e, %Core.IntLiteral.as.ImplicitAs.impl.Convert.0f0 [concrete] +// CHECK:STDOUT: %Core.IntLiteral.as.ImplicitAs.impl.Convert.specific_fn: = specific_function %Core.IntLiteral.as.ImplicitAs.impl.Convert.0f0, @Core.IntLiteral.as.ImplicitAs.impl.Convert(%int_32) [concrete] +// CHECK:STDOUT: %bound_method: = bound_method %int_42.20e, %Core.IntLiteral.as.ImplicitAs.impl.Convert.specific_fn [concrete] +// CHECK:STDOUT: %int_42.c68: %i32 = int_value 42 [concrete] +// CHECK:STDOUT: %S: type = class_type @S [concrete] +// CHECK:STDOUT: %empty_struct_type: type = struct_type {} [concrete] +// CHECK:STDOUT: %pattern_type.7da: type = pattern_type %S [concrete] +// CHECK:STDOUT: %S.val: %S = struct_value () [concrete] +// CHECK:STDOUT: %.289: type = cpp_overload_set_type @Core.IntLiteral.as.ImplicitAs.impl.Convert [concrete] +// CHECK:STDOUT: %empty_struct.269: %.289 = struct_value () [concrete] +// CHECK:STDOUT: %const.e39: type = const_type %S [concrete] +// CHECK:STDOUT: %ptr.ff5: type = ptr_type %const.e39 [concrete] +// CHECK:STDOUT: %TakesConstS__carbon_thunk.type: type = fn_type @TakesConstS__carbon_thunk [concrete] +// CHECK:STDOUT: %TakesConstS__carbon_thunk: %TakesConstS__carbon_thunk.type = struct_value () [concrete] +// CHECK:STDOUT: %ptr.5c7: type = ptr_type %S [concrete] +// CHECK:STDOUT: %type_where: type = facet_type > [concrete] +// CHECK:STDOUT: %facet_value: %type_where = facet_value %S, () [concrete] +// CHECK:STDOUT: %AggregateT.as_type.as.Destroy.impl.Op.type.df1: type = fn_type @AggregateT.as_type.as.Destroy.impl.Op, @AggregateT.as_type.as.Destroy.impl(%facet_value) [concrete] +// CHECK:STDOUT: %AggregateT.as_type.as.Destroy.impl.Op.cc2: %AggregateT.as_type.as.Destroy.impl.Op.type.df1 = struct_value () [concrete] +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: imports { +// CHECK:STDOUT: %Cpp: = namespace file.%Cpp.import_cpp, [concrete] { +// CHECK:STDOUT: .TakesConstInt = %.6a4 +// CHECK:STDOUT: .S = %S.decl +// CHECK:STDOUT: .TakesConstS = %.7c2 +// CHECK:STDOUT: import Cpp//... +// CHECK:STDOUT: } +// CHECK:STDOUT: %.6a4: %.fc4 = cpp_overload_set_value @ImplicitAs.Convert [concrete = constants.%empty_struct.cca] +// CHECK:STDOUT: %TakesConstInt.decl: %TakesConstInt.type = fn_decl @TakesConstInt [concrete = constants.%TakesConstInt] { +// CHECK:STDOUT: +// CHECK:STDOUT: } { +// CHECK:STDOUT: +// CHECK:STDOUT: } +// CHECK:STDOUT: %Core.import_ref.ee7: @Core.IntLiteral.as.ImplicitAs.impl.%Core.IntLiteral.as.ImplicitAs.impl.Convert.type (%Core.IntLiteral.as.ImplicitAs.impl.Convert.type.340) = import_ref Core//prelude/parts/int, loc23_39, loaded [symbolic = @Core.IntLiteral.as.ImplicitAs.impl.%Core.IntLiteral.as.ImplicitAs.impl.Convert (constants.%Core.IntLiteral.as.ImplicitAs.impl.Convert.1c0)] +// CHECK:STDOUT: %ImplicitAs.impl_witness_table.9e9 = impl_witness_table (%Core.import_ref.ee7), @Core.IntLiteral.as.ImplicitAs.impl [concrete] +// CHECK:STDOUT: %S.decl: type = class_decl @S [concrete = constants.%S] {} {} +// CHECK:STDOUT: %.7c2: %.289 = cpp_overload_set_value @Core.IntLiteral.as.ImplicitAs.impl.Convert [concrete = constants.%empty_struct.269] +// CHECK:STDOUT: %TakesConstS__carbon_thunk.decl: %TakesConstS__carbon_thunk.type = fn_decl @TakesConstS__carbon_thunk [concrete = constants.%TakesConstS__carbon_thunk] { +// CHECK:STDOUT: +// CHECK:STDOUT: } { +// CHECK:STDOUT: +// CHECK:STDOUT: } +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: fn @F() { +// CHECK:STDOUT: !entry: +// CHECK:STDOUT: %Cpp.ref.loc8: = name_ref Cpp, imports.%Cpp [concrete = imports.%Cpp] +// CHECK:STDOUT: %TakesConstInt.ref: %.fc4 = name_ref TakesConstInt, imports.%.6a4 [concrete = constants.%empty_struct.cca] +// CHECK:STDOUT: %int_42: Core.IntLiteral = int_value 42 [concrete = constants.%int_42.20e] +// CHECK:STDOUT: %impl.elem0: %.1df = impl_witness_access constants.%ImplicitAs.impl_witness.204, element0 [concrete = constants.%Core.IntLiteral.as.ImplicitAs.impl.Convert.0f0] +// CHECK:STDOUT: %bound_method.loc8_21.1: = bound_method %int_42, %impl.elem0 [concrete = constants.%Core.IntLiteral.as.ImplicitAs.impl.Convert.bound] +// CHECK:STDOUT: %specific_fn: = specific_function %impl.elem0, @Core.IntLiteral.as.ImplicitAs.impl.Convert(constants.%int_32) [concrete = constants.%Core.IntLiteral.as.ImplicitAs.impl.Convert.specific_fn] +// CHECK:STDOUT: %bound_method.loc8_21.2: = bound_method %int_42, %specific_fn [concrete = constants.%bound_method] +// CHECK:STDOUT: %Core.IntLiteral.as.ImplicitAs.impl.Convert.call: init %i32 = call %bound_method.loc8_21.2(%int_42) [concrete = constants.%int_42.c68] +// CHECK:STDOUT: %.loc8_21.1: %i32 = value_of_initializer %Core.IntLiteral.as.ImplicitAs.impl.Convert.call [concrete = constants.%int_42.c68] +// CHECK:STDOUT: %.loc8_21.2: %i32 = converted %int_42, %.loc8_21.1 [concrete = constants.%int_42.c68] +// CHECK:STDOUT: %TakesConstInt.call: init %empty_tuple.type = call imports.%TakesConstInt.decl(%.loc8_21.2) +// CHECK:STDOUT: name_binding_decl { +// CHECK:STDOUT: %s.patt: %pattern_type.7da = binding_pattern s [concrete] +// CHECK:STDOUT: %s.var_patt: %pattern_type.7da = var_pattern %s.patt [concrete] +// CHECK:STDOUT: } +// CHECK:STDOUT: %s.var: ref %S = var %s.var_patt +// CHECK:STDOUT: %.loc10_19.1: %empty_struct_type = struct_literal () +// CHECK:STDOUT: %.loc10_19.2: init %S = class_init (), %s.var [concrete = constants.%S.val] +// CHECK:STDOUT: %.loc10_3.1: init %S = converted %.loc10_19.1, %.loc10_19.2 [concrete = constants.%S.val] +// CHECK:STDOUT: assign %s.var, %.loc10_3.1 +// CHECK:STDOUT: %.loc10_13: type = splice_block %S.ref [concrete = constants.%S] { +// CHECK:STDOUT: %Cpp.ref.loc10: = name_ref Cpp, imports.%Cpp [concrete = imports.%Cpp] +// CHECK:STDOUT: %S.ref: type = name_ref S, imports.%S.decl [concrete = constants.%S] +// CHECK:STDOUT: } +// CHECK:STDOUT: %s: ref %S = bind_name s, %s.var +// CHECK:STDOUT: %Cpp.ref.loc11: = name_ref Cpp, imports.%Cpp [concrete = imports.%Cpp] +// CHECK:STDOUT: %TakesConstS.ref: %.289 = name_ref TakesConstS, imports.%.7c2 [concrete = constants.%empty_struct.269] +// CHECK:STDOUT: %s.ref: ref %S = name_ref s, %s +// CHECK:STDOUT: %.loc11_19.1: %S = bind_value %s.ref +// CHECK:STDOUT: %.loc11_19.2: ref %S = value_as_ref %.loc11_19.1 +// CHECK:STDOUT: %addr.loc11: %ptr.5c7 = addr_of %.loc11_19.2 +// CHECK:STDOUT: %.loc11_20.1: %ptr.ff5 = as_compatible %addr.loc11 +// CHECK:STDOUT: %.loc11_20.2: %ptr.ff5 = converted %addr.loc11, %.loc11_20.1 +// CHECK:STDOUT: %TakesConstS__carbon_thunk.call: init %empty_tuple.type = call imports.%TakesConstS__carbon_thunk.decl(%.loc11_20.2) +// CHECK:STDOUT: %facet_value: %type_where = facet_value constants.%S, () [concrete = constants.%facet_value] +// CHECK:STDOUT: %.loc10_3.2: %type_where = converted constants.%S, %facet_value [concrete = constants.%facet_value] +// CHECK:STDOUT: %AggregateT.as_type.as.Destroy.impl.Op.bound: = bound_method %s.var, constants.%AggregateT.as_type.as.Destroy.impl.Op.cc2 +// CHECK:STDOUT: +// CHECK:STDOUT: %bound_method.loc10: = bound_method %s.var, %AggregateT.as_type.as.Destroy.impl.Op.specific_fn +// CHECK:STDOUT: %addr.loc10: %ptr.5c7 = addr_of %s.var +// CHECK:STDOUT: %AggregateT.as_type.as.Destroy.impl.Op.call: init %empty_tuple.type = call %bound_method.loc10(%addr.loc10) +// CHECK:STDOUT: +// CHECK:STDOUT: } +// CHECK:STDOUT: diff --git a/toolchain/check/testdata/interop/cpp/function/reference.carbon b/toolchain/check/testdata/interop/cpp/function/reference.carbon index c5ef90ff7582..f92e802e6718 100644 --- a/toolchain/check/testdata/interop/cpp/function/reference.carbon +++ b/toolchain/check/testdata/interop/cpp/function/reference.carbon @@ -402,10 +402,10 @@ fn F() { // CHECK:STDOUT: // CHECK:STDOUT: constants { // CHECK:STDOUT: %empty_tuple.type: type = tuple_type () [concrete] -// CHECK:STDOUT: %S: type = class_type @S [concrete] // CHECK:STDOUT: %.1b9: type = cpp_overload_set_type @TakesRValue [concrete] // CHECK:STDOUT: %empty_struct: %.1b9 = struct_value () [concrete] // CHECK:STDOUT: %empty_struct_type: type = struct_type {} [concrete] +// CHECK:STDOUT: %S: type = class_type @S [concrete] // CHECK:STDOUT: %S.val: %S = struct_value () [concrete] // CHECK:STDOUT: %ptr.5c7: type = ptr_type %S [concrete] // CHECK:STDOUT: %TakesRValue__carbon_thunk.type: type = fn_type @TakesRValue__carbon_thunk [concrete] @@ -422,8 +422,8 @@ fn F() { // CHECK:STDOUT: .S = %S.decl // CHECK:STDOUT: import Cpp//... // CHECK:STDOUT: } -// CHECK:STDOUT: %S.decl: type = class_decl @S [concrete = constants.%S] {} {} // CHECK:STDOUT: %.1f6: %.1b9 = cpp_overload_set_value @TakesRValue [concrete = constants.%empty_struct] +// CHECK:STDOUT: %S.decl: type = class_decl @S [concrete = constants.%S] {} {} // CHECK:STDOUT: %TakesRValue__carbon_thunk.decl: %TakesRValue__carbon_thunk.type = fn_decl @TakesRValue__carbon_thunk [concrete = constants.%TakesRValue__carbon_thunk] { // CHECK:STDOUT: // CHECK:STDOUT: } { diff --git a/toolchain/check/testdata/interop/cpp/function/struct.carbon b/toolchain/check/testdata/interop/cpp/function/struct.carbon index 8ff1c5c29ec7..daa8893380b3 100644 --- a/toolchain/check/testdata/interop/cpp/function/struct.carbon +++ b/toolchain/check/testdata/interop/cpp/function/struct.carbon @@ -525,10 +525,10 @@ fn F() { // CHECK:STDOUT: // CHECK:STDOUT: constants { // CHECK:STDOUT: %empty_tuple.type: type = tuple_type () [concrete] -// CHECK:STDOUT: %S: type = class_type @S [concrete] // CHECK:STDOUT: %.c5d: type = cpp_overload_set_type @foo [concrete] // CHECK:STDOUT: %empty_struct: %.c5d = struct_value () [concrete] // CHECK:STDOUT: %empty_struct_type: type = struct_type {} [concrete] +// CHECK:STDOUT: %S: type = class_type @S [concrete] // CHECK:STDOUT: %S.val: %S = struct_value () [concrete] // CHECK:STDOUT: %ptr.5c7: type = ptr_type %S [concrete] // CHECK:STDOUT: %foo__carbon_thunk.type: type = fn_type @foo__carbon_thunk [concrete] @@ -545,8 +545,8 @@ fn F() { // CHECK:STDOUT: .S = %S.decl // CHECK:STDOUT: import Cpp//... // CHECK:STDOUT: } -// CHECK:STDOUT: %S.decl: type = class_decl @S [concrete = constants.%S] {} {} // CHECK:STDOUT: %.a21: %.c5d = cpp_overload_set_value @foo [concrete = constants.%empty_struct] +// CHECK:STDOUT: %S.decl: type = class_decl @S [concrete = constants.%S] {} {} // CHECK:STDOUT: %foo__carbon_thunk.decl: %foo__carbon_thunk.type = fn_decl @foo__carbon_thunk [concrete = constants.%foo__carbon_thunk] { // CHECK:STDOUT: // CHECK:STDOUT: } { @@ -583,10 +583,10 @@ fn F() { // CHECK:STDOUT: // CHECK:STDOUT: constants { // CHECK:STDOUT: %empty_tuple.type: type = tuple_type () [concrete] -// CHECK:STDOUT: %S: type = class_type @S [concrete] // CHECK:STDOUT: %.c5d: type = cpp_overload_set_type @foo [concrete] // CHECK:STDOUT: %empty_struct: %.c5d = struct_value () [concrete] // CHECK:STDOUT: %empty_struct_type: type = struct_type {} [concrete] +// CHECK:STDOUT: %S: type = class_type @S [concrete] // CHECK:STDOUT: %S.val: %S = struct_value () [concrete] // CHECK:STDOUT: %foo.type: type = fn_type @foo [concrete] // CHECK:STDOUT: %foo: %foo.type = struct_value () [concrete] @@ -603,8 +603,8 @@ fn F() { // CHECK:STDOUT: .S = %S.decl // CHECK:STDOUT: import Cpp//... // CHECK:STDOUT: } -// CHECK:STDOUT: %S.decl: type = class_decl @S [concrete = constants.%S] {} {} // CHECK:STDOUT: %.a21: %.c5d = cpp_overload_set_value @foo [concrete = constants.%empty_struct] +// CHECK:STDOUT: %S.decl: type = class_decl @S [concrete = constants.%S] {} {} // CHECK:STDOUT: %foo.decl: %foo.type = fn_decl @foo [concrete = constants.%foo] { // CHECK:STDOUT: // CHECK:STDOUT: } { @@ -638,10 +638,10 @@ fn F() { // CHECK:STDOUT: --- fail_todo_import_definition_single_data_member_value_param_type.carbon // CHECK:STDOUT: // CHECK:STDOUT: constants { -// CHECK:STDOUT: %S: type = class_type @S [concrete] // CHECK:STDOUT: %.c5d: type = cpp_overload_set_type @As.Convert [concrete] // CHECK:STDOUT: %empty_struct: %.c5d = struct_value () [concrete] // CHECK:STDOUT: %empty_struct_type: type = struct_type {} [concrete] +// CHECK:STDOUT: %S: type = class_type @S [concrete] // CHECK:STDOUT: } // CHECK:STDOUT: // CHECK:STDOUT: imports { @@ -650,8 +650,8 @@ fn F() { // CHECK:STDOUT: .S = %S.decl // CHECK:STDOUT: import Cpp//... // CHECK:STDOUT: } -// CHECK:STDOUT: %S.decl: type = class_decl @S [concrete = constants.%S] {} {} // CHECK:STDOUT: %.a21: %.c5d = cpp_overload_set_value @As.Convert [concrete = constants.%empty_struct] +// CHECK:STDOUT: %S.decl: type = class_decl @S [concrete = constants.%S] {} {} // CHECK:STDOUT: } // CHECK:STDOUT: // CHECK:STDOUT: fn @F() { @@ -668,10 +668,10 @@ fn F() { // CHECK:STDOUT: --- fail_todo_import_definition_multiple_data_members_value_param_type.carbon // CHECK:STDOUT: // CHECK:STDOUT: constants { -// CHECK:STDOUT: %S: type = class_type @S [concrete] // CHECK:STDOUT: %.c5d: type = cpp_overload_set_type @As.Convert [concrete] // CHECK:STDOUT: %empty_struct: %.c5d = struct_value () [concrete] // CHECK:STDOUT: %empty_struct_type: type = struct_type {} [concrete] +// CHECK:STDOUT: %S: type = class_type @S [concrete] // CHECK:STDOUT: } // CHECK:STDOUT: // CHECK:STDOUT: imports { @@ -680,8 +680,8 @@ fn F() { // CHECK:STDOUT: .S = %S.decl // CHECK:STDOUT: import Cpp//... // CHECK:STDOUT: } -// CHECK:STDOUT: %S.decl: type = class_decl @S [concrete = constants.%S] {} {} // CHECK:STDOUT: %.a21: %.c5d = cpp_overload_set_value @As.Convert [concrete = constants.%empty_struct] +// CHECK:STDOUT: %S.decl: type = class_decl @S [concrete = constants.%S] {} {} // CHECK:STDOUT: } // CHECK:STDOUT: // CHECK:STDOUT: fn @F() { @@ -699,10 +699,10 @@ fn F() { // CHECK:STDOUT: // CHECK:STDOUT: constants { // CHECK:STDOUT: %empty_tuple.type: type = tuple_type () [concrete] -// CHECK:STDOUT: %S: type = class_type @S [concrete] // CHECK:STDOUT: %.c5d: type = cpp_overload_set_type @foo [concrete] // CHECK:STDOUT: %empty_struct: %.c5d = struct_value () [concrete] // CHECK:STDOUT: %empty_struct_type: type = struct_type {} [concrete] +// CHECK:STDOUT: %S: type = class_type @S [concrete] // CHECK:STDOUT: %S.val: %S = struct_value () [concrete] // CHECK:STDOUT: %pattern_type.cd8: type = pattern_type %S [concrete] // CHECK:STDOUT: %ptr.edf: type = ptr_type %S [concrete] @@ -720,12 +720,12 @@ fn F() { // CHECK:STDOUT: .N = %N // CHECK:STDOUT: import Cpp//... // CHECK:STDOUT: } +// CHECK:STDOUT: %.a21: %.c5d = cpp_overload_set_value @foo [concrete = constants.%empty_struct] // CHECK:STDOUT: %N: = namespace [concrete] { // CHECK:STDOUT: .S = %S.decl // CHECK:STDOUT: import Cpp//... // CHECK:STDOUT: } // CHECK:STDOUT: %S.decl: type = class_decl @S [concrete = constants.%S] {} {} -// CHECK:STDOUT: %.a21: %.c5d = cpp_overload_set_value @foo [concrete = constants.%empty_struct] // CHECK:STDOUT: %foo__carbon_thunk.decl: %foo__carbon_thunk.type = fn_decl @foo__carbon_thunk [concrete = constants.%foo__carbon_thunk] { // CHECK:STDOUT: // CHECK:STDOUT: } { @@ -781,10 +781,10 @@ fn F() { // CHECK:STDOUT: // CHECK:STDOUT: constants { // CHECK:STDOUT: %empty_tuple.type: type = tuple_type () [concrete] -// CHECK:STDOUT: %S: type = class_type @S [concrete] // CHECK:STDOUT: %.92e: type = cpp_overload_set_type @foo [concrete] // CHECK:STDOUT: %empty_struct: %.92e = struct_value () [concrete] // CHECK:STDOUT: %empty_struct_type: type = struct_type {} [concrete] +// CHECK:STDOUT: %S: type = class_type @S [concrete] // CHECK:STDOUT: %S.val: %S = struct_value () [concrete] // CHECK:STDOUT: %ptr.887: type = ptr_type %S [concrete] // CHECK:STDOUT: %foo__carbon_thunk.type: type = fn_type @foo__carbon_thunk [concrete] @@ -805,12 +805,12 @@ fn F() { // CHECK:STDOUT: .N2 = %N2 // CHECK:STDOUT: import Cpp//... // CHECK:STDOUT: } +// CHECK:STDOUT: %.218: %.92e = cpp_overload_set_value @foo [concrete = constants.%empty_struct] // CHECK:STDOUT: %N2: = namespace [concrete] { // CHECK:STDOUT: .S = %S.decl // CHECK:STDOUT: import Cpp//... // CHECK:STDOUT: } // CHECK:STDOUT: %S.decl: type = class_decl @S [concrete = constants.%S] {} {} -// CHECK:STDOUT: %.218: %.92e = cpp_overload_set_value @foo [concrete = constants.%empty_struct] // CHECK:STDOUT: %foo__carbon_thunk.decl: %foo__carbon_thunk.type = fn_decl @foo__carbon_thunk [concrete = constants.%foo__carbon_thunk] { // CHECK:STDOUT: // CHECK:STDOUT: } { @@ -850,11 +850,11 @@ fn F() { // CHECK:STDOUT: // CHECK:STDOUT: constants { // CHECK:STDOUT: %empty_tuple.type: type = tuple_type () [concrete] -// CHECK:STDOUT: %O: type = class_type @O [concrete] -// CHECK:STDOUT: %S: type = class_type @S [concrete] // CHECK:STDOUT: %.c5d: type = cpp_overload_set_type @foo [concrete] // CHECK:STDOUT: %empty_struct: %.c5d = struct_value () [concrete] // CHECK:STDOUT: %empty_struct_type: type = struct_type {} [concrete] +// CHECK:STDOUT: %O: type = class_type @O [concrete] +// CHECK:STDOUT: %S: type = class_type @S [concrete] // CHECK:STDOUT: %S.val: %S = struct_value () [concrete] // CHECK:STDOUT: %ptr.149: type = ptr_type %S [concrete] // CHECK:STDOUT: %foo__carbon_thunk.type: type = fn_type @foo__carbon_thunk [concrete] @@ -876,9 +876,9 @@ fn F() { // CHECK:STDOUT: .O = %O.decl // CHECK:STDOUT: import Cpp//... // CHECK:STDOUT: } +// CHECK:STDOUT: %.a21: %.c5d = cpp_overload_set_value @foo [concrete = constants.%empty_struct] // CHECK:STDOUT: %O.decl: type = class_decl @O [concrete = constants.%O] {} {} // CHECK:STDOUT: %S.decl: type = class_decl @S [concrete = constants.%S] {} {} -// CHECK:STDOUT: %.a21: %.c5d = cpp_overload_set_value @foo [concrete = constants.%empty_struct] // CHECK:STDOUT: %foo__carbon_thunk.decl: %foo__carbon_thunk.type = fn_decl @foo__carbon_thunk [concrete = constants.%foo__carbon_thunk] { // CHECK:STDOUT: // CHECK:STDOUT: } { @@ -1001,10 +1001,10 @@ fn F() { // CHECK:STDOUT: // CHECK:STDOUT: constants { // CHECK:STDOUT: %empty_tuple.type: type = tuple_type () [concrete] -// CHECK:STDOUT: %S: type = class_type @S [concrete] // CHECK:STDOUT: %.c5d: type = cpp_overload_set_type @foo__carbon_thunk [concrete] // CHECK:STDOUT: %empty_struct.109: %.c5d = struct_value () [concrete] // CHECK:STDOUT: %empty_struct_type: type = struct_type {} [concrete] +// CHECK:STDOUT: %S: type = class_type @S [concrete] // CHECK:STDOUT: %S.val: %S = struct_value () [concrete] // CHECK:STDOUT: %ptr.5c7: type = ptr_type %S [concrete] // CHECK:STDOUT: %foo__carbon_thunk.type: type = fn_type @foo__carbon_thunk [concrete] @@ -1025,8 +1025,8 @@ fn F() { // CHECK:STDOUT: .S = %S.decl // CHECK:STDOUT: import Cpp//... // CHECK:STDOUT: } -// CHECK:STDOUT: %S.decl: type = class_decl @S [concrete = constants.%S] {} {} // CHECK:STDOUT: %.a21: %.c5d = cpp_overload_set_value @foo__carbon_thunk [concrete = constants.%empty_struct.109] +// CHECK:STDOUT: %S.decl: type = class_decl @S [concrete = constants.%S] {} {} // CHECK:STDOUT: %foo__carbon_thunk.decl: %foo__carbon_thunk.type = fn_decl @foo__carbon_thunk [concrete = constants.%foo__carbon_thunk] { // CHECK:STDOUT: // CHECK:STDOUT: } { @@ -1141,9 +1141,9 @@ fn F() { // CHECK:STDOUT: // CHECK:STDOUT: constants { // CHECK:STDOUT: %empty_tuple.type: type = tuple_type () [concrete] -// CHECK:STDOUT: %S: type = class_type @S [concrete] // CHECK:STDOUT: %.c5d: type = cpp_overload_set_type @foo [concrete] // CHECK:STDOUT: %empty_struct: %.c5d = struct_value () [concrete] +// CHECK:STDOUT: %S: type = class_type @S [concrete] // CHECK:STDOUT: %ptr.5c7: type = ptr_type %S [concrete] // CHECK:STDOUT: %foo__carbon_thunk.type: type = fn_type @foo__carbon_thunk [concrete] // CHECK:STDOUT: %foo__carbon_thunk: %foo__carbon_thunk.type = struct_value () [concrete] @@ -1188,9 +1188,9 @@ fn F() { // CHECK:STDOUT: --- import_decl_pointer_return_type.carbon // CHECK:STDOUT: // CHECK:STDOUT: constants { -// CHECK:STDOUT: %S: type = class_type @S [concrete] // CHECK:STDOUT: %.c5d: type = cpp_overload_set_type @foo [concrete] // CHECK:STDOUT: %empty_struct: %.c5d = struct_value () [concrete] +// CHECK:STDOUT: %S: type = class_type @S [concrete] // CHECK:STDOUT: %ptr: type = ptr_type %S [concrete] // CHECK:STDOUT: %foo.type: type = fn_type @foo [concrete] // CHECK:STDOUT: %foo: %foo.type = struct_value () [concrete] @@ -1220,9 +1220,9 @@ fn F() { // CHECK:STDOUT: --- import_definition_pointer_return_type.carbon // CHECK:STDOUT: // CHECK:STDOUT: constants { -// CHECK:STDOUT: %S: type = class_type @S [concrete] // CHECK:STDOUT: %.c5d: type = cpp_overload_set_type @foo [concrete] // CHECK:STDOUT: %empty_struct: %.c5d = struct_value () [concrete] +// CHECK:STDOUT: %S: type = class_type @S [concrete] // CHECK:STDOUT: %ptr: type = ptr_type %S [concrete] // CHECK:STDOUT: %foo.type: type = fn_type @foo [concrete] // CHECK:STDOUT: %foo: %foo.type = struct_value () [concrete] diff --git a/toolchain/check/testdata/interop/cpp/function/union.carbon b/toolchain/check/testdata/interop/cpp/function/union.carbon index 794484b1b181..7b38dc0ec050 100644 --- a/toolchain/check/testdata/interop/cpp/function/union.carbon +++ b/toolchain/check/testdata/interop/cpp/function/union.carbon @@ -486,10 +486,10 @@ fn F() { // CHECK:STDOUT: --- fail_import_decl_value_param_type.carbon // CHECK:STDOUT: // CHECK:STDOUT: constants { -// CHECK:STDOUT: %U: type = class_type @U [concrete] // CHECK:STDOUT: %.c5d: type = cpp_overload_set_type @ [concrete] // CHECK:STDOUT: %empty_struct: %.c5d = struct_value () [concrete] // CHECK:STDOUT: %empty_struct_type: type = struct_type {} [concrete] +// CHECK:STDOUT: %U: type = class_type @U [concrete] // CHECK:STDOUT: } // CHECK:STDOUT: // CHECK:STDOUT: imports { @@ -498,8 +498,8 @@ fn F() { // CHECK:STDOUT: .U = %U.decl // CHECK:STDOUT: import Cpp//... // CHECK:STDOUT: } -// CHECK:STDOUT: %U.decl: type = class_decl @U [concrete = constants.%U] {} {} // CHECK:STDOUT: %.a21: %.c5d = cpp_overload_set_value @ [concrete = constants.%empty_struct] +// CHECK:STDOUT: %U.decl: type = class_decl @U [concrete = constants.%U] {} {} // CHECK:STDOUT: } // CHECK:STDOUT: // CHECK:STDOUT: fn @F() { @@ -516,10 +516,10 @@ fn F() { // CHECK:STDOUT: // CHECK:STDOUT: constants { // CHECK:STDOUT: %empty_tuple.type: type = tuple_type () [concrete] -// CHECK:STDOUT: %U: type = class_type @U [concrete] // CHECK:STDOUT: %.c5d: type = cpp_overload_set_type @foo [concrete] // CHECK:STDOUT: %empty_struct: %.c5d = struct_value () [concrete] // CHECK:STDOUT: %empty_struct_type: type = struct_type {} [concrete] +// CHECK:STDOUT: %U: type = class_type @U [concrete] // CHECK:STDOUT: %U.val: %U = struct_value () [concrete] // CHECK:STDOUT: %ptr.86f: type = ptr_type %U [concrete] // CHECK:STDOUT: %foo__carbon_thunk.type: type = fn_type @foo__carbon_thunk [concrete] @@ -536,8 +536,8 @@ fn F() { // CHECK:STDOUT: .U = %U.decl // CHECK:STDOUT: import Cpp//... // CHECK:STDOUT: } -// CHECK:STDOUT: %U.decl: type = class_decl @U [concrete = constants.%U] {} {} // CHECK:STDOUT: %.a21: %.c5d = cpp_overload_set_value @foo [concrete = constants.%empty_struct] +// CHECK:STDOUT: %U.decl: type = class_decl @U [concrete = constants.%U] {} {} // CHECK:STDOUT: %foo__carbon_thunk.decl: %foo__carbon_thunk.type = fn_decl @foo__carbon_thunk [concrete = constants.%foo__carbon_thunk] { // CHECK:STDOUT: // CHECK:STDOUT: } { @@ -573,10 +573,10 @@ fn F() { // CHECK:STDOUT: --- fail_import_definition_single_data_member_value_param_type.carbon // CHECK:STDOUT: // CHECK:STDOUT: constants { -// CHECK:STDOUT: %U: type = class_type @U [concrete] // CHECK:STDOUT: %.c5d: type = cpp_overload_set_type @As.Convert [concrete] // CHECK:STDOUT: %empty_struct: %.c5d = struct_value () [concrete] // CHECK:STDOUT: %empty_struct_type: type = struct_type {} [concrete] +// CHECK:STDOUT: %U: type = class_type @U [concrete] // CHECK:STDOUT: } // CHECK:STDOUT: // CHECK:STDOUT: imports { @@ -585,8 +585,8 @@ fn F() { // CHECK:STDOUT: .U = %U.decl // CHECK:STDOUT: import Cpp//... // CHECK:STDOUT: } -// CHECK:STDOUT: %U.decl: type = class_decl @U [concrete = constants.%U] {} {} // CHECK:STDOUT: %.a21: %.c5d = cpp_overload_set_value @As.Convert [concrete = constants.%empty_struct] +// CHECK:STDOUT: %U.decl: type = class_decl @U [concrete = constants.%U] {} {} // CHECK:STDOUT: } // CHECK:STDOUT: // CHECK:STDOUT: fn @F() { @@ -603,10 +603,10 @@ fn F() { // CHECK:STDOUT: --- fail_import_definition_multiple_data_members_value_param_type.carbon // CHECK:STDOUT: // CHECK:STDOUT: constants { -// CHECK:STDOUT: %U: type = class_type @U [concrete] // CHECK:STDOUT: %.c5d: type = cpp_overload_set_type @As.Convert [concrete] // CHECK:STDOUT: %empty_struct: %.c5d = struct_value () [concrete] // CHECK:STDOUT: %empty_struct_type: type = struct_type {} [concrete] +// CHECK:STDOUT: %U: type = class_type @U [concrete] // CHECK:STDOUT: } // CHECK:STDOUT: // CHECK:STDOUT: imports { @@ -615,8 +615,8 @@ fn F() { // CHECK:STDOUT: .U = %U.decl // CHECK:STDOUT: import Cpp//... // CHECK:STDOUT: } -// CHECK:STDOUT: %U.decl: type = class_decl @U [concrete = constants.%U] {} {} // CHECK:STDOUT: %.a21: %.c5d = cpp_overload_set_value @As.Convert [concrete = constants.%empty_struct] +// CHECK:STDOUT: %U.decl: type = class_decl @U [concrete = constants.%U] {} {} // CHECK:STDOUT: } // CHECK:STDOUT: // CHECK:STDOUT: fn @F() { @@ -634,10 +634,10 @@ fn F() { // CHECK:STDOUT: // CHECK:STDOUT: constants { // CHECK:STDOUT: %empty_tuple.type: type = tuple_type () [concrete] -// CHECK:STDOUT: %U: type = class_type @U [concrete] // CHECK:STDOUT: %.c5d: type = cpp_overload_set_type @foo [concrete] // CHECK:STDOUT: %empty_struct: %.c5d = struct_value () [concrete] // CHECK:STDOUT: %empty_struct_type: type = struct_type {} [concrete] +// CHECK:STDOUT: %U: type = class_type @U [concrete] // CHECK:STDOUT: %U.val: %U = struct_value () [concrete] // CHECK:STDOUT: %pattern_type.eb9: type = pattern_type %U [concrete] // CHECK:STDOUT: %ptr.87e: type = ptr_type %U [concrete] @@ -655,12 +655,12 @@ fn F() { // CHECK:STDOUT: .N = %N // CHECK:STDOUT: import Cpp//... // CHECK:STDOUT: } +// CHECK:STDOUT: %.a21: %.c5d = cpp_overload_set_value @foo [concrete = constants.%empty_struct] // CHECK:STDOUT: %N: = namespace [concrete] { // CHECK:STDOUT: .U = %U.decl // CHECK:STDOUT: import Cpp//... // CHECK:STDOUT: } // CHECK:STDOUT: %U.decl: type = class_decl @U [concrete = constants.%U] {} {} -// CHECK:STDOUT: %.a21: %.c5d = cpp_overload_set_value @foo [concrete = constants.%empty_struct] // CHECK:STDOUT: %foo__carbon_thunk.decl: %foo__carbon_thunk.type = fn_decl @foo__carbon_thunk [concrete = constants.%foo__carbon_thunk] { // CHECK:STDOUT: // CHECK:STDOUT: } { @@ -716,10 +716,10 @@ fn F() { // CHECK:STDOUT: // CHECK:STDOUT: constants { // CHECK:STDOUT: %empty_tuple.type: type = tuple_type () [concrete] -// CHECK:STDOUT: %U: type = class_type @U [concrete] // CHECK:STDOUT: %.92e: type = cpp_overload_set_type @foo [concrete] // CHECK:STDOUT: %empty_struct: %.92e = struct_value () [concrete] // CHECK:STDOUT: %empty_struct_type: type = struct_type {} [concrete] +// CHECK:STDOUT: %U: type = class_type @U [concrete] // CHECK:STDOUT: %U.val: %U = struct_value () [concrete] // CHECK:STDOUT: %ptr.8c1: type = ptr_type %U [concrete] // CHECK:STDOUT: %foo__carbon_thunk.type: type = fn_type @foo__carbon_thunk [concrete] @@ -740,12 +740,12 @@ fn F() { // CHECK:STDOUT: .N2 = %N2 // CHECK:STDOUT: import Cpp//... // CHECK:STDOUT: } +// CHECK:STDOUT: %.218: %.92e = cpp_overload_set_value @foo [concrete = constants.%empty_struct] // CHECK:STDOUT: %N2: = namespace [concrete] { // CHECK:STDOUT: .U = %U.decl // CHECK:STDOUT: import Cpp//... // CHECK:STDOUT: } // CHECK:STDOUT: %U.decl: type = class_decl @U [concrete = constants.%U] {} {} -// CHECK:STDOUT: %.218: %.92e = cpp_overload_set_value @foo [concrete = constants.%empty_struct] // CHECK:STDOUT: %foo__carbon_thunk.decl: %foo__carbon_thunk.type = fn_decl @foo__carbon_thunk [concrete = constants.%foo__carbon_thunk] { // CHECK:STDOUT: // CHECK:STDOUT: } { @@ -785,11 +785,11 @@ fn F() { // CHECK:STDOUT: // CHECK:STDOUT: constants { // CHECK:STDOUT: %empty_tuple.type: type = tuple_type () [concrete] -// CHECK:STDOUT: %O: type = class_type @O [concrete] -// CHECK:STDOUT: %U: type = class_type @U [concrete] // CHECK:STDOUT: %.c5d: type = cpp_overload_set_type @foo [concrete] // CHECK:STDOUT: %empty_struct: %.c5d = struct_value () [concrete] // CHECK:STDOUT: %empty_struct_type: type = struct_type {} [concrete] +// CHECK:STDOUT: %O: type = class_type @O [concrete] +// CHECK:STDOUT: %U: type = class_type @U [concrete] // CHECK:STDOUT: %U.val: %U = struct_value () [concrete] // CHECK:STDOUT: %ptr.a6c: type = ptr_type %U [concrete] // CHECK:STDOUT: %foo__carbon_thunk.type: type = fn_type @foo__carbon_thunk [concrete] @@ -811,9 +811,9 @@ fn F() { // CHECK:STDOUT: .O = %O.decl // CHECK:STDOUT: import Cpp//... // CHECK:STDOUT: } +// CHECK:STDOUT: %.a21: %.c5d = cpp_overload_set_value @foo [concrete = constants.%empty_struct] // CHECK:STDOUT: %O.decl: type = class_decl @O [concrete = constants.%O] {} {} // CHECK:STDOUT: %U.decl: type = class_decl @U [concrete = constants.%U] {} {} -// CHECK:STDOUT: %.a21: %.c5d = cpp_overload_set_value @foo [concrete = constants.%empty_struct] // CHECK:STDOUT: %foo__carbon_thunk.decl: %foo__carbon_thunk.type = fn_decl @foo__carbon_thunk [concrete = constants.%foo__carbon_thunk] { // CHECK:STDOUT: // CHECK:STDOUT: } { @@ -936,10 +936,10 @@ fn F() { // CHECK:STDOUT: // CHECK:STDOUT: constants { // CHECK:STDOUT: %empty_tuple.type: type = tuple_type () [concrete] -// CHECK:STDOUT: %U: type = class_type @U [concrete] // CHECK:STDOUT: %.c5d: type = cpp_overload_set_type @foo__carbon_thunk [concrete] // CHECK:STDOUT: %empty_struct.109: %.c5d = struct_value () [concrete] // CHECK:STDOUT: %empty_struct_type: type = struct_type {} [concrete] +// CHECK:STDOUT: %U: type = class_type @U [concrete] // CHECK:STDOUT: %U.val: %U = struct_value () [concrete] // CHECK:STDOUT: %ptr.86f: type = ptr_type %U [concrete] // CHECK:STDOUT: %foo__carbon_thunk.type: type = fn_type @foo__carbon_thunk [concrete] @@ -960,8 +960,8 @@ fn F() { // CHECK:STDOUT: .U = %U.decl // CHECK:STDOUT: import Cpp//... // CHECK:STDOUT: } -// CHECK:STDOUT: %U.decl: type = class_decl @U [concrete = constants.%U] {} {} // CHECK:STDOUT: %.a21: %.c5d = cpp_overload_set_value @foo__carbon_thunk [concrete = constants.%empty_struct.109] +// CHECK:STDOUT: %U.decl: type = class_decl @U [concrete = constants.%U] {} {} // CHECK:STDOUT: %foo__carbon_thunk.decl: %foo__carbon_thunk.type = fn_decl @foo__carbon_thunk [concrete = constants.%foo__carbon_thunk] { // CHECK:STDOUT: // CHECK:STDOUT: } { @@ -1076,9 +1076,9 @@ fn F() { // CHECK:STDOUT: // CHECK:STDOUT: constants { // CHECK:STDOUT: %empty_tuple.type: type = tuple_type () [concrete] -// CHECK:STDOUT: %U: type = class_type @U [concrete] // CHECK:STDOUT: %.c5d: type = cpp_overload_set_type @foo [concrete] // CHECK:STDOUT: %empty_struct: %.c5d = struct_value () [concrete] +// CHECK:STDOUT: %U: type = class_type @U [concrete] // CHECK:STDOUT: %ptr.86f: type = ptr_type %U [concrete] // CHECK:STDOUT: %foo__carbon_thunk.type: type = fn_type @foo__carbon_thunk [concrete] // CHECK:STDOUT: %foo__carbon_thunk: %foo__carbon_thunk.type = struct_value () [concrete] @@ -1123,9 +1123,9 @@ fn F() { // CHECK:STDOUT: --- import_decl_pointer_return_type.carbon // CHECK:STDOUT: // CHECK:STDOUT: constants { -// CHECK:STDOUT: %U: type = class_type @U [concrete] // CHECK:STDOUT: %.c5d: type = cpp_overload_set_type @foo [concrete] // CHECK:STDOUT: %empty_struct: %.c5d = struct_value () [concrete] +// CHECK:STDOUT: %U: type = class_type @U [concrete] // CHECK:STDOUT: %ptr: type = ptr_type %U [concrete] // CHECK:STDOUT: %foo.type: type = fn_type @foo [concrete] // CHECK:STDOUT: %foo: %foo.type = struct_value () [concrete] @@ -1155,9 +1155,9 @@ fn F() { // CHECK:STDOUT: --- import_definition_pointer_return_type.carbon // CHECK:STDOUT: // CHECK:STDOUT: constants { -// CHECK:STDOUT: %U: type = class_type @U [concrete] // CHECK:STDOUT: %.c5d: type = cpp_overload_set_type @foo [concrete] // CHECK:STDOUT: %empty_struct: %.c5d = struct_value () [concrete] +// CHECK:STDOUT: %U: type = class_type @U [concrete] // CHECK:STDOUT: %ptr: type = ptr_type %U [concrete] // CHECK:STDOUT: %foo.type: type = fn_type @foo [concrete] // CHECK:STDOUT: %foo: %foo.type = struct_value () [concrete] diff --git a/toolchain/check/testdata/interop/cpp/namespace.carbon b/toolchain/check/testdata/interop/cpp/namespace.carbon index 5ef4d426a2ad..768f75fe7758 100644 --- a/toolchain/check/testdata/interop/cpp/namespace.carbon +++ b/toolchain/check/testdata/interop/cpp/namespace.carbon @@ -366,9 +366,9 @@ fn Use(y: Cpp.Y) -> i32 { // CHECK:STDOUT: // CHECK:STDOUT: constants { // CHECK:STDOUT: %empty_tuple.type: type = tuple_type () [concrete] -// CHECK:STDOUT: %X: type = class_type @X [concrete] // CHECK:STDOUT: %.c5d: type = cpp_overload_set_type @foo [concrete] // CHECK:STDOUT: %empty_struct: %.c5d = struct_value () [concrete] +// CHECK:STDOUT: %X: type = class_type @X [concrete] // CHECK:STDOUT: %ptr.13d: type = ptr_type %X [concrete] // CHECK:STDOUT: %foo__carbon_thunk.type: type = fn_type @foo__carbon_thunk [concrete] // CHECK:STDOUT: %foo__carbon_thunk: %foo__carbon_thunk.type = struct_value () [concrete] diff --git a/toolchain/check/testdata/interop/cpp/stdlib/string_view.carbon b/toolchain/check/testdata/interop/cpp/stdlib/string_view.carbon index 27643c12dbfe..e11f6ef06542 100644 --- a/toolchain/check/testdata/interop/cpp/stdlib/string_view.carbon +++ b/toolchain/check/testdata/interop/cpp/stdlib/string_view.carbon @@ -60,14 +60,14 @@ fn G() -> str { // CHECK:STDOUT: %F.type: type = fn_type @F [concrete] // CHECK:STDOUT: %empty_tuple.type: type = tuple_type () [concrete] // CHECK:STDOUT: %F: %F.type = struct_value () [concrete] +// CHECK:STDOUT: %.fd2: type = cpp_overload_set_type @Consume__carbon_thunk [concrete] +// CHECK:STDOUT: %empty_struct.c28: %.fd2 = struct_value () [concrete] // CHECK:STDOUT: %str.ee0: type = class_type @String [concrete] // CHECK:STDOUT: %int_64: Core.IntLiteral = int_value 64 [concrete] // CHECK:STDOUT: %u64: type = class_type @UInt, @UInt(%int_64) [concrete] // CHECK:STDOUT: %int_8: Core.IntLiteral = int_value 8 [concrete] // CHECK:STDOUT: %u8: type = class_type @UInt, @UInt(%int_8) [concrete] // CHECK:STDOUT: %ptr.3e8: type = ptr_type %u8 [concrete] -// CHECK:STDOUT: %.fd2: type = cpp_overload_set_type @Consume__carbon_thunk [concrete] -// CHECK:STDOUT: %empty_struct.c28: %.fd2 = struct_value () [concrete] // CHECK:STDOUT: %str.3b1: %ptr.3e8 = string_literal "hello" [concrete] // CHECK:STDOUT: %int_5: %u64 = int_value 5 [concrete] // CHECK:STDOUT: %String.val: %str.ee0 = struct_value (%str.3b1, %int_5) [concrete] diff --git a/toolchain/driver/testdata/stdin.carbon b/toolchain/driver/testdata/stdin.carbon index 53f9f2e450b8..62dbcdfeb907 100644 --- a/toolchain/driver/testdata/stdin.carbon +++ b/toolchain/driver/testdata/stdin.carbon @@ -30,6 +30,7 @@ // CHECK:STDOUT: ir0: {decl_id: inst, is_export: false} // CHECK:STDOUT: ir1: {decl_id: inst, is_export: false} // CHECK:STDOUT: import_ir_insts: {} +// CHECK:STDOUT: clang_decls: {} // CHECK:STDOUT: name_scopes: // CHECK:STDOUT: name_scope0: {inst: inst14, parent_scope: name_scope, has_error: false, extended_scopes: [], names: {}} // CHECK:STDOUT: entity_names: {} diff --git a/toolchain/lower/file_context.cpp b/toolchain/lower/file_context.cpp index b18af64c61da..b352745380ac 100644 --- a/toolchain/lower/file_context.cpp +++ b/toolchain/lower/file_context.cpp @@ -437,6 +437,20 @@ auto FileContext::BuildFunctionDecl(SemIR::FunctionId function_id, return nullptr; } + // Don't lower C++ functions that use a thunk. We will never reference them + // directly, and their signatures would not be expected to match the + // corresponding C++ function anyway. + if (function.special_function_kind == + SemIR::Function::SpecialFunctionKind::HasCppThunk) { + // Make sure Clang emits this function. + // TODO: This shouldn't be necessary: Clang should emit definitions of + // functions that it emits calls to. But this doesn't currently work. + auto clang_decl_id = sem_ir().functions().Get(function_id).clang_decl_id; + HandleReferencedCppFunction(cast( + sem_ir().clang_decls().Get(clang_decl_id).key.decl)); + return nullptr; + } + // TODO: Consider tracking whether the function has been used, and only // lowering it if it's needed. @@ -467,7 +481,7 @@ auto FileContext::BuildFunctionDecl(SemIR::FunctionId function_id, CARBON_CHECK(!specific_id.has_value(), "Specific functions cannot have C++ definitions"); HandleReferencedCppFunction( - sem_ir().clang_decls().Get(clang_decl_id).decl->getAsFunction()); + sem_ir().clang_decls().Get(clang_decl_id).key.decl->getAsFunction()); // TODO: Check that the signature and mangling generated by Clang and the // one we generated are the same. } diff --git a/toolchain/lower/mangler.cpp b/toolchain/lower/mangler.cpp index 45e7ae8ce79f..572a310031ec 100644 --- a/toolchain/lower/mangler.cpp +++ b/toolchain/lower/mangler.cpp @@ -151,8 +151,11 @@ auto Mangler::Mangle(SemIR::FunctionId function_id, return "main"; } if (function.clang_decl_id.has_value()) { - return MangleCppClang(cast( - sem_ir().clang_decls().Get(function.clang_decl_id).decl)); + CARBON_CHECK(function.special_function_kind != + SemIR::Function::SpecialFunctionKind::HasCppThunk, + "Shouldn't mangle C++ function that uses a thunk"); + const auto& clang_decl = sem_ir().clang_decls().Get(function.clang_decl_id); + return MangleCppClang(cast(clang_decl.key.decl)); } RawStringOstream os; os << "_C"; @@ -208,7 +211,7 @@ auto Mangler::MangleGlobalVariable(SemIR::InstId pattern_id) -> std::string { auto var_name = sem_ir().entity_names().Get(var_name_id); if (var_name.clang_decl_id.has_value()) { return MangleCppClang(cast( - sem_ir().clang_decls().Get(var_name.clang_decl_id).decl)); + sem_ir().clang_decls().Get(var_name.clang_decl_id).key.decl)); } RawStringOstream os; diff --git a/toolchain/lower/testdata/interop/cpp/constructor.carbon b/toolchain/lower/testdata/interop/cpp/constructor.carbon index a63748f14e1e..956a7c721eb0 100644 --- a/toolchain/lower/testdata/interop/cpp/constructor.carbon +++ b/toolchain/lower/testdata/interop/cpp/constructor.carbon @@ -57,8 +57,18 @@ fn F() { // CHECK:STDOUT: ; Function Attrs: nocallback nofree nosync nounwind willreturn memory(argmem: readwrite) // CHECK:STDOUT: declare void @llvm.lifetime.start.p0(ptr captures(none)) #0 // CHECK:STDOUT: +// CHECK:STDOUT: ; Function Attrs: alwaysinline mustprogress +// CHECK:STDOUT: define dso_local void @_ZN1CC1Ev.carbon_thunk(ptr %return) #1 { +// CHECK:STDOUT: entry: +// CHECK:STDOUT: %return.addr = alloca ptr, align 8 +// CHECK:STDOUT: store ptr %return, ptr %return.addr, align 8 +// CHECK:STDOUT: %0 = load ptr, ptr %return.addr, align 8 +// CHECK:STDOUT: call void @_ZN1CC1Ev(ptr nonnull align 4 dereferenceable(8) %0) +// CHECK:STDOUT: ret void +// CHECK:STDOUT: } +// CHECK:STDOUT: // CHECK:STDOUT: ; Function Attrs: mustprogress noinline optnone -// CHECK:STDOUT: define linkonce_odr dso_local void @_ZN1CC1Ev(ptr nonnull align 4 dereferenceable(8) %this) #1 comdat align 2 { +// CHECK:STDOUT: define linkonce_odr dso_local void @_ZN1CC1Ev(ptr nonnull align 4 dereferenceable(8) %this) unnamed_addr #2 comdat align 2 { // CHECK:STDOUT: entry: // CHECK:STDOUT: %this.addr = alloca ptr, align 8 // CHECK:STDOUT: store ptr %this, ptr %this.addr, align 8 @@ -68,7 +78,7 @@ fn F() { // CHECK:STDOUT: } // CHECK:STDOUT: // CHECK:STDOUT: ; Function Attrs: mustprogress noinline nounwind optnone -// CHECK:STDOUT: define linkonce_odr dso_local void @_ZN1CC2Ev(ptr nonnull align 4 dereferenceable(8) %this) unnamed_addr #2 comdat align 2 { +// CHECK:STDOUT: define linkonce_odr dso_local void @_ZN1CC2Ev(ptr nonnull align 4 dereferenceable(8) %this) unnamed_addr #3 comdat align 2 { // CHECK:STDOUT: entry: // CHECK:STDOUT: %this.addr = alloca ptr, align 8 // CHECK:STDOUT: store ptr %this, ptr %this.addr, align 8 @@ -80,20 +90,10 @@ fn F() { // CHECK:STDOUT: ret void // CHECK:STDOUT: } // CHECK:STDOUT: -// CHECK:STDOUT: ; Function Attrs: alwaysinline mustprogress -// CHECK:STDOUT: define dso_local void @_ZN1CC1Ev.carbon_thunk(ptr %return) #3 { -// CHECK:STDOUT: entry: -// CHECK:STDOUT: %return.addr = alloca ptr, align 8 -// CHECK:STDOUT: store ptr %return, ptr %return.addr, align 8 -// CHECK:STDOUT: %0 = load ptr, ptr %return.addr, align 8 -// CHECK:STDOUT: call void @_ZN1CC1Ev(ptr nonnull align 4 dereferenceable(8) %0) -// CHECK:STDOUT: ret void -// CHECK:STDOUT: } -// CHECK:STDOUT: // CHECK:STDOUT: attributes #0 = { nocallback nofree nosync nounwind willreturn memory(argmem: readwrite) } -// CHECK:STDOUT: attributes #1 = { mustprogress noinline optnone "min-legal-vector-width"="0" "no-trapping-math"="true" "stack-protector-buffer-size"="0" "target-cpu"="x86-64" "target-features"="+cmov,+cx8,+fxsr,+mmx,+sse,+sse2,+x87" "tune-cpu"="generic" } -// CHECK:STDOUT: attributes #2 = { mustprogress noinline nounwind optnone "min-legal-vector-width"="0" "no-trapping-math"="true" "stack-protector-buffer-size"="0" "target-cpu"="x86-64" "target-features"="+cmov,+cx8,+fxsr,+mmx,+sse,+sse2,+x87" "tune-cpu"="generic" } -// CHECK:STDOUT: attributes #3 = { alwaysinline mustprogress "min-legal-vector-width"="0" "no-trapping-math"="true" "stack-protector-buffer-size"="0" "target-cpu"="x86-64" "target-features"="+cmov,+cx8,+fxsr,+mmx,+sse,+sse2,+x87" "tune-cpu"="generic" } +// CHECK:STDOUT: attributes #1 = { alwaysinline mustprogress "min-legal-vector-width"="0" "no-trapping-math"="true" "stack-protector-buffer-size"="0" "target-cpu"="x86-64" "target-features"="+cmov,+cx8,+fxsr,+mmx,+sse,+sse2,+x87" "tune-cpu"="generic" } +// CHECK:STDOUT: attributes #2 = { mustprogress noinline optnone "min-legal-vector-width"="0" "no-trapping-math"="true" "stack-protector-buffer-size"="0" "target-cpu"="x86-64" "target-features"="+cmov,+cx8,+fxsr,+mmx,+sse,+sse2,+x87" "tune-cpu"="generic" } +// CHECK:STDOUT: attributes #3 = { mustprogress noinline nounwind optnone "min-legal-vector-width"="0" "no-trapping-math"="true" "stack-protector-buffer-size"="0" "target-cpu"="x86-64" "target-features"="+cmov,+cx8,+fxsr,+mmx,+sse,+sse2,+x87" "tune-cpu"="generic" } // CHECK:STDOUT: // CHECK:STDOUT: !llvm.module.flags = !{!0, !1, !2, !3, !4} // CHECK:STDOUT: !llvm.dbg.cu = !{!5} diff --git a/toolchain/lower/testdata/interop/cpp/enum.carbon b/toolchain/lower/testdata/interop/cpp/enum.carbon index b1b5cd5c3b7c..820dbf1f0816 100644 --- a/toolchain/lower/testdata/interop/cpp/enum.carbon +++ b/toolchain/lower/testdata/interop/cpp/enum.carbon @@ -120,8 +120,6 @@ fn Call() { // CHECK:STDOUT: ret void, !dbg !24 // CHECK:STDOUT: } // CHECK:STDOUT: -// CHECK:STDOUT: declare void @_ZN1C1FENS_1EE(i16) -// CHECK:STDOUT: // CHECK:STDOUT: ; Function Attrs: nocallback nofree nosync nounwind willreturn memory(argmem: readwrite) // CHECK:STDOUT: declare void @llvm.lifetime.start.p0(ptr captures(none)) #0 // CHECK:STDOUT: @@ -136,11 +134,14 @@ fn Call() { // CHECK:STDOUT: ret void // CHECK:STDOUT: } // CHECK:STDOUT: +// CHECK:STDOUT: declare void @_ZN1C1FENS_1EE(i16 signext) #2 +// CHECK:STDOUT: // CHECK:STDOUT: ; uselistorder directives // CHECK:STDOUT: uselistorder ptr @llvm.lifetime.start.p0, { 6, 5, 4, 3, 2, 1, 0 } // CHECK:STDOUT: // CHECK:STDOUT: attributes #0 = { nocallback nofree nosync nounwind willreturn memory(argmem: readwrite) } // CHECK:STDOUT: attributes #1 = { alwaysinline mustprogress "min-legal-vector-width"="0" "no-trapping-math"="true" "stack-protector-buffer-size"="0" "target-cpu"="x86-64" "target-features"="+cmov,+cx8,+fxsr,+mmx,+sse,+sse2,+x87" "tune-cpu"="generic" } +// CHECK:STDOUT: attributes #2 = { "no-trapping-math"="true" "stack-protector-buffer-size"="0" "target-cpu"="x86-64" "target-features"="+cmov,+cx8,+fxsr,+mmx,+sse,+sse2,+x87" "tune-cpu"="generic" } // CHECK:STDOUT: // CHECK:STDOUT: !llvm.module.flags = !{!0, !1, !2, !3, !4} // CHECK:STDOUT: !llvm.dbg.cu = !{!5} @@ -198,8 +199,6 @@ fn Call() { // CHECK:STDOUT: ret void, !dbg !18 // CHECK:STDOUT: } // CHECK:STDOUT: -// CHECK:STDOUT: declare void @_ZN1C1FENS_1EE(i16) -// CHECK:STDOUT: // CHECK:STDOUT: ; Function Attrs: nocallback nofree nosync nounwind willreturn memory(argmem: readwrite) // CHECK:STDOUT: declare void @llvm.lifetime.start.p0(ptr captures(none)) #0 // CHECK:STDOUT: @@ -214,8 +213,11 @@ fn Call() { // CHECK:STDOUT: ret void // CHECK:STDOUT: } // CHECK:STDOUT: +// CHECK:STDOUT: declare void @_ZN1C1FENS_1EE(i16 signext) #2 +// CHECK:STDOUT: // CHECK:STDOUT: attributes #0 = { nocallback nofree nosync nounwind willreturn memory(argmem: readwrite) } // CHECK:STDOUT: attributes #1 = { alwaysinline mustprogress "min-legal-vector-width"="0" "no-trapping-math"="true" "stack-protector-buffer-size"="0" "target-cpu"="x86-64" "target-features"="+cmov,+cx8,+fxsr,+mmx,+sse,+sse2,+x87" "tune-cpu"="generic" } +// CHECK:STDOUT: attributes #2 = { "no-trapping-math"="true" "stack-protector-buffer-size"="0" "target-cpu"="x86-64" "target-features"="+cmov,+cx8,+fxsr,+mmx,+sse,+sse2,+x87" "tune-cpu"="generic" } // CHECK:STDOUT: // CHECK:STDOUT: !llvm.module.flags = !{!0, !1, !2, !3, !4} // CHECK:STDOUT: !llvm.dbg.cu = !{!5} diff --git a/toolchain/lower/testdata/interop/cpp/extern_c.carbon b/toolchain/lower/testdata/interop/cpp/extern_c.carbon index eeadbdf81e12..eb67435fb4b5 100644 --- a/toolchain/lower/testdata/interop/cpp/extern_c.carbon +++ b/toolchain/lower/testdata/interop/cpp/extern_c.carbon @@ -153,8 +153,6 @@ fn MyF() { // CHECK:STDOUT: ret void, !dbg !11 // CHECK:STDOUT: } // CHECK:STDOUT: -// CHECK:STDOUT: declare void @_Zpl1XS_(ptr sret({}), ptr, ptr) -// CHECK:STDOUT: // CHECK:STDOUT: ; Function Attrs: alwaysinline mustprogress // CHECK:STDOUT: define dso_local void @_Zpl1XS_.carbon_thunk(ptr %0, ptr %1, ptr %return) #0 { // CHECK:STDOUT: entry: @@ -174,7 +172,10 @@ fn MyF() { // CHECK:STDOUT: ret void // CHECK:STDOUT: } // CHECK:STDOUT: +// CHECK:STDOUT: declare void @_Zpl1XS_() #1 +// CHECK:STDOUT: // CHECK:STDOUT: attributes #0 = { alwaysinline mustprogress "min-legal-vector-width"="0" "no-trapping-math"="true" "stack-protector-buffer-size"="0" "target-cpu"="x86-64" "target-features"="+cmov,+cx8,+fxsr,+mmx,+sse,+sse2,+x87" "tune-cpu"="generic" } +// CHECK:STDOUT: attributes #1 = { "no-trapping-math"="true" "stack-protector-buffer-size"="0" "target-cpu"="x86-64" "target-features"="+cmov,+cx8,+fxsr,+mmx,+sse,+sse2,+x87" "tune-cpu"="generic" } // CHECK:STDOUT: // CHECK:STDOUT: !llvm.module.flags = !{!0, !1, !2, !3, !4} // CHECK:STDOUT: !llvm.dbg.cu = !{!5} diff --git a/toolchain/lower/testdata/interop/cpp/function_decl.carbon b/toolchain/lower/testdata/interop/cpp/function_decl.carbon index a051aa878ba6..f46d7325564b 100644 --- a/toolchain/lower/testdata/interop/cpp/function_decl.carbon +++ b/toolchain/lower/testdata/interop/cpp/function_decl.carbon @@ -2,7 +2,7 @@ // Exceptions. See /LICENSE for license information. // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // -// INCLUDE-FILE: toolchain/testing/testdata/min_prelude/convert.carbon +// INCLUDE-FILE: toolchain/testing/testdata/min_prelude/int.carbon // // AUTOUPDATE // TIP: To test this file alone, run: @@ -106,6 +106,26 @@ fn MyF() { Cpp.foo2(); } +// ============================================================================ +// Default arguments +// ============================================================================ + +// --- with_default_args.h + +void F(int a = 1, int b = 2); + +// --- call_with_default_args.carbon + +library "[[@TEST_NAME]]"; + +import Cpp library "with_default_args.h"; + +fn MyF() { + Cpp.F(); + Cpp.F(3); + Cpp.F(3, 4); +} + // CHECK:STDOUT: ; ModuleID = 'import_function_decl.carbon' // CHECK:STDOUT: source_filename = "import_function_decl.carbon" // CHECK:STDOUT: target datalayout = "e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-i128:128-f80:128-n8:16:32:64-S128" @@ -307,3 +327,54 @@ fn MyF() { // CHECK:STDOUT: !9 = !{} // CHECK:STDOUT: !10 = !DILocation(line: 8, column: 3, scope: !7) // CHECK:STDOUT: !11 = !DILocation(line: 6, column: 1, scope: !7) +// CHECK:STDOUT: ; ModuleID = 'call_with_default_args.carbon' +// CHECK:STDOUT: source_filename = "call_with_default_args.carbon" +// CHECK:STDOUT: target datalayout = "e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-i128:128-f80:128-n8:16:32:64-S128" +// CHECK:STDOUT: target triple = "x86_64-unknown-linux-gnu" +// CHECK:STDOUT: +// CHECK:STDOUT: define void @_CMyF.Main() !dbg !7 { +// CHECK:STDOUT: entry: +// CHECK:STDOUT: call void @_Z1Fii.carbon_thunk0(), !dbg !10 +// CHECK:STDOUT: call void @_Z1Fii.carbon_thunk1(i32 3), !dbg !11 +// CHECK:STDOUT: call void @_Z1Fii(i32 3, i32 4), !dbg !12 +// CHECK:STDOUT: ret void, !dbg !13 +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: declare void @_Z1Fii(i32, i32) +// CHECK:STDOUT: +// CHECK:STDOUT: ; Function Attrs: alwaysinline mustprogress +// CHECK:STDOUT: define dso_local void @_Z1Fii.carbon_thunk0() #0 { +// CHECK:STDOUT: entry: +// CHECK:STDOUT: call void @_Z1Fii(i32 1, i32 2) +// CHECK:STDOUT: ret void +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: ; Function Attrs: alwaysinline mustprogress +// CHECK:STDOUT: define dso_local void @_Z1Fii.carbon_thunk1(i32 %a) #0 { +// CHECK:STDOUT: entry: +// CHECK:STDOUT: %a.addr = alloca i32, align 4 +// CHECK:STDOUT: store i32 %a, ptr %a.addr, align 4 +// CHECK:STDOUT: %0 = load i32, ptr %a.addr, align 4 +// CHECK:STDOUT: call void @_Z1Fii(i32 %0, i32 2) +// CHECK:STDOUT: ret void +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: attributes #0 = { alwaysinline mustprogress "min-legal-vector-width"="0" "no-trapping-math"="true" "stack-protector-buffer-size"="0" "target-cpu"="x86-64" "target-features"="+cmov,+cx8,+fxsr,+mmx,+sse,+sse2,+x87" "tune-cpu"="generic" } +// CHECK:STDOUT: +// CHECK:STDOUT: !llvm.module.flags = !{!0, !1, !2, !3, !4} +// CHECK:STDOUT: !llvm.dbg.cu = !{!5} +// CHECK:STDOUT: +// CHECK:STDOUT: !0 = !{i32 7, !"Dwarf Version", i32 5} +// CHECK:STDOUT: !1 = !{i32 2, !"Debug Info Version", i32 3} +// CHECK:STDOUT: !2 = !{i32 1, !"wchar_size", i32 4} +// CHECK:STDOUT: !3 = !{i32 8, !"PIC Level", i32 0} +// CHECK:STDOUT: !4 = !{i32 7, !"PIE Level", i32 2} +// CHECK:STDOUT: !5 = distinct !DICompileUnit(language: DW_LANG_C, file: !6, producer: "carbon", isOptimized: false, runtimeVersion: 0, emissionKind: FullDebug) +// CHECK:STDOUT: !6 = !DIFile(filename: "call_with_default_args.carbon", directory: "") +// CHECK:STDOUT: !7 = distinct !DISubprogram(name: "MyF", linkageName: "_CMyF.Main", scope: null, file: !6, line: 6, type: !8, spFlags: DISPFlagDefinition, unit: !5) +// CHECK:STDOUT: !8 = !DISubroutineType(types: !9) +// CHECK:STDOUT: !9 = !{} +// CHECK:STDOUT: !10 = !DILocation(line: 7, column: 3, scope: !7) +// CHECK:STDOUT: !11 = !DILocation(line: 8, column: 3, scope: !7) +// CHECK:STDOUT: !12 = !DILocation(line: 9, column: 3, scope: !7) +// CHECK:STDOUT: !13 = !DILocation(line: 6, column: 1, scope: !7) diff --git a/toolchain/lower/testdata/interop/cpp/method.carbon b/toolchain/lower/testdata/interop/cpp/method.carbon index 2dabde9d713a..e22966792a49 100644 --- a/toolchain/lower/testdata/interop/cpp/method.carbon +++ b/toolchain/lower/testdata/interop/cpp/method.carbon @@ -89,8 +89,18 @@ fn Call(n: Cpp.NeedThunk) { // CHECK:STDOUT: ret i32 %by_val__carbon_thunk.call, !dbg !11 // CHECK:STDOUT: } // CHECK:STDOUT: +// CHECK:STDOUT: ; Function Attrs: alwaysinline mustprogress +// CHECK:STDOUT: define dso_local i32 @_ZNK1A6by_valEv.carbon_thunk(ptr %this) #0 { +// CHECK:STDOUT: entry: +// CHECK:STDOUT: %this.addr = alloca ptr, align 8 +// CHECK:STDOUT: store ptr %this, ptr %this.addr, align 8 +// CHECK:STDOUT: %0 = load ptr, ptr %this.addr, align 8 +// CHECK:STDOUT: %call = call i32 @_ZNK1A6by_valEv(ptr nonnull align 8 dereferenceable(12) %0) +// CHECK:STDOUT: ret i32 %call +// CHECK:STDOUT: } +// CHECK:STDOUT: // CHECK:STDOUT: ; Function Attrs: mustprogress noinline nounwind optnone -// CHECK:STDOUT: define linkonce_odr dso_local i32 @_ZNK1A6by_valEv(ptr nonnull align 8 dereferenceable(12) %this) #0 comdat align 2 { +// CHECK:STDOUT: define linkonce_odr dso_local i32 @_ZNK1A6by_valEv(ptr nonnull align 8 dereferenceable(12) %this) #1 comdat align 2 { // CHECK:STDOUT: entry: // CHECK:STDOUT: %this.addr = alloca ptr, align 8 // CHECK:STDOUT: store ptr %this, ptr %this.addr, align 8 @@ -100,18 +110,8 @@ fn Call(n: Cpp.NeedThunk) { // CHECK:STDOUT: ret i32 %0 // CHECK:STDOUT: } // CHECK:STDOUT: -// CHECK:STDOUT: ; Function Attrs: alwaysinline mustprogress -// CHECK:STDOUT: define dso_local i32 @_ZNK1A6by_valEv.carbon_thunk(ptr %this) #1 { -// CHECK:STDOUT: entry: -// CHECK:STDOUT: %this.addr = alloca ptr, align 8 -// CHECK:STDOUT: store ptr %this, ptr %this.addr, align 8 -// CHECK:STDOUT: %0 = load ptr, ptr %this.addr, align 8 -// CHECK:STDOUT: %call = call i32 @_ZNK1A6by_valEv(ptr nonnull align 8 dereferenceable(12) %0) -// CHECK:STDOUT: ret i32 %call -// CHECK:STDOUT: } -// CHECK:STDOUT: -// CHECK:STDOUT: attributes #0 = { mustprogress noinline nounwind optnone "min-legal-vector-width"="0" "no-trapping-math"="true" "stack-protector-buffer-size"="0" "target-cpu"="x86-64" "target-features"="+cmov,+cx8,+fxsr,+mmx,+sse,+sse2,+x87" "tune-cpu"="generic" } -// CHECK:STDOUT: attributes #1 = { alwaysinline mustprogress "min-legal-vector-width"="0" "no-trapping-math"="true" "stack-protector-buffer-size"="0" "target-cpu"="x86-64" "target-features"="+cmov,+cx8,+fxsr,+mmx,+sse,+sse2,+x87" "tune-cpu"="generic" } +// CHECK:STDOUT: attributes #0 = { alwaysinline mustprogress "min-legal-vector-width"="0" "no-trapping-math"="true" "stack-protector-buffer-size"="0" "target-cpu"="x86-64" "target-features"="+cmov,+cx8,+fxsr,+mmx,+sse,+sse2,+x87" "tune-cpu"="generic" } +// CHECK:STDOUT: attributes #1 = { mustprogress noinline nounwind optnone "min-legal-vector-width"="0" "no-trapping-math"="true" "stack-protector-buffer-size"="0" "target-cpu"="x86-64" "target-features"="+cmov,+cx8,+fxsr,+mmx,+sse,+sse2,+x87" "tune-cpu"="generic" } // CHECK:STDOUT: // CHECK:STDOUT: !llvm.module.flags = !{!0, !1, !2, !3, !4} // CHECK:STDOUT: !llvm.dbg.cu = !{!5} @@ -231,10 +231,6 @@ fn Call(n: Cpp.NeedThunk) { // CHECK:STDOUT: ret void, !dbg !14 // CHECK:STDOUT: } // CHECK:STDOUT: -// CHECK:STDOUT: declare void @_ZNK9NeedThunk8ImplicitEa(ptr, i8) -// CHECK:STDOUT: -// CHECK:STDOUT: declare void @_ZNH9NeedThunk8ExplicitES_a(ptr, i8) -// CHECK:STDOUT: // CHECK:STDOUT: ; Function Attrs: nocallback nofree nosync nounwind willreturn memory(argmem: readwrite) // CHECK:STDOUT: declare void @llvm.lifetime.start.p0(ptr captures(none)) #0 // CHECK:STDOUT: @@ -252,6 +248,8 @@ fn Call(n: Cpp.NeedThunk) { // CHECK:STDOUT: ret void // CHECK:STDOUT: } // CHECK:STDOUT: +// CHECK:STDOUT: declare void @_ZNK9NeedThunk8ImplicitEa(ptr nonnull align 1 dereferenceable(1), i8 signext) #2 +// CHECK:STDOUT: // CHECK:STDOUT: ; Function Attrs: alwaysinline mustprogress // CHECK:STDOUT: define dso_local void @_ZNH9NeedThunk8ExplicitES_a.carbon_thunk(ptr %0, ptr %c) #1 { // CHECK:STDOUT: entry: @@ -267,11 +265,14 @@ fn Call(n: Cpp.NeedThunk) { // CHECK:STDOUT: ret void // CHECK:STDOUT: } // CHECK:STDOUT: +// CHECK:STDOUT: declare void @_ZNH9NeedThunk8ExplicitES_a(i8 signext) #2 +// CHECK:STDOUT: // CHECK:STDOUT: ; uselistorder directives // CHECK:STDOUT: uselistorder ptr @llvm.lifetime.start.p0, { 1, 0 } // CHECK:STDOUT: // CHECK:STDOUT: attributes #0 = { nocallback nofree nosync nounwind willreturn memory(argmem: readwrite) } // CHECK:STDOUT: attributes #1 = { alwaysinline mustprogress "min-legal-vector-width"="0" "no-trapping-math"="true" "stack-protector-buffer-size"="0" "target-cpu"="x86-64" "target-features"="+cmov,+cx8,+fxsr,+mmx,+sse,+sse2,+x87" "tune-cpu"="generic" } +// CHECK:STDOUT: attributes #2 = { "no-trapping-math"="true" "stack-protector-buffer-size"="0" "target-cpu"="x86-64" "target-features"="+cmov,+cx8,+fxsr,+mmx,+sse,+sse2,+x87" "tune-cpu"="generic" } // CHECK:STDOUT: // CHECK:STDOUT: !llvm.module.flags = !{!0, !1, !2, !3, !4} // CHECK:STDOUT: !llvm.dbg.cu = !{!5} diff --git a/toolchain/lower/testdata/interop/cpp/parameters.carbon b/toolchain/lower/testdata/interop/cpp/parameters.carbon index e48e0bad1fde..9ebc2832d64d 100644 --- a/toolchain/lower/testdata/interop/cpp/parameters.carbon +++ b/toolchain/lower/testdata/interop/cpp/parameters.carbon @@ -140,10 +140,6 @@ fn PassValueExpr(y: Cpp.Y) { // CHECK:STDOUT: ret void, !dbg !18 // CHECK:STDOUT: } // CHECK:STDOUT: -// CHECK:STDOUT: declare void @_Z11pass_signedasil(i8, i16, i32, i64) -// CHECK:STDOUT: -// CHECK:STDOUT: declare void @_Z13pass_unsignedhtjm(i8, i16, i32, i64) -// CHECK:STDOUT: // CHECK:STDOUT: declare i16 @_CMakeShort.Main() // CHECK:STDOUT: // CHECK:STDOUT: define void @_CPassShort.Main(i16 %a, ptr %b) !dbg !19 { @@ -170,8 +166,6 @@ fn PassValueExpr(y: Cpp.Y) { // CHECK:STDOUT: ret void, !dbg !28 // CHECK:STDOUT: } // CHECK:STDOUT: -// CHECK:STDOUT: declare void @_Z10pass_shorts(i16) -// CHECK:STDOUT: // CHECK:STDOUT: ; Function Attrs: nocallback nofree nosync nounwind willreturn memory(argmem: readwrite) // CHECK:STDOUT: declare void @llvm.lifetime.start.p0(ptr captures(none)) #0 // CHECK:STDOUT: @@ -196,6 +190,8 @@ fn PassValueExpr(y: Cpp.Y) { // CHECK:STDOUT: ret void // CHECK:STDOUT: } // CHECK:STDOUT: +// CHECK:STDOUT: declare void @_Z11pass_signedasil(i8 signext, i16 signext, i32, i64) #2 +// CHECK:STDOUT: // CHECK:STDOUT: ; Function Attrs: alwaysinline mustprogress // CHECK:STDOUT: define dso_local void @_Z13pass_unsignedhtjm.carbon_thunk(ptr %0, ptr %1, ptr %2, ptr %3) #1 { // CHECK:STDOUT: entry: @@ -219,6 +215,8 @@ fn PassValueExpr(y: Cpp.Y) { // CHECK:STDOUT: ret void // CHECK:STDOUT: } // CHECK:STDOUT: +// CHECK:STDOUT: declare void @_Z13pass_unsignedhtjm(i8 zeroext, i16 zeroext, i32, i64) #2 +// CHECK:STDOUT: // CHECK:STDOUT: ; Function Attrs: alwaysinline mustprogress // CHECK:STDOUT: define dso_local void @_Z10pass_shorts.carbon_thunk(ptr %0) #1 { // CHECK:STDOUT: entry: @@ -230,11 +228,14 @@ fn PassValueExpr(y: Cpp.Y) { // CHECK:STDOUT: ret void // CHECK:STDOUT: } // CHECK:STDOUT: +// CHECK:STDOUT: declare void @_Z10pass_shorts(i16 signext) #2 +// CHECK:STDOUT: // CHECK:STDOUT: ; uselistorder directives // CHECK:STDOUT: uselistorder ptr @llvm.lifetime.start.p0, { 9, 8, 7, 6, 5, 4, 3, 2, 1, 0 } // CHECK:STDOUT: // CHECK:STDOUT: attributes #0 = { nocallback nofree nosync nounwind willreturn memory(argmem: readwrite) } // CHECK:STDOUT: attributes #1 = { alwaysinline mustprogress "min-legal-vector-width"="0" "no-trapping-math"="true" "stack-protector-buffer-size"="0" "target-cpu"="x86-64" "target-features"="+cmov,+cx8,+fxsr,+mmx,+sse,+sse2,+x87" "tune-cpu"="generic" } +// CHECK:STDOUT: attributes #2 = { "no-trapping-math"="true" "stack-protector-buffer-size"="0" "target-cpu"="x86-64" "target-features"="+cmov,+cx8,+fxsr,+mmx,+sse,+sse2,+x87" "tune-cpu"="generic" } // CHECK:STDOUT: // CHECK:STDOUT: !llvm.module.flags = !{!0, !1, !2, !3, !4} // CHECK:STDOUT: !llvm.dbg.cu = !{!5} @@ -289,8 +290,6 @@ fn PassValueExpr(y: Cpp.Y) { // CHECK:STDOUT: ret void, !dbg !15 // CHECK:STDOUT: } // CHECK:STDOUT: -// CHECK:STDOUT: declare void @_Z11pass_struct1X(ptr) -// CHECK:STDOUT: // CHECK:STDOUT: ; Function Attrs: nocallback nofree nosync nounwind willreturn memory(argmem: readwrite) // CHECK:STDOUT: declare void @llvm.lifetime.start.p0(ptr captures(none)) #0 // CHECK:STDOUT: @@ -315,12 +314,15 @@ fn PassValueExpr(y: Cpp.Y) { // CHECK:STDOUT: ; Function Attrs: nocallback nofree nounwind willreturn memory(argmem: readwrite) // CHECK:STDOUT: declare void @llvm.memcpy.p0.p0.i64(ptr noalias writeonly captures(none), ptr noalias readonly captures(none), i64, i1 immarg) #2 // CHECK:STDOUT: +// CHECK:STDOUT: declare void @_Z11pass_struct1X(i64, i32) #3 +// CHECK:STDOUT: // CHECK:STDOUT: ; uselistorder directives // CHECK:STDOUT: uselistorder ptr @llvm.memcpy.p0.p0.i64, { 1, 0 } // CHECK:STDOUT: // CHECK:STDOUT: attributes #0 = { nocallback nofree nosync nounwind willreturn memory(argmem: readwrite) } // CHECK:STDOUT: attributes #1 = { alwaysinline mustprogress "min-legal-vector-width"="0" "no-trapping-math"="true" "stack-protector-buffer-size"="0" "target-cpu"="x86-64" "target-features"="+cmov,+cx8,+fxsr,+mmx,+sse,+sse2,+x87" "tune-cpu"="generic" } // CHECK:STDOUT: attributes #2 = { nocallback nofree nounwind willreturn memory(argmem: readwrite) } +// CHECK:STDOUT: attributes #3 = { "no-trapping-math"="true" "stack-protector-buffer-size"="0" "target-cpu"="x86-64" "target-features"="+cmov,+cx8,+fxsr,+mmx,+sse,+sse2,+x87" "tune-cpu"="generic" } // CHECK:STDOUT: // CHECK:STDOUT: !llvm.module.flags = !{!0, !1, !2, !3, !4} // CHECK:STDOUT: !llvm.dbg.cu = !{!5} @@ -362,8 +364,6 @@ fn PassValueExpr(y: Cpp.Y) { // CHECK:STDOUT: ret void, !dbg !15 // CHECK:STDOUT: } // CHECK:STDOUT: -// CHECK:STDOUT: declare void @_Z11pass_struct1Y(ptr) -// CHECK:STDOUT: // CHECK:STDOUT: declare void @_CMake.Main(ptr sret([12 x i8])) // CHECK:STDOUT: // CHECK:STDOUT: define void @_CPassInitExpr.Main() !dbg !16 { @@ -398,6 +398,8 @@ fn PassValueExpr(y: Cpp.Y) { // CHECK:STDOUT: // CHECK:STDOUT: declare void @_ZN1YC1ERKS_(ptr nonnull align 4 dereferenceable(12), ptr nonnull align 4 dereferenceable(12)) unnamed_addr #2 // CHECK:STDOUT: +// CHECK:STDOUT: declare void @_Z11pass_struct1Y(ptr dead_on_return) #2 +// CHECK:STDOUT: // CHECK:STDOUT: ; uselistorder directives // CHECK:STDOUT: uselistorder ptr @llvm.lifetime.start.p0, { 1, 0 } // CHECK:STDOUT: diff --git a/toolchain/lower/testdata/interop/cpp/reference.carbon b/toolchain/lower/testdata/interop/cpp/reference.carbon index 0769c77c27dc..fc17e41fffdf 100644 --- a/toolchain/lower/testdata/interop/cpp/reference.carbon +++ b/toolchain/lower/testdata/interop/cpp/reference.carbon @@ -68,18 +68,6 @@ fn PassRefs() { // CHECK:STDOUT: ret void, !dbg !20 // CHECK:STDOUT: } // CHECK:STDOUT: -// CHECK:STDOUT: declare void @_Z8TakeCRefR1C(ptr) -// CHECK:STDOUT: -// CHECK:STDOUT: declare void @_Z9TakeCRRefO1C(ptr) -// CHECK:STDOUT: -// CHECK:STDOUT: declare void @_Z13TakeConstCRefRK1C(ptr) -// CHECK:STDOUT: -// CHECK:STDOUT: declare void @_Z10TakeIntRefRi(ptr) -// CHECK:STDOUT: -// CHECK:STDOUT: declare void @_Z11TakeIntRRefOi(i32) -// CHECK:STDOUT: -// CHECK:STDOUT: declare void @_Z15TakeConstIntRefRKi(ptr) -// CHECK:STDOUT: // CHECK:STDOUT: ; Function Attrs: nocallback nofree nosync nounwind willreturn memory(argmem: readwrite) // CHECK:STDOUT: declare void @llvm.lifetime.start.p0(ptr captures(none)) #0 // CHECK:STDOUT: @@ -96,6 +84,8 @@ fn PassRefs() { // CHECK:STDOUT: ret void // CHECK:STDOUT: } // CHECK:STDOUT: +// CHECK:STDOUT: declare void @_Z8TakeCRefR1C(ptr nonnull align 1 dereferenceable(1)) #3 +// CHECK:STDOUT: // CHECK:STDOUT: ; Function Attrs: alwaysinline mustprogress // CHECK:STDOUT: define dso_local void @_Z9TakeCRRefO1C.carbon_thunk(ptr %0) #2 { // CHECK:STDOUT: entry: @@ -106,6 +96,8 @@ fn PassRefs() { // CHECK:STDOUT: ret void // CHECK:STDOUT: } // CHECK:STDOUT: +// CHECK:STDOUT: declare void @_Z9TakeCRRefO1C(ptr nonnull align 1 dereferenceable(1)) #3 +// CHECK:STDOUT: // CHECK:STDOUT: ; Function Attrs: alwaysinline mustprogress // CHECK:STDOUT: define dso_local void @_Z13TakeConstCRefRK1C.carbon_thunk(ptr %0) #2 { // CHECK:STDOUT: entry: @@ -116,6 +108,8 @@ fn PassRefs() { // CHECK:STDOUT: ret void // CHECK:STDOUT: } // CHECK:STDOUT: +// CHECK:STDOUT: declare void @_Z13TakeConstCRefRK1C(ptr nonnull align 1 dereferenceable(1)) #3 +// CHECK:STDOUT: // CHECK:STDOUT: ; Function Attrs: alwaysinline mustprogress // CHECK:STDOUT: define dso_local void @_Z10TakeIntRefRi.carbon_thunk(ptr %0) #2 { // CHECK:STDOUT: entry: @@ -126,6 +120,8 @@ fn PassRefs() { // CHECK:STDOUT: ret void // CHECK:STDOUT: } // CHECK:STDOUT: +// CHECK:STDOUT: declare void @_Z10TakeIntRefRi(ptr nonnull align 4 dereferenceable(4)) #3 +// CHECK:STDOUT: // CHECK:STDOUT: ; Function Attrs: alwaysinline mustprogress // CHECK:STDOUT: define dso_local void @_Z11TakeIntRRefOi.carbon_thunk(ptr %0) #2 { // CHECK:STDOUT: entry: @@ -136,6 +132,8 @@ fn PassRefs() { // CHECK:STDOUT: ret void // CHECK:STDOUT: } // CHECK:STDOUT: +// CHECK:STDOUT: declare void @_Z11TakeIntRRefOi(ptr nonnull align 4 dereferenceable(4)) #3 +// CHECK:STDOUT: // CHECK:STDOUT: ; Function Attrs: alwaysinline mustprogress // CHECK:STDOUT: define dso_local void @_Z15TakeConstIntRefRKi.carbon_thunk(ptr %0) #2 { // CHECK:STDOUT: entry: @@ -146,12 +144,15 @@ fn PassRefs() { // CHECK:STDOUT: ret void // CHECK:STDOUT: } // CHECK:STDOUT: +// CHECK:STDOUT: declare void @_Z15TakeConstIntRefRKi(ptr nonnull align 4 dereferenceable(4)) #3 +// CHECK:STDOUT: // CHECK:STDOUT: ; uselistorder directives // CHECK:STDOUT: uselistorder ptr @llvm.lifetime.start.p0, { 3, 2, 1, 0 } // CHECK:STDOUT: // CHECK:STDOUT: attributes #0 = { nocallback nofree nosync nounwind willreturn memory(argmem: readwrite) } // CHECK:STDOUT: attributes #1 = { nocallback nofree nounwind willreturn memory(argmem: readwrite) } // CHECK:STDOUT: attributes #2 = { alwaysinline mustprogress "min-legal-vector-width"="0" "no-trapping-math"="true" "stack-protector-buffer-size"="0" "target-cpu"="x86-64" "target-features"="+cmov,+cx8,+fxsr,+mmx,+sse,+sse2,+x87" "tune-cpu"="generic" } +// CHECK:STDOUT: attributes #3 = { "no-trapping-math"="true" "stack-protector-buffer-size"="0" "target-cpu"="x86-64" "target-features"="+cmov,+cx8,+fxsr,+mmx,+sse,+sse2,+x87" "tune-cpu"="generic" } // CHECK:STDOUT: // CHECK:STDOUT: !llvm.module.flags = !{!0, !1, !2, !3, !4} // CHECK:STDOUT: !llvm.dbg.cu = !{!5} diff --git a/toolchain/lower/testdata/interop/cpp/return.carbon b/toolchain/lower/testdata/interop/cpp/return.carbon index dcbcc43ba45e..37c386e61f33 100644 --- a/toolchain/lower/testdata/interop/cpp/return.carbon +++ b/toolchain/lower/testdata/interop/cpp/return.carbon @@ -111,8 +111,6 @@ fn Var() { // CHECK:STDOUT: ret i8 %.loc6_40.2, !dbg !11 // CHECK:STDOUT: } // CHECK:STDOUT: -// CHECK:STDOUT: declare i8 @_Z8ReturnU8v() -// CHECK:STDOUT: // CHECK:STDOUT: define i16 @_CGetU16.Main() !dbg !12 { // CHECK:STDOUT: entry: // CHECK:STDOUT: %.loc7_43.1.temp = alloca i16, align 2, !dbg !13 @@ -122,8 +120,6 @@ fn Var() { // CHECK:STDOUT: ret i16 %.loc7_43.2, !dbg !14 // CHECK:STDOUT: } // CHECK:STDOUT: -// CHECK:STDOUT: declare i16 @_Z9ReturnU16v() -// CHECK:STDOUT: // CHECK:STDOUT: define i32 @_CGetU32.Main() !dbg !15 { // CHECK:STDOUT: entry: // CHECK:STDOUT: %ReturnU32.call = call i32 @_Z9ReturnU32v(), !dbg !16 @@ -149,8 +145,6 @@ fn Var() { // CHECK:STDOUT: ret i8 %.loc11_40.2, !dbg !23 // CHECK:STDOUT: } // CHECK:STDOUT: -// CHECK:STDOUT: declare i8 @_Z8ReturnI8v() -// CHECK:STDOUT: // CHECK:STDOUT: define i16 @_CGetI16.Main() !dbg !24 { // CHECK:STDOUT: entry: // CHECK:STDOUT: %.loc12_43.1.temp = alloca i16, align 2, !dbg !25 @@ -160,8 +154,6 @@ fn Var() { // CHECK:STDOUT: ret i16 %.loc12_43.2, !dbg !26 // CHECK:STDOUT: } // CHECK:STDOUT: -// CHECK:STDOUT: declare i16 @_Z9ReturnI16v() -// CHECK:STDOUT: // CHECK:STDOUT: define i32 @_CGetI32.Main() !dbg !27 { // CHECK:STDOUT: entry: // CHECK:STDOUT: %ReturnI32.call = call i32 @_Z9ReturnI32v(), !dbg !28 @@ -278,6 +270,8 @@ fn Var() { // CHECK:STDOUT: ret void // CHECK:STDOUT: } // CHECK:STDOUT: +// CHECK:STDOUT: declare zeroext i8 @_Z8ReturnU8v() #2 +// CHECK:STDOUT: // CHECK:STDOUT: ; Function Attrs: alwaysinline mustprogress // CHECK:STDOUT: define dso_local void @_Z9ReturnU16v.carbon_thunk(ptr %return) #1 { // CHECK:STDOUT: entry: @@ -289,6 +283,8 @@ fn Var() { // CHECK:STDOUT: ret void // CHECK:STDOUT: } // CHECK:STDOUT: +// CHECK:STDOUT: declare zeroext i16 @_Z9ReturnU16v() #2 +// CHECK:STDOUT: // CHECK:STDOUT: ; Function Attrs: alwaysinline mustprogress // CHECK:STDOUT: define dso_local void @_Z8ReturnI8v.carbon_thunk(ptr %return) #1 { // CHECK:STDOUT: entry: @@ -300,6 +296,8 @@ fn Var() { // CHECK:STDOUT: ret void // CHECK:STDOUT: } // CHECK:STDOUT: +// CHECK:STDOUT: declare signext i8 @_Z8ReturnI8v() #2 +// CHECK:STDOUT: // CHECK:STDOUT: ; Function Attrs: alwaysinline mustprogress // CHECK:STDOUT: define dso_local void @_Z9ReturnI16v.carbon_thunk(ptr %return) #1 { // CHECK:STDOUT: entry: @@ -311,11 +309,14 @@ fn Var() { // CHECK:STDOUT: ret void // CHECK:STDOUT: } // CHECK:STDOUT: +// CHECK:STDOUT: declare signext i16 @_Z9ReturnI16v() #2 +// CHECK:STDOUT: // CHECK:STDOUT: ; uselistorder directives // CHECK:STDOUT: uselistorder ptr @llvm.lifetime.start.p0, { 19, 18, 17, 16, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0 } // CHECK:STDOUT: // CHECK:STDOUT: attributes #0 = { nocallback nofree nosync nounwind willreturn memory(argmem: readwrite) } // CHECK:STDOUT: attributes #1 = { alwaysinline mustprogress "min-legal-vector-width"="0" "no-trapping-math"="true" "stack-protector-buffer-size"="0" "target-cpu"="x86-64" "target-features"="+cmov,+cx8,+fxsr,+mmx,+sse,+sse2,+x87" "tune-cpu"="generic" } +// CHECK:STDOUT: attributes #2 = { "no-trapping-math"="true" "stack-protector-buffer-size"="0" "target-cpu"="x86-64" "target-features"="+cmov,+cx8,+fxsr,+mmx,+sse,+sse2,+x87" "tune-cpu"="generic" } // CHECK:STDOUT: // CHECK:STDOUT: !llvm.module.flags = !{!0, !1, !2, !3, !4} // CHECK:STDOUT: !llvm.dbg.cu = !{!5} @@ -404,8 +405,6 @@ fn Var() { // CHECK:STDOUT: ret void, !dbg !11 // CHECK:STDOUT: } // CHECK:STDOUT: -// CHECK:STDOUT: declare void @_Z4Makev(ptr sret([16 x i8])) -// CHECK:STDOUT: // CHECK:STDOUT: define void @_CLet.Main() !dbg !12 { // CHECK:STDOUT: entry: // CHECK:STDOUT: %.loc9_27.1.temp = alloca [16 x i8], align 1, !dbg !13 @@ -435,11 +434,14 @@ fn Var() { // CHECK:STDOUT: ret void // CHECK:STDOUT: } // CHECK:STDOUT: +// CHECK:STDOUT: declare void @_Z4Makev(ptr dead_on_unwind writable sret(%struct.X) align 8) #2 +// CHECK:STDOUT: // CHECK:STDOUT: ; uselistorder directives // CHECK:STDOUT: uselistorder ptr @llvm.lifetime.start.p0, { 1, 0 } // CHECK:STDOUT: // CHECK:STDOUT: attributes #0 = { nocallback nofree nosync nounwind willreturn memory(argmem: readwrite) } // CHECK:STDOUT: attributes #1 = { alwaysinline mustprogress "min-legal-vector-width"="0" "no-trapping-math"="true" "stack-protector-buffer-size"="0" "target-cpu"="x86-64" "target-features"="+cmov,+cx8,+fxsr,+mmx,+sse,+sse2,+x87" "tune-cpu"="generic" } +// CHECK:STDOUT: attributes #2 = { "no-trapping-math"="true" "stack-protector-buffer-size"="0" "target-cpu"="x86-64" "target-features"="+cmov,+cx8,+fxsr,+mmx,+sse,+sse2,+x87" "tune-cpu"="generic" } // CHECK:STDOUT: // CHECK:STDOUT: !llvm.module.flags = !{!0, !1, !2, !3, !4} // CHECK:STDOUT: !llvm.dbg.cu = !{!5} diff --git a/toolchain/lower/testdata/interop/cpp/template.carbon b/toolchain/lower/testdata/interop/cpp/template.carbon index ea029ed1ec5a..510a633a16a5 100644 --- a/toolchain/lower/testdata/interop/cpp/template.carbon +++ b/toolchain/lower/testdata/interop/cpp/template.carbon @@ -62,13 +62,6 @@ fn PassClass(a: Cpp.Class) -> Cpp.Class { // CHECK:STDOUT: ret i32 %0 // CHECK:STDOUT: } // CHECK:STDOUT: -// CHECK:STDOUT: ; Function Attrs: mustprogress noinline nounwind optnone -// CHECK:STDOUT: define linkonce_odr dso_local void @_Z8identityI5ClassET_S1_() #0 comdat { -// CHECK:STDOUT: entry: -// CHECK:STDOUT: %x = alloca %class.Class, align 1 -// CHECK:STDOUT: ret void -// CHECK:STDOUT: } -// CHECK:STDOUT: // CHECK:STDOUT: ; Function Attrs: alwaysinline mustprogress // CHECK:STDOUT: define dso_local void @_Z8identityI5ClassET_S1_.carbon_thunk(ptr %x, ptr %return) #1 { // CHECK:STDOUT: entry: @@ -84,6 +77,13 @@ fn PassClass(a: Cpp.Class) -> Cpp.Class { // CHECK:STDOUT: ret void // CHECK:STDOUT: } // CHECK:STDOUT: +// CHECK:STDOUT: ; Function Attrs: mustprogress noinline nounwind optnone +// CHECK:STDOUT: define linkonce_odr dso_local void @_Z8identityI5ClassET_S1_() #0 comdat { +// CHECK:STDOUT: entry: +// CHECK:STDOUT: %x = alloca %class.Class, align 1 +// CHECK:STDOUT: ret void +// CHECK:STDOUT: } +// CHECK:STDOUT: // CHECK:STDOUT: attributes #0 = { mustprogress noinline nounwind optnone "min-legal-vector-width"="0" "no-trapping-math"="true" "stack-protector-buffer-size"="0" "target-cpu"="x86-64" "target-features"="+cmov,+cx8,+fxsr,+mmx,+sse,+sse2,+x87" "tune-cpu"="generic" } // CHECK:STDOUT: attributes #1 = { alwaysinline mustprogress "min-legal-vector-width"="0" "no-trapping-math"="true" "stack-protector-buffer-size"="0" "target-cpu"="x86-64" "target-features"="+cmov,+cx8,+fxsr,+mmx,+sse,+sse2,+x87" "tune-cpu"="generic" } // CHECK:STDOUT: diff --git a/toolchain/sem_ir/BUILD b/toolchain/sem_ir/BUILD index d0ff22cc8f70..7382908ab75d 100644 --- a/toolchain/sem_ir/BUILD +++ b/toolchain/sem_ir/BUILD @@ -55,6 +55,7 @@ cc_library( ":typed_insts", "//common:hashtable_key_context", "//common:ostream", + "//common:raw_string_ostream", "//toolchain/base:canonical_value_store", "@llvm-project//clang:ast", ], diff --git a/toolchain/sem_ir/clang_decl.cpp b/toolchain/sem_ir/clang_decl.cpp index a8dbcc736abc..f14bab416faa 100644 --- a/toolchain/sem_ir/clang_decl.cpp +++ b/toolchain/sem_ir/clang_decl.cpp @@ -5,13 +5,32 @@ #include "toolchain/sem_ir/clang_decl.h" #include "clang/AST/DeclBase.h" +#include "clang/AST/TextNodeDumper.h" +#include "common/ostream.h" +#include "common/raw_string_ostream.h" namespace Carbon::SemIR { +auto ClangDeclKey::Print(llvm::raw_ostream& out) const -> void { + RawStringOstream decl_stream; + auto policy = decl->getASTContext().getPrintingPolicy(); + policy.TerseOutput = true; + if (isa(decl)) { + decl_stream << ""; + } else { + decl->print(decl_stream, policy); + } + + if (num_params != -1) { + out << "{decl: \"" << FormatEscaped(decl_stream.TakeStr()) + << "\", num_params: " << num_params << "}"; + } else { + out << "\"" << FormatEscaped(decl_stream.TakeStr()) << "\""; + } +} + auto ClangDecl::Print(llvm::raw_ostream& out) const -> void { - out << "{decl: "; - decl->print(out); - out << ", inst_id: " << inst_id << "}"; + out << "{key: " << key << ", inst_id: " << inst_id << "}"; } } // namespace Carbon::SemIR diff --git a/toolchain/sem_ir/clang_decl.h b/toolchain/sem_ir/clang_decl.h index f977d73b15c3..beb999c6e7b2 100644 --- a/toolchain/sem_ir/clang_decl.h +++ b/toolchain/sem_ir/clang_decl.h @@ -5,50 +5,59 @@ #ifndef CARBON_TOOLCHAIN_SEM_IR_CLANG_DECL_H_ #define CARBON_TOOLCHAIN_SEM_IR_CLANG_DECL_H_ +#include + +#include "clang/AST/Decl.h" #include "common/hashtable_key_context.h" #include "common/ostream.h" #include "toolchain/base/canonical_value_store.h" #include "toolchain/sem_ir/ids.h" -// NOLINTNEXTLINE(readability-identifier-naming) -namespace clang { - -// Forward declare indexed types, for integration with ValueStore. -class Decl; - -} // namespace clang - namespace Carbon::SemIR { -// A Clang declaration mapped to a Carbon instruction. +// A key describing a Clang declaration that can be looked up in the value +// store. This is a `clang::Decl*` pointing to a canonical declaration, plus any +// other information that affects the mapping into Carbon. Currently this +// includes the number of imported parameters for a function with default +// arguments. // -// Note that Clang's AST uses address-identity for nodes, which means the -// pointer is the canonical way to represent a specific AST node and is expected -// to be sufficient for comparison, hashing, etc. -// -// This type is specifically designed for use in a `CanonicalValueStore` and -// provide a single canonical access from SemIR to each `clang::Decl*` used. -// This also ensures that a given `clang::Decl*` is associated with exactly one -// instruction, and the `inst_id` here provides access to that instruction from -// either the `ClangDeclId` or the `clang::Decl*`. -struct ClangDecl : public Printable { +// A canonical declaration pointer is used so that we can perform direct address +// comparisons and hash this structure based on its contents. +struct ClangDeclKey : public Printable { + // For declaration classes that are unrelated to FunctionDecl, no parameter + // count is expected. + template + requires(std::derived_from && + !std::derived_from && + !std::derived_from) + explicit ClangDeclKey(DeclT* decl) : ClangDeclKey(decl, -1, UncheckedTag()) {} + + // For declaration classes that are derived from FunctionDecl, a parameter + // count is required. + static auto ForFunctionDecl(clang::FunctionDecl* decl, int num_params) + -> ClangDeclKey { + return ClangDeclKey(decl, num_params, UncheckedTag()); + } + + // Factory function for clang declaration that is dynamically known to not be + // a function declaration. + static auto ForNonFunctionDecl(clang::Decl* decl) -> ClangDeclKey { + CARBON_CHECK(!isa(decl)); + return ClangDeclKey(decl, -1, UncheckedTag()); + } + auto Print(llvm::raw_ostream& out) const -> void; - // Equality comparison uses the address-identity property of the Clang AST and - // just compares the `decl` pointers. The `inst_id` is always the same due to - // the canonicalization. - auto operator==(const ClangDecl& rhs) const -> bool { - return decl == rhs.decl; - } - // Support direct comparison with the Clang AST node pointer. - auto operator==(const clang::Decl* rhs_decl) const -> bool { - return decl == rhs_decl; + auto operator==(const ClangDeclKey& rhs) const -> bool { + return decl == rhs.decl && num_params == rhs.num_params; } // Hashing for ClangDecl. See common/hashing.h. - friend auto CarbonHashValue(const ClangDecl& value, uint64_t seed) + friend auto CarbonHashValue(const ClangDeclKey& value, uint64_t seed) -> HashCode { - return HashValue(value.decl, seed); + // Manual hashing support is required because this type has tail padding in + // 64-bit compilations. + return HashValue(std::pair{value.decl, value.num_params}, seed); } // The Clang declaration pointing to the Clang AST. @@ -56,10 +65,40 @@ struct ClangDecl : public Printable { // `clang::LazyDeclPtr`. clang::Decl* decl = nullptr; + // The number of parameters to import for a function declaration. Excludes the + // implicit object parameter, if there is one. Always -1 for a non-function + // declaration. + int32_t num_params = -1; + + private: + struct UncheckedTag { + explicit UncheckedTag() = default; + }; + ClangDeclKey(clang::Decl* decl, int num_params, UncheckedTag /*_*/) + : decl(decl->getCanonicalDecl()), num_params(num_params) {} +}; + +// A Clang declaration mapped to a Carbon instruction. +// +// Instances of this type are managed by a `ClangDeclStore`, which ensures that +// a single `ClangDecl` exists for each `ClangDeclKey` used. +struct ClangDecl : public Printable { + // Comparison against ClangDeclKey, required by CanonicalValueStore. + auto operator==(const ClangDeclKey& rhs) const -> bool { return key == rhs; } + auto operator==(const ClangDecl& rhs) const -> bool { return key == rhs.key; } + + // Hashing for ClangDecl. See common/hashing.h. + friend auto CarbonHashValue(const ClangDecl& value, uint64_t seed) + -> HashCode { + return HashValue(value.key, seed); + } + + auto Print(llvm::raw_ostream& out) const -> void; + + // The key by which this declaration can be looked up. + ClangDeclKey key; + // The instruction the Clang declaration is mapped to. - // - // This is stored along side the `decl` pointer to avoid having to lookup both - // the pointer and the instruction ID in two separate areas of storage. InstId inst_id; }; @@ -79,7 +118,7 @@ struct ClangDeclId : public IdBase { // Use the AST node pointer directly when doing `Lookup` to find an ID. using ClangDeclStore = - CanonicalValueStore; + CanonicalValueStore; } // namespace Carbon::SemIR diff --git a/toolchain/sem_ir/file.cpp b/toolchain/sem_ir/file.cpp index 2dc2d76b0eb8..24d830d1ac8c 100644 --- a/toolchain/sem_ir/file.cpp +++ b/toolchain/sem_ir/file.cpp @@ -101,6 +101,7 @@ auto File::OutputYaml(bool include_singletons) const -> Yaml::OutputMapping { map.Add("sem_ir", Yaml::OutputMapping([&](Yaml::OutputMapping::Map map) { map.Add("import_irs", import_irs_.OutputYaml()); map.Add("import_ir_insts", import_ir_insts_.OutputYaml()); + map.Add("clang_decls", clang_decls_.OutputYaml()); map.Add("name_scopes", name_scopes_.OutputYaml()); map.Add("entity_names", entity_names_.OutputYaml()); map.Add("functions", functions_.OutputYaml()); @@ -139,6 +140,7 @@ auto File::CollectMemUsage(MemUsage& mem_usage, llvm::StringRef label) const mem_usage.Collect(MemUsage::ConcatLabel(label, "import_irs_"), import_irs_); mem_usage.Collect(MemUsage::ConcatLabel(label, "import_ir_insts_"), import_ir_insts_); + mem_usage.Collect(MemUsage::ConcatLabel(label, "clang_decls_"), clang_decls_); mem_usage.Collect(MemUsage::ConcatLabel(label, "struct_type_fields_"), struct_type_fields_); mem_usage.Collect(MemUsage::ConcatLabel(label, "insts_"), insts_); diff --git a/toolchain/sem_ir/yaml_test.cpp b/toolchain/sem_ir/yaml_test.cpp index 843de2f4f4a0..569aa51494fb 100644 --- a/toolchain/sem_ir/yaml_test.cpp +++ b/toolchain/sem_ir/yaml_test.cpp @@ -58,6 +58,7 @@ TEST(SemIRTest, Yaml) { auto file = Yaml::Mapping(ElementsAre( Pair("import_irs", Yaml::Mapping(SizeIs(2))), Pair("import_ir_insts", Yaml::Mapping(SizeIs(0))), + Pair("clang_decls", Yaml::Mapping(SizeIs(0))), Pair("name_scopes", Yaml::Mapping(SizeIs(1))), Pair("entity_names", Yaml::Mapping(SizeIs(1))), Pair("functions", Yaml::Mapping(SizeIs(1))),