Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions toolchain/check/BUILD
Original file line number Diff line number Diff line change
Expand Up @@ -155,6 +155,7 @@ cc_library(
"//toolchain/sem_ir:expr_info",
"//toolchain/sem_ir:file",
"//toolchain/sem_ir:formatter",
"//toolchain/sem_ir:stringify",
"//toolchain/sem_ir:typed_insts",
"@llvm-project//clang:ast",
"@llvm-project//clang:basic",
Expand Down
26 changes: 25 additions & 1 deletion toolchain/check/cpp/type_mapping.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@
#include "toolchain/sem_ir/expr_info.h"
#include "toolchain/sem_ir/ids.h"
#include "toolchain/sem_ir/inst.h"
#include "toolchain/sem_ir/stringify.h"
#include "toolchain/sem_ir/type.h"
#include "toolchain/sem_ir/type_info.h"
#include "toolchain/sem_ir/typed_insts.h"
Expand Down Expand Up @@ -229,6 +230,29 @@ static auto MapToCppType(Context& context, SemIR::InstId inst_id)
return mapped_type;
}

// Maps the type of a given Carbon instruction to a C++ type. Adds type sugar so
// the type prints the same as the Carbon type.
static auto MapToPrettyCppType(Context& context, SemIR::InstId inst_id)
-> clang::QualType {
auto type = MapToCppType(context, inst_id);
if (type.isNull()) {
return clang::QualType();
}

auto type_inst_id =
context.types().GetInstId(context.insts().Get(inst_id).type_id());
auto type_name = SemIR::StringifyConstantInst(context.sem_ir(), type_inst_id);

// TODO: Cache these and only create them once per type!
auto& ast = context.ast_context();
auto* typedef_decl = clang::TypedefDecl::Create(
ast, ast.getTranslationUnitDecl(), clang::SourceLocation(),
clang::SourceLocation(), &ast.Idents.get(type_name),
ast.getTrivialTypeSourceInfo(type));
return ast.getTypedefType(clang::ElaboratedTypeKeyword::None, std::nullopt,
typedef_decl);
}

