Test calling std::make_unique on a Carbon type from Carbon. (#7563)

As a byproduct, this introduces a new top-level directory
`integration_tests` for tests like this.

This also fixes a latent bug with name mangling on Mac.
This commit is contained in:
Geoff Romer
2026-07-29 16:07:10 +00:00
committed by GitHub
parent 8ac0edb280
commit 2ac425e591
6 changed files with 86 additions and 5 deletions
+18
View File
@@ -0,0 +1,18 @@
# 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
# This package is for integration tests of the entire Carbon system,
# encompassing things like libraries as well as the toolchain proper. These
# will typically be execution tests, which use the toolchain to build and run a
# test binary, rather than directly checking the toolchain's output. This kind
# of testing should be used sparingly, because it's substantially more costly,
# and not applicable when the toolchain is built as a cross-compiler.
load("//bazel/carbon_rules:defs.bzl", "carbon_binary")
# TODO: Change this to `carbon_test` once that exists.
carbon_binary(
name = "make_unique_test",
srcs = ["make_unique_test.carbon"],
)
+22
View File
@@ -0,0 +1,22 @@
// 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
import Cpp library "<memory>";
class C {
fn C(i: i32) -> Self {
return {.i = i};
}
var i: i32;
}
fn Run() -> i32 {
var ptr: Cpp.std.unique_ptr(C) = Cpp.std.make_unique(C, 42);
if (not ptr.get().HasValue()) {
return 1;
}
let ref c: C = *ptr.get().Get();
return if c.i == 42 then 0 else 1;
}
+3 -1
View File
@@ -587,7 +587,7 @@ static auto BuildCppFunctionDeclForNonGenericCarbonFn(Context& context,
SemIR::Mangler m(context.sem_ir(), context.total_ir_count(),
context.mangle_string_fingerprint());
std::string mangled_name =
m.Mangle(target.function_id, SemIR::SpecificId::None);
m.MangleWithPlatform(target.function_id, SemIR::SpecificId::None);
function_decl->addAttr(
clang::AsmLabelAttr::Create(context.ast_context(), mangled_name));
@@ -1415,6 +1415,8 @@ auto ExportVarToCpp(Context& context, SemIR::InstId inst_id,
}
// Set the Carbon mangled variable name.
// TODO: do we need to apply the platform mangling, like we do for exported
// functions?
SemIR::Mangler m(context.sem_ir(), context.total_ir_count(),
context.mangle_string_fingerprint());
std::string mangled_name = m.MangleGlobalVariable(var_storage.pattern_id);
+2
View File
@@ -384,6 +384,8 @@ cc_library(
"//common:raw_string_ostream",
"//toolchain/base:kind_switch",
"@llvm-project//clang:ast",
"@llvm-project//clang:codegen",
"@llvm-project//llvm:Core",
"@llvm-project//llvm:Support",
],
)
+30 -4
View File
@@ -6,7 +6,9 @@
#include <string>
#include "clang/CodeGen/ModuleBuilder.h"
#include "common/raw_string_ostream.h"
#include "llvm/IR/Module.h"
#include "toolchain/base/kind_switch.h"
#include "toolchain/sem_ir/entry_point.h"
#include "toolchain/sem_ir/ids.h"
@@ -183,12 +185,14 @@ auto Mangler::MangleInverseQualifiedNameScope(llvm::raw_ostream& os,
}
}
auto Mangler::Mangle(SemIR::FunctionId function_id,
SemIR::SpecificId specific_id) -> std::string {
auto Mangler::MangleImpl(SemIR::FunctionId function_id,
SemIR::SpecificId specific_id, llvm::raw_ostream& os)
-> void {
const auto& function = sem_ir().functions().Get(function_id);
if (SemIR::IsEntryPoint(sem_ir(), function_id)) {
CARBON_CHECK(!specific_id.has_value(), "entry point should not be generic");
return "main";
os << "main";
return;
}
// Clang should emit C++ function declarations for us.
@@ -199,7 +203,6 @@ auto Mangler::Mangle(SemIR::FunctionId function_id,
"Shouldn't mangle C++ function");
}
RawStringOstream os;
os << "_C";
MangleNameId(os, function.name_id);
@@ -251,7 +254,30 @@ auto Mangler::Mangle(SemIR::FunctionId function_id,
}
MangleSpecificId(os, specific_id);
}
auto Mangler::Mangle(SemIR::FunctionId function_id,
SemIR::SpecificId specific_id) -> std::string {
RawStringOstream os;
MangleImpl(function_id, specific_id, os);
return os.TakeStr();
}
auto Mangler::MangleWithPlatform(SemIR::FunctionId function_id,
SemIR::SpecificId specific_id) -> std::string {
RawStringOstream os;
CARBON_CHECK(sem_ir_.cpp_file());
// The only platform mangling that's relevant for us is applying a global
// prefix, if the platform has one.
if (char prefix = sem_ir_.cpp_file()
->GetCodeGenerator()
->GetModule()
->getDataLayout()
.getGlobalPrefix()) {
os << prefix;
}
MangleImpl(function_id, specific_id, os);
return os.TakeStr();
}
+11
View File
@@ -30,6 +30,14 @@ class Mangler {
auto Mangle(SemIR::FunctionId function_id, SemIR::SpecificId specific_id)
-> std::string;
// Equivalent to Mangle(), but produces a name that has also gone through
// the platform's mangling. This is needed when the resulting name will be
// used in a way that suppresses platform mangling, such as the value of an
// `asm` label attribute, but it needs to match the mangled name from
// another context that doesn't suppress platform mangling.
auto MangleWithPlatform(SemIR::FunctionId function_id,
SemIR::SpecificId specific_id) -> std::string;
// Produce a deterministically unique mangled name for the given global
// variable pattern, or an empty string if the variable doesn't bind any
// names, in which case it can't be referenced from another file and should be
@@ -42,6 +50,9 @@ class Mangler {
SemIR::SpecificId specific_id) -> std::string;
private:
auto MangleImpl(SemIR::FunctionId function_id, SemIR::SpecificId specific_id,
llvm::raw_ostream& os) -> void;
// Mangle this `NameId` as an individual name component.
auto MangleNameId(llvm::raw_ostream& os, SemIR::NameId name_id) -> void;