mirror of
https://github.com/carbon-language/carbon-lang.git
synced 2026-10-05 17:31:07 +01:00
Add support for macros pointing to a constexpr integer (#6441)
Similarly to the enums, these are for the moment only available when referenced with a global scope “::”. Only integer constexpr are available for now. Part of #6303
This commit is contained in:
@@ -25,7 +25,6 @@ auto TryEvaluateMacroToConstant(Context& context, SemIR::LocId loc_id,
|
||||
|
||||
clang::Sema& sema = context.clang_sema();
|
||||
clang::Preprocessor& preprocessor = sema.getPreprocessor();
|
||||
|
||||
clang::Parser parser(preprocessor, sema, false);
|
||||
|
||||
llvm::SmallVector<clang::Token> tokens(macro_info->tokens().begin(),
|
||||
@@ -67,6 +66,8 @@ auto TryEvaluateMacroToConstant(Context& context, SemIR::LocId loc_id,
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
result_expr = result_expr->IgnoreParenImpCasts();
|
||||
|
||||
if (isa<clang::StringLiteral>(result_expr) ||
|
||||
isa<clang::CharacterLiteral>(result_expr) ||
|
||||
isa<clang::CXXNullPtrLiteralExpr>(result_expr)) {
|
||||
@@ -78,6 +79,16 @@ auto TryEvaluateMacroToConstant(Context& context, SemIR::LocId loc_id,
|
||||
sema.getASTContext()));
|
||||
|
||||
clang::APValue ap_value = evaluated_result.Val;
|
||||
// TODO: Add support for other types.
|
||||
if (ap_value.isLValue()) {
|
||||
if (!result_expr->EvaluateAsInt(evaluated_result, sema.getASTContext())) {
|
||||
context.TODO(loc_id,
|
||||
"Unsupported: macro evaluated to a non-integer LValue");
|
||||
return nullptr;
|
||||
}
|
||||
ap_value = evaluated_result.Val;
|
||||
}
|
||||
|
||||
switch (ap_value.getKind()) {
|
||||
case clang::APValue::Int:
|
||||
if (result_expr->getType()->isBooleanType()) {
|
||||
|
||||
+100
@@ -681,6 +681,69 @@ fn F() {
|
||||
Cpp.M_A_NO_SCOPE;
|
||||
}
|
||||
|
||||
// --- constexpr_int.carbon
|
||||
|
||||
library "[[@TEST_NAME]]";
|
||||
|
||||
import Cpp inline '''
|
||||
constexpr int a = 1;
|
||||
#define M_CONSTEXPR_INT ::a
|
||||
''';
|
||||
|
||||
fn F() {
|
||||
//@dump-sem-ir-begin
|
||||
let a: i32 = Cpp.M_CONSTEXPR_INT;
|
||||
//@dump-sem-ir-end
|
||||
}
|
||||
|
||||
// --- fail_import_constexpr_no_scope.carbon
|
||||
|
||||
library "[[@TEST_NAME]]";
|
||||
|
||||
import Cpp inline '''
|
||||
constexpr int a = 1;
|
||||
// CHECK:STDERR: fail_import_constexpr_no_scope.carbon:[[@LINE+7]]:33: error: use of undeclared identifier 'a'; did you mean '::a'? [CppInteropParseError]
|
||||
// CHECK:STDERR: 13 | #define M_CONSTEXPR_NO_SCOPE a
|
||||
// CHECK:STDERR: | ^
|
||||
// CHECK:STDERR: | ::a
|
||||
// CHECK:STDERR: fail_import_constexpr_no_scope.carbon:[[@LINE-5]]:18: note: '::a' declared here [CppInteropParseNote]
|
||||
// CHECK:STDERR: 5 | constexpr int a = 1;
|
||||
// CHECK:STDERR: | ^
|
||||
#define M_CONSTEXPR_NO_SCOPE a
|
||||
''';
|
||||
|
||||
fn F() {
|
||||
// CHECK:STDERR: fail_import_constexpr_no_scope.carbon:[[@LINE+4]]:16: note: in `Cpp` name lookup for `M_CONSTEXPR_NO_SCOPE` [InCppNameLookup]
|
||||
// CHECK:STDERR: let a: i32 = Cpp.M_CONSTEXPR_NO_SCOPE;
|
||||
// CHECK:STDERR: ^~~~~~~~~~~~~~~~~~~~~~~~
|
||||
// CHECK:STDERR:
|
||||
let a: i32 = Cpp.M_CONSTEXPR_NO_SCOPE;
|
||||
}
|
||||
|
||||
// --- fail_todo_import_macro_constexpr_float.carbon
|
||||
|
||||
library "[[@TEST_NAME]]";
|
||||
|
||||
import Cpp inline '''
|
||||
constexpr float b = 1.0f;
|
||||
#define M_CONSTEXPR_FLOAT ::b
|
||||
''';
|
||||
|
||||
fn F() {
|
||||
// CHECK:STDERR: fail_todo_import_macro_constexpr_float.carbon:[[@LINE+11]]:16: error: semantics TODO: `Unsupported: macro evaluated to a non-integer LValue` [SemanticsTodo]
|
||||
// CHECK:STDERR: let a: f32 = Cpp.M_CONSTEXPR_FLOAT;
|
||||
// CHECK:STDERR: ^~~~~~~~~~~~~~~~~~~~~
|
||||
// CHECK:STDERR: fail_todo_import_macro_constexpr_float.carbon:[[@LINE+8]]:16: note: in `Cpp` name lookup for `M_CONSTEXPR_FLOAT` [InCppNameLookup]
|
||||
// CHECK:STDERR: let a: f32 = Cpp.M_CONSTEXPR_FLOAT;
|
||||
// CHECK:STDERR: ^~~~~~~~~~~~~~~~~~~~~
|
||||
// CHECK:STDERR:
|
||||
// CHECK:STDERR: fail_todo_import_macro_constexpr_float.carbon:[[@LINE+4]]:16: error: member name `M_CONSTEXPR_FLOAT` not found in `Cpp` [MemberNameNotFoundInInstScope]
|
||||
// CHECK:STDERR: let a: f32 = Cpp.M_CONSTEXPR_FLOAT;
|
||||
// CHECK:STDERR: ^~~~~~~~~~~~~~~~~~~~~
|
||||
// CHECK:STDERR:
|
||||
let a: f32 = Cpp.M_CONSTEXPR_FLOAT;
|
||||
}
|
||||
|
||||
// --- lambda.carbon
|
||||
|
||||
library "[[@TEST_NAME]]";
|
||||
@@ -1828,6 +1891,43 @@ fn F() {
|
||||
// CHECK:STDOUT: <elided>
|
||||
// CHECK:STDOUT: }
|
||||
// CHECK:STDOUT:
|
||||
// CHECK:STDOUT: --- constexpr_int.carbon
|
||||
// CHECK:STDOUT:
|
||||
// CHECK:STDOUT: constants {
|
||||
// CHECK:STDOUT: %int_32: Core.IntLiteral = int_value 32 [concrete]
|
||||
// CHECK:STDOUT: %i32: type = class_type @Int, @Int(%int_32) [concrete]
|
||||
// CHECK:STDOUT: %pattern_type.7ce: type = pattern_type %i32 [concrete]
|
||||
// CHECK:STDOUT: %const: type = const_type %i32 [concrete]
|
||||
// CHECK:STDOUT: %int_1.22e: %const = int_value 1 [concrete]
|
||||
// CHECK:STDOUT: %int_1.5d2: %i32 = int_value 1 [concrete]
|
||||
// CHECK:STDOUT: }
|
||||
// CHECK:STDOUT:
|
||||
// CHECK:STDOUT: imports {
|
||||
// CHECK:STDOUT: %Cpp: <namespace> = namespace file.%Cpp.import_cpp, [concrete] {
|
||||
// CHECK:STDOUT: .M_CONSTEXPR_INT = %int_1
|
||||
// CHECK:STDOUT: import Cpp//...
|
||||
// CHECK:STDOUT: }
|
||||
// CHECK:STDOUT: %int_1: %const = int_value 1 [concrete = constants.%int_1.22e]
|
||||
// CHECK:STDOUT: }
|
||||
// CHECK:STDOUT:
|
||||
// CHECK:STDOUT: fn @F() {
|
||||
// CHECK:STDOUT: !entry:
|
||||
// CHECK:STDOUT: name_binding_decl {
|
||||
// CHECK:STDOUT: %a.patt: %pattern_type.7ce = value_binding_pattern a [concrete]
|
||||
// CHECK:STDOUT: }
|
||||
// CHECK:STDOUT: %Cpp.ref: <namespace> = name_ref Cpp, imports.%Cpp [concrete = imports.%Cpp]
|
||||
// CHECK:STDOUT: <elided>
|
||||
// CHECK:STDOUT: %M_CONSTEXPR_INT.ref: %const = name_ref M_CONSTEXPR_INT, imports.%int_1 [concrete = constants.%int_1.22e]
|
||||
// CHECK:STDOUT: %.loc11_10: type = splice_block %i32.loc11 [concrete = constants.%i32] {
|
||||
// CHECK:STDOUT: %int_32.loc11: Core.IntLiteral = int_value 32 [concrete = constants.%int_32]
|
||||
// CHECK:STDOUT: %i32.loc11: type = class_type @Int, @Int(constants.%int_32) [concrete = constants.%i32]
|
||||
// CHECK:STDOUT: }
|
||||
// CHECK:STDOUT: %.loc11_19.1: %i32 = as_compatible %M_CONSTEXPR_INT.ref [concrete = constants.%int_1.5d2]
|
||||
// CHECK:STDOUT: %.loc11_19.2: %i32 = converted %M_CONSTEXPR_INT.ref, %.loc11_19.1 [concrete = constants.%int_1.5d2]
|
||||
// CHECK:STDOUT: %a: %i32 = value_binding a, %.loc11_19.2
|
||||
// CHECK:STDOUT: <elided>
|
||||
// CHECK:STDOUT: }
|
||||
// CHECK:STDOUT:
|
||||
// CHECK:STDOUT: --- lambda.carbon
|
||||
// CHECK:STDOUT:
|
||||
// CHECK:STDOUT: constants {
|
||||
|
||||
Reference in New Issue
Block a user