Files
carbon-lang/toolchain/check/cpp/macros.cpp
T
Ivana Ivanovska 3b0dad9dd5 Add support for simple object-like macros (#6326)
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
2025-11-11 11:24:20 +00:00

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