Branch data Line data Source code
1 : : // Copyright (C) 2020-2025 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->has_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->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 : 36 : }
77 : :
78 : : } // namespace Rust
|