auto InventClangArg(Context& context, SemIR::InstId arg_id) -> clang::Expr* {
clang::ExprValueKind value_kind;
switch (SemIR::GetExprCategory(context.sem_ir(), arg_id)) {
Expand Down Expand Up @@ -262,7 +286,7 @@ auto InventClangArg(Context& context, SemIR::InstId arg_id) -> clang::Expr* {
return nullptr;
}

clang::QualType arg_cpp_type = MapToCppType(context, arg_id);
clang::QualType arg_cpp_type = MapToPrettyCppType(context, arg_id);
if (arg_cpp_type.isNull()) {
CARBON_DIAGNOSTIC(CppCallArgTypeNotSupported, Error,
"call argument of type {0} is not supported",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -234,7 +234,7 @@ fn F() {
// CHECK:STDERR: 16 | let c2: Cpp.C = c1 + 5;
// CHECK:STDERR: | ^
// CHECK:STDERR: fail_call_with_wrong_type.carbon:[[@LINE-7]]:10: in file included here [InCppInclude]
// CHECK:STDERR: ./binary_operators.h:5:6: note: candidate function not viable: no known conversion from 'int' to 'C' for 2nd argument [CppInteropParseNote]
// CHECK:STDERR: ./binary_operators.h:5:6: note: candidate function not viable: no known conversion from 'Core.IntLiteral' (aka 'int') to 'C' for 2nd argument [CppInteropParseNote]
// CHECK:STDERR: 5 | auto operator+(C lhs, C rhs) -> C;
// CHECK:STDERR: | ^ ~~~~~
// CHECK:STDERR:
Expand All @@ -243,7 +243,7 @@ fn F() {
// CHECK:STDERR: 25 | let c3: Cpp.C = 6 + c1;
// CHECK:STDERR: | ^
// CHECK:STDERR: fail_call_with_wrong_type.carbon:[[@LINE-16]]:10: in file included here [InCppInclude]
// CHECK:STDERR: ./binary_operators.h:5:6: note: candidate function not viable: no known conversion from 'int' to 'C' for 1st argument [CppInteropParseNote]
// CHECK:STDERR: ./binary_operators.h:5:6: note: candidate function not viable: no known conversion from 'Core.IntLiteral' (aka 'int') to 'C' for 1st argument [CppInteropParseNote]
// CHECK:STDERR: 5 | auto operator+(C lhs, C rhs) -> C;
// CHECK:STDERR: | ^ ~~~~~
// CHECK:STDERR:
Expand Down
10 changes: 5 additions & 5 deletions toolchain/check/testdata/interop/cpp/function/reference.carbon
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,7 @@ fn F() {
// CHECK:STDERR: 29 | Cpp.TakesLValue(t);
// CHECK:STDERR: | ^
// CHECK:STDERR: fail_lvalue_ref.carbon:[[@LINE-20]]:10: in file included here [InCppInclude]
// CHECK:STDERR: ./lvalue_ref.h:5:6: note: candidate function not viable: no known conversion from 'T' to 'S &' for 1st argument [CppInteropParseNote]
// CHECK:STDERR: ./lvalue_ref.h:5:6: note: candidate function not viable: no known conversion from 'Cpp.T' (aka 'T') to 'S &' for 1st argument [CppInteropParseNote]
// CHECK:STDERR: 5 | auto TakesLValue(S&) -> void;
// CHECK:STDERR: | ^ ~~
// CHECK:STDERR:
Expand All @@ -70,7 +70,7 @@ fn F() {
// CHECK:STDERR: 40 | Cpp.TakesLValue(u as const Cpp.S);
// CHECK:STDERR: | ^
// CHECK:STDERR: fail_lvalue_ref.carbon:[[@LINE-31]]:10: in file included here [InCppInclude]
// CHECK:STDERR: ./lvalue_ref.h:5:6: note: candidate function not viable: 1st argument ('const S') would lose const qualifier [CppInteropParseNote]
// CHECK:STDERR: ./lvalue_ref.h:5:6: note: candidate function not viable: 1st argument ('const Cpp.S' (aka 'const S')) would lose const qualifier [CppInteropParseNote]
// CHECK:STDERR: 5 | auto TakesLValue(S&) -> void;
// CHECK:STDERR: | ^ ~~
// CHECK:STDERR:
Expand Down Expand Up @@ -142,7 +142,7 @@ fn F() {
// CHECK:STDERR: 28 | Cpp.TakesRValue(t);
// CHECK:STDERR: | ^
// CHECK:STDERR: fail_rvalue_ref.carbon:[[@LINE-19]]:10: in file included here [InCppInclude]
// CHECK:STDERR: ./rvalue_ref.h:5:6: note: candidate function not viable: no known conversion from 'T' to 'S' for 1st argument [CppInteropParseNote]
// CHECK:STDERR: ./rvalue_ref.h:5:6: note: candidate function not viable: no known conversion from 'Cpp.T' (aka 'T') to 'S' for 1st argument [CppInteropParseNote]
// CHECK:STDERR: 5 | auto TakesRValue(S&&) -> void;
// CHECK:STDERR: | ^ ~~~
// CHECK:STDERR:
Expand All @@ -152,7 +152,7 @@ fn F() {
// CHECK:STDERR: 38 | Cpp.TakesRValue(({} as Cpp.S) as const Cpp.S);
// CHECK:STDERR: | ^
// CHECK:STDERR: fail_rvalue_ref.carbon:[[@LINE-29]]:10: in file included here [InCppInclude]
// CHECK:STDERR: ./rvalue_ref.h:5:6: note: candidate function not viable: 1st argument ('const S') would lose const qualifier [CppInteropParseNote]
// CHECK:STDERR: ./rvalue_ref.h:5:6: note: candidate function not viable: 1st argument ('const Cpp.S' (aka 'const S')) would lose const qualifier [CppInteropParseNote]
// CHECK:STDERR: 5 | auto TakesRValue(S&&) -> void;
// CHECK:STDERR: | ^ ~~~
// CHECK:STDERR:
Expand Down Expand Up @@ -211,7 +211,7 @@ fn F() {
// CHECK:STDERR: 29 | Cpp.TakesConstLValue(t);
// CHECK:STDERR: | ^
// CHECK:STDERR: fail_const_lvalue_ref.carbon:[[@LINE-20]]:10: in file included here [InCppInclude]
// CHECK:STDERR: ./const_lvalue_ref.h:5:6: note: candidate function not viable: no known conversion from 'T' to 'const S' for 1st argument [CppInteropParseNote]
// CHECK:STDERR: ./const_lvalue_ref.h:5:6: note: candidate function not viable: no known conversion from 'Cpp.T' (aka 'T') to 'const S' for 1st argument [CppInteropParseNote]
// CHECK:STDERR: 5 | auto TakesConstLValue(const S&) -> void;
// CHECK:STDERR: | ^ ~~~~~~~~
// CHECK:STDERR:
Expand Down
Loading