Skip to content

Commit 7be6538

Browse files
Add support for character literals in macros (carbon-language#6419)
Adding support for macros with character literals. Part of carbon-language#6303
1 parent 093700b commit 7be6538

File tree

3 files changed

+138
-1
lines changed

3 files changed

+138
-1
lines changed

toolchain/check/cpp/import.cpp

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2298,6 +2298,13 @@ static auto MapConstant(Context& context, SemIR::LocId loc_id,
22982298
MakeImportedLocIdAndInst<SemIR::FloatValue>(
22992299
context, imported_loc_id,
23002300
{.type_id = type_id, .float_id = float_id}));
2301+
} else if (auto* character_literal =
2302+
dyn_cast<clang::CharacterLiteral>(expr)) {
2303+
inst_id = AddInstInNoBlock(
2304+
context, MakeImportedLocIdAndInst<SemIR::CharLiteralValue>(
2305+
context, imported_loc_id,
2306+
{.type_id = type_id,
2307+
.value = SemIR::CharId(character_literal->getValue())}));
23012308
} else {
23022309
context.TODO(loc_id, llvm::formatv(
23032310
"Unsupported: C++ constant expression type: '{0}'",

toolchain/check/cpp/macros.cpp

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -61,7 +61,8 @@ auto TryEvaluateMacroToConstant(Context& context, SemIR::LocId loc_id,
6161
return nullptr;
6262
}
6363

64-
if (isa<clang::StringLiteral>(result_expr)) {
64+
if (isa<clang::StringLiteral>(result_expr) ||
65+
isa<clang::CharacterLiteral>(result_expr)) {
6566
return result_expr;
6667
}
6768

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

Lines changed: 129 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -412,6 +412,135 @@ fn F() {
412412
Cpp.MyDouble = 1.0;
413413
}
414414

415+
// --- character_literals.h
416+
417+
#define M_LOWERCASE 'a'
418+
#define M_UPPRCASE 'A'
419+
#define M_DIGIT '1'
420+
#define M_SPACE ' '
421+
#define M_TAB '\t'
422+
#define M_UTF8_CHAR u8'X'
423+
424+
// --- import_character_literals.carbon
425+
426+
library "[[@TEST_NAME]]";
427+
428+
import Cpp library "character_literals.h";
429+
430+
fn F() {
431+
let a: char = Cpp.M_LOWERCASE;
432+
let b: char = Cpp.M_UPPRCASE;
433+
let c: char = Cpp.M_DIGIT;
434+
let d: char = Cpp.M_SPACE;
435+
let e: char = Cpp.M_TAB;
436+
let f: char = Cpp.M_UTF8_CHAR;
437+
}
438+
439+
// --- character_literals_operators.h
440+
441+
#define M_CONDITIONAL (1 < 2 ? 'a' : 'b')
442+
#define M_A_PLUS_ONE 'a' + 1
443+
#define M_A_EQUAL ('a' == 97)
444+
445+
// --- import_character_literals_operators.carbon
446+
447+
library "[[@TEST_NAME]]";
448+
449+
import Cpp library "character_literals_operators.h";
450+
451+
fn F() {
452+
let a: char = Cpp.M_CONDITIONAL;
453+
let b: i32 = Cpp.M_A_PLUS_ONE;
454+
let c: bool = Cpp.M_A_EQUAL;
455+
}
456+
457+
// --- multiple_characters.h
458+
459+
#define MULTIPLE_CHARS 'AB'
460+
461+
// --- import_multiple_characters.carbon
462+
463+
library "[[@TEST_NAME]]";
464+
465+
// CHECK:STDERR: import_multiple_characters.carbon:[[@LINE+4]]:10: in file included here [InCppInclude]
466+
// CHECK:STDERR: ./multiple_characters.h:2:24: warning: multi-character character constant [CppInteropParseWarning]
467+
// CHECK:STDERR: 2 | #define MULTIPLE_CHARS 'AB'
468+
// CHECK:STDERR: | ^
469+
import Cpp library "multiple_characters.h";
470+
471+
fn F() {
472+
// CHECK:STDERR: import_multiple_characters.carbon:[[@LINE+4]]:15: note: in `Cpp` name lookup for `MULTIPLE_CHARS` [InCppNameLookup]
473+
// CHECK:STDERR: let a: i32 = Cpp.MULTIPLE_CHARS;
474+
// CHECK:STDERR: ^~~~~~~~~~~~~~~~~~
475+
// CHECK:STDERR:
476+
let a: i32 = Cpp.MULTIPLE_CHARS;
477+
}
478+
479+
// --- unsupported_character_literal_types.h
480+
481+
#define M_UTF16_CHAR u'a'
482+
#define M_UTF32_CHAR U'a'
483+
#define M_WIDE_CHAR L'a'
484+
485+
// --- fail_unsupported_character_literal_types.carbon
486+
487+
library "[[@TEST_NAME]]";
488+
489+
import Cpp library "unsupported_character_literal_types.h";
490+
491+
fn F() {
492+
// CHECK:STDERR: fail_unsupported_character_literal_types.carbon:[[@LINE+11]]:16: error: semantics TODO: `Unsupported: C++ literal's type `char16_t` could not be mapped to a Carbon type` [SemanticsTodo]
493+
// CHECK:STDERR: let a: char = Cpp.M_UTF16_CHAR;
494+
// CHECK:STDERR: ^~~~~~~~~~~~~~~~
495+
// CHECK:STDERR: fail_unsupported_character_literal_types.carbon:[[@LINE+8]]:16: note: in `Cpp` name lookup for `M_UTF16_CHAR` [InCppNameLookup]
496+
// CHECK:STDERR: let a: char = Cpp.M_UTF16_CHAR;
497+
// CHECK:STDERR: ^~~~~~~~~~~~~~~~
498+
// CHECK:STDERR:
499+
// CHECK:STDERR: fail_unsupported_character_literal_types.carbon:[[@LINE+4]]:16: error: member name `M_UTF16_CHAR` not found in `Cpp` [MemberNameNotFoundInInstScope]
500+
// CHECK:STDERR: let a: char = Cpp.M_UTF16_CHAR;
501+
// CHECK:STDERR: ^~~~~~~~~~~~~~~~
502+
// CHECK:STDERR:
503+
let a: char = Cpp.M_UTF16_CHAR;
504+
// CHECK:STDERR: fail_unsupported_character_literal_types.carbon:[[@LINE+11]]:16: error: semantics TODO: `Unsupported: C++ literal's type `char32_t` could not be mapped to a Carbon type` [SemanticsTodo]
505+
// CHECK:STDERR: let b: char = Cpp.M_UTF32_CHAR;
506+
// CHECK:STDERR: ^~~~~~~~~~~~~~~~
507+
// CHECK:STDERR: fail_unsupported_character_literal_types.carbon:[[@LINE+8]]:16: note: in `Cpp` name lookup for `M_UTF32_CHAR` [InCppNameLookup]
508+
// CHECK:STDERR: let b: char = Cpp.M_UTF32_CHAR;
509+
// CHECK:STDERR: ^~~~~~~~~~~~~~~~
510+
// CHECK:STDERR:
511+
// CHECK:STDERR: fail_unsupported_character_literal_types.carbon:[[@LINE+4]]:16: error: member name `M_UTF32_CHAR` not found in `Cpp` [MemberNameNotFoundInInstScope]
512+
// CHECK:STDERR: let b: char = Cpp.M_UTF32_CHAR;
513+
// CHECK:STDERR: ^~~~~~~~~~~~~~~~
514+
// CHECK:STDERR:
515+
let b: char = Cpp.M_UTF32_CHAR;
516+
// CHECK:STDERR: fail_unsupported_character_literal_types.carbon:[[@LINE+11]]:16: error: semantics TODO: `Unsupported: C++ literal's type `wchar_t` could not be mapped to a Carbon type` [SemanticsTodo]
517+
// CHECK:STDERR: let c: char = Cpp.M_WIDE_CHAR;
518+
// CHECK:STDERR: ^~~~~~~~~~~~~~~
519+
// CHECK:STDERR: fail_unsupported_character_literal_types.carbon:[[@LINE+8]]:16: note: in `Cpp` name lookup for `M_WIDE_CHAR` [InCppNameLookup]
520+
// CHECK:STDERR: let c: char = Cpp.M_WIDE_CHAR;
521+
// CHECK:STDERR: ^~~~~~~~~~~~~~~
522+
// CHECK:STDERR:
523+
// CHECK:STDERR: fail_unsupported_character_literal_types.carbon:[[@LINE+4]]:16: error: member name `M_WIDE_CHAR` not found in `Cpp` [MemberNameNotFoundInInstScope]
524+
// CHECK:STDERR: let c: char = Cpp.M_WIDE_CHAR;
525+
// CHECK:STDERR: ^~~~~~~~~~~~~~~
526+
// CHECK:STDERR:
527+
let c: char = Cpp.M_WIDE_CHAR;
528+
}
529+
530+
// --- fail_assign_to_character_literals.carbon
531+
532+
library "[[@TEST_NAME]]";
533+
534+
import Cpp library "character_literals.h";
535+
536+
fn F() {
537+
// CHECK:STDERR: fail_assign_to_character_literals.carbon:[[@LINE+4]]:2: error: expression is not assignable [AssignmentToNonAssignable]
538+
// CHECK:STDERR: Cpp.M_LOWERCASE = 'b';
539+
// CHECK:STDERR: ^~~~~~~~~~~~~~~
540+
// CHECK:STDERR:
541+
Cpp.M_LOWERCASE = 'b';
542+
}
543+
415544
// --- boolean_literal_macro.h
416545
#define M_TRUE true
417546
#define M_FALSE false

0 commit comments

Comments
 (0)