mirror of
https://github.com/carbon-language/carbon-lang.git
synced 2026-09-24 09:10:13 +01:00
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:
@@ -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"],
|
||||
)
|
||||
@@ -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;
|
||||
}
|
||||
@@ -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);
|
||||
|
||||
@@ -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",
|
||||
],
|
||||
)
|
||||
|
||||
@@ -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();
|
||||
}
|
||||
|
||||
|
||||
@@ -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;
|
||||
|
||||
|
||||
Reference in New Issue
Block a user