Line data Source code
1 : // Copyright (C) 2020-2026 Free Software Foundation, Inc.
2 :
3 : // This file is part of GCC.
4 :
5 : // GCC is free software; you can redistribute it and/or modify it under
6 : // the terms of the GNU General Public License as published by the Free
7 : // Software Foundation; either version 3, or (at your option) any later
8 : // version.
9 :
10 : // GCC is distributed in the hope that it will be useful, but WITHOUT ANY
11 : // WARRANTY; without even the implied warranty of MERCHANTABILITY or
12 : // FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
13 : // for more details.
14 :
15 : // You should have received a copy of the GNU General Public License
16 : // along with GCC; see the file COPYING3. If not see
17 : // <http://www.gnu.org/licenses/>.
18 :
19 : #include "expected.h"
20 : #include "libproc_macro_internal/tokenstream.h"
21 : #include "optional.h"
22 : #include "rust-ast-full-decls.h"
23 : #include "rust-builtin-ast-nodes.h"
24 : #include "rust-expand-format-args.h"
25 : #include "rust-token-converter.h"
26 : #include "rust-system.h"
27 : #include "rust-macro-builtins.h"
28 : #include "rust-ast-fragment.h"
29 : #include "rust-ast.h"
30 : #include "rust-cfg-strip.h"
31 : #include "rust-diagnostics.h"
32 : #include "rust-expr.h"
33 : #include "rust-lex.h"
34 : #include "rust-macro-invoc-lexer.h"
35 : #include "rust-macro.h"
36 : #include "rust-parse.h"
37 : #include "rust-session-manager.h"
38 : #include "rust-attribute-values.h"
39 : #include "rust-fmt.h"
40 : #include "rust-token.h"
41 :
42 : #include "rust-macro-builtins-helpers.h"
43 : namespace Rust {
44 :
45 : const BiMap<std::string, BuiltinMacro> MacroBuiltin::builtins = {{
46 : {"assert", BuiltinMacro::Assert},
47 : {"file", BuiltinMacro::File},
48 : {"line", BuiltinMacro::Line},
49 : {"column", BuiltinMacro::Column},
50 : {"include_bytes", BuiltinMacro::IncludeBytes},
51 : {"include_str", BuiltinMacro::IncludeStr},
52 : {"stringify", BuiltinMacro::Stringify},
53 : {"compile_error", BuiltinMacro::CompileError},
54 : {"concat", BuiltinMacro::Concat},
55 : {"env", BuiltinMacro::Env},
56 : {"option_env", BuiltinMacro::OptionEnv},
57 : {"cfg", BuiltinMacro::Cfg},
58 : {"include", BuiltinMacro::Include},
59 : {"format_args", BuiltinMacro::FormatArgs},
60 : {"format_args_nl", BuiltinMacro::FormatArgsNl},
61 : {"concat_idents", BuiltinMacro::ConcatIdents},
62 : {"module_path", BuiltinMacro::ModulePath},
63 : {"asm", BuiltinMacro::Asm},
64 : // FIXME: Is that okay
65 : {"llvm_asm", BuiltinMacro::Asm},
66 : {"global_asm", BuiltinMacro::GlobalAsm},
67 : {"log_syntax", BuiltinMacro::LogSyntax},
68 : {"trace_macros", BuiltinMacro::TraceMacros},
69 : {"test", BuiltinMacro::Test},
70 : {"bench", BuiltinMacro::Bench},
71 : {"test_case", BuiltinMacro::TestCase},
72 : {"global_allocator", BuiltinMacro::GlobalAllocator},
73 : {"cfg_accessible", BuiltinMacro::CfgAccessible},
74 : {"RustcEncodable", BuiltinMacro::RustcDecodable},
75 : {"RustcDecodable", BuiltinMacro::RustcEncodable},
76 : {"Clone", BuiltinMacro::Clone},
77 : {"Copy", BuiltinMacro::Copy},
78 : {"Debug", BuiltinMacro::Debug},
79 : {"Default", BuiltinMacro::Default},
80 : {"Eq", BuiltinMacro::Eq},
81 : {"PartialEq", BuiltinMacro::PartialEq},
82 : {"Ord", BuiltinMacro::Ord},
83 : {"PartialOrd", BuiltinMacro::PartialOrd},
84 : {"Hash", BuiltinMacro::Hash},
85 : }};
86 :
87 : AST::MacroTranscriberFunc
88 9272 : format_args_maker (AST::FormatArgs::Newline nl)
89 : {
90 9276 : return [nl] (location_t loc, AST::MacroInvocData &invoc,
91 : AST::InvocKind semicolon) {
92 4 : return MacroBuiltin::format_args_handler (loc, invoc, semicolon, nl);
93 9272 : };
94 : }
95 :
96 : AST::MacroTranscriberFunc
97 9272 : inline_asm_maker (AST::AsmKind global_asm)
98 : {
99 9311 : return [global_asm] (location_t loc, AST::MacroInvocData &invoc,
100 : AST::InvocKind semicolon) {
101 39 : return MacroBuiltin::asm_handler (loc, invoc, semicolon, global_asm);
102 9272 : };
103 : }
104 :
105 : AST::MacroTranscriberFunc
106 4636 : inline_llvm_asm_maker (AST::AsmKind global_asm)
107 : {
108 4638 : return [global_asm] (location_t loc, AST::MacroInvocData &invoc,
109 : AST::InvocKind semicolon) {
110 2 : return MacroBuiltin::llvm_asm_handler (loc, invoc, semicolon, global_asm);
111 4636 : };
112 : }
113 :
114 : std::unordered_map<std::string, AST::MacroTranscriberFunc>
115 : MacroBuiltin::builtin_transcribers = {
116 : {"assert", MacroBuiltin::assert_handler},
117 : {"file", MacroBuiltin::file_handler},
118 : {"line", MacroBuiltin::line_handler},
119 : {"column", MacroBuiltin::column_handler},
120 : {"include_bytes", MacroBuiltin::include_bytes_handler},
121 : {"include_str", MacroBuiltin::include_str_handler},
122 : {"stringify", MacroBuiltin::stringify_handler},
123 : {"compile_error", MacroBuiltin::compile_error_handler},
124 : {"concat", MacroBuiltin::concat_handler},
125 : {"env", MacroBuiltin::env_handler},
126 : {"cfg", MacroBuiltin::cfg_handler},
127 : {"include", MacroBuiltin::include_handler},
128 : {"format_args", format_args_maker (AST::FormatArgs::Newline::No)},
129 : {"format_args_nl", format_args_maker (AST::FormatArgs::Newline::Yes)},
130 : {"asm", inline_asm_maker (AST::AsmKind::Inline)},
131 : // FIXME: Is that okay?
132 : {"llvm_asm", inline_llvm_asm_maker (AST::AsmKind::Inline)},
133 : {"global_asm", inline_asm_maker (AST::AsmKind::Global)},
134 : {"option_env", MacroBuiltin::option_env_handler},
135 : /* Unimplemented macro builtins */
136 : {"concat_idents", MacroBuiltin::sorry},
137 : {"module_path", MacroBuiltin::sorry},
138 : {"log_syntax", MacroBuiltin::sorry},
139 : {"trace_macros", MacroBuiltin::sorry},
140 : {"test", MacroBuiltin::sorry},
141 : {"bench", MacroBuiltin::sorry},
142 : {"test_case", MacroBuiltin::sorry},
143 : {"global_allocator", MacroBuiltin::sorry},
144 : {"cfg_accessible", MacroBuiltin::sorry},
145 : {"rustc_const_stable", MacroBuiltin::sorry},
146 : {"rustc_const_unstable", MacroBuiltin::sorry},
147 : {"track_caller", MacroBuiltin::sorry},
148 : /* Derive builtins do not need a real transcriber, but still need one. It
149 : should however never be called since builtin derive macros get expanded
150 : differently, and benefit from knowing on what kind of items they are
151 : applied (struct, enums, unions) rather than receiving a list of tokens
152 : like regular builtin macros */
153 : {"RustcEncodable", MacroBuiltin::proc_macro_builtin},
154 : {"RustcDecodable", MacroBuiltin::proc_macro_builtin},
155 : {"Clone", MacroBuiltin::proc_macro_builtin},
156 : {"Copy", MacroBuiltin::proc_macro_builtin},
157 : {"Debug", MacroBuiltin::proc_macro_builtin},
158 : {"Default", MacroBuiltin::proc_macro_builtin},
159 : {"Eq", MacroBuiltin::proc_macro_builtin},
160 : {"PartialEq", MacroBuiltin::proc_macro_builtin},
161 : {"Ord", MacroBuiltin::proc_macro_builtin},
162 : {"PartialOrd", MacroBuiltin::proc_macro_builtin},
163 : {"Hash", MacroBuiltin::proc_macro_builtin},
164 : /* offset_of is not declared in Rust 1.49 but still needed for
165 : Rust-for-Linux, so we still create a transcriber and warn the user */
166 : {"offset_of", MacroBuiltin::offset_of_handler},
167 : };
168 :
169 : tl::optional<BuiltinMacro>
170 0 : builtin_macro_from_string (const std::string &identifier)
171 : {
172 0 : auto macro = MacroBuiltin::builtins.lookup (identifier);
173 0 : rust_assert (macro.has_value ());
174 :
175 0 : return macro;
176 : }
177 :
178 : tl::optional<AST::Fragment>
179 0 : MacroBuiltin::sorry (location_t invoc_locus, AST::MacroInvocData &invoc,
180 : AST::InvocKind semicolon)
181 : {
182 0 : rust_sorry_at (invoc_locus, "unimplemented builtin macro: %qs",
183 : invoc.get_path ().as_string ().c_str ());
184 :
185 0 : return AST::Fragment::create_error ();
186 : }
187 :
188 : tl::optional<AST::Fragment>
189 1 : MacroBuiltin::proc_macro_builtin (location_t invoc_locus,
190 : AST::MacroInvocData &invoc,
191 : AST::InvocKind semicolon)
192 : {
193 1 : rust_error_at (invoc_locus, "cannot invoke derive macro: %qs",
194 1 : invoc.get_path ().as_string ().c_str ());
195 :
196 1 : return AST::Fragment::create_error ();
197 : }
198 :
199 : } // namespace Rust
|