mirror of
https://github.com/carbon-language/carbon-lang.git
synced 2026-09-24 22:02:23 +01:00
Adds support for object-like macros with a single replacement
numeric-literal kind token. Only macros that evaluate to an integer
constant are supported for now. When detected at name lookup, they are
imported as a constant integer value in Carbon.
Demo:
```c++
// --- macros.h
#define CONFIG_VALUE 2
```
``` c++
// main.carbon
library "Main";
import Cpp library "macros.h";
import Core library "io";
fn Run() {
let a: i32 = Cpp.CONFIG_VALUE;
Core.Print(a);
}
```
```c++
$ bazel-bin/toolchain/carbon compile main.carbon
$ bazel-bin/toolchain/carbon link main.o \--output=demo_carbon
$ ./demo_carbon
2
```
Part of #6303
47 lines
1.7 KiB
C++
47 lines
1.7 KiB
C++
// Part of the Carbon Language project, under the Apache License v2.0 with LLVM
|
|
// Exceptions. See /LICENSE for license information.
|
|
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
|
|
|
#include "toolchain/check/cpp/macros.h"
|
|
|
|
#include "clang/AST/ASTContext.h"
|
|
#include "clang/Sema/Sema.h"
|
|
|
|
namespace Carbon::Check {
|
|
|
|
auto TryEvaluateMacroToConstant(Context& context, SemIR::LocId loc_id,
|
|
SemIR::NameId name_id,
|
|
clang::MacroInfo* macro_info) -> clang::Expr* {
|
|
auto name_str_opt = context.names().GetAsStringIfIdentifier(name_id);
|
|
CARBON_CHECK(macro_info, "macro info missing");
|
|
if (macro_info->getNumTokens() != 1) {
|
|
context.TODO(loc_id,
|
|
llvm::formatv("Unsupported: macro with {0} replacement tokens",
|
|
macro_info->getNumTokens()));
|
|
return nullptr;
|
|
}
|
|
const clang::Token& tok = macro_info->getReplacementToken(0);
|
|
if (!tok.is(clang::tok::numeric_constant)) {
|
|
context.TODO(loc_id,
|
|
"Unsupported: macro replacement token kind: " +
|
|
std::string(clang::tok::getTokenName(tok.getKind())));
|
|
return nullptr;
|
|
}
|
|
clang::Sema& sema = context.clang_sema();
|
|
clang::ExprResult result = sema.ActOnNumericConstant(tok);
|
|
clang::Expr* result_expr = result.get();
|
|
|
|
if (!result_expr || result.isInvalid()) {
|
|
CARBON_DIAGNOSTIC(
|
|
InCppMacroEvaluation, Error,
|
|
"failed to evaluate macro Cpp.{0} to a valid constant expression",
|
|
std::string);
|
|
context.emitter().Emit(loc_id, InCppMacroEvaluation, (*name_str_opt).str());
|
|
return nullptr;
|
|
}
|
|
|
|
return result_expr;
|
|
}
|
|
|
|
} // namespace Carbon::Check
|