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 : : #ifndef RUST_AST_BASE_H
20 : : #define RUST_AST_BASE_H
21 : : // Base for AST used in gccrs, basically required by all specific ast things
22 : :
23 : : #include "rust-system.h"
24 : : #include "rust-hir-map.h"
25 : : #include "rust-token.h"
26 : : #include "rust-location.h"
27 : : #include "rust-diagnostics.h"
28 : : #include "rust-keyword-values.h"
29 : :
30 : : namespace Rust {
31 : : // TODO: remove typedefs and make actual types for these
32 : : typedef int TupleIndex;
33 : : struct Session;
34 : : struct MacroExpander;
35 : :
36 : 22228669 : class Identifier
37 : : {
38 : : public:
39 : : // Create dummy identifier
40 : 6569 : Identifier () : ident (""), loc (UNDEF_LOCATION) {}
41 : : // Create identifier with dummy location
42 : 774672 : Identifier (std::string ident, location_t loc = UNDEF_LOCATION)
43 : 1547112 : : ident (ident), loc (loc)
44 : : {}
45 : : // Create identifier from token
46 : 67276 : Identifier (const_TokenPtr token)
47 : 67276 : : ident (token->get_str ()), loc (token->get_locus ())
48 : 67276 : {}
49 : :
50 : 26116764 : Identifier (const Identifier &) = default;
51 : 5724855 : Identifier (Identifier &&) = default;
52 : 0 : Identifier &operator= (const Identifier &) = default;
53 : 5185 : Identifier &operator= (Identifier &&) = default;
54 : :
55 : 3211 : location_t get_locus () const { return loc; }
56 : 9904350 : const std::string &as_string () const { return ident; }
57 : :
58 : 9805271 : bool empty () const { return ident.empty (); }
59 : :
60 : : bool operator== (const Identifier &other) const
61 : : {
62 : : return ident == other.ident;
63 : : }
64 : :
65 : 1 : operator const std::string & () const { return ident; }
66 : :
67 : : private:
68 : : std::string ident;
69 : : location_t loc;
70 : : };
71 : :
72 : : std::ostream &operator<< (std::ostream &os, Identifier const &i);
73 : :
74 : : namespace AST {
75 : : // foward decl: ast visitor
76 : : class ASTVisitor;
77 : : using AttrVec = std::vector<Attribute>;
78 : :
79 : 845386 : class Visitable
80 : : {
81 : : public:
82 : 680953 : virtual ~Visitable () = default;
83 : : virtual void accept_vis (ASTVisitor &vis) = 0;
84 : : };
85 : :
86 : : /**
87 : : * Base function for reconstructing and asserting that the new NodeId is
88 : : * different from the old NodeId. It then wraps the given pointer into a unique
89 : : * pointer and returns it.
90 : : */
91 : : template <typename T>
92 : : std::unique_ptr<T>
93 : 192 : reconstruct_base (const T *instance)
94 : : {
95 : 192 : auto *reconstructed = instance->reconstruct_impl ();
96 : :
97 : 192 : rust_assert (reconstructed->get_node_id () != instance->get_node_id ());
98 : :
99 : 192 : return std::unique_ptr<T> (reconstructed);
100 : : }
101 : :
102 : : /**
103 : : * Reconstruct multiple items in a vector
104 : : */
105 : : template <typename T>
106 : : std::vector<std::unique_ptr<T>>
107 : 180 : reconstruct_vec (const std::vector<std::unique_ptr<T>> &to_reconstruct)
108 : : {
109 : 180 : std::vector<std::unique_ptr<T>> reconstructed;
110 : 180 : reconstructed.reserve (to_reconstruct.size ());
111 : :
112 : 351 : for (const auto &elt : to_reconstruct)
113 : 171 : reconstructed.emplace_back (std::unique_ptr<T> (elt->reconstruct_impl ()));
114 : :
115 : 180 : return reconstructed;
116 : : }
117 : :
118 : : // Delimiter types - used in macros and whatever.
119 : : enum DelimType
120 : : {
121 : : PARENS,
122 : : SQUARE,
123 : : CURLY
124 : : };
125 : :
126 : : // forward decl for use in token tree method
127 : : class Token;
128 : :
129 : : // A tree of tokens (or a single token) - abstract base class
130 : 2578923 : class TokenTree : public Visitable
131 : : {
132 : : public:
133 : 313409 : virtual ~TokenTree () {}
134 : :
135 : : // Unique pointer custom clone function
136 : 7811003 : std::unique_ptr<TokenTree> clone_token_tree () const
137 : : {
138 : 7811003 : return std::unique_ptr<TokenTree> (clone_token_tree_impl ());
139 : : }
140 : :
141 : : virtual std::string as_string () const = 0;
142 : :
143 : : /* Converts token tree to a flat token stream. Tokens must be pointer to
144 : : * avoid mutual dependency with Token. */
145 : : virtual std::vector<std::unique_ptr<Token>> to_token_stream () const = 0;
146 : :
147 : : protected:
148 : : // pure virtual clone implementation
149 : : virtual TokenTree *clone_token_tree_impl () const = 0;
150 : : };
151 : :
152 : : // Abstract base class for a macro match
153 : 22125 : class MacroMatch : public Visitable
154 : : {
155 : : public:
156 : : enum MacroMatchType
157 : : {
158 : : Fragment,
159 : : Repetition,
160 : : Matcher,
161 : : Tok
162 : : };
163 : :
164 : 2019 : virtual ~MacroMatch () {}
165 : :
166 : : virtual std::string as_string () const = 0;
167 : : virtual location_t get_match_locus () const = 0;
168 : :
169 : : // Unique pointer custom clone function
170 : 5402 : std::unique_ptr<MacroMatch> clone_macro_match () const
171 : : {
172 : 5402 : return std::unique_ptr<MacroMatch> (clone_macro_match_impl ());
173 : : }
174 : :
175 : : virtual MacroMatchType get_macro_match_type () const = 0;
176 : :
177 : : protected:
178 : : // pure virtual clone implementation
179 : : virtual MacroMatch *clone_macro_match_impl () const = 0;
180 : : };
181 : :
182 : : // A token is a kind of token tree (except delimiter tokens)
183 : : class Token : public TokenTree, public MacroMatch
184 : : {
185 : : // A token is a kind of token tree (except delimiter tokens)
186 : : // A token is a kind of MacroMatch (except $ and delimiter tokens)
187 : :
188 : : const_TokenPtr tok_ref;
189 : :
190 : : /* new idea: wrapper around const_TokenPtr used for heterogeneuous storage
191 : : * in token trees. rather than convert back and forth when parsing macros,
192 : : * just wrap it. */
193 : :
194 : : public:
195 : : // Unique pointer custom clone function
196 : 14858990 : std::unique_ptr<Token> clone_token () const
197 : : {
198 : 14858990 : return std::unique_ptr<Token> (clone_token_impl ());
199 : : }
200 : :
201 : : // Constructor from lexer const_TokenPtr
202 : 1030682 : Token (const_TokenPtr lexer_tok_ptr) : tok_ref (std::move (lexer_tok_ptr)) {}
203 : :
204 : 833950 : bool is_string_lit () const
205 : : {
206 : 833950 : switch (get_id ())
207 : : {
208 : : case STRING_LITERAL:
209 : : case BYTE_STRING_LITERAL:
210 : : case RAW_STRING_LITERAL:
211 : : return true;
212 : 795431 : default:
213 : 795431 : return false;
214 : : }
215 : : }
216 : :
217 : : std::string as_string () const override;
218 : 1165 : location_t get_match_locus () const override
219 : : {
220 : 1165 : return tok_ref->get_locus ();
221 : : };
222 : :
223 : : void accept_vis (ASTVisitor &vis) override;
224 : :
225 : : // Return copy of itself but in token stream form.
226 : : std::vector<std::unique_ptr<Token>> to_token_stream () const override;
227 : :
228 : 4037349 : TokenId get_id () const { return tok_ref->get_id (); }
229 : 17 : bool should_have_str () const { return tok_ref->should_have_str (); }
230 : 697831 : const std::string &get_str () const { return tok_ref->get_str (); }
231 : :
232 : 6043 : location_t get_locus () const { return tok_ref->get_locus (); }
233 : :
234 : 1 : PrimitiveCoreType get_type_hint () const { return tok_ref->get_type_hint (); }
235 : :
236 : : // Get a new token pointer copy.
237 : 10389781 : const_TokenPtr get_tok_ptr () const { return tok_ref; }
238 : :
239 : 138197 : MacroMatchType get_macro_match_type () const override
240 : : {
241 : 138197 : return MacroMatchType::Tok;
242 : : }
243 : :
244 : : protected:
245 : : // No virtual for now as not polymorphic but can be in future
246 : 25894437 : /*virtual*/ Token *clone_token_impl () const { return new Token (*this); }
247 : :
248 : : /* Use covariance to implement clone function as returning this object
249 : : * rather than base */
250 : 7606002 : Token *clone_token_tree_impl () const final override
251 : : {
252 : 7606002 : return clone_token_impl ();
253 : : }
254 : :
255 : : /* Use covariance to implement clone function as returning this object
256 : : * rather than base */
257 : 0 : Token *clone_macro_match_impl () const final override
258 : : {
259 : 0 : return clone_token_impl ();
260 : : }
261 : : };
262 : :
263 : : // A literal - value with a type. Used in LiteralExpr and LiteralPattern.
264 : 22529 : struct Literal
265 : : {
266 : : public:
267 : : enum LitType
268 : : {
269 : : CHAR,
270 : : STRING,
271 : : BYTE,
272 : : BYTE_STRING,
273 : : RAW_STRING,
274 : : INT,
275 : : FLOAT,
276 : : BOOL,
277 : : ERROR
278 : : };
279 : :
280 : : private:
281 : : /* TODO: maybe make subclasses of each type of literal with their typed
282 : : * values (or generics) */
283 : : std::string value_as_string;
284 : : LitType type;
285 : : PrimitiveCoreType type_hint;
286 : :
287 : : public:
288 : 33284 : std::string as_string () const { return value_as_string; }
289 : :
290 : 29277 : LitType get_lit_type () const { return type; }
291 : :
292 : 20343 : PrimitiveCoreType get_type_hint () const { return type_hint; }
293 : :
294 : 492558 : Literal (std::string value_as_string, LitType type,
295 : : PrimitiveCoreType type_hint)
296 : 492558 : : value_as_string (std::move (value_as_string)), type (type),
297 : 492558 : type_hint (type_hint)
298 : : {}
299 : :
300 : 0 : static Literal create_error ()
301 : : {
302 : 0 : return Literal ("", ERROR, PrimitiveCoreType::CORETYPE_UNKNOWN);
303 : : }
304 : :
305 : : // Returns whether literal is in an invalid state.
306 : 17109630 : bool is_error () const { return type == ERROR; }
307 : : };
308 : :
309 : : /* Forward decl - definition moved to rust-expr.h as it requires LiteralExpr
310 : : * to be defined */
311 : : class AttrInputLiteral;
312 : :
313 : : /* TODO: move applicable stuff into here or just don't include it because
314 : : * nothing uses it A segment of a path (maybe) */
315 : 341197 : class PathSegment
316 : : {
317 : : public:
318 : 55359 : virtual ~PathSegment () {}
319 : :
320 : : virtual std::string as_string () const = 0;
321 : :
322 : : // TODO: add visitor here?
323 : : };
324 : :
325 : : // A segment of a simple path without generic or type arguments
326 : 282185 : class SimplePathSegment : public PathSegment
327 : : {
328 : : std::string segment_name;
329 : : location_t locus;
330 : : NodeId node_id;
331 : :
332 : : // only allow identifiers, "super", "self", "crate", or "$crate"
333 : : public:
334 : : // TODO: put checks in constructor to enforce this rule?
335 : 170619 : SimplePathSegment (std::string segment_name, location_t locus)
336 : 341238 : : segment_name (std::move (segment_name)), locus (locus),
337 : 170619 : node_id (Analysis::Mappings::get ().get_next_node_id ())
338 : 170619 : {}
339 : :
340 : : /* Returns whether simple path segment is in an invalid state (currently, if
341 : : * empty). */
342 : 478600 : bool is_error () const { return segment_name.empty (); }
343 : :
344 : : // Creates an error SimplePathSegment
345 : 636 : static SimplePathSegment create_error ()
346 : : {
347 : 636 : return SimplePathSegment (std::string (""), UNDEF_LOCATION);
348 : : }
349 : :
350 : : std::string as_string () const override;
351 : :
352 : 147736 : location_t get_locus () const { return locus; }
353 : 276114 : NodeId get_node_id () const { return node_id; }
354 : 3221523 : const std::string &get_segment_name () const { return segment_name; }
355 : 150875 : bool is_super_path_seg () const
356 : : {
357 : 150875 : return as_string ().compare (Values::Keywords::SUPER) == 0;
358 : : }
359 : 372479 : bool is_crate_path_seg () const
360 : : {
361 : 372479 : return as_string ().compare (Values::Keywords::CRATE) == 0;
362 : : }
363 : 402863 : bool is_lower_self_seg () const
364 : : {
365 : 402863 : return as_string ().compare (Values::Keywords::SELF) == 0;
366 : : }
367 : 2079 : bool is_big_self () const
368 : : {
369 : 2079 : return as_string ().compare (Values::Keywords::SELF_ALIAS) == 0;
370 : : }
371 : : };
372 : :
373 : : // A simple path without generic or type arguments
374 : 3950610 : class SimplePath
375 : : {
376 : : bool opening_scope_resolution;
377 : : std::vector<SimplePathSegment> segments;
378 : : location_t locus;
379 : : NodeId node_id;
380 : :
381 : : public:
382 : : // Constructor
383 : 657183 : explicit SimplePath (std::vector<SimplePathSegment> path_segments,
384 : : bool has_opening_scope_resolution = false,
385 : : location_t locus = UNDEF_LOCATION)
386 : 657183 : : opening_scope_resolution (has_opening_scope_resolution),
387 : 657183 : segments (std::move (path_segments)), locus (locus),
388 : 657183 : node_id (Analysis::Mappings::get ().get_next_node_id ())
389 : 657183 : {}
390 : :
391 : 1046 : explicit SimplePath (Identifier ident)
392 : 1046 : : opening_scope_resolution (false),
393 : 3138 : segments ({SimplePathSegment (ident.as_string (), ident.get_locus ())}),
394 : 1046 : locus (ident.get_locus ()),
395 : 1046 : node_id (Analysis::Mappings::get ().get_next_node_id ())
396 : 1046 : {}
397 : :
398 : : // Creates an empty SimplePath.
399 : 491439 : static SimplePath create_empty ()
400 : : {
401 : 491439 : return SimplePath (std::vector<SimplePathSegment> ());
402 : : }
403 : :
404 : : // Returns whether the SimplePath is empty, i.e. has path segments.
405 : 237529 : bool is_empty () const { return segments.empty (); }
406 : :
407 : : const std::string as_string () const;
408 : :
409 : 131739 : bool has_opening_scope_resolution () const
410 : : {
411 : 131739 : return opening_scope_resolution;
412 : : }
413 : :
414 : 54523 : location_t get_locus () const { return locus; }
415 : 124 : NodeId get_node_id () const { return node_id; }
416 : :
417 : : // does this need visitor if not polymorphic? probably not
418 : :
419 : : // path-to-string comparison operator
420 : 12778609 : bool operator== (const std::string &rhs) const
421 : : {
422 : 12778609 : return !opening_scope_resolution && segments.size () == 1
423 : 25554803 : && segments[0].as_string () == rhs;
424 : : }
425 : :
426 : : /* Creates a single-segment SimplePath from a string. This will not check to
427 : : * ensure that this is a valid identifier in path, so be careful. Also, this
428 : : * will have no location data.
429 : : * TODO have checks? */
430 : 4811 : static SimplePath from_str (std::string str, location_t locus)
431 : : {
432 : 4811 : std::vector<AST::SimplePathSegment> single_segments
433 : 9622 : = {AST::SimplePathSegment (std::move (str), locus)};
434 : 4811 : return SimplePath (std::move (single_segments), false, locus);
435 : 4811 : }
436 : :
437 : 63455 : const std::vector<SimplePathSegment> &get_segments () const
438 : : {
439 : 141242 : return segments;
440 : : }
441 : :
442 : 3370364 : std::vector<SimplePathSegment> &get_segments () { return segments; }
443 : :
444 : 190383 : const SimplePathSegment &get_final_segment () const
445 : : {
446 : 190383 : return segments.back ();
447 : : }
448 : : };
449 : :
450 : : // path-to-string inverse comparison operator
451 : : inline bool
452 : 914 : operator!= (const SimplePath &lhs, const std::string &rhs)
453 : : {
454 : 914 : return !(lhs == rhs);
455 : : }
456 : :
457 : : // forward decl for Attribute
458 : : class AttrInput;
459 : :
460 : : // Visibility of item - if the item has it, then it is some form of public
461 : 307470 : struct Visibility
462 : : {
463 : : public:
464 : : enum VisType
465 : : {
466 : : PRIV,
467 : : PUB,
468 : : PUB_CRATE,
469 : : PUB_SELF,
470 : : PUB_SUPER,
471 : : PUB_IN_PATH
472 : : };
473 : :
474 : : private:
475 : : VisType vis_type;
476 : : // Only assigned if vis_type is IN_PATH
477 : : SimplePath in_path;
478 : : location_t locus;
479 : :
480 : : // should this store location info?
481 : :
482 : : public:
483 : : // Creates a Visibility - TODO make constructor protected or private?
484 : 473426 : Visibility (VisType vis_type, SimplePath in_path, location_t locus)
485 : 343238 : : vis_type (vis_type), in_path (std::move (in_path)), locus (locus)
486 : : {}
487 : :
488 : 3517 : VisType get_vis_type () const { return vis_type; }
489 : :
490 : : // Returns whether visibility is in an error state.
491 : 4137904 : bool is_error () const
492 : : {
493 : 201989 : return vis_type == PUB_IN_PATH && in_path.is_empty ();
494 : : }
495 : :
496 : : // Returns whether a visibility has a path
497 : 3937848 : bool has_path () const { return !is_error () && vis_type >= PUB_CRATE; }
498 : :
499 : : // Returns whether visibility is public or not.
500 : 165665 : bool is_public () const { return vis_type != PRIV && !is_error (); }
501 : :
502 : 2656 : location_t get_locus () const { return locus; }
503 : :
504 : : // empty?
505 : : // Creates an error visibility.
506 : 6108 : static Visibility create_error ()
507 : : {
508 : 6108 : return Visibility (PUB_IN_PATH, SimplePath::create_empty (),
509 : 6108 : UNDEF_LOCATION);
510 : : }
511 : :
512 : : // Unique pointer custom clone function
513 : : /*std::unique_ptr<Visibility> clone_visibility() const {
514 : : return std::unique_ptr<Visibility>(clone_visibility_impl());
515 : : }*/
516 : :
517 : : /* TODO: think of a way to only allow valid Visibility states - polymorphism
518 : : * is one idea but may be too resource-intensive. */
519 : :
520 : : // Creates a public visibility with no further features/arguments.
521 : : // empty?
522 : 13780 : static Visibility create_public (location_t pub_vis_location)
523 : : {
524 : 13780 : return Visibility (PUB, SimplePath::create_empty (), pub_vis_location);
525 : : }
526 : :
527 : : // Creates a public visibility with crate-relative paths
528 : 266 : static Visibility create_crate (location_t crate_tok_location,
529 : : location_t crate_vis_location)
530 : : {
531 : 266 : return Visibility (PUB_CRATE,
532 : 266 : SimplePath::from_str (Values::Keywords::CRATE,
533 : : crate_tok_location),
534 : 266 : crate_vis_location);
535 : : }
536 : :
537 : : // Creates a public visibility with self-relative paths
538 : 0 : static Visibility create_self (location_t self_tok_location,
539 : : location_t self_vis_location)
540 : : {
541 : 0 : return Visibility (PUB_SELF,
542 : 0 : SimplePath::from_str (Values::Keywords::SELF,
543 : : self_tok_location),
544 : 0 : self_vis_location);
545 : : }
546 : :
547 : : // Creates a public visibility with parent module-relative paths
548 : 96 : static Visibility create_super (location_t super_tok_location,
549 : : location_t super_vis_location)
550 : : {
551 : 96 : return Visibility (PUB_SUPER,
552 : 96 : SimplePath::from_str (Values::Keywords::SUPER,
553 : : super_tok_location),
554 : 96 : super_vis_location);
555 : : }
556 : :
557 : : // Creates a private visibility
558 : 453158 : static Visibility create_private ()
559 : : {
560 : 453158 : return Visibility (PRIV, SimplePath::create_empty (), UNDEF_LOCATION);
561 : : }
562 : :
563 : : // Creates a public visibility with a given path or whatever.
564 : 18 : static Visibility create_in_path (SimplePath in_path,
565 : : location_t in_path_vis_location)
566 : : {
567 : 18 : return Visibility (PUB_IN_PATH, std::move (in_path), in_path_vis_location);
568 : : }
569 : :
570 : : std::string as_string () const;
571 : 61 : const SimplePath &get_path () const { return in_path; }
572 : 41396 : SimplePath &get_path () { return in_path; }
573 : :
574 : : protected:
575 : : // Clone function implementation - not currently virtual but may be if
576 : : // polymorphism used
577 : : /*virtual*/ Visibility *clone_visibility_impl () const
578 : : {
579 : : return new Visibility (*this);
580 : : }
581 : : };
582 : :
583 : : // aka Attr
584 : : // Attribute AST representation
585 : : struct Attribute
586 : : {
587 : : private:
588 : : SimplePath path;
589 : :
590 : : // bool has_attr_input;
591 : : std::unique_ptr<AttrInput> attr_input;
592 : :
593 : : location_t locus;
594 : :
595 : : bool inner_attribute;
596 : :
597 : : // TODO: maybe a variable storing whether attr input is parsed or not
598 : :
599 : : public:
600 : : // Returns whether Attribute has AttrInput
601 : 3336625 : bool has_attr_input () const { return attr_input != nullptr; }
602 : :
603 : : // Constructor has pointer AttrInput for polymorphism reasons
604 : 109152 : Attribute (SimplePath path, std::unique_ptr<AttrInput> input,
605 : : location_t locus = UNDEF_LOCATION, bool inner_attribute = false)
606 : 109152 : : path (std::move (path)), attr_input (std::move (input)), locus (locus),
607 : 109152 : inner_attribute (inner_attribute)
608 : : {}
609 : :
610 : : bool is_derive () const;
611 : :
612 : : std::vector<std::reference_wrapper<AST::SimplePath>> get_traits_to_derive ();
613 : :
614 : : // default destructor
615 : 1611410 : ~Attribute () = default;
616 : :
617 : : // no point in being defined inline as requires virtual call anyway
618 : : Attribute (const Attribute &other);
619 : :
620 : : // no point in being defined inline as requires virtual call anyway
621 : : Attribute &operator= (const Attribute &other);
622 : :
623 : : // default move semantics
624 : 248391 : Attribute (Attribute &&other) = default;
625 : 386 : Attribute &operator= (Attribute &&other) = default;
626 : :
627 : : // Unique pointer custom clone function
628 : : std::unique_ptr<Attribute> clone_attribute () const
629 : : {
630 : : return std::unique_ptr<Attribute> (clone_attribute_impl ());
631 : : }
632 : :
633 : : // Creates an empty attribute (which is invalid)
634 : 9334 : static Attribute create_empty ()
635 : : {
636 : 9334 : return Attribute (SimplePath::create_empty (), nullptr);
637 : : }
638 : :
639 : : // Returns whether the attribute is considered an "empty" attribute.
640 : 98568 : bool is_empty () const { return attr_input == nullptr && path.is_empty (); }
641 : :
642 : : // Returns whether the attribute has no input
643 : 5914 : bool empty_input () const { return !attr_input; }
644 : :
645 : 4175 : location_t get_locus () const { return locus; }
646 : :
647 : 33949 : AttrInput &get_attr_input () const { return *attr_input; }
648 : :
649 : : /* e.g.:
650 : : #![crate_type = "lib"]
651 : : #[test]
652 : : #[cfg(target_os = "linux")]
653 : : #[allow(non_camel_case_types)]
654 : : #![allow(unused_variables)]
655 : : */
656 : :
657 : : // Full built-in attribute list:
658 : : /* cfg
659 : : * cfg_attr
660 : : * test
661 : : * ignore
662 : : * should_panic
663 : : * derive
664 : : * macro_export
665 : : * macro_use
666 : : * proc_macro
667 : : * proc_macro_derive
668 : : * proc_macro_attribute
669 : : * allow
670 : : * warn
671 : : * deny
672 : : * forbid
673 : : * deprecated
674 : : * must_use
675 : : * link
676 : : * link_name
677 : : * no_link
678 : : * repr
679 : : * crate_type
680 : : * no_main
681 : : * export_name
682 : : * link_section
683 : : * no_mangle
684 : : * used
685 : : * crate_name
686 : : * inline
687 : : * cold
688 : : * no_builtins
689 : : * target_feature
690 : : * doc
691 : : * no_std
692 : : * no_implicit_prelude
693 : : * path
694 : : * recursion_limit
695 : : * type_length_limit
696 : : * panic_handler
697 : : * global_allocator
698 : : * windows_subsystem
699 : : * feature */
700 : :
701 : : std::string as_string () const;
702 : :
703 : 2079 : bool is_inner_attribute () const { return inner_attribute; }
704 : :
705 : : // no visitor pattern as not currently polymorphic
706 : :
707 : 2988993 : const SimplePath &get_path () const { return path; }
708 : 6149575 : SimplePath &get_path () { return path; }
709 : :
710 : : // Call to parse attribute body to meta item syntax.
711 : : void parse_attr_to_meta_item ();
712 : :
713 : : /* Determines whether cfg predicate is true and item with attribute should
714 : : * not be stripped. Attribute body must already be parsed to meta item. */
715 : : bool check_cfg_predicate (const Session &session) const;
716 : :
717 : : // Returns whether body has been parsed to meta item form or not.
718 : : bool is_parsed_to_meta_item () const;
719 : :
720 : : /* Returns any attributes generated from cfg_attr attributes. Attribute body
721 : : * must already be parsed to meta item. */
722 : : std::vector<Attribute> separate_cfg_attrs () const;
723 : :
724 : : protected:
725 : : // not virtual as currently no subclasses of Attribute, but could be in
726 : : // future
727 : : /*virtual*/ Attribute *clone_attribute_impl () const
728 : : {
729 : : return new Attribute (*this);
730 : : }
731 : : };
732 : :
733 : : // Attribute body - abstract base class
734 : 926918 : class AttrInput : public Visitable
735 : : {
736 : : public:
737 : : enum AttrInputType
738 : : {
739 : : LITERAL,
740 : : MACRO,
741 : : META_ITEM,
742 : : TOKEN_TREE,
743 : : };
744 : :
745 : 313409 : virtual ~AttrInput () {}
746 : :
747 : : // Unique pointer custom clone function
748 : 1269940 : std::unique_ptr<AttrInput> clone_attr_input () const
749 : : {
750 : 1269940 : return std::unique_ptr<AttrInput> (clone_attr_input_impl ());
751 : : }
752 : :
753 : : virtual std::string as_string () const = 0;
754 : :
755 : : virtual bool check_cfg_predicate (const Session &session) const = 0;
756 : :
757 : : // Parse attribute input to meta item, if possible
758 : 0 : virtual AttrInput *parse_to_meta_item () const { return nullptr; }
759 : :
760 : 0 : virtual std::vector<Attribute> separate_cfg_attrs () const { return {}; }
761 : :
762 : : // Returns whether attr input has been parsed to meta item syntax.
763 : : virtual bool is_meta_item () const = 0;
764 : :
765 : : virtual AttrInputType get_attr_input_type () const = 0;
766 : :
767 : : protected:
768 : : // pure virtual clone implementation
769 : : virtual AttrInput *clone_attr_input_impl () const = 0;
770 : : };
771 : :
772 : : // Forward decl - defined in rust-macro.h
773 : : class MetaNameValueStr;
774 : :
775 : : // abstract base meta item inner class
776 : 130 : class MetaItemInner : public Visitable
777 : : {
778 : : protected:
779 : : // pure virtual as MetaItemInner
780 : : virtual MetaItemInner *clone_meta_item_inner_impl () const = 0;
781 : :
782 : : public:
783 : : enum class Kind
784 : : {
785 : : LitExpr,
786 : : MetaItem,
787 : : };
788 : :
789 : : // Unique pointer custom clone function
790 : 91142 : std::unique_ptr<MetaItemInner> clone_meta_item_inner () const
791 : : {
792 : 91142 : return std::unique_ptr<MetaItemInner> (clone_meta_item_inner_impl ());
793 : : }
794 : :
795 : : virtual Kind get_kind () = 0;
796 : :
797 : : virtual ~MetaItemInner ();
798 : :
799 : : virtual location_t get_locus () const = 0;
800 : :
801 : : virtual std::string as_string () const = 0;
802 : :
803 : : /* HACK: used to simplify parsing - creates a copy of that type, or returns
804 : : * null */
805 : : virtual std::unique_ptr<MetaNameValueStr> to_meta_name_value_str () const;
806 : :
807 : : // HACK: used to simplify parsing - same thing
808 : 0 : virtual SimplePath to_path_item () const
809 : : {
810 : 0 : return SimplePath::create_empty ();
811 : : }
812 : :
813 : 0 : virtual Attribute to_attribute () const { return Attribute::create_empty (); }
814 : :
815 : : virtual bool check_cfg_predicate (const Session &session) const = 0;
816 : :
817 : 44 : virtual bool is_key_value_pair () const { return false; }
818 : : };
819 : :
820 : : // Container used to store MetaItems as AttrInput (bridge-ish kinda thing)
821 : : class AttrInputMetaItemContainer : public AttrInput
822 : : {
823 : : std::vector<std::unique_ptr<MetaItemInner>> items;
824 : :
825 : : public:
826 : 6422 : AttrInputMetaItemContainer (std::vector<std::unique_ptr<MetaItemInner>> items)
827 : 6422 : : items (std::move (items))
828 : : {}
829 : :
830 : : // copy constructor with vector clone
831 : 30445 : AttrInputMetaItemContainer (const AttrInputMetaItemContainer &other)
832 : 30445 : {
833 : 30445 : items.reserve (other.items.size ());
834 : 84119 : for (const auto &e : other.items)
835 : 53674 : items.push_back (e->clone_meta_item_inner ());
836 : 30445 : }
837 : :
838 : : // copy assignment operator with vector clone
839 : : AttrInputMetaItemContainer &
840 : : operator= (const AttrInputMetaItemContainer &other)
841 : : {
842 : : AttrInput::operator= (other);
843 : :
844 : : items.reserve (other.items.size ());
845 : : for (const auto &e : other.items)
846 : : items.push_back (e->clone_meta_item_inner ());
847 : :
848 : : return *this;
849 : : }
850 : :
851 : : // default move constructors
852 : : AttrInputMetaItemContainer (AttrInputMetaItemContainer &&other) = default;
853 : : AttrInputMetaItemContainer &operator= (AttrInputMetaItemContainer &&other)
854 : : = default;
855 : :
856 : : std::string as_string () const override;
857 : :
858 : : void accept_vis (ASTVisitor &vis) override;
859 : :
860 : : bool check_cfg_predicate (const Session &session) const override;
861 : :
862 : 615 : AttrInputType get_attr_input_type () const final override
863 : : {
864 : 615 : return AttrInput::AttrInputType::META_ITEM;
865 : : }
866 : :
867 : : // Clones this object.
868 : : std::unique_ptr<AttrInputMetaItemContainer>
869 : : clone_attr_input_meta_item_container () const
870 : : {
871 : : return std::unique_ptr<AttrInputMetaItemContainer> (
872 : : clone_attr_input_meta_item_container_impl ());
873 : : }
874 : :
875 : : std::vector<Attribute> separate_cfg_attrs () const override;
876 : :
877 : 70740 : bool is_meta_item () const override { return true; }
878 : :
879 : : // TODO: this mutable getter seems dodgy
880 : 68551 : std::vector<std::unique_ptr<MetaItemInner>> &get_items () { return items; }
881 : : const std::vector<std::unique_ptr<MetaItemInner>> &get_items () const
882 : : {
883 : : return items;
884 : : }
885 : :
886 : : protected:
887 : : // Use covariance to implement clone function as returning this type
888 : 30445 : AttrInputMetaItemContainer *clone_attr_input_impl () const final override
889 : : {
890 : 30445 : return clone_attr_input_meta_item_container_impl ();
891 : : }
892 : :
893 : 30445 : AttrInputMetaItemContainer *clone_attr_input_meta_item_container_impl () const
894 : : {
895 : 30445 : return new AttrInputMetaItemContainer (*this);
896 : : }
897 : : };
898 : :
899 : : // A token tree with delimiters
900 : 257039 : class DelimTokenTree : public TokenTree, public AttrInput
901 : : {
902 : : DelimType delim_type;
903 : : std::vector<std::unique_ptr<TokenTree>> token_trees;
904 : : location_t locus;
905 : :
906 : : protected:
907 : 633497 : DelimTokenTree *clone_delim_tok_tree_impl () const
908 : : {
909 : 633497 : return new DelimTokenTree (*this);
910 : : }
911 : :
912 : : /* Use covariance to implement clone function as returning a DelimTokenTree
913 : : * object */
914 : 0 : DelimTokenTree *clone_attr_input_impl () const final override
915 : : {
916 : 0 : return clone_delim_tok_tree_impl ();
917 : : }
918 : :
919 : : /* Use covariance to implement clone function as returning a DelimTokenTree
920 : : * object */
921 : 205001 : DelimTokenTree *clone_token_tree_impl () const final override
922 : : {
923 : 205001 : return clone_delim_tok_tree_impl ();
924 : : }
925 : :
926 : : public:
927 : 193574 : DelimTokenTree (DelimType delim_type,
928 : : std::vector<std::unique_ptr<TokenTree>> token_trees
929 : : = std::vector<std::unique_ptr<TokenTree>> (),
930 : : location_t locus = UNDEF_LOCATION)
931 : 193574 : : delim_type (delim_type), token_trees (std::move (token_trees)),
932 : 193574 : locus (locus)
933 : : {}
934 : :
935 : : // Copy constructor with vector clone
936 : 1032316 : DelimTokenTree (DelimTokenTree const &other)
937 : 1032316 : : delim_type (other.delim_type), locus (other.locus)
938 : : {
939 : 1032316 : token_trees.clear ();
940 : 1032316 : token_trees.reserve (other.token_trees.size ());
941 : 8843141 : for (const auto &e : other.token_trees)
942 : 7810825 : token_trees.push_back (e->clone_token_tree ());
943 : 1032316 : }
944 : :
945 : : // overloaded assignment operator with vector clone
946 : 45 : DelimTokenTree &operator= (DelimTokenTree const &other)
947 : : {
948 : 45 : delim_type = other.delim_type;
949 : 45 : locus = other.locus;
950 : :
951 : 45 : token_trees.clear ();
952 : 45 : token_trees.reserve (other.token_trees.size ());
953 : 223 : for (const auto &e : other.token_trees)
954 : 178 : token_trees.push_back (e->clone_token_tree ());
955 : :
956 : 45 : return *this;
957 : : }
958 : :
959 : : // move constructors
960 : 194720 : DelimTokenTree (DelimTokenTree &&other) = default;
961 : : DelimTokenTree &operator= (DelimTokenTree &&other) = default;
962 : :
963 : 20 : static DelimTokenTree create_empty () { return DelimTokenTree (PARENS); }
964 : :
965 : : std::string as_string () const override;
966 : :
967 : : void accept_vis (ASTVisitor &vis) override;
968 : :
969 : 0 : bool check_cfg_predicate (const Session &) const override
970 : : {
971 : : // this should never be called - should be converted first
972 : 0 : rust_assert (false);
973 : : return false;
974 : : }
975 : :
976 : : AttrInputMetaItemContainer *parse_to_meta_item () const override;
977 : :
978 : : std::vector<std::unique_ptr<Token>> to_token_stream () const override;
979 : :
980 : : std::unique_ptr<DelimTokenTree> clone_delim_token_tree () const
981 : : {
982 : : return std::unique_ptr<DelimTokenTree> (clone_delim_tok_tree_impl ());
983 : : }
984 : :
985 : 3430 : bool is_meta_item () const override { return false; }
986 : :
987 : 5221 : AttrInputType get_attr_input_type () const final override
988 : : {
989 : 5221 : return AttrInput::AttrInputType::TOKEN_TREE;
990 : : }
991 : :
992 : : std::vector<std::unique_ptr<TokenTree>> &get_token_trees ()
993 : : {
994 : 558886 : return token_trees;
995 : : }
996 : :
997 : : const std::vector<std::unique_ptr<TokenTree>> &get_token_trees () const
998 : : {
999 : 0 : return token_trees;
1000 : : }
1001 : :
1002 : 167164 : DelimType get_delim_type () const { return delim_type; }
1003 : 110389 : location_t get_locus () const { return locus; }
1004 : : };
1005 : :
1006 : : /* Forward decl - definition moved to rust-expr.h as it requires LiteralExpr
1007 : : * to be defined */
1008 : : class AttrInputLiteral;
1009 : :
1010 : : // abstract base meta item class
1011 : 92163 : class MetaItem : public MetaItemInner
1012 : : {
1013 : : public:
1014 : : enum class ItemKind
1015 : : {
1016 : : Path,
1017 : : Word,
1018 : : NameValueStr,
1019 : : PathExpr,
1020 : : Seq,
1021 : : ListPaths,
1022 : : ListNameValueStr,
1023 : : };
1024 : :
1025 : 1570 : MetaItemInner::Kind get_kind () override
1026 : : {
1027 : 1570 : return MetaItemInner::Kind::MetaItem;
1028 : : }
1029 : :
1030 : : virtual ItemKind get_item_kind () const = 0;
1031 : : };
1032 : :
1033 : : // Forward decl - defined in rust-expr.h
1034 : : class MetaItemLitExpr;
1035 : :
1036 : : // Forward decl - defined in rust-expr.h
1037 : : class MetaItemPathExpr;
1038 : :
1039 : : // Forward decl - defined in rust-macro.h
1040 : : class MetaItemPath;
1041 : :
1042 : : // Forward decl - defined in rust-macro.h
1043 : : class MetaItemSeq;
1044 : :
1045 : : // Forward decl - defined in rust-macro.h
1046 : : class MetaWord;
1047 : :
1048 : : // Forward decl - defined in rust-macro.h
1049 : : class MetaListPaths;
1050 : :
1051 : : // Forward decl - defined in rust-macro.h
1052 : : class MetaListNameValueStr;
1053 : :
1054 : : /* Base statement abstract class. Note that most "statements" are not allowed
1055 : : * in top-level module scope - only a subclass of statements called "items"
1056 : : * are. */
1057 : 1793 : class Stmt : public Visitable
1058 : : {
1059 : : public:
1060 : : enum class Kind
1061 : : {
1062 : : Empty,
1063 : : Item,
1064 : : Let,
1065 : : Expr,
1066 : : MacroInvocation,
1067 : : };
1068 : :
1069 : : // Unique pointer custom clone function
1070 : 24456 : std::unique_ptr<Stmt> clone_stmt () const
1071 : : {
1072 : 24456 : return std::unique_ptr<Stmt> (clone_stmt_impl ());
1073 : : }
1074 : :
1075 : : virtual ~Stmt () {}
1076 : :
1077 : : virtual std::string as_string () const = 0;
1078 : :
1079 : : virtual location_t get_locus () const = 0;
1080 : :
1081 : : virtual void mark_for_strip () = 0;
1082 : : virtual bool is_marked_for_strip () const = 0;
1083 : :
1084 : : // TODO: put this in a virtual base class?
1085 : 1566816 : virtual NodeId get_node_id () const { return node_id; }
1086 : :
1087 : : virtual Kind get_stmt_kind () = 0;
1088 : :
1089 : : // TODO: Can we remove these two?
1090 : : virtual bool is_item () const = 0;
1091 : 9150 : virtual bool is_expr () const { return false; }
1092 : :
1093 : 38 : virtual void add_semicolon () {}
1094 : :
1095 : : protected:
1096 : 612965 : Stmt () : node_id (Analysis::Mappings::get ().get_next_node_id ()) {}
1097 : :
1098 : : // Clone function implementation as pure virtual method
1099 : : virtual Stmt *clone_stmt_impl () const = 0;
1100 : :
1101 : : NodeId node_id;
1102 : : };
1103 : :
1104 : : // Rust "item" AST node (declaration of top-level/module-level allowed stuff)
1105 : 401589 : class Item : public Stmt
1106 : : {
1107 : : public:
1108 : : enum class Kind
1109 : : {
1110 : : MacroRulesDefinition,
1111 : : MacroInvocation,
1112 : : Module,
1113 : : ExternCrate,
1114 : : UseDeclaration,
1115 : : Function,
1116 : : TypeAlias,
1117 : : Struct,
1118 : : EnumItem,
1119 : : Enum,
1120 : : Union,
1121 : : ConstantItem,
1122 : : StaticItem,
1123 : : Trait,
1124 : : Impl,
1125 : : ExternBlock,
1126 : : };
1127 : :
1128 : : virtual Kind get_item_kind () const = 0;
1129 : :
1130 : : // Unique pointer custom clone function
1131 : 43585 : std::unique_ptr<Item> clone_item () const
1132 : : {
1133 : 43585 : return std::unique_ptr<Item> (clone_item_impl ());
1134 : : }
1135 : :
1136 : : /* Adds crate names to the vector passed by reference, if it can
1137 : : * (polymorphism). TODO: remove, unused. */
1138 : : virtual void
1139 : 0 : add_crate_name (std::vector<std::string> &names ATTRIBUTE_UNUSED) const
1140 : 0 : {}
1141 : :
1142 : 45531 : Stmt::Kind get_stmt_kind () final { return Stmt::Kind::Item; }
1143 : :
1144 : : // FIXME: ARTHUR: Is it okay to have removed that final? Is it *required*
1145 : : // behavior that we have items that can also be expressions?
1146 : 0 : bool is_item () const override { return true; }
1147 : :
1148 : : virtual std::vector<Attribute> &get_outer_attrs () = 0;
1149 : : virtual const std::vector<Attribute> &get_outer_attrs () const = 0;
1150 : :
1151 : 480990 : virtual bool has_outer_attrs () const { return !get_outer_attrs ().empty (); }
1152 : :
1153 : : protected:
1154 : : // Clone function implementation as pure virtual method
1155 : : virtual Item *clone_item_impl () const = 0;
1156 : :
1157 : : /* Save having to specify two clone methods in derived classes by making
1158 : : * statement clone return item clone. Hopefully won't affect performance too
1159 : : * much. */
1160 : 2326 : Item *clone_stmt_impl () const final override { return clone_item_impl (); }
1161 : : };
1162 : :
1163 : : // Item that supports visibility - abstract base class
1164 : : class VisItem : public Item
1165 : : {
1166 : : Visibility visibility;
1167 : : std::vector<Attribute> outer_attrs;
1168 : :
1169 : : protected:
1170 : : // Visibility constructor
1171 : 71127 : VisItem (Visibility visibility,
1172 : : std::vector<Attribute> outer_attrs = std::vector<Attribute> ())
1173 : 71127 : : visibility (std::move (visibility)), outer_attrs (std::move (outer_attrs))
1174 : 71127 : {}
1175 : :
1176 : : // Visibility copy constructor
1177 : 84220 : VisItem (VisItem const &other)
1178 : 84220 : : visibility (other.visibility), outer_attrs (other.outer_attrs)
1179 : 84220 : {}
1180 : :
1181 : : // Overload assignment operator to clone
1182 : 0 : VisItem &operator= (VisItem const &other)
1183 : : {
1184 : 0 : visibility = other.visibility;
1185 : 0 : outer_attrs = other.outer_attrs;
1186 : :
1187 : 0 : return *this;
1188 : : }
1189 : :
1190 : : // move constructors
1191 : 1681 : VisItem (VisItem &&other) = default;
1192 : : VisItem &operator= (VisItem &&other) = default;
1193 : :
1194 : : public:
1195 : : /* Does the item have some kind of public visibility (non-default
1196 : : * visibility)? */
1197 : 1246 : bool has_visibility () const { return visibility.is_public (); }
1198 : :
1199 : : std::string as_string () const override;
1200 : :
1201 : : // TODO: this mutable getter seems really dodgy. Think up better way.
1202 : 4110449 : Visibility &get_visibility () { return visibility; }
1203 : : const Visibility &get_visibility () const { return visibility; }
1204 : :
1205 : 7539097 : std::vector<Attribute> &get_outer_attrs () override { return outer_attrs; }
1206 : 479607 : const std::vector<Attribute> &get_outer_attrs () const override
1207 : : {
1208 : 479607 : return outer_attrs;
1209 : : }
1210 : :
1211 : : virtual Item::Kind get_item_kind () const override = 0;
1212 : : };
1213 : :
1214 : : // forward decl of ExprWithoutBlock
1215 : : class ExprWithoutBlock;
1216 : :
1217 : : // Base expression AST node - abstract
1218 : 93848 : class Expr : public Visitable
1219 : : {
1220 : : public:
1221 : : enum class Kind
1222 : : {
1223 : : PathInExpression,
1224 : : QualifiedPathInExpression,
1225 : : Literal,
1226 : : Operator,
1227 : : Grouped,
1228 : : Array,
1229 : : ArrayIndex,
1230 : : Tuple,
1231 : : TupleIndex,
1232 : : Struct,
1233 : : Call,
1234 : : MethodCall,
1235 : : FieldAccess,
1236 : : Closure,
1237 : : Block,
1238 : : ConstExpr,
1239 : : ConstBlock,
1240 : : Continue,
1241 : : Break,
1242 : : Range,
1243 : : Box,
1244 : : Return,
1245 : : UnsafeBlock,
1246 : : Loop,
1247 : : If,
1248 : : IfLet,
1249 : : Match,
1250 : : Await,
1251 : : AsyncBlock,
1252 : : InlineAsm,
1253 : : LlvmInlineAsm,
1254 : : Identifier,
1255 : : FormatArgs,
1256 : : OffsetOf,
1257 : : MacroInvocation,
1258 : : Borrow,
1259 : : Dereference,
1260 : : ErrorPropagation,
1261 : : Negation,
1262 : : ArithmeticOrLogical,
1263 : : Comparison,
1264 : : LazyBoolean,
1265 : : TypeCast,
1266 : : Assignment,
1267 : : CompoundAssignment,
1268 : : Try,
1269 : : };
1270 : :
1271 : : virtual Kind get_expr_kind () const = 0;
1272 : :
1273 : : // Unique pointer custom clone function
1274 : 46 : std::unique_ptr<Expr> clone_expr () const
1275 : : {
1276 : 2666671 : return std::unique_ptr<Expr> (clone_expr_impl ());
1277 : : }
1278 : :
1279 : : /* TODO: public methods that could be useful:
1280 : : * - get_type() - returns type of expression. set_type() may also be useful
1281 : : * for some?
1282 : : * - evaluate() - evaluates expression if constant? can_evaluate()? */
1283 : :
1284 : : virtual std::string as_string () const = 0;
1285 : :
1286 : 3012 : virtual ~Expr () {}
1287 : :
1288 : : virtual location_t get_locus () const = 0;
1289 : :
1290 : 42 : virtual bool is_literal () const { return false; }
1291 : :
1292 : : // HACK: strictly not needed, but faster than full downcast clone
1293 : : virtual bool is_expr_without_block () const = 0;
1294 : :
1295 : : virtual void mark_for_strip () = 0;
1296 : : virtual bool is_marked_for_strip () const = 0;
1297 : :
1298 : 17999965 : virtual NodeId get_node_id () const { return node_id; }
1299 : :
1300 : 0 : virtual void set_node_id (NodeId id) { node_id = id; }
1301 : :
1302 : : virtual std::vector<Attribute> &get_outer_attrs () = 0;
1303 : :
1304 : : // TODO: think of less hacky way to implement this kind of thing
1305 : : // Sets outer attributes.
1306 : : virtual void set_outer_attrs (std::vector<Attribute>) = 0;
1307 : :
1308 : : protected:
1309 : : // Constructor
1310 : 1841421 : Expr () : node_id (Analysis::Mappings::get ().get_next_node_id ()) {}
1311 : :
1312 : : // Clone function implementation as pure virtual method
1313 : : virtual Expr *clone_expr_impl () const = 0;
1314 : :
1315 : : NodeId node_id;
1316 : : };
1317 : :
1318 : : // AST node for an expression without an accompanying block - abstract
1319 : 1788155 : class ExprWithoutBlock : public Expr
1320 : : {
1321 : : protected:
1322 : : // pure virtual clone implementation
1323 : : virtual ExprWithoutBlock *clone_expr_without_block_impl () const = 0;
1324 : :
1325 : : /* Save having to specify two clone methods in derived classes by making
1326 : : * expr clone return exprwithoutblock clone. Hopefully won't affect
1327 : : * performance too much. */
1328 : 2626862 : ExprWithoutBlock *clone_expr_impl () const final override
1329 : : {
1330 : 2626862 : return clone_expr_without_block_impl ();
1331 : : }
1332 : :
1333 : 157667 : bool is_expr_without_block () const final override { return true; };
1334 : :
1335 : : public:
1336 : : // Unique pointer custom clone function
1337 : 43 : std::unique_ptr<ExprWithoutBlock> clone_expr_without_block () const
1338 : : {
1339 : 43 : return std::unique_ptr<ExprWithoutBlock> (clone_expr_without_block_impl ());
1340 : : }
1341 : : };
1342 : :
1343 : : /* HACK: IdentifierExpr, delete when figure out identifier vs expr problem in
1344 : : * Pratt parser */
1345 : : /* Alternatively, identifiers could just be represented as single-segment
1346 : : * paths
1347 : : */
1348 : : class IdentifierExpr : public ExprWithoutBlock
1349 : : {
1350 : : std::vector<Attribute> outer_attrs;
1351 : : Identifier ident;
1352 : : location_t locus;
1353 : :
1354 : : public:
1355 : 159270 : IdentifierExpr (Identifier ident, std::vector<Attribute> outer_attrs,
1356 : : location_t locus)
1357 : 477810 : : outer_attrs (std::move (outer_attrs)), ident (std::move (ident)),
1358 : 159270 : locus (locus)
1359 : 159270 : {}
1360 : :
1361 : 12 : std::string as_string () const override { return ident.as_string (); }
1362 : :
1363 : 118282 : location_t get_locus () const override final { return locus; }
1364 : :
1365 : 50403 : Identifier get_ident () const { return ident; }
1366 : :
1367 : : void accept_vis (ASTVisitor &vis) override;
1368 : :
1369 : : // Clones this object.
1370 : : std::unique_ptr<IdentifierExpr> clone_identifier_expr () const
1371 : : {
1372 : : return std::unique_ptr<IdentifierExpr> (clone_identifier_expr_impl ());
1373 : : }
1374 : :
1375 : : // "Error state" if ident is empty, so base stripping on this.
1376 : 0 : void mark_for_strip () override { ident = {""}; }
1377 : 9675054 : bool is_marked_for_strip () const override { return ident.empty (); }
1378 : :
1379 : : const std::vector<Attribute> &get_outer_attrs () const { return outer_attrs; }
1380 : 51380160 : std::vector<Attribute> &get_outer_attrs () override { return outer_attrs; }
1381 : :
1382 : 0 : void set_outer_attrs (std::vector<Attribute> new_attrs) override
1383 : : {
1384 : 0 : outer_attrs = std::move (new_attrs);
1385 : 0 : }
1386 : :
1387 : 146189 : Expr::Kind get_expr_kind () const override { return Expr::Kind::Identifier; }
1388 : :
1389 : : protected:
1390 : : // Clone method implementation
1391 : 556588 : IdentifierExpr *clone_expr_without_block_impl () const final override
1392 : : {
1393 : 556588 : return clone_identifier_expr_impl ();
1394 : : }
1395 : :
1396 : 556588 : IdentifierExpr *clone_identifier_expr_impl () const
1397 : : {
1398 : 556588 : return new IdentifierExpr (*this);
1399 : : }
1400 : : };
1401 : :
1402 : : // Pattern base AST node
1403 : 942729 : class Pattern : public Visitable
1404 : : {
1405 : : public:
1406 : : enum class Kind
1407 : : {
1408 : : Literal,
1409 : : Identifier,
1410 : : Wildcard,
1411 : : Rest,
1412 : : Range,
1413 : : Reference,
1414 : : Struct,
1415 : : TupleStruct,
1416 : : Tuple,
1417 : : Grouped,
1418 : : Slice,
1419 : : Alt,
1420 : : Path,
1421 : : MacroInvocation,
1422 : : };
1423 : :
1424 : : // Unique pointer custom clone function
1425 : 311329 : std::unique_ptr<Pattern> clone_pattern () const
1426 : : {
1427 : 311329 : return std::unique_ptr<Pattern> (clone_pattern_impl ());
1428 : : }
1429 : :
1430 : : virtual Kind get_pattern_kind () = 0;
1431 : :
1432 : : // possible virtual methods: is_refutable()
1433 : :
1434 : : virtual ~Pattern () {}
1435 : :
1436 : : virtual std::string as_string () const = 0;
1437 : :
1438 : : // as only one kind of pattern can be stripped, have default of nothing
1439 : 0 : virtual void mark_for_strip () {}
1440 : 4698764 : virtual bool is_marked_for_strip () const { return false; }
1441 : :
1442 : : virtual location_t get_locus () const = 0;
1443 : : virtual NodeId get_node_id () const = 0;
1444 : :
1445 : : protected:
1446 : : // Clone pattern implementation as pure virtual method
1447 : : virtual Pattern *clone_pattern_impl () const = 0;
1448 : : };
1449 : :
1450 : : // forward decl for Type
1451 : : class TraitBound;
1452 : :
1453 : : // Base class for types as represented in AST - abstract
1454 : 155441 : class Type : public Visitable
1455 : : {
1456 : : public:
1457 : : // Unique pointer custom clone function
1458 : 183226 : std::unique_ptr<Type> clone_type () const
1459 : : {
1460 : 183226 : return std::unique_ptr<Type> (clone_type_impl ());
1461 : : }
1462 : :
1463 : : // Similar to `clone_type`, but generates a new instance of the node with a
1464 : : // different NodeId
1465 : 186 : std::unique_ptr<Type> reconstruct () const { return reconstruct_base (this); }
1466 : :
1467 : : // virtual destructor
1468 : 186183 : virtual ~Type () {}
1469 : :
1470 : : virtual std::string as_string () const = 0;
1471 : :
1472 : : /* HACK: convert to trait bound. Virtual method overriden by classes that
1473 : : * enable this. */
1474 : 13 : virtual TraitBound *to_trait_bound (bool) const { return nullptr; }
1475 : : /* as pointer, shouldn't require definition beforehand, only forward
1476 : : * declaration. */
1477 : :
1478 : : // as only two kinds of types can be stripped, have default of nothing
1479 : 0 : virtual void mark_for_strip () {}
1480 : 1055113 : virtual bool is_marked_for_strip () const { return false; }
1481 : :
1482 : : virtual location_t get_locus () const = 0;
1483 : :
1484 : : // TODO: put this in a virtual base class?
1485 : 605803 : virtual NodeId get_node_id () const { return node_id; }
1486 : : virtual Type *reconstruct_impl () const = 0;
1487 : :
1488 : : protected:
1489 : 944008 : Type () : node_id (Analysis::Mappings::get ().get_next_node_id ()) {}
1490 : 170 : Type (NodeId node_id) : node_id (node_id) {}
1491 : :
1492 : : // Clone and reconstruct function implementations as pure virtual methods
1493 : : virtual Type *clone_type_impl () const = 0;
1494 : :
1495 : : NodeId node_id;
1496 : : };
1497 : :
1498 : : // A type without parentheses? - abstract
1499 : 317491 : class TypeNoBounds : public Type
1500 : : {
1501 : : public:
1502 : : // Unique pointer custom clone function
1503 : 46913 : std::unique_ptr<TypeNoBounds> clone_type_no_bounds () const
1504 : : {
1505 : 46913 : return std::unique_ptr<TypeNoBounds> (clone_type_no_bounds_impl ());
1506 : : }
1507 : :
1508 : 6 : std::unique_ptr<TypeNoBounds> reconstruct () const
1509 : : {
1510 : 6 : return reconstruct_base (this);
1511 : : }
1512 : :
1513 : : virtual TypeNoBounds *reconstruct_impl () const override = 0;
1514 : :
1515 : : protected:
1516 : : // Clone function implementation as pure virtual method
1517 : : virtual TypeNoBounds *clone_type_no_bounds_impl () const = 0;
1518 : :
1519 : : /* Save having to specify two clone methods in derived classes by making
1520 : : * type clone return typenobounds clone. Hopefully won't affect performance
1521 : : * too much. */
1522 : 183056 : TypeNoBounds *clone_type_impl () const final override
1523 : : {
1524 : 183056 : return clone_type_no_bounds_impl ();
1525 : : }
1526 : :
1527 : 943872 : TypeNoBounds () : Type () {}
1528 : : };
1529 : :
1530 : : /* Abstract base class representing a type param bound - Lifetime and
1531 : : * TraitBound extends it */
1532 : : class TypeParamBound : public Visitable
1533 : : {
1534 : : public:
1535 : : enum TypeParamBoundType
1536 : : {
1537 : : TRAIT,
1538 : : LIFETIME
1539 : : };
1540 : :
1541 : 26239 : virtual ~TypeParamBound () {}
1542 : :
1543 : : // Unique pointer custom clone function
1544 : 4906 : std::unique_ptr<TypeParamBound> clone_type_param_bound () const
1545 : : {
1546 : 4906 : return std::unique_ptr<TypeParamBound> (clone_type_param_bound_impl ());
1547 : : }
1548 : :
1549 : 0 : std::unique_ptr<TypeParamBound> reconstruct () const
1550 : : {
1551 : 0 : return reconstruct_base (this);
1552 : : }
1553 : :
1554 : : virtual std::string as_string () const = 0;
1555 : :
1556 : 11440 : NodeId get_node_id () const { return node_id; }
1557 : :
1558 : : virtual location_t get_locus () const = 0;
1559 : :
1560 : : virtual TypeParamBoundType get_bound_type () const = 0;
1561 : :
1562 : : virtual TypeParamBound *reconstruct_impl () const = 0;
1563 : :
1564 : : protected:
1565 : : // Clone function implementation as pure virtual method
1566 : : virtual TypeParamBound *clone_type_param_bound_impl () const = 0;
1567 : :
1568 : : TypeParamBound () : node_id (Analysis::Mappings::get ().get_next_node_id ())
1569 : : {}
1570 : 596 : TypeParamBound (NodeId node_id) : node_id (node_id) {}
1571 : :
1572 : : NodeId node_id;
1573 : : };
1574 : :
1575 : : // Represents a lifetime (and is also a kind of type param bound)
1576 : 75651 : class Lifetime : public TypeParamBound
1577 : : {
1578 : : public:
1579 : : enum LifetimeType
1580 : : {
1581 : : NAMED, // corresponds to LIFETIME_OR_LABEL
1582 : : STATIC, // corresponds to 'static
1583 : : WILDCARD // corresponds to '_
1584 : : };
1585 : :
1586 : : private:
1587 : : LifetimeType lifetime_type;
1588 : : std::string lifetime_name;
1589 : : location_t locus;
1590 : : NodeId node_id;
1591 : :
1592 : : public:
1593 : : // Constructor
1594 : 48632 : Lifetime (LifetimeType type, std::string name = std::string (),
1595 : : location_t locus = UNDEF_LOCATION)
1596 : 48632 : : TypeParamBound (Analysis::Mappings::get ().get_next_node_id ()),
1597 : 48632 : lifetime_type (type), lifetime_name (std::move (name)), locus (locus)
1598 : 48632 : {}
1599 : :
1600 : 0 : Lifetime (NodeId id, LifetimeType type, std::string name = std::string (),
1601 : : location_t locus = UNDEF_LOCATION)
1602 : 0 : : TypeParamBound (id), lifetime_type (type),
1603 : 0 : lifetime_name (std::move (name)), locus (locus)
1604 : : {}
1605 : :
1606 : 43655 : static Lifetime elided () { return Lifetime (WILDCARD, ""); }
1607 : :
1608 : : // Returns true if the lifetime is in an error state.
1609 : : std::string as_string () const override;
1610 : :
1611 : : void accept_vis (ASTVisitor &vis) override;
1612 : :
1613 : 10426 : LifetimeType get_lifetime_type () const { return lifetime_type; }
1614 : :
1615 : 10478 : location_t get_locus () const override final { return locus; }
1616 : :
1617 : 30402 : std::string get_lifetime_name () const { return lifetime_name; }
1618 : :
1619 : 19 : TypeParamBoundType get_bound_type () const override
1620 : : {
1621 : 19 : return TypeParamBound::TypeParamBoundType::LIFETIME;
1622 : : }
1623 : :
1624 : : protected:
1625 : : /* Use covariance to implement clone function as returning this object
1626 : : * rather than base */
1627 : 0 : Lifetime *clone_type_param_bound_impl () const override
1628 : : {
1629 : 0 : return new Lifetime (node_id, lifetime_type, lifetime_name, locus);
1630 : : }
1631 : 0 : Lifetime *reconstruct_impl () const override
1632 : : {
1633 : 0 : return new Lifetime (lifetime_type, lifetime_name, locus);
1634 : : }
1635 : : };
1636 : :
1637 : : /* Base generic parameter in AST. Abstract - can be represented by a Lifetime
1638 : : * or Type param */
1639 : : class GenericParam : public Visitable
1640 : : {
1641 : : public:
1642 : : enum class Kind
1643 : : {
1644 : : Lifetime,
1645 : : Type,
1646 : : Const,
1647 : : };
1648 : :
1649 : : virtual ~GenericParam () {}
1650 : :
1651 : : // Unique pointer custom clone function
1652 : 22341 : std::unique_ptr<GenericParam> clone_generic_param () const
1653 : : {
1654 : 22341 : return std::unique_ptr<GenericParam> (clone_generic_param_impl ());
1655 : : }
1656 : :
1657 : : virtual std::string as_string () const = 0;
1658 : :
1659 : : virtual location_t get_locus () const = 0;
1660 : :
1661 : : virtual Kind get_kind () const = 0;
1662 : :
1663 : 882446 : NodeId get_node_id () const { return node_id; }
1664 : :
1665 : : protected:
1666 : 1663 : GenericParam () : node_id (Analysis::Mappings::get ().get_next_node_id ()) {}
1667 : 35028 : GenericParam (NodeId node_id) : node_id (node_id) {}
1668 : :
1669 : : // Clone function implementation as pure virtual method
1670 : : virtual GenericParam *clone_generic_param_impl () const = 0;
1671 : :
1672 : : NodeId node_id;
1673 : : };
1674 : :
1675 : : // A lifetime generic parameter (as opposed to a type generic parameter)
1676 : : class LifetimeParam : public GenericParam
1677 : : {
1678 : : Lifetime lifetime;
1679 : : std::vector<Lifetime> lifetime_bounds;
1680 : : AST::AttrVec outer_attrs;
1681 : : location_t locus;
1682 : :
1683 : : public:
1684 : 0 : Lifetime get_lifetime () const { return lifetime; }
1685 : :
1686 : 129529 : Lifetime &get_lifetime () { return lifetime; }
1687 : :
1688 : 131180 : AST::AttrVec &get_outer_attrs () { return outer_attrs; }
1689 : :
1690 : : // Returns whether the lifetime param has any lifetime bounds.
1691 : 20 : bool has_lifetime_bounds () const { return !lifetime_bounds.empty (); }
1692 : :
1693 : 129218 : std::vector<Lifetime> &get_lifetime_bounds () { return lifetime_bounds; }
1694 : :
1695 : : const std::vector<Lifetime> &get_lifetime_bounds () const
1696 : : {
1697 : 0 : return lifetime_bounds;
1698 : : }
1699 : :
1700 : : // Returns whether the lifetime param has an outer attribute.
1701 : 0 : bool has_outer_attribute () const { return !outer_attrs.empty (); }
1702 : :
1703 : : // Constructor
1704 : 1487 : LifetimeParam (Lifetime lifetime, std::vector<Lifetime> lifetime_bounds,
1705 : : AST::AttrVec outer_attrs, location_t locus)
1706 : 2974 : : lifetime (std::move (lifetime)),
1707 : 1487 : lifetime_bounds (std::move (lifetime_bounds)),
1708 : 1487 : outer_attrs (std::move (outer_attrs)), locus (locus)
1709 : 1487 : {}
1710 : :
1711 : : std::string as_string () const override;
1712 : :
1713 : : void accept_vis (ASTVisitor &vis) override;
1714 : :
1715 : 489 : location_t get_locus () const override final { return locus; }
1716 : :
1717 : 4165 : Kind get_kind () const override final { return Kind::Lifetime; }
1718 : :
1719 : : protected:
1720 : : /* Use covariance to implement clone function as returning this object
1721 : : * rather than base */
1722 : 3152 : LifetimeParam *clone_generic_param_impl () const override
1723 : : {
1724 : 3152 : return new LifetimeParam (*this);
1725 : : }
1726 : : };
1727 : :
1728 : 56872 : class AssociatedItem : public Visitable
1729 : : {
1730 : : protected:
1731 : : // Clone function implementation as pure virtual method
1732 : : virtual AssociatedItem *clone_associated_item_impl () const = 0;
1733 : :
1734 : : public:
1735 : : virtual ~AssociatedItem () {}
1736 : :
1737 : 55921 : std::unique_ptr<AssociatedItem> clone_associated_item () const
1738 : : {
1739 : 55921 : return std::unique_ptr<AssociatedItem> (clone_associated_item_impl ());
1740 : : }
1741 : :
1742 : : virtual std::string as_string () const = 0;
1743 : :
1744 : : virtual void mark_for_strip () = 0;
1745 : : virtual bool is_marked_for_strip () const = 0;
1746 : :
1747 : : virtual location_t get_locus () const = 0;
1748 : :
1749 : : virtual NodeId get_node_id () const = 0;
1750 : : };
1751 : :
1752 : : // Item used in trait declarations - abstract base class
1753 : : class TraitItem : public AssociatedItem
1754 : : {
1755 : : protected:
1756 : 396548 : TraitItem (location_t locus)
1757 : 396548 : : node_id (Analysis::Mappings::get ().get_next_node_id ()),
1758 : 793096 : vis (Visibility::create_private ()), locus (locus)
1759 : 396548 : {}
1760 : :
1761 : 775 : TraitItem (Visibility vis, location_t locus)
1762 : 775 : : node_id (Analysis::Mappings::get ().get_next_node_id ()), vis (vis),
1763 : 775 : locus (locus)
1764 : 775 : {}
1765 : :
1766 : : // Clone function implementation as pure virtual method
1767 : : virtual TraitItem *clone_associated_item_impl () const override = 0;
1768 : :
1769 : : NodeId node_id;
1770 : : Visibility vis;
1771 : : location_t locus;
1772 : :
1773 : : public:
1774 : : // Unique pointer custom clone function
1775 : : std::unique_ptr<TraitItem> clone_trait_item () const
1776 : : {
1777 : : return std::unique_ptr<TraitItem> (clone_associated_item_impl ());
1778 : : }
1779 : :
1780 : 7876 : NodeId get_node_id () const override { return node_id; }
1781 : 5068 : location_t get_locus () const override { return locus; }
1782 : : };
1783 : :
1784 : : // Abstract base class for an item used inside an extern block
1785 : : class ExternalItem : public Visitable
1786 : : {
1787 : : public:
1788 : 59485 : ExternalItem () : node_id (Analysis::Mappings::get ().get_next_node_id ()) {}
1789 : :
1790 : 408366 : ExternalItem (NodeId node_id) : node_id (node_id) {}
1791 : :
1792 : : virtual ~ExternalItem () {}
1793 : :
1794 : : // Unique pointer custom clone function
1795 : 63 : std::unique_ptr<ExternalItem> clone_external_item () const
1796 : : {
1797 : 63 : return std::unique_ptr<ExternalItem> (clone_external_item_impl ());
1798 : : }
1799 : :
1800 : : virtual std::string as_string () const = 0;
1801 : :
1802 : : virtual void mark_for_strip () = 0;
1803 : : virtual bool is_marked_for_strip () const = 0;
1804 : :
1805 : 43 : virtual NodeId get_node_id () const { return node_id; }
1806 : :
1807 : : protected:
1808 : : // Clone function implementation as pure virtual method
1809 : : virtual ExternalItem *clone_external_item_impl () const = 0;
1810 : :
1811 : : NodeId node_id;
1812 : : };
1813 : :
1814 : : /* Data structure to store the data used in macro invocations and macro
1815 : : * invocations with semicolons. */
1816 : : struct MacroInvocData
1817 : : {
1818 : : private:
1819 : : SimplePath path;
1820 : : DelimTokenTree token_tree;
1821 : :
1822 : : // One way of parsing the macro. Probably not applicable for all macros.
1823 : : std::vector<std::unique_ptr<MetaItemInner>> parsed_items;
1824 : : bool parsed_to_meta_item = false;
1825 : : MacroExpander *expander = nullptr;
1826 : :
1827 : : public:
1828 : : std::string as_string () const;
1829 : :
1830 : 59480 : MacroInvocData (SimplePath path, DelimTokenTree token_tree)
1831 : 59480 : : path (std::move (path)), token_tree (std::move (token_tree))
1832 : 59480 : {}
1833 : :
1834 : : // Copy constructor with vector clone
1835 : 396534 : MacroInvocData (const MacroInvocData &other)
1836 : 396534 : : path (other.path), token_tree (other.token_tree),
1837 : 396534 : parsed_to_meta_item (other.parsed_to_meta_item)
1838 : : {
1839 : 396534 : parsed_items.reserve (other.parsed_items.size ());
1840 : 396534 : for (const auto &e : other.parsed_items)
1841 : 0 : parsed_items.push_back (e->clone_meta_item_inner ());
1842 : 396534 : }
1843 : :
1844 : : // Copy assignment operator with vector clone
1845 : : MacroInvocData &operator= (const MacroInvocData &other)
1846 : : {
1847 : : path = other.path;
1848 : : token_tree = other.token_tree;
1849 : : parsed_to_meta_item = other.parsed_to_meta_item;
1850 : : expander = other.expander;
1851 : :
1852 : : parsed_items.reserve (other.parsed_items.size ());
1853 : : for (const auto &e : other.parsed_items)
1854 : : parsed_items.push_back (e->clone_meta_item_inner ());
1855 : :
1856 : : return *this;
1857 : : }
1858 : :
1859 : : // Move constructors
1860 : 64456 : MacroInvocData (MacroInvocData &&other) = default;
1861 : : MacroInvocData &operator= (MacroInvocData &&other) = default;
1862 : :
1863 : : // Invalid if path is empty, so base stripping on that.
1864 : 18 : void mark_for_strip () { path = SimplePath::create_empty (); }
1865 : 159692 : bool is_marked_for_strip () const { return path.is_empty (); }
1866 : :
1867 : : // Returns whether the macro has been parsed already.
1868 : 132 : bool is_parsed () const { return parsed_to_meta_item; }
1869 : : // TODO: update on other ways of parsing it
1870 : :
1871 : : // TODO: this mutable getter seems kinda dodgy
1872 : 119046 : DelimTokenTree &get_delim_tok_tree () { return token_tree; }
1873 : : const DelimTokenTree &get_delim_tok_tree () const { return token_tree; }
1874 : :
1875 : : // Set the delim token tree of a macro invocation
1876 : 45 : void set_delim_tok_tree (DelimTokenTree tree) { token_tree = tree; }
1877 : :
1878 : : // TODO: this mutable getter seems kinda dodgy
1879 : 125015 : SimplePath &get_path () { return path; }
1880 : : const SimplePath &get_path () const { return path; }
1881 : :
1882 : 61715 : void set_expander (MacroExpander *new_expander) { expander = new_expander; }
1883 : 221 : MacroExpander *get_expander ()
1884 : : {
1885 : 221 : rust_assert (expander);
1886 : 221 : return expander;
1887 : : }
1888 : :
1889 : : void
1890 : 132 : set_meta_item_output (std::vector<std::unique_ptr<MetaItemInner>> new_items)
1891 : : {
1892 : 132 : parsed_items = std::move (new_items);
1893 : : }
1894 : : // TODO: mutable getter seems kinda dodgy
1895 : : std::vector<std::unique_ptr<MetaItemInner>> &get_meta_items ()
1896 : : {
1897 : : return parsed_items;
1898 : : }
1899 : : const std::vector<std::unique_ptr<MetaItemInner>> &get_meta_items () const
1900 : : {
1901 : : return parsed_items;
1902 : : }
1903 : : };
1904 : :
1905 : : class SingleASTNode : public Visitable
1906 : : {
1907 : : public:
1908 : : enum class Kind
1909 : : {
1910 : : Expr,
1911 : : Item,
1912 : : Stmt,
1913 : : Extern,
1914 : : Assoc,
1915 : : Type,
1916 : : Pattern,
1917 : : };
1918 : :
1919 : : private:
1920 : : Kind kind;
1921 : :
1922 : : // FIXME make this a union
1923 : : std::unique_ptr<Expr> expr;
1924 : : std::unique_ptr<Item> item;
1925 : : std::unique_ptr<Stmt> stmt;
1926 : : std::unique_ptr<ExternalItem> external_item;
1927 : : std::unique_ptr<AssociatedItem> assoc_item;
1928 : : std::unique_ptr<Type> type;
1929 : : std::unique_ptr<Pattern> pattern;
1930 : :
1931 : : public:
1932 : 49724 : SingleASTNode (std::unique_ptr<Expr> expr)
1933 : 49724 : : kind (Kind::Expr), expr (std::move (expr))
1934 : : {}
1935 : :
1936 : 10771 : SingleASTNode (std::unique_ptr<Item> item)
1937 : 10771 : : kind (Kind::Item), item (std::move (item))
1938 : : {}
1939 : :
1940 : 640 : SingleASTNode (std::unique_ptr<Stmt> stmt)
1941 : 640 : : kind (Kind::Stmt), stmt (std::move (stmt))
1942 : : {}
1943 : :
1944 : 3 : SingleASTNode (std::unique_ptr<ExternalItem> item)
1945 : 3 : : kind (Kind::Extern), external_item (std::move (item))
1946 : : {}
1947 : :
1948 : 2228 : SingleASTNode (std::unique_ptr<AssociatedItem> item)
1949 : 2228 : : kind (Kind::Assoc), assoc_item (std::move (item))
1950 : : {}
1951 : :
1952 : 497 : SingleASTNode (std::unique_ptr<Type> type)
1953 : 497 : : kind (Kind::Type), type (std::move (type))
1954 : : {}
1955 : :
1956 : 1 : SingleASTNode (std::unique_ptr<Pattern> pattern)
1957 : 1 : : kind (Kind::Pattern), pattern (std::move (pattern))
1958 : : {}
1959 : :
1960 : : SingleASTNode (SingleASTNode const &other);
1961 : :
1962 : : SingleASTNode operator= (SingleASTNode const &other);
1963 : :
1964 : 24500 : SingleASTNode (SingleASTNode &&other) = default;
1965 : : SingleASTNode &operator= (SingleASTNode &&other) = default;
1966 : :
1967 : 100314 : Kind get_kind () const { return kind; }
1968 : :
1969 : : std::unique_ptr<Expr> &get_expr ()
1970 : : {
1971 : : rust_assert (kind == Kind::Expr);
1972 : : return expr;
1973 : : }
1974 : :
1975 : : std::unique_ptr<Item> &get_item ()
1976 : : {
1977 : : rust_assert (kind == Kind::Item);
1978 : : return item;
1979 : : }
1980 : :
1981 : : std::unique_ptr<Stmt> &get_stmt ()
1982 : : {
1983 : : rust_assert (kind == Kind::Stmt);
1984 : : return stmt;
1985 : : }
1986 : :
1987 : : /**
1988 : : * Access the inner nodes and take ownership of them.
1989 : : * You can only call these functions once per node
1990 : : */
1991 : :
1992 : 653 : std::unique_ptr<Stmt> take_stmt ()
1993 : : {
1994 : 653 : rust_assert (!is_error ());
1995 : 653 : return std::move (stmt);
1996 : : }
1997 : :
1998 : 49659 : std::unique_ptr<Expr> take_expr ()
1999 : : {
2000 : 49659 : rust_assert (!is_error ());
2001 : 49659 : return std::move (expr);
2002 : : }
2003 : :
2004 : 10770 : std::unique_ptr<Item> take_item ()
2005 : : {
2006 : 10770 : rust_assert (!is_error ());
2007 : 10770 : return std::move (item);
2008 : : }
2009 : :
2010 : 3 : std::unique_ptr<ExternalItem> take_external_item ()
2011 : : {
2012 : 3 : rust_assert (!is_error ());
2013 : 3 : return std::move (external_item);
2014 : : }
2015 : :
2016 : 2228 : std::unique_ptr<AssociatedItem> take_assoc_item ()
2017 : : {
2018 : 2228 : rust_assert (!is_error ());
2019 : 2228 : return std::move (assoc_item);
2020 : : }
2021 : :
2022 : 497 : std::unique_ptr<Type> take_type ()
2023 : : {
2024 : 497 : rust_assert (!is_error ());
2025 : 497 : return std::move (type);
2026 : : }
2027 : :
2028 : 1 : std::unique_ptr<Pattern> take_pattern ()
2029 : : {
2030 : 1 : rust_assert (!is_error ());
2031 : 1 : return std::move (pattern);
2032 : : }
2033 : :
2034 : : void accept_vis (ASTVisitor &vis) override;
2035 : :
2036 : : bool is_error ();
2037 : :
2038 : : std::string as_string () const;
2039 : : };
2040 : :
2041 : : // A crate AST object - holds all the data for a single compilation unit
2042 : : struct Crate
2043 : : {
2044 : : std::vector<Attribute> inner_attrs;
2045 : : // dodgy spacing required here
2046 : : /* TODO: is it better to have a vector of items here or a module (implicit
2047 : : * top-level one)? */
2048 : : std::vector<std::unique_ptr<Item>> items;
2049 : :
2050 : : NodeId node_id;
2051 : :
2052 : : public:
2053 : : // Constructor
2054 : 4591 : Crate (std::vector<std::unique_ptr<Item>> items,
2055 : : std::vector<Attribute> inner_attrs)
2056 : 4591 : : inner_attrs (std::move (inner_attrs)), items (std::move (items)),
2057 : 4591 : node_id (Analysis::Mappings::get ().get_next_node_id ())
2058 : 4591 : {}
2059 : :
2060 : : // Copy constructor with vector clone
2061 : 16 : Crate (Crate const &other)
2062 : 16 : : inner_attrs (other.inner_attrs), node_id (other.node_id)
2063 : : {
2064 : 16 : items.reserve (other.items.size ());
2065 : 413 : for (const auto &e : other.items)
2066 : 397 : items.push_back (e->clone_item ());
2067 : 16 : }
2068 : :
2069 : 109 : ~Crate () = default;
2070 : :
2071 : : // Overloaded assignment operator with vector clone
2072 : : Crate &operator= (Crate const &other)
2073 : : {
2074 : : inner_attrs = other.inner_attrs;
2075 : : node_id = other.node_id;
2076 : :
2077 : : items.reserve (other.items.size ());
2078 : : for (const auto &e : other.items)
2079 : : items.push_back (e->clone_item ());
2080 : :
2081 : : return *this;
2082 : : }
2083 : :
2084 : : // Move constructors
2085 : : Crate (Crate &&other) = default;
2086 : : Crate &operator= (Crate &&other) = default;
2087 : :
2088 : : // Get crate representation as string (e.g. for debugging).
2089 : : std::string as_string () const;
2090 : :
2091 : : // Delete all crate information, e.g. if fails cfg.
2092 : 1 : void strip_crate ()
2093 : : {
2094 : 1 : inner_attrs.clear ();
2095 : 1 : inner_attrs.shrink_to_fit ();
2096 : :
2097 : 1 : items.clear ();
2098 : 1 : items.shrink_to_fit ();
2099 : : // TODO: is this the best way to do this?
2100 : 1 : }
2101 : :
2102 : 86189 : NodeId get_node_id () const { return node_id; }
2103 : : const std::vector<Attribute> &get_inner_attrs () const { return inner_attrs; }
2104 : 70761 : std::vector<Attribute> &get_inner_attrs () { return inner_attrs; }
2105 : :
2106 : : std::vector<std::unique_ptr<AST::Item>> take_items ()
2107 : : {
2108 : : return std::move (items);
2109 : : }
2110 : :
2111 : : void set_items (std::vector<std::unique_ptr<AST::Item>> &&new_items)
2112 : : {
2113 : : items = std::move (new_items);
2114 : : }
2115 : : };
2116 : :
2117 : : } // namespace AST
2118 : : } // namespace Rust
2119 : :
2120 : : namespace std {
2121 : : template <> struct less<Rust::Identifier>
2122 : : {
2123 : : bool operator() (const Rust::Identifier &lhs,
2124 : : const Rust::Identifier &rhs) const
2125 : : {
2126 : : return lhs.as_string () < rhs.as_string ();
2127 : : }
2128 : : };
2129 : :
2130 : : template <> struct hash<Rust::Identifier>
2131 : : {
2132 : : std::size_t operator() (const Rust::Identifier &k) const
2133 : : {
2134 : : using std::hash;
2135 : : using std::size_t;
2136 : : using std::string;
2137 : :
2138 : : return hash<string> () (k.as_string ()) ^ (hash<int> () (k.get_locus ()));
2139 : : }
2140 : : };
2141 : :
2142 : : } // namespace std
2143 : :
2144 : : #endif
|