Skip to content

Commit 77804e9

Browse files
committed
Create Clang type sugar matching Carbon type names.
1 parent 925250f commit 77804e9

File tree

4 files changed

+33
-8
lines changed

4 files changed

+33
-8
lines changed

toolchain/check/BUILD

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -155,6 +155,7 @@ cc_library(
155155
"//toolchain/sem_ir:expr_info",
156156
"//toolchain/sem_ir:file",
157157
"//toolchain/sem_ir:formatter",
158+
"//toolchain/sem_ir:stringify",
158159
"//toolchain/sem_ir:typed_insts",
159160
"@llvm-project//clang:ast",
160161
"@llvm-project//clang:basic",

toolchain/check/cpp/type_mapping.cpp

Lines changed: 25 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@
2222
#include "toolchain/sem_ir/expr_info.h"
2323
#include "toolchain/sem_ir/ids.h"
2424
#include "toolchain/sem_ir/inst.h"
25+
#include "toolchain/sem_ir/stringify.h"
2526
#include "toolchain/sem_ir/type.h"
2627
#include "toolchain/sem_ir/type_info.h"
2728
#include "toolchain/sem_ir/typed_insts.h"
@@ -229,6 +230,29 @@ static auto MapToCppType(Context& context, SemIR::InstId inst_id)
229230
return mapped_type;
230231
}
231232

