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 "optional.h"
20 : #include "rust-ast-fragment.h"
21 : #include "rust-ast.h"
22 : #include "rust-builtin-ast-nodes.h"
23 : #include "rust-diagnostics.h"
24 : #include "rust-macro-builtins-helpers.h"
25 : #include "rust-macro-builtins.h"
26 : #include "rust-macro-invoc-lexer.h"
27 : #include "rust-parse.h"
28 :
29 : namespace Rust {
30 :
31 : tl::optional<AST::Fragment>
32 18 : MacroBuiltin::offset_of_handler (location_t invoc_locus,
33 : AST::MacroInvocData &invoc,
34 : AST::InvocKind semicolon)
35 : {
36 18 : MacroInvocLexer lex (invoc.get_delim_tok_tree ().to_token_stream ());
37 18 : Parser<MacroInvocLexer> parser (lex);
38 :
39 18 : auto last_token = macro_end_token (invoc.get_delim_tok_tree (), parser);
40 :
41 18 : auto type = parser.parse_type ();
42 :
43 : // if we don't see a type, there might be an eager macro expansion missing
44 : // FIXME: handle that
45 18 : if (!type)
46 : {
47 1 : rust_error_at (invoc_locus, "could not parse type argument for %qs",
48 : "offset_of");
49 :
50 : // we skip so we can still parse the field arg and check if it is correct
51 1 : while (parser.peek_current_token ()->get_id () != COMMA
52 6 : && parser.peek_current_token ()->get_id () != last_token)
53 1 : parser.skip_token ();
54 : }
55 :
56 18 : parser.skip_token (COMMA);
57 :
58 18 : auto field_tok = parser.parse_identifier_or_keyword_token ();
59 18 : auto invalid_field = !field_tok || !field_tok.value ()->should_have_str ();
60 :
61 1 : if (invalid_field)
62 1 : rust_error_at (invoc_locus, "could not parse field argument for %qs",
63 : "offset_of");
64 :
65 18 : if (!type || invalid_field)
66 2 : return tl::nullopt;
67 :
68 48 : auto field = Identifier (field_tok.value ()->get_str ());
69 :
70 : // FIXME: Do we need to do anything to handle the optional comma at the end?
71 16 : parser.maybe_skip_token (COMMA);
72 :
73 32 : return AST::Fragment ({AST::SingleASTNode (std::make_unique<AST::OffsetOf> (
74 : std::move (type), field, invoc_locus))},
75 80 : invoc.get_delim_tok_tree ().to_token_stream ());
76 52 : }
77 :
78 : } // namespace Rust
|