// Copyright (C) 2020-2025 Free Software Foundation, Inc.
// This file is part of GCC.
// GCC is free software; you can redistribute it and/or modify it under
// the terms of the GNU General Public License as published by the Free
// Software Foundation; either version 3, or (at your option) any later
// version.
// GCC is distributed in the hope that it will be useful, but WITHOUT ANY
// WARRANTY; without even the implied warranty of MERCHANTABILITY or
// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
// for more details.
// You should have received a copy of the GNU General Public License
// along with GCC; see the file COPYING3. If not see
// .
#ifndef RUST_MACRO_BUILTINS_H
#define RUST_MACRO_BUILTINS_H
#include "rust-ast.h"
#include "rust-builtin-ast-nodes.h"
#include "rust-ast-fragment.h"
#include "rust-location.h"
#include "bi-map.h"
namespace Rust {
// FIXME: Add a BuiltinMacro class which contains a name (or should it?), a
// transcriber and extra info if necessary
// then make a global map
//
// All builtin macros possible
//
enum class BuiltinMacro
{
Assert,
File,
Line,
Column,
IncludeBytes,
IncludeStr,
Stringify,
CompileError,
Concat,
Env,
OptionEnv,
Cfg,
Include,
FormatArgs,
FormatArgsNl,
ConcatIdents,
ModulePath,
Asm,
LlvmAsm,
GlobalAsm,
LogSyntax,
TraceMacros,
Test,
Bench,
TestCase,
GlobalAllocator,
CfgAccessible,
RustcDecodable,
RustcEncodable,
Clone,
Copy,
Debug,
Default,
Eq,
PartialEq,
Ord,
PartialOrd,
Hash,
};
tl::optional
builtin_macro_from_string (const std::string &identifier);
//
// This class provides a list of builtin macros implemented by the compiler.
// The functions defined are called "builtin transcribers" in that they
// replace the transcribing part of a macro definition.
//
// Like regular macro transcribers, they are responsible for building and
// returning an AST fragment: basically a vector of AST nodes put together.
//
// Unlike regular declarative macros where each match arm has its own
// associated transcriber, builtin transcribers are responsible for handling
// all match arms of the macro. This means that you should take extra care
// when implementing a builtin containing multiple match arms: You will
// probably need to do some lookahead in order to determine which match arm
// the user intended to use.
//
// An example of this is the `assert!()` macro:
//
// ```
// macro_rules! assert {
// ($cond:expr $(,)?) => {{ ... }};
// ($cond : expr, $ ($arg : tt) +) = > {{ ... }};
// }
// ```
//
// If more tokens exist beyond the optional comma, they need to be handled as
// a token-tree for a custom panic message.
//
// These builtin macros with empty transcribers are defined in the standard
// library. They are marked with a special attribute,
// `#[rustc_builtin_macro]`. When this attribute is present on a macro
// definition, the compiler should look for an associated transcriber in the
// mappings. Meaning that you must remember to insert your transcriber in the
// `builtin_macros` map of the `Mappings`.
//
// This map is built as a static variable in the `insert_macro_def()` method
// of the `Mappings` class.
class MacroBuiltin
{
public:
static const BiMap builtins;
static std::unordered_map
builtin_transcribers;
static tl::optional assert_handler (location_t invoc_locus,
AST::MacroInvocData &invoc,
AST::InvocKind semicolon);
static tl::optional file_handler (location_t invoc_locus,
AST::MacroInvocData &invoc,
AST::InvocKind semicolon);
static tl::optional column_handler (location_t invoc_locus,
AST::MacroInvocData &invoc,
AST::InvocKind semicolon);
static tl::optional
include_bytes_handler (location_t invoc_locus, AST::MacroInvocData &invoc,
AST::InvocKind semicolon);
static tl::optional
include_str_handler (location_t invoc_locus, AST::MacroInvocData &invoc,
AST::InvocKind semicolon);
static tl::optional
stringify_handler (location_t invoc_locus, AST::MacroInvocData &invoc,
AST::InvocKind semicolon);
static tl::optional
compile_error_handler (location_t invoc_locus, AST::MacroInvocData &invoc,
AST::InvocKind semicolon);
static tl::optional concat_handler (location_t invoc_locus,
AST::MacroInvocData &invoc,
AST::InvocKind semicolon);
static tl::optional env_handler (location_t invoc_locus,
AST::MacroInvocData &invoc,
AST::InvocKind semicolon);
static tl::optional cfg_handler (location_t invoc_locus,
AST::MacroInvocData &invoc,
AST::InvocKind semicolon);
static tl::optional
include_handler (location_t invoc_locus, AST::MacroInvocData &invoc,
AST::InvocKind semicolon);
static tl::optional line_handler (location_t invoc_locus,
AST::MacroInvocData &invoc,
AST::InvocKind semicolon);
static tl::optional asm_handler (location_t invoc_locus,
AST::MacroInvocData &invoc,
AST::InvocKind semicolon,
AST::AsmKind is_global_asm);
static tl::optional
format_args_handler (location_t invoc_locus, AST::MacroInvocData &invoc,
AST::InvocKind semicolon, AST::FormatArgs::Newline nl);
static tl::optional sorry (location_t invoc_locus,
AST::MacroInvocData &invoc,
AST::InvocKind semicolon);
/* Builtin procedural macros do not work directly on tokens, but still need a
* builtin transcriber to be considered proper builtin macros */
static tl::optional
proc_macro_builtin (location_t, AST::MacroInvocData &, AST::InvocKind);
};
} // namespace Rust
namespace std {
template <> struct hash
{
size_t operator() (const Rust::BuiltinMacro ¯o) const noexcept
{
return hash::type> () (
static_cast::type> (macro));
}
};
} // namespace std
#endif // RUST_MACRO_BUILTINS_H