233+
// Maps the type of a given Carbon instruction to a C++ type. Adds type sugar so
234+
// the type prints the same as the Carbon type.
235+
static auto MapToPrettyCppType(Context& context, SemIR::InstId inst_id)
236+
-> clang::QualType {
237+
auto type = MapToCppType(context, inst_id);
238+
if (type.isNull()) {
239+
return clang::QualType();
240+
}
241+
242+
auto type_inst_id =
243+
context.types().GetInstId(context.insts().Get(inst_id).type_id());
244+
auto type_name = SemIR::StringifyConstantInst(context.sem_ir(), type_inst_id);
245+
246+
// TODO: Cache these and only create them once per type!
247+
auto& ast = context.ast_context();
248+
auto* typedef_decl = clang::TypedefDecl::Create(
249+
ast, ast.getTranslationUnitDecl(), clang::SourceLocation(),
250+
clang::SourceLocation(), &ast.Idents.get(type_name),
251+
ast.getTrivialTypeSourceInfo(type));
252+
return ast.getTypedefType(clang::ElaboratedTypeKeyword::None, std::nullopt,
253+
typedef_decl);
254+
}
255+
232256
auto InventClangArg(Context& context, SemIR::InstId arg_id) -> clang::Expr* {
233257
clang::ExprValueKind value_kind;
234258
switch (SemIR::GetExprCategory(context.sem_ir(), arg_id)) {
@@ -262,7 +286,7 @@ auto InventClangArg(Context& context, SemIR::InstId arg_id) -> clang::Expr* {
262286
return nullptr;
263287
}
264288

265-
clang::QualType arg_cpp_type = MapToCppType(context, arg_id);
289+
clang::QualType arg_cpp_type = MapToPrettyCppType(context, arg_id);
266290
if (arg_cpp_type.isNull()) {
267291
CARBON_DIAGNOSTIC(CppCallArgTypeNotSupported, Error,
268292
"call argument of type {0} is not supported",

toolchain/check/testdata/interop/cpp/function/operators.carbon

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -234,7 +234,7 @@ fn F() {
234234
// CHECK:STDERR: 16 | let c2: Cpp.C = c1 + 5;
235235
// CHECK:STDERR: | ^
236236
// CHECK:STDERR: fail_call_with_wrong_type.carbon:[[@LINE-7]]:10: in file included here [InCppInclude]
237-
// CHECK:STDERR: ./binary_operators.h:5:6: note: candidate function not viable: no known conversion from 'int' to 'C' for 2nd argument [CppInteropParseNote]
237+
// 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]
238238
// CHECK:STDERR: 5 | auto operator+(C lhs, C rhs) -> C;
239239
// CHECK:STDERR: | ^ ~~~~~
240240
// CHECK:STDERR:
@@ -243,7 +243,7 @@ fn F() {
243243
// CHECK:STDERR: 25 | let c3: Cpp.C = 6 + c1;
244244
// CHECK:STDERR: | ^
245245
// CHECK:STDERR: fail_call_with_wrong_type.carbon:[[@LINE-16]]:10: in file included here [InCppInclude]
246-
// CHECK:STDERR: ./binary_operators.h:5:6: note: candidate function not viable: no known conversion from 'int' to 'C' for 1st argument [CppInteropParseNote]
246+
// 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]
247247
// CHECK:STDERR: 5 | auto operator+(C lhs, C rhs) -> C;
248248
// CHECK:STDERR: | ^ ~~~~~
249249
// CHECK:STDERR:

toolchain/check/testdata/interop/cpp/function/reference.carbon

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -59,7 +59,7 @@ fn F() {
5959
// CHECK:STDERR: 29 | Cpp.TakesLValue(t);
6060
// CHECK:STDERR: | ^
6161
// CHECK:STDERR: fail_lvalue_ref.carbon:[[@LINE-20]]:10: in file included here [InCppInclude]
62-
// CHECK:STDERR: ./lvalue_ref.h:5:6: note: candidate function not viable: no known conversion from 'T' to 'S &' for 1st argument [CppInteropParseNote]
62+
// 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]
6363
// CHECK:STDERR: 5 | auto TakesLValue(S&) -> void;
6464
// CHECK:STDERR: | ^ ~~
6565
// CHECK:STDERR:
@@ -70,7 +70,7 @@ fn F() {
7070
// CHECK:STDERR: 40 | Cpp.TakesLValue(u as const Cpp.S);
7171
// CHECK:STDERR: | ^
7272
// CHECK:STDERR: fail_lvalue_ref.carbon:[[@LINE-31]]:10: in file included here [InCppInclude]
73-
// CHECK:STDERR: ./lvalue_ref.h:5:6: note: candidate function not viable: 1st argument ('const S') would lose const qualifier [CppInteropParseNote]
73+
// 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]
7474
// CHECK:STDERR: 5 | auto TakesLValue(S&) -> void;
7575
// CHECK:STDERR: | ^ ~~
7676
// CHECK:STDERR:
@@ -142,7 +142,7 @@ fn F() {
142142
// CHECK:STDERR: 28 | Cpp.TakesRValue(t);
143143
// CHECK:STDERR: | ^
144144
// CHECK:STDERR: fail_rvalue_ref.carbon:[[@LINE-19]]:10: in file included here [InCppInclude]
145-
// CHECK:STDERR: ./rvalue_ref.h:5:6: note: candidate function not viable: no known conversion from 'T' to 'S' for 1st argument [CppInteropParseNote]
145+
// 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]
146146
// CHECK:STDERR: 5 | auto TakesRValue(S&&) -> void;
147147
// CHECK:STDERR: | ^ ~~~
148148
// CHECK:STDERR:
@@ -152,7 +152,7 @@ fn F() {
152152
// CHECK:STDERR: 38 | Cpp.TakesRValue(({} as Cpp.S) as const Cpp.S);
153153
// CHECK:STDERR: | ^
154154
// CHECK:STDERR: fail_rvalue_ref.carbon:[[@LINE-29]]:10: in file included here [InCppInclude]
155-
// CHECK:STDERR: ./rvalue_ref.h:5:6: note: candidate function not viable: 1st argument ('const S') would lose const qualifier [CppInteropParseNote]
155+
// 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]
156156
// CHECK:STDERR: 5 | auto TakesRValue(S&&) -> void;
157157
// CHECK:STDERR: | ^ ~~~
158158
// CHECK:STDERR:
@@ -211,7 +211,7 @@ fn F() {
211211
// CHECK:STDERR: 29 | Cpp.TakesConstLValue(t);
212212
// CHECK:STDERR: | ^
213213
// CHECK:STDERR: fail_const_lvalue_ref.carbon:[[@LINE-20]]:10: in file included here [InCppInclude]
214-
// 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]
214+
// 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]
215215
// CHECK:STDERR: 5 | auto TakesConstLValue(const S&) -> void;
216216
// CHECK:STDERR: | ^ ~~~~~~~~
217217
// CHECK:STDERR:

0 commit comments

Comments
 (0)