// 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