Skip to content

Commit 8866e39

Browse files
Add support for string literals in macros (#6408)
Adding support for macros with string literals. Part of #6303
1 parent 00ee693 commit 8866e39

File tree

3 files changed

+111
-15
lines changed

3 files changed

+111
-15
lines changed

toolchain/check/cpp/import.cpp

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2234,6 +2234,21 @@ static auto MapConstant(Context& context, SemIR::LocId loc_id,
22342234
clang::Expr* expr) -> SemIR::InstId {
22352235
CARBON_CHECK(expr, "empty expression");
22362236

2237+
if (auto* string_literal = dyn_cast<clang::StringLiteral>(expr)) {
2238+
if (!string_literal->isOrdinary() && !string_literal->isUTF8()) {
2239+
context.TODO(loc_id,
2240+
llvm::formatv("Unsupported: string literal type: {0}",
2241+
expr->getType()));
2242+
return SemIR::ErrorInst::InstId;
2243+
}
2244+
StringLiteralValueId string_id =
2245+
context.string_literal_values().Add(string_literal->getString());
2246+
auto inst_id =
2247+
MakeStringLiteral(context, Parse::StringLiteralId::None, string_id);
2248+
context.imports().push_back(inst_id);
2249+
return inst_id;
2250+
}
2251+
22372252
SemIR::TypeId type_id = MapType(context, loc_id, expr->getType()).type_id;
22382253
if (!type_id.has_value()) {
22392254
context.TODO(loc_id, llvm::formatv("Unsupported: C++ literal's type `{0}` "

toolchain/check/cpp/macros.cpp

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,10 @@ auto TryEvaluateMacroToConstant(Context& context, SemIR::LocId loc_id,
6161
return nullptr;
6262
}
6363

64+
if (isa<clang::StringLiteral>(result_expr)) {
65+
return result_expr;
66+
}
67+
6468
clang::Expr::EvalResult evaluated_result;
6569
CARBON_CHECK(result_expr->EvaluateAsConstantExpr(evaluated_result,
6670
sema.getASTContext()));

toolchain/check/testdata/interop/cpp/macros.carbon

Lines changed: 92 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -254,28 +254,105 @@ fn F() {
254254
}
255255

256256
// --- string_literal_object_like_macro.h
257-
#define CONFIG_VALUE "abc"
258257

259-
// --- fail_todo_import_string_literal_object_like_macro.carbon
258+
#define SimpleString "abc"
259+
#define EmptyString ""
260+
#define EscapeCharacter " \t "
261+
#define Concatenated "a" "b"
262+
#define RawString R"a( foo: "bar" { 123 } )a"
263+
#define Utf8String u8"абв"
264+
265+
#define CONCAT_STR(A, B) #A #B
266+
#define Indirect CONCAT_STR(x, y)
267+
268+
// --- import_string_literal_object_like_macro.carbon
260269

261270
library "[[@TEST_NAME]]";
262271

263272
import Cpp library "string_literal_object_like_macro.h";
264273

265274
fn F() {
266-
// TODO: Get rid of the second error.
267-
// CHECK:STDERR: fail_todo_import_string_literal_object_like_macro.carbon:[[@LINE+11]]:3: error: semantics TODO: `Unsupported: macro evaluated to a constant of type: const char[4]` [SemanticsTodo]
268-
// CHECK:STDERR: Cpp.CONFIG_VALUE;
269-
// CHECK:STDERR: ^~~~~~~~~~~~~~~~
270-
// CHECK:STDERR: fail_todo_import_string_literal_object_like_macro.carbon:[[@LINE+8]]:3: note: in `Cpp` name lookup for `CONFIG_VALUE` [InCppNameLookup]
271-
// CHECK:STDERR: Cpp.CONFIG_VALUE;
272-
// CHECK:STDERR: ^~~~~~~~~~~~~~~~
273-
// CHECK:STDERR:
274-
// CHECK:STDERR: fail_todo_import_string_literal_object_like_macro.carbon:[[@LINE+4]]:3: error: member name `CONFIG_VALUE` not found in `Cpp` [MemberNameNotFoundInInstScope]
275-
// CHECK:STDERR: Cpp.CONFIG_VALUE;
276-
// CHECK:STDERR: ^~~~~~~~~~~~~~~~
277-
// CHECK:STDERR:
278-
Cpp.CONFIG_VALUE;
275+
let a: str = Cpp.SimpleString;
276+
let b: str = Cpp.EmptyString;
277+
let c: str = Cpp.EscapeCharacter;
278+
let d: str = Cpp.Concatenated;
279+
let e: str = Cpp.RawString;
280+
let f: str = Cpp.Utf8String;
281+
let g: str = Cpp.Indirect;
282+
}
283+
284+
// --- unsupported_string_literal_types.h
285+
286+
#define Utf16Greeting u"Hello"
287+
#define Utf32Greeting U"Hello"
288+
#define WideGreeting L"Hello"
289+
290+
// --- fail_import_unsupported_string_literal_types.carbon
291+
292+
library "[[@TEST_NAME]]";
293+
294+
import Cpp library "unsupported_string_literal_types.h";
295+
296+
fn F() {
297+
// CHECK:STDERR: fail_import_unsupported_string_literal_types.carbon:[[@LINE+11]]:2: error: semantics TODO: `Unsupported: string literal type: const char16_t[6]` [SemanticsTodo]
298+
// CHECK:STDERR: Cpp.Utf16Greeting;
299+
// CHECK:STDERR: ^~~~~~~~~~~~~~~~~
300+
// CHECK:STDERR: fail_import_unsupported_string_literal_types.carbon:[[@LINE+8]]:2: note: in `Cpp` name lookup for `Utf16Greeting` [InCppNameLookup]
301+
// CHECK:STDERR: Cpp.Utf16Greeting;
302+
// CHECK:STDERR: ^~~~~~~~~~~~~~~~~
303+
// CHECK:STDERR:
304+
// CHECK:STDERR: fail_import_unsupported_string_literal_types.carbon:[[@LINE+4]]:2: error: member name `Utf16Greeting` not found in `Cpp` [MemberNameNotFoundInInstScope]
305+
// CHECK:STDERR: Cpp.Utf16Greeting;
306+
// CHECK:STDERR: ^~~~~~~~~~~~~~~~~
307+
// CHECK:STDERR:
308+
Cpp.Utf16Greeting;
309+
// CHECK:STDERR: fail_import_unsupported_string_literal_types.carbon:[[@LINE+11]]:2: error: semantics TODO: `Unsupported: string literal type: const char32_t[6]` [SemanticsTodo]
310+
// CHECK:STDERR: Cpp.Utf32Greeting;
311+
// CHECK:STDERR: ^~~~~~~~~~~~~~~~~
312+
// CHECK:STDERR: fail_import_unsupported_string_literal_types.carbon:[[@LINE+8]]:2: note: in `Cpp` name lookup for `Utf32Greeting` [InCppNameLookup]
313+
// CHECK:STDERR: Cpp.Utf32Greeting;
314+
// CHECK:STDERR: ^~~~~~~~~~~~~~~~~
315+
// CHECK:STDERR:
316+
// CHECK:STDERR: fail_import_unsupported_string_literal_types.carbon:[[@LINE+4]]:2: error: member name `Utf32Greeting` not found in `Cpp` [MemberNameNotFoundInInstScope]
317+
// CHECK:STDERR: Cpp.Utf32Greeting;
318+
// CHECK:STDERR: ^~~~~~~~~~~~~~~~~
319+
// CHECK:STDERR:
320+
Cpp.Utf32Greeting;
321+
// CHECK:STDERR: fail_import_unsupported_string_literal_types.carbon:[[@LINE+11]]:2: error: semantics TODO: `Unsupported: string literal type: const wchar_t[6]` [SemanticsTodo]
322+
// CHECK:STDERR: Cpp.WideGreeting;
323+
// CHECK:STDERR: ^~~~~~~~~~~~~~~~
324+
// CHECK:STDERR: fail_import_unsupported_string_literal_types.carbon:[[@LINE+8]]:2: note: in `Cpp` name lookup for `WideGreeting` [InCppNameLookup]
325+
// CHECK:STDERR: Cpp.WideGreeting;
326+
// CHECK:STDERR: ^~~~~~~~~~~~~~~~
327+
// CHECK:STDERR:
328+
// CHECK:STDERR: fail_import_unsupported_string_literal_types.carbon:[[@LINE+4]]:2: error: member name `WideGreeting` not found in `Cpp` [MemberNameNotFoundInInstScope]
329+
// CHECK:STDERR: Cpp.WideGreeting;
330+
// CHECK:STDERR: ^~~~~~~~~~~~~~~~
331+
// CHECK:STDERR:
332+
Cpp.WideGreeting;
333+
}
334+
335+
// --- fail_bad_string.carbon
336+
337+
library "[[@TEST_NAME]]";
338+
339+
import Cpp inline '''
340+
#define BadString "123" 456
341+
''';
342+
343+
fn F() {
344+
// CHECK:STDERR: fail_bad_string.carbon:[[@LINE+11]]:2: error: failed to parse macro Cpp.BadString to a valid constant expression [InCppMacroEvaluation]
345+
// CHECK:STDERR: Cpp.BadString;
346+
// CHECK:STDERR: ^~~~~~~~~~~~~
347+
// CHECK:STDERR: fail_bad_string.carbon:[[@LINE+8]]:2: note: in `Cpp` name lookup for `BadString` [InCppNameLookup]
348+
// CHECK:STDERR: Cpp.BadString;
349+
// CHECK:STDERR: ^~~~~~~~~~~~~
350+
// CHECK:STDERR:
351+
// CHECK:STDERR: fail_bad_string.carbon:[[@LINE+4]]:2: error: member name `BadString` not found in `Cpp` [MemberNameNotFoundInInstScope]
352+
// CHECK:STDERR: Cpp.BadString;
353+
// CHECK:STDERR: ^~~~~~~~~~~~~
354+
// CHECK:STDERR:
355+
Cpp.BadString;
279356
}
280357

281358
// --- floating_point_literal_macro.h

0 commit comments

Comments
 (